zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    复制代码

  • 相关阅读:
    使用三星720n液晶显示器的体会
    昨天终于买显示器了
    2005525早上
    抵制日货的结果zt
    读写配置文件类
    递归 访问树节点
    IE条件注释
    闭包 页面渐变
    模块 替换HTML 字符实体(双引号、左右尖括号)
    闭包 查找节点序号
  • 原文地址:https://www.cnblogs.com/JasonPeng1/p/12118822.html
Copyright © 2011-2022 走看看