leetcode刷题——回溯算法(1)

目录

77题. 组合

216.组合总和III

17.电话号码的字母组合

39. 组合总和

40.组合总和II

131.分割回文串

93.复原IP地址

78.子集

90.子集II

491.非递减子序列

46.全排列

47.全排列 II

332.重新安排行程

51. N皇后

37. 解数独


回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案

回溯三部曲。

  • 回溯函数模板返回值以及参数
  • 回溯函数终止条件
  • 回溯搜索的遍历过程

回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

77题. 组合

力扣题目链接(opens new window)

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

剪纸:如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了

  1. 已经选择的元素个数:path.size();

  2. 还需要的元素个数为: k - path.size();

  3. 在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

class Solution {
    //有序集合List add addAll remove removeall contains isEmpty get set size indexOf clear
    //arraylist构造方法可以直接传入集合
        List<List<Integer>> res=new ArrayList();
        List<Integer> tem=new ArrayList();
    public List<List<Integer>> combine(int n, int k) {      
        back(n,k,1);
        return res;
    }
    public void back(int n , int k,int begin){
        if(tem.size()==k){
            res.add(new ArrayList(tem));
            return;
        }
        for(int i=begin;i<=n-(k-tem.size())+1;i++){
            tem.add(i);
            back(n,k,i+1);
            tem.remove(tem.size()-1);
        }

    }
}

216.组合总和III

力扣题目链接(opens new window)

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

  • 所有数字都是正整数。
  • 解集不能包含重复的组合。

示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]]

示例 2: 输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]

class Solution {
    public List<List<Integer>> res=new ArrayList();
    public LinkedList<Integer> tem=new LinkedList();
    //双链表实现了List和Deque接口。 实现所有可选列表操作,并允许所有元素(包括null 构造方法可以传入集合
    //addFirst addLast removeFirst  getFirst set
    //offer offerFirst peek peekFirst poll pollFirst
    public List<List<Integer>> combinationSum3(int k, int n) {
        back(k,n,1);
        return res;
    }
    public void back(int k,int n,int begin){
//只要达到k个数字,我们就判断剩下的n是为0 才添加进去,否则就不加入,并且都return
        if(tem.size()==k){
            if(n==0) res.add(new LinkedList(tem));
            return;
        }
        for(int i=begin;i<=9-(k-tem.size())+1;i++){
            tem.add(i);
            back(k,n-i,i+1);
            tem.removeLast();
        }
    }
}

17.电话号码的字母组合

力扣题目链接(opens new window)

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

本题每一个数字代表的是不同集合,也就是求不同集合之间的组合,不需要控制索引起始位置

前面2道题目 都是求同一个集合中的组合!需要控制起始元素,保证不重复

这里注意一下输入按键不是2-9的情况

class Solution {
    public String[] ss={"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    public List<String> res=new ArrayList();
    public StringBuilder tem=new StringBuilder();

    public List<String> letterCombinations(String digits) {
        
       if(digits==null||digits.length()==0) return res;
        back(0,digits);
        return res;
    }
    public void back(int begin,String digits){
    //digits长度就是搜索的深度
        if(tem.length()==digits.length()){
            res.add(new String(tem));
            return;
        }
        int index=digits.charAt(begin)-'0'-2;
        String str=ss[index];
        for(int i=0;i<str.length();i++){
            tem.append(str.charAt(i));
            back(begin+1,digits);
            tem.deleteCharAt(tem.length()-1);
        }
    }
}

39. 组合总和

力扣题目链接(opens new window)

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。

示例 1:

  • 输入:candidates = [2,3,6,7], target = 7,
  • 所求解集为: [ [7], [2,2,3] ]

示例 2:

  • 输入:candidates = [2,3,5], target = 8,
  • 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]
class Solution {
    public List<List<Integer>> res=new ArrayList();
    List<Integer> tem=new ArrayList();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        back(candidates,target,0);
        return res;
    }
    public void back(int[] candidates, int target,int begin){
        if(target==0){
            res.add(new ArrayList(tem));
            return;
        }
        // if(target<0) return; 
        for(int i=begin;i<candidates.length;i++){
            if(target-candidates[i]<0) continue;//剪纸
            tem.add(candidates[i]);
            //这里设置起始点在i 下次搜索还是可以取值i位置的数字
            //从而实现重复利用数字
            back(candidates,target-candidates[i],i);
            tem.remove(tem.size()-1);
        }
    }
}

