1、该系列为ACWing中算法基础课,已购买正版,课程作者为yxc
2、y总培训真的是业界良心,大家有时间可以报一下
3、为啥写在这儿,问就是oneNote的内存不够了QAQ

ACwing C++ 算法笔记1 基础算法

  • 一、排序
    • 1.1 快排
    • 1.2 归并排序
    • 1.3 快速选择算法
  • 二、二分
    • 2.1 整数二分
    • 2.2 浮点数二分

本节内容:排序(快排、归并排序)、二分(整数二分、浮点数二分)

一、排序

排序算法中稳定:如果说原序列中两个值是相同的,排完序后两个值的位置不发生变化则是稳定的,可能发生变化就是不稳定的。
推荐阅读:十大排序算法(力扣)、十大排序算法总结(ACWing)

1.1 快排

  • 快排基于分治的思想,是不稳定的算法,但是如果将快排的 a i a_{i} ai​变为 < a i , i > <a_{i},i> <ai​,i>的二元组(相同的数变为不同的数),就是稳定的算法;
  • 时间复杂度为O(NlogN),最坏N^2
  • 快排的步骤:
      1. 确定分界点:
      • 确定分界点的常用方式:(1) 直接取左边界q[l];(2) 取两端的中间点q[(l+r)/2],(3) 取右边界q[r];(4) 取随机点;
      1. 调整区间:(假设确定x为分界点)满足小于等于x的在左边,大于等于x的在右边;
      1. 递归:递归的处理左右两段区间;

=============================================================

  • 调整区间的简单实现方法1(暴力做法但时间复杂度是线性的):

    • 1、先开两个额外的数组 a[],b[]
    • 2、扫描整个区间 q[l-r],小于等于x插到a,大于x插到b;
    • 3、将数组 a[],b[]的数据放入q[]中;
  • 调整区间的实现方法2(双指针):

    • 1、用两个指针i,j,从两边同时向中间走;
    • 2、先开始移动ii指向的数字小于x,则i后移一位;直到如果数字大于等于x(应该放在右边),则停止移动i,开始持续移动j
    • 3、当j指向的数大于x,持续移动j;当j指向的数小于xi,j的数字错位(此时i指向的数需要放到右边,j指向的数需要放到左边),交换i,j指向的两个数字,并继续移动i,j,直到两个指针相遇;(注意,这里不需要交换的两个数字在新的区间里是有顺序的,它的顺序会在下一次递归里进行排序)

快排代码实现:

在C++输入大量的数字时建议用scanf,而不是cin;同理,JAVA中不用sanner,而是BufferedReader

