題目描述
題目原鏈接:重排鏈表
給定一個單鏈表 L:L0→L1→…→Ln-1→Ln ,
將其重新排列後變爲: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。
示例 1:
給定鏈表 1->2->3->4, 重新排列爲 1->4->2->3.
解釋: 因爲無重複字符的最長子串是 “abc”,所以其長度爲 3。
示例 2:
給定鏈表 1->2->3->4->5, 重新排列爲 1->5->2->4->3.
解答思路
這道題目是我在字節跳動2019年秋招提前批中遇到的,當時寫不出來,所以現在想在這裏總結一下該題的解決思路。
流程:
- 把鏈表先拆分爲兩半;(使用快慢指針)
- 對鏈表的後半段進行反轉的操作;(使用反轉鏈表的方法)
- 用兩個指針分別指向兩條鏈表的頭節點,然後將第一條鏈表的當前節點指向第二條鏈表的當前節點,然後兩個節點都移動到下一位。
注意:
對鏈表的拆分應該注意後半段長度比前半段的小,這樣在第三步的時候才能正常完成鏈接。如果是前半段的長度比較小,那麼後半段的最後一個節點將得不到連接。因爲整個鏈表拆分爲2,所以前半段鏈表最多隻能比後半段鏈表大1個長度。
代碼
public class Solution {
public void reorderList(ListNode head) {
if (head == null || head.next == null) {
return;
}
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode p1 = head;
ListNode p2 = reverse(slow.next);
slow.next = null;
while (p1 != null && p2 != null) {
ListNode pNext = p1.next;
p1.next = p2;
p1 = pNext;
pNext = p2.next;
p2.next = p1;
p2 = pNext;
}
}
// 反轉鏈表的代碼
public ListNode reverse(ListNode head) {
ListNode cur = head;
ListNode pre = null;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}