《算法通关村第二关黄金挑战一一K个一组反转》

news2024/9/21 22:05:16

《算法通关村第二关黄金挑战一一K个一组反转》

描述

每 k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

解法

头插法

理解图:
在这里插入图片描述

穿针引线法

理解图
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码实现

package AlgorithmSecond;

import AlgorithmFirst.LinkedNode;

public class GroupReverse {
    /**
     * 头插法
     *
     * @param head
     * @param k
     * @return
     */
    public static LinkedNode HeadInsertMethod(LinkedNode head, int k) {
        LinkedNode dummyNode = new LinkedNode(0);
        dummyNode.setNext(head);
        LinkedNode cur = head;
        int len = 0; // 先计算出链表的长度
        while (cur != null) {
            len++;
            cur = cur.getNext();
        }
        int n = len / k; // 计算出有几组
        LinkedNode pre = dummyNode;
        cur = head;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < k - 1; j++) {
                LinkedNode next = cur.getNext();
                cur.setNext(cur.getNext().getNext());
                next.setNext(pre.getNext());
                pre.setNext(next);
            }
            pre = cur;
            cur = cur.getNext();
        }
        return dummyNode.getNext();
    }
/**
* 穿针引线法
*/
    public static LinkedNode TheSecondMethod(LinkedNode head, int k) {
        LinkedNode dummyNode = new LinkedNode(0);
        dummyNode.setNext(head);
        LinkedNode pre = dummyNode;
        LinkedNode end = dummyNode;
        while (end.getNext() != null) {
            // 找到要处理的区间的末尾
            for (int i = 0; i < k && end != null; i++) {
                end = end.getNext();
            }
            if (end == null) {
                break;
            }
            // 将要处理的区间裁剪下来
            LinkedNode start = pre.getNext();
            LinkedNode next = end.getNext();
            end.setNext(null);
            // 执行反转
            pre.setNext(reverse(start));
            start.setNext(next);
            // 调整指针,为下一组做准备
            pre = start;
            end = pre;
        }
        return dummyNode.getNext();
    }

    private static LinkedNode reverse(LinkedNode head) {
        LinkedNode pre = null;
        LinkedNode cur = head;
        while(cur!= null){
            LinkedNode next = cur.getNext();
            cur.setNext(pre);
            pre = cur;
            cur = next;
        }
        return pre;
    }

    public static void main(String[] args) {
        int[] vars = {1, 3, 4, 5, 7, 8, 9};
        LinkedNode head = LinkedNode.initList(vars);
        LinkedNode.printLinkedList(TheSecondMethod(head, 4));
    }
}

链表

package AlgorithmFirst;

public class LinkedNode {
    private int data;
    private LinkedNode next;

    public LinkedNode(int data) {
        this.data = data;
    }

    /**
     * 获取数据
     *
     * @return 数据值
     */
    public int getData() {
        return this.data;
    }

    /**
     * 设置数据的值
     *
     * @param data 数据
     */
    public void setData(int data) {
        this.data = data;
    }

    /**
     * 获取下一个节点
     *
     * @return 当前节点的下一个几点
     */
    public LinkedNode getNext() {
        return this.next;
    }

    /**
     * 设置下一个节点的值
     *
     * @param next 下一个节点
     */
    public void setNext(LinkedNode next) {
        this.next = next;
    }

    /**
     * 获取链表长度
     *
     * @param head 头节点
     * @return
     */
    public static int getListLength(LinkedNode head) {
        int length = 0;
        LinkedNode node = head;
        while (node != null) {
            length++;
            node = node.next;
        }
        return length;
    }

    /**
     * 缺省位置,直接在最后插入
     *
     * @param head       头节点
     * @param insertNode 插入节点
     * @return 头节点
     */
    public static LinkedNode insertNode(LinkedNode head, LinkedNode insertNode) {
        int size = getListLength(head);
        // return insertNode(head,insertNode,size+1); 修改一下,以便insertNode后面的元素能够全部插入进来。
        int count = 1;
        LinkedNode temp = head;
        if (head == null) {
            return insertNode;
        }
        while (temp != null) {
            if (count == size) {
                temp.next = insertNode;
                temp = null;
            } else {
                temp = temp.next;
                count++;
            }
        }
        return head;
    }

    /**
     * 指定位置插入
     *
     * @param head       头节点
     * @param nodeInsert 插入节点
     * @param position   插入位置,从1开始
     * @return 返回头节点
     */
    public static LinkedNode insertNode(LinkedNode head, LinkedNode nodeInsert, int position) {
        if (head == null) {
            // 如果head == null 表示当前链表为空,可以直接返回当前节点,或者报异常,这里直接把它当作头节点。
            return nodeInsert;
        }
        // 已经存在的元素的个数
        int size = getListLength(head);
        if (position > size + 1 || position < 1) {
            System.out.println("位置参数越界");
            return head;
        }

        // 表头插入
        if (position == 1) {
            nodeInsert.next = head;
            // 这里可以直接 return nodeInsert
            head = nodeInsert;
            return head;
        }

        LinkedNode pNode = head;
        int count = 1;
        // 这里position 被上面的size限制住了,不用考虑pNode = null
        while (count < position - 1) {
            pNode = pNode.next;
            count++;
        }
        nodeInsert.next = pNode.next;
        pNode.next = nodeInsert;
        return head;
    }

    /**
     * 缺省参数的删除最后一个节点
     *
     * @param head 链表头节点
     * @return 返回新链表头节点
     */
    public static LinkedNode deleteNode(LinkedNode head) {
        int size = getListLength(head);
        return deleteNode(head, size);
    }

    /**
     * 根据位置删除节点
     *
     * @param head     链表头节点
     * @param position 位置从1开始,最大链表大小 超出不删除,返回原头节点。
     * @return 新链表头节点
     */
    public static LinkedNode deleteNode(LinkedNode head, int position) {
        if (head == null) {
            // 链表为空,无法删除
            return null;
        }
        int size = getListLength(head);
        if (position > size || position < 1) {
            System.out.println("输入参数有误");
            return head;
        }
        if (position == 1) {
            return head.next;
        } else {
            LinkedNode cur = head;
            int count = 1;
            while (count < position - 1) {
                cur = cur.next;
                count++;
            }
            LinkedNode curNode = cur.next;
            cur.next = curNode.next;
            //上面两行可以简化成 : cur.next = cur.next.next
        }
        return head;
    }

    public static LinkedNode initList(int[] vals) {
        LinkedNode head = null;
        for (int val : vals) {
            head = insertNode(head, new LinkedNode(val));
        }
        return head;
    }

    public static void printLinkedList(LinkedNode head) {
        int count = 0;
        while (head != null) {
            System.out.println("第 " + ++count + " 个:" + head.data);
            head = head.next;
        }
    }

    public static void main(String[] args) {
        LinkedNode head = new LinkedNode(0);
        for (int i = 0; i < 10; i++) {
            head = LinkedNode.insertNode(head, new LinkedNode(i + 1));
        }
        System.out.println("origin:");
        printLinkedList(head);
        head = deleteNode(head, 3);
        System.out.println("delete the third ");
        printLinkedList(head);
        head = deleteNode(head);
        System.out.println("delete the last one");
        printLinkedList(head);
        head = insertNode(head, new LinkedNode(11));
        System.out.println("insert one from last");
        printLinkedList(head);
        head = insertNode(head, new LinkedNode(22222), 1);
        System.out.println("insert to first");
        printLinkedList(head);
    }

}

近期在自学 Java 做项目,加入了一个编程学习圈子,里面有编程学习路线和原创的项目教程,感觉非常不错。还可以 1 对 1 和大厂嘉宾交流答疑,也希望能对大家有帮助,扫 ⬇️ 二维码即可加入。

在这里插入图片描述

也可以点击链接:我正在「编程导航」和朋友们讨论有趣的话题,你⼀起来吧?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1122599.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【超级基础版】十进制与二进制的转换

目录 一、为什么是二进制&#xff1f; 二、二进制的加法和乘法 三、二进制向十进制转换 四、十进制整数向二进制转换 五、十进制小数向二进制小数的转换 六、八进制和十六进制的引入 一、为什么是二进制&#xff1f; 我们知道电脑的数据本质上是0和1&#xff0c;就是我们…

已更新!c++第四章知识点合集(自定义函数的格式和使用方法详解, #include,函数的嵌套 递归,局部变量与全局变量的区别等等)

c知识点合集已经完成欢迎前往主页查看&#xff0c;点点赞点点关注不迷路哦 点我进入c第一章知识点合集 MYSQL知识点持续更新中 MYSQL第一章节DDL数据定义语言的操作----点我进入 MYSQL第二章节DDL-数据库操作语言 DQL-数据查询语言----点我进入 MYSQL-第三章节DCL-管理用户&…

库函数qsort的使用

在排序时&#xff0c;我们通常写的函数只能排一种固定的类型&#xff0c;那有没有一种方法可以用来对所有的数据类型&#xff0c;进行排序呢&#xff1f;库函数中的qsort函数就可以实现这种排序。 首先qsort的函数参数有四个&#xff0c;第一个是数组的起始地址(即数组名)&…

【ML】cheatsheet

LR 原理与面试题目DT, Adaboost, GBDT, xgboost 原理 细节 与 例子 https://www.cnblogs.com/createMoMo/p/12635709.html xgboost挺详细的算法原理与例子 https://zhuanlan.zhihu.com/p/660468945 着重lightgbm就xgboost的改善方向 https://zhuanlan.zhihu.com/p/366952043机器…

什么是卷积神经网络?解决了什么问题?

什么是卷积神经网络&#xff1f; 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;是一种深度神经网络模型&#xff0c;主要用于图像识别、语音识别和自然语言处理等任务。它通过卷积层、池化层和全连接层来实现特征提取和分类。 解决了什么问…

pycharm使用Git拉取最新代码(配置了远程服务器)

首先分享一下如何在pycharm设置代理&#xff08;毕竟pull代码往往是从GitHub上&#xff09;。因为即便本地开启了代理&#xff0c;PyCharm并不会自动使用它。需要在PyCharm的设置中手动配置代理。 下面是在PyCharm中设置代理的步骤&#xff1a; 主菜单中选择File > Settin…

Node学习笔记之MySQL基本使用

使用 SQL 管理数据库 其实写接口简单来说就是操作数据库数据&#xff0c;所以我们需要学会数据库的增、删、查、改等基本操作 1. 什么是 SQL SQL&#xff08;英文全称&#xff1a;Structured Query Language&#xff09;是结构化查询语言&#xff0c;专门用来访问和处理数据…

Kubernetes技术与架构-网络 1

基于OSI网络模型&#xff0c;Kubernetes集群的网络策略包括7层负载均衡的网关路由策略&#xff0c;以及4层3层的网络IP地址策略&#xff0c;这些网络策略是保证Kubernetes集群内Pod之间的网络访问的互联互通&#xff0c;本文主要描述Kubernetes集群的网络策略的基本使用方式。 …

基于nodejs+vue旅行社网站系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Linux笔记之diff和vimdiff

Linux笔记之diff和vimdiff code review! 文章目录 Linux笔记之diff和vimdiff一.diff1.1.使用diff比较文件夹1.2.使用diff比较文件1.4.colordiff——带颜色输出差异 二.vimdiff2.1.vimdiff颜色差异2.2.vimfiff调整栏宽2.3.修改颜色变谈&#xff0c;使代码可以看清楚2.4.vimdif…

[AUTOSAR][诊断管理][ECU][$14] 清除诊断相关信息

文章目录 一、简介(1)应用场景(2)清除DTC原理(3) 请求格式二、示例代码(1) 14_cls_dtc_info.c三、 常见bug大揭秘一、简介 根据ISO14119-1标准中所述,诊断服务14主要用于Client向Server(ECU)请求清除诊断相关信息。 (1)应用场景 一般而言,14诊断服务,主要应用场景…

面向对象(基础)特征一:封装性(encapsulation)

文章目录 一、介绍&#xff08;1&#xff09;封装性&#xff08;2&#xff09;权限修饰符 二、案例&#xff08;1&#xff09;案例1 三、练习&#xff08;1&#xff09;练习1&#xff08;2&#xff09;练习2&#xff08;3&#xff09;练习3&#xff08;4&#xff09;练习4 面向…

【2023年11月第四版教材】软考高项极限冲刺篇笔记(3)

8 成本管理 成本类型:可变成本、固定成本、直接成本、间接成本、机会成本、沉没成本 应急储备:成本基准内 管理成本:成本基准外 进度偏差:SV,SPI 成本管理主要是规划和控制 成本估算 类比估算 参数估算 自上而下估算 三点估算 备选方案分析 储备分析 质量成本 总资…

strstr函数和strtok函数

文章目录 strstr函数函数使用函数模拟实现strtok函数 strstr函数 参数为两个字符串的地址&#xff0c;在str1中找str2不包括结束符。 函数使用 #include<stdio.h> #include<string.h>int main() {char* str1 "abcdeffgmnlo";char* str2 "de"…

《语音优先》智能语音技术驱动的交互界面设计与语音机器人设计(译者序)...

“言为心声,语为心境”&#xff0c;语言与对话是我们沟通与协作的重要方式。而智能语音技术是一种基于人工智能和自然语言处理技术的语音交互技术。它可以通过语音识别技术将用户的语音指令转换为文本&#xff0c;然后通过自然语言处理技术对文本进行分析和理解&#xff0c;最终…

TP-LINK XDR6088 WiFi6路由器 简单开箱评测

TL-XDR6088易展版AX6000双频WiFi6路由器 简单开箱测评&#xff0c;双2.5G网口&#xff0c;双频8流&#xff0c;8颗FEM&#xff0c;支持Docker。 TP-LINK XDR5470 WiFi6路由器 简单开箱评测&#xff1a;https://blog.zeruns.tech/archives/725.html TP-LINK XDR3040 WiFi6路由…

WinMIPS64汇编指令详解

目录 MIPS指令R I J三种格式 MIPS五种寻址方式 立即数寻址 寄存器寻址 基址寻址 PC相对寻址 伪直接寻址 WinMIPS64汇编指令 助记 从内存中加载数据 lb lbu lh lhu lw lwu ld l.d lui 存储数据到内存 sb sh sw sd s.d 算术运算 daddi daddui dadd…

C++笔记之vector的初始化以及assign()方法

C笔记之vector的初始化以及assign()方法 —— 2023年4月15日 上海 code review 文章目录 C笔记之vector的初始化以及assign()方法代码——实践出真知0. 空的vector1. 花括号(initializer_list)——最推荐的初始化方法2. 花括号3. 圆括号花括号4. 圆括号5. 圆括号6. 指针花括号7…

我做不到受每个人喜欢

我做不到受每个人喜欢 我想描述一下昨天发生争吵后我个人的观点&#xff0c;希望能够重新呈现出一种积极的态度。 首先&#xff0c;让我简要梳理一下事件的经过&#xff0c;当天我像往常一样去另一个宿舍找人聊天&#xff0c;可能因为说话声音有点大&#xff0c;坐在我后面的那…

GUI设计——PyQt5快速入门

一、学习目标 了解有关GUI界面设计的基本语法能够编写简单的界面设计程序 二、PyQt5 安装与环境配置 首先&#xff0c;本人通过网上的教程&#xff0c;在Index of / (qt.io)官网上下载好了 Qt Designer 和 Qt Creator 。本人下载的版本为 5.14。随后&#xff0c;通过网络的资源…