數組中未出現的最小正整數


題目:

給定一個無序整型數組arr,找到數組中未出現的最小正整數。要求時間復雜度為O(N)空間復雜度為O(1)。

例如:

arr=[-1,2,3,4]。返回1。

arr=[1,2,3,4]。返回5。

分析:

這道題要理解最小正整數的意思,最小的正整數就是1,所以考察的方法就是在數組中找1,然后找2,依次找下去...。直到第一個沒有找到的數,這個數就是未出現的最小的正整數。但是這樣的時間復雜度很大,達到了O(n2)。

空間復雜度算法

再來看一個時間復雜度為O(N)的算法,新開辟一個數組,元素初始化為0。把原來的數組中的數字放到新的數組中,放置的位置要合適,也就是要在1234...這樣合適的位置。如果這個數小於1或者大於數組的長度,就把這個數忽略掉,不放到新的數組中。完成之后,從頭到尾遍歷新的數組,找到第一個值不等於下標+1的數,下標+1就是那個未出現的最小正整數。

舉個列子:原數組

新數組

然后從新數組的開始掃面整個數組,發現下標0的元素值不等於下標+1,所以下標+1也就是0+1就是未出現的最小的正整數。

原數組

新數組

可以看出第一個下標+1不等於對應的值的就是下標2,所以未出現的最小整數就是3。

這里注意,原數組中的第一個2放置到了合適的位置后,后面緊接着又來了一個2,直接把它扔掉就可以了。

縮減空間復雜度

上面的算法是把原數組copy到了一個新的數組,如果直接在原數組上修改位置呢?就減少了空間復雜度。但是這樣的弊端就是破壞了原來的數組。

方法:定義兩個變量

l表示已經[1~l]的正整數已經找到了合適的位置,l的初值為0;

上面的算法中,如果一個數字太大了,就會被扔掉。這里用r表示這個邊界,如果大於這個r的數就會被扔掉。r的初值為N表示[1-r]的元素都不會被扔掉, 大於r的就會被扔掉。但是這個r的值是變化的,如果[l+1~r]中有一個元素不合法,那么這個r就是減少1,因為最多已經不能放下[1~r]了,最多只能放下[1~r-1]了。

所以代碼實現:

int missMinNum(int arr[], int n)
{
	int l = 0;
	int r = n;

	while(l < r)
	{
		if(arr[l] == l + 1)//在理想的位置
		{
			l++;
		}
		else if(arr[l] > r || arr[l] <= l || arr[arr[l] - 1] == arr[l])//不合法的數據
		{
			arr[l] = arr[--r];
		}
		else//合法但是沒有在理想的位置上
		{
			swap(arr, l, arr[l] - 1);
		}

	}//while

	return l + 1;

}//missMinMun()

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM