算法排序:递归、回溯、数论、插入、希尔、归并、选择、冒泡、快排、贪心、动态规划

数论思想:利用数学公式或者定理或者规律求解问题;

算法思想中最难的点:递归+动态规划;树论:二叉树,红黑树

思考题:

  1. 微信分销系统中有一个返利,大家应该都知道,比如B是A的下线,C是B的下线,那么在分钱返利的时候A可以分B,C的钱,这时候我们是不是就要分别找B,C的最后上级。这个问题我们一般怎么来解决呢?

  2. 斐波那契数列:1 1 2 3 5 8 13 21 有什么特点?从第三个数开始 就等于前面两个数相加; 求解公式:f(n)=f(n-1)+f(n-2) 终止条件:n<=2 f(n)=1

递归

递归的定义

比如我们在某窗口排队人太多了,我不知道我排在第几个,那么我就问我前面的人排第几个,
因为知道他排第几我就知道我是第几了。但前面的人也不知道自己排第几那怎么办呢?他也可以继续往前面问,直到问到第一个人,然后从第一个人一直传到我这里 我就很清楚的知道我是第几了。以上这个场景就是一个典型的递归。我们在这个过程中大家有没有发现一个规律那么就是会有一个问的过程,问到第一个后有一个回来的过程吧。这就是递(问)加归(回)。那么这个过程我们是不是可以用一个数学公式来求解呢?那这个数学公式又是什么?

f(n)=f(n-1)+1

f(n):表示我的位置

f(n-1):表示我前面的那个人;

自己调用自己;

递归应用场景

  1. 一个问题的解可以分解为几个子问题的解:子问题,我们通过分治的思想可以把一个数据规模大的问题,分解为很多小的问题。
    我们可以把刚刚那个问前面的那个人看为子问题。大化小

  2. 这个问题与分解之后的子问题,求解思路完全一样

  3. 一定有一个最后确定的答案,即递归的终止条件:刚刚那个问题就是第一个人。第一个人是肯定知道自己排第几吧即n=1的时候,如果没有这个特性那么我们这个递归就会出现死循环,最后程序就是栈溢出;stack out of

递归的时间和空间复杂度分析

以斐波那契数列为例为分析递归树:f(n)=f(n-1)+f(n-2)

时间复杂度和空间复杂度都是:O(2^n)=>O(n)或者O(nlogn)

递归优化

  1. 使用非递归: 所有的递归代码理论上是一定可以转换成非递归的
  2. 加入缓存:把我们中间的运算结果保存起来,这样就可以把递归降至为o(n)
  3. 尾递归:什么是尾递归?尾递归就是调用函数一定出现在末尾,没有任何其他的操作了。因为我们编译器在编译代码时,如果发现函数末尾已经没有操作了,这时候就不会创建新的栈,而且覆盖到前面去。倒着算,不需要在回溯了,因为我们每次会把中间结果带下去。
