一、问题描述
题目描述
一个整数可以由连续的自然数之和来表示。
给定一个整数,计算该整数有几种连续自然数之和的表达式,且打印出每种表达式。
输入描述
一个目标整数T (1 <=T<= 1000)
输出描述
该整数的所有表达式和表达式的个数。
如果有多种表达式,输出要求为:自然数个数最少的表达式优先输出,每个表达式中按自然数递增的顺序输出,具体的格式参见样例。
在每个测试数据结束时,输出一行“Result:X”,其中X是最终的表达式个数。
用例
用例1
输入
9
输出
9=9
9=4+5
9=2+3+4
Result:3
说明
整数 9 有三种表示方法,第1个表达式只有1个自然数,最先输出,
第2个表达式有2个自然数,第2次序输出,
第3个表达式有3个自然数,最后输出。每个表达式中的自然数都是按递增次序输出的。数字与符号之间无空格。
用例2
输入
10
输出
10=10
10=1+2+3+4
Result:2
题目解析
考察点
考察滑动窗口算法和数组操作。
解析思路
- 生成自然数数组:首先生成一个从1到目标整数T的自然数数组
arr
。例如,如果目标整数是9,则生成数组[1, 2, 3, 4, 5, 6, 7, 8, 9]
。 - 初始化指针和变量:使用两个指针
left
和right
,初始时都指向数组的起始位置(索引0)。同时,初始化一个变量sum
用于存储当前窗口内元素的和,初始值为arr[0]
。 - 滑动窗口逻辑:
- 移动
right
指针:right
指针从左向右移动,每次移动后计算从left
到right
之间的子数组和,更新sum
的值。 - 判断
sum
与目标整数的关系:- 如果
sum > target
,则移动left
指针向右一位,并从sum
中减去arr[left]
的值,缩小窗口。 - 如果
sum === target
,则将当前窗口内的元素作为一个表达式保存起来。然后,同时移动left
和right
指针,更新sum
的值为sum += arr[right] - arr[left]
。注意检查right
指针是否越界。 - 如果
sum < target
,则移动right
指针向右一位,并将arr[right]
的值加到sum
中,扩大窗口。
- 如果
- 移动
- 结束条件:当
left
指针移动到数组尾部时,结束搜索。 - 输出结果:按照自然数个数从少到多的顺序输出所有找到的表达式,并在最后输出表达式的总数。
注意事项
- 边界检查:在移动
right
指针时,要注意检查是否越界。 - 表达式格式:输出的表达式中,数字与符号之间无空格,确保格式正确。
- 效率考虑:滑动窗口算法的时间复杂度为O(n),适用于本题的规模。
二、JavaScript算法源码
以下是 JavaScript 代码的详细中文注释和讲解:
JavaScript 代码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline"); // 引入 readline 模块,用于读取控制台输入// 创建 readline 接口
const rl = readline.createInterface({input: process.stdin, // 输入流为标准输入output: process.stdout, // 输出流为标准输出
});// 监听输入事件
rl.on("line", (line) => {getResult(parseInt(line)); // 调用 getResult 方法,传入输入的整数
});// 主逻辑函数
function getResult(t) {// 创建一个数组,内容为 1 到 t 的连续整数const arr = new Array(t).fill(0).map((_, i) => i + 1);// 用于存储所有满足条件的子数组const ans = [];// 初始化双指针 l 和 r,以及当前子数组的和 sumlet l = 0; // 左指针let r = 1; // 右指针let sum = arr[l]; // 当前子数组的和// 使用滑动窗口算法遍历数组while (l < t) {if (sum > t) {// 如果当前子数组的和大于 t,移动左指针并减去对应的值sum -= arr[l++];} else if (sum == t) {// 如果当前子数组的和等于 t,将其加入结果集ans.push(arr.slice(l, r));// 移动左指针并减去对应的值sum -= arr[l++];// 如果右指针超出数组范围,退出循环if (r >= t) break;// 移动右指针并加上对应的值sum += arr[r++];} else {// 如果当前子数组的和小于 t,移动右指针并加上对应的值sum += arr[r++];}}// 对结果集中的子数组按长度排序,并输出ans.sort((a, b) => a.length - b.length) // 按子数组长度从小到大排序.forEach((sub) => {console.log(`${t}=${sub.join("+")}`); // 输出子数组});// 输出满足条件的子数组的总数console.log(`Result:${ans.length}`);
}
详细讲解
1. 输入获取
const readline = require("readline"); // 引入 readline 模块// 创建 readline 接口
const rl = readline.createInterface({input: process.stdin, // 输入流为标准输入output: process.stdout, // 输出流为标准输出
});// 监听输入事件
rl.on("line", (line) => {getResult(parseInt(line)); // 调用 getResult 方法,传入输入的整数
});
- 功能:
- 使用
readline
模块从控制台读取输入。 - 监听
line
事件,当用户输入一行内容时,调用getResult
方法。
- 使用
- 说明:
parseInt(line)
将输入的字符串转换为整数。
2. 初始化数组
const arr = new Array(t).fill(0).map((_, i) => i + 1);
- 功能:
- 创建一个长度为
t
的数组arr
。 - 数组内容为
1
到t
的连续整数。
- 创建一个长度为
- 说明:
new Array(t).fill(0)
创建一个长度为t
的数组,并用0
填充。map((_, i) => i + 1)
将数组内容替换为1
到t
的连续整数。- 例如,如果
t = 5
,则arr = [1, 2, 3, 4, 5]
。
3. 滑动窗口算法
let l = 0; // 左指针
let r = 1; // 右指针
let sum = arr[l]; // 当前子数组的和while (l < t) {if (sum > t) {sum -= arr[l++]; // 如果和大于 t,移动左指针} else if (sum == t) {ans.push(arr.slice(l, r)); // 如果和等于 t,记录子数组sum -= arr[l++]; // 移动左指针if (r >= t) break; // 如果右指针超出范围,退出循环sum += arr[r++]; // 移动右指针} else {sum += arr[r++]; // 如果和小于 t,移动右指针}
}
- 功能:
- 使用滑动窗口算法遍历数组,找到所有和为
t
的连续子数组。
- 使用滑动窗口算法遍历数组,找到所有和为
- 说明:
l
和r
分别表示滑动窗口的左边界和右边界。sum
表示当前窗口内元素的和。- 如果
sum > t
,移动左指针并减去对应的值。 - 如果
sum == t
,记录当前子数组,并移动左指针。 - 如果
sum < t
,移动右指针并加上对应的值。
4. 结果排序与输出
ans.sort((a, b) => a.length - b.length) // 按子数组长度从小到大排序.forEach((sub) => {console.log(`${t}=${sub.join("+")}`); // 输出子数组});console.log(`Result:${ans.length}`); // 输出满足条件的子数组的总数
- 功能:
- 对结果集中的子数组按长度从小到大排序。
- 使用
join("+")
将子数组拼接成字符串并输出。 - 输出满足条件的子数组的总数。
- 说明:
sort((a, b) => a.length - b.length)
按子数组长度排序。join("+")
将数组元素用+
拼接成字符串。- 例如,子数组
[2, 3, 4]
会被拼接为2+3+4
。
代码运行示例
示例 1:
输入:
5
输出:
5=5
5=2+3
Result:2
解释:
- 数组
arr = [1, 2, 3, 4, 5]
。 - 满足条件的子数组:
[5]
[2, 3]
- 总数为
2
。
示例 2:
输入:
15
输出:
15=15
15=7+8
15=4+5+6
15=1+2+3+4+5
Result:4
解释:
- 数组
arr = [1, 2, 3, ..., 15]
。 - 满足条件的子数组:
[15]
[7, 8]
[4, 5, 6]
[1, 2, 3, 4, 5]
- 总数为
4
。
总结
-
功能:
- 找到所有和为
t
的连续子数组。 - 按子数组长度从小到大输出结果。
- 找到所有和为
-
优点:
- 使用滑动窗口算法,时间复杂度为
O(n)
,效率高。 - 代码逻辑清晰,易于理解。
- 使用滑动窗口算法,时间复杂度为
-
适用场景:
- 适用于需要查找连续子数组满足特定条件的场景。
如果您有其他问题,欢迎随时提问!
三、Java算法源码
以下是 Java 代码的详细中文注释和讲解:
Java 代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringJoiner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in); // 创建 Scanner 对象,用于读取输入getResult(sc.nextInt()); // 调用 getResult 方法,传入输入的整数}public static void getResult(int t) {// 创建一个数组,内容为 1 到 t 的连续整数int[] arr = new int[t];for (int i = 0; i < t; i++) {arr[i] = i + 1;}// 用于存储所有满足条件的子数组ArrayList<int[]> ans = new ArrayList<>();// 初始化双指针 l 和 r,以及当前子数组的和 sumint l = 0; // 左指针int r = 1; // 右指针int sum = arr[l]; // 当前子数组的和// 使用滑动窗口算法遍历数组while (l < t) {if (sum > t) {// 如果当前子数组的和大于 t,移动左指针并减去对应的值sum -= arr[l++];} else if (sum == t) {// 如果当前子数组的和等于 t,将其加入结果集ans.add(Arrays.copyOfRange(arr, l, r));// 移动左指针并减去对应的值sum -= arr[l++];// 如果右指针超出数组范围,退出循环if (r >= t) break;// 移动右指针并加上对应的值sum += arr[r++];} else {// 如果当前子数组的和小于 t,移动右指针并加上对应的值sum += arr[r++];}}// 对结果集中的子数组按长度排序ans.sort((a, b) -> a.length - b.length);// 输出所有满足条件的子数组for (int[] an : ans) {StringJoiner sj = new StringJoiner("+"); // 使用 StringJoiner 拼接字符串for (int v : an) {sj.add(v + ""); // 将子数组中的每个元素加入 StringJoiner}System.out.println(t + "=" + sj); // 输出结果}// 输出满足条件的子数组的总数System.out.println("Result:" + ans.size());}
}
详细讲解
1. 输入获取
Scanner sc = new Scanner(System.in); // 创建 Scanner 对象,用于读取输入
getResult(sc.nextInt()); // 调用 getResult 方法,传入输入的整数
- 功能:
- 使用
Scanner
从控制台读取一个整数t
。 - 调用
getResult
方法,传入t
作为参数。
- 使用
2. 初始化数组
int[] arr = new int[t];
for (int i = 0; i < t; i++) {arr[i] = i + 1;
}
- 功能:
- 创建一个长度为
t
的数组arr
。 - 数组内容为
1
到t
的连续整数。
- 创建一个长度为
- 说明:
- 例如,如果
t = 5
,则arr = [1, 2, 3, 4, 5]
。
- 例如,如果
3. 滑动窗口算法
int l = 0; // 左指针
int r = 1; // 右指针
int sum = arr[l]; // 当前子数组的和while (l < t) {if (sum > t) {sum -= arr[l++]; // 如果和大于 t,移动左指针} else if (sum == t) {ans.add(Arrays.copyOfRange(arr, l, r)); // 如果和等于 t,记录子数组sum -= arr[l++]; // 移动左指针if (r >= t) break; // 如果右指针超出范围,退出循环sum += arr[r++]; // 移动右指针} else {sum += arr[r++]; // 如果和小于 t,移动右指针}
}
- 功能:
- 使用滑动窗口算法遍历数组,找到所有和为
t
的连续子数组。
- 使用滑动窗口算法遍历数组,找到所有和为
- 说明:
l
和r
分别表示滑动窗口的左边界和右边界。sum
表示当前窗口内元素的和。- 如果
sum > t
,移动左指针并减去对应的值。 - 如果
sum == t
,记录当前子数组,并移动左指针。 - 如果
sum < t
,移动右指针并加上对应的值。
4. 结果排序
ans.sort((a, b) -> a.length - b.length);
- 功能:
- 对结果集中的子数组按长度从小到大排序。
- 说明:
- 使用
sort
方法和 Lambda 表达式实现排序。
- 使用
5. 输出结果
for (int[] an : ans) {StringJoiner sj = new StringJoiner("+"); // 使用 StringJoiner 拼接字符串for (int v : an) {sj.add(v + ""); // 将子数组中的每个元素加入 StringJoiner}System.out.println(t + "=" + sj); // 输出结果
}System.out.println("Result:" + ans.size()); // 输出满足条件的子数组的总数
- 功能:
- 使用
StringJoiner
将子数组拼接成字符串并输出。 - 输出满足条件的子数组的总数。
- 使用
- 说明:
StringJoiner
是 Java 8 引入的工具类,用于拼接字符串。- 例如,子数组
[2, 3, 4]
会被拼接为2+3+4
。
代码运行示例
示例 1:
输入:
5
输出:
5=5
5=2+3
Result:2
解释:
- 数组
arr = [1, 2, 3, 4, 5]
。 - 满足条件的子数组:
[5]
[2, 3]
- 总数为
2
。
示例 2:
输入:
15
输出:
15=15
15=7+8
15=4+5+6
15=1+2+3+4+5
Result:4
解释:
- 数组
arr = [1, 2, 3, ..., 15]
。 - 满足条件的子数组:
[15]
[7, 8]
[4, 5, 6]
[1, 2, 3, 4, 5]
- 总数为
4
。
总结
-
功能:
- 找到所有和为
t
的连续子数组。 - 按子数组长度从小到大输出结果。
- 找到所有和为
-
优点:
- 使用滑动窗口算法,时间复杂度为
O(n)
,效率高。 - 代码逻辑清晰,易于理解。
- 使用滑动窗口算法,时间复杂度为
-
适用场景:
- 适用于需要查找连续子数组满足特定条件的场景。
如果您有其他问题,欢迎随时提问!
四、Python算法源码
以下是 Python 代码的详细中文注释和讲解:
Python 代码
# 输入获取
t = int(input()) # 从控制台读取输入的整数 t# 算法入口
def getResult():# 创建一个数组,内容为 1 到 t 的连续整数arr = [i + 1 for i in range(t)]# 用于存储所有满足条件的子数组ans = []# 初始化双指针 l 和 r,以及当前子数组的和 totall = 0 # 左指针r = 1 # 右指针total = arr[l] # 当前子数组的和# 使用滑动窗口算法遍历数组while l < t:if total > t:# 如果当前子数组的和大于 t,移动左指针并减去对应的值total -= arr[l]l += 1elif total == t:# 如果当前子数组的和等于 t,将其加入结果集ans.append(arr[l:r])# 移动左指针并减去对应的值total -= arr[l]l += 1# 如果右指针超出数组范围,退出循环if r >= t:breakelse:# 移动右指针并加上对应的值total += arr[r]r += 1else:# 如果当前子数组的和小于 t,移动右指针并加上对应的值total += arr[r]r += 1# 对结果集中的子数组按长度排序ans.sort(key=lambda x: len(x))# 输出所有满足条件的子数组for an in ans:print(f"{t}={'+'.join(map(str, an))}")# 输出满足条件的子数组的总数print(f"Result:{len(ans)}")# 算法调用
getResult()
详细讲解
1. 输入获取
t = int(input()) # 从控制台读取输入的整数 t
- 功能:
- 使用
input()
函数从控制台读取一行输入。 - 将输入转换为整数并赋值给变量
t
。
- 使用
2. 初始化数组
arr = [i + 1 for i in range(t)]
- 功能:
- 创建一个长度为
t
的数组arr
。 - 数组内容为
1
到t
的连续整数。
- 创建一个长度为
- 说明:
- 使用列表推导式生成数组。
- 例如,如果
t = 5
,则arr = [1, 2, 3, 4, 5]
。
3. 滑动窗口算法
l = 0 # 左指针
r = 1 # 右指针
total = arr[l] # 当前子数组的和while l < t:if total > t:total -= arr[l] # 如果和大于 t,移动左指针l += 1elif total == t:ans.append(arr[l:r]) # 如果和等于 t,记录子数组total -= arr[l] # 移动左指针l += 1if r >= t: # 如果右指针超出范围,退出循环breakelse:total += arr[r] # 移动右指针r += 1else:total += arr[r] # 如果和小于 t,移动右指针r += 1
- 功能:
- 使用滑动窗口算法遍历数组,找到所有和为
t
的连续子数组。
- 使用滑动窗口算法遍历数组,找到所有和为
- 说明:
l
和r
分别表示滑动窗口的左边界和右边界。total
表示当前窗口内元素的和。- 如果
total > t
,移动左指针并减去对应的值。 - 如果
total == t
,记录当前子数组,并移动左指针。 - 如果
total < t
,移动右指针并加上对应的值。
4. 结果排序与输出
ans.sort(key=lambda x: len(x)) # 按子数组长度从小到大排序for an in ans:print(f"{t}={'+'.join(map(str, an))}") # 输出子数组print(f"Result:{len(ans)}") # 输出满足条件的子数组的总数
- 功能:
- 对结果集中的子数组按长度从小到大排序。
- 使用
join
将子数组拼接成字符串并输出。 - 输出满足条件的子数组的总数。
- 说明:
sort(key=lambda x: len(x))
按子数组长度排序。join
将数组元素用+
拼接成字符串。- 例如,子数组
[2, 3, 4]
会被拼接为2+3+4
。
代码运行示例
示例 1:
输入:
5
输出:
5=5
5=2+3
Result:2
解释:
- 数组
arr = [1, 2, 3, 4, 5]
。 - 满足条件的子数组:
[5]
[2, 3]
- 总数为
2
。
示例 2:
输入:
15
输出:
15=15
15=7+8
15=4+5+6
15=1+2+3+4+5
Result:4
解释:
- 数组
arr = [1, 2, 3, ..., 15]
。 - 满足条件的子数组:
[15]
[7, 8]
[4, 5, 6]
[1, 2, 3, 4, 5]
- 总数为
4
。
总结
-
功能:
- 找到所有和为
t
的连续子数组。 - 按子数组长度从小到大输出结果。
- 找到所有和为
-
优点:
- 使用滑动窗口算法,时间复杂度为
O(n)
,效率高。 - 代码逻辑清晰,易于理解。
- 使用滑动窗口算法,时间复杂度为
-
适用场景:
- 适用于需要查找连续子数组满足特定条件的场景。
如果您有其他问题,欢迎随时提问!
五、C/C++算法源码:
以下是 C++ 和 C语言 的代码实现,并附带详细的中文注释和讲解:
C++ 代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;// 算法入口
void getResult(int t) {// 创建一个数组,内容为 1 到 t 的连续整数vector<int> arr(t);for (int i = 0; i < t; i++) {arr[i] = i + 1;}// 用于存储所有满足条件的子数组vector<vector<int>> ans;// 初始化双指针 l 和 r,以及当前子数组的和 totalint l = 0; // 左指针int r = 1; // 右指针int total = arr[l]; // 当前子数组的和// 使用滑动窗口算法遍历数组while (l < t) {if (total > t) {// 如果当前子数组的和大于 t,移动左指针并减去对应的值total -= arr[l++];} else if (total == t) {// 如果当前子数组的和等于 t,将其加入结果集vector<int> sub(arr.begin() + l, arr.begin() + r);ans.push_back(sub);// 移动左指针并减去对应的值total -= arr[l++];// 如果右指针超出数组范围,退出循环if (r >= t) break;// 移动右指针并加上对应的值total += arr[r++];} else {// 如果当前子数组的和小于 t,移动右指针并加上对应的值total += arr[r++];}}// 对结果集中的子数组按长度排序sort(ans.begin(), ans.end(), [](const vector<int>& a, const vector<int>& b) {return a.size() < b.size();});// 输出所有满足条件的子数组for (const auto& sub : ans) {cout << t << "=";for (size_t i = 0; i < sub.size(); i++) {if (i > 0) cout << "+";cout << sub[i];}cout << endl;}// 输出满足条件的子数组的总数cout << "Result:" << ans.size() << endl;
}int main() {int t;cin >> t; // 从控制台读取输入的整数 tgetResult(t); // 调用算法函数return 0;
}
C语言 代码
#include <stdio.h>
#include <stdlib.h>// 算法入口
void getResult(int t) {// 创建一个数组,内容为 1 到 t 的连续整数int* arr = (int*)malloc(t * sizeof(int));for (int i = 0; i < t; i++) {arr[i] = i + 1;}// 用于存储所有满足条件的子数组int** ans = (int**)malloc(t * sizeof(int*));int* ansLen = (int*)malloc(t * sizeof(int));int ansCount = 0;// 初始化双指针 l 和 r,以及当前子数组的和 totalint l = 0; // 左指针int r = 1; // 右指针int total = arr[l]; // 当前子数组的和// 使用滑动窗口算法遍历数组while (l < t) {if (total > t) {// 如果当前子数组的和大于 t,移动左指针并减去对应的值total -= arr[l++];} else if (total == t) {// 如果当前子数组的和等于 t,将其加入结果集int* sub = (int*)malloc((r - l) * sizeof(int));for (int i = l; i < r; i++) {sub[i - l] = arr[i];}ans[ansCount] = sub;ansLen[ansCount] = r - l;ansCount++;// 移动左指针并减去对应的值total -= arr[l++];// 如果右指针超出数组范围,退出循环if (r >= t) break;// 移动右指针并加上对应的值total += arr[r++];} else {// 如果当前子数组的和小于 t,移动右指针并加上对应的值total += arr[r++];}}// 对结果集中的子数组按长度排序(冒泡排序)for (int i = 0; i < ansCount - 1; i++) {for (int j = 0; j < ansCount - 1 - i; j++) {if (ansLen[j] > ansLen[j + 1]) {// 交换子数组int* tempSub = ans[j];ans[j] = ans[j + 1];ans[j + 1] = tempSub;// 交换子数组长度int tempLen = ansLen[j];ansLen[j] = ansLen[j + 1];ansLen[j + 1] = tempLen;}}}// 输出所有满足条件的子数组for (int i = 0; i < ansCount; i++) {printf("%d=", t);for (int j = 0; j < ansLen[i]; j++) {if (j > 0) printf("+");printf("%d", ans[i][j]);}printf("\n");}// 输出满足条件的子数组的总数printf("Result:%d\n", ansCount);// 释放动态分配的内存for (int i = 0; i < ansCount; i++) {free(ans[i]);}free(ans);free(ansLen);free(arr);
}int main() {int t;scanf("%d", &t); // 从控制台读取输入的整数 tgetResult(t); // 调用算法函数return 0;
}
详细讲解
1. 输入获取
-
C++:
int t; cin >> t; // 从控制台读取输入的整数 t
-
C语言:
int t; scanf("%d", &t); // 从控制台读取输入的整数 t
-
功能:
- 从控制台读取一个整数
t
,表示目标和。
- 从控制台读取一个整数
2. 初始化数组
-
C++:
vector<int> arr(t); for (int i = 0; i < t; i++) {arr[i] = i + 1; }
-
C语言:
int* arr = (int*)malloc(t * sizeof(int)); for (int i = 0; i < t; i++) {arr[i] = i + 1; }
-
功能:
- 创建一个长度为
t
的数组,内容为1
到t
的连续整数。
- 创建一个长度为
3. 滑动窗口算法
-
C++:
int l = 0; // 左指针 int r = 1; // 右指针 int total = arr[l]; // 当前子数组的和while (l < t) {if (total > t) {total -= arr[l++]; // 如果和大于 t,移动左指针} else if (total == t) {vector<int> sub(arr.begin() + l, arr.begin() + r); // 记录子数组ans.push_back(sub);total -= arr[l++]; // 移动左指针if (r >= t) break; // 如果右指针超出范围,退出循环total += arr[r++]; // 移动右指针} else {total += arr[r++]; // 如果和小于 t,移动右指针} }
-
C语言:
int l = 0; // 左指针 int r = 1; // 右指针 int total = arr[l]; // 当前子数组的和while (l < t) {if (total > t) {total -= arr[l++]; // 如果和大于 t,移动左指针} else if (total == t) {int* sub = (int*)malloc((r - l) * sizeof(int)); // 记录子数组for (int i = l; i < r; i++) {sub[i - l] = arr[i];}ans[ansCount] = sub;ansLen[ansCount] = r - l;ansCount++;total -= arr[l++]; // 移动左指针if (r >= t) break; // 如果右指针超出范围,退出循环total += arr[r++]; // 移动右指针} else {total += arr[r++]; // 如果和小于 t,移动右指针} }
-
功能:
- 使用滑动窗口算法遍历数组,找到所有和为
t
的连续子数组。
- 使用滑动窗口算法遍历数组,找到所有和为
4. 结果排序与输出
-
C++:
sort(ans.begin(), ans.end(), [](const vector<int>& a, const vector<int>& b) {return a.size() < b.size(); });for (const auto& sub : ans) {cout << t << "=";for (size_t i = 0; i < sub.size(); i++) {if (i > 0) cout << "+";cout << sub[i];}cout << endl; }cout << "Result:" << ans.size() << endl;
-
C语言:
for (int i = 0; i < ansCount - 1; i++) {for (int j = 0; j < ansCount - 1 - i; j++) {if (ansLen[j] > ansLen[j + 1]) {int* tempSub = ans[j];ans[j] = ans[j + 1];ans[j + 1] = tempSub;int tempLen = ansLen[j];ansLen[j] = ansLen[j + 1];ansLen[j + 1] = tempLen;}} }for (int i = 0; i < ansCount; i++) {printf("%d=", t);for (int j = 0; j < ansLen[i]; j++) {if (j > 0) printf("+");printf("%d", ans[i][j]);}printf("\n"); }printf("Result:%d\n", ansCount);
-
功能:
- 对结果集中的子数组按长度从小到大排序。
- 输出所有满足条件的子数组。
- 输出满足条件的子数组的总数。
总结
-
功能:
- 找到所有和为
t
的连续子数组。 - 按子数组长度从小到大输出结果。
- 找到所有和为
-
优点:
- 使用滑动窗口算法,时间复杂度为
O(n)
,效率高。 - 代码逻辑清晰,易于理解。
- 使用滑动窗口算法,时间复杂度为
-
适用场景:
- 适用于需要查找连续子数组满足特定条件的场景。
如果您有其他问题,欢迎随时提问!
六、尾言
什么是华为OD?
华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。
为什么刷题很重要?
-
机试是进入技术面的第一关:
华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。 -
技术面试需要手撕代码:
技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。 -
入职后的可信考试:
入职华为后,还需要通过“可信考试”。可信考试分为三个等级:- 入门级:主要考察基础算法与编程能力。
- 工作级:更贴近实际业务需求,可能涉及复杂的算法或与工作内容相关的场景题目。
- 专业级:最高等级,考察深层次的算法以及优化能力,与薪资直接挂钩。
刷题策略与说明:
2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:
-
关注历年真题:
- 题库中的旧题占比较大,建议优先刷历年的A卷、B卷、C卷、D卷题目。
- 对于每道题目,建议深度理解其解题思路、代码实现,以及相关算法的适用场景。
-
适应新题目:
- E卷中包含全新题目,需要掌握全面的算法知识和一定的灵活应对能力。
- 建议关注新的刷题平台或交流群,获取最新题目的解析和动态。
-
掌握常见算法:
华为OD考试通常涉及以下算法和数据结构:- 排序算法(快速排序、归并排序等)
- 动态规划(背包问题、最长公共子序列等)
- 贪心算法
- 栈、队列、链表的操作
- 图论(最短路径、最小生成树等)
- 滑动窗口、双指针算法
-
保持编程规范:
- 注重代码的可读性和注释的清晰度。
- 熟练使用常见编程语言,如C++、Java、Python等。
如何获取资源?
-
官方参考:
- 华为招聘官网或相关的招聘平台会有一些参考信息。
- 华为OD的相关公众号可能也会发布相关的刷题资料或学习资源。
-
加入刷题社区:
- 找到可信的刷题交流群,与其他备考的小伙伴交流经验。
- 关注知名的刷题网站,如LeetCode、牛客网等,这些平台上有许多华为OD的历年真题和解析。
-
寻找系统性的教程:
- 学习一本经典的算法书籍,例如《算法导论》《剑指Offer》《编程之美》等。
- 完成系统的学习课程,例如数据结构与算法的在线课程。
积极心态与持续努力:
刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。
考试注意细节
-
本地编写代码
- 在本地 IDE(如 VS Code、PyCharm 等)上编写、保存和调试代码,确保逻辑正确后再复制粘贴到考试页面。这样可以减少语法错误,提高代码准确性。
-
调整心态,保持冷静
- 遇到提示不足或实现不确定的问题时,不必慌张,可以采用更简单或更有把握的方法替代,确保思路清晰。
-
输入输出完整性
- 注意训练和考试时都需要编写完整的输入输出代码,尤其是和题目示例保持一致。完成代码后务必及时调试,确保功能符合要求。
-
快捷键使用
- 删除行可用
Ctrl+D
,复制、粘贴和撤销分别为Ctrl+C
,Ctrl+V
,Ctrl+Z
,这些可以正常使用。 - 避免使用
Ctrl+S
,以免触发浏览器的保存功能。
- 删除行可用
-
浏览器要求
- 使用最新版的 Google Chrome 浏览器完成考试,确保摄像头开启并正常工作。考试期间不要切换到其他网站,以免影响考试成绩。
-
交卷相关
- 答题前,务必仔细查看题目示例,避免遗漏要求。
- 每完成一道题后,点击【保存并调试】按钮,多次保存和调试是允许的,系统会记录得分最高的一次结果。完成所有题目后,点击【提交本题型】按钮。
- 确保在考试结束前提交试卷,避免因未保存或调试失误而丢分。
-
时间和分数安排
- 总时间:150 分钟;总分:400 分。
- 试卷结构:2 道一星难度题(每题 100 分),1 道二星难度题(200 分)。及格分为 150 分。合理分配时间,优先完成自己擅长的题目。
-
考试环境准备
- 考试前请备好草稿纸和笔。考试中尽量避免离开座位,确保监控画面正常。
- 如需上厕所,请提前规划好时间以减少中途离开监控的可能性。
-
技术问题处理
- 如果考试中遇到断电、断网、死机等技术问题,可以关闭浏览器并重新打开试卷链接继续作答。
- 出现其他问题,请第一时间联系 HR 或监考人员进行反馈。
祝你考试顺利,取得理想成绩!