• 代码随想录笔记--回溯算法篇


    目录

    1--回溯算法理论基础

    2--组合问题

    3--组合问题的剪枝操作

    4--组合总和III

    5--电话号码的字母组合

    6--组合总和

    7--组合总和II

    8--分割回文串

    9--复原 IP 地址

    10--子集

    11--子集II

    12--递增子序列

    13--全排列

    14--全排列II

    15--N皇后

    16--解数独


    1--回溯算法理论基础

            回溯算法本质上是一个暴力搜索的过程,其常用于解决组合切割子集排列等问题,其一般模板如下:

    1. void backTracking(参数){
    2. if(终止条件){
    3. // 1. 收获结果;
    4. // 2. return;
    5. }
    6. for(..遍历){
    7. // 1. 处理节点
    8. // 2. 递归搜索
    9. // 3. 回溯 // 即撤销对节点的处理
    10. }
    11. return;
    12. }

    2--组合问题

    主要思路:

            基于回溯法,暴力枚举 k 个数,需注意回溯弹出元素的操作;

    1. #include
    2. #include
    3. class Solution {
    4. public:
    5. std::vectorint>> combine(int n, int k) {
    6. std::vector<int> path;
    7. backTracking(n, k, path, 1); // 从第 1 个数开始
    8. return res;
    9. }
    10. void backTracking(int n, int k, std::vector<int> path, int start){
    11. if(path.size() == k){
    12. res.push_back(path);
    13. return;
    14. }
    15. for(int i = start; i <= n; i++){
    16. path.push_back(i);
    17. backTracking(n, k, path, i + 1); // 递归暴力搜索下一个数
    18. path.pop_back(); // 回溯
    19. }
    20. }
    21. private:
    22. std::vectorint>> res;
    23. };
    24. int main(int argc, char* argv[]){
    25. int n = 4, k = 2;
    26. Solution S1;
    27. std::vectorint>> res = S1.combine(n, k);
    28. for(auto v : res){
    29. for(int item : v) std::cout << item << " ";
    30. std::cout << std::endl;
    31. }
    32. return 0;
    33. }

    3--组合问题的剪枝操作

            上题的组合问题中,对于进入循环体 for(int i = start; i <= n; i++):

    已选择的元素数量为:path.size()

    仍然所需的元素数量为:k - path.size()

    剩余的元素集合为:n - i + 1

    则为了满足要求,必须满足:k-path.size() <= n - i + 1,即 i <= n - k + path.size() + 1

    因此,可以通过以下条件完成剪枝操作:

    for(int i = start; i <= i <= n - k + path.size() + 1; i++)

    1. #include
    2. #include
    3. class Solution {
    4. public:
    5. std::vectorint>> combine(int n, int k) {
    6. std::vector<int> path;
    7. backTracking(n, k, path, 1); // 从第 1 个数开始
    8. return res;
    9. }
    10. void backTracking(int n, int k, std::vector<int> path, int start){
    11. if(path.size() == k){
    12. res.push_back(path);
    13. return;
    14. }
    15. for(int i = start; i <= n - k + path.size() + 1; i++){
    16. path.push_back(i);
    17. backTracking(n, k, path, i + 1); // 暴力下一个数
    18. path.pop_back(); // 回溯
    19. }
    20. }
    21. private:
    22. std::vectorint>> res;
    23. };
    24. int main(int argc, char* argv[]){
    25. int n = 4, k = 2;
    26. Solution S1;
    27. std::vectorint>> res = S1.combine(n, k);
    28. for(auto v : res){
    29. for(int item : v) std::cout << item << " ";
    30. std::cout << std::endl;
    31. }
    32. return 0;
    33. }

    4--组合总和III

    主要思路:

            类似于上面的组合问题,基于回溯来暴力枚举每一个数,需要注意剪枝操作;

    1. #include
    2. #include
    3. class Solution {
    4. public:
    5. std::vectorint>> combinationSum3(int k, int n) {
    6. std::vector<int> path;
    7. backTracking(k, n, 0, path, 1);
    8. return res;
    9. }
    10. void backTracking(int k, int n, int sum, std::vector<int>path, int start){
    11. if(sum > n) return; // 剪枝
    12. if(path.size() == k){ // 递归终止
    13. if(sum == n){
    14. res.push_back(path);
    15. }
    16. return;
    17. }
    18. for(int i = start; i <= 9 + path.size() - k + 1; i++){ // 剪枝
    19. path.push_back(i);
    20. sum += i;
    21. backTracking(k, n, sum, path, i + 1); // 递归枚举下一个数
    22. // 回溯
    23. sum -= i;
    24. path.pop_back();
    25. }
    26. }
    27. private:
    28. std::vectorint>> res;
    29. };
    30. int main(int argc, char* argv[]){
    31. int k = 3, n = 7;
    32. Solution S1;
    33. std::vectorint>> res = S1.combinationSum3(k, n);
    34. for(auto v : res){
    35. for(int item : v) std::cout << item << " ";
    36. std::cout << std::endl;
    37. }
    38. return 0;
    39. }

    5--电话号码的字母组合

    主要思路:

            根据传入的字符串,遍历每一个数字字符,基于回溯法,递归遍历每一个数字字符对应的字母;

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vector letterCombinations(std::string digits) {
    7. if(digits.length() == 0) return res;
    8. std::vector letter = {"", " ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    9. backTracking(digits, letter, 0);
    10. return res;
    11. }
    12. void backTracking(std::string digits, std::vector letter, int cur){
    13. if(cur == digits.size()){
    14. res.push_back(tmp);
    15. return;
    16. }
    17. int letter_idx = digits[cur] - '0';
    18. int letter_size = letter[letter_idx].size();
    19. for(int i = 0; i < letter_size; i++){
    20. tmp.push_back(letter[letter_idx][i]);
    21. backTracking(digits, letter, cur+1);
    22. // 回溯
    23. tmp.pop_back();
    24. }
    25. }
    26. private:
    27. std::vector res;
    28. std::string tmp;
    29. };
    30. int main(int argc, char* argv[]){
    31. std::string test = "23";
    32. Solution S1;
    33. std::vector res = S1.letterCombinations(test);
    34. for(std::string str : res) std::cout << str << " ";
    35. std::cout << std::endl;
    36. return 0;
    37. }

    6--组合总和

    主要思路:

            经典组合问题,通过回溯法暴力递归遍历;

    1. #include
    2. #include
    3. class Solution {
    4. public:
    5. std::vectorint>> combinationSum(std::vector<int>& candidates, int target) {
    6. if(candidates.size() == 0) return res;
    7. backTracking(candidates, target, 0, 0, path);
    8. return res;
    9. }
    10. void backTracking(std::vector<int>& candidates, int target, int sum, int start, std::vector<int>path){
    11. if(sum > target) return; // 剪枝
    12. if(sum == target) {
    13. res.push_back(path);
    14. return;
    15. }
    16. for(int i = start; i < candidates.size(); i++){
    17. sum += candidates[i];
    18. path.push_back(candidates[i]);
    19. backTracking(candidates, target, sum, i, path);
    20. // 回溯
    21. sum -= candidates[i];
    22. path.pop_back();
    23. }
    24. }
    25. private:
    26. std::vectorint>> res;
    27. std::vector<int> path;
    28. };
    29. int main(int argc, char* argv[]){
    30. // candidates = [2,3,6,7], target = 7
    31. std::vector<int> test = {2, 3, 6, 7};
    32. int target = 7;
    33. Solution S1;
    34. std::vectorint>> res = S1.combinationSum(test, target);
    35. for(auto vec : res){
    36. for(int val : vec) std::cout << val << " ";
    37. std::cout << std::endl;
    38. }
    39. return 0;
    40. }

    7--组合总和II

    主要思路:

            基于回溯法,暴力递归遍历数组;

            本题不能包含重复的组合,但由于有重复的数字,因此需要进行树层上的去重

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vectorint>> combinationSum2(std::vector<int>& candidates, int target) {
    7. if(candidates.size() == 0) return res;
    8. std::sort(candidates.begin(), candidates.end());
    9. std::vector<bool> visited(candidates.size(), false);
    10. backTracking(candidates, target, 0, 0, visited);
    11. return res;
    12. }
    13. void backTracking(std::vector<int>& candidates, int target, int sum, int start, std::vector<bool>& visited){
    14. if(sum > target) return; // 剪枝
    15. if(sum == target){
    16. res.push_back(path);
    17. return;
    18. }
    19. for(int i = start; i < candidates.size(); i++){
    20. // 树层剪枝去重
    21. if(i > 0 && candidates[i-1] == candidates[i]){
    22. if(visited[i-1] == false) continue;
    23. }
    24. sum += candidates[i];
    25. path.push_back(candidates[i]);
    26. visited[i] = true;
    27. backTracking(candidates, target, sum, i+1, visited);
    28. // 回溯
    29. sum -= candidates[i];
    30. path.pop_back();
    31. visited[i] = false;
    32. }
    33. }
    34. private:
    35. std::vectorint>> res;
    36. std::vector<int> path;
    37. };
    38. int main(int argc, char* argv[]){
    39. // candidates = [10,1,2,7,6,1,5], target = 8
    40. std::vector<int> test = {10, 1, 2, 7, 6, 1, 5};
    41. int target = 8;
    42. Solution S1;
    43. std::vectorint>> res = S1.combinationSum2(test, target);
    44. for(auto vec : res){
    45. for(int val : vec) std::cout << val << " ";
    46. std::cout << std::endl;
    47. }
    48. return 0;
    49. }

    8--分割回文串

    主要思路:

            基于回溯法,暴力加入子串,判断每一个子串是否是一个回文子串,如果不是回文子串则跳过,否则继续,直到将字符串的所有字符都遍历完;

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vector> partition(std::string s) {
    7. if(s.length() == 0) return res;
    8. backTracking(s, 0);
    9. return res;
    10. }
    11. void backTracking(std::string s, int startIdx){
    12. if(startIdx >= s.size()){
    13. res.push_back(tmp);
    14. return;
    15. }
    16. for(int i = startIdx; i < s.size(); i++){
    17. std::string str = s.substr(startIdx, i - startIdx + 1);
    18. if(is_valid(str) == false) continue; // 不合法的
    19. // 合法的
    20. tmp.push_back(str);
    21. backTracking(s, i+1);
    22. // 回溯
    23. tmp.pop_back();
    24. }
    25. }
    26. // 判断是否是回文子串
    27. bool is_valid(std::string str){
    28. for(int i = 0, j = str.size()-1; i <= j; i++, j--){
    29. if(str[i] != str[j]) return false;
    30. }
    31. return true;
    32. }
    33. private:
    34. std::vector> res;
    35. std::vector tmp;
    36. };
    37. int main(int argc, char* argv[]){
    38. // s = "aab"
    39. std::string str = "aab";
    40. Solution S1;
    41. std::vector> res = S1.partition(str);
    42. for(auto vec : res){
    43. for(std::string s : vec) std::cout << s << " ";
    44. std::cout << std::endl;
    45. }
    46. return 0;
    47. }

    9--复原 IP 地址

    主要思路:

            基于回溯法,递归遍历数字字符串,需要判断数字字符串是否合法;

            递归终止条件是当前加入的 ‘.’ 号已经为 3 个了,这时还需要判断最后一个数字字符串是否合法;

            比较难的地方可能在于判断字符是否有效;

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vector restoreIpAddresses(std::string s) {
    7. if(s.length() < 4 || s.length() > 12) return res; // 剪枝
    8. backTracking(s, 0, 0);
    9. return res;
    10. }
    11. void backTracking(std::string s, int start_inx, int numpoints){
    12. if(numpoints == 3){
    13. std::string str = s.substr(start_inx, s.length() - start_inx);
    14. if(isvalid(str)){
    15. res.push_back(s);
    16. return;
    17. }
    18. }
    19. for(int i = start_inx; i < s.length(); i++){
    20. std::string str = s.substr(start_inx, i - start_inx + 1);
    21. if(isvalid(str) == false) break;
    22. s.insert(s.begin() + i + 1, '.'); // 插入 '.'
    23. numpoints += 1;
    24. backTracking(s, i + 2, numpoints); // 从 i + 2 开始,因为新加入了一个 '.'字符
    25. // 回溯
    26. s.erase(s.begin() + i + 1);
    27. numpoints -= 1;
    28. }
    29. }
    30. bool isvalid(std::string str){
    31. int len = str.length();
    32. if(len <= 0 || len > 3) return false;
    33. if (str[0] == '0' && len > 1) { // 不合法
    34. return false;
    35. }
    36. int num = 0;
    37. for(int i = 0; i < len; i++){
    38. num = num * 10 + (str[i] - '0');
    39. if(num > 255) return false;
    40. }
    41. return true;
    42. }
    43. private:
    44. std::vector res;
    45. int numpoints = 0;
    46. };
    47. int main(int argc, char* argv[]){
    48. // s = "25525511135"
    49. std::string test = "25525511135";
    50. Solution S1;
    51. std::vector res = S1.restoreIpAddresses(test);
    52. for(auto str : res) std::cout << str << " ";
    53. std::cout << std::endl;
    54. return 0;
    55. }

    10--子集

    主要思路:

            基于回溯法,暴力遍历加入每一个元素,每加入一个元素就收获一次结果;

    1. #include
    2. #include
    3. class Solution {
    4. public:
    5. std::vectorint>> subsets(std::vector<int>& nums) {
    6. dfs(nums, 0);
    7. return res;
    8. }
    9. void dfs(std::vector<int>& nums, int start_idx){
    10. if(start_idx > nums.size()) return; // 可以删去
    11. res.push_back(path);
    12. for(int i = start_idx; i < nums.size(); i++){
    13. path.push_back(nums[i]);
    14. dfs(nums, i+1);
    15. // 回溯
    16. path.pop_back();
    17. }
    18. }
    19. private:
    20. std::vectorint>> res;
    21. std::vector<int> path;
    22. };
    23. int main(int argc, char* argv[]){
    24. // nums = [1,2,3]
    25. std::vector<int> nums = {1, 2, 3};
    26. Solution S1;
    27. std::vectorint>> res = S1.subsets(nums);
    28. for(auto vec : res){
    29. for(auto val : vec) std::cout << val << " ";
    30. std::cout << std::endl;
    31. }
    32. return 0;
    33. }

    11--子集II

    主要思路:
            类似于上题的子集问题,暴力遍历每一个元素,每加入一个元素收获一次结果;

            需要注意的是,本题需要去重,因此采用类似组合问题的去重逻辑:先对数组进行排序,再进行树层上的去重;

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vectorint>> subsetsWithDup(std::vector<int>& nums) {
    7. std::sort(nums.begin(), nums.end());
    8. std::vector<bool> visited(nums.size(), false);
    9. dfs(nums, 0, visited);
    10. return res;
    11. }
    12. void dfs(std::vector<int>& nums, int start_idx, std::vector<bool>& visited){
    13. if(start_idx > nums.size()) return; // 可以省略
    14. res.push_back(path);
    15. for(int i = start_idx; i < nums.size(); i++){
    16. // 树层上去重
    17. if(i > 0 && nums[i-1] == nums[i] && visited[i-1] == false){
    18. continue;
    19. }
    20. path.push_back(nums[i]);
    21. visited[i] = true;
    22. dfs(nums, i+1, visited);
    23. // 回溯
    24. path.pop_back();
    25. visited[i] = false;
    26. }
    27. }
    28. private:
    29. std::vectorint>> res;
    30. std::vector<int> path;
    31. };
    32. int main(int argc, char* argv[]){
    33. // nums = [1,2,2]
    34. std::vector<int> nums = {1, 2, 2};
    35. Solution S1;
    36. std::vectorint>> res = S1.subsetsWithDup(nums);
    37. for(auto vec : res){
    38. for(auto val : vec) std::cout << val << " ";
    39. std::cout << std::endl;
    40. }
    41. return 0;
    42. }

    12--递增子序列

    主要思路:

            基于回溯法,暴力遍历每一个元素;

            判断一个元素是否可以加入路径的条件:元素大于路径的最后一个结点(保证递增);因为有重复的元素,因此需要在树层上进行去重,树层去重需要判断当前元素是否在遍历之前出现过,如果出现过则舍弃;

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vectorint>> findSubsequences(std::vector<int>& nums) {
    7. if(nums.size() == 0) return res;
    8. backTracking(nums, 0);
    9. return res;
    10. }
    11. void backTracking(std::vector<int>& nums, int start_idx){
    12. if(path.size() > 1){
    13. res.push_back(path); // 每一层递归加入一个结果
    14. }
    15. std::set<int> my_set; // 每一层递归新建一个set
    16. for(int i = start_idx; i < nums.size(); i++){
    17. if(path.size() > 0 && nums[i] < path.back() || my_set.find(nums[i]) != my_set.end()){ // 树层上去重
    18. continue;
    19. }
    20. path.push_back(nums[i]);
    21. my_set.insert(nums[i]);
    22. backTracking(nums, i+1);
    23. // 回溯
    24. path.pop_back();
    25. }
    26. }
    27. private:
    28. std::vectorint>> res;
    29. std::vector<int> path;
    30. };
    31. int main(int argc, char* argv[]){
    32. // nums = [4,6,7,7]
    33. std::vector<int> nums = {4, 6, 7, 7};
    34. Solution S1;
    35. std::vectorint>> res = S1.findSubsequences(nums);
    36. for(auto vec : res){
    37. for(int val : vec) std::cout << val << " ";
    38. std::cout << std::endl;
    39. }
    40. return 0;
    41. }

    13--全排列

    主要思路:

            基于回溯法,暴力遍历每一个元素;由于是排列,因此结果的元素数量肯定与数组大小相同;

            每一轮递归,都需要从索引 0 开始遍历;使用一个数组来记录当前元素是否被访问过;

    1. #include
    2. #include
    3. class Solution {
    4. public:
    5. std::vectorint>> permute(std::vector<int>& nums) {
    6. if(nums.size() == 0) return res;
    7. std::vector<bool> visited(nums.size(), false);
    8. backTracking(nums, visited);
    9. return res;
    10. }
    11. void backTracking(std::vector<int>& nums, std::vector<bool>& visited){
    12. if(path.size() == nums.size()){
    13. res.push_back(path);
    14. return;
    15. }
    16. for(int i = 0; i < nums.size(); i++){
    17. if(visited[i] == true) continue;
    18. path.push_back(nums[i]);
    19. visited[i] = true;
    20. backTracking(nums, visited);
    21. // 回溯
    22. visited[i] = false;
    23. path.pop_back();
    24. }
    25. }
    26. private:
    27. std::vectorint>> res;
    28. std::vector<int> path;
    29. };
    30. int main(int argc, char* argv[]){
    31. // nums = [1,2,3]
    32. std::vector<int> nums = {1, 2, 3};
    33. Solution S1;
    34. std::vectorint>> res = S1.permute(nums);
    35. for(auto vec : res){
    36. for(auto val : vec) std::cout << val << " ";
    37. std::cout << std::endl;
    38. }
    39. return 0;
    40. }

    14--全排列II

    主要思路:

            主要思路类似于上题的全排列,但本题的数组含有重复元素,因此需要进行树层上的去重(先对数组进行排序);

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vectorint>> permuteUnique(std::vector<int>& nums) {
    7. if(nums.size() == 0) return res;
    8. std::sort(nums.begin(), nums.end());
    9. std::vector<bool> visited(nums.size(), false);
    10. backTracking(nums, visited);
    11. return res;
    12. }
    13. void backTracking(std::vector<int>& nums, std::vector<bool>& visited){
    14. if(path.size() == nums.size()){
    15. res.push_back(path);
    16. return;
    17. }
    18. for(int i = 0; i < nums.size(); i++){
    19. if(i > 0 && nums[i-1] == nums[i] && visited[i-1] == false) continue; // 树层上去重
    20. if(visited[i] == true) continue; // 重复元素
    21. path.push_back(nums[i]);
    22. visited[i] = true;
    23. backTracking(nums, visited);
    24. // 回溯
    25. path.pop_back();
    26. visited[i] = false;
    27. }
    28. }
    29. private:
    30. std::vectorint>> res;
    31. std::vector<int> path;
    32. };
    33. int main(int argc, char* argv[]){
    34. // nums = [1,1,2]
    35. std::vector<int> nums = {1, 1, 2};
    36. Solution S1;
    37. std::vectorint>> res = S1.permuteUnique(nums);
    38. for(auto vec : res){
    39. for(auto val : vec) std::cout << val << " ";
    40. std::cout << std::endl;
    41. }
    42. return 0;
    43. }

    15--N皇后

    主要思路:

            基于回溯法,递归每一行,暴力枚举每一列是否适合放皇后;

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. std::vector> solveNQueens(int n) {
    7. std::vector board(n, std::string(n, '.'));
    8. backTracking(n, 0, board);
    9. return res;
    10. }
    11. void backTracking(int n, int row, std::vector& board){
    12. if(row == n){
    13. res.push_back(board);
    14. return;
    15. }
    16. for(int col = 0; col < n; col++){
    17. if(isValid(board, row, col)){ // [row, col]可以放一个皇后
    18. board[row][col] = 'Q';
    19. backTracking(n, row+1, board);
    20. // 回溯
    21. board[row][col] = '.';
    22. }
    23. }
    24. }
    25. bool isValid(const std::vector& board, int row, int col){
    26. // 检查行
    27. for(int i = 0; i < row; i++){
    28. if(board[i][col] == 'Q') return false;
    29. }
    30. // 检查列
    31. for(int i = 0; i < board.size(); i++){
    32. if(board[row][i] == 'Q') return false;
    33. }
    34. // 检查主对角线
    35. for(int i = row - 1, j = col - 1; i >=0 && j >=0; i--, j--){
    36. if(board[i][j] == 'Q') return false;
    37. }
    38. // 检查反对角线
    39. for(int i = row - 1, j = col + 1; i >= 0 && j <= board.size(); i--, j++){
    40. if(board[i][j] == 'Q') return false;
    41. }
    42. return true;
    43. }
    44. private:
    45. std::vector> res;
    46. };
    47. int main(int argc, char* argv[]){
    48. // n = 4
    49. int n = 4;
    50. Solution S1;
    51. std::vector> res = S1.solveNQueens(n);
    52. for(auto vec : res){
    53. for(auto val : vec) std::cout << val << " ";
    54. std::cout << std::endl;
    55. }
    56. return 0;
    57. }

    16--解数独

    主要思路:

            基于回溯法,两层循环分别判断行和列,枚举 9 个数是否适合加入到当前行和列;

    1. #include
    2. #include
    3. #include
    4. class Solution {
    5. public:
    6. void solveSudoku(std::vectorchar>>& board) {
    7. backTracking(board);
    8. }
    9. bool backTracking(std::vectorchar>>& board){
    10. for(int row = 0; row < board.size(); row++){
    11. for(int col = 0; col < board[0].size(); col++){
    12. if(board[row][col] == '.'){
    13. for(char k = '1'; k <= '9'; k++){
    14. if(isValid(board, row, col, k)){
    15. board[row][col] = k;
    16. if(backTracking(board) == true){ // 递归
    17. return true;
    18. }
    19. // 回溯
    20. board[row][col] = '.';
    21. }
    22. }
    23. return false; // 尝试了 9 个数也不能递归返回 true, 就返回 false
    24. }
    25. }
    26. }
    27. return true; // 遍历完没有返回 false,说明找到的合适棋盘
    28. }
    29. bool isValid(const std::vectorchar>>& board, int row, int col, char val){
    30. // 检查同一行
    31. for(int i = 0; i < board[0].size(); i++){
    32. if(board[row][i] == val) return false;
    33. }
    34. // 检查同一列
    35. for(int i = 0; i < board.size(); i++){
    36. if(board[i][col] == val) return false;
    37. }
    38. // 检查九宫格
    39. int startRow = (row / 3) * 3;
    40. int startCol = (col / 3) * 3;
    41. for (int i = startRow; i < startRow + 3; i++){ // 判断九宫格内是否重复
    42. for (int j = startCol; j < startCol + 3; j++){
    43. if (board[i][j] == val){
    44. return false;
    45. }
    46. }
    47. }
    48. return true;
    49. }
    50. };
    51. int main(int argc, char* argv[]){
    52. std::vectorchar>> board = {{'5', '3', '.', '.', '7', '.', '.', '.', '.'},
    53. {'6', '.', '.', '1', '9', '5', '.', '.', '.'},
    54. {'.', '9', '8', '.', '.', '.', '.', '6', '.'},
    55. {'8', '.', '.', '.', '6', '.', '.', '.', '3'},
    56. {'4', '.', '.', '8', '.', '3', '.', '.', '1'},
    57. {'7', '.', '.', '.', '2', '.', '.', '.', '6'},
    58. {'.', '6', '.', '.', '.', '.', '2', '8', '.'},
    59. {'.', '.', '.', '4', '1', '9', '.', '.', '5'},
    60. {'.', '.', '.', '.', '8', '.', '.', '7', '9'}};
    61. Solution S1;
    62. S1.solveSudoku(board);
    63. for(auto vec : board){
    64. for(auto val : vec) std::cout << val << " ";
    65. std::cout << std::endl;
    66. }
    67. return 0;
    68. }

  • 相关阅读:
    Promise简(resolve,reject,catch)
    Charles抓包工具的基本操作
    Aspose.Cells for Python via .NET crack
    JS/CSS 交互
    【frida实战】“一行”代码教你获取WeGame平台中所有的lua脚本
    竹间智能用认知智能为企业的发展提供助力
    如何借助边缘智能网关打造智慧城市便民驿站
    Win11系统电脑怎么C盘扩容教学
    MySQL - 如何判断一行扫描数?
    java18-枚举类和注解
  • 原文地址:https://blog.csdn.net/weixin_43863869/article/details/132722009