#include <iostream>using namespace std;const int N = 100010;int q[N];void quick_sort(int q[], int l, int r)
{if (l >= r) return;// 判断边界:没有数或只有1个数就returnint i = l - 1, j = r + 1, x = q[l + r >> 1];// 两侧和中间的指针while (i < j){do i ++ ; while (q[i] < x); // q[i] <= x 会发生数组越界do j -- ; while (q[j] > x);if (i < j) swap(q[i], q[j]);// 或设置第三个变量交换}quick_sort(q, l, j); quick_sort(q, j + 1, r);
}int main()
{int n;scanf("%d", &n);for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);quick_sort(q, 0, n - 1);for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);return 0;
}
  • 注意循环while (q[i] < x)不能写为q[i]<=x ,否则会一直满足<=关键值得这个条件,就会发生数组越界(如49,59,88, 37,98,97,68,54,31,3,其中x=98)

  • 两个指针交换完之后都要移动一格,因此设计ij都在边界外,不管三七二十一先移动左右指针,再判断;

  • x可以取q[l]q[(l+r)/2]q[r]

  • 如果在quick_sort(q, l, j); quick_sort(q, j + 1, r);时取x = r ;或在quick_sort(q, l, i-1); quick_sort(q, i, r);时取x = l 会面临边界造成的quick_sort()函数递归死循环的问题。例如长度为2的区间[1, 2],如果取x = q[l],那么划分结束后会分成一个长度是0的区间quick_sort(q, l, i-1)——>quick_sort(q, 0, -1)和一个长度是2的区间quick_sort(q, i, r)——>quick_sort(q, 0, 1),就无限递归了。具体代码如下:

  • j为中间点:

  • i为中间点:

  • 注意:由于使用do-while循环,所以ij一定会自增!!,使得循环会继续下去,但是如果采用while循环(ij的初始化做出对应的变更),ij在特殊情况下不自增的话,循环就会卡死;

  • 在循环中产生的边界问题

    • quick_sort(a, l, j); quick_sort(a, j + 1, r);为什么不能换成 quick_sort(a, l, i); quick_sort(a, i + 1, r)(即将 j+1 换成 i+1 作为中间区域的边界 / 为什么不能将 i-1 换为 j-1)?

      • 比如 x=3, 一段数 ,2,4,5,*,此时i走到了4下面,j走到了2下面,quick_sort(a, l, i); 中,左边区间包括了一个大于x=3的4,会导致排序错误。所以如果是 i 的话,i 要包括在右边区间里面,也就是 quick_sort(a, l, i-1); quick_sort(a, i, r);
    • do i++; while(q[i] < x)do j--; while(q[j] > x)不能用q[i] <= xq[j] >= x
      • 假设q[l..r]全相等则执行完do i++; while(q[i] <= x);之后,i会自增到r+1;然后继续执行q[i] <= x 判断条件,造成数组下标越界(但这貌似不会报错) 并且如果之后的q[i] <= x (此时i > r) 条件也不幸成立,就会造成一直循环下去,造成内存超限(Memory Limit Exceeded)
    • while循环代替do-while:用while(q[i] < x) i++;while(q[j] > x) j--;判断, 当q[i]q[j]都为 x 时, ij 都不会更新,导致 while 陷入死循环。(应改为while(q[i] <= x) i++; while(q[j] >= x) j--;)。可以代替为以下代码,这样即使循环结束时q[i]==q[j]==xi,j也能更新。
另一种快排方法
int partition( int[] nums, int left, int right)
{int pivot = nums[left]; // 左边第一个数为基准数int i = left + 1;int j = right;while(true){  //向右遍历扫描while(i <= j && nums[i] <= pivot) i++;//向左遍历扫描while(i <= j && nums[j] => pivot) j--;if(i >= j)break;//交换int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}//把nums[j]和基准数交换nums[left] = nums[j];nums[j] = povit;return j;
}void quickSort(int[] nums, int l, int r) {// 子数组长度为 1 时终止递归if (l >= r) return;// 哨兵划分操作int i = partition(nums, l, r);// 递归左(右)子数组执行哨兵划分quickSort(nums, l, i - 1);quickSort(nums, i + 1, r);
}// 调用
int main()
{vector<int> nums = { 4, 1, 3, 2, 5, 1};quickSort(nums, 0, nums.size() - 1);for (int i = 0; i < nums.size(); i ++ ) printf("%d ", nums[i]);return 0;
}
  • 快排的边界问题:取中间区域的值作为基准值也需要考虑向上还是向下取整的问题,想要用 i - 1 和 i 的话,需要用 x = q[l + r + 1 >> 1]x = q[r]作为基准值;用 j 和 j + 1 的时候,需要用 x = q[l + r >> 1]x = q[l]

============================================================================================

  • java模板1

    import java.util.*;
    import java.io.*;
    public class Main{public static void main(String[] args) throws IOException{BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(reader.readLine());int[] arr = new int[n];String[] strs = reader.readLine().split(" ");for(int i = 0; i < n; i++){arr[i] = Integer.parseInt(strs[i]);}quickSort(arr, 0, arr.length - 1);for(int i = 0; i < arr.length; i++){System.out.print(arr[i] + " ");}reader.close();}public static void quickSort(int[] arr, int start, int end){if(start < end){int low = start;int high = end;int stard = arr[start];while(low < high){while(low < high && stard <= arr[high]){high--;}arr[low] = arr[high];while(low < high && arr[low] <= stard){low++;}arr[high] = arr[low];}arr[low] = stard;quickSort(arr, start, low);quickSort(arr, low+1 ,end);}}
    }
    
  • java模板2

    public class Main {public static void main(String[] args) throws IOException {//     输入BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(reader.readLine());int[] arr = new int[n];String[] strs = reader.readLine().split(" ");for( int i=0; i<n;i++){arr[i] = Integer.parseInt(strs[i]);}quickSort(arr, 0, arr.length-1);//   输出for(int i = 0; i< arr.length;i++){System.out.print(arr[i]+ " ");}reader.close();}public static void quickSort(int[] arr, int start , int end) {if (start >= end) return;int left = start - 1, right = end + 1, mid = arr[start+((end-start) >> 1)];while (left < right) {do {left++;} while (arr[left] < mid);do {right--;} while (arr[right] > mid);if (left < right) {int tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;}}quickSort(arr, start, right);quickSort(arr, right + 1, end);}
    }
    
  • 问题证明:快速排序算法的证明与边界分析

  • 快排虽然每次划分的区间不一定恰好是N/2,但是期望是N/2的,此情况下其递归的层数期望也是 l o g 2 N log_{2}N log2​N的。

1.2 归并排序

  • 归并的基本思想也是分治,时间复杂度为O(Nlog(N)),且算法是稳定的。

  • 归并的步骤:

    • 找分界点,以中间点为分界线,归并是先递归再分别处理(快排是先分两边再递归)
    • 递归排序左边和右边,两边变为有序的链表;
    • 归并,将两个有序的数组合并为一个有序的数组;
  • 归并两个有序数组的方法(暴力方法)

    • 比较两个指针位置的数的大小,找到两个数组中的最小值,直到一个指针到达终点,可以把剩下的补到结果里(新开一个存结果的数组);
    • 在归并两个数组过程中,一个指针最多扫描一半的数组,因此总共扫描长度为O(N),每个元素只会被比较一次,时间复杂度为O(N);该步骤只是算法中的递归一次执行的;
  • 算法时间复杂度O(Nlog(N))的具体计算:数组为n,需要除 log ⁡ 2 n \log_{2}n log2​n次才能除到1,因此共有 log ⁡ 2 n \log_{2}n log2​n层,每一层的时间复杂度为O(n),因此总共O(Nlog(N))

  • C++模板

    #include <iostream>
    using namespace std;const int N = 1000010;int q[N], tmp[N];
    void merge_sort(int q[], int l, int r)
    {if (l >= r) return; // 元素个数是1或没有元素;int mid = l + r >> 1;merge_sort(q, l, mid), merge_sort(q, mid + 1, r);// 归并int k = 0, i = l, j = mid + 1; // k是当前已经合并的数目,ij是左右指针while (i <= mid && j <= r)if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ]; // 如果左半部分现在指的数小于右半部分,tmp[k] = q[i]; k++, j++;else tmp[k ++ ] = q[j ++ ];  // 右半部分现在指的数小于左半部分;// 处理未循环完的部分;while (i <= mid) tmp[k ++ ] = q[i ++ ];while (j <= r) tmp[k ++ ] = q[j ++ ];// 复制结果,将tmp[0..r-l+1]复制到q[l..r]中for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
    }int main()
    {int n;scanf("%d", &n);for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);merge_sort(a, 0, n - 1);for (int i = 0; i < n; i ++ ) printf("%d ", a[i]);return 0;
    }
    
  • 归并排序求逆序对:

    • 将所有的逆序对分为三大类:
    • (1)两个数同时出现在左半边;
    • (2)两个数同时出现在右半边;
    • (3)一个在左半边,一个在右半边;

    • 假定归并排序的函数可以在整个区间排好序的同时,求出区间内部所有逆序对的个数(Sj = mid-i+1)从imid都比j大。逆序对的个数最坏情况下是n*(n-1)/2

      #include <iostream>using namespace std;typedef long long LL;const int N = 100010;
      int n;
      int q[N], tmp[N];LL merge_sort(int l, int r)
      {if(l>=r) return 0; // 或(l==r)int mid = l+r >> 1;LL res = merge_sort(l, mid) + merge_sort(mid+1, r);// 归并的过程int k = 0, i = l, j = mid+1;while(i<=mid && j <=r)if(q[i]<=q[j]) tmp[k++] = q[i++]; // 如果左半部分现在指的数小于右半部分else{tmp[k++] = q[j++];            // 右半部分现在指的数小于左半部分(i到mid的数都大于j);res+=mid-i+1;}//处理未循环完的部分while(i<=mid) tmp[k++] = q[i++];while(j<= r) tmp[k++] = q[j++];//物归原主,i循环原始数组,j循环临时数组for (int i = l, j=0; i <= r; i ++, j++ ) q[i] = tmp[j];return res;
      }int main()
      {cin >> n;for (int i = 0; i < n; i ++) cin >> q[i];cout << merge_sort(0, n-1) << endl;return 0;
      }
      

