ReOrder list 链表 重排序

ReOrder list 链表 重排序_第1张图片


关于单链表的题目,最重要的便是指针的操作。我近期涉及到的单链表的题目对我最大的感想就是:无论是对单链表的任何操作,一个单链表的标识便是它的头指针。所以很多的操作无非就是一个“新”的头节点带领着一列元素罢了。

对于上述的题目,可能刚开始的时候会无从下手,至少我是这样,我在考虑怎样将Ln移动到L1之后,怎样得到Ln-1的指针呢。其实分开来看,无非就是两个链表的merge, L = L0 , L1 , ...  L(n/2)  ;   R =  Ln, Ln-1, ... , L(n/2+1). 怎样得到这两个链表呢?

对于L, 直接截取链表的前 n/2 个元素即可。分为两种方法,

    1     首先计算整个链表的长度n, 然后 将头指针移动 n/2 次,便得到了 L:

    2  可以使用快慢指针的方式,快的指针每次移动两步,慢的指针每次移动一步,直到快的指针到达链表尾部时,此时的慢指针就是要找的分界点。


对于 R,由于在寻找L的过程中,将整个链表分成了前后断,后一段为 L(n/2+1), L (n/2+2), ... , Ln, 但是我们需要的R刚好是它的reverse。这里便涉及到链表的reverse的操作,其实很简单,只需要遍历一遍,将每个节点依次插入到 “新的” 链表的表头即可。

比如: L1,L2,L3 ,现要将这个链表reverse。设新的链表头为RR:

则RR = NULL;对于节点L1, 将L1插入到链表的表头,RR = L1,依次有 RR = L2,L1; RR = L3,L2,L1,

,因此达到了上述的reverse的目的。

最后一步直接merge L 和 R 即可。代码大致为:

    void reorderList(ListNode *head) {
        if(head == NULL) return;
        ListNode *tail = new ListNode(0);
        ListNode *t1 = head;
        int len = 0 ;
        while(t1)
        {
            len++;
            t1 = t1->next;
        }
        int mid = len/2;
        t1 = head;
        while(mid--) t1 = t1->next;
        ListNode *t2 = t1->next;
        t1->next = NULL;
        ListNode *t3 = NULL;
        //reverse
        while(t2)
        {
            t1 = tail->next;
            t3 = t2->next;
            tail->next = t2;
            t2->next = t1;
            t2 = t3;
        }
        
        t2 = tail->next;
        t1 = head;
        ListNode *t4 = NULL;
        while(t2)
        {
            t3 = t1->next;
            t4 = t2->next;
            t1->next = t2;
            t2->next = t3;
            t1 = t3;
            t2 = t4;
        }
        
    }

总结: 链表的操作主要是头节点的重要性。





你可能感兴趣的:(LeetCode,单链表,merge,reverse)