华为OD机试 - 小朋友分组最少调整次数 - 贪心算法(Python/JS/C/C++ 2024 E卷 100分)
华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
n (3 ≤ n ≤ 90000 且可以整除 3) 个学生排成一排,学生编号分别是 1 到 n,n 为 3 的整数倍数,老师随机抽签决定将所有学生分成 m 个 3 人的小组(n = 3 * m)。
为了便于同组学生交流,老师决定将小组成员安排到一起,也就是同组成员彼此相连,同组任意两个成员之间无其它组的成员。
因此老师决定调整队伍,老师每次可以调整任意一名学生到队伍的任意位置,计为调整了一次,请计算最少调整多少次可以达到目标。
注意:对于小组之间没有顺序要求,同组学生之间没有顺序要求。
二、输入描述
第一行输入初始排列顺序序列
第二行输入分组排列顺序序列
三、输出描述
输出一个整数k,表示至少调整k次。
四、测试用例
测试用例1:
1、输入
4 2 8 5 3 6 1 9 7
6 3 1 2 4 8 7 9 5
2、输出
1
3、说明
只有一个组(例如 [4, 2, 8] 对应的组号)需要调整位置,使其成员在最终排列中相邻。这意味着只需要一次调整就能实现目标排列。因此,输出结果为 1,表示至少需要一次调整。
测试用例2:
1、输入
8 9 7 5 6 3 2 1 4
7 8 9 4 2 1 3 5 6
2、输出
0
3、说明
每组3个学生的编号在初始排列和目标排列中的组号顺序已经是对应的,并且组内成员在初始排列中已经彼此相邻。
通过检查可以发现,每个组的成员在初始排列中已经满足相邻的条件,因此不需要进行任何调整。
五、解题思路
这道题的目的是通过最少的调整次数,将一组学生按照指定的目标顺序排列,使得同组的学生在最终排列中彼此相连。题目的核心在于寻找一种策略,能够有效地将学生移动到合适的位置,同时最小化移动次数。
在计算调整次数时,采用了一种贪心的策略,优先处理需要最少调整的情况(如两两交换),从而减少整体调整次数。
(1)将学生编号映射为组号:
我们的目标是将学生编号转化为组号。因为每个组有3个学生,我们可以通过将目标排列中的每个学生编号映射到其组号(即编号除以3)来得到初始序列中每个学生的目标组号。
(2)记录组号的位置:
我们需要记录每个组号在初始排列中的位置。为此,我们创建一个数组列表,每个列表存储对应组号在初始排列中出现的位置。
(3)计算最少调整次数:
我们通过遍历每个组的位置列表来计算是否需要调整。如果一个组的所有成员在初始序列中已经连续排列,那么不需要调整;否则,需要进行一次调整。
如果一个组只有一个成员,则需要两次调整,因为要将其与另两个成员排在一起。如果有两个成员且它们间隔较大,也需要一次调整。
(4)计算组间交错:
为了避免多余的调整,计算组间的交错情况。如果一个组的成员之间有其他组的成员插入,这表明需要额外的调整。通过遍历整个组号序列,记录每个组号的出现次数,我们可以发现是否存在组间交错,并调整次数。
(5)输出最小调整次数:
最后,我们取前述计算出的两种调整方法的最小值作为最终的最小调整次数。
六、Python算法源码
# 导入必要的模块
import sysdef main():# 读取输入的初始排列顺序initial_order = list(map(int, sys.stdin.readline().strip().split()))# 读取输入的目标排列顺序target_order = list(map(int, sys.stdin.readline().strip().split()))student_count = len(initial_order)group_count = student_count // 3# 创建一个映射数组,将学生编号映射到目标序列中的组号group_mapping = [0] * (student_count + 1)for i in range(student_count):group_mapping[target_order[i]] = i // 3# 将初始顺序转换为组号数组group_order = [group_mapping[student] for student in initial_order]# 创建一个列表数组,用于存储每个组号在初始序列中出现的位置group_positions = [[] for _ in range(group_count)]for i, group in enumerate(group_order):group_positions[group].append(i)minimum_moves = 0# 遍历每个组的位置列表,计算需要的最少移动次数for positions in group_positions:if len(positions) == 3:# 如果一个组有3个成员,检查他们是否连续if positions[1] - positions[0] > 1 or positions[2] - positions[1] > 1:minimum_moves += 1elif len(positions) == 2:# 如果一个组有2个成员,检查他们是否间隔过大if positions[1] - positions[0] > 2:minimum_moves += 1elif len(positions) == 1:# 如果一个组只有1个成员,最坏情况需要两次调整minimum_moves += 2# 通过计算组间的交错情况,可能减少调整次数encountered_groups = set()overlap_adjustments = 0for group in group_order:if group not in encountered_groups:encountered_groups.add(group)else:overlap_adjustments += 1# 取两种调整方法的最小值minimum_moves = min(minimum_moves, overlap_adjustments)# 输出最小调整次数print(minimum_moves)# 调用主函数
if __name__ == "__main__":main()
七、JavaScript算法源码
// 使用Node.js的readline模块读取输入
const readline = require('readline');const rl = readline.createInterface({input: process.stdin,output: process.stdout
});let inputLines = [];rl.on('line', (line) => {inputLines.push(line.trim());if (inputLines.length === 2) {rl.close();}
});rl.on('close', () => {// 读取初始排列顺序const initialOrder = inputLines[0].split(' ').map(Number);// 读取目标排列顺序const targetOrder = inputLines[1].split(' ').map(Number);const studentCount = initialOrder.length;const groupCount = studentCount / 3;// 创建一个映射数组,将学生编号映射到目标序列中的组号const groupMapping = new Array(studentCount + 1).fill(0);for (let i = 0; i < studentCount; i++) {groupMapping[targetOrder[i]] = Math.floor(i / 3);}// 将初始顺序转换为组号数组const groupOrder = initialOrder.map(student => groupMapping[student]);// 创建一个数组列表的数组,用于存储每个组号在初始序列中出现的位置const groupPositions = Array.from({length: groupCount}, () => []);for (let i = 0; i < groupOrder.length; i++) {groupPositions[groupOrder[i]].push(i);}let minimumMoves = 0;// 遍历每个组的位置列表,计算需要的最少移动次数for (const positions of groupPositions) {if (positions.length === 3) {// 如果一个组有3个成员,检查他们是否连续if (positions[1] - positions[0] > 1 || positions[2] - positions[1] > 1) {minimumMoves++;}} else if (positions.length === 2) {// 如果一个组有2个成员,检查他们是否间隔过大if (positions[1] - positions[0] > 2) {minimumMoves++;}} else if (positions.length === 1) {// 如果一个组只有1个成员,最坏情况需要两次调整minimumMoves += 2;}}// 通过计算组间的交错情况,可能减少调整次数const encounteredGroups = new Set();let overlapAdjustments = 0;for (const group of groupOrder) {if (!encounteredGroups.has(group)) {encounteredGroups.add(group);} else {overlapAdjustments++;}}// 取两种调整方法的最小值minimumMoves = Math.min(minimumMoves, overlapAdjustments);// 输出最小调整次数console.log(minimumMoves);
});
八、C算法源码
#include <stdio.h>
#include <stdlib.h>// 主函数
int main() {// 定义变量int n = 0;int initialOrder[90000];int targetOrder[90000];// 读取初始排列顺序while (scanf("%d", &initialOrder[n]) != EOF && getchar() != '\n') {n++;}// 读取目标排列顺序int m = 0;while (scanf("%d", &targetOrder[m]) != EOF && getchar() != '\n') {m++;}// 计算组数int groupCount = n / 3;// 创建组映射数组,将学生编号映射到组号int *groupMapping = (int *)malloc((n + 1) * sizeof(int));for (int i = 0; i < m; i++) {groupMapping[targetOrder[i]] = i / 3;}// 将初始顺序转换为组号数组int groupOrder[90000];for (int i = 0; i < n; i++) {groupOrder[i] = groupMapping[initialOrder[i]];}// 创建组位置数组int **groupPositions = (int **)malloc(groupCount * sizeof(int *));int *counts = (int *)calloc(groupCount, sizeof(int));for (int i = 0; i < groupCount; i++) {groupPositions[i] = (int *)malloc(3 * sizeof(int));}// 记录每个组的位置for (int i = 0; i < n; i++) {int group = groupOrder[i];groupPositions[group][counts[group]++] = i;}int minimumMoves = 0;// 遍历每个组,计算调整次数for (int i = 0; i < groupCount; i++) {if (counts[i] == 3) {if (groupPositions[i][1] - groupPositions[i][0] > 1 || groupPositions[i][2] - groupPositions[i][1] > 1) {minimumMoves++;}} else if (counts[i] == 2) {if (groupPositions[i][1] - groupPositions[i][0] > 2) {minimumMoves++;}} else if (counts[i] == 1) {minimumMoves += 2;}}// 计算组间的交错情况int *encounteredGroups = (int *)calloc(groupCount, sizeof(int));int overlapAdjustments = 0;for (int i = 0; i < n; i++) {int group = groupOrder[i];if (!encounteredGroups[group]) {encounteredGroups[group] = 1;} else {overlapAdjustments++;}}// 取最小调整次数if (overlapAdjustments < minimumMoves) {minimumMoves = overlapAdjustments;}// 输出结果printf("%d\n", minimumMoves);// 释放内存free(groupMapping);for (int i = 0; i < groupCount; i++) {free(groupPositions[i]);}free(groupPositions);free(counts);free(encounteredGroups);return 0;
}
九、C++算法源码
#include <bits/stdc++.h>
using namespace std;int main(){ios::sync_with_stdio(false);cin.tie(0);// 读取初始排列顺序vector<int> initialOrder;string line;getline(cin, line);stringstream ss(line);int num;while(ss >> num){initialOrder.push_back(num);}// 读取目标排列顺序vector<int> targetOrder;getline(cin, line);stringstream ss2(line);while(ss2 >> num){targetOrder.push_back(num);}int n = initialOrder.size();int groupCount = n / 3;// 创建组映射数组,将学生编号映射到组号vector<int> groupMapping(n+1, 0);for(int i=0;i<n;i++){groupMapping[targetOrder[i]] = i / 3;}// 将初始顺序转换为组号数组vector<int> groupOrder(n, 0);for(int i=0;i<n;i++){groupOrder[i] = groupMapping[initialOrder[i]];}// 创建组位置数组vector<vector<int>> groupPositions(groupCount, vector<int>());for(int i=0;i<n;i++){groupPositions[groupOrder[i]].push_back(i);}int minimumMoves = 0;// 遍历每个组,计算调整次数for(auto &positions : groupPositions){if(positions.size() == 3){if(positions[1] - positions[0] > 1 || positions[2] - positions[1] > 1){minimumMoves++;}}else if(positions.size() == 2){if(positions[1] - positions[0] > 2){minimumMoves++;}}else if(positions.size() == 1){minimumMoves += 2;}}// 计算组间的交错情况unordered_set<int> encounteredGroups;int overlapAdjustments = 0;for(auto &group : groupOrder){if(encounteredGroups.find(group) == encounteredGroups.end()){encounteredGroups.insert(group);}else{overlapAdjustments++;}}// 取最小调整次数minimumMoves = min(minimumMoves, overlapAdjustments);// 输出结果cout << minimumMoves;return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
相关文章:

华为OD机试 - 小朋友分组最少调整次数 - 贪心算法(Python/JS/C/C++ 2024 E卷 100分)
华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Python/JS/C/C)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,…...

数字农业与遥感监测平台
随着全球人口的增长和气候变化的挑战,农业的可持续发展变得尤为重要。数字农业作为现代农业发展的重要方向,正逐渐成为提高农业生产效率、保障粮食安全的关键手段。遥感技术作为数字农业的重要组成部分,通过监测作物生长状况、土壤湿度、病虫…...

2023年12月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 + 解析
一、单选题 1、下列程序运行的结果是?( ) print(hello) print(world) A.helloworld B.hello world C.hello world D.helloworld 正确答案:B 答案解析:本题考察的 Python 编程基础,print 在打印时…...

【优选算法】——双指针(下篇)!
🌈个人主页:秋风起,再归来~ 🔥系列专栏:C刷题算法总结 🔖克心守己,律己则安 目录 1、有效三角形的个数 2、查找总价值为目标值的两个商品 3、三数之和 4、四数之和 5、完结散花 1、有…...
C#中函数重载的说明
一.函数重载的基本概念 C# 中的函数重载是指在同一个类中定义多个同名的函数,但这些函数的参数类型、参数个数、参数顺序等不同,以便适应不同的调用需求,增加代码的兼容性。 二.函数重载的作用 2.1定义多个相类似的函数,减少函…...

图论day56|广度优先搜索理论基础 、bfs与dfs的对比(思维导图)、 99.岛屿数量(卡码网)、100.岛屿的最大面积(卡码网)
图论day56|广度优先搜索理论基础 、bfs与dfs的对比(思维导图)、 99.岛屿数量(卡码网)、100.岛屿的最大面积(卡码网)) 广度优先搜索理论基础bfs与dfs的对比(思维导图)&…...

