华为OD机试 - 最少交换次数 - 感谢@on your left反馈(Python/JS/C/C++ 2025 A卷 100分)

在这里插入图片描述

2025华为OD机试题库(按算法分类):2025华为OD统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

感谢@on your left反馈,2025-04-01,A卷100分考试真题。

在这里插入图片描述

一、题目描述

给出数字K,请输出所有小于K的整数组合到一起的最小交换次数。

组合一起是指满足条件的数字相邻,不要求相邻后在数组中的位置。

取值范围:

-100 <= K <= 100

-100 <= 数组中的数值 <= 100

二、输入描述

第一行输入数组:1 3 1 4 0

第二行输入K数值:2

三、输出描述

第一行输出的最少交换次数:1

四、测试用例

测试用例1

1、输入

2 1 5 6 1
2

2、输出

1

3、说明

小于 2 的数字有 1, 1(共 2 个)。

滑动窗口法可得最少交换次数为 1。

测试用例2

1、输入

2 7 9 5 8 7 4
5

2、输出

1

3、说明

小于 5 的数字有 2, 4(共 2 个)。
通过滑动窗口法得到最小交换次数为 1。

五、解题思路

利用滑动窗口的思想,窗口大小为所有小于K的整数,然后窗口中大于K的整数是需要替换的次数。

详细解题思路

  1. 读取输入的整数数组和目标数值K;
  2. 统计数组中小于K的整数个数,记为count;
  3. 如果count为1,表示只有一个小于K的整数,不需要交换,直接输出0;
  4. 初始化最小交换次数minSwapCount为0;
  5. 遍历数组前count个元素,如果元素大于等于K,将minSwapCount加1;
  6. 将minSwapCount赋值给临时变量temp;
  7. 从第count个元素开始遍历数组,记当前元素为nums[j],前一个元素为nums[l],后一个元素为nums[r],其中l = j - count,r = j;
  8. 如果nums[l]大于等于K且nums[r]小于K,表示交换nums[l]和nums[r]可以减少一次交换次数,将temp减1;
  9. 如果nums[l]小于K且nums[r]大于等于K,表示交换nums[l]和nums[r]可以增加一次交换次数,将temp加1;
  10. 更新最小交换次数minSwapCount为min(minSwapCount, temp),保留较小的值;
  11. 输出最小交换次数minSwapCount;

六、Python算法源码

# 定义函数计算将所有小于K的数字组合在一起所需的最少交换次数
def min_swaps_to_group(nums, k):
    # 统计数组中小于k的元素数量
    count = sum(1 for num in nums if num < k)
    
    # 如果没有或只有一个满足条件的数字,则无需交换
    if count <= 1:
        return 0
    
    # 计算初始窗口(前count个元素)中不满足条件(>=k)的数字数量
    bad = sum(1 for num in nums[:count] if num >= k)
    min_swaps = bad  # 初始化最小交换次数为初始窗口中的bad数量
    
    # 使用滑动窗口遍历数组,窗口大小为count
    for i in range(1, len(nums) - count + 1):
        # 如果移出窗口的数字大于等于k,则bad数量减少1
        if nums[i - 1] >= k:
            bad -= 1
        # 如果新进入窗口的数字大于等于k,则bad数量增加1
        if nums[i + count - 1] >= k:
            bad += 1
        # 更新最小交换次数
        min_swaps = min(min_swaps, bad)
    
    return min_swaps

if __name__ == '__main__':
    # 从输入中读取数字数组(空格分隔)
    nums = list(map(int, input().split()))
    # 从输入中读取k值
    k = int(input())
    # 输出最少交换次数
    print(min_swaps_to_group(nums, k))

七、JavaScript算法源码

// 定义函数计算将所有小于K的数字组合在一起所需的最少交换次数
function minSwapsToGroup(nums, k) {
    // 统计数组中小于k的元素数量
    let count = nums.filter(num => num < k).length;
    
    // 如果没有或只有一个满足条件的数字,则不需要交换
    if (count <= 1) {
        return 0;
    }
    
    // 计算初始窗口(前count个元素)中不满足条件(>=k)的数字数量
    let bad = 0;
    for (let i = 0; i < count; i++) {
        if (nums[i] >= k) {
            bad++;
        }
    }
    
    let minSwaps = bad; // 初始化最小交换次数
    
    // 使用滑动窗口遍历数组,窗口大小为count
    for (let i = 1; i <= nums.length - count; i++) {
        // 如果移出窗口的数字大于等于k,则bad数量减少1
        if (nums[i - 1] >= k) {
            bad--;
        }
        // 如果新进入窗口的数字大于等于k,则bad数量增加1
        if (nums[i + count - 1] >= k) {
            bad++;
        }
        // 更新最小交换次数
        minSwaps = Math.min(minSwaps, bad);
    }
    
    return minSwaps;
}

// 示例:假设有输入字符串和K值(根据不同环境,可用prompt()等方式获取输入)
const inputLine = "1 3 1 4 0";  // 测试用例输入的数组字符串
const kValue = 2;               // 测试用例K值

// 将输入字符串转换为数字数组
const nums = inputLine.split(" ").map(Number);

// 输出计算结果
console.log(minSwapsToGroup(nums, kValue));

八、C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 函数:计算将所有小于K的数字组合在一起所需的最少交换次数
int minSwapsToGroup(int* nums, int n, int k) {
    int count = 0;
    // 统计数组中小于k的元素数量
    for (int i = 0; i < n; i++) {
        if (nums[i] < k)
            count++;
    }
    
    // 如果没有或只有一个满足条件的数字,则无需交换
    if (count <= 1)
        return 0;
    
    int bad = 0;
    // 计算初始窗口(前count个元素)中不满足条件(>=k)的数字数量
    for (int i = 0; i < count; i++) {
        if (nums[i] >= k)
            bad++;
    }
    
    int minSwaps = bad;
    
    // 使用滑动窗口遍历数组,窗口大小为count
    for (int i = 1; i <= n - count; i++) {
        // 如果移出窗口的数字大于等于k,则bad数量减少1
        if (nums[i - 1] >= k)
            bad--;
        // 如果新进入窗口的数字大于等于k,则bad数量增加1
        if (nums[i + count - 1] >= k)
            bad++;
        if (bad < minSwaps)
            minSwaps = bad;
    }
    
    return minSwaps;
}

int main() {
    char line[1024];
    // 从标准输入读取一行字符串(数组数字,以空格分隔)
    fgets(line, sizeof(line), stdin);
    
    int nums[1000];
    int n = 0;
    // 使用strtok分割字符串,转换为整数数组
    char* token = strtok(line, " \n");
    while (token != NULL) {
        nums[n++] = atoi(token);
        token = strtok(NULL, " \n");
    }
    
    int k;
    // 读取K值
    scanf("%d", &k);
    
    // 计算最少交换次数并输出结果
    printf("%d\n", minSwapsToGroup(nums, n, k));
    
    return 0;
}

九、C++算法源码

#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;

// 函数:计算将所有小于K的数字组合在一起所需的最少交换次数
int minSwapsToGroup(const vector<int>& nums, int k) {
    int n = nums.size();
    int count = 0;
    // 统计数组中小于k的元素数量
    for (int num : nums) {
        if (num < k)
            count++;
    }
    
    // 如果没有或只有一个满足条件的数字,则不需要交换
    if (count <= 1)
        return 0;
    
    int bad = 0;
    // 计算初始窗口(前count个元素)中不满足条件(>=k)的数字数量
    for (int i = 0; i < count; i++) {
        if (nums[i] >= k)
            bad++;
    }
    
    int minSwaps = bad;
    
    // 使用滑动窗口遍历数组,窗口大小为count
    for (int i = 1; i <= n - count; i++) {
        // 如果移出窗口的数字大于等于k,则bad数量减少1
        if (nums[i - 1] >= k)
            bad--;
        // 如果新进入窗口的数字大于等于k,则bad数量增加1
        if (nums[i + count - 1] >= k)
            bad++;
        minSwaps = min(minSwaps, bad);
    }
    
    return minSwaps;
}

int main() {
    string line;
    // 从标准输入读取一行字符串(数字,以空格分隔)
    getline(cin, line);
    stringstream ss(line);
    vector<int> nums;
    int num;
    // 将字符串中的数字读入vector中
    while (ss >> num) {
        nums.push_back(num);
    }
    
    int k;
    // 读取K值
    cin >> k;
    
    // 输出最少交换次数
    cout << minSwapsToGroup(nums, k) << endl;
    
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2025 A卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

### 华为OD机试糖果问题的Python解题思路 #### 问题描述 小明从糖果盒中随意抓取一定数量的糖果,每次可以执行三种操作之一:取出一半糖果并舍去余数;如果当前糖果数目为奇数,则可以从盒子中再拿一个糖果或将手里的一个糖果放回去。目标是最少经过几次这样的操作能够使手中的糖果变为一颗。 为了达到这个目的,采用贪心策略来解决问题[^3]。具体来说,在每一步都尽可能快速地减少糖果的数量直到只剩下一颗为止。当遇到奇数个糖果时,优先考虑加一而不是减一,因为这样可以在下一轮更有效地通过除以2的方式大量削减糖果总数。 #### 贪婪算法析 对于任意正整数n表示初始糖果数: - 如果 n 是偶数,则直接将其除以2; - 若 n 为奇数,则判断 (n+1)/2 和 (n−1)/2 的大小关系,选择较小的那个作为下一步的结果,这是因为我们希望更快接近1。 这种做法基于这样一个事实——当我们面对两个连续的奇数值时,较大的那个总是可以通过增加1变成一个小得多的新值(即其半数),而较小的一个则需要两次操作才能完成同样的效果(先减后除)[^4]。 #### Python代码实现 下面给出了解决上述问题的具体Python程序: ```python def min_steps_to_one(n): steps = 0 while n != 1: if n % 2 == 0: n //= 2 elif ((n + 1) // 2) < ((n - 1) // 2): n += 1 else: n -= 1 steps += 1 return steps if __name__ == "__main__": candy_count = int(input().strip()) print(min_steps_to_one(candy_count)) ``` 此函数接收一个参数`n`代表起始的糖果数量,并返回将这些糖果减少到只有一个所需的最小步数。主程序部读入用户输入的数据并调用该方法打印最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值