继续leetcode刷题生涯
这里记录的都是笔者觉得有点意思的做法
参考了好几位大佬的题解,尤其是powcai大佬和labuladong大佬,感谢各位大佬
class WordDictionary:
def __init__(self):
"""
Initialize your data structure here.
"""
from collections import defaultdict
self.lookup = {}
def addWord(self, word: str) -> None:
"""
Adds a word into the data structure.
"""
tree = self.lookup
for a in word:
tree = tree.setdefault(a,{})
tree["#"] = {}
def search(self, word: str) -> bool:
"""
Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
"""
def helper(word, tree):
if not word:
if "#" in tree:
return True
return False
if word[0] == ".":
for t in tree:
if helper(word[1:], tree[t]):
return True
elif word[0] in tree:
if helper(word[1:],tree[word[0]]):
return True
return False
return helper(word, self.lookup)
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
lookup = {}
# word存入前缀树
for word in words:
t = lookup
for a in word:
t = t.setdefault(a, {})
t["end"] = 1
res = []
row = len(board)
col = len(board[0])
# dfs
def dfs(i, j, lookup, s):
c = board[i][j]
if c not in lookup:
return
lookup = lookup[c]
if "end" in lookup and lookup["end"] == 1:
res.append(s+c)
lookup["end"] = 0
board[i][j] = "#"
for x,y in [[-1,0], [1,0], [0,-1],[0,1]]:
tmp_i = x + i
tmp_j = y + j
if 0 <= tmp_i < row and 0 <= tmp_j < col and board[tmp_i][tmp_j] != "#":
dfs(tmp_i, tmp_j, lookup, s + c)
board[i][j] = c
for i in range(row):
for j in range(col):
dfs(i, j, lookup, "")
return res
# 问题分成求 nums[0:n - 1]或者 nums[1:n]
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums: return 0
if len(nums) == 1: return nums[0]
def helper(nums):
if not nums: return 0
if len(nums) == 1: return nums[0]
n = len(nums)
dp = [0] * (n+1)
dp[1] = nums[0]
for i in range(2, n+1):
dp[i] = max(dp[i-1], dp[i-2]+nums[i-1])
return dp[-1]
return max(helper(nums[1:]), helper(nums[:-1]))
# 暴力 O(n^2)
class Solution:
def shortestPalindrome(self, s: str) -> str:
r = s[::-1]
for i in range(len(s) + 1):
if s.startswith(r[i:]):
return r[:i] + s
# KMP O(n)
class Solution:
def shortestPalindrome(self, s: str) -> str:
def get_table(p):
table = [0] * len(p)
i, j = 1, 0
while i < len(p):
if p[i] == p[j]:
j += 1
table[i] = j
i += 1
else:
if j > 0:
j = table[j-i]
else:
i += 1
j = 0
return table
table = get_table(s + "#" + s[::-1])
return s[table[-1]:][::-1] + s
# 普通排序 nlogn
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
return sorted(nums, reverse=True)[k-1]
# 堆排序 klogn
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
import heapq
return heapq.nlargest(k, nums)[-1]
# 手写堆排序
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def adjust_heap(idx, max_len):
left = 2 * idx + 1
right = 2 * idx + 2
max_loc = idx
if left < max_len and nums[max_loc] < nums[left]:
max_loc = left
if right < max_len and nums[max_loc] < nums[right]:
max_loc = right
if max_loc != idx:
nums[idx], nums[max_loc] = nums[max_loc], nums[idx]
adjust_heap(max_loc, max_len)
# 建堆
n = len(nums)
for i in range(n // 2 - 1, -1, -1):
adjust_heap(i, n)
# print(nums)
res = None
for i in range(1, k + 1):
# print(nums)
res = nums[0]
nums[0], nums[-i] = nums[-i], nums[0]
adjust_heap(0, n - i)
return res
# 快排 O(n)最差O(n^2)
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def partition(left, right):
pivot = nums[left]
l = left + 1
r = right
while l <= r:
if nums[l] < pivot and nums[r] > pivot:
nums[l], nums[r] = nums[r], nums[l]
if nums[l] >= pivot:
l += 1
if nums[r] <= pivot:
r -= 1
nums[r], nums[left] = nums[left], nums[r]
return r
left = 0
right = len(nums) - 1
while 1:
idx = partition(left, right)
if idx == k - 1:
return nums[idx]
if idx < k - 1:
left = idx + 1
if idx > k - 1:
right = idx - 1
# 回溯
class Solution:
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
if n <= 0 or n > (k * 9): return []
res = []
def helper(k, n, start, tmp):
if k == 0:
if n == 0:
res.append(tmp)
return
for i in range(start, 10):
if n - i < 0: break
helper(k - 1, n - i, i + 1, tmp + [i])
helper(k, n, 1, [])
return res
# 库函数
class Solution:
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
import itertools
return [item for item in itertools.combinations(range(1, 10), k) if sum(item) == n]
# 集合
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
s = set(nums)
if len(s) != len(nums):
return True
return False
# 分而治之
class Solution:
def getSkyline(self, buildings: List[List[int]]) -> List[List[int]]:
if not buildings: return []
if len(buildings) == 1:
return [[buildings[0][0], buildings[0][2]], [buildings[0][1], 0]]
mid = len(buildings) // 2
left = self.getSkyline(buildings[:mid])
right = self.getSkyline(buildings[mid:])
return self.merge(left, right)
def merge(self, left, right):
lh = rh = 0
l = r = 0
res = []
while l < len(left) and r < len(right):
if left[l][0] < right[r][0]:
cp = [left[l][0], max(left[l][1], rh)]
lh = left[l][1]
l += 1
elif left[l][0] > right[r][0]:
cp = [right[r][0], max(right[r][1], lh)]
rh = right[r][1]
r += 1
else:
cp = [left[l][0], max(left[l][1], right[r][1])]
lh = left[l][1]
rh = right[r][1]
l += 1
r += 1
if len(res) == 0 or res[-1][1] != cp[1]:
res.append(cp)
res.extend(left[l:] or right[r:])
return res
class Solution:
def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
if len(set(nums)) == len(nums):
return False
lookup = {}
for index, num in enumerate(nums):
if num in lookup and index-lookup[num] <= k:
return True
lookup[num] = index
return False
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
if t < 0: return False
n = len(nums)
d = {}
w = t + 1
for i in range(n):
m = nums[i] // w
if m in d:
return True
if m - 1 in d and abs(nums[i] - d[m - 1]) < w:
return True
if m + 1 in d and abs(nums[i] - d[m + 1]) < w:
return True
d[m] = nums[i]
if i >= k: del d[nums[i - k] // w]
return False