认识时间复杂度

常数时间的操作:
一个操作如果和样本的数据量没关系,每次都是固定时间内完成的操

时间复杂度是一个算法流程中,常数操作数量的一个指标。常用O(独坐big O)来表示。具体来说,先要对一个算法流程非常熟悉,然后写出这个算法流程中发生了多少常数操作,进而总结出这个算法中常数操作数量的表达式。

在表达式中,只要高阶项,不要低阶项,也不要高阶项的系数

评价一个算法流程的好坏,先看时间复杂度的指标,如果相同,不能根据高阶系数判断,因为不同的常数时间的操作的执行时间不同,因此,需要分析不同数据样本的实际运行时间判断

异或运算

image.png
这种异或方式的交换最好不要放在数组中进行,例如
public 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];
}
如果i,j相等,则arr[i]会变为0

问题一:在一个数字序列中,有一个数出现了奇数次,其他数都出现了偶数次,找到这个奇数。
问题二:在一个数字序列中,有两个数出现了奇数次,其他数都出现了偶数次,寻找这两个数

  1. package class01;
  2. public class Code07_EvenTimesOddTimes {
  3. public static void printOddTimesNum1(int[] arr) {
  4. int eO = 0;
  5. for (int cur : arr) {
  6. eO ^= cur;
  7. }
  8. System.out.println(eO);
  9. }
  10. public static void printOddTimesNum2(int[] arr) {
  11. int eO = 0, eOhasOne = 0;
  12. for (int curNum : arr) {
  13. eO ^= curNum;
  14. }
  15. //e0=a^b
  16. //e0不等于0
  17. //e0的二进制位上一定有一个位置x是1,则a和b则在这个位上一个是1,一个是0
  18. int rightOne = eO & (~eO + 1); //常规操作:一个数 与 这个数取反加1 === 提取这个数的最右边的1
  19. //在所有数组中,将数分为x上是1和x上是0的两个部分
  20. //数组中异或上在x位置上是0的数,结果就是a或者b
  21. for (int cur : arr) {
  22. if ((cur & rightOne) != 0) {
  23. eOhasOne ^= cur;
  24. }
  25. }
  26. System.out.println(eOhasOne + " " + (eO ^ eOhasOne));
  27. }
  28. public static void main(String[] args) {
  29. int a = 5;
  30. int b = 7;
  31. a = a ^ b;
  32. b = a ^ b;
  33. a = a ^ b;
  34. System.out.println(a);
  35. System.out.println(b);
  36. int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 };
  37. printOddTimesNum1(arr1);
  38. int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 };
  39. printOddTimesNum2(arr2);
  40. }
  41. }

局部最小值问题

查询一个数组的任意一个局部最小值(如果第0个元素 < 第1个元素,0就是局部最小 , 第length - 1个元素 < 第length - 2元素,length - 1 就是局部最小),中间部分要满足局部最小值需要该位置上的值既小于左边元素值也小于右边元素值,。其中,数组无序且相邻两个数一定不相等。
image.png

  1. package class01;
  2. public class Code09_FindOneLessValueIndex {
  3. public static int getLessIndex(int[] arr) {
  4. if (arr == null || arr.length == 0) {
  5. return -1; // no exist
  6. }
  7. if (arr.length == 1 || arr[0] < arr[1]) {
  8. return 0;
  9. }
  10. if (arr[arr.length - 1] < arr[arr.length - 2]) {
  11. return arr.length - 1;
  12. }
  13. int left = 1;
  14. int right = arr.length - 2;
  15. int mid = 0;
  16. while (left < right) {
  17. mid = (left + right) / 2;
  18. if (arr[mid] > arr[mid - 1]) {
  19. right = mid - 1;
  20. } else if (arr[mid] > arr[mid + 1]) {
  21. left = mid + 1;
  22. } else {
  23. return mid;
  24. }
  25. }
  26. return left;
  27. }
  28. public static void printArray(int[] arr) {
  29. for (int i = 0; i != arr.length; i++) {
  30. System.out.print(arr[i] + " ");
  31. }
  32. System.out.println();
  33. }
  34. public static void main(String[] args) {
  35. int[] arr = { 6, 5, 3, 4, 6, 7, 8 };
  36. printArray(arr);
  37. int index = getLessIndex(arr);
  38. System.out.println("index: " + index + ", value: " + arr[index]);
  39. }
  40. }

选择排序

  1. package class01;
  2. import java.util.Arrays;
  3. public class Code01_SelectionSort {
  4. public static void selectionSort(int[] arr) {
  5. if (arr == null || arr.length < 2) {
  6. return;
  7. }
  8. for (int i = 0; i < arr.length - 1; i++) {
  9. int minIndex = i;
  10. for (int j = i + 1; j < arr.length; j++) {
  11. minIndex = arr[j] < arr[minIndex] ? j : minIndex;
  12. }
  13. swap(arr, i, minIndex);
  14. }
  15. }
  16. public static void swap(int[] arr, int i, int j) {
  17. int tmp = arr[i];
  18. arr[i] = arr[j];
  19. arr[j] = tmp;
  20. }
  21. // for test
  22. public static void comparator(int[] arr) {
  23. Arrays.sort(arr);
  24. }
  25. // for test
  26. public static int[] generateRandomArray(int maxSize, int maxValue) {
  27. int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
  28. for (int i = 0; i < arr.length; i++) {
  29. arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
  30. }
  31. return arr;
  32. }
  33. // for test
  34. public static int[] copyArray(int[] arr) {
  35. if (arr == null) {
  36. return null;
  37. }
  38. int[] res = new int[arr.length];
  39. for (int i = 0; i < arr.length; i++) {
  40. res[i] = arr[i];
  41. }
  42. return res;
  43. }
  44. // for test
  45. public static boolean isEqual(int[] arr1, int[] arr2) {
  46. if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
  47. return false;
  48. }
  49. if (arr1 == null && arr2 == null) {
  50. return true;
  51. }
  52. if (arr1.length != arr2.length) {
  53. return false;
  54. }
  55. for (int i = 0; i < arr1.length; i++) {
  56. if (arr1[i] != arr2[i]) {
  57. return false;
  58. }
  59. }
  60. return true;
  61. }
  62. // for test
  63. public static void printArray(int[] arr) {
  64. if (arr == null) {
  65. return;
  66. }
  67. for (int i = 0; i < arr.length; i++) {
  68. System.out.print(arr[i] + " ");
  69. }
  70. System.out.println();
  71. }
  72. // for test
  73. public static void main(String[] args) {
  74. int testTime = 500000;
  75. int maxSize = 100;
  76. int maxValue = 100;
  77. boolean succeed = true;
  78. for (int i = 0; i < testTime; i++) {
  79. int[] arr1 = generateRandomArray(maxSize, maxValue);
  80. int[] arr2 = copyArray(arr1);
  81. selectionSort(arr1);
  82. comparator(arr2);
  83. if (!isEqual(arr1, arr2)) {
  84. succeed = false;
  85. printArray(arr1);
  86. printArray(arr2);
  87. break;
  88. }
  89. }
  90. System.out.println(succeed ? "Nice!" : "Fucking fucked!");
  91. int[] arr = generateRandomArray(maxSize, maxValue);
  92. printArray(arr);
  93. selectionSort(arr);
  94. printArray(arr);
  95. }
  96. }

