力扣 旋转数组 C语言实现

2023-10-27

原题地址

https://leetcode-cn.com/explore/interview/card/top-interview-questions-easy/1/array/23/

题目描述

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 1:
输入: [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:
输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

说明:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的原地算法。

1. 暴力解法

在刚看到这个题目时,脑子里第一时间想到的,最简单的解法:创建一个temp数组整个把原数组复制过来,然后再按照旋转后的结果逐个元素地覆盖原数组。代码如下:

void 
rotate(int* nums, int numsSize, int k)
{
    int i, j;

    int temp[numsSize];
	
	/* 复制数组元素 */
    for (i = 0; i < numsSize; i++)
        temp[i] = nums[i];
	
	/* 把后k个元素覆盖到原数组的前k个位置上 */
    j = 0;
    for (i = numsSize - k; i < numsSize; i++, j++)
        nums[j] = temp[i];
    
    /* 剩余部分按顺序覆盖 */
    for (i = 0; i < numsSize - k; i++, j++)
        nums[j] = temp[i];
}

时间复杂度,复制数组为n,覆盖原数组也是n,所以总的时间复杂度为 O ( n ) O (n) O(n)
空间复杂度,因为有temp数组的存在,所以需要n个元素的空间,因此空间复杂度也是 O ( n ) O(n) O(n)

2. 递归算法

由于暴力算法并不满足问题对空间复杂度的要求,因此琢磨了一下其他的解法。在手动旋转的过程中发现了一个不需要额外空间的算法:

  1. 将前k个数据与数组最后k个数据逐个交换
  2. 将后n - i * k个数据视为新的数组,重复操作1,注意k要对剩余元素数量n - i * k取模,以保证数组的访问不会越界,其中i表示操作1执行的次数
  3. k = 0或者只剩一个数据时,算法结束。

举个栗子,对于数组[1, 2, 3, 4, 5]n = 5, k = 2,那么每一轮的操作结果如下所示:

  1. 将前2个与后2个数据交换:[1, 2, 3, 4, 5] → [4, 2, 3, 1, 5] → [4, 5, 3, 1, 2]
  2. [3, 1, 2]视为新数组,k对3取模还是2,交换前2个数据与后2个数据:[4, 5, 3, 1, 2] → [4, 5, 1, 3, 2] → [4, 5, 1, 2, 3]
  3. [2]视为新数组,由于只剩一个数据,算法结束

这个算法的思想十分适合递归,因此直接一波递归。代码如下所示:

/* begin表示新数组开始的下标 */
void 
rotate(int *nums, int begin, int numsSize, int k)
{
    /* 到最后几轮,k很有可能会比剩余的数组数量长 */
    k = k % (numsSize - begin);

    if (k == 0)
        return;

    if (begin >= numsSize - 1)
        return;
    
    int i, j;
    /* 逐个交换 */
    for (i = begin, j = 0; i < numsSize && j < k; i++, j++)
    {
        int temp = nums[i];
        nums[i] = nums[numsSize - k + j];
        nums[numsSize - k + j] = temp;
    }
    
    /* 递归调用处理 */
    return rotate_r(nums, begin + k, numsSize, k);
}

void
rotate(int *nums, int numsSize, int k)
{
    rotate_r(nums, 0, numsSize, k);
}

此外,递归操作会占用大量的栈空间,虽然这个代码用了尾递归,但还是不如循环。所以可以改成循环来处理,比较简单,不再列出代码。

3. 更简单的算法

当我把代码提交上去后,发现还有代码时间比我的算法还要快,于是看了一下。代码如下:

void reverse(int* nums,int left,int right){
    while(left<right){
        int temp=nums[left];
        nums[left++]=nums[right];
        nums[right--]=temp;
    }
}

void rotate_alg1(int* nums, int numsSize, int k){
    k%=numsSize;//若k>numsSize则移动位置为余数;
	/* 先整个倒序 */
    reverse(nums,0,numsSize-1);
    /* 前k个倒序 */
    reverse(nums,0,k-1);
    /* 后n-k个倒序 */
    reverse(nums,k,numsSize-1);
}

理解起来更加简单了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

力扣 旋转数组 C语言实现 的相关文章

随机推荐

  • windows多用户远程登录工具 RDPWrap配置

    目录 准备 配置 完 准备 下载 在https github com stascorp rdpwrap releases tag v1 6 2下载RDPWrap v1 6 2 zip 下载后解压 配置 install bat右键管理员运行
  • (未解决)selenium.common.exceptions.NoSuchWindowException: Message: no such window

    执行代码如下 from selenium import webdriver from time import sleep if name main driver webdriver Chrome driver implicitly wait
  • 【1day】​万户协同办公平台 ezoffice未授权访问漏洞学习

    注 该文章来自作者日常学习笔记 请勿利用文章内的相关技术从事非法测试 如因此产生的一切不良后果与作者无关 目录
  • vue3中hooks的介绍及用法

    大家好 今天这篇文章是介绍一下vue3中的hooks以及它的用法 本文内容主要有以下两点 什么是hooks vue3中hooks的使用方法 一 什么是hooks hook是钩子的意思 看到 钩子 是不是就想到了钩子函数 事实上 hooks
  • 告别了夸克,我已经找到了比你更强大的浏览器

    老实说 夸克真的是一款非常不错的浏览器 但是随着更新这个app越来越臃肿 还搞起了付费网盘 很多人转身选择其他浏览器 以前也给大家推荐过Alook浏览器 X浏览器等 今天 再给大家推荐3款浏览器 比夸克更牛 更好用 不信就往下看吧 1 多御
  • 【论文精读】360MVSNet

    今天读的是发表在WACV2023上的MVS文章 该文章提出了基于全景相机的MVS pipeline 文章链接 点击前往 代码链接 暂未开源 文章目录 Abstract 1 Introduction 2 Related works 3 Met
  • day28 回溯

    93 复原IP地址 本质上是分割问题 判断一个分割的值是否有效 回溯需要去掉 78 子集 收集每个树的节点 90 子集II 收集每个树的节点 树层去重 package algor trainingcamp import java util
  • pycharm中的 opencv-python 没有函数提示的解决方案

    pycharm中用 pip install opencv python 安装的cv2可能没有函数提示功能 ctrl 鼠标左键 也不会进入源代码 解决方案如下 1 找到cv2对应python编译器的安装路径 pycharm左下角 将鼠标放在编
  • 什么是页缓存(Page Cache)(转载)

    我们知道文件一般存放在硬盘 机械硬盘或固态硬盘 中 CPU 并不能直接访问硬盘中的数据 而是需要先将硬盘中的数据读入到内存中 然后才能被 CPU 访问 由于读写硬盘的速度比读写内存要慢很多 DDR4 内存读写速度是机械硬盘500倍 是固态硬
  • teamviewer 试用期到期以后怎么卸载然后安装使用

    1 1 退出TeamViewer远程软件 卸载软件 2 2 按键盘的 win R 组合键打开 运行 输入 appdata 3 3 在弹出的窗口中 找到并删除TeamViewer文件夹 4 4 按键盘的 win R 组合键打开 运行 输入 r
  • 降噪电路_TWS蓝牙耳机降噪要选对蓝牙晶振

    如今 越来越多的手机开始取消3 5mm耳机接口 转而采用USB C接口耳机或是无线蓝牙耳机 但消费者对音乐分辨率的要求却始终有增无减 一项调查显示 音质已成为消费者选择耳机或音箱产品时最看重的因素 76 的受访者为此投了赞成票 79 的受访
  • 启动指定用户docker

    有段时间没用docker了 都不记得怎么操作了 启动指定用户docker 方法如下
  • 目标检测正负样本区分和平衡策略总结

    目标检测正负样本区分策略和平衡策略总结 一 知乎0 简介本文抛弃网络具体结构 仅仅从正负样本区分和正负样本平衡策略进行分析 大体可以分为 正负样本定义 正负样本采样和平衡loss设计三个方面 主要是网络预测输出和loss核心设计即仅仅涉及网
  • Darknet下的Yolo v3

    一 网址 https github com AlexeyAB darknet 二 训练自己的数据 检测人头 1 经过1周训练的效果图 总体上效果还是很OK的 检测精度也比较高 2 数据准备 2 1 标注工具 标注工具在我的其他博客里有说明
  • STM32微控制器综合实训8 PWM输出实验

    实验8 PWM输出实验 用STM32的定时器来产生PWM呼吸灯 文章目录 代码讲解 main c timer c 编译仿真 第一次仿真 第二次仿真 第三次仿真 第四次仿真 遇到的错误 总结 代码讲解 main c int main void
  • TortoiseGit 入门指南04:查看提交日志

    如果每次提交都按照规定格式书写提交信息 这样一来就可以使用日志功能来查看开发过程 找出所做的更改以及更改原因 在仓库中右击鼠标 选择 TortoiseGit Show log 打开日志对话框 默认日志对话框仅列出所选文件或目录及其子目录文件
  • hive设置为本地模式,从而避免MapReduce

    配置如下参数 可以开启Hive的本地模式 hive gt set hive exec mode local auto true 默认为false
  • Java抒写简单区块链

    区块链的产生基础 区块链 是一种分布式数据库 是一串使用密码学方法相关联产生的数据块链表 每个数据块都包含了一次网络交易信息 用于验证其信息的有效性和生成下一个区块 其特点 1 去中心化 实现点对点直接交互 既节约资源 使交易自主化 简易化
  • 【C语法】1124循环结构

    include
  • 力扣 旋转数组 C语言实现

    原题地址 https leetcode cn com explore interview card top interview questions easy 1 array 23 题目描述 给定一个数组 将数组中的元素向右移动 k 个位置