算法练习-链表(二)

news2024/9/23 17:16:33

算法练习-链表(二)

文章目录

  • 算法练习-链表(二)
    • 1. 奇偶链表
      • 1.1 题目
      • 1.2 题解
    • 2. K 个一组翻转链表
      • 2.1 题目
      • 2.2 题解
    • 3. 剑指 Offer 22. 链表中倒数第k个节点
      • 3.1 题目
      • 3.2 题解
        • 3.2.1 解法1
        • 3.2.2 解法2
    • 4. 删除链表的倒数第 N 个结点
      • 4.1 题目
      • 4.2 题解
        • 4.2.1 解法1
        • 4.2.2 解法2
    • 5. 相交链表
      • 5.1 题目
      • 5.2 题解
    • 6. 环形链表
      • 6.1 题目
      • 6.2 题解

1. 奇偶链表

链接:https://leetcode.cn/problems/odd-even-linked-list

1.1 题目

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。

请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。

你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。

示例 1:

请添加图片描述

输入: head = [1,2,3,4,5]
输出: [1,3,5,2,4]
示例 2:

请添加图片描述

输入: head = [2,1,3,5,6,4,7]
输出: [2,3,6,7,1,5,4]

1.2 题解

创建两个链表,分别存储奇链表和偶链表,最后进行连接

由于没有新创建节点进行插入,所以满足题目空间复杂度O(1)的要求

/**
 * 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 oddEvenList(ListNode head) {
        ListNode newHead1 = new ListNode();
        ListNode newHead2 = new ListNode();
        ListNode tail1 = newHead1;
        ListNode tail2 = newHead2;
        if (head == null) {
            return null;
        }
        int count = 1;
        ListNode p = head;
        while (p != null) {
            ListNode tmp = p.next;
            if (count % 2 == 1) {
                p.next = null;
                tail1.next = p;
                tail1 = tail1.next;
            } else {
                p.next = null;
                tail2.next = p;
                tail2 = tail2.next;
            }
            count++;
            p = tmp;
        }
        tail1.next = newHead2.next;
        return newHead1.next;
    }
}

2. K 个一组翻转链表

链接:https://leetcode.cn/problems/reverse-nodes-in-k-group

2.1 题目

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

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

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:

请添加图片描述

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
示例 2:

请添加图片描述

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

2.2 题解

创建一个新的头节点,将反转后的链表接入头节点,只需考虑细节方面的问题

/**
 * 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) {
        ListNode newHead = new ListNode();
        ListNode tail = newHead;

        ListNode p = head;
        while (p != null) {
            int count = 0;
            ListNode q = p;

            while (q != null) {
                count++;
                if (count == k) {
                    break;
                }
                q = q.next;
            }
            
            if (q == null) {
                tail.next = p;
                return newHead.next;
            } else {
                ListNode tmp = q.next;
                ListNode[] nodes = reverse(p, q);
                tail.next = nodes[0];
                tail = nodes[1];
                p = tmp;
            }
        }
        return newHead.next;
    }

    public ListNode[] reverse(ListNode head, ListNode tail) {
        ListNode pre = null;
        ListNode cur = head;
        while (cur != tail) {
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        tail.next = pre;

        return new ListNode[]{tail, head};
    }
}

3. 剑指 Offer 22. 链表中倒数第k个节点

链接:https://leetcode.cn/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof

3.1 题目

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2.

返回链表 4->5.

3.2 题解

3.2.1 解法1

先遍历链表,找出链表长度n,然后找正数第 n - k + 1 个节点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode newHead = new ListNode();
        newHead.next = head;
        ListNode p = newHead;
        int num = 0;
        while (p.next != null) {
            p = p.next;
            num++;
        }
        int n = num - k ;
        while(n != 0) {
            head = head.next;
            n--;
        }
        return head;
    }
}

3.2.2 解法2

先让快指针走到第k的位置,然后快慢指针一起移动

当快指针走到头,慢指针所在的位置为倒数第k个节点

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode fast = head;
        ListNode slow = head;
        int count = 0;
        while (fast != null) {
            count++;
            if (count == n) {
                break;
            }
            fast = fast.next;
        }
        if (fast == null) {
            return null;
        }
        fast = fast.next;

        while (fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
}

4. 删除链表的倒数第 N 个结点

链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list

4.1 题目

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

请添加图片描述

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:

输入:head = [1], n = 1
输出:[]
示例 3:

输入:head = [1,2], n = 1
输出:[1]

4.2 题解

所有方法同3,只是增加了删除操作

4.2.1 解法1

/**
 * 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 removeNthFromEnd(ListNode head, int n) {
        ListNode newHead = new ListNode();
        newHead.next = head;
        ListNode p = newHead;
        int m = 0;
        while (p.next != null) {
            p = p.next;
            m++;
        }
        p = newHead;
        int num = m - n;
        while (num != 0) {
            p = p.next;
            num--;
        }
        p.next = p.next.next;
        return newHead.next;
    }
}

4.2.2 解法2

/**
 * 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 removeNthFromEnd(ListNode head, int n) {
        ListNode fast = head;
        ListNode slow = head;
        int count = 0;
        while (fast != null) {
            count++;
            if (count == n) {
                break;
            }
            fast = fast.next;
        }
        if (fast == null) {
            return head;
        }
        ListNode pre = null;

        while (fast.next != null) {
            pre = slow;
            slow = slow.next;
            fast = fast.next;
        }

        if (pre == null) {
            head = head.next;
        } else {
            pre.next = slow.next;
        }
        return head;
    }
}

5. 相交链表

链接:https://leetcode.cn/problems/intersection-of-two-linked-lists

5.1 题目

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:

请添加图片描述

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
listA - 第一个链表
listB - 第二个链表
skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。

示例 1:

请添加图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

示例 2:
请添加图片描述

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at ‘2’
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [1,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:

请添加图片描述

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

5.2 题解

两指针分别从两个链表头遍历,到达链表结尾之后,转移到另一个链表的表头

如果两个指针相遇,则两链表相交

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode newHeadA = new ListNode();
        ListNode newHeadB = new ListNode();
        newHeadA.next = headA;
        newHeadB.next = headB;
        ListNode p = newHeadA;
        ListNode q = newHeadB;
        int a = 0;
        int b = 0;
        while (p.next != q.next && a != 2 && b != 2) {
            if (p.next == null) {
                p = newHeadB;
                a++;
            } else {
                p = p.next;
            }
            if (q.next == null) {
                q = newHeadA;
                b++; 
            } else {
                q = q.next;
            }
        }
        if (a == 2 || b == 2) {
            return null;
        }
        return p.next;
    }
}

6. 环形链表

链接:https://leetcode.cn/problems/linked-list-cycle

6.1 题目

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例 1:

请添加图片描述

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:

请添加图片描述

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:

请添加图片描述

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

6.2 题解

快慢指针,如果两指针可以相遇,则该链表尾环形链表

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode newHead = new ListNode();
        newHead.next = head;
        ListNode low = newHead;
        ListNode fast = newHead;
        while (fast != null && fast.next != null) {
            low = low.next;
            fast = fast.next.next; 
            if (fast == low) {
                return true;
            }
        }
        return false;
    }
}

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

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

相关文章

中国智能物流行业市场规模及未来发展趋势

中国智能物流行业市场规模及未来发展趋势编辑中国智能物流行业市场规模正在快速增长。随着电子商务、物流配送、物联网等行业的发展,物流行业需求不断提高,智能物流产品应运而生。智能物流行业主要通过智能化管理、智能路径规划、智能定位、物流配送等方…

Java特性之设计模式【工厂模式】

一、工厂模式 概述 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通…

投票需要什么流程微信投票互助平台的免费投票平台搭建

“最美家政人”网络评选投票_免费小程序投票推广_小程序投票平台好处手机互联网给所有人都带来不同程度的便利,而微信已经成为国民的系统级别的应用。现在很多人都会在微信群或朋友圈里转发投票,对于运营及推广来说找一个合适的投票小程序能够提高工作效…

Java-集合(5)

Map接口 JDK8 Map接口实现子类的特点 Map和Collection是并列关系,Map用于保存具有映射关系的数据:Key-ValueMap中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中Map中的key不允许重复,原因和HashSet一样Map…

2023年美赛MCM 问题C:预测Wordle结果 ​

目录2023年美赛MCM 问题C: 预测Wordle结果 ​1. 背景2. 要求3. 附件1. 数据文件。2. 纽约时报网站上发布的 Wordle 指南4. 参考2023年美赛MCM 问题C: 预测Wordle结果 ​ 1. 背景 Wordle 是纽约时报目前每天提供的流行拼图。 玩家尝试通过在六次或更少的尝试中猜测一个五个字母…

记录一次Binder内存相关的问题导致APP被杀的BUG排查过程

事情的起因的QA压测过程发生进程号变更,怀疑APP被杀掉过,于是开始看日志 APP的压测平台会上报进程号变更时间点,发现是在临晨12:20分,先大概确定在哪个日志文件去找关键信息一开始怀疑是crash,然后就在日志…

shiro CVE-2020-1957

0x00 前言 在之前只是单纯的复现了漏洞&#xff0c;没有记笔记&#xff0c;所以补充了这篇分析笔记。 影响版本&#xff1a;shiro < 1.5.2 0x01 环境搭建 环境用的是&#xff1a;https://github.com/lenve/javaboy-code-samples/tree/master/shiro/shiro-basic 0x02 漏…

用python实现对AES加密的视频数据流解密

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法。 在做网络爬虫的时候,会遇到经过AES加密的数据,可以使用python来进行解密。 在做爬虫的时候,通常可以找到一个key,这个key是一个十六进制的一串字符,这传字符是解密的关键。所以对于…

SpringBoot2.X整合ClickHouse项目实战-从零搭建整合(三)

一、ClickHouseSpringBoot2.XMybatisPlus整合搭建 二、需求描述和数据库准备 三、ClickHouse统计SQL编写实战和函数使用 四、ClickHouseSpringBoot2.X案例-基础模块搭建 controller/request层 mapper层 model层 service层 五、ClickHouseSpringBoot2.X案例-数据统计接口 …

城市轨道交通供电系统研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…

一文告诉你什么是财务数据治理?

大家好&#xff0c;我是梦想家Alex&#xff0c;今天是周末&#xff0c;就不给大家分享技术文了&#xff5e;应出版社老师推荐&#xff0c;文末给大家送几本DAMA中国主席力荐&#xff0c;20位行业专家历时2年共同打造的《财务数据治理实战》&#xff0c;将数据治理理论应用于财务…

怎样查询PMP成绩?

【如何查询成绩】1、输入网址&#xff08;PMI官网&#xff0c;不知道网址的私戳&#xff09;&#xff0c;点击 Log In如果忘记 PMI 的账号和密码了&#xff0c;怎么办&#xff1f;可以在你报名机构官网的个人中心的学习中心的我的报名处查看 PMI 的注册名和密码2、点击 Exam An…

CMake 入门学习4 软件包管理

CMake 入门学习4 软件包管理一、Linux下的软件包管理1. 检索已安装的软件包2. 让自己编译软件支持pkg-config搜索3. 在CMakeLists查找已安装的软件包二、适合Windows下的包管理工具1. vcpkg2. Conan(1) 安装Conan(2) 配置Conan(3) 创建工程(4) 安装依赖库(5) 使用依赖库三、CMa…

汉字----dgfont

Abstract 字符生成是一个具有挑战性的问题,特别是对于一些由大量字符组成的书写系统,近年来受到了广泛的关注。然而,现有的字体生成方法通常是在监督学习中。它们需要大量的配对数据,这是劳动密集型和昂贵的收集。此外,常见的图像到图像转换模型通常将风格定义为纹理和颜…

golang入门笔记——内存管理

文章目录自动内存管理概念自动内存管理-相关概念&#xff1a;追踪垃圾回收&#xff1a;分代GC&#xff08;Generational GC&#xff09;引用计数内存分配Go内存分配-分块Go内存分配——多级缓存Go内存管理优化Balanced GC自动内存管理 概念 1.动态内存 程序在运行时根据需求…

大数据全系安装

内容版本号CentOS7.6.1810ZooKeeper3.4.6Hadoop2.9.1HBase1.2.0MySQL5.6.51HIVE2.3.7Sqoop1.4.6flume1.9.0kafka2.8.1scala2.12davinci3.0.1spark2.4.8flink1.13.5 1. 下载CentOS 7镜像 CentOS官网 2. 安装CentOS 7系统——采用虚拟机方式 2.1 新建虚拟机 2.2.1 [依次选择]-&…

SPI通讯简介

一、基本概念 SPI是串行外设接口(Serial Peripheral Interface)的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;主要应用在EEPROM,FLASH,实时时钟&#xff0c;AD转换器&#xff0c;多MCU间通讯等等&#xff0c;SPI端口可以在多主器件…

从业6年,对敏捷和自动化测试的一点心得

不久前&#xff0c;参加Thoughtworks组织的一场自动化测试的分享&#xff0c;同事由于出差国外不能参加&#xff0c;特意嘱托我提问两个问题&#xff1a; 在互联网这个将“敏捷”与“持续集成”进行积极实践的环境里&#xff0c;“敏捷测试”与“自动化测试”成了一个大家经常…

【数据库数据乱码错误】存进去的数据乱码(???)

目录 1.当我新增一条数据的时候&#xff0c;成功后查看数据库中的数据时&#xff0c;竟然变成&#xff1f;&#xff1f;&#xff1f;乱码格式了&#xff1a; 2.那么问题有3处需要注意&#xff1a; 第一&#xff1a;settings配置 第二&#xff1a;POM文件 第三&#xff1a;…

JavaWeb8-线程安全问题

目录 1.概念 1.1.单线程 1.2.多线程 2.导致线程不安全的5个因素 ①抢占式执行&#xff08;首要原因&#xff09; ②多个线程同时修改了同一个变量 ③非原子性操作 ④内存可见性 ⑤指令重排序 线程优点&#xff1a;加速程序性能。线程缺点&#xff1a;存在安全问题。 1…