1.3 快速选择算法

  • 快速选择算法的时间复杂度是O(n)(依次处理的区间长度为n+n/2+n/4+... <= 2n)。

  • 快速选择算法的含义是:

    • 首先对数组进行快速排序(找到分界点;左边所有数left <=x, 右边所有数 right >=x,中间值不一定等于x;递归排序 left,递归排序 right)(Sl和Sr是左右两边数的数量)

    • 其次选择k,如果k<=Sl ,则递归左半边;反之,k>Sr递归右半边,找k-Sl的数

  • 与快排的不同在于快排需要递归两边,快速选择每次只需要递归一边。

  • 举例:给定一个长度为 n 的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k 个数。

    do-while循环,这里将第k个数转化为找k-1的下标
    #include <iostream>
    #include <vector>using namespace std;
    vector<int> a;int quick_sort(int l, int r, int k) {if(l >= r) return a[k];int x = a[l], i = l - 1, j = r + 1;while (i < j) {do i++; while (a[i] < x);do j--; while (a[j] > x);if (i < j) swap(a[i], a[j]);}if (k <= j) return quick_sort(l, j, k);else return quick_sort(j + 1, r, k);
    }int main() {int n, k;cin >> n >> k;a = vector<int>(n, 0);for (int i = 0; i < n; i++) {cin >> a[i];}cout << quick_sort(0, n - 1, k - 1) << endl;return 0;
    }
    while循环
    #include <iostream>using namespace std;const int N = 100010;
    int n, k;
    int q[N];int quick_sort(int l, int r, int k)
    {if(l == r) return q[l];int x = q[l], i= l-1, j = r+1;while(i<j){while( q[++i] < x);while( q[--j] > x);if(i<j) swap(q[i], q[j]);}//查看左边数的数量int sl = j-l+1;if(k <= sl) return quick_sort(l, j, k);return quick_sort(j+1, r, k-sl);
    }int main()
    {cin >> n >> k;for (int i = 0; i < n; i ++ ) cin >> q[i];cout << quick_sort(0, n-1, k) << endl;return 0;
    }
    
  • 快速选择算法里可以写if(l == r) return q[l];if(l >= r) return q[l];;但是在快排里必须写if(l == r) return q[l];,因为在快排里区间可能是没有数的(即出现l>r的情况)

二、二分

