求助大神单链表算法题

输入一个链表输出该链表中倒數第k个结点。为了符合大多数人的习惯本题从1开始计数,即链表的尾结点是倒数第1个结点例如一个链表有6个结点,从头结点开始它们嘚值依次是1、2、3、4、5、6这个链表的倒数第3个结点是值为4的结点,需要保证时间复杂度。

设置两个指针p1,p2从头到尾开始出发,一个指针先出發k个节点然后第二个指针再进行出发,当第一个指针到达链表的节点的时候则第二个指针表示的位置就是链表的倒数第k个节点的位置。

//now开始走,直到cur走到最后一个指针, // 此时now所指的就是倒数的k个节点

总结:当我们用一个指针遍历链表不能解决问题的时候可以尝试用两个指針来遍历链表。可以让其中一个指针遍历的速度快一些(比如一次在链表上走两步)或者让它先在链表上走若干步。

输入一个单链表链表从尾到头打印链表每个节点的值。输入描述:输入为链表的表头;输出描述:输出为需要打印的“新链表”的表头

首先我们想到从尾到头打印出来,由于单链表的查询只能从头到尾所以可以想出栈的特性,先进后出所以非递归可以把链表的点全部放入一个栈当中,然后依次取出栈顶的位置即可

栈的特点是后进先出,即最后压入栈的元素最先弹出考虑到栈的这一特点,使用栈将链表元素顺序倒置从链表的头节点开始,依次将每个节点压入栈内然后依次弹出栈内的元素并存储到数组中。

//另外还有 递归和非递归的待更新
非递归嘚描述当中经常会用栈或者队列这些数据结构来改写一些递归的算法。其实递归的算法的时间复杂度是递归树的高度所以递归的层数樾高,时间复杂度也就会越高的

有一个单向链表,链表当中有可能出现“环”如何用程序判断出这个链表是有环链表?
不允许修改链表结构时间复杂度O(n),空间复杂度O(1)

首先从头节点开始,依次遍历单链表的每一个节点每遍历到一个新节点,就从头节点重新遍历新节點之前的所有节点用新节点ID和此节点之前所有节点ID依次作比较。如果发现新节点之前的所有节点当中存在相同节点ID则说明该节点被遍曆过两次,链表有环;如果之前的所有节点当中不存在相同的节点就继续遍历下一个新节点,继续重复刚才的操作

假设从链表头节点箌入环点的距离是D,链表的环长是S那么算法的时间复杂度是0+1+2+3+….+(D+S-1) = (D+S-1)(D+S)/2 , 可以简单地理解成 O(NN)而此算法没有创建额外存储空间,空间复杂度可以簡单地理解成为O(1)

这种方法是暴力破解的方式,时间复杂度太高

首先创建两个指针1和2,同时指向这个链表的头节点然后开始一个大循環,在循环体中让指针1每次向下移动一个节点,让指针2每次向下移动两个节点然后比较两个指针指向的节点是否相同。如果相同则判断出链表有环,如果不同则继续下一次循环。

说明 :在循环的环里面跑的快的指针一定会反复遇到跑的慢的指针 ,比如:在一个环形跑道上两个运动员在同一地点起跑,一个运动员速度快一个运动员速度慢。当两人跑了一段时间速度快的运动员必然会从速度慢嘚运动员身后再次追上并超过,原因很简单因为跑道是环形的。

有一个单向链表链表当中有可能出现“环”,那么如何知道链表中环嘚长度呢

由[3.如何判断一个链表有环]可以知道,快慢指针可以找到链表是否有环存在如果两个指针第一次相遇后,第二次相遇是什么时候呢第二次相遇是不是可以认为快的指针比慢的指针多跑了一个环的长度。所以找到第二次相遇的时候就找到了环的大小

//链表为空则返回null //两指针相遇,则返回相遇的结点 //链表无环则返回null //node为空则代表链表无环 //再次相遇则循环结束

给一个链表,若其中包含环请找出该链表的环的入口结点,否则输出null。

如果链表存在环那么计算出环的长度n,然后准备两个指针pSlowpFast,pFast先走n步然后pSlow和pFase一块走,当两者相遇时即为环的入口处;所以解决三个问题:如何判断一个链表有环;如何判断链表中环的大小;链表中环的入口结点。实际上最后的判断就洳同链表的倒数第k个节点

//相遇点即是入环节点 //当找到入环点时(未必是第一个) //两个指针未相遇,就继续往下跑

以上5题的套路其实都非常类似,第5题可以说是前面几道题的一个汇总题目吧链表类的题利用快慢指针,两个指针确实挺多的如下面题目7

给定单链表的头指针和一个結点指针,定一个函数在时间复杂度为O(1)删除链表结点

思路一:自杀不行就杀别人

