有效三角形个数与和为s的两个数字

五、有效三角形的个数

给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

示例

题目要求返回所有数组中可以组成有效三角形的元素组合。

最简单的解法就是暴力枚举,列出所有组合,记录下可以组成三角形的三元组个数。

示例一的解析给出两次相同组合,说明虽然两个元素值一样,但是下标不一样,也可以算作一组。

直接套三层循环暴力过掉。

代码:

java 复制代码
class Solution {
    public int triangleNumber(int[] nums) {
        int count=0;
        for(int a=0;a<nums.length;a++){
            for(int b=1;b<nums.length;b++){
                for(int c=2;c<nums.length;c++){
                    while(b<=a){
                        b++;
                    }
                    while(c<=b){
                        c++;
                    }
                    if(c>=nums.length){
                        break;
                    }
                    if((nums[a]+nums[b])>nums[c]){
                        if ((nums[a]+nums[c])>nums[b]){
                            if ((nums[b]+nums[c])>nums[a]){
                                count++;
                            }
                        }
                    }
                }
            }
        }
        return count;
    }
}

但是肯定报错,时间复杂度起步 O(n³) ,必然超时。

需要想一个更优解法。

题目说明所有的用例都是非负整数,那就可以给数组先排序,再进行遍历。

乱序数组很难找出规律,而且最主要的原因在于不能移动,因为保证不了移动后的整数大小。

这里用一组暴力解法报错的例子找更优解。

刚才说了,乱序数组无法向不确定大小的位置移动寻找有效三角形,所以先让数组排序。

此时再基于三层循环的思路做优化。

让三个指针分别指向数组左右侧

如果写过盛水最多的容器题目,那应该能想到用指针优化这题。

我们固定 a ,让 b 移动,会发现两种情况。

若是最小的数加上这个区间里最大的数依旧小于等于 C ,那么 a 要向右移。

反之,这个区间里的数都不用算了,全是有效三角形。

完成一次循环后,C 的位置向左移一格,继续寻找有效三角形,直到 C 移到2的位置。

优化后的代码:

java 复制代码
class Solution {
    public int triangleNumber(int[] nums) {
        int count=0;
        Arrays.sort(nums);
        for(int i=nums.length-1;i>=2;i--){
            int left=0,right=i-1;
            while(left<right){
                if(nums[left]+nums[right]>nums[i]){
                    count+=right-left;
                    right--;
                }else{
                    left++;
                }
            }
        }
        return count;
    }
}

六、和为s的两个数字

购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。

这是一道简单题,暴力解法依旧两层循环枚举,同时肯定超时。

代码:

java 复制代码
class Solution {
    public int[] twoSum(int[] price, int target) {
        int[] arr={-1,-1};
        for(int i=0;i<price.length;i++){
            for(int j=1;j<price.length;j++){
                if((price[i]+price[j])==target && price[i]!=price[j]){
                    arr[0]=price[i];
                    arr[1]=price[j];
                }
            }
        }
        return arr;
    }
}

优化解法依旧采用双指针。

由于数组升序排列降低了很多难度,所以不用考虑这么多,直接把指针放在左右两侧。

等到和为 target ,把这两个整数放到一个新数组里返回。

代码:

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

注意一下,如果返回值写在循环体里,外边一定要再给一个返回值,否则编译器会认为可能没有返回值从而报错。

相关推荐
和芯星通unicore3 分钟前
卫星信号消失的地方,定位如何继续?——解密和芯星通DR 航位推算算法
人工智能·算法·gnss·智能驾驶gnss模块
邵奈一40 分钟前
让WorkBuddy用上OpenCode免费模型:Magpie小白教程
算法
人工智能培训1 小时前
边缘AI与大模型轻量化:让智能跑进每一个终端
大数据·人工智能·算法·重构·生活
lengxuenong2 小时前
树状数组 · 信息学学习手册3-优化LIS
c++·学习·算法
动词ing2 小时前
【题目练习】外观数列
算法
余额瞒着我当琳2 小时前
C++11,发展历史浅谈,初始化列表和对象初始化,右值引用和移动语义
java·开发语言·c++·算法
suhan2 小时前
【数据结构】六、图:4.图的遍历(深度优先算法DFS、广度优先算法BFS)
数据结构·算法·排序算法
suhan2 小时前
【数据结构】六、图:3.十字链表、邻接多重表、边集数组
数据结构·算法·排序算法
Dola_Zou2 小时前
工商业储能系统核心策略
算法·自动化·软件工程