#143 重排链表

题目:

给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:
输入:head = [1,2,3,4]
输出:[1,4,2,3]

示例 2:
输入:head = [1,2,3,4,5]
输出:[1,5,2,4,3]

提示:
链表的长度范围为 [1, 5 * 104]
1 <= node.val <= 1000

思路1:

使用双链表法

代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */


 /**
    思路:使用线性表解决
    因为链表不支持下标访问,所以无法随机访问链表中任意位置的元素
    因此可以利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可    
 */
class Solution {
    public void reorderList(ListNode head) {
        // 如果链表为空或只有一个节点,无需重排
        if (head == null) {
            return;
        }

        // 创建一个列表来存储所有节点
        List<ListNode> list = new ArrayList<ListNode>();
        ListNode node = head;

        // 将链表中的所有节点添加到列表中
        while (node != null) {
            list.add(node);
            node = node.next;
        }

        // 使用双指针技巧重新排序
        int i = 0; // 前指针,从列表开头开始
        int j = list.size() - 1; // 后指针,从列表末尾开始

        while (i < j) {
            // 将前指针指向的节点的 next 指向后指针指向的节点
            list.get(i).next = list.get(j);
            i++; // 前指针向后移动

            // 如果 i 和 j 相遇,说明已经处理完所有节点
            if (i == j) {
                break;
            }

            // 将后指针指向的节点的 next 指向新的前指针指向的节点
            list.get(j).next = list.get(i);
            j--; // 后指针向前移动
        }

        // 将最后一个处理的节点的 next 置为 null,避免出现环
        list.get(i).next = null;
    }
}

复杂度:

时间复杂度:O(n)
空间复杂度:O(n)

思路2:

1.链表原地反转
2.寻找链表中点
3.链表合并

posted @ 2024-08-26 08:52  KenWan  阅读(5)  评论(0编辑  收藏  举报