题目:有整数数组a,求其循环右移k位后的值,要求最小空间复杂度。
例如:
int[] a = {1,2,3,4,5,6,7};循环右移5位后,
值为:{3,4,5,6,7,1,2}。
最基本的实现:
public void toRightMove(int[] nums, int k) {
if (k == 0 || k == nums.length) {
return;
}
int lastIndex = nums.length - 1;
int t = 0;
while (k > 0) {
t = nums[lastIndex];
for (int i = lastIndex; i > 0; i--) {
nums[i] = nums[i - 1];
}
nums[0] = t;
k--;
}
Log.e("tag","toRightMove>>result:"+nums);
}
算法时间复杂度为O(KN),N为数组长度。
通过举例可以发现,原数组与移位后的数组之间是存在规律的。化整为零来看,是将原数组根据k值一分为二。结果是这两部分的整体置换。
详见:数组元素循环右移问题
这是一道今日头条的算法题,笔者的实现是上面那种。当时也发现了这一现象,但一时又没理出实现思路,只能作罢。所以并没给面试官留下多深的影响。
这里贴出代码,高效的实现是:
public void toRightMove2(int[] nums, int k) {
if(nums == null || nums.length == 0){
return;
}
k = k % nums.length;
if (k == 0 || k == nums.length) {
return;
}
int lastIndex = nums.length - 1;
int t;
for(int i = 0,j = lastIndex;i <j;i++,j --){
t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
for(int i = 0,j = k -1;i < j;i++,j --){
t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
for(int i = k,j = lastIndex;i < j;i++,j --){
t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
Log.e("tag","toRightMove>>result:"+nums);
}
此时时间复杂度降为了O(N/2)。