如何编写函数shift(int* arr, int k)
将数组循环移位一个整数k?我不能从堆中说出“malloc”内存。
例如,使用伪代码,shift([1, 2, 3, 4], 2)
返回[3, 4, 1, 2]
,shift([3, 1, 5, 5], 103)
返回[1, 5, 5, 3]
。我已经尝试使用模数来实现这种效果,如这个Java程序所示,其中我基本上迭代了一半的数组和交换值。
public static int* shift(int* arr, int k) {
int half_array_len = arr.length / 2;
for (int i = 0; i < half_array_len; ++i) {
// Swap!
int newIndex = (i + k) % arr.length;
int temp = arr[i];
arr[i] = arr[newIndex];
arr[newIndex] = arr[i];
}
return arr;
}
但是,我相信这个功能仅适用于偶数长的数组。
如何为任何长度的数组实现shift
?答案可以使用您想要的任何语言(Java,C ++,Ook Ook!等)。
答案 0 :(得分:8)
(之前已被问过几次。)基本上,在Bentley的“编程珍珠”(Juggling,Reversal和Block Swap算法)中描述和分析了三个专门用于解决这个问题的经典就地算法。这些幻灯片详细描述了它们
http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf
最简单的算法是反转算法。只需反转整个阵列,然后单独反转每个[n - k]和[k]块。完成。 (从哪一端计算[k]块取决于移位的方向。)
当然,首先对k
进行规范化是有意义的,即k = k % n
以确保k
小于n
。
P.S。在C ++中,答案是使用std::rotate
,它完全符合您的要求。但我怀疑这是你寻求的答案。虽然你可能想看看std::rotate
的一些实现(如果只发现它们通常使用Reversal算法:)
答案 1 :(得分:1)
我假设您的意思是您只能使用恒定数量的额外空间来执行此功能。可以使用以下算法(Python)在O(n*(k mod n))
时间内使用一个临时值完成:
def shift_one(array):
temp = array[-1] #put last element of array in a temp
for i in range(len(array)-1)[::-1]:
array[i+1] = array[i] #put each element in the next slot
array[0] = temp #then put the temp at the beginning
return array
def shift(array, k):
for i in range(k%len(array)):
array = shift_one(array)
return array
如果你实际上并不局限于恒定的额外空间,你可以使用以下算法在k
时间O(n)
额外的空间(几乎相同的事情):{/ p>
def shift(array, k):
k = k % len(array) #shifting by len(array) does nothing
temp = array[-k:] #copy out the last k elements
for i in range(len(array)-k)[::-1]:
array[i+k] = array[i]
array[:k] = temp
return array
另外,如果你有像Python这样的列表可以比数组更多,那么有一个非常简单的解决方案:
def shift(array, k):
#take the last k elements and put them at the front
return array[-k:]+array[:-k]