【10】Regular Expression Matching html
【17】Letter Combinations of a Phone Number git
【22】Generate Parentheses (2019年2月13日)算法
給了一個N,生成N對括號的全部狀況的字符串。數組
n = 3ide
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
題解:dfs生成。google
1 class Solution { 2 public: 3 vector<string> generateParenthesis(int n) { 4 vector<string> res; 5 string str; 6 int left = n, right = n; 7 dfs(str, res, left, right); 8 return res; 9 } 10 void dfs(string& str, vector<string>& res, int left, int right) { 11 if (left == 0 && right == 0) { 12 res.push_back(str); 13 return; 14 } 15 if (left <= right && left - 1 >= 0) { 16 str += "("; 17 dfs(str, res, left-1, right); 18 str.pop_back(); 19 } 20 if (left < right && right - 1 >= 0) { 21 str += ")"; 22 dfs(str, res, left, right - 1); 23 str.pop_back(); 24 } 25 } 26 };
【37】Sudoku Solver (2019年3月18日,google tag)spa
題意:填數獨rest
題解:backtracking,惟一的難點是判斷每個 3 * 3 的 block 是否合法的時候,座標的判斷須要點技巧。code
1 class Solution { 2 public: 3 void solveSudoku(vector<vector<char>>& board) { 4 dfs(board); 5 return; 6 } 7 const int n = 9, size = 3; 8 bool dfs(vector<vector<char>>& board) { 9 for (int i = 0; i < n; ++i) { 10 for (int j = 0; j < n; ++j) { 11 if (board[i][j] == '.') { 12 for (char c = '1'; c <= '9'; ++c) { 13 if (isValid(board, i, j, c)) { 14 board[i][j] = c; 15 if (dfs(board)) {return true;} 16 board[i][j] = '.'; 17 } 18 } 19 return false; 20 } 21 } 22 } 23 return true; 24 } 25 bool isValid(vector<vector<char>>& board, int r, int c, char x) { 26 const int idxR = (r / size) * 3, idxC = (c / size) * 3; 27 for (int i = 0; i < n; ++i) { 28 if (board[r][i] == x || board[i][c] == x) {return false;} 29 if (board[idxR+i/3][idxC+i%3] == x) {return false;} 30 } 31 return true; 32 } 33 };
【39】Combination Sum htm
【40】Combination Sum II
【44】Wildcard Matching
【46】Permutations (2019年1月23日,谷歌tag複習)(M)
給了一個distinct numbers 的數組,返回全部的排列。
題解:dfs
1 class Solution { 2 public: 3 vector<vector<int>> permute(vector<int>& nums) { 4 dfs(nums); 5 return ret; 6 } 7 vector<int> arr; 8 vector<vector<int>> ret; 9 void dfs(const vector<int>& nums) { 10 if (arr.size() == nums.size()) { 11 ret.push_back(arr); 12 return; 13 } 14 for (int i = 0; i < nums.size(); ++i) { 15 set<int> st(arr.begin(), arr.end()); 16 if (st.find(nums[i]) != st.end()) { continue; } 17 arr.push_back(nums[i]); 18 dfs(nums); 19 arr.pop_back(); 20 } 21 return; 22 } 23 };
【47】Permutations II (2019年2月17日,有重複元素的全排列。今天周賽的第四題 996. Number of Squareful Arrays)
寫一個有重複元素的全排列。
Input: [1,1,2] Output: [ [1,1,2], [1,2,1], [2,1,1] ]
題解:咱們能夠先 sort 一下數組,而後用一個臨時的array,存放如今結果,重點是遇到重複元素的時候如何避免生成重複的序列。若是當前想放進列表的元素已經訪問過了,就continue,若是當前想放進列表的元素和它前一個元素的值同樣,可是前一個元素尚未放進數組裏面,那麼這個元素確定不能放在數組裏面,好比說原數組是[2, 2],對應下標是[0, 1],若是第一個2尚未在列表裏面,那麼第二個2就確定不讓它在列表裏面。由於若是第二個2在列表裏面而且在第一個2前面,就有 [1,0] 和 [0,1] 的兩種排列。
1 class Solution { 2 public: 3 vector<vector<int>> permuteUnique(vector<int>& nums) { 4 const int n = nums.size(); 5 sort(nums.begin(), nums.end()); 6 vector<vector<int>> ret; 7 vector<int> visited(n, 0), arr; 8 dfs(nums, ret, arr, visited); 9 return ret; 10 } 11 void dfs(vector<int>& nums, vector<vector<int>>& ret, vector<int>& arr, vector<int>& visited) { 12 if (arr.size() == nums.size()) { 13 ret.push_back(arr); 14 return; 15 } 16 for (int i = 0; i < nums.size(); ++i) { 17 if (visited[i]) {continue;} 18 if (i -1 >= 0 && nums[i] == nums[i-1] && !visited[i-1]) {continue;} 19 arr.push_back(nums[i]); 20 visited[i] = 1; 21 dfs(nums, ret, arr, visited); 22 arr.pop_back(); 23 visited[i] = 0; 24 } 25 } 26 };
【51】N-Queens
【52】N-Queens II
【60】Permutation Sequence
【77】Combinations (2019年1月21日,算法羣打卡題)
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
Input: n = 4, k = 2 Output: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
題解:直接回溯。
1 class Solution { 2 public: 3 vector<vector<int>> ret; 4 vector<vector<int>> combine(int n, int k) { 5 vector<int> nums; 6 dfs(nums, 1, n, k); 7 return ret; 8 } 9 void dfs(vector<int>& nums, int cur, const int n, const int k) { 10 if (nums.size() == k) { 11 ret.push_back(nums); 12 return; 13 } 14 for (int i = cur; i <= n; ++i) { 15 nums.push_back(i); 16 dfs(nums, i + 1, n, k); //這裏注意不要寫錯了。 我有時候會寫成 dfs(nums, cur + 1, n, k); 17 nums.pop_back(); 18 } 19 return; 20 } 21 };
【78】Subsets (類似的題目見 90 題)
給了一個 distinct 的數組,返回它全部的子集。
題解見位運算專題【78】題,同樣的。http://www.javashuo.com/article/p-ucajkeok-kt.html
【79】Word Search (2019年1月25日,谷歌tag複習) (Medium)
給了一個單詞板和一個單詞,四聯通,問能不能在板子上面找到這個單詞。
題解:backtracking,注意邊界哇哭死,沒有一次AC
1 class Solution { 2 public: 3 bool exist(vector<vector<char>>& board, string word) { 4 n = board.size(), m = board[0].size(); 5 for (int i = 0; i < n; ++i) { 6 for (int j = 0; j < m; ++j) { 7 if (board[i][j] == word[0]) { 8 vector<vector<int>> visit(n, vector<int>(m, 0)); 9 visit[i][j] = 1; 10 if (dfs(board, i, j, word, 0, visit)) { 11 return true; 12 } 13 } 14 } 15 } 16 return false; 17 } 18 int n, m; 19 bool dfs(vector<vector<char>>& board, int x, int y, const string word, int cur, vector<vector<int>>& visit) { 20 if (cur + 1 == word.size()) { 21 return true; 22 } 23 for (int i = 0; i < 4; ++i) { 24 int newx = x + dirx[i], newy = y + diry[i]; 25 if (newx >= 0 && newx < n && newy >= 0 && newy < m && !visit[newx][newy] && board[newx][newy] == word[cur+1]) { 26 visit[newx][newy] = 1; 27 if (dfs(board, newx, newy, word, cur + 1, visit)) { 28 return true; 29 } 30 visit[newx][newy] = 0; 31 } 32 } 33 return false; 34 } 35 int dirx[4] = {-1, 0, 1, 0}; 36 int diry[4] = {0, -1, 0, 1}; 37 };
【89】Gray Code
【90】Subsets II (算法羣,2018年11月21日)
給了一個有重複數字的數組,返回它全部的unique子集。
Input: [1,2,2] Output: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]
題解:回溯法。用set去重,有一點須要注意的是,千萬不能每次遞歸的時候對 如今vector的狀態sort一下,否則遞歸回溯的時候確定有問題的。
1 class Solution { 2 public: 3 vector<vector<int>> subsetsWithDup(vector<int>& nums) { 4 const int n = nums.size(); 5 vector<vector<int>> ret; 6 set<vector<int>> stRet; 7 vector<int> temp; 8 dfs(nums, stRet, 0, temp); 9 for (auto ele : stRet) { 10 ret.push_back(ele); 11 } 12 return ret; 13 } 14 void dfs(const vector<int>& nums, set<vector<int>>& st, int cur, vector<int>& temp) { 15 vector<int> t1 = temp; 16 sort(t1.begin(), t1.end()); 17 st.insert(t1); 18 if (cur == nums.size()) {return;} 19 for (int i = cur; i < nums.size(); ++i) { 20 temp.push_back(nums[i]); 21 dfs(nums, st, i+1, temp); 22 temp.pop_back(); 23 } 24 } 25 };
2019年2月25日更新一個更好的解法:
若是當前層次有兩個同樣的數,必定不會選擇後面的那個數字。(能夠參考 有重複元素的permutation)
1 class Solution { 2 public: 3 vector<vector<int>> subsetsWithDup(vector<int>& nums) { 4 vector<vector<int>> res; 5 sort(nums.begin(), nums.end()); 6 if (nums.empty()) {return res;} 7 vector<int> path; 8 dfs(nums, res, path, 0); 9 return res; 10 } 11 void dfs(vector<int>& nums, vector<vector<int>>& res, vector<int>& path, int start) { 12 res.push_back(path); 13 for (int i = start; i < nums.size(); ++i) { 14 if (i != start && nums[i] == nums[i-1]) {continue;} 15 path.push_back(nums[i]); 16 dfs(nums, res, path, i + 1); 17 path.pop_back(); 18 } 19 } 20 };
【93】Restore IP Addresses (2019年2月14日)
給了一個串純數字的字符串,在字符串裏面加‘.’,返回全部合法的ip字符串。
Input: "25525511135" Output: ["255.255.11.135", "255.255.111.35"]
題解:backtracking,用一個新的字符串保存當前的ip字符串。ipv4的每個小段必須是[0, 255],四個小段。
1 class Solution { 2 public: 3 vector<string> restoreIpAddresses(string s) { 4 const int n = s.size(); 5 vector<string> ret; 6 if (n == 0) {return ret;} 7 string temp; 8 dfs(s, 0, ret, temp, 0); 9 return ret; 10 } 11 void dfs(const string s, int cur, vector<string>& ret, string& temp, int part) { 12 if (cur == s.size() && part == 4) { 13 ret.push_back(temp); 14 return; 15 } 16 if (part >= 4) {return;} 17 string num; 18 if (s[cur] == '0') { 19 string oriTemp = temp; 20 num = string(1, s[cur]); 21 temp += temp.empty() ? (num) : ("." + num); 22 dfs(s, cur + 1, ret, temp, part + 1); 23 temp = oriTemp; 24 } else { 25 string oriTemp = temp; 26 for (int k = 0; k <= 2; ++k) { 27 if (cur + k >= s.size()) {break;} 28 num += s[cur + k]; 29 int inum = stoi(num); 30 if (inum < 1 || inum > 255) {break;} 31 temp += temp.empty() ? (num) : ("." + num); 32 dfs(s, cur + k + 1, ret, temp, part + 1); 33 temp = oriTemp; 34 } 35 } 36 } 37 };
【126】Word Ladder II
【131】Palindrome Partitioning
【140】Word Break II(2018年12月19日,算法羣,相似題目 472. DFS專題)
【211】Add and Search Word - Data structure design
【212】Word Search II
【216】Combination Sum III
【254】Factor Combinations
【267】Palindrome Permutation II
【291】Word Pattern II
【294】Flip Game II
【306】Additive Number
【320】Generalized Abbreviation
【351】Android Unlock Patterns
【357】Count Numbers with Unique Digits
【401】Binary Watch
【411】Minimum Unique Word Abbreviation
【425】Word Squares
【526】Beautiful Arrangement
【691】Stickers to Spell Word
【784】Letter Case Permutation
【842】Split Array into Fibonacci Sequence
給了一個字符串 S,看能不能經過分割字符串,把字符串搞成一個斐波那契數組。(1 <= S.size() <= 200)
題解:就是暴力搜,可是WA吐了快,有幾個點要注意,若是是 「000」 這種是能夠返回的,返回 [0, 0, 0]。而後若是分割的字符串太長的就要continue,否則你 long long 也沒有用,200位確定超過 long long 了。
1 // WA到吐了,太多狀況 2 class Solution { 3 public: 4 vector<int> splitIntoFibonacci(string S) { 5 vector<int> ans; 6 if (S.empty()) { return ans; } //S若是是「000」是能夠的,因此須要留着dfs. 7 return dfs(S, ans, 0) ? ans : vector<int>{}; 8 } 9 bool dfs(string S, vector<int>& ans, int cur_idx) { 10 int n = S.size(); 11 if (cur_idx == n) { 12 return ans.size() >= 3 ? true : false; 13 } 14 for (int i = cur_idx; i < n; ++i) { 15 if (ans.size() < 2) { 16 string strNumber = S.substr(cur_idx, i - cur_idx + 1); 17 if (strNumber.size() > 10 || strNumber.size() > 1 && strNumber[0] == '0') {continue; } 18 long long number = stoll(strNumber); 19 if (number > INT_MAX) {continue;} 20 ans.push_back(number); 21 if (dfs(S, ans, i + 1)) { 22 return true; 23 } 24 ans.pop_back(); 25 } else { 26 int ansSize = ans.size(); 27 int num1 = ans.back(), num2 = ans[ansSize - 2]; 28 string strNumber = S.substr(cur_idx, i - cur_idx + 1); 29 if (strNumber.size() > 10 || strNumber.size() > 1 && strNumber[0] == '0') {continue; } 30 long long num3 = stoll(strNumber); 31 if (num3 > INT_MAX) {continue;} 32 if (num1 + num2 == num3) { 33 ans.push_back(num3); 34 if (dfs(S, ans, i + 1)){ 35 return true; 36 } 37 ans.pop_back(); 38 } 39 } 40 } 41 return false; 42 } 43 };
可是好像個人方法巨慢,能夠看看discuss怎麼求解的。