算法复习大纲

JAVA算法复习大纲

JAVA算法复习大纲

排序

选择排序:

5,1,128,96,76,2
(1)1,5,128,96,76,2
(2)1,2,128,96,76,5
(3)1,2,5,96,78,128
(4)1,2,5,78,96,128
(5)1,2,5,78,96,128

选择排序:找到最小的元素,插入到有序区,有序区是没有元素的,插入的时候会交换元素

编程

import java.util.Arrays;

public class xuanzepaixu {
    public static void main(String[] args) {
        int numbs[] = {5,1,128,96,76,2};
        selectionSort(numbs);
        System.out.println(Arrays.toString(numbs));
    }

    public static void selectionSort(int[] numbs){
        for (int i = 0; i < numbs.length-1; i++) {
            int min = i;
            for (int j = i+1; j < numbs.length; j++) {
                if (numbs[j]<numbs[min]){
                    min=j;
                }
            }

            if (i!=min){
                int tmp = numbs[i];
                numbs[i]=numbs[min];
                numbs[min]=tmp;
            }
        }
    }
}

插入排序

123,45,19,23,634,4
(1)45,123,19,23,634,4
(2)19,45123,23,634,4
(3)19,2345123,634,4
(4)19,23,45,123634,4
(5)419,23,45,123634

插入排序:插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动

编程

import java.util.Arrays;

public class 插入排序 {
    public static void main(String[] args) {
        int numbs[] = {123,45,19,23,634,4};
        InsertionSort(numbs);
        System.out.println(Arrays.toString(numbs));
    }
    public static void InsertionSort(int[] numbs){
        for (int i = 0; i < numbs.length-1; i++) {
            for (int j = i+1; j > 0; j--) {
                if (numbs[j]<numbs[j-1]){
                    int tmp = numbs[j];
                    numbs[j]=numbs[j-1];
                    numbs[j-1]=tmp;
                }
            }
        }
    }
}

冒泡排序

5,1,128,96,76,2

(1) 1,5,96,76,2,128

(2) 1,5,76,2,96,128

(3) 1,5,2,76,96,128

(4) 1,2,5,76,96,128

(5) 1,2,5,76,96,128

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

编程

import java.util.Arrays;

public class 冒泡排序 {
    public static void main(String[] args) {
        int numbs[] = {1,5,96,76,2,128};
        BubbleSort(numbs);
        System.out.println(Arrays.toString(numbs));
    }
    public static void BubbleSort(int[] nums){

        for (int i = 0; i < nums.length-1; i++) {
            for (int j = 0; j < nums.length-1-i; j++) {
                if (nums[j]>nums[j+1]){
                    int tmp = nums[j];
                    nums[j]=nums[j+1];
                    nums[j+1]=tmp;
                }
            }
        }
    }

}

合并排序

假定有 8 个元素,第一步,划分为四对,每一对两个元素,用 merge 算法合并成四个有序的序列;第二步,把四个序列划分成两对,用 merge 算法合并成两个有序的序列;最后,再利用merge算法合并成一个有序的序列。

算法复习大纲

编程

合并两个有序序列,并返回结果

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class 合并排序 {
    public static void main(String[] args) {
        List<Integer> A  = new ArrayList<Integer>();
        A.add(1);
        A.add(3);
        A.add(7);
        A.add(8);
        List<Integer> B  = new ArrayList<Integer>();
        B.add(2);
        B.add(4);
        B.add(5);
        B.add(6);
        List<Integer> C  = merge(A,B);
        System.out.println(C);
    }

    public static List<Integer> merge(List<Integer> A, List<Integer> B){
        List<Integer> C = new ArrayList<>();

        int i=0;
        int j=0;
        int n = A.size();
        int m = B.size();

        while ((i<n)&&(j<m)){
            if (A.get(i)<B.get(j)){
                C.add(A.get(i));
                i++;
            }else{
                C.add(B.get(j));
                j++;
            }
        }

        while (i<n){
            C.add(A.get(i));
            i++;
        }

        while (j<m){
            C.add(B.get(j));
            j++;
        }

        return C;
    }

}

堆建立

4,1,6,3,8,2,10,5,9,11,7

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z8324APZ-1625552480498)(http://t4king.oss-cn-beijing.aliyuncs.com/uPic/%E5%A0%86%E5%BB%BA%E7%AB%8B(2)].png)

基数排序

例:链表 L 中元素的关键字值分别为:

​ 3097、3673、2985、1358、6138、9135、4782、1367、3684、0139

1. 按关键字中的数字 d1,把 L 中的元素分布到链表情况:

L0 L1 L2 L3 L4 L5 L6 L7 L8 L9
4782 3673 3684 2985 3097 1358 0139
9135 1367 6138

把 L0 ~L9 的元素顺序链接到 L 后,L 中的元素顺序如下

​ 4782 3673 3684 2985 9135 3097 1367 1358 6138 0139

2. 按关键字中的数字 d2,把 L 中的元素分布到链表情况:

L0 L1 L2 L3 L4 L5 L6 L7 L8 L9
9135 1358 1367 3673 4782 3097
6138 3684
0139 2985

把 L0 ~L9 的元素顺序链接到 L 后,L 中的元素顺序如下
9135 6138 0139 1358 1367 3673 4782 3684 2985 3097

3. 按关键字中的数字 d3,把 L 中的元素分布到链表情况:

L0 L1 L2 L3 L4 L5 L6 L7 L8 L9
3097 9135 1358 3673 4782 2985
6138 1367 3684
0139

把 L0 ~L9 的元素顺序链接到 L 后,L 中的元素顺序如下
3097 9135 6138 0139 1358 1367 3673 3684 4782 2985

4. 按关键字中的数字 d4,把 L 中的元素分布到链表情况:

L0 L1 L2 L3 L4 L5 L6 L7 L8 L9
0139 1358 2985 3097 4782 6138 9135
1367 3673
3684

把 L0 ~L9 的元素顺序链接到 L 后,L 中的元素顺序如下
0139 1358 1367 2985 3097 3673 3684 4782 6138 9135

Union_Find操作

find(x):寻找元素 x 所在集合
union(x,y):把元素 x 和元素 y 所在集合合并成一个集合

Union

利用该数据结构合并两个集合的情况

图 (a) 表示由集合 {1,3,5,8}, {2,7,10}, {4,6}, {9} 所组成的森林
图 (b) 表示由元素 1 所在集合、与元素 7 所在集合合并的情况

算法复习大纲
该数据结构的缺点
树的高度可能很大,变成退化树,成为线性表

union(x,y)操作
若 x 和 y 是当前森林中两棵不同树的根结点,
如果 rank(x) > rank(y) 把 x 作为 y 的父亲
如果 rank(x) < rank(y) 把 y 作为 x 的父亲
如果 rank(x) = rank(y) 把 x 作为 y 的父亲,rank(x) + 1

Find

路径压缩

find(x) 操作时,找到 x 的根结点 y 之后,再沿着 x 到 y 的路径,改变路径上所有结点的父指针,使其直接指向 y

算法复习大纲

(a) 表示集合 {1,2,3,4}, {5,6,7,8}

b) 表示执行 union(4,6) 之后的结果

算法复习大纲

递归

阶层

计算阶乘函数 n!
阶乘函数可归纳定义为

算法复习大纲

递归算法如下:

public class 递归阶层 {
    public static void main(String[] args) {
        int n =5;
        System.out.println(f(n));
    }
    public static int f(int n){
        if(n==0||n==1){
            return 1;
        }
        return n*f(n-1);
    }
}

斐波那契数列

关系式:

F(1)=F(2)=1;

F(n)=F(n-1)+F(n-2) (n≥3)

递归算法如下:

public class 斐波那契数列 {
    public static void main(String[] args) {
        int n = 20;
        int f = f(n);
        System.out.println(f);
    }
    public static int f(int n){
        if (n==1||n==2){
            return 1;
        }
        return f(n-1)+f(n-2);
    }
}

整数幂的计算

int power(int x,int n){
	int y=0;
	if(n==0)y==1;
	else{
		y=power(x,x/2);
		y=y*y;
		if(n%2==1)
		y=y*x;
	}
	return y;

}

递归(2)

数组主元素

 A 是具有 n 个元素的数组,x 是 A 中的一个元素,若 A中有一半以上的元素与 x 相同,就称 x 是数组的主元素。

例:数组 A={1,3,2,3,3,4,3} 中,
元素 3 是该数组的主元素

编程

public int getCandidate(int nums[], int begin, int end ){
    int j = begin,count = 1;
    int c = nums[j];
    while(j<end-1 && count>0) {
        j++;
        if(nums[j]==c) {
            count = count + 1;
        }else {
            count = count - 1;
        }
    }
    if(j==end-1 && count>0) {
        return nums[j];                      //当剩余的时候说明很有可能是组元素,此时我们返回此时下标到验证函数中验证
    }else if(j==end-1 && count == 0 ) {
        return 0;                       //返回0代表没有组元素
    }else {
        return getCandidate(nums,j,end);      //递归调用
    }
}

分治

分治法解最大最小问题的过程

分治法解最大最小问题的过程例子:

算法复习大纲

合并排序的分治算法

算法的实现

merge_sort(Type A[ ], int low, int high)
      {    int mid;
           if (high > low)
           {    mid = (high – low) / 2;
                 merge_sort(A[ ], low, mid);
                 merge_sort(A[ ], mid + 1, high);
                 merge(A[ ], low, mid, high, high – low);
           }
      }       

快速排序

把序列就地划分为两个子序列,使第一个子序列的所有元素都小于第二个子序列的所有元素,不断地进行这样的划分,最后构成 n 个子序列,每个子序列只有一个元素,这时,整个序列就是按递增顺序排序的序列了

枢点元素:

把序列的第一个元素作为枢点元素,重新排列这个序列

void quick_sort(Type A[ ], int low, int high)
{
   int k;
   if (low < high) {
      k = split(A, low, high);
      quick_sort(A, low, k-1);
      quick_sort(A, k+1, high);
   }
}

快速排序下列数字:
8,1,4,9,0,3,5,2,7,6

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-82AfxdOV-1625552480506)(http://t4king.oss-cn-beijing.aliyuncs.com/uPic/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F(1)].png)

线性选择

以下数求出第三大需要几次分区

137,96,88,108,17,87,65,35,76,45,66,18

(a)17,18,88,108,137,87,65,35,76,45,66,96

(b)88,66,45,87,65,35,76,96,108,137

以下数求出第五小需要几次分区

8 1 4 9 0 3 5 2 7 6

(a) 2 1 4 5 0 3 6 9 2 7

(b) 2 1 0 3 4 5

© 4

分治(2)选择问题

中值(5个元素为一组)

① 若算法复习大纲,直接排序数组,第 k 个元素即为所求元素;否则,转 ②

② 把元素划分为 p = ⌊n / 5 ⌋ 组,每组 5 个元素,不足 5 个元素的那一组不予处理
③ 取每组的中值元素,构成一个规模为 p 的数组 M
④ 对数组 M 递归地执行算法,得到一个中值的中值元素 m
⑤ 把原数组划分成三组,使得大于 m 的元素存放于 P,等于 m 的元素存放于 Q,小于 m 的元素存放于 R
⑥ 如果 | P | > k,对 P 递归地执行算法;否则转 ⑦
⑦ 如果 | P | + | Q | > k,m 就是所选择的元素;否则转8;
⑧ 对 Q 递归地执行算法。

例题

找出下面37个元素的第16大元素;

35, 43, 2, 19, 28, 62, 36, 7, 5, 13, 25, 13, 32, 11, 1, 9, 12, 23, 37, 39, 58, 43, 41, 51, 27, 8, 26, 34, 22, 15, 19, 54, 48, 30, 24, 6, 10

算法复习大纲

贪婪算法

不断地从问题的 n 个元素中选取一个最优的元素的取值,作为局部解向量中的一个分量,使其既满足约束方程,又使目标函数取极值最快,当 n 个元素的取值均求取之后,解向量就成为完整的向量,它就是问题的解

背包问题

载重量为 M 的背包,重量为算法复习大纲、价值为算法复习大纲 的物体,1 ≤ i ≤ n,把物体装满背包,使背包内的物体价值最大
物体可以分割的背包问题,及物体不可分割的背包问题,把后者称为 0/1 背包问题

背包问题(可以分割),n=7,m=20的

载重价值12,7,5,19,20,18,13

重量为 4,5,3,9,10,11,18

载重价值 12 7 5 19 20 18 13
重量 4 5 3 9 10 11 18
/ / / / / / / /
平均价值 3 1.4 1.7 2.1 2 1.63 0.72
☑️ ☑️ ☑️

价值最大:12+19+2*7=45

单元最短路径

狄斯奎诺(Dijkstra)算法

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

普里姆

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

克鲁斯卡尔

算法复习大纲

算法复习大纲

霍夫曼编码

算法复习大纲

WTL算法(一):

所有根结点相加

WTL=17+32+63+59+122+132+87+254+172+426=1364

WTL算法(二):

所有叶子结点*层数相加

85 * 2 + 43 * 3 + 44 * 3…

深度优先DFS

(先往深的走,走到头了,就后退)栈

算法复习大纲

广度优先BFS

算法复习大纲

动态规划

货郎担

由城市 1 出发,经城市 2, 3, 4然后返回1的最短路径长度为:

算法复习大纲

算法复习大纲

多段图最短路径

求解图所示的最短路径问题

算法复习大纲

算法复习大纲

算法复习大纲

算法复习大纲

最长公共子序列

字符串A=xyxxyx B=yxxxy 求最长公共子序列

空集 x y x x y x
空集 0 0 0 0 0 0 0
y 0 0 1 1 1 1 1
x 0 1 1 2 2 2 2
x 0 1 1 2 3 3 3
x 0 1 1 2 3 3 4
y 0 1 2 2 3 4 4

1.yxxy

2.xxxy

背包问题

(不可分割)6个物体,重量:4,2,2,1,3,2。价值:3,6,5,4,3,4。载重为8.

0 1 2 3 4 5 6 7 8
0 0 0 0 0 0 0 0 0 0
1 0 0 4 4 4 4 4 4 4
2 0 0 4 4 4 7 7 7 7
3 0 4 4 8 8 8 11 11 11
4 0 4 5 9 9 13 13 13 16
5 0 4 6 10 11 15 15 19 19
6 0 4 6 10 11 15 15 19 19

{0,1,1,1,0,1}

时间复杂度

算法复习大纲

上一篇:Arrays类 2021-05-23


下一篇:leetcode——第96题——不同的二叉搜索树