按奇偶校验排序数组结果不可靠

时间:2019-03-12 03:32:18

标签: c++

我是一名新程序员,我正在尝试按奇偶校验对整数向量进行排序-将偶数放在赔率前。奇数或偶数内部的顺序本身并不重要。例如,给定输入[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;
    }
};

4 个答案:

答案 0 :(得分:5)

如果您只需要在偶数前加上偶数而不是完整的排序,我建议您使用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;
}

答案 1 :(得分:2)

因为merge函数假定两个范围已排序,因此在合并排序中使用。相反,您应该只使用vector的{​​{3}}函数:

result.insert(result.end(), even.begin(), even.end());
result.insert(result.end(), odd.begin(), odd.end());
return result;

答案 2 :(得分:2)

无需创建三个单独的向量。当您在结果向量中分配了足够的空间时,该向量可用作最终向量,还可以存储子向量,并存储分隔的奇数和偶数。

使用向量的价值是避免插入和移动,该向量在幕后是数组。数组/向量之所以快速,是因为它们允许从头开始的偏移量立即访问内存。利用这一点!

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

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;
    }
};

答案 3 :(得分:0)

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

  // 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和{{1}之前复制元素}(当然也不要使用--j,而是横向复制元素;也请以std::swap的形式传递A)。

const std::vector<int>& A

在上述两种情况下(原地为 原地),该函数的复杂度为O(N),N为{{ 1}},比一般的O(N log N)对N个元素进行排序要好得多。这是因为问题实际上并没有 sort 太多-它只会将奇数与偶数分开。因此,无需调用完整的排序算法。