【LeetCode Hot100 双指针】移动零、盛最多水的容器、三数之和、接雨水

双指针

    • 1. 移动零
      • 题目描述
      • 解题思路
        • 关键思路:
        • 步骤:
        • 时间复杂度:
        • 空间复杂度:
      • 代码实现
    • 2. 盛最多水的容器
      • 题目解析
      • 解题思路
      • 代码实现
    • 3. 三数之和
      • 问题描述:
      • 解题思路:
      • 算法步骤:
      • 代码实现:
    • 4. 接雨水
      • 问题描述:
      • 解题思路:
      • 算法步骤:
      • 代码实现:

1. 移动零

题目描述

给定一个数组 nums,编写一个方法,将所有零元素移动到数组的末尾,同时保持非零元素的相对顺序不变。必须 原地 修改数组,且不能使用额外的数组。

解题思路

此问题要求将数组中的所有零元素移动到末尾,保持非零元素的相对顺序不变,并且必须在原数组上修改。常规的做法可能会用两个临时数组,但这里需要在 O(1) 空间复杂度下完成任务。因此,我们需要设计一个在原数组上操作的解法。

关键思路:

我们可以使用 双指针法 来解决该问题:

  1. 指针 p 用于遍历数组中的元素,用来指向需要替换的位置(即当前非零元素应该放的位置)。
  2. 指针 q 用于遍历数组中的元素,指向当前正在检查的元素。
步骤:
  1. 初始化两个指针 pq

    • p 指向当前可以插入非零元素的位置。
    • q 用来遍历整个数组,检查每一个元素。
  2. 遍历数组:

    • nums[p] 为零时:
      • 如果 nums[q] 也为零,直接跳过 q,继续检查下一个元素。
      • 如果 nums[q] 为非零元素,交换 nums[p]nums[q],将非零元素移到前面,同时将 pq 向后移动。
    • nums[p] 不是零时,直接将 p 向后移动,继续检查下一个位置。
  3. 结束条件:q 遍历完数组时,操作结束。

时间复杂度:
  • 单遍历数组,时间复杂度为 O(n),其中 n 是数组的长度。
空间复杂度:
  • 使用了常数空间,仅使用了两个指针,空间复杂度为 O(1)。

代码实现

class Solution {public void moveZeroes(int[] nums) {int p = 0, q = 1;while (q < nums.length) {if (nums[p] == 0) {while (q < nums.length - 1 && nums[q] == 0) {q++;}nums[p] = nums[q];nums[q] = 0;} p++;q++;}}
}

2. 盛最多水的容器

题目解析

题目要求我们在一个给定的整数数组 height[] 中,找到两条垂直线所构成的容器的最大面积。两条线的 x 轴坐标为数组中的两个元素位置,而容器的高度则是由这两个位置的较短的线决定的。

我们可以利用 双指针法 来解决这个问题,这样可以在一次遍历中找到最大面积,且时间复杂度为 O(n)。

解题思路

  1. 定义两个指针

    • 初始化两个指针 pq,分别指向数组的两端。即 p = 0q = height.length - 1
  2. 计算面积

    • 在每一步中,我们计算当前两条垂直线之间的面积,面积的计算公式为:
      area = ( q − p ) × min ⁡ ( height[p] , height[q] ) \text{area} = (\text{q} - \text{p}) \times \min(\text{height[p]}, \text{height[q]}) area=(qp)×min(height[p],height[q])
    • q - p 是两条线之间的宽度,min(height[p], height[q]) 是这两条线所能组成的容器的高度。
  3. 移动指针

    • 为了找到可能的最大面积,我们需要移动其中较短的线来尝试提高容器的高度。我们移动短板的指针,若 height[p] < height[q],则 p++;否则,q--。通过这种方式,我们不断调整指针,寻找可能的最大面积。
  4. 结束条件

    • pq 相遇时,所有可能的组合都已经检查过,我们返回最大面积。
  5. 为什么移动短板

    • 面积是由短板来决定的,如果选择移动长板保留短板,那么移动后的面积不可能比移动前的更大了。 假设移动长板后得到的新板长度比之前的短板长,那么容器的高度仍然是短板的长度,而宽度减小了;如果移动长板后得到的新板长度比之前的短板短,那么面积就更小了。

代码实现

class Solution {public int maxArea(int[] height) {int p = 0, q = height.length - 1;  // 初始化指针int result = 0;  // 用来存储最大面积while (p < q) {int area = (q - p) * Math.min(height[p], height[q]);  // 计算当前的面积result = Math.max(result, area);  // 更新最大面积// 移动短板if (height[p] < height[q]) {p++;  // 如果左边的高度小,移动左指针} else {q--;  // 如果右边的高度小,移动右指针}}return result;  // 返回最大面积}
}

3. 三数之和

问题描述:

给定一个整数数组 nums,找出所有和为零的三元组,要求不重复地返回结果。

解题思路:

这个问题要求在数组中找到所有和为零的三元组,并且不允许返回重复的三元组。考虑到以下几点:

  1. 排序:首先,我们可以将数组 nums 进行排序,这样可以更方便地处理重复元素并使用双指针方法进行优化。
  2. 去重:由于数组可能包含重复的元素,我们需要跳过重复的三元组。可以通过跳过相同的元素来避免重复结果。
  3. 双指针:对于每个固定的 i,我们使用双指针 jk 来遍历剩余的数组,寻找和为零的元素。这样可以有效地减少时间复杂度。
  4. 优化:通过判断最小的三个数和最大的两个数的和的情况,提前排除无解的情况,减少不必要的计算。

算法步骤:

  1. 排序数组:对 nums 数组进行排序。
  2. 遍历数组:用一个 i 来遍历数组,确保 nums[i] 是固定的。
  3. 使用双指针:对于每一个固定的 i,使用两个指针 jk 来遍历数组中的元素,查找 nums[i] + nums[j] + nums[k] == 0 的三元组。
  4. 跳过重复元素:跳过重复的元素,以避免返回重复的三元组。
  5. 优化判断:通过判断数组中最小和最大的元素的和来减少不必要的计算。

代码实现:

class Solution {public List<List<Integer>> threeSum(int[] nums) {// 先把数组变成有序的数组Arrays.sort(nums);List<List<Integer>> ans = new ArrayList<>();int n = nums.length;// 最后留两个位置给 j 和 kfor (int i = 0; i < n - 2; i++) {if (i > 0 && nums[i] == nums[i - 1]) {// 如果和上一个数值相同就跳过,避免重复continue;}int j = i + 1;int k = n - 1;// 优化 1: 最小的三个数加和 > 0 就说明没有 j, k 加一起能 = 0,都 > 0if (nums[i] + nums[i + 1] + nums[i + 2] > 0) break;// 优化 2:nums[i] 和两个最大的数相加都 < 0,说明当前 i 和后面的任意 j, k 相加都 < 0if (nums[i] + nums[n - 1] + nums[n - 2] < 0) continue;while (j < k) {int s = nums[i] + nums[j] + nums[k];if (s == 0) {List<Integer> list = new ArrayList<>();list.add(nums[i]);list.add(nums[j]);list.add(nums[k]);ans.add(list);j++;// 避免重复while (j < k && nums[j] == nums[j - 1]) {j++;}k--;// 避免重复while (k > j && nums[k] == nums[k + 1]) {k--;}} else if (s > 0) {k--;} else {j++;}}}return ans;}
}

4. 接雨水

问题描述:

给定一个整数数组 height,其中每个元素代表一个柱子的高度。请计算能够接住多少个雨水。

解题思路:

此问题是经典的“接雨水”问题。我们需要计算每个位置能接住的雨水量。对于每个位置,能接住的雨水量取决于该位置的左边和右边的最大高度。因此,我们可以将问题转化为以下步骤:

  1. 计算每个位置的左边最大高度:对于数组中的每个位置 i,我们可以记录从左到右遍历时,当前位置左边的最大高度。这样可以确定该位置上方能够容纳多少水。
  2. 计算每个位置的右边最大高度:对于数组中的每个位置 i,我们可以记录从右到左遍历时,当前位置右边的最大高度。同样,这也帮助我们计算该位置上方能容纳多少水。
  3. 计算每个位置的水量:每个位置的水量由当前高度、左边最大高度和右边最大高度共同决定。具体来说,当前位置能容纳的水量为:Math.min(left_max, right_max) - height[i]

算法步骤:

  1. 创建两个数组 pre_maxsuf_max:分别记录每个位置的左边最大高度和右边最大高度。
  2. 计算左边最大高度:从左到右遍历,更新 pre_max[i] 为当前位置 i 及其左边所有位置的最大高度。
  3. 计算右边最大高度:从右到左遍历,更新 suf_max[i] 为当前位置 i 及其右边所有位置的最大高度。
  4. 计算接住的雨水:对于每个位置 i,水量为 Math.min(pre_max[i], suf_max[i]) - height[i],然后将水量累加得到总水量。

代码实现:

class Solution {public int trap(int[] height) {int ans = 0;int n = height.length;int[] pre_max = new int[n];int[] suf_max = new int[n];// 计算左边最大高度pre_max[0] = height[0];for (int i = 1; i < n; i++) {pre_max[i] = Math.max(pre_max[i-1], height[i]);}// 计算右边最大高度suf_max[n-1] = height[n-1];for (int i = n-2; i >= 0; i--) {suf_max[i] = Math.max(suf_max[i+1], height[i]);}// 计算每个位置的水量for (int i = 0; i < n; i++) {ans += Math.min(pre_max[i], suf_max[i]) - height[i];}return ans;}
}

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

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

相关文章

python-leetcode 28.两数相加

题目&#xff1a; 给定两个非空链表&#xff0c;表示两个非负整数&#xff0c;它们每位数字都是按照逆序地方式存储&#xff0c;并且每个节点只能存储一位数字。请将两数相加&#xff0c;并以相同的形式返回一个表示和的链表。 输入&#xff1a;l1 [2,4,3], l2 [5,6,4] 输出…

3.3 学习UVM中的uvm_driver 类分为几步?

文章目录 前言1. 定义2. 核心功能3. 适用场景4. 使用方法5. 完整代码示例5.1 事务类定义5.2 Driver 类定义5.3 Sequencer 类定义5.4 测试平台 6. 代码说明7. 总结 前言 以下是关于 UVM 中 uvm_driver 的详细解释、核心功能、适用场景、使用方法以及一个完整的代码示例&#xff…

【云安全】云原生- K8S API Server 未授权访问

API Server 是 Kubernetes 集群的核心管理接口&#xff0c;所有资源请求和操作都通过 kube-apiserver 提供的 API 进行处理。默认情况下&#xff0c;API Server 会监听两个端口&#xff1a;8080 和 6443。如果配置不当&#xff0c;可能会导致未授权访问的安全风险。 8080 端口…

微信小程序配置3 配置sass

1. 在config。json文件里面的setting配置“sass” 2. 改你需要的页面后缀名为scss。 3.查看页面即可看到样式。

XML DOM

XML DOM XML DOM(Document Object Model)是一种用于访问和操作XML文档的标准方式。它提供了一种树形结构来表示XML文档,使得开发者能够方便地对XML数据进行读取、修改和操作。本文将详细介绍XML DOM的基本概念、结构、操作方法以及应用场景。 一、XML DOM的基本概念 XML …

[概率论] 随机变量

Kolmogorov 定义的随机变量是基于测度论和实变函数的。这是因为随机变量的概念需要精确地定义其可能的取值、发生的概率以及这些事件之间的依赖关系。 测度论&#xff1a;在数学中&#xff0c;测度论是用来研究集合大小的理论&#xff0c;特别是无穷可数集和无界集的大小。对于…

16.React学习笔记.React更新机制

一. 发生更新的时机以及顺序## image.png props/state改变render函数重新执行产生新的VDOM树新旧DOM树进行diff计算出差异进行更新更新到真实的DOM 二. React更新流程## React将最好的O(n^3)的tree比较算法优化为O(n)。 同层节点之间相互比较&#xff0c;不跨节点。不同类型的节…

基于 openEuler 构建 LVS-DR 群集

1、环境准备 准备好下面四台台服务器&#xff1a; 主机名IP角色openEuler-1192.168.121.11Director ServeropenEuler-2192.168.121.12Real Server1openEuler-3192.168.121.13Real Server2Rocky8192.168.121.51Client 2、Web服务器配置 在两台RS上安装并配置nginx服务&#…

凸包算法—— cad c#二次开发

效果如下&#xff1a; 代码如下&#xff1a; using IfoxDemo; //[assembly: CommandClass(typeof(IFoxDemo.凸包class))]//只允许此类快捷键命令 namespace IFoxDemo {public class 凸包class{public static class 凸包助手{/// <summary>/// 计算点集的凸包并返回多段线…

ctfshow-36D杯

ctfshow-36D杯 给你shell ($obj[secret] ! $flag_md5 ) ? haveFun($flag) : echo "here is your webshell: $shell_path"; 这是个弱比较&#xff0c;输入?give_me_shell前三个是0说明二进制小于1000000就是ASCII的64&#xff0c; 0-32是不可见或非打印字符&…

Linux ARM64 将内核虚拟地址转化为物理地址

文章目录 前言一、通用方案1.1 kern_addr_valid1.2 __pa 二、ARM64架构2.1 AT S1E1R2.2 is_kernel_addr_vaild2.3 va2pa_helper 三、demo演示参考资料 前言 本文介绍一种通用的将内核虚拟地址转化为物理地址的方案以及一种适用于ARM64 将内核虚拟地址转化为物理地址的方案&…

单例模式和单例Bean

单例模式 定义&#xff1a;单例模式是一种软件设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。 实现方式 饿汉式&#xff1a;在类加载时就立即创建单例实例&#xff0c;线程安全&#xff0c;调用效率高&#xff0c;但可能会造成…

全排列(力扣46)

这道题让我们求这个集合有多少种排列方式&#xff0c;那么与之前组合问题的不同就在于要考虑元素之间的顺序了&#xff0c;所以每一层递归的or循环的起始值无需变量控制&#xff0c;都从0开始。但是一个排列中不能出现相同元素&#xff0c;所以别忘了去重&#xff0c;这里的去重…

本地部署DeepSeek集成VSCode创建自己的AI助手

文章目录 安装Ollama和CodeGPT安装Ollama安装CodeGPT 下载并配置DeepSeek模型下载聊天模型&#xff08;deepseek-r1:1.5b&#xff09;下载自动补全模型&#xff08;deepseek-coder:1.3b&#xff09; 使用DeepSeek进行编程辅助配置CodeGPT使用DeepSeek模型开始使用AI助手 ✍️相…

云原生AI Agent应用安全防护方案最佳实践(上)

当下&#xff0c;AI Agent代理是一种全新的构建动态和复杂业务场景工作流的方式&#xff0c;利用大语言模型&#xff08;LLM&#xff09;作为推理引擎。这些Agent代理应用能够将复杂的自然语言查询任务分解为多个可执行步骤&#xff0c;并结合迭代反馈循环和自省机制&#xff0…

解锁云电脑爽玩TGA游戏,ToDesk、海马云等多款云电脑游戏横测

作为一名游戏爱好者&#xff0c;我深入研究了云电脑技术在游戏娱乐中的应用。通过对比传统游戏机与云电脑的成本效益&#xff0c;我发现云电脑以其低成本和灵活性脱颖而出。我以自身为例&#xff0c;分析了云电脑如何满足对游戏体验的高要求。在测评中&#xff0c;我选择了ToDe…

【Android开发】安卓手机APP使用机器学习进行QR二维码识别

前言:本项目是一个 Android 平台的二维码扫描应用,具备二维码扫描和信息展示功能。借助 AndroidX CameraX 库实现相机的预览、图像捕获与分析,使用 Google ML Kit 进行二维码识别。为方便大家了解项目全貌,以下将介绍项目核心代码文件 MainActivity.java 和 AndroidManifes…

uniapp中对于文件和文件夹的处理,内存的查询

目录 移动文件到指定文件夹 新增本地文件夹 设定本地文件过期时间&#xff0c;清除超时文件&#xff0c;释放内存 操作本地文件之----删除 uniapp获取设备剩余存储空间的方法 读取本地文件夹下的文件 移动文件到指定文件夹 function moveTempFile(tempFilePath, targetFo…

qt widget和qml界面集成到一起

将 Qt Widgets 和 QML 界面集成在一起可以利用 QQuickWidget 或 QQuickView。以下是基本步骤: 使用 QQuickWidget 创建 Qt Widgets 项目: 创建一个基于 Widgets 的应用程序。添加 QQuickWidget: 在你的窗口或布局中添加 QQuickWidget。 例如,可以在 QMainWindow 中使用: …

HTML之JavaScript使用JSON

HTML之JavaScript使用JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。JSON是JavaScript对象的字符串表示法&#xff0c;它使用文本表示一个js对象的信息&#xff0c;可以将json字符串转换…