【力扣】143. 重排链表
给定一个单链表 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.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorder-list
/** * 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, j = list.size() - 1; while (i < j) { //把n-1 设置为 i的下一个节点 list.get(i).next = list.get(j); i++;// 到第二个节点 if (i == j) { //如果i == j 说明已经到中间值了 break; } list.get(j).next = list.get(i); //将n-1的下一个节点设置为i+1的值 j--; } list.get(i).next = null; //将中间值的内容设置为null,防止死循环 } }
时间复杂度O(n)
空间复杂度O(n)
另一种复杂,但空间复杂度为O(1)的算法:
1、先找到 原链表 的 中点
2、倒置 后一半链表
3、将两半链表穿插拼接
public void reorderList(ListNode head) { if (head == null || head.next == null || head.next.next == null) { return; } //找中点,链表分成两个 ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } ListNode newHead = slow.next; slow.next = null; //第二个链表倒置 newHead = reverseList(newHead); //链表节点依次连接 while (newHead != null) { ListNode temp = newHead.next; newHead.next = head.next; head.next = newHead; head = newHead.next; newHead = temp; } } private ListNode reverseList(ListNode head) { if (head == null) { return null; } ListNode tail = head; head = head.next; tail.next = null; while (head != null) { ListNode temp = head.next; head.next = tail; tail = head; head = temp; } return tail; }
一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