【2024年华为OD机试】 (C卷,100分)- 堆栈中的剩余数字(Java JS PythonC/C++)

在这里插入图片描述

一、问题描述

题目描述

向一个空栈中依次存入正整数,假设入栈元素 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

说明

题目解析

考察点

考察栈的操作和递归逻辑处理。

解析思路

  1. 初始化栈:创建一个空栈,用于存储入栈的元素。
  2. 遍历输入元素:按照输入顺序依次处理每个元素。
  3. 入栈前检查
    • 每当有新元素 num 将要入栈前,从栈顶开始遍历栈中的元素,尝试用 num 依次减去栈中的元素。
    • 如果在遍历过程中 num 变为 0,则说明找到了符合条件的元素序列,将这些元素全部出栈,并将 num * 2 入栈。
    • 如果遍历完栈中所有元素,num 仍未变为 0,则直接将 num 入栈。
  4. 递归处理
    • 当将 num * 2 入栈时,这个操作也是一个元素入栈的过程,因此需要递归地执行入栈前的检查逻辑。
    • 这意味着每次入栈新元素后,都需要重新检查栈顶元素是否满足条件,直到没有更多的元素可以合并为止。
  5. 输出结果:遍历完所有输入元素后,栈中剩余的元素即为最终结果。按照栈顶到栈底的顺序输出这些元素。

