编程之美 -2.17数组循环移位

简介: 编程之美 -2.17数组循环移位

题目

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度位O(N),且只允许使用俩个附加变量。

分析

暴力法

不考虑复杂度要求,我们可以写出双层循环的代码。

时间复杂度O(len*pos);使用了三个附加变量i、j、tmp

C

#include<stdio.h>
int* RighShift(int* n, int len, int pos)//右移函数
{
  int i = 0;
  int j = 0;
  pos = pos % len;//防止pos超过数组长度
  for (i = 0; i < pos; i++)//右移pos轮
  {
    int tmp = n[len - 1];
    for (j = len - 1; j >= 0; j--)//每轮交换len-1次
    {
      n[j] = n[j - 1];
    }
    n[0] = tmp;
  }
  return n;
}
void PrintInt(int* n, int len)//输出数组的元素
{
  int i = 0;
  for (i = 0; i < len; i++) 
  {
    printf("%d ", n[i]);
  }
  printf("\n");
}
int main()
{
  int n[] = { 1,2,3,4,5,6 };
  int pos = 3;
  int len = sizeof(n) / sizeof(n[0]);
  RighShift(n, len, pos);
  PrintInt(n, len);
  return 0;
}

三次反转法

第一次将数组全部元素前后反转。

第二次将数组[0,pos-1]范围的元素前后反转

第三次将数组[pos,len-1]范围的元素前后反转。如下图


具体实现如下

C

#include<stdio.h>
void swap(int* n, int front, int later)//交换函数
{
  int tmp = n[front];
  n[front] = n[later];
  n[later] = tmp;
}
int* RighShift(int* n, int len, int pos)//右移函数
{
  int i = 0;
  pos = pos % len;
  for (i = 0; i < (len >> 1); i++)//第一次交换
  {
    swap(n, i, len - 1 - i);
  }
  for (i = 0; i < (pos >> 1); i++)
  {
    swap(n, i, pos - 1 - i);
  }
  for (i = pos; i < ((pos + len) >> 1); i++)
  {
    swap(n, i, len - 1 - (i - pos));
  }
  return n;
}
void PrintInt(int* n, int len)//输出数组的元素
{
  int i = 0;
  for (i = 0; i < len; i++)
  {
    printf("%d ", n[i]);
  }
  printf("\n");
}
int main()
{
  int n[] = { 1,2,3,4,5,6 };
  int pos = 3;
  int len = sizeof(n) / sizeof(n[0]);
  RighShift(n, len, pos);
  PrintInt(n, len);
  return 0;
}


这次代码已经符合题目要求了,时间复杂度为O(N),附加变量有tmp和i。但是还可以优化代码将三次for循环写成一个反转函数。优化如下

C

#include<stdio.h>
void swap(int* n, int front, int later)//交换函数
{
  int tmp = n[front];
  n[front] = n[later];
  n[later] = tmp;
}
void Reverse(int* n, int start, int end)//反转函数  范围[start, end);
{
  int i = 0;
  for(i = start; i < (start + end) >> 1; i++)
  {
    swap(n, i, end - 1 - (i - start));
  }
}
int* RighShift(int* n, int len, int pos)//右移函数
{
  pos = pos % len;
  Reverse(n, 0, len);
  Reverse(n, 0, pos);
  Reverse(n, pos, len);
  return n;
}
void PrintInt(int* n, int len)//输出数组的元素
{
  int i = 0;
  for (i = 0; i < len; i++)
  {
    printf("%d ", n[i]);
  }
  printf("\n");
}
int main()
{
  int n[] = { 1,2,3,4,5,6 };
  int pos = 3;
  int len = sizeof(n) / sizeof(n[0]);
  RighShift(n, len, pos);
  PrintInt(n, len);
  return 0;
}


本章完!

目录
相关文章
|
8月前
谭浩强数组相关代码
谭浩强数组相关代码
39 0
|
5月前
|
存储 Java 索引
八股day01_数组
八股day01_数组
|
人工智能 C语言 C++
数组和指针一道非常值得深思的笔试题
数组和指针一道非常值得深思的笔试题
71 0
|
C语言
C语言程序设计(王立柱)第三章答案 指针和数组
只有聪明人才能看见的摘要~( ̄▽ ̄~)~
98 0
|
C语言
C语言程序设计(王立柱)第九章答案 二维数组和指针
只有聪明人才能看见的摘要~( ̄▽ ̄~)~
82 0
|
存储 C++
【C生万物】 指针和数组笔试题汇总 (下)
【C生万物】 指针和数组笔试题汇总 (下)
91 0
|
存储
【C生万物】 指针和数组笔试题汇总 (上)
【C生万物】 指针和数组笔试题汇总 (上)
48 0
|
算法 测试技术 C语言
【数组和进阶指针经典笔试题12道】这些题,满足你对数组和指针的所有幻想,come on !
【数组和进阶指针经典笔试题12道】这些题,满足你对数组和指针的所有幻想,come on !
126 0
【数组和进阶指针经典笔试题12道】这些题,满足你对数组和指针的所有幻想,come on !
|
存储 编译器 程序员
【C初阶】数组
【C】数组 一维数组,二维数组,数组越界
106 0
【C初阶】数组
|
存储 Java 数据挖掘
Java基础知识练习(减肥计划、逢七过、不死神兔、百钱百鸡、数组元素求和、数组内容相同、查找、反转、评委打分)
Java基础知识练习(减肥计划、逢七过、不死神兔、百钱百鸡、数组元素求和、数组内容相同、查找、反转、评委打分)!
Java基础知识练习(减肥计划、逢七过、不死神兔、百钱百鸡、数组元素求和、数组内容相同、查找、反转、评委打分)