首页 > 其他分享 >花费最大金额-数组

花费最大金额-数组

时间:2023-11-02 12:34:09浏览次数:35  
标签:arr target 花费 int 金额 pc 枚举 数组

题目:双十一众多商品进行打折销售,小明想购买自己心仪的一些物品,但由于受购买资金限制,所以他决定从众多心仪商品中购买三件,而且想尽可能的花完资金,现在请你设计一个程序帮助小明计算尽可能花费的最大资金数额。

输入描述

输入第一行为一维整型数组M,数组长度小于100,数组元素记录单个商品的价格,单个商品价格小于1000。
输入第二行为购买资金的额度R,R小于100000。

输出描述

输出为满足上述条件的最大花费额度。
注意:如果不存在满足上述条件的商品,请返回-1。

示例

输入:
23,26,36,27
78
输出:
76
说明:
金额23、26和27相加得到76,而且最接近且小于输入金额78
输入:
23,20,40
26
输出:
-1
说明:
因为输入的商品,无法组合出来满足三件之和小于26.故返回-1

`

public class 最大花费金额 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String[] strings = sc.nextLine().split(",");
        int[] arr = Arrays.stream(strings).mapToInt(Integer::parseInt).toArray();
        int limit = sc.nextInt();
        Arrays.sort(arr);
        //处理并排序
        //格式正确,无需考虑小于3个的情况
        int result = -1;
        //计算,双指针,固定左边两个数,遍历下一个数
        for (int i = 0; i < arr.length - 2; i++) {
            for (int j = i + 2; j < arr.length; j++) {
                int curResult = arr[i] + arr[i + 1] + arr[j];
                if (curResult > limit) {
            //因为排好序了,所以如果已经超出,则继续外层循环
                    break;
                } else {
                    result = Math.max(curResult, result);
                }
            }
        }
        System.out.println(result);
    }
}

`
思路与算法

题目要求找到与目标值target 最接近的三元组,这里的「最接近」即为差值的绝对值最小。我们可以考虑直接使用三重循环枚举三元组,找出与目标值最接近的作为答案,时间复杂度为 O(N3)。然而本题的N最大为1000,会超出时间限制。

那么如何进行优化呢?我们首先考虑枚举第一个元素 a,对于剩下的两个元素 b 和 c,我们希望它们的和最接近target−a。对于 b 和 c,如果它们在原数组中枚举的范围(既包括下标的范围,也包括元素值的范围)没有任何规律可言,那么我们还是只能使用两重循环来枚举所有的可能情况。因此,我们可以考虑对整个数组进行升序排序,这样一来:

假设数组的长度为 n,我们先枚举 a,它在数组中的位置为 i;

为了防止重复枚举,我们在位置[i+1,n) 的范围内枚举 b 和 c。

当我们知道了 b 和 c 可以枚举的下标范围,并且知道这一范围对应的数组元素是有序(升序)的,那么我们是否可以对枚举的过程进行优化呢?

答案是可以的。借助双指针,我们就可以对枚举的过程进行优化。我们用 pb和 pc分别表示指向 b 和 c 的指针,初始时,pb指向位置 i+1,即左边界;pc指向位置 n−1,即右边界。在每一步枚举的过程中,我们用 a+b+c 来更新答案,并且:

如果 a+b+c≥target,那么就将 pc向左移动一个位置;

如果 a+b+c<target,那么就将 pb向右移动一个位置。

这是为什么呢?我们对 a+b+c≥target的情况进行一个详细的分析:

如果 a+b+c≥target,并且我们知道 pb到 pc这个范围内的所有数是按照升序排序的,那么如果 pc不变而 pb向右移动,那么 a+b+c的值就会不断地增加,显然就不会成为最接近 target\的值了。因此,我们可以知道在固定了 pc的情况下,此时的 pb就可以得到一个最接近 target的值,那么我们以后就不用再考虑 pc了,就可以将 pc向左移动一个位置。

