以预先指定的顺序对数组变量进行随机播放,而不使用“输入数组大小”的额外内存

时间:2010-10-11 04:05:24

标签: c++ algorithm

输入:

  A[4] = {0,4,-1,1000} - Actual Array
  P[4] = {1,0,3,2} - Order to be reshuffled 

输出:

    A[4] = {4,0,1000,-1}

条件:不要使用其他数组作为内存。可以使用额外的变量或两个。

问题:我在C ++中使用以下程序,但是对于数组P的某些输入,这会失败。

#include<iostream>

using namespace std;

void swap(int *a_r,int *r)
{
    int temp = *r;
    *r = *a_r;
    *a_r = temp;
}
int main()
{
    int A[4] = {0,4,-1,1000};
    int P[4] = {3,0,1,2};
    int value = A[0] , dest = P[0];

    for(int i=0; i<4;i++)
    {
        swap(&A[dest],&value);
        dest = P[dest];
    }
    for(int i=0;i<4;i++)
        cout<<A[i]<<" ";
}

6 个答案:

答案 0 :(得分:4)

由于你有一个名为P的备用数组,并且在引用的问题中没有任何内容规定它必须被视为一个常量数组,你可以这样做:

for (i = 0; i < 4; i++)
    P[i] = A[P[i]];
for (i = 0; i < 4; i++)
    A[i] = P[i];

如果您不允许修改P,那么您必须更加努力工作(如果A的数据类型与A的数据类型不同或兼容,您还必须更加努力地工作。 p)。

然而,我担心这是一个狡猾的技巧,并没有真正回答这个问题;它完成了工作,但没有回答这个问题。

答案 1 :(得分:1)

首先,我非常喜欢 Jonathan 的解决方案,但我觉得我也可以添加一些有趣的想法。

主要观察结果是数组P由几个循环组成 我们考虑一下p = {1, 4, 3, 2, 0, 5}。有三个循环:0 => 1 => 4 => 02 => 3 => 25 => 5。要在一个循环旁边替换变量,我们根本不需要额外的内存。我们就像这样经历它

do {
    a[i] = a[p[i]];
    i = p[i];
} while (i != first_i);

(不过,最后一个元素需要特别注意。)完整的工作版本:

    for (int i = 0; i < n; ++i) {
        if (p[i] < 0) {
            // been at index 'i' already
            continue;
        }

        // new loop found
        int j = i;
        int first_value = a[i]; // to be put in last position in the chain
        int prev_j; // we always store previous 'j' index
        do {
            a[j] = a[p[j]];

            prev_j = j;
            j = p[j]; // move to next 'j'
            p[prev_j] = -1; // mark element as processed
        } while (i != j);
        a[prev_j] = first_value;
    }

我的解决方案唯一的问题是它使用p数组将元素标记为'已处理'。一些采访者可能认为没问题,其他人 - 不是,取决于他们想到的解决方案。

答案 2 :(得分:1)

int _tmain(int argc, _TCHAR* argv[])
{
    A[4] = {0,4,-1,1000}
    P[4] = {1,0,3,2}
    int temp = arr2[0];

    for(int i=0;i<4;i++)
    {
        for(temp = P[i];i<3;temp = P[temp])
        {
        if(temp >= i)
        {
            int data; 
            data = A[i];
            A[i] = A[temp];
            A[temp] = data;
            break;
        }
        }

    }
    _getch();
    return 1;
}

答案 3 :(得分:1)

int _tmain(int argc, _TCHAR* argv[])
{
    A[4] = {0,4,-1,1000}
    P[4] = {1,0,3,2}
    int temp = arr2[0];

    for(int i=0;i<4;i++)
    {
        for(temp = P[i];i<3;temp = P[temp])
        {
        if(temp >= i)
        {
            int data; 
            data = A[i];
            A[i] = A[temp];
            A[temp] = data;
            break;
        }
        }

    }
    _getch();
    return 1;
}

答案 4 :(得分:0)

略微修改以计算目标值

int main()
{
    int A[4] = {0,4,-1,1000};
    int P[4] = {3,0,1,2};
    int value = A[0], dest = P[0];

    for(int i=0; i<4-1;i++)
    {
      int count=0;
      dest = P[i];
      while(dest<i){ //if P[i] points to lower value, it got swapped with some other position. 
        dest = P[dest];
      }
      swap(&A[dest],&A[i]);
    }
    for(int i=0;i<4;i++)
        cout<<A[i]<<" ";
    cout<<"\n";
}       

答案 5 :(得分:0)

可能认为它违背了问题的精神 - 但可以使用单个局部变量的多个堆栈实例(从运行时的角度来看)(代码透视)。允许变异P同样不确定,所以,FWIW - 一个递归的答案......

template <int N>
void shuffle(int (&a)[N], int p[], int i = -1)
{
    if (++i < N)
    {
        int result = a[p[i]];
        shuffle(a, p, i);
        a[i] = result;
    }
}