双指针算法专题

embedded/2025/1/12 16:05:40/

目录

1. 移动零

1.1 算法原理

1.2 算法代码 

2. 复写零

2.1 算法原理 

 2.2 算法代码

3. 快乐数

3.1 算法原理

3.2 算法代码

4. 盛水最多的容器

4.1 算法原理

 

4.2 算法代码

5. 有效三角形的个数

5.1 算法原理

5.2 算法代码

6. 剑指 offer:和为 s 的两个数(原)

6.1 算法原理

6.2 算法代码


1. 移动零

283. 移动零 - 力扣(LeetCode)

1.1 算法原理

双指针:

  1. cur: 从左向右扫描数组
  2. dest: 非 0 数据的最后一个位置

划分区间: [0, dest] = 非 0  [dest + 1, cur - 1] => 0  [cur, n - 1] 待处理

情况处理:

  1. nums[cur] == 0, cur++
  2. nums[cur] != 0, swap(++dest, cur)

1.2 算法代码 

class Solution {public void moveZeroes(int[] nums) {// [0, dest] => 非 0// [dest + 1, cur - 1] => 0// [cur, n - 1] => 未处理int dest = -1, cur = 0, n = nums.length;while(cur < n) {if(nums[cur] != 0) swap(nums, ++dest, cur);cur++;}}void swap(int[] nums, int x, int y) {int t = nums[x];nums[x] = nums[y];nums[y] = t;} 
}

2. 复写零

1089. 复写零 - 力扣(LeetCode)

2.1 算法原理 

核心: 双指针 => 从后往前完成复写操作

  • 找到最后一个要复写的数(位置) => 双指针

cur: 最后一个要复写的数  dest: 最后一个进行复写的位置
1.1 判断一下 cur 位置的值
1.2 决定 dest 往后走几步
    1.2.1 arr[cur] != 0 --> dest += 1
    1.2.2 arr[cur] == 0 --> dest += 2
1.3 判断 dest 是否已经到结束位置(dest >= n - 1 时, 结束)
1.4 if(dest 没有结束) cur++; 
      else break;

  • 根据 cur 位置的值, 从后(dest 位置)往前进行复写零操作

    2.1 若 cur 非零, arr[dest--] = arr[cur--]
    2.2 若 cur 为零, arr[dest] = arr[dest - 1] = arr[cur--], dest -= 2;

 2.2 算法代码

class Solution {public void duplicateZeros(int[] arr) {// cur -> 当前位置 // dest -> 最后一个要复写的位置int cur = 0, dest = -1, n = arr.length;while(dest < n - 1) {if(arr[cur] == 0) dest += 2;else dest += 1;if(dest >= n - 1) break;cur++;}// 处理边界情况if(dest >= n) {arr[n - 1] = 0;dest -= 2;cur--;}// 从后往前, 完成复写操作while(cur >= 0) {if(arr[cur] == 0) {arr[dest] = arr[dest - 1] = 0;dest -= 2;}else {arr[dest] = arr[cur];dest -= 1;}cur--;}}
}

3. 快乐数

202. 快乐数 - 力扣(LeetCode)

3.1 算法原理

解法: 快慢双指针

问题转换: 链表是否带环

  1. 定义快慢双指针
  2. 快指针每次移动两步
  3. 慢指针每次移动一步
  4. 由题意得, 两个指针一定会相遇
  5. 若相遇时值为 1, 则为快乐数.

3.2 算法代码

class Solution {public boolean isHappy(int n) {// 初始化 => 保证 slow 和 fast 初始时不相等int slow = n, fast = f(n);// 快慢双指针 => 是否带环while(slow != fast) {slow = f(slow);fast = f(f(fast));}return slow == 1;}// 对 n 的每个 bit 位进行平方求和操作public int f(int n) {int ret = 0;while(n != 0) {ret += Math.pow(n % 10, 2);n /= 10;}return ret;}
}

4. 盛水最多的容器

11. 盛最多水的容器 - 力扣(LeetCode)

4.1 算法原理

  1. 解法一: 暴力枚举 --> O(N^2) 超时
  2. 解法二: 利用单调性 --> O(N)

解法二过程: 

1. 定义 left 和 right 指针, 分别指向数组的头和尾
2. 若 arr[left] < arr[right] 则 left++;
    若 arr[right] < arr[left] 则 right--;
(因为指针一旦进行移动, 宽必定减小, 
所以向内枚举时, 要保留值("高")更大的指针, 仅移动值("高")更小的指针)

4.2 算法代码

class Solution {public int maxArea(int[] height) {int n = height.length;int ret = 0, left = 0, right = n - 1;while(left != right) {ret = Math.max((right - left) * Math.min(height[right], height[left]), ret);if(height[left] < height[right]) left++;else right--;}return ret;}
}

5. 有效三角形的个数

611. 有效三角形的个数 - 力扣(LeetCode)

5.1 算法原理

核心: 对数组排序后, 使用双指针, 对暴力解法进行优化