冒泡排序

  1. package class01;
  2. import java.util.Arrays;
  3. public class Code02_BubbleSort {
  4. public static void bubbleSort(int[] arr) {
  5. if (arr == null || arr.length < 2) {
  6. return;
  7. }
  8. for (int e = arr.length - 1; e > 0; e--) {
  9. for (int i = 0; i < e; i++) {
  10. if (arr[i] > arr[i + 1]) {
  11. swap(arr, i, i + 1);
  12. }
  13. }
  14. }
  15. }
  16. public static void swap(int[] arr, int i, int j) {
  17. arr[i] = arr[i] ^ arr[j];
  18. arr[j] = arr[i] ^ arr[j];
  19. arr[i] = arr[i] ^ arr[j];
  20. }
  21. // for test
  22. public static void comparator(int[] arr) {
  23. Arrays.sort(arr);
  24. }
  25. // for test
  26. public static int[] generateRandomArray(int maxSize, int maxValue) {
  27. int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
  28. for (int i = 0; i < arr.length; i++) {
  29. arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
  30. }
  31. return arr;
  32. }
  33. // for test
  34. public static int[] copyArray(int[] arr) {
  35. if (arr == null) {
  36. return null;
  37. }
  38. int[] res = new int[arr.length];
  39. for (int i = 0; i < arr.length; i++) {
  40. res[i] = arr[i];
  41. }
  42. return res;
  43. }
  44. // for test
  45. public static boolean isEqual(int[] arr1, int[] arr2) {
  46. if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
  47. return false;
  48. }
  49. if (arr1 == null && arr2 == null) {
  50. return true;
  51. }
  52. if (arr1.length != arr2.length) {
  53. return false;
  54. }
  55. for (int i = 0; i < arr1.length; i++) {
  56. if (arr1[i] != arr2[i]) {
  57. return false;
  58. }
  59. }
  60. return true;
  61. }
  62. // for test
  63. public static void printArray(int[] arr) {
  64. if (arr == null) {
  65. return;
  66. }
  67. for (int i = 0; i < arr.length; i++) {
  68. System.out.print(arr[i] + " ");
  69. }
  70. System.out.println();
  71. }
  72. // for test
  73. public static void main(String[] args) {
  74. int testTime = 500000;
  75. int maxSize = 100;
  76. int maxValue = 100;
  77. boolean succeed = true;
  78. for (int i = 0; i < testTime; i++) {
  79. int[] arr1 = generateRandomArray(maxSize, maxValue);
  80. int[] arr2 = copyArray(arr1);
  81. bubbleSort(arr1);
  82. comparator(arr2);
  83. if (!isEqual(arr1, arr2)) {
  84. succeed = false;
  85. break;
  86. }
  87. }
  88. System.out.println(succeed ? "Nice!" : "Fucking fucked!");
  89. int[] arr = generateRandomArray(maxSize, maxValue);
  90. printArray(arr);
  91. bubbleSort(arr);
  92. printArray(arr);
  93. }
  94. }

插入排序

  1. package class01;
  2. import java.util.Arrays;
  3. public class Code03_InsertionSort {
  4. public static void insertionSort(int[] arr) {
  5. if (arr == null || arr.length < 2) {
  6. return;
  7. }
  8. for (int i = 1; i < arr.length; i++) {
  9. for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
  10. swap(arr, j, j + 1);
  11. }
  12. }
  13. }
  14. public static void swap(int[] arr, int i, int j) {
  15. arr[i] = arr[i] ^ arr[j];
  16. arr[j] = arr[i] ^ arr[j];
  17. arr[i] = arr[i] ^ arr[j];
  18. }
  19. // for test
  20. public static void comparator(int[] arr) {
  21. Arrays.sort(arr);
  22. }
  23. // for test
  24. public static int[] generateRandomArray(int maxSize, int maxValue) {
  25. int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
  26. for (int i = 0; i < arr.length; i++) {
  27. arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
  28. }
  29. return arr;
  30. }
  31. // for test
  32. public static int[] copyArray(int[] arr) {
  33. if (arr == null) {
  34. return null;
  35. }
  36. int[] res = new int[arr.length];
  37. for (int i = 0; i < arr.length; i++) {
  38. res[i] = arr[i];
  39. }
  40. return res;
  41. }
  42. // for test
  43. public static boolean isEqual(int[] arr1, int[] arr2) {
  44. if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
  45. return false;
  46. }
  47. if (arr1 == null && arr2 == null) {
  48. return true;
  49. }
  50. if (arr1.length != arr2.length) {
  51. return false;
  52. }
  53. for (int i = 0; i < arr1.length; i++) {
  54. if (arr1[i] != arr2[i]) {
  55. return false;
  56. }
  57. }
  58. return true;
  59. }
  60. // for test
  61. public static void printArray(int[] arr) {
  62. if (arr == null) {
  63. return;
  64. }
  65. for (int i = 0; i < arr.length; i++) {
  66. System.out.print(arr[i] + " ");
  67. }
  68. System.out.println();
  69. }
  70. // for test
  71. public static void main(String[] args) {
  72. int testTime = 500000;
  73. int maxSize = 100;
  74. int maxValue = 100;
  75. boolean succeed = true;
  76. for (int i = 0; i < testTime; i++) {
  77. int[] arr1 = generateRandomArray(maxSize, maxValue);
  78. int[] arr2 = copyArray(arr1);
  79. insertionSort(arr1);
  80. comparator(arr2);
  81. if (!isEqual(arr1, arr2)) {
  82. succeed = false;
  83. break;
  84. }
  85. }
  86. System.out.println(succeed ? "Nice!" : "Fucking fucked!");
  87. int[] arr = generateRandomArray(maxSize, maxValue);
  88. printArray(arr);
  89. insertionSort(arr);
  90. printArray(arr);
  91. }
  92. }

递归

求一个数组中最大的数
image.png
image.png

  1. package class01;
  2. public class Code08_GetMax {
  3. public static int getMax(int[] arr) {
  4. return process(arr, 0, arr.length - 1);
  5. }
  6. public static int process(int[] arr, int L, int R) {
  7. if (L == R) {
  8. return arr[L];
  9. }
  10. int mid = L + ((R - L) >> 1);
  11. int leftMax = process(arr, L, mid);
  12. int rightMax = process(arr, mid + 1, R);
  13. return Math.max(leftMax, rightMax);
  14. }
  15. }

归并排序

image.png
image.png

小和问题:
image.png

  1. public static int smallSum(int[] arr) {
  2. if (arr == null || arr.length < 2) {
  3. return 0;
  4. }
  5. return mergeSort(arr, 0, arr.length - 1);
  6. }
  7. public static int mergeSort(int[] arr, int l, int r) {
  8. if (l == r) {
  9. return 0;
  10. }
  11. int mid = l + ((r - l) >> 1);
  12. return mergeSort(arr, l, mid)
  13. + mergeSort(arr, mid + 1, r)
  14. + merge(arr, l, mid, r);
  15. }
  16. public static int merge(int[] arr, int l, int m, int r) {
  17. int[] help = new int[r - l + 1];
  18. int i = 0;
  19. int p1 = l;
  20. int p2 = m + 1;
  21. int res = 0;
  22. while (p1 <= m && p2 <= r) {
  23. res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
  24. help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
  25. }
  26. while (p1 <= m) {
  27. help[i++] = arr[p1++];
  28. }
  29. while (p2 <= r) {
  30. help[i++] = arr[p2++];
  31. }
  32. for (i = 0; i < help.length; i++) {
  33. arr[l + i] = help[i];
  34. }
  35. return res;
  36. }
  37. // for test
  38. public static int comparator(int[] arr) {
  39. if (arr == null || arr.length < 2) {
  40. return 0;
  41. }
  42. int res = 0;
  43. for (int i = 1; i < arr.length; i++) {
  44. for (int j = 0; j < i; j++) {
  45. res += arr[j] < arr[i] ? arr[j] : 0;
  46. }
  47. }
  48. return res;
  49. }
  50. // for test
  51. public static int[] generateRandomArray(int maxSize, int maxValue) {
  52. int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
  53. for (int i = 0; i < arr.length; i++) {
  54. arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
  55. }
  56. return arr;
  57. }
  58. // for test
  59. public static int[] copyArray(int[] arr) {
  60. if (arr == null) {
  61. return null;
  62. }
  63. int[] res = new int[arr.length];
  64. for (int i = 0; i < arr.length; i++) {
  65. res[i] = arr[i];
  66. }
  67. return res;
  68. }
  69. // for test
  70. public static boolean isEqual(int[] arr1, int[] arr2) {
  71. if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
  72. return false;
  73. }
  74. if (arr1 == null && arr2 == null) {
  75. return true;
  76. }
  77. if (arr1.length != arr2.length) {
  78. return false;
  79. }
  80. for (int i = 0; i < arr1.length; i++) {
  81. if (arr1[i] != arr2[i]) {
  82. return false;
  83. }
  84. }
  85. return true;
  86. }
  87. // for test
  88. public static void printArray(int[] arr) {
  89. if (arr == null) {
  90. return;
  91. }
  92. for (int i = 0; i < arr.length; i++) {
  93. System.out.print(arr[i] + " ");
  94. }
  95. System.out.println();
  96. }
  97. // for test
  98. public static void main(String[] args) {
  99. int testTime = 500000;
  100. int maxSize = 100;
  101. int maxValue = 100;
  102. boolean succeed = true;
  103. for (int i = 0; i < testTime; i++) {
  104. int[] arr1 = generateRandomArray(maxSize, maxValue);
  105. int[] arr2 = copyArray(arr1);
  106. if (smallSum(arr1) != comparator(arr2)) {
  107. succeed = false;
  108. printArray(arr1);
  109. printArray(arr2);
  110. break;
  111. }
  112. }
  113. System.out.println(succeed ? "Nice!" : "Fucking fucked!");
  114. }

逆序对问题,和求小和问题类似,只不过是变成小于的关系

  1. public static int versePairs(int[] arr){
  2. if(arr==null||arr.lenth==1){
  3. return 0;
  4. }
  5. return process(arr,0,arr.length-1);
  6. }
  7. public static int process(int[] arr, int l, int r){
  8. if(l==r){
  9. return 0;
  10. }
  11. int mid = l + (r - l) >> 1;
  12. return process(arr, l, mid)
  13. +process(arr, mid+1, r)
  14. +merge(arr, l, mid, r);
  15. }
  16. public static int merge(int[] arr, int l, int mid, int r){
  17. int[] help = new int[r-l+1];
  18. int i = 0;
  19. int p1 = l;
  20. int p2 = mid + 1;
  21. int res = 0;
  22. while(p1<=mid && p2<=r){
  23. res += arr[p1]>arr[p2] ? 1:0;
  24. help[i++] = arr[p1]<arr[p2] ? arr[p1++] : arr[p2++];
  25. }
  26. while(p1<=mid){
  27. help[i++] = arr[p1++];
  28. }
  29. while(p2<=r){
  30. help[i++] = arr[p2++];
  31. }
  32. for(int i=0;i<help.length;i++){
  33. arr[l+i]=help[i];
  34. }
  35. return res;
  36. }

荷兰国旗问题(快速排序)

