leetcode总结——矩阵

Z字符串
螺旋矩阵
矩阵置0
矩阵查找类型1
矩阵查找类型2

细胞生命
矩阵乘法

Z字符串
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:

L   C   I    R
E T O E S  I I G
E   D   H    N

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。

请你实现这个将字符串进行指定行数变换的函数:string convert(string s, int numRows);

示例 1:
输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”

示例 2:
输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:

L     D     R
E   O E   I I
E C   I H   N
T     S     G

解析:
1:表示二维数组的方式:List
行向量:List.add()
列向量:List.get(index).append
2:字符串转字符 .toCharArray()
字符转字符串:toString
Builder转字符串:toString
3:利用: if(row0||rownumRows-1)going=!going;
row+=going?1:-1;转化指针的移动方向

import java.util.*;
import java.lang.*;
class Solution {
    public String convert(String s, int numRows) {
        if(numRows==1)return s;
        List list=new LinkedList<>();
        for(int i=0;i

螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

示例 2:
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

解析:leetcode总结——矩阵_第1张图片
其中 if(h1

import java.lang.*;
import java.util.*;
class Solution {
    public List spiralOrder(int[][] matrix) {
        List list=new LinkedList<>();
        if(matrix.length==0||matrix[0].length==0)return list;
        int h1=0,h2=matrix.length-1;
        int w1=0,w2=matrix[0].length-1;
        while(h1<=h2&&w1<=w2){
            for(int i=w1;i<=w2;i++)list.add(matrix[h1][i]);
            for(int j=h1+1;j<=h2;j++)list.add(matrix[j][w2]);
            if(h1w1;p--)list.add(matrix[h2][p]);
            for(int q=h2;q>h1;q--)list.add(matrix[q][w1]);
            }
            h1++;w1++;h2--;w2--;
        }
        return list;
        
    }
}

旋转矩阵:
给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:

给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],

原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
示例 2:

给定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],

原地旋转输入矩阵,使其变为:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]

class Solution {
    public void rotate(int[][] matrix) {
    int len=matrix[0].length;
    for(int width=len,i=0;width>0;width=width-2,i++){
        for(int p=0;p

矩阵置0
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
示例 1:
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
示例 2:
输入:
[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]
输出:
[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]
解析:利用二次遍历矩阵

class Solution {
    public void setZeroes(int[][] matrix) {
        Listrow=new LinkedList<>();
        Listcol=new LinkedList<>();
        for(int i=0;i

矩阵查找
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
输出: true

示例 2:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
输出: false
解析:将二维矩阵转化一维矩阵 关键在于行列下标对应关系pivotElement = matrix[pivotIdx / n][pivotIdx % n];

class Solution {
  public boolean searchMatrix(int[][] matrix, int target) {
    int m = matrix.length;
    if (m == 0) return false;
    int n = matrix[0].length;
    // 二分查找
    int left = 0, right = m * n - 1;
    int pivotIdx, pivotElement;
    while (left <= right) {
      pivotIdx = (left + right) / 2;
      pivotElement = matrix[pivotIdx / n][pivotIdx % n];
      if (target == pivotElement) return true;
      else {
        if (target < pivotElement) right = pivotIdx - 1;
        else left = pivotIdx + 1;
      }
    }
  return false;  }}

矩阵查找类型2:
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。

解析:分治法

class Solution {
    private int[][] matrix;
    private int target;
    public boolean searchMatrix(int[][] matrix, int target) {
        this.matrix = matrix;
        this.target = target;
        if (matrix == null || matrix.length == 0) {
            return false;
        }

        return searchRec(0, 0, matrix[0].length-1, matrix.length-1);
    }
    private boolean searchRec(int left, int up, int right, int down) {
        if (left > right || up > down) {
            return false;
        } else if (target < matrix[up][left] || target > matrix[down][right]) {
            return false;
        }
        int mid = left + (right-left)/2;
        int row = up;
        while (row <= down && matrix[row][mid] <= target) {
            if (matrix[row][mid] == target) {
                return true;
            }
            row++;
        }
        return searchRec(left, row, mid-1, down) || searchRec(mid+1, up, right, row-1);
    }
}

解析:左下角开始的删边法

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        // start our "pointer" in the bottom-left
        int row = matrix.length-1;
        int col = 0;
        while (row >= 0 && col < matrix[0].length) {
            if (matrix[row][col] > target) {
                row--;
            } else if (matrix[row][col] < target) {
                col++;
            } else { // found it
                return true;
            }
        }

        return false;
    }
}
```

细胞生命
根据百度百科,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞具有一个初始状态 live(1)即为活细胞, 或 dead(0)即为死细胞。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:

如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
根据当前状态,写一个函数来计算面板上细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。
示例:
输入:
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
输出:
[
[0,0,0],
[1,0,1],
[0,1,1],
[0,1,0]
]

解析:
1:利用原地状态置换,也就是说新增状态-1,-2
2:将所有的if语句转化为?:表达式(精彩!!)
3:八方遍历的特殊写法top bottom left right

class Solution {
    public void gameOfLife(int[][] board) {
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[0].length; j++){
                board[i][j] = checkLoc(board, i, j);
            }
        }
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board[0].length; j++){
                board[i][j] = board[i][j] == 1 || board[i][j] == -2 ? 1 : 0;
            }
        }
    }

    public int checkLoc(int[][] board, int i, int j){
        int count = 0;
        int left = Math.max(j - 1, 0);
        int right = Math.min(j + 1, board[i].length - 1);
        int top = Math.max(i - 1, 0);
        int bottom = Math.min(i + 1, board.length - 1);
        for(int x = top; x <= bottom; x++){
            for(int y = left; y <= right; y++){
                count = board[x][y] == 1 || board[x][y] == -1 ? count + 1 : count;
            }
        }
        return board[i][j] == 1 ? (count == 3 || count == 4 ? 1 : -1) : (count == 3 ? -2 : 0);
    }
}

矩阵乘法:
给定两个稀疏矩阵 A 和 B,请你返回 AB。你可以默认 A 的列数等于 B 的行数。
请仔细阅读下面的示例。
示例:
输入:
A = [
[ 1, 0, 0],
[-1, 0, 3]
]
B = [
[ 7, 0, 0 ],
[ 0, 0, 0 ],
[ 0, 0, 1 ]
]
输出:

     |  1 0 0 |   | 7 0 0 |   |  7 0 0 |
AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 |
                  | 0 0 1 |
public class Solution {
    private Map> map(int[][] m) {
        Map> rows = new HashMap<>();
        for(int i=0; i cols = rows.get(i);
                if (cols == null) {
                    cols = new HashMap<>();
                    rows.put(i, cols);
                }
                cols.put(j, m[i][j]);
            }
        }
        return rows;
    }
    public int[][] multiply(int[][] A, int[][] B) {
        int[][] C = new int[A.length][B[0].length];
        Map> arows = map(A);
        Map> brows = map(B);
        for(int i: arows.keySet()) {
            Map acol = arows.get(i);
            for(int j: acol.keySet()) {
                Map bcol = brows.get(j);
                if (bcol == null) continue;
                int a = acol.get(j);
                for(int l: bcol.keySet()) {
                    C[i][l] += a * bcol.get(l);
                }
            }
        }
        return C;
    }
}

你可能感兴趣的:(Leetcode1)