# 0418【LeetCode 算法笔记】Task02 数组基础

28 阅读7分钟

参考资料:

开源内容:github.com/datawhalech…

电子网站:datawhalechina.github.io/leetcode-no…

image.png ————————————

增删改查

O(1):尾部增、尾部删、访问

O(n): 改、查找、中间插入、删除中间、

🚩 ——Day3

66. 加一

class Solution: # O(n) O(1)
    def plusOne(self, digits: List[int]) -> List[int]:
        n = len(digits)
        # 直接构造
        left = n - 1 
        while left >= 0 and digits[left] == 9:
            digits[left] = 0
            left -= 1

        if left == -1:
            return [1] + digits 

        digits[left] += 1
        return digits
class Solution {// O(n) O(1)
public:
    vector<int> plusOne(vector<int>& digits) {
        int n = digits.size();
        int left = n - 1; // 连续为 9 的最左侧索引
        while (left >= 0 && digits[left] == 9){
            digits[left] = 0;
            --left;
        }

        if (left == -1){// 全部是 9
            vector<int> ret(n + 1, 0);// 默认 初始化为 0
            ret[0] = 1;
            return ret;
        }else{// 中间出现 小于 9 的数, 这样进位终止 不会再影响 前面部分了
            digits[left] += 1;
            return digits;
        }

    }
};

724. 寻找数组的中心下标

class Solution: # O(n) O(1)
    def pivotIndex(self, nums: List[int]) -> int:
        total = sum(nums)
        temp = 0
        for i in range(len(nums)):
            # if temp == (total - nums[i]) / 2:
            if temp * 2 + nums[i] == total:
                return i 
            temp += nums[i]

        return -1
class Solution {// O(n) O(1)
public:
    int pivotIndex(vector<int>& nums) {
        int total = accumulate(nums.begin(), nums.end(), 0);
        int leftSum = 0;
        for (int i = 0; i < nums.size(); ++i){
            if (2 * leftSum + nums[i] == total){
                return i;
            }
            leftSum += nums[i];
        }
        return -1;
    }
};

189. 轮转数组

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)
        for i in range(k):
            nums.insert(0, nums.pop())
class Solution {// O(n) O(1)
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k %= n;
        reverse(nums, 0, n - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, n - 1);
    }
    // 子模块
    void reverse(vector<int>& nums, int start, int end){
        while (start < end){
            swap(nums[start], nums[end]);
            ++start;
            --end;
        }
    }
};
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # k % n 的尾部元素 往前 移。 剩余 元素右移 
        # n = 7 k = 3
        #  1 2 3 4 5 6 7 
        #  7 6 5 4 3 2 1
        #  5 6 7  1 2 3 4
        k = k % len(nums) 
        nums[:] = nums[::-1]
        nums[:k] = nums[:k][::-1]
        nums[k:] = nums[k:][::-1]
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)
        nums[:] = nums[-k:] + nums[:-k]

🚩——Day4

48. 旋转图像

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None: # O(n^2) O(1)
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        # 水平翻转
        for i in range(n//2):
            for j in range(n):
                matrix[i][j], matrix[n - 1 - i][j] = matrix[n - 1 - i][j], matrix[i][j]

        # 主对角线 翻转
        for i in range(n):
            for j in range(i):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
class Solution {// 水平翻转 + 主对角线翻转  O(n^2)  O(1)
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        for (int i = 0; i < n / 2; ++i){
            for (int j = 0; j < n; ++j){
               swap(matrix[i][j], matrix[n - 1 - i][j]); 
            }            
        }

        for (int i = 0; i < n; ++i){
            for (int j = 0; j < i; ++j){
                swap(matrix[i][j], matrix[j][i]);
            }
        }

    }
};

54. 螺旋矩阵

class Solution: # 按层模拟 O(mn) O(1)
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        m, n = len(matrix), len(matrix[0])
        left = 0
        right = n - 1
        top = 0
        bottom = m - 1
        ret = []
        while left <= right or top <= bottom: # 还有行 或 列
            for j in range(left, right + 1):
                ret.append(matrix[top][j])
            top += 1
            if top > bottom: break 

            for i in range(top, bottom + 1):
                ret.append(matrix[i][right])

            right -= 1
            if left > right:  break

            for j in range(right, left - 1, -1):
                ret.append(matrix[bottom][j])

            bottom -= 1
            if top > bottom: break 

            for i in range(bottom, top - 1, -1):
                ret.append(matrix[i][left])

            left += 1
            if left > right: break 

        return ret 
