c ++在未排序的数组中找到第一个缺失的正值

时间:2018-04-18 12:26:33

标签: c++ algorithm

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

  

1,找到输入的最小值和最大值,并用a标记负值   特别正面的价值。       2.确保min以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;
}

2 个答案:

答案 0 :(得分:1)

在这里,

  

因为我们不能使用额外的空间。我 *可以将值标记为否定以表示已采用该广告位。

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

这些行:

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

abs(num),因为可能有{0,-4,-5,6,1,2,3}这样的情况,所以'2'会被标记为'-2 '在迭代之前。

这些行是,

  1. 获取索引'num' - 1的值,基本上,因为valMin将始终为1,否则它将返回该函数。

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

  3. 因此,例如,在输入数组中,迭代将如下:

      

    {0,-4,-5,6,1,2,3} =&gt; {0,MAX,MAX,6,1,2,3}} {0,MAX,MAX, 6 ,1,2,3} =&gt; {0,MAX,MAX,6,1,-2,3}} {0,MAX,MAX,6, 1 ,2,3} =&gt; {0,MAX,MAX,6,1,-2,3}} {0,MAX,MAX,6,1, 2 ,3} =&gt; {0,-MAX,MAX,6,1,-2,3}
    {0,MAX,MAX,6,1,2, 3 } =&gt; {0,-MAX,-MAX,6,1,-2,3}

    然后,if (A[i - valMin] > 0) return i;会检查第一个条目是肯定的,即i-valMin还是我应该说i-1。所以,基本上,第一个正面index + 1就是答案。

    这里,在示例输入数组中,{0,-MAX,-MAX,6,1,-2,3};第一个正指数是3,所以答案是3 + 1,即4

答案 1 :(得分:0)

我们的想法是将有关号码n的存在的信息编码为位置A[n-valMin]中数字的符号。

-1,-2147483647,-2,-1,4,3

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