题目 难度
排列类 全排列 Medium
全排列 II Medium
无重复字符串的排列组合 Medium
有重复字符串的排列组合 Medium
排列序列 Hard
组合类 组合 Medium
17. 电话号码的字母组合 Medium
子集类 78. 子集 Medium
90. 子集 II Medium
面试题 08.04. 幂集 Medium
回溯类

37. 解数独

| Hard |

一、 排列类题目

46. 全排列

题解

  1. class Solution {
  2. public:
  3. vector<vector<int>> res;
  4. vector<bool> visited;
  5. vector<int> path;
  6. vector<vector<int>> permute(vector<int> nums) {
  7. for (int i = 0; i < nums.size(); ++i) {
  8. visited.push_back(false);
  9. }
  10. dfs(nums, 0);
  11. return res;
  12. }
  13. void dfs(vector<int> &nums, int deep) {
  14. if (deep == nums.size()) {
  15. res.push_back(path);
  16. return;
  17. }
  18. for (int i = 0; i < nums.size(); ++i) {
  19. if (!visited[i]) {
  20. visited[i] = true;
  21. path.push_back(nums[i]);
  22. dfs(nums, deep + 1);
  23. visited[i] = false;
  24. path.pop_back();// 弹出来 以便 其余数字排列时加入进去;
  25. }
  26. }
  27. }
  28. };

47.全排列 II

  1. class Solution {
  2. vector<vector<int>> ans;
  3. vector<int> path;
  4. vector<bool> visited;
  5. public:
  6. vector<vector<int>> permuteUnique(vector<int> &nums) {
  7. if (nums.empty()) {
  8. return ans;
  9. }
  10. for (int i = 0; i < nums.size(); i++) {
  11. visited.push_back(false);
  12. }
  13. // 排序是去重的首要操作,方便下面 nums[i-1]==nums[i]的判断
  14. // 如果不排序,[2,1,2] 这样的数据无法判断出来
  15. sort(nums.begin(), nums.end(), greater<int>());
  16. dfs(nums, 0);
  17. return ans;
  18. }
  19. void dfs(vector<int> &nums, int deep) {
  20. if (deep == nums.size()) {
  21. ans.push_back(path);
  22. return;
  23. }
  24. for (int i = 0; i < nums.size(); i++) {
  25. if (!visited[i]) {
  26. if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
  27. continue;
  28. }
  29. visited[i] = true;
  30. path.push_back(nums[i]);
  31. dfs(nums, deep + 1);
  32. visited[i] = false;
  33. path.pop_back();
  34. }
  35. }
  36. }
  37. };

面试题 08.07 无重复字符串的排列组合

  1. class Solution {
  2. public:
  3. vector<string> ans;
  4. vector<char> path;
  5. vector<bool> visited;
  6. vector<string> permutation(string S) {
  7. for (int i = 0; i < S.length(); i++) {
  8. visited.push_back(false);
  9. }
  10. dfs(S, 0);
  11. return ans;
  12. }
  13. void dfs(string s, int deep) {
  14. if (deep == s.length()) {
  15. // char 与 string 转换
  16. string ss(path.begin(), path.end());
  17. ans.push_back(ss);
  18. return;
  19. }
  20. for (int i = 0; i < s.length(); i++) {
  21. if (!visited[i]) {
  22. visited[i] = true;
  23. path.push_back(s[i]);
  24. dfs(s, deep + 1);
  25. path.pop_back();
  26. visited[i] = false;
  27. }
  28. }
  29. }
  30. };

面试题 08.08 有重复字符串的排列组合

  1. class Solution {
  2. public:
  3. vector<string> ans;
  4. vector<char> path;
  5. vector<bool> visited;
  6. vector<string> permutation(string S) {
  7. for (int i = 0; i < S.length(); i++) {
  8. visited.push_back(false);
  9. }
  10. sort(S.begin(), S.end());
  11. dfs(S, 0);
  12. return ans;
  13. }
  14. void dfs(string s, int deep) {
  15. if (deep == s.length()) {
  16. string ss(path.begin(), path.end());
  17. ans.push_back(ss);
  18. return;
  19. }
  20. for (int i = 0; i < s.length(); i++) {
  21. if (!visited[i]) {
  22. // 剪枝;
  23. if (i > 0 && s[i - 1] == s[i] && !visited[i - 1]) {
  24. continue;
  25. }
  26. visited[i] = true;
  27. path.push_back(s[i]);
  28. dfs(s, deep + 1);
  29. path.pop_back();
  30. visited[i] = false;
  31. }
  32. }
  33. }
  34. };

