468. 验证IP地址
class Solution:
def validIPAddress(self, queryIP: str) -> str:
def isIPv4(ip: str) -> bool:
return all(s and s.isdigit() and not(s[0] == '0' and len(s) > 1) and 0 <= int(s) <= 255 for s in sp) if len(sp := ip.split(".")) == 4 else False
def isIPv6(ip: str) -> bool:
return all(s and len(s) <= 4 and all(c in "0123456789ABCDEFabcdef" for c in s) for s in sp) if len(sp := ip.split(":")) == 8 else False
if "." in queryIP and ":" not in queryIP and isIPv4(queryIP):
return "IPv4"
elif ":" in queryIP and "." not in queryIP and isIPv6(queryIP):
return "IPv6"
return "Neither"
560. 和为 K 的子数组
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
s = 0; res = 0
# # 哨兵,起始边界条件
d = defaultdict(int); d[0] = 1
for num in nums:
s += num
res += d[s-k]
d[s] += 1
return res
# 一维前缀和
# 前缀和 + hash表
# s[i] = s[i-1] + num[i]
# 找使 s[i] - s[j] == k 的 j 的个数
# hash表记录前缀和出现的次数
# 时间复杂度:O(n),其中 n 为数组的长度。我们遍历数组的时间复杂度为 O(n),中间利用哈希表查询删除的复杂度均为 O(1),因此总时间复杂度为 O(n)。
# 空间复杂度:O(n)
138. 复制带随机指针的链表
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
if not head: return None
d = dict()
p = head
while p:
d[p] = Node(p.val)
p = p.next
p = head
while p:
d[p].next = d.get(p.next)
d[p].random = d.get(p.random)
p = p.next
return d[head]
209. 长度最小的子数组
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
n = len(nums)
res = n + 1; s = 0
i = j = 0
while j < n:
s += nums[j]
while s >= target:
res = min(res, j - i + 1)
s -= nums[i]
i += 1
j += 1
return res if res != n + 1 else 0
# 时间复杂度:O(n)
# 空间复杂度:O(1)
739. 每日温度
class Solution:
def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
s = []
res = [0] * len(temperatures)
for i, v in enumerate(temperatures):
while s and v > s[-1][1]:
s_i, s_v = s.pop()
res[s_i] = i - s_i
s.append((i, v))
return res
# 1.若栈为空或当日温度小于栈顶温度,则直接入栈
# 2.若当日温度大于栈顶温度,说明栈顶元素升温日找到,将栈顶元素出栈,计算其与当日相差的天数
136. 只出现一次的数字
class Solution:
def singleNumber(self, nums: List[int]) -> int:
res = 0
for num in nums:
res ^= num
return res
498. 对角线遍历
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
res = []
m = len(mat); n = len(mat[0])
for k in range(m+n-1):
if k % 2 == 0:
res += [mat[x][k-x] for x in range(min(m-1,k), max(-1,k-n), -1)]
else:
res += [mat[x][k-x] for x in range(max(0,k-n+1),min(m,k+1))]
return res
剑指 Offer 36. 二叉搜索树与双向链表
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def dfs(self, root: 'Node') -> 'Node':
if not root: return
self.dfs(root.left)
# 双向链表
root.left = self.pre
self.pre.right = root
# 右移指针
self.pre = root
self.dfs(root.right)
def treeToDoublyList(self, root: 'Node') -> 'Node':
if not root: return
self.pre = head = Node()
self.dfs(root)
# 首尾相连
self.pre.right, head.right.left = head.right, self.pre
return head.right
224. 基本计算器
class Solution:
def calculate(self, s: str) -> int:
ops = [1]
sign = 1
res = 0
n = len(s)
i = 0
while i < n:
if s[i] == ' ':
i += 1
elif s[i] == '+':
sign = ops[-1]
i += 1
elif s[i] == '-':
sign = -ops[-1]
i += 1
elif s[i] == '(':
ops.append(sign)
i += 1
elif s[i] == ')':
ops.pop()
i += 1
else:
num = 0
while i < n and s[i].isdigit():
num = num * 10 + ord(s[i]) - ord('0')
i += 1
res += num * sign
return res
剑指 Offer 09. 用两个栈实现队列
class CQueue:
def __init__(self):
self.s1, self.s2 = [], []
def appendTail(self, value: int) -> None:
self.s1.append(value)
def deleteHead(self) -> int:
if not self.s2:
while self.s1: self.s2.append(self.s1.pop())
return self.s2.pop() if self.s2 else -1
# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()
460. LFU 缓存
class Node:
def __init__(self, key, val, pre=None, nex=None, freq=0):
self.pre = pre
self.nex = nex
self.freq = freq
self.val = val
self.key = key
def insert(self, nex):
nex.pre = self
nex.nex = self.nex
self.nex.pre = nex
self.nex = nex
def create_linked_list():
head = Node(0, 0)
tail = Node(0, 0)
head.nex = tail
tail.pre = head
return (head, tail)
class LFUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.size = 0
self.minFreq = 0
self.freqMap = collections.defaultdict(create_linked_list)
self.keyMap = {}
def delete(self, node):
if node.pre:
node.pre.nex = node.nex
node.nex.pre = node.pre
if node.pre is self.freqMap[node.freq][0] and node.nex is self.freqMap[node.freq][-1]:
self.freqMap.pop(node.freq)
return node.key
def increase(self, node):
node.freq += 1
self.delete(node)
self.freqMap[node.freq][-1].pre.insert(node)
if node.freq == 1:
self.minFreq = 1
elif self.minFreq == node.freq - 1:
head, tail = self.freqMap[node.freq - 1]
if head.nex is tail:
self.minFreq = node.freq
def get(self, key: int) -> int:
if key in self.keyMap:
self.increase(self.keyMap[key])
return self.keyMap[key].val
return -1
def put(self, key: int, value: int) -> None:
if self.capacity != 0:
if key in self.keyMap:
node = self.keyMap[key]
node.val = value
else:
node = Node(key, value)
self.keyMap[key] = node
self.size += 1
if self.size > self.capacity:
self.size -= 1
deleted = self.delete(self.freqMap[self.minFreq][0].nex)
self.keyMap.pop(deleted)
self.increase(node)
912. 排序数组
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def merge_sort(a: list, l: int, r: int) -> list:
if l >= r: return a
m = l + r >> 1
i = l; j = m + 1
tmp = []
merge_sort(a, l, m); merge_sort(a, m + 1, r)
while i <= m and j <= r:
if a[i] < a[j]:
tmp.append(a[i])
i += 1
else:
tmp.append(a[j])
j += 1
tmp += a[i:m+1]
tmp += a[j:r+1]
a[l:r+1] = tmp
return a
return merge_sort(nums, 0, len(nums) - 1)
207. 课程表
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
edges = collections.defaultdict(list)
indeg = [0] * numCourses
for info in prerequisites:
edges[info[1]].append(info[0])
indeg[info[0]] += 1
q = collections.deque([u for u in range(numCourses) if indeg[u] == 0])
visited = 0
while q:
visited += 1
u = q.popleft()
for v in edges[u]:
indeg[v] -= 1
if indeg[v] == 0:
q.append(v)
return visited == numCourses
402. 移掉 K 位数字
class Solution:
def removeKdigits(self, num: str, k: int) -> str:
numStack = []
# 构建单调递增的数字串
for digit in num:
while k and numStack and numStack[-1] > digit:
numStack.pop()
k -= 1
numStack.append(digit)
# 如果 K > 0,删除末尾的 K 个字符
finalStack = numStack[:-k] if k else numStack
# 抹去前导零
return "".join(finalStack).lstrip('0') or "0"
958. 二叉树的完全性检验
# 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(object):
def isCompleteTree(self, root):
q = [(root, 1)]
i = 0
while i < len(q):
node, v = q[i]
if node:
q.append((node.left, 2*v))
q.append((node.right, 2*v+1))
i += 1
return q[-1][1] == len(q)
# 时间复杂度:O(N)
# 空间复杂度:O(N)
61. 旋转链表
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
# 若链表为空,返回head
if not head:
return head
# 获取链表的长度
n = 0
cur = head
while cur:
n += 1
cur = cur.next
# 若k的长度大于n,将k对n求余
k = k % n
# 若k==0表示循环了一整遍,直接返回head
if k == 0:
return head
# 创建快慢指针
slow = fast = head
# fast指针先走k步
while k:
fast = fast.next
k -= 1
# 让fast指针走到队尾
while fast.next:
fast = fast.next
slow = slow.next
# 此时show.next为新的链表头
h = slow.next
# 断开slow.next
slow.next = None
# 链表首位相接
fast.next = head
# 返回新的链表头
return h
11. 盛最多水的容器
class Solution:
def maxArea(self, height: List[int]) -> int:
res = 0
l = 0; r = len(height) - 1
while l < r:
# 相同条件下边界距离越远,面积越大,所以设置左右指针从两边向中间移动;哪个边界小,哪个边界移动重新寻找机会,希望用边界高度的增加弥补两边界距离的减小
if height[l] < height[r]:
res = max(res, (r - l) * height[l])
l += 1
else:
res = max(res, (r - l) * height[r])
r -= 1
return res
剑指 Offer 54. 二叉搜索树的第k大节点
# Definition for a binary tree node.
# class TreeNode:
# def __init__(sel