40.组合总和II

力扣题目链接(opens new window)

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

说明: 所有数字(包括目标数)都是正整数。解集不能包含重复的组合。

class Solution {
    public List<List<Integer>> res =new ArrayList();
    public List<Integer> tem=new ArrayList();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        back(candidates,target,0);
        return res;
    }
    public void back(int[] candidates, int target,int begin){
        if(target==0){
            res.add(new ArrayList(tem));
            return;
        }
        for(int i=begin;i<candidates.length&&target-candidates[i]>=0;i++){
            //这里限制同一层中 从第二个节点开始 如果当前节点和上一个节点相同 那就不继续添加,
            //从而阻止重复
            if(i!=begin&&candidates[i]==candidates[i-1]) continue;
            tem.add(candidates[i]);
            back(candidates,target-candidates[i],i+1);
            tem.remove(tem.size()-1);
        }
    }
}

131.分割回文串

力扣题目链接(opens new window)

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回 s 所有可能的分割方案。

示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ]

class Solution {
    public List<List<String>> res =new ArrayList();
    public List<String> tem=new ArrayList();
    public List<List<String>> partition(String s) {
        back(s,0);
        return res;
    }
    //解题思路:每一层切割的遍历逻辑是 切割1,2,...,n个字符
    //到下一层又继续从左到右切割 例如 abcd  第一层 a ab abc abcd 第二层 (a,b/bc/bcd) (ab,c/cd) (abc,d)
    public void back(String s,int begin){
        if(begin==s.length()){
            res.add(new ArrayList(tem));
            return;
        }
        StringBuilder sb=new StringBuilder();
        for(int i=begin;i<s.length();i++){
            //第一种方法 逐步添加字符到sb 
            sb.append(s.charAt(i));
            if(!isPalindrome(sb.toString())) continue;

            //第二种方法 直接利用子字符串判断s.substring(begin,i+1)
            // if(!isPalindrome(s.substring(begin,i+1))) continue;

            tem.add(sb.toString());
            back(s,i+1);
            tem.remove(tem.size()-1);
        }
    }
    public boolean isPalindrome(String s){
        for(int i=0;i<s.length()/2;i++){
            if(s.charAt(i)!=s.charAt(s.length()-i-1)) return false;
        }
        return true;
    }
}

93.复原IP地址

力扣题目链接(opens new window)

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201" 和 "192.168.1.1" 是 有效的 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效的 IP 地址。

示例 1:

  • 输入:s = "25525511135"
  • 输出:["255.255.11.135","255.255.111.35"]
class Solution {
    public List<String> res=new ArrayList();
    public List<Integer> tem=new ArrayList();
    public List<String> restoreIpAddresses(String s) {
        if(s.length()<4||s.length()>12) return res;
        back(s,0);
        return res;
    }
    public void back(String s,int begin){
        if(tem.size()==4){
            StringBuilder str=new StringBuilder();
            if(begin==s.length()){
                for(Integer ss:tem){
                    str.append(ss+".");
                }
                str.deleteCharAt(str.length()-1);
                res.add(str.toString());
            } 
            return;
        }
        
        StringBuilder sb=new StringBuilder();
        //每次只会最多分割3个数字
        for(int i=begin;i<begin+3 &&i<s.length();i++){
            sb.append(s.charAt(i));
            //如果数字位数超过1且第一位为0 不合法
            if(sb.length()>1&&sb.charAt(0)=='0') continue;
            Integer num=Integer.parseInt(sb.toString());
            if(num>=0&&num<=255){
                tem.add(num);
                back(s,i+1);
                tem.remove(tem.size()-1);
            }
        }
    }
}

78.子集

力扣题目链接(opens new window)

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例: 输入: nums = [1,2,3] 输出: [ [3],   [1],   [2],   [1,2,3],   [1,3],   [2,3],   [1,2],   [] ]

class Solution {
    public List<List<Integer>> res=new ArrayList();
    public List<Integer> tem=new ArrayList();
    public List<List<Integer>> subsets(int[] nums) {
        back(nums,0);
        return res;
    }
    public void back(int[] nums,int begin){
        res.add(new ArrayList(tem));
        if(begin==nums.length) return;

        for(int i=begin;i<nums.length;i++){
            tem.add(nums[i]);
            back(nums,i+1);
            tem.remove(tem.size()-1);
        }
    }
}

