31、[中等] 下一个排列数组双指针class Solution { public: void nextPermutation(vectorint nums) { int i nums.size() - 2; while (i 0 nums[i] nums[i 1]) i--; if (i 0) { int j nums.size() - 1; while (j 0 nums[i] nums[j]) j--; swap(nums[i], nums[j]); } reverse(nums.begin() i 1, nums.end()); } };32、[困难] 最长有效括号栈字符串动态规划动态规划class Solution { public: int longestValidParentheses(string s) { int ret 0; int n s.size(); vectorint dp(n, 0); for (int i 1; i n; i) { if (s[i] )) { if (s[i - 1] () { dp[i] (i 2 ? dp[i - 2] : 0) 2; } else if (i - dp[i - 1] 0 s[i - dp[i - 1] - 1] () { dp[i] dp[i - 1] ((i - dp[i - 1]) 2 ? dp[i - dp[i - 1] - 2] : 0) 2; } ret max(ret, dp[i]); } } return ret; } };栈class Solution { public: int longestValidParentheses(string s) { int ret 0; stackint stk; stk.push(-1); for (int i 0; i s.size(); i) { if (s[i] () { stk.push(i); } else { stk.pop(); if (stk.empty()) { stk.push(i); } else { ret max(ret, i - stk.top()); } } } return ret; } };不需要额外的空间class Solution { public: int longestValidParentheses(string s) { int left 0, right 0, maxlength 0; for (int i 0; i s.size(); i) { if (s[i] () { left; } else { right; } if (left right) { maxlength max(maxlength, 2 * right); } else if (right left) { left right 0; } } left right 0; for (int i (int)s.size() - 1; i 0; i--) { if (s[i] () { left; } else { right; } if (left right) { maxlength max(maxlength, 2 * left); } else if (left right) { left right 0; } } return maxlength; } };33、[中等] 搜索旋转排序数组二分查找class Solution { public: int search(vectorint nums, int target) { int n nums.size(); if (!n) { return -1; } if (n 1) { return nums[0] target ? 0 : -1; } int left 0, right n - 1; while (left right) { int mid (right left) / 2; if (nums[mid] target) { return mid; } if (nums[0] nums[mid]) { if (nums[0] target target nums[mid]) { right mid - 1; } else { left mid 1; } } else { if (nums[mid] target target nums[n - 1]) { left mid 1; } else { right mid - 1; } } } return -1; } };34、[中等] 在排序数组中查找元素的第一个和最后一个二分查找class Solution { public: vectorint searchRange(vectorint nums, int target) { if (nums.size() 0) { return {-1, -1}; } int left 0, right nums.size() - 1; int begin 0, end 0; // 二分左端点 while (left right) { int mid left (right - left) / 2; if (nums[mid] target) { left mid 1; } else { right mid; } } // 判断结果 if (nums[right] ! target) { return {-1, -1}; } else { begin left; } // 二分右端点 left 0; right nums.size() - 1; while (left right) { int mid left (right - left 1) / 2; if (nums[mid] target) { right mid - 1; } else { left mid; } } end left; return {begin, end}; } };35、[简单] 搜索插入位置二分查找数组class Solution { public: int searchInsert(vectorint nums, int target) { int left 0, right nums.size() - 1; if (nums[right] target) return right 1; while (left right) { int mid left (right - left) / 2; if (nums[mid] target) left mid 1; else right mid; } return left; } };36、[中等] 有效的数独数组哈希表矩阵class Solution { public: bool isValidSudoku(vectorvectorchar board) { bool row[9][10]; bool col[9][10]; bool grid[3][3][10]; for (int i 0; i 9; i) { for (int j 0; j 9; j) { if (board[i][j] ! .) { int num board[i][j] - 0; // 是否是有效的 if (row[i][num] || col[j][num] || grid[i / 3][j / 3][num]) { return false; } row[i][num] col[j][num] grid[i / 3][j / 3][num] true; } } } return true; } };37、[困难] 解数独位运算数组回溯矩阵class Solution { private: bool row[9][10]; bool col[9][10]; bool grid[3][3][10]; bool dfs(vectorvectorchar board) { for (int i 0; i 9; i) { for (int j 0; j 9; j) { if (board[i][j] .) { // 填数 for (int num 1; num 9; num) { if (!row[i][num] !col[j][num] !grid[i / 3][j / 3][num]) { board[i][j] 0 num; row[i][num] col[j][num] grid[i / 3][j / 3][num] true; if (dfs(board) true) { return true; } // 恢复现场 board[i][j] .; row[i][num] col[j][num] grid[i / 3][j / 3][num] false; } } return false; } } } return true; } public: void solveSudoku(vectorvectorchar board) { // 初始化 for (int i 0; i 9; i) { for (int j 0; j 9; j) { if (board[i][j] ! .) { int num board[i][j] - 0; row[i][num] col[j][num] grid[i / 3][j / 3][num] true; } } } dfs(board); } };38、[中等] 外观数列字符串class Solution { public: string countAndSay(int n) { string ret 1; for (int i 1; i n; i) { string tmp; int len ret.size(); for (int left 0, right 0; right len;) { while (right len ret[left] ret[right]) { right; } tmp to_string(right - left) ret[left]; left right; } ret tmp; } return ret; } };39、[中等] 组合总和数组回溯class Solution { private: vectorvectorint ret; vectorint path; public: vectorvectorint combinationSum(vectorint candidates, int target) { dfs(candidates, 0, target); return ret; } void dfs(vectorint candidates, int pos, int target) { if (target 0) { ret.push_back(path); return; } if (target 0) { return; } for (int i pos; i candidates.size(); i) { path.push_back(candidates[i]); dfs(candidates, i, target - candidates[i]); path.pop_back(); } } };class Solution { public: vectorvectorint combinationSum(vectorint candidates, int target) { vectorvectorint solutions; vectorint solution; int curSum 0; dfs(solutions, solution, curSum, 0, target, candidates); return solutions; } void dfs(vectorvectorint solutions, vectorint solution, int curSum, int preIdx, int target, vectorint candidates) { if (curSum target) { if (curSum target) { // 保存当前组合 solutions.push_back(solution); } return; } // 从后选一个数字累加 for (int i preIdx; i candidates.size(); i) { solution.push_back(candidates[i]); dfs(solutions, solution, curSum candidates[i], i, target, candidates); // 回溯 solution.pop_back(); } } };40、[中等] 组合总和 Ⅱ数组回溯class Solution { private: vectorpairint, int freq; vectorvectorint ret; vectorint path; public: vectorvectorint combinationSum2(vectorint candidates, int target) { sort(candidates.begin(), candidates.end()); for (int num : candidates) { if (freq.empty() || num ! freq.back().first) { freq.emplace_back(num, 1); } else { freq.back().second; } } dfs(0, target); return ret; } void dfs(int pos, int target) { if (target 0) { ret.push_back(path); return; } if (pos freq.size() || target freq[pos].first) { return; } dfs(pos 1, target); int most min(target / freq[pos].first, freq[pos].second); for (int i 1; i most; i) { path.push_back(freq[pos].first); dfs(pos 1, target - i * freq[pos].first); } for (int i 1; i most; i) { path.pop_back(); } } };