递归--数据结构--黑马

news2024/9/22 4:18:44

递归

总结一句话,上手直接多刷Leetcode,比看这个更有用。

定义

递归是一种解决计算问题的方法,其中解决方案取决于同一类问题的更小子集。

例如,单链表递归遍历的例子:

void f(Node node) {
    if (node == null) {
        return;
    }
    f(node.next);
}

说明:

  1. 自己调用自己,如果每个函数对应一个解决方案,自己调用自己意味着解决方案一样(有规律)。
  2. 每次调用,函数处理的数据会较上次缩减(子集),而且最后会缩减至无需继续递归。
  3. 内层函数调用(子集处理)完成,外层函数才能算调用完成。

例如,

// 假如链表是,1 -> 2 -> 3 -> null    
void f(Node node) {
    if (node == null) {
        return;
    }
    System.out.println("before: " + node.value);
    f(node.next);
    System.out.println("after: " + node.value);
}

根据递归的性质,从链表头节点开始遍历,打印第一个节点值 n o d e . v a l u e = 1 node.value=1 node.value=1 ,进入 f ( n o d e . n e x t ) f(node.next) f(node.next) 第二个节点不为空,打印第二个节点值 n o d e . v a l u e = 2 node.value=2 node.value=2 ,进入 f ( n o d e . n e x t ) f(node.next) f(node.next) 到第三个节点(不为null),打印第三个节点值 n o d e . v a l u e = 3 node.value=3 node.value=3 ,进入 f ( n o d e . n e x t ) f(node.next) f(node.next) ,因为当前节点为null,则进入 i f if if 语句,return返回,执行第三次 f f f 函数的输出语句,得到 n o d e . v a l u e = 3 node.value=3 node.value=3 ,然后执行第二次 f f f 函数的输出语句,得到 n o d e . v a l u e = 2 node.value=2 node.value=2 ,最后执行第一次 f f f 函数的输出语句,得到 n o d e . v a l u e = 1 node.value=1 node.value=1

使用伪代码执行流程如下,不考虑语法正确。

// 假如链表是,1 -> 2 -> 3 -> null   
void f(Node node = 1) {
    System.out.println("before: " + node.value);			// 1
    void f(Node node = 2) {
        System.out.println("before: " + node.value);		// 2
        void f(Node node = 3) {
            System.out.println("before: " + node.value);	// 3
            void f(Node node = null) {
                if (node == null) {
                    return;
                }
            }
            System.out.println("after: " + node.value);		// 3
        }
        System.out.println("after: " + node.value);			// 2
    }
    System.out.println("after: " + node.value);				// 1
}

简单应用

例1 - 阶乘

用递归方法求阶乘

  • 阶乘定义: n ! = 1 ⋅ 2 ⋅ 3 ⋯ ( n − 2 ) ⋅ ( n − 1 ) ⋅ n n!=1·2·3 \cdots(n-2)·(n-1)·n n!=123(n2)(n1)n ,其中 n n n 为自然数, 0 ! = 1 0!=1 0!=1
  • 递推关系