image.png
问题一:
image.png
问题二:
image.png
image.png

  1. package class02;
  2. import java.util.Arrays;
  3. public class Code06_QuickSort {
  4. public static void quickSort(int[] arr) {
  5. if (arr == null || arr.length < 2) {
  6. return;
  7. }
  8. quickSort(arr, 0, arr.length - 1);
  9. }
  10. public static void quickSort(int[] arr, int l, int r) {
  11. if (l < r) {
  12. swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
  13. int[] p = partition(arr, l, r);
  14. quickSort(arr, l, p[0] - 1);
  15. quickSort(arr, p[1] + 1, r);
  16. }
  17. }
  18. public static int[] partition(int[] arr, int l, int r) {
  19. int less = l - 1;
  20. int more = r;
  21. while (l < more) {
  22. if (arr[l] < arr[r]) {
  23. swap(arr, ++less, l++);
  24. } else if (arr[l] > arr[r]) {
  25. swap(arr, --more, l);
  26. } else {
  27. l++;
  28. }
  29. }
  30. swap(arr, more, r);
  31. return new int[] { less + 1, more };
  32. }
  33. public static void swap(int[] arr, int i, int j) {
  34. int tmp = arr[i];
  35. arr[i] = arr[j];
  36. arr[j] = tmp;
  37. }
  38. // for test
  39. public static void comparator(int[] arr) {
  40. Arrays.sort(arr);
  41. }
  42. // for test
  43. public static int[] generateRandomArray(int maxSize, int maxValue) {
  44. int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
  45. for (int i = 0; i < arr.length; i++) {
  46. arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
  47. }
  48. return arr;
  49. }
  50. // for test
  51. public static int[] copyArray(int[] arr) {
  52. if (arr == null) {
  53. return null;
  54. }
  55. int[] res = new int[arr.length];
  56. for (int i = 0; i < arr.length; i++) {
  57. res[i] = arr[i];
  58. }
  59. return res;
  60. }
  61. // for test
  62. public static boolean isEqual(int[] arr1, int[] arr2) {
  63. if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
  64. return false;
  65. }
  66. if (arr1 == null && arr2 == null) {
  67. return true;
  68. }
  69. if (arr1.length != arr2.length) {
  70. return false;
  71. }
  72. for (int i = 0; i < arr1.length; i++) {
  73. if (arr1[i] != arr2[i]) {
  74. return false;
  75. }
  76. }
  77. return true;
  78. }
  79. // for test
  80. public static void printArray(int[] arr) {
  81. if (arr == null) {
  82. return;
  83. }
  84. for (int i = 0; i < arr.length; i++) {
  85. System.out.print(arr[i] + " ");
  86. }
  87. System.out.println();
  88. }
  89. // for test
  90. public static void main(String[] args) {
  91. int testTime = 500000;
  92. int maxSize = 100;
  93. int maxValue = 100;
  94. boolean succeed = true;
  95. for (int i = 0; i < testTime; i++) {
  96. int[] arr1 = generateRandomArray(maxSize, maxValue);
  97. int[] arr2 = copyArray(arr1);
  98. quickSort(arr1);
  99. comparator(arr2);
  100. if (!isEqual(arr1, arr2)) {
  101. succeed = false;
  102. printArray(arr1);
  103. printArray(arr2);
  104. break;
  105. }
  106. }
  107. System.out.println(succeed ? "Nice!" : "Fucking fucked!");
  108. int[] arr = generateRandomArray(maxSize, maxValue);
  109. printArray(arr);
  110. quickSort(arr);
  111. printArray(arr);
  112. }
  113. }

image.png

image.png

  1. package class02;
  2. import java.util.Arrays;
  3. public class Code03_HeapSort {
  4. public static void heapSort(int[] arr) {
  5. if (arr == null || arr.length < 2) {
  6. return;
  7. }
  8. //for (int i = 0; i < arr.length; i++) { //O(NlogN)
  9. // heapInsert(arr, i);
  10. //}
  11. for(int i=arr.length-1; i>=0; i--){ //O(N)
  12. heapifer(arr,i,arr.length);
  13. }
  14. int size = arr.length;
  15. swap(arr, 0, --size);
  16. while (size > 0) {
  17. heapify(arr, 0, size);
  18. swap(arr, 0, --size);
  19. }
  20. }
  21. public static void heapInsert(int[] arr, int index) {
  22. while (arr[index] > arr[(index - 1) / 2]) {
  23. swap(arr, index, (index - 1) /2);
  24. index = (index - 1)/2 ;
  25. }
  26. }
  27. public static void heapify(int[] arr, int index, int size) {
  28. int left = index * 2 + 1;
  29. while (left < size) {
  30. int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
  31. largest = arr[largest] > arr[index] ? largest : index;
  32. if (largest == index) {
  33. break;
  34. }
  35. swap(arr, largest, index);
  36. index = largest;
  37. left = index * 2 + 1;
  38. }
  39. }
  40. public static void swap(int[] arr, int i, int j) {
  41. int tmp = arr[i];
  42. arr[i] = arr[j];
  43. arr[j] = tmp;
  44. }
  45. // for test
  46. public static void comparator(int[] arr) {
  47. Arrays.sort(arr);
  48. }
  49. // for test
  50. public static int[] generateRandomArray(int maxSize, int maxValue) {
  51. int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
  52. for (int i = 0; i < arr.length; i++) {
  53. arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
  54. }
  55. return arr;
  56. }
  57. // for test
  58. public static int[] copyArray(int[] arr) {
  59. if (arr == null) {
  60. return null;
  61. }
  62. int[] res = new int[arr.length];
  63. for (int i = 0; i < arr.length; i++) {
  64. res[i] = arr[i];
  65. }
  66. return res;
  67. }
  68. // for test
  69. public static boolean isEqual(int[] arr1, int[] arr2) {
  70. if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
  71. return false;
  72. }
  73. if (arr1 == null && arr2 == null) {
  74. return true;
  75. }
  76. if (arr1.length != arr2.length) {
  77. return false;
  78. }
  79. for (int i = 0; i < arr1.length; i++) {
  80. if (arr1[i] != arr2[i]) {
  81. return false;
  82. }
  83. }
  84. return true;
  85. }
  86. // for test
  87. public static void printArray(int[] arr) {
  88. if (arr == null) {
  89. return;
  90. }
  91. for (int i = 0; i < arr.length; i++) {
  92. System.out.print(arr[i] + " ");
  93. }
  94. System.out.println();
  95. }
  96. // for test
  97. public static void main(String[] args) {
  98. int testTime = 500000;
  99. int maxSize = 100;
  100. int maxValue = 100;
  101. boolean succeed = true;
  102. for (int i = 0; i < testTime; i++) {
  103. int[] arr1 = generateRandomArray(maxSize, maxValue);
  104. int[] arr2 = copyArray(arr1);
  105. heapSort(arr1);
  106. comparator(arr2);
  107. if (!isEqual(arr1, arr2)) {
  108. succeed = false;
  109. break;
  110. }
  111. }
  112. System.out.println(succeed ? "Nice!" : "Fucking fucked!");
  113. int[] arr = generateRandomArray(maxSize, maxValue);
  114. printArray(arr);
  115. heapSort(arr);
  116. printArray(arr);
  117. }
  118. }

heapfy构建大顶堆的时间负责度:
image.png
image.png

  1. package class02;
  2. import java.util.PriorityQueue;
  3. public class Code04_SortArrayDistanceLessK {
  4. public void sortedArrDistanceLessK(int[] arr, int k) {
  5. //java实现小根堆,但如果java提供的小根堆满足不了题目的高效需求,需要自己手写
  6. PriorityQueue<Integer> heap = new PriorityQueue<>();
  7. int index = 0;
  8. for (; index <= Math.min(arr.length, k); index++) {
  9. heap.add(arr[index]);
  10. }
  11. int i = 0;
  12. for (; index < arr.length; i++, index++) {
  13. heap.add(arr[index]);
  14. arr[i] = heap.poll();
  15. }
  16. while (!heap.isEmpty()) {
  17. arr[i++] = heap.poll();
  18. }
  19. }
  20. }

