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

指针与算法的双人舞:蓝桥杯两道趣味题的降维打击

蓝桥杯奇趣挑战:如何用指针和算法“驯服”无序数组与环形迷宫?

🎩 博客引言

"你是否有过这样的体验?面对一段看似混乱的数组,像解开一团纠缠的耳机线,想用最优雅的方式让它乖乖听话?又或者,站在环形迷宫的起点,明明终点就在眼前,却因找不到最短路径而焦头烂额?
今天,我们将借蓝桥杯算法大赛的两道经典题目,揭秘如何用 指针的精准操作 和 算法的智慧策略 ,让无序数据俯首称臣,让环形迷宫变成坦途!无需复杂代码,只需逻辑的跃迁——准备好了吗?"


📖 博客正文
Part 1 | 蓝桥杯算法大赛:逻辑与代码的竞技场

蓝桥杯作为国内顶尖的IT赛事,其算法赛题以“短小精悍、思维刁钻”著称,既考察选手对基础数据结构(如数组、链表)的掌控力,又挑战其对算法思想(如贪心、双指针、BFS)的灵活运用。今天分析的两道题,正是蓝桥杯“小而美”风格的典型代表。


Part 2 | 题目一:双指针奇偶重排(指针+算法)

💡 问题核心
给定一个数组,要求通过交换操作,使得所有奇数下标元素的值大于相邻的偶数下标元素(从0开始)。例如 [1,3,2,4] 变为 [1,4,2,3]

🔑 算法思路解析

  1. 双指针的默契配合:使用两个指针分别指向奇数下标和偶数下标,逐对检查相邻元素。

  2. 贪心策略的巧思:若发现奇数下标元素小于相邻偶数下标元素,立即交换——这种“局部最优”操作最终能保证全局满足条件。

  3. 边界控制:只需遍历奇数下标(从1开始),确保不越界即可。

⚡ 思维亮点

  • 时间复杂度仅需 O(n),一次遍历解决问题,高效如“外科手术刀”。

  • 无需额外空间,原地操作体现算法设计的简洁之美。

    #include <stdio.h>  // 引入标准输入输出库,用于printf等函数// 交换两个整数的值
    // 参数:a - 指向第一个整数的指针,b - 指向第二个整数的指针
    void swap(int *a, int *b) {int temp = *a;  // 创建临时变量存储a指针指向的值*a = *b;        // 将b指针指向的值赋给a指针指向的内存*b = temp;      // 将临时变量存储的原a值赋给b指针指向的内存
    }/*** 对数组进行重排,使得每个奇数下标元素大于相邻的偶数下标元素* 参数:arr - 待重排的数组指针,size - 数组的长度*/
    void rearrangeArray(int *arr, int size) {// 遍历所有奇数下标(从1开始,每次步进2)for (int i = 1; i < size; i += 2) {// 检查当前奇数位置元素是否小于左侧偶数位置元素(i-1必然存在,因为i>=1)if (arr[i] < arr[i - 1]) {swap(&arr[i], &arr[i - 1]);  // 交换当前奇数位置和左侧偶数位置的元素}// 检查右侧偶数位置是否存在(i+1 < size),且当前奇数位置元素是否小于右侧元素if (i + 1 < size && arr[i] < arr[i + 1]) {swap(&arr[i], &arr[i + 1]);  // 交换当前奇数位置和右侧偶数位置的元素}}
    }int main() {// 初始化测试数组(原始数组:[1, 3, 2, 4])int arr[] = {1, 3, 2, 4};// 计算数组长度:总字节数除以单个元素字节数int size = sizeof(arr) / sizeof(arr[0]);// 调用重排函数处理数组rearrangeArray(arr, size);// 打印格式化结果printf("Array after rearrangement: ");printf("[");  // 输出开头的左方括号for (int i = 0; i < size; i++) {             // 遍历数组所有元素printf(i == 0 ? "%d" : ", %d", arr[i]);   // 三元运算符控制输出格式:首元素不加逗号,后续元素前加逗号}printf("]\n");  // 输出结尾的右方括号和换行符return 0;       // 程序正常退出,返回状态码0
    }

    输出结果:


Part 3 | 题目二:环形数组最短跳跃(算法+指针)

