字节算法-链表翻转与变形

文章目录

题目与变形

字节一面中关于 K个一组链表反转 的题目变形。

  • K个一组链表反转。
  • K个一组链表反转,链表尾不足K个的元素也需要反转。
  • K个一组链表反转,但是从链表尾部开始反转。
  • 反转从位置 left 到位置 right 的链表节点

解法

四个算法万变不离其宗,主要掌握原题即可。

java 复制代码
public class No0025ReverseGroup2 {
    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8};
        int k = 3;
        No0025ReverseGroup2 demo = new No0025ReverseGroup2();
        ListNode node = ListNode.createListNode(array);
        System.out.println("原始节点: " + node);
        ListNode res = demo.reverseKGroup(node, k);
        System.out.println("K个一组反转: " + res);
        ListNode res2 = demo.reverseKGroup2(ListNode.createListNode(array), k);
        System.out.println("剩余不足也K个反转: " + res2);
        ListNode res3 = demo.reverseKGroup3(ListNode.createListNode(array), k);
        System.out.println("从尾部开始K个一组反转: " + res3);
        ListNode res4 = demo.reverseKGroup4(ListNode.createListNode(array), 3, 6);
        System.out.println("反转指定区域的链表: " + res4);
    }
    
    /**
     * 反转 left 到 right 位置的元素
     */
    private ListNode reverseKGroup4(ListNode listNode, int begin, int stop) {
        ListNode result = new ListNode();
        result.next = listNode;
        ListNode left = result;
        ListNode right = result;

        for (int i = 0; i < stop; i++) {
            if (i < begin - 1) {
                // 保持 left.next 指向反转的起始节点
                left = left.next;
            }
            right = right.next;
        }

        while (left.next != right) {
            // 理解这里就OK了
            ListNode curr = left.next;
            left.next = curr.next;
            curr.next = right.next;
            right.next = curr;
        }
        return result.next;
    }

    /**
     * 变形2,从链表尾部开始 k 个一组反转
     */
    private ListNode reverseKGroup3(ListNode listNode, int k) {
        int count = 0;
        ListNode countNode = listNode;
        while (Objects.nonNull(countNode)) {
            countNode = countNode.next;
            count++;
        }

        ListNode result = new ListNode(0);
        result.next = listNode;
        ListNode left = result;
        ListNode right = result;

        int beginIndex = count % 3;
        for (int i = 0; i < beginIndex; i++) {
            left = left.next;
            right = right.next;
        }

        while (true) {
            for (int i = 0; i < k && Objects.nonNull(right); i++) {
                right = right.next;
            }
            if (Objects.isNull(right)) {
                break;
            }
            ListNode leftPtr = left.next;
            while (left.next != right) {
            	// 理解这里就OK了
                ListNode curr = left.next;
                left.next = curr.next;
                curr.next = right.next;
                right.next = curr;
            }
            left = leftPtr;
            right = leftPtr;
        }

        return result.next;
    }

    /**
     * 变形1,剩余元素不足K个也需要反转
     */
    private ListNode reverseKGroup2(ListNode listNode, int k) {
        ListNode result = new ListNode(0);
        result.next = listNode;
        ListNode left = result;
        ListNode right = result;
        ListNode preRight = right;

        while (true) {
            for (int i = 0; i < k && Objects.nonNull(right); i++) {
                preRight = right;
                right = right.next;
            }
            if (Objects.isNull(right)) {
                // 处理剩余部分的反转
                ListNode curr = left.next;
                left.next = curr.next;
                curr.next = preRight.next;
                preRight.next = curr;
                break;
            }
            ListNode leftPtr = left.next;
            while (left.next != right) {
	            // 理解这里就OK了
                ListNode curr = left.next;
                left.next = curr.next;
                curr.next = right.next;
                right.next = curr;
            }
            left = leftPtr;
            right = leftPtr;
        }
        return result.next;
    }

    /**
     * 原题,K个一组反转
     */
    private ListNode reverseKGroup(ListNode listNode, int k) {
        ListNode result = new ListNode(0);
        result.next = listNode;
        ListNode left = result;
        ListNode right = result;

        while (true) {
            for (int i = 0; i < k && Objects.nonNull(right); i++) {
                right = right.next;
            }
            if (Objects.isNull(right)) {
                break;
            }
            ListNode leftPtr = left.next;
            while (left.next != right) {
            	// 理解这里就OK了
                ListNode curr = left.next;
                left.next = curr.next;
                curr.next = right.next;
                right.next = curr;
            }
            left = leftPtr;
            right = leftPtr;
        }
        return result.next;
    }
}
java 复制代码
// 补充自用节点类
public class ListNode {
    public int val;
    public ListNode next;

    public ListNode() {
    }

    public ListNode(int val) {
        this.val = val;
    }

    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }

    public static ListNode createListNode(int[] array) {
        ListNode head = new ListNode(array[0]);
        ListNode node = head;
        for (int i = 1; i < array.length; i++) {
            ListNode next = new ListNode(array[i]);
            node.next = next;
            node = next;
        }
        return head;
    }
}
相关推荐
考虑考虑1 分钟前
点阵图更改背景文字
java·后端·java ee
ZHE|张恒9 分钟前
Spring Boot 3 + Flyway 全流程教程
java·spring boot·后端
TitosZhang9 分钟前
排序算法稳定性判断
数据结构·算法·排序算法
TDengine (老段)33 分钟前
TDengine 数学函数 CRC32 用户手册
java·大数据·数据库·sql·时序数据库·tdengine·1024程序员节
一种乐趣40 分钟前
PHP推荐权重算法以及分页
算法·php·推荐算法
心随雨下1 小时前
Tomcat日志配置与优化指南
java·服务器·tomcat
Kapaseker1 小时前
Java 25 中值得关注的新特性
java
wljt1 小时前
Linux 常用命令速查手册(Java开发版)
java·linux·python
撩得Android一次心动1 小时前
Android 四大组件——BroadcastReceiver(广播)
android·java·android 四大组件
canonical_entropy1 小时前
Nop平台到底有什么独特之处,它能用在什么场景?
java·后端·领域驱动设计