妥妥的去面試之數據結構與算法(一)

筆者由於在找工作,所以近期最主要的任務就是準備面試,不打無準備之仗。只有你準備充分了,那麼你想要的機會纔有機會入你懷中。

筆者會將準備面試的學習過程記錄下來,方便自己覆盤的同時也希望能給一道找工作的小夥伴們一些幫助。筆者準備的內容大綱如下

7911186-9c84d76a4df01570.png
Android面試大綱.png

妥妥的去面試之數據結構與算法(一)

下面是本篇博客的正菜部分:

一、找出數組中重複的數字

在一個長度爲n的數組裏的所有數字都在0~n-1的範圍內。找出數組中任意一個重複的數字。

注意:如果題目改成找出數組中重複的數字的話,就需要和面試官溝通,我是找出所有重複的數字還是只需要找出一個就好了。

排序法

先把原數組進行一次排序,再對排序好的數組從頭到尾進行遍歷,很容易找到重複的數字,排序長度爲n的數組需要O(nlogn)的時間。

哈希表法

可以藉助哈希表解決該問題,從頭到尾掃描該數組,判斷該掃描到的數是否存在於該哈希表中,如果不存在則放於該哈希表中,如果存在則爲重複元素。這個算法的時間複雜度是O(n),但卻是以大小爲O(n)的空間複雜度爲代價。

交換法

如果沒有重複元素的話,那麼重排該數組後,數字i會出現在下標i的位置。如果有重複元素的話,下標i的位置可能不止一個數字,也可能沒有數字。

從頭到尾掃描數組,掃描到下標爲i的數字(用m表示)看是否等於i,如果是則接着掃描下一個數字,如果不是,再拿它和下標爲m的那個數字比較,如果相等,則找到一個重複數字,如果不相等,就和它交換。重複這樣的操作,直到找到重複的數字。

代碼實例:

如果不存在重複元素的話,返回-1(具體返回的值可以和面試官溝通)

public int getDuplicateNumber(int[] numbers){
        int len = numbers.length;
        if(numbers == null || len <= 0) return -1;
        for(int i=0;i<len;i++){
            if(numbers[i] < 0 || numbers[i] > len-1)
                return -1;
        }
        
        for(int i=0;i<len;i++){
            
            while(numbers[i] != i){
                if(numbers[i] == numbers[numbers[i]]){
                    return numbers[i];  //找到重複元素
                }
                else {
                    //交換numbers[i]和numbers[numbers[i]]的值
                    int temp = numbers[i];
                    numbers[i] = numbers[temp];
                    numbers[temp] = temp;
                }
            }
            
        }
        return -1;
    }

二、不能修改數組找出重複的數字

在一個長度爲n+1的數組裏的所有數字都在1~n的範圍內。找出數組中任意一個重複的數字。不能改變原數組並且不可藉助大小超過O(n)的輔助空間。

二分法

因爲長度是n+1,所以該數組至少有一個重複的數字。可以根據長度進行一半一半的分割。比如長度爲8的數組,把它分兩半:1-4,5-7。先在數組中找在1-4範圍內的數的個數,如果超過4個說明重複的數字在1-4中。這樣就縮小了範圍,之後繼續二分,在數組中分別找1-2,3-4這兩組數字的個數,直到找到一個重複的數字。

public int getDuplicateNumber2(int[] numbers){
        int len = numbers.length;
        if(numbers == null || len <= 0) return -1;
        int start = 1;
        int end = len-1;
        
        while(end >= start){
            int middle = ((end - start) >> 1)+start;
            int count = countRange(numbers,len,start,middle);
            if(end == start){
                if(count > 1) return start;  //找到重複元素
                else break;
            }
            if(count >(middle-start+1))
                end = middle;
            else
                start = middle+1;
        
        }
        return -1;
    }
    
private int countRange(int[] numbers, int len, int start, int end) {
        if(numbers == null)
            return 0;
        int count = 0;
        for(int i=0;i<len;i++){
            if(numbers[i]>=start && numbers[i]<=end)
                ++count;
        }
        return count;
    }

參考:劍指offer P39

面試系列的文章都放於 面試妥妥的 建議小夥伴們關注該專題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章