劍指offer程式設計Java實現pdf——持續更新中...
阿新 • • 發佈:2019-02-02
二叉樹的深度為: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,這時可以查詢low和high之間的和,若=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-1這n個數字排成一個圓圈,從數字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