按奇偶校验排序数组结果不稳健

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了按奇偶校验排序数组结果不稳健相关的知识,希望对你有一定的参考价值。

我是一个新的程序员,我试图按他们的平价排序一个整数向量 - 在偶数前加上偶数。奇数或偶数内部的顺序无关紧要。例如,给定输入[3,1,2,4],输出可以是[2,4,3,1]或[4,2,1,3]等。下面是我的c ++代码,有时我幸运的是,矢量得到了正确的排序,有时却没有。我导出奇数和偶数向量,它们看起来是正确的,但当我试图将它们组合在一起时,它只是搞砸了。有人可以帮我调试吗?

class Solution 
public:
    vector<int> sortArrayByParity(vector<int>& A) 
        unordered_multiset<int> even;
        unordered_multiset<int> odd;
        vector<int> result(A.size());

        for(int C:A)
        
            if(C%2 == 0)
                even.insert(C);
            else
                odd.insert(C);
        
        merge(even.begin(),even.end(),odd.begin(),odd.end(),result.begin());
        return result;
    
;
答案

如果您在赔率之前只需要偶数值而不是完整的排序我建议您使用std::partition。你给它两个迭代器和一个谓词。谓词返回true的元素将出现在其他元素之前。它就地工作,应该非常快。

像这样的东西:

std::vector<int> sortArrayByParity(std::vector<int>& A)

    std::partition(A.begin(), A.end(), [](int value)  return value % 2 == 0; );
    return A;

另一答案

因为merge函数假定两个范围已排序,这在合并排序中使用。相反,你应该只使用insertvector函数:

result.insert(result.end(), even.begin(), even.end());
result.insert(result.end(), odd.begin(), odd.end());
return result;
另一答案

无需创建三个单独的向量。由于您已在结果向量中分配了足够的空间,因此该向量也可用作最终向量,以存储子向量,存储分离的奇数和偶数。

使用矢量(在封面下是一个数组)的值是为了避免插入和移动。数组/向量很快,因为它们允许从一开始就作为偏移立即访问内存。利用这个!

代码只是保留下一个奇数和偶数索引的索引,然后相应地分配正确的单元格。

class Solution 

public:
// As this function does not access any members, it can be made static
    static std::vector<int> sortArrayByParity(std::vector<int>& A) 

      std::vector<int> result(A.size());
      uint even_index = 0;
      uint odd_index = A.size()-1;

      for(int element: A)
      
        if(element%2 == 0)
          result[even_index++] = element;
        else
          result[odd_index--] = element;
      
      return result;
    
;
另一答案

利用您不关心偶数或奇数本身的顺序这一事实,您可以使用一种非常简单的算法来就地对数组进行排序:

  // Assume helper function is_even() and is_odd() are defined.
  void sortArrayByParity(std::vector<int>& A)
  
    int i = 0;  // scanning from beginning
    int j = A.size()-1;  // scanning from end
    do 
      while (i < j && is_even(A[i])) ++i;  // A[i] is an even at the front
      while (i < j && is_odd(A[j])) --j;  // A[j] is an odd at the back
      if (i >= j) break;
      // Now A[i] must be an odd number in front of an even number A[j]
      std::swap(A[i], A[j]);
      ++i;
      --j;
     while (true);
  

请注意,上面的函数返回void,因为向量是就地排序的。如果你想要返回输入向量的排序副本,你需要在函数内部定义一个新的向量,并在每个++i--j之前复制元素(当然不要使用std::swap但是复制元素交叉相反;同样,通过A作为const std::vector<int>& A)。

  // Assume helper function is_even() and is_odd() are defined.
  std::vector<int> sortArrayByParity(const std::vector<int>& A)
  
    std::vector<int> B(A.size());
    int i = 0;  // scanning from beginning
    int j = A.size()-1;  // scanning from end
    do 
      while (i < j && is_even(A[i])) 
        B[i] = A[i];
        ++i;
      
      while (i < j && is_odd(A[j])) 
        B[j] = A[j];
        --j;
      
      if (i >= j) break;
      // Now A[i] must be an odd number in front of an even number A[j]
      B[i] = A[j];
      B[j] = A[i];
      ++i;
      --j;
     while (true);
    return B;
  

在上述两种情况下(就地或非现场),函数具有复杂度O(N),N是A中的元素数量,比用于排序N个元素的一般O(N log N)好得多。这是因为这个问题实际上并没有太多分类 - 它只是从奇数中分离出来。因此,无需调用完整的排序算法。

以上是关于按奇偶校验排序数组结果不稳健的主要内容,如果未能解决你的问题,请参考以下文章

按奇偶校验排序数组

922-按奇偶校验排序数组II

Leetcode-905 按奇偶校验排序数组

「 每日一练,快乐水题 」905. 按奇偶排序数组

922. 按奇偶排序数组 II『简单』

手把手带你刷好题—— 39.按奇偶排序数组(双指针)