LC25K个一组翻转链表、LC206反转链表

LC25方法一、acwing

// pre 指向 需要翻转的 局部链表的 第1个结点 的 之前的结点
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        auto dummy = new ListNode(-1), pre = dummy;
        dummy->next = head;

        // 改成 while(1)也可, 因为跳出循环是靠下面的 break.
        // while(head)可以特判 head == null 情况, 不用等到下面break 就提前跳出
        // while(pre->next) 可以特判 head == null 和 pre->next == null 的情况
        while (pre->next) {
            // 1. 判断是否 还有 k 个结点
            auto q = pre->next;
            for (int i = 1; i < k && q; i ++ ) q = q->next; // 能否移动 k - 1 次
            if (!q) break; // 跳出 for循环, 要么 1.移动了k-1次,q不为空; 2.q为空,不够k个

            // 1. 判断是否 还有 k 个结点
            // int cnt = 0;
            // for (auto q = pre->next; q && cnt <= k; q = q->next) cnt ++ ;
            // if (cnt < k ) break;

            // 2.1 局部翻转链表
            auto a = pre->next, b = a->next;
            for (int i = 1; i < k; i ++ ) { // k-1 次. 注意 不能while(--k), k值 不能变动
                auto c = b->next;
                b->next = a;
                a = b, b = c;
            }

            // 2.2 处理 局部链表 首尾结点 处的 连接情况
            head = pre->next; // 用 head 暂存 pre->next
            pre->next = a, head->next = b;

            // 2.3 pre 更新为 下一段需要局部翻转的链表段的 前一个结点, 即 b之前的结点 head
            pre = head; // pre需要指向b之前的结点, b之前的结点是 head 而不是 a !!!
        }

        return dummy->next;
    }
};

LC25方法二、递归

class Solution {
 public:
    ListNode* reverseKGroup(ListNode* head, int k) {
       if(head==nullptr) return nullptr;//递归的结束条件
       ListNode*a=head;
       ListNode*b=head;
       for(int i=0;i<k;i++){
           //下面是递归时一条链接的情况
           if(b==nullptr)return head;//说明不是k的整数倍,直接返回此时的head
           b=b->next;//把b移动到k的前一个位置
       }
       //把a到b之间的节点反转,不算b
        ListNode*newNode = reverseOperator(a,b);
        
        a->next= reverseKGroup(b,k);//递归调用本函数,这个太难想到了

        return newNode;
    }
    ListNode* reverseOperator(ListNode* n, ListNode* b ){
        ListNode* pre=nullptr;
        ListNode*cur=n;
        ListNode*nxt=n;
        //循环条件就限定了只反转b之前的节点
        while(cur!=b){
            nxt=cur->next;
            cur->next=pre;
            pre=cur;
            cur=nxt;
        }
        return pre;
    }
};

LC25方法三、栈(时间空间复杂度高)

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        stack<ListNode*> stk;
        ListNode* res=new ListNode;
        ListNode* p=res,*q;
        int i;
        while(head){
            for(i=0;head&&i<k;i++){//k个一组进栈
                stk.push(head);
                head=head->next;
            }
            if(i!=k)break;//不成一组跳出
            while(!stk.empty()){//逆序出栈
                p->next=stk.top();
                p=stk.top();
                stk.pop();
            }
            q=head;
        }
        p->next=q;//接上余下的点
        return res->next;
    }
};

LC206反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = NULL, *pre = head;
        while (pre != NULL) {
            ListNode* t = pre->next;
            pre->next = cur;
            cur = pre;
            pre = t;
        }
        return cur;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值