首页 > 编程语言 >【Java 优选算法】双指针(下)

【Java 优选算法】双指针(下)

时间:2024-09-17 20:55:30浏览次数:13  
标签:right Java nums int ++ -- 算法 指针 left

欢迎关注个人主页:逸狼


创造不易,可以点点赞吗~

如有错误,欢迎指出~



有效三角形的个数

题目链接

解法

解法1:暴力枚举--->O(n^3)

解法2:利用单调性,使用双指针来解决---->O(n^2)

  1. 优化:对整个数组进行排序
  2. 先固定最大数
  3. 在最大数的左区间内,使用双指针算法,快速统计出符合要求的个数

统计分为两种情况:

  • 能构成三角形的 a+b>c 
  • 不能构成三角形的 a+b<=c 

画图举例

代码

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

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

题目链接

解法

解法一:暴力枚举,时间复杂度:O(n^2)--->超时

解法二:利用单调性,使用双指针算法解决,时间复杂度:O(n)

用sum表示两数相加的值,t表示目标值,无非就三种情况:

  • sum<t  ---->left++
  • sum>t  --->right--
  • sum=t  ---->返回结果

注意:本题一定是有返回结果的,但为了照顾编译器,最后可以随意返回一个数组

画图举例

代码

class Solution {
    public int[] twoSum(int[] price, int target) {
        int sum=0,left=0,right=price.length-1;
        while(left<right){
            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};
    }
}

三数之和

题目链接

解法

解法一:排序+暴力枚举+利用set去重, 时间复杂度:O(n^3)

解法二:排序+双指针

  1. 排序
  2. 固定一个数a
  3. 在该数后面的区间内,利用"双指针算法"快速找到两个数的和等于 -a即可

处理细节问题:

  • 去重
    1. 找到一种结果后,left和right指针要跳过重复的元素,
    2. 当使用完一次双指针算法之后,i也要跳过重复元素(细节1和2都要避免越界)
  • 不漏
    • 找到一种结果之后,不要停,缩小区间,继续寻找

画图举例

代码

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ret=new ArrayList<>();
        int n=nums.length;
        for(int i = 0;i < n;){
            if(nums[i] > 0) break;

            int left=i+1,right =n-1,target=-nums[i];
            
            while(left < right){
                int sum=nums[left]+nums[right];
                if(sum > target) right--;
                else if(sum < target) left++;
                else{
                    ret.add(new ArrayList<Integer>(Arrays.asList(nums[i],nums[left],nums[right])));
                    left++;right--;//缩小区间,继续寻找
                    //left,right去重
                    while(left < right && nums[left] == nums[left-1]) left++;
                    while(left < right && nums[right] == nums[right+1]) right--;
                }
            }
            i++;
            //i去重
            while(i < n && nums[i] ==nums[i-1]) i++;
        }
        return ret;
    }
}

四数之和

题目链接

解法

解法1:排序 + 暴力枚举 + 利用set去重

解法2: 排序 + 双指针(主要利用"三数之和"(上一题)的思路)

  1. 依次固定一个数a;
  2. 在a后面的区间内,利用"三数之和" 找到三个数,是这三个数等于target-a即可
    1. 依次固定一个数b
    2. 在b的后面的区间内,利用双指针找到两个数,是这两个数的和等于target-a-b即可

处理细节:

  • 不重
  • 不漏

画图举例

代码

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> ret = new ArrayList<>();
        int n = nums.length;
        for(int i=0;i<n;){//固定数a
            for(int j=i+1;j<n;){//固定数b
                int left=j+1,right=n-1;
                long aim=(long)target-nums[i]-nums[j];//可能有溢出的风险,所以用long
                while(left<right){
                    int sum = nums[left] + nums[right];
                    if(sum > aim) right--;
                    else if(sum < aim) left++;
                    else{
                        ret.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
                        left++; right--;
                        //left 和 right 去重
                        while(left < right && nums[left] == nums[left-1]) left++;
                        while(left < right && nums[right] == nums[right+1]) right--;
                    } 
                }
                j++;
                //j去重
                while(j<n && nums[j] == nums[j-1]) j++;

            }
            i++;
            //i去重
            while(i<n && nums[i] == nums[i-1]) i++;
        }
        return ret;
    }
}

