lintcode 中等題:find the missing number 尋找缺失的數


題目

給出一個包含 0 .. N 中 N 個數的序列,找出0 .. N 中沒有出現在序列中的那個數。

樣例

N = 4 且序列為 [0, 1, 3] 時,缺失的數為2

注意

可以改變序列中數的位置。

挑戰

在數組上原地完成,使用O(1)的額外空間和O(N)的時間。

解題

重新定義一個數組存放排序后的數,空間復雜度和時間復雜度都是O(N)

public class Solution {
    /**    
     * @param nums: an array of integers
     * @return: an integer
     */
    public int findMissing(int[] nums) {
        // write your code here
        boolean[] A = new boolean[nums.length +1];
        for(int i = 0;i<nums.length; i++){
            A[nums[i]] = true;
        }
        int n = 0;
        for(int i = 0;i< A.length ;i++){
            if(A[i] == false){
                n = i;
                break;
            }
        }
        
        return n;
    }
}
Java Code

總耗時: 1674 ms

class Solution:
    # @param nums: a list of integers
    # @return: an integer
    def findMissing(self, nums):
        # write your code here
        A = [False]*(len(nums) + 1)
        for a in nums:
            A[a] = True
        for i in range(len(A)):
            if A[i] == False:
                return i
Python Code

總耗時: 276 ms

在下面的挑戰中,說可以在原始數組上面操作,如何在原始數組上面操作?空間復雜度並且是O(1) 

 i^i = 0 一個數自身的異或等於0

這個可以空間復雜可以是O(1),就有下面的代碼了

public class Solution {
    /**    
     * @param nums: an array of integers
     * @return: an integer
     */
    public int findMissing(int[] nums) {
        // write your code here
        int res = 0;
        for( int i =0;i< nums.length ;i++){
            res = res ^ nums[i] ^ i;
        }
        res = res^(nums.length);
        return res;
    }
}
Java Code

總耗時: 1802 ms

class Solution:
    # @param nums: a list of integers
    # @return: an integer
    def findMissing(self, nums):
        # write your code here
        res = 0
        for i in range(len(nums)):
            res = res ^ i ^ nums[i]
        res ^= len(nums)
        return res 
Python Code

總耗時: 297 ms

書影博客中看到通過求和來找缺失的數,我都被這個機智的方法嚇到了,竟然如此如此的機智

直接復制其代碼:

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        return n * (n + 1) / 2 - sum(nums)

 看到一個很牛逼的方法

在原始數組上,把A[i] 調整到其原來的位置 是的A[i] = i ,結束的地方就是當A[i] <0 此題目沒有負數也沒有影響的,A[i]>=n 顯然的A[n]越界了。

以下面例子進行解釋
[9,8,7,6,2,0,1,5,4],是長度為9的數組,按照題目的要求應該是0到9十個數字,找出缺失的那一個。
第0下標,9>=9 不做交換,下面的輸出是只對交換的情況,在輸出當前交換前和交換后的情況 ,黃色標記是交換的兩個元素
第1下標,A[1]!=1 A[1]與A[A[1]]進行交換,即 8 4交換
before: [9, 8, 7, 6, 2, 0, 1, 5, 4] later: [9, 4, 7, 6, 2, 0, 1, 5, 8]
交換后的A[1]依舊不等於1,繼續A[1]與A[A[1]]交換,即 4 2 交換 before: [9, 4, 7, 6, 2, 0, 1, 5, 8] later: [9, 2, 7, 6, 4, 0, 1, 5, 8]
2 7 進行交換 before: [9, 2, 7, 6, 4, 0, 1, 5, 8] later: [9, 7, 2, 6, 4, 0, 1, 5, 8]
7 5 進行交換 before: [9, 7, 2, 6, 4, 0, 1, 5, 8] later: [9, 5, 2, 6, 4, 0, 1, 7, 8]
5 0 進行交換 before: [9, 5, 2, 6, 4, 0, 1, 7, 8] later: [9, 0, 2, 6, 4, 5, 1, 7, 8]
9 0 進行交換 before: [9, 0, 2, 6, 4, 5, 1, 7, 8] later: [0, 9, 2, 6, 4, 5, 1, 7, 8]
此時A[1]>=n 不進行交換
第2下標,A[2]=2不進行交換
第3下標,A[3]!=3,6 1 進行交換 before: [0, 9, 2, 6, 4, 5, 1, 7, 8] later: [0, 9, 2, 1, 4, 5, 6, 7, 8]
1 9 進行交換 before: [0, 9, 2, 1, 4, 5, 6, 7, 8] later: [0, 1, 2, 9, 4, 5, 6, 7, 8]
以后的下標都和其元素值相等,不需要交換

下面只需要遍歷數組,找出下標和值不相等的點即可,當都滿足的時候,說明是n值不在數組中
說明下,中間有個缺失的數,那么一定有個其他數字占據了他的位置,找到這個位置就是答案了。
可以看出在一次交換時候,至少把一個元素調整到其所在的下標位置,也就是A[tmp] = tmp 這個元素 ,而A[i] = A[tmp]之前的元素的值,不能保證每次都使得自己的元素回到自己的位置,所以要用while多次循環。

如下,好好體會:

public class Solution {
    /**    
     * @param A: an array of integers
     * @return: an integer
     */
    public int findMissing(int[] A) {
        // write your code here
        int n = A.length;
        for(int i = 0;i< n;i++){
            
            while( A[i] != i){
                if(A[i] <0 || A[i] >= n)
                    break;
                int tmp = A[i];
                A[i] = A[tmp];
                A[tmp] = tmp;
            }
        }
        for(int i =0;i <n;i++){
            if(A[i] !=i)
                return i;
        }
        return n;
    }
}

 總耗時: 2141 ms

class Solution:
    # @param A: a list of integers
    # @return: an integer
    def findMissing(self, A):
        # write your code here
        n = len(A)
        if A == None or n == 0:
            return 0
        # num0 = A
        for i in range(n):
            while A[i] != i:
                # num0 = A[:]
                if A[i]<0 or A[i]>=n:
                    break
                tmp = A[i]
                A[i] = A[tmp]
                A[tmp] = tmp
                # if n > 6:
                    # print 'before:',num0
                    # print ' later:',A
                 
        for i in range(n):
            if A[i]!=i:
                return i
        return n
Python Code

總耗時: 352 ms

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM