Code Ganker: Reorder List -- LeetCode

2014年3月18日星期二

Reorder List -- LeetCode

原题链接: http://oj.leetcode.com/problems/reorder-list/
这是一道比较综合的链表操作的题目,要按照题目要求给链表重新连接成要求的结果。其实理清思路也比较简单,分三步完成:(1)将链表切成两半,也就是找到中点,然后截成两条链表;(2)将后面一条链表进行reverse操作,就是反转过来;(3)将两条链表按顺序依次merge起来。
这几个操作都是我们曾经接触过的操作了,第一步找中点就是用Linked List Cycle中的walker-runner方法,一个两倍速跑,一个一倍速跑,知道快的碰到链表尾部,慢的就正好停在中点了。第二步是比较常见的reverse操作,在Reverse Nodes in k-Group也有用到了,一般就是一个个的翻转过来即可。第三步是一个merge操作,做法类似于Sort List中的merge,只是这里不需要比较元素打小了,只要按顺序左边取一个,右边取一个就可以了。
接下来看看时间复杂度,第一步扫描链表一遍,是O(n),第二步对半条链表做一次反转,也是O(n),第三部对两条半链表进行合并,也是一遍O(n)。所以总的时间复杂度还是O(n),由于过程中没有用到额外空间,所以空间复杂度O(1)。代码如下:
public void reorderList(ListNode head) {
    if(head == null || head.next==null)
    {
        return;
    }
    ListNode walker = head;
    ListNode runner = head;
    while(runner.next!=null && runner.next.next!=null)
    {
        walker = walker.next;
        runner = runner.next.next;
    }
    ListNode head1 = head;
    ListNode head2 = walker.next;
    walker.next = null;
    head2 = reverse(head2);
    while(head1!=null && head2!=null)
    {
        ListNode next = head2.next;
        head2.next = head1.next;
        head1.next = head2;
        head1 = head2.next;
        head2 = next;
    }
}
private ListNode reverse(ListNode head)
{
    ListNode pre = null;
    ListNode cur = head;
    while(cur!=null)
    {
        ListNode next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}
这道题看起来比较复杂,其实理清思路之后就都是链表常见的几个基本操作。这里我想多说一下reverse操作,因为这是链表最常见的操作。有时候在第一轮电面这种比较基础的面试中,可能会要求实现reverse操作,但是因为有点过于简单,面试官会要求递归和非递归都实现一下。上面的代码使用非递归的方式实现reverse。下面我们列举一下递归的代码,有兴趣的朋友可以看看哈。
public ListNode recursive_reverse(ListNode head) {
    if(head == null || head.next==null)
        return head;
    return recursive_reverse(head, head.next);
}
private ListNode recursive_reverse(ListNode current, ListNode next) 
{
    if (next == null) return current;
    ListNode newHead = recursive_reverse(current.next, next.next);
    next.next = current;
    current.next = null;
    return newHead;
}

没有评论:

发表评论