💡 问题核心
在环形数组中,每个元素表示最大跳跃步数,求从起点出发返回自身的最短跳跃次数。若无法返回则输出-1。例如 [2,3,1,1,4] 的答案是2(路径:0→1→0)。

🔑 算法思路解析

  1. BFS的降维打击:将跳跃过程视为层级遍历,用队列记录每一步可达的位置,首次回到起点即为最短路径。

  2. 环形特性的破解:通过取模运算处理环形索引,避免无限循环。

  3. 剪枝优化:记录已访问的位置,防止重复计算。

⚡ 思维亮点

  • 最短路径问题中,BFS天然适合寻找最小步数

  • 环形数组的取模操作(index % n)是解题的灵魂,化“无限”为“有限”。

#include <stdio.h>    // 标准输入输出库(如printf)
#include <stdlib.h>   // 标准库(如动态内存分配、exit函数)
#include <stdbool.h>  // 布尔类型支持(bool, true, false)// 定义队列最大容量(假设足够大以处理题目输入)
#define MAX_QUEUE_SIZE 100000// 队列节点结构体,存储当前位置和已用步数
typedef struct {int pos;   // 当前数组下标(从0开始)int steps; // 到达此位置所需的跳跃次数
} QueueNode;    // 定义结构体类型名为 QueueNodeQueueNode queue[MAX_QUEUE_SIZE]; // 静态数组实现的队列存储空间
int front = 0;                   // 队列头指针(指向下一个要取出的元素位置)
int rear = 0;                    // 队列尾指针(指向下一个要插入的位置)/*** 将元素加入队列尾部* @param pos   当前位置* @param steps 已用步数*/
void enqueue(int pos, int steps) {if (rear >= MAX_QUEUE_SIZE) { // 防止队列溢出(超过容量)fprintf(stderr, "Queue overflow!\n"); // 输出错误信息到标准错误流exit(EXIT_FAILURE);        // 终止程序并返回失败状态}queue[rear].pos = pos;        // 将pos存入队列尾部queue[rear].steps = steps;    // 将steps存入队列尾部rear++;                       // 尾指针后移
}/*** 从队列头部取出元素* @return 队列头部节点*/
QueueNode dequeue() {if (front >= rear) {          // 防止队列下溢(无元素时尝试取出)fprintf(stderr, "Queue underflow!\n");exit(EXIT_FAILURE);}return queue[front++];        // 返回头指针指向的元素,然后头指针后移
}/*** 判断队列是否为空* @return true为空,false非空*/
bool isEmpty() {return front >= rear;         // 当头指针≥尾指针时队列为空
}/*** 计算环形数组返回起点所需的最短跳跃次数* @param arr 环形数组指针* @param n   数组长度* @return 最小跳跃次数,无法返回则-1*/
int minJumps(int *arr, int n) {if (n == 0) return -1;        // 处理空数组直接返回-1// 动态分配并初始化访问标记数组(calloc会清零内存)bool *visited = (bool *)calloc(n, sizeof(bool));front = rear = 0;             // 重置队列指针到初始位置enqueue(0, 0);                // 起点入队(位置0,步数0)visited[0] = true;            // 标记起点已访问// 广度优先搜索(BFS)主循环while (!isEmpty()) {QueueNode current = dequeue();      // 取出队首元素int currentPos = current.pos;        // 当前所在位置int currentSteps = current.steps;    // 当前已用步数int maxJump = arr[currentPos];       // 当前可跳跃的最大步数(由数组值决定)// 遍历所有可能的跳跃步长(从1到maxJump)for (int k = 1; k <= maxJump; k++) {// 正向跳跃计算下一个位置:(currentPos + k) % nint nextPos = (currentPos + k) % n;  // 环形数组取模处理if (nextPos == 0) {               // 如果回到起点0free(visited);                // 释放内存return currentSteps + 1;      // 返回总步数(当前步数+1)}if (!visited[nextPos]) {          // 如果该位置未被访问过visited[nextPos] = true;      // 标记为已访问enqueue(nextPos, currentSteps + 1); // 将新位置和步数入队}// 反向跳跃计算下一个位置:(currentPos - k + n) % nnextPos = (currentPos - k + n) % n;  // +n确保结果非负再取模if (nextPos == 0) {               // 同样检查是否回到起点free(visited);return currentSteps + 1;}if (!visited[nextPos]) {          // 未访问则处理visited[nextPos] = true;enqueue(nextPos, currentSteps + 1);}}}free(visited);           // 释放动态分配的内存return -1;               // 队列空且未找到路径时返回-1
}int main() {// 测试用例:数组 [2,3,1,1,4]int arr[] = {2, 3, 1, 1, 4};int n = sizeof(arr) / sizeof(arr[0]);  // 计算数组长度int result = minJumps(arr, n);         // 调用核心算法函数// 打印输入数组(带方括号)int length = sizeof(arr) / sizeof(arr[0]);printf("[");for (int i = 0; i < length; i++) {printf(i == 0 ? "%d" : ", %d", arr[i]); // 控制逗号格式}printf("]\n");// 打印结果(英文输出,与之前需求一致)printf("Minimum jumps to return to start: %d\n", result); // 输出:2return 0; // 正常结束程序
}

输出结果:

 

Part 4 | 双题对比
双指针奇偶重排”和“环形数组最短跳跃的对比
维度时钟夹角题二进制反码题
核心数学平面几何数论/组合数学
算法范式枚举/方程求解位运算/模式匹配
优化关键运动连续性二进制模式规律
思维挑战物理现象建模数字本质分析
实际应用钟表设计/动画密码学/编码理论
Part 5 | 总结:指针与算法的交响曲

两道题看似差异巨大,却共享同一内核:用指针精准定位问题,用算法高效拆解逻辑

  • 奇偶重排是“静态战场”的闪电战,双指针的简单遍历即可定乾坤;

  • 环形跳跃则是“动态迷宫”的迂回术,BFS的层级推进方显智慧。
    蓝桥杯的题海战术中,掌握这种“一题一宇宙”的思维切换能力,才是真正的降维打击!


📝 博客结语

        算法之美,在于将混沌变为秩序,将不可能化为可能。无论是驯服无序数组,还是征服环形迷宫,背后都是逻辑与想象力的共舞。希望今天的分析能让你感受到:算法不是冰冷的代码,而是解决问题的艺术。

下一次,当你面对一段顽皮的数组时,愿你能微笑着举起指针,对它说:‘乖,站好!’ 

http://www.xdnf.cn/news/242695.html

相关文章:

  • Windows 查看电脑是否插拔过U盘
  • 【业务领域】电脑主板芯片电路结构
  • 【音视频】ffplay数据结构分析
  • C++中常用的十大排序方法之1——冒泡排序
  • 内存安全的攻防战:工具链与语言特性的协同突围
  • SIEMENS PLC程序代码 赋值 + 判断
  • 数值求解Eikonal方程的方法及开源实现
  • 25.4.30数据结构|并查集 路径压缩
  • 《汉诺塔问题的C语言实现》
  • 第十一届蓝桥杯 2020 C/C++组 既约分数
  • RocketMQ常见面试题一
  • 25_04_30Linux架构篇、第1章_02源码编译安装Apache HTTP Server 最新稳定版本是 2.4.62
  • 若依 FastAPI + Vue3 项目 Docker 部署笔记( 启动器打包教程)
  • 华为云Astro大屏连接器创建操作实例:抽取物联网iotda影子设备数据的连接器创建
  • (B题|矿山数据处理问题)2025年第二十二届五一数学建模竞赛(五一杯/五一赛)解题思路|完整代码论文集合
  • 【音频】Qt6实现MP3播放器
  • 深入自制操作系统(一、Bootloader的实现)
  • 微软与Meta大幅增加人工智能基础设施投入
  • AI大模型基础设施:NVIDIA的用于AI大语言模型训练和推理的几款主流显卡
  • Arduino程序函数从入门到精通
  • 中国发布Web3计划:区块链列为核心基础技术,不排除发展加密资产应用!
  • 2025五一杯B题超详细解题思路
  • Qwen3 发布:优化编码与代理能力,强化 MCP 支持引领 AI 新潮流
  • 在阿里云 Ubuntu 24.04 上部署 RabbitMQ:一篇实战指南
  • 24.Linux中RTC的驱动实验_csdn
  • MATLAB R2024a安装教程
  • Spring MVC 与 FreeMarker 整合
  • Sigmoid函数导数推导详解
  • CSS学习笔记14——移动端相关知识(rem,媒体查询,less)
  • 奇偶ASCII值判断