90.子集II

力扣题目链接(opens new window)

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

  • 输入: [1,2,2]
  • 输出: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]

这道题目类似之前那个集合里面有重复数字的,那就需要在当前层判断

如果有相同的节点就只是处理一次

所以本道题目和上题基本一致,只不过需要先对数组排序,然后判断

class Solution {
    public List<List<Integer>> res=new ArrayList();
    public List<Integer> tem=new ArrayList();
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        //改动1 对数组排序
        Arrays.sort(nums);
        back(nums,0);
        return res;
    }
    public void back(int[] nums,int begin){
        res.add(new ArrayList(tem));
        if(begin==nums.length) return;

        for(int i=begin;i<nums.length;i++){
            //改动2 判断当前节点和上一个是否相同,注意第一个节点不做判断
            if(i!=begin&&nums[i]==nums[i-1]) continue;
            tem.add(nums[i]);
            back(nums,i+1);
            tem.remove(tem.size()-1);
        }
    }
}

491.非递减子序列

力扣题目链接(opens new window)

给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。

示例:

  • 输入: [4, 6, 7, 7]
  • 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

说明:

  • 给定数组的长度不会超过15。
  • 数组中的整数范围是 [-100,100]。
  • 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。
class Solution {

    public List<List<Integer>> res = new ArrayList();
    public List<Integer> tem = new ArrayList();

    public List<List<Integer>> findSubsequences(int[] nums) {

        back(nums, 0);
        return res;
    }

    public void back(int[] nums, int begin) {
        if (tem.size() > 1)
            res.add(new ArrayList(tem));
        // hashset方法 clear add remove
        if (begin >= nums.length)
            return;
        HashSet<Integer> map = new HashSet();
        for (int i = begin; i < nums.length; i++) {
            if (map.contains(nums[i]))
                continue;
            if (tem.size() != 0 && nums[i] < tem.get(tem.size() - 1))
                continue;
            map.add(nums[i]);
            tem.add(nums[i]);
            back(nums, i + 1);
            tem.remove(tem.size() - 1);

        }

    }
}

46.全排列

力扣题目链接(opens new window)

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

  • 输入: [1,2,3]
  • 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
//第一种方法
class Solution {
    public List<List<Integer>> res=new ArrayList();
    public List<Integer> tem=new ArrayList();
    HashSet<Integer> set=new HashSet();
    public List<List<Integer>> permute(int[] nums) {
        for(int i=0;i<nums.length;i++){
            set.add(nums[i]);
        }
        back();
        return res;
        
    }
    public void back(){
        if(set.size()==0) {
            res.add(new ArrayList(tem));
            return;
        }

        HashSet<Integer> sset=new HashSet(set);
        for(Integer num:sset){
            tem.add(num);
            set.remove(num);
            back();
            tem.remove(tem.size()-1);
            set.add(num);
        }
       
    }
}

//第二种方法
class Solution {
    public List<List<Integer>> res = new ArrayList();
    public List<Integer> tem = new ArrayList();
    boolean[] used;

    public List<List<Integer>> permute(int[] nums) {
        used = new boolean[nums.length];
        back(nums);
        return res;

    }

    public void back(int[] nums) {
        if (tem.size() == nums.length) {
            res.add(new ArrayList(tem));
            return;
        }

        for (int i = 0; i < nums.length; i++) {
            if (used[i])
                continue;
            used[i] = true;
            tem.add(nums[i]);
            back(nums);
            tem.remove(tem.size() - 1);
            used[i] = false;
        }

    }
}

47.全排列 II

力扣题目链接(opens new window)

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:

  • 输入:nums = [1,1,2]
  • 输出: [[1,1,2], [1,2,1], [2,1,1]]

示例 2:

  • 输入:nums = [1,2,3]
  • 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

这道题就需要控制每一层中不能重复回溯节点 利用used数组

关键:biguse是为了记录集合的数字只能使用一次,同一树枝只能用一次数字,所以是全局变量,需要回溯退回标记

used数组是用在每一层的for遍历中,所以每层都有一个局部变量used数组,标注当前层使用过的节点不能再继续使用

