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

文章目录

题目与变形

字节一面中关于 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;
    }
}
相关推荐
.道阻且长.5 小时前
2.LeetCode算法习题讲解--双指针--复写零
算法·leetcode·职场和发展
·薯条大王6 小时前
经济实惠玩云服务器|一台云服务器多人共用,子账号配置教程
java·linux·运维·服务器·汇编·c++·python
To_OC7 小时前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
ZJH__GO9 小时前
网络编程v4pro--实现聊天室文件传输功能
java·服务器·网络·计算机网络
程序员黑豆9 小时前
Windows 系统 Java 环境变量配置全攻略:解决“不是内部或外部命令”
java·前端·ai编程
命运之光9 小时前
【C语言完整代码】就诊信息管理系统
java·c语言·开发语言
凤山老林9 小时前
Spring Boot @Async 线上实战:从默认配置到生产级线程池治理
java·spring boot·后端
Forever Nore10 小时前
学完C语言力扣第一题做不来正常吗
数据结构·算法
marvelyu10 小时前
每天10分钟学会OceanBase系列(Day 20):跨机房容灾实战——构建多数据中心高可用架构
java·大数据·数据库