import random
import numpy as np
import copy
import functools
# 综合排序的方式选择从样本容量和稳定性角度考虑:当样本量较小时,选择插入排序,即使是O(N**2),但常数项极低。
# 当排序的是基础类型,使用快排,因为不计较稳定性。当排序的是自定义类时,使用归并排序,需要考虑稳定性。
# processArray(size, start, end):产生[start, end]的size大小的随机整数数组
# bubbleSort(alist):冒泡排序,时间复杂度O(N**2)
# selectionSort(alist):选择排序,时间复杂度O(N**2),额外空间复杂度O(1)
# insertionSort(alist):插入排序,时间复杂度O(N**2)
# mergeSort(alist):归并排序,时间复杂度O(NlogN),额外空间复杂度O(n)
# NetherLandsFlag(alist, num):荷兰国旗问题(将数组调整为,左面比这个数小,中间和这个数相等,右面比这个数大),时间复杂度O(N),额外空间复杂度O(1)
# quickSort(alist):快速排序(最差时间复杂度O(N**2)),随机快速排序(期望时间复杂度O(N*logN),额外空间复杂度O(logN)(划分点的存储))
# heapSort(alist):堆排序
# maxGap(alist):通过桶排序实现了两个相邻数的最大差值
# rotateMatrix(matrix): 旋转正方形矩阵90度
# isPalindrome(pHead): 判断链表是否是回文结构,时间复杂度O(N),额外空间复杂度O(1)
# listPartition(pHead, num): 将链表调整为左面的数比num小,中间的数和num相等,右面的数大于num,时间复杂度为O(n),额外空间复杂度O(1)
# copyListWithRand(pHead): 复制复杂链表(节点指针包括随机指针),(使用字典,键为原来的节点,值为复制后的节点)
# copyListWithRand2(pHead): 复制复杂链表(在原有节点的基础上1->1`->2->2`->3->3`...,然后再将复制后的节点提出)
# getCommonNode(): 求两个链表相交,求第一个公共节点(需要考虑单链表是否有环等)
# preOrderRecur(pHead): 先序遍历(递归版本)
# preOrderUnRecur(pHead): 先序遍历(非递归版本)
# serialByPre(pHead): 先序遍历序列化
# inOrderRecur(pHead): 中序遍历(递归版本)
# inOrderUnRecur(pHead): 中序遍历(非递归版本)
# posOrderRecur(pHead): 后序遍历(递归版本)
# posOrderUnRecur(pHead): 后序遍历(非递归版本)
# getSuccessorNode(node): 通过对节点中增加父节点指针,寻找节点的后继节点
# SerialByLevel(pHead): 按层遍历序列化
# reconByLevelString(levelStr):按层遍历反序列化
# isBalanceTree(pHead): 判断一棵树是否是平衡二叉树
# isBST(pHead): 判断一棵树是否是搜索二叉树
# isCBT(pHead): 判断一棵树是否是完全二叉树
# getTreeNodeNum(pHead): 求一颗完全二叉树的节点数,时间复杂度O((logN)**2)
# countIslands(matrix): 矩阵中有多少个岛
# Trie(): 前缀树
# 贪心策略: lowestString(strsList): 给定一个字符串类型的数组strsList,找到一种拼接方式,使得把所有字符串拼起来之后形成的字符串具有最低的字典序
# lessMoney(alist): 哈夫曼编码问题
# findMaximizedCapital(k, w, profitsList, capitalList):项目利润列表profitsList,成本列表capitalList。k个项目,w为起始资金
# bestArrangement(programs, startTime): 会议室安排项目宣讲,安排尽可能多的项目
# 递归: hanoiProcess(n, fromStr, toStr, helpStr): 汉诺塔(递归)
# printAllSub(str1, index, resultStr): 打印字符串所有的子序列
# minPath1(matrix): 求矩阵中从左上角到右下角,所经节点的和最小
# isSum1(arr1, aim): 数组中数字累加和能否正好是aim
# coins(alist, aim): 再给定一个整数aim代表要找的钱数,求换钱有多少种方法
# 由暴力递归改成动态规划: coins2(alist, aim)、coins3(alist, aim)、coins4(alist, aim)
# winCard1(alist): 排成一条线的纸牌博弈问题
# 由暴力递归改成动态规划: winCard2(alist)
# ways(N, curPosition, restSteps, K):机器人处于位置M,经过P步后,走到位置K,一共有多少种方法
# 由暴力递归改成动态规划: ways2(N, curPosition, restSteps, K)
# isMatch(str1, str2): 带有‘.’和‘*’的字符串匹配问题
# 由暴力递归改成动态规划: isMatchDPMatrix(str1, str2)
# getIndexOf(str1, str2): 使用KMP算法,检验str2是否是str1的子串
# KMP应用:判断一棵树是否是另一棵树的子树(将两棵树进行序列化,如果这棵树序列化后的字符串是另一个字符串的子串,则满足)
# maxLcpsLength(str1): Manacher算法,求解最长回文子串的长度。
# shortestEnd(str1): 利用Manacher算法求解在字符串末尾添加最短字符串使整体构成回文串
# getMinKNumsByBFPRT(alist, k): 应用BFPRT算法求解数组中第k个小的数,并将前k个数返回
# getMaxWindow(alist, w): 应用双端队列,求解固定大小为w的窗口内的最大值
# getNum(arr, num): 应用双端队列求解,满足子数组中最大值和最小值的差值小于num的子数组的数量
# drabStrack(alist): 利用单调栈求解数组中左面离它最近的比它小的数的索引和右面最近的比它小的数的索引
# maxRecFromBottom(heightList): 应用单调栈求分布直方图中的最大面积
# maxRecSize(matrix): 应用单调栈求,全是1或0的所有矩形区域中,最大的矩形区域为1的数量
# morris(pHead): Morris遍历,利用叶节点的左右指针指向空的这个空间实现了额外空间复杂度为O(1)的遍历
# morrisPre(pHead):Morris先序遍历
# morrisIn(pHead):Morris中序遍历
# morrisPos(pHead): Morris后序遍历
# maxLength(alist, aim): 给定数组,返回满足累加和为aim的子数组的最大长度
# mostEOR(alist): 将给定数组进行分组,保证每组的异或和为0,返回最多的子数组数
# MaxDistanceInTree(pHead): 节点A走到节点B的距离为:A走到B最短路径上的节点个数。求一颗二叉树上的最远距离
# getMaxHuo(pHead): 活跃度的计算
# MyCache(object): 自定义一种缓存结构(LRU),实现某些特定功能
# LFUCache(object): 应用二维双向链表,在LRU的基础上实现了set()和get()的时间复杂度均是O(1)
# getValueFromStr(str1): 给定字符串,字符串表示一个公式,可能有整数、加减乘除符号和左右括号,返回公式计算结果
# SkipList(object): 跳表结构,跳跃表是为了解决平衡树插入或者删除操作过于复杂而进行设计的。
# 采用了随机的思想简化了维持平衡的过程,而保持查找的时间复杂度依旧是O(logN)
# maxLengthAwesom(alist, aim): 给定数组和一个整数aim,求累加和小于等于aim,的最长子数组。时间复杂度O(N)
# josephusKill2(pHead, m): 环形单链表的约瑟夫问题,链表长度N,时间复杂度O(N)
# isMatch(str1, str2): 带有‘.’和‘*’的字符串匹配问题
# getMinSteps(eggNum, floorNum): 扔鸡蛋问题(动态规划)
def processArray(size, start, end):
alist1 = [None] * size
alist2 = [None] * random.randint(0, size)
for i in range(len(alist2)):
randomNum = random.randint(start, end)
while randomNum in alist2:
randomNum = random.randint(start, end)
alist2[i] = randomNum
for i in range(size):
randomNum = random.randint(start, end)
while randomNum in alist1:
randomNum = random.randint(start, end)
alist1[i] = randomNum
return alist1, alist2
def insertionSort(alist):
"""插入排序"""
if len(alist) < 2:
return alist
for i in range(1, len(alist)):
j = i
while alist[j] < alist[j - 1] and j > 0:
alist[j], alist[j - 1] = alist[j - 1], alist[j]
j = j - 1
return alist
def selectionSort(alist):
"""选择排序"""
if len(alist) < 2:
return alist
for i in range(len(alist) - 1):
minIndex = i
for j in range(i + 1, len(alist)):
minIndex = j if alist[j] < alist[minIndex] else minIndex
alist[i], alist[minIndex] = alist[minIndex], alist[i]
return alist
def bubbleSort(alist):
"""冒泡排序"""
if len(alist) < 2:
return alist
for end in range(len(alist) - 1, 0, -1):
for i in range(end):
if alist[i] > alist[i + 1]:
alist[i], alist[i + 1] = alist[i + 1], alist[i]
return alist
def mergeSort(alist):
"""归并排序"""
if alist == [] or len(alist) < 2:
return alist
mid = len(alist) // 2
leftList = mergeSort(alist[:mid])
rightList = mergeSort(alist[mid:])
resultList = []
leftIndex, rightIndex = 0, 0
while leftIndex < len(leftList) and rightIndex < len(rightList):
if leftList[leftIndex] < rightList[rightIndex]:
resultList.append(leftList[leftIndex])
leftIndex += 1
else:
resultList.append(rightList[rightIndex])
rightIndex += 1
resultList += leftList[leftIndex:]
resultList += rightList[rightIndex:]
return resultList
def quickSort(alist):
"""快速排序"""
if alist == [] or len(alist) < 2:
return alist
quickSortProcess(alist, 0, len(alist) - 1)
return alist
def quickSortProcess(arr, start, end):
if start < end:
# 随机快速排序是随机选取一个数作为标准值进行排序
# 经典快速排序是直接将最后一个值作为标准值进行比较排序
temp = random.randint(start, end)
arr[temp], arr[end] = arr[end], arr[temp]
lessRight, moreRight = partition(arr, start, end)
quickSortProcess(arr, start, lessRight - 1)
quickSortProcess(arr, moreRight + 1, end)
def partition(arr, start, end):
cur, less, more = start, start - 1, end
while cur < more:
if arr[cur] < arr[end]:
arr[cur], arr[less + 1] = arr[less + 1], arr[cur]
cur += 1
less += 1
elif arr[cur] > arr[end]:
arr[cur], arr[more - 1] = arr[more - 1], arr[cur]
more -= 1
else:
cur += 1
arr[more], arr[end] = arr[end], arr[more]
return less + 1, more
def heapSort(alist):
"""堆排序"""
if len(alist) < 2:
return alist
for i in range(len(alist)):
heapInsert(alist, i)
heapSize = len(alist)
alist[0], alist[heapSize - 1] = alist[heapSize - 1], alist[0]
heapSize -= 1
while heapSize > 0:
heapify(alist, 0, heapSize)
alist[0], alist[heapSize - 1] = alist[heapSize - 1], alist[0]
heapSize -= 1
return alist
def heapInsert(alist, index):
"""建立大根堆结构"""
while alist[index] > alist[(index - 1) // 2] and ((index - 1) // 2 >= 0):
alist[index], alist[(index - 1) // 2] = alist[(index - 1) // 2], alist[index]
index = (index - 1) // 2
def heapify(alist, index, heapSize):
left = index * 2 + 1
while left < heapSize:
largest = left + 1 if left + 1 < heapSize and alist[left + 1] > alist[left] else left
largest = largest if alist[largest] > alist[index] else index
if largest == index:
break
alist[largest], alist[index] = alist[index], alist[largest]
index = largest
left = index * 2 + 1
def maxGap(alist):
"""桶排序"""
if alist is None or len(alist) < 2:
return 0
n = len(alist)
minNum = min(alist)
maxNum = max(alist)
if minNum == maxNum:
return 0
bucketBool = [False] * (n + 1)
bucketMax = [0] * (n + 1)
bucketMin = [0] * (n + 1)
for i in range(n):
bid = bucket(alist[i], n, minNum, maxNum)
bucketMin[bid] = min(bucketMin[bid], alist[i]) if bucketBool[bid] else alist[i]
bucketMax[bid] = max(bucketMax[bid], alist[i]) if bucketBool[bid] else alist[i]
bucketBool[bid] = True
res = 0
lastMax = bucketMax[0]
for i in range(n + 1):
if bucketBool[i]:
res = max(res, bucketMin[i] - lastMax)
lastMax = bucketMax[i]
return res
def bucket(num, n, minNum, maxNum):
return int((num - minNum) * n / (maxNum - minNum))
def NetherLandsFlag(alist, num):
start, cur, end = -1, 0, len(alist)
while cur < end:
if alist[cur] < num:
alist[start + 1], alist[cur] = alist[cur], alist[start + 1]
start += 1
cur += 1
elif alist[cur] > num:
alist[cur], alist[end - 1] = alist[end - 1], alist[cur]
end -= 1
else:
cur += 1
return alist
def rightMethod(alist):
"""绝对正确的方法"""
return alist
def copyArray(alist):
"""产生一个相同的数组"""
# if alist == []:
# return []
# res = [None] * len(alist)
# for i in range(len(alist)):
# res[i] = alist[i]
res = copy.deepcopy(alist)
return res
def testMain():
testTimes = 50000
size = 10
start, end = 0, 100
testFlag = True
for i in range(testTimes):
arr1, arr2 = processArray(size, start, end)
res1 = copyArray(arr2)
res2 = copyArray(arr2)
resultList1 = heapSort(res1)
resultList2 = mergeSort(res2)
if resultList1 != resultList2:
testFlag = False
if testFlag:
print("方法测试正确!")
else:
print('arr1: ', arr2)
print('resultList1: ', resultList1)
print('resultList2: ', resultList2)
def rotateMatrix(matrix):
"""旋转矩阵90度"""
tR, tC, dR, dC = 0, 0, len(matrix) - 1, len(matrix[0]) - 1
while tR < dR:
rotateEdge(matrix, tR, tC, dR, dC)
tR += 1
tC += 1
dR -= 1
dC -= 1
return matrix
def rotateEdge(matrix, tR, tC, dR, dC):
for i in range(dR - tR):
matrix[tR][tC + i], matrix[tR + i][dC], matrix[dR][dC - i], matrix[dR - i][tC] = \
matrix[dR - i][tC], matrix[tR][tC + i], matrix[tR + i][dC], matrix[dR][dC - i]
class listNode(object):
def __init__(self, value):
self.value = value
self.next = None
class treeNode(object):
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def isPalindrome(pHead):
"""判断链表是否是回文结构"""
if pHead is None or pHead.next is None:
return True
quickPoint = pHead
slowPoint = pHead
while quickPoint.next is not None and quickPoint.next.next is not None:
quickPoint = quickPoint.next.next
slowPoint = slowPoint.next
# 此时slowPoint指向的是中点位置
tempPoint = slowPoint.next
slowPoint.next = None
while tempPoint is not None:
tempPoint2 = tempPoint.next
tempPoint.next = slowPoint
slowPoint = tempPoint
tempPoint = tempPoint2
point1 = pHead
point2 = slowPoint
res = True
while point1 is not None and point2 is not None:
if point1.value != point2.value:
res = False
break
point1 = point1.next
point2 = point2.next
# 检查完后需要将原来逆序的部分进行还原
tempPoint = slowPoint.next
slowPoint.next = None
while tempPoint is not None:
tempPoint2 = tempPoint.next
tempPoint.next = slowPoint
slowPoint = tempPoint
tempPoint = tempPoint2
return res
def listPartition(pHead, num):
"""调整链表顺序,满足左面的部分比num小,中间的部分和num相等,右面的部分比num大"""
sH, sT = listNode(None), listNode(None) # small head, small tail
eH, eT = listNode(None), listNode(None) # equal head, equal tail
bH, bT = listNode(None), listNode(None) # big head, big tail
nextNode = listNode(None)
while pHead is not None:
nextNode = pHead.next
pHead.next = None
if pHead.value < num:
if sH is None:
sH, sT = pHead, pHead
else:
sT.next = pHead
sT = pHead
elif pHead.value == num:
if eH is None:
eH, eT = pHead, pHead
else:
eT.next = pHead
eT = pHead
else:
if bH is None:
bH, bT = pHead, pHead
else:
bT.next = pHead
bT = pHead
pHead = nextNode
if sT is not None:
sT.next = eH
eT = sT if eT is None else eT
if eT is not None:
eT.next = bH
return sH if sH is not None else eH if eH is not None else bH
def copyListWithRand(pHead):
"""复制复杂链表(带有随机指针)"""
nodeDict = {}
cur = pHead
while cur:
nodeDict.update({cur: listNode(cur.value)})
cur = cur.next
cur = pHead
while cur:
nodeDict.get(cur).next = nodeDict.get(cur.next)
nodeDict.get(cur).rand = nodeDict.get(cur.rand)
cur = cur.next
return nodeDict.get(pHead)
def copyListWithRand2(head):
"""复制复杂链表(带有随机指针)"""
if not head:
return None
cur = head
while cur:
nextNode = cur.next
cur.next = listNode(cur.val)
cur.next.next = nextNode
cur = nextNode
cur = head
while cur:
nextNode = cur.next.next
copyNode = cur.next
copyNode.random = cur.random.next if cur.random is not None else None
cur = nextNode
res = head.next
cur = head
while cur:
nextNode = cur.next.next
copyNode = cur.next
cur.next = nextNode
copyNode.next = nextNode.next if nextNode is not None else None
cur = nextNode
return res
数据结构与算法--python学习笔记一(听了左神的课,自己整理的,左神还是强啊)(前面提到的方法有的在后面的博客里)
最新推荐文章于 2022-07-06 11:45:08 发布