常见算法

22 阅读5分钟

1.查找算法

基本查找

  • 循环一个一个遍历

二分查找

  • 设置left mid right三个变量
  • 每查一次就可以减少一半区间长度

插值查找和斐波那契查找

  • 本质上就是二分查找,只不过mid的计算方式被优化 image.png

分块查找

2.排序算法

冒泡排序

  • 相邻数据两两比较,小的放前面,大的放后面。
  • 第一轮循环结束后,最大值已经找到了,并且在数组的最右面。
public class maopao {
    public static void main(String[] args) {
        //冒泡排序
        int[] arr = {2,4,5,3,1};
        for(int i=1;i<arr.length;i++){//外循环控制要执行多少论,n个数据需要运行n-1轮
            for(int j=0;j<arr.length-i;j++){//内循环用来交换数据,并且每过1轮就可以少交换1次哦
                if(arr[j]>arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        for(int i=0;i<arr.length;i++){
            System.out.println(arr[i]);
        }

    }
}

选择排序

  • 从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较,小的放前面,大的放后面。依次类推。
public class xuanze {
    public static void main(String[] args) {
        int[] arr = {1,5,3,2,4};
        for(int i=0;i<arr.length-1;i++){//表示要循环几轮
            for(int j=i+1;j<arr.length;j++){//从arr[i]开始,依次和后面的元素比较大小
                if(arr[i] > arr[j]){
                    int temp = arr[j];
                    arr[j] = arr[i];
                    arr[i] = temp;
                }
            }
        }
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }

    }
}

插入排序

  • 将0索引的元素到N索引的元素看作是有序的,其他的视为无序的,然后去遍历无序的数据,并把元素插入到前面有序数据中合适的位置,遇到相同元素,直接插在后面。
public class charu {
    public static void main(String[] args) {
        int[] arr = {3,44,38,5,47,15,36,16,27,2,46,5,34,56,34};
        //1.先找到无序数据的开始索引
        int startIndex = -1;
        for(int i = 0; i < arr.length; i++){
            if(arr[i]>arr[i+1]){
                startIndex = i+1;
                break;
            }
        }
        //2.遍历无序数据,开始进行插入
        for(int i = startIndex; i < arr.length; i++){
            int k = i; //因为后续交换的时候要用到i的值
            for(int j = k-1; j >= 0;j--){
                if(arr[k]<arr[j]){
                    int temp = arr[j];
                    arr[j] = arr[k];
                    arr[k] = temp;
                    k--;
                }
                else if(arr[k]>=arr[j]){
                    break; //一旦发现k所在的位置比j指的数据要大,就说明找到了要插入的位置,就不用再移动比较了,这个地方可以画图模拟一下。
                }
            }
        }
        //3.输出数组
        for(int i = 0; i < arr.length; i++){
            System.out.print(arr[i]+ " ");
        }

    }
}

快速排序

  • 用到了递归算法:方法调用方法本身。递归一定要有出口,要不然会内存溢出。
  • 第一轮把0索引作为基准数,确定基准数在数组中正确的位置。(基准数归位
  • 比基准数小的全部在左边,大的全部在右边。
  • 如果基准数选最左边,先移动右指针
  • 如果基准数选最右边,先移动左指针
  • 如果基准数选中间,顺序无所谓
  • 下面是一个很重要的防御保护思想,外层循环只是控制一个入口,内层最好单独去判断。
while(外层条件) {
    while(外层条件 && 内层条件) {
        // ...
    }
     if(外层条件 && 内层条件){
     }
}
import java.util.Arrays;

public class quicksort {
    public static void main(String[] args) {
        int[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 19, 8};
        quickSort(arr, 0, arr.length - 1);

        for(int i = 0; i < arr.length; i++){
            System.out.print(arr[i] + " ");
        }
    }

    public static void quickSort(int[] arr, int left, int right){
        // 递归结束条件
        if(left >= right){
            return;
        }

        int start = left;
        int end = right;
        int baseNumber = arr[left];  // 基准数

        while(start < end){
            // 从右往左找比基准数小的
            while(start < end && arr[end] >= baseNumber){
                end--;
            }

            // 从左往右找比基准数大的
            while(start < end && arr[start] <= baseNumber){
                start++;
            }

            // 交换start和end指向的元素
            if(start < end){
                int temp = arr[start];
                arr[start] = arr[end];
                arr[end] = temp;
            }
        }
        // 基准数归位
        arr[left] = arr[start];
        arr[start] = baseNumber;

        // 递归排序左右子数组
        quickSort(arr, left, start - 1);  // 排序左边
        quickSort(arr, start + 1, right); // 排序右边
    }
}

3.Arrays的API

  • 它是操作数组的工具类 image.png
import java.util.Arrays;

public class ArraysDemo {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9,10};
        //1.将数组转化为字符串
        System.out.println("------------------------------toString----------------------");
        System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        //2.binarySearch:二分查找元素
        //细节1:使用二分查找时,数组一定要是有序的,使用Java中这个方法时,还要是升序的。
        //细节2:如果元素不存在,返回值= 负的(插入点-1)   比如20应该插在索引10的地方,所以返回-11
        //不减1会导致  查找0的时候,如果不存在,返回-0,就出问题了。
        System.out.println("-----------------------------binarySearch--------------------");
        System.out.println(Arrays.binarySearch(arr,10));//9
        System.out.println(Arrays.binarySearch(arr,2));//1
        System.out.println(Arrays.binarySearch(arr,20));//-11

        //3.copyOf:拷贝数组
        //如果比原数组长度大,会补上默认值。
        System.out.println("-----------------------------copyOf--------------------");
        int[] copy = Arrays.copyOf(arr,8);
        int[] copy2 = Arrays.copyOf(arr,20);
        System.out.println(Arrays.toString(copy));//[1, 2, 3, 4, 5, 6, 7, 8]
        System.out.println(Arrays.toString(copy2));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

        //4.copyOfRange:指定范围拷贝
        //包头不包尾,包左不包右
        System.out.println("-----------------------------copyOfRange--------------------");
        int[]  copy3 = Arrays.copyOfRange(arr,0,8);//[1, 2, 3, 4, 5, 6, 7, 8]
        System.out.println(Arrays.toString(copy3));

        //5.fill:填充数组
        System.out.println("-----------------------------fill--------------------");
        Arrays.fill(arr,100);
        System.out.println(Arrays.toString(arr));//[100, 100, 100, 100, 100, 100, 100, 100, 100, 100]

        //6.sort:排序
        //底层使用快速排序,默认升序
        System.out.println("-----------------------------sort--------------------");
        int[]  arr2 = {12,2,8,67,4,3,23,333,23,-90};
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2));//[-90, 2, 3, 4, 8, 12, 23, 23, 67, 333]
    }
}

array的sort方法的排序规则


package com.cqupt;

import java.util.Arrays;
import java.util.Comparator;

public class ArrayDemo {
    public static void main(String[] args) {
        //sort的排序规则
       Integer[] arr = {2,3,1,5,6,7,8,4,9};
       //第二个参数是一个接口,所以我们在调用方法的时候,需要传递这个接口的实现类对象,作为排序的规则
        //但是这个实现类,只使用一次,所以没必要单独写一个类,直接new一个这个类的对象就可以了。
        //o1-o2:升序
        //o2-o1:降序
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        System.out.println(Arrays.toString(arr));
    }
}