NC2 题解 | #重排链表#

重排链表

http://www.nowcoder.com/practice/3d281dc0b3704347846a110bf561ef6b

题意分析

  • 给出一个链表,需要我们对这个链表进行重新排列,交错取出原来的链表最前面没有被取过的和最后面没有被取过的结点,新的链表就是按照这个取出的顺序重新拼接而成的一个链表。
  • 样例解释
    图片说明

思路分析

  • 题目的意思是给我们一个链表的头结点,需要我们不能改变结点内部的值,只能改变结点的next指针。这样的话,我们首先需要知道的就是将这个链表的所有的结点先进行保存,我们可以开一个动态数组vector,然后,我们使用双指针的方法一个l,一个r,用来表示当前最前面可以选择的结点的位置和当前最后面可以选择的结点的位置。这样的话我们就可以通过移动指针,然后不断更新每个结点的next结点。
    图片说明

写法一

  • 代码如下
    • 需要遍历整个链表的所有的结点,时间复杂度为O(n)
    • 需要存储整个链表的所有的结点的值和指针,空间复杂度为O(n)
/**
 * 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){
            return;
        }
        vector<ListNode*> v;
        ListNode* now=head;
        // 将所有的结点先存入一个动态数组里面
        while(now){
            v.push_back(now);
            now=now->next;
        }
        // 定义动态数组的双指针,分别指向最前面的没被使用的结点和最后面没被使用的结点的位置
        int l=1,r=v.size()-1;
        now=head;
        int x=0;  // 我们定义一个x用来表示我们现在是取最前面的结点还是取后面的结点
        while(l<=r){
            if(x&1){
                now->next=v[l];
                l++;
            }else{
                now->next=v[r];
                r--;
            }
            now=now->next;
            x++;
        }
        // 最后记得把链表的最后的结点的next结点指向为NULL,不断会段错误
        now->next=NULL;
    }
};

写法二

  • 如果对我上面的while循环感觉比较难理解的话,可以尝试使用下面的写法,就是我们先把前面取的指针和后面取的指针都放到不同的动态数组里面,然后对两个数组轮流取结点就可以了。这种写法的空间复杂度是一样的,就是切入点有一点不一样。

  • 代码如下

    • 需要遍历整个链表的所有的结点,时间复杂度为O(n)
    • 需要存储整个链表,空间复杂度为O(n)
/**
 * 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) return;
        vector<ListNode*> pre,suf;  // pre表示取的前面的结点,suf表示取的后面的结点
        ListNode* now = head;
        while(now){  // 我们先将所有的结点都暂时存放到pre数组里面
            pre.push_back(now);
            now=now->next;
        }
        int x=pre.size(),mid=(x+1)/2;
        while(x>mid){  //然后我们将后半部分的节点存放到我们的suf数组里面
            suf.push_back(pre[x-1]);
            pre.pop_back();
            x--;
        }
        now=head;
        int len2=suf.size(),len1=pre.size();
        int l=1,r=0;
        // l指针表示的是当前的pre数组可以用的结点的位置,r指针表示的是的当前的suf数组可以用结点的位置
        while(l<len1||r<len2){
            if(l==r){
                now->next=pre[l];
                l++;
            }else{
                now->next=suf[r];
                r++;
            }
            now=now->next;
        }
        // 记得最后的节点的next指针指向NULL
        now->next=NULL;
    }
};
全部评论

相关推荐

06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
06-05 19:46
已编辑
武汉大学 后端
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务