60. 排列序列

题解:题解

  1. class Solution {
  2. public:
  3. vector<bool> visited;
  4. int n, k;
  5. vector<int> factorial;
  6. string getPermutation(int n, int k) {
  7. this->n = n;
  8. this->k = k;
  9. calcFactorial();
  10. visited = vector<bool>(n + 1, false);
  11. string str;
  12. dfs(0, str);
  13. return str;
  14. }
  15. void dfs(int index, string &str) {
  16. if (index == n) { return; }
  17. int cnt = factorial[n - index - 1];
  18. for (int i = 1; i <= n; ++i) {
  19. if (visited[i]) { continue; }
  20. if (cnt < k) {
  21. k -= cnt;
  22. continue;
  23. }
  24. visited[i] = 1;
  25. string tmp;
  26. stringstream ss;
  27. ss << i;
  28. ss >> tmp;
  29. str.append(tmp);
  30. dfs(index + 1, str);
  31. return;
  32. }
  33. }
  34. void calcFactorial() {
  35. factorial = vector<int>(n, 0);
  36. factorial[0] = 1;
  37. for (int i = 1; i < n; i++) {
  38. factorial[i] = factorial[i - 1] * i;
  39. }
  40. }
  41. };

二、组合类题目

77.组合

题解

  1. class Solution {
  2. public:
  3. vector<vector<int>> res;
  4. vector<int> path;
  5. vector<int> nums;
  6. vector<vector<int>> combine(int n, int k) {
  7. if( k<=0 || k>n ){
  8. return res;
  9. }
  10. for (int i = 1; i <= n; ++i) {
  11. nums.push_back(i);
  12. }
  13. dfs(nums, 0, k, 1);
  14. return res;
  15. }
  16. void dfs(vector<int> &nums, int deep, int k, int start) {
  17. if (deep == k) {
  18. res.push_back(path);
  19. return;
  20. }
  21. for (int i = start; i <= nums.size(); ++i) {
  22. path.push_back(i);
  23. dfs(nums, deep + 1, k, i + 1);
  24. path.pop_back();
  25. }
  26. }
  27. };

17. 电话号码的字母组合

  1. class Solution {
  2. public:
  3. unordered_map<char, string> map = {
  4. {'2', "abc"},
  5. {'3', "def"},
  6. {'4', "ghi"},
  7. {'5', "jkl"},
  8. {'6', "mno"},
  9. {'7', "pqrs"},
  10. {'8', "tuv"},
  11. {'9', "wxyz"}
  12. };
  13. vector<string> ans;
  14. string current;
  15. vector<string> letterCombinations(string digits) {
  16. if (digits.size() == 0) {
  17. return ans;
  18. }
  19. dfs(0, digits);
  20. return ans;
  21. }
  22. void dfs(int index, string &digits) {
  23. if (index == digits.size()) {
  24. ans.push_back(current);
  25. return;
  26. }
  27. for (int i = 0; i < map[digits[index]].size(); i++) {
  28. current.push_back(map[digits[index]][i]);
  29. dfs(index + 1, digits);
  30. current.pop_back();
  31. }
  32. }
  33. };

三、子集类

78. 子集

  1. class Solution {
  2. public:
  3. vector<vector<int>> ans;
  4. vector<int> path;
  5. vector<bool> visited;
  6. int N;
  7. vector<vector<int>> subsets(vector<int> &nums) {
  8. N = nums.size();
  9. if (N == 0) {
  10. return ans;
  11. }
  12. visited = vector<bool>(N, 0);
  13. sort(nums.begin(), nums.end());
  14. dfs(0, nums);
  15. return ans;
  16. }
  17. void dfs(int index, vector<int> &nums) {
  18. ans.push_back(path);
  19. for (int i = index; i < nums.size(); i++) {
  20. path.push_back(nums[i]);
  21. visited[i] = 1;
  22. dfs(i + 1, nums);
  23. path.pop_back();
  24. visited[i] = 0;
  25. }
  26. }
  27. };

