[leetcode]First Missing Positive

本文介绍了一种解决寻找未排序数组中首个缺失正整数问题的方法,提出了使用改进的插入排序算法,并讨论了其效率及实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

First Missing Positive

Difficulty:Hard

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.

题目就是要找出给的未排序数组中,第一个不存在其中的自然数,也就是第一个不存在的正整数。题目要求时间复杂度是O(n),空间复杂度是O(1).

一开始觉得数组中会有很多连续的数,所以就想对插入排序进行改进来计算,改进就是想在已经插入的数中,如果是连续的就只保存开头和结尾,比如(2,3,4,5就只用2->5来保存),整个插入排序用链表进行维护,这样每次插入要比较的数量就会少很多。

后来想想这个做法在数组中连续的数很少的情况下根本没什么优势,并不能保证复杂度都是 O(n)和空间复杂度是O(1),不过leetcode还是给通过了,而且比70%已通过的算法都快,不知道是不是直接用插入排序也会给通过。。。

最后看了网上的解答,通过在原数组的进行交换,把数放到该放的位置上,比如数字5就与数组第5个位置的数进行交换,进行两次循环就能找出答案,我这真的太麻烦了。。。

 int firstMissingPositive(vector<int>& nums) {
	 if (nums.size() == 0)//为空返回1
		 return 1;
	 list<pair<int, int>> record;//第一个int是插入的数 第二个数表示状态 0表示左右没有连续 1表示是连续数的开头 2表示连续数的结尾
	 int i = 0;
	 for (; i < nums.size(); i++){//找到第一个大于0的数的位置并把数插入到record中
		 if (nums[i] > 0){
			 record.push_back(pair<int, int>(nums[i], false));
			 break;
		 }
	 }
	 for (i=i + 1; i < nums.size(); i++){//循环生成record

		 list<pair<int, int>>::iterator it = record.begin();
		 list<pair<int, int>>::iterator it_last;
		 int k = 0;
		 if (nums[i]>0)
		 while (1){
			 if (it != record.end()){//寻找插入点 头/中间插入
				 if (nums[i] > it->first){//未寻找到插入点
					 it_last = it;
					 it++;
					 k++;
				 }
				 else{//寻找到插入点
					 
					 if (k>0){//中间插入
					
						 if (it->first == nums[i] || (it_last->second == 1 && it->second == 2))
							 break;

						 if ((nums[i] - it_last->first) == 1 && (it->first - nums[i]) == 1){//左右都与插入值相连
							 if (it_last->second >0 && it->second > 0){//当前是连续输结尾 后是连续输开头时才应该插入
								 if (it_last->second > it->second){
									 record.erase(it_last);
									 record.erase(it);
								 }
								 break;
							 }
							 else if (it_last->second >0){
								 it->second = 2;
								 record.erase(it_last);
								 break;
							 }
							 else if (it->second > 0){
								 it_last->second = 1;
								 record.erase(it);
								 break;
							 }
							 else{
								 it_last->second = 1;
								 it->second = 2;
								 break;
							 }
						 }
						 else if ((nums[i] - it_last->first) == 1){ //与左边相连
							 if (it_last->second >0){
								 record.insert(it, pair<int, int>(nums[i], 2));
								 record.erase(it_last);
								 break;
							 }
							 else{
								 record.insert(it, pair<int, int>(nums[i], 2));
								 it_last->second = 1;
								 break;
							 }

						 }
						 else if ((it->first - nums[i]) == 1){//与右边相连
							 if (it->second > 0){
								 record.insert(it, pair<int, int>(nums[i], 1));
								 record.erase(it);
								 break;
							 }
							 else{
								 it->second = 2;
								 record.insert(it, pair<int, int>(nums[i], 1));
								 break;
							 }
						 }
						 else{//左右都不相连
							 record.insert(it, pair<int, int>(nums[i], 0));
							 break;
						 }

					 }
					 else{//头部插入
						 if (it->first == nums[i])
							 break;

						 if ((it->first - nums[i]) == 1){
							 if (it->second == 0){
								 it->second = 2;
								 record.push_front(pair<int, int>(nums[i], 1));
								 break;
							 }
							 else{
								 record.push_front(pair<int, int>(nums[i], 1));
								 record.erase(it);
								 break;
							 }
						 }
						 else{
							 record.push_front(pair<int, int>(nums[i], 0));
							 break;
						 }
					 }

				 }
			 }
			 else{//末尾插入
		
				 if ((nums[i] - it_last->first) == 1){
					 if (it_last->second == 0){
						 it_last->second = 1;
						 record.push_back(pair<int, int>(nums[i], 2));
						 break;
					 }
					 else{
						 record.push_back(pair<int, int>(nums[i], 2));
						 record.erase(it_last);
						 break;
					 }
				 }
				 else{
					 record.push_back(pair<int, int>(nums[i], 0));
					 break;
				 }

			 }

		 }

	 }

	 list<pair<int, int>>::iterator it = record.begin();
	 list<pair<int, int>>::iterator it_tmp = it;
	 bool isEnd = false;
	 for (int j = 1; j <= nums.size()+1; j++){//查找第一个丢失的正整数
		 if (j != it->first){
			 if (j < it->first){
				 return j;
			 }
			 else{
				 if (it->second ==1){
						 it_tmp = it;
						 it_tmp++;
						 if (it_tmp != record.end()){
							 if (it_tmp->first <= j){
								 it++;
								 j--;
							 }
						 }
						 else{
							 return j;
						 }

				 }
				 else if (it->second == 2){
					 return j;
				 }
				 else{
					 return j;
				 }
			 }
		 }
	 }
	 return 1;

 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值