同样地,在 a+b+c<target时:如果 a+b+c<target并且我们知道 pb到 pc这个范围内的所有数是按照升序排序的,那么如果 pb不变而 pc向左移动,那么 a+b+c的值就会不断地减小,显然就不会成为最接近 target的值了。因此,我们可以知道在固定了 pb的情况下,此时的 pc就可以得到一个最接近 target的值,那么我们以后就不用再考虑 pb了,就可以将 pb向右移动一个位置。实际上,pb和 pc就表示了我们当前可以选择的数的范围,而每一次枚举的过程中,我们尝试边界上的两个元素,根据它们与 target的值的关系,选择「抛弃」左边界的元素还是右边界的元素,从而减少了枚举的范围。
小优化
本题也有一些可以减少运行时间(但不会减少时间复杂度)的小优化。当我们枚举到恰好等于 target的 a+b+c时,可以直接返回 target作为答案,因为不会有再比这个更接近的值了。
当我们枚举 a,b,c中任意元素并移动指针时,可以直接将其移动到下一个与这次枚举到的不相同的元素,减少枚举的次数。

作者:力扣官方题解
链接:https://leetcode.cn/problems/3sum-closest/solutions/301382/zui-jie-jin-de-san-shu-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:arr,target,花费,int,金额,pc,枚举,数组
From: https://www.cnblogs.com/xiaoyezilei/p/17805130.html

相关文章

  • 力扣2610. 转换二维数组(哈希表)
    给你一个整数数组 nums 。请你创建一个满足以下条件的二维数组:二维数组应该 只 包含数组 nums 中的元素。二维数组中的每一行都包含 不同 的整数。二维数组的行数应尽可能 少 。返回结果数组。如果存在多种答案,则返回其中任何一种。请注意,二维数组的每一行上可以......
  • java语言基础数组,方法,类相关知识点的梳理总结
     Java是一种强大的面向对象编程语言,具有丰富的语法和功能。以下是Java语言的一些基础知识点的总结:数组(Arrays):数组是一种用于存储相同数据类型元素的数据结构。声明数组:int[]numbers=newint[5];,这创建了一个包含5个整数的数组。访问数组元素:intfirstNumber=......
  • 后缀数组
    后缀数组以前学了,虽然写了板子,但是好像没学懂,所以重学一遍,随便做了几道板题。定义\(sa_i\):排名第\(i\)的后缀是哪一个。\(rk_i\):第\(i\)个后缀的排名。做法主要是倍增,每一个后缀初始长度为\(1\),然后倍增长度扩展,维护每一轮的排序结果。让一个长度为\(2^i\)的串被......
  • app支付金额为100,但是前端却显示50,这种情况是怎么回事呢?该如何处理?
    app支付金额为100,但是前端却显示50,这种情况是怎么回事呢?该如何处理?1、可能是服务端没有正常响应返回数据导致的问题--前端发起请求到服务端后没有正常响应返回响应数据,导致回显金额跟实际支付金额不一致;2、可能是前端展示的问题--前端正常请求了,服务端也正常响应返回数据了,包括......
  • js 判断数组对象中是否含有重复的值
    //判断对象数组是否有相同属性相同:true\不相同:falsehasFun(array){returnarray.some((item,index)=>{return(array.findIndex((v,i)=>{return(i!==index&&JSON.stringify(v.item......
  • 88. 合并两个有序数组
    描述给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为......
  • 代码 测试用例 测试用例 测试结果 26. 删除有序数组中的重复项
    给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通......
  • 如何将内容添加到数组中?
    内容来自DOChttps://q.houxu6.top/?s=如何将内容添加到数组中?在JavaScript中,如何将一个对象(如字符串或数字)添加到数组中?使用Array.prototype.push方法将值添加到数组的末尾://初始化数组vararr=["Hi","Hello","Bonjour"];//在数组末尾添加新值arr.push(......
  • c# 将十进制数字转换成字节数组
    //将十进制数字转换成字节数组//由数字创建字节数组publicstaticbyte[]DecimalToByteArray(decimalsrc){//创建内存流MemoryStream,stream作为存放二进制数据的缓存using(MemoryStreamstream=newMemoryStream())......
  • 无涯教程-C语言 - 数组(Array)
    数组是一种数据结构,可以存储相同类型的元素的固定大小的顺序集合。所有数组均包含连续的内存位置,最低地址对应于第一个元素,最高地址对应于最后一个元素。声明数组要在C中声明数组,程序员可以指定元素的类型和数组所需的元素数量,如下所示-typearrayName[arraySize];这称为......