C语言三种方法解决轮转数组问题

目录
  • 题目
    • 1.题目描述
    • 2.要求
    • 3.原题链接
  • 二、相关知识点
  • 三、解决思路
    • 旋转法
    • 直接法
    • 空间换取时间

题目

1.题目描述

给你一个数组,将数组中的元素向右轮转 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.要求

进阶:

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

3.原题链接

189. 轮转数组 - 力扣(LeetCode) (leetcode-cn.com)

二、相关知识点

本题实际上涉及到了复杂度的问题,包括时间复杂度和空间复杂度。

三、解决思路

旋转法

最优思路,这需要我们有较好的理解力了,可以把数组分为三个部分

假设我们需要选择k个数字:

1.后k个数字逆置

2.前n-k个数字逆置

3.整体逆置

此方法为最优法。符合题目要求

以示例 1为例子说明:

1 2 3 4 5 6 7//旋转3个数字
1 2 3 4 7 6 5//后k个数字逆置
4 3 2 1 7 6 5//前n-k个数字逆置
5 6 7 1 2 3 4//整体逆置

源代码如下:

void reverse(int*nums,int left,int right)
{
    while(left<right)
    {
        int tmp = nums[left];
        nums[left]=nums[right];
        nums[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);
}

注意点:k的大小可能大于数组的大小,所以我们要取模!

这个算法的时间复杂度为O(N),空间复杂度为O(1)

附上结果运行图:

直接法

看到这道题,我们的第一种想法就是直接去旋转,当k=1是。我们就直接把最后一位的数字移动第一位,然后第二位开始往后移动,我们可以创建一个临时的变量来记录当前的最后一位,当k很大时,我们自然就是用循环去做,这是每个人都能想得到的一种方法

代码如下

void rotate(int* nums, int numsSize, int k){
    k %=numsSize;
  while(k--){
      int tmp = nums[numsSize-1];
      for(int end = numsSize-2;end>=0;--end){
          nums[end+1] = nums[end];
      }
      nums[0] = tmp;
  }
}

遗憾的是,这种算法的空间复杂(k*N),没能跑得过去,超时了,给出运行结果图

空间换取时间

以空间换取时间,这是比较常见的,就是额外开辟一个数组,存放选择的几个数字,然后将之前的数据存储到该数组的后半部分。最后将新数组拷贝到原来的数组中

代码如下

void rotate(int* nums, int numsSize, int k){
   k %= numsSize;
   int *newnum = (int*)malloc(sizeof(int)*numsSize);
   int j = 0;
   for(int i =numsSize-k;i<numsSize;i++){
       newnum[j++] =nums[i];
   }
   for(int i = 0;i<numsSize-k;i++){
       newnum[i+k] = nums[i];
   }
   memcpy(nums,newnum,sizeof(int)*numsSize);
}

运行结果如图

虽然也是通过了,但是效率不如思路一。

到此这篇关于C语言三种方法解决轮转数组问题 的文章就介绍到这了,更多相关C语言轮转数组内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言超详细讲解轮转数组

    目录 题目描述 实例 解题思路 1. 先整体逆转 2.逆转子数组[0, k - 1] 3.逆转子数组[k, numsSize - 1] 易错点 代码 题目描述 给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数.OJ链接 实例 1.实例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

  • C语言三种方法解决轮转数组问题

    目录 题目 1.题目描述 2.要求 3.原题链接 二.相关知识点 三.解决思路 旋转法 直接法 空间换取时间 题目 1.题目描述 给你一个数组,将数组中的元素向右轮转 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.要求 进阶

  • JavaScript三种方法解决约瑟夫环问题的方法

    目录 概述 问题描述 循环链表 有序数组 数学递归 总结 概述 约瑟夫环问题又称约瑟夫杀人问题或丢手绢问题,是一道经典的算法问题.问题描述也有很多变式,但大体的解题思路是相同的.本篇将以循环链表.有序数组.数学递归三种方式来解决约瑟夫环问题. 问题描述 先来看一下什么是约瑟夫环问题? 在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀

  • 三种方法解决ASP.NET Core 6中的依赖项

    依赖性注入是一种技术,它允许我们注入一个特定类的依赖对象,而不是直接创建这些实例. 使用依赖注入的好处显而易见,它通过放松模块间的耦合,来增强系统的可维护性和可测试性. 依赖注入允许我们修改具体实现,而不必改变依赖于它们的依赖类型. ASP.NET Core 很重视依赖注入技术.ASP.NET Core 中内置的依赖注入提供功能模块,并不像 StructureMap 和 Ninject 等IoC(控制反转)容器那样功能丰富,但它速度快,易于配置,而且易于使用.我们可以使用它在 ASP.NET C

  • Docker容器互访的三种方法

    我们都知道docker容器之间是互相隔离的,不能互相访问,但如果有些依赖关系的服务要怎么办呢.下面介绍三种方法解决容器互访问题. 方式一.虚拟ip访问 安装docker时,docker会默认创建一个内部的桥接网络docker0,每创建一个容器分配一个虚拟网卡,容器之间可以根据ip互相访问. [root@33fcf82ab4dd /]# [root@CentOS ~]# ifconfig ...... docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICA

  • Java语言通过三种方法实现队列的示例代码

    目录 队列 图解 数组模拟队列 队列优化—循环队列 代码 使用java内部队列 代码 队列 队列是一种特殊的线性表,只允许在表的前端进行删除操作,在表的后端进行插入操作. 队列是一个有序列表,可以用数组或是链表来实现. 遵循先入先出的原则.即:先存入队列的数据,要先取出.后存入的要后取出. 就相当于我们日常生活中的排队,先来先服务,后来的只能在后面进行排队等待. 图解 数组模拟队列 通过对定义的了解,发现队列很像我们的数组,那我们是不是可以通过数组来模拟队列,下面我们来实践一下. 首先先分析一下

  • 详解C语言快速排序三种方法的单趟实现

    目录 交换排序的思想 冒泡排序的思想 快速排序的整体框架 快速排序单趟实现逻辑 1. hoare版本单趟实现(左右指针法) 2.挖坑法单趟排序实现 3.前后指针法 交换排序的思想 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排 序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 冒泡排序的思想 冒泡排序比较简单,我们之前使用也很多,简单讲解,就是比较两个数,如果比他大就交换,没有他大就接着向后比,一直到数组结束,这是单趟

  • C语言通过三种方法实现属于你的通讯录

    目录 一.基础版本 1.1 通讯录的个人信息(结构体来实现) 1.2通讯录名单 1.3人员初始化 1.4菜单 1.5主函数 二.功能的实现 2.1.增加人数 2.2.删除人数 2.3.查找 2.4.展示 2.5.排序(这里我是通过名字) 三.通讯录进阶(设置动态存储) 3.1通讯录从静态改为动态 3.2通讯录的初始化 3.3通讯录的增加需要判断是否满了 四.文件的形式存储通讯录 4.1人员信息的保存 4.2人员信息的流入 一.基础版本 前提准备: 1.通讯录里面的人的个人信息(姓名.性别.年龄.

  • 读取Java文件到byte数组的三种方法(总结)

    读取Java文件到byte数组的三种方法(总结) package zs; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Rando

  • JavaScript中数组去除重复的三种方法

    废话不多说了,具体方法如下所示: 方法一:返回新数组每个位子类型没变 function outRepeat(a){ var hash=[],arr=[]; for (var i = 0; i < a.length; i++) { hash[a[i]]!=null; if(!hash[a[i]]){ arr.push(a[i]); hash[a[i]]=true; } } console.log(arr); } outRepeat([2,4,4,5,"a","a"

  • PHP遍历数组的三种方法及效率对比分析

    本文实例分析了PHP遍历数组的三种方法及效率对比.分享给大家供大家参考.具体分析如下: 今天有个朋友问我一个问题php遍历数组的方法,告诉她了几个.顺便写个文章总结下,如果总结不全还请朋友们指出 第一.foreach() foreach()是一个用来遍历数组中数据的最简单有效的方法. <?php $urls= array('aaa','bbb','ccc','ddd'); foreach ($urls as $url){ echo "This Site url is $url! <b

随机推荐