力扣热门算法题 128. 最长连续序列,134. 加油站,143. 重排链表

128. 最长连续序列,134. 加油站,143. 重排链表,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.26 可通过leetcode所有测试用例。

目录

128. 最长连续序列

解题思路

完整代码

Python

Java

134. 加油站

解题思路

完整代码

Python

Java

143. 重排链表

解题思路

完整代码

Python

Java


128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

解题思路

要在 O(n) 的时间复杂度内解决这个问题,我们可以使用哈希表来存储数组中的每个数字,以便快速判断一个数字是否存在于数组中。接下来,我们可以遍历数组,并对每个元素执行以下步骤:

  1. 检查当前数字是否是序列的开始:对于数组中的每个数字,检查其减一的结果是否也在数组中。如果不在,说明当前数字是一个序列的开始。

  2. 探索序列:从当前序列的开始数字出发,不断增加 1,探索序列的长度,同时在哈希表中查找增加后的数字是否存在。

  3. 更新最大长度:在探索过程中,不断更新找到的最长序列的长度。

  4. 返回最大长度:遍历结束后,返回找到的最长序列的长度。

这种方法之所以有效,是因为它确保每个数字最多被探索两次:一次是作为其他数字的后续部分,一次是作为序列的开始。因此,总的时间复杂度仍然保持在 O(n)。

完整代码

Python
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        num_set = set(nums)
        longest_streak = 0

        for num in num_set:
            # 只有当 num - 1 不在集合中时,才考虑以 num 为起点,这样可以避免重复
            if num - 1 not in num_set:
                current_num = num
                current_streak = 1

                # 探索当前序列
                while current_num + 1 in num_set:
                    current_num += 1
                    current_streak += 1

                # 更新最大长度
                longest_streak = max(longest_streak, current_streak)

        return longest_streak
Java
class Solution {
public int longestConsecutive(int[] nums) {
    Set<Integer> num_set = new HashSet<Integer>();
    for (int num : nums) {
        num_set.add(num);
    }

    int longestStreak = 0;

    for (int num : num_set) {
        // 只有当 num - 1 不在集合中时,才考虑以 num 为起点
        if (!num_set.contains(num-1)) {
            int currentNum = num;
            int currentStreak = 1;

            // 探索当前序列
            while (num_set.contains(currentNum+1)) {
                currentNum += 1;
                currentStreak += 1;
            }

            // 更新最大长度
            longestStreak = Math.max(longestStreak, currentStreak);
        }
    }

    return longestStreak;
}

}

134. 加油站

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gas 和 cost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

示例 1:

输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

示例 2:

输入: gas = [2,3,4], cost = [3,4,3]
输出: -1
解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。

解题思路

要解决这个问题,我们可以遵循以下的思路:

  1. 总体判断:如果总的汽油量小于总的消耗量,那么无法绕环路行驶一周。这是因为,不论从哪里出发,汽油总是不够用的。

  2. 寻找起始位置:如果总的汽油量大于或等于总的消耗量,那么一定存在一个起始位置可以绕环路一周。我们可以从头开始遍历加油站,尝试每个加油站作为起点,并计算从该起点开始绕环路的过程中的累积净汽油量(当前加油站的汽油量减去到下一个加油站的消耗量)。如果在某个点累积净汽油量变为负数,说明不能从当前起点绕一周,需要尝试下一个加油站作为新的起点,并重置累积净汽油量。

  3. 维护当前净汽油量和总净汽油量:在遍历过程中,我们维护一个当前净汽油量来判断是否能从当前加油站走到下一个加油站。同时,我们也维护一个总净汽油量来判断是否总体上能绕环路一周。

  4. 返回结果:如果找到了可以作为起始点的加油站,返回其索引;如果遍历结束也没有找到,返回 -1。

完整代码

Python
class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        if sum(gas) < sum(cost):
            return -1

        start, total_tank, curr_tank = 0, 0, 0
        for i in range(len(gas)):
            total_tank += gas[i] - cost[i]
            curr_tank += gas[i] - cost[i]
            # 如果当前累积净汽油量小于0,从下一个加油站重新开始
            if curr_tank < 0:
                start = i + 1
                curr_tank = 0

        return start if total_tank >= 0 else -1
