C/C++面试之算法系列--整数数组的循环右移
来源:互联网 发布:虚无世界2java 编辑:程序博客网 时间:2024/04/29 05:11
【转摘序】方法四:整体翻转,再局部翻转,没有申请额外的空间,从两头往中间互换,移动的次数少,时间效率也高。算法新颖,在面试中可以算最好的答案,关键是要能体现你的与众不同,当然了通俗的算法你也要知道,这样才能让自己不落入俗套。
整体和局部翻转的思想在“算法系列--以单词为最小单位翻转字符串 ”算法四以及“从"反转32 位数"算法题分析面试策略 ”都有应用,由此可见对于算法题,要充分理解其精髓,便可举一反三,以一推十,以不变应万变!
×××××××××××××××××××××××××
【题目】有一个整数数组,现要求实现这个整数数组的循环右移。如:
1,2,3,4,5 则循环右移两位后结果是:4,5,1,2,3。
方法一:(最最容易想到的办法)
void RightCircleShift_00(int buffer[],int shift)
{
int i,j,tt;
for(i=0;i<shift;i++)
{
tt = buffer[ARRSIZE-1];
for(j=ARRSIZE-1;j>0;j--)
buffer[j] = buffer[j-1];
buffer[0] = tt;
}
}
这个办法是用两个循环来控制,内循环每次向右移动一位,外循环则用来限制移动的位数。算法需要执行 ARRSIZE * ShiftValue次,时间复杂度是O( N2 )。
方法二:(由方法一得到的递归程序)
void RightCircleShift_01(int buffer[],int shift)
{
int *p,tt;
tt = *(buffer+ARRSIZE-1);
for(p = buffer+ARRSIZE-1;p > buffer;p--)
*p = *(p-1);
*buffer = tt;
// 上面实现右移一位
// 每移动一次减1,未移完接着调用
shift--;
if(shift > 0)
RightCircleShift_00(buffer,shift);
}
这个程序跟方法一类似,区别就是它是用递归来实现的。同样需要执行ARRSIZE * ShiftValue次,时间复杂度也是O( N2 )。
递归的原则是每次调用只处理一层,即只剥一层皮,要注意退出条件和需要递归调用的条件,严格来说上面程序的递归逻辑不好
方法三: 利用库函数拷贝
void RightCircleShift_02(int buffer[],int shift)
{
int *title,*r,*p;
if(shift == 0)
return;
// 循环的圈数可能大于1了
shift = shift % ARRSIZE;
title = (int *)malloc(sizeof(int)*shift);
if( title == NULL )
return;
r = buffer + (ARRSIZE - shift);
memcpy(title, r, shift * sizeof(int));
p = buffer + shift;
memmove(p, buffer, (ARRSIZE - shift) * sizeof(int));
memcpy(buffer, title, shift * sizeof(int));
free(title);
}
这个算法需要移动位数大小的临时辅助空间。如需移动两位,则申请两个的空间,然后把从右边起的两个元素拷贝的临时辅助空间,然后前面的元素向后移动两位,最后再把临时空间里面的两个元素拷贝到前面的两位即可完成循环右移。需要执行 ARRSIZE次,时间复杂度是O( N )。
上述方法重复利用了库函数,当题目没有明确限定的情况下适当的使用库函数可以简化程序。
方法四:整体翻转,再局部翻转
void RightCircleShift_04(int buffer[],int shift)
{
shift %= ARRSIZE;
ReverseArray(buffer,1,ARRSIZE);
ReverseArray(buffer,1,shift);
ReverseArray(buffer,shift+1,ARRSIZE);
}
void ReverseArray(int buffer[],int start,int end)
{
int tt;
if(end > ARRSIZE)
return;
// 换成数组下标
start -= 1;
end -= 1;
while(start < end)
{
tt = buffer[start];
buffer[start++] = buffer[end];
buffer[end--] = tt;
}
}
这个办法也是很不错,需要两次扫描数组即可,时间复杂度O(N)。
没有申请额外的空间,从两头往中间互换,移动的次数少,时间效率也高。算法新颖,在面试中可以算最好的答案,关键是能体现能力。
算法是网友 luodongshui 提出的:
<!--[if !supportLists]-->1、<!--[endif]-->先将整个数组反转。
<!--[if !supportLists]-->2、<!--[endif]-->然后再反转前shift个元素。
<!--[if !supportLists]-->3、<!--[endif]-->接着再反转后N-shift个元素。
参考资料:
http://blog.csdn.net/ammana_babi/archive/2007/06/21/1660973.aspx
- C/C++面试之算法系列--整数数组的循环右移
- C/C++面试之算法系列--从“整数转换成字符串”看算法的联想
- C/C++面试之算法系列--从“整数转换成字符串”看算法的联想
- C/C++面试之算法系列--约瑟夫环:每隔两个循环删除数组元素,求最后删除者的下标问题
- C/C++面试之算法系列--atoi(char *str)将字符串转换成整数
- C/C++面试之算法系列--atoi(char *str)将字符串转换成整数
- 整数数组的循环右移收藏
- 【我解C语言面试题系列】004 数组的循环右移问题
- C/C++面试之算法系列--二维动态数组定义及二维静态数组与**P的区别
- 整数型的有序递增数组循环右移x位后,查找指定整数 算法
- C/C++面试之算法系列--去除数组中的重复数字
- 数组循环右移的算法
- C/C++面试之算法系列--菲波拉契数列的递归与非递归算法
- C/C++面试之算法系列--几个最大子字符串的算法题
- C/C++面试之算法系列--菲波拉契数列的递归与非递归算法
- 【C/C++】数组元素循环右移问题
- 整数数组的循环左移和右移
- C/C++面试之算法系列--N!的尾部连续0的个数
- PIMS,我的作品
- 2007.09.9 星期几? 晴
- C/C++面试之算法系列--以单词为最小单位翻转字符串
- 暂时没有时间写,谢谢您的光临
- 开始真的生活
- C/C++面试之算法系列--整数数组的循环右移
- 我的大学是一个忏悔的轮回
- C++中复杂静态数据成员的初始化
- 健康指南:人体十大最佳黄金时间
- 疲惫的一天
- 利用javascript获得窗口的大小
- 一种新的穿透防火墙的数据传输技术
- [VC++]点对点(P2P)多线程断点续传的实现
- C# 逐行驱动打印