36 Valid Sudoku

来源:互联网 发布:微信抢红包透视软件 编辑:程序博客网 时间:2024/06/05 10:55

接下来写两道题,Valid Sudoku 和 Sudoku Solver,分别是判断现有的九宫格是否符合要求,和 求出九宫格的解法。

Valid Sudoku 之前写过两次,第一次是很naive的写法,通过很new出一个新的array来检查duplicates的element,因为那时还不知道HashSet这么好用的东东。

第二次是用到了HashSet,并且学到一个很好用的方法,set.add() 会返回 boolean value,true代表没有出现过/添加成功,false表示已经有重复元素/添加失败。这非常好用!!但是还是有些地方可以再优化,比如我原有代码都是不管任何位置的点,都把该点所在的行列,和小方格中所有的位置都查一遍,这其实是可以优化的,因为在这之前的其实不需要查了,只要查之后的,这样应该会较大提高性能。

之前的代码如下,其实效率已经达到93%了,但是测试完今天的代码,虽然通过了,但是效率只有20-30%,回头一想,自己SB了,下面这个代码既然利用set那就是check整行,整列,整个box,一共用了9+9+9=27 次set,已经是最优解了,而我今天的方法其实还是按照 挨个 遍历的思路,没找到一个点,遍以这个点为参照去验证,实际上用了81次set,肯定慢呀。之前的高效率代码如下,其实已经非常清晰明了:

public class Solution {    public boolean isValidSudoku(char[][] board) {        HashSet<Character> set= new HashSet<Character>();                for(int i=0; i<9; i++){            set.clear();            for(int j=0; j<9; j++){                if( board[i][j]!= '.' && !set.add(board[i][j]) ) return false; // set.add()返回boolean,这里用在检查重复值非常巧妙            }        }        for(int i=0; i<9; i++){            set.clear();            for(int j=0; j<9; j++){                if( board[j][i]!= '.' && !set.add(board[j][i]) ) return false;            }        }        for(int i=0; i<9; i+=3){            for(int j=0; j<9; j+=3){                set.clear();                for(int x=i; x<i+3; x++){                    for(int y=j; y<j+3; y++){                        if( board[x][y]!= '.' && !set.add(board[x][y]) ) return false;                    }                }            }        }        return true;    }            // the following code need to allocate a new array, that is maybe why the program is so slow    /*    public boolean hasUniElem(char [] arr){        boolean[] check = new boolean[10]; // 10 digits!! not 9 digits        for(int i=0; i<arr.length; i++){            if(Character.isDigit(arr[i])){                if(check[Character.getNumericValue(arr[i])]==true) return false;                else if(check[Character.getNumericValue(arr[i])]==false) check[Character.getNumericValue(arr[i])]=true;            }        }        return true;    }        public char[] fetchColumn(char[][] board, int colNum){        char[] result = new char[9];        for(int i=0; i<9; i++){            result[i]=board[i][colNum];        }        return result;    }        public char[] fetchBox(char[][] board, int rowNum, int colNum){        char[] result = new char[9];        for(int i=rowNum; i<rowNum; i++){            for(int j=colNum; j<colNum+3; j++){            result[i]=board[i][j];            }        }        return result;    }*/}

今天的代码,效率其实不高,还是沿用了 每个点都检查 这样的 naive 思路,不提倡,还是整体考虑整行,整列,整box 更加有效

public class Solution {    public boolean isValidSudoku(char[][] board) {        for(int i=0; i<9; i++){            for(int j=0; j<9; j++){                if(!check(board, i, j)) return false;            }        }        return true;    }        public boolean check(char[][] board, int i, int j){        HashSet<Character> set = new HashSet<>();                for(int k=j; k<9; k++){            if(board[i][k]!='.' && !set.add(board[i][k])) return false;        }                set.clear();        for(int k=i; k<9; k++){            if(board[k][j]!='.' && !set.add(board[k][j])) return false;        }                set.clear();        for(int p=i; p<i/3*3+3; p++){            for(int q=j; q<j/3*3+3; q++){                if(board[p][q]!='.' && !set.add(board[p][q])) return false;            }        }                return true;    }}





0 0
原创粉丝点击