class Solution {// 按层模拟  O(mn) O(1)
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        int left = 0, right = n - 1, top = 0, bottom = m - 1;
        vector<int> ret;
        while (left <= right || top <= bottom){
            for (int j = left; j <= right; ++j){
                ret.emplace_back(matrix[top][j]);
            }
            if (++top > bottom) break;

            for (int i = top; i <= bottom; ++i){
                ret.emplace_back(matrix[i][right]);
            }
            if (--right < left) break;

            for (int j = right; j > left - 1; --j){
                ret.emplace_back(matrix[bottom][j]);
            }
            if (--bottom < top)  break;

            for (int i = bottom; i > top - 1; --i){
                ret.emplace_back(matrix[i][left]);
            }
            if (++left > right) break;
        } 
        return ret;
    }
};

498. 对角线遍历

class Solution:  # O(mn) O(1)
    def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
        # 偶数 向上 行索引 - 1, 列索引 - 1。 直到 矩形边缘。  (i, 0)  (m - 1, i - m + 1)
        # 奇数 向下  行 + 1 列  -1   (0, i)  (i - n + 1, n - 1)
        m, n = len(mat), len(mat[0])
        ret = []
        for i in range(m + n - 1): # 6 - 1
            if i % 2 == 0: # 偶数
                x = i if i < m else m - 1
                y = 0 if i < m else i - m + 1
                while x >= 0 and y < n:
                    ret.append(mat[x][y])
                    x -= 1
                    y += 1
            else:  # 奇数
                x = 0 if i < n else i - n + 1
                y = i if i < n else n - 1
                while x < m and y >= 0:
                    ret.append(mat[x][y])
                    x += 1
                    y -= 1
        return ret 

class Solution {// O(mn) O(1)
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
        int m = mat.size(), n = mat[0].size();
        vector<int> ret;
        for (int i = 0; i < m + n - 1; ++i){
            if (i % 2 == 0){// 偶数
                int x = (i < m ? i : m - 1);
                int y = (i < m ? 0 : i - m + 1);
                while (x >= 0 && y < n){
                    ret.emplace_back(mat[x][y]);
                    --x;
                    ++y;
                }
            }else{// 奇数
                int x = (i < n ? 0 : i - n + 1);
                int y = (i < n ? i : n - 1);
                while (x < m && y >= 0){
                    ret.emplace_back(mat[x][y]);
                    ++x;
                    --y;
                }

            }

        }
        return ret;
    }
};

——

485. 最大连续 1 的个数

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        n = len(nums)
        left = 0
        ret = 0
        while left < n:
            while left < n and nums[left] == 0:
                left += 1

            right = left 
            while right < n and nums[right] == 1:
                right += 1
            ret = max(ret, right - left)
            left = right 

        return ret
class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
        int n = nums.size();
        int ret = 0;
        int left = 0;
        while (left < n){
            while (left < n && nums[left] == 0){
                ++left;
            }
            int right = left;
            while (right < n  && nums[right] == 1){
                ++right;
            }
            ret = max(ret, right - left);
            left = right;
        }
        return ret;
    }
};

238. 除自身以外数组的乘积

class Solution: # O(n) O(1)
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)
        ret = [1] * n  # 记录  每一个数 左侧的乘积
        for i in range(1, n):
            ret[i] = ret[i - 1] * nums[i - 1]

        right = 1
        for i in range(n - 1, -1, -1):
            ret[i] = ret[i] * right
            right *= nums[i]

        return ret 
class Solution {// O(n)、O(1)
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> ret(n, 1);
        for (int i = 1; i < n; ++i){
            ret[i] = ret[i - 1] * nums[i - 1]; 
        }

        int right = 1;
        for (int i = n - 1; i >= 0; --i){
            ret[i] *= right;
            right *= nums[i]; 
        }
        return ret;
    }
};

73. 矩阵置零

class Solution: # O(mn) O(1)
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        m, n = len(matrix), len(matrix[0])
        # 一个标记变量 标记 第一列 原本是否 存在 0 
        flag_col0 = False  # 第一列 包含 0
        for i in range(m):
            if matrix[i][0] == 0:
                flag_col0 = True
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[0][j] = 0  # 第 0 行 记录 每一列的 含 0 情况
                    matrix[i][0] = 0  # 第 0 列 记录 每一行 含 0 情况 
 
        # 修改, 注意 行 为 逆向遍历
        for i in range(m - 1, -1, -1):
            for j in range(1, n):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0

            if flag_col0:
                matrix[i][0] = 0 # 最后 修改 第 一 列                    
class Solution {// O(mn) O(1)
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        bool flag_col0 = false;

