当前位置: 首页 > news >正文

华为OD机试 2025B卷 - 最小循环子数组(C++PythonJAVAJSC语言)

2025B卷目录点击查看: 华为OD机试2025B卷真题题库目录|机考题库 + 算法考点详解

2025B卷 100分题型

题目描述

给定一个由若干整数组成的数组nums,请检查数组是否是由某个子数组重复循环拼接而成,请输出这个最小的子数组。

输入描述

第一行输入数组中元素个数n,1 ≤ n ≤ 100000

第二行输入数组的数字序列nums,以空格分割,0 ≤ nums[i] < 10

备注

数组本身是其最大的子数组,循环1次可生成的自身;

输出描述

输出最小的子数组的数字序列,以空格分割;

示例1

输入

9
1 2 1 1 2 1 1 2 1

输出

1 2 1

说明

数组[1,2,1,1,2,1,1,2,1] 可由子数组[1,2,1]重复循环3次拼接而成

解题思路

问题理解

这道题要求我们找到一个最小的子数组,该子数组通过循环拼接可以构成原始数组。例如,对于数组 [1,2,1,1,2,1,1,2,1],最小的循环子数组是 [1,2,1],它重复3次可以生成原数组。

算法原理

这个问题可以使用 KMP 算法的思想来解决。KMP 算法主要用于字符串匹配,但其中的"前缀函数"(next数组)可以帮助我们找到循环模式。

KMP 的 next 数组在这里的应用

  1. next数组记录了每个位置的最长相等前后缀长度
  2. 对于数组末尾位置 i,next[i] 表示数组的前 next[i] 个元素与末尾的 next[i] 个元素相同
  3. 如果数组是由某个子数组循环构成的,那么 (数组长度 - next[末尾位置]) 就是可能的循环子数组的长度

关键思路

如果一个数组是循环构成的,假设循环子数组长度为 k,数组长度为 n,则有:

  • n 必须是 k 的整数倍
  • 如果 (n % (n - next[n-1]) == 0),说明数组可以被分成整数个循环子数组
  • 此时最小循环子数组长度为 (n - next[n-1])
  • 否则,无法找到真正的循环子数组,整个数组本身就是最小的"循环子数组"(循环1次)

示例分析

对于输入 [1,2,1,1,2,1,1,2,1]

  1. 构建 next 数组:[0,0,1,1,2,3,4,5,6]
  2. 最后一个元素的 next 值是 6
  3. 计算:9 % (9 - 6) = 9 % 3 = 0,可以整除
  4. 因此最小循环子数组长度为 3
  5. 输出前 3 个元素:[1,2,1]

Java

import java.util.Arrays;
import java.util.Scanner;
import java.util.StringJoiner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 读取数组长度int arrayLength = Integer.parseInt(sc.nextLine());// 读取数组元素并将其转换为整数数组int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();// 初始化next数组,用于存储KMP算法中的前缀信息int[] next = new int[arrayLength];// 初始化前缀索引int prefixIndex = 0;// 初始化当前索引int currentIndex = 1;// 使用KMP算法的思想构建next数组while (currentIndex < arrayLength) {// 如果当前元素与前缀元素相等,则更新next数组if (nums[currentIndex] == nums[prefixIndex]) {next[currentIndex++] = ++prefixIndex;} else if (prefixIndex > 0) {// 如果前缀索引大于0,则回退到前一个前缀prefixIndex = next[prefixIndex - 1];} else {// 如果前缀索引为0,则移动到下一个元素currentIndex++;}}// 获取next数组的最后一个值int lastNextValue = next[arrayLength - 1];// 计算子数组长度int subArrayLength = arrayLength % (arrayLength - lastNextValue) == 0 ? arrayLength - lastNextValue : arrayLength;// 使用StringJoiner构建输出字符串StringJoiner sj = new StringJoiner(" ");// 将子数组的元素添加到输出字符串中for (int i = 0; i < subArrayLength; i++) sj.add(nums[i] + "");// 输出结果System.out.println(sj.toString());}
}

Python

import sys# 从控制台读取输入
input_lines = sys.stdin.readlines()
# 读取数组长度
array_length = int(input_lines[0].strip())
# 读取数组元素并将其转换为整数数组
nums = list(map(int, input_lines[1].strip().split()))# 初始化next数组,用于存储KMP算法中的前缀信息
next = [0] * array_length
# 初始化前缀索引
prefix_index = 0
# 初始化当前索引
current_index = 1# 使用KMP算法的思想构建next数组
while current_index < array_length:# 如果当前元素与前缀元素相等,则更新next数组if nums[current_index] == nums[prefix_index]:prefix_index += 1next[current_index] = prefix_indexcurrent_index += 1elif prefix_index > 0:# 如果前缀索引大于0,则回退到前一个前缀prefix_index = next[prefix_index - 1]else:# 如果前缀索引为0,则移动到下一个元素current_index += 1# 获取next数组的最后一个值
last_next_value = next[array_length - 1]
# 计算子数组长度
sub_array_length = array_length - last_next_value if array_length % (array_length - last_next_value) == 0 else array_length# 使用列表构建输出字符串
output = ' '.join(str(nums[i]) for i in range(sub_array_length))
# 输出结果
print(output)

JavaScript

