我们得到了一个由不同非负整数组成的排序数组,在这里我们必须找到最小的缺失数。因此,在本教程中,我们将探索解决此问题的不同方法,并通过各种示例讨论其时间复杂度。
问题描述很简单。给定一个不同非负整数的排序数组,我们需要找到其中最小的缺失数。让我们举个例子来理解这个问题。
假设我们有一个数组 [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>