f ( n ) = { 1 , n = 1 n ∗ f ( n − 1 ) , n > 1 f(n) = \begin{cases} 1, & n=1 \\ n*f(n-1), & n>1 \end{cases} f(n)={1,nf(n1),n=1n>1

public class Factorial {
    public int f(int n) {
        if (n == 1) {
            return 1;
        }
        return n * f(n - 1);
    }
}

例2 - 递归反向打印字符串

public class ReversePrintString{
    
    public static void f(int n, String str) {
        if (n == str.length()) {		// 当n索引等于字符串长度,return
            return;
        }
        f(n + 1, str);
        System.out.println(str.charAt(n));
    }
    
    public static void main(String[] args) {
        f(0, "abcd");
    }
}

例3 - 递归版二分查找

public class BinarySearch {
    
    public static int search(int[] a, int target) {
        return f(a, target, 0, a.length - 1);
    }
    
    // 实现递归的方法
    private static int f (int[] a, int target, int i, int j) {
        if (i > j) {
            // 递归终止条件,未找到
            return -1;
        }
        int m = (i + j) >>> 1;
        if (target < a[m]) {
            return f(a, target, i, m - 1);
        } else if (target > a[m]) {
            return f(a, target, m + 1, j);
        } else {
            return m;
        }
    }
    
}

例4 - 递归版冒泡排序

public class BubbleSort{
    
    public static void sort (int[] a) {
        bubble(a, a.length - 1);
    }
    
    private static void bubble(int[] a, int j) {
        if (j == 0) {
            return;
        }
        for(int i = 0; i < j; i++) {
            if (a[i] > a[i + 1]) {
                swap(a, i, i + 1);
            }
        }
        bubble(a, j - 1);
    }
    
    
    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}
递归版冒泡排序改进
public class BubbleSort{
    
    public static void sort (int[] a) {
        bubble(a, a.length - 1);
    }
    
    private static void bubble(int[] a, int j) {
        if (j == 0) {
            return;
        }
        int x = 0;		// 使用变量x记录下次排序的右边界
        for(int i = 0; i < j; i++) {
            if (a[i] > a[i + 1]) {
                swap(a, i, i + 1);
            	x = i;
            }
        }
        bubble(a, x);
    }
    
    
    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

或者不使用递归,直接使用循环,如下

public class BubbleSort{
    
    public static void sort (int[] a) {
        int j = a.length - 1;
        while (true) {
        	int x = 0;		// 使用变量x记录下次排序的右边界
            for(int i = 0; i < j; i++) {
                if (a[i] > a[i + 1]) {
                    swap(a, i, i + 1);
                    x = i;
                }
            }
            j = x;
            if (j == 0) {
            	break;
            }
        }
    }
    
    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    
    public static void main(String[] args) {
        int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

例5 - 递归版插入排序

public class InsertionSort{
    public static void sort(int[] a) {
        insertion(a, 1);
    }
    
    public static void insertion(int[] a, int low) {
        if (low == a.length) {
            return;
        }
		int t = a[low];
        int i = low - 1;
        while (i >= 0 && a[i] > t) {
            a[i + 1] = a[i];
            i--;
        }
        if (low - 1 != i) {
			a[i + 1] = t;
        }
        insertion(a, low + 1);
    }
    
}

不使用递归,直接使用循环,如下

public class InsertionSort{
    public static void sort(int[] a) {
        for(int low = 1; low < a.length; low++) {
			int t = a[low];			// 插入的值
            int i = low - 1;		// 已排序的右边界
            while (i >= 0 && a[i] > t) {
                a[i + 1] = a[i];
                i--;
            }
            // 找到插入点,找到比插入值小的索引
            if (low - 1 != i) {
                a[i + 1] = t;
            }
        }
    }
}

例6 - 斐波那契数列

递推关系

f ( n ) = { 0 , n = 0 1 n = 1 f ( n − 1 ) + f ( n − 2 ) , n > 1 f(n) =\begin{cases}0,& n=0\\ 1 & n=1 \\ f(n - 1)+f(n-2), & n>1 \end{cases} f(n)= 0,1f(n1)+f(n2),n=0n=1n>1

public class Fibonacci {
    public static int f(int n) {
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        return f(n - 1) + f(n - 2);
    }
}

改进算法如下,使用空间换时间

public class Fibonacci {
    public static int fibonacci (int n) {
        int[] cache = new int[n + 1];
        Arrays.fill(cache, -1);
        cache[0] = 1;
        cache[1] = 1;
        return f(n, cache);
    }
    
    public static int f (int n, int[] cache) {
        if (cache[n] != -1) {
            return cache[n];
        } 
        cache[n] = f(n - 1) + f(n - 2);
        return cache[n];
    }
}

递归时间复杂度计算

Master theorem 主定理

若有递归式
T ( n ) = a T ( n b + f ( n ) ) T(n)=aT(\frac{n}{b} + f(n)) T(n)=aT(bn+f(n))
其中

  • T ( n ) T(n) T(n) 是问题运行的时间, n n n 是数据规模
  • a 是子问题个数
  • T ( n b ) T(\frac{n}{b}) T(bn) 子问题运行的时间,每个子问题被拆成原问题数据规模的 n b \frac{n}{b} bn
  • f ( n ) f(n) f(n) 是除去递归外运行的时间。

x = l o g b a x=log_{b}a x=logba ,即 x = l o g 子问题缩小倍数 x=log_{子问题缩小倍数} x=log子问题缩小倍数 子问题个数

那么
T ( n ) = { Θ ( n x ) f ( n ) = O ( n c ) 并且 c < x Θ ( n x l o g n ) f ( n ) = Θ ( n x ) Θ ( n c ) f ( n ) = Ω ( n c ) 并且 c > x T(n) = \begin{cases} \Theta(n^x) & f(n)=O(n^c)并且c<x\\ \Theta(n^xlogn) & f(n)=\Theta(n^x)\\ \Theta(n^c) & f(n)=\Omega(n^c)并且c>x \end{cases} T(n)= Θ(nx)Θ(nxlogn)Θ(nc)f(n)=O(nc)并且c<xf(n)=Θ(nx)f(n)=Ω(nc)并且c>x

例 1

T ( n ) = 2 T ( n 2 + n 4 ) T(n)=2T(\frac{n}{2} + n^4) T(n)=2T(2n+n4)

  • x = 1 < 4 x=1<4 x=1<4 ,由后者决定时间复杂度 Θ ( n 4 ) \Theta(n^4) Θ(n4)
例 2

T ( n ) = T ( 7 n 10 + n 4 ) T(n)=T(\frac{7n}{10} + n^4) T(n)=T(107n+n4)

  • x = 0 < 1 x=0<1 x=0<1 ,由后者决定时间复杂度 Θ ( n ) \Theta(n) Θ(n)
例 3

T ( n ) = 16 T ( n 4 + n 2 ) T(n)=16T(\frac{n}{4} + n^2) T(n)=16T(4n+n2)

  • x = 2 = 2 x=2=2 x=2=2 ,由前者决定时间复杂度 Θ ( n 2 l o g n ) \Theta(n^2logn) Θ(n2logn)
例 4 - 递归-二分查找
public static int f(int[] a, int target, int i, int j) {
    int m = (i + j) >>> 1;
    if (i > j) {
        return - 1;
    }
    if (target < a[m]) {
        return f(a, target, i, m - 1);
    } else if (target > a[m]) {
        return f(a, target, m + 1, j);
    } else {
        return m;
    }
}
  • 子问题个数 a = 1 a=1 a=1
  • 子问题数据规模缩小倍数 b = 2 b = 2 b=2
  • 除递归外执行的计算是常数级 c = 0 c=0 c=0

T ( n ) = T ( n 2 + n 0 ) T(n)=T(\frac{n}{2} + n^0) T(n)=T(2n+n0)

  • 因为 x = 0 = 0 x=0=0 x=0=0 ,时间复杂度为 Θ ( l o g n ) \Theta(logn) Θ(logn)
例 5 - 递归-归并排序
// 伪代码
void split(B[], i, j, A[]) {
    if (j - i <= 1) {
        return;
    }
    m = (i + j) >>> 1;
    
    // 递归
    split(B[], i, m - 1, A[]);
    split(B[], m + 1, j, A[]);
    
    // 合并
    merge(B, i, m, j, A);
}
  • 子问题个数 a = 2 a=2 a=2
  • 子问题数据规模缩减倍数 b = 2 b=2 b=2
  • 除递归外,主要时间花在合并上,用 f ( n ) = n f(n)=n f(n)=n 表示;

T ( n ) = 2 T ( n 2 + n ) T(n)=2T(\frac{n}{2} + n) T(n)=2T(2n+n)

  • 因为 x = 1 = 1 x=1=1 x=1=1 ,时间复杂度为 Θ ( n l o g n ) \Theta(nlogn) Θ(nlogn)

展开定理

例 1 - 递归求和
long sum(long n) {
    if (n == 1) {
        return 1;
    }
    return sum(n - 1) + n;
}

T ( n ) = T ( n − 1 ) + c T(n)=T(n - 1) + c T(n)=T(n1)+c T ( 1 ) = c T(1)=c T(1)=c

如下展开过程

T ( n ) = T ( n − 2 ) + c + c T(n)=T(n - 2) + c + c T(n)=T(n2)+c+c

T ( n ) = T ( n − 3 ) + c + c + c T(n)=T(n - 3) + c + c + c T(n)=T(n3)+c+c+c

⋯ \cdots

T ( n ) = T ( 1 ) + ( n − 1 ) c = n c T(n)=T(1)+(n-1)c=nc T(n)=T(1)+(n1)c=nc

时间复杂度: O ( n ) O(n) O(n)

例 2 - 递归冒泡排序
void bubble(int[] a, int high) {
    if (high == 0) {
        return;
    }
    for(int i = 0; i < high; i++) {
        if (a[i] > a[i + 1]) {
            // 交换
            swap(a, i, i + 1);
        }
    }
    return bubble(a, high - 1);
}

T ( n ) = T ( n − 1 ) + n T(n)=T(n - 1) + n T(n)=T(n1)+n T ( 1 ) = c T(1)=c T(1)=c

如下展开过程

T ( n ) = T ( n − 2 ) + ( n − 1 ) + n T(n)=T(n - 2) + (n - 1) + n T(n)=T(n2)+(n1)+n

T ( n ) = T ( n − 3 ) + ( n − 1 ) + ( n − 2 ) + n T(n)=T(n - 3) + (n - 1) + (n - 2) + n T(n)=T(n3)+(n1)+(n2)+n

⋯ \cdots

T ( n ) = T ( 1 ) + 2 + ⋯ + n = T ( 1 ) + ( n − 1 ) n + 2 2 = c + n 2 2 + n 2 − 1 T(n)=T(1)+2+\cdots+n=T(1)+(n - 1)\frac{n+2}{2}=c+\frac{n^2}{2}+\frac{n}{2}-1 T(n)=T(1)+2++n=T(1)+(n1)2n+2=c+2n2+2n1

时间复杂度: O ( n 2 ) O(n^2) O(n2)

推导公式网址

推导公式网址
在这里插入图片描述

多路递归

例 1-汉诺塔

public class HanoiTower{
    
    static LinkedList<Integer> a = new LinkedList<>();
    static LinkedList<Integer> b = new LinkedList<>();
    static LinkedList<Integer> c = new LinkedList<>();
    
    static void init(int n) {
        for (int i = n; i >= 1; i--) {
            a.addLast(i);
        }
    }
    // n 为圆盘个数
    // a, 源
    // b, 借
    // c, 目标
    static void move(int n, LinkedList<Integer> a, LinkedList<Integer> b, LinkedList<Integer> c) {
        if (n == 0) {
            return;
        }
        move(n - 1, a, c, b);			// 借助c盘,将a盘的n-1个移到b盘
        c.addLast(a.removeLast());		// 将a盘中的最后一个移到c盘
        move(n - 1, b, a, c);			// 借助a盘,将b盘的n-1个移动到c盘
    }
    
    public void print(){
        System.out.println("------------");
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
    
    public static void main(String[] args) {
        // init(3);
        // print();			// a=[3, 2, 1], b=[], c=[]
        // b.addLast(a.removeLast());		
        // print();			// a=[3, 2], b=[1], c[]
        
        init(3);
        print();
        move(3, a, b, c);
        print();
    }
}

​ 使用展开定理,或者使用公式网址,子问题个数是2,数据规模比原来减少1, T ( n ) = 2 T ( n − 1 ) + c T(n)=2T(n-1)+c T(n)=2T(n1)+c ,中间操作(将a中的最后一个移动到c)看作常数 c c c
在这里插入图片描述

例 2-杨辉三角

public class PascalTriangle {
    
    // 返回某个位置的值
    public static int element(int i, int j) {
        if (i == 0 || i == j) {
            return 1;
        }
        return element(i - 1, j - 1) + element(i - 1, j);
    }
    
    // 打印空格
    public void printSpace(int n, int i) {
        int num = (n - 1 - i) * 2;
        for(int j = 0; j < num; j++) {
            System.out.print(" ");
        }
    }
    
    
    // 打印前n行的杨辉三角
    public static void print(int n) {
        for(int i = 0; i < n; i++) {
            printSpace(n, i);
            for(int j = 0; j <= i; j++) {
                System.out.printf("-%4d", element(i, j)); 	// 左对齐,并占4位
            }
            System.out.print();		// 换行处理
        }
    }
    
    public static void main(String[] args) {
        print(5);
    }
    
}

改进杨辉三角,使用二维数组记录已经计算过的每项元素

public class PascalTriangle {
    
    // 返回某个位置的值
    public static int element(int[][] triangle, int i, int j) {
        if (triangle[i][j] > 0) {
            return triangle[i][j];
        }
        if (i == 0 || i == j) {
            triangle[i][j] = 1;
            return 1;
        }
        triangle[i][j] = element(triangle, i - 1, j - 1) + element(triangle, i - 1, j)
        return triangle[i][j];
    }  
    
    // 打印前n行的杨辉三角
    public static void print(int n) {
        // 创建二维数组
        int[][] triangle = new int[n][];
        for(int i = 0; i < n; i++) {
            // 初始化每行i+1个元素
            triangle[i] = new int[i + 1];
            for(int j = 0; j <= i; j++) {
                System.out.printf("-%4d", element(triangle, i, j)); 	// 左对齐,并占4位
            }
            System.out.print();		// 换行处理
        }
    }
    
    public static void main(String[] args) {
        print(5);
    }
    
}

改进杨辉三角,使用一维数组

public class PascalTriangle { 
    
    public static void createRow(int[] row, int i) {
        if (i == 0) {
            row[0] = 1;
            return;
        }
        for(int j = i; j > 0; j--) {
            row[j] = row[j] + row[j - 1];
        }
    }
    
    // 打印前n行的杨辉三角
    public static void print(int n) {
        // 初始一维数组
        int[] triangle = new int[n];
        for(int i = 0; i < n; i++) {
            // 计算
            createRow(row, i);
            for(int j = 0; j <= i; j++) {
                System.out.printf("-%4d", element(triangle, i, j)); 	// 左对齐,并占4位
            }
            System.out.print();		// 换行处理
        }
    }
    
    public static void main(String[] args) {
        print(5);
    }
    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2051220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

class_2:数学运算和注释

1、运算符优先级 2、导入算数库 import matha -1 b -2 c 3 #一元二次方程 delta b ** 2 -4*a*c print((-b math.sqrt(delta))/(2*a)) print((-b - math.sqrt(delta))/(2*a)) 3、注释

KEEPALIVED高可用集群知识大全

目录 一、KEEPALIVED高可用集群简介 1、Keepalived 高可用集群的工作原理 2、Keepalived 高可用集群的作用 二、KEEPALIVED部署 1、网络配置 2、软件安装与启动 3、配置虚拟路由器 4、效果实现 三、启用keepalived日志功能 四、KEEPALIVED的几种工作模式 1、KEEPALI…

【多线程】初步认识Thread类及其应用

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;多线程 / javaEE初阶 上篇文章我们简单介绍了什么是进程与线程&#xff0c;以及他们之间的区别与联系&#xff0c;实际应用中还是以多线程编程为主的&#xff0c;所以这篇文章就让我们更加深入地去剖…

深入理解Python range()函数与for循环的完美配合

文末赠免费精品编程资料~~ 今天我们要聊的是一个超级实用且基础的功能组合——range() 函数和 for 循环。无论你是刚开始学习Python&#xff0c;还是已经有点基础&#xff0c;这篇文章都将帮助你更深入地理解和掌握这两个工具。 1. 什么是 range()&#xff1f; range() 是Py…

YOLOV8网络结构|搞懂head

head里面的模块之前在backbone出现过的&#xff0c;有conv和c2f&#xff0c;还有concat是新的&#xff0c;就是用来做连接的&#xff0c;就是把几个通道的输出给连接起来&#xff0c;有C,H,W三个维度的&#xff0c;就看最后连接的参数&#xff0c;是按照哪个方向把他们加起来&a…

【C++从小白到大牛】布隆过滤器

布隆过滤器的提出 布隆过滤器概念 布隆过滤器的原理&#xff1a; 布隆过滤器的运作的总体过程&#xff1a; 布隆过滤器的插入 原码 布隆过滤器的查找 布隆过滤器删除 关于布隆过滤器的面试题&#xff1a; 1. 给两个文件&#xff0c;分别有100亿个query&#xff0c;我们…

EmguCV学习笔记 VB.Net 4.2 二值化

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 教程VB.net版本请访问&#xff1a;EmguCV学习笔记 VB.Net 目录-CSDN博客 教程C#版本请访问&#xff1a;EmguCV学习笔记 C# 目录-CSD…

K8S资源之PVPVC

概念 类似于Docker的数据卷挂载&#xff0c;将Pod中重要的文件挂载到宿主机上&#xff0c;如果Pod发生崩溃等情况自愈时&#xff0c;保证之前存储的数据没有丢失。 如上图中&#xff0c;将各个Pod中的目录挂载到存储层&#xff0c;如果Pod宕机后自愈均从存储层获取之前的数据…

STM32——I2C和SPI波形分析

波形分析 I2C波形 //写命令 void OLED_WR_CMD(uint8_t cmd) { HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100); } //写数据 void OLED_WR_DATA(uint8_t data) { HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&am…

【Linux线程】线程的深度解析(线程是什么?线程与进程区别是什么?)

目录 一、前言 二、 什么是线程 &#x1f4a7;线程的引入&#x1f4a7; &#x1f4a7;线程的基本概念 &#x1f4a7; &#x1f4a7;线程的理解 &#x1f4a7; &#x1f4a7;进程与线程的关系&#x1f4a7; &#x1f4a7;程序如何划分&#xff08;重拾页表、见一下LWP&…

行业分析---AI时代是不断更新自身技术还是会利用新技术?

1 背景 最近有两个热点新闻&#xff0c;&#xff08;1&#xff09;“孟晚舟建议不要选和机器竞争的职业&#xff0c;根本不是它的对手”&#xff1b;&#xff08;2&#xff09;“周鸿祎建议萝卜快跑把无人出租车卖给司机&#xff0c;可实现三赢”。 技术的变革在互联网领域是比…

QT翻金币小游戏(含音频图片文件资源)

目录 QT翻金币小游戏 音频图片资源文件获取 效果展示 图片 视频 实现代码 main.cpp mymainwindow.h mymainwindow.cpp startscene.h startscene.cpp selectscene.cpp playscene.h playscene.cpp mypushbutton.h mypushbutton.cpp dataconfig.h dataconfig.cpp QT…

音频剪辑用什么工具?试试这三款

音乐&#xff0c;是情感的传递者&#xff0c;是灵魂的慰藉。作为一名音乐人&#xff0c;我一直在探索如何更好地捕捉和表达音乐的精髓。在这个数字化的时代&#xff0c;音频剪辑软件成为了我们表达创意的重要工具。今天&#xff0c;我想从一个音乐人的角度&#xff0c;分享我使…

C语言每日好题(3)

有任何不懂的问题可以评论区留言&#xff0c;能力范围内都会一一回答 #define _CRT_SECURE_NO_WARNING #include <stdio.h> #include <string.h> int main(void) {if ((strlen("abc") - strlen("abcdef")) > 0)printf(">\n")…

CentOS 7 下载/安装

下载 centos安装包下载_开源镜像站-阿里云centos安装包是阿里云官方提供的开源镜像免费下载服务&#xff0c;每天下载量过亿&#xff0c;阿里巴巴开源镜像站为包含centos安装包的几百个操作系统镜像和依赖包镜像进行免费CDN加速&#xff0c;更新频率高、稳定安全。https://mir…

SpringBoot(一)

1.Spring Boot概要 1.1 SpringBoot介绍 随着动态语言的流行&#xff08;Ruby、Scala、Node.js&#xff09;, Java的开发显得格外的笨重&#xff1b;繁多的配置、低下的开发效率、复杂的部署流程以及第三方技术整合难度大。 在上述环境下&#xff0c;Spring Boot由此诞生&#…

每天五分钟计算机视觉:搭建人脸识别的Siamese深度神经网络模型

本文重点 前面的一篇文章中介绍了关于一次学习的问题,解决一次学习问题的关键在于学习到一个函数d,这个d可以计算出两张图片中的人脸是不是同一个人。那么我们需要搭建什么样的神经网络才可以让模型学习出这样的函数d呢?本文我们介绍一下Siamese神经网络结构,它可以帮助我…

快速上手体验MyPerf4J监控springboot应用(docker版快速开始-本地版)

使用MyPerf4J监控springboot应用 快速启动influxdb时序数据库日志收集器telegrafgrafana可视化界面安装最终效果 项目地址 项目简介: 一个针对高并发、低延迟应用设计的高性能 Java 性能监控和统计工具。 价值 快速定位性能瓶颈快速定位故障原因 快速启动 监控本地应用 idea配…

BeagleBone Black 上手

芯片特性 板级功能 资源内存 SDRAM 512MB DDR3L 800MHZ A single 256Mb x16 DDR3L 4Gb (512MB) memory device is used. The memory used is one of two devices: MT41K256M16HA-125 from Micron D2516EC4BXGGB from Kingston It will operate at a clock frequency of 400M…

DDD领域驱动设计的原理与实践

目录 什么是DDD领域驱动设计&#xff1f; 定义与概念&#xff1a; 核心思想&#xff1a; 核心概念&#xff1a; 核心原则&#xff1a; 优势与应用&#xff1a; 与微服务架构和传统三层架构的关系&#xff1a; 理解领域模型 举例 统一语言&#xff08;Ubiquitous Langu…