主要讲解在 oj 的面试背景下,如何处理数据结构。
因为动态链表比较复杂,每次需要重建的时间成本比较大。因此在题目中一般采用数组模拟静态链表的操作。 定义:e[index]表示编号为index的节点的数值,ne[index]表示编号为index的节点的子节点,每次最后还需要index++表示生成新的数组位置。
e = [0]*100000 ne = [0]*100000 index = 0 head = -1 N = int(input()) def add_to_head(x): # 头插链表,链表的尾部是-1 # 注意设置全局变量 global e, index, head, ne e[index] = x ne[index] = head head = index index += 1 def insert(k, x): # 插入到第k个后面 global e, index,ne e[index] = x ne[index] = ne[k] ne[k] = index index += 1 def delete(k): # 删除第K个插入的数后面的数 global ne ne[k] = ne[ne[k]] for i in range(N): # 注意这里的读入方法 s, *p = input().split() if s == 'H': # int这个函数只能操作字符型 add_to_head(int(p[0])) elif s == 'I': k, x = map(int, p) insert(k-1, x) elif s == 'D': k = int(p[0]) if k == 0: head = ne[head] else: delete(k-1) while head != -1: print(e[head], end=' ') head = ne[head]Trie字典树
class Trie: def __init__(self): """ Initialize your data structure here. """ self.dic = {} def insert(self, word: str) -> None: """ Inserts a word into the trie. """ ## 一定要另外调用字典 dic = self.dic for i in word: if not i in dic: dic[i] = {} dic = dic[i] dic['end'] = True def search(self, word: str) -> bool: """ Returns if the word is in the trie. """ dic = self.dic for i in word: if not i in dic: return False dic = dic[i] if 'end' in dic: return True return False def startsWith(self, prefix: str) -> bool: """ Returns if there is any word in the trie that starts with the given prefix. """ dic = self.dic for i in prefix: if not i in dic: return False dic = dic[i] return True类似题目:前缀统计,最大异或对
需要支持的操作:
插入一个数求集合中的最小值删除最小值删除任意一个元素修改任意一个元素之前写过的手撕堆
我发现还是把这个存储堆的序列从1开始编号方便,这样左节点是2i,右节点是2i+1;查询父节点时i//2。
变大了堆顶的元素,下移。每次和两个子节点中小的那个交换位置,直到两个子节点都大于等于。
def down(x): # 时间复杂度是logn child = 2*x while child <= size: if child+1 <= size and heap[child+1]<heap[child]: child += 1 if heap[child] < heap[x]: heap[x], heap[child] = heap[child], heap[x] x = child child *= 2 else: break减小了某个叶节点,上移。每次和父节点进行比较,如果父节点大于自己,交换。
专门的并查集的讲解参考,可以参考 。这里在总结一下并查集的子函数结构。
生成新的并查集编号,一般我习惯用字典。
def __init__(self): self.fathernode = {} self.val = {} self.size = {} # 初始化节点 def new_UF(self, node): # 当节点已经存在时 if node in self.fathernode: return self.fathernode[node] = node self.val[node] = 1.0 # 数值 self.size[node] = 1 # 规模寻找每个节点的父节点,这里可以用递归也可以用迭代。递归会更简单一些。
# -------------------------------递归------------------------------ # 查询父节点 同时进行值的更新 # 使用递归 同时对路径进行压缩 将每个节点连接到与父节点的关系 def getfather(self, node): if self.fathernode[node] == node: return node # 递归得到父节点 fa = self.getfather(self.fathernode[node]) # 递归的更新当前节点得值 前父节点关系值 * 更新后得父节点值 self.val[node] = self.val[self.fathernode[node]] * self.val[node] # 将节点的父节点更新为最父节点 self.fathernode[node] = fa return fa # -----------------------------迭代-------------------------------- def findfather(self, node): while self.fathernode[node] != node: self.fathernode[node] = self.fathernode[self.fathernode[node]] node = self.fathernode[node] return node实现合并,一般方法就是合并父节点。
def union(self, node1, node2): node1fa = self.findfather(node1) node2fa = self.findfather(node2) if node1fa == node2fa: return self.count += 1 size_node1 = self.nodesize[node1fa] size_node2 = self.nodesize[node2fa] if size_node1>size_node2: self.fathernode[node2fa] = node1fa self.nodesize[node1fa] += size_node2 else: self.fathernode[node1fa] = node2fa self.nodesize[node2fa] += size_node1思路是使用一个并查集,然后我们维护了每个节点到根节点的距离。保证维护并查集中,每个节点到根节点的距离,定义距离为0,1,2,3 , 1吃0, 2吃1, 0吃2且与1一类。
## 利用并查集解决问题 # 维护并查集中,每个节点到根节点的距离,定义距离为0,1,2,3 # 1吃0, 2吃1, 0吃2且与1一类 N, M = map(int, input().split()) p = {} d = {} def new(x): p[x] = x d[x] = 0 def find(x): if x == p[x]: return x t = find(p[x]) # 先对px进行完路径压缩,这样可以维护好d[px] d[x] += d[p[x]] # d[px]表示了p[x]到根节点的距离,在加上x到px的距离 p[x] = t return p[x] def union(x,y,t): fx = find(x) fy = find(y) p[fx] = fy # 把x连接到y上 add = (d[y]-d[x]+t)# 因为(d[x]+?-d[y]-1)%3 == 0,所以?=d[y]+1-d[x],这里的问号是d[fx]距离d[fy]的距离。 d[fx] = add ans = 0 for i in range(M): a,x,y = map(int,input().split()) if x>N or y>N: ans += 1 #print(x,y) else: if x not in p: new(x) if y not in p: new(y) fx = find(x) fy = find(y) if a == 1: if fx == fy: if (d[x] - d[y])%3 != 0: ans += 1 # 同类矛盾 else: union(x,y, 0) elif a == 2: if fx == fy: if (d[x]-d[y]-1)%3 != 0: # 因为x吃y,所以x比y大1的距离 ans += 1 else: union(x, y, 1) print(ans)