源码编译方式安装htppd软件
一.源码编译安装httpd软件 1.安装阿帕奇的依赖,安装apr软件,阿帕奇正常运行的环境这个环境就是apr。 2.安装apr-util软件,主要提供针对apr环境的管理工具, 3.安装阿帕奇软件即httpd软件。 如上图所示,就是三个软件的…...

MES制造执行系统原型图动端 Axure原型 交互设计 Axure实战项目
MES制造执行系统原型移动端 Manufacturing Execution System prototype MES制造执行系统原型图移动端是专门为制造执行系统设计的移动端是一个可视化的设计。用于展示和演示该系统在移动设备上的功能和界面。通过原型图,可以清晰地了解制造执行系统在移动端的各个…...

flutter 仿淘宝推荐二级分类效果
先看效果 一开始 用的PageView 做的, 然后重写PageScrollPhysics一顿魔改, 最后发现还是有一些小bug。 后面又想到pageview 能做,listview肯定也能做,最后用ListView加GridView 把功能实现了。 listview 实现pageview 的分页滑动…...
报错 - LangChain AgentExecutor - ‘function‘ object has no attribute ‘get‘
使用 AgentExecutor 调用了使用两个 tool 的agent,报一下错误: 如果 agent 只使用 一个tool,没有报错 File "/Users/xx/miniconda3/envs/env1/lib/python3.11/site-packages/pydantic/_internal/_validators.py", line 44, in sequ…...
【DIY小记】通过降低电压和Process Lasso工具优化CPU超频表现
又到了创作纪念日,秉承着笔耕不辍的理念,笔者还是继续分享一下DIY日常。 在上一篇文章当中,笔者介绍了一些作为新手小白超频CPU和NVIDIA显卡的经验。今天又有了更新,笔者通过降低CPU工作电压,并且结合Process Lasso对…...

