目录
跳跃游戏I
求最长跳跃距离问题
class Solution:
def canJump(self, nums: List[int]) -> bool:
n, rightmost = len(nums), 0
for i in range(n):
if i <= rightmost:
rightmost = max(rightmost, i + nums[i])
if rightmost >= n-1:
return True
return False
跳跃游戏II
求最短跳跃次数问题,相比较I增加一层if判断
class Solution:
def jump(self, nums: List[int]) -> int:
n = len(nums)
maxpos = 0
std = 0
end = 0
for i in range(n-1):
if i <= maxpos:
maxpos = max(maxpos, i + nums[i])
if i == end:
end = maxpos
std += 1
return std
接雨水
class Solution:
def trap(self, height: List[int]) -> int:
n = len(height)
#时间复杂度O(n), 空间复杂度O(n)
# right = [0] * n
# left = [0] * n
# max1, max2 = 0, 0
# ansx = 0
# for i in range(n):
# max1 = max(height[i], max1)
# right[i] = max1
# for i in range(n-1, -1, -1):
# max2 = max(height[i], max2)
# left[i] = max2
# for i in range(n):
# ansx += max((min(left[i], right[i]) -height[i]), 0)
# return ansx
时间复杂度O(n),空间复杂度O(1)
i, j = 0, n-1
ans = 0
max_left, max_right = 0, 0
while(i<=j):
max_left = max(max_left, height[i])
max_right = max(max_right, height[j])
if max_left < max_right:
ans += max_left-height[i]
i += 1
else:
ans += max_right-height[j]
j -= 1
return ans
搜索插入位置
自己写的:
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
n = len(nums)
if target > nums[n-1]:
return n
for i in range(n):
if target > nums[i]:
continue
else:
return i
别人写的:
def lower_bound(nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1 # 闭区间 [left, right]
while left <= right: # 区间不为空
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1 # 范围缩小到 [mid+1, right]
else:
right = mid - 1 # 范围缩小到 [left, mid-1]
return left
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
return lower_bound(nums, target)
#库函数写法
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
return bisect_left(nums, target)
路径总和
求是否有总和为k的路径
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
if not root.left and not root.right:
return targetSum == root.val
return self.hasPathSum(root.left, targetSum-root.val) or self.hasPathSum(root.right, targetSum-root.val)
路径总和II
求出所有总和为k的路径
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
ans = []
path = []
def dfs(root, targetSum):
if not root:
return
path.append(root.val)
targetSum -= root.val
if not root.left and not root.right and targetSum == 0:
ans.append(path[:])
dfs(root.left, targetSum)
dfs(root.right, targetSum)
path.pop()
dfs(root, targetSum)
return ans
合并两个有序链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
prehead = ListNode(-1)
prev = prehead
while l1 and l2:
if l1.val <= l2.val:
prev.next = l1
l1 = l1.next
else:
prev.next = l2
l2 = l2.next
prev = prev.next
# 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 if l1 is not None else l2
return prehead.next
合并排序链表中的重复元素II
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = cur = ListNode(next = head)
while cur.next and cur.next.next:
val = cur.next.val
if cur.next.next.val == val:
while cur.next and cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return dummy.next
LRU缓存
库函数版本
class LRUCache(collections.OrderedDict):
def __init__(self, capacity: int):
super().__init__()
self.capacity = capacity
def get(self, key: int) -> int:
if key not in self:
return -1
self.move_to_end(key)
return self[key]
def put(self, key: int, value: int) -> None:
if key in self:
self.move_to_end(key)
self[key] = value
if len(self) > self.capacity:
self.popitem(last = False)
正常版本
class DLinkedNode:
def __init__(self, key=0, value=0):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.cache = dict()
# 使用伪头部和伪尾部节点
self.head = DLinkedNode()
self.tail = DLinkedNode()
self.head.next = self.tail
self.tail.prev = self.head
self.capacity = capacity
self.size = 0
def get(self, key: int) -> int:
if key not in self.cache:
return -1
# 如果 key 存在,先通过哈希表定位,再移到头部
node = self.cache[key]
self.moveToHead(node)
return node.value
def put(self, key: int, value: int) -> None:
if key not in self.cache:
# 如果 key 不存在,创建一个新的节点
node = DLinkedNode(key, value)
# 添加进哈希表
self.cache[key] = node
# 添加至双向链表的头部
self.addToHead(node)
self.size += 1
if self.size > self.capacity:
# 如果超出容量,删除双向链表的尾部节点
removed = self.removeTail()
# 删除哈希表中对应的项
self.cache.pop(removed.key)
self.size -= 1
else:
# 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
node = self.cache[key]
node.value = value
self.moveToHead(node)
def addToHead(self, node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
def removeNode(self, node):
node.prev.next = node.next
node.next.prev = node.prev
def moveToHead(self, node):
self.removeNode(node)
self.addToHead(node)
def removeTail(self):
node = self.tail.prev
self.removeNode(node)
return node
去除重复元素
单个字符串去除
def merge_and_deduplicate(s):
result_list = []
for char in s:
# 如果字符不在结果列表中,则添加
if char not in result_list:
result_list.append(char)
# 将结果列表转换为字符串并返回
return ''.join(result_list)
# 示例
strings = "AprogramAmiFng"
result = merge_and_deduplicate(strings)
print(result) # 输出:'helordpwtgmin'
多个字符串合并去除
def merge_and_deduplicate(strings):
result_list = []
for s in strings:
for char in s:
if char not in result_list:
result_list.append(char)
return ''.join(result_list)
strings = ["hello", "world", "python", "programming"]
result = merge_and_deduplicate(strings)
print(result)
组合
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
path, ans = [], []
def dfs(i, k):
if k == 0:
ans.append(path[:])
return
for j in range(i, n+1):
path.append(j)
dfs(j + 1, k-1)
path.pop()
dfs(1, k)
return ans
电话号码的字母组合
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
hashx = {
"2":'abc',
'3':'def',
'4':'ghi',
'5':'jkl',
'6':'mno',
'7':'pqrs',
'8':'tuv',
'9':'wxyz'
}
if len(digits) == 0:
return []
ans, path = [], []
length = len(digits)
def dfs(i):
if i == length:
ans.append(''.join(path))
return
c = digits[i]
for value in hashx[c]:
path.append(value)
dfs(i+1)
path.pop()
dfs(0)
return ans
括号生成
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
# def generate(A):
# if len(A) == 2*n:
# if valid(A):
# ans.append("".join(A))
# return
# else:
# A.append('(')
# generate(A)
# A.pop()
# A.append(')')
# generate(A)
# A.pop()
# def valid(A):
# bal = 0
# for c in A:
# if c == '(': bal += 1
# else: bal -= 1
# if bal < 0: return False
# return bal == 0
# ans = []
# generate([])
# return ans
ans = []
def dfs(S, left, right):
if len(S) == 2*n:
ans.append("".join(S))
return
if left < n:
S.append('(')
dfs(S, left+1, right)
S.pop()
if right < left:
S.append(')')
dfs(S, left, right+1)
S.pop()
dfs([], 0, 0)
return ans
颠倒二进制位
class Solution:
def reverseBits(self, n: int) -> int:
res = 0
for i in range(32):
res = (res<<1) | (n&1)
n >>= 1
return res
只出现一次的数字
class Solution:
def singleNumber(self, nums: List[int]) -> int:
# nums.sort()
# # print(nums)
# flag = 0
# n = len(nums)
# if len(nums) == 1:
# return nums[0]
# if nums[0] != nums[1]:
# return nums[0]
# if nums[n-2]!= nums[n-1]:
# return nums[n-1]
# for i in range(1, len(nums)-1):
# if nums[i+1] == nums[i] or nums[i] == nums[i-1]:
# continue
# else:
# flag = nums[i]
# return flag
return reduce(lambda x,y:x^y, nums)
单词搜索
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
directions = [
(-1, 0),
(1, 0),
(0,1),
(0,-1)
]
def dfs(i, j, k):
if board[i][j] != word[k]:
return False
if k == len(word)-1:
return True
visited.add((i,j))
result = False
for di, dj in directions:
newi = i + di
newj = j + dj
if 0<=newi<len(board) and 0<= newj < len(board[1]):
if (newi, newj) not in visited:
if dfs(newi, newj, k + 1):
result = True
break
visited.remove((i, j))
return result
h, w = len(board), len(board[0])
visited = set()
for i in range(h):
for j in range(w):
if dfs(i, j, 0):
return True
return False
移动0(HOT100)
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
# n = len(nums)
# if n <= 1:
# return nums
# # for i in range(n):
# for j in range(n-1):
# if nums[j] == 0:
# k = j + 1
# while k < n-1 and nums[k] == 0:
# k += 1
# q = nums[k]
# nums[k] = 0
# nums[j] = q
# else:
# continue
# return nums
if not nums:
return 0
j = 0
for i in range(len(nums)):
if nums[i]:
nums[j] = nums[i]
j += 1
for i in range(j, len(nums)):
nums[i] = 0
找到字符串中所有字母异位词(HOT100)
自己的超时版本:
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
ans = []
left = 0
right = len(s)-1
if len(s) == len(p):
if sorted(s) == sorted(p):
return [0]
else:
return []
while left <= right-len(p) + 1:
while s[left] not in p and left < right-len(p) + 1:
left += 1
if sorted(s[left:left+len(p)]) == sorted(p):
ans.append(left)
left += 1
return ans
使用Counter()计数器
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
n, m = len(s), len(p)
cntp = Counter(p)
cnts = Counter()
ans = []
for i, x in enumerate(s):
cnts[x] += 1
if i+1 >= m:
if cntp == cnts:
ans.append(i+1-m)
cnts[s[i+1-m]] -= 1
return ans
螺旋矩阵
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
len_x = len(matrix)
len_y = len(matrix[0])
ans = []
left, top = 0, 0
right, bottom = len_y-1, len_x-1
while(True):
for i in range(left, right+1):
ans.append(matrix[top][i])
top += 1
if top>bottom:break
for i in range(top, bottom+1):
ans.append(matrix[i][right])
right -= 1
if right<left:break
for i in range(right,left-1,-1):
ans.append(matrix[bottom][i])
bottom -= 1
if bottom<top:break
for i in range(bottom, top-1, -1):
ans.append(matrix[i][left])
left += 1
if left>right:break
return ans
旋转图像
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
n = len(matrix)
for i in range(n//2):
for j in range((n+1)//2):
matrix[i][j], matrix[n-j-1][i], matrix[n-i-1][n-j-1], matrix[j][n-1-i] = matrix[n-j-1][i], matrix[n-i-1][n-j-1], matrix[j][n-1-i], matrix[i][j]
return matrix
一个小组的最大实力
自己写的shi山
class Solution:
def maxStrength(self, nums: List[int]) -> int:
nums.sort()
abs_num = 0
ans = 1
for i in nums:
if i < 0:
abs_num += 1
if i != 0:
ans *= i
if len(nums) <= 1:
return int(nums[0])
elif abs_num == 0 and nums[-1] == 0:
return 0
elif abs_num == 1 and nums[-1]==0:
return 0
elif abs_num%2 == 1:
return int(ans / nums[abs_num-1])
else:
return int(ans)
别人的:
class Solution:
def maxStrength(self, nums: List[int]) -> int:
mn = mx = nums[0]
for x in nums[1:]:
mn, mx = min(mn, x, mx*x, mn*x), max(mx, x, mx*x, mn*x)
return mx
字符串中的额外字符
这题还没太会,动态规划
class Solution:
def minExtraChar(self, s: str, dictionary: List[str]) -> int:
d = set(dictionary)
@cache
def dfs(i:int):
if i < 0:
return 0
res = dfs(i-1) + 1
for j in range(i+1):
if s[j:i+1] in d:
res = min(res, dfs(j-1))
return res
return dfs(len(s)-1)
倍数求和
自己写的
class Solution:
def sumOfMultiples(self, n: int) -> int:
ans_set = set()
for i in range(1, n+1):
if i % 3 == 0:
ans_set.add(i)
if i % 5 == 0:
ans_set.add(i)
if i % 7 == 0:
ans_set.add(i)
ans = 0
for x in ans_set:
ans += x
return ans
#优化
def sumOfMultiples(self, n: int) -> int:
res = 0
for i in range(1, n+1):
if i % 3 == 0 or i % 5 == 0 or i % 7 == 0:
res += i
return res
别人的
class Solution:
def sumOfMultiples(self, n: int) -> int:
def f(m: int) -> int:
return (m + n // m * m) * (n // m) // 2
return f(3) + f(5) + f(7) - f(3 * 5) - f(3 * 7) - f(5 * 7) + f(3 * 5 * 7)