题目描述
一个袋子里面有n个球,每个球上面都有一个号码(拥有相同号码的球是无区别的)。如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积。
例如:如果袋子里面的球的号码是{1, 1, 2, 3},这个袋子就是幸运的,
因为1 + 1 + 2 + 3 > 1 * 1 * 2 * 3
你可以适当从袋子里移除一些球(可以移除0个,但是别移除完),要使移除后的袋子是幸运的。现在让你编程计算一下你可以获得的多少种不同的幸运的袋子。
eg:
输入:
3
1 1 1
输出:
2
以下是本篇文章正文内容,下面案例可供参考
解题思路
- 将号码从小到大排序
因为 拥有相同号码的球是无区别的 ,所以要将相同的号码跳过 - 当前号码和其前面的号码不满足幸运条件时,
break
- 当返回上层递归时,需要回溯,再继续计算当前号码和其前面的号码是否满足幸运条件
- 记录满足的种树,返回
代码如下
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
Arrays.sort(arr);//排序
System.out.println(find(arr, 0, 0, 1));
}
}
/**
* 每日一题-幸运的袋子
*
* @param arr 袋子中的号码
* @param index 从index位置遍历
* @param sum 袋子中的号码和
* @param multi 袋子中的号码积
* @return 幸运的种数
*/
private static int find(int[] arr, int index, long sum, int multi) {
int count = 0;
for (int i = index; i < arr.length; i++) {
sum += arr[i];//求和
multi *= arr[i];//求积
if (sum > multi) {
count += 1 + find(arr, i + 1, sum, multi);//继续遍历下一个数
} else if (arr[i] == 1) {//若arr[i]=1,1和任何数的和>1和任何数的积
count += find(arr, i + 1, sum, multi);
} else {
break;//说明不构成幸运,直接break
}
//回溯
sum -= arr[i];
multi /= arr[i];
//因为相同的无区别,跳过重复的号码
while (i < arr.length - 1 && arr[i] == arr[i + 1]) {
i++;
}
}
return count;
}
}
特殊情况
当arr[i]=1时,1和任何数的和>1和任何数的积