算法---LeetCode 143. 重排链表

1. 题目

原题链接

给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:
给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
Related Topics 链表
👍 602 👎 0

2. 题解

2.1 解法1: 存储

使用 list 存储链表, 然后按照一前一后顺序重排链表

    class Solution {
        public void reorderList(ListNode head) {
            if (head == null) {
                return;
            }
            List<ListNode> nodeList = new ArrayList<>();
            ListNode p = head;
            while (p != null) {
                nodeList.add(p);
                p = p.next;
            }
            //头尾指针依次取元素
            int i = 0, j = nodeList.size() - 1;
            while (i < j) {
                nodeList.get(i).next = nodeList.get(j);
                i++;
                //偶数个节点的情况,会提前相遇
                if (i == j) {
                    break;
                }
                nodeList.get(j).next=nodeList.get(i);
                j--;
            }
            nodeList.get(i).next = null;
        }
    }

2.2 解法2: 寻找链表中点 + 链表逆序 + 合并链表

  1. 找到原链表的中点(参考「876. 链表的中间结点」)。
    我们可以使用快慢指针来 O(N) 地找到链表的中间节点。
    如果节点个数是偶数的话,slow 走到的是左端点,利用这一点,我们可以把奇数和偶数的情况合并,不需要分开考虑。
  2. 将原链表的右半端反转(参考「206. 反转链表」)。
    我们可以使用迭代法实现链表的反转。
  3. 将原链表的两端合并。
    因为两链表长度相差不超过 1,因此直接合并即可。
    class Solution {
        public void reorderList(ListNode head) {
            if (head == null || head.next == null) {
                return;
            }
            // 快慢指针找链表中点
            ListNode slow = head;
            ListNode fast = head;
            while (fast.next != null && fast.next.next != null) {
                fast = fast.next.next;
                slow = slow.next;
            }
            // 分割链表并反转后一个链表
            ListNode second = slow.next;
            slow.next = null;
            second = reverse(second);

            // 合并两个链表
            ListNode first = head;
            while (first != null && second != null) {
                // 保存两个结点的后驱结点
                ListNode fNext = first.next;
                ListNode sNext = second.next;
                // 建立连接
                first.next = second;
                second.next = fNext;

                first = fNext;
                second = sNext;
            }

        }


        // 反转链表
        public ListNode reverse(ListNode head) {
            ListNode pre = null;
            ListNode curr = head;
            while (curr != null) {
                ListNode temp = curr.next;
                curr.next = pre;
                pre = curr;
                curr = temp;
            }
            return pre;
        }

    }

参考:
详细通俗的思路分析,多解法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值