給定一個數組,找出陣列缺少的最小的正整數
題目使這樣的:請設計一個高效演算法,查詢陣列中未出現的最小正整數。
給定一個整數陣列A,請返回陣列中未出現的最小正整數。
測試樣例:
[-1,2,3,4]
返回1
一看到這個題目我想到的是用另外的一個數組B,長度為A的長度+1,來儲存遍歷陣列A的數的值。 if(A[i] == i+1) B[i+1] = A[i]。然後遍歷陣列B,出現空缺的地方即是最小未出現的正整數。但是假如要求額外空間複雜度為O(1),那就沒辦法了。有的人會想到排序,但是排序最好需要O(nlog2n)的時間複雜度。如果要求時間複雜度為O(n),並且空間複雜度為O(1),那麼要怎麼做呢?這方法是我在牛客網上看到的。聽完之後,感覺特別不可思議,實在是太厲害了。在我的理解裡,這是一種正向和逆向結合的思想。從前往後和從後往前不停地進行,理想情況和實際情況實時地更新,最後的臨界點必然是兩者相等。
在這個演算法裡,有兩個額外變數。一個是match,初始值為0。用來標記從正整數1開始已經連續出現的正整數個數。比如說[3, 5, 2, 1, 6] 出現的連續正整數序列為{1 2 3 },所以match= 3;還有一個變數是maxMatch,初始值是整個陣列的長度,因為陣列在沒遍歷之前,無法得知其中的元素,所以看作是最理想的情況:裡面的數剛好是1到n。
說了兩個變數之後,便是演算法的部分了。
首先從第0位置開始,如果A[0]=match+1;那麼說明出現了下一個連續的正整數,所以match++;
如果A[0] != mach+1,那麼有幾種情況。
第一種情況是,A[0]<=match,那麼這個值是我們不需要的,因為match之前的正整數已經出現了。所以這時候剩下的數最多能使match的值達到maxMatch-1,因為這個無效的元素,需要佔用一個位置。同理如果A[0]>maxMatch,這個值也是不需要的,maxMatch-1;還有就是如果這個數在match和maxMatch的範圍之內,我們需要判斷這個數應該在的位置上,是否已經有了這個數。比如說A[0]=3,那麼我們只需要比較A[2]位置上是否是3,如果是那麼這個數也不是我們需要的,這是maxMatch-1;以上幾種情況都是遍歷的位置上的數是不需要的,那麼我們應該把後面的數調到這個位置上,進行重新搜尋。
還有一種情況就是 match+1<A[0]<=maxMatch,並且A[0]應該在的位置上的數不是A[0],那麼這個數就是我們可能需要的,所以把它放在它應該在的位置。比如說[3, 5, 2, 1, 6],3應該在的位置是2,A[2]上的數字是2,不等於3.所以3應該放在2的位置。這時我們應該交換兩個數的位置A[0] <=> A[2];
這樣一直搜尋下去,最終便是達到臨界點,然後結束搜尋。最終的結果便是match+1;
public static int firstMissingPosition(int[] nums) { if(null == nums){ throw new NullPointerException("輸入的陣列為空..."); }else if(0 == nums.length){ return 1; } int match = 0; int maxMatch = nums.length; while(match<maxMatch){ if(nums[match]==match+1){ match++; }else if(nums[match]<=match || nums[match]>maxMatch || nums[nums[match]-1] == nums[match]){ maxMatch--; nums[match] = nums[maxMatch]; }else { int temp = nums[match]; nums[match] = nums[temp-1]; nums[temp-1] = temp; } } return match+1; }
程式碼量很少,但是思路真的是很精妙。不得不為之讚歎!
相關推薦
給定一個數組,找出陣列缺少的最小的正整數
題目使這樣的:請設計一個高效演算法,查詢陣列中未出現的最小正整數。 給定一個整數陣列A,請返回陣列中未出現的最小正整數。 測試樣例: [-1,2,3,4] 返回1 一看到這個題目我想到的是用另外的一個數組B,長度為A的長度+1,來儲存遍歷陣列A的數的值。 if(A[i]
給定一個數組,找出這個和最大的連續子陣列的和
將這個連續子陣列分為兩部分,一個是字首,一個是後一個元素,要使這個連續子陣列最大,那麼它的字首肯定不能為負,不然這個字首對即將加上的值就無意義,用一個max記錄最大值,每次當前綴加上後一個元素的時候判斷和是否大於max,大於則更新max,再判斷和是否小於0,小於0則將字首更
給定一個數組,找出其中出現奇數次的元素
package com.yzcl.test; public class JiShu { public static void main(String[] args) { //給定一個含有n個元素的整型陣列a,例如{1,1,2,4,3,3,1},找出其中出現奇數次的元素,並列印,輸出:1,
給定一個數組,求出陣列元素的排列和組合——Java實現
1. 思路 組合數C(n,m)和全排列A(n,n)可以通過遞迴的方式,直接實現。 而A(n,m)則可以通過組合數和全排列間接求出A(n,m)=C(n,m)*A(m,m),即對得到的組合數中的每個元素進行全排列 2. Java實現 package com.zfy.test
給定一個數組,按序排列,從陣列找出若干個數,使得這若干個數字的和與M最為接近,(揹包問題)
思路:對於陣列中的每一個數,觀察它們取或不取對最後結果的影響。並且記錄下若干數字的和與M的差的絕對值最小時所取到的若干數字。 /* * 微軟100, 9月28題, 輸入和接近M * sum 即為M值 * num排序的陣列 * len陣列長度 * vec所取到若干數
給定一個數組,其中只有一個數出現一次,別的數都出現3次,找出這個數(go)
1.思路 用兩個數one=0、two=0分別記錄bits位上1出現的次數,如果一個數出現一次,則one等於這個數,two=0; 如果一個數出現兩次,則two等於這個數, one等於0;如果一個數出現第三次,則one = 0, two = 0 ,three等於這個數。 我們以陣
給定一個數組,其中只有一個數出現一次,別的數都出現3次,找出這個數
題目描述 給定一個數組,其中只有一個數x出現一次,別的數都出現3次,找出這個數x。(線性時間複雜度) 思路 這個用異或不可以。 可以設定一個長度為32的int陣列。統計每位上出現1的次數,如果次數能被3整除,說明x該位上為0,否則為1 java程式碼實
給定一個數組,陣列中有正有負,求出連續陣列中和值最大的數(陣列長度大於等於1)
刷牛牛客遇到的題,想給出完整而又簡潔的function(python解答,但是關鍵是思想,語言不是問題啦)1.給定一個數組,陣列中有正有負,求出連續(全部都是正的時候,所有值累加就是最大值)(全部為負的時候,max(array)就是我們想要的)# -*- coding:utf
給定一個數組,陣列中有正負數,求出所有字陣列中和值最大的值。
/**當我們加上一個正數時,和會增加;當我們加上一個負數時,和會減少。如果當前得到的和是個負數,那麼這個和在接下來的累加中應該拋棄並重新清零, 不然的話這個負數將會減少接下來的和 */ public static int maxSum(int[] a) { int
一個輸入的陣列中長度為101,陣列範圍[1,100],存在一個數重複,找出重複的數
/********************************************* *函式功能: 一個輸入的陣列中長度為101,陣列範圍[1,100],存在一個數重複,找出重複的數 *引數說明 * 輸入: [1,2,4,5,6,...,39,39,40,41,
有自己的程式碼--題目:給定一個數組,裡面全是正整數。數字大小表示這一步最多可以向後移動幾個節點。總是從陣列第一個元素開始移動。問如何移動,可以以最少步數移動到最後一個節點。
原文:https://yq.aliyun.com/articles/547799 描述: 題目:給定一個數組,裡面全是正整數。數字大小表示這一步最多可以向後移動幾個節點。總是從陣列第一個元素開始移動。問如何移動,可以以最少步數移動到最後一個節點。 例如:[3,4,2
給定一個數組,根據陣列名求陣列的長度
題目:給定一個數組名字,如何根據陣列名求陣列的長度? 本題來自於一個同學筆試題,筆試中是實現一個氣泡排序,但是排序的引數只有一個數組名,沒有陣列中元素的個數;void bubbleSort(int a
給定一個數組,返回最大子陣列的累加和並且返回該子陣列
給定一個數組Arr,返回子陣列的最大累加和 例如 arr[] = {1,-2,3,5,-2,6,-1};所有子陣列中,[3,5,-2,6] 可以累加出最大和12 函式在設計的時候,應該考慮傳入的陣列Arr,同時要有一個傳出陣列,返回值會最大累加和,為整數 以下是程式碼
面試題:給定一個數組,陣列中只包含0和1。請找到一個最長的子序列,其中0和1的數量是相同的
這個題目,看起來比較簡單,一些同學可能認為題目的描述符合動態規劃的特徵,然後就開始用動態規劃解,努力找狀態轉移方程。這些同學的感覺,是很正確的。但,找狀態轉移方程,我們要對原來的陣列進行變換一下。 原來是0和1的串,我們將0都換為-1。這樣題目目標就變成,找到一個最長的子串,子串數字和是0。設原陣列為A
題目三:給定一個數組,值可以為正、負和0,請返回累加和為給定值k的最長子陣列長度。
import java.util.HashMap; /** * * 2、給定一個數組,值可以為正、負和0,請返回累加和為給定值k的最長子陣列長度。 * 咱們可以反推,比如:1- 100,陣列和為1000. * 要求最長和為300的子陣列,我可以反著求第一
題目四:給定一個數組,值可以為正、負和0,請返回累加和小於等於k的最長子陣列長度。 時間複雜度:O(n)
import java.util.HashMap; /** * * 3、給定一個數組,值可以為正、負和0,請返回累加和小於等於k的最長子陣列長度。 時間複雜度:O(n) * * 這裡需要分為兩步,第一步是獲取,以每個位置開頭最小和的長度。第二步,從0到N逐
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。 如果你最多只允許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。
pan stat 給定 arr 註意 turn 大於 交易 nbsp 給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。 如果你最多只允許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。 註意你不能在買入股票前賣出股票。 示例 1
JS寫一個方法,傳入一個數組,返回該陣列的層深
現在我們有一個多維陣列,我們想得到該陣列的層深,即最大維度 如:var arr = [1, [4,[5,6,[7]]], [2,3]] = 0;返回4;那麼我們該怎麼做呢? 核心思想:遞迴,迴圈遍歷 // 這裡傳入兩個引數 // 引數一為陣列 // 引數二為初始陣列的層深 function fo(
隨機數生成一個數組,對該陣列檢索
生成一個含100個隨機數的陣列,對其進行檢索,這裡以二分檢索為例。 import java.util.Random; import java.util.Scanner; //引入隨機數的二分檢索 public class RandomErfen { public static voi
給定一個數組,請倒序輸出每一個數
題目描述: 給定一個數組, int[] abc = { 20, 90, 48, 92}; 請倒序輸出每一個數。 即,輸出 92 48 90 20 c #include<stdio.h> int main() { int a[4]={20,90,48