資料結構與演算法基礎01—— 常見基本排序、二分法與異或運算
阿新 • • 發佈:2021-06-29
常見基本排序
選擇排序
基本思路:從第一位開始標記,每次選出最小數字與標記位交換
程式碼實現:
private static void selectSort(int[] arr) { if(arr == null || arr.length < 2){ return; } for (int i = 0; i < arr.length-1; i++) { int index = i; for (int j = i + 1; j < arr.length; j++) {View Codeif(arr[j] < arr[index]){ index = j; } } swap(arr, i ,index); } }
氣泡排序
基本思路:每次比較相鄰兩個數大小,每次迴圈選出當輪最大/小數字,每次迴圈次數環比減一
程式碼實現:
private static void bubbleSort(int[] arr) { if (arr == null || arr.length < 2) {View Codereturn; } for (int end = arr.length-1; end >0; end--) { for (int start = 0; start < end; start++) { if(arr[start]>arr[start+1]){ swap(arr, start, start+1); } } } }
插入排序
基本思路:保證前面有序的情況下,依次把後面數字插入到指定位置繼續保證有序
程式碼實現:
private static void insertionSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int i = 1; i < arr.length; i++) { for (int j = i; j > 0 && arr[j]<arr[j-1]; j--) { swap(arr,j,j-1); } } }View Code
二分法
基本思路:根據左右邊界計算中間位置,中間值和目標值比較,如果中間值小於目標值,左邊界等於中間位置+1,如果中間值大於目標值,右邊界等於中間位置-1。
在一個有序陣列中,找某個數是否存在
private static boolean isExist(int[] arr, int num) { if(arr == null || arr.length <2){ return false; } int L = 0; int R = arr.length-1; int mid = 0; while (L < R){ mid = L + ((R-L) >> 1); if(arr[mid] == num){ return true; }else if(arr[mid] < num){ L = mid + 1; }else{ R = mid - 1; } } return arr[L] == num; }View Code
在一個有序陣列中,找>=某個數最左側的位置
private static int leftmostPosition(int[] arr, int num) { int L = 0; int R = arr.length-1; int mid = 0; int index = -1; while (L <= R){ mid = L + ((R-L) >> 1); if(arr[mid] >= num){ index = mid; R = mid - 1; }else{ L = mid + 1; } } return index; }View Code
在一個有序陣列中,找<=某個數最右側的位置
private static int rightmostPosition(int[] arr, int num) { int L = 0; int R = arr.length-1; int mid = 0; int index = -1; while (L <= R){ mid = L + ((R-L) >> 1); if(arr[mid] <= num){ index = mid; L = mid + 1; }else{ R = mid - 1; } } return index; }View Code
相鄰兩數不等,區域性最小值問題
private static int localMinimum(int[] arr){ if(arr == null || arr.length<=1){ return -1; } if(arr[0] < arr[1]){ return 0; } if(arr[arr.length - 1] < arr[arr.length - 2]){ return arr.length - 1; } int L = 1; int R = arr.length - 2; int mid = 0; while (L < R){ mid = L + ((R - L) >> 1); if(arr[mid] > arr[mid-1]){ R = mid - 1; }else if(arr[mid] > arr[mid+1]){ L = mid + 1; }else{ return mid; } } return -1; }View Code
異或運算
基本規則:相同則0,不同則1
不用額外變數交換兩個數
private static void swap(int[] arr, int a, int b){ arr[a] = arr[a] ^ arr[b]; arr[b] = arr[a] ^ arr[b]; arr[a] = arr[a] ^ arr[b]; }View Code
一個數組中有一種數出現奇數次,其他數都出現了偶數次,怎麼找到並列印這種數
private static int getNum(int[] arr){ if(arr == null || 0 == arr.length){ return -1; } int num = 0; for (int i = 0; i < arr.length; i++) { num ^= arr[i]; } return num; }View Code
一個數組中有兩種數出現奇數次,其他數都出現了偶數次,怎麼找到並列印這兩種數
private static void printNums(int[] arr){ int num = 0; for (int i = 0; i < arr.length; i++) { num ^= arr[i]; // 最終結果是兩種數:a^b } // a^b不等於0,所以在某個位置,一個數是0,一個數是1 // 找出最右位置的1,然後取該位置為0的數字進行異或就可以找出其中一個數 int farRightOne = num & ((~num)+1); int onlyOne = 0; for (int i = 0; i < arr.length; i++) { if((arr[i] & farRightOne) != 0){ onlyOne ^= arr[i]; } } System.out.println(onlyOne + " ^ " + (num ^ onlyOne)); }View Code
數出二進位制1的個數
private static int getNumberOfOne(int num) { int count = 0; while (num != 0 ){ num &= num - 1; count++; } return count; }View Code