算法学习列表
由于某些机缘巧合的原因,最近重新开始学习算法,学习那二十年前的我最喜欢,而却又抛弃了的东西。虽然现在已不能全心全意埋头苦学,也没有了当年灵光的头脑和意气风发的精神面貌,但却可细水长流,慢慢品尝。岁月就像那深藏的红酒,越品越醇。
Reference:
https://www.runoob.com/w3cnote/the-friendship-algorithm-the-big-bang-theory.html
一、排序
快速排序(Quick Sort):
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
def quick_sort(arr): if len(arr)<=1: return arr else: pivot=arr[0] less=[i for i in arr[1:] if i<=pivot] greater=[i for i in arr[1:] if i>pivot] return quick_sort(less)+[pivot]+quick_sort(greater)
归并排序(Merge Sort):
也叫合并排序,是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
算法步骤:
1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4. 重复步骤3直到某一指针达到序列尾
5. 将另一序列剩下的所有元素直接复制到合并序列尾
def merge_sort(arr): if len(arr)<=1: return arr else: mid=len(arr)//2 left=merge_sort(arr[:mid]) right=merge_sort(arr[mid:]) return merge(left,right) def merge(a,b): x=len(a) y=len(b) low=0 high=0 r=[] while low<x and high<y: if a[low]<b[high]: r.append(a[low]) low+=1 else: r.append(b[high]) high+=1 if low==x: r=r+b[high:] return r elif high==y: r=r+a[low:] return r data=[4,6,9,1,2,7,3,0,5,8] print("Org: ", data) print("Sort: ",merge_sort(data))
二、二叉树
遍历:
def preorder_traverse(self, root: TreeNode) -> List[int]: # 前序遍历(先根遍历) def preorder(node: TreeNode): if not node: return r.append(node.val) preorder(node.left) preorder(node.right) r = [] preorder(root) return r def inorder_traverse(self, root: Optional[TreeNode]) -> List[int]: # 中序遍历(中根遍历) def inorder(node: TreeNode): if not node: return if node.left: t1=inorder(node.left) if t1: r.append(t1) r.append(node.val) if node.right: t2=inorder(node.right) if t2: r.append(t2) r = [] inorder(root) return r def postorder_traverse(self, root: Optional[TreeNode]) -> List[int]: # 后序遍历(后根遍历) def postorder(node: TreeNode): if not node: return postorder(node.left) postorder(node.right) r.append(node.val) r = [] postorder(root) return r def levelOrder_traverse(self, root: Optional[TreeNode]) -> List[List[int]]: # 层序遍历 s=[] s.append(root) r=[] while len(s)>0: next=[] tmp_r=[] for i in s: if not i: continue if i: tmp_r.append(i.val) if i.left: next.append(i.left) if i.right: next.append(i.right) if len(tmp_r)>0: r.append(tmp_r) s=next return r
三、查找搜索
二分查找(Binary Search):
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
def binarySearch(arr,n):
print("========== Search %s in %s =========="%(n,arr))
if arr==None or len(arr)==0: return None
arrLen=len(arr)
min=0
max=arrLen-1
mid=int(arrLen/2)
while mid>=0 and mid<=arrLen-1:
pivot=arr[mid]
if n==pivot:
return mid
elif max==0 or min==arrLen-1:
return None
elif n<pivot:
max=mid
mid=int((min+max)/2)
elif n>pivot:
min=mid
mid=int((min+max+1)/2)
return None
广度优先搜索(Breadth-First Search,BFS):
【From】https://www.cnblogs.com/cs-whut/p/11147348.html
在广度优先搜索算法中,解答树上结点的扩展是按它们在树中的层次进行的。首先生成第一层结点,同时检查目标结点是否在所生成的结点中,如果不在,则将所有的第一层结点逐一扩展,得到第二层结点,并检查第二层结点是否包含目标结点,……,对层次为 n+1 的任一结点进行扩展之前,必须先考虑完层次为 n 的结点的每种可能的状态。因此,对于同一层结点来说,求解问题的价值是相同的,可以按任意顺序来扩展它们。通常采用的原则是先生成的结点先扩展。
为了便于进行搜索,要设置一个表存储所有的结点。由于在广度优先搜索算法中,要满足先生成的结点先扩展的原则,所以存储结点的表一般采用队列这种数据结构。
广度优先搜索算法的搜索步骤一般是:
(1)从队列头取出一个结点,检查它按照扩展规则是否能够扩展,如果能则产生一个新结点。
(2)检查新生成的结点,看它是否已在队列中存在,如果新结点已经在队列中出现过,就放弃这个结点,然后回到第(1)步。否则,如果新结点未曾在队列中出现过,则将它加入到队列尾。
(3)检查新结点是否目标结点。如果新结点是目标结点,则搜索成功,程序结束;若新结点不是目标结点,则回到第(1)步,再从队列头取出结点进行扩展。
最终可能产生两种结果:找到目标结点,或扩展完所有结点而没有找到目标结点。
如果目标结点存在于解答树的有限层上,广度优先搜索算法一定能保证找到一条通向它的最佳路径,因此广度优先搜索算法特别适用于只需求出最优解的问题。当问题需要给出解的路径,则要保存每个结点的来源,也就是它是从哪一个节点扩展来的。
void BFS() { 队列初始化; 初始结点入队; while(队列非空) { 队头元素出队,赋给current; while(current 还可以扩展) { 由结点current扩展出新结点new; if (new 重复于已有的结点状态) continue; new结点入队; if (new结点是目标状态) { 置flag = true; break; } } } }
深度优先搜索(Depth-First Search,DFS):
【From】https://www.cnblogs.com/DWVictor/p/10048554.html
深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法。它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念。
/** * DFS核心伪代码 * 前置条件是visit数组全部设置成false * @param n 当前开始搜索的节点 * @param d 当前到达的深度 * @return 是否有解 */ bool DFS(Node n, int d){ if (isEnd(n, d)){//一旦搜索深度到达一个结束状态,就返回true return true; } for (Node nextNode in n){//遍历n相邻的节点nextNode if (!visit[nextNode]){// visit[nextNode] = true;//在下一步搜索中,nextNode不能再次出现 if (DFS(nextNode, d+1)){//如果搜索出有解 //做些其他事情,例如记录结果深度等 return true; } //重新设置成false,因为它有可能出现在下一次搜索的别的路径中 visit[nextNode] = false; } } return false;//本次搜索无解 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2017-12-07 有用的 Angular CLI 命令参数