写出一段代码将链表中的两个节点位置互换位置_以leetcode25题来谈谈链表相关思路

57dc8cbf14c916fb73f6ed251a9b0d52.png

在面对leetcode上链表相关问题时,有一些注意点:

  1. 交换链表节点时,我们可以先记录下 prev cur next节点指针。当遍历到cur节点时,记录前后两个节点,在遍历过程中修改prev cur next达到交换节点的效果。
  2. 最先定义一个虚拟节点dummy->next = head 起到固定的作用。如果头节点也移动了,则直接通过这个虚拟节点返回。
  3. 判断链表有环: 快(2步)慢(1步)指针相遇,相遇后从相遇点和起点同时出发(速度1步),再次相遇为环位置。
  4. 两个链表A和B判断是否相交, A+B B+A后长度相同。从头节点开始遍历,当节点next为nullptr时再指向另一个链表头节点,之后遍历相遇时就可以判断相交。

接下来做一道非常经典的链表题目: 25. K 个一组翻转链表

64ae16c3b77d031b4815e822cc25bcbc.png
  1. 考虑用prev head tail三个指针去记录k个一组子链表的首(head)尾(tail)节点,prevhead的前一个节点,因为head tail都反转了,需要用prev去维系前面子链表和当前反转子链表的关系。
  2. 定义个函数,输入head tail,经过翻转后返回新的head tail
  3. 担心第一个节点就要会被移动,所以先定义一个虚节点dummy,放在链表首节点前。dummy->next = head

接下来上代码:

class Solution {
public:
    // 反转head到tail这一段的链表,并返回反转后的首尾节点 head tail
    pair<ListNode*, ListNode*> reverseHeadAndTail(ListNode* head, ListNode* tail) {
        ListNode* prev = tail->next, * cur = head;
        while (prev != tail) {  // 每次都改变prev和cur的next指向,之后向后遍历
            ListNode* next = cur->next;
            cur->next = prev;   // 每次只改cur的next指针指向
            prev = cur;
            cur = next;
        } 

        return {tail, head};
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* dummy = new ListNode(-1);  // head可能会移动,所以设置一个虚节点
        dummy->next = head;
        ListNode* prev = dummy;
        while (head) {
            ListNode* tail = prev;
            // head tail 即为需要翻转的子链表
            for (int i = 0; i < k; i++) {
                tail = tail->next;
                if (tail == nullptr) return dummy->next;
            }
            ListNode* next = tail->next;
            pair<ListNode*, ListNode*> res = reverseHeadAndTail(head, tail);
            head = res.first;
            tail = res.second;

            prev->next = head;
            tail->next = next;
            prev = tail;
            head = next;
        }

        return dummy->next;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值