// 斐波纳契/微信分销系统
// 1 1 2 3 5 8 13
// f(n) = f(n-1) + f(n-2)
// 递归
// 递归优化
// 1. 使用非递归
// 2. 加入缓存
// 3. 尾递归
// 递归注意事项----栈溢出和时间问题
public class FibonacciSeq {//递归 40 : 102334155 耗时:316 mspublic static int fab(int n) { // 时间复杂度/空间复杂度 O(2^n) => 如何优化if (n <= 2) return 1;return fab(n - 1) + fab(n - 2);}//尾递 第一个优化 40 : 102334155 耗时:0 mspublic static int noFab(int n) { // 不使用递归-节约空间if (n <= 2) return 1;int a = 1;int b = 1;int c = 0;for (int i = 3; i <= n; i ++) {c = a + b;a = b;b = c;}return c;}//尾递 40 : 102334155 耗时:0 mspublic static int noFabSimple(int data[], int n) { // 不使用递归--占用空间if (n <= 2) return 1;data[1] = 1;data[2] = 1;for (int i = 3; i <= n; i ++) {data[i] = data[i - 1] + data[i - 2];}return data[n];}//尾递 40 : 102334155 耗时:0 mspublic static int fab2(int data[], int n) {if (n <= 2) return 1;if (data[n] > 0) return data[n];int res = fab2(data,n-1) + fab2(data,n-2);data[n] = res;return res;}//尾递: 改成尾递归 prepre 上上一次运行结果  pre 上次运行结果public static int tailFab2(int n, int prepre, int pre) {if (n <= 2) return pre;return tailFab2(n - 1, pre, pre + prepre);}//求N的阶乘 用普通的递归怎么写 5=5*4*3*2*1 => f(n) = n * f(n-1)public static int fac(int n) {if (n <= 1) return 1;return n * fac(n - 1);}//改成尾递归 求N的阶乘 用普通的递归怎么写 5=5*4*3*2*1 => f(n) = n * f(n-1)public static int tailFac(int n, int res) {//尾递归if (n <= 1) return res;return tailFac(n-1, n * res);}public static void main(String[] args) {//        for (int i = 1; i <= 40; i++) {//            long start = System.currentTimeMillis();
//            System.out.println(i + " : " + fab(i) + " 耗时:" + (System.currentTimeMillis() - start) + " ms");
//        }
//
//        for (int i = 1; i <= 40; i++) {//            long start = System.currentTimeMillis();
//            System.out.println(i + " : " + noFab(i) + " 耗时:" + (System.currentTimeMillis() - start) + " ms");
//        }
//
//        data = new int[41];
//        for (int i = 1; i <= 40; i++) {//            long start = System.currentTimeMillis();
//            System.out.println(i + " : " + noFabSimple(data, i) + " 耗时:" + (System.currentTimeMillis() - start) + " ms");
//        }
//
//        data = new int[41];
//        for (int i = 1; i <= 40; i++) {//            long start = System.currentTimeMillis();
//            System.out.println(i + " : " + fab2(data, i) + " 耗时:" + (System.currentTimeMillis() - start) + " ms");
//        }
//
//        for (int i = 1; i <= 40; i++) {//            long start = System.currentTimeMillis();
//            System.out.println(i + " : " + tailFab2(i, 1, 1) + " 耗时:" + (System.currentTimeMillis() - start) + " ms");
//        }
//
//
//        for (int i = 1; i <= 10; i++) {//            long start = System.currentTimeMillis();
//            System.out.println(i + " : " + tailFac(i, 1) + " 耗时:" + (System.currentTimeMillis() - start) + " ms");
//        }
//
//        for (int i = 1; i <= 10; i++) {//            long start = System.currentTimeMillis();
//            System.out.println(i + " : " + fac(i) + " 耗时:" + (System.currentTimeMillis() - start) + " ms");
//        }}
}
/**递归1 : 1 耗时:0 ms2 : 1 耗时:0 ms3 : 2 耗时:0 ms4 : 3 耗时:0 ms5 : 5 耗时:0 ms6 : 8 耗时:0 ms7 : 13 耗时:0 ms8 : 21 耗时:0 ms9 : 34 耗时:0 ms10 : 55 耗时:0 ms11 : 89 耗时:0 ms12 : 144 耗时:0 ms13 : 233 耗时:0 ms14 : 377 耗时:0 ms15 : 610 耗时:0 ms16 : 987 耗时:1 ms17 : 1597 耗时:0 ms18 : 2584 耗时:0 ms19 : 4181 耗时:0 ms20 : 6765 耗时:0 ms21 : 10946 耗时:0 ms22 : 17711 耗时:0 ms23 : 28657 耗时:1 ms24 : 46368 耗时:0 ms25 : 75025 耗时:0 ms26 : 121393 耗时:1 ms27 : 196418 耗时:1 ms28 : 317811 耗时:1 ms29 : 514229 耗时:1 ms30 : 832040 耗时:4 ms31 : 1346269 耗时:4 ms32 : 2178309 耗时:7 ms33 : 3524578 耗时:11 ms34 : 5702887 耗时:17 ms35 : 9227465 耗时:30 ms36 : 14930352 耗时:50 ms37 : 24157817 耗时:90 ms38 : 39088169 耗时:145 ms39 : 63245986 耗时:242 ms40 : 102334155 耗时:316 ms不使用递归0 : 1 耗时:0 ms1 : 1 耗时:0 ms2 : 1 耗时:0 ms3 : 2 耗时:0 ms4 : 3 耗时:0 ms5 : 5 耗时:0 ms6 : 8 耗时:0 ms7 : 13 耗时:0 ms8 : 21 耗时:0 ms9 : 34 耗时:0 ms10 : 55 耗时:0 ms11 : 89 耗时:0 ms12 : 144 耗时:0 ms13 : 233 耗时:0 ms14 : 377 耗时:0 ms15 : 610 耗时:0 ms16 : 987 耗时:0 ms17 : 1597 耗时:0 ms18 : 2584 耗时:0 ms19 : 4181 耗时:0 ms20 : 6765 耗时:0 ms21 : 10946 耗时:0 ms22 : 17711 耗时:0 ms23 : 28657 耗时:0 ms24 : 46368 耗时:0 ms25 : 75025 耗时:0 ms26 : 121393 耗时:0 ms27 : 196418 耗时:0 ms28 : 317811 耗时:0 ms29 : 514229 耗时:0 ms30 : 832040 耗时:0 ms31 : 1346269 耗时:0 ms32 : 2178309 耗时:0 ms33 : 3524578 耗时:0 ms34 : 5702887 耗时:0 ms35 : 9227465 耗时:0 ms36 : 14930352 耗时:0 ms37 : 24157817 耗时:0 ms38 : 39088169 耗时:0 ms39 : 63245986 耗时:0 ms40 : 102334155 耗时:0 ms*/

