Reorder List
今天是一道有关链表的题目,来自LeetCode,难度为Medium,Acceptance为23%。
题目如下
Given a singly linked list L:
L0→L1→…→Ln-1→Ln
,
reorder it to:L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.
Example
For example,
Given1->2->3->4->null
, reorder it to1->4->2->3->null
.
解题思路及代码见阅读原文
回复0000查看更多题目
解题思路
首先,该题是要将链表末尾的节点反向合并到链表中。因为是单向链表,所以一定涉及到反转链表的操作,那么我第一个想到的就是用一个栈,先将所有的节点进栈,然后在合并的时候出栈即可。
然而,用上述方法提交代码会得到Memory Limit Exceed的错误。那么显然用O(n)的方法是不行的,可以考虑就是采用O(1)的算法。
那么,我们可以采用如下思路:一、将链表从中间分开,分成两个链表;二、将后面一个链表反转;三、合并两个链表。第三步合并链表相对比较简单,较为复杂的是前面两步。
第一步分开链表,我们可以采用如Linked List Cycle(回复022查看)中采用的快慢指针的方法,当快指针到底链表末尾的时候,慢指针自然到达链表的中点,在此处即可将链表分开。
第二步反转链表方法就有很多了,可以采用头插法,也可以采用每个节点依次指向前一个节点,这里我采用的第二种方法。
下面我们来看代码。
代码如下
/**
* Definition for ListNode.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int val) {
* this.val = val;
* this.next = null;
* }
* }
*/
public class Solution {
/**
* @param head: The head of linked list.
* @return: void
*/
public void reorderList(ListNode head) {
// write your code here
if(null == head)
return;
// find mid node
ListNode fast = head, slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode head2 = slow.next;
slow.next = null;
//reverse
head2 = reverse(head2);
//merge
merge(head, head2);
}
private ListNode reverse(ListNode head) {
if(head == null)
return null;
ListNode current = head, next = current.next, prev = null;
while(current != null) {
current.next = prev;
prev = current;
current = next;
if(current != null)
next = current.next;
else
next = null;
}
return prev;
}
private ListNode merge(ListNode head1, ListNode head2) {
if(null == head1)
return head2;
if(null == head2)
return head1;
ListNode p = head1, next1 = head1.next, next2 = head2.next;
while(head1 != null && head2 != null) {
head1.next = head2;
head2.next = next1;
head1 = next1;
head2 = next2;
if(head1 != null)
next1 = head1.next;
if(head2 != null)
next2 = head2.next;
}
return p;
}
}
关注我
该公众号会每天推送常见面试题,包括解题思路是代码,希望对找工作的同学有所帮助