查找算法
性能优化小案例1.二分法查找
public static int find(int[] array, int aim) {
for (int i = 0; i < array.length; i++) {
if (aim == array[i]) {
return i;
}
}
return -1;
}
public static int find(int[] array, int aim) {
// 初始化left = 最左侧, right = 最右侧
int left = 0;
int right = array.length - 1;
// 当left > right则表示遍历完成
while (left <= right) {
// 获取中间的值
int middle = (left + right) / 2;
int middleValue = array[middle];
if (middleValue == aim) {
// 已经找到目标
return middle;
} else if (middleValue < aim) {
// 目标在middle的右侧,重置left
left = middle + 1;
} else {
// 目标在middle的左侧,重置right
right = middle - 1;
}
}
return -1;
}
练习:利用二分法查找降序排列数组的某个值
public class Find {
public static int find(int[] array, int aim) {
// 初始化left = 最左侧, right = 最右侧
int left = 0;
int right = array.length;
// 当left > right则表示遍历完成
while (left <= right) {
// 获取中间的值
int middle = (left + right) / 2;
int middleValue = array[middle];
if (middleValue == aim) {
// 已经找到目标
return middle;
} else if (middleValue < aim) {
// 目标在middle的左侧,重置right
right = middle - 1;
} else {
// 目标在middle的右侧,重置left
left = middle + 1;
}
}
return -1;
}
public static void main(String[] args) {
int[] array = {100, 90, 80, 75, 22, 3, 2};
int result1 = find(array, 22);
if (result1 == -1) {
System.out.println("22 不存在数组中");
} else {
System.out.println("22 存在数组中,索引值是 " + result1);
}
int result2 = find(array, 50);
if (result2 == -1) {
System.out.println("50 不存在数组中");
} else {
System.out.println("50 存在数组中,索引值是 " + result2);
}
}
}
练习:根据已排好序的字母二分查找某值
import java.util.ArrayList;
import java.util.Comparator;
public class Address {
public static int find(ArrayList<String> array, String aim) {
// 初始化left = 最左侧, right = 最右侧
int left = 0;
int right = array.size();
// 当left > right则表示遍历完成
while (left <= right) {
// 获取中间的值
int middle = (left + right) / 2;
String middleValue = array.get(middle);
if (middleValue.equals(aim)) {
// 已经找到目标
return middle;
} else if (middleValue.compareTo(aim) > 0) {
// 目标在middle的左侧,重置right
right = middle - 1;
} else {
// 目标在middle的右侧,重置left
left = middle + 1;
}
}
return -1;
}
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<>();
array.add("Allen");
array.add("Emma");
array.add("James");
array.add("Jeanne");
array.add("Kelly");
array.add("Kevin");
array.add("Mary");
array.add("Natasha");
array.add("Olivia");
array.add("Rose");
int result1 = find(array, "Kelly");
if (result1 == -1) {
System.out.println("Kelly 不存在名单中");
} else {
System.out.println("Kelly 存在名单中,位置是 " + result1);
}
int result2 = find(array, "Edith");
if (result2 == -1) {
System.out.println("Edith 不存在名单中");
} else {
System.out.println("Edith 存在名单中,位置是 " + result2);
}
}
}
性能优化小案例2.二次(查重)问题
public static ArrayList<Integer> repeat(int[] array) {
ArrayList<Integer> result = new ArrayList<>();
int[] exists = new int[11];
for (int i = 0; i < array.length; i++) {
int value = array[i];
// 如果当前位置已经为1,则表示重复
if (exists[value] == 1) {
result.add(value);
} else {
// 否则将当前位置设置为1
exists[value] = 1;
}
}
return result;
}
练习:字符串查重
import java.util.ArrayList;
public class Second {
public static ArrayList<Character> repeat(String str) {
ArrayList<Character> result = new ArrayList<>();
int[] exists = new int[26];
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (exists[c - 'a'] == 1) {
result.add(c);
} else {
exists[c - 'a'] = 1;
}
}
return result;
}
public static void main(String[] args) {
String str = "abcdkioudofanzdfpqwe";
System.out.println(repeat(str));
}
}
排序算法
冒泡排序
练习:冒泡排序的降序排序算法
package com.youkeda;
import java.util.Arrays;
public class Sort {
// 冒泡排序
public static void bubbleSort(int[] array) {
// 每次循环,都能冒泡出剩余元素中最大的元素,因此需要循环 array.length 次
for (int i = 0; i < array.length; i++) {
// 每次遍历,只需要遍历 0 到 array.length - i - 1中元素,因此之后的元素都已经是最大的了
for (int j = 0; j < array.length - i - 1; j++) {
// 交换元素
if (array[j] < array[j + 1]) {
int temp = array[j + 1];
array[j + 1] = array[j];
array[j] = temp;
}
}
}
}
public static void main(String[] args) {
int[] array = {9, 2, 4, 7, 5, 3};
// Arrays.toString 可以方便打印数组内容
System.out.println(Arrays.toString(array));
bubbleSort(array);
System.out.println(Arrays.toString(array));
}
}
方式二:
import java.util.Arrays;
public class Demo {
public static void bubbleSort(int[] array) {
int maxIndex = 0;
for (int i = 0; i < array.length; i++) {
for (int j = i+1; j < array.length; j++) {
//如果后面的数大于前面的数,排前面
if (array[i]<array[j]) {
//交换
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
public static void main(String[] args) {
int[] array = {9, 2, 4, 7, 5, 3};
// Arrays.toString 可以方便打印数组内容
System.out.println(Arrays.toString(array));
bubbleSort(array);
System.out.println(Arrays.toString(array));
}
}
选择排序
练习:选择排序的升序排列代码
import java.util.Arrays;
public class Demo {
public static void selectSort(int[] array) {
//i仅仅起到循环次数的作用
for (int i = 0; i < array.length; i++) {
//每次从数组第一个数开始比较最大数的index
int maxIndex = 0;
for (int j = 0; j < array.length-i; j++) {
//找到比array[maxIndex]大的数了,更新maxIndex值
if (array[j]>array[maxIndex]) {
maxIndex = j;
}
}
//如果找到了就是最新的maxIndex值,否则第一个数就是最大值,交换最大值和右边的数
int temp = array[maxIndex];
array[maxIndex] = array[array.length-i-1];
array[array.length-i-1] = temp;
}
}
public static void main(String[] args) {
int[] array = {9, 2, 4, 7, 5, 3};
// Arrays.toString 可以方便打印数组内容
System.out.println(Arrays.toString(array));
selectSort(array);
System.out.println(Arrays.toString(array));
}
}
插入排序
练习:插入排序的升序排序
(注意边界情况)
import java.util.Arrays;
public class Sort {
// 插入排序
public static void insertSort(int[] array) {
// 从倒数第二位开始,遍历到底0位,遍历 N-1 次
for (int i = array.length - 2; i >= 0; i--) {
// 存储当前抽离的元素
int temp = array[i];
// 从抽离元素的右侧开始遍历
int j = i + 1;
while (j <= array.length - 1) {
// 如果某个元素,小于临时元素,则这个元素左移
if (array[j] < temp) {
array[j - 1] = array[j];
} else {
// 如果大于,则直接将临时元素插入,然后退出循环。
array[j - 1] = temp;
break;
}
j++;
}
// 处理到达尾部的情况
if (j == array.length) {
array[j - 1] = temp;
}
}
}
public static void main(String[] args) {
int[] array = {9, 2, 4, 7, 5, 3};
// Arrays.toString 可以方便打印数组内容
System.out.println(Arrays.toString(array));
insertSort(array);
System.out.println(Arrays.toString(array));
}
}
插序进阶—-二分插入排序
源码:
import java.util.Arrays;
public class Sort {
// 查找应该插入的索引位置
public static int searchIndex(int[] array, int left, int right, int aim) {
// 循环查找节点位置
while (left < right) {
int middle = (left + right) / 2;
int value = array[middle];
if (value < aim) {
left = middle + 1;
} else {
right = middle - 1;
}
}
// 如果最终元素仍然大于目标元素,则将索引位置往左边移动一个
if(array[left] > aim){
return left -1;
}
// 否则就是当前位置
return left;
}
// 插入排序
public static void insertSort(int[] array) {
// 从倒数第二位开始,遍历到底0位,遍历 N-1 次
for (int i = array.length - 2; i >= 0; i--) {
// 存储当前抽离的元素
int temp = array[i];
int index = searchIndex(array, i + 1, array.length - 1, temp);
// 根据插入的索引位置,进行数组的移动和插入
int j = i + 1;
while (j <= index) {
array[j - 1] = array[j];
j++;
}
array[j - 1] = temp;
}
}
public static void main(String[] args) {
int[] array = {9, 2, 4, 7, 5, 3};
// Arrays.toString 可以方便打印数组内容
System.out.println(Arrays.toString(array));
insertSort(array);
System.out.println(Arrays.toString(array));
}
}
链表
链表常用方式,固定下来的解题:
- 方便对头节点的操作,创建哑节点dummyhead
- cur = dummyhed, cur指向当前节点
- cur = cur->next,进行链表遍历