参考资料:
电子网站:datawhalechina.github.io/leetcode-no…
————————————
增删改查
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;
}
}
}
};