C++实现LeetCode(25.每k个一组翻转链表)

 更新时间:2021年07月13日 16:57:20   作者:Grandyang  
这篇文章主要介绍了C++实现LeetCode(25.每k个一组翻转链表),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

[LeetCode] 25. Reverse Nodes in k-Group 每k个一组翻转链表

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

Example:

Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

Note:

  • Only constant extra memory is allowed.
  • You may not alter the values in the list's nodes, only nodes itself may be changed.

这道题让我们以每k个为一组来翻转链表,实际上是把原链表分成若干小段,然后分别对其进行翻转,那么肯定总共需要两个函数,一个是用来分段的,一个是用来翻转的,以题目中给的例子来看,对于给定链表 1->2->3->4->5,一般在处理链表问题时,大多时候都会在开头再加一个 dummy node,因为翻转链表时头结点可能会变化,为了记录当前最新的头结点的位置而引入的 dummy node,加入 dummy node 后的链表变为 -1->1->2->3->4->5,如果k为3的话,目标是将 1,2,3 翻转一下,那么需要一些指针,pre 和 next 分别指向要翻转的链表的前后的位置,然后翻转后 pre 的位置更新到如下新的位置:

-1->1->2->3->4->5
|        |  |
pre      cur next

-1->3->2->1->4->5
|     |  |
cur   pre next

以此类推,只要 cur 走过k个节点,那么 next 就是 cur->next,就可以调用翻转函数来进行局部翻转了,注意翻转之后新的 cur 和 pre 的位置都不同了,那么翻转之后,cur 应该更新为 pre->next,而如果不需要翻转的话,cur 更新为 cur->next,代码如下所示:

解法一:

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if (!head || k == 1) return head;
        ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = head;
        dummy->next = head;
        for (int i = 1; cur; ++i) {
            if (i % k == 0) {
                pre = reverseOneGroup(pre, cur->next);
                cur = pre->next;
            } else {
                cur = cur->next;
            }
        }
        return dummy->next;
    }
    ListNode* reverseOneGroup(ListNode* pre, ListNode* next) {
        ListNode *last = pre->next, *cur = last->next;
        while(cur != next) {
            last->next = cur->next;
            cur->next = pre->next;
            pre->next = cur;
            cur = last->next;
        }
        return last;
    }
};

我们也可以在一个函数中完成,首先遍历整个链表,统计出链表的长度,然后如果长度大于等于k,交换节点,当 k=2 时,每段只需要交换一次,当 k=3 时,每段需要交换2此,所以i从1开始循环,注意交换一段后更新 pre 指针,然后 num 自减k,直到 num<k 时循环结束,参见代码如下:

解法二:

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = pre;
        dummy->next = head;
        int num = 0;
        while (cur = cur->next) ++num;
        while (num >= k) {
            cur = pre->next;
            for (int i = 1; i < k; ++i) {
                ListNode *t = cur->next;
                cur->next = t->next;
                t->next = pre->next;
                pre->next = t;
            }
            pre = cur;
            num -= k;
        }
        return dummy->next;
    }
};

我们也可以使用递归来做,用 head 记录每段的开始位置,cur 记录结束位置的下一个节点,然后调用 reverse 函数来将这段翻转,然后得到一个 new_head,原来的 head 就变成了末尾,这时候后面接上递归调用下一段得到的新节点,返回 new_head 即可,参见代码如下:

解法三:

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode *cur = head;
        for (int i = 0; i < k; ++i) {
            if (!cur) return head;
            cur = cur->next;
        }
        ListNode *new_head = reverse(head, cur);
        head->next = reverseKGroup(cur, k);
        return new_head;
    }
    ListNode* reverse(ListNode* head, ListNode* tail) {
        ListNode *pre = tail;
        while (head != tail) {
            ListNode *t = head->next;
            head->next = pre;
            pre = head;
            head = t;
        }
        return pre;
    }
};

到此这篇关于C++实现LeetCode(25.每k个一组翻转链表)的文章就介绍到这了,更多相关C++实现每k个一组翻转链表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中读写txt文件并分离字符的方法

    C++中读写txt文件并分离字符的方法

    今天小编就为大家分享一篇C++中读写txt文件并分离字符的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • c/c++拷贝构造函数和关键字explicit详解

    c/c++拷贝构造函数和关键字explicit详解

    这篇文章主要介绍了c/c++拷贝构造函数和关键字explicit的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-08-08
  • C++通过自定义函数求一元二次方程的根

    C++通过自定义函数求一元二次方程的根

    这篇文章主要介绍了C++通过自定义函数求一元二次方程的根,涉及C++数学运算相关技巧,非常简单实用,需要的朋友可以参考下
    2016-05-05
  • C语言库函数qsort的使用详解

    C语言库函数qsort的使用详解

    C语言库函数中的qsort的是一个回调函数,回调函数就是一个通过函数指针调用的函数,这篇文章主要介绍了C语言库函数qsort的使用,需要的朋友可以参考下
    2022-06-06
  • C++实现闹钟程序的方法

    C++实现闹钟程序的方法

    这篇文章主要介绍了C++实现闹钟程序的方法,比较实用的功能,需要的朋友可以参考下
    2014-08-08
  • C++ OpenCV实现抖音"蓝线挑战"特效

    C++ OpenCV实现抖音"蓝线挑战"特效

    这篇文章主要介绍了如何使用OpenCV C++ 实现抖音上的特效“蓝线挑战”。文中的示例代码讲解详细,对我们学习OpenCV有一定的帮助,需要的可以参考一下
    2022-01-01
  • kernel劫持modprobe path内容详解

    kernel劫持modprobe path内容详解

    这篇文章主要为大家介绍了kernel劫持modprobe path的内容详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • C语言从txt文件中逐行读入数据存到数组中的实现方法

    C语言从txt文件中逐行读入数据存到数组中的实现方法

    下面小编就为大家带来一篇C语言从txt文件中逐行读入数据存到数组中的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • C++ plog日志使用方法介绍

    C++ plog日志使用方法介绍

    最近突然心血来潮,想学一下日志方面的操作。在网上找了很多日志相关的技术,最终还是决定使用plog,小巧,快速,跨平台
    2022-10-10
  • C语言16进制与ASCII字符相互转换

    C语言16进制与ASCII字符相互转换

    大家好,本篇文章主要讲的是C语言16进制与ASCII字符相互转换,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01

最新评论