算法课笔记
第一次课
归并排序
-
指针正着排
-
package com.LeetCode.day02.demo02; import java.lang.reflect.Array; import java.util.Arrays; public class MergeSort { public static void mergeSort(int[] arr) { if (arr == null || arr.length < 2) { return; } mergeSort(arr, 0, arr.length - 1); } public static void mergeSort(int[] arr, int L, int R) { if (L == R) { return; } int mid = L + ((R - L) >> 1); mergeSort(arr, L, mid); mergeSort(arr, mid + 1, R); merge(arr, L, mid, R); } // 归并函数 public static void merge(int[] arr, int L, int mid, int R) { int[] help = new int[R - L + 1]; int i = 0; int p1 = L; int p2 = mid + 1; // 先把小的数放在数组最前面 while (p1 <= mid && p2 <= R) { help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; } while (p1 <= mid) { help[i++] = arr[p1++]; } while (p2 <= R) { help[i++] = arr[p2++]; } // 拷贝help数组中的元素到arr数组中 for (i = 0; i < help.length; i++) { arr[L + i] = help[i]; } System.out.println(Arrays.toString(help)); } public static void main(String[] args) { int a[] = new int[]{7,5,1,6,4}; mergeSort(a); System.out.println(Arrays.toString(a)); } }
-
指针倒着排
-
package com.LeetCode.day02.demo02; import java.util.Arrays; public class mergeSort3 { public static void mergeSort(int[] arr) { if (arr == null || arr.length < 2) { return; } mergeSort(arr, 0, arr.length - 1); } public static void mergeSort(int[] arr, int L, int R) { if (L == R) { return; } int mid = L + ((R - L) >> 1); mergeSort(arr, L, mid); mergeSort(arr, mid + 1, R); merge(arr, L, mid, R); } // 归并函数 public static void merge(int[] arr, int L, int mid, int R) { int[] help = new int[arr.length]; int i = R; int p1 = mid; int p2 = R; // 先把大的数放在数组最后面 while (p1 >= L && p2 >= mid+1) { help[i--] = arr[p1] > arr[p2] ? arr[p1--] : arr[p2--]; } while (p1 >= L) { help[i--] = arr[p1--]; } while (p2 >= mid+1) { help[i--] = arr[p2--]; } // 拷贝help数组到arr数组 while(L<=R){ arr[L]=help[L++]; } //System.out.println(Arrays.toString(help)); } public static void main(String[] args) { int a[] = new int[]{7, 5, 1, 6, 4}; mergeSort(a); System.out.println(Arrays.toString(a)); } }
-
归并排序的练习
(1)小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组
的小和。
例子:
[1,3,4,2,5]
1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16
package com.LeetCode.day02.demo02; import java.lang.reflect.Array; import java.util.Arrays; public class smallSum { public static int smallSum(int[] arr, int L, int R) { if (L == R) { return 0; } int mid = L + (R - L) / 2; return smallSum(arr, L, mid) + smallSum(arr, mid + 1, R) + merge(arr, L, mid, R); } public static int merge(int[] arr, int L, int mid, int R) { int[] help = new int[R - L + 1]; int i = 0; int p1 = L; int p2 = mid + 1; int res = 0; while (p1 <= mid && p2 <= R) { // 如果左边数组的当前指针指向的数比右边数组的当前指针指向的数小 那么右边数组中所有数都比左边这个数大,所以有(R - p2 + 1) * arr[p1] res += arr[p1] < arr[p2] ? (R - p2 + 1) * arr[p1] : 0; help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; } while (p1 <= mid) { help[i++] = arr[p1++]; } while (p2 <= R) { help[i++] = arr[p2++]; } for (i = 0; i < help.length; i++) { arr[L + i] = help[i]; } return res; } public static void main(String[] args) { int[] arr = new int[]{1, 3, 4, 2, 5}; int result = smallSum(arr,0,arr.length-1); System.out.println(result); // System.out.println(Arrays.toString(arr)); } }
(2)逆序对问题
在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数
例如在数组[4,5,8,3,2,1]
全部逆序对:(3,2)(3,1)(2,1)(8,3)(8,2)(8,1)(5,3)(5,2)(5,1)(4,3)(4,2)(4,1) 一共 12个package com.LeetCode.day02.demo02; import java.util.Arrays; public class nixudui { public static int reverseCp(int[] arr, int L, int R) { if (arr == null || arr.length < 2) { return 0; } if (L == R) { return 0; } int mid = L + (R - L) / 2; return reverseCp(arr, L, mid) + reverseCp(arr, mid + 1, R) + merge(arr, L, mid, R); } public static int merge(int[] arr, int L, int mid, int R) { int[] help = new int[arr.length]; int i = R; int p1 = mid; int p2 = R; int res = 0; while (p1 >= L && p2 >= mid + 1) { //res += arr[p1] > arr[p2] ? (p2-mid) : 0; if(arr[p1] > arr[p2]){ res+=(p2-mid); // 打印所有逆序对 for(int j = p2;j>=mid+1;j--){ System.out.println("("+arr[p1]+","+arr[j]+")" ); } } help[i--] = arr[p1] > arr[p2] ? arr[p1--] : arr[p2--]; } while (p1 >= L) { help[i--] = arr[p1--]; } while (p2 >= mid + 1) { help[i--] = arr[p2--]; } while(L<=R){ arr[L]=help[L++]; } return res; } public static void main(String[] args) { // int test[] = {7, 5, 1, 6, 4}; int test[] = {4,5,8,3,2,1}; int result = reverseCp(test, 0, test.length - 1); System.out.println(result); System.out.println(Arrays.toString(test)); } }