1. 程式人生 > 其它 >演算法基礎入門——選擇、冒泡、插入、二分、異或運算

演算法基礎入門——選擇、冒泡、插入、二分、異或運算

public class code01 {
    /**
     * 選擇排序
     * 遍歷一輪選擇最小的,每輪確定一個數的位置
     * 時間複雜度O(N^2),額外空間複雜度O(1)
     */
    public static void selectionSort(int[] arr) {
        if (arr == null || arr.length < 2){
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int
minIndex = i; for (int j = i + 1; j <arr.length; j++) { minIndex = arr[j] < arr[minIndex] ? j : minIndex; } // 如果minIndex等於i,就是其本身就不用交換,如果使用異或交換就會變為0 if (minIndex != i) { swap(arr, i, minIndex); } } }
/** * 氣泡排序 * 遍歷一輪,確定一個數的位置,相鄰比較 * 時間複雜度O(N^2),額外空間複雜度O(1) */ public static void bubbleSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int k = arr.length - 1; k > 0; k--) { for (int i = 0; i < k; i++) {
if (arr[i] > arr[i+1]) { swap(arr, i, i + 1); } } } } /** * 插入排序 * 左邊有序,右邊無序 * 時間複雜度O(N^2),額外空間複雜度O(1) */ public static void insertionSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int i = 1; i < arr.length; i++) { for (int j = i - 1; j >= 0 && arr[j] > arr[j+1]; j--) { swap(arr, j, j+1); } } } /** * 陣列交換 */ public static void swap(int[] arr, int i, int j) { arr[i] = arr[i] ^ arr[j]; arr[j] = arr[i] ^ arr[j]; arr[i] = arr[i] ^ arr[j]; } /** * 在有序陣列中,使用二分法查詢某數是否存在 * @return */ public static boolean BSExist(int[] arr, int num) { if (arr == null && arr.length == 0) { return false; } int left = 0; int right = arr.length -1; int mid = 0; while (left < right) { // mid = left + ((right - left) >> 1); mid = (left + right) / 2; if (arr[mid] == num) { return true; } else if (arr[mid] > num) { right = mid -1; } else { left = mid + 1; } } // return sortedArr[left] == num; return false; } /** * 在有序陣列中,使用二分查詢>=某個數的最左側位置 * @return */ public static int BSNearLeft(int[] arr, int num) { if (arr == null && arr.length == 0) { return 0; } int index = -1; int left = 0; int right = arr.length -1; int mid; while (left < right) { mid = left + ((right - left) >> 1); if (arr[mid] >= num) { index = mid; right = mid -1; } else { left = mid + 1; } } return index; } /** * 一個數組中有一種數出現了奇數次,其他數都出現了偶數次,怎麼找到這一個數? * 運用異或運算,出現偶數次的數異或後等於0,最後異或的結果就是出現奇數次的數 * 0^N == N * N^N == 0 * @param arr */ public static void printOddTimesNum1(int[] arr) { int a = 0; for (int b :arr) { a = a ^ b; } System.out.println(a); } /** * 一個數組中有兩種數出現了奇數次,其他數都出現了偶數次,怎麼找到這兩個數 * @param arr */ public static void printOddTimesNum2(int[] arr) { int a = 0; int one = 0; // 獲取到2個數異或的值 for (int b :arr) { a = a ^ b; } // 獲取2個數異或的值的最右邊的1,與上(取反+1) int rightOne = a & (~a + 1); // 將陣列分為2類,獨自異或,可以得到一個出現奇數次的數 for (int b :arr) { if ((b & rightOne) != 0) { one ^= b; } } System.out.println(one +" "+ (one ^ a)); } /** * 用遞迴方法找一個數組中的最大值 * @param arr * @param left * @param right * @return */ public static int getMax(int[] arr, int left, int right) { if (left == right) { return arr[left]; } int mid = left + ((right - left) >> 1); int leftMax = getMax(arr, left, mid); int rightMax = getMax(arr, mid + 1, right); return Math.max(leftMax,rightMax); } /** * 區域性最小值問題 * 區域性最小值的概念。arr長度為1時,arr[0]是區域性最小。arr的長度為N(N > 1)時,如果arr[0]<arr[1],那麼arr[0]是區域性最小; * 如果arr[N-1]<arr[N-2],那麼arr[N-1]是區域性最小;如果0<i<N-1,既有arr[i]<arr[i-1],又有arr[i]<arr[i+1],那麼arr[i]是區域性最小。 * 給定無序陣列arr,已知arr中任意兩個相鄰的數都不相等。寫一個函式,只需返回arr中任意一個區域性最小出現的位置即可。 * @param arr * @return */ public static int getLessIndex(int[] arr) { if (arr == null || arr.length == 0) { return -1; } if (arr.length == 1 || arr[0] < arr[1]) { return 0; } if (arr[arr.length - 1] < arr[arr.length - 2]) { return arr.length -1; } int left = 1; int right = arr.length - 2; int mid = 0; while (left < right) { mid = left + ((right - left) >> 1); // 注意這裡判斷條件 // 上升趨勢,拋棄右邊,保持先降後升的趨勢 if (arr [mid] > arr[mid - 1]) { right = mid - 1; // 下降趨勢,拋棄左邊 保持先降後升趨勢 } else if (arr[mid] > arr[mid + 1]) { left = mid + 1; } else { // 找到區域性最小了 return mid; } } // 剩餘一個 return left; } public static void main(String[] args) { int[] arr1 = {212,1561,451,15415,451,12,4511,45315,5616,4565}; // 選擇排序 selectionSort(arr1); for (int i = 0; i < arr1.length; i++) { System.out.println(arr1[i]); } int[] arr2 = {212,1561,451,15415,451,12,4511,45315,5616,4565}; // 氣泡排序 bubbleSort(arr2); for (int i = 0; i < arr2.length; i++) { System.out.println(arr2[i]); } int[] arr3 = {212,1561,451,15415,451,12,4511,45315,5616,4565}; // 插入排序 insertionSort(arr3); for (int i = 0; i < arr2.length; i++) { System.out.println(arr3[i]); } // 二分查詢某數 boolean b = BSExist(arr3, 451); System.out.println(b); // 二分查詢>=某數最左側位置 int i = BSNearLeft(arr3, 452); System.out.println(i); // 一個數組中有一種數出現了奇數次,其他數都出現了偶數次,怎麼找到這一個數 int[] arr4 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; printOddTimesNum1(arr4); // 一個數組中有兩種數出現了奇數次,其他數都出現了偶數次,怎麼找到這兩個數 int[] arr5 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; printOddTimesNum2(arr5); // 遞迴獲取陣列最大值 int max = getMax(arr3, 0, arr3.length - 1); System.out.println(max); // 區域性最小值問題 int[] arr6 = {6, 5, 7, 3, 4, 6, 7, 8}; for (int j = 0; j != arr6.length; j++) { System.out.print(arr6[j] + " "); } System.out.println(); int index = getLessIndex(arr6); System.out.println("index: " + index + ", value: " + arr6[index]); } }