leetcode matrix专题

参考题解:https://leetcode-cn.com/problems/rotate-image/solution/xuan-zhuan-tu-xiang-by-leetcode/

解法1:

最容易理解

 

 

JAVA版

 

 

复制代码
class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        //transpose matrix
        for(int i = 0;i<n;i++){
            for(int j = i;j<n;j++){
                int tmp = matrix[j][i];
                matrix[j][i] = matrix[i][j];
                matrix[i][j] = tmp;
            }
        }
        //reverse each column in each row
        for(int i = 0;i<n;i++){
            for(int j = 0;j<n/2;j++){
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[i][n-j-1];
                matrix[i][n-j-1] = tmp;
            }
        }
    }
}
复制代码

 

 解法2:

 

 

 

复制代码
class Solution {
    public void rotate(int[][] matrix) {
        int len = matrix.length;
        for(int i=0;i<len/2;i++){
            int start = i;
            int end = len - i - 1;
            for(int j = 0;j<end - start;j++){
                int temp = matrix[start][start+j];
                matrix[start][start + j] = matrix[end-j][start];
                matrix[end - j][start] = matrix[end][end-j];
                matrix[end][end-j] = matrix[start+j][end];
                matrix[start+j][end] =temp;
            }
        }
    }
}
复制代码

 


 

2019-10-29

13:03:27

 

解法1: 

 

 

复制代码
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if(matrix.empty() || matrix[0].empty()) return{};
        vector<int> res;
        int m = matrix.size(), n = matrix[0].size();
        //确定上下左右四条边的位置
        int up = 0,down = m-1,left = 0,right = n-1;
        while(true){
            for(int i=left;i<=right;i++) res.push_back(matrix[up][i]);
            if(++up > down) break;
            for(int i=up;i<=down;i++) res.push_back(matrix[i][right]);
            if(--right<left) break;
            for(int i=right;i>=left;i--) res.push_back(matrix[down][i]);
            if(--down < up) break;
            for(int i=down;i>=up;i--) res.push_back(matrix[i][left]);
            if(++left > right) break;
        }
        return res;
    }
};
复制代码

 

 

解法1:

 

 

 JAVA版

复制代码
class Solution {
    public int[][] generateMatrix(int n) {
        int[][] arr = new int[n][n];
        int c = 1,j = 0;
        while(c <= n*n){
            for(int i=j;i<n-j;i++)
                arr[j][i] = c++;
            for(int i=j+1;i<n-j;i++)
                arr[i][n-j-1] = c++;
            for(int i=n-j-2;i>=j;i--)
                arr[n-j-1][i] = c++;
            for(int i=n-j-2;i>j;i--)
                arr[i][j] = c++;
            j++;
        }
        return arr;
    }
}
复制代码

解法2:
C++

 

 

复制代码
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        if(n == 0) return {{}};
        vector<vector<int>> res(n,vector<int>(n,0));
        int down = 0,up = n-1,left = 0,right = n-1;
        int itm = 1;
        while(left <= right && down <= up){
            for(int i=left;i<=right;i++) res[down][i] = itm++;
            for(int i=down+1;i<=up;i++) res[i][right] = itm++;
            for(int i=right-1;i>=left;i--) res[up][i] = itm++;
            for(int i=up-1;i>=down+1;i--) res[i][left] = itm++;
            down++;
            up--;
            left++;
            right--;
        }
        return res;
    }
};
复制代码

 

 

 解法1:

 

 

时间复杂度O(MN)

 

 

 

 

复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int R = matrix.length;
        int C = matrix[0].length;
        Set<Integer> rows = new HashSet<Integer>();
        Set<Integer> cols = new HashSet<Integer>();
        //Essentially,we mark the rows and columns that are to be made zero
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                if(matrix[i][j] == 0){
                    rows.add(i);
                    cols.add(j);
                }
            }
        }
        //Iterate over the array once again and using the rows and cols sets,
        //update the element
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                if(rows.contains(i) || cols.contains(j)){
                    matrix[i][j] = 0;
                }
            }
        }
    }
}
复制代码

解法2:

 

 

 

 

 

 

复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int MODIFIED = -1000000;
        int R = matrix.length;
        int C = matrix[0].length;
        for(int r = 0;r<R;r++){
            for(int c=0;c<C;c++){
                if(matrix[r][c] == 0){
                    for(int k = 0;k<C;k++){
                        if(matrix[r][k] != 0){
                            matrix[r][k] = MODIFIED;
                        }
                    }
                    for(int k=0;k<R;k++){
                        if(matrix[k][c] != 0){
                            matrix[k][c] = MODIFIED;
                        }
                    }
                }
            }
        }
        for(int r = 0;r<R;r++){
            for(int c = 0;c<C;c++){
                if(matrix[r][c] == MODIFIED){
                    matrix[r][c] = 0;
                }
            }
        }
    }
}
复制代码

 

 改进版:

 

 

 

 

复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
        boolean row0_flag = false;
        boolean col0_flag = false;
        //第一行是否有0
        for(int j=0;j<col;j++){
            if(matrix[0][j] == 0){
                row0_flag = true;
                break;
            }
        }
        //第一列是否有0
        for(int i=0;i<row;i++){
            if(matrix[i][0] == 0){
                col0_flag = true;
                break;
            }
        }
        //把第一行第一列作为标志位
        for(int i=1;i<row;i++){
            for(int j=1;j<col;j++){
                if(matrix[i][j]==0){
                    matrix[i][0] = matrix[0][j] = 0;
                }
            }
        }
        //置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(row0_flag){
            for(int j=0;j<col;j++){
                matrix[0][j] = 0;
            }
        }
        if(col0_flag){
            for(int i=0;i<row;i++){
                matrix[i][0] = 0;
            }
        }
    }
}
复制代码

 

 参考题解:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/ju-zhen-zhong-de-zui-chang-di-zeng-lu-jing-by-leet/

解法1:

普通DFS。超时

 

 

复制代码
class Solution {
    private static final int[][] dirs = {{0,1},{1,0},{0,-1},{-1,0}};
    private int m,n;
    public int longestIncreasingPath(int[][] matrix) {
        if(matrix.length == 0) return 0;
        m = matrix.length;
        n = matrix[0].length;
        int ans = 0;
        for(int i = 0;i<m;++i)
            for(int j = 0;j<n;++j)
                ans = Math.max(ans,dfs(matrix,i,j));
        return ans;
    }
    private int dfs(int[][] matrix,int i,int j){
        int ans = 0;
        for(int[] d : dirs){
            int x = i + d[0],y = j + d[1];
            if(0 <= x && x<m && 0 <= y && y<n && matrix[x][y] > matrix[i][j])
                ans = Math.max(ans,dfs(matrix,x,y));
        }
        return ++ans;
    }
}
复制代码

 

 

 

 

 

 

 

 DFS + 记忆化搜索

复制代码
class Solution {
    private static final int[][] dirs = {{0,1},{1,0},{0,-1},{-1,0}};
    private int m,n;
    public int longestIncreasingPath(int[][] matrix) {
        if(matrix.length == 0) return 0;
        m = matrix.length;
        n = matrix[0].length;
        int[][] cache = new int[m][n];
        int ans = 0;
        for(int i = 0;i<m;++i)
            for(int j = 0;j<n;++j)
                ans = Math.max(ans,dfs(matrix,i,j,cache));
        return ans;
    }
    private int dfs(int[][] matrix,int i,int j,int[][] cache){
        if(cache[i][j] != 0) return cache[i][j];
        for(int[] d : dirs){
            int x = i + d[0],y = j + d[1];
            if(0 <= x && x<m && 0 <= y && y<n && matrix[x][y] > matrix[i][j])
                cache[i][j] = Math.max(cache[i][j],dfs(matrix,x,y,cache));
        }
        return ++cache[i][j];
    }
}
复制代码

 

 

 

 具体见:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/ju-zhen-zhong-de-zui-chang-di-zeng-lu-jing-by-leet/

 

 参考题解:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/san-chong-jie-fa-by-jason-2-4/

没看懂


 

 解法1:

二分查找

 

 

