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

【刷题系列】LeetCode消失的数字、轮转数组

文章目录

  • 1、消失的数字
    • 1.1 题目描述
    • 1.2 题目分析
  • 2、轮转数字
    • 2.1 题目描述
    • 2.2 题目分析

1、消失的数字

原题链接:消失的数字

1.1 题目描述

数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
注意:本题相对书上原题稍作改动

示例 1:
输入:[3,0,1]
输出:2

示例 2:
输入:[9,6,4,2,3,5,7,0,1]
输出:8

1.2 题目分析

思路一:
首先想到的思路是等差数列求和,数组nums包含0到n的所有整数,但是缺了一个,那么我们只需要对0到n求和,再将得到的前n项和减去数组的和,得到的差值就是那个缺失的数字。
代码实现:

int missingNumber(int* nums, int numsSize) {int sum = numsSize * (numsSize + 1) / 2;for(int i = 0;i < numsSize; ++i){sum-=nums[i];}return sum;
}

思路二:
第二个思路是利用位运算。常见的位运算有按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>)。
我们这里要用到的是按位异或(^),按位异或是相同为0不同为1,例如5 ^ 3,5的二进制是0101,3的二进制的0011,他们按位异或的结果就是0110,也就是6。任何整数和它本身按位异或,得到的结果都是0,和0按位异或,得到的结果是它本身。
首先nums数组中有n个数,而0到n有n+1个数,总共2n+1个数,而那个消失的数字只在n+1个数中出现一次,而其他数字都出现了两次,所以我们可以用0对这2n+1个数依次按位异或,得到的最后结果就是那个消失的数字。
举个小例子:
nums:[0,1,3]
0~n:0 1 2 3
先让0和nums依次按位异或:

  1. 0^0 = 0
  2. 0^1 = 1
  3. 1^3 = 2

再让2和0~n依次按位异或:

  1. 2^0 = 2
  2. 2^1 = 3
  3. 3^2 = 1
  4. 1^3 = 2

可以看到,最终的结果就是消失的2
代码实现如下:

int missingNumber(int* nums, int numsSize) {int x = 0;int n = numsSize;for(int j = 0;j < numsSize;++j){x^=nums[j];}for(int i = 0;i <= n;++i){x ^= i;}return x;
}

2、轮转数字

原题链接:轮转数组

2.1 题目描述

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

2.2 题目分析

思路一:
使用memcpy()函数,该函数的用法在cppreference中如下:
https://legacy.cplusplus.com/reference/cstring/memcpy/?kw=memcpy
在这里插入图片描述
它一共有三个参数,第一个表示要复制到的目标内存块,第二个是表示我们要复制的内容,第三个是我们要复制的字节数。
首先我们让k和数组的长度进行取模,这样做的原因是,当k和numsSize为倍数关系时,数组轮转后还是原来的数组,取模可以减少不必要的重复计算。紧接着我们创建一个临时数组tmp,用来存储旋转后的元素,在进行拷贝的过程中,要确定自己的拷贝位置以及要拷贝的字节数。
首先我们要先把nums数组中的后k个元素复制到tmp数组的起始位置,然后再把nums数组前numsSize-k个元素复制到tmp数组中,从下标为k的位置上开始放,因为题目要我们返回的是nums数组,因此最后一步我们将tmp整个拷贝到nums,完成旋转操作。
实现代码如下:

void rotate(int* nums, int numsSize, int k) {k %= numsSize;int tmp[numsSize];//0  n-k-1   n-k  n-1memcpy(tmp,nums+numsSize-k,sizeof(int)*k);memcpy(tmp+k,nums,sizeof(int)*(numsSize-k));memcpy(nums,tmp,sizeof(int)*numsSize);
}

思路二: 先逆置前n-k个,再逆置后k个,最后将整个数组逆置。

假设现在有一个数组[1,2,3,4,5],k = 3,先逆置前n-k个也就是前2个,得到数组[2,1,3,4,5],再逆置后k个也就是后三个,得到数组[2,1,5,4,3],再整体逆置,得到数组[3,4,5,1,2],得到最终答案。

我们可以先封装一个逆置函数,即左右双指针向中间步进,借助第三个变量来逆置。然后再根据上面的思路对数组进行分段逆置。
代码实现如下:

void Reverse(int* a, int left, int right)
{while(left<right){int tmp = a[left];a[left] = a[right];a[right] = tmp;++left;--right;}
}void rotate(int* nums, int numsSize, int k) {k %= numsSize;Reverse(nums,0,numsSize-k-1);Reverse(nums,numsSize-k,numsSize-1);Reverse(nums,0,numsSize-1);
}

本期文章就到这里啦,刷题系列会紧随我的刷题进度不断更新的,大家如果有想到更优化的方法,也可以在评论区提出,有不足和错误的地方,也请指出,下一篇文章见,拜拜~

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

相关文章:

  • 前端微服务详解
  • Datawhale AI春训营——用AI帮助老人点餐
  • Redis 及其在系统设计中的作用
  • Docker 的基本概念和优势以及在应用程序开发中的实际应用
  • 金融行业一体化运维监控平台解决方案
  • 阶段性人生答疑解惑篇:穿越市场迷雾,重构生命坐标系
  • Java Thread类深度解析:构造方法与核心方法全攻略
  • 多级缓存架构深度解析:从设计原理到生产实践
  • 【AI提示词】艺人顾问
  • Turso:一个基于 libSQL的分布式数据库
  • 最新AI-Python机器学习与深度学习技术在植被参数反演中的核心技术应用
  • Vue.js 的组件化开发指南
  • 四、Python编程基础04
  • 【ES实战】Elasticsearch中模糊匹配类的查询
  • 【嵌入式系统设计师(软考中级)】第二章:嵌入式系统硬件基础知识(2)
  • 常见接口测试常见面试题(JMeter)
  • Vue3 + TypeScript,使用provide提供只读的响应式数据的详细分析与解决方法
  • 蓝牙 LE:安全模式和程序说明(蓝牙中的网络安全)
  • 3D模型文件格式之《FBX格式介绍》
  • 密码学的hash函数,哈希碰撞, collision resistance, BTC用到的SHA-256简介
  • elementui日历显示红点及根据日程范围判断是否有红点
  • 实验三 进程间通信实验
  • 504 nginx解决方案
  • arm64适配系列文章-第六章-arm64环境上rabbitmq-management的部署,构建cluster-operator
  • LeetCode238_除自身以外数组的乘积
  • 2025.5.4机器学习笔记:PINN文献阅读
  • React状态提升深度解析:原理、实战与最佳实践
  • 声音分离人声和配乐-从头设计数字生命第4课——仙盟创梦IDE
  • 树莓派安装GStreamer ,opencv支持, 并在虚拟环境中使用的安装方法
  • 从数据到智慧:解密机器学习的自主学习密码