比较器

image.png

桶排序

image.png

  1. package class03;
  2. import java.util.Arrays;
  3. public class Code01_CountSort {
  4. // only for 0~200 value
  5. public static void countSort(int[] arr) {
  6. if (arr == null || arr.length < 2) {
  7. return;
  8. }
  9. int max = Integer.MIN_VALUE;
  10. for (int i = 0; i < arr.length; i++) {
  11. max = Math.max(max, arr[i]);
  12. }
  13. int[] bucket = new int[max + 1];
  14. for (int i = 0; i < arr.length; i++) {
  15. bucket[arr[i]]++;
  16. }
  17. int i = 0;
  18. for (int j = 0; j < bucket.length; j++) {
  19. while (bucket[j]-- > 0) {
  20. arr[i++] = j;
  21. }
  22. }
  23. }
  24. // for test
  25. public static void comparator(int[] arr) {
  26. Arrays.sort(arr);
  27. }
  28. // for test
  29. public static int[] generateRandomArray(int maxSize, int maxValue) {
  30. int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
  31. for (int i = 0; i < arr.length; i++) {
  32. arr[i] = (int) ((maxValue + 1) * Math.random());
  33. }
  34. return arr;
  35. }
  36. // for test
  37. public static int[] copyArray(int[] arr) {
  38. if (arr == null) {
  39. return null;
  40. }
  41. int[] res = new int[arr.length];
  42. for (int i = 0; i < arr.length; i++) {
  43. res[i] = arr[i];
  44. }
  45. return res;
  46. }
  47. // for test
  48. public static boolean isEqual(int[] arr1, int[] arr2) {
  49. if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
  50. return false;
  51. }
  52. if (arr1 == null && arr2 == null) {
  53. return true;
  54. }
  55. if (arr1.length != arr2.length) {
  56. return false;
  57. }
  58. for (int i = 0; i < arr1.length; i++) {
  59. if (arr1[i] != arr2[i]) {
  60. return false;
  61. }
  62. }
  63. return true;
  64. }
  65. // for test
  66. public static void printArray(int[] arr) {
  67. if (arr == null) {
  68. return;
  69. }
  70. for (int i = 0; i < arr.length; i++) {
  71. System.out.print(arr[i] + " ");
  72. }
  73. System.out.println();
  74. }
  75. // for test
  76. public static void main(String[] args) {
  77. int testTime = 500000;
  78. int maxSize = 100;
  79. int maxValue = 150;
  80. boolean succeed = true;
  81. for (int i = 0; i < testTime; i++) {
  82. int[] arr1 = generateRandomArray(maxSize, maxValue);
  83. int[] arr2 = copyArray(arr1);
  84. countSort(arr1);
  85. comparator(arr2);
  86. if (!isEqual(arr1, arr2)) {
  87. succeed = false;
  88. printArray(arr1);
  89. printArray(arr2);
  90. break;
  91. }
  92. }
  93. System.out.println(succeed ? "Nice!" : "Fucking fucked!");
  94. int[] arr = generateRandomArray(maxSize, maxValue);
  95. printArray(arr);
  96. countSort(arr);
  97. printArray(arr);
  98. }
  99. }
package class03;

import java.util.Arrays;

public class Code02_RadixSort {

