编程练习:重排链表|难度:中等

将给定的单链表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}.

我的思路是:
  1. 先找到中间结点
  2. 将后半段翻转
  3. 将后半段节点依次插入
这几项的实现方法为:
  1. 快慢指针。快指针一次走两步,慢指针一次走一步。快指针的速度是慢的两倍,快指针到末尾的时候,慢指针正好到中间。(妙啊!)
    while(fast->next!=nullptr&&fast->next->next!=nullptr) {// 这个判断注意顺序,一个next要写在两个next之前
    slow = slow->next;
    fast = fast->next->next;
    }

  2. 翻转。没什么好说的

  3. 依次插入。注意后半段一定要单独出来,即:
    se = slow->next;
    fi = head;
    slow->next = nullptr;

完整代码:
/**
 * 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==nullptr||head->next==nullptr||head->next->next==nullptr)
            return ;
        ListNode *slow,*fast;//中间
        slow = head;
        fast = head;
        while(fast->next!=nullptr&&fast->next->next!=nullptr) {// 这个判断注意顺序,一个next要写在两个next之前
            slow = slow->next;
            fast = fast->next->next;
        }
        //printf("%d\n",slow->data);
  
        ListNode *m,*p;//翻转
        m = slow->next;
        while(m->next!=nullptr){
            p = m->next;
            m->next = p->next;
            p->next = slow->next;
            slow->next = p;       
  
        }
  
        ListNode *se,*fi,*tem;//合并
        se = slow->next;
        fi = head;
        slow->next = nullptr;
        while(fi!=nullptr&&se!=nullptr){
            tem = se;
            se = se->next;
            tem->next = fi->next;
            fi->next = tem;       
            fi = fi->next->next;
             
        }
        }
};

还有一种暴力解法也贴一下,时间复杂度有点高,退出条件也需要想一想,不过就很简短哈哈 爽

class Solution {
public:
    void reorderList(ListNode *head) {
        if(head==nullptr||head->next==nullptr||head->next->next==nullptr)
            return ;
        ListNode *p,*m,*q;
        p = head;
        m = p;
        q = m;
        while(p->next!=m && p->next!=nullptr){
            m = head->next;
            while(m->next->next!=nullptr){
                m = m->next;       
            } 
            q = m->next;
            m->next = NULL;    
            q->next = p->next;
            p->next = q;   
            p = q->next;
            }
        return ;
        }
};

注意:做这种题一定要判空!不要让蓝桥杯的悲剧重演

if(head==nullptr||head->next==nullptr||head->next->next==nullptr) return ;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值