前言
继续leetcode刷题生涯
这里记录的都是笔者觉得有点意思的做法
参考了好几位大佬的题解,尤其是powcai大佬和labuladong大佬,感谢各位大佬
371. 两整数之和
# 位运算
class Solution(object):
def getSum(self, a, b):
"""
:type a: int
:type b: int
:rtype: int
"""
# 2^32
MASK = 0x100000000
# 整型最大值
MAX_INT = 0x7FFFFFFF
MIN_INT = MAX_INT + 1
while b != 0:
# 计算进位
carry = (a & b) << 1
# 取余范围限制在 [0, 2^32-1] 范围内
a = (a ^ b) % MASK
b = carry % MASK
return a if a <= MAX_INT else ~((a % MIN_INT) ^ MAX_INT)
# 偷鸡
class Solution(object):
def getSum(self, a, b):
return sum([a, b])
372. 超级次方
# (xy)%k=(x%k)(y%k)%k
class Solution:
def superPow(self, a: int, b: List[int]) -> int:
if not b: return 1
tmp = b.pop()
return (((self.superPow(a, b)) ** 10) % 1337 * (a ** tmp) % 1337 ) % 1337
373. 查找和最小的K对数字
# 暴力
def kSmallestPairs(self, nums1, nums2, k):
import itertools
return map(list, sorted(itertools.product(nums1, nums2), key=sum)[:k])
# 堆
class Solution:
def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
import heapq
res = []
queue = []
if not nums1 or not nums2:
return []
heapq.heappush(queue, (nums1[0] + nums2[0], (0, 0)))
# 防止重复加入
visited = {(0, 0)}
while queue and len(res) < k:
_, (i, j) = heapq.heappop(queue)
res.append((nums1[i], nums2[j]))
# 每次nums1 或者 nums2 移动
if i + 1 < len(nums1) and (i + 1, j) not in visited:
heapq.heappush(queue, (nums1[i + 1] + nums2[j], (i + 1, j)))
visited.add((i + 1, j))
if j + 1 < len(nums2) and (i, j + 1) not in visited:
heapq.heappush(queue, (nums1[i] + nums2[j + 1], (i, j + 1)))
visited.add((i, j + 1))
return res
374. 猜数字大小
# 二分
class Solution:
def guessNumber(self, n: int) -> int:
left = 1
right = n
while left < right:
mid = (left + right) // 2
if guess(mid) == 1:
left = mid + 1
else:
right = mid
return left
375. 猜数字大小 II
class Solution:
def getMoneyAmount(self, n: int) -> int:
@functools.lru_cache(maxsize=None)
def sol(l, r) :
if r-l == 2 : return l
if r-l <= 1 : return 0
return min((i+max(sol(l,i), sol(i+1,r)) for i in range(l, r)))
return sol(1,n+1)
376. 摆动序列
# 动态规划
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
# dp 记录 i位置前一个位置是上升, 还是下降dp[i][0]表示下降 dp[i][1] 表示上升
if not nums: return 0
dp = [[1] * 2 for _ in range(len(nums))]
for i in range(1, len(nums)):
# 上升到下降
if nums[i - 1] > nums[i]:
dp[i][0] = dp[i - 1][1] + 1
dp[i][1] = dp[i - 1][1]
elif nums[i - 1] < nums[i]:
dp[i][1] = dp[i - 1][0] + 1
dp[i][0] = dp[i - 1][0]
else:
dp[i][0] = dp[i - 1][0]
dp[i][1] = dp[i - 1][1]
return max(dp[-1])
377. 组合总和 Ⅳ
# 动态规划
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
from collections import defaultdict
dp = defaultdict(int)
dp[0] = 1
for i in range(1, target + 1):
for num in nums:
dp[i] += dp[i - num]
return dp[target]
378. 有序矩阵中第K小的元素
class Solution:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
n = len(matrix)
left = matrix[0][0]
right = matrix[-1][-1]
def search_less_equal(mid):
i = 0
j = n - 1
res = 0
while i < n and j >= 0:
if matrix[i][j] <= mid:
res += (j + 1)
i += 1
else:
j -= 1
return res
while left < right:
mid = (left + right) // 2
num = search_less_equal(mid)
if num < k:
left = mid + 1
else:
right = mid
return left
380. 常数时间插入、删除和获取随机元素
import random
class RandomizedSet:
def __init__(self):
"""
Initialize your data structure here.
"""
self.a = set()
def insert(self, val: int) -> bool:
"""
Inserts a value to the set. Returns true if the set did not already contain the specified element.
"""
if val not in self.a:
self.a.add(val)
return True
return False
def remove(self, val: int) -> bool:
"""
Removes a value from the set. Returns true if the set contained the specified element.
"""
if val in self.a:
self.a.remove(val)
return True
return False
def getRandom(self) -> int:
"""
Get a random element from the set.
"""
return random.choice(list(self.a))