华为OD机试(C卷+D卷)2024真题目录(Java & c++ & python)
题目描述
给一个正整数数列 nums,一个跳数 jump,及幸存数量 left。
运算过程为:从索引0的位置开始向后跳,中间跳过 J 个数字,命中索引为 J+1 的数字,该数被敲出,并从该点起跳,以此类推,直到幸存 left 个数为止,然后返回幸存数之和。
约束:
0是第一个起跳点
起跳点和命中点之间间隔 jump 个数字,已被敲出的数字不计入在内。
跳到末尾时无缝从头开始(循环查找),并可以多次循环。
若起始时 left > len(nums) 则无需跳数处理过程。
方法设计:
/**
- @param nums 正整数数列,长度范围 [1, 10000]
- @param jump 跳数,范围 [1, 10000]
- @param left 幸存数量,范围 [0, 10000]
- @return 幸存数之和
*/
int sumOfLeft(int[] nums, int jump, int left)
输入描述
第一行输入正整数数列
第二行输入跳数
第三行输入幸存数量
输出描述
输出幸存数之和
示例1
输入
1,2,3,4,5,6,7,8,9
4
3
输出
13
说明:从1(索引为0)开始起跳,中间跳过 4 个数字,因此依次删除 6,2,8,5,4,7。剩余1,3,9,返回和为13
解题思路
示例1中删点过程如下:
通过上面图示我们可以发现,被删除节点其实是作为起跳点,因此基于普通数组来操作的话,既要实现节点删除,又要实现基于删除点进行下次的起跳。
那么可以通过模拟实现。
参考代码
#include <iostream>
#include <vector>
#include <numeric> // For std::accumulate
using namespace std;
int sumOfLeft(vector<int> &nums, int jump, int left) {
int start = 1;
int n = nums.size();
while (n > left) {
start += jump;
start %= n;
nums.erase(nums.begin() + start);
--n; // 更新当前的节点数
}
return accumulate(nums.begin(), nums.end(), 0);
}
int main() {
// 示例用法
vector<int> nums = {1, 2, 3, 4, 5, 6, 7};
int jump = 2;
int left = 3;
cout << sumOfLeft(nums, jump, left) << endl;
return 0;
}