const readline = require('readline');const rl = readline.createInterface({input: process.stdin,output: process.stdout
});// 读取用户输入
rl.on('line', arrayLength => {rl.on('line', arrayElements => {// 将输入的字符串转换为整数数组const nums = arrayElements.split(' ').map(Number);const next = new Array(parseInt(arrayLength)).fill(0);let prefixIndex = 0;let currentIndex = 1;// 使用KMP算法的思想构建next数组while (currentIndex < nums.length) {if (nums[currentIndex] === nums[prefixIndex]) {next[currentIndex++] = ++prefixIndex;} else if (prefixIndex > 0) {prefixIndex = next[prefixIndex - 1];} else {currentIndex++;}}// 获取next数组的最后一个值const lastNextValue = next[nums.length - 1];// 计算子数组长度const subArrayLength = nums.length % (nums.length - lastNextValue) === 0 ? nums.length - lastNextValue : nums.length;// 构建输出字符串const output = nums.slice(0, subArrayLength).join(' ');console.log(output);rl.close();});
}) 

C++

#include <iostream>
#include <vector>
#include <sstream>
#include <string>
using namespace std;
int main() {// 创建输入流对象以读取用户输入string line;// 读取数组长度int arrayLength;getline(cin, line);arrayLength = stoi(line);// 读取数组元素并将其转换为整数数组getline(cin, line);istringstream iss(line);vector<int> nums(arrayLength);for (int i = 0; i < arrayLength; ++i) {iss >> nums[i];}// 初始化next数组,用于存储KMP算法中的前缀信息vector<int> next(arrayLength, 0);// 初始化前缀索引int prefixIndex = 0;// 初始化当前索引int currentIndex = 1;// 使用KMP算法的思想构建next数组while (currentIndex < arrayLength) {// 如果当前元素与前缀元素相等,则更新next数组if (nums[currentIndex] == nums[prefixIndex]) {next[currentIndex++] = ++prefixIndex;} else if (prefixIndex > 0) {// 如果前缀索引大于0,则回退到前一个前缀prefixIndex = next[prefixIndex - 1];} else {// 如果前缀索引为0,则移动到下一个元素currentIndex++;}}// 获取next数组的最后一个值int lastNextValue = next[arrayLength - 1];// 计算子数组长度int subArrayLength = arrayLength % (arrayLength - lastNextValue) == 0 ? arrayLength - lastNextValue : arrayLength;// 使用ostringstream构建输出字符串ostringstream oss;// 将子数组的元素添加到输出字符串中for (int i = 0; i < subArrayLength; i++) {oss << nums[i];if (i < subArrayLength - 1) {oss << " ";}}// 输出结果cout << oss.str() << endl;return 0;
}

C语言

#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main() {// 读取数组长度int arrayLength;scanf("%d", &arrayLength);// 读取数组元素int* nums = (int*)malloc(arrayLength * sizeof(int));for (int i = 0; i < arrayLength; i++) {scanf("%d", &nums[i]);}// 初始化next数组,用于存储KMP算法中的前缀信息int* next = (int*)calloc(arrayLength, sizeof(int));// 初始化前缀索引int prefixIndex = 0;// 初始化当前索引int currentIndex = 1;// 使用KMP算法的思想构建next数组while (currentIndex < arrayLength) {// 如果当前元素与前缀元素相等,则更新next数组if (nums[currentIndex] == nums[prefixIndex]) {prefixIndex++;next[currentIndex] = prefixIndex;currentIndex++;} else if (prefixIndex > 0) {// 如果前缀索引大于0,则回退到前一个前缀prefixIndex = next[prefixIndex - 1];} else {// 如果前缀索引为0,则移动到下一个元素next[currentIndex] = 0;currentIndex++;}}// 获取next数组的最后一个值int lastNextValue = next[arrayLength - 1];// 计算子数组长度int subArrayLength = arrayLength % (arrayLength - lastNextValue) == 0 ? arrayLength - lastNextValue : arrayLength;// 输出结果for (int i = 0; i < subArrayLength; i++) {printf("%d", nums[i]);if (i < subArrayLength - 1) {printf(" ");}}printf("\n");// 释放内存free(nums);free(next);return 0;
}
http://www.dtcms.com/a/269197.html

相关文章:

  • 【论文笔记】World Models for Autonomous Driving: An Initial Survey
  • 【C++读取输入空格到CHAR数组】2022-7-19
  • 在vue3+ts项目中引入element-plus及其图标
  • 【读代码】深度解析TEN VAD:实时语音活动检测的高性能开源解决方案
  • 从被动救火到主动预测!碧桂园服务以图谱技术重塑IT运维底座
  • 开放端口,开通数据库连接权限,无法连接远程数据库 解决方案
  • Debian 11 Bullseye 在线安装docker
  • Java 命令行参数详解:系统属性、JVM 选项与应用配置
  • axios无感刷新token
  • 万物智联时代启航:鸿蒙OS重塑全场景开发新生态
  • Android kotlin中 Channel 和 Flow 的区别和选择
  • 《Effective Python》第十二章 数据结构与算法——当精度至关重要时使用 decimal
  • 【R语言】Can‘t subset elements that don‘t exist.
  • 学习日记-spring-day42-7.7
  • Java --接口--内部类分析
  • [学习] C语言数学库函数背后的故事:`double erf(double x)`
  • qiankun 微前端框架子应用间通信方法详解
  • 一份多光谱数据分析
  • Spring MVC HandlerInterceptor 拦截请求及响应体
  • [netty5: LifecycleTracer ResourceSupport]-源码分析
  • idea启动后闪一下,自动转为后台运行
  • 全国产化行业自主无人机智能处理单元-AI飞控+通信一体化模块SkyCore-I
  • VmWare 安装 mac 虚拟机
  • 量子计算+AI芯片:光子计算如何重构神经网络硬件生态
  • C++ 定位 New 表达式深度解析与实战教程
  • 如果让计算机理解人类语言- Word2Vec(Word to Vector,2013)
  • 系统学习Python——并发模型和异步编程:基础知识
  • 无需公网IP的文件交互:FileCodeBox容器化部署技术解析
  • AI编程才刚起步,对成熟的软件工程师并未带来质变
  • Java 内存分析工具 Arthas