算法-链表

这篇博客探讨了两种链表操作问题:1. 指定区间单链表节点反转,通过创建辅助节点,定位起点,迭代反转指定区间内的节点。2. K个一组翻转链表,通过维护头节点,判断每次反转的边界,逐组反转。这两个问题都需要对链表的节点操作有深入理解,并能有效地交换节点连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表

单链表

1.2021-4-14 指定区间单链表节点反转

题目:

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例

在这里插入图片描述输入

head = [1,2,3,4,5], left = 2, right = 4

输出

[1,4,3,2,5]

思路

两个考点

第一个:当没有头节点的时候,需要自己创建一个
ListNode *myhead=new ListNode(0);
myhead->next=head;

第二个反转链表结束后需要获取的两个节点,
以[1 2 3 4 5] 2 4为例,我们需要让1->4
还需要让2->5。

那么相当于指定pre和now,pre在4时,now在5时结束。
然后需要让1->next->next指向now,1->next指向pre。

因此我们首先要先让hh=myhead,移动到1的位置。
即移动left-1次。
此时让pre=hh->next,now=hh->next->next。
另外整个反转循环应该是2到4,即right-left次。

代码:

   /**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        ListNode* myhead=new ListNode(0);
        myhead->next=head;
        ListNode* hh=myhead;
        right-=left;
        while(left>1){
            hh=hh->next;
            left--;
        }
        ListNode* pre=hh->next;
        ListNode* now=hh->next->next;
        while(right>0){
            ListNode* tmp=now->next;
            now->next=pre;
            pre=now;
            now=tmp;
            right--;
        }
        hh->next->next=now;
        hh->next=pre;
        return myhead->next;
    }
};

2.2021-4-15 K 个一组翻转链表

题目:

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

进阶:

你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例
在这里插入图片描述提示

列表中节点的数量在范围 sz 内
1 <= sz <= 5000
0 <= Node.val <= 1000
1 <= k <= sz

思路

这道题可以和反转链表和2个一组反转链表放在一起看。
其实是k个一组进行一次翻转。
首先在不满足k个剩余时退出,我们要用tmp1=当前开头->next,遍历到末尾,看是否cnt==k。
这里要非常注意tmp1是从当前开头的下一个开始,这样如果剩余刚好为k-1时,tmp1在前进k-1次时,tmp->next会为nullptr。

下个注意点就是在k个反转后要记录tmp3=h->next,处理完以后h=tmp3。

代码:

  /**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if(k<=1)return head;
        ListNode* h =new ListNode(0);
        ListNode* mh =h;
        h->next=head;
        while(true){
            ListNode* tmp1 =mh->next;
            int cnt=0;
            while(tmp1&&cnt!=k){
                cnt++;
                tmp1=tmp1->next;
            }
            if(cnt!=k)break;
            ListNode* prev =mh->next;
            ListNode* cur =prev->next;
            while(cnt-->1){
                ListNode* tmp2 =cur->next;
                cur->next=prev;
                prev=cur;
                cur=tmp2;
            }
            ListNode* tmp3 =mh->next;
            mh->next->next=cur;
            mh->next=prev;
            mh=tmp3;
        }
        return h->next;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值