给定大小为n的数组arr [] ,其中每个元素的范围为0到n-1 。重新排列给定的数组,使arr [i]变为arr [arr [i]] 。这应该在O(1)额外空间的情况下完成。
例子:
Input: arr[] = {3, 2, 0, 1}
Output: arr[] = {1, 0, 3, 2}
Explanation:
In the given array
arr[arr[0]] is 1 so arr[0] in output array is 1
arr[arr[1]] is 0 so arr[1] in output array is 0
arr[arr[2]] is 3 so arr[2] in output array is 3
arr[arr[3]] is 2 so arr[3] in output array is 2
Input: arr[] = {4, 0, 2, 1, 3}
Output: arr[] = {3, 4, 2, 0, 1}
Explanation:
arr[arr[0]] is 3 so arr[0] in output array is 3
arr[arr[1]] is 4 so arr[1] in output array is 4
arr[arr[2]] is 2 so arr[2] in output array is 2
arr[arr[3]] is 0 so arr[3] in output array is 0
arr[arr[4]] is 1 so arr[4] in output array is 1
Input: arr[] = {0, 1, 2, 3}
Output: arr[] = {0, 1, 2, 3}
Explanation:
arr[arr[0]] is 0 so arr[0] in output array is 0
arr[arr[1]] is 1 so arr[1] in output array is 1
arr[arr[2]] is 2 so arr[2] in output array is 2
arr[arr[3]] is 3 so arr[3] in output array is 3
如果消除了多余的空间条件,这个问题将变得非常容易。问题的主要部分是在没有额外空间的情况下执行此操作。
我们强烈建议您单击此处并进行实践,然后再继续解决方案。
以下解决方案的功劳归功于Ganesh Ram Sundaram。
方法:给定数组的数组元素位于0到n-1之间。现在需要一个可以同时存储两个不同值的数组元素。为了实现此增量,第i个索引处的每个元素都将增加(arr [arr [i]]%n)* n 。在第一步的增量操作之后,每个元素都同时包含旧值和新值。可以通过arr [i]%n获得旧值,并且可以通过arr [i] / n获得新值。
如何做到这一点?
假设一个元素是a ,另一个元素是b ,两个元素都小于n。因此,如果元素a增加b * n 。因此该元素变为a + b * n,因此当a + b * n除以n时,该值为b,而a + b * n %n为a。
算法:
- 从头到尾遍历数组。
- 对于每个索引,按array [array [index]] %n递增元素。要获得第ith个元素,请找到带有n的模,即array [index]%n。
- 从头到尾再次遍历Travsese数组
- 将第i个元素除以n(即array [i] / n)后,打印第i个元素。
执行:
C++
#include
using namespace std;
// The function to rearrange an array
// in-place so that arr[i] becomes arr[arr[i]].
void rearrange(int arr[], int n)
{
// First step: Increase all values by (arr[arr[i]]%n)*n
for (int i=0; i < n; i++)
arr[i] += (arr[arr[i]]%n)*n;
// Second Step: Divide all values by n
for (int i=0; i
Java
class Rearrange
{
// The function to rearrange an array in-place so that arr[i]
// becomes arr[arr[i]].
void rearrange(int arr[], int n)
{
// First step: Increase all values by (arr[arr[i]]%n)*n
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
// Second Step: Divide all values by n
for (int i = 0; i < n; i++)
arr[i] /= n;
}
// A utility function to print an array of size n
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println("");
}
/* Driver program to test above functions */
public static void main(String[] args)
{
Rearrange rearrange = new Rearrange();
int arr[] = {3, 2, 0, 1};
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);
}
}
// This code has been contributed by Mayank Jaiswal
Python3
# Python3 program to Rearrange
# an array so that arr[i] becomes
# arr[arr[i]]
# The function to rearrange an
# array in-place so that arr[i]
# becomes arr[arr[i]].
def rearrange(arr, n):
# First step: Increase all values
# by (arr[arr[i]] % n) * n
for i in range(0, n):
arr[i] += (arr[arr[i]] % n) * n
# Second Step: Divide all values
# by n
for i in range(0, n):
arr[i] = int(arr[i] / n)
# A utility function to print
# an array of size n
def printArr(arr, n):
for i in range(0, n):
print (arr[i], end =" ")
print ("")
# Driver program
arr = [3, 2, 0, 1]
n = len(arr)
print ("Given array is")
printArr(arr, n)
rearrange(arr, n);
print ("Modified array is")
printArr(arr, n)
# This code is contributed by shreyanshi_arun
C#
// C# Program to rearrange an array
// so that arr[i] becomes arr[arr[i]]
// with O(1) extra space
using System;
class Rearrange
{
// Function to rearrange an
// array in-place so that arr[i]
// becomes arr[arr[i]].
void rearrange(int []arr, int n)
{
// First step: Increase all values
// by (arr[arr[i]] % n) * n
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
// Second Step: Divide all values by n
for (int i = 0; i < n; i++)
arr[i] /= n;
}
// A utility function to
// print an array of size n
void printArr(int []arr, int n)
{
for (int i = 0; i < n; i++)
Console.Write(arr[i] + " ");
Console.WriteLine("");
}
// Driver Code
public static void Main()
{
Rearrange rearrange = new Rearrange();
int []arr = {3, 2, 0, 1};
int n = arr.Length;
Console.Write("Given Array is :");
rearrange.printArr(arr, n);
rearrange.rearrange(arr, n);
Console.Write("Modified Array is :");
rearrange.printArr(arr, n);
}
}
// This code has been contributed by Nitin Mittal.
PHP
Javascript
输出:
Given array is
3 2 0 1
Modified array is
1 0 3 2
复杂度分析:
- 时间复杂度: O(n),只需要对数组进行一次遍历。因此,时间复杂度为O(n)。
- 辅助空间: O(1),不需要额外的空间。
上述解决方案的问题是,它可能导致溢出。
这是一个更好的解决方案:
重新排列数组,如果’arr [i]’为’j’,则’arr [j]’变为’i’