90. 子集 II

  1. class Solution {
  2. public:
  3. int N;
  4. vector<vector<int>> ans;
  5. vector<int> path;
  6. vector<bool> visited;
  7. vector<vector<int>> subsetsWithDup(vector<int> &nums) {
  8. N = nums.size();
  9. if (nums.size() == 0) {
  10. return ans;
  11. }
  12. visited = vector<bool>(N, 0);
  13. sort(nums.begin(), nums.end());
  14. dfs(0, nums);
  15. return ans;
  16. }
  17. void dfs(int index, vector<int> &nums) {
  18. ans.push_back(path);
  19. for (int i = index; i < nums.size(); i++) {
  20. //减枝
  21. if (i > 0 && !visited[i - 1] && nums[i] == nums[i - 1]) {
  22. continue;
  23. }
  24. visited[i] = 1;
  25. path.push_back(nums[i]);
  26. dfs(i + 1, nums);
  27. path.pop_back();
  28. visited[i] = 0;
  29. }
  30. }
  31. };

面试题 08.04. 幂集

  1. class Solution {
  2. public:
  3. int N;
  4. vector<vector<int>> ans;
  5. vector<int> path;
  6. vector<bool> visited;
  7. vector<vector<int>> subsets(vector<int> &nums) {
  8. N = nums.size();
  9. if (nums.size() == 0) {
  10. return ans;
  11. }
  12. visited = vector<bool>(N, 0);
  13. sort(nums.begin(), nums.end());
  14. dfs(0, nums);
  15. return ans;
  16. }
  17. void dfs(int index, vector<int> &nums) {
  18. ans.push_back(path);
  19. for (int i = index; i < nums.size(); i++) {
  20. //减枝
  21. if (i > 0 && !visited[i - 1] && nums[i] == nums[i - 1]) {
  22. continue;
  23. }
  24. visited[i] = 1;
  25. path.push_back(nums[i]);
  26. dfs(i + 1, nums);
  27. path.pop_back();
  28. visited[i] = 0;
  29. }
  30. }
  31. };

37. 解数独

题解:https://leetcode.cn/problems/sudoku-solver/solution/hui-su-fa-jie-shu-du-by-i_use_python/

  1. vector<vector<int>> rowUsed;
  2. vector<vector<int>> colUsed;
  3. vector<vector<vector<int>>> boxUsed;
  4. void solveSudoku(vector<vector<char>> &board) {
  5. rowUsed = vector<vector<int>>(9, vector<int>(10));
  6. colUsed = vector<vector<int>>(9, vector<int>(10));
  7. boxUsed = vector<vector<vector<int>>>(3, vector<vector<int>>(3, vector<int>(10)));
  8. for (int row = 0; row < board.size(); row++) {
  9. for (int col = 0; col < board[0].size(); col++) {
  10. int num = board[row][col] - '0';
  11. if (num >= 1 && num <= 9) {
  12. rowUsed[row][num] = 1;
  13. colUsed[col][num] = 1;
  14. boxUsed[row / 3][col / 3][num] = 1;
  15. }
  16. }
  17. }
  18. recSolveSudoKu(board, rowUsed, colUsed, boxUsed, 0, 0);
  19. }
  20. bool recSolveSudoKu(vector<vector<char>> &board, vector<vector<int>> &rowUsed,
  21. vector<vector<int>> &colUsed, vector<vector<vector<int>>> &boxUsed, int row, int col) {
  22. if (col == board[0].size()) {
  23. col = 0;
  24. row += 1;
  25. if (row == board.size()) {
  26. return true;
  27. }
  28. }
  29. if (board[row][col] == '.') {
  30. for (int num = 1; num <= 9; num++) {
  31. bool canUsed = !(rowUsed[row][num] || colUsed[col][num] || boxUsed[row / 3][col / 3][num]);
  32. if (canUsed) {
  33. rowUsed[row][num] = 1;
  34. colUsed[col][num] = 1;
  35. boxUsed[row / 3][col / 3][num] = 1;
  36. board[row][col] = char(num + '0');
  37. if (recSolveSudoKu(board, rowUsed, colUsed, boxUsed, row, col + 1)) {
  38. return true;
  39. }
  40. rowUsed[row][num] = 0;
  41. colUsed[col][num] = 0;
  42. boxUsed[row / 3][col / 3][num] = 0;
  43. board[row][col] = '.';
  44. }
  45. }
  46. } else {
  47. return recSolveSudoKu(board, rowUsed, colUsed, boxUsed, row, col + 1);
  48. }
  49. return false;
  50. }