题目
Given an unsorted integer array, find the smallest missing positive integer.
Example 1:
Input: [1,2,0]
Output: 3
Example 2:
Input: [3,4,-1,1]
Output: 2
Example 3:
Input: [7,8,9,11,12]
Output: 1
Note:
Your algorithm should run in O(n) time and uses constant extra space.
解法1
假如我们忽略要求中的常量级别的额外空间,我们可以考虑使用位图解决。
位图是使用位来代表某种状态,只能是两种。比如男女性别,使用1代表男性,使用0代表女性,java中,一个int值是32位,也就是可以代表32个用户的性别。
如果统计一千万个用户的性别,使用位图能大大减少内存的占用。
这里我们使用Java自带的BitSet来实现。
初始化一个bitSet
[0,0,0,0,0,0,0,0,0,0]
输入是1 ,就将第0位置为1,表示存在整数1
[1,0,0,0,0,0,0,0,0,0]
输入3,将第2位置为1,表示存在整数3
这样完成一次遍历。
然后在遍历bitSet,查找第一个是0的位置,返回对应的正整数。
public int firstMissingPositive(int[] nums) {
BitSet set = new BitSet(2);
if (nums == null || nums.length < 1) {
return 1;
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
set.set(nums[i]-1,true);
}
}
for(int i = 0; i < set.length(); i++) {
if (!set.get(i)) {
return i+1;
}
}
return set.length()+1;
}
解法二
参考leetcode讨论区得票最高的做法。
首先我们还是参考位图的方法,比如将输入1,2,4,5,放到一个数组里[1,2,-,4,5],这样我们很明显的看到缺少了3
假如可以新建一个数组变量来存储,那么就很简单了,但因为题中要求是常量级别的额外空间,所以我们需要考虑使用原来的数组,进行原地操作。
先来确认一个前提,比如给的是[-1,2,3,6],长度是4,那么我们只要在这个数组中将1-4的值调整好即可,其他在1-4范围之外的值不用考虑位置,因为最后判断标准是第一个位置和其值不匹配的即是第一个缺失的正整数,可以说是“德不配位”。
下面看代码。
public int firstMissingPositive2(int[] nums) {
if (nums == null || nums.length < 1) {
return 1;
}
for (int i = 0; i < nums.length; i++) {
// 只关注在1-nums.length之间的数字,将这些数字放到对应的位置上。
while(nums[i] > 0 && nums[i] <= nums.length && nums[nums[i] - 1] != nums[i]){
swap(nums,i, nums[i] - 1);
}
}
//经历过上面的操作,所有1-nums.length的数字都放到了对应的位置,即value-1的位置。
for (int i = 0; i < nums.length; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
//注意 如果最后没有 说明给的是1-nums.length,那么需要返回下一个正整数。
return nums.length + 1;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
网友评论