注意事项

  • 递归逻辑:每次入栈新元素(包括 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

总结

  1. 功能:

    • 处理数字数组,根据规则将元素压入栈。
    • 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
  2. 优点:

    • 使用数组模拟栈结构,逻辑清晰。
    • 适用于需要动态调整数据结构的场景。
  3. 适用场景:

    • 适用于需要根据特定规则处理数组元素的场景。

如果您有其他问题,欢迎随时提问!

三、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

总结

  1. 功能:

    • 处理整数数组,根据规则将元素压入栈。
    • 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
  2. 优点:

    • 使用栈结构,逻辑清晰。
    • 适用于需要动态调整数据结构的场景。
  3. 适用场景:

    • 适用于需要根据特定规则处理数组元素的场景。

如果您有其他问题,欢迎随时提问!

四、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

总结

  1. 功能:

    • 处理数字数组,根据规则将元素压入栈。
    • 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
  2. 优点:

    • 使用列表模拟栈结构,逻辑清晰。
    • 适用于需要动态调整数据结构的场景。
  3. 适用场景:

    • 适用于需要根据特定规则处理数组元素的场景。

如果您有其他问题,欢迎随时提问!

五、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 结构模拟栈。
    • 反转栈并拼接成字符串。

总结

  1. 功能:

    • 处理数字数组,根据规则将元素压入栈。
    • 如果找到一组连续的元素,其和等于当前元素,则清除这些元素,并将当前元素的两倍压入栈。
  2. 优点:

    • 使用栈结构,逻辑清晰。
    • 适用于需要动态调整数据结构的场景。
  3. 适用场景:

    • 适用于需要根据特定规则处理数组元素的场景。

如果您有其他问题,欢迎随时提问!

六、尾言

什么是华为OD?

华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。

为什么刷题很重要?

  1. 机试是进入技术面的第一关:
    华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。

  2. 技术面试需要手撕代码:
    技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。

  3. 入职后的可信考试:
    入职华为后,还需要通过“可信考试”。可信考试分为三个等级:

    • 入门级:主要考察基础算法与编程能力。
    • 工作级:更贴近实际业务需求,可能涉及复杂的算法或与工作内容相关的场景题目。
    • 专业级:最高等级,考察深层次的算法以及优化能力,与薪资直接挂钩。

刷题策略与说明:

2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:

  1. 关注历年真题:

    • 题库中的旧题占比较大,建议优先刷历年的A卷、B卷、C卷、D卷题目。
    • 对于每道题目,建议深度理解其解题思路、代码实现,以及相关算法的适用场景。
  2. 适应新题目:

    • E卷中包含全新题目,需要掌握全面的算法知识和一定的灵活应对能力。
    • 建议关注新的刷题平台或交流群,获取最新题目的解析和动态。
  3. 掌握常见算法:
    华为OD考试通常涉及以下算法和数据结构:

    • 排序算法(快速排序、归并排序等)
    • 动态规划(背包问题、最长公共子序列等)
    • 贪心算法
    • 栈、队列、链表的操作
    • 图论(最短路径、最小生成树等)
    • 滑动窗口、双指针算法
  4. 保持编程规范:

    • 注重代码的可读性和注释的清晰度。
    • 熟练使用常见编程语言,如C++、Java、Python等。

如何获取资源?

  1. 官方参考:

    • 华为招聘官网或相关的招聘平台会有一些参考信息。
    • 华为OD的相关公众号可能也会发布相关的刷题资料或学习资源。
  2. 加入刷题社区:

    • 找到可信的刷题交流群,与其他备考的小伙伴交流经验。
    • 关注知名的刷题网站,如LeetCode、牛客网等,这些平台上有许多华为OD的历年真题和解析。
  3. 寻找系统性的教程:

    • 学习一本经典的算法书籍,例如《算法导论》《剑指Offer》《编程之美》等。
    • 完成系统的学习课程,例如数据结构与算法的在线课程。

积极心态与持续努力:

刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。

考试注意细节

  1. 本地编写代码

    • 在本地 IDE(如 VS Code、PyCharm 等)上编写、保存和调试代码,确保逻辑正确后再复制粘贴到考试页面。这样可以减少语法错误,提高代码准确性。
  2. 调整心态,保持冷静

    • 遇到提示不足或实现不确定的问题时,不必慌张,可以采用更简单或更有把握的方法替代,确保思路清晰。
  3. 输入输出完整性

    • 注意训练和考试时都需要编写完整的输入输出代码,尤其是和题目示例保持一致。完成代码后务必及时调试,确保功能符合要求。
  4. 快捷键使用

    • 删除行可用 Ctrl+D,复制、粘贴和撤销分别为 Ctrl+CCtrl+VCtrl+Z,这些可以正常使用。
    • 避免使用 Ctrl+S,以免触发浏览器的保存功能。
  5. 浏览器要求

    • 使用最新版的 Google Chrome 浏览器完成考试,确保摄像头开启并正常工作。考试期间不要切换到其他网站,以免影响考试成绩。
  6. 交卷相关

    • 答题前,务必仔细查看题目示例,避免遗漏要求。
    • 每完成一道题后,点击【保存并调试】按钮,多次保存和调试是允许的,系统会记录得分最高的一次结果。完成所有题目后,点击【提交本题型】按钮。
    • 确保在考试结束前提交试卷,避免因未保存或调试失误而丢分。
  7. 时间和分数安排

    • 总时间:150 分钟;总分:400 分。
    • 试卷结构:2 道一星难度题(每题 100 分),1 道二星难度题(200 分)。及格分为 150 分。合理分配时间,优先完成自己擅长的题目。
  8. 考试环境准备

    • 考试前请备好草稿纸和笔。考试中尽量避免离开座位,确保监控画面正常。
    • 如需上厕所,请提前规划好时间以减少中途离开监控的可能性。
  9. 技术问题处理

    • 如果考试中遇到断电、断网、死机等技术问题,可以关闭浏览器并重新打开试卷链接继续作答。
    • 出现其他问题,请第一时间联系 HR 或监考人员进行反馈。

祝你考试顺利,取得理想成绩!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/67331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java安全—SPEL表达式XXESSTI模板注入JDBCMyBatis注入

前言 之前我们讲过SpringBoot中的MyBatis注入和模板注入的原理&#xff0c;那么今天我们就讲一下利用以及发现。 这里推荐两个专门研究java漏洞的靶场&#xff0c;本次也是根据这两个靶场来分析代码&#xff0c;两个靶场都是差不多的。 https://github.com/bewhale/JavaSec …

51单片机入门基础

目录 一、基础知识储备 &#xff08;一&#xff09;了解51单片机的基本概念 &#xff08;二&#xff09;掌握数字电路基础 &#xff08;三&#xff09;学习C语言编程基础 二、开发环境搭建 &#xff08;一&#xff09;硬件准备 &#xff08;二&#xff09;软件准备 三、…

基于Java的百度AOI数据解析与转换的实现方法

目录 前言 一、AOI数据结构简介 1、官网的实例接口 2、响应参数介绍 二、Java对AOI数据的解析 1、数据解析流程图 2、数据解析实现 3、AOI数据解析成果 三、总结 前言 在当今信息化社会&#xff0c;地理信息数据在城市规划、交通管理、商业选址等领域扮演着越来越重要的…

【WEB】网络传输中的信息安全 - 加密、签名、数字证书与HTTPS

文章目录 1. 概述2. 网络传输安全2.1.什么是中间人攻击2.2. 加密和签名2.2.1.加密算法2.2.2.摘要2.2.3.签名 2.3.数字证书2.3.1.证书的使用2.3.2.根证书2.3.3.证书链 2.4.HTTPS 1. 概述 本篇主要是讲解讲一些安全相关的基本知识&#xff08;如加密、签名、证书等&#xff09;&…

shell练习2

需求&#xff1a;判断192.168.1.0/24网络中&#xff0c;当前在线的ip有哪些&#xff0c;并编写脚本打印出来。 #!/bin/bashnmap -sn 192.168.1.0/24 | grep Nmap scan report for | awk {print $5} 注意&#xff1a;当运行 bash ip.sh 时出现 nmap: command not found 的错误…

【运维自动化-作业平台】魔法变量到底如何使用之主机列表类型

蓝鲸作业平台&#xff0c;以下简称作业平台或JOB平台 魔法变量&#xff1a;JOB平台执行引擎提供的特有的变量能力用法 脚本中使用&#xff0c;并且需要事先声明&#xff1a;job_import {{变量名}} 声明后&#xff0c;同样是使用 dollar 符 大括号&#xff1a;${变量名}来取值…

活动预告 | CCF开源发展委员会开源供应链安全技术研讨会(2025第一期)——“大模型时代的开源供应链安全风控技术”...

点击蓝字 关注我们 CCF Opensource Development Committee CCF开源发展委员会开源供应链安全工作组&#xff08;以下简称CCF-ODC-OSS&#xff09;将于1月17日下午在北京黄大年茶思屋举行2025年第一期开源供应链安全技术研讨会&#xff0c;此次研讨会主题为“大模型时代的开源供…

XML序列化和反序列化的学习

1、基本介绍 在工作中&#xff0c;经常为了调通上游接口&#xff0c;从而对请求第三方的参数进行XML序列化&#xff0c;这里常使用的方式就是使用JAVA扩展包中的相关注解和类来实现xml的序列化和反序列化。 2、自定义工具类 import javax.xml.bind.JAXBContext; import javax.x…

基于php求职招聘系统设计

基于php求职招聘系统设计 摘要 随着社会信息化时代的到来&#xff0c;如今人们社会的生活节奏普遍加快&#xff0c;人们对于工作效率的要求也越来越高&#xff0c;企业 举办招聘会耗时耗财&#xff0c;个人参加招聘会漫无目的寻找不到“方向”&#xff0c;网络搜索工作量目的…

SDK调用文心一言如何接入,文心一言API接入教程

一、前期准备 注册百度智能云账号&#xff1a; 前往百度智能云官网注册一个账号。这是接入文心一言API的基础。 了解API接口&#xff1a; 在百度智能云开放平台中&#xff0c;找到文心一言API的详情页&#xff0c;了解提供的API接口类型&#xff08;如云端API、移动端API、离线…

【机器学习】数据拟合-最小二乘法(Least Squares Method)

最小二乘法&#xff08;Least Squares Method&#xff09; 最小二乘法是一种广泛使用的数据拟合方法&#xff0c;用于在统计学和数学中找到最佳拟合曲线或模型&#xff0c;使得观测数据点与模型预测值之间的误差平方和最小化。以下是详细介绍&#xff1a; 基本概念 假设有一组…

Flutter 多终端测试 自定义启动画面​​​​​​​ 更换小图标和应用名称

多终端测试 flutter devices flutter run -d emulator-5554 flutter run -d emulator-5556 自定义启动画面 之前&#xff1a; 进入assert 3x 生成 1x 2x dart run flutter_native_splash:create dart run flutter_native_splash:remove 现在&#xff08;flutter_nativ…

springMVC实现文件上传

目录 一、创建项目 二、引入依赖 三、web.xml 四、编写上传文件的jsp页面 五、spring-mvc.xml 六、controller 七、运行 一、创建项目 二、引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.o…

Java内存与缓存

Java内存管理和缓存机制是构建高性能应用程序的关键要素。它们之间既有联系又有区别&#xff0c;理解这两者对于优化Java应用至关重要。 Java 内存模型 Java内存模型&#xff08;JMM&#xff09;定义了线程如何以及何时可以看到其他线程修改过的共享变量的值&#xff0c;并且规…

图片和短信验证码(头条项目-06)

1 图形验证码接口设计 将后端⽣成的图⽚验证码存储在redis数据库2号库。 结构&#xff1a; {img_uuid:0594} 1.1 创建验证码⼦应⽤ $ cd apps $ python ../../manage.py startapp verifications # 注册新应⽤ INSTALLED_APPS [django.contrib.admin,django.contrib.auth,…

云服务信息安全管理体系认证,守护云端安全

在数据驱动的时代&#xff0c;云计算已成为企业业务的超级引擎&#xff0c;推动着企业飞速发展。然而&#xff0c;随着云计算的广泛应用&#xff0c;信息安全问题也日益凸显&#xff0c;如同暗流涌动下的礁石&#xff0c;时刻威胁着企业的航行安全。这时&#xff0c;云服务信息…

LabVIEW与WPS文件格式的兼容性

LabVIEW 本身并不原生支持将文件直接保存为 WPS 格式&#xff08;如 WPS 文档或表格&#xff09;。然而&#xff0c;可以通过几种间接的方式实现这一目标&#xff0c;确保您能将 LabVIEW 中的数据或报告转换为 WPS 可兼容的格式。以下是几种常见的解决方案&#xff1a; ​ 导出…

创建 WordPress 插件(第一部分):添加管理页面

WordPress 是互联网上最受欢迎的内容管理系统之一。它是用 PHP 创建的&#xff0c;可以处理从博客到商业网站的一切需求。事实上&#xff0c;我们的博客和网站都使用 WordPress。在本文中&#xff0c;我将向你展示如何创建一个 WordPress 插件&#xff0c;该插件会在管理员控制…

解锁企业数据管理统一身份认证难题,EasyMR助力企业敏捷提效

在数字经济迅猛发展的当下&#xff0c;企业数据量正以令人惊叹的速度持续增长。据IDC研究显示&#xff0c;至2025年&#xff0c;全球数据总量预计将超175 ZB。数据的爆发式增长对企业而言&#xff0c;既是机遇&#xff0c;更是巨大挑战。 如今&#xff0c;大数据已然成为企业决…

OPT: Open Pre-trained Transformer语言模型

摘要 大规模语言模型通常需要数十万计算日的训练时间&#xff0c;展现了在零样本和小样本学习中的显著能力。鉴于其计算成本之高&#xff0c;这些模型在没有大量资本投入的情况下难以复现。对于那些通过API提供的少数模型&#xff0c;研究者无法获取完整的模型权重&#xff0c…