首页 > 编程语言 >双指针算法专题

双指针算法专题

时间:2025-01-07 10:28:45浏览次数:3  
标签:arr 专题 cur dest int 算法 right left 指针

目录

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

标签:arr,专题,cur,dest,int,算法,right,left,指针
From: https://blog.csdn.net/2401_83595513/article/details/144415213

相关文章

  • 【复现】基于自适应遗传算法的分布式电源优化配置[IEEE33、IEEE118节点](Matlab代码实
     ......
  • C++学习笔记#01——指针与链表
    在自学C++的时候,发现指针是一个很难绕开的东西,看了一些参考资料和别人的程序,写一些垃圾。Part1指针指针是一个指向一片内存地址的变量,相当于家的门牌号。我们即可以通过变量名来访问一个变量,也可以通过它对应的地址来访问。就像你的老师可以点你的名字找你,也可以找你宿舍的门......
  • 排序算法模板--python版
    在刷算法题时,排序是一个非常常见的操作。Python提供了多种排序算法的实现方式,而在一些经典的算法题中,我们需要手动实现不同的排序算法以符合题目要求。以下是一些常见的排序算法模板,包含了冒泡排序、选择排序、插入排序、快速排序、归并排序和堆排序,这些算法的模板通常会在刷......
  • 关于app签名算法一些问题
    app签名算法相关问题如何修改签名算法1.为什么要修改签名算法?1.生成新的密钥库(KeyStore)和密钥(Key)2.修改签名算法(使用新的签名算法)3.确认签名算法是否生效4.兼容性和注意事项总结如何将SHA256中的1024位密钥改为2048位密钥步骤概览1.生成新的RSA2048位密......
  • java毕业设计-基于springboot+vue的协同过滤推荐算法旅游信息管理平台设计和实现,基于
    博主介绍:✌️码农一枚,专注于大学生项目实战开发、讲解和毕业......
  • 欧拉回路算法
    网络上关于求欧拉回路的线性算法的资料普遍缺少证明。本文将通过分析欧拉回路的性质直接推导出这一算法。算法流程基本的定义可以参考Alex_Wei的博客,本文不再赘述。算法流程部分仅推导求无向图欧拉回路的算法,求有向图欧拉回路的算法的推导过程是类似的,更改一些对应术语即可。......
  • 室内障碍物射线追踪算法matlab模拟仿真
    1.算法运行效果图预览(完整程序运行后无水印)   增加发射点   加入室内墙壁:   同时增加发射点和室内墙壁:   2.算法运行软件版本matlab2022a 3.部分核心程序(完整版代码包含详细中文注释和操作步骤视频)%最终显示射线的间隔,如果配置高泽间隔......
  • 【算法】算法初步
    要学好数据结构和算法的设计与分析,请务必先打好C语言基础,因为C语言中的数据存储、内存映射、指针等等概念最接近计算机的底层原理,数据结构是数据在内存空间当中的组织形式,而算法则是提供了解决某个问题的一种思路,而数据结构与算法设计一定会涉及到最核心的部分:提升性能——......
  • 通过粒子群优化算法(PSO)优化BP神经网络(matlab代码)
    引言在机器学习与人工智能领域,神经网络作为一种强大的计算模型,广泛应用于分类、回归、预测等多种任务。BP神经网络,即反向传播神经网络,以其简单有效的结构和强大的学习能力,成为研究者们关注的焦点。然而,BP神经网络在实际应用中存在一些问题,如容易陷入局部极小值、收敛速度慢等......
  • C语言基础:指针(常量指针和指针常量)
    main函数原型定义:main函数有多种定义格式,main函数也是函数,函数相关的结论对我们main函数也有效(也可以定义main函数的函数指针)main函数的完整写法: intmain(intargc,char*argv[]){} intmian(intargc,char**argv){}扩展写法: main(){}等价intmain(){} intmain......