排序性能分析

  1. 时间效率:决定了算法运行多久,O(1)
  2. 空间复杂度
  3. 比较次数&交换次数
  4. 稳定性 1 9 *3 5 3 第一种:1 *3 3 5 9 第二种:1 3 *3 5 9 相同的两个数排完序后,相对位置不变。稳定排序有什么意义?应用在哪里呢? 例如电商订单排序(从小到大排,金额相同的按下单时间)

插入排序

看以下这个例子:对7 8 9 0 4 3进行插入排序
7 8 9 0 4 3
7 8 9 0 4 3
7 8 9 0 4 3
0 7 8 9 4 3
0 4 7 8 9 3
0 3 4 7 8 9

 public static int[] insertSort(int arr[]) {for (int i = 1; i < arr.length; i++) {int curr = arr[i];int pre = i - 1;for (; pre >= 0 ; pre--) {if (curr < arr[pre]) {arr[pre+1] = arr[pre];} else {break;}}arr[pre+1] = curr;}return arr;}

希尔排序

增量分段:add=n/2 n=10 =>5,2,1

   public static void shellSort(int data[]) {int n = data.length;for (int add = n/2; add >= 1 ; add/=2) {for (int i = add; i < n; i++) {int temp = data[i];int j = i - add;for (; j >= 0; j-=add) {if (data[j] > temp) {data[j + add] = data[j];} else {break;}}data[j+add] = temp;}}}

归并排序

public static void mergeSort(int[] arr, int left, int right) {if (left < right) {int mid = (left + right)/2;mergeSort(arr, left, mid);mergeSort(arr, mid+1, right);merge(arr, left, mid, right);}}public static void merge(int[] arr, int left, int mid, int right) {int temp[] = new int[arr.length];int leftPoint = left;int rightPoint = mid + 1;int cur = left; //当前位置while (leftPoint <= mid && rightPoint <= right) {if (arr[leftPoint] < arr[rightPoint]) {temp[cur] = arr[leftPoint];leftPoint++;} else {temp[cur] = arr[rightPoint];rightPoint++;}cur++;}while (leftPoint <= mid) {temp[cur++] = arr[leftPoint++];}while (rightPoint <= right) {temp[cur++] = arr[rightPoint++];}for (int i = left; i <= right; i++) {arr[i] = temp[i];}}

选择

选择排序的思路和插入排序非常相似,也分已排序和未排序区间。但选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。但是不像插入排序会移动数组 选择排序会每次进行交换

    public static int[] selectSort(int data[]) {for (int i = 0; i < data.length -1; i++) {int minloc = i;for (int j = i+1; j < data.length; j++) {if (data[j] < data[minloc]) {minloc = j;}}int minTemp = data[minloc];data[minloc] = data[i];data[i] = minTemp;}return data;}

冒泡

核心思路:冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作。

第一次冒泡的结果:4 5 6 3 2 1->4 5 3 6 2 1 - > 4 5 3 2 6 1 -> 4 5 3 2 1 6,哪个元素的位置确定了,6
第二次冒泡的结果:4 5 3 2 1 6->4 3 5 2 1 6 -> 4 3 2 5 1 6 -> 4 3 2 1 5 6
第三次冒泡的结果:4 3 2 1 5 6->3 4 2 1 5 6 -> 3 2 4 1 5 6 -> 3 2 1 4 5 6
第四次冒泡的结果:3 2 1 4 5 6->2 3 1 4 5 6 -> 2 1 3 4 5 6
第五次冒泡的结果:2 1 3 4 5 6->1 2 3 4 5 6

    public static int[] dubbleSort(int data[]) {for (int i = 0; i < data.length; i++) {for (int j = i+1; j < data.length; j++) {if (data[j] < data[i]) {int temp = data[j];data[j] = data[i];data[i] = temp;}}}return data;}
    public static void dubbleSortTest(int arr[]) {for (int i = 0; i < arr.length-1; i++) {boolean flag = false;for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j+1]) {int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;flag = true;}}if (!flag) break;}}