复制代码
class Solution {
public:
    int bisearch(vector<int>& v,int t){
        int l = 0;
        int r = v.size()-1;
        while(l < r){
            int m = l + (r-l+1)/2;
            if(v[m] <= t)
                l = m;
            else
                r = m -1;
        }
        return l;
    }
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        if(matrix.empty()) return -1;
        int R = matrix.size();
        int C = matrix[0].size();
        int low = matrix[0][0];
        int high = matrix[R-1][C-1];
        while(low < high){
            int mid = low +(high-low)/2;
            int count = 0;
            for(int i=0;i<R;++i){
                if(matrix[i][0]<= mid){
                    count += bisearch(matrix[i],mid) + 1;
                }else{
                    break;
                }
            }
            if(count < k)
                low = mid + 1;
            else
                high = mid;
        }
        return high;
    }
};
复制代码

 

 解法2:

二分查找

复制代码
class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        int row = matrix.length;
        int col = matrix[0].length;
        int left = matrix[0][0];
        int right = matrix[row - 1][col - 1];
        while(left < right){
            //每次循环都保证第k小的数在start-end之间,
            int mid = (left + right) /2;
            //找二维矩阵中<= mid 的元素总个数
            int count = findNotBiggerThanMid(matrix,mid,row,col);
            if(count < k)
                left = mid + 1;
            else
                right = mid;
        }
        return right;
    }
    private int findNotBiggerThanMid(int[][] matrix,int mid,int row,int col){
        int i = row -1;
        int j= 0;
        int count = 0;
        while(i >= 0 && j < col){
            if(matrix[i][j] <= mid){
                count += i + 1;
                j++;
            }
            else
                i--;
        }
        return count;
    } 
}
复制代码

 


 

 

解法1:

从右上到左下

 

 

 

复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        if(matrix.size() == 0){
            return false;
        }
        int i = 0;
        int j = matrix[0].size()-1;
        while(i < matrix.size() && j>=0){
            if(matrix[i][j] == target)
                return true;
            if(matrix[i][j] < target)
                ++i;
            else
                --j;
        }
        return false;
    }
};
复制代码

 

 

 

解法1:DFS + 回溯

 

 

 

复制代码
class Solution {
public:
    int dir[4][4] = {{-1,0},{1,0},{0,-1},{0,1}};
    bool exist(vector<vector<char>>& board, string word) {
        int m = board.size();//几行
        int n = board[0].size();;//几列
        vector<vector<bool>> visited(m,vector<bool>(n));//是否被访问过
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(dfs(i,j,0,board,word,visited))
                    return true;
            }
        }
        return false;
    }
    bool dfs(int x,int y,int index,vector<vector<char>>& board,string &word,
             vector<vector<bool>>& visited){
        if(index == word.size()-1){
            return word[index] == board[x][y];
        }
        if(word[index] == board[x][y]){
            visited[x][y] = true;
            for(int i =0;i<4;i++){
                int new_x = x+dir[i][0];
                int new_y = y+dir[i][1];
                if(new_x >= 0 && new_x<board.size()&&new_y >= 0 &&new_y<board[0].size()
                  &&!visited[new_x][new_y])
                    if(dfs(new_x,new_y,index+1,board,word,visited))
                        return true;
                    
            }
            visited[x][y] = false; //回溯
        }
        return false;
    }
};
复制代码

解法2:

回溯+DFS

 

 

复制代码
class Solution {
    public boolean exist(char[][] board, String word) {
        boolean[][] visited = new boolean[board.length][board[0].length];
        for(int i=0;i<board.length;i++)
            for(int j=0;j<board[0].length;j++)
                if(word.charAt(0) == board[i][j] && backtrack(i,j,0,word,visited,board))
                    return true;
        return false;
    }
    private boolean backtrack(int i,int j,int idx,String word,boolean[][] visited,char[][] board){
        if(idx == word.length()) return true;
        if(i >= board.length || i<0 || j>=board[0].length || j<0 || board[i][j] != word.charAt(idx) || visited[i][j])
            return false;
        visited[i][j] = true;
        if(backtrack(i+1,j,idx+1,word,visited,board) || backtrack(i-1,j,idx+1,word,visited,board) || backtrack(i,j+1,idx+1,word,visited,board)||backtrack(i,j-1,idx+1,word,visited,board) )
            return true;
        visited[i][j] = false;//回溯
        return false;
        
    }
}
复制代码

 

 

解法1:

 

 

 

