数组元素左移的解法
来源:互联网 发布:拉丁美洲独立运动知乎 编辑:程序博客网 时间:2024/06/08 11:18
题目:对于一维数组A[0...n-1](n>1),设计在时间和空间上方面尽可能有效率的算法,将A中的序列循环左移P(0<p<n)个位置,即将A中的数据从(A0,A1,A2......An-1)转变成(Ap,Ap+1......An-1,A0,A1......Ap-1),并分析所设计算法的时间复杂度和空间复杂度
其实我想大家在看到这道题时,很希望能使用链表来做。因为这样只需把其看成一个队列,队头移出,队尾移进,不浪费额外的空间且时间复杂度为线性阶;甚至熟悉指针的同学更能想到把原链表的尾指针指向首元结点,第p个结点的指针指向null,而头指针指向第p+1个结点,这样,只需简单的操作且时间复杂度为常数阶,可以不费吹灰之力解决问题。不过,题目硬性要求要使用一维数组,所以难度上就加大了。
原始链表
移位后链表
接下来是四种解决方法
C语言实现
算法1
创造一个额外数组,用来存取移位的数据
#include<stdio.h>
int main()
{
int arr[10]={0,1,2,3,4,5,6,7,8,9};
int s[10];
int p;
scanf("%d", &p);
for(int i=0; i<p; i++)
s[i]=arr[i];
for(int i=p; i<10; i++)
arr[i-p]=arr[i];
for(int i=9,j=p; i>9-p; i--)
arr[i]=s[--j];
for(int i=0; i<10; i++)
printf("%3d", arr[i]);
return 0;
}
时间复杂度O(n),缺点:牺牲空间。
算法2
循环p次,每次把最前面的数移到最后面
#include<stdio.h>
int main()
{
int arr[10]={0,1,2,3,4,5,6,7,8,9};
int p;
scanf("%d", &p);
for(int i=0; i<p; i++){
int temp=arr[0];
for(int j=1; j<10; j++)
arr[j-1]=arr[j];
arr[9]=temp;
}
for(int i=0; i<10; i++)
printf("%3d", arr[i]);
return 0;
}
时间复杂度:O(n^2),缺点:牺牲时间
前两种方法都不是特别好,随着时间的减少,空间的利用会增大。
其实很多时候,时间和空间都是此消彼长的。
算法3
先全反序,再以9-p与10-p为界限,分别对前后进行反序
#include<stdio.h>
int main()
{
int arr[10]={0,1,2,3,4,5,6,7,8,9};
int p;
scanf("%d", &p);
for(int i=0; i<5; i++){
int temp=arr[i];
arr[i]=arr[9-i];
arr[9-i]=temp;
}
for(int i=0; i<(10-p)/2; i++){
int temp=arr[i];
arr[i]=arr[9-p-i];
arr[9-p-i]=temp;
}
for(int i=0; i<p/2; i++){
int temp=arr[9-i];
arr[9-i]=arr[10-i-p];
arr[10-p-i]=temp;
}
for(int i=0; i<10; i++)
printf("%3d", arr[i]);
return 0;
}
时间复杂度:O(n)
算法4
以p为间隔,分别往前移位,第一个数则移到最后相应的位置
#include<stdio.h>
int main()
{
int arr[10]={0,1,2,3,4,5,6,7,8,9};
int p;
scanf("%d", &p);
for(int i=0; i<p; i++){
int temp=arr[i];
int pos=i;
while(pos<10){
arr[pos]=arr[pos+p];
pos+=p;
}
arr[pos-p]=temp;
}
for(int i=9; i>9-10%p; i--){
int temp=arr[9];
for(int j=8; j>9-p; j--)
arr[j+1]=arr[j];
arr[10-p]=temp;
}
for(int i=0; i<10; i++)
printf("%3d", arr[i]);
return 0;
}
时间复杂度:O(n^2),这个方法我起初也想到过,不过觉得不太可行就没去尝试,今天上午上课听到老师说到这个方法,就去尝试了一下,老师举的例子是12个数移位是3,的确是看似简单。不过我发现其中是有原因的,因为12能整除3,所以每次移位都能恰好。而假设10个数移位3,就不能刚刚好了,所以,需要对最后面的数进行额外的处理,我发现,需要把后面的数进行向右移位余数个位数,只有这样,才能成功移位。而且即使这样,时间复杂度也为n^2,时间上牺牲太多,故不太建议。
综上,建议使用算法3
- 数组元素左移的解法
- 数组元素循环左移
- 数组元素的循环左移和右移...
- 对于给定的数组,循环左移p个元素
- 关于字符串左移的解法
- 数组元素循环左/右移问题
- 数组元素循环左/右移问题
- 将数组中的元素循环左移 p 个元素
- 数组剔除元素后的乘积Python解法
- 队列实现对有n个元素的数组循环左移k位
- 【算法】字符串左移函数的O(n)解法
- 数组元素循环左移p个位置
- 左移数组中的前P个元素
- [珠玑之椟]字符串和序列:左移、哈希、最长重复子序列的后缀数组解法、最大连续子序列
- [珠玑之椟]字符串和序列:左移、哈希、最长重复子序列的后缀数组解法、最大连续子序列
- [珠玑之椟]字符串和序列:左移、哈希、最长重复子序列的后缀数组解法、最大连续子序列
- [珠玑之椟]字符串和序列:左移、哈希、最长重复子序列的后缀数组解法、最大连续子序列
- 字符串的左旋转最佳解法
- 从一个数组中同时找出最大最小数-算法导论第九章
- 第4周项目5(1) 猴子选大王
- C语言求一个整数的二进制形式表示中1的个数,用函数实现
- linux输出文件行数
- 使用Python3解压gz、tar、tgz、zip、rar五种格式的压缩文件例子
- 数组元素左移的解法
- hihoCoder1181 欧拉路·二 ( Fleury )
- 三种创建多线程的方式
- Redis Cluster安装配置
- angularjs路由(ngRoute)
- Java容器(一)之Iterator与Iterable接口
- 【转】jvm系列(一):java类的加载机制
- nginx比apache快的原因
- LeetCode:Reverse Vowels of a String