1. 程式人生 > 其它 >0~n-1中缺失的數字

0~n-1中缺失的數字

技術標籤:資料結構和演算法

一個長度為n-1的遞增排序陣列中的所有數字都是唯一的,並且每個數字都在範圍0~n-1之內。在範圍0~n-1內的n個數字中有且只有一個數字不在該陣列中,請找出這個數字。

輸入: [0,1,3]
輸出: 2

輸入: [0,1,2,3,4,5,6,7,9]
輸出: 8

特殊例子:

輸入: [0]
輸出: 1

輸入:[1]
輸出: 0


最直接的思路就是按照陣列遍歷, 找出下標和值不對應的數字, 如果沒有就是nums.count, 時間複雜度是O(N).

class Solution {
    func missingNumber(_ nums: [Int]) -> Int {

        for (i,num) in nums.enumerated() {
            if (i == num) {

            } else {
                return i
            }
        }
        return nums.count 
    }

}

優化下, 自然是用二分法了, 先找中間位置的數字,

  • 中間位置的數字 == 下表, 說明缺失的數字在後半部分, 並且不可能是此值, 所以用left = index+1
  • 中間位置的數字 != 下表, 說明缺失的數字在前半部分, 同時也有可能是本身,所以index不能減1

最後還有2個特殊的值, 頭部值和尾部值,

  • 頭部就判斷是否等於0, 等於0, 說明正常; 不等於0, 那缺失的就是此數字
  • 尾部判斷是否等於count-1, 如果相等, 那就是缺了最後一個數字; 如果不相等, 說明缺失的數字在0~count-1之間
class Solution {
    func missingNumber(_ nums: [Int]) -> Int {
        let count = nums.count
        // 特殊用例, 如果最後一個都符合條件, 那就是count不滿足
        if nums[count-1] == count-1 {
            return count
        }
        // 頭部不滿足條件,返回0
        if nums[0] != 0 {
            return 0
        }

        // 開始二分查詢
        var left = 0
        var right = count-1
        while left<right {

            // 找到中間位置的數字
            let index = (left+right)/2
            // 中間位置數字相等,說明在後半部分,
            if index == nums[index] {
                left = index+1
            } else {
                // 中間位置數字不相等,說明在前半部分,也有可能是本身,所以index不能減1
                right = index
            }


        }

        return left

    }
}