每天算法 -- first missing positive integer linear time const space -- hard

Stripe:

Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.

For example, the input [3, 4, -1, 1], should give 2. The input [1, 2, 0] should give 3.

You can modify the input array in-place.

题目分析:

这题的目的是非常清晰的,即在一串数字当中寻找从第一个缺失的正数。要求是线性的时间常量的空间复杂度。同时,数字序列中还会包含负数和0.

其实两个关于时间或者空间的硬性要求只要去掉其中一个,都是好处理的。如果不需要线性的时间,排序足够解决问题了,如果不需要常量级空间复杂度,那么也可以使用一个哈希表来存储已经出现的正数。

同时满足两者的条件,就必须要从最后一个提示入手,modify the input array in-place. 也就是说,我们是可以将数组进行一定程度的修改。

算法想要达到最高的效率,就必须要搞清楚输入数据的具体模式,并针对这种具体的模式做最合适的处理。

 

数学表达:

即存在一个序列,a_1,a_2, a_3, ... a_n , 其中有意义的序列是1,2,3,...,k-1, k+1, ... m, k\geq 1 and \leq m, m \leq n,其它的数都是无意义数。如果存在某种方法,可以使得输入数据变为该有意义序列,那么就可以容易得出k的值。由于序列的特征如上,我们可以通过数组的下标来建立这样的有序列。即数组的下标为0的空间存1,下标为1的存2,等等以此类推。

 

算法设计:

可以设计这样的算法:

遍历整个数组,若该元素的值,我们假定是e 处于1到n之间,那么将它和位于下标e-1位置的元素互换。同时,判断互换的元素值是否满足条件,若满足条件就必须要互换。然后继续判断下一个元素。

最终在数组的头部,就会出现一个有意义序列,通过对该序列的判断可以得出正确的值。

 

实现:

#include <iostream>
#include <set>
#include <vector>
#include <algorithm>

int findFirstMissingNumber(std::vector<int> &data)
{
    std::for_each(data.begin(), data.end(), [&](int &val) {
        if (val > 0 && val <= data.size())
        {
            std::swap(val, data[val - 1]);
            if (val > 0 && val <= data.size())
            {
                std::swap(val, data[val - 1]);
            }
        }
    });

    std::for_each(data.begin(), data.end(), [](int val) {
        std::cout << val << " ";
    });
    std::cout << std::endl;
    int index = 1;
    auto result = std::find_if(data.begin(), data.end(), [&index](int val) {
        if (val != index)
        {
            std::cout << "missing val " << index << std::endl;
            return true;
        }
        else
        {
            index++;
            return false;
        }
    });

    if (result == data.end())
    {
        std::cout << "no missing val " << data.size() + 1 << std::endl;
    }
}

int main()
{
    std::vector<std::vector<int>> datas = {
        {1, 4, 2, 0},
        {2, 3, 9, -1},
        {2, 3, 9, 1},
        {1, 2, 3, 4}
        };
    std::for_each(datas.begin(), datas.end(), [](auto &data) { findFirstMissingNumber(data); });
}
$ ./a.exe
1 2 0 4
missing val 3
9 2 3 -1
missing val 1
1 2 3 9
missing val 4
1 2 3 4
no missing val 5

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值