2023荣耀校招机试(java&python&C++)组装新的数组
题目
给你一个整数M和数组N,N中的元素为连续整数,要求根据N中的元素组装成新的数组R,组装规则:
- R中元素总和加起来等于M
- R中的元素可以从N中重复选取
- R中的元素最多只能有1个不在N中,且比N中的数字都要小(不能为负数)
备注:
1 ≤ M ≤ 30
1 ≤ N.length ≤ 1000
输入描述
第一行输入是连续数组N,采用空格分隔
第二行输入数字M
输出描述
输出的是组装办法数量,int类型
用例1
输入
2
5
输出
1
说明
只有1种组装办法,就是[2,2,1]
用例2
输入
2 3
5
输出
2
说明
一共两种组装办法,分别是[2,2,1],[2,3]
C++
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
// 定义一个函数,接收一个整数数组和一个目标值m,返回数组中所有小于等于m的元素组合成m的方法数
int getResult(vector<int>& arr, int m) {
// 创建一个新的数组,存储原数组中小于等于m的元素
vector<int> newArr;
for (int val : arr) {
if (val <= m) {
newArr.push_back(val);
}
}
// 找到新数组中最小的元素
int min = *min_element(newArr.begin(), newArr.end());
// 调用dfs函数,从新数组的第0个元素开始,递归地计算所有可能的组合方法数
return dfs(newArr, 0, 0, min, m, 0);
}
// 定义一个递归函数,接收一个整数数组,一个索引值,一个当前和值,一个最小值,一个目标值和一个计数器
int dfs(vector<int>& arr, int index, int sum, int min, int m, int count) {
// 如果当前和大于目标值,则返回计数器
if (sum > m) {
return count;
}
// 如果当前和等于目标值或者当前和与目标值之差小于最小值且大于0,则返回计数器加一
if (sum == m || (m - sum < min && m - sum > 0)) {
return count + 1;
}
// 遍历数组中从索引开始到末尾的所有元素,对每个元素调用dfs函数,并更新计数器
for (int i = index; i < arr.size(); i++) {
count = dfs(arr, i, sum + arr[i], min, m, count);
}
// 返回最终的计数器
return count;
}
int main() {
string line;
// 使用getline函数读取第一行输入作为字符串
getline(cin,line);
// 使用stringstream类将字符串转换为流对象
stringstream ss(line);
// 创建一个整数向量来存储输入的整数
vector<int> arr;
// 使用流提取运算符从流对象中读取每个整数,并将其推入向量中
int num;
while(ss >> num){
arr.push_back(num);
}
// 使用cin读取第二行输入作为整数
cin >> num;
// 调用getResult函数并打印结果
cout << getResult(arr,num) << endl;
}
python
import sys
def dfs(arr, index, sum, min, m, count):
# 递归函数,用于计算所有可能的组合数
if sum > m:
return count # 如果当前和大于目标值,返回当前计数
if sum == m or (m - sum < min and m - sum > 0):
return count + 1 # 如果当前和等于目标值,或者剩余空间小于最小值,返回当前计数加一
for i in range(index, len(arr)):
count = dfs(arr, i, sum + arr[i], min, m, count) # 对每个元素进行递归调用,累加和和计数
return count # 返回最终的计数
def getResult(arr, m):
newArr = []
for val in arr:
if val <= m:
newArr.append(val) # 过滤掉大于目标值的元素
minval = min(newArr) # 找到数组中的最小值
return dfs(newArr, 0, 0, minval, m, 0) # 调用递归函数
line = input() # 输入一行数字,以空格分隔
arr = list(map(int, line.split())) # 将输入转换为整数数组
num = int(input()) # 输入一个整数作为目标值
print(getResult(arr, num)) # 输出结果
JAVA
// 导入必要的包
import java.util.ArrayList;
import java.util.Scanner;
// 定义一个类
public class Main {
// 定义一个函数,接收一个整数数组列表和一个目标值m,返回数组中所有小于等于m的元素组合成m的方法数
public static int getResult(ArrayList<Integer> arr, int m) {
// 创建一个新的数组列表,存储原数组中小于等于m的元素
ArrayList<Integer> newArr = new ArrayList<>();
for (int val : arr) {
if (val <= m) {
newArr.add(val);
}
}
// 找到新数组中最小的元素
int min = Integer.MAX_VALUE;
for (int val : newArr) {
if (val < min) {
min = val;
}
}
// 调用dfs函数,从新数组的第0个元素开始,递归地计算所有可能的组合方法数
return dfs(newArr, 0, 0, min, m, 0);
}
// 定义一个递归函数,接收一个整数数组列表,一个索引值,一个当前和值,一个最小值,一个目标值和一个计数器
public static int dfs(ArrayList<Integer> arr, int index, int sum, int min, int m,
int count) {
// 如果当前和大于目标值,则返回计数器
if (sum > m) {
return count;
}
// 如果当前和等于目标值或者当前和与目标值之差小于最小值且大于0,则返回计数器加一
if (sum == m || (m - sum < min && m - sum > 0)) {
return count + 1;
}
// 遍历数组中从索引开始到末尾的所有元素,对每个元素调用dfs函数,并更新计数器
for (int i = index; i < arr.size(); i++) {
count = dfs(arr, i, sum + arr.get(i), min, m, count);
}
// 返回最终的计数器
return count;
}
public static void main(String[] args) {
String line;
// 使用Scanner类读取第一行输入作为字符串
Scanner sc = new Scanner(System.in);
line = sc.nextLine();
// 使用split方法将字符串按空格分割为字符串数组,并转换为整数数组列表
String[] strArr = line.split(" ");
ArrayList<Integer> arr = new ArrayList<>();
for (String s : strArr) {
arr.add(Integer.parseInt(s));
}
// 使用nextInt方法读取第二行输入作为整数,并关闭Scanner对象
int num = sc.nextInt();
sc.close();
// 调用getResult函数并打印结果
System.out.println(getResult(arr,num));
}
}