        for (int i = 0; i < m; ++i){
            if (matrix[i][0] == 0)  flag_col0 = true;
            for (int j = 1; j < n; ++j){
                if (matrix[i][j] == 0){
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }    
        }
        
        // 修改
        for (int i = m - 1; i >= 0; --i){
            for (int j = 1; j < n; ++j){
                if (matrix[i][0] == 0 || matrix[0][j] == 0){
                    matrix[i][j] = 0;
                }
            }
            // 修改 第 0 列
            if (flag_col0){
                matrix[i][0] = 0;
            }
        }

    }
};

59. 螺旋矩阵 II

class Solution:  # O(n^2) O(1)
    def generateMatrix(self, n: int) -> List[List[int]]:
        # 直接构造
        matrix = [[0] * n for _ in range(n)]

        num = 1
        left = 0
        right = n - 1
        top = 0
        bottom = n - 1
        while num <= n * n:
            for j in range(left, right + 1):
                matrix[top][j] = num
                num += 1
            top += 1
            if top > bottom:
                break 
            
            for i in range(top, bottom + 1):
                matrix[i][right] = num
                num += 1
            
            right -= 1
            if left > right:
                break 

            for j in range(right, left - 1, -1):
                matrix[bottom][j] = num 
                num += 1
            bottom -= 1
            if top > bottom:
                break 

            for i in range(bottom, top - 1, -1):
                matrix[i][left] =  num 
                num += 1 
            left += 1
            if left > right:
                break 

        return matrix
class Solution {// O(n^2) O(1)
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> matrix(n, vector<int>(n, 0));
        int num = 1;
        int left = 0, right = n - 1, top = 0, bottom = n - 1;
        while (num <= n * n){
            for (int j = left; j <= right; ++j){
                matrix[top][j] = num;
                ++num;
            }
            if (++top > bottom){
                break;
            }
            for (int i = top; i <= bottom; ++i){
                matrix[i][right] = num;
                ++num;
            }
            if (--right < left){
                break;
            }

            for (int j = right; j > left - 1; --j){// 注意这里的边界
                matrix[bottom][j] = num;
                ++num;
            }
            if (--bottom < top){
                break;
            }

            for (int i = bottom; i > top - 1; --i){// 注意这里的边界
                matrix[i][left] = num;
                ++num;
            }

            if (++left > right){
                break;
            }
        }
        return matrix;
    }
};

289. 生命游戏

class Solution: # O(mn) O(1)
    def gameOfLife(self, board: List[List[int]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        # 标记状态  -1 表示原来是活的,现在死了。 2 表示原来是 死的,现在活了
        m, n = len(board), len(board[0])
        for i in range(m):
            for j in range(n):
                cnt = 0
                for ni, nj in (i - 1, j - 1), (i, j - 1), (i + 1, j - 1), (i - 1, j), (i + 1, j), (i - 1, j + 1), (i, j + 1), (i + 1, j + 1):
                    if 0 <= ni < m and 0 <= nj < n and abs(board[ni][nj]) == 1:
                        cnt += 1

                if board[i][j] == 1:
                    if cnt < 2 or cnt > 3:
                        board[i][j] = -1
                else:
                    if cnt == 3:
                        board[i][j] = 2

        # 修改
        for i in range(m):
            for j in range(n):
                if board[i][j] == -1:
                    board[i][j] = 0 
                elif board[i][j] == 2:
                    board[i][j] = 1
class Solution {// 使用额外标记数字 -1 和 2  O(mn) O(1)
public:
    void gameOfLife(vector<vector<int>>& board) {
        int m = board.size(), n = board[0].size();
        for (int i = 0; i < m; ++i){
            for (int j = 0; j < n; ++j){
                int cnt = 0;
                int di[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
                int dj[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
                for (int idx = 0; idx < 8; ++idx){
                    int ni = i + di[idx], nj = j + dj[idx];
                    if (0 <= ni && ni < m && nj >= 0 && nj < n && abs(board[ni][nj]) == 1){
                        ++cnt;
                    }
                }
                if (board[i][j] == 1){
                  if (cnt < 2 || cnt > 3){
                    board[i][j] = -1;
                    }
                }else{
                    if (cnt == 3){
                       board[i][j] = 2; 
                    }
                }                  
            }
        }
        // 修改 标记 的地方
        for (int i = 0; i < m; ++i){
            for (int j = 0; j < n; ++j){
                if (board[i][j] == -1)   board[i][j] = 0;
                else if (board[i][j] == 2) board[i][j] = 1;
            }
        }

    }
};