一、问题描述
题目描述
向一个空栈中依次存入正整数,假设入栈元素 n(1<=n<=2^31-1)按顺序依次为 nx…n4、 n3、n2、 n1, 每当元素入栈时,如果 n1=n2+…+ny(y 的范围[2,x], 1<=x<=1000),则 n1~ny 全部元素出栈,重新入栈新元素 m(m=2*n1)。
如:依次向栈存入 6、 1、 2、 3, 当存入 6、 1、 2 时,栈底至栈顶依次为[6、 1、 2];当存入 3时, 3=2+1, 3、 2、 1 全部出栈,重新入栈元素 6(6=2*3),此时栈中有元素 6;
因为 6=6,所以两个 6 全部出栈,存入 12,最终栈中只剩一个元素 12。
输入描述
使用单个空格隔开的正整数的字符串,如”5 6 7 8″, 左边的数字先入栈,输入的正整数个数为 x, 1<=x<=1000。
输出描述
最终栈中存留的元素值,元素值使用空格隔开,如”8 7 6 5″, 栈顶数字在左边。
用例
用例1
输入
5 10 20 50 85 1
输出
1 170
说明
5+10+20+50=85, 输入 85 时, 5、 10、 20、 50、 85 全部出栈,入栈 170,最终依次出栈的数字为 1 和 170。
用例2
输入
6 7 8 13 9
输出
9 13 8 7 6
说明
无
用例3
输入
1 2 5 7 9 1 2 2
输出
4 1 9 14 1
说明
无
题目解析
考察点
考察栈的操作和递归逻辑处理。
解析思路
- 初始化栈:创建一个空栈,用于存储入栈的元素。
- 遍历输入元素:按照输入顺序依次处理每个元素。
- 入栈前检查:
- 每当有新元素
num
将要入栈前,从栈顶开始遍历栈中的元素,尝试用num
依次减去栈中的元素。 - 如果在遍历过程中
num
变为 0,则说明找到了符合条件的元素序列,将这些元素全部出栈,并将num * 2
入栈。 - 如果遍历完栈中所有元素,
num
仍未变为 0,则直接将num
入栈。
- 每当有新元素
- 递归处理:
- 当将
num * 2
入栈时,这个操作也是一个元素入栈的过程,因此需要递归地执行入栈前的检查逻辑。 - 这意味着每次入栈新元素后,都需要重新检查栈顶元素是否满足条件,直到没有更多的元素可以合并为止。
- 当将
- 输出结果:遍历完所有输入元素后,栈中剩余的元素即为最终结果。按照栈顶到栈底的顺序输出这些元素。
注意事项
- 递归逻辑:每次入栈新元素(包括
num * 2
)后,都需要重新检查栈顶元素是否满足条件,这是一个递归过程。确保递归逻辑正确处理,避免无限递归。 - 栈操作:在处理元素出栈和入栈时,要注意栈的状态变化,确保操作的正确性。
- 边界条件:处理输入元素时,要注意边界条件,如栈为空时的处理等。
二、JavaScript算法源码
以下是 JavaScript 代码的详细中文注释和讲解:
JavaScript 代码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");// 创建 readline 接口,用于从控制台读取输入
const rl = readline.createInterface({input: process.stdin, // 输入流output: process.stdout, // 输出流
});// 监听输入事件,每次读取一行输入
rl.on("line", (line) => {// 将输入的一行字符串按空格分割,并转换为数字数组const nums = line.split(" ").map(Number);// 调用 getResult 方法处理数组,并输出结果console.log(getResult(nums));
});// 处理数字数组,返回最终结果
function getResult(nums) {// 使用数组模拟栈结构const stack = [nums[0]]; // 将数组的第一个元素压入栈// 遍历数组的剩余元素for (let i = 1; i < nums.length; i++) {// 调用 push 方法处理当前元素push(nums[i], stack);}// 将栈中的元素反转(从栈底到栈顶),并用空格拼接成字符串return stack.reverse().join(" ");
}// 将元素压入栈,并根据规则处理
function push(num, stack) {let sum = num; // 初始化 sum 为当前元素的值// 从栈顶向栈底遍历for (let i = stack.length - 1; i >= 0; i--) {sum -= stack[i]; // 减去当前栈中的元素// 如果 sum 等于 0,说明找到了一组连续的元素,其和等于当前元素if (sum == 0) {stack.splice(i); // 清除栈中从当前位置到栈顶的所有元素push(num * 2, stack); // 将当前元素的两倍压入栈return;} else if (sum < 0) {// 如果 sum 小于 0,说明无法找到满足条件的连续元素,退出循环break;}}// 如果没有找到满足条件的连续元素,直接将当前元素压入栈stack.push(num);
}
详细讲解
1. 输入获取
const readline = require("readline");const rl = readline.createInterface({input: process.stdin,output: process.stdout,
});rl.on("line", (line) => {const nums = line.split(" ").map(Number);console.log(getResult(nums));
});
- 功能:
- 使用
readline
模块从控制台读取输入。 - 将输入的一行字符串按空格分割成数组,并转换为数字。
- 调用
getResult
方法处理数组,并输出结果。
- 使用
- 说明:
readline.createInterface
创建一个接口,用于读取输入和输出。rl.on("line", callback)
监听输入事件,每次读取一行输入。line.split(" ")
按空格分割字符串。map(Number)
将字符串数组转换为数字数组。
2. 处理数字数组
function getResult(nums) {const stack = [nums[0]]; // 将数组的第一个元素压入栈for (let i = 1; i < nums.length; i++) {push(nums[i], stack); // 处理数组的剩余元素}return stack.reverse().join(" "); // 反转栈并拼接成字符串
}
- 功能:
- 使用数组模拟栈结构。
- 将数组的第一个元素压入栈。
- 遍历数组的剩余元素,调用
push
方法处理每个元素。 - 将栈中的元素反转(从栈底到栈顶),并用空格拼接成字符串。
- 说明:
stack
是一个数组,用于模拟栈的行为。stack.reverse()
将栈中的元素反转。join(" ")
将数组元素用空格拼接成字符串。
3. 压栈操作
function push(num, stack) {let sum = num; // 初始化 sum 为当前元素的值for (let i = stack.length - 1; i >= 0; i--) {sum -= stack[i]; // 减去当前栈中的元素if (sum == 0) {stack.splice(i); // 清除栈中从当前位置到栈顶的所有元素push(num * 2, stack); // 将当前元素的两倍压入栈return;} else if (sum < 0) {break; // 如果 sum 小于 0,退出循环}}stack.push(num); // 将当前元素压入栈
}
- 功能:
- 将元素压入栈,并根据规则处理。
- 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
- 如果没有找到满足条件的连续元素,直接将当前元素压入栈。
- 说明:
sum
初始化为当前元素的值。- 从栈顶向栈底遍历,依次减去栈中的元素。
- 如果
sum == 0
,说明找到了一组连续的元素,其和等于当前元素。 - 如果
sum < 0
,说明无法找到满足条件的连续元素,退出循环。 stack.splice(i)
清除栈中从当前位置到栈顶的所有元素。
代码运行示例
示例 1:
输入:
1 2 3 6 3
输出:
12 3
解释:
- 初始栈:
[1]
- 处理
2
:栈变为[1, 2]
- 处理
3
:栈变为[1, 2, 3]
- 处理
6
:找到3 + 2 + 1 = 6
,清除[1, 2, 3]
,压入6 * 2 = 12
,栈变为[12]
- 处理
3
:栈变为[12, 3]
- 最终结果:
12 3
示例 2:
输入:
1 2 3 4
输出:
1 2 3 4
解释:
- 初始栈:
[1]
- 处理
2
:栈变为[1, 2]
- 处理
3
:栈变为[1, 2, 3]
- 处理
4
:栈变为[1, 2, 3, 4]
- 最终结果:
1 2 3 4
总结
-
功能:
- 处理数字数组,根据规则将元素压入栈。
- 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
-
优点:
- 使用数组模拟栈结构,逻辑清晰。
- 适用于需要动态调整数据结构的场景。
-
适用场景:
- 适用于需要根据特定规则处理数组元素的场景。
如果您有其他问题,欢迎随时提问!
三、Java算法源码
以下是 Java 代码的详细中文注释和讲解:
Java 代码
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.StringJoiner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 读取输入的一行数字,并将其转换为整数数组int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();// 调用 getResult 方法并输出结果System.out.println(getResult(nums));}// 处理整数数组,返回最终结果public static String getResult(int[] nums) {// 使用 LinkedList 模拟栈结构LinkedList<Integer> stack = new LinkedList<>();// 将数组的第一个元素压入栈stack.add(nums[0]);// 遍历数组的剩余元素for (int i = 1; i < nums.length; i++) {// 调用 push 方法处理当前元素push(nums[i], stack);}// 使用 StringJoiner 将栈中的元素按从栈底到栈顶的顺序拼接成字符串StringJoiner sj = new StringJoiner(" ");while (stack.size() > 0) {sj.add(stack.removeLast() + ""); // 从栈顶移除元素并添加到结果中}return sj.toString();}// 将元素压入栈,并根据规则处理public static void push(int num, LinkedList<Integer> stack) {int sum = num; // 初始化 sum 为当前元素的值// 从栈顶向栈底遍历for (int i = stack.size() - 1; i >= 0; i--) {sum -= stack.get(i); // 减去当前栈中的元素// 如果 sum 等于 0,说明找到了一组连续的元素,其和等于当前元素if (sum == 0) {// 清除栈中从当前位置到栈顶的所有元素stack.subList(i, stack.size()).clear();// 将当前元素的两倍压入栈push(num * 2, stack);return;} else if (sum < 0) {// 如果 sum 小于 0,说明无法找到满足条件的连续元素,退出循环break;}}// 如果没有找到满足条件的连续元素,直接将当前元素压入栈stack.add(num);}
}
详细讲解
1. 输入获取
Scanner sc = new Scanner(System.in);
int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
- 功能:
- 使用
Scanner
读取输入的一行数字。 - 将输入的数字按空格分割成字符串数组。
- 将字符串数组转换为整数数组
nums
。
- 使用
- 说明:
sc.nextLine()
读取一行输入。split(" ")
按空格分割字符串。mapToInt(Integer::parseInt)
将字符串转换为整数。toArray()
将流转换为整数数组。
2. 处理整数数组
public static String getResult(int[] nums) {LinkedList<Integer> stack = new LinkedList<>();stack.add(nums[0]);for (int i = 1; i < nums.length; i++) {push(nums[i], stack);}StringJoiner sj = new StringJoiner(" ");while (stack.size() > 0) {sj.add(stack.removeLast() + "");}return sj.toString();
}
- 功能:
- 使用
LinkedList
模拟栈结构。 - 将数组的第一个元素压入栈。
- 遍历数组的剩余元素,调用
push
方法处理每个元素。 - 使用
StringJoiner
将栈中的元素按从栈底到栈顶的顺序拼接成字符串。
- 使用
- 说明:
LinkedList
是一个双向链表,可以模拟栈的行为。StringJoiner
用于拼接字符串,分隔符为空格。
3. 压栈操作
public static void push(int num, LinkedList<Integer> stack) {int sum = num;for (int i = stack.size() - 1; i >= 0; i--) {sum -= stack.get(i);if (sum == 0) {stack.subList(i, stack.size()).clear();push(num * 2, stack);return;} else if (sum < 0) {break;}}stack.add(num);
}
- 功能:
- 将元素压入栈,并根据规则处理。
- 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
- 如果没有找到满足条件的连续元素,直接将当前元素压入栈。
- 说明:
sum
初始化为当前元素的值。- 从栈顶向栈底遍历,依次减去栈中的元素。
- 如果
sum == 0
,说明找到了一组连续的元素,其和等于当前元素。 - 如果
sum < 0
,说明无法找到满足条件的连续元素,退出循环。
代码运行示例
示例 1:
输入:
1 2 3 6 3
输出:
12
解释:
- 初始栈:
[1]
- 处理
2
:栈变为[1, 2]
- 处理
3
:栈变为[1, 2, 3]
- 处理
6
:找到3 + 2 + 1 = 6
,清除[1, 2, 3]
,压入6 * 2 = 12
,栈变为[12]
- 处理
3
:栈变为[12, 3]
- 最终结果:
12 3
示例 2:
输入:
1 2 3 4
输出:
1 2 3 4
解释:
- 初始栈:
[1]
- 处理
2
:栈变为[1, 2]
- 处理
3
:栈变为[1, 2, 3]
- 处理
4
:栈变为[1, 2, 3, 4]
- 最终结果:
1 2 3 4
总结
-
功能:
- 处理整数数组,根据规则将元素压入栈。
- 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
-
优点:
- 使用栈结构,逻辑清晰。
- 适用于需要动态调整数据结构的场景。
-
适用场景:
- 适用于需要根据特定规则处理数组元素的场景。
如果您有其他问题,欢迎随时提问!
四、Python算法源码
以下是 Python 代码的详细中文注释和讲解:
Python 代码
# 输入获取
nums = list(map(int, input().split())) # 将输入的一行字符串按空格分割,并转换为整数列表# 将元素压入栈,并根据规则处理
def push(num, stack):total = num # 初始化 total 为当前元素的值# 从栈顶向栈底遍历for i in range(len(stack) - 1, -1, -1):total -= stack[i] # 减去当前栈中的元素# 如果 total 等于 0,说明找到了一组连续的元素,其和等于当前元素if total == 0:del stack[i:] # 清除栈中从当前位置到栈顶的所有元素push(num * 2, stack) # 将当前元素的两倍压入栈returnelif total < 0:# 如果 total 小于 0,说明无法找到满足条件的连续元素,退出循环break# 如果没有找到满足条件的连续元素,直接将当前元素压入栈stack.append(num)# 算法入口
def getResult():stack = [nums[0]] # 将数组的第一个元素压入栈# 遍历数组的剩余元素for i in range(1, len(nums)):push(nums[i], stack) # 处理数组的剩余元素stack.reverse() # 将栈中的元素反转(从栈底到栈顶)# 将栈中的元素用空格拼接成字符串return " ".join(map(str, stack))# 算法调用
print(getResult())
详细讲解
1. 输入获取
nums = list(map(int, input().split()))
- 功能:
- 从控制台读取一行输入。
- 将输入的一行字符串按空格分割成列表。
- 将列表中的每个字符串转换为整数。
- 说明:
input()
读取一行输入。split()
按空格分割字符串。map(int, ...)
将字符串列表转换为整数列表。list(...)
将映射结果转换为列表。
2. 压栈操作
def push(num, stack):total = num # 初始化 total 为当前元素的值# 从栈顶向栈底遍历for i in range(len(stack) - 1, -1, -1):total -= stack[i] # 减去当前栈中的元素# 如果 total 等于 0,说明找到了一组连续的元素,其和等于当前元素if total == 0:del stack[i:] # 清除栈中从当前位置到栈顶的所有元素push(num * 2, stack) # 将当前元素的两倍压入栈returnelif total < 0:# 如果 total 小于 0,说明无法找到满足条件的连续元素,退出循环break# 如果没有找到满足条件的连续元素,直接将当前元素压入栈stack.append(num)
- 功能:
- 将元素压入栈,并根据规则处理。
- 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
- 如果没有找到满足条件的连续元素,直接将当前元素压入栈。
- 说明:
total
初始化为当前元素的值。- 从栈顶向栈底遍历,依次减去栈中的元素。
- 如果
total == 0
,说明找到了一组连续的元素,其和等于当前元素。 - 如果
total < 0
,说明无法找到满足条件的连续元素,退出循环。 del stack[i:]
清除栈中从当前位置到栈顶的所有元素。stack.append(num)
将当前元素压入栈。
3. 算法入口
def getResult():stack = [nums[0]] # 将数组的第一个元素压入栈# 遍历数组的剩余元素for i in range(1, len(nums)):push(nums[i], stack) # 处理数组的剩余元素stack.reverse() # 将栈中的元素反转(从栈底到栈顶)# 将栈中的元素用空格拼接成字符串return " ".join(map(str, stack))
- 功能:
- 使用列表模拟栈结构。
- 将数组的第一个元素压入栈。
- 遍历数组的剩余元素,调用
push
方法处理每个元素。 - 将栈中的元素反转(从栈底到栈顶),并用空格拼接成字符串。
- 说明:
stack
是一个列表,用于模拟栈的行为。stack.reverse()
将栈中的元素反转。map(str, stack)
将栈中的元素转换为字符串。" ".join(...)
将列表元素用空格拼接成字符串。
4. 算法调用
print(getResult())
- 功能:
- 调用
getResult
方法,并输出结果。
- 调用
代码运行示例
示例 1:
输入:
1 2 3 6 3
输出:
12 3
解释:
- 初始栈:
[1]
- 处理
2
:栈变为[1, 2]
- 处理
3
:栈变为[1, 2, 3]
- 处理
6
:找到3 + 2 + 1 = 6
,清除[1, 2, 3]
,压入6 * 2 = 12
,栈变为[12]
- 处理
3
:栈变为[12, 3]
- 最终结果:
12 3
示例 2:
输入:
1 2 3 4
输出:
1 2 3 4
解释:
- 初始栈:
[1]
- 处理
2
:栈变为[1, 2]
- 处理
3
:栈变为[1, 2, 3]
- 处理
4
:栈变为[1, 2, 3, 4]
- 最终结果:
1 2 3 4
总结
-
功能:
- 处理数字数组,根据规则将元素压入栈。
- 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
-
优点:
- 使用列表模拟栈结构,逻辑清晰。
- 适用于需要动态调整数据结构的场景。
-
适用场景:
- 适用于需要根据特定规则处理数组元素的场景。
如果您有其他问题,欢迎随时提问!
五、C/C++算法源码:
以下是 C++ 和 C 语言的代码实现,并附上详细的中文注释和讲解:
C++ 代码
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>using namespace std;// 将元素压入栈,并根据规则处理
void push(int num, vector<int>& stack) {int total = num; // 初始化 total 为当前元素的值// 从栈顶向栈底遍历for (int i = stack.size() - 1; i >= 0; i--) {total -= stack[i]; // 减去当前栈中的元素// 如果 total 等于 0,说明找到了一组连续的元素,其和等于当前元素if (total == 0) {stack.erase(stack.begin() + i, stack.end()); // 清除栈中从当前位置到栈顶的所有元素push(num * 2, stack); // 将当前元素的两倍压入栈return;} else if (total < 0) {// 如果 total 小于 0,说明无法找到满足条件的连续元素,退出循环break;}}// 如果没有找到满足条件的连续元素,直接将当前元素压入栈stack.push_back(num);
}// 算法入口
string getResult(vector<int>& nums) {vector<int> stack;stack.push_back(nums[0]); // 将数组的第一个元素压入栈// 遍历数组的剩余元素for (int i = 1; i < nums.size(); i++) {push(nums[i], stack); // 处理数组的剩余元素}reverse(stack.begin(), stack.end()); // 将栈中的元素反转(从栈底到栈顶)// 将栈中的元素用空格拼接成字符串stringstream result;for (int num : stack) {result << num << " ";}string res = result.str();if (!res.empty()) {res.pop_back(); // 去掉最后一个多余的空格}return res;
}int main() {// 输入获取string input;getline(cin, input); // 读取一行输入stringstream ss(input);vector<int> nums;int num;while (ss >> num) {nums.push_back(num); // 将输入的数字存入数组}// 算法调用cout << getResult(nums) << endl;return 0;
}
C 语言代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 定义栈结构
typedef struct {int* data; // 栈数据int size; // 栈大小int capacity; // 栈容量
} Stack;// 初始化栈
void initStack(Stack* stack, int capacity) {stack->data = (int*)malloc(capacity * sizeof(int));stack->size = 0;stack->capacity = capacity;
}// 压栈操作
void pushStack(Stack* stack, int num) {if (stack->size >= stack->capacity) {stack->capacity *= 2; // 扩容stack->data = (int*)realloc(stack->data, stack->capacity * sizeof(int));}stack->data[stack->size++] = num;
}// 将元素压入栈,并根据规则处理
void push(int num, Stack* stack) {int total = num; // 初始化 total 为当前元素的值// 从栈顶向栈底遍历for (int i = stack->size - 1; i >= 0; i--) {total -= stack->data[i]; // 减去当前栈中的元素// 如果 total 等于 0,说明找到了一组连续的元素,其和等于当前元素if (total == 0) {stack->size = i; // 清除栈中从当前位置到栈顶的所有元素push(num * 2, stack); // 将当前元素的两倍压入栈return;} else if (total < 0) {// 如果 total 小于 0,说明无法找到满足条件的连续元素,退出循环break;}}// 如果没有找到满足条件的连续元素,直接将当前元素压入栈pushStack(stack, num);
}// 算法入口
char* getResult(int* nums, int numsSize) {Stack stack;initStack(&stack, numsSize); // 初始化栈pushStack(&stack, nums[0]); // 将数组的第一个元素压入栈// 遍历数组的剩余元素for (int i = 1; i < numsSize; i++) {push(nums[i], &stack); // 处理数组的剩余元素}// 反转栈中的元素(从栈底到栈顶)for (int i = 0; i < stack.size / 2; i++) {int temp = stack.data[i];stack.data[i] = stack.data[stack.size - 1 - i];stack.data[stack.size - 1 - i] = temp;}// 将栈中的元素用空格拼接成字符串char* result = (char*)malloc(1000 * sizeof(char));int pos = 0;for (int i = 0; i < stack.size; i++) {pos += sprintf(result + pos, "%d ", stack.data[i]);}if (pos > 0) {result[pos - 1] = '\0'; // 去掉最后一个多余的空格}free(stack.data); // 释放栈内存return result;
}int main() {// 输入获取char input[1000];fgets(input, 1000, stdin); // 读取一行输入int nums[1000];int numsSize = 0;char* token = strtok(input, " ");while (token != NULL) {nums[numsSize++] = atoi(token); // 将输入的数字存入数组token = strtok(NULL, " ");}// 算法调用char* result = getResult(nums, numsSize);printf("%s\n", result);free(result); // 释放结果内存return 0;
}
详细讲解
1. 输入获取
-
C++:
string input; getline(cin, input); // 读取一行输入 stringstream ss(input); vector<int> nums; int num; while (ss >> num) {nums.push_back(num); // 将输入的数字存入数组 }
- 使用
getline
读取一行输入。 - 使用
stringstream
将输入按空格分割并转换为整数。
- 使用
-
C:
char input[1000]; fgets(input, 1000, stdin); // 读取一行输入 int nums[1000]; int numsSize = 0; char* token = strtok(input, " "); while (token != NULL) {nums[numsSize++] = atoi(token); // 将输入的数字存入数组token = strtok(NULL, " "); }
- 使用
fgets
读取一行输入。 - 使用
strtok
将输入按空格分割并转换为整数。
- 使用
2. 压栈操作
-
C++:
void push(int num, vector<int>& stack) {int total = num;for (int i = stack.size() - 1; i >= 0; i--) {total -= stack[i];if (total == 0) {stack.erase(stack.begin() + i, stack.end());push(num * 2, stack);return;} else if (total < 0) {break;}}stack.push_back(num); }
- 使用
vector
模拟栈。 - 如果找到满足条件的连续元素,清除栈中元素并压入两倍值。
- 使用
-
C:
void push(int num, Stack* stack) {int total = num;for (int i = stack->size - 1; i >= 0; i--) {total -= stack->data[i];if (total == 0) {stack->size = i;push(num * 2, stack);return;} else if (total < 0) {break;}}pushStack(stack, num); }
- 使用自定义
Stack
结构模拟栈。 - 如果找到满足条件的连续元素,清除栈中元素并压入两倍值。
- 使用自定义
3. 算法入口
-
C++:
string getResult(vector<int>& nums) {vector<int> stack;stack.push_back(nums[0]);for (int i = 1; i < nums.size(); i++) {push(nums[i], stack);}reverse(stack.begin(), stack.end());stringstream result;for (int num : stack) {result << num << " ";}string res = result.str();if (!res.empty()) {res.pop_back();}return res; }
- 使用
vector
模拟栈。 - 反转栈并拼接成字符串。
- 使用
-
C:
char* getResult(int* nums, int numsSize) {Stack stack;initStack(&stack, numsSize);pushStack(&stack, nums[0]);for (int i = 1; i < numsSize; i++) {push(nums[i], &stack);}for (int i = 0; i < stack.size / 2; i++) {int temp = stack.data[i];stack.data[i] = stack.data[stack.size - 1 - i];stack.data[stack.size - 1 - i] = temp;}char* result = (char*)malloc(1000 * sizeof(char));int pos = 0;for (int i = 0; i < stack.size; i++) {pos += sprintf(result + pos, "%d ", stack.data[i]);}if (pos > 0) {result[pos - 1] = '\0';}free(stack.data);return result; }
- 使用自定义
Stack
结构模拟栈。 - 反转栈并拼接成字符串。
- 使用自定义
总结
-
功能:
- 处理数字数组,根据规则将元素压入栈。
- 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
-
优点:
- 使用栈结构,逻辑清晰。
- 适用于需要动态调整数据结构的场景。
-
适用场景:
- 适用于需要根据特定规则处理数组元素的场景。
如果您有其他问题,欢迎随时提问!
六、尾言
什么是华为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 或监考人员进行反馈。
祝你考试顺利,取得理想成绩!