class Solution {
   
    public List<List<Integer>> res=new ArrayList();
    public List<Integer> tem=new ArrayList();
    boolean[] bigUse;
    public List<List<Integer>> permuteUnique(int[] nums) {
       
        bigUse=new boolean[nums.length];
        back(nums);
        return res;
        
    }
    public void back(int[] nums){
        if(tem.size()==nums.length) {
            res.add(new ArrayList(tem));
            return;
        }

        int[] used=new int[21];
        for (int i = 0; i < nums.length; i++) {
            
            if (used[nums[i]+10]==1||bigUse[i])
                continue;
            bigUse[i]=true;
            used[nums[i]+10] = 1;
            tem.add(nums[i]);
            back(nums);
            tem.remove(tem.size() - 1);
            bigUse[i]=false;
            
        }
       
    }
}

332.重新安排行程

力扣题目链接(opens new window)

给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始

思路 :利用一个map存储一个起点对应的多个终点的集合,map的key就是起点,val是又一个treemap有序数组,存储多个终点作为tmap的key  value是该终点的次数

因为会存在多个起点和终点都相同的情况。

首先遍历所有的数组把数据存入map,再进行back回溯

终止条件就是res的长度等于ticket数量+1

先取出res的最后一个元素作为key 去map搜索对应的全部终点作为for循环的集合

如果map不存在这个key就代表这个路径不可选,退回

如果存在就进行for遍历 遍历过程中,判断tmap的val是否为0,0代表该航班已经用完,跳过

定义新的treemap,把该终点的val减一 ,map也需要重新添加这个key,为了下一层循环控制使用次数

回溯需要注意

判断res的大小是否满足,满足就直接退出循环

不满足就恢复之前的情况,继续遍历for

恢复之前的情况需要注意重新添加tmap和map

class Solution {
    public List<String> res = new ArrayList();
    Map<String, TreeMap<String, Integer>> map = new HashMap();

    public List<String> findItinerary(List<List<String>> tickets) {
        for (List<String> ss : tickets) {
            String key = ss.get(0);
            TreeMap<String, Integer> tmap = map.getOrDefault(key, new TreeMap<String, Integer>());
            Integer tmapVal = tmap.getOrDefault(ss.get(1), 0);
            tmap.put(ss.get(1), tmapVal + 1);
            map.put(key, tmap);
        }
        res.add("JFK");
        back(tickets.size() + 1);
        return res;

    }

    public void back(int airLength) {
        if (res.size() == airLength)
            return;

        String key = res.get(res.size() - 1);
        if (!map.containsKey(key))
            return;
        Map<String, Integer> vals = map.get(key);
        for (Map.Entry<String, Integer> destination : vals.entrySet()) {
            String desKey = destination.getKey();
            Integer desVal = destination.getValue();
            if (desVal == 0)
                continue;

            // 定义新的tmap put key, 并且map重新 put key
            TreeMap<String, Integer> newVal = new TreeMap(vals);
            newVal.put(desKey, desVal - 1);
            map.put(key, newVal);
            res.add(desKey);
            back(airLength);
            if (res.size() != airLength) {
                res.remove(res.size() - 1);
                // 回溯,恢复tmap和map的原来的key
                newVal.put(desKey, desVal);
                map.put(key, newVal);
            } else
                break;
        }

    }
}

51. N皇后

力扣题目链接(opens new window)

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

used二维数组记录每个位置使用情况

used2一维数组记得每一列的使用情况,用于检查不同一列

back回溯中是一行一行放置Q的,所以已经控制一行中只有一个Q

回溯时需要判断是否满足对角线是否有Q,不仅仅是相邻的对角线元素,整个对角线都需要判断

并且我们只需要判断左上角和右上角,下面的行不用判断,因为我们是从第一行到最后一行放置的,后面的还没放,不用理会

每一行用stringbuilder添加字符串,利用setCharAt改变Q的位置

这道题还可以直接创建二维数组,放置Q的位置,最后再用String.copyValueOf(char[])创建string

class Solution {
    public List<List<String>> res = new ArrayList();
    public List<String> tem = new ArrayList();
    public boolean[][] used;
    public boolean[] used2;

    public List<List<String>> solveNQueens(int n) {
        used = new boolean[n][n];
        used2=new boolean[n];
        back(n, 0);
        return res;
    }