标签:right,Java,nums,int,++,--,算法,指针,left
From: https://blog.csdn.net/2301_80898480/article/details/142031816

相关文章

  • 代码随想录算法训练营第六十天 | Bellman_ford之判断负权回路
    目录Bellman_ford之判断负权回路思路常规拓展方法一: Bellman_ford-超时方法二:Bellman_ford2方法三:Bellman_ford队列优化Bellman_ford之判断负权回路题目链接:卡码网:95.城市间货物运输II文章讲解:代码随想录 某国为促进城市间经济交流,决定对货物运输提供......
  • Java - 2 变量
    Java-2变量变量是程序的基本组成单位变量的三个基本要素:类型+名称+值声明变量=分配内存先声明,后使用变量在同一个作用域不可以重名数据类型基本数据类型:数值型/字符型(本质是整数)/布尔型引用数据类型:类(class)/接口(interface)/数组([])/*数值型-整数*/......
  • 代码随想录算法训练营第六十天 | Bellman_ford 队列优化算法
    目录Bellman_ford队列优化算法思路模拟过程方法一:Bellman_ford队列优化Bellman_ford队列优化算法题目链接:卡码网:94.城市间货物运输I文章讲解:代码随想录 某国为促进城市间经济交流,决定对货物运输提供补贴。共有n个编号为1到n的城市,通过道路网络连接,......
  • 算法与数据结构——哈希优化策略与算法选择
    哈希优化策略在算法题中,我们通常通过线性查找替换为哈希查找来降低算法的时间复杂度。我们借助一个算法题来加深理解。Question给定一个整数数组nums和一个目标元素target,请在数组中搜索“和”为target的两个元素,并返回他们的数组索引。返回任意一个即可。线性查找:以时间换......
  • JavaScript:对组织值进行排序
    要对组织值进行排序,你可以使用JavaScript中的数组排序方法 sort()。下面是一些示例代码,展示如何对不同类型的组织值进行排序:示例1:对数字数组进行排序constnumbers=[5,2,9,1,5,6];//使用sort()方法进行升序排序numbers.sort((a,b)=>a-b);console.log(n......
  • Java轻量级测试框架的实现与使用 总篇
    Java轻量级测试框架的实现与使用总篇java8,jdk8,测试,assert背景每次写算法题,用例不过总要到本地调试一下,总觉得测试代码写起来又没营养又很麻烦,即便是借助junit测试框架也很麻烦,太重了,写完又觉得测试代码不美观需要删掉。正好在学习spring过程中接触到注解,研究其原理时......
  • 前端JavaScript面试重难点: 闭包+内存泄漏+垃圾回收机制
    前置知识!!!闭包是Javascript语言的一个重难点,也是它的特色,很多高级应用都要依靠闭包来实现。在各种专业文献上学习"闭包"的时候,就一个感觉–“抽象”!特别是学习内存泄漏的时候,没想明白为什么使用闭包的时候不及时清除函数中的元素会导致内存泄漏,直到我的......
  • 代码随想录算法训练营第七天|第454题.四数相加II 383. 赎金信 第15题. 三数之和 第18
    第454题.四数相加II给定四个包含整数的数组列表 A,B,C,D,计算有多少个元组(i,j,k,l) ,使得 A[i]+B[j]+C[k]+D[l]=0。为了使问题简单化,所有的A,B,C,D具有相同的长度 N,且0≤N≤500。所有整数的范围在-2^28到2^28-1之间,最终结果不会超......
  • 代码随想录算法训练营第一天|704二分查找 27移除数组 977.有序数组的平方
    704二分查找给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。示例1:输入:nums=[-1,0,3,5,9,12],target=9输出:4解释:9出现在nums中并且下标为4示例 2:输......
  • Java 如何计算jar包的HASH哈希值
    在做授权系统的时候用到了一个小功能发出来分享一下。全部代码如下:importjava.io.File;importjava.io.FileInputStream;importjava.io.InputStream;importjava.net.URISyntaxException;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmExcepti......