我們得到了一個由不同非負整數組成的排序數組,在這裡我們必須找到最小的缺失數。因此,在本教程中,我們將探索解決此問題的不同方法,並透過各種範例討論其時間複雜度。
問題描述很簡單。給定一個不同非負整數的排序數組,我們需要找出其中最小的缺失數。讓我們舉個例子來理解這個問題。
假設我們有一個陣列 [1, 2, 4, 5, 6]。在這裡,我們可以看到這個陣列中的數字 2 和 4 之間有一個空格。這種差異表明有一個數字丟失了。現在我們必須找到適合該位置的最小數字。
要判斷是否缺少數字,我們首先要查看數組中是否包含數字3。如果數組中不存在數字 3,我們可以說它是缺失數字,因為數字 3 不包含在數組中。
現在讓我們來看看解決這個問題的一些方法。
解決此問題的最簡單方法之一是循環數組並確保每個項目都位於正確的位置。如果元素不在正確的位置,我們會發現最小的缺失數。
這是上述解釋的程式碼 -
<!DOCTYPE html> <html> <body> <h2>Find Smallest Missing Number</h2> <p>Array: [0, 1, 2, 3, 5, 6]</p> <p>Result: <span id="result"></span></p> <script> function findSmallestMissingNumber(arr) { let n = arr.length; for (let i = 0; i < n; i++) { if (arr[i] !== i) { return i; } } return n; } const arr = [0, 1, 2, 3, 5, 6]; const result = findSmallestMissingNumber(arr); document.getElementById("result").innerHTML = result; </script> </body> </html>
由於我們要遍歷整個數組,因此該方法的時間複雜度為 O(n)。
但是,這個解決方案效率低下,因為它沒有利用「向我們提供了一個已排序的陣列」這一事實。
在這裡,我們將使用二分搜尋方法來更有效地解決這個問題。在這種方法中,我們會對數組中不存在的第一個元素進行二分搜尋。這種方法的程式碼是 -
<!DOCTYPE html> <html> <body> <div id="result"></div> <script> function findSmallestMissingNumber(arr) { let n = arr.length; let low = 0; let high = n - 1; let mid = 0; while (high - low > 1) { mid = Math.floor((low + high) / 2); if (arr[mid] - mid !== arr[low] - low) { high = mid; } else if (arr[mid] - mid !== arr[high] - high) { low = mid; } } return arr[low] + 1; } const arr = [0, 1, 2, 3, 4, 5, 6, 8]; const result = findSmallestMissingNumber(arr); document.getElementById("result").innerHTML = "Array: " + JSON.stringify(arr) ; document.getElementById("result").innerHTML += "<br>The smallest missing number is: " + result; </script> </body> </html>
由於我們正在進行二分搜索,因此上述方法的時間複雜度為 O(log n)。
這種方法比我們簡單的方法更有效,因為它利用了陣列已排序的事實。
我們將討論的第三種方法是線性搜尋方法。此方法依賴於數組已排序的事實,這將允許我們應用線性搜尋來識別遺失的數字。
線性搜尋方法的工作原理是迭代數組並將每個成員與其索引進行比較。如果某個元素的索引不等於其值,則缺少的元素位於數組中位於該元素之前的其他位置。我們傳回缺失元素的索引。
線性搜尋方法的程式碼如下 -
<!DOCTYPE html> <html> <body> <h2>Find Smallest Missing Number</h2> <p>Array: [1, 2, 3, 5]</p> <p>Result: <span id="result"></span></p> <script> function findSmallestMissingNumber(arr) { for (let i = 0; i < arr.length; i++) { if (arr[i] !== i+1) { return i+1; } } return arr.length+1; } const arr = [1, 2, 3, 5]; const result = findSmallestMissingNumber(arr); document.getElementById("result").innerHTML = result; </script> </body> </html>
這種方法的時間複雜度是 O(n),因為我們要迭代整個陣列。
這種方法的效率低於二分搜尋方法,但對於小型陣列很有用。
我們將討論的第四種方法是改進的二分搜尋方法。此方法與二分查找方法非常相似,只不過我們不是將中間元素與缺少的整數進行比較,而是將其與其索引進行比較。
修改後的二分搜尋方法背後的基本想法是在每一步將陣列分成兩半,並將中間元素與其索引進行比較。如果中間元素大於其索引,則缺失的成員必須位於陣列的左半部。如果中間元素等於或小於其索引,則缺少的元素一定位於陣列的右半部。
這是修改後的二分查找方法的程式碼實作 -
<!DOCTYPE html> <html> <body> <h2>Find Smallest Missing Number</h2> <p>Predefined array:</p> <pre id="inputArray"><script> // Define the input array const inputArray = [0, 1, 2, 3, 4, 6, 7, 8]; // Display the input array in the pre tag document.getElementById("inputArray").innerHTML = JSON.stringify(inputArray); function findMissingNumber() { // Call the findSmallestMissingNumber function to get the result const result = findSmallestMissingNumber(inputArray); // Display the result using the innerHTML method document.getElementById("result").innerHTML = `The smallest missing number is: ${result}`; } // Copy the findSmallestMissingNumber function here function findSmallestMissingNumber(arr) { let left = 0; let right = arr.length - 1; while (left <= right) { let mid = Math.floor((left + right) / 2); if (arr[mid] > mid) { right = mid - 1; } else { left = mid + 1; } } return left; } </script>