查找算法

性能优化小案例1.二分法查找

image.pngimage.png

  1. public static int find(int[] array, int aim) {
  2. for (int i = 0; i < array.length; i++) {
  3. if (aim == array[i]) {
  4. return i;
  5. }
  6. }
  7. return -1;
  8. }

image.png
image.png
image.png

  1. public static int find(int[] array, int aim) {
  2. // 初始化left = 最左侧, right = 最右侧
  3. int left = 0;
  4. int right = array.length - 1;
  5. // 当left > right则表示遍历完成
  6. while (left <= right) {
  7. // 获取中间的值
  8. int middle = (left + right) / 2;
  9. int middleValue = array[middle];
  10. if (middleValue == aim) {
  11. // 已经找到目标
  12. return middle;
  13. } else if (middleValue < aim) {
  14. // 目标在middle的右侧,重置left
  15. left = middle + 1;
  16. } else {
  17. // 目标在middle的左侧,重置right
  18. right = middle - 1;
  19. }
  20. }
  21. return -1;
  22. }

image.png

练习:利用二分法查找降序排列数组的某个值

  1. public class Find {
  2. public static int find(int[] array, int aim) {
  3. // 初始化left = 最左侧, right = 最右侧
  4. int left = 0;
  5. int right = array.length;
  6. // 当left > right则表示遍历完成
  7. while (left <= right) {
  8. // 获取中间的值
  9. int middle = (left + right) / 2;
  10. int middleValue = array[middle];
  11. if (middleValue == aim) {
  12. // 已经找到目标
  13. return middle;
  14. } else if (middleValue < aim) {
  15. // 目标在middle的左侧,重置right
  16. right = middle - 1;
  17. } else {
  18. // 目标在middle的右侧,重置left
  19. left = middle + 1;
  20. }
  21. }
  22. return -1;
  23. }
  24. public static void main(String[] args) {
  25. int[] array = {100, 90, 80, 75, 22, 3, 2};
  26. int result1 = find(array, 22);
  27. if (result1 == -1) {
  28. System.out.println("22 不存在数组中");
  29. } else {
  30. System.out.println("22 存在数组中,索引值是 " + result1);
  31. }
  32. int result2 = find(array, 50);
  33. if (result2 == -1) {
  34. System.out.println("50 不存在数组中");
  35. } else {
  36. System.out.println("50 存在数组中,索引值是 " + result2);
  37. }
  38. }
  39. }

练习:根据已排好序的字母二分查找某值

image.pngimage.png

  1. import java.util.ArrayList;
  2. import java.util.Comparator;
  3. public class Address {
  4. public static int find(ArrayList<String> array, String aim) {
  5. // 初始化left = 最左侧, right = 最右侧
  6. int left = 0;
  7. int right = array.size();
  8. // 当left > right则表示遍历完成
  9. while (left <= right) {
  10. // 获取中间的值
  11. int middle = (left + right) / 2;
  12. String middleValue = array.get(middle);
  13. if (middleValue.equals(aim)) {
  14. // 已经找到目标
  15. return middle;
  16. } else if (middleValue.compareTo(aim) > 0) {
  17. // 目标在middle的左侧,重置right
  18. right = middle - 1;
  19. } else {
  20. // 目标在middle的右侧,重置left
  21. left = middle + 1;
  22. }
  23. }
  24. return -1;
  25. }
  26. public static void main(String[] args) {
  27. ArrayList<String> array = new ArrayList<>();
  28. array.add("Allen");
  29. array.add("Emma");
  30. array.add("James");
  31. array.add("Jeanne");
  32. array.add("Kelly");
  33. array.add("Kevin");
  34. array.add("Mary");
  35. array.add("Natasha");
  36. array.add("Olivia");
  37. array.add("Rose");
  38. int result1 = find(array, "Kelly");
  39. if (result1 == -1) {
  40. System.out.println("Kelly 不存在名单中");
  41. } else {
  42. System.out.println("Kelly 存在名单中,位置是 " + result1);
  43. }
  44. int result2 = find(array, "Edith");
  45. if (result2 == -1) {
  46. System.out.println("Edith 不存在名单中");
  47. } else {
  48. System.out.println("Edith 存在名单中,位置是 " + result2);
  49. }
  50. }
  51. }

性能优化小案例2.二次(查重)问题

image.png
image.png
image.pngimage.pngimage.pngimage.pngimage.pngimage.pngimage.pngimage.pngimage.png

  1. public static ArrayList<Integer> repeat(int[] array) {
  2. ArrayList<Integer> result = new ArrayList<>();
  3. int[] exists = new int[11];
  4. for (int i = 0; i < array.length; i++) {
  5. int value = array[i];
  6. // 如果当前位置已经为1,则表示重复
  7. if (exists[value] == 1) {
  8. result.add(value);
  9. } else {
  10. // 否则将当前位置设置为1
  11. exists[value] = 1;
  12. }
  13. }
  14. return result;
  15. }

image.png

练习:字符串查重

image.pngimage.png

  1. import java.util.ArrayList;
  2. public class Second {
  3. public static ArrayList<Character> repeat(String str) {
  4. ArrayList<Character> result = new ArrayList<>();
  5. int[] exists = new int[26];
  6. for (int i = 0; i < str.length(); i++) {
  7. char c = str.charAt(i);
  8. if (exists[c - 'a'] == 1) {
  9. result.add(c);
  10. } else {
  11. exists[c - 'a'] = 1;
  12. }
  13. }
  14. return result;
  15. }
  16. public static void main(String[] args) {
  17. String str = "abcdkioudofanzdfpqwe";
  18. System.out.println(repeat(str));
  19. }
  20. }

排序算法

冒泡排序

image.png
image.pngimage.png
image.png
image.pngimage.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.pngimage.pngimage.pngimage.png
image.png
image.png

练习:冒泡排序的降序排序算法

  1. package com.youkeda;
  2. import java.util.Arrays;
  3. public class Sort {
  4. // 冒泡排序
  5. public static void bubbleSort(int[] array) {
  6. // 每次循环,都能冒泡出剩余元素中最大的元素,因此需要循环 array.length 次
  7. for (int i = 0; i < array.length; i++) {
  8. // 每次遍历,只需要遍历 0 到 array.length - i - 1中元素,因此之后的元素都已经是最大的了
  9. for (int j = 0; j < array.length - i - 1; j++) {
  10. // 交换元素
  11. if (array[j] < array[j + 1]) {
  12. int temp = array[j + 1];
  13. array[j + 1] = array[j];
  14. array[j] = temp;
  15. }
  16. }
  17. }
  18. }
  19. public static void main(String[] args) {
  20. int[] array = {9, 2, 4, 7, 5, 3};
  21. // Arrays.toString 可以方便打印数组内容
  22. System.out.println(Arrays.toString(array));
  23. bubbleSort(array);
  24. System.out.println(Arrays.toString(array));
  25. }
  26. }

方式二:

  1. import java.util.Arrays;
  2. public class Demo {
  3. public static void bubbleSort(int[] array) {
  4. int maxIndex = 0;
  5. for (int i = 0; i < array.length; i++) {
  6. for (int j = i+1; j < array.length; j++) {
  7. //如果后面的数大于前面的数,排前面
  8. if (array[i]<array[j]) {
  9. //交换
  10. int temp = array[i];
  11. array[i] = array[j];
  12. array[j] = temp;
  13. }
  14. }
  15. }
  16. }
  17. public static void main(String[] args) {
  18. int[] array = {9, 2, 4, 7, 5, 3};
  19. // Arrays.toString 可以方便打印数组内容
  20. System.out.println(Arrays.toString(array));
  21. bubbleSort(array);
  22. System.out.println(Arrays.toString(array));
  23. }
  24. }

选择排序

image.pngimage.png
image.png
image.png
image.pngimage.png

练习:选择排序的升序排列代码

  1. import java.util.Arrays;
  2. public class Demo {
  3. public static void selectSort(int[] array) {
  4. //i仅仅起到循环次数的作用
  5. for (int i = 0; i < array.length; i++) {
  6. //每次从数组第一个数开始比较最大数的index
  7. int maxIndex = 0;
  8. for (int j = 0; j < array.length-i; j++) {
  9. //找到比array[maxIndex]大的数了,更新maxIndex值
  10. if (array[j]>array[maxIndex]) {
  11. maxIndex = j;
  12. }
  13. }
  14. //如果找到了就是最新的maxIndex值,否则第一个数就是最大值,交换最大值和右边的数
  15. int temp = array[maxIndex];
  16. array[maxIndex] = array[array.length-i-1];
  17. array[array.length-i-1] = temp;
  18. }
  19. }
  20. public static void main(String[] args) {
  21. int[] array = {9, 2, 4, 7, 5, 3};
  22. // Arrays.toString 可以方便打印数组内容
  23. System.out.println(Arrays.toString(array));
  24. selectSort(array);
  25. System.out.println(Arrays.toString(array));
  26. }
  27. }

插入排序

image.pngimage.png
image.png
image.png
image.pngimage.png
image.pngimage.png

练习:插入排序的升序排序

(注意边界情况)

  1. import java.util.Arrays;
  2. public class Sort {
  3. // 插入排序
  4. public static void insertSort(int[] array) {
  5. // 从倒数第二位开始,遍历到底0位,遍历 N-1 次
  6. for (int i = array.length - 2; i >= 0; i--) {
  7. // 存储当前抽离的元素
  8. int temp = array[i];
  9. // 从抽离元素的右侧开始遍历
  10. int j = i + 1;
  11. while (j <= array.length - 1) {
  12. // 如果某个元素,小于临时元素,则这个元素左移
  13. if (array[j] < temp) {
  14. array[j - 1] = array[j];
  15. } else {
  16. // 如果大于,则直接将临时元素插入,然后退出循环。
  17. array[j - 1] = temp;
  18. break;
  19. }
  20. j++;
  21. }
  22. // 处理到达尾部的情况
  23. if (j == array.length) {
  24. array[j - 1] = temp;
  25. }
  26. }
  27. }
  28. public static void main(String[] args) {
  29. int[] array = {9, 2, 4, 7, 5, 3};
  30. // Arrays.toString 可以方便打印数组内容
  31. System.out.println(Arrays.toString(array));
  32. insertSort(array);
  33. System.out.println(Arrays.toString(array));
  34. }
  35. }

插序进阶—-二分插入排序

image.png
image.pngimage.png
源码:

  1. import java.util.Arrays;
  2. public class Sort {
  3. // 查找应该插入的索引位置
  4. public static int searchIndex(int[] array, int left, int right, int aim) {
  5. // 循环查找节点位置
  6. while (left < right) {
  7. int middle = (left + right) / 2;
  8. int value = array[middle];
  9. if (value < aim) {
  10. left = middle + 1;
  11. } else {
  12. right = middle - 1;
  13. }
  14. }
  15. // 如果最终元素仍然大于目标元素,则将索引位置往左边移动一个
  16. if(array[left] > aim){
  17. return left -1;
  18. }
  19. // 否则就是当前位置
  20. return left;
  21. }
  22. // 插入排序
  23. public static void insertSort(int[] array) {
  24. // 从倒数第二位开始,遍历到底0位,遍历 N-1 次
  25. for (int i = array.length - 2; i >= 0; i--) {
  26. // 存储当前抽离的元素
  27. int temp = array[i];
  28. int index = searchIndex(array, i + 1, array.length - 1, temp);
  29. // 根据插入的索引位置,进行数组的移动和插入
  30. int j = i + 1;
  31. while (j <= index) {
  32. array[j - 1] = array[j];
  33. j++;
  34. }
  35. array[j - 1] = temp;
  36. }
  37. }
  38. public static void main(String[] args) {
  39. int[] array = {9, 2, 4, 7, 5, 3};
  40. // Arrays.toString 可以方便打印数组内容
  41. System.out.println(Arrays.toString(array));
  42. insertSort(array);
  43. System.out.println(Arrays.toString(array));
  44. }
  45. }

链表

链表常用方式,固定下来的解题:

  1. 方便对头节点的操作,创建哑节点dummyhead
  2. cur = dummyhed, cur指向当前节点
  3. cur = cur->next,进行链表遍历