基础算法模板(Java实现)

目录

1 基础算法

1.1 排序

1.2 二分

1.2.1 整数二分

1.2.2 浮点数二分

1.3 高精度

1.4 前缀和

1.4.1 一维前缀和

1.4.2 二维前缀和

1.5 差分

1.5.1 一维差分

1.5.2 二维差分

1.6 双指针算法

1.7 位运算

1.8 离散化

1.9 区间合并

2 数据结构

2.1 链表

2.1.1 单链表

2.1.2 双链表

2.2 栈

2.3 队列

2.4 单调栈

2.5 单调队列

2.6 KMP

2.7 Trie

2.8 并查集

2.9 堆

2.10 哈希表

2.10.1 拉链法

2.10.2 开放寻址法

2.11 字符串哈希

3 搜索与图论

3.1 DFS与BFS

3.2 树与图的遍历

3.2.1 深度优先遍历

3.2.2 广度优先遍历

3.3 拓扑排序

3.4 最短路

3.4.1 朴素Dijkstra

3.4.2 堆优化Dijkstra

3.4.3 Bellman-Ford

3.4.4 SPFA

3.4.5 Floyd

3.5 最小生成树

3.5.1 朴素Prim

3.5.2 Kruskal


1 基础算法

1.1 排序

        排序主要分为以下几种,在做算法题的时候主要使用到快速排序和归并排序。快速排序可以直接使用语言自带的排序函数,但是需要掌握手写实现,归并排序需要重点掌握实现,其他排序只需掌握原理即可。另外需要熟记各种排序的时间复杂度、空间复杂度、稳定性。

算法 时间复杂度(平均) 空间复杂度 是否稳定
直接插入排序 O(n^2) O(1)
希尔排序 O(n^1.3) O(1)
冒泡排序 O(n^2) O(1)
快速排序 O(nlogn) O(logn)
选择排序 O(n^2) O(1)
堆排序 O(nlogn) O(1)
归并排序 O(nlogn) O(n)
基数排序 O(d(n+r)) O(r)

需要知道的一些结论:

      一趟结束之后能确定一个元素的最终位置的排序方法有交换排序和选择排序。其他的选择排序、归并排序、基数排序都不能确定。

      排序趟数与序列的原始状态有关的排序方法有冒泡排序和快速排序。在序列已经有序的情况下冒泡排序的时间复杂度降为O(n),快速排序的时间复杂度升为O(n^2)。

直接插入排序:

       对序列A的元素A[0] ~ A[n-1],令i从1到n-1枚举,进行n-1趟操作。第i趟时,序列A的前i个元素A[0] ~ A[i-1]已经有序,序列A范围[i,n-1]的元素还未有序,那么该趟从[0,i-1]中寻找某个位置j,使得A[i]插入位置j后(此时A[j] ~ A[i-1]会后移一位至A[j+1] ~ A[i]),范围[0,i]有序。

    void insertSort(int[] arr) {
        for (int i = 1; i <= arr.length - 1; i++) {//n-1轮
            int temp = arr[i], j = i;
            while (j >= 1 && temp < arr[j - 1]) {
                arr[j] = arr[j - 1];
                j--;
            }
            arr[j] = temp;
        }
    }

希尔排序:

      将序列分成若干组,每组元素之间间隔距离为d,例如某一组元素的位置为i, i + d, i + 2d, ...,对每一组的元素进行插入排序之后,再对全体进行插入排序。

冒泡排序:

      从前往后两两相邻的数进行交换,只要左边的数比右边的数大,就交换两个数的位置,一共进行n-1趟。第一趟的时候把最大的数交换到n-1的位置,第i趟的时候的时候把第i大的数交换到n-i的位置。

    void bubbleSort(int[] arr) {
        for (int i = 1; i <= arr.length - 1; i++) {//比较n-1轮
            for (int j = 0; j < arr.length - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

快速排序:

        在一趟排序的过程中,选择某一个数为基准,先从右往左找第一个比它小的数,与之交换。在从左往右找第一个比它大的数,与之交换。直到这个基准数左边的数都比它小,右边的数都比它大为止。然后再递归的对这个基准数左右两边的两组数进行快速排序。

    int partition(int lo, int hi, int[] arr) {
        int temp = arr[lo];
        while (lo < hi) {
            while (lo < hi && arr[hi] > temp) {
                hi--;
            }
            arr[lo] = arr[hi];
            while (lo < hi && arr[lo] < temp) {
                lo++;
            }
            arr[hi] = arr[lo];
        }
        arr[lo] = temp;
        return lo;
    }

    void quickSortHelper(int lo, int hi, int[] arr) {
        if (lo < hi) {
            int pivot = partition(lo, hi, arr);
            quickSortHelper(lo, pivot - 1, arr);
            quickSortHelper(pivot + 1, hi, arr);
        }
    }

    //快速排序
    void quickSort(int[] arr) {
        quickSortHelper(0, arr.length - 1, arr);
    }

       更优雅的模板:

    void quickSort(int[] q, int l, int r) {
        if (l >= r) return;
        int i = l - 1, j = r + 1, x = q[l + r >> 1];
        while (i < j) {
            do i++; while (q[i] < x);
            do j--; while (q[j] > x);
            if (i < j) {
                int temp = q[i];
                q[i] = q[j];
                q[j] = temp;
            }
        }
        quickSort(q, l, j);
        quickSort(q, j + 1, r);
    }

选择排序:

      对一个序列A中的元素A[0]~A[n-1],令i从0到n-1枚举,进行n趟操作,每趟从待排序部分[i,n-1]中选择最小的元素,令其与待排序部分第一个元素A[i]交换,这样A[i]就会与当前有序序列[0,i-1]形成新的有序序列[0,i],n趟操作后,所有元素有序。

    void selectSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[min]) {
                    min = j;
                }
            }
            int temp = arr[i];
            arr[i] = arr[min];
            arr[min] = temp;
        }
    }

堆排序:

      将序列视为完全二叉树顺序结构,从n/2 ~ 1的顺序依次筛选构建小根堆或者大根堆。

归并排序:

      先从左到右两两一组,再进行组内排序。第二趟的时候从左到右每4个一组,再进行组内排序。最终只剩下一组,再进行组内排序。

    void mergeSort(int[] q, int l, int r) {
        if (l >= r) {
            return;
        }
        int mid = l + r >> 1;
        mergeSort(q, l, mid);
        mergeSort(q, mid + 1, r);
        int[] temp = new int[r - l + 1];
  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值