小和問題
在一個數組中, 每個數左邊比當前數小的數累加起來, 叫作這個數組的小和。 求一個數組的小和。例子:
[1,2,3,4]
1左邊比1小的數, 沒有;
2左邊比2小的數, 1;
3左邊比3小的數, 1, 2;
4左邊比4小的數, 1,2,3,;
因此小和爲1+1+2+1+2+3=10
思路:歸併排序的思想,在將兩個數組merge的過程當中統計右邊有多少個數大於左邊的這個數,而後乘於個數最後相加便可.java
public class work1 { public static int mergeSort(int[] arr, int left, int right) { if(left == right) return 0; int mid = left + (right - left) / 2; return mergeSort(arr, left, mid) + mergeSort(arr, mid+1, right) + merge(arr, left, mid, right); } public static int merge(int[] arr, int left, int mid, int right) { int[] help = new int[right - left +1]; int i = 0; int res = 0; int p1 = left; int p2 = mid + 1; while(p1 <= mid && p2 <= right) { //在合併的時候計算右邊有多少個元素大於arr[p1],而後arr[p1]與個數相乘後加起來. res += arr[p1] < arr[p2]? arr[p1] *(right - p2 + 1) : 0; help[i++] = arr[p1] < arr[p2]? arr[p1++] : arr[p2++]; } while(p1 <= mid) { help[i++] = arr[p1++]; } while(p2 <= right) { help[i++] = arr[p2++]; } for(i = 0; i < help.length; i++) arr[left + i] = help[i]; return res; } public static void main(String[] args) { int[] arr = new int[] {1,2,3,4}; System.out.print("原始數組:"); for(int i = 0; i < arr.length; i++) if(i != arr.length - 1) System.out.print(arr[i] + " "); else System.out.println(arr[i]); int sum = mergeSort(arr, 0 ,arr.length - 1); System.out.print("小數和:"); System.out.println(sum); } }
運行結果:
數組
荷蘭國旗問題:例如,給定數組:[334,6,323,44,88,88,56,90],給定一個值88,那麼通過處理原數組可能得一種狀況是:[56, 6, 44, 88, 88, 323, 90, 334],須要注意的是,小於88的部分不須要有序,大於88的部分也不須要有序,返回等於4部分的左右兩個下標,即[3, 4]
思路:快排的思想,使用兩個指針分別維護左邊小於num的區間與右邊大於num的區間,掃描一遍便可完成左邊小於num,右邊大於num,但左邊和右邊不須要有序.less
import java.util.Scanner; public class work2 { public static int[] partition(int[] arr, int L, int R, int num) { int less = L - 1; int more = R + 1; while(L < more) { if(arr[L] < num) { swap(arr, ++less, L++); }else if(arr[L] > num) { swap(arr, --more, L); }else { L++; } } return new int[]{less + 1, more - 1}; } public static void swap(int[] arr, int i,int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } public static void main(String[] args) { int[] arr = new int[]{334,6,323,44,88,88,56,90}; System.out.print("原始數組:"); for(int i = 0; i < arr.length; i++) if(i != arr.length - 1) System.out.print(arr[i] + " "); else System.out.println(arr[i]); System.out.print("請輸入一個整數:"); Scanner in = new Scanner(System.in); int num = in.nextInt(); int[] p = partition(arr, 0, arr.length - 1, num); System.out.println("partition以後"); for(int i = 0; i < arr.length; i++) if(i != arr.length - 1) System.out.print(arr[i] + " "); else System.out.println(arr[i]); System.out.println(num + "的左邊界爲:" + p[0] + ",右邊界爲:" + p[1]); } }
運行結果:
ide