算法题
希望2017
博客内容涉及GO、Java、MySQL、软件开发、数据结构与算法等
展开
-
动态规划|剑指 Offer II 093. 最长斐波那契数列
如果数组 arr 中存在三个下标 i、j、k 满足 arr[i]>arr[j]>arr[k] 且 arr[k]+arr[j]=arr[i],则 arr[k]、arr[j] 和 arr[i] 三个元素组成一个斐波那契式子序列。由于数组 arr 严格递增,因此 arr[i]>arr[j]>arr[k] 等价于 i>j>k。这道题说明了打表的过程是依赖状态转移方程的。把这道题的官解再次细化一下,可视化一下,这样理解起来更容易一些。原创 2024-07-07 22:20:59 · 252 阅读 · 0 评论 -
acwing 291.蒙德里安的梦想
根据上面的分析可以得到,一个合法的状态j,可以由很多个其他的合法状态转移而来,现在把每个合法的状态j的前一个合法状态集合求出来。状态计算:f[i,j] = ∑f[i-1,k],f[i-1,k]指的是可以到达f[i,j]的合法f[i-1]的状态。动态规划思路: 状态表示:f[i,j]表示已经将前i-1列摆好,且从第i-1列,伸出到第i列的状态是j的所有方案。结果状态:f[m,0],即前m列已经被铺满,m+1列一个格子都没有被占,即m列中没有伸到m+1列的小方块的状态。解法: 核心:先放横着的,再放竖着的。原创 2024-07-07 22:07:24 · 362 阅读 · 0 评论 -
回溯法、全排列、子集等
子集问题描述:使用集合S{1,2,3}中的元素构建新的集合,每个元素只能使用一次,元素一样的集合只算一个,eg.{1,2},{2},{1,2,3}…给定一个集合S{a,b,c},把其中元素按照不同顺序进行排序,eg.“abc”,“bca”,“cab”…其实这个子集问题的本质就是高中学到的组合问题,n个元素有几种组合方式,答案数量为C(n,m);基本思想是树(解答树)的遍历,如果是使用dfs(暴搜),那么可以使用递归来写。其实上面两个点,也是对应着高中数学里面的“排列”与“组合”先空着,有空再学再写。原创 2024-05-10 14:12:47 · 251 阅读 · 1 评论 -
二分查找入门、二分查找模板
二分查找的具体实现是一个难点,挺复杂的,可以背住一个模板,然后以后再慢慢学习。下面是y总的二分模板(比较难懂,之后再学)原创 2024-05-10 14:10:11 · 175 阅读 · 0 评论 -
Dijkstra求最短路径
进行第二次打表,本次打表不是从v0出发,而是从点集S出发,求得S到各点的最短距离,将距离最短的点更新加入S,然后不断重复,直到目标点被添加入点集S时,结束,此时找到最短路径。详见青大王卓课程:https://www.bilibili.com/video/BV1nJ411V7bd?从源点v0出发,求得到其余所有点的距离,打成第一张表,然后以此表为依据,寻找距离v0最近的点,将该点加入到v0的点集S中;利用了广度优先搜索,使用贪心思想,不断扫描各点距离源点的距离,然后将最短距离保存,直到所有点扫描完毕。原创 2024-05-07 22:40:55 · 302 阅读 · 0 评论 -
浮点数加法
浮点数有时候计算结果会出现长尾小数,例如0.1+0.11=0.21000000000002,这种结果很麻烦。用包装类就可以轻松的解决这个问题,不过想着很久没写加法了,高精度加法也不咋写了,自己造下轮子熟悉一下算法,于是就写了个浮点数的加法,原理就是小学加法。原创 2024-03-18 22:53:22 · 257 阅读 · 0 评论 -
基础图算法|prim算法的Java实现
prim算法的Java实现原创 2023-02-11 19:30:26 · 222 阅读 · 0 评论 -
算法基础|prim算法的实现
prim算法的实现,比较代码风格偏工程,看着复杂,其实还是很简单的。。原创 2023-02-07 17:01:26 · 82 阅读 · 0 评论 -
图|AcWing 846. 树的重心
在树中:有n个结点,则有n-1条边,由于用图的方式表示树,也要在意每条边的方向,由于每条边两个方向,因此一共最多2*(n-1)条边,方便起见开2N条边。这里的e存储的是边,一个e对应着一个有向边。j = e[i],代表着i这个点到j有条边。由于是树,肯定存在i = e[j];算法不难理解,实现比较麻烦,sum与res的使用很巧妙,是一个工具写法,可以背下来。学习静态链表写法对于找工作有什么意义呢?由于是双向的,所以e得开2N,ne也是如此。2023年2月2日17:17:53。原创 2023-02-02 19:05:42 · 108 阅读 · 0 评论 -
动态规划|188. 买卖股票的最佳时机 IV
dp[i][j][1]代表第i天时,第j次买卖时持有股票时的收益;dp[i][j][0]代表第i天时,第j次买卖时持有股票时的收益。原创 2023-01-16 15:08:44 · 156 阅读 · 0 评论 -
动态规划|121. 买卖股票的最佳时机
由于标签中说这道题可以用动态规划去做,那么根据动态规划题目的规律,最后的答案肯定是dp[i]之类的,这个i大概率是天数,也就是维护第i天的最大盈利。上面讲到了,对于i天,只有两种状态——持有股票或者不持有,因此将dp[i]扩展一下,扩展成dp[i]{0,1},dp[i][0]代表第i天不持有股票时的最大收益,dp[i][1]代表第i天持有股票时的最大收益。由于我不是计算机或者数学的天纵奇才或者大罗神仙,没法凭空想出一些绚丽的转移方程,然后一步优化到位,因此我只能通过简单的做法一步一步蚕食这道题目。原创 2023-01-13 16:40:00 · 708 阅读 · 0 评论 -
动态规划|474. 一和零
刚开始的时候,我是把k循环放到最里面去的,跑出来的结果很大,而且一个都不符合,分析了一下发现如果把[k]放到最内层去遍历,会导致重复使用,因此【k】必须是最外层的循环。像极了中学时代的那种看上去花里胡哨,实质上是根据考点设计出题的题目。题目看上去很唬人,但是恰恰是这样说明该题设计的目的很强,指向dp的01背包,就是为了考01背包设计的。其中:k表示候选元素的范围,(i,j)表示0与1的上限个数。既然有了转移方程,那么该如何遍历呢?为什么说是考察01背包,中描述的很清楚,不赘述。原创 2023-01-10 14:49:47 · 311 阅读 · 0 评论 -
动态规划|剑指 Offer II 101. 分割等和子集
找个问题可以放大一点,转化为:nums是否存在子集Q,这个Q的所有元素加起来等于一个tar(tar是一个任意的给定的正整数)。题目给了一个数组nums,要求说是在数组里面找个一个子集,找个子集的和与剩下的元素组成的子集的和相等。在这个问题中,当tar=sum/2时,就是该题目原本的解答了。一些前提条件判定的分析就不写了,比如说sum必须为偶数, halfSum > maxNum啥的。相当于:一个集合N,是否存在一个子集Q,sum{Q} = sum{N-Q}简洁的说法:nums设为集合N,N是否存在子集Q,原创 2023-01-06 17:10:59 · 355 阅读 · 0 评论 -
剑指 Offer II 097. 子序列的数目--Java
代表字符串的子串,这个子串从头开始直到i个字符,eg. str=“1234”,str[:3]意义就是"123"(严格意义的比较,不仅是字符相等,还得是所在位置的一致)。既可以是合法子串的末尾元素,也可也不是,因此这两种情况都要考虑。是b,而这个b可以由s[2]或s[3]或s[4]满足)集合划分:这群相同的子序列中,最末元素是否是。个字符串的动态规划问题,一般就是二维dp,相同的子序列,属性为数量。时,处于【不是s[i]】分别代表一个字符串。的中的合法子串数量和。的中的合法子串数量和。相等,既然如此,那么。原创 2023-01-06 10:45:48 · 272 阅读 · 0 评论 -
动态规划|AcWing 901. 滑雪
因此对于该题目,首先是理解怎么一回事,然后去体会记忆化递归的妙处,然后再去多做相似、相关类型的题目,对递归、计划化搜索熟悉后再回来看这道题,常看常新。使用二维数组记录,从某个点出发时的最长距离,这样当想要得知点(i,j)最长距离时,只要比较点(i,j)上下左右四个点哪个点最大即可。1.只能从高处向低处滑行,这个条件保证了从f(i,j)递归时不会重复走到f(i,j)。对于只学过一点算法的入门者而言,想要通过自己写出题解中的递归难度是非常大的。,想要通过这一道题完全掌握该题要考察的知识点是不可能的。原创 2023-01-03 15:38:25 · 255 阅读 · 0 评论 -
动态规划|285. 没有上司的舞会
原本不想写题解的,因为难度确实不大,但是阳了之后逻辑能力被严重耽误,很那思考多一些的东西,感觉大脑的“内存”不够了,遂借助文章的形式梳理一遍题目,顺便写下来充实博客。:根据题目,观察可知,父结点的状态,可以由子结点转移过来,这样一来,就可以使用dfs的方式遍历整个树,然后进行比较root结点两个状态中那个最大即可。当结点i不取值时,其子节点们就可以取值了,这样一来,i结点的最大值为其所有子节点最大值的和(取值或者不取值~);因为树上每个结点都是可以一个状态的集合,当做状态来去转移,也就可使用动态规划了。原创 2022-12-27 17:46:35 · 326 阅读 · 0 评论 -
动态规划|最短Hamilton路径
2022年12月22日11:23:10“n个点,从0开始,到n结束,求涵盖所有点的最短路径”有n个点,有n!条路径可以选择,不过题目中要求是0开始,n-1点结束,因此一共是(n-2)!条路径,在(n-2)!条路径中选择一条最短的路径即为答案,但是时间复杂度太高了。使用动态规划来减少重复。设w[][]为图的邻接表,用以表示点与点之间的权值;f[j]为终点为j时的所有路线的集合(起点先不关注),而终点为j时,前面点的数量还是没有确定的,需要进行确定才可以进一步减少集合的范围。此时引入一个路径状态。原创 2022-12-22 11:41:45 · 611 阅读 · 1 评论 -
动态规划|石子合并——遍历顺序的思考(Java)
其中f(i,j)依赖的前面数据是图中标出的蓝色与绿色部分,因此使用常见的双循环遍历的时候,就会因为无法获得绿色部分数据而出错,避免这种情况可以使用倒叙遍历,就是倒着遍历,从下往上,从左往右,这样就可以满足转移时对前文数据的依赖。而通过长度进行遍历的方式本质上是斜着遍历,即下图中蓝色、绿色、黄色、红色的遍历顺序,这样遍历,每次用到前面的数据的时候,上一次遍历都已经准备好了。原创 2022-12-18 22:55:32 · 187 阅读 · 0 评论 -
排序|快速排序的简单实现
其实很简单,把比x小的数都放到x的左边,把x数大的数都放到x的右边,此时x在数组的下标为i,这个i其实和数组排序后x所在的位置是一样的。也就是说这个分组操作之后,就将x的位置排好了。而且也将数组更加的有序化了。至于如何分组,可以使用一种朴素的实现方式,那就是直接创建两个数组a与b,用以存储大于等于x的数和小于x的数。至于x,不放入数组中,或者放入a中最末尾。其实漏掉了一个重要的东西,就是x的位置在分完之后代表着什么,有什么意义?很多教程里面讲到,这个函数需要把数组分成一边大于某数x,另一边小于x。原创 2022-11-29 11:08:39 · 234 阅读 · 0 评论 -
算法题|剑指 Offer II 038. 每日温度
单调栈很简单,就是在栈的基础上进行了一些改动,让每个入栈元素都与栈顶元素进行比较,如果入栈元素大于栈顶元素,栈顶元素则弹出,直至空栈或者栈顶元素大于入栈元素(也可以反过来,单调增或单调减都可以的)。这样就能表现一个特别的效果,即从栈底到栈顶呈现出单调的特性,栈底也保存着当前最大(或最小)的元素,入栈元素是弹出栈元素左边第一个比它大(或小)的元素,等等。这道题是很好的一道单调栈的练习题,感觉并不是有问题然后再出现解答,而是根据单调栈这个数据结构设计的题目。也就是说是跟着一个答案寻出了一道题目。原创 2022-11-08 19:14:38 · 92 阅读 · 0 评论 -
算法题|滑动窗口的最大值
校核方式为:查看元素中堆顶元素是否属于滑动窗口的范围内,查看的方法为比较堆顶元素下标是否大于滑动窗口左指针下标(i-k)。如果堆顶元素不在滑动窗口范围内,则弹出该元素,重复校核新堆顶元素,直至堆顶元素满足校核要求。每加入一个元素,视为滑动窗口向右移动一格(此时滑动窗口右指针为i),每次加入元素对该优先队列进行校核。官解第一种方法使用的优先队列,这个方法我觉得很妙,于是补充一下细节,加深对题目的理解。输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3。原创 2022-10-18 14:42:24 · 282 阅读 · 0 评论 -
算法题|剑指 Offer 35. 复杂链表的复制
题目出处:力扣描述:请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。---考察如何进行深拷贝;根据题解,解法有2种,第1种为复制后拆分,第2种为使用哈希表思路如下:复制后拆分代码量比较大, 稍后再实现,先选择实现哈希表做法:实现如下:(可以对照着上面的思路看代码实现)...原创 2022-07-13 10:20:07 · 63 阅读 · 0 评论 -
算法基础|迪杰斯特拉算法初次实现|DijkstraAlgorithm
迪杰斯特拉算法原创 2023-02-03 16:18:17 · 145 阅读 · 0 评论 -
算法基础|avl树实现思路、左旋与右旋的理解
旋转是改变子树结构的行为,通常说的进行左旋or右旋,指的是改变某棵树的某些结点的父子关系,从外观上看,就好像把某些结点向左or向右的进行了旋转。旋转得当可以减少树的高度(可以将高度-1)。............原创 2022-06-22 09:54:53 · 898 阅读 · 0 评论 -
算法基础|二叉树的遍历算法--中序非递归算法|Java实现
源自B站王卓老师的数据结构课程数据结构与算法基础(青岛大学-王卓)_哔哩哔哩_bilibili第08周03--5.5遍历二叉树和线索二叉树5--二叉树的遍历算法--中序非递归算法课程是C语言的,我写了个Java的实现,写了个大概,没细究是否有bug,我估计是有的。......原创 2022-06-16 12:16:37 · 218 阅读 · 0 评论 -
基础排序|基数排序初次实现
基数排序源于桶排序,桶排序源于计数排序因此只要按照如此途径进行学习,理解基数排序就非常容易了:计数排序-->桶排序-->基数排序当然,由于这些排序的实现过程很简单,不用按照顺序实现也是可以的。基数排序的实现过程:设置若干桶,首先将个位数的值,将数据放入桶中,然后顺序取出,在将数据同过十位数放入桶中,如此反复,直到最高位,最后一次取出就是排序后的结果。...原创 2022-06-14 21:42:25 · 71 阅读 · 0 评论 -
基础排序|计数排序初次实现
计数排序的原理很简单,就是把数组A中的数映射到另一个数组B的下标上,数组B中的元素是数的个数,每次映射到一个下标出,该下标的数值就+1,跟个计数器似的。> 感觉计组里面好多这样的算法。代码实现:...原创 2022-06-14 20:41:33 · 55 阅读 · 0 评论 -
算法|快速排序再次实现
分步骤实现快速排序,从最基础的地方开始实现快速排序。快拍实现原理:数组里面随便选择一个数(这里选择的是中间那个数),作为比较数,然后把大于比较数的放到左边,把小于比较数的放到右边,然后以比较数的下标为界可以将原数组分为两个数组,这两个数组重复上述操作,直到满足终止条件(数组长度==1时或其他什么的)返回,终止递归。写这种递归的算法,可以先分步的写出来,也就是像之前一样,先实现递归的第一个步骤:这里先实现第一步——让指针...原创 2022-06-14 15:45:18 · 90 阅读 · 0 评论 -
算法基础|再次实现希尔排序
希尔排序是高级排序的一种,希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。在代码上最大的不同在于其有个步长变量,该变量随着大循环不断减少至1,这个步长变量控制每次插入排序的分组。伪代码如下:老韩牛逼,老韩的实现方法教学如下:首先实现第一步,在起始步长时,对各组进行排序对上面那个一步的算法进行扩展,扩展到步长自动减少:上面算法原创 2022-06-13 21:37:44 · 53 阅读 · 0 评论 -
单向环形链表实现约瑟夫环
题目来自于老韩的算法教程,实现一个约瑟夫环,不过是用单向环形链表,这是我第二次实现了,第一次实现的时候很痛苦,这次倒是轻松很多。题目如下:.Josephu问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k (1...原创 2022-06-11 19:05:13 · 894 阅读 · 0 评论 -
排序|快速排序初次实现
著名的排序算法,说是冒泡排序的强化版,刚开始的时候我倒是没看出来和冒泡排序有什么联系,后来想了一想,确实如此,本质上还是非常接近的,都是不断的把最小的数往前移,把最大的数往后放,而且用的都是两数交换的方式。而且这个算法也是分治法的一种体现。 刚开始我觉得很难理解,但是后来多想了一会儿,就发现其实也没有那么复杂,实现原理还是很简单的,思考出这个算法才是真正难得地方。public class Quicksort { public static ...原创 2022-03-26 19:22:43 · 76 阅读 · 0 评论 -
排序|归并排序初次实现
归并排序体现了分治法,其中用到了递归的思想,这使得代码看上去非常的轻巧但又非常高效。归并排序如何做到排序的? 归并排序把数组分成两个部分,然后让其执行后面的排序(该排序算法可以将两个有序数组组成一个有序数组),但是执行之前会进入递归,将数组前后两部分排好序。如何做到通过递归将前后两部分排好序? 不断的将数组进行分割,直至成一个元素,开始向上收归,收归的过程中不断将元素按照写好的排序规则进行排序,最终排序成一个大数组,即目标数组。public class ...原创 2022-03-26 12:28:18 · 341 阅读 · 0 评论 -
排序|希尔排序初次实现
希尔排序作为高级排序的守门员,对于初学者而言还是非常友好的。~ 希尔排序是什么?希尔排序的就是在进行插入排序前,先对距离较远的元素进行交换,减少插入排序的遍历次数,让h=1的时候多多的break一些;~ 希尔排序的本质是什么? (我自认为)本质就是通过提前预排序减少元素离本位的距离,提高h=1时插入的效率。注意点:希尔排序本质还是插入排序,这对理解逻辑和实现代码至关重要。public class SellSort { public stat...原创 2022-03-25 22:43:05 · 269 阅读 · 0 评论 -
排序|插入排序初次实现
插入排序和冒泡、选择排序一样,都是简单排序,原理很简单,和做算法题的时候暴力枚举没什么区别,不用教自己琢磨也能琢磨出来的排序。public class InsertionSort { public static void main(String[] args) { int[] arr = {-7,6,5,4,3,2,1}; sort(arr); for (int i:arr) { System.out.print(i+"原创 2022-03-25 16:02:31 · 1287 阅读 · 0 评论 -
排序|选择排序初次实现
选择排序的意思很简单,就是不断和把第一个元素和后面元素比较,谁小谁放在第一个元素里面,然后每完成一次遍历,第一个元素的下标+1;实现代码如下:public class Selection_sort { public static void main(String[] args) { int[] arr = {-7,6,5,4,3,2,1}; sort(arr); for (int i:arr) { System.ou原创 2022-03-25 15:19:31 · 261 阅读 · 0 评论 -
排序|冒泡排序第2次实现
一次编程练习冒泡排序的算法的思路:指针遍历一次,就会把一个最大的数放到最后,每遍历一次后指针遍历的上限-1。程序实现的一些思路:1.本质上是两次循环,大循环套一个小循环1.1 大循环的循环一次就能把一个最大的数放到最后1.2 小循环一次可以把指针向后移动一位1.2.1 移动时可以进行数值判断2.确定一些循环停止的终点是比较关键的2.1确定大循环停止的点2.1确定小循环停止的点public class BubbleSort { pub...原创 2022-03-24 16:01:18 · 179 阅读 · 0 评论 -
中缀表达式转后缀表达式的理解
中缀表达式转后缀表达式实现思路原创 2022-03-19 21:41:28 · 178 阅读 · 0 评论 -
算法题|反转链表
尚硅谷-数据结构与算法-韩顺平-反转链表-例题题目:将一个链表反转原创 2022-03-15 21:42:43 · 375 阅读 · 0 评论 -
链表|合并两个有序的单链表,合并之后的链表依然有序
【尚硅谷-韩顺平-数据结构与算法(Java解释版)-链表-课后练习.】题目:合并两个有序的单链表,合并之后的链表依然有序解题要点:1.写一个链表增加方法2.要断开要添加的节点后面的节点,而不是抛掉(如果不理解,需增加对链表认识)public class ListTest1 { public static void main(String[] args) { Hero hero = new Hero(1,"林欢喜","戏法王子"); Hero he原创 2022-03-15 21:27:23 · 1251 阅读 · 0 评论