【趣味算法题】找到缺失的最小正整数

【题目描述】

有一个随机序列的数组,找到其中缺失的最小正整数

举例如下,在[1,  2,  0] 中,该最小正整数应为3

在[3,  4,  -1,  1]中,该最小正整数应该为2

 

【解题思路】

如果允许开辟任意大小的空间,易得用桶的思想可以解决这题

简单的说,开辟一个数组,从1扫过来如果不存在那么break输出即可

 

如果对空间的要求是O(1) ,利用桶排序接下来有一个非常漂亮的解决方法:

 

我们可以把每个数字放在其该放的地方。什么意思呢?

比如 A[0] = 1, A[1] = 2, A[2] = 3, 诸如此类

然后放好之后从1扫过来如果不存在那么break输出即可

 

关键就是在于,如何将每个数字放在其该放的地方呢

方法如下:

 

如果 A[i] 是合法的数 (合法的意思是 A[i] > 0 && A[i] < n)

那么A[i] 应该放的位置为 A[A[i] - 1] 才对。

如果当然的 A[i] 不在 A[A[i] - 1] 的话,那么swap (A[i], A[A[i] - 1]) 即可

 

这到题目就是利用这个思路解决,如果碰到重复出现的数字也是可以解决 :)

 

【算法效率分析】

O(1) space, and O(n) time

 

 

My Source Code:

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

using namespace std;

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        bucket_sort (nums);

        for (int i = 0; i < nums.size (); ++i) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }

        return nums.size () + 1;
    }

    void bucket_sort (vector <int> & nums) {
        for (int i = 0; i < nums.size (); ++i) {
            while (nums[i] != i + 1) {
                if (nums[i] < 0 || nums[i] > nums.size () || \
                    nums[i] == nums[nums[i] - 1]) {
                        break;
                    }
                cout << "i = " << i << "\t" << nums[i] << "\t" << nums[nums[i] - 1] << endl;
                swap (nums[i], nums[nums[i] - 1]);
                cout << "\t";
                for (int j = 0; j < nums.size (); ++j) {
                    cout << nums[j] << " ";
                }
                cout << endl << endl;
            }
        }
    }
};

int main () {

    Solution sl;
    vector <int> vc;
    vc.push_back (3);
    vc.push_back (-4);
    vc.push_back (2);
    vc.push_back (1);
    vc.push_back (5);

    cout << sl.firstMissingPositive (vc);

    return 0;
}

 

推荐阅读文章:

三种线性排序算法 计数排序、桶排序与基数排序

https://www.byvoid.com/blog/sort-radix/

转载于:https://www.cnblogs.com/wushuaiyi/p/4558557.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值