k个一组翻转链表

题目

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例 :

给定这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明 :

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

心得

写这道题目可以用递归,但对递归不太了解,所以明天打算写一下递归的专题,暂时不在这道题上耗时间了,等递归用的顺手的时候再回来写它。

学到的点:

1、计算时间复杂度,虽然我在一个大循环里面包了两个不同的小循环,但是时间复杂度加在一起,一共是 f ( 3 l − l k ) f(3l-\frac{l}{k}) f(3lkl),并不是我想的会复杂度很高。

2、要理清楚ListNode的存储结构,不然容易出现指向地址的值产生循环的情况。

思路

注:里面precorr默认使用0->xxxxxx如此,虽然画的是直接指向需要转换的链表的头指针,但是他们默认是.next指向。

我没太看仔细看网上的思路,跟着自己的想法写了这个,用语言不知道要怎么表达,干脆放图好了:

在上图中,先考虑只改变ListNode链表首的翻转变动。 k = 1 k = 1 k=1的时候链表不做改动, k = 2 k = 2 k=2的时候两两交换, k = 3 k = 3 k=3的时候就把 k = 2 k=2 k=2时候翻转好的链表作为一个整体,再和指向的第三个链表做一次两两交换, k = 4 k=4 k=4就可以把 k = 3 k=3 k=3的已经转换好的链表看做一个整体,再与指向的第四个链表做一次两两交换,以此类推。

这样就可以发现可以根据 k k k数量的做一次循环了,这个循环的复杂度只有 f ( k ) f(k) f(k),需要的指针如下所示:

指针end永远都是跟在second的后面,指向链表尾部,second指向end的前一个的原因就是上面说的将前一部分看做一个整体,和后面指向的数字进行两两交换,first->second就是那个整体,end是那个后面指向的数字。所以first永远都是指在要交换的链表头(就是比如图上1->2->3->4时候, k = 3 k=3 k=3,第一次要对1->2->3交换,那first指向链表中存储1的位置,当前面三个交换完之后,对下一组进行交换,那么first就应该指向4,因为它是下一组的链表之首。)

pre.next这个指针我用来存储头节点,到最后可以通过输出它,而输出已经被翻转好的链表。

但是,因为end指针会一直和first指针进行交换,所以pre.next指针指向的地址只会一直跟着first,而无法将转换好的链表完整输出:

所以我加了一个corr指针去跟踪这个翻转后的完整的链表,让corr指向翻转好的链表地址。

这样,就得到正确的结果了。

为了知道有多少段链表需要我去进行翻转,而不用临时判空等操作浪费时间,所以在用循环知道了链表会有多长之后,整除 k k k,知道了有多少段链表需要翻转,然后再整合上面的思路。

优化

emm我觉得递归的话可能效率更高?因为时间都浪费在让occr这个指针去跟踪更新的链表了。

题目来源

leedcode

参考代码

参考代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值