1. 程式人生 > >劍指offer程式設計Java實現pdf——持續更新中...

劍指offer程式設計Java實現pdf——持續更新中...

二叉樹的深度為:4



面試題41:和為s的兩個數字VS和為s的連續正數序列

題目一大致為:     輸入一個遞增排序的陣列和一個數字s,在陣列中查詢兩個數,使得他們的和正好是s。 思路:     對於有序陣列,用兩個指標分別指向頭和尾部,然後將他們的和與s比較,若等於s,退出;若<s,則頭指標向後移;若>s,則尾指標向前移;直到兩個指標相遇。 Java程式碼
public class MainTest {
    public static void main(String[] args) {
        int array[] = { 1, 2, 4, 7, 11, 15 };  
        int s = 15;  
        int result[] = new int[2];// 儲存兩個解  
        result = getTwoSumEqualsNum(array, s);  
  
        if (result != null) {// 存在這樣的解,輸出  
            System.out.println("一組解為:" + result[0] + "、" + result[1]);  
        } else {  
            System.out.println("不存在");  
        }  
    }
    public static int[] getTwoSumEqualsNum(int[] arr, int num) {
        int[] result = new int[2];
        int l = 0, r = arr.length - 1;
        while (l < r) {
            int s = arr[l] + arr[r];
            if (s == num) {
                result[0] = arr[l];
                result[1] = arr[r];
                return result;
            } else if (s < num) {
                l++;
            } else {
                r--;
            }
        }
        return null;
    }
}
執行結果:
一組解為:4、11


題目二大致為:     輸入一個正數s,打印出所有和為s的連續正數序列(至少含有兩個數)。 思路: s至少要為3,這樣才能滿足至少含有兩個數,若s>3,這時可以查詢lowhigh之間的和,若=s,則輸出;若<s,則增加high,若>s,則增加low,這樣就減少了他們之間的數,直到low<(1+s)/2;即小於中間值,因為兩個中間值的和可能為s Java程式碼
public class MainTest {
    public static void main(String[] args) {
        findSequenceSumEqualsNum(15);
    }
    public static void findSequenceSumEqualsNum(int num) {
        int low = 1, high = 2, sequenceSum = low + high;
        int mid = num / 2;
        while (low <= mid) {
            while (sequenceSum < num && low <= mid) {
                high++;
                sequenceSum += high;
            }
            if (sequenceSum == num) {
                printSequence(low, high);
            }
            sequenceSum -= low;
            low++;
        }
    }
    private static void printSequence(int low, int high) {
        if (low < high) {
            for (int i = low; i <= high; i++) {
                System.out.print(i + "、");
            }
            System.out.println();
        }
    }
}
執行結果:
1、2、3、4、5、
4、5、6、
7、8、


面試題42:翻轉單詞順序VS左旋轉字串

題目一大致為:     輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。為簡單起見,標點符號和普通字母一樣處理。 思路:     兩次翻轉,對於字串"I am a student.",首先進行第一次翻轉,即翻轉完為:".tneduts a ma I",然後再對每個單詞翻轉,最終為:"student. a am I" Java實現
public class MainTest {
    public static void main(String[] args) {
        String s = "I   am a student. ";  
        System.out.println(reverseSentence(s));  
    }
    public static String reverseSentence(String str) {
        StringBuilder result = new StringBuilder();
        String reverseStr = reverseWord(str);
        int start = 0;
        for (int i = 0; i < reverseStr.length(); i++) {
            if (reverseStr.charAt(i) == ' ') {
                result.append(reverseWord(reverseStr.substring(start, i)));
                while (i < reverseStr.length() && reverseStr.charAt(i) == ' ') {
                    result.append(' ');
                    i++;
                }
                start = i;
            }
        }
        result.append(reverseStr.substring(start, str.length()));
        return result.toString();
    }
    public static String reverseWord(String word) {
        StringBuilder sb = new StringBuilder();
        for (int i = word.length() - 1; i >= 0; i--) {
            sb.append(word.charAt(i));
        }
        return sb.toString();
    }
}
執行結果:
 student. a am   I


面試題44:撲克牌的順序

題目大致為:     從撲克牌中隨機抽出5張牌,判斷是不是一個順子,即這5張牌是不是連續的。2~10為數字本身,A為1,J為11,Q為12,K為13,而大、小王可以看成是任意數字。 思路:     實則本題是判斷一個數組是否是連續的,將大、小王看成是0,0可以充當任何的數。這樣我的思路是:先對陣列排序,排序後統計出0的個數,在計算非0數之間的缺少的數字個數的總和,若是在這個過程中發現前後兩個的差為0則為相同的元素,則不符合題意;在滿足題意的情況下,若是0的個數大於等於缺少的數字個數的總和,那麼滿足條件,否則不滿足條件。 Java程式碼:

import java.util.Arrays;

public class MainTest { public static void main(String[] args) { // 模擬隨機抽牌,大小王為0,A為1,J為11,Q為12,K為13,其實就是個陣列,判斷陣列是否是順序的 // 測試1:正好填補 int array_1[] = { 0, 0, 1, 4, 5 }; System.out.println(isSequence(array_1)); // 測試2:不能填補 int array_2[] = { 0, 1, 4, 5, 6 }; System.out.println(isSequence(array_2)); // 測試3:有相同元素 int array_3[] = { 0, 1, 3, 3, 4, }; System.out.println(isSequence(array_3)); // 測試4:正好填補 int array_4[] = { 0, 10, 0, 11, 7, }; System.out.println(isSequence(array_4)); } public static boolean isSequence(int[] arr) { Arrays.sort(arr); int zeroNum = 0, gap1Num = 0; for (int i = 0; i < arr.length - 1; i++) { if (arr[i] == 0) { zeroNum++; } else { int gap = arr[i + 1] - arr[i]; if (gap == 0) { return false; } else { gap1Num += gap - 1; } } } if (zeroNum >= gap1Num) { return true; } return false; } }執行結果:
true
false
false
true


面試題45:圓圈中最後剩下的數字

題目大致為: 0,1,...,n-1n個數字排成一個圓圈,從數字0開始每次從這個圓圈裡刪除第m個數字。求出這個圓圈裡剩下的最後一個數字。 思路:     第一種辦法就是通過環形連結串列模擬這樣的刪除過程;但是作者推匯出了這樣的關係式,具體關係式可以見書P231 Java程式碼
public class MainTest {
    public static void main(String[] args) {
        System.out.println(lastNumInCircle(20, 3));  //方法1
        System.out.println(lastRemaining(20, 3));  //方法2
        System.out.println(lastNumInCircle(20, 23));  //方法1
        System.out.println(lastRemaining(20, 23));  //方法2
    }
    public static int lastNumInCircle(int n, int count) {
        ListNode root = new ListNode(-1), p = root;
        for (int i = 0; i < n; i++) {
            p.next = new ListNode(i);
            p = p.next;
        }
        p.next = root.next;
        while (--n > 0) {
            for (int i = 0; i < count - 1; i++) {
                p = p.next;
            }
            p.next = p.next.next;
        }
        return p.value;
    }
    public static int lastRemaining(int n, int m) {  
        if (n < 1 || m < 1) {  
            return -1;  
        }  
  
        int last = 0;  
        for (int i = 2; i <= n; i++) {  
            last = (last + m) % i;  
        }  
        return last;  
    }  
}
執行結果:
19
19
18
18


面試題46:求1+2+...+n

題目大致為:     求1+2+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。 Java程式碼: