优选算法的灵动之章:双指针专题(一)

news/2025/2/27 8:46:31

个人主页:手握风云

专栏:算法

目录

一、双指针算法思想

二、算法题精讲

2.1. 查找总价格为目标值的两个商品

2.2. 盛最多水的容器

​编辑

2.3. 移动零

2.4. 有效的三角形个数


一、双指针算法思想

        双指针算法主要用于处理数组、链表等线性数据结构中的问题。它通过设置两个指针,在数据结构上进行遍历和操作,从而实现高效解决问题。

二、算法题精讲

2.1. 查找总价格为目标值的两个商品

       我们优先想到的是暴力解法:利用两层for循环来检验两个数的和是否为目标值。那么此时的时间复杂度为O(n^{2})

java">class Solution {
    public int[] twoSum(int[] price, int target) {
        int len = price.length;
        for(int i=0;i<len;i++){
            for(int j=i+1;j<len;j++){
                if(price[i]+price[j] == target){
                    return new int[]{price[i],price[j]};
                }
            }
        }
        return new int[0];
    }
}

       但题目当中给出数组是按照升序排列的,那么我们就可以利用单调性定义左右两个指针来遍历数组。我们先定义一个sum变量,sum的值等于左右指针所指的值之和。然后通过sum与target的比较,如果sum小于target,则左指针向右移动;如果sum大于target,则右指针向左移动;如果sum等于target,则返回两个数。

完整代码实现:

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

2.2. 盛最多水的容器

       首先,我们得明白如何计算容器的体积,容器的底就可以用两个数组的下标相减得到,容器的高根据木桶效应是数组中最小的元素。我们先选左右边界来作为容器,此时我们记容器体积为v1,如果left指针向右移动,则容器的底一定在减小,如果遇到比左边界小的数,那么高就会减小,如果遇到比左边界大的数,那么高不变。所以容器的体积一定是在减小。此时我们就可以把左边界干掉,left向右移动,得到新的容器体积v2,根据上面的逻辑,我们同理可以把右边界干掉。以此类推,直到找出最大的容器体积。

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

2.3. 移动零

        本题要求在不复制数组的情况下原地对数组进行操作。我们先定义cur和dest两个指针,cur指针的作用是先扫描数组,将数组分为已处理和待处理的两个区间,dest指针是将已处理的区间变为非零区间和零区间。当cur遇到零元素时,不做任何处理,直接让cur向右移动一位;当cur遇到非零元素时,先让dest向右移动一位,再让两个指针所指向的值进行交换。直到cur遍历完整个数组

  

完整代码实现:

java">public class Solution {
    public void moveZeroes(int[] nums){
        for (int cur = 0,dest = -1; cur < nums.length; cur++) {
            if(nums[cur] != 0){
                dest++;
                int temp = nums[cur];
                nums[cur] = nums[dest];
                nums[dest] = temp;
            }
        }
    }
}

2.4. 有效的三角形个数

        要找到有效的三角形个数,就是在数组中找到能够构成三角形的三元子数组。我们首先想到的暴力解法,利用三层for循环来查找,此时的时间复杂度为O(n^{3})

        对于三条边的比较,我们只需要让三角形较小的两条边之和与最大的边进行比较即可。,要想得到最大值,首先我们可以先对数组进行一个排序,使数组呈升序排列。排序之后,先固定右侧的最大值,在定义left和right两个指针,让right指针指向被固定值的左侧。如果两个元素之和大于最大值,那么left指针向右移动,两个元素之和一定会大于最大值,此时我们就可以干掉右指针所指向的数;如果两个元素之和小于等于最大值,那么right指针向左移动,两个元素之和一定会小于等于最大值,此时我们就可以干掉左指针所指向的数。完成之后,我们就可以将固定值向左移动,在进行上述操作,直到固定数组的第三个元素。

完整代码实现:

java">class Solution {
    public int triangleNumber(int[] nums) {
        Arrays.sort(nums);//排序,优化
        int ret = 0,len = nums.length;
        for (int i = len-1; i >= 2; i--) {//先固定最大的数
            int left = 0,right = i-1;
            while(left < right){
                if(nums[left] + nums[right] > nums[i]){
                    ret += right - left;
                    right--;
                }else{
                    left++;
                }
            }
        }
        return ret;
    }
}

http://www.niftyadmin.cn/n/5869822.html

相关文章

【Keil5教程及技巧】耗时一周精心整理万字全网最全Keil5(MDK-ARM)功能详细介绍【建议收藏-细细品尝】

&#x1f48c; 所属专栏&#xff1a;【单片机开发软件技巧】 &#x1f600; 作  者&#xff1a; 于晓超 &#x1f680; 个人简介&#xff1a;嵌入式工程师&#xff0c;专注嵌入式领域基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大家&#xff1…

计算机视觉(opencv-python)入门之常见图像预处理操作(待补充)

图像预处理是计算机视觉任务中的关键步骤&#xff0c;它通过对原始图像进行处理&#xff0c;以提高后续图像分析、特征提取和识别的准确性。 示例图片 常见图像预处理方法 灰度化处理 法一 #灰度化处理 #法1&#xff0c;直接读取灰度图 import cv2 gray_imagecv2.imread(te…

天猫代运营公司推荐:品融电商

天猫代运营公司推荐&#xff1a;品融电商 在电商行业竞争日益激烈的今天&#xff0c;选择一家专业的天猫代运营公司成为众多品牌商家提升市场竞争力、实现销售增长的关键。在众多代运营公司中&#xff0c;品融电商凭借其专业的团队、丰富的经验和显著的成功案例&#xff0c;脱…

Docker usage on ubuntu

1. Transfer docker image to another machine # save image in machine A $ docker save -o myDockerImage.tar myDockerImage.tar:latest # copy myDockerImage.tar to another machine and load $ docker load -i myDockerImage.tar # check via $ docker images

6 - 预处理器

文章目录 一、宏1、宏定义 - 空格问题2、宏调用 二、宏不是函数 一、宏 1、宏定义 - 空格问题 #define f (x) ((x) - 1) /* error */ #define f(x) ((x) - 1) /* ok */2、宏调用 printf("f(3): %d, f (3): %d\n", f(3), f (3));二、宏不是函数 更新 ing

期权帮|股指期货基差和价差有什么区别?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 股指期货基差和价差有什么区别&#xff1f; 一、股指期货基差 股指期货基差是指股指期货价格与其对应的现货指数价格之间的差额。 股指期货基差计算公式&#xff1a;基差 现…

第75节 绘制圆形(arc)

在 HarmonyOS 开发中&#xff0c;如果你使用的是 TypeScript (TS) 语法&#xff0c;并且你正在处理画布&#xff08; Canvas &#xff09;相关的功能&#xff0c; arc 和 arcTo 是两个用于绘制弧线的 Canvas API 方法。下面是如何在 HarmonyOS 中使用这两个方法的详细说…

Uniapp 从入门到精通:动画与过渡效果的运用

Uniapp 从入门到精通:动画与过渡效果的运用 前言一、引言1.1 Uniapp 简介1.2 动画与过渡效果的重要性二、Uniapp 基础回顾2.1 开发环境搭建2.2 基础语法与组件三、动画与过渡效果基础3.1 CSS 动画基础3.2 Vue 过渡效果四、Uniapp 中的动画与过渡效果高级应用4.1 使用 uni.crea…