参考题解: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; } } } }
解法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]; } }
没看懂
解法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); } }