Java
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int totalTank = 0;
        int currTank = 0;
        int startingStation = 0;
        for (int i = 0; i < gas.length; i++) {
            totalTank += gas[i] - cost[i];
            currTank += gas[i] - cost[i];
            // 如果当前累积净汽油量小于0,从下一个加油站重新开始
            if (currTank < 0) {
                startingStation = i + 1;
                currTank = 0;
            }
        }
        return totalTank >= 0 ? startingStation : -1;
    }
}

143. 重排链表

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L0 → L1 → … → Ln - 1 → Ln

请将其重新排列后变为:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …

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

示例 1:

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

示例 2:

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

解题思路

  1. 找到链表的中点:使用快慢指针法找到链表的中点。快指针每次移动两步,慢指针每次移动一步,当快指针到达链表末尾时,慢指针将位于链表的中间位置。

  2. 反转链表的后半部分:从中点开始反转链表的后半部分。反转后,链表的后半部分将以逆序的形式出现。

  3. 合并链表的前半部分和反转后的后半部分:将链表的前半部分和反转后的后半部分交替合并,形成最终的链表。

完整代码

Python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reorderList(self, head: Optional[ListNode]) -> None:
        if not head:
            return
        
        # 1. 找到中点
        slow, fast = head, head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        
        # 2. 反转后半部分
        prev, curr = None, slow
        while curr:
            next_temp = curr.next
            curr.next = prev
            prev = curr
            curr = next_temp
        
        # 3. 合并两个链表
        first, second = head, prev
        while second.next:
            first.next, first = second, first.next
            second.next, second = first, second.next
Java
/**
 * 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 void reorderList(ListNode head) {
        if (head == null) return;
        
        // 1. 找到中点
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        
        // 2. 反转后半部分
        ListNode prev = null, curr = slow, temp;
        while (curr != null) {
            temp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = temp;
        }
        
        // 3. 合并两个链表
        ListNode first = head, second = prev;
        while (second.next != null) {
            temp = first.next;
            first.next = second;
            first = temp;
            
            temp = second.next;
            second.next = first;
            second = temp;
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker 部署 FRP 内网穿透 实现端口映射

Frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议&#xff0c;且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 官网地址&#xff1a;https://github.com/fatedier/frp 准备工作…

VS2019连接MySQL

VS2019连接MySQL 下载MySQL Connector/C配置头文件&#xff0c;库文件路径配置头文件路径配置库的路径复制dll文件 MySQL的用户设置将权限赋值给新用户 编写代码往数据库写入 老师布置的作业让我们用VS2019连接MySQL实现一个小型的日志系统&#xff0c;中间踩了很多的坑&#x…

【3】3道链表力扣题:删除链表中的节点、反转链表、判断一个链表是否有环

3道链表力扣题 一、删除链表中的节点&#x1f30f; 题目链接&#x1f4d5; 示例&#x1f340; 分析&#x1f4bb; 代码 二、反转链表&#x1f30f; 题目链接&#x1f4d5; 示例&#x1f340; 分析① 递归② 迭代 三、判断一个链表是否有环&#x1f30f; 题目链接&#x1f4d5; …

文件操作(顺序读写篇)

1. 顺序读写函数一览 函数名功能适用于fgetc字符输入函数所有输入流fputc字符输出函数所有输出流fgets文本行输入函数所有输入流fputs文本行输出函数所有输出流fscanf格式化输入函数所有输入流fprintf格式化输出函数所有输出流fread二进制输入文件fwrite二进制输出文件 上面说…

FPGA----ZCU106的petalinux 2019.1使用USB传输数据

1、实际项目中需要用到开发板的串口进行数据交互&#xff0c;之前讲的几节只是启动了网口&#xff08;如下链接&#xff09;。因此&#xff0c;本次给大家带来的官方自带串口例程的使用方法&#xff0c;本文的vivado工程和下述连接一样&#xff0c;PL端什么配置都没有。 FPGA-…

A Simple Problem with Integers(线段树)

目录 描述 输入 输出 样例输入 样例输出 思路 建树 第一次错误解法&#xff08;正确解法在下面&#xff0c;可跳过这一步&#xff09; 正确解法 code 描述 You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of …

云架构(二) 大使模式

Ambassador pattern &#xff08;https://learn.microsoft.com/en-us/azure/architecture/patterns/ambassador&#xff09; 简单描述 创建一个助手服务&#xff0c;这个服务代表消费服务或者应用程序发送网络请求。大使服务可以看做是与客户机同一个位置的进程外代理。 这种…

如何快速掌握数字化运维方法,构建数字化运维体系?

⛳️ 写在前面参与规则&#xff01;&#xff01;&#xff01; ✅参与方式&#xff1a;关注博主、点赞、收藏、评论&#xff0c;任意评论&#xff08;每人最多评论三次&#xff09; ⛳️本次送书1~4本【取决于阅读量&#xff0c;阅读量越多&#xff0c;送的越多】 主要内容读者…

简单实现企业微信远程打卡教程(永不迟到)

最近玩手游时刚好用到了手机模拟器&#xff0c;就是在电脑上安装一个手机模拟器&#xff0c;然后用电脑来挂机手机游戏 今天我突然有了一个想法&#xff0c;既然这个模拟器就是相当于一个虚拟的手机&#xff0c;那么是不是可以给它装上企业微信&#xff0c;然后让它帮我远程打卡…

vs_BuildTools.exe

Microsoft C Build Tools - Visual Studio vs_BuildTools.exe 安装无反应 无法进入安装界面。 转了一大圈&#xff1a; 最后决定更新系统&#xff0c;解决。 参考链接&#xff1a;执行了最后一步&#xff0c;更新系统&#xff1a; Fix: Faulting Application Path Error o…

详细了解RC4加密算法

一.什么是RC4加密算法 RC4加密算法是一种对称加密算法&#xff1a; 对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法&#xff0c;就是加密密钥能够从解密密钥中推算出来&#xff0c;同时解密密钥也可以从加密密钥中推算出来。而在大多数的对…

gpt-llm-trainer 出炉

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

如果有效的编写 ChatGPT 提示?

1. 明确目标&#xff1a;确定使用 ChatGPT 的目的。无论是创意写作、产生想法还是查找信息&#xff0c;知道你想要什么可以让你更有效地使用这个工具。 2. 具体说明&#xff1a;你的提示越具体&#xff0c;ChatGPT 就越能理解你的需求。例如&#xff0c;你可以要求 ChatGPT…

哔哩哔哩直播姬第三方obs推流使用教程

1 obs studio下载(官方下载较慢) 链接&#xff1a;https://pan.baidu.com/s/1fIKJkieYIta0gG-sX7Cr6g?pwdz7s9 提取码&#xff1a;z7s9 2 打开哔哩哔哩直播姬客户端并登录(pc版) 3 打开obs客户端进行推流(如果推流不成功,可能是驱动的问题,记得更新下驱动) 首先添加播放源 …

在同一个网站上自动下载多个子页面内容

一、问题现象 第一次遇到这样的问题&#xff0c;如下图&#xff1a; 即在同一个网站上下载多个内容时&#xff0c;第一个内容明明已经正常get到了&#xff0c;但开始第二个页面的查询 以后&#xff0c;原来已经查出的内容就找不到了。 二、解决办法 我不知道大家是不是遇到…

暴雨服务器X7740赋能大模型训练

数字经济浪潮愈演愈烈,大模型训练对服务器的要求也越来越高。在此背景下,暴雨信息发布专门为大规模模型训练而设计的全新旗舰GPU服务器—X7740,以卓越的计算性能、高速网络通信能力以及创新的能效表现,有效赋能大模型训练。 X7740 搭载了暴雨信息最新一代的英特尔至强可扩展处理…

基于springboot实现数据库的加解密

项目地址 https://github.com/Chenchicheng/spring-ibatis-encryption 功能说明 支持使用注解的方式目标类进行加解密支持同一个类多个字段分别使用不同的加密方式支持自定义加密方法 本地调试 pull代码到本地&#xff0c;更换application.yml中的数据库用户名和密码&…

ubuntu 安装 cloudcompare(两种方法)

方法一 &#xff1a;从 snap 安装 &#xff08;推荐&#xff09; 安装简单&#xff0c;基本上功能都有&#xff08;读写保存las&#xff0c;pcd&#xff0c;标注等&#xff09; 安装&#xff1a; sudo apt-get update sudo apt install snap sudo snap install cloudcompare…

【c++初阶】类与对象(中)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…

Java知识点重点拓展

1.2 Java语言的特点 Java语言的广泛应用主要得益于它的核心特点&#xff0c;主要包括跨平台性、面向对象特性、安全性等。 特性描述跨平台性Java能够在多种操作系统上运行&#xff0c;这得益于JVM&#xff08;Java虚拟机&#xff09;。只要设备安装了对应的JVM&#xff0c;Jav…