✅创作者:陈书予
🎉个人主页:陈书予的个人主页
🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区
🌟专栏地址: Java华为OD机试真题(2022&2023)
文章目录
- 1. 题目描述
- 2. 输入描述
- 3. 输出描述
- 4. Java算法源码
- 5. 测试
- 6.解题思路![在这里插入图片描述](https://img-blog.csdnimg.cn/f108fb2640c349828939c7df9dc7191d.png)
1. 题目描述
给你一个整数M和数组N,N中的元素为连续整数,要求根据N中的元素组装成新的数组R。
组装规则:
R中元素总和加起来等于M;
R中的元素可以从N中重复选取;
R中的元素最多只能有1个不在N中,且比N中的数字都要小(不能为负数)
2. 输入描述
第一行输入是连续数组N,采用空格分隔;
第二行输入数字M;
3. 输出描述
输出的是组装办法数量,int类型。
补充:
1 <= N.length <= 30
1 <= N.length <= 1000
4. Java算法源码
/**
* 给你一个整数M和数组N
*
* N中的元素为连续整数,要求根据N中的元素组装成新的数组R
*
* 1、R中元素总和加起来等于M
* 2、R中的元素可以从N中重复选取
* 3、R中的元素最多只能有1个不在N中,且比N中的数字都要小(不能为负数)
*/
// 组装办法数量
private static int sum = 0;
private static int min = Integer.MAX_VALUE;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 连续数组N,采用空格分隔
String[] N = sc.nextLine().split(" ");
// 新数组R数字之和 = 数字M
int M = sc.nextInt();
// 数组N
int[] arr = new int[N.length];
for (int i = 0; i < N.length; i++) {
arr[i] = Integer.parseInt(N[i]);
// 取数组N的最小值
min = Math.min(min, arr[i]);
}
get(0, arr, M, 0);
System.out.println(sum);
}
/**
*
* @param idx
* @param n 连续数组N,采用空格分隔
* @param M 新数组R数字之和 = 数字M
* @param rSum 新数组R数字之和
*/
public static void get(int idx, int[] n, int M, int rSum) {
if (rSum == M) {
sum++;
return;
}
if (rSum > M) {
return;
}
/**
* R中的元素最多只能有1个不在N中,且比N中的数字都要小
*
* 新数组R数字之和 - 当前新数组R数字之和 <= 取数组N的最小值
*/
if (M - rSum <= min - 1) {
sum++;
return;
}
for (int i = idx; i < n.length; i++) {
get(i, n, M, rSum + n[i]);
}
}
5. 测试
6.解题思路
- 读取输入的连续数组
N
和数字M
。 - 将连续数组
N
转换为整数数组arr
。 - 初始化变量
sum
表示组装办法数量,初始值为 0。 - 初始化变量
min
表示数组N
中的最小值,初始值为正无穷大。 - 遍历数组
N
,将每个元素转换为整数,并更新min
的值为数组N
的最小值。 - 调用递归函数
get(0, arr, M, 0)
,计算组装办法数量。 - 在递归函数
get
中,如果当前新数组R
的数字之和等于M
,则将sum
加 1。 - 如果当前新数组
R
的数字之和大于M
,则返回。 - 如果
M - rSum <= min - 1
,表示剩余的数字和已经小于等于min - 1
,则将sum
加 1,并返回。 - 否则,从当前索引
idx
开始遍历数组N
,递归调用get
函数,更新索引idx
和新数组R
的数字之和rSum
。 - 最后,输出组装办法数量
sum
。