算法小知识-----8.08-----K 个一组翻转链表

56 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情

今天确实是抽了,强硬挑战困难题

K个一组翻转链表

该题出自力扣的25题 —— K个一组翻转链表【困难题】,不过这算是困难题里面比较简单的

审题

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

  • k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
  • 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
  • 这道题确实是困难题里面比较简单的,并不会考究算法的深度,只是考验设计的全面性
  • 给出一个链表的头结点,给出k的整数值,需要把链表按照K个为一组去反转,可以参考从前做过的一道题 —— 链表反转;利用那道题作为一个API去调用即可
  • 拥有了一个调用的API,那么只需要对链表按照边界分组,需要判断K个是否会超出界限
  • 反转后需要对链表进行拼接,需要保存反转的上一个节点,保存尾部节点;反转后调用next方法拼接

编码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {

        //进阶:你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?
        ListNode hair = new ListNode(0);
        hair.next = head;
        ListNode first = hair;
        while (head != null){
            // 2 先行判断是否到达k
            ListNode tail = first;
            for (int i = 0; i < k; i++) {
                tail = tail.next;
                if (tail == null){
                    return hair.next;
                }
            }

            ListNode next = tail.next;


            ListNode[] listNodes = reverseList(head, tail);
            ListNode top = listNodes[0];
            ListNode last = listNodes[1];
            last.next = next;
            first.next = top;
            first = last;
            head = last.next;

        }
        return hair.next;
    }

    public ListNode[] reverseList(ListNode head,ListNode tail) {
        ListNode prev = tail.next;
        ListNode cur = head;
        while (prev != tail){
            ListNode next = cur.next;
            cur.next = prev;
            prev = cur;
            cur = next;
        }
        return new ListNode[]{tail,head};
    }
}

image.png