可以仅使用 std::sort() 将零移动到数组的末尾

possible to move zeros to the end of the array using only std::sort()?

本文关键字:移动 数组 std sort      更新时间:2023-10-16

我正在研究这个问题:

给定一个数组 nums,编写一个函数将所有 0 移动到它的末尾,同时保持非零元素的相对顺序。

我知道如何通过进行就地交换来回答这个问题,但我也想看看是否有可能用std::sort来解决它。

根据 cplusplus.com:

排序函数的比较器函数是一个二进制函数,它接受范围内的两个元素作为参数,并返回可转换为布尔值的值。返回的值指示作为第一个参数传递的元素是否被视为在其定义的特定严格弱排序中先于第二个参数。

该函数不得修改其任何参数。

这可以是函数指针或函数对象。

//comments below are based on my understanding
static bool comp(int a, int b){
    //lambda function evaluates to true - no swap, 
    //evaluates to false -swap
    if(a==0) return false;
    if(b==0) return true;
    //if neither a nor b is 0 them do not swap
    return true;
}
void moveZeroes(vector<int>& nums) {
    sort(nums.begin(),nums.end(),comp);
}

给定的测试用例是[0,1,0,3,12]

我的输出是[12,3,1,0,0]

你几乎做对了。在比较器函数中,您必须返回false才能不交换它们。此外,将std::sort更改为std::stable_sort以保持值的原始顺序。

static bool comp(int a, int b)
{
    //lambda function evaluates to true - no swap, 
    //evaluates to false -swap
    if(a==0) return false;
    if(b==0) return true;
    //if neither a nor b is 0 them do not swap
    return false;
}
void moveZeros(std::vector<int>& nums)
{
    std::stable_sort(nums.begin(),nums.end(),comp);
}

现场演示

正如Drew Dormann指出的那样,稳定分区是正确的算法。这是代码:

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> data { 0, 1, 0, 3, 12 };
    std::stable_partition(
        data.begin(), data.end(), [](int n) { return n != 0; });
    for (auto i : data)
        cout << i << ' ';
    cout << endl;
}

输出1 3 12 0 0

要使用的排序顺序只是零比所有非零值"大",并且等于其他零。 所有其他非零值都"小于"零,并且等效于任何其他非零值。

正确构造比较函数,然后您可以在调用std::stable_sort中使用它来实现您要做的事情。