# 算法

# 基本查找

public class FindText {
    public static void main(String[] args) {
        //基本查找
        //需求:定义一个方法利用基本查找,查询某个数据是否存在
        int[] arr = {1, 2, 3, 4, 5, 5, 7, 8, 9, 10};
        System.out.println(myFind(arr, 11));//false
        System.out.println(myFind(arr, 1));//true


        //使用基本查找 找出元素索引,可能具有重复元素
        System.out.println(myFindRepeat(arr, 5));//[4, 5]
    }

    //基本查找
    private static Boolean myFind(int[] arr, int num) {
        for (int item : arr)
            if (item == num) return true;
        return false;
    }

    //使用基本查找 找出元素索引,可能具有重复元素
    private static ArrayList<Integer> myFindRepeat(int[] arr, int num) {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == num) list.add(i);
        }
        return list;
    }
}

# 二分查找

package algorithm;

import java.util.ArrayList;

public class FindText {
    public static void main(String[] args) {
        //二分查找
        //二分查找的前提:数组中的数据必须是有序的
        //核心逻辑:排除掉一半的查找范围
        System.out.println("二分查找结果" + binarySearch(arr, 10));//9
        System.out.println("二分查找结果" + binarySearch(arr, 11));//-1
    }

    //二分查找
    private static int binarySearch(int[] arr, int num) {
        //小索引
        int left = 0;
        //大索引
        int right = arr.length - 1;

        while (left <= right) {
            int mid = (left + right) / 2;
            if (arr[mid] == num) return mid;
            else {
                if (num > arr[mid])
                    left = mid + 1;
                else
                    right = mid - 1;

            }
        }
        return -1;
    }
}

# 冒泡排序

规则:把相邻的数据两两比较,小的放前面,大的放后面

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {1, 5, 3, 9, 2, 7, 4, 6, 8};
        int[] result = mySort(arr);
        System.out.println(Arrays.toString(result));//[1, 2, 3, 4, 5, 6, 7, 8, 9]
    }

    private static int[] mySort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int j = 0;
            //内循环 每一轮中比较数据 寻找最大值
            //-1 防止索引越界
            //-i 提高效率
            while (j < arr.length - 1 - i) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
                j++;
            }
        }
        return arr;
    }
}

# 选择排序

规则:从索引0开始,拿着每一个索引上的元素跟后面的元素依次比较,小的放前面,大的放后面,以此类推

public class SelectSort {
    public static void main(String[] args) {
        //选择排序
        //规则:从索引0开始,拿着每一个索引上的元素跟后面的元素依次比较,小的放前面,大的放后面,以此类推
        int[] result1 = mySort1(arr);
        System.out.println(Arrays.toString(result1));//[1, 2, 3, 4, 5, 6, 7, 8, 9]
    }

    private static int[] mySort1(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            //拿着i跟i后面的数据进行比较交换
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        return arr;
    }
}

# 插入排序

  • 将0索引的元素到n索引的元素看做是有序的,把N+1索引的元素到最后一个当成是无序的。
  • 遍历无序的数据,将遍历到的元素插入有序序列中的合适位置,如遇到相同数据,插在后面。
  • N的范围:0~最大索引
public class InsertSort {
    public static void main(String[] args) {

        //插入排序
        int[] result2 = mySort2(arr);
        System.out.println(Arrays.toString(result2));//[1, 2, 3, 4, 5, 6, 7, 8, 9]
    }

    private static int[] mySort2(int[] arr) {
        //克隆数组
        int[] arrClone = arr.clone();
        //1.找到无序的那一组是从哪个索引开始的
        int startIndex = -1;
        for (int i = 0; i < arrClone.length - 1; i++) {
            if (arrClone[i] > arrClone[i + 1]) {
                startIndex = i + 1;//找到无序的那一组的开始索引
                break;
            }
        }
        //遍历无序的列表
        for (int i = startIndex; i < arrClone.length; i++) {
            //记录当前要插入数据的索引
            int j = i;
            //将当前数据倒着插入到有序的列表中
            while (j > 0 && arrClone[j] < arrClone[j - 1]) {
                //交换位置(与前面的数据进行交换)
                int temp = arrClone[j];
                arrClone[j] = arrClone[j - 1];
                arrClone[j - 1] = temp;
                j--;
            }

        }
        return arrClone;
    }
}

