抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

blaire

👩🏻‍💻ブレア🥣

image

1.1 二分查找, while l <= r

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution:
def search(self, nums: List[int], target: int) -> int:
if not nums:
return -1

l, r = 0, len(nums) - 1

while l <= r:
mid = (r - l)//2 + l

if nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid - 1
else:
return mid

return -1

34. 在排序数组中查找元素的第一个和最后一个位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:

if not nums:
return [-1, -1]

def binSearch(nums, t, flag):
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
if nums[mid] > t:
r = mid - 1
elif nums[mid] < t:
l = mid + 1
else:
if flag == "L":
r = mid - 1
else:
l = mid + 1

if flag == 'L' and r + 1 < len(nums) and nums[r + 1] == t:
return r + 1
if flag == 'R' and l - 1 >= 0 and nums[l - 1] == t:
return l - 1
return -1

return [binSearch(nums=nums, t=target, flag='L'), binSearch(nums=nums, t=target, flag='R')]

88. 合并两个有序数组 - 逆向双指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from typing import List

class Solution:
def merge(self, A: List[int], m: int, B: List[int], n: int) -> None:
"""
Do not return anything, modify A in-place instead.
"""
pa, pb = m - 1, n - 1
tail = m + n - 1

while pa >= 0 or pb >= 0:
if pa == -1:
A[tail] = B[pb]
pb -= 1
elif pb == -1:
A[tail] = A[pa]
pa -= 1
elif A[pa] > B[pb]:
A[tail] = A[pa]
pa -= 1
else:
A[tail] = B[pb]
pb -= 1
tail -= 1

return A[:] # 如果需要返回数组副本,则添加这一行

15. 3Sum - for for while , second_ix & third_ix 两边夹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = list()

# 枚举 a
for first in range(n):
# 需要和上一次枚举的数不相同
if first > 0 and nums[first] == nums[first - 1]:
continue
# c 对应的指针初始指向数组的最右端
third = n - 1
target = -nums[first]
# 枚举 b
for second in range(first + 1, n):
# 需要和上一次枚举的数不相同
if second > first + 1 and nums[second] == nums[second - 1]:
continue
# 需要保证 b 的指针在 c 的指针的左侧
while second < third and nums[second] + nums[third] > target:
third -= 1
# 如果指针重合,随着 b 后续的增加
# 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if second == third:
break
if nums[second] + nums[third] == target:
ans.append([nums[first], nums[second], nums[third]])

return ans

11. Container With Most Water 双指针 - 移动 l 和 r 较小的一方才可能增加 area

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def maxArea(self, height: List[int]) -> int:
l, r = 0, len(height) - 1
area = 0
while l < r:
area = max(area, min(height[l], height[r]) * (r-l))
if height[l] < height[r]:
l += 1
else:
r -= 1
return area

2. DFS / Stack

2.1 字符串解码 “3[a2[c]]” == “accacc”, stack == [(3, ""), (2,"a")]

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def decodeString(self, s: str) -> str:
stack, res, multi = [], "", 0
for c in s:
if c == '[':
stack.append([multi, res])
res, multi = "", 0
elif c == ']':
cur_multi, last_res = stack.pop()
res = last_res + cur_multi * res
elif '0' <= c <= '9':
multi = multi * 10 + int(c)
else:
res += c
return res

215. 数组中的第K个最大元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from heapq import heapify, heappush, heappop 
# python中的heap是小根堆: heapify(hp) , heappop(hp), heappush(hp, v)
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
n = len(nums)
if k == 0 or k > n:
return []

hp = nums[:k]

heapify(hp)

for i in range(k, n):
v = nums[i]
if v > hp[0]:
heappop(hp)
heappush(hp, v)

return hp[0]

3. dynamic programming

Using dynamic programming to solve problems is generally 3 steps:

  1. state
  2. Find the state transition equation
  3. Boundary processing

When analyzing the state of the problem, don’t analyze the whole, just analyze the last stage! Because dynamic programming problems are divided into multiple stages, the state representation of each stage is the same, and our final answer is in the last stage.

3.1

爬楼梯 climbing-stairs , ✔️ 新建{}or[] ,滚动数组