3、Docker搭建MQTT及Spring Boot 3.x集成MQTT
一、前言 本篇主要是围绕着两个点,1、Docker 搭建单机版本 MQTT(EMQX),2、Spring Boot 3.x 集成 MQTT(EMQX); 而且这里的 MQTT(EMQX)的搭建也只是一个简单的过程&#x…...
六种定时任务记录
1、java自带的Timer Timer是java中自带的类。 优点:使用简单,缺点是当添加并执行多个任务时,前面任务的执行用时和异常将影响到后面任务。 Timer timer new Timer();timer.schedule(new TimerTask() {int i 0;Overridepublic void run() …...

Dos下编译环境搭建和C运行程序生成
文章目录 前言一、需要准备的Tool二、搭建步骤 前言 因为工作需要,需要搭建个Dos下的编译环境来进行Code App开发,如下记录下搭建过程。 一、需要准备的Tool 编译环境:Win10/win11 编译工具: DOSBox0.74 Turboc2.7z 二、搭建步骤 1.双击压…...
【MySQL】入门篇—SQL基础:数据查询语言(DQL):复杂的SELECT语句
在实际应用中,复杂的SELECT语句可以帮助我们从多个表中提取相关信息,进行数据分析,生成报告,甚至进行数据挖掘。 掌握复杂的SELECT语句对于数据分析师、数据库管理员和开发者来说是必不可少的技能。 应用场景: 多表查…...

Appium环境搭建、Appium连接真机
文章目录 一、安装Android SDK二、安装Appium-desktop三、安装Appium Inspector 一、安装Android SDK 首先需要安装jdk,这里就不演示安装jdk的过程了 SDK下载地址:Android SDK 下载 1、点击 Android SDK 下载 -> SKD Tools 2、选择对应的版本进行下…...

【X线源】关于滨松MCS2软件的说明
【X线源】关于滨松MCS2软件的说明 1.软件背景2.MCS2界面3.MCS2操作4.常见问题 1.软件背景 滨松为了方便客户将滨松MFX集成进自己的系统,滨松提供了MFX二次开发相关的信息和Demo代码。参考博客说明: 【X线源】关于滨松MFX二次开发demo示例简介 https://…...

【深度学习代码调试2】环境配置篇(中) -- 列出conda环境中所有env的pytorch版本
【深度学习代码调试2】环境配置篇(中) -- 列出conda环境中所有env的pytorch版本 写在最前面如何检查所有 Conda 环境中的 PyTorch 版本(并重点提示 PyTorch 1.7.1 版本)1. 列出所有 Conda 环境2. 检查每个环境中的 PyTorch 版本方…...
C语言运算符和表达式
1.C语言赋值运算符实例讲解 C 使用运算符(operator)来代表算术运算。例如,运算符可以使它两侧的值加在一起。如果您觉得术语“运算符”听起来比较奇怪,那么请您记住那些东西总得有个名称。与其被称之为“那些东西”或“数学符号”,被称之为“…...

RetinaNet 分类头和回归头的网络结构分析
RetinaNet 是由 Facebook AI Research(FAIR)在 2017 年提出的一种高效的一阶段(one-stage)目标检测算法。相比于两阶段(two-stage)方法,RetinaNet 通过引入 Focal Loss 解决了类别不平衡问题&am…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...