1、题目描述
一个整数可以由连续的自然数之和来表示给定一个整数,计算该整数有几种连续自然数之和的表达式,且打印出每种表达式。
2、输入描述
一个目标整数T(1<=T<=1000)。
3、输出描述
该整数的所有表达式和表达式的个数。如果有多种表达式,输出要求为:
自然数个数最少的表达式优先输出
每个表达式中按自然数递增的顺序输出,具体的格式参见样例。
在每个测试数据结束时,输出一行”Result:X”,其中X是最终的表达式个数。
用例:
输入
100
输出
100=100
100=18+19+20+21+22
100=9+10+11+12+13+14+15+16
3
温馨提示!!!
华为OD机试考试官方会对考生代码查重。华为od机试因为有题库所以有很大的概率抽到原题。如果碰到了题库中的原题,千万不要直接使用题解中的代码,一定要做些修改,比如代码中的变量名,除此之外,代码的组织结构和逻辑也要进行一些改变,所以在日常的刷题中,要提前编写好属于自己的代码。
4、题解
本题可通过回溯法解答,但是当输入的数值较大时会出现超时,另外也可以通过滑动窗口法解决。
代码如下:
回溯法
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = Integer.parseInt(sc.nextLine());
List<List<Integer>> res = new ArrayList<>();
backtrack(num, 0, 0, new ArrayList<>(), res);
Collections.sort(res, ((o1, o2) -> {
if (o1.size() != o2.size()) {
return o1.size() - o2.size();
}else {
return o1.get(0) - o2.get(0);
}
}));
for (List<Integer> item : res) {
StringBuilder sb = new StringBuilder();
sb.append(num).append("=");
for (Integer i : item) {
sb.append(i).append("+");
}
System.out.println(sb.deleteCharAt(sb.length()-1));
}
System.out.println(res.size());
}
private static void backtrack(int num, int tmp, int index, List<Integer> tmps,
List<List<Integer>> res) {
if (tmp == num) {
if (tmps.size() == 1) {
res.add(new ArrayList<>(tmps));
}else {
int step = tmps.get(0);
boolean flag = true;
for (int i=1; i<tmps.size(); i++) {
// 判断数字是否连续
if (tmps.get(i) - step != 1) {
flag = false;
}else {
step = tmps.get(i);
}
}
if (flag) {
res.add(new ArrayList<>(tmps));
}
}
}else {
for (int i=index; i<=num; i++) {
tmp += i;
tmps.add(i);
backtrack(num, tmp, i+1, tmps, res);
tmp -= i;
tmps.remove(tmps.size()-1);
}
}
}
滑动窗口法
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
int[] arr = new int[t];
for (int i = 0; i < t; i++) {
arr[i] = i + 1;
}
// 符合要求的数组集合
List<int[]> arrList = new ArrayList<>();
int left = 0;
int right = 1;
// 计算窗口之和
int sum = arr[left];
// 滑动窗口
while (left < t) {
// 窗口之和大于目标t则left右移
if (sum > t) {
sum -= arr[left++];
} else if (sum == t) {
// 窗口之和等于目标t,则获取到合适窗口
int[] tmpArr = Arrays.copyOfRange(arr, left, right);
arrList.add(tmpArr);
// left指针右移,继续探索新窗口
sum -= arr[left++];
// 若right指针超出范围,跳出循环
if (right >= t) {
break;
}
// right指针右移,继续探索新窗口
sum += arr[right++];
} else {
// 窗口之和小于目标t,right指针右移
sum += arr[right++];
}
}
// 按照自然数个数升序排序
arrList.sort(Comparator.comparingInt(x -> x.length));
// 按照指定格式输出
for (int[] array : arrList) {
StringJoiner stringJoiner = new StringJoiner("+");
for (int i : array) {
stringJoiner.add(String.valueOf(i));
}
System.out.println(t + "=" + stringJoiner);
}
System.out.println(arrList.size());
}
执行结果如下: