LeetCode 41. First Missing Positive
我失去了一只臂膀, 就睁开了一只眼睛。
—— 顾城
Problem
Given an unsorted integer array, find the smallest missing positive integer.
Example 1:
1 | Input: [1,2,0] |
Example 2:
1 | Input: [3,4,-1,1] |
Example 3:
1 | Input: [7,8,9,11,12] |
Note:
Your algorithm should run in O(n) time and uses constant extra space.
Solution
LeetCode 第一题
思路
打 ACM 被血虐,无聊来看看 LeetCode,顺手选了一个 Hard 的题目。题意很简单,不像 ACM 一样嘟噜嘟噜说很多。第一反应有些懵,要求 O (n) 的时间复杂度,和 O (1) 的空间。但很快灵光一闪想到 O (n) 时间复杂度的排序后,就有了思路。数列中 n 个数,最优情况下值分别为 1~n,这样我们可以分别把数列中的数字放到自己对应的下标中去 (我向 vector 中额外加了一个数,这样子就可以对应的下标放对应的数),遇到大于 n 或小于 0 的数就不进行操作。处理完之后开始扫一遍数组,(因为我加了一个数,所以从下标为 1 的位置开始扫到 n 就好了),第 1 个值和下标不对应的数就是答案。如果全都对应,那答案为 n+1。
一开始本来想用迭代完成对数组的处理 (想以最优的解法来处理,减少数字变动的次数),结果写崩了,思路不是太流畅。遂用了递归实现,结果发现用了 4ms,仅击败了 80% 左右的答案。又开始优化,虽然比一开始的想法差点,数字交换次数会多一些,但代码很简洁,代码量极少。而且仅用了 0ms,为最优答案。
AC 代码 Ver1
1 | class Solution |
AC 代码 Ver2
1 | class Solution |
Note
自己 LeetCode 第一题 1A,还是很开心的。一开始打 ACM 心情不太好,看这题过了突然高兴起来。
递归速度要比迭代慢一些,而且有一定的空间消耗。
小心用异或来交换值,比如这题自己写了
1 | nums[i] ^= nums[nums[i]]; |
结果却报了错,自己懵了许久。过了一会才恍然大悟,因为 nums[nums[i]]
中使用了 nums[i]
作下标, 而 nums[i]
的值在之前的异或中已经更换了值 = =。
好像 std::swap()
函数交换要快一些,自己用异或写的函数竟然会 4ms,而 swap()
实现的版本只要 0ms。