class getCommonNode(object): """返回两个单链表的第一个相交点""" def FindFirstCommonNode(self, pHead1, pHead2): loop1 = self.getLoopNode(pHead1) loop2 = self.getLoopNode(pHead2) if loop1 is None and loop2 is None: return self.noLoop(pHead1, pHead2) if loop1 is not None and loop2 is not None: return self.bothLoop(pHead1, pHead2, loop1, loop2) return None def getLoopNode(self, pHead): if pHead is None or pHead.next is None or pHead.next.next is None: return pHead slow = pHead.next fast = pHead.next.next while slow != fast: if fast.next is None or fast.next.next is None: return None fast = fast.next.next slow = slow.next fast = pHead while slow != fast: slow = slow.next fast =fast.next return slow def noLoop(self, pHead1, pHead2): """两个无环链表的第一个相交公共点""" if pHead1 is None or pHead2 is None: return None cur1 = pHead1 cur2 = pHead2 moreLen = 0 while cur1.next is not None: moreLen += 1 cur1 = cur1.next while cur2.next is not None: moreLen -= 1 cur2 = cur2.next if cur1 != cur2: return None cur1 = pHead1 if moreLen > 0 else pHead2 cur2 = pHead2 if cur1 == pHead1 else pHead1 moreLen = abs(moreLen) while moreLen != 0: moreLen -= 1 cur1 = cur1.next while cur1 != cur2: cur1 = cur1.next cur2 = cur2.next return cur1 def bothLoop(self, pHead1, pHead2, loop1, loop2): if loop1 == loop2: "入环结点相同,退化到两个无环单链表相交问题" cur1 = pHead1 cur2 = pHead2 moreLen = 0 while cur1 != loop1: moreLen += 1 cur1 = cur1.next while cur2.next != loop2: moreLen -= 1 cur2 = cur2.next if cur1 != cur2: return None cur1 = pHead1 if moreLen > 0 else pHead2 cur2 = pHead2 if cur1 == pHead1 else pHead1 moreLen = abs(moreLen) while moreLen != 0: moreLen -= 1 cur1 = cur1.next while cur1 != cur2: cur1 = cur1.next cur2 = cur2.next return cur1 else: "两个有环单链表相交问题,且是不同的入环点" cur1 = loop1.next while cur1 != loop1: if cur1 == loop2: return loop1 cur1 = cur1.next return None def preOrderRecur(pHead): """先序遍历(递归版本)""" if pHead is None: return pHead print(pHead.value + " ") preOrderRecur(pHead.left) preOrderRecur(pHead.right) def preOrderUnRecur(pHead): """先序遍历(非递归版本)""" if pHead is None: return pHead tempList = [] tempList.append(pHead) while tempList != []: curnode = tempList.pop() print(curnode.value + " ") if curnode.right is not None: tempList.append(curnode.right) if curnode.left is not None: tempList.append(curnode.left) def serialByPre(pHead): """先序遍历序列化""" if pHead is None: return "#!" resultStr = pHead.value + "!" resultStr += serialByPre(pHead.left) resultStr += serialByPre(pHead.right) return resultStr def reconByPreString(preStr): """先序遍历反序列化""" valueList = preStr.split("!") tempList = [] for i in range(len(valueList)): tempList.index(0, valueList[i]) return reconPreOrder(tempList) def reconPreOrder(tempList): valueStr = tempList.pop() if valueStr == "#": return None node = treeNode(valueStr) node.left = reconPreOrder(tempList) node.right = reconPreOrder(tempList) return node def inOrderRecur(pHead): """中序遍历(递归版本)""" if pHead is None: return pHead inOrderRecur(pHead.left) print(pHead.value + " ") inOrderRecur(pHead.right) def inOrderUnRecur(pHead): """中序遍历(非递归版本)""" if pHead is None: return pHead tempList = [] while tempList != [] or pHead is not None: if pHead is not None: tempList.append(pHead) pHead = pHead.left else: pHead = tempList.pop() print(pHead.value + " ") pHead = pHead.right def posOrderRecur(pHead): """后序遍历(递归版本)""" if pHead is None: return pHead inOrderRecur(pHead.left) inOrderRecur(pHead.right) print(pHead.value + " ") def posOrderUnRecur(pHead): """后序遍历(非递归版本)""" if pHead is None: return pHead tempList1, tempList2 = [], [] tempList1.append(pHead) while tempList1 != []: pHead = tempList1.pop() tempList2.append(pHead) if pHead.left is not None: tempList1.append(pHead.left) if pHead.right is not None: tempList1.append(pHead.right) while tempList2 != []: print(tempList2.pop() + " ") # 如果一个节点有右子树,则这个节点的后继节点就是这个节点右子树的最左的节点 # 如果一个节点没有右子树,则寻找这个节点作为哪个节点左子树的最后一个节点(中序遍历:左、中、右) # 通过这个节点向上寻找,直到满足这个节点作为该节点的左子树的最后一个节点,也就是表明这个树的左子树已经遍历完,该打印父节点了。 class withParentNode(object): def __init__(self, value): self.value = value self.right, self.left, self.parent = None, None, None def getSuccessorNode(node): """通过节点中增加的父节点指针,找后继节点""" if node is None: return None if node.right is not None: return getLeftMost(node.right) else: # 这个节点没有右子树 parentNode = node.parent while parentNode is not None and parentNode.left != node: node = parentNode parentNode = node.parent return parentNode def getLeftMost(node): """找右子树中最左的节点""" if node is None: return None while node.left is not None: node = node.left return node def SerialByLevel(pHead): """按层序列化""" if pHead is None: return '#!' res = str(pHead.value) + '!' queueList = [] queueList.append(pHead) while queueList != []: pHead = queueList.pop() if pHead.left is not None: res += str(pHead.left.value) + '!' queueList.append(pHead.left) else: res += '#' if pHead.right is not None: res += str(pHead.right.value) + '!' queueList.append(pHead.right) else: res += '#' return res def reconByLevelString(levelStr): """按层遍历反序列化""" levelList = [] for i in levelStr: if i != '!': levelList.append(i) index = 0 pHead = generateNodeByString(levelList[index]) index += 1 queueList = [] if pHead is not None: queueList.append(pHead) while queueList != []: curNode = queueList.pop() curNode.left = generateNodeByString(levelList[index]) index += 1 curNode.right = generateNodeByString(levelList[index]) index += 1 if curNode.left is not None: queueList.append(curNode.left) if curNode.right is not None: queueList.append(curNode.right) return curNode def generateNodeByString(str1): if str1 == '#': return None return treeNode(int(str1)) def isBalanceTree(pHead): """判断一棵树是否是平衡二叉树(任一节点的左子树和右子树高度差小于2) 使用递归,函数返回两个值,一个是这个树的高度,一个是这个树是否是平衡二叉树""" return isBalanceTreeProcess(pHead)[0] def isBalanceTreeProcess(pHead): if pHead is None: return True, 0 leftDataIsB, leftDataHigh = isBalanceTreeProcess(pHead.left) if not leftDataIsB: # 左子树不平衡,则没有继续的必要,直接返回False return False, 0 rightDataIsB, rightDataHigh = isBalanceTreeProcess(pHead.right) if not rightDataIsB: # 右子树不平衡,则没有继续的必要,直接返回False return False, 0 # 运行到此时仍没有返回,证明该节点左子树和右子树都是平衡二叉树 if abs(leftDataHigh - rightDataHigh) > 1: return False, 0 return True, max(leftDataHigh, rightDataHigh) + 1 def isBST(pHead): """判断一棵树是否是搜索二叉树""" if pHead is None: return True res = True pre = treeNode(None) cur1 = pHead while cur1 is not None: cur2 = cur1.left if cur2 is not None: while cur2.right is not None and cur2.right != cur1: cur2 = cur2.right if cur2.right is None: cur2.right = cur1 cur1 = cur1.left continue else: cur2.right = None if pre is not None and pre.value > cur1.value: res = False pre = cur1 cur1 = cur1.right return res def isCBT(pHead): """判断一棵树是否是完全二叉树""" if pHead is None: return True queueList = [] leafNode = False queueList.append(pHead) while queueList != []: pHead = queueList.pop() leftNode = pHead.left rightNode = pHead.right if (leafNode and (leftNode is not None or rightNode is not None)) or (leftNode is None and rightNode is not None): # 两种情况下返回False # 1. 一个节点有右子树,没有左子树,则不是完全二叉树 # 2. 当有一个节点只有左子树,没有右子树时,leftNode=True,同一层次往后节点则只能是叶节点,否则不是完全二叉树 return False if leftNode is not None: queueList.insert(0, leftNode) if rightNode is not None: queueList.insert(0, rightNode) else: # 当一个节点只有左子树没有右子树时,标记位变为True,同一层次后面的节点和下面所有的节点必须都是叶节点 leftNode = True return True def getTreeNodeNum(pHead): """求一颗完全二叉树的节点数,时间复杂度小于O(N)""" if pHead is None: return 0 return getTreeNodeNumProcess(pHead, 1, mostLeftLevel(pHead, 1)) def getTreeNodeNumProcess(pHead, level, high): # level:pHead节点在第几层 # high:这棵树的深度(固定值) # 返回的是以pHead为根节点的子树一共有多少个节点 if level == high: # pHead节点到了最后一层,即是叶节点。则以pHead为头的子树就1个节点 return 1 if mostLeftLevel(pHead.right, level + 1) == high: # 该节点右子树的最左节点如果到了最后一层,则表明该节点的左子树是满二叉树,则左子树节点数可以通过公式算出,右子树是完全二叉树 return (1 << (high - level)) + getTreeNodeNumProcess(pHead.right, level + 1, high) else: # 如果该节点右子树的最左节点没到最后一层,则表明该节点的右子树是少一层的满二叉树,右子树节点数可以通过公式算出,左子树是完全二叉树 return (1 << (high - level - 1)) + getTreeNodeNumProcess(pHead.left, level + 1, high) def mostLeftLevel(pHead, level): while pHead is not None: level += 1 pHead = pHead.left return level - 1 def countIslands(matrix): """矩阵中有多少个岛""" if matrix is None or matrix[0] is None: return 0 res = 0 for i in range(len(matrix)): for j in range(len(matrix[0])): if matrix[i][j] == 1: res += 1 infect(matrix, i, j, len(matrix), len(matrix[0])) return res def infect(matrix, i, j, N, M): if i < 0 or i >= N or j < 0 or j > M or matrix[i][j] != 1: return matrix[i][j] = 2 infect(matrix, i + 1, j, N, M) infect(matrix, i - 1, j, N, M) infect(matrix, i, j + 1, N, M) infect(matrix, i, j - 1, N, M) class TrieTree(object): """前缀树节点""" def __init__(self): self.path = 0 # 有多少个字符串经过这个节点 self.end = 0 # 有多少个字符串以这个节点结尾 self.nexts = [None] * 26 # 这个结点往下一共有26(限定)个方向 class Trie(object): """前缀树""" def __init__(self): self.rootNode = TrieTree() # 头结点 def insert(self, strWord): if strWord is None: return strList = list(strWord) node = self.rootNode for i in range(len(strList)): index = ord(strList[i]) - ord('a') if node.nexts[index] is None: node.nexts[index] = TrieTree() node = node.nexts[index] node.path += 1 node.end += 1 def search(self, strWord): # 查找strWord出现过几次 if strWord is None: return 0 strList = list(strWord) node = self.rootNode for i in range(len(strList)): index = ord(strList[i]) - ord('a') if node.nexts[index] is None: return 0 node = node.nexts[index] return node.end def delete(self, strWord): if self.search(strWord) != 0: strList = list(strWord) node = self.rootNode for i in range(len(strList)): index = ord(strList[i]) - ord('a') node.nexts[index].path -= 1 if node.nexts[index].path == 0: node.nexts[index] = None return node = node.nexts[index] node.end -= 1 def prefixNumber(self, pre): """查某个字符串的前缀数量是多少""" if pre is None: return 0 preList = list(pre) node = self.rootNode for i in range(len(preList)): index = ord(preList[i]) - ord('a') if node.nexts[index] is None: return 0 node = node.nexts[index] return node.path def strCompare(str1, str2): if str1 + str2 < str2 + str1: return -1 elif str1 + str2 > str2 + str1: return 1 else: return 0 def lowestString(strsList): if strsList is None or len(strsList) == 0: return "" strsList = sorted(strsList, key=functools.cmp_to_key(strCompare)) res = "" for i in range(len(strsList)): res += strsList[i] return res # 原题求解,是将数组调整为小根堆,将最小的两个数相加放回到原数组中,直至数组中仅剩一个数为止 def lessMoney(alist): pQ = [] for i in range(len(alist)): pQ.append(alist[i]) pQ = sorted(pQ, reverse=True) sum, cur = 0, 0 while len(pQ) > 1: cur = pQ.pop() + pQ.pop() sum += cur pQ.append(alist[i]) pQ = sorted(pQ, reverse=True) return sum class moreProfits(object): def __init__(self, profit, cost): self.profit = profit self.cost = cost def minCostComparator(node1, node2): # 花费(小根堆)比较器 return node1.cost - node2.cost def maxProfitComparator(node1, node2): # 利润(大根堆)比较器 return node2.profit - node1.profit # 首先将项目按照成本大小压入小根堆(成本)中,然后依次将目前能做的项目(成本小于启动资金)压入利润大根堆(利润)中,每做一个项目,启动 # 资金相应变化,相应从成本堆中进行弹出,直到做完k个项目,或者成本堆中无项目可谈,而利润堆中无项目可做为止 def findMaximizedCapital(k, w, profitsList, capitalList): # 通过两个根堆(一个大根堆(利润),一个小根堆(花费))实现安排项目的使用顺序 # 仅能做k个项目,初始资金为w nodes = [None] * len(profitsList) for i in range(len(profitsList)): nodes[i] = moreProfits(profitsList[i], capitalList[i]) minCostList, maxProfitList = [], [] for i in range(len(nodes)): minCostList.append(nodes[i]) minCostList = sorted(minCostList, key=functools.cmp_to_key(minCostComparator)) for i in range(k): while minCostList != [] and minCostList[-1].cost <= w: maxProfitList.append(minCostList.pop()) maxProfitList = sorted(maxProfitList, key=functools.cmp_to_key(maxProfitComparator)) if maxProfitList == []: return w w += maxProfitList.pop().profit return w class meetingNode(object): def __init__(self, start, end): self.start = start self.end = end def meetingCompare(o1, o2): return o1.end - o2.end def bestArrangement(programs, startTime): programs = sorted(programs, key=functools.cmp_to_key(meetingCompare)) result = 0 for i in range(len(programs)): if startTime <= programs[i].start: result += 1 startTime = programs[i].end return result
数据结构与算法--python学习笔记二(听了左神的课,自己整理的,左神还是强啊)
最新推荐文章于 2024-03-14 21:24:04 发布