    // only for no-negative value
    public static void radixSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        radixSort(arr, 0, arr.length - 1, maxbits(arr));
    }

    public static int maxbits(int[] arr) {
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < arr.length; i++) {
            max = Math.max(max, arr[i]);
        }
        int res = 0;
        while (max != 0) {
            res++;
            max /= 10;
        }
        return res;
    }

    public static void radixSort(int[] arr, int begin, int end, int digit) {
        final int radix = 10;
        int i = 0, j = 0;

        int[] bucket = new int[end - begin + 1];
        for (int d = 1; d <= digit; d++) {
            int[] count = new int[radix];
            for (i = begin; i <= end; i++) {
                j = getDigit(arr[i], d);
                count[j]++;
            }
            for (i = 1; i < radix; i++) {
                count[i] = count[i] + count[i - 1];
            }
            for (i = end; i >= begin; i--) {
                j = getDigit(arr[i], d);
                bucket[count[j] - 1] = arr[i];
                count[j]--;
            }
            for (i = begin, j = 0; i <= end; i++, j++) {
                arr[i] = bucket[j];
            }
        }
    }

    public static int getDigit(int x, int d) {
        return ((x / ((int) Math.pow(10, d - 1))) % 10);
    }

    // for test
    public static void comparator(int[] arr) {
        Arrays.sort(arr);
    }

    // for test
    public static int[] generateRandomArray(int maxSize, int maxValue) {
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) ((maxValue + 1) * Math.random());
        }
        return arr;
    }

    // for test
    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    // for test
    public static boolean isEqual(int[] arr1, int[] arr2) {
        if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
            return false;
        }
        if (arr1 == null && arr2 == null) {
            return true;
        }
        if (arr1.length != arr2.length) {
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    // for test
    public static void printArray(int[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    // for test
    public static void main(String[] args) {
        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100000;
        boolean succeed = true;
        for (int i = 0; i < testTime; i++) {
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            int[] arr2 = copyArray(arr1);
            radixSort(arr1);
            comparator(arr2);
            if (!isEqual(arr1, arr2)) {
                succeed = false;
                printArray(arr1);
                printArray(arr2);
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");

        int[] arr = generateRandomArray(maxSize, maxValue);
        printArray(arr);
        radixSort(arr);
        printArray(arr);

    }

}

排序的稳定性

排序算法稳定性:意思就是说大小相同的两个值在排序之前和排序之后的先后顺序不变,这就是稳定的。

(1)冒泡排序:原理是通过相邻的两个元素作比较,把小的向前移或者把大的向后移,移动就是交换这两个元素。如果说碰到相等的两个元素是不会做处理的。所以是稳定的排序。

(2)选择排序:原理是从第一个元素开始,在之后的所有元素中选择一个最小的交换过来。如果说原序列中第一个元素和第二个元素相等,第三个元素是个最小值,经过选择会把第一个元素和第三个元素交换,这时第二个元素就跑到前面去了。如:3,3,1序列,经过选择排序会变成1,3,3。所以是不稳定的排序。

(3)插入排序:原理是从第二个元素开始,和前面的所有元素作比较,如果比前面元素最大的(也就是前面元素的最后一个)大,直接插入在前面元素的最后面(也就是保持自身位置不变,再取它的下一个元素开始);如果比前面元素最大的小,就和第二大的作比较,以此找到自己的位置;如果在前面找到了和自己大小相等的值,就乖乖的插入后面,如:1,2,3,2,最后一个元素2先和3作比较,嗯比3小,再和2作比较,嗯相等,插入后就变成1,2,2,3,所以是稳定的排序。

(4)快速排序:原理是(最简便的操作)以第一个元素为基准,在后面的所有元素中进行前后夹击,从开头可末尾一个一个取元素和基准作比较,前面进攻的遇到比基准大的停下来,后面进攻的遇到比基准小的停下来,这时候,如果前面的还在前面,后面的还在后面,基准原地不动,交换这两个被攻击到的元素;如果前面进攻的和后面进攻的攻击的是同一个元素或前面进攻的攻到了后方友军的身后,就把后方友军进攻的元素和基准作交换,并以基准当前的位置断开,基准休息,前面的序列和后面的序列再打一遍,打到只剩一个敌人。(跑题了么?)如:2,2,3,2为基准,这时索引会在2的位置停下来,很无奈,只能交换2和2变成:2,2,3了。所以是不稳定的排序。

(5)归并排序:原理是通过递归法,把序列A切半分成A1和A2,再把A1和A2的每个元素互相比较取较小的依次放回A中。递归就是把序列无限切半,切到只有一个元素为止,再一点一点的拼回去。由于比较是发生在拼回去的时候,在比较时,前面的序列还是在前如 if(A1[0]<=A2[0]),遇到相等的值也是取A1中的元素先放入A中,所以是稳定的排序。(如果你非要比较时写成 if(A1[0]<A2[0])那就是不稳定的了,相等的时候会取A2中的元素,不过这就是你故意的了)

(6)基数排序:原理是(1-低位优先)新建10个序列组成数组,先通过个位数字将序列元素依次放到对应索引的新序列中,如:个位是0,就放到数组索引为0的新序列中,再从数组的序列中以索引从小到大的顺序依次取出元素放回原序列,再通过十位数字的大小整理一遍,以此类推,最终得到有序序列。(2-高位优先)新建10个序列组成数组,以最高位的数字为基准依次放入对应数组索引的序列中,如果序列中元素个数大于1或不相等,再建10个序列组成数组,以当前位的次一位数字为基准放入数组序列中,最后从低位数组开始取出放回原序列,最终得到有序序列。由于相等的元素各个位上的数字也相等,所以在经过依次放入和依次取出的过程顺序是不发生改变的。所以是稳定的排序。

(7)希尔排序:原理是在插入排序的基础上,取序列长度的一半为一个增量进行间隔式的插入排序,这个增量会在进行完插入排序后再次减半,直到减至1。插入排序是稳定的,但是当增量不同时,相当于将序列间隔的分成不同的序列进行插入排序,两个序列中的相等的元素就可能会被打乱位置。如:3,4,5,2,2,该序列长度为5,取一半是2,以2为增量进行插入排序会把序列分成4,2以及3,5,2,当然索引位置不变,进行插入排序会得到2,4以及2,3,5,还原会序列就是2,2,3,4,5。所以是不稳定的排序。

(8)堆排序:原理是把序列看成是完全二叉树,通过重复构造大顶堆或小顶堆来实现,每次构造完成会将最上面的节点取出,其余的节点再次构造成堆。如:

image.png

所以是不稳定的排序。

总结:不稳定的排序:堆排序,快速排序,希尔排序,选择排序。

       稳定的排序:冒泡排序,插入排序,归并排序,基数排序。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/217254/1652842354142-26e326ea-64ce-4735-8f61-53bc5b7bf1de.png#clientId=u3f0a4901-1e8e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=517&id=u5334964a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1034&originWidth=1434&originalType=binary&ratio=1&rotation=0&showTitle=false&size=451587&status=done&style=none&taskId=u328155ea-ceef-4251-82b5-cbe25d9134e&title=&width=717)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/217254/1652842607885-e8752057-15e2-451e-86a0-bc87760d5c71.png#clientId=u3f0a4901-1e8e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=305&id=ue4c2fccb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=610&originWidth=1582&originalType=binary&ratio=1&rotation=0&showTitle=false&size=543989&status=done&style=none&taskId=u71e3b6a7-bc44-4c13-82ea-cf2a96c924f&title=&width=791)<br />解答5:快排可以通过partition来把大于某数和不大于的分开,同样也能把奇数和偶数分开,这种0 1问题快排可以做到时间复杂度O(NlogN),空间复杂度O(1),但是不稳定。

image.png
例如:
image.png

哈希表

image.png

有序表

image.png
image.png

链表

image.png
image.png
image.png
image.png

package class04;

import java.util.Stack;

public class Code04_IsPalindromeList {

    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }

    // need n extra space
    public static boolean isPalindrome1(Node head) {
        Stack<Node> stack = new Stack<Node>();
        Node cur = head;
        while (cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        while (head != null) {
            if (head.value != stack.pop().value) {
                return false;
            }
            head = head.next;
        }
        return true;
    }

    // need n/2 extra space
    public static boolean isPalindrome2(Node head) {
        if (head == null || head.next == null) {
            return true;
        }
        Node right = head.next;
        Node cur = head;
        while (cur.next != null && cur.next.next != null) {
            right = right.next;
            cur = cur.next.next;
        }
        Stack<Node> stack = new Stack<Node>();
        while (right != null) {
            stack.push(right);
            right = right.next;
        }
        while (!stack.isEmpty()) {
            if (head.value != stack.pop().value) {
                return false;
            }
            head = head.next;
        }
        return true;
    }

    // need O(1) extra space
    public static boolean isPalindrome3(Node head) {
        if (head == null || head.next == null) {
            return true;
        }
        Node n1 = head;
        Node n2 = head;
        while (n2.next != null && n2.next.next != null) { // find mid node
            n1 = n1.next; // n1 -> mid
            n2 = n2.next.next; // n2 -> end
        }
        n2 = n1.next; // n2 -> right part first node
        n1.next = null; // mid.next -> null
        Node n3 = null;
        while (n2 != null) { // right part convert
            n3 = n2.next; // n3 -> save next node
            n2.next = n1; // next of right node convert
            n1 = n2; // n1 move
            n2 = n3; // n2 move
        }
        n3 = n1; // n3 -> save last node
        n2 = head;// n2 -> left first node
        boolean res = true;
        while (n1 != null && n2 != null) { // check palindrome
            if (n1.value != n2.value) {
                res = false;
                break;
            }
            n1 = n1.next; // left to mid
            n2 = n2.next; // right to mid
        }
        n1 = n3.next;
        n3.next = null;
        while (n1 != null) { // recover list
            n2 = n1.next;
            n1.next = n3;
            n3 = n1;
            n1 = n2;
        }
        return res;
    }

    public static void printLinkedList(Node node) {
        System.out.print("Linked List: ");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {

        Node head = null;
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(2);
        head.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(2);
        head.next.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

    }

}

image.png
image.png
image.png

package class04;

public class Code05_SmallerEqualBigger {

    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }

    public static Node listPartition1(Node head, int pivot) {
        if (head == null) {
            return head;
        }
        Node cur = head;
        int i = 0;
        while (cur != null) {
            i++;
            cur = cur.next;
        }
        Node[] nodeArr = new Node[i];
        i = 0;
        cur = head;
        for (i = 0; i != nodeArr.length; i++) {
            nodeArr[i] = cur;
            cur = cur.next;
        }
        arrPartition(nodeArr, pivot);
        for (i = 1; i != nodeArr.length; i++) {
            nodeArr[i - 1].next = nodeArr[i];
        }
        nodeArr[i - 1].next = null;
        return nodeArr[0];
    }

    public static void arrPartition(Node[] nodeArr, int pivot) {
        int small = -1;
        int big = nodeArr.length;
        int index = 0;
        while (index != big) {
            if (nodeArr[index].value < pivot) {
                swap(nodeArr, ++small, index++);
            } else if (nodeArr[index].value == pivot) {
                index++;
            } else {
                swap(nodeArr, --big, index);
            }
        }
    }

    public static void swap(Node[] nodeArr, int a, int b) {
        Node tmp = nodeArr[a];
        nodeArr[a] = nodeArr[b];
        nodeArr[b] = tmp;
    }

    public static Node listPartition2(Node head, int pivot) {
        Node sH = null; // small head
        Node sT = null; // small tail
        Node eH = null; // equal head
        Node eT = null; // equal tail
        Node bH = null; // big head
        Node bT = null; // big tail
        Node next = null; // save next node
        // every node distributed to three lists
        while (head != null) {
            next = head.next;
            head.next = null;
            if (head.value < pivot) {
                if (sH == null) {
                    sH = head;
                    sT = head;
                } else {
                    sT.next = head;
                    sT = head;
                }
            } else if (head.value == pivot) {
                if (eH == null) {
                    eH = head;
                    eT = head;
                } else {
                    eT.next = head;
                    eT = head;
                }
            } else {
                if (bH == null) {
                    bH = head;
                    bT = head;
                } else {
                    bT.next = head;
                    bT = head;
                }
            }
            head = next;
        }
        // small and equal reconnect
        if (sT != null) {
            sT.next = eH;
            eT = eT == null ? sT : eT;
        }
        // all reconnect
        if (eT != null) {
            eT.next = bH;
        }
        return sH != null ? sH : eH != null ? eH : bH;
    }

    public static void printLinkedList(Node node) {
        System.out.print("Linked List: ");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head1 = new Node(7);
        head1.next = new Node(9);
        head1.next.next = new Node(1);
        head1.next.next.next = new Node(8);
        head1.next.next.next.next = new Node(5);
        head1.next.next.next.next.next = new Node(2);
        head1.next.next.next.next.next.next = new Node(5);
        printLinkedList(head1);
        // head1 = listPartition1(head1, 4);
        head1 = listPartition2(head1, 5);
        printLinkedList(head1);

    }

}

image.png

package class04;

import java.util.HashMap;

public class Code06_CopyListWithRandom {

    public static class Node {
        public int value;
        public Node next;
        public Node rand;

        public Node(int data) {
            this.value = data;
        }
    }

    public static Node copyListWithRand1(Node head) {
        HashMap<Node, Node> map = new HashMap<Node, Node>();
        Node cur = head;
        while (cur != null) {
            map.put(cur, new Node(cur.value));
            cur = cur.next;
        }
        cur = head;
        while (cur != null) {
            map.get(cur).next = map.get(cur.next);
            map.get(cur).rand = map.get(cur.rand);
            cur = cur.next;
        }
        return map.get(head);
    }

    public static Node copyListWithRand2(Node head) {
        if (head == null) {
            return null;
        }
        Node cur = head;
        Node next = null;
        // copy node and link to every node
        while (cur != null) {
            next = cur.next;
            cur.next = new Node(cur.value);
            cur.next.next = next;
            cur = next;
        }
        cur = head;
        Node curCopy = null;
        // set copy node rand
        while (cur != null) {
            next = cur.next.next;
            curCopy = cur.next;
            curCopy.rand = cur.rand != null ? cur.rand.next : null;
            cur = next;
        }
        Node res = head.next;
        cur = head;
        // split
        while (cur != null) {
            next = cur.next.next;
            curCopy = cur.next;
            cur.next = next;
            curCopy.next = next != null ? next.next : null;
            cur = next;
        }
        return res;
    }

    public static void printRandLinkedList(Node head) {
        Node cur = head;
        System.out.print("order: ");
        while (cur != null) {
            System.out.print(cur.value + " ");
            cur = cur.next;
        }
        System.out.println();
        cur = head;
        System.out.print("rand:  ");
        while (cur != null) {
            System.out.print(cur.rand == null ? "- " : cur.rand.value + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = null;
        Node res1 = null;
        Node res2 = null;
        printRandLinkedList(head);
        res1 = copyListWithRand1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRand2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(4);
        head.next.next.next.next = new Node(5);
        head.next.next.next.next.next = new Node(6);

        head.rand = head.next.next.next.next.next; // 1 -> 6
        head.next.rand = head.next.next.next.next.next; // 2 -> 6
        head.next.next.rand = head.next.next.next.next; // 3 -> 5
        head.next.next.next.rand = head.next.next; // 4 -> 3
        head.next.next.next.next.rand = null; // 5 -> null
        head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4

        printRandLinkedList(head);
        res1 = copyListWithRand1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRand2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");

    }

}

image.png

package class04;

public class Code07_FindFirstIntersectNode {

    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }

    public static Node getIntersectNode(Node head1, Node head2) {
        if (head1 == null || head2 == null) {
            return null;
        }
        Node loop1 = getLoopNode(head1);
        Node loop2 = getLoopNode(head2);
        if (loop1 == null && loop2 == null) {
            return noLoop(head1, head2);
        }
        if (loop1 != null && loop2 != null) {
            return bothLoop(head1, loop1, head2, loop2);
        }
        return null;
    }

    public static Node getLoopNode(Node head) {
        if (head == null || head.next == null || head.next.next == null) {
            return null;
        }
        Node n1 = head.next; // n1 -> slow
        Node n2 = head.next.next; // n2 -> fast
        while (n1 != n2) {
            if (n2.next == null || n2.next.next == null) {
                return null;
            }
            n2 = n2.next.next;
            n1 = n1.next;
        }
        n2 = head; // n2 -> walk again from head
        while (n1 != n2) {
            n1 = n1.next;
            n2 = n2.next;
        }
        return n1;
    }

    public static Node noLoop(Node head1, Node head2) {
        if (head1 == null || head2 == null) {
            return null;
        }
        Node cur1 = head1;
        Node cur2 = head2;
        int n = 0;
        while (cur1.next != null) {
            n++;
            cur1 = cur1.next;
        }
        while (cur2.next != null) {
            n--;
            cur2 = cur2.next;
        }
        if (cur1 != cur2) {  //如果两个链表的尾指针不相等,两条链表不相交
            return null;
        }
        //那个链表更长就把它给cur1,更短的给cur2
        cur1 = n > 0 ? head1 : head2;  
        cur2 = cur1 == head1 ? head2 : head1;
        n = Math.abs(n);
        while (n != 0) {
            n--;
            cur1 = cur1.next;
        }
        while (cur1 != cur2) {
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        return cur1;
    }

    //两个有环链表,返回第一个相交节点,如果不相交返回Null
    public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) {
        Node cur1 = null;
        Node cur2 = null;
        if (loop1 == loop2) {
            cur1 = head1;
            cur2 = head2;
            int n = 0;
            while (cur1 != loop1) {
                n++;
                cur1 = cur1.next;
            }
            while (cur2 != loop2) {
                n--;
                cur2 = cur2.next;
            }
            cur1 = n > 0 ? head1 : head2;
            cur2 = cur1 == head1 ? head2 : head1;
            n = Math.abs(n);
            while (n != 0) {
                n--;
                cur1 = cur1.next;
            }
            while (cur1 != cur2) {
                cur1 = cur1.next;
                cur2 = cur2.next;
            }
            return cur1;
        } else {
            cur1 = loop1.next;
            while (cur1 != loop1) {
                if (cur1 == loop2) {
                    //返回loop1或loop2都可以
                    return loop1;
                }
                cur1 = cur1.next;
            }
            //如果cur1在loop1环上走一圈都还没有与loop2相交,则两条有环链表不相交 
            return null;
        }
    }

    public static void main(String[] args) {
        // 1->2->3->4->5->6->7->null
        Node head1 = new Node(1);
        head1.next = new Node(2);
        head1.next.next = new Node(3);
        head1.next.next.next = new Node(4);
        head1.next.next.next.next = new Node(5);
        head1.next.next.next.next.next = new Node(6);
        head1.next.next.next.next.next.next = new Node(7);

        // 0->9->8->6->7->null
        Node head2 = new Node(0);
        head2.next = new Node(9);
        head2.next.next = new Node(8);
        head2.next.next.next = head1.next.next.next.next.next; // 8->6
        System.out.println(getIntersectNode(head1, head2).value);

        // 1->2->3->4->5->6->7->4...
        head1 = new Node(1);
        head1.next = new Node(2);
        head1.next.next = new Node(3);
        head1.next.next.next = new Node(4);
        head1.next.next.next.next = new Node(5);
        head1.next.next.next.next.next = new Node(6);
        head1.next.next.next.next.next.next = new Node(7);
        head1.next.next.next.next.next.next = head1.next.next.next; // 7->4

        // 0->9->8->2...
        head2 = new Node(0);
        head2.next = new Node(9);
        head2.next.next = new Node(8);
        head2.next.next.next = head1.next; // 8->2
        System.out.println(getIntersectNode(head1, head2).value);

        // 0->9->8->6->4->5->6..
        head2 = new Node(0);
        head2.next = new Node(9);
        head2.next.next = new Node(8);
        head2.next.next.next = head1.next.next.next.next.next; // 8->6
        System.out.println(getIntersectNode(head1, head2).value);

    }

}

二叉树

image.png

package class05;

import java.util.Stack;

public class Code01_PreInPosTraversal {

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    public static void preOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value + " ");
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }

    public static void inOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        inOrderRecur(head.left);
        System.out.print(head.value + " ");
        inOrderRecur(head.right);
    }

    public static void posOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        posOrderRecur(head.left);
        posOrderRecur(head.right);
        System.out.print(head.value + " ");
    }

    public static void preOrderUnRecur(Node head) {
        System.out.print("pre-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.add(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                System.out.print(head.value + " ");
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
        System.out.println();
    }

    public static void inOrderUnRecur(Node head) {
        System.out.print("in-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                } else {
                    head = stack.pop();
                    System.out.print(head.value + " ");
                    head = head.right;
                }
            }
        }
        System.out.println();
    }

    public static void posOrderUnRecur1(Node head) {
        System.out.print("pos-order: ");
        if (head != null) {
            Stack<Node> s1 = new Stack<Node>();
            Stack<Node> s2 = new Stack<Node>();
            s1.push(head);
            while (!s1.isEmpty()) {
                head = s1.pop();
                s2.push(head);
                if (head.left != null) {
                    s1.push(head.left);
                }
                if (head.right != null) {
                    s1.push(head.right);
                }
            }
            while (!s2.isEmpty()) {
                System.out.print(s2.pop().value + " ");
            }
        }
        System.out.println();
    }

    public static void posOrderUnRecur2(Node h) {
        System.out.print("pos-order: ");
        if (h != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.push(h);
            Node c = null;
            while (!stack.isEmpty()) {
                c = stack.peek();
                if (c.left != null && h != c.left && h != c.right) {
                    stack.push(c.left);
                } else if (c.right != null && h != c.right) {
                    stack.push(c.right);
                } else {
                    System.out.print(stack.pop().value + " ");
                    h = c;
                }
            }
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = new Node(5);
        head.left = new Node(3);
        head.right = new Node(8);
        head.left.left = new Node(2);
        head.left.right = new Node(4);
        head.left.left.left = new Node(1);
        head.right.left = new Node(7);
        head.right.left.left = new Node(6);
        head.right.right = new Node(10);
        head.right.right.left = new Node(9);
        head.right.right.right = new Node(11);

        // recursive
        System.out.println("==============recursive==============");
        System.out.print("pre-order: ");
        preOrderRecur(head);
        System.out.println();
        System.out.print("in-order: ");
        inOrderRecur(head);
        System.out.println();
        System.out.print("pos-order: ");
        posOrderRecur(head);
        System.out.println();

        // unrecursive
        System.out.println("============unrecursive=============");
        preOrderUnRecur(head);
        inOrderUnRecur(head);
        posOrderUnRecur1(head);
        posOrderUnRecur2(head);

    }

}