  1. 对数组进行排序
  2. 固定最大的数
  3. 利用双指针, 在最大数的左区间中, 快速选出可以组成三角形的个数

5.2 算法代码

class Solution {public int triangleNumber(int[] nums) {Arrays.sort(nums);int n = nums.length, ret = 0;for(int i = n - 1; i >= 2; i--) {int right = i - 1, left = 0;while(right != left) {if(nums[left] != 0 && nums[right] + nums[left] > nums[i]) {ret += right - left;right--;}else left++;}}return ret;}
}

6. 剑指 offer:和为 s 的两个数(原)

LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)

6.1 算法原理

给出的数组就是排好序的数组, 直接 right, left 双指针快速定位和为 s 的两个数.

6.2 算法代码

class Solution {public int[] twoSum(int[] price, int target) {int left = 0, right = price.length - 1;while(left != right) {if(price[left] + price[right] > target) right--;else if(price[left] + price[right] < target) left++;else return new int[]{price[left], price[right]};}return price;}
}

END


http://www.ppmy.cn/embedded/153323.html

相关文章

Tableau和PowerBI实现报表数据的下钻

Tableau实现报表数据下钻 用集操作实现树状图的数据下钻&#xff1a;连接数据源后&#xff0c;在类别字段上右键新建集。创建计算字段用于类别表头&#xff0c;将计算字段拖入视图&#xff0c;选中的集内成员显示自身&#xff0c;未被选中的显示加号。基于钻取字段创建下一层的…

基于单片机的指纹密码锁

【摘要】 本设计是一款基于单片机的指纹识别电子密码锁系统。该系统以STC89C52单片机作为模块核心同时结合ZFM-60指纹模块实现录取指纹并存储指纹数据的功能&#xff0c;并且通过HS12864-15C液晶显示比对流程及比对结果&#xff0c;该指纹电子密码锁通过直流继电器与发光二极管…

金山WPS Android面试题及参考答案

说说你所知道的所有集合?并阐述其内部实现。 在 Android 开发(Java 语言基础上)中有多种集合。 首先是 List 集合,主要包括 ArrayList 和 LinkedList。 ArrayList 是基于数组实现的动态数组。它的内部有一个数组来存储元素,当添加元素时,如果数组容量不够,会进行扩容操作…

英文字体:复古八十年代优雅品牌邀请函电影标题设计衬线字体 Eighties Nostalgia Font

嘿&#xff0c;大家好&#xff0c;我希望你们一切顺利&#xff0c;考虑到现在世界上发生的一切&#xff0c;你们在生活的各个方面都取得了进步。过去 3 年对我们所有人来说都是过山车&#xff0c;我一直非常怀念美好的时光。怀旧之情将我带到了 Pinterest&#xff0c;自然而然地…

【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)

【Web安全】SQL 注入攻击技巧详解&#xff1a;UNION 注入&#xff08;UNION SQL Injection&#xff09; 引言 UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集&#xff0c;可以获取数据库中未授权的数据。这种注入技术要…

磁盘满造成业务异常问题排查

最近遇到一个因为磁盘满导致的问题&#xff0c;分享一下&#xff0c;希望能够帮助到以后遇到同样问题的朋友。 早上突然收到业务老师反馈说&#xff1a;上传文件不能正常上传了。 想想之前都好好的&#xff0c;最近又没有更新&#xff0c;为什么突然不能使用了呢&#xff1f;…

STM32U575按键转换及设备驱动

要求通过单片机实现以下功能&#xff1a; 1.单片机有三种工作模式&#xff08;定义全局变量MM表示模式,MM1,2,3表示三种不同的模式&#xff09; LED控制模式风扇控制模式蜂鸣器控制模式 2.可以在某一个模式下通过拓展板KEY1按键控制设备 按键按下一次&#xff0c;设备打开&…

【CSS】HTML页面定位CSS - position 属性 relative 、absolute、fixed 、sticky

目录 relative 相对定位 absolute 绝对定位 fixed 固定定位 sticky 粘性定位 position&#xff1a;relative 、absolute、fixed 、sticky &#xff08;四选一&#xff09; top&#xff1a;距离上面的像素 bottom&#xff1a;距离底部的像素 left&#xff1a;距离左边的像素…