LeetCode 51-70题

 

正文

本博客记录的是 LeetCode 51 到 70 题的题解

之前很少使用的语法

string(n, '.')
INT_MIN, INT_MAX
// 58. Length of Last Word
stringstream ssin(s);
string word;
int res;
while (ssin >> word) res = word.size();
// 60. Permutation Sequence
next_permutation(res.begin(), res.end());
# 51. N-Queens
ans.append([''.join(graph[i]) for i in range(n)])
# 58. Length of Last Word
len(s.rstrip().split(" ")[-1])
// 60. Permutation Sequence
res.append(str(nums.pop(tk // mod)))
# 63. Unique Paths II
f = [[0] * (m + 1) for i in range(n + 1)] # 先 m 后 n
f[i][j] = (f[i - 1][j] if i + 1 else 0) + (f[i][j - 1] if j + 1 else 0)

51. N-Queens

挺简单的 N 皇后问题,主要是 三个维度进行打表,配合 DFS遍历行

class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
cols = [False] * n
diag = [False] * (2 * n + 10)
anti_diag = [False] * (2 * n + 10)
ans = []
graph = [['.'] * n for i in range(n)]
def dfs(cur):
if cur == n:
ans.append([''.join(graph[i]) for i in range(n)])
return
for i in range(n):
if not cols[i] and not diag[cur - i + n] and not anti_diag[cur + i]:
cols[i] = diag[cur - i + n] = anti_diag[cur + i] = True
graph[cur][i] = 'Q'
dfs(cur + 1)
graph[cur][i] = '.'
cols[i] = diag[cur - i + n] = anti_diag[cur + i] = False
dfs(0)
return ans

52. N-Queens II

和上一题一模一样,不过返回的数值不同,不必维护 graph 数组了

class Solution:
def totalNQueens(self, n: int) -> int:
cols = [False] * n
diag = [False] * (2 * n + 10)
anti_diag = [False] * (2 * n + 10)
ans = [0]
def dfs(cur):
if cur == n:
ans[0] += 1
return
for i in range(n):
if not cols[i] and not diag[cur - i + n] and not anti_diag[cur + i]:
cols[i] = diag[cur - i + n] = anti_diag[cur + i] = True
dfs(cur + 1)
cols[i] = diag[cur - i + n] = anti_diag[cur + i] = False
dfs(0)
return ans[0]

53. Maximum Subarray

本题其实对应两种做法,第一种是 O(N) 的DP,第二种是简化的线段树O(nlogn)

动态规划

class Solution:
def maxSubArray(self, nums: List[int]) -> int:
last = res = int(-1e10)
n = len(nums)
for i in range(n):
last = nums[i] + max(0, last)
res = max(last, res)
return res

线段树

没必要真正的开数组查询,这里我们仅仅只需要一次查询,所以说不需要把数组开出来。
就像是线段树中的 build函数,然后我们查询头结点的数值就可以得到结果

class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
def get_max(l, r):
if l == r:
ret = [nums[l], nums[l], nums[l], nums[l]]
else:
mid = (l + r) // 2
t1 = get_max(l, mid)
t2 = get_max(mid + 1, r)
ret = [max(max(t1[0], t2[0]), t1[2] + t2[1]), max(t1[1], t1[3] + t2[1]),
max(t2[2], t2[3] + t1[2]), t1[3] + t2[3]]
return ret
res = get_max(0, n - 1)
return res[0]

54. Spiral Matrix

两个循环搞定,一个循环是改变方向,一个循环是沿着方向不断行走

class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
n, m = len(matrix), len(matrix[0])
st = [[False] * m for i in range(n)]
def check(x, y):
return x >= 0 and y >= 0 and x < n and y < m
dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
res = [matrix[0][0]]
cx, cy = 0, 0
st[0][0] = True
cur_dir = -1
while len(res) != n * m:
cur_dir = (cur_dir + 1) % 4
while check(cx + dx[cur_dir], cy + dy[cur_dir]) and not st[cx + dx[cur_dir]][cy + dy[cur_dir]]:
cx, cy = cx + dx[cur_dir], cy + dy[cur_dir]
st[cx][cy] = True
res.append(matrix[cx][cy])
return res

55. Jump Game

注意我们之前证明过的 JUMP GAME II 的单调性即可

class Solution:
def canJump(self, nums: List[int]) -> bool:
n = len(nums)
j = -1
max_idx = 0
while max_idx > j:
i, j = j + 1, max_idx
for k in range(i, j + 1):
max_idx = max(max_idx, nums[k] + k)
if max_idx >= n - 1:
return True
return False

更简洁的代码

class Solution:
def canJump(self, nums: List[int]) -> bool:
n = len(nums)
j = 0
for i in range(n):
if i > j:
return False
j = max(j, nums[i] + i)
return True

56. Merge Intervals

较为简单的区间合并问题,主要是通过端点排序,然后进行贪心处理

class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key=lambda x: [x[0], x[1]])
res = []
n = len(intervals)
pre_start = 0
max_end = -1e9
for i in range(n):
if intervals[i][0] <= max_end:
max_end = max(max_end, intervals[i][1])
else:
if pre_start <= max_end:
res.append([pre_start, max_end])
pre_start = intervals[i][0]
max_end = intervals[i][1]
res.append([pre_start, max_end])
return res

57. Insert Interval

和上一题类似,不过是需要自己插入排序一下

class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
n = len(intervals)
if n == 0 or newInterval[0] > intervals[-1][0]:
intervals.append(newInterval)
else:
for i in range(n):
if intervals[i][0] >= newInterval[0]:
intervals.insert(i, newInterval)
break
n += 1
pre_start, max_end = 0, -1e9
res = []
for i in range(n):
if intervals[i][0] <= max_end:
max_end = max(max_end, intervals[i][1])
else:
if pre_start <= max_end:
res.append([pre_start, max_end])
pre_start, max_end = intervals[i][0], intervals[i][1]
res.append([pre_start, max_end])
return res

仔细读题发现 intervals没有交集,因此我们可以将 intervals 不和 newInterval 重叠的部分放入到 res中,计算中间重叠部分的最早起点和最晚终点即可;

class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
n = len(intervals)
res = []
k = 0
while k < n and intervals[k][1] < newInterval[0]:
res.append(intervals[k])
k += 1
pre_start, max_end = newInterval[0], newInterval[1]
while k < n and intervals[k][0] <= max_end:
pre_start = min(pre_start, intervals[k][0])
max_end = max(max_end, intervals[k][1])
k += 1
res.append([pre_start, max_end])
while k < n:
res.append(intervals[k])
k += 1
return res

58. Length of Last Word

简单的模拟题

class Solution:
def lengthOfLastWord(self, s: str) -> int:
n, cnt = len(s), 0
for i in range(n - 1, -1, -1):
if s[i] == ' ' and cnt != 0:
break
cnt = cnt + 1 if s[i] != ' ' else cnt
return cnt
class Solution:
def lengthOfLastWord(self, s: str) -> int:
return len(s.rstrip().split(" ")[-1])

有点意思的C++语法

class Solution {
public:
int lengthOfLastWord(string s) {
stringstream ssin(s);
int res = 0;
string word;
while (ssin >> word) res = word.size();
return res;
}
};

59. Spiral Matrix II

最方便的就是使用数组打表

class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
cur_dir = 0
st = [[False] * n for i in range(n)]
res = [[-1] * n for i in range(n)]
cx, cy = 0, 0
for i in range(n * n):
st[cx][cy] = True
res[cx][cy] = i + 1
nx, ny = cx + dx[cur_dir], cy + dy[cur_dir]
if nx < 0 or nx >= n or ny < 0 or ny >= n or st[nx][ny]:
cur_dir = (cur_dir + 1) % 4
nx, ny = cx + dx[cur_dir], cy + dy[cur_dir]
cx, cy = nx, ny
return res

60. Permutation Sequence

寻找排列组合的规律即可
每一个位置上,他往后的位置对应的组合数量。

class Solution:
def getPermutation(self, n: int, k: int) -> str:
res = []
st = [False] * 11
order = [-1 for i in range(11)]
tk = k - 1
mod = 2
for i in range(n - 2, -1, -1):
order[i] = tk % mod
tk //= mod
mod += 1
order[n - 1] = 0
for i in range(n):
cnt = 0
for j in range(1, n + 1):
if not st[j]:
if cnt == order[i]:
res.append(str(j))
st[j] = True
break
else:
cnt += 1
return ''.join(res)

更为简洁的代码

class Solution:
def getPermutation(self, n: int, k: int) -> str:
res = []
nums = list(range(1, n + 1))
tk = k - 1
for i in range(n):
mod = 1
for j in range(i + 1, n):
mod *= (j - i)
res.append(str(nums.pop(tk // mod)))
tk %= mod
return ''.join(res)

61. Rotate List

链表模拟,头尾相接后,查找新的头和尾

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head:
return head
t, n = head, 0
end = None
while t:
n += 1
if not t.next:
end = t
t = t.next
k %= n
end.next = head
t = head
for i in range(0, n - 1 - k):
t = t.next
head = t.next
t.next = None
return head

62. Unique Paths

dp 求解组合数

class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# C(m + n - 2, m - 1)
# C(x, y) = C(x - 1, y) + C(x - 1, y - 1)
x, y = m + n - 2, min(m - 1, n - 1)
f = [[0] * (m + n + 1) for i in range(m + n + 1)]
f[0][0] = 1
for i in range(1, x + 1):
for j in range(x + 1):
f[i][j] = f[i - 1][j] + (f[i - 1][j - 1] if j else 0)
return f[x][y]

python 的大整数

class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# C(m + n - 2, m - 1)
x, y = m + n - 2, min(m - 1, n - 1)
fenmu, fenzi = 1, 1
for i in range(1, y + 1):
fenmu *= i
fenzi *= (x - i + 1)
return fenzi // fenmu

63. Unique Paths II

class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
n, m = len(obstacleGrid), len(obstacleGrid[0])
f = [[0] * (m + 1) for i in range(n + 1)] # 先 m 后 n
f[0][0] = 1
for i in range(n):
for j in range(m):
if obstacleGrid[i][j]:
f[i][j] = 0
elif not (i == 0 and j == 0):
f[i][j] = (f[i - 1][j] if i + 1 else 0) + (f[i][j - 1] if j + 1 else 0)
return f[n - 1][m - 1]

64. Minimum Path Sum

简单 DP

class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
n, m = len(grid), len(grid[0])
f = [[400001010] * (m + 1) for i in range(n + 1)]
f[0][0] = grid[0][0]
for i in range(n):
for j in range(m):
if not (i == 0 and j == 0):
f[i][j] = grid[i][j] + min(f[i - 1][j] if i + 1 else 101010100,
f[i][j - 1] if j + 1 else 101010100)
return f[n - 1][m - 1]

65. Valid Number

主要是学会写函数模块,重复利用起来就好

class Solution:
def check_integer(self, s:str) -> bool:
if not s:
return False
return self.check_digits(s[1:]) if s[0] == '+' or s[0] == '-' else self.check_digits(s)
def check_digits(self, s: str) -> bool:
if not s:
return False
for i in range(len(s)):
if '0' <= s[i] <= '9':
continue
return False
return True
def check_decimal_number(self, s: str) -> bool:
if not s:
return False
s = s[1:] if s[0] == '+' or s[0] == '-' else s
n, pos = len(s), -1
for i in range(n):
if s[i] == '.':
pos = i
break
if pos == -1:
return False
if pos == 0:
return self.check_digits(s[1:])
elif pos == n - 1:
return self.check_digits(s[:-1])
else:
return self.check_digits(s[:pos]) and self.check_digits(s[pos+1:])
def isNumber(self, s: str) -> bool:
if not s:
return False
pos = -1
for i in range(len(s)):
if s[i] == 'e' or s[i] == 'E':
pos = i
break
if pos != -1:
return (self.check_decimal_number(s[:pos]) or self.check_integer(s[:pos])) \
and self.check_integer(s[pos + 1:])
else:
return self.check_integer(s) or self.check_decimal_number(s)

66. Plus One

简单模拟即可, O(n)复杂度

class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
n = len(digits)
digits[-1] += 1
k = n - 1
while digits[k] > 9:
digits[k] = 0
k -= 1
if k < 0:
k = 0
digits.insert(0, 0)
digits[k] += 1
return digits

67. Add Binary

模拟按位加法就可以

class Solution:
def addBinary(self, a: str, b: str) -> str:
a = a[::-1]
b = b[::-1]
n, m = len(a), len(b)
if n < m:
a, b = b, a
n, m = m, n
t = 0
res = ""
for i in range(n):
t += int(a[i])
if i < m:
t += int(b[i])
res += str(t % 2)
t //= 2
if t:
res += str(t)
return res[::-1]

68. Text Justification

简单的模拟题

class Solution:
def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
n = len(words)
i = 0
res = []
while i < n:
s = ''
# st - ed 为双指针范围
st = i
len_cnt = len(words[i])
ed = i + 1
while ed < n and len_cnt + len(words[ed]) + 1 <= maxWidth:
len_cnt += len(words[ed]) + 1
ed += 1
# st --> ed - 1 为字符串范围,刚好 ed 我下一个 i 的位置
# 下面我们分配字符串
word_cnt = ed - st
if ed != n:
if word_cnt == 1:
s = words[st] + (maxWidth - len_cnt) * ' '
else:
s = words[st]
len_cnt -= (word_cnt - 1)
for j in range(st + 1, ed):
if j - st <= (maxWidth - len_cnt) % (word_cnt - 1):
s += ' '
s += ' ' * ((maxWidth - len_cnt) // (word_cnt - 1)) + words[j]
else:
len_cnt = len(words[st])
s = words[st]
for j in range(st + 1, ed):
s += ' ' + words[j]
len_cnt += len(words[j]) + 1
s += (maxWidth - len_cnt) * ' '
i = ed
res.append(s)
return res

69. Sqrt(x)

简单二分题目

class Solution:
def mySqrt(self, target: int) -> int:
# 二分 x ** 2 <= target 的最大值
l, r = 0, 100010
while l < r:
mid = (l + r + 1) // 2
if mid * mid <= target:
l = mid
else:
r = mid - 1
return l

70. Climbing Stairs

斐波那契额数列做法很多

  1. dp 模拟
  2. 快速幂
  3. 数学公式

dp

# f[n] = f[n - 1] + f[n - 2]
class Solution:
def climbStairs(self, n: int) -> int:
a, b = 1, 1
if n == 0 or n == 1:
return 1
else:
for i in range(2, n + 1):
c = a + b
a, b = b, c
return c

矩阵快速幂

快速幂推导图示

# 2. 快速幂
class Solution:
def mult(self, A, B):
T = [[0, 0], [0, 0]]
for i in range(2):
for j in range(2):
for k in range(2):
T[i][j] += A[i][k] * B[k][j]
return T.copy()
def climbStairs(self, n: int) -> int:
if n == 0 or n == 1:
return 1
t = n - 1
B = [[1, 1], [1, 0]]
C = [[1, 0], [0, 1]] # 单位矩阵,快速幂结束后为 B^(n-1)
while t:
if t % 2 == 1:
C = self.mult(B, C)
B = self.mult(B, B)
t //= 2
A = [[1, 1], [0, 0]]
C = self.mult(A, C)
return C[0][0]

数学公式


但是当 n 很大时候,可能会出现精度问题

# 数学公式
class Solution:
def qmi(self, x, y):
res = 1.0
while y:
if y % 2 == 1:
res *= x
x *= x
y //= 2
return res
def climbStairs(self, n: int) -> int:
if n == 0 or n == 1:
return 1
n += 1
t = 5 ** 0.5
return round((self.qmi((1 + t) / 2, n) - self.qmi((1 - t) / 2, n)) / t)
posted @   lucky_light  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示