
参考题解: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);
}
}
