268. Missing Number

Swift 3.0


//
//  E_268_MissingNumber.swift
//  AlgorithmLeetCode
//
//  Created by okerivy on 2017/3/9.
//  Copyright ? 2017年 okerivy. All rights reserved.
//  https://leetcode.com/problems/missing-number

import Foundation




// MARK: - 題目名稱: 268. Missing Number

/* MARK: - 所屬類別:
 標(biāo)簽: Array, Math, Bit Manipulation
 
 相關(guān)題目:
  (H) First Missing Positive
  (E) Single Number
  (M) Find the Duplicate Number
 
 */

/* MARK: - 題目英文:
 
 Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.
 
 For example,
 Given nums = [0, 1, 3] return 2.
 
 Note:
 Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
 
 Credits:
 Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
 
 */


/* MARK: - 題目翻譯:
 
 給定一個(gè)數(shù)組,數(shù)組包含 n 個(gè)取自 0, 1, 2, ..., n 的不同的數(shù)字,從數(shù)組中找到丟失的那個(gè)數(shù)字。
 
 例如:給定 nums = [0, 1, 3] 返回 2.
 
 注意:
 你的算法應(yīng)當(dāng)使用線性的時(shí)間復(fù)雜度(即時(shí)間復(fù)雜度為O(n))。你能夠只使用常量的額外空間來解決這題嗎?
 
 */



/* MARK: - 解題思路:
 
 1.
 從 0, 1, 2, ..., n 中取 n 個(gè)不同的數(shù)字組成數(shù)組 nums,尋找丟失的那個(gè)數(shù)字,非常自然的想法就是將 0, 1, 2, ..., n 加和之后,減去數(shù)組 nums 的和就得到了丟失的那個(gè)數(shù)字。
 
 思路非常簡單。但是為了避免加和造成的溢出,
 這里有一個(gè)小技巧:即不需要將兩個(gè)數(shù)組先加起來之后再做減法,可以邊加邊減。
 例如 數(shù)組
 數(shù)字     0   1   3   4   5   6   7   8   // 缺失的是 2
 下標(biāo)     0   1   2   3   4   5   6   7   // 8個(gè)元素
 
 進(jìn)行相加相減運(yùn)算 上下全部進(jìn)行 (i - nums[i])
 0-0+1-1+3-2+4-3+5-4+6-5+7-6+8-7 = 0-0 1-1 3-3 4-4 5-5 6-6 7-7 2-8 = 2-8
 
 (i - nums[i]) = 2-8
 
 可以看到 2 已經(jīng)出來了 因?yàn)?nums.count = 8 所以再次相加一次 ans + (i - nums[i])
 nums.count + 2-8 = 8 + 2-8 = 2
 
 
 2.
 其基本思想是利用異或XOR運(yùn)算。我們都知道一個(gè)a^b^b =a,這意味著相同數(shù)量的兩異或操作將消除數(shù)量和揭示原數(shù)。
 在這個(gè)解決方案中,我運(yùn)用異或XOR操作的指標(biāo)和數(shù)組的值。
 在一個(gè)沒有缺數(shù)字完整的陣列,指標(biāo)值應(yīng)完全對(duì)應(yīng)(nums[index] = index),所以在丟失數(shù)組,剩下的最后是失蹤數(shù)字。
 
 例如 數(shù)組
 數(shù)字     0   1   3   4   5   6   7   8   // 缺失的是 2
 下標(biāo)     0   1   2   3   4   5   6   7   // 0..7 有8個(gè)元素
 
 進(jìn)行異或運(yùn)算 上下全部進(jìn)行 (i ^ nums[i])
 0^0^1^1^3^2^4^3^5^4^6^5^7^6^8^7 = 0^0^1^1^3^3^4^4^5^5^6^6^7^7^8^2 = 8^2
 
 (i ^ nums[i]) = 8^2
 
 可以看到 2 已經(jīng)出來了 因?yàn)?xor = nums.count = 8 所以再次異或一次 xor ^ (i ^ nums[i])
 8^2^nums.count = 8^2^8 = 2
 
 
 ---------------------------------
 異或是一種基于二進(jìn)制的位運(yùn)算,用符號(hào)XOR或者 ^ 表示,
 
 其運(yùn)算法則是對(duì)運(yùn)算符兩側(cè)數(shù)的每一個(gè)二進(jìn)制位,同值取0,異值取1。
 
 異或的性質(zhì)
 交換律:a ^ b = b ^ a
 結(jié)合律:a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c
        d = a ^ b ^ c 可以推出 a = d ^ b ^ c
 自反性:a ^ b ^ a = b
 
 
 
 算法題目
 
 ①1-1000放在含有1001個(gè)元素的數(shù)組中,只有唯一的一個(gè)元素值重復(fù),其它均只出現(xiàn)一次。每個(gè)數(shù)組元素只能訪問一次,設(shè)計(jì)一個(gè)算法,將它找出來;不用輔助存儲(chǔ)空間,能否設(shè)計(jì)一個(gè)算法實(shí)現(xiàn)?
 
 前面提到異或具有交換律和結(jié)合律,所以1^2^...^n^...^n^...^1000,無論這兩個(gè)n出現(xiàn)在什么位置,都可以轉(zhuǎn)換成為1^2^...^1000^(n^n)的形式。
 
 其次,對(duì)于任何數(shù)x,都有x^x=0,x^0=x。
 
 所以1^2^...^n^...^n^...^1000 = 1^2^...^1000^(n^n)= 1^2^...^1000^0 = 1^2^...^1000(即序列中除了n的所有數(shù)的異或)。
 
 令,1^2^...^n^..^1000(序列中包含一個(gè)n)的結(jié)果為T
 則1^2^..^n^..^n^..^1000(序列中包含2個(gè)n)的結(jié)果就是T^n。
 T^(T^n)=n。
 
 所以,將所有的數(shù)全部異或,得到的結(jié)果與1^2^3^...^1000的結(jié)果進(jìn)行異或,得到的結(jié)果就是重復(fù)數(shù)。
 
 */


/* MARK: - 復(fù)雜度分析:
 間復(fù)雜度是O(n),空間復(fù)雜度為O(1)
 
 */


// MARK: - 代碼:
private class Solution {
    
    // 加法求和
    func missingNumber(_ nums: [Int]) -> Int {
        var ans = 0
        for i in 0..<nums.count {
            ans = ans + i - nums[i]
        }
        ans += nums.count
        return ans
    }
    
    // 異或運(yùn)算
    func missingNumber2(_ nums: [Int]) -> Int {
        var xor = nums.count
        for i in 0..<nums.count {
            xor = xor ^ i ^ nums[i];
        }
        return xor;
    }

}



// MARK: - 測(cè)試代碼:
func missingNumber() {
  
    print(Solution().missingNumber([0, 1, 3, 4, 5, 6, 7]))
    print(Solution().missingNumber([1, 2, 3, 4, 5]))
    print(Solution().missingNumber([0, 1, 2, 4, 5]))
    print(Solution().missingNumber([5, 1, 2, 0, 4]))

}



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容