5、 listnode 5.1 反转链表 while循环中引入两个中间变量pre,next存储当前节点的前一个节点和下一个节点初始值为None class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # 返回ListNode def ReverseList(self, pHead): # write code here if pHead == None or pHead.next ==None: return pHead pre = None # 前一个节点(None初始化) next = None # 下一个节点(None初始化) while pHead != None: next = pHead.next # 先保存下一个节点 pHead.next = pre # 下一个节点指向前一个节点(反转链表) pre = pHead # 前一个节点更新(用于下一个循环使用,也用于返回值) pHead = next # 用下一个节点替代当前节点(触发下一步循环) return pre # 原链表最后一个节点next为none, 因此循环结束返回pre 5.2 链表中的节点每k个一组翻转 1、对输出链表向尾向头赋值,引入一个临时变量next,尾部时next=None, 后续next=cur class Solution: def reverseKGroup(self , head , k ): # write code here buf = [] while head: buf.append(head.val) head = head.next n = len(buf) if n==0: return None i_max = n//k for i in range(i_max): t = buf[i*k:(i+1)*k] buf[i*k:(i+1)*k] = t[::-1] buf = buf[::-1] #print('buf=',buf) next = None for i in range(n): cur = ListNode(buf[i]) cur.next = next next = cur return cur 5.3 链表中环的入口结点 遍历单链表的每个结点,如果当前结点地址没有出现在set中,则存入set中 否则,出现在set中,则当前结点就是环的入口结点,整个单链表遍历完,若没出现在set中,则不存在环 class Solution: def EntryNodeOfLoop(self, pHead): # write code here if not pHead or not pHead.next: return None visited = set() while pHead: if pHead not in visited: visited.add(pHead) pHead = pHead.next else: return pHead return None 5.4 删除链表的倒数第n个节点 1、将链表节点加入一个List型数组 arr, 通过操作arr[i].next来实现删除 2、head实际长度可能为 0,1,2,3……,head值尽量不要动,其它操作用副本t=head 3、删除的位置在中间是正常情况,异常情况要考虑头尾,超范围等 class Solution: def removeNthFromEnd(self , head , n ): # write code here if not head: return None t = head arr = [] while t: arr.append(t) t = t.next m = len(arr) if m==1: if n==1: return None else: return head if n==1: arr[-2].next = None head = arr[0] elif n==m: head = arr[1] elif 1<=n-1<=m and 1<=n+1<=m: arr[-(n+1)].next = arr[-(n-1)] return head 5.5 合并有序链表 1、读入两个链表合成一个list再由大小到排序 2、对输出链表向尾向头赋值,引入一个临时变量next,尾部时next=None, 后续next=cur class Solution: def mergeTwoLists(self , l1 , l2 ): # write code here if l1==None and l2==None: return None tmp = [] while l1: tmp.append(l1.val) l1 = l1.next while l2: tmp.append(l2.val) l2 = l2.next tmp = sorted(tmp,reverse=1) n = len(tmp) next = None for i in range(n): cur = ListNode(tmp[i]) cur.next = next next = cur return cur 6、 tree 6.1 数组生成二叉树 class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None L = [1,2,3,4,5,6,7,8,9] n = len(L) Tree = [] for i in range(n): Tree.append(TreeNode(L[i])) for i in range(n): if 2*i+1<=n-1: Tree[i].left = Tree[2*i+1] if 2*i+2<=n-1: Tree[i].right = Tree[2*i+2] root = Tree[0] def dfs(root): if not root: return print(root.val, end=' ') dfs(root.left) dfs(root.right) dfs(root) 6.2 二叉树的层序遍历 1、BFS广度优先搜索,先获得每一层需要输出节点的个数,再一个个减小到0,这一层输出结束后,再输出下一层 2、queue.insert(0, cur.left),新增节点插入到0位 class Solution: def levelOrder(self , root ): # write code here if not root: return None queue = [root] res = [] def bfs(root): while queue: n = len(queue) level = [] while n>0: cur = queue.pop() level.append(cur.val) if cur.left: queue.insert(0, cur.left) if cur.right: queue.insert(0, cur.right) n -= 1 res.append(level) return res return bfs(root) 6.3 二叉树的之字形层序遍历 1、BFS广度优先搜索,先获得每一层需要输出节点的个数,再一个个减小到0,这一层输出结束后,再输出下一层 2、queue.insert(0, cur.left),新增节点插入到0位 3、之字型:引入一个变量k记录奇偶层,层数从0开始,奇数层tmp.appe***al) 改成 tmp.insert(0,t.val) class Solution: def zigzagLevelOrder(self , root ): # write code here if not root: return None queue = [root] res = [] k = 0 while queue: n = len(queue) tmp = [] while n>0: t = queue.pop() #print('k=',k) if k%2==0: tmp.appe***al) else: tmp.insert(0,t.val) if t.left: queue.insert(0,t.left) if t.right: queue.insert(0,t.right) n -= 1 k += 1 res.append(tmp) print('res=',res) return res 6.4 二叉树先序,中序和后序遍历 pre = [] def dfs_pre(root): if not root: return pre.append(root.val) dfs_pre(root.left) dfs_pre(root.right) mid = [] def dfs_mid(root): if not root: return dfs_mid(root.left) mid.append(root.val) dfs_mid(root.right) post = [] def dfs_post(root): if not root: return dfs_post(root.left) dfs_post(root.right) post.append(root.val) class Solution: def threeOrders(self , root ): # write code here dfs_pre(root) dfs_mid(root) dfs_post(root) return [pre,mid,post] 6.5 二叉树中找到两个节点的最近公共祖先 1、先dfs搜索,返回节点路径 2、取路径交集返回最近的交点 def dfs(root,o1,res): if root.val == o1: #print('res=',res) return res if root.left: t = dfs(root.left,o1,res+[root.left.val]) if t: return t if root.right: t = dfs(root.right,o1,res+[root.right.val]) if t: return t class Solution: def lowestCommonAncestor(self , root , o1 , o2 ): # write code here L1 = dfs(root,o1,[root.val]) L2 = dfs(root,o2,[root.val]) #print(L1) #print(L2) L1 = L1[::-1] L2 = L2[::-1] for i in L1: for j in L2: if i==j: return i return None 6.6 二叉树根节点到叶子节点和为指定值的路径 1、先dfs搜索,返回节点路径 2、当前为末端节点,且满足路径和条件,全局保存 class Solution: def pathSum(self , root , i ): # write code here if not root: return [] res = [root.val] out = [] def dfs(root,res): if not root.left and not root.right and sum(res)==i: out.append(res) if root.left: dfs(root.left,res+[root.left.val]) if root.right: dfs(root.right,res+[root.right.val]) dfs(root,res) #print('out=',out) return out ''' 6.7 二叉树重建 #============================================================================================= https://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=196&&tqId=37109&rp=1&ru=/activity/oj&qru=/ta/job-code-total/question-ranking 解题思路: 前序遍历:先根节点,再左子树,最后右子树 中序遍历:先左子树,再根节点,最后右子树 我们可以先从前序遍历的第一个元素得到根节点root=TreeNode(pre.pop(0)) 再从中序排序中找到根节点所在位置,以这个位置为中心,可以得到二叉树的左子树与右子树 二叉树可以分开看,左子树可以看成一个新的二叉树,不断细分,可以确定到每一个叶子节点 同理,右子树也可以,看成新的二叉树,我们可以通过递归来实现 特殊情况的考虑:无论哪一个遍历为空,题目所求都没有意义 #============================================================================================= ''' # -*- coding:utf-8 -*- class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: # 返回构造的TreeNode根节点 def reConstructBinaryTree(self, pre, tin): # write code here if not pre or not tin: return None #print('pre=',pre) #print('tin=',tin) #print('---') val = pre.pop(0) root = TreeNode(val) i = tin.index(val) root.left = self.reConstructBinaryTree(pre, tin[:i]) root.right = self.reConstructBinaryTree(pre, tin[i+1:]) return root pre = [1,2,3,4,5,6,7] tin = [3,2,4,1,6,5,7] Solution().reConstructBinaryTree(pre, tin) ''' 6.8 二叉树深度 https://www.nowcoder.com/practice/8a2b2bf6c19b4f23a9bdb9b233eefa73?tpId=196&&tqId=37055&rp=1&ru=/activity/oj&qru=/ta/job-code-total/question-ranking ''' # -*- coding:utf-8 -*- class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None # @param root TreeNode类 # @return int整型 # class Solution: def maxDepth(self , root ): # write code here if not root: return 0 out = [] def dfs(root,res): if not root: return if not root.left and not root.right: out.append(res) if root.left: dfs(root.left, res+[root.left.val]) if root.right: dfs(root.right, res+[root.right.val]) dfs(root,[root.val]) depth = 0 for i in out: if len(i)>depth: depth = len(i) return depth ''' 6.9 最小生成树 https://www.nowcoder.com/practice/735a34ff4672498b95660f43b7fcd628?tpId=196&&tqId=37574&rp=1&ru=/activity/oj&qru=/ta/job-code-total/question-ranking ''' # 返回最小的花费代价使得这n户人家连接起来 # @param n int n户人家的村庄 # @param m int m条路 # @param cost int二维数组 一维3个参数,表示连接1个村庄到另外1个村庄的花费的代价 # @return int # class Solution: def miniSpanningTree(self , n , m , cost ): # write code here p = list(range(n+1)) height = [0 for _ in range(n+1)] cost = list(sorted(cost, key=lambda x: x[2])) def find(n): while n != p[n]: n = p[n] return n i = 0 ans = 0 for a, b, c in cost: if i == n - 1: break pa = find(a) pb = find(b) if pa == pb: continue if height[pa] > height[pb]: p[pb] = pa elif height[pb] > height[pa]: p[pa] = pb else: height[pb] += 1 p[pa] = pb ans += c i += 1 return ans Solution().miniSpanningTree(3,3,[[1,3,3],[1,2,1],[2,3,1]]) 7、 biSearch def biSearch(L, v): x1 = 0 x2 = len(L)-1 while x1<x2: #print('x1=',x1,'x2=',x2) xm = (x1+x2)//2 if L[xm] < v: # 注意这里<,<=要多测试 x1 = xm+1 # 注意这里xm+1,xm要多测试 else: x2 = xm return x1 7.1 最长增长子序列 L = arr n = len(L) #-------------------------------------- # 数组B维护的是当前最长递增子序列的最小末尾值,参见下文 # https://blog.csdn.net/sinat_31790817/article/details/78348722 B = [L[0]] dp = [1] for i in range(1, n): if L[i]>B[-1]: B.append(L[i]) dp.append(len(B)) else: t = biSearch(B, L[i]) B[t] = L[i] dp.append(t+1) print('B=',B) print('dp=',dp) #-------------------------------------- # 在dp序列中反向寻找第一个出现的maxLen,maxLen-1,maxLen-2,…… 1,所对应的原数组元素 C = [] maxLen = max(dp) for i in range(len(dp)-1,-1,-1): if dp[i]==maxLen: C.append(L[i]) maxLen -= 1 return C[::-1] 7.2 求平方根 def f(x): return x*x class Solution: def sqrt(self , x ): # write code here y = x if y<0: return None elif y==0: return 0 elif y==1: return 1 else: x1 = 1 x2 = x while x2-x1>1e-4: xm = (x1+x2)/2 #print('xm=',xm) if (f(x1)-y)*(f(xm)-y)>0: x1 = xm else: x2 = xm print('x2=',x2) return int(x2) 7.3 求立方根 y = float(input()) x1 = 0.0 if y>0: x2 = max(y,1) else: x2 = min(y,-1) f = lambda x:x**3 k = 0 while abs(x1-x2) > 1e-4: x0 = (x1+x2)/2 if (f(x1)-y)*(f(x0)-y)>0: x1 = x0 else: x2 = x0 k += 1 print(round(x1*10)/10)