    public void back(int n, int j) {
        if (tem.size() == n) {
            res.add(new ArrayList(tem));
            return;
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append(".");
        }
        for (int i = 0; i < n; i++) {
            if(diag(j,i)) continue;
            if (used2[i])
                continue;
            sb.setCharAt(i, 'Q');
            used2[i] = true;
            used[j][i] = true;
            tem.add(sb.toString());
            back(n, j + 1);
            tem.remove(tem.size() - 1);
            used2[i] = false;
            used[j][i] = false;
            sb.setCharAt(i, '.');
        }
    }
    public boolean diag(int j,int i){
       
        //只需要检查左上角45度和右上角45度
        for(int jj=j-1,ii=i-1;jj>=0&&ii>=0;ii--,jj--){
            if(used[jj][ii]) return true;
        }
        for(int jj=j-1,ii=i+1;jj>=0&&ii>=0&&ii<used.length;ii++,jj--){
            if(used[jj][ii]) return true;
        }
        return false;
    }
}

第二种方法
class Solution {
    public List<List<String>> res = new ArrayList();
    public char[][] chessboard;
    public boolean[] used2;

    public List<List<String>> solveNQueens(int n) {
        used2 = new boolean[n];
        chessboard = new char[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                chessboard[i][j] = '.';
            }
        }
        back(n, 0);
        return res;
    }

    public void back(int n, int j) {
        if (j == n) {
            List<String> tem = new ArrayList();
            for (char[] ss : chessboard) {
                tem.add(String.copyValueOf(ss));
            }
            res.add(new ArrayList(tem));
            return;
        }

        for (int i = 0; i < n; i++) {
            if (diag(j, i))
                continue;
            if (used2[i])
                continue;
            chessboard[j][i] = 'Q';
            used2[i] = true;
            back(n, j + 1);
            used2[i] = false;
            chessboard[j][i] = '.';
        }
    }

    public boolean diag(int j, int i) {

        // 只需要检查左上角45度和右上角45度
        for (int jj = j - 1, ii = i - 1; jj >= 0 && ii >= 0; ii--, jj--) {
            if (chessboard[jj][ii] == 'Q')
                return true;
        }
        for (int jj = j - 1, ii = i + 1; jj >= 0 && ii >= 0 && ii < chessboard.length; ii++, jj--) {
            if (chessboard[jj][ii] == 'Q')
                return true;
        }
        return false;
    }
}

37. 解数独

力扣题目链接(opens new window)

编写一个程序,通过填充空格来解决数独问题。

一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 '.' 表示。

思路:逐个遍历二维数组填入数据,每次填写一个,都需要递归进入下一层,重复填充所有的二维数组空格数据,如果在填充过程中冲突,就返回false并且恢复数据为空值,层层回溯到最上面,更改数字填充(注意填充过程会出现1-9个数字都出现冲突的情况,返回false)

class Solution {  
    public void solveSudoku(char[][] board) {
        back(board);
    }

    public boolean back(char[][] board) {

        for (int r = 0; r < board.length; r++) {
            for (int c = 0; c < board[0].length; c++) {
                if (board[r][c] != '.')
                    continue;
                for (char i = '1'; i <= '9'; i++) {
                    if (isValid(r, c, i, board)) {
                        board[r][c] = i;
                        if (back(board))
                            return true;
                        // 这一步不能省略,因为可能会存在当前空格9个数字都不能填写,那就需要保持为空
                        board[r][c] = '.';
                    }

                }
                // 这一步不能省略,因为会存在当前空格9个数字都不能填写,说明需要回溯上上层返回false
                return false;

            }
        }

        return true;

    }

    public boolean isValid(int row, int col, char num, char[][] board) {
        for (int i = 0; i < board.length; i++) {
            if (board[row][i] == num)
                return false;
        }
        for (int j = 0; j < board.length; j++) {
            if (board[j][col] == num)
                return false;
        }
        int rr = row / 3;
        int cc = col / 3;
        for (int ii = rr * 3; ii < rr * 3 + 3; ii++) {
            for (int jj = cc * 3; jj < cc * 3 + 3; jj++) {
                if (board[ii][jj] == num)
                    return false;
            }
        }
        return true;

    }
}

回溯算法完结,*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值