快排


快排和归并的对比:

  1. 归并排序的处理过程是由下到上的,先处理子问题,然后再合并。
  2. 快排其实就是从上到下,先分区,在处理子问题,不用合并。
    其优化就是优化基准数,提供一个取三个数中间的思路.

45 28 80 90 50 16 100 10
基准数:一般就是取要排序序列的第一个。
第一次排序基准数:45
从后面往前找到比基准数小的数进行对换:
*10 28 80 90 50 16 100 *45
从前面往后面找比基准数大的进行对换:
10 28 *45 90 50 16 100 *80
。。。
以基准数分为3部分,左边的比之小,右边比之大:
{10 28 16} 45 {50 90 100 80}
到此第一次以45位基准数的排序完成。

public static void quickSort(int data[], int left, int right) {int base = data[left]; //基准数int ll = left; //从左边找的位置int rr = right; //从右边找的位置while (ll < rr) {//从右边找比基数小的数while (ll < rr && data[rr] >= base) {rr--;}if (ll < rr) { //表示有找到比之大的int temp = data[rr];data[rr] = data[ll];data[ll] = temp;ll++;}while (ll < rr && data[ll] <= base) {ll++;}if (ll < rr) {int temp = data[rr];data[rr] = data[ll];data[ll] = temp;rr--;}}if (left < ll)quickSort(data, left, ll-1);if (ll < right)quickSort(data, ll+1, right);}

对比

贪心算法

概念

概念:贪心算法又叫做贪婪算法,它在求解某个问题是,总是做出眼前最大利益。
也就是说只顾眼前不顾大局,所以它是局部最优解。核心点:通过局部最优推出全局最优

贪心算法的套路:一定会有一个排序。哈夫曼编码,贪心算法,压缩算法。最短路径

思考题

1.某天早上公司领导找你解决一个问题,明天公司有N个同等级的会议需要使用同一个会议室,现在给你这个N个会议的开始和结束
时间,你怎么样安排才能使会议室最大利用?即安排最多场次的会议?电影的话 那肯定是最多加票价最高的,入场率。综合算法

2.双十一马上就要来了,小C心目中的女神在购物车加了N个东西,突然她中了一个奖可以清空购物车5000元的东西(不能找零),每个东西只能买一件,那么她应该如何选择物品使之中奖的额度能最大利用呢?如果存在多种最优组合你只需要给出一种即可,嘿嘿 现在女神来问你,你该怎么办?

/*** 贪心算法* 最优* 最短* 最好** 先按照开始时间排序, 之后按照当前开始时间,比较开始时间是否大于结束时间*/
public class Meeting implements Comparable<Meeting> {int meNum;int startTime;int endTime;public Meeting(int meNum, int startTime, int endTime) {super();this.meNum = meNum;this.startTime = startTime;this.endTime = endTime;}@Overridepublic int compareTo(Meeting o) {if (this.endTime > o.endTime) {return 1;}return -1;}@Overridepublic String toString() {return "GreedySort{" +"meNum=" + meNum +", startTime=" + startTime +", endTime=" + endTime +'}';}/*** 4* 0 9* 8 10* 10 12* 8 20* GreedySort{meNum=1, startTime=0, endTime=9}* GreedySort{meNum=3, startTime=10, endTime=12}*/public static void main(String[] args) {Scanner scanner = new Scanner(System.in);List<Meeting> meetings = new ArrayList<>();int n = scanner.nextInt(); //会议for (int i = 0; i < n; i++) {int start = scanner.nextInt();int end = scanner.nextInt();Meeting meeting = new Meeting(i+1, start, end);meetings.add(meeting);}meetings.sort(null);int curTime = 0; //当前时间,从一天的0点开始for (int i = 0; i < n; i++) {Meeting meeting = meetings.get(i);if (meeting.startTime >= curTime) {System.out.println(meeting.toString());curTime = meeting.endTime;}}}
}

动态规划

思考题–背包问题:小偷去某商店盗窃,背有一个背包,容量是50kg,现在有以下物品(物品不能切分,且只有一个),请问小偷应该怎么拿才能得到最大的价值?

物品 重量 价值
物品1 10kg 60元
物品2 20kg 100元
物品3 40kg 120元

5kg的袋子

物品 重量 价值
物品1 1 6
物品2 2 10
物品3 4 12

把5kg的袋子,拆分成1kg,1kg这样子计算,里面的表格就表示当前重量下能装的最多的钱。表格的数列就表示是要装的物品

物品 1kg 2kg 3kg 4kg 5kg
加入物品1 6 6 6 6 6
加入物品2 6 10 10+6=16 10+6=16 16
加入物品3 6 10 16 16 18
/*** 背包算法* 购物车问题保存价值一样就可以*/
public class Backpack {public static List<Integer> group(int dp[][], int good_list[]) {int value_max = dp[0].length - 1;int good_max = dp.length - 1;List<Integer> good_group = new ArrayList();while (value_max > 0 && good_max > 0) {if (dp[good_max][value_max] <= dp[good_max-1][value_max]) {good_max -= 1;} else {good_group.add(good_max);value_max -= good_list[good_max-1];good_max -= 1;}}return good_group;}public static int cart(int weight[], int lw) {int n = weight.length;int dp[][] = new int[n+1][lw+1]; //n表示物品、w表示重量,初始化全是0for (int i = 1; i <= n; i++) { //每次加的物品for (int w = 1; w <= lw; w++) {if (weight[i-1] <= w) { //当前物品重量小于分割重量 表示这个物品可以装进去dp[i][w] = Math.max(weight[i-1] + dp[i-1][w-weight[i-1]], dp[i-1][w]);} else {dp[i][w] = dp[i-1][w];}}}List<Integer> good_group = group(dp, weight);System.out.print("组合:");for (Integer integer : good_group) {System.out.print(integer + "\t");}System.out.println();return dp[n][lw];}public static int backpack(int value[], int weight[], int lw) {int n = weight.length;int dp[][] = new int[n+1][lw+1]; //n表示物品、w表示重量,初始化全是0for (int i = 1; i <= n; i++) { //每次加的物品for (int w = 1; w <= lw; w++) {if (weight[i-1] <= w) { //当前物品重量小于分割重量 表示这个物品可以装进去dp[i][w] = Math.max(value[i-1] + dp[i-1][w-weight[i-1]], dp[i-1][w]);} else {dp[i][w] = dp[i-1][w];}}}List<Integer> good_group = group(dp, weight);System.out.print("组合:");for (Integer integer : good_group) {System.out.print(integer + "\t");}System.out.println();return dp[n][lw];}/*** 组合:4 3   1* 8* 组合:3   1* 180*/public static void main(String[] args) {System.out.println(cart(new int[]{1,2,3,4,5,9},8));System.out.println(backpack(new int[]{60, 100, 120},new int[]{10, 20, 30},40));}
}

数据结构与算法(二):排序(递归、回溯、数论、插入、希尔、归并、选择、冒泡、快排、贪心、动态规划)相关推荐

  1. 常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构)

    常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构) 数据结构和算法作为程序员的基本功,一定得稳扎稳打的学习,我们常见的框架底层就是各类数据 ...

  2. 数据结构排序算法实验报告_[数据结构与算法系列]排序算法(二)

    我的上一篇文章向大家介绍了排序算法中的冒泡排序.插入排序和选择排序.它们都是平均时间复杂度为 O(n^2) 的排序算法,同时还为大家讲解了什么是原地排序和什么是排序的稳定性.下图是这三种算法的比较,不 ...

  3. 数据结构与算法(一)回溯

    数据结构与算法(一)回溯(backtrack) 回溯算法是对树形或者图形结构执行一次深度优先遍历,实际上类似枚举的搜索尝试过程,在遍历的过程中寻找问题的解. 深度优先遍历有个特点:当发现已不满足求解条 ...

  4. 【数据结构与算法】排序优化

    冒泡.插入.选择 O(n^2) 基于比较 快排.归并 O(nlogn) 基于比较 计数.基数.桶 O(n) 不基于比较 总结:如何实现一个通用的高性能的排序函数? 一.如何选择合适的排序算法? 1.排 ...

  5. 数据结构与算法之排序算法

    数据结构与算法之排序算法 排序算法的介绍 ​ 排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排序的过程. 排序的分类 1)内部排序:指将需要处理的数据都加载到内部 ...

  6. 从零开始学数据结构和算法(二)线性表的链式存储结构

    链表 链式存储结构 定义 线性表的链式存储结构的特点是用一组任意的存储单元的存储线性表的数据元素,这组存储单元是可以连续的,也可以是不连续的. 种类 结构图 单链表 应用:MessageQueue 插 ...

  7. 数据结构与算法(Python)– 回溯法(Backtracking algorithm)

    数据结构与算法(Python)– 回溯法(Backtracking algorithm) 1.回溯法 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条 ...

  8. 在Object-C中学习数据结构与算法之排序算法

    笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速 ...

  9. 数据结构与算法之暴力递归改动态规划

    数据结构与算法之暴力递归改动态规划 目录 二维数组最小路径和 暴力递归改动态规划解析 任意选择数组arr中的数字,看能不能累加得到aim 1. 二维数组最小路径和 (一) 题目描述 (二) 思路 递归 ...

  10. 数据结构与算法(三) 排序算法(代码示例)

    数据结构与算法三 排序算法 1. 选择排序 2. 插入排序 3. 冒泡排序 4. 归并排序 5. 快速排序 6. 希尔排序 7. 堆排序 总结 1. 选择排序 选择排序的基本原理: 对于未排序的一组记 ...

