41. First Missing Positive
题目:
Given an unsorted integer array, find the first missing positive integer.
For example,
Given [1,2,0] return 3,
and [3,4,-1,1] return 2.
Your algorithm should run in O(n) time and uses constant space.
链接: http://leetcode.com/problems/first-missing-positive/
题解:
找到第一个missing positive,要求O(n)。首先就想到了像sort colors一样的swap方法。把invalid case都swap到array的后部,两次pass就可以找到first mission positive。
Time Complexity - O(n), Space Complexity - O(1)
public class Solution {
public int firstMissingPositive(int[] nums) {
if(nums == null || nums.length == 0)
return 1;
int lo = 0, hi = nums.length - 1;
while(lo <= hi) {
if(nums[lo] <= 0 || nums[lo] > hi) //invalid case
swap(nums, lo, hi--);
else if (nums[lo] == lo + 1)
lo++;
else if(nums[lo] < lo + 1) // duplicates in lower index
swap(nums, lo, hi--);
else {
if(nums[lo] == nums[nums[lo] - 1]) // duplicates in high index
swap(nums, lo, hi--);
else
swap(nums, lo, nums[lo] - 1); // swap to correct position
}
}
for(int i = 0; i < nums.length; i++)
if(nums[i] != i + 1)
return i + 1;
return nums.length + 1;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
更简洁的写法是
public class Solution {
public int firstMissingPositive(int[] nums) {
if(nums == null || nums.length == 0)
return 1;
for(int i = 0; i < nums.length; i++) {
if(nums[i] > 0 && nums[i] < nums.length && nums[i] != nums[nums[i] - 1]) {
swap(nums, i, nums[i] - 1);
i--; // recheck newly swaped value at position i
}
}
for(int i = 0; i < nums.length; i++)
if(nums[i] != i + 1)
return i + 1;
return nums.length + 1;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
二刷:
二刷依然写得比较复杂, reference里面有很多很简洁的写法,要加以学习。思路是利用排除法和双指针夹逼,使用类似于sort colors里面的swap()来在O(n)的时间和O(1)的space遍历数组,我们有一下几种case:
- 当 nums == null || nums.length == 0的时候,我们返回最小正整数 1
- 设定lo = 0, hi = nums.length - 1
- 当nums[lo] <= 0或者nums[lo] > hi的时候,这两种情况为invalid,我们肯定能在数组中找到更合适的元素,我们swap(nums, lo, hi),然后hi--
- 接下来,当nums[lo] = lo + 1的时候,这时候是valid condition,我们增加lo = lo + 1
- 假如nums[lo] < lo +1,经历过上面的条件以后,我们可以肯定nums[lo] - 1 >= 0并且nums[lo] - 1 < lo,说明我们之前已经处理过nums[lo] - 1这个index,并且找到了一个合理的值。那么现在我们可以判断出这里的nums[lo]是一个duplicate,我们执行 swap(nums, lo, hi--)把它移动到数组末尾去。这个条件说明在lo这个index出现了duplicate。
- 现在剩下的情况是我们的nums[lo] > lo + 1,并且nums[lo] < hi。这时候算是我们的一般情况,我们要把这个nums[lo]交换到他应该处于的为止,并且这个位置的index > lo而且index < hi。 因为在理想的情况下,我们的index与值的对应关系应该是i = nums[i] - 1,所以我们要尝试把nums[lo]换到nums[lo] - 1这个位置。但在这个时候我们需要进行一个判断, 就是假如 lo = 2, nums[lo] = 5, 假设nums[nums[lo] - 1] = nums[4]也等于5怎么办? 假如我们交换的话,那程序就会陷入死循环。这个时候我们判断出这里当前的nums[lo]其实也是一个duplicate,是higher index ”nums[lo] - 1"这个位置的duplicate。所以我们依然执行swap(nums, lo, hi--),把这个数字交换到当前的尾部去。
- 最后的情况就是nums[lo] != nums[nums[lo] - 1], 我们可以放心大胆地执行swap(nums, lo, nums[lo] - 1),让循环去判断接下来的情况。
- 最后我们需要从头算一遍i从0到nums.length - 1, nums[i]是否等于 i + 1,假如不等,即可返回i+1,否则我们要返回nums.length + 1。
可以简化的地方有很多很多很多。希望三刷的时候能理清逻辑,大大简化。
Java:
Time Complexity - O(n), Space Complexity - O(1)
public class Solution {
public int firstMissingPositive(int[] nums) {
if (nums == null || nums.length == 0) {
return 1;
}
int lo = 0, hi = nums.length - 1;
while (lo <= hi) {
if(nums[lo] <= 0 || nums[lo] > hi) {
swap(nums, lo, hi--);
} else if (nums[lo] == lo + 1) {
lo++;
} else if (nums[lo] < lo + 1) {
swap(nums, lo, hi--);
} else if (nums[lo] == nums[nums[lo] - 1]) {
swap(nums, lo, hi--);
} else {
swap(nums, lo, nums[lo] - 1);
}
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
return nums.length + 1;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
把很多条件都放在了一起,少了几行。 还可以设置一个index变量来避免第二次循环的查找,留给三刷了。
public class Solution {
public int firstMissingPositive(int[] nums) {
if (nums == null || nums.length == 0) {
return 1;
}
int lo = 0, hi = nums.length - 1;
while (lo <= hi) {
if (nums[lo] == lo + 1) {
lo++;
} else if(nums[lo] <= 0 || nums[lo] > hi || nums[lo] < lo + 1 || nums[lo] == nums[nums[lo] - 1]) {
swap(nums, lo, hi--);
} else {
swap(nums, lo, nums[lo] - 1);
}
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
return nums.length + 1;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
题外话:
1/23/2016,现在我家已经彻底被大雪封住了。有生以来从来没见过这么大的雪,还在继续下着。我家的门在一个走廊里,整个走廊现在都是30厘米左右高的雪。出去走廊走到外面的话,雪都累积到了大腿根部。幸好之前屯了不少粮食,现在还可以在家里吃鸳鸯火锅(小肥羊辣汤/海底捞酸菜鱼汤)。 据说有20万户断电,希望大家都平安吧。
三刷:
用得二刷逻辑。
Java:
public class Solution {
public int firstMissingPositive(int[] nums) {
if (nums == null || nums.length == 0) return 1;
int lo = 0, hi = nums.length - 1;
while (lo <= hi) {
if (nums[lo] > hi || nums[lo] <= 0) swap(nums, lo, hi--);
else if (nums[lo] == lo + 1) lo++;
else if (nums[lo] < lo + 1) swap(nums, lo, hi--);
else if (nums[lo] == nums[nums[lo] - 1]) swap(nums, lo, hi--);
else swap(nums, lo, nums[lo] - 1);
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] != i + 1) return i + 1;
}
return nums.length + 1;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
class Solution {
public int firstMissingPositive(int[] nums) {
if (nums == null || nums.length == 0) return 1;
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0 && nums[i] < nums.length && nums[i] != nums[nums[i] - 1]) {
swap(nums, i, nums[i] - 1); // swap nums[i] out until nums[i] = i + 1 or nums[i] is invalid
i--;
}
}
for (int i = 0; i < nums.length; i++) if (nums[i] != i + 1) return i + 1;
return nums.length + 1;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
Reference:
https://leetcode.com/discuss/20385/concise-o-n-solution
https://leetcode.com/discuss/32761/clear-java-solution
https://leetcode.com/discuss/60525/100%25-fast-elegant-java-index-based-solution-with-explanation
https://leetcode.com/discuss/28531/o-1-space-java-solution
https://leetcode.com/discuss/24013/my-short-c-solution-o-1-space-and-o-n-time
41. First Missing Positive的更多相关文章
- LeetCode - 41. First Missing Positive
41. First Missing Positive Problem's Link ---------------------------------------------------------- ...
- [Leetcode][Python]41: First Missing Positive
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 41: First Missing Positivehttps://oj.le ...
- [array] leetcode - 41. First Missing Positive - Hard
leetcode - 41. First Missing Positive - Hard descrition Given an unsorted integer array, find the fi ...
- LeetCode题解41.First Missing Positive
41. First Missing Positive Given an unsorted integer array, find the first missing positive integer. ...
- 刷题41. First Missing Positive
一.题目说明 题目是41. First Missing Positive,求一个未排序队列中缺失的最小正整数.时间复杂度要求是O(n).难度是Hard,确实难. 二.我的解答 不考虑时间复杂度,首先对 ...
- [LeetCode] 41. First Missing Positive 首个缺失的正数
Given an unsorted integer array, find the smallest missing positive integer. Example 1: Input: [1,2, ...
- leetcode 41 First Missing Positive ---java
Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] ...
- Java [Leetcode 41]First Missing Positive
题目描述: Given an unsorted integer array, find the first missing positive integer. For example,Given [1 ...
- leetcode problem 41 -- First Missing Positive
Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] ...
随机推荐
- Mvc中把list从View传入Controller
public class User { public string Name { get; set; } public bool IsChecked { get;set;} public int Ag ...
- dotNet中初始化器的使用
dotNet中初始化器的使用 2013年12月7日 13:27 有两类初始化器: 对象初始化器和集合初始化器 比如现在有一个User类: Public class User { public in ...
- Python原始套接字编程
在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_R ...
- 从Keil 4升级到Keil 5的工程,想返回来用Keil 4打开
情景描述: 笔者电脑程序Keil 4升级到Keil 5,相应地,原来项目上的工程也在第一次用Keil 5打开的时候进行了升级.之后,由于客户需要开发资料,其版本为Keil 4,我尝试着用Keil 4打 ...
- SQL日语词汇
データベース 数据库 DATABASE インスタンス (数据库)实例 INSTANCE ユーザー 用戶 USER ログイン・ログアウト ログオン・ログオフ 登录 LOGIN/LOGOUT LOGNO/ ...
- Java异常的深入研究与分析
前言 本文是异常内容的集大成者,力求全面,深入的异常知识研究与分析.本文由金丝燕网独家撰写,参考众多网上资源,经过内容辨别取舍,文字格式校验等步骤编辑而成,以飨读者.对于本文的内容,建议小白需要多多思 ...
- 屏蔽ios7中某个页面的默认手势滑回返回
- (void)viewWillDisappear:(BOOL)animated {[super viewWillDisappear:YES];self.navigationController.in ...
- Windows 10 响应式设计和设备友好的开发
使用Effective pixels有效像素设计UI 什么是缩放像素和Effective有效像素: 当你的应用程序运行在Windows的设备,系统用一个算法控制的规范,字体,和其他UI元素显示在屏幕上 ...
- android 中使用回调方法(适用于自定义view传值到activity、adapter传值到activity)
如图所示: 每当listview中有选中的操作时都需要发消息给activity,用来实时改变真实需要支付的剩余金额. 代码暂不公开啦!公司项目!
- android开发 java与c# 兼容AES加密
由于android客户端采用的是AES加密,服务器用的是asp.net(c#),所以就造成了不一致的加密与解密问题,下面就贴出代码,已经试验过. using System; using System. ...