1. 程式人生 > >《劍指offer》- 面試題3:陣列中重複的數字(java實現)

《劍指offer》- 面試題3:陣列中重複的數字(java實現)

題目一: 

        在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是重複的數字2或者3。

       比較容易想到的方法用雜湊表存出現過的數,從頭到尾遍歷一遍,每遍歷一個數字都可以判斷雜湊表中是否包含當前數字。時間複雜度O(n),同時還用了O(n)的空間。

        注意到數字都在0-n-1的範圍,如果沒有重複的數字,排序後,數字i應該正好在下標為i的位置。所以我們從頭掃描陣列,掃到下標為i的位置時,判斷值是否為i,是則掃描下一位;如果不是,比如它為m,我們判斷它是否和下標為m的數字相同,相同則說明出現重複數字,不同我們就交換這兩個數字,這樣m就到了下標為m的位置。重複這個過程就能找到重複的數字。

        上述思路可以用如下Java程式碼實現:       

public class DuplicationInArray {
    private int duplicatedNumber;
    public boolean findDuplicatedNumber(int[] array, int length) {
        if (array == null || length <= 0) throw new IllegalArgumentException("Wrong Arguments");
        for (int i = 0; i < length; i++) {
            if (array[i] < 0 || array[i] > length -1) throw new IllegalArgumentException("Wrong Numbers in Array");
        }
        for (int i = 0; i < length; i++) {
            while (array[i] != i) {
                if (array[i] == array[array[i]]) {
                    duplicatedNumber = array[i];
                    return true;
                }
                //swap
                int temp = array[i];
                array[i] = array[temp];
                array[temp] = temp;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        DuplicationInArray duplicationInArray = new DuplicationInArray();
        int[] array = {2,3,1,0,2,5,3};
        if(duplicationInArray.findDuplicatedNumber(array,array.length)) System.out.println("find duplicated number is "+ duplicationInArray.duplicatedNumber);
    }
}

題目二:

        在一個長度為n+1的數組裡的所有數字都在1~n的範圍內,所以陣列中至少有一個數字是重複的。請找出陣列中任意一個重複的數字,但是不能修改輸入的陣列。例如輸入陣列{2,3,5,4,3,2,6,7},輸出的重複數字是2或3。

        不能修改陣列很容易又想到用雜湊表輔助,但是有沒有更好的方法?

        借鑑二分法的思想,如果把1~n的陣列中的數按值大小分為兩部分,前半部分1~m,後半部分m+1~n。如果1~m部分數字數目大於m,則說明這一半的區間中一定有重複的數字,反之另一邊存在重複的數字。不斷將重複數字的區間一分為二,最終找到重複數字。

        需要指出的是這種演算法不能保證找到所有重複數字

。例如{2,3,5,4,3,2,6,7}中,1~2範圍內數字出現兩次,但是不能判斷是某一個數字出現兩次,還是1和2各出現一次。程式碼實現如下:

public class DuplicationInArrayNotEdit {
    private int countRange(int[] array,int length, int start, int end) {
        if (start < 0 || end > length-1) throw new IllegalArgumentException("Wrong Arguments");
        int count = 0;
        for (int i = 0; i < length; ++i) {
            if (array[i] <= end && array[i] >= start) ++count;
        }
        return count;
    }
    public int returnOneDuplication(int[] array) {
        if (array == null) throw new IllegalArgumentException("Wrong Arguments");
        int length = array.length;
        int start = 1;
        int end = length - 1;
        while (start <= end) {
            int middle = ((end -start) >> 1) + start;
            int count = countRange(array, length, start, middle);
            if (start == end) {
                if (count > 1) return start;
                else break;
            }
            if (count > middle - start + 1) end = middle;
            else start = middle + 1; //注意這個+1
        }
        return -1;
    }

    public static void main(String[] args) {
        DuplicationInArrayNotEdit duplicationInArrayNotEdit = new DuplicationInArrayNotEdit();
        int[] Array = new int[]{2,3,5,4,3,2,6,7};
        System.out.println(duplicationInArrayNotEdit.returnOneDuplication(Array));
    }
}
    對於輸入長度為n的陣列,由於基於二分法的思想,所以countRange呼叫的次數為logn,每次遍歷需要O(n),所以總的時間複雜度為O(nlogn),空間複雜度為O(1),相當於用空間換時間。

相關推薦

offer試題12矩陣的路徑Java實現

題目:請設計一個函式,用來判斷在一個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則該路徑不能再進入該格子。 例如 a b c e s f c s a d e e 矩

offer試題7重建二叉樹Java實現

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 思路:可以把二叉樹分為左右子樹分別構建,前序

Java offer 試題3陣列重複數字

題目一:找出陣列中的重複數字 在一個長度為n的數組裡所有數字都在0~n-1的範圍內,陣列中某些數字是重複的,但不知道有幾個數字重複,也不知道有幾個數字重複幾次,請找出任意一個重複的數字。例如:輸入長度為7的數字組{2,3,1,0,2,5,3},對應的輸出是2或3 解法一: 對陣列進行排序

offer試題陣列重複數字 google 面試

目錄 參考部落格: 題目一:找出陣列中重複的數字 思路一 思路二 題目二:不修改陣列找出重複的數字 測試: 牛客:  牛客高贊(和思路二類似都是hash對映,網友思路真是腦洞大開,這裡相關溢位問題考慮的只有~(1<<31)>>1,

offer試題30:包含min函式的棧Java實現

題目:定義棧的資料結構,請在該型別中實現一個能夠得到棧的最小元素的min函式,在該棧中,呼叫min,push,及pop的時間複雜度都為O(1)。 直接上程式碼: import java.util.Stack; public class Solution {

offer試題59 對稱的二叉樹java實現

解題思路: 可以定義一種遍歷演算法,先訪問根節點,再遍歷右子樹後遍歷左子樹,可以將這種遍歷方法稱為對稱的前序遍歷。現在可以通過比較二叉樹的前序遍歷序列和對稱前序遍歷序列來判斷二叉樹是否對稱。如果兩個序

offer--試題19二叉樹的映象--Java實現

題目描述: 請完成一個函式,輸入一個二叉樹,該函式輸出它的映象。 解題思路: 我們先前序遍歷這棵樹的每個結點,如果這個結點有子結點,就交換它的兩個子結點。當交換完所有非葉子結點的左右子結點後,就得到了樹的映象。 這裡採用了遞迴方式和非遞迴方式。

offer》- 試題3陣列重複數字java實現

題目一:         在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是重複

Offer試題3二維陣列的查詢Java版解法

題目:在一個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。 第一種解法是全遍歷,這種方

Offer——試題31整數1出現的次數

整數中1出現的次數(從1到n整數中1出現的次數) 題目:求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer

Offer試題66矩陣的路徑 java實現

/************************************************************** * Copyright (c) 2016, * All rights reserved. * 版 本 號:v1.0

試題3 陣列重複數字

找出陣列中重複的數字 長度為n的數組裡所有數字在0~n-1範圍內,某些數字是重複的,但不知道每個數字重複了幾次。 例n=7,陣列為{2, 3, 1, 0, 2, 5, 3},對應輸出為2,或3; 解答: 方法1:對陣列進行排序,從頭到尾掃描 複雜度為O(nlog

leetcode 287. 尋找重複數【Medium】【陣列】 && Offer 試題3 題目2不修改陣列找出重複數字

       這道題leetcode和劍指Offer題目略有不同。leetcode說陣列中的重複數可能不止一個,但是結果要求返回一個就行;劍指Offer上說只有一個重複的數,但是重複的次數不一定。兩個題目的共性就是隻需要返回一個重複的數即可。 leetco

Offer第二版試題3陣列重複元素

從今天開始,學習劍指Offer(第二版)中的所有演算法題,並且用java實現一遍,同步更新Blog劍指Offer(第二版)面試題3:陣列中重複的數字題目一:找出陣列中重複的數字 (限定不可以重複數字是-1,如果沒有重複數字,返回-1)       在一個長度為n的數組裡得所有

leetcode 240. 搜尋二維矩陣 II【陣列】【Medium】&&Offer試題4二維陣列的查詢

題目: 編寫一個高效的演算法來搜尋 m x n 矩陣 matrix 中的一個目標值 target。該矩陣具有以下特性: 每行的元素從左到右升序排列。 每列的元素從上到下升序排列。 示例: 現有矩陣 matrix 如下: [

Offer試題3 二維陣列的查詢

題目描述:在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。   1 2 8 9

offer{試題31連續子陣列的最大和}

思路: public class test31 { public int findMaxSum(int[] arr) { if(arr.length==0) return 0; int cur = arr[0];

Offer.試題3.陣列重複數字

在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字

offer試題二維陣列的查詢

  題目描述 思路一:遍歷整個二維陣列 思路二:利用該二維陣列的特性(時間複雜度為O(n),因為每次比較都會去掉一行或一列) 思路三:二分法   題目描述 在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一

offer{試題8旋轉陣列的最小數字}

思路:還是設定兩個指標,一頭一尾,隨時變動指標,左半部分大指標往中間去,右半部分大指標前移, public class test08 { /** * 把一個數組最開始的若干個元素搬到陣列的末尾, 我們稱之陣列的旋轉。 * 輸入一個遞增