1
2
3
4
5
6
7
8
class Solution:
def climbStairs(self, n: int) -> int:
dp = {}
dp[1] = 1
dp[2] = 2
for i in range(3,n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
No. dynamic programming Flag
no-gd 31. n个骰子的点数 dp[i][j] ,表示投掷完 i 枚骰子后,点数 j 的出现次数 ✔️
  Summary 20 dynamic programming
(4.1) DP表示状态
easy Climbing Stairs , 新建{}or[] ,滚动数组
2. 连续子数组的最大和
addition 63. 多少种 不同路径 II, store = [[0]*n for i in range(m)] 二维初始化

addition
Edit Distance/编辑距离【word1 转换成 word2】
   1. dp = [ [0] * (m + 1) for _ in range(n + 1)]
   2. dp[i][j] = min(A,B,C)

✔️❎
addition 5. Longest Palindromic Substring/最长回文子串
1. 枚举子串的长度 l+1,从小问题到大问题
2. 枚举子串的起始位置 i, j=i+l 子串结束位置, dp[i][j] = (dp[i+1][j-1] and s[i]==s[j])
✔️❎
good 把数字翻译成字符串 Fib ✔️❎
addition Leetcode 64. Minimum Path Sum, 最小路径和 grid[i][j] = min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j]
addition 115. Distinct Subsequences I Hard
addition 940. 不同的子序列 II Hard
addition Interleaving String/交错字符串 Hard

4. sliding window & hash

No. Question Flag
(6). sliding Window
  65. 最长不含重复字符的子字符串 滑动窗口 ✔️❎
  14. 和为s的连续正数序列    [sliding window]

input:target = 9
output:[[2,3,4],[4,5]]
✔️❎
(7). 模拟
  21. 圆圈中最后剩下的数字

1. 当数到最后一个结点不足m个时,需要跳到第一个结点继续数
2. 每轮都是上一轮被删结点的下一个结点开始数 m 个
3. 寻找 f(n,m) 与 f(n-1,m) 关系
4. A: f(n,m)=(m+x)%n
5. Python 深度不够手动设置 sys.setrecursionlimit(100000)
东大 Lucien 题解,讲得最清楚的那个。官方讲解有误




✔️❎
  35. 顺时针打印矩阵 left, right, top, bottom = 0, columns - 1, 0, rows - 1 ✔️❎
  56. 把数组排成最小的数, sorted vs sort, strs.sort(key=cmp_to_key(sort_rule)) ✔️❎
  70. 把字符串转换成整数
     int_max, int_min, bndry = 231-1, -231, 2**31//10
     bndry=2147483647//10=214748364 ,则以下两种情况越界
     res > bndry or res == bndry and c >‘7’
✔️❎

5. linkedList

No. Question Flag
(3). linkedList
  7. 从尾到头打印链表:
reversePrint(head.next) + [head.val]
  8. 反转链表 pre, cur = head, head.next   pre.next = None   (循环版 双指针)
image
  10. 合并两个排序的链表    [Recursion]
p.next = self.mergeTwoLists(l1.next, l2)
addition 旋转单链表 (F1. 环 F2. 走n-k%n 断开)
举例: 给定 1->2->3->4->5->6->NULL, K=3
则4->5->6->1->2->3->NULL
addition 92. 翻转部分单链表 reverse(head: ListNode, tail: ListNode)
举例:1->2->3->4->5->null, from = 2, to = 4 结果:1->4->3->2->5->null
addition 链表划分, 描述: 给定一个单链表和数值x,划分链表使得小于x的节点排在大于等于x的节点之前
addition 82. 删除排序链表中的重复元素 II 链表1->2->3->3->4->4->5 处理后为 1->2->5.
addition 输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
输出:2 -> 1 -> 9,即912
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 定义链表节点类
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
if head is None:
return []
else:
return self.reversePrint(head.next) + [head.val]

# 示例用法
# 创建链表 1 -> 3 -> 2
head = ListNode(1)
head.next = ListNode(3)
head.next.next = ListNode(2)

# 创建 Solution 对象并调用 reversePrint 方法
solution = Solution()
result = solution.reversePrint(head)

# 打印结果
print(result) # 输出 [2, 3, 1]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 输入: 1->2->3->4->5->NULL
# 输出: 5->4->3->2->1->NULL

class ListNode:
def __init__(self, x):
self.val = x
self.next = None


class Solution(object):
def reverseList(self, head) -> ListNode:
if not head or not head.next:
return head

pre, cur = head, head.next
pre.next = None

while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp

return pre

合并2个有序链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 is None:
return l2
if l2 is None:
return l1

if l1.val < l2.val:
p = ListNode(l1.val)
p.next = self.mergeTwoLists(l1.next, l2)
else:
p = ListNode(l2.val)
p.next = self.mergeTwoLists(l1, l2.next)

return p

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 创建一个环:将链表的尾节点指向头节点,形成一个环。
# 找到断开点:从头节点开始,走 𝑛 − 𝑘 % 𝑛 步,然后在这个点断开环。
# 形成新的链表:新的链表从断开点开始,前半部分接在断开点后面

class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
if not head or not head.next or k == 0:
return head

# 计算链表长度,并找到尾节点
length = 1
tail = head
while tail.next:
tail = tail.next
length += 1

# 将尾节点连接到头节点,形成环
tail.next = head

# 找到新的尾节点位置 (length - k % length - 1)
new_tail_pos = length - k % length - 1
new_tail = head
for _ in range(new_tail_pos):
new_tail = new_tail.next

# 新的头节点是新的尾节点的下一个节点
new_head = new_tail.next

# 断开环
new_tail.next = None

return new_head

# 示例用法
# 创建链表 1 -> 2 -> 3 -> 4 -> 5 -> 6
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)
head.next.next.next.next = ListNode(5)
head.next.next.next.next.next = ListNode(6)

# 创建 Solution 对象并调用 rotateRight 方法
solution = Solution()
k = 3
new_head = solution.rotateRight(head, k)

# 打印结果
current = new_head
while current:
print(current.val, end=" -> " if current.next else " -> NULL")
current = current.next

6. stack

No. Question Flag
(2). Stack
  394. 字符串解码 [a]2[bc]
  28. 包含min函数的栈
  29. 最小的k个数【堆排的逆向】 heapq.heappop(hp),heapq.heappush(hp, -arr[i]) ✔️❎
  36. 滑动窗口的最大值 (同理于包含 min 函数的栈) deque.popleft(),双端队列+单调 ✔️❎
  59 II. 队列的最大值 , 维护个单调的deque
   import queue, queue.deque(), queue.Queue(), deq[0], deq[-1]
✔️❎
(5). DFS / BFS
  66. 矩阵中的路径 , 经典好题: 深搜+回溯 def dfs(i, j, k): ✔️❎
  61. 机器人的运动范围 bfs good
   from queue import Queue, q.get() q.pup()
✔️❎
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from collections import deque
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
q = deque()
q.append((0,0))
s = set()
s.add((0,0))
while q:
x, y = q.popleft()
for (i, j) in [(x+1, y), (x, y+1)]:
if valid(i, j, k, s, m, n):
q.append((i, j))
s.add((i, j))
return len(s)

7. string

8. Tree 剑指

No. Question Flag
easy
(1). Tree
  1.1 平衡二叉树
abs(maxHigh(root.left) - maxHigh(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
  1.2 对称的二叉树
return root == None or isSymmetricHelper(root.left, root.right)
  1.3 二叉树的镜像递归+swap后
root.left = self.mirrorTree(root.right)
root.left = self.mirrorTree(root.right)
root.left = right;root.right = left
  1.4 二叉搜索树的第k大节点    [中序遍历 倒序, 右-中-左] ✔️❎
good 1.5 (两个节点)二叉树的最近公共祖先    [Recursion] 后序遍历+路径回溯 ✔️❎
good 1.6 (两个节点)二叉搜索树的最近公共祖先    Recursion + 剪枝 ✔️❎
good 1.7 二叉树中和为某一值的路径 递归回溯 ✔❎️
  1.8 二叉搜索树的后序遍历序列
  1.9 二叉搜索树与双向链表
image
additional 求二叉树第K层的节点个数 [Recursion] ,root != None and k==1,返回1
f(root.left, k-1) + f(root.right, k-1)
additional 求二叉树第K层的叶子节点个数 [Recursion]
if(k==1 and root.left and root.right is null) return 1;
✔️❎
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None

class Solution:
def isBalanced(self, root: TreeNode) -> bool:
def maxHigh(root):
if root == None:
return 0
return max(maxHigh(root.left), maxHigh(root.right)) + 1

if root == None:
return True
return abs(maxHigh(root.left) - maxHigh(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)

Comments