C++ c++;在未排序的数组中查找第一个缺少的正值

C++ c++;在未排序的数组中查找第一个缺少的正值,c++,algorithm,C++,Algorithm,我试图理解在未排序的数组中找到第一个缺失正值的解决方案。它是这样工作的 1,找到输入的最小值和最大值,并用 特殊正值。 2.在确保最小值以1开始(否则我们知道“1”丢失)之后,我们扫描输入,类似于计数排序,因为我们不能 使用额外的空间。我无法将这些值标记为负值来表示 吃角子老虎了 3.在valMin和valMax之间扫描我们刚刚计算的输入范围,如果我们可以确定任何插槽未被占用(如中为正值),则我们 知道那是丢失号码的位置 我的问题是这两条线在做什么 int &val = nums[abs

我试图理解在未排序的数组中找到第一个缺失正值的解决方案。它是这样工作的

1,找到输入的最小值和最大值,并用 特殊正值。 2.在确保最小值以1开始(否则我们知道“1”丢失)之后,我们扫描输入,类似于计数排序,因为我们不能 使用额外的空间。我无法将这些值标记为负值来表示 吃角子老虎了

3.在valMin和valMax之间扫描我们刚刚计算的输入范围,如果我们可以确定任何插槽未被占用(如中为正值),则我们 知道那是丢失号码的位置

我的问题是这两条线在做什么

int &val = nums[abs(num) - valMin];
if (val > 0) val = -val;
例如,如果您的输入数组是
{1,-3,2,1,4,3}
在此点之后,数组变为
-1,-2147483647,-2,-1,4,3

#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>

using namespace std;

int firstMissingPositive(vector<int> &A) {

        int valMin = INT32_MAX, valMax = 0;

        for (auto &num:A) {

            if (num > 0) {
                valMin = min(valMin, num);
                valMax = max(valMax, num);

            } else {

                num = INT32_MAX;

            }
        }

        for (auto &num:A)
            cout << num << ",";

        cout << "\n";

        if (valMin != 1) return 1;
        for (int &num:A) {
            if (num != 0 and abs(num) != INT32_MAX) {
                int &val = A[abs(num) - valMin];
                if (val > 0) val = -val;
            }
        }
        for (auto &num:A)
                    cout << num << ",";

        //scan the range the input where we just did count on between valMin and valMax,
        //if we can any slot isn’t taken (as in is positive) then we know that’s the slot where the missing number is.

        for (int i = valMin; i < valMax; ++i) {
            if (A[i - valMin] > 0) return i;
        }
        return valMax + 1;
    }

int main()
{
    std::vector<int> v = { 1, -3, 2, 1, 4, 3 };
    int answer = firstMissingPositive(v);
    cout << answer;
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int firstMissingPositive(向量&A){
int valMin=INT32_MAX,valMax=0;
用于(自动编号:A(&N){
如果(数值>0){
valMin=min(valMin,num);
valMax=max(valMax,num);
}否则{
num=INT32_MAX;
}
}
用于(自动编号:A(&N)

cout其思想是将数字
n
的存在信息编码为位置
a[n-valMin]
中数字的符号

-1,-2147483647,-2,-1,4,3
这里我们看到1,2,3,4是存在的,因为前4个数组元素有负号。所以,第一个缺少的正数是5。

这里

因为我们不能使用额外的空间。我可以将值标记为负数,以指示插槽已占用

解决方案是使用相同的输入数组来标记所使用的插槽

这些线路:

int&val=nums[abs(num)-valMin];
如果(val>0)val=-val;

abs(num),因为可能存在类似{0,-4,-5,6,1,2,3}的情况,所以在迭代之前将“2”标记为“-2”

这些线路是,

  • 在索引'num'-1处获取值,本质上,因为valMin将始终为1,否则它将返回函数

  • 然后检查该值是否为正值,这意味着该索引以前从未被逻辑检查过,否则它将为负值。因此,如果该值为正值,则make为负值,以标记数组中存在与该索引对应的

  • 因此,例如,在输入数组中,迭代将如下所示:

    0.0,最大,1,1,1,2,3,3}<
    {{0,最大,0 0,-0-4-4,-4,-5,5,5,6,6,6,6,6,6,6,1,1,1,1,1,1,2,2,2,2,3}{{0,0,0,0,0,0,0,最大,1,1,1,1,2,2,3 3}<<0<<<

    {{{{00,0,0,0,最大,0,最大,最大,0,最大,最大,最大,最大,最大,最大,最大,最大,最大,最大,最大,0,最大,最大,最大,最大,最大,最大,最大,最大,最大,最大,最大,最大,<6<强>6<强>6<<强>6<<强>>>>,0,0,0,0,0,0,6<3}=>{0,-MAX,-MAX,6,1,-2,3}

    然后,
    如果(A[i-valMin]>0)返回i;
    将检查第一个为正的条目,即
    i-valMin
    或者我应该说
    i-1
    。因此,本质上,第一个为正的
    索引+1
    就是答案


    这里,在示例输入数组中,
    {0,-MAX,-MAX,6,1,-2,3}
    ;第一个正索引是3,所以答案是3+1,即4,这也是一个完全的垃圾循环;因为如果你传递向量
    [1100,200,300]
    ,你会发现它崩溃了。(您会注意到,它试图编辑索引数组中的项,因此,通过使用这些较大的数字,它将尝试编辑超出边界的数据),它应该确保该值在向量大小的范围内,并且是!=0或+/-INT32_MAX@UKMonkey
    [1100200300]
    似乎工作正常?尝试将其替换为
    .at()
    而不是
    []
    ,您将看到异常被抛出。