第36题:有效的数独

解题思路

36. 有效的数独
题目要求判断九宫格中的任意数字在它所在行、列以及3*3宫格内只出现一次
可以使用以下三种方法解决:

  1. 使用哈希表HashSet、List(ArrayList和LinkedList)
  2. 使用boolean数组
  3. 使用比特进行位运算

代码

方法一:使用哈希表HashSet
//运行时间:3ms  内存消耗:38.4MB
class Solution {
    public boolean isValidSudoku(char[][] board) {
        //把九行、九列、九个九宫格都用Set数组表示。此外可以把Set数组换成List数组
        Set<Character>[] rows = new Set[9];
        Set<Character>[] cols = new Set[9];
        Set<Character>[] boxes = new Set[9];
        for(int i=0;i<9;i++){
            rows[i] = new HashSet<>();  //如果使用List数组,那么HashSet换成ArrayList或LinkedList
            cols[i] = new HashSet<>(); 
            boxes[i] = new HashSet<>();
        }
         for(int row=0; row<9; row++){
             for(int col=0 ; col<9; col++){
                 char num = board[row][col];
                 if(num == '.') continue;
                 if(rows[row].contains(num)) return false;
                 if(cols[col].contains(num)) return false;
                 int boxIndex = (row/3)*3+col/3;
                 if(boxes[boxIndex].contains(num)) return false;

                 rows[row].add(num);
                 cols[col].add(num);
                 boxes[boxIndex].add(num);
             }
         }
         return true;
    }
}
方法二:使用boolean数组
//运行时间:2ms  内存消耗:38.7MB
class Solution {
    public boolean isValidSudoku(char[][] board) {
        //把九行、九列、九个九宫格都用二维布尔数组表示  不需要额外初始化,默认起始值为false
         boolean[][] rows = new boolean[9][9];
         boolean[][] cols = new boolean[9][9];
         boolean[][] boxes = new boolean[9][9];

         for(int row=0; row<9; row++){
             for(int col=0 ; col<9; col++){
                 char num = board[row][col];
                 if(num == '.') continue;
                 num = (char)(num-'1');  //eg:5放到rows[row][4]、cols[col][4]、boxes[boxIndex][4]
                 if(rows[row][num]) return false;
                 if(cols[col][num]) return false;
                 int boxIndex = (row/3)*3+col/3;
                 if(boxes[boxIndex][num]) return false;

                 rows[row][num] = true;
                 cols[col][num] = true;
                 boxes[boxIndex][num] = true;
             }
         }
         return true;
    }
}
方法三:使用比特进行位运算

在该方法中要注意:

Java中byte、short、char在进行运算时会自动转换为int再进行运算,它们进行运算返回的结果为int型。

①使用short类型存储9个数值,因为short类型为16个字节>9个字节,可以存储9个数值的状态:出现过为1,未出现过为0。

//运行时间:1ms  内存消耗:38.2MB
class Solution {
    public boolean isValidSudoku(char[][] board) {
        //把九行、九列、九个九宫格都用short类型表示,因为short类型为16个字节>9个字节
         short[] rows = new short[9];
         short[] cols = new short[9];
         short[] boxes = new short[9];

         for(int row=0; row<9; row++){
             for(int col=0 ; col<9; col++){
                 char num = board[row][col];
                 if(num == '.') continue;
                 num = (char)(1<<(num - '1'));//int->char
                 if((rows[row]&num)!=0) return false;
                 if((cols[col]&num)!=0) return false;
                 int boxIndex = (row/3)*3+col/3;
                 if((boxes[boxIndex]&num)!=0) return false;

                 rows[row] = (short)(rows[row] | num); //int->short
                 cols[col] =(short)(cols[col] | num);
                 boxes[boxIndex] =(short)(boxes[boxIndex] | num) ;
             }
         }
         return true;
    }
}

②使用char类型存储9个数值,因为char类型同样为16个字节>9个字节,可以存储9个数值的状态:出现过为1,未出现过为0。

class Solution {
//运行时间:2ms  内存消耗:37.9MB
    public boolean isValidSudoku(char[][] board) {
        //把九行、九列、九个九宫格都用char类型表示,因为char类型为16个字节>9个字节
         char[] rows = new char[9];
         char[] cols = new char[9];
         char[] boxes = new char[9];

         for(int row=0; row<9; row++){
             for(int col=0 ; col<9; col++){
                 char num = board[row][col];
                 if(num == '.') continue;
                 num = (char)(1<<(num - '1'));
                 if((rows[row]&num)!=0) return false;
                 if((cols[col]&num)!=0) return false;
                 int boxIndex = (row/3)*3+col/3;
                 if((boxes[boxIndex]&num)!=0) return false;

                 rows[row] = (char)(rows[row] | num);
                 cols[col] =(char)(cols[col] | num);
                 boxes[boxIndex] =(char)(boxes[boxIndex] | num) ;
             }
         }
         return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值