Leetcode之查找(二)

目錄

9.set-matrix-zeroes

10.generate-parentheses

11.letter-combinations-of-a-phone-number

12.valid-sudoku

13.sudoku-solver


9.set-matrix-zeroes

題目:給定一個m*n的矩陣,如果有一個元素是0,就把該元素所在的行和列上的元素全置爲0,要求使用原地算法。

分析:最簡單的方法是分別用兩個list存儲元素爲0的行和列,再遍歷矩陣,如果該元素的行或者列在list中,就把其置爲0,但這種方法需要額外的存儲空間,而題意要求用原地算法,所以我們需採用另一種方法。我們可以用每行和每列的第一個元素作爲標記,這個標記用來表示這一行或者這一列是否需要賦零。首先遍歷整個矩陣,如果 matrix[i][j] == 0 就將第 i 行和第 j 列的第一個元素標記,但是由於第一行和第一列的標記都是 cell[0][0],所以需要一個額外的變量標記第一列是否需置爲零,同時用 cell[0][0] 繼續表示第一行的標記。

    public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        if(row == 0)
            return;
        boolean flag = false;//用於標記第一列是否要設置爲0
        int col = matrix[0].length;
        for(int i = 0;i < row;i++){
            if(matrix[i][0] == 0)
                flag = true;
            for(int j = 1;j < col;j++){
                if(matrix[i][j] == 0){//標記第i行和第j列的第一個元素爲0
                    matrix[i][0] = 0;matrix[0][j] = 0;
                }
            }
        }
        for(int i = 1;i < row;i++) {
            for (int j = 1; j < col; j++) {
                if(matrix[i][0] == 0 || matrix[0][j] == 0)
                    matrix[i][j] = 0;
            }
        }
        if(matrix[0][0] == 0){//第一行是否需要設置爲0
            for(int i = 1;i < col;i++)
                matrix[0][i] = 0;
        }
        if(flag){//第一列是否需要設置爲0
            for(int i = 0;i < row;i++)
                matrix[i][0] = 0;
        }
    }

10.generate-parentheses

題目:給出n對括號,請編寫一個函數來生成所有的由n對括號組成的合法組合。例如,給出n=3,解集爲:"((()))", "(()())", "(())()", "()(())", "()()()"

分析:回溯法。添加括號只有左括號和右括號兩種選擇,我們可以通過跟蹤到目前爲止放置的左括號和右括號的數目來保證序列的有效性,如果左括號數量小於n,可以放一個左括號;如果右括號數量小於左括號的數量,可以放一個右括號;而當右括號數量等於n時就得到了一個有效序列。

    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        if(n == 0)
            return result;
       f(0,0,n,"",result);
        return result;
    }

    private void f(int left, int right, int n,String cur, List<String> result) {
        if(right == n){
            result.add(cur);
            return;
        }
        if(left < n)
            f(left + 1,right,n,cur + "(",result);
        if(right < left)
            f(left,right+1,n,cur + ")",result);
    }

11.letter-combinations-of-a-phone-number

題目:給出一個僅包含數字的字符串,給出所有可能的字母組合。數字到字母的映射方式如下:(就像電話上數字和字母的映射一樣)。Input:Digit string "23"Output:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].注意:雖然上述答案是按字典序排列的,但你的答案可以按任意的順序給出。

分析:回溯法。先將對應的映射存入到map中或者String數組中,然後對於每個數字依次放入其中一個字母,通過回溯窮舉即可。

    String[] map = {" ","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    public List<String> letterCombinations(String digits) {
        List<String> result = new ArrayList<>();
        if(digits.length() == 0)
            return result;
        f(result,digits,new StringBuilder(),0);
        return result;
    }

    private void f(List<String> result, String digits,StringBuilder cur, int index) {
        if(index == digits.length()){
            result.add(cur.toString());
            return;
        }
        String s = map[digits.charAt(index) - '0'];
        for(int i = 0;i < s.length();i++){
            cur.append(s.charAt(i));
            f(result,digits,cur,index + 1);
            cur.deleteCharAt(cur.length() - 1);
        }
    }

12.valid-sudoku

題目:判斷一個 9x9 的數獨是否有效。數獨:數字 1-9 在每一行只能出現一次;數字 1-9 在每一列只能出現一次;數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

分析:按照從左往右、從上往下的順序遍歷一次board,只通過一次遍歷來判斷每一行、每一列、每個九宮格是否有相同的數字。因爲board中的整數限定在1到9的範圍內,因此可以分別建立哈希表(這裏採用二維數組)來存儲1-9在在行、列、九宮格上出現的次數。注意第i行第j列的數字在第(row / 3) * 3 + col / 3個子數獨。

   public boolean isValidSudoku(char[][] board) {
        int[][] row = new int[9][10];//第i行j的數量個數
        int[][] col = new int[9][10];
        int[][] cube = new int[9][10];
        for(int i = 0;i < 9;i++){
            for(int j = 0;j < 9;j++){
                if(board[i][j] == '.')
                    continue;
                int cur = board[i][j] - '0',box = i / 3 * 3 + j / 3;
                if(row[i][cur] == 1 || col[j][cur] == 1 || cube[box][cur] == 1)
                    return false;
                row[i][cur] = 1;
                col[j][cur] = 1;
                cube[box][cur] = 1;
            }
        }
        return true;
  }

13.sudoku-solver

題目:請編寫一個程序,給數獨中的剩餘的空格填寫上數字,空格用字符'.'表示,假設給定的數獨只有唯一的解法

分析:最簡單的方法是暴力法,對每個空格判斷寫入1-9是否符合數獨,符合則試着填入。這裏採用另一種優化的方法,跟上題類似,建立哈希表(這裏採用二維數組)來存儲1-9在在行、列、九宮格上是否出現,確定可用才填入,如果填充失敗就進行回溯。

   public void solveSudoku(char[][] board) {
        boolean[][] row = new boolean[9][10];//第i行中j是否出現
        boolean[][] col = new boolean[9][10];
        boolean[][] cube = new boolean[9][10];
        //初始化
        for(int i = 0;i < 9;i++)
            for(int j = 0;j < 9;j++)
                if(board[i][j] != '.'){
                    int num = board[i][j] - '0';
                    row[i][num] = true;col[j][num] = true;
                    cube[i/3*3+j/3][num] = true;
                }
        solveSudokuCore(board,row,col,cube,0);
    }

    private boolean solveSudokuCore(char[][] board, boolean[][] row, boolean[][] col, boolean[][] cube, int count) {
        if(count == 81)
            return true;
        int r = count / 9,c = count % 9;
        if(board[r][c] != '.')
            return solveSudokuCore(board,row,col,cube,count + 1);
        for(int i = 1;i <= 9;i++){//依次看1-9是否能填入
            int box = r / 3 * 3 + c / 3;
            if(!row[r][i] && !col[c][i] && !cube[box][i]){
                board[r][c] = (char)('0' + i);//試探
                row[r][i] = true;col[c][i] = true;cube[box][i] = true;
                if(solveSudokuCore(board,row,col,cube,count + 1))
                    return true;
                board[r][c] = '.';//回溯
                row[r][i] = false;col[c][i] = false;cube[box][i] = false;
            }
        }
        return false;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章