41. 缺失的第一个正数

41. 缺失的第一个正数

题目:https://leetcode.cn/problems/first-missing-positive/

思路

这里要求 O(1) 的空间复杂度来解决这道图,说明不能自己创建状态数组来记录,这说明了要寻找自身的信息。这道题的额外信息是:利用数组的下标来记录信息。将 i 处的值与 nums[i] 处的值呼唤,说明了:nums[i] 这个值在 nums 是存在的

代码(哈希思想)、

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        // 1. 不符合条件的 (<=0) 都改为 n+1
        // 2. 如果数 num 存在,那么第num个位置数字为负,否则为正
        // 3. 数的位置大于0的数,这个数字不存在,就是答案,否则为 n+1
        int n = nums.size();
        for (auto& num : nums) {
            if (num <= 0) {
                num = n + 1;
            }
        }

        for (int i = 0; i < n; i++) {
            int x = abs(nums[i]);
            if (x <= n) {
                nums[x - 1] = -abs(nums[x - 1]);
            }
        }
        
        for (int i = 1; i <= n; i++) {
            if (nums[i - 1] >= 0) return i;
        }

        return n + 1;
    }
};

代码(交换座位的思想)

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();

        int idx = 0;
        while (idx < n) {
            if (nums[idx] > 0 && nums[idx] <= n) {
                if (nums[idx] == idx + 1) { // 已经在正确的位置上
                    idx++;
                } else {
                    if (nums[nums[idx] - 1] != nums[idx]) { // 只有在不相等时才交换
                        std::swap(nums[idx], nums[nums[idx] - 1]);
                    } else {
                        idx++;
                    }
                }
            } else {
                idx++;
            }
        }

        for (int i = 0; i < n; i++) {
            if (nums[i] != i + 1) { return i + 1; } // 找到第一个不等于 i + 1 的位置
        }

        return n + 1;
    }
};

可以对上面的代码进行一些化简(虽然并没有什么用,而且可读性更差了)

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();

        int idx = 0;
        while (idx < n) {
            if ((nums[idx] > 0 && nums[idx] <= n) && nums[idx] != nums[nums[idx] - 1]) {
                std::swap(nums[idx], nums[nums[idx] - 1]);
            } else {
                idx++;
            }
        }

        for (int i = 0; i < n; i++) {
            if (nums[i] != i + 1) { return i + 1; } // 找到第一个不等于 i + 1 的位置
        }

        return n + 1;
    }
};