最新文章

  1. unity-tweak-tool不能打开的解决办法
  2. 看准网点评没有了_大众点评“亡”于2020
  3. zbb20170606 oracle 查看空表
  4. 解决ubuntu中连接mysql时报错:Access denied for user ‘root‘@‘localhost‘
  5. 图解Go语言内存分配
  6. java jinq_将JINQ与JPA和H2一起使用
  7. 《Android进阶之光》--View体系与自定义View
  8. 零基础自学编程应读书籍
  9. SecureCRT配置前--Linux网卡设置
  10. php类知识点滴---类的实例化,构造函数,继承初步
  11. UIImage保存到相册
  12. 9. 工作区和暂存区
  13. wps mysql ubuntu_Ubuntu 安装WPS
  14. 【WordPress】小卡的土豆园开张
  15. 如何开始使用接口自动化测试脚本
  16. 关于十二平均律及律学发展简史
  17. 伯爵写给女巫的一封信
  18. macos 系统固件 路径_itunes下载固件在哪里 itunes下载固件位置【介绍】
  19. html tr隐藏 边框存在,CSS 设置tr的边框
  20. linux c openssl aes 加解密

热门文章

  1. 小程的自学编程路途起点
  2. mac终端查看php版本_Mac切换php版本方法
  3. 什么是interrupt
  4. 使用shapeit进行单倍型分析
  5. 微信小程序——获取用户个人信息
  6. 【vue js】省市区js数据转为tree结构
  7. Quick Reference 代码速查表
  8. Mac解决JAVA_HOME问题
  9. keras中的目标函数和优化函数
  10. MultiTimer | 一款可无限扩展的软件定时器