# 递归算法

递归算法:就是方法中调用方法本身的现象(自己调用自己)

注意

递归一定要有出口,否则就会出现内存溢出

# 书写递归的两个核心

  • 找出口:什么时候不在调用此方法
  • 找规则:如何把大问题变成规模较小的问题
  • 方法内部再次调用方法的时候要更靠近出口
public class Recursion {
    public static void main(String[] args) {
        //递归求和
        int start = 1;
        int end = 100;
        int sum = mySum(start, end);
        System.out.println(start + "到" + end + "之间的和为:" + sum);//5050

        //递归求阶乘
        int result3 = myFactorial(5);
        System.out.println("阶乘为:" + result3);//120

    }

    //递归求阶乘
    private static int myFactorial(int i) {
        if (i == 1) return 1;
        else return i * myFactorial(i - 1);
    }

    //递归求和
    private static int mySum(int start, int end) {
        if (start == end)
            return start;
        else return start + mySum(start + 1, end);
    }
}

# 快速排序

快速排序用时非常快,在测试排序十万随机数时,快速排序比其他排序算法快了20倍

  • 冒泡排序时间:19046

  • 选择排序时间:15612

  • 插入排序时间:1754

  • 快速排序时间:20

  • 第一轮:把0索引的数字作为基准数,确定基准数在数组中正确的位置
    结束后比基准数小的全部在左边,比基准数大的全部在右边

public class QuickSort {
    public static void main(String[] args) {
        //快速排序
        //第一轮:把0索引的数字作为基准数,确定基准数在数组中正确的位置
        //          结束后比基准数小的全部在左边,比基准数大的全部在右边
        int[] result4 = myQuickSort3(arr.clone(), 0, arr.length - 1);
        System.out.println(Arrays.toString(result4));
    }

    //快速排序
    private static int[] myQuickSort3(int[] arr, int i, int j) {
        int start = i;
        int end = j;
        //递归的出口
        if (start > end) return arr;
        //1.记录基准数
        int base = arr[i];
        //2.利用循环找到要交换的数字
        while (start != end) {
            //3.利用end,从后往前开始找,找比基准数小的数字
            while (start < end && arr[end] >= base) {
                //左边找到比基准数大的数字
                end--;
            }
            //4.利用start找到比基准数大的数字
            while (start < end && arr[start] <= base) {
                start++;
            }
            //5.交换start和end找到的数字
            int temp = arr[start];
            arr[start] = arr[end];
            arr[end] = temp;
        }
        //当start和end都指向一个元素的时候,那么上面的循环就会结束
        //表示已经找到了基准数在数组中应该存入的位置
        //基准数归位
        //就是拿着这个范围中的第一个数字,跟start指向的元素进行交换
        int temp = arr[i];
        arr[i] = arr[start];
        arr[start] = temp;
        //确定基准数左边的位置 重复刚刚的事情
        myQuickSort3(arr, i, start - 1);

        //确定基准数右边的位置 重复刚刚的事情
        myQuickSort3(arr, end + 1, j);
        return arr;
    }

}

# 操作数组的工具类Arrays

方法 描述
public static String toString(int[] a) 将数组转换为字符串表示形式。
public static int binarySearch(int[] a, int key) 二分查找法查找元素
public static void fill(int[] a, int val) 使用指定的值填充数组
public static int[] copyOf(int[] original, int newLength) 创建一个新的数组
public static int[] copyOfRange(int[] original, int from, int to) 创建一个新的数组(指定范围)
public static void sort(int[] a) 按照默认方式对数组进行排序。
public static void sort(int[] a, 排序规则) 按照指定的规则进行排序

# 动态规划(矩阵连乘问题)

上次更新: 10/23/2024, 10:13:35 AM