根据了解的条件,如果只有一个单链表的头指针链表的刪除操作其实正常的是O(n)的时间复杂度。因为首先想到的是从头开始顺序遍历单链表然后找到节点,再进行删除但是这样的方式达箌的时间复杂度并不是O(1);实际上纯粹的删除节点操作,链表的删除操作是O(1)前提是需要找到删除指定节点的前一个结点就可以。

進阶:如果我们删除的节点是A那么我们把A下一个节点B和A的data进行交换,然后我们删除节点B是不是也可以达到同样的效果。先用要被删除节點后面那个位置的节点数据替换要被删除的节点然后让当前节点指向后一个位置,实际上删除的是给定节点后面那个位置!自杀不行僦杀别人,然后成为别人 (此思路还未实现)

做题时遇到对时间复杂度又要求的时候,可以考虑空间换时间的思想(虽然此处并未用到),增加一个指針,双指针一前一后,循环这个链表,找到该节点后删除即可.

//找到节点开始删除

题目的考虑的点,也很特别

输入两个单链表找出他们的第一個公共结点。

首先是两个链表是否相交,如果相交,则由于单链表的指针是指向下一个节点的如果两个单链表的第一个公共节点就说明他们後面的节点都是在一起的。类似下图由于两个链表的长度可能是不一致的,所以首先比较两个链表的长度mn,然后用两个指针分别指向兩个链表的头节点让较长的链表的指针先走|m-n|个长度,如果他们下面的节点是一样的就说明出现了第一个公共节点。

输入两个单调递增嘚链表输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则

这道题比较简单,合并两个有序的链表就可以设置两个指针进行操作即可,同时比较大小但是也需要注意两个链表的长度进行比较。

题目:请实现函数ComplexListNode Clone(ComplexListNode head)复制一个复杂链表。在复杂链表中每个结点除了有一个Next指针指向下一个结点外,还有一个Sibling指向链表中的任意结点或者NULL

 下图是一个含有5个结点的复杂链表。图中实線箭头表示m_pNext指针虚线箭头表示m_pSibling指针。为简单起见指向NULL的指针没有画出。

第一种:O(n2)的普通解法

  第一步是复制原始链表上的每一个结點并用Next节点链接起来;
  第二步是设置每个结点的Sibling节点指针。

第二种 :借助辅助空间的O(n)解法

  第一步仍然是复制原始链表上的每个結点N创建N'然后把这些创建出来的结点用Next链接起来。同时我们把<N,N'>的配对信息放到一个哈希表中
  第二步还是设置复制链表上每个结点嘚m_pSibling。由于有了哈希表我们可以用O(1)的时间根据S找到S'。

第三种:不借助辅助空间的O(n)解法

  第一步仍然是根据原始链表的每个结点N创建对应嘚N'(把N'链接在N的后面)

  第三步把这个长链表拆分成两个链表:把奇数位置的结点用Next链接起来就是原始链表,偶数数值的则是复制链表

//1、复制每个结点,如复制结点A得到A1将结点A1插到结点A后面; //3、拆分链表,将链表拆分为原链表和复制后的链表

题目:定义一个函数輸入一个链表的头结点,反转该链表并输出反转后链表的头结点如图:


利用栈先进后出的思想,将链表全部压入栈中,再取出即可.

把原链表嘚结点一个个摘掉,每次摘掉的链表都让他成为新的链表的头结点然后更新新链表。下面以链表1→2→3→4为例画个图来看下每次访问的原链表节点都会成为新链表的头结点

 已知一个带头结点的单链表结點结构为(data,link)假设该链表只给出了头指针list
在不改变链表的前提下,设计一个尽可能高效的算法查找链表中倒数第k个位置上的结点(k為正整数),
若查找成功算法输出该结点的data域的值,并返回1
否则,只返回0
设置两个指针p、q,分别指向该链表的第一个元素(头结点嘚下一个元素)和头结点一个整数num(初值为1),
p向后移动一个位置num值加1如果num值大于k,则pq一起移动,p移动到表尾q指针指的就是倒数苐k个位置上的结点。
如果链表结束q一直是指向头结点,那么该结点不存在

Wii游戏机有两个手柄每个手柄使鼡两节电池(这两个电池可以是不同的品牌),其中至少一块电池没电时该手柄没电

工程师们在玩游戏时,总是用最简单的方式更换电池:有手柄没电时把所有没电的电池拿走一一换上新电池即可(有电的电池总是继续使用)。当有手柄没电但没有新电池可用时才停止玩Wii

告诉你每个品牌电池的使用时间以及该品牌电池的个数,请计算工程师们玩游戏时间的最小值和最大值

输入第一行为一个正整数n,表示电池的种数接下来n行,每行两个整数L和F表示使用时间为L的电池有F个(电池不必成对出现,即F可以是奇数)

输出仅一行,包含两個整数分别表示工程师们的最短游戏时间和最长游戏时间(短的时间在前)。两个整数之间以空格隔开

我要回帖

 

随机推荐