任务是重新排列数组,以便arr[i]
变为arr[arr[i]]
O(1)
额外空格。
示例:
2 1 3 5 4 0
变为:
3 1 5 0 4 2
我可以想到一个O(n²)
解决方案。提出了O(n)
解决方案here:
- 按
arr[i]
增加每个数组元素(arr[arr[i]] % n)*n
。- 将每个元素除以
醇>n
。
但这非常有限,因为它会导致缓冲区溢出。
有人可以对此提出改进吗?
答案 0 :(得分:1)
如果数组中的值都是正数(或全部为负数),则避免溢出的一种方法可能是运行置换周期并使用整数符号来标记访问索引。 (或者,如果数组长度小于2 ^(一个数组元素的位数 - 1),而不是使用符号,我们可以将所有值向左移一位并使用第一位标记访问索引。)该算法在运行期间导致较少的迭代次数和较少的原始数组值修改,而不是您要求改进的算法。
JSFiddle:http://jsfiddle.net/alhambra1/ar6X6/
JavaScript代码:
function rearrange(arr){
var visited = 0,tmp,indexes,zeroTo
function cycle(startIx){
tmp = {start: startIx, value: arr[startIx]}
indexes = {from: arr[startIx], to: startIx}
while (indexes.from != tmp.start){
if (arr[indexes.from] == 0)
zeroTo = indexes.to
if (indexes.to == visited){
visited++
arr[indexes.to] = arr[indexes.from]
} else {
arr[indexes.to] = -arr[indexes.from]
}
indexes.to = indexes.from
if (indexes.from != tmp.start)
indexes.from = arr[indexes.from]
}
if (indexes.to == visited){
visited++
arr[indexes.to] = tmp.value
} else {
arr[indexes.to] = -tmp.value
}
}
while (visited < arr.length - 1){
cycle(visited)
while (arr[visited] < 0 || visited == zeroTo){
arr[visited] = -arr[visited]
visited++
}
}
return arr
}
答案 1 :(得分:0)
//遍历数组直到最后。 //对于每个索引,将元素按array [array [index]%n]递增。要获取第ith个元素,请找到具有n的模,即array [index]%n。 //再次遍历到结束 //将第i个元素除以n,即array [i] / n
class Rearrange
{
void rearrange(int arr[], int n)
{
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
for (int i = 0; i < n; i++)
arr[i] /= n;
}
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println("");
}
public static void main(String[] args)
{
Rearrange rearrange = new Rearrange();
int arr[] = {6, 4, 9, 2, 5, 7};
int n = arr.length;
System.out.println("Given Array is :");
rearrange.printArr(arr, n);
rearrange.rearrange(arr, n);
System.out.println("Modified Array is :");
rearrange.printArr(arr, n);
}
}