复制代码
public boolean isValidSudoku(char[][] board) {
        // 记录某行,某位数字是否已经被摆放
        boolean[][] row = new boolean[9][9];
        // 记录某列,某位数字是否已经被摆放
        boolean[][] col = new boolean[9][9];
        // 记录某 3x3 宫格内,某位数字是否已经被摆放
        boolean[][] block = new boolean[9][9];

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (board[i][j] != '.') {
                    int num = board[i][j] - '1';
                    int blockIndex = i / 3 * 3 + j / 3;
                    if (row[i][num] || col[j][num] || block[blockIndex][num]) {
                        return false;
                    } else {
                        row[i][num] = true;
                        col[j][num] = true;
                        block[blockIndex][num] = true;
                    }
                }
            }
        }
        return true;
    }
复制代码

解法2:

 

 

复制代码
    public boolean isValidSudoku(char[][] board) {
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j] == '.') continue;
                for(int k =8;k>j;k--){
                    if(board[i][j] == board[i][k])
                        return false;
                }
                for(int k=8;k>i;k--){
                    if(board[i][j]==board[k][j])
                        return false;
                }
                for(int k=i+1;k%3!=0;k++){
                    for(int h = j/3*3;h<j/3*3 + 3;h++){
                        if(board[i][j] == board[k][h])
                            return false;
                    }
                }
            }
        }
        return true;
    }
复制代码

解法3:

C++

 

 

复制代码
class Solution {
public:
   bool isValidSudoku(vector<vector<char>>& board) {
        vector<vector<int>> rows(9, vector<int>(10, 0));//共9行,每行10个数字对应0~9
        vector<vector<int>> cols(9, vector<int>(10, 0));//9列
        vector<vector<int>> cell(9, vector<int>(10, 0));//9个单元格
        for (int i = 0; i < 9; ++i) {
            for (int j = 0; j < 9; ++j) {
                if(board[i][j]=='.') continue;
                int e = board[i][j] - '0';
                if (rows[i][e] == 0) rows[i][e]++;
                else return false; //如果有重复的直接返回false
                if (cols[j][e] == 0) cols[j][e]++;
                else return false;
                int ci = map(i, j);
                if (cell[ci][e] == 0) cell[ci][e]++;
                else return false;
            }
        }
        return true;
    }
    int map(int i, int j) {
        int a = i / 3;
        int b = j / 3;
        return a + b * 3;
    }
};
复制代码

 

 

参考题解:https://leetcode-cn.com/problems/sudoku-solver/solution/jie-shu-du-by-leetcode/

 

 

 

复制代码
class Solution {
    //box size
    int n = 3;
    //row size
    int N = n * n;
    
    int[][] rows = new int[N][N+1];
    int[][] columns = new int[N][N+1];
    int[][] boxes = new int[N][N+1];
    char[][] board;
    boolean sudokuSolved = false;
    
    public boolean couldPlace(int d,int row,int col){
        int idx = (row/n)*n + col/n;
        return rows[row][d] + columns[col][d] + boxes[idx][d] == 0;
    }
    
    public void placeNumber(int d,int row,int col){
        int idx = (row/n)*n + col/n;
        rows[row][d]++;
        columns[col][d]++;
        boxes[idx][d]++;
        board[row][col] = (char)(d+'0');
    }
    public void removeNumber(int d,int row,int col){
        int idx = (row/n)*n + col/n;
        rows[row][d]--;
        columns[col][d]--;
        boxes[idx][d]--;
        board[row][col]= '.';
    }
    public void placeNextNumbers(int row,int col){
        if((col == N-1) && (row == N-1)){
            sudokuSolved = true;
        }
        else{
            if(col == N-1) backtrack(row + 1,0);
            else backtrack(row,col+1);
        }
    }
    public void backtrack(int row,int col){
        if(board[row][col] == '.'){
            for(int d = 1;d<10;d++){
                if(couldPlace(d,row,col)){
                    placeNumber(d,row,col);
                    placeNextNumbers(row,col);
                    if(!sudokuSolved) removeNumber(d,row,col);//回溯
                }
            }
        }
        else placeNextNumbers(row,col);
    }
    public void solveSudoku(char[][] board) {
        this.board = board;
        for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        char num = board[i][j];
        if (num != '.') {
          int d = Character.getNumericValue(num);
          placeNumber(d, i, j);
        }
      }
    }
        backtrack(0,0);
    }
}
复制代码

posted @ 2019-12-30 11:32  JasonPeng1  阅读(247)  评论(0编辑  收藏  举报