LeetCode刷题笔记 41. 缺失的第一个正数

题目要求

给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive

示例 1:

输入: [1,2,0]
输出: 3

示例 2:

输入: [3,4,-1,1]
输出: 2

示例 3:

输入: [7,8,9,11,12]
输出: 1

说明:

你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。

基础补习

桶排序

[图解] 桶排序

c++实现案例

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

using namespace std;

void bksort(float A[], int l, int h) {
    int size = h - l + 1;
    vector<vector<float> > b(size);//有size个数据,就分配size个桶
    for (int i = l; i <= h; i++) {
        int bi = size * A[i];//元素A[i]的桶编号
        b[bi].push_back(A[i]);//将元素A[i]压入桶中
    }
    for (int i = 0; i < size; i++)
        sort(b[i].begin(), b[i].end());//桶内排序
    int idx = l;//指向数组A的下标
    for (int i = 0; i < size; i++) {//遍历桶
        for (int j = 0; j < b[i].size(); j++) {//遍历桶内元素
            A[idx++] = b[i][j];
        }
    }
}

int main() {
    float A[] = { 0.78,0.17,0.39,0.26,0.72,0.94,0.21,0.12,0.23,0.68 };
    bksort(A, 2, 9);
    for (int i = 0; i < 10; i++)
        cout << A[i] << " ";

参考代码(有误)
【排序(C++实现)】:桶排序

题解

数组解法

https://github.com/soulmachine/leetcode

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Solution{
public:
    int firstMissingPositive(int A[],int n) {
        bucket_sort(A,n);
        for (int i = 0; i < n; ++i)
            if (A[i] != (i + 1))
                return i + 1;
        return n + 1;
	}
private:
    static void bucket_sort(int A[],int n) {
        for (int i = 0; i < n; i++) {
            while (A[i] != i + 1) {
                // 当前位置元素 == 当前元素值所对应位置上的值
                if (A[i] <= 0 || A[i] > n || A[i] == A[A[i] - 1])
                    break;
                swap(A[i],A[A[i] - 1]);
			}
		}
	}
};

主要思路

这里的主要思路是先利用桶排序把元素交换到对应序号的位置上,即占位(2换到A[1],4换到A[5],等等)。
数组中对应位置没有相应元素处为其他元素,所以经过排序后对数组从0开始查找对应位置上是否存在对应元素即可。

Vector改写版

习惯了vector。。。

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        // 先进行桶排序
        bk_sort(nums);
        // 找出最小的桶(此时并没有将各桶进行最后的合并)
        if(nums.size()==0) return 1;
        for(int i=0;i<nums.size();i++){
            if(nums[i]!=(i+1))
                return i+1;      
        }             
        return nums.size()+1;                
    }
private:
    static void bk_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;
                swap(nums[i],nums[nums[i]-1]);
            }
        }
    }
};

然后。。。竟然超出时间限制了!尴尬,再看别的题解吧。。。

https://leetcode-cn.com/problems/first-missing-positive/solution/cchao-guo-100kan-wei-wei-da-lao-ti-jie-hou-xie-de-/

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        vector<int>::size_type n=nums.size();
        if(n==0) return 1;
        for(size_t i=0;i<n;i++) {
            while(nums[i]>0&&nums[i]<=n&&nums[i]!=nums[nums[i]-1]&&i+1!=nums[i])
                swap(nums[i],nums[nums[i]-1]);
        }
        for(size_t i=0;i<n;i++) {
            if(i+1!=nums[i])
                return i+1;
        }
        return n+1;
    }
};

测试用时比较玄学就不列了。
另外可以把 i+1!=nums[i] 的条件去了,不影响通过,但加上该条件更佳(避免一定重复)。

看来是while里面又带个if判断增加了时间,将前文对应代码进行修改,通过。

其他

vector<int>::size_type  
::号前面是命名空间,后面是自定义的类型
要用到这个类型时,必须加上命名空间,防止和其他命名空间中的定义重复。
vector<int>::size_type ix=0   
定义一个vector<int>命名空间中类型为size_type的变量ix,并将其赋值为0
发布了18 篇原创文章 · 获赞 0 · 访问量 1817

猜你喜欢

转载自blog.csdn.net/g534441921/article/details/104095358