编程之美 -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;
}


本章完!

目录
相关文章
|
7月前
谭浩强数组相关代码
谭浩强数组相关代码
37 0
|
算法
算法刷题-数组
算法刷题-数组
60 0
算法刷题-数组
|
4月前
|
Java
Java数组几道练习题
Java数组几道练习题
41 11
|
4月前
|
存储 Java 索引
八股day01_数组
八股day01_数组
|
6月前
|
C语言
C语言学习记录——鹏哥二分法查找数组中元素 复习整理
C语言学习记录——鹏哥二分法查找数组中元素 复习整理
29 0
|
7月前
|
C++
【一刷《剑指Offer》】面试题 3:二维数组中的查找
【一刷《剑指Offer》】面试题 3:二维数组中的查找
剑指offer(数组相关面试题)
剑指offer(数组相关面试题)
|
机器学习/深度学习 存储 算法
【算法思维训练-剑指Offer联名 一】数组篇
【算法思维训练-剑指Offer联名 一】数组篇
83 0
剑指Offer_编程题_数组中只出现一次的数字
剑指Offer_编程题_数组中只出现一次的数字
62 0
|
算法 Linux C语言
几道数组相关的面试题
几道数组相关的面试题
92 0
几道数组相关的面试题