反转链表和部分反转

反转链表和部分反转

反转链表

ListNode* reverseList(ListNode* head) {
       if(head==nullptr) {
           return head;
       }
       if(head->next==nullptr){
           return head;
       }
       ListNode* p  = head;
       ListNode* q  = p->next;
       ListNode* r  = nullptr;
       p->next = nullptr;
       while(q) {
           r = q->next;
           q->next = p;
           p=q;
           q=r;
       }
       return p;

  }

关键点:
1.虽是三个指针,但是逐个元素进行操作
2.使用p和q两个指针配合工作,使得两个节点间的指向反向,同时用r记录剩下的链表
3.q是操作完的最后一个元素,因此要返回它

参考:
https://blog.csdn.net/feliciafay/article/details/6841115

反转链表(部分反转)

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

示例 1:

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii

思路:利用全部反转的逻辑,作一次封装;
关键点:
1.保存或记录要反转部分的前继和后继node;
2.判断特殊值,如,要反转的部分是从链表头开始的这种情况;

/**
* 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)
    {
        if (!head)
            return nullptr;

        ListNode *p = nullptr;
        ListNode *q = nullptr;

        p = head;

        if (left < 0 || right < 0 || left > right)
            return nullptr;

        int list_length = 0;
        while (p)
        {
            p = p->next;
            list_length++;
        }

        if (left > list_length || right > list_length)
            return nullptr;

        int index = 1;
        int length = right - left + 1;
        ListNode *temp_tail = nullptr;

        //要反转的长度就是链表的长度,那直接全部返转
        if (length == list_length)
            return reverse(head, length, &temp_tail);
        //要反转的长度就是链表的长度为1,那可以不作任何操作
        if (left == right)
            return head;

        p = nullptr;//保存要反转部分的前继
        q = head;//保存要反转部分的第一个节点
        while (index < left)
        {
            p = q;
            q = q->next;
            index++;
        }
        //保存要反转部分的第一个节点
        ListNode *temp_head = reverse(q, length, &temp_tail);

        //要反转的部分有可能是从链表头部开始的做个判断即可
        if (p)
        {
            p->next = temp_head;
            q->next = temp_tail;
            return head;
        }
        else
        {
            q->next = temp_tail;
            return temp_head;
        }
    }
    /*head:反转部分的第一个节点
    length:反转部分的长度
    tail:指向要反转部分的最后一个结点的下一个元素(以备后序的拼接 )
    返回值:返回反转成功后的链表头
    */
    ListNode *reverse(ListNode *head, int length, ListNode **tail)
    {
        if (!head || length == 0)
            return nullptr;
        ListNode *p = nullptr;;
        ListNode *q = nullptr;;
        ListNode *r = nullptr;;
        p = head;
        q = p->next;
        p->next = nullptr;
        int index = 1;
        while (q)
        {
            r = q->next;
            q->next = p;
            p = q;
            q = r;
            index++;
            if (index >= length)
            {
                break;
            }
        }
        *tail = q;
        return p;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值