【问题标题】:How to switch C++ array elements positions based on specified conditions?如何根据指定条件切换 C++ 数组元素位置?
【发布时间】:2019-01-08 17:16:33
【问题描述】:

我在完成这项家庭作业时遇到了一点问题。任务说:

"编写一个名为 MoveSmallest 的函数,它移动数组开头的所有最小整数元素。所有剩余的项目必须留在原处。(数组及其大小是参数)

示例: 数组:2, 3, 5, 1, 2, 3, 6, 4, 2, 1, 1 变为 1, 1, 1, 2, 3, 5, 2、3、6、4、2

void MoveSmallest(int A[],int n)
{
int Min;
for(int i=0;i<n;i++)
{
    if(i==0)
    {
        Min=A[i];
    }
    else if(A[i]<=Min)
    {
        Min=A[i];
    }
}

到目前为止,我只是想检查哪一个是数组中最小的元素。我不知道下一步该做什么。

【问题讨论】:

  • 您可以使用 std::swap() 来...呃..交换数组中的两个元素。您所需要的只是弄清楚您需要哪些。您可以编写另一个循环,将每个元素与 Min 进行比较,并将其与最左边的一个元素交换。
  • 你已经迈出了正确的第一步。您现在需要弄清楚如何将所有等于 Min 的元素移动到数组的开头。一个好的开始方法是考虑只将一个元素移动到开头,以及如何将所有后续元素向下移动一个位置。 @grungegurunge Swap 在这里不起作用,因为 OP 提到需要保留剩余元素的顺序
  • @GLC 以及如何将所有后续元素向下移动一个位置您的意思是“向上”?
  • “所有剩余的物品必须留在原处。” 我认为这意味着“必须保持原样”,对吧?因为示例中的第一个2 肯定不会停留在数组中的同一个位置。
  • 这似乎是使用std::min_elementstd::stable_partition 的两行解决方案。

标签: c++ arrays function


【解决方案1】:

一旦找到最小值,剩下要做的就是四处移动,以便在数组的开头有最小值。

您可以通过置换值来做到这一点,直到到达数组的“左侧”(即索引 0)。

void MoveSmallest(int A[],int n)
{
    int Min;
    for(int i=0;i<n;i++)
    {
        if(i==0)
        {
            Min=A[i];
        }
        else if(A[i]<=Min)
        {
            Min=A[i];
        }
    }

    for(int i = 0; i < n; i++)
    {
        if(A[i] == Min)
        {
            for(int j = i; j > 0; j--)
            {
                int tmp = A[j];
                A[j] = A[j-1];
                A[j-1] = tmp;
            }
        }
    }
}

您也可以使用std::swap 代替临时变量tmp 进行排列。

【讨论】:

  • 谢谢。我认为这就是我的解决方案,因为我只能使用 C++ 的基础知识。
  • 此解决方案可能有效,但效率低下,因为它在运行时是二次方的。 100 个元素意味着 10000 次循环迭代。有更有效的方法来划分项目,例如使用分治法,类似于合并排序。
  • 是的,我知道这些注意事项。但鉴于这是一个家庭作业,我猜想一个简单易写的解决方案最适合这个问题。
  • 是的。正如@n0m1s 所说。我只能使用语言的基础知识。它不必是最优的或有效的。
  • @TheM1KE25 合并排序可以使用“语言基础”来实现。问题是您还没有想出更好的方法来使用语言的基础知识。
【解决方案2】:

从数组的末尾开始,跟踪您遇到的最小元素的数量。然后每当你遇到一个非最小元素时,将它向右移动你到目前为止遇到的最小元素的数量:

void MoveSmallest(int A[], int n)
{
    int min;

    //Find min logic

    //shift non-min elements and count min elements
    int cnt = 0;
    for (int i = n-1; i >=0; --i)
    {
        if (A[i] == min)
            cnt++;
        else
            A[i+cnt] = A[i];
    }

    //Add min elements
    for (int i = 0; i < cnt; ++i)
        A[i] = min;

}

这将在 O(n) 时间和 O(1) 空间中运行。

【讨论】:

    【解决方案3】:

    由于您的帖子提到“基本 C++”,但没有提到什么是“基本”,这里是另一种解决方案。这是假设为“工作”目的创建数组被认为是“基本 C++”。

    void MoveSmallest(int A[], int n)
    {
        // get the minimum value
        int Min = A[0];
        for (int i = 1; i < n; ++i)
        {
            if (A[i] < Min)
                Min = A[i];
        }
    
        // get the count of the number of minimum values
        int minCount = 0;
        for (int i = 0; i < n; ++i)
        {
            if (A[i] == Min)
                ++minCount;
        }
    
        if (minCount > 0)
        {
            // create a work array and fill in the first
            // minCount values with the minimum value
            int *B = new int[n];
            for (int i = 0; i < minCount; ++i)
                B[i] = Min;
    
            // now fill in the rest of the work array with the values
            // in the A[] array that are not equal to Min
            int current_pos = minCount;
            for (int i = 0; i < n; ++i)
            {
                if (A[i] != Min)
                    B[current_pos++] = A[i];
            }
    
            // Now copy work array back to A array  
            for (int i = 0; i < n; ++i)
                A[i] = B[i];
    
            // get rid of work array
            delete[] B;
        }
    }
    

    Live Example

    这运行在线性时间O(n),而不是二次时间O(n*n)

    当然缺点是你需要为工作数组留出空间,所以内存成本是线性的O(n)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      • 2022-09-28
      • 2020-06-06
      • 1970-01-01
      • 2020-03-19
      • 2022-08-13
      • 1970-01-01
      相关资源
      最近更新 更多