2.1 整数二分

  • 整数二分的本质不是单调性:如果有单调性,那么一定可以二分,但是可以二分的题目不一定非要单调性。

  • 整数二分的本质是边界:假设给定一个区间[l,r],我们在区间中定义了某种性质。使得在右半边区间是满足的,在左半边区间是不满足的,整个区间可以被一分为二,二分可以寻找性质的边界(两个边界都可以)。(即找到一个性质,可以将数据一分为二)

  • 整数二分需要注意边界问题。

  • 整数二分有两个模板,分别适用不同的情况。两个模板核心的区别是 int mid = l + r + 1 >> 1;要不要加一,代表了两个区域的边界点;

  • 首先讨论寻找红色区域的边界点:

    • 1、找到中间点mid = (l+r+1)/2,并判断中间值是否满足该性质if (check(mid))checktrue说明满足条件,中间值在红色区间,答案在[mid, r],更新方式是将[l, r]区间更新为[mid, r]区间(l = mid);2、checkfalse说明,mid取在绿色区域,答案在[l, mid-1],更新方式是将[l, r]区间更新为[l, mid-1]区间(r = mid-1)。

  • 其次讨论寻找绿色的边界点:

    • 1、求mid =(l+r)/2if (check(mid))是否满足绿色的性质checktrue说明满足条件,中间值在绿色区间,答案在[l, mid],更新方式是将[l, r]区间更新为[l, mid]区间(r = mid);2、checkfalse说明,mid取在红色区域,答案在[mid+1, r],更新方式是将[l, r]区间更新为[mid+1, r]区间(l = mid+1)。
  • 因此选择两个模板是看l还是r等于mid

    // check 函数
    bool check(int x) {/* ... */} // 检查x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
    // mid 属于左半边
    int bsearch_1(int l, int r)
    {while (l < r){int mid = l + r >> 1;if (check(mid)) r = mid;    // check()判断mid是否满足性质else l = mid + 1;}return l;
    }// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
    // mid 属于右半边
    int bsearch_2(int l, int r)
    {while (l < r){int mid = l + r + 1 >> 1;if (check(mid)) l = mid;else r = mid - 1;}return l;
    }
    
  • 为什么mid要加一:

    • c++整数除法是下取整,当l = r-1时,如果mid = (l+r)/2mid=l,如果寻找红色边界且check返回true那么区间更新为[mid, r], l = mid => l,边界进入死循环;
    • 因此当mid = (l+r+1)/2,相同情况下mid=r不会死循环。
  • 举例(数的范围):

    • 给定一个按照升序排列的长度为 n 的整数数组,以及 q 个查询。对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 0 开始计数)。如果数组中不存在该元素,则返回 -1 -1
    • 输入格式,第一行包含整数 n 和 q,表示数组长度和询问个数。第二行包含 n 个整数(均在 1∼10000 范围内),表示完整数组。接下来 q 行,每行包含一个整数 k,表示一个询问元素。
    • 输出格式。共 q 行,每行包含两个整数,表示所求元素的起始位置和终止位置。如果数组中不存在该元素,则返回 -1 -1
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 100010;int n, m;
int q[N];int main()
{scanf("%d%d", &n, &m);for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);while(m --){int x;scanf("%d", &x);int l = 0, r = n-1;// 查询左端点while(l < r){// x以后所有数大于等于x;int mid = l+r >> 1;if (q[mid] >=x)  r = mid;  else  l = mid+1;}if(q[l] != x) cout<< "-1 -1"<< endl;// 如果用q[l]>x来判断,当数组中所有数都小于x时,判断就错了else {cout << l << ' ';// 查询右端点int l = 0, r = n-1;while (l<r){int mid = l+r+1 >>1;if(q[mid] <=x)  l = mid;else r = mid - 1;}cout << l << endl;}}return 0;
}

