📌  相关文章
📜  重新排列数组,使arr [i]变成arr [arr [i]],并增加O(1)个空间

📅  最后修改于: 2021-04-24 15:10:23             🧑  作者: Mango

给定大小为n的数组arr [] ,其中每个元素的范围为0n-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。

算法:

  1. 从头到尾遍历数组。
  2. 对于每个索引,按array [array [index]] %n递增元素。要获得第ith个元素,请找到带有n的模,即array [index]%n。
  3. 从头到尾再次遍历Travsese数组
  4. 将第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’