- 剑指 Offer 35. 复杂链表的复制
- 剑指 Offer 36. 二叉搜索树与双向链表
- 剑指 Offer 41. 数据流中的中位数
- 剑指 Offer 51. 数组中的逆序对
- 剑指 Offer 60. n个骰子的点数
- 剑指 Offer 62. 圆圈中最后剩下的数字
- 剑指 Offer 65. 不用加减乘除做加法
剑指 Offer 35. 复杂链表的复制
比普通链表多了一个random指针,因此如果按照链表next的顺序遍历一个个新建,无法知道random指向的节点在哪,所以需要用一个哈希表去一个个查询random指向的节点在哪。
"""
# 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: 'Node') -> 'Node':
if not head:
return
dic ={}
cur = head
while cur:
dic[cur]=Node(cur.val) # 这里相当于将(原节点cur,新建节点cur)存入dic
cur = cur.next
cur =head
while cur: #dict.get()是返回对应键的值,如果不存在则返回default
dic[cur].next = dic.get(cur.next) # 前者相当于取出新建节点,将他的next指向(cur.next, 新建节点)中的新建节点
dic[cur].random = dic.get(cur.random) #同上,只不过是random
cur = cur.next
return dic[head]
剑指 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 treeToDoublyList(self, root: 'Node') -> 'Node':
def dfs(node): # 深度优先,中序遍历
if not node:
return
dfs(node.left)
if self.pre:
self.pre.right = node #将1节点的right指向2节点
node.left = self.pre #将2节点的left指向1节点
else:
self.head = node
self.pre = node
dfs(node.right)
if not root: return
self.pre = None
dfs(root)
self.head.left = self.pre #将头部节点和尾部节点相连
self.pre.right = self.head
return self.head
剑指 Offer 41. 数据流中的中位数
class MedianFinder:
def __init__(self):
"""
initialize your data structure here.
"""
self.A = []
self.B = []
def addNum(self, num: int) -> None:
if len(self.A)==len(self.B):
heappush(self.B,-num)
tmp = -heappop(self.B)
heappush(self.A, tmp)
else:
heappush(self.A,num)
tmp = -heappop(self.A)
heappush(self.B, tmp)
def findMedian(self) -> float:
return self.A[0] if len(self.A)!=len(self.B) else (self.A[0]-self.B[0])/2.0
剑指 Offer 51. 数组中的逆序对
归并排序
class Solution:
def reversePairs(self, nums: List[int]) -> int:
def merge_sort(l,r):
if l>=r: #直到分成单个元素
return 0
m=(l+r)//2
res = merge_sort(l,m)+merge_sort(m+1,r) # 递归分割
i,j = l, m+1 # 排序
tmp[l:r+1] = nums[l:r+1] # 先复制一遍数字到tmp,排序在原nums里
for k in range(l,r+1):
if i == m+1: # 说明左边的数字已经全都添加到排序后的list里面了
nums[k] = tmp[j]# 将右边的待排序数字加入排序后的list里
j+=1 # 这里不存在逆序对,因为题目要求是左边数字大于右边的情况,此时左边数组已经空了
elif j == r+1 or tmp[i]<=tmp[j]: # 添加左边数字,说明其小于右边数组,不存在逆序对,或者是右边数组已经全部添加到排序后的list里面了,虽然左边数字大,但是没有比它小的右边数字了,不存在逆序对
nums[k] = tmp[i]
i+=1
else: # 左右数组都还有待排序的数字,并且右边数字更小,此时符合逆序对的条件
nums[k] = tmp[j]
j+=1
res+=m-i+1 # 这里加上的是左边数组内目前还有的数字个数
return res
tmp = [0 for _ in range(len(nums))]
return merge_sort(0,len(nums)-1)
剑指 Offer 60. n个骰子的点数
class Solution:
def dicesProbability(self, n: int) -> List[float]:
dp = [1/6]*6
for i in range(2,n+1):
tmp=[0]*(5*i+1)
for j in range(len(dp)):
for k in range(6):
tmp[j+k] += dp[j]/6
dp = tmp
return dp
剑指 Offer 62. 圆圈中最后剩下的数字
class Solution:
def lastRemaining(self, n: int, m: int) -> int:
x = 0
for i in range(2,n+1):
x = (x+m)%i
return x
剑指 Offer 65. 不用加减乘除做加法
class Solution:
def add(self, a: int, b: int) -> int:
x = 0xffffffff
a,b = a&x,b&x
while b:
a,b = (a^b),(a&b)<<1 & x # &x是为了防止溢出32位
return a if a<=0x7fffffff else ~(a^x)