206, 92, 65. Reverse Linked List 系列

Reverse Linked List是典型的链表头插法的实例。头插法比较简单易懂,条理清晰,是做很多linked list题目的关键。首先用最简单的Reverse Linked List这道题举例,简单说明一下什么是头插法。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head==nullptr)
            return nullptr;
        ListNode* dummy=new ListNode(-1);
        ListNode* cur=head;
        dummy->next=head;
        while(head->next!=nullptr){
            ListNode* next=head->next->next;
            head->next->next=dummy->next;
            dummy->next=head->next;
            head->next=next;
        }
        return dummy->next;
    }
};

在linked list里面,dummy和head是永远不会变的两个节点。头插法就是不停的将head->next插入到dummy和dummy->next之间,也就是除了dummy之外整个链表的开头。整个过程一共有四步

1.新建一个指针指向要移动的节点的下一个节点

2.移动head的下一个节点的next指针,指向dummy->next

3.dummy指向刚刚插入的节点

4.head指向新的next节点。

对于移动哪一个节点,改变哪一个指针,可以记住这样一个规律。先“pin”住一个节点,或者有新的指针指向它,那么指向这个节点就有两个指针了,9⃣️的指针就可以被改变。


Reverse Linked List这道题是reverse整个的linked list,翻转的是dummy和nullptr之间的链表串。那么对于reverse第m到n个元素之间的链表串,同样也可以这么做,只要找到相对应的dummy(链表之前的一个node)和对应的nullptr(要翻转的链表之后的那个node)就可以了。

但是如果我们one-pass,那么就需要一个count,计算我们移动了几个node。

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode* begin;
        //ListNode* end;
        ListNode* dummy = new ListNode(-1);
        ListNode* cur=dummy;
        int count=0;
        if(head==nullptr)
            return nullptr;
        dummy->next = head;//begin before start(dumy), end after start(nullptr)
        for(int i=1;i<m;++i){
            cur=cur->next;
        }
        begin=cur;
        cur=dummy;
        /*for(int i=0;i<=n;++i){
            cur=cur->next;
        }
        end=cur;*/
        ListNode* flag=begin->next;
        while(flag->next!=nullptr&&count<n-m){<span style="white-space:pre">	</span>//<span style="font-family: Arial, Helvetica, sans-serif;">flag->next!=end</span>
            ListNode* new_next=flag->next->next;
            flag->next->next=begin->next;
            begin->next=flag->next;
            flag->next=new_next;
            count++;
        }
        return dummy->next;
    }
};


第三道题Reverse Linked List in K-group也是同理,跟上面题一样,找到要翻转的链表之前对应的dummy节点和之后对应的nullptr节点。

class Solution {
public:
    ListNode* reverseKGroup(ListNode *head, int k) {
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        ListNode* cur = dummy->next;
        ListNode* pre = dummy;
        ListNode* next = nullptr;
        int count=0;
        while(cur!=nullptr){
            count++;
            next = cur->next;
            if(count==k){
                count=0;
                pre = reverse(pre, next);
            }
            cur=next;
        }
        return dummy->next;
    }
private:
    ListNode* reverse(ListNode *pre, ListNode *end){
        ListNode* head;
        ListNode* cur;
        head = pre->next;
        //cur = head->next;
        while(head->next!=end){
            ListNode* next = head->next->next;
            head->next->next = pre->next;
            pre->next = head->next;
            head->next=next;
        }
        head->next = end;
        return head;
    }
};






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值