【问题标题】:Sort Array By Parity the result is not robust按奇偶校验排序数组结果不可靠
【发布时间】:2019-03-12 03:32:18
【问题描述】:

我是一名新程序员,我正在尝试按奇偶性对整数向量进行排序 - 将偶数放在赔率前面。奇数或偶数本身的顺序无关紧要。比如给定一个输入[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::merge 适用于排序范围。 en.cppreference.com/w/cpp/algorithm/merge您的范围未排序。
  • 考虑使用算法标头中的std::sort 和自定义比较器,按照您想要的方式对它们进行排序。
  • std::merge 并没有按照你的想法去做。

标签: c++


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    因为merge 函数假定两个范围是已排序的,这在归并排序中使用。相反,您应该只使用vectorinsert 函数:

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

    【讨论】:

      【解决方案3】:

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

      使用向量的价值在于避免插入和移动。数组/向量很快,因为它们允许立即访问内存作为从一开始的偏移量。好好利用这个!

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

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

      【讨论】:

        【解决方案4】:

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

          // 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&lt;int&gt;&amp; 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;
          }
        

        在上述两种情况下(in-placeout-of-place),函数的复杂度为 O(N),N 是 @987654328 中的元素数@,比对 N 个元素进行排序的一般 O(N log N) 好得多。这是因为这个问题实际上并没有排序——它只区分偶数和奇数。因此,无需调用成熟的排序算法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-06-29
          • 2013-06-25
          • 1970-01-01
          • 2015-04-04
          • 2013-04-21
          • 2019-05-10
          相关资源
          最近更新 更多