数据结构与算法--python学习笔记二(听了左神的课,自己整理的,左神还是强啊)

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值