链表算法面试题---交换链表的节点II

题目描述

给定一个链表,和一个正整数值X,请你把链表的节点按照每X个进行交换,然后返回交换后的链表。如果剩余的节点不足X个,则不用交换。

在之前我们做过的 交换链表的节点I中,是固定的两两交换,本题是它的升级版,交换的节点数,可动态传入。

示例:

在这里插入图片描述

解题思路:

相比固定的两两节点交换,本题我们首先还是先考虑把链表按照X的值,进行划分多个子链表,然后利用反转链表的方式,最后再拼接回原链表。
链表的题目一般对于算法思路上都比较容易理解,主要考验的还是编码的能力,本题看起来比较简单,实际对于编写的思路和技巧还是有一定要求的。

代码实现:


public class SwapListNode_02 {
    public static void main(String[] args) {
        SwapListNode_02 c = new SwapListNode_02();
        ListNode n = new ListNode(1);
        ListNode head = n;
        for (int i = 2; i < 5; i++) {
            n.next = new ListNode(i);
            n = n.next;
        }
        System.out.println(c.swapListNode(head, 2));
    }

    public ListNode swapListNode(ListNode head, int x) {
        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode pre = dummy;
		//整体处理过程请看图解
        while (head != null) {
            ListNode tail = pre;
            for (int i = 0; i < x; i++) {
                tail = tail.next;
                if (tail == null) {
                    return dummy.next;
                }
            }
            ListNode tailNext = tail.next;
            ListNode[] rev = reverseList(head, tail);
            head = rev[1];
            tail = rev[0];
            pre.next = head;
            tail.next = tailNext;
            pre = tail;
            head = tailNext;
        }
        return dummy.next;
    }

    private ListNode[] reverseList(ListNode head, ListNode tail) {
        ListNode pre = tail.next;
        ListNode cur = head;
        while (pre != tail) {
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return new ListNode[]{head, tail};

    }
}

图解过程

初始化一个哑结点,和每个子链表的前一个节点
在这里插入图片描述

ListNode tail = pre;
for (int i = 0; i < x; i++) {
    tail = tail.next;
    if (tail == null) {
        return dummy.next;
    }
}

在这里插入图片描述

ListNode tailNext = tail.next;

在这里插入图片描述

进入反转链表的流程

ListNode[] rev = reverseList(head, tail);
ListNode pre = tail.next;
ListNode cur = head;

在这里插入图片描述

ListNode next = cur.next;
cur.next = pre;

在这里插入图片描述

pre = cur;
cur = next;

在这里插入图片描述
第一次反转结束,重新反转流程,如下图,当第二次反转结果时,tail==pre,跳出循环,方法返回当前的head节点,和tail节点
在这里插入图片描述

交换head和tail节点

head = rev[1];
tail = rev[0];

在这里插入图片描述

pre.next = head;
tail.next = tailNext;

在这里插入图片描述

pre = tail;
head = tailNext;

在这里插入图片描述

第一次遍历完成,最终结果如下
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值