重排链表

题目

Alt
题目来源:https://leetcode-cn.com/problems/reorder-list/

思路

自己的思路

首先我们需要解读一下题目:先看题目限定条件:不能单纯的改变节点内部的值,而是需要实际进行节点交换,所以需要对原链表进行节点交换操作

  1. 起初自己分析了很多,一开始是想着快捷路径,先从第二个节点开始,没增加一个节点,那么就把它放到头节点的后面,然后再尝试看看能否通过进行依次的交换得到结果,后来发现这种思路对于节点少的链表可以,但是当链表数量多时,却行不通。
  2. 第二个思路还是盯着最后一个节点永远在头节点之后这个条件,也是尝试着通过一次遍历就能得到正确结果,结果发现这样子也行不通
  3. 第三个思路就比较接近正确的思路的,通过对链表进行分割,将链表分割为两份,然后将后面的链表一次插入到前面的链表中间去,但是到后面的思路也出现了偏差:一方面我始终只盯着头尾,想着不用对后面的链表进行反转(好像这样子也行,但是存在一个问题就是:如果你从后面开始插入,那么就需要一个判断:比如第一个例子,链表分为两份,一份是1 2 3,后面的链表就为4,如果从后面开始插入的话,那么结果就不正确),而且寻找链表中点我采用的是一种比较笨的方法:遍历整个链表,求出链表的节点个数,然后再通过除2的方法得到中点

参考思路

首先,我们需要解决三个问题:

  1. 问题一:如何寻找到链表的中点,我采用的就是笨方法,那么还有一种巧妙的方法就是利用快慢指针进行,因为快指针所走的路程永远是慢指针的两倍,那么等到快指针走完的时候,那么慢指针所在的节点就是链表中点,代码如下:
        ListNode* fast = head, * slow = head;
		while (fast && fast->next) {  //利用快慢指针寻找中点
			slow = slow->next;
			fast = fast->next->next;
		}
  1. 问题二:如何进行链表的反转。这个问题我们就得复习一下关于链表反转的相关知识了:链表的反转有常用的两种方法,第一种就是依次将每个节点放到新的头节点的头部;第二种方法就是保存第一个节点,然后再每次的交换中,都是将第一个节点后面的节点放到新的头节点的后面。相关知识在https://blog.csdn.net/clearLB/article/details/104035215,代码如下,这里采用的是第一种方法:将每个节点放在新链表的头部
        ListNode* res = slow->next;
		slow->next = NULL;
		//对后边的链表进行反转
		ListNode* start = NULL;
		ListNode* temp;
		while (res != NULL) {
			temp = res->next;
			res->next = start;
			start = res;
			res = temp;
		}
  1. 问题三:如何插入。我们现在已经得到了分离的两个链表,最后一个步骤就是将后边反转的链表插入到前面的链表中,先直接上代码吧:
        ListNode* H = head;
		ListNode* ch;
		while (start != NULL) {
			temp = H->next;
			ch = start->next;//保存下一个要插入的点
			H->next = start;//将点插入
			start->next = temp;
			H = temp;
			start = ch;
		}

这里我们将后面的链表是否为空作为循环条件(因为后面链表肯定都要插入到前面的链表当中,所以我们只需要判断后面的链表是否为空即可)

完整代码如下:

class Solution {
public:
    void reorderList(ListNode* head) {
        if(head==NULL)
        return;
       ListNode* fast = head, * slow = head;
		while (fast && fast->next) {  //利用快慢指针寻找中点
			slow = slow->next;
			fast = fast->next->next;
		}
		ListNode* res = slow->next;
		slow->next = NULL;
		//对后边的链表进行反转
		ListNode* start = NULL;
		ListNode* temp;
		while (res != NULL) {
			temp = res->next;
			res->next = start;
			start = res;
			res = temp;
		}
		//进行插入
		ListNode* H = head;
		ListNode* ch;
		while (start != NULL) {
			temp = H->next;
			ch = start->next;//保存下一个要插入的点
			H->next = start;//将点插入
			start->next = temp;
			H = temp;
			start = ch;
		}
    }
};

总结

这道题其实就是几个之前的知识点的组合,如快慢指针的灵活运用,链表的反转,和链表的插入,关键在于是否懂得灵活运用组合来解题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值