[leetcode 3] reorder-list

17 篇文章 0 订阅

题目描述
将给定的单链表L: L 0→L 1→…→L n-1→L n,
重新排序为: L 0→L n →L 1→L n-1→L 2→L n-2→…
要求使用原地算法,并且不改变节点的值
例如:
对于给定的单链表{1,2,3,4},将其重新排序为{1,4,2,3}.
Given a singly linked list L: L 0→L 1→…→L n-1→L n,
reorder it to: L 0→L n →L 1→L n-1→L 2→L n-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}.

原地算法简介:
在计算机科学中,一个原地算法(in-place algorithm)基本上不需要额外辅助的数据结构,然而,允许少量额外的辅助变量来转换数据的算法。当算法运行时,输入的数据通常会被要输出的部分覆盖掉。不是原地算法有时候称为非原地(not-in-place)或不得其所(out-of-place)。

思路:

  • 要求使用原地算法,那就不能利用栈等数据结构;
  • 利用cur指针和last指针作为索引分别指向头尾即将要插入的结点,插入过的结点就从链表中删除;
  • 当链表的长度小于等于2时,完成最后一次插入;
  • 注意到GetLastTwo函数返回的是链表的倒数第二个结点,这么做的目的是更方便的删除最后一个结点。

代码:

/**
 * 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 || head->next == NULL || head->next->next == NULL)
            return;
        ListNode *cur = head->next;
        ListNode *last = GetLastTwo(cur);
        ListNode *tem = head;
        while (last && cur != last)
        {
            tem->next = last->next;
            last->next = NULL;
            tem = tem->next;
            tem->next = cur;
            cur = cur->next;
            tem = tem->next;
            last = GetLastTwo(cur);
        }
        if (last == NULL)
        {
            tem->next = cur;
            cur->next = NULL;
        }
        else
        {
            tem->next = cur->next;
            tem = tem->next;
            tem->next = cur;
            cur->next = NULL;
        }
        return;
    }
    ListNode *GetLastTwo(ListNode *head) // 取倒数第二个结点
    {
        if (head == NULL || head->next == NULL)
            return NULL;
        while (head->next->next != NULL)
        {
            head = head->next;
        }
        return head;
    }
};

运行时间:254ms,占用内存:1760k。

之后看了大神们的思路,大多是利用快慢指针找到中间结点,对后半部分逆序,再合并两个链表。学习了~
代码:

/**
 * 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 || head->next == NULL || head->next->next == NULL)
            return;
         
        //快慢指针找中点
        ListNode* fast = head;
        ListNode* low = head;
        while(fast->next != NULL && fast->next->next != NULL){
            fast = fast->next->next;
            low = low->next;
        }
         
        //对low后面的部分逆序
        fast = low->next;
        low->next = NULL;
        while(fast != NULL){
            ListNode* temp = fast->next;
            fast->next = low->next;
            low->next = fast;
            fast = temp;
        }
         
        //合并low前面和后面两部分
        ListNode* p = head;
        ListNode* q = low->next;
        while(p != NULL && q != NULL){
            low->next = q->next;
            q->next = p->next;
            p->next = q;
            p = q->next;
            q = low->next;
        }
    }

运行时间:23ms,占用内存:1796k。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值