2.2 浮点数二分

  • 浮点数二分本质上也是一个边界,但没有整除,每次区间可以严格的缩小一半。

  • 当区间长度很小时(r-l<= 10-e^6),认为找到了答案。

  • 浮点数二分需要注意,当求一个浮点数的平方根时,右边界需要扩大,否则二分会产生问题。(如浮点数x=0.01,平方根是0.1,不在0-0.01之间,需要将右边界改为x+1max(1, x),不能直接取右边界为x

  • 举例,开平方:

#include <iostream>using namespace std;int main()
{double x;cin >> x;double l = 0, r = 100; // r不能等于x,x的二次方根一定在这个区间里;while ( r-l >1e-6){double mid= (l+r)/2;if(mid*mid >= x) r = mid;else l = mid;}printf("%lf\n", l);return 0;
}
  • 保留4位小数需要r-l >1e-6,保留5位小数需要r-l >1e-7;保留6位小数需要r-l >1e-8

  • 浮点数二分的另一种写法,不用精度去表示迭代,而是直接循环100次。

#include <iostream>using namespace std;int main()
{double x;cin >> x;double l = 0, r = 100;for(int i = 0; i<100, i++){double mid= (l+r)/2;if(mid*mid >= x) r = mid;else l = mid;}printf("%lf\n", l);return 0;
}

AcWing 算法基础课第一节基础算法1排序、二分相关推荐

  1. AcWing 算法基础课第三节基础算法3 双指针、位运算、离散化、区间合并

    1.该系列为ACWing中算法基础课,已购买正版,课程作者为yxc 2.y总培训真的是业界良心,大家有时间可以报一下 3.为啥写在这儿,问就是oneNote的内存不够了QAQ ACwing C++ 算 ...

  2. (算法设计与分析)第一章算法概述-第一节:算法基本概念和算法复杂性分析

    文章目录 一:算法与程序 (1)算法的定义 (2)算法的五大特征 (3)算法与程序的区别 (4)算法的描述方法 二:算法复杂性分析 (1)时间复杂度 A:算法时间复杂度表示方法 B:表示算法渐进时间复 ...

  3. yxc_第一章 基础算法(三)_区间合并

    截止2022.1.19,y总的基础算法网课已经全部听完.明天上午开始学习数据结构. 接下来还剩:第一章其他剩余的打卡题目.解决完这个问题之后,y总第一章基础算法就算暂时告一段落了. 未来算法学习的路还 ...

  4. 信息学奥赛一本通 提高篇 第一部分 基础算法 第2章 二分与三分

    信息学奥赛一本通 提高篇 提高版 第一部分 基础算法 第2章 二分与三分 信息学奥赛一本通 提高篇 提高版 第一部分 基础算法 第2章 二分与三分_mrcrack的博客-CSDN博客_信息学奥赛一本通 ...

  5. 【gitlab+jenkins+docker】第一节 基础环境介绍与准备

    [gitlab+jenkins+docker]手把手教你搭建基于gitlab+jenkins+docker的项目的自动化部署流程 架构 环境介绍 docker安装 docker-compose安装(二 ...

  6. 人工智能算法:卷1基础算法+卷2受大自然启发的算法+卷3深度学习和神经网络电子书

    ISBN:9787115005786 包装:平装 字数:538000 页数:598 版次:7 开本:16开 用纸:胶版纸 正文语种:中文 人工智能算法:卷1基础算法+卷2受大自然启发的算法+卷3深度学 ...

  7. AcWing算法基础课 第一讲小结(持续更新中)

    目录 前言 一.快速排序法及其扩展 快速排序法 介绍 思路 + 步骤 模拟代入 模板 练习 扩展(求第k个数) 思路 代码 二.归并排序法 归并排序 思路 思路 + 步骤 模拟代入 模板 练习 应用( ...

  8. AcWing算法基础课第一讲(2):高精度加减乘除、前缀和、差分

    文章目录 1. 高精度加法 2. 高精度减法 3. 高精度乘低精度 4. 高精度除以低精度 5. 一维前缀和 6. 二维前缀和 7. 一维差分 8. 二维差分 1. 高精度加法 这里讲解两个大整数的加 ...

  9. yxc_第一章 基础算法(一)

    目录 一.快速排序 1.零散知识点 (1)swap()函数: (2)>>位运算 (3)const int N=1e6+10: 2.快速排序模板题 (1)AcWing 785 快速排序 3. ...

最新文章

  1. 9种设计模式在Spring中的运用,一定要非常熟练!
  2. Thrift RPC 系列教程(5)—— 接口设计篇:struct enum设计
  3. 基于SP4062电路IO接口八通道保护板
  4. vba手机号码归属_Android手机号码归属地的查询
  5. PHP返回数据json数据样式要求是对象{},而不是[]
  6. vSphere Data Protection 6.1.2部署与配置
  7. 基于表单数据的封装,泛型,反射以及使用BeanUtils进行处理
  8. fatal error: Eigen3/Core: 没有那个文件或目录
  9. pixhawk学习笔记-----mavlink
  10. matlab中 晶闸管整流桥导通角_逆变角如何设置,晶闸管2011-6-6
  11. windows下,可替换telnet的工具tcping.exe
  12. Node.js 清洗万恶的种子
  13. 微信小程序-实现保存图片功能的3种方式
  14. nyoj 712 探 寻 宝 藏(双线dp 第六届河南省程序设计大赛)
  15. 离散化-利用计算机求解y=x,离散信号处理(双语)-中国大学mooc-题库零氪
  16. Java SE 第三讲(原生数据类型使用陷阱 Pitfall of Primitive Data Type)
  17. FCN(Fully Convolutional Network)与Unet:谈到语义分割不得不提的两个网络
  18. PDF在线压缩、转换工具
  19. PyTorch官方中文文档上线啦!
  20. RGB与Lab颜色空间互相转换

热门文章

  1. 关于Javascript正则表达式替换
  2. OpenStack_Networking
  3. 7.0窗口改变大小 axure rp_用axurerp7.0设计android界面原型时怎么设置尺寸
  4. DNS原理与手撸域名之自己解析域名
  5. 转: 关于UI开发(总结一些技术和一些论坛牛人讨论)
  6. websocket java详解_WebSocket详解
  7. 从0到1,微商产品如何完成项目孵化?
  8. FileInputFormat类中split切分算法和host选择算法介绍
  9. 网赚项目:公众号小说项目暴利玩法
  10. Lucene开源全文检索引擎快速入门