题意整理
- 给定1-9共9个数字,a数组记录了每个数字的价格。
- 牛牛手上有n元钱,为了凑出最大的数字带回家,问牛牛应该怎么买,并返回最大的数字。
方法一(贪心)
1.解题思路
- 首先计算最便宜的数字是多少。
- 然后根据最便宜的数字,得到最多买多少个数字,以及买了之后,剩余多少钱。因为要凑出最大的数字,所以数字个数应尽可能多。
- 先假设买的全是最便宜的数字,如果某个数字比最便宜数字大,并且可以用剩余的钱来补,则将当前数字替换为这个较大的数字。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 得到牛牛能够凑到的最大的数字 * @param n int整型 牛牛能够承受的价格 * @param a int整型一维数组 1-9这九个数字的价格数组 * @return string字符串 */ public String buyNumber (int n, int[] a) { //求最便宜的数字是多少 int num=1; for(int i=2;i<=9;i++){ if(a[i-1]<a[num-1]){ num=i; } } //如果最便宜的都买不起,直接返回-1 if(n<a[num-1]) return "-1"; //cnt带回的数字的最大个数,remain是剩余的钱 int cnt=n/a[num-1]; int remain=n%a[num-1]; //初始化可变字符串 StringBuilder sb=new StringBuilder(); for(int i=9;i>=num;i--){ //如果剩余的钱可以换更大的数字,则换取更大的数字 while(remain>=a[i-1]-a[num-1]&&cnt>0){ sb.append(i); cnt--; remain-=a[i-1]-a[num-1]; } } return sb.toString(); } }
3.复杂度分析
- 时间复杂度:假设最小的数字是num,最多添加个数字到可变字符串,所以时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。
方法二(贪心+排序)
1.解题思路
- 首先计算最便宜的数字是多少。
- 然后只要剩余的钱大于最便宜的数字,说明可以继续买。先确定当前最长长度,只要大于等于最长长度,则可以选更大的数字,将最后确定的数字添加到可变字符串,并扣掉对应的花费。
- 将得到的字符串转化为字符数组,并排序,反转之后即是最大的组合。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 得到牛牛能够凑到的最大的数字 * @param n int整型 牛牛能够承受的价格 * @param a int整型一维数组 1-9这九个数字的价格数组 * @return string字符串 */ public String buyNumber (int n, int[] a) { //求最便宜的数字是多少 int num=1; for(int i=2;i<=9;i++){ if(a[i-1]<a[num-1]){ num=i; } } //如果最便宜的都买不起,直接返回-1 if(n<a[num-1]) return "-1"; StringBuilder sb=new StringBuilder(); while(n>=a[num-1]){ int maxLen=0; int curNum=-1; //寻找满足当前长度最大,并且当前数字最大对应的curNum for(int i=1;i<=9;i++){ if(n/a[i-1]>=maxLen){ maxLen=n/a[i-1]; curNum=i; } } //添加到sb sb.append(curNum); n-=a[curNum-1]; } //转化为字符数组,并排序 char[] arr=sb.toString().toCharArray(); Arrays.sort(arr); //再转化为可变字符串,并反转,得到最大的数字 StringBuilder res=new StringBuilder(); res.append(arr); return res.reverse().toString(); } }
3.复杂度分析
- 时间复杂度:假设最小的数字是num,最多添加个数字到可变字符串,对应排序的时间复杂度为,所以最终的时间复杂度为。
- 空间复杂度:不需要额外长度为的arr字符数组,所以空间复杂度为。