
算法刷题笔记
文章平均质量分 64
自己刷程序员代码面试指南和leetcode的笔记和心得
zuiziyoudexiao
真正的自由不是随心所欲,而是自我主宰,若求随心所欲,则必随波逐流。
展开
-
2-22逆序打印链表
题目描述给定一个链表,从尾到头打印每一个元素。解题方法1链表是链式存储结构,不同于数组,没有办法直接逆序遍历。第一反应,我们可以借助于栈或数组,先顺序遍历链表把所有元素存储到数组或栈中,然后再遍历数组或栈进行逆序打印。空间复杂度为n,时间复杂度为n,不推荐。解题方法2既然可以使用栈解决,那么很自然想到可以使用递归来解决,对于每一层递归只打印第一个节点元素。public ...原创 2020-03-20 11:43:17 · 283 阅读 · 0 评论 -
2-21按照左右半区的方式重新组合链表
题目描述解题方法1先找到左半区和右边区的第一个节点,将左右半区看做两个链表。然后分别从两个链表中取出首节点连接到新链表末尾,直到左右半区均为空。public class Test { public static void main(String[] args) throws Exception { int[] arr = {1,2,3,7,8,9,10};...原创 2020-02-29 16:22:22 · 204 阅读 · 0 评论 -
2-20合并两个有序链表
题目描述传入两个有序链表,进行合并,最后返回新链表头节点。解题方法1使用两个指针p,q分别指向两个链表,比较两个指针指向的值,将值更小的那个节点断开连接到新链表末尾并将值更小节点对应指针后移,当两个指针有一个为null时结束遍历。循环退出后,两个链表可能有一个还有节点,将非空的链表连接到新链表之后即可。若两个链表长度为 m n,则时间复杂度为 m+n。public class ...原创 2020-02-29 16:20:52 · 171 阅读 · 0 评论 -
2-19有序环形链表中插入新节点
题目描述给定一个环形单链表的头节点,和一个num值,生成一个新节点插入到原链表中。保证环形链表从头节点开始到最后一个节点是非降序排序。解题方法1比如,环形链表为 1 2 2 3 5 5 7当num=3,新节点应该插入到第四个节点和第五个节点之间,当num=8,新节点应该在尾节点和头节点之间,当num=0时新节点也在尾节点和头节点之间,不过此时要将新节点作为头节点返回。...原创 2020-02-29 16:19:55 · 218 阅读 · 0 评论 -
2-18一种怪异的节点删除方式
题目描述只给定一个节点p,在头节点未知的情况下删除该节点p。链表的数据域为int值。解题方法如果不知道头节点,我们是无法得到p的前驱节点的,此时我们可以交换p与p的后继节点q的数据域,然后删除节点q,从而达到了类似的效果。不过这样做有两个问题:1.如果p是最后一个节点就无法删除,因为p的下一个节点为null。2.在实际工程问题中一个节点可能代表很复杂的结构,甚至节点是禁止访问的。...原创 2020-02-29 16:17:30 · 151 阅读 · 0 评论 -
2-17单链表的排序
题目描述我们知道选择排序的思想是将第一个元素与后面元素有条件进行交换,再让第二个元素与后面元素有条件进行交换,直到整个顺序表有序。总之就是选一个最小值放在第一个位置,选次小值放在第二个位置,直到完成升序排序。现在给定一个头节点,完成单链表的选择排序。解题方法1最笨的方法可以把链表元素存放到数组中,然后排好序再连接成链表,但是空间复杂度太高。这里直接用选择排序的思想对链表进行操作。其...原创 2020-02-29 16:16:06 · 174 阅读 · 0 评论 -
2-15删除单链表中指定值的节点
题目描述给定一个头节点,一个num值,删除链表中所有值为num的节点。解题方法1此题难度比较低,遍历寻找所有值为num的节点然后删除即可。注意维护一个前驱节点。时间复杂度为n。public class Test { public static void main(String[] args) throws Exception { int[] arr = ...原创 2020-02-29 16:14:35 · 344 阅读 · 0 评论 -
2-14删除无序链表中值重复出现的节点
题目描述删除无需链表中值重复出现的节点解题方法1可以使用哈希表来优化查找过程。遍历链表,依次将节点的值放入哈希表,如果当前节点p的值在哈希表中已存在就删除该节点p。注意要使用一个指针pre维护最近没有被删除的节点,将它作为删除节点的前驱节点。public class Test { public static void main(String[] args) throws...原创 2020-02-29 16:12:49 · 251 阅读 · 0 评论 -
2-13链表每k个节点之间逆序
题目描述链表每k个节点之间逆序,最后不足k个的节点不用逆序。解题方法1最简便的方式可以使用栈来完成,将链表节点依次入栈,当栈中元素达到k个时再依次出栈尾插到新链表中,这样不断入栈k个元素出栈k个元素就可以实现每k个节点之间逆序。需要注意的是,如果链表长度不是k的倍数,会有最后一组节点不足k个。如果循环结束栈中还有元素就将这些元素按原链表顺序插入到新链表之后(头插)。public cl...原创 2020-02-29 16:09:26 · 541 阅读 · 0 评论 -
2-12寻找相交链表的相交节点
题目描述两个单链表,它们可能相交也可能不相交,传入两个头节点,如果相交返回第一个相交节点,如果不相交返回null。如果两个链表相交,从相交节点往后的部分是两个链表共享的。解题方法1最简单的方法可以使用哈希表,依次遍历两个链表将节点指针存放到哈希表,那么哈希表中第一个重复的节点就是相交节点。但是空间复杂度为n。public class Test { public stat...原创 2020-02-29 16:05:52 · 282 阅读 · 0 评论 -
2-11寻找链表中的环
题目描述传入一个头节点判断链表是否有环,如果有环返回第一个入环的节点,如果没有环返回null。解题方法1可以使用哈希表来完成,每遍历一个节点就把该节点的引用存储到哈希表,如果哈希表中出现了重复的引用,那么那个重复的引用就是第一个入环的节点。如果没有出现重复的引用说明没有环。public class Test { public static void main(String[...原创 2020-02-29 16:03:04 · 444 阅读 · 0 评论 -
2-10两个单链表生成相加链表
题目描述解题方法1第一时间想到的方法是,我们可以把两个链表转化成两个整数,然后求和,再将求和后的整数转化为求和链表。把链表转化为整数,我们可以先求链表表长,然后给每个节点值乘上相应的幂方,将各节点依次求和。对整数转化为链表,我们可以使用头插法,依次对10取余将结果进行插入。代码如下:public class Test { public static void main(St...原创 2020-02-29 15:53:17 · 427 阅读 · 0 评论 -
2-9复制含有随机指针的链表
题目描述例如:原链表和赋值后链表如下所示,上箭头表示随机指针。解题方法1我们可以申请一个哈希表,遍历原链表保存原节点和复制节点的一个映射。如下:然后我们再遍历原链表进行新链表的建立。如遍历到节点1时,通过哈希表查找到1的复制节点1‘,然后查找到1节点的rand指针为空则把1’的rand指针也赋值为空,之后把1’插入到新链表。当遍历到节点2时,通过哈希表查找到2的复制节点2‘...原创 2020-02-29 15:50:49 · 141 阅读 · 0 评论 -
2-8按值划分链表
题目描述给定一个链表头节点和一个整数pivot,将这个链表调整为左边都是小于pivot的节点,中间都是等于pivot的节点,右边都是大于pivot的节点。解题方法1我们可以申请一个node引用类型的数组,将原链表的节点都存放到这个数组中。然后在数组中根据pivot调整位置,最后再把数组中节点按顺序依次相连即可。现在最主要的问题就是,具体如何对节点数组进行调整。可以定义三个变量 l...原创 2020-02-29 15:45:38 · 216 阅读 · 0 评论 -
2-7回文链表
题目描述判断一个链表是否为回文结构例如 1 2 1 返回true,1 2 3 返回false。解题方法1可以使用栈来解决,首先遍历链表求表长。然后将链表前一半节点元素依次入栈,然后再依次出栈与后续遍历节点进行比较。如果是奇数忽略中间节点。此种方式时间复杂度为n,空间复杂度也为n。public class Test { public static void main...原创 2020-02-29 15:42:39 · 101 阅读 · 0 评论 -
2-6约瑟夫环
题目描述解题方法1如果链表数据为 10 20 30 40 50 60 70 80 90 。那么按照如上规则,节点的删除顺序应该为 30 60 90 40 80 50 20 70 最后剩下的节点为10。最常规的方法,我们只需要设置一个计数器count,然后每遍历一个节点count加一,当count==m时删除当前节点并让count=0,不断遍历节点和删除直到剩下最后一个节点退出循环。需...原创 2020-02-29 15:39:42 · 239 阅读 · 0 评论 -
2-5反转链表一部分
题目描述解题方法1其实和反转整个链表是一个原理,依然使用头插的方法。只需要将第from-1个节点当成头节点,将第to个节点当成最后一个节点即可。首先遍历一遍链表,找到第from-1个节点phead和第to+1个节点ptail。然后反转from–to的部分,最后再将反转后的链表与节点ptail连接起来。代码如下:public class Test { public stat...原创 2020-02-29 15:31:36 · 230 阅读 · 0 评论 -
2-4反转链表
题目描述反转单链表解题方法1遍历链表,利用头插法将节点依次插入到头节点之后。public class Test { public static void main(String[] args) throws Exception { int[] arr = {10,20,30,40,50}; Node head = create(arr); ...原创 2020-02-29 15:29:53 · 115 阅读 · 0 评论 -
2-3删除链表中间节点
题目描述删除链表的中间节点解题方法1如果链表长度为n,令k = n/2向上取整。那么要删除的节点就是第k个节点。只需要先计算链表长度求k值,然后找到第k-1个节点,然后删除第k个节点。public class Test { public static void main(String[] args) throws Exception { int[] arr =...原创 2020-02-29 15:28:08 · 216 阅读 · 0 评论 -
2-2删除单链表倒数第k个节点
题目描述删除单链表倒数第k个节点,要求时间复杂度为n,空间复杂度为1。解题方法1最简单的方法,先将链表遍历一遍求出链表长度n,那么倒数第k个节点其实就是第n-k+1个节点。然后再次遍历链表找到待删除的节点和删除节点前一个节点即可。public class Test { public static void main(String[] args) throws Except...原创 2020-02-29 15:24:45 · 344 阅读 · 0 评论 -
2-1打印两个有序链表公共部分
题目描述传入两个链表头节点,打印两个有序链表的公共部分。解题方法1使用两个引用p和q依次指向两个链表,然后比较p和q所指向的值。如果p.val < q.val p向后移动一位。如果p.val > q.val q向后移动一位。如果相等打印此节点的值然后pq均向后移动一位。直到p和q有一个遍历到头,程序终止。public class Test { pub...原创 2020-02-29 15:23:42 · 160 阅读 · 0 评论 -
1-10max-min不超过num的子数组
题目描述给定一个数组arr和一个值num,求子数组的最大值 - 最小值 <= num 的子数组的数量。如给定arr = {3,2,5,1,4,6},num = 2 ,则符合条件的子数组有两个,为 {3,2} {4,6}。解题方法1我们可以暴力检索所有的子数组,然后求出每个子数组的最大值与最小值进而解决问题。但是时间复杂度为n^3,有优化的空间。代码如下:public cl...原创 2020-02-29 13:45:07 · 142 阅读 · 0 评论 -
1-9 求最大子矩阵问题
题目描述求最大子矩阵问题。解题方法1首先,我们以每一行做切割统计以当前行作为底的情况下,每个位置往上1的数量(遇到0为止),这样针对每一行我们都可以得到一个数组。如:第一行数组为 1 0 1 1,第二行数组为 2 1 2 2,第三行数组为 3 2 3 0。而针对每一行得到的那个数组,我们可以看做一个条形统计图,然后在这个条形统计图中找到的最大矩形的面积就是每一行对应的最大子矩阵中元...原创 2020-02-29 13:42:45 · 434 阅读 · 0 评论 -
1-8 数组的maxtree
题目描述一个数组的maxtree定义如下:数组没有重复元素,包括maxtree在内的每个子树都是根节点最大,而且maxtree是二叉树。给定一个没有重复元素的数组arr,要求生成这个数组对应的maxtree,且时间复杂度和空间复杂度都要求为n。解题方法1一个数组的matree不是唯一的,但是我们要的是符合时间复杂度和空间复杂度的构建方法。那么如何尽快找到每个数左右两侧第一...原创 2020-02-29 13:37:08 · 359 阅读 · 0 评论 -
1-7 生成窗口最大值数组
题目描述计算生成窗口最大值数组有一个整型数组arr和一个大小为w的窗口从数组最左边滑到最右边。现在要求实现一个函数,输入整型数组arr和窗口长度w,输出一个最大值数组res记录每个窗口的最大值。解题方法1最简单粗暴的方法就是直接两层遍历,代码如下。但是时间复杂度为 n*w 显然有优化的空间。public class Test { public static...原创 2020-02-29 13:33:21 · 175 阅读 · 0 评论 -
1-6 汉诺塔问题的改进
题目描述汉诺塔问题的改进。有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘; 大盘不能叠在小盘上面。 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。问具体应该怎样移动。以上是经典的汉诺塔问题,现在修改一下移动的规则,不能从a塔直接移动到c塔,也不能直接从...原创 2020-02-29 13:30:58 · 662 阅读 · 0 评论 -
1-5 一个栈排序另一个栈
题目描述用一个栈实现另一个栈的排序。一个栈中元素的类型为整型,现在将该栈从顶到底按从大到小的顺序排序,只允许额外使用一个栈,不允许使用其他数据结构。解题方法1设待排序的栈为s1,辅助的栈为s2,再定义一个变量e保存刚刚从s1出栈的元素。先弹出s1的栈顶保存到变量e,然后比较e与s2的栈顶top,如果e<=top就将e压入s2,如果e>top将s2栈顶弹出压入s1。然后一...原创 2020-02-29 13:28:33 · 150 阅读 · 0 评论 -
1-4 实现猫狗队列
题目描述实现猫狗队列。解题尝试我们可以定义三个队列catq,dogq和allq,catq只存放cat对象,dogq只存放dog对象,allq存放所有对象。这样all队列就可以记录所有元素的入队顺序。这样可以解决部分问题,但是如果要弹出一个dog对象或cat对象就难以实现了,因为如果要弹出的对象在allq队列中不是allq的队头那么就无法将allq队列中相应元素弹出。那么除了使用...原创 2020-02-29 13:25:44 · 698 阅读 · 0 评论 -
1-3 用递归和栈操作逆序一个栈
题目描述仅用递归和栈操作逆序一个栈,不能使用其他数据结构。一个栈依次压入10 20 30 40 50,那么从栈顶到栈底依次为50 40 30 20 10。将这个栈转置后从栈顶到栈底为10 20 30 40 50,也就是实现栈中元素的逆序。解题尝试我们可以先使用递归逆序打印一个栈,然后看看此题和它有没有什么联系。逆序打印很好实现,代码如下:public s...原创 2020-02-29 13:21:10 · 192 阅读 · 0 评论 -
1-2 两个栈模拟一个队列
题目描述用两个栈模拟一个队列,实现队列基本的入队,出队,取队头的功能。解题方法1首先准备两个栈s1和s2,s1作为压入栈,s2作为弹出栈。而且必须满足,将s1数据转给s2时必须一次性全部转完,如果s2还有数据就不能把s1数据转给s2。实现入队操作只需要对s1入栈即可。实现出队功能时,如果s2不为空,s2直接出栈。如果s2为空s1有数据,那么把s1的所有数据出栈,入栈到s2,然后s2...原创 2020-02-29 13:18:26 · 422 阅读 · 0 评论 -
1-1 带有getmin功能的栈
题目描述实现一个特殊的栈,在实现栈基本功能的基础上,再实现返回栈中最小元素的操作。要求push,pop,getmin的操作时间复杂度都是 1。设计的栈类型可以使用现成的栈结构。解题尝试自己最初的设想是在栈中增加一个成员变量min,用来记录最小值,每入栈一个元素就把这个元素和min比较,如果小于min就更新min的值。但是如果值为min的那个最小元素出栈了,那么就无法判断当前栈中哪...原创 2020-02-29 13:16:50 · 295 阅读 · 0 评论