LeetCode_Reorder List

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.

For example,

Given {1,2,3,4}, reorder it to {1,4,2,3}.

典型的考察链表操作基本功的题目,对于链表的操作无非两个最基本的:插入和删除,这里要求按照给定的方式,将链表重新排序,由于排序之后,Ln要排到Ln-1之前,但是所给出的结点数据结构里没有保存当前结点前驱结点的指针,同时算法不允许投机取巧改变结点的值。

最一般的思想:如果每次都去找Ln...Ln-1...的位置在去执行题目要求的操作,那么每次找到需要向前插入的节点需要O(n),总共需要插入O(n)次,时间复杂度是O(n2),空间复杂的O(1);

进一步思考(我的解法):如果实现吧所有节点的地址都保存下来记为指针数组pointers[n],那么在操作过程中只需要对数组中的节点进行操作就可以了,省去了每次查找"Ln"节点的时间,由此时间复杂度O(n),空间复杂度O(n);

再进一步(这个事看别人的):在Discuss板块中,有人给出的算法,将后一半的链表执行倒序操作,然后在将被分解的两部分合并起来就可以了,时间复杂度O(n),空间复杂度O(1):

我的解法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */


class Solution {
public:
    void reorderList(ListNode *head) {
        if (head==NULL)
        {
            return ;
        }
        //思路:
        //创建一个等于链表长度的指针数组,保存链表中每个元素的指针
        //然后按照要求进行调整
        //双向遍历指针数组
        ListNode *ptop=head;
        ListNode *pbuttom=head;
        ListNode **pPointerArray;
        int  arraySize=0;
        while (pbuttom!=NULL)
        {
            pbuttom=pbuttom->next;
            arraySize++;
        }

        pPointerArray=new ListNode*[arraySize];
        pbuttom=head;
        int i=0;
        while (pbuttom!=NULL)
        {
            pPointerArray[i]=pbuttom;
            i++;
            pbuttom=pbuttom->next;
        }
        
        i=0;
        int j=arraySize-1;
        while (i<j)
        {
            //cut j
            pPointerArray[j-1]->next=pPointerArray[j]->next;
            //insert  j to i next
            pPointerArray[j]->next=pPointerArray[i]->next;
            pPointerArray[i]->next=pPointerArray[j];
            i++;
            j--;
        }
        
        delete[] pPointerArray;
    }
};

最好的解法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */


class Solution {
public:
    //void reorderList(ListNode *head) {
    //    if (head==NULL)
    //    {
    //        return ;
    //    }
    //    //思路:
    //    //创建一个等于链表长度的指针数组,保存链表中每个元素的指针
    //    //然后按照要求进行调整
    //    //双向遍历指针数组
    //    ListNode *ptop=head;
    //    ListNode *pbuttom=head;
    //    ListNode **pPointerArray;
    //    int  arraySize=0;
    //    while (pbuttom!=NULL)
    //    {
    //        pbuttom=pbuttom->next;
    //        arraySize++;
    //    }

    //    pPointerArray=new ListNode*[arraySize];
    //    pbuttom=head;
    //    int i=0;
    //    while (pbuttom!=NULL)
    //    {
    //        pPointerArray[i]=pbuttom;
    //        i++;
    //        pbuttom=pbuttom->next;
    //    }
    //    
    //    i=0;
    //    int j=arraySize-1;
    //    while (i<j)
    //    {
    //        //cut j
    //        pPointerArray[j-1]->next=pPointerArray[j]->next;
    //        //insert  j to i next
    //        pPointerArray[j]->next=pPointerArray[i]->next;
    //        pPointerArray[i]->next=pPointerArray[j];
    //        i++;
    //        j--;
    //    }
    //    
    //    delete[] pPointerArray;
    //}
    void reorderList(ListNode *head) {
        if (head==NULL)
        {
            return ;
        }

        //calculate the length of the list
        ListNode *pCurrent=head;
        int ListLen=0;
        while (pCurrent!=NULL)
        {
            ListLen++;
            pCurrent=pCurrent->next;
        }
        if (ListLen==1)
        {
            return;
        }
        //partation
        int halpLen=ListLen-ListLen/2;
        ListNode *pSecond=head;
        ListNode *pPreSecond=NULL;
        for (int i=0;i<halpLen;i++)
        {
            pPreSecond=pSecond;
            pSecond=pSecond->next;
        }
        pPreSecond->next=NULL;

        //reverse Second half
        pPreSecond=pSecond;
        pSecond=pSecond->next;
        pPreSecond->next=NULL;
        ListNode *pPostSecond;
        while (pSecond!=NULL)
        {
            //存储正序表下一个头节点 
            pPostSecond=pSecond->next;
            //从正序表断开当前节点
            pSecond->next=pPreSecond;
            //更新逆序表头节点
            pPreSecond=pSecond;
            //保证pSecond始终指向正序表头
            pSecond=pPostSecond;
        }
        pSecond=pPreSecond;

        ListNode *pFirst=head;
        while (pSecond!=NULL)
        {
            //保存后半部分逆序表头节点
            pPostSecond=pSecond->next;
            //将节点插入对应位置
            pSecond->next=pFirst->next;
            pFirst->next=pSecond;

            //更新下次待操作节点
            pFirst=pSecond->next;
            pSecond=pPostSecond;
        } 
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值