DFS基础——迷宫

迷宫

配套视频讲解

关于dfs和bfs的区别讲解。

对于上图,假设我们要找从1到5的最短路,那么我们用dfs去找,并且按照编号从大到小的顺序去找,首先找到的路径如下,

从节点1出发,我们发现节点2可以走,于是我们就走向了节点2,然后又发现节点2可以走向节点4,于是走向了节点4,然后从节点4走向了节点5,我们只是找到了一条从节点1到节点5的路径,但是我们并不能确定是否是最短路径,所以我们还需要继续去找。我们回退到节点4,与节点4相连的节点3和节点5都已经被遍历过了,所以我们回退到节点2,与节点2相连的节点1和节点4都已经被遍历过了,所以我们回退到节点1,此时节点3也与节点1相连,于是我们走向节点3,后面的路径如下图所示,

我们通过节点3走向了节点5。然后返回到节点3,与节点3相连的节点1和节点5都已经被遍历过了,所以我们回退到节点1,此时与节点1相连的节点2和节点3都已经被遍历过了,dfs退出。

我们找到了两条路径,通过对比这两天路径的长度,我们可以找到最短路径,可以看出,我们穷尽了所有从节点1到达节点5的路径。

接下来看一看bfs是怎么找的。

我们是用队列实现的bfs过程,一开始队列里面只有起始点,即[1]。从队列里面拿出一个节点,即节点1,然后去走此时节点1能够到达的所有节点。如上图所示,bfs会同时向多个方向拓展,节点1与节点2,节点3相连,那么第一步它会从节点1走向节点,也会从节点1走向节点3。这时分别将节点2和节点3加入队列,并且此时,节点1已经出队,即[2,3]。然后去走所有与节点2相连且没有被遍历过的节点,再去走所有与节点3相连且没有被遍历过的节点,如下图所示,

第二步从节点3走到节点5,也从节点2走向了节点4,但是此时我发现已经走到终点了,并且长度为2,即便在后续遍历中我可以走到终点,但是现在所到达的所有点长度已经是2了,那么后续继续走长度一定比2大,所以我可以确定,此时的路径一定是最短路。

dfs题目分析

这一道题我们可以用dfs也可以用bfs,但是对于迷宫最短路类题目,最好的方法是bfs。通过这道题如果采用dfs来做,需要用到dfs里的回溯和剪枝。

首先分析题意,我们要找从起点到终点的最短路,并且这个最短路的行走路线是字典序最小,其实字典序最小好操作,我们只需要在遍历上下左右四个方向的时候按照字典序从小到大的顺序遍历就行了。即

static char[] direct = {'D','L','R','U'};
static int[] nexty = {0,-1,1,0};
static int[] nextx = {1,0,0,-1};

接下来考虑如何找最短路,对于dfs而言,要找最短路,我必须把当前可走的所有路都遍历结束后,才能确定哪一条路是最短路,对于某一个位置,我当前向左走,标记左边的节点为已遍历过,并且把这个’L’存入,走到终点后我再回退,那么再次回到这个位置时,我会选择其它可以走的方向,那么我们要把左边的节点已遍历过的标记清空,表示没有遍历过,并且把在这里存入的’L’取出。即

for (int i = 0; i < 4; i++) {
		int xx = x + nextx[i];
		int yy = y + nexty[i];
		if(xx >= 0 && xx < n && yy >= 0 && yy < m &&visit[xx][yy] == 0 && map[xx][yy] == '0') {
			visit[xx][yy] = 1;
			path[s] = direct[i];//更新路径
            ......
			dfs(xx, yy, s+1);
			visit[xx][yy] = 0;//回溯 dfs返回的时候,往往需要对之前做的标记进行重置	
		}
	}

解释一下上述代码,for (int i = 0; i < 4; i++)表示四个方向遍历,它遍历的顺序由nextx和nexty数组决定,而我们在最开始就给他规定了遍历的顺序是按字典序从小到大遍历的。然后if语句一是判断下一个位置的坐标是否越界,二是判断下一个位置是否之前被遍历过,三是判断下一个位置是否可以走,都没问题的话我就去走这个位置,然后标记这个位置被走过,并且存入此时走的方向,visit[xx][yy] = 1;path[s] = direct[i];,然后就是进入dfs,那么这里dfs三个参数分别表示下一个位置的x坐标,y坐标,以及走到下一个位置走了几步。dfs结束后,我要给visit标记复原,即visit[xx][yy] = 0;

上述是正常dfs以及回溯的过程,接下来我们要加入剪枝。什么情况下我可以确定这条路一定不会成为答案?也就是这条路的长度超过了我们此时记录的最短路的长度,即

if(s >= step) {
	return;
}

s表示我走到当前节点的步数,step表示此时记录的最短路的长度,我还没有走到终点步数就比最短路长,那么它必然不会成为最短路,所以后面就不需要遍历了,直接返回。

还有第二种剪枝,这个不太好想,也是比较最短路的长度,我们比较的是到达当前位置的长度以及在之前我走到该位置的最短长度。比如有一个点A,我走到这里耗费了s步,但是我之前记录我走到这里耗费了s1步,而s1<s,那么说明我之前走到这里再向后走的路径一定比我现在走到这里再向后走的路径短,那么此时我就没有必要遍历了。即

if(s > dp[x][y]) {
		return;
}

s表示我走到当前节点(x,y)的步数, d p [ x ] [ y ] dp[x][y] dp[x][y]表示我之前走到该节点的最短路。那么在dfs的过程中我们要更新dp数组,

for (int i = 0; i < 4; i++) {
		int xx = x + nextx[i];
		int yy = y + nexty[i];
		if(xx >= 0 && xx < n && yy >= 0 && yy < m &&visit[xx][yy] == 0 && map[xx][yy] == '0') {
			visit[xx][yy] = 1;
			dp[xx][yy] = Math.min(dp[xx][yy], s+1);//更新dp
			path[s] = direct[i];//更新路径
			dfs(xx, yy, s+1);
			visit[xx][yy] = 0;//回溯 dfs返回的时候,往往需要对之前做的标记进行重置
			//path[s] = '';
		}
	}

在回溯的时候我们只回溯了visit数组,为什么呢?dp数组不需要回溯,因为它记录的就是一个全局的值,即在我所有到达(x,y)点的路径中最短路径的长度。而path数组虽然需要回溯,但是我们在下一个遍历的时候,下一个的值会直接覆盖之前的值,所以不需要特意给他回溯。那么你也可以理解有回溯,即注释的那个地方//path[s] = '';,这里写和不写效果是一样的。

然后我们看当走到终点时,如何处理,

//判断是否走到终点
if(x == n-1 && y == m-1) {
    if(s < step) {//当前步数小于之前的最优值,对结果进行一下记录
        step = s;
        String string = "";
        for (int i = 0; i < s; i++) {
            //System.out.print(" "+path[i] + " ");
            string += path[i];
        }
        //set.add(string);
        result = string;
    }
    //System.out.println();
}

判断一下此时走到终点的路径长度是否小于我之前记录的长度,如果小于,我要更新最短路径长度,以及这条路径每一步走的方向。

最后这道题,给我们的图是一个字符串,我们可以把它转化成二维字符数组,转化细节在shuju函数里。

dfs题目代码

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Set;

public class Main{
	/*
	 * 在步数最少的前提下,请找出字典序最小的一个作为答案
	 * 如何保证找到的第一个路径一定是字典序最小的
	 * 遍历的时候,按照字典序从小到大的顺序去遍历
	 * D<L<R<U
	 * DDRURRDDDR
	 * DRRURRDDDR
	 * 如何记录我们的路径
	 * bfs 
	 * node{
	 * x,y,path//走到当前节点的路径
	 * }
	 * path
	 */
    static int n = 30;
    static int m = 50;
    static char[][]  map = new char[n][m];
    static char[] direct = {'D','L','R','U'};
    static int[] nexty = {0,-1,1,0};
    static int[] nextx = {1,0,0,-1};
    static int[][] visit = new int[n][m];
    
    //dfs
    static char[] path = new char[n*m+1];
    static int step = n*m+1;
    static String result = "";
    static Set<String> set = new HashSet<String>();
    static int[][] dp = new int[n][m];
public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);
	shuju();
    for(int i=0;i<n;i++){
        Arrays.fill(dp[i], n*m+1);
    }
    sc.close();
    visit[0][0] = 1;
    dfs(0,0,0);
    System.out.println(result);
}
private static void shuju() {
	// TODO Auto-generated method stub
	String string = "01010101001011001001010110010110100100001000101010"
			+"00001000100000101010010000100000001001100110100101"
			+"01111011010010001000001101001011100011000000010000"
			+"01000000001010100011010000101000001010101011001011"
			+"00011111000000101000010010100010100000101100000000"
			+"11001000110101000010101100011010011010101011110111"
			+"00011011010101001001001010000001000101001110000000"
			+"10100000101000100110101010111110011000010000111010"
			+"00111000001010100001100010000001000101001100001001"
			+"11000110100001110010001001010101010101010001101000"
			+"00010000100100000101001010101110100010101010000101"
			+"11100100101001001000010000010101010100100100010100"
			+"00000010000000101011001111010001100000101010100011"
			+"10101010011100001000011000010110011110110100001000"
			+"10101010100001101010100101000010100000111011101001"
			+"10000000101100010000101100101101001011100000000100"    //D -> L -> R -> U
			+"10101001000000010100100001000100000100011110101001"
			+"00101001010101101001010100011010101101110000110101"
			+"11001010000100001100000010100101000001000111000010"
			+"00001000110000110101101000000100101001001000011101"
			+"10100101000101000000001110110010110101101010100001"
			+"00101000010000110101010000100010001001000100010101"
			+"10100001000110010001000010101001010101011111010010"
			+"00000100101000000110010100101001000001000000000010"
			+"11010000001001110111001001000011101001011011101000"
			+"00000110100010001000100000001000011101000000110011"
			+"10101000101000100010001111100010101001010000001000"
			+"10000010100101001010110000000100101010001011101000"
			+"00111100001000010000000110111000000001000000001011"
			+"10000001100111010111010001000110111010101101111000";
			
			//将上面的一大串字符转为数组中存储,且数组为int型,仅存0 和 1两个值 
			int[][] moze= new int[30][50];
			for (int i = 0 ; i < 30 ; i++) {
				for(int j = 0 ; j < 50 ; j++) {
					map[i][j] = string.charAt(i*50+j); //
				}
			}
}
private static void dfs(int x, int y, int s) {//s当前已经走的步数  走的路径的方向path[i] 表示第i步走的方向
	/* 剪枝
	 * 1.s走到x,y所需要的步数,step当前记录的走完迷宫所需要的最短的步数,s>step return
	 * 2.dp[x][y] 当前走到x,y点所需要的最短距离,s>dp[x][y] return
	 * 
	 * 
	 * dfs{
	 * 1.剪枝
	 * 2.回溯
	 * 3.递归
	 * 
	 * }
	 */
	//剪枝操作
	if(s >= step) {
		return;
	}
	if(s > dp[x][y]) {
		return;
	}
	//判断是否走到终点
	if(x == n-1 && y == m-1) {
		//System.out.print("---" + x + " " + y + " ");
		if(s < step) {//当前步数小于之前的最优值,对结果进行一下记录
			step = s;
			String string = "";
			for (int i = 0; i < s; i++) {
				//System.out.print(" "+path[i] + " ");
				string += path[i];
			    
			}
			//set.add(string);
			result = string;
		}
		//System.out.println();
	}
	for (int i = 0; i < 4; i++) {
		int xx = x + nextx[i];
		int yy = y + nexty[i];
		if(xx >= 0 && xx < n && yy >= 0 && yy < m &&visit[xx][yy] == 0 && map[xx][yy] == '0') {
			visit[xx][yy] = 1;
			dp[xx][yy] = Math.min(dp[xx][yy], s+1);//更新dp
			path[s] = direct[i];//更新路径
			dfs(xx, yy, s+1);
			visit[xx][yy] = 0;//回溯 dfs返回的时候,往往需要对之前做的标记进行重置
			
		}
	}
}
}


bfs题目分析

迷宫最短路问题最简单的做法就是使用bfs去做,bfs与dfs的区别是bfs第一次走到终点的路径一定是最短路,他不用把所有可行路径都遍历一次。接下来大致讲一下bfs的过程。

在bfs的过程我是同时多个方向扩展路径,所以每一个点,当前我走到这里需要的步数以及这条路上的方向我都要记录,所以我要自己写一个节点类,里面存了节点坐标和走到该点的一个路径,这个路径既表示了这条路上每一步走的方向也表明了路的长度。x和y表示当前点的坐标,pathString表示走到当前点的路径。

static class node{
    int x;
    int y;
    String pathString;
    public node(int x, int y, String pathString) {
        super();
        this.x = x;
        this.y = y;
        this.pathString = pathString;
    }

}

首先把起点加入队列,并标记起点已经被访问过,

LinkedList<node> queue = new LinkedList<>();//申请一个队列
queue.add(new node(0, 0, ""));//把起点放入队列
visit[0][0] =1;
String shunxv ="";//记录最短路径

然后依次从队列里面取出点,直到队列为空。取出点后我们先判断该点是否为终点节点,如果是说明我们找到了一条最短路,后续不需要遍历了,直接退出。否则我要向四个方向去遍历。通过if语句判断下一个位置的坐标是否越界,下一个位置是否可走,下一个位置是否已经被遍历过,都满足的话我就可以走向下一个位置,把它对应的信息添加到队列里面,然后标记该位置已经被走过。

while(!queue.isEmpty()){
    node  t = queue.poll();
    int x1 = t.x;
    int y1 = t.y;
    String str1 = t.pathString;
    if(x1==n-1&&y1==m-1){//判断是否走到终点
        shunxv = str1;
        break;
    }
    for(int i=0;i<4;i++){//向四个方向去遍历
        int x2= x1+nextx[i];
        int y2= y1+nexty[i];
        if(x2>=0&&x2<=n-1&&y2>=0&&y2<=m-1&&map[x2][y2]=='0'&&visit[x2][y2]!=1){
            queue.add(new node(x2, y2, str1+direct[i]));
            visit[x2][y2]=1;
        }
    }
}

bfs题目代码

import java.util.LinkedList;
import java.util.Scanner;
public class Main{
	/*
	 * 在步数最少的前提下,请找出字典序最小的一个作为答案
	 * 如何保证找到的第一个路径一定是字典序最小的
	 * 遍历的时候,按照字典序从小到大的顺序去遍历
	 * D<L<R<U
	 * DDRURRDDDR
	 * DRRURRDDDR
	 * 如何记录我们的路径
	 * bfs 
	 * node{
	 * x,y,path//走到当前节点的路径
	 * }
	 * path
	 */
	static class node{
		int x;
		int y;
		String pathString;
		public node(int x, int y, String pathString) {
			super();
			this.x = x;
			this.y = y;
			this.pathString = pathString;
		}
		
	}
    static int n = 30;
    static int m = 50;
    static char[][]  map = new char[n][m];
    static char[] direct = {'D','L','R','U'};
    static int[] nexty = {0,-1,1,0};
    static int[] nextx = {1,0,0,-1};
    static int[][] visit = new int[n][m];
    static String res;
public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);
	shuju();
    sc.close();
	bfs();
}
private static void shuju() {
	// TODO Auto-generated method stub
	String string = "01010101001011001001010110010110100100001000101010"
			+"00001000100000101010010000100000001001100110100101"
			+"01111011010010001000001101001011100011000000010000"
			+"01000000001010100011010000101000001010101011001011"
			+"00011111000000101000010010100010100000101100000000"
			+"11001000110101000010101100011010011010101011110111"
			+"00011011010101001001001010000001000101001110000000"
			+"10100000101000100110101010111110011000010000111010"
			+"00111000001010100001100010000001000101001100001001"
			+"11000110100001110010001001010101010101010001101000"
			+"00010000100100000101001010101110100010101010000101"
			+"11100100101001001000010000010101010100100100010100"
			+"00000010000000101011001111010001100000101010100011"
			+"10101010011100001000011000010110011110110100001000"
			+"10101010100001101010100101000010100000111011101001"
			+"10000000101100010000101100101101001011100000000100"    //D -> L -> R -> U
			+"10101001000000010100100001000100000100011110101001"
			+"00101001010101101001010100011010101101110000110101"
			+"11001010000100001100000010100101000001000111000010"
			+"00001000110000110101101000000100101001001000011101"
			+"10100101000101000000001110110010110101101010100001"
			+"00101000010000110101010000100010001001000100010101"
			+"10100001000110010001000010101001010101011111010010"
			+"00000100101000000110010100101001000001000000000010"
			+"11010000001001110111001001000011101001011011101000"
			+"00000110100010001000100000001000011101000000110011"
			+"10101000101000100010001111100010101001010000001000"
			+"10000010100101001010110000000100101010001011101000"
			+"00111100001000010000000110111000000001000000001011"
			+"10000001100111010111010001000110111010101101111000";
			
			//将上面的一大串字符转为数组中存储,且数组为int型,仅存0 和 1两个值 
			int[][] moze= new int[30][50];
			for (int i = 0 ; i < 30 ; i++) {
				for(int j = 0 ; j < 50 ; j++) {
					map[i][j] = string.charAt(i*50+j); //
				}
			}
}
private static void bfs() {
	// TODO Auto-generated method stub
	LinkedList<node> queue = new LinkedList<>();//申请一个队列
    queue.add(new node(0, 0, ""));//把起点放入队列
    visit[0][0] =1;
    String shunxv ="";//记录最短路径
    while(!queue.isEmpty()){
        node  t = queue.poll();
        int x1 = t.x;
        int y1 = t.y;
        String str1 = t.pathString;
        if(x1==n-1&&y1==m-1){//判断是否走到终点
            shunxv = str1;
            break;
        }
        for(int i=0;i<4;i++){//向四个方向去遍历
            int x2= x1+nextx[i];
            int y2= y1+nexty[i];
            if(x2>=0&&x2<=n-1&&y2>=0&&y2<=m-1&&map[x2][y2]=='0'&&visit[x2][y2]!=1){
                queue.add(new node(x2, y2, str1+direct[i]));
                visit[x2][y2]=1;
            }
        }
    }
    System.out.println(shunxv);
}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面试算法-88-反转链表

题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 解 class Solution {public ListNode reverseList(ListNode head) {if(head null || hea…

opencv-批量调整图片的曝光率

#--coding:utf-8-- import cv2 import numpy as np import osdef gamma_trans(img,gamma):#gamma函数处理gamma_table[np.power(x/255.0,gamma)*255.0 for x in range(256)]#建立映射表gamma_tablenp.round(np.array(gamma_table)).astype(np.uint8)#颜色值为整数return cv2.LU…

2024年最新阿里云服务器价格表(配置价格+带宽价格+磁盘)

2024年腾讯云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新的云服务器优惠券…

WindowsServer2008 安装

一、镜像包 链接&#xff1a;https://pan.baidu.com/s/1t4ju_NN2Od4_1HXeWimaPw?pwd58uq 提取码&#xff1a;58uq 二、安装步骤 第一步&#xff1a;点击创建新的虚拟机 第二步&#xff1a;点击下一步 &#xff08; 可以选典型&#xff0c;也可以选择自定义&#xff09; 第…

JavaScript基础知识汇总【全!】

JavaScript 基础 JavaScript 运行在客户端的脚本语言&#xff0c;不需要编译&#xff0c;由js解释器(js引擎)逐行解释执行。Node.js也可以用于服务器端编程。JavaScript组成: ECMAScript(JavaScript语法)、DOM(文档对象模型)访问HTML文档的所有元素、BOM(浏览器对象模型)它使J…

LeetCode-热题100:42. 接雨水

题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a; height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a; 6 解释&#xff1a; 上面是由数组 [0,1,0,2,1,…

定时器及其简单使用

定时器及其简单使用 文章目录 定时器及其简单使用ARM32单片机定时器定时器原理系统主频与定时时间的关系定时器计时上限预分频器 基于定时器应用配置Timer.cPSC、CAR减1原因 PWM什么是PWM?如何生成PWM&#xff1f;PWM输出使用PWM模式有效电平定时器可以输出几个通道的PWM&…

JUC(二)

1、wait notify Owner 线程发现条件不满足&#xff0c;调用 wait 方法&#xff0c;即可进入 WaitSet 变为 WAITING 状态 BLOCKED 和 WAITING 的线程都处于阻塞状态&#xff0c;不占用 CPU 时间片 BLOCKED 线程会在 Owner 线程释放锁时唤醒 WAITING 线程会在 Owner 线程调用 …

什么是Linux?它与其他操作系统有何区别?

什么是Linux&#xff1f;它与其他操作系统有何区别&#xff1f; 什么是Linux&#xff1f;它与其他操作系统有何区别&#xff1f;摘要引言正文内容了解LinuxLinux与其他操作系统的区别开放性多样性安全性 &#x1f914; QA环节小结 参考资料表格总结总结未来展望 博主 默语带您 …

超高并发下Redis热点数据风险破解

1 介绍 作者是互联网一线研发负责人,所在业务也是业内核心流量来源,经常参与 业务预定、积分竞拍、商品秒杀等工作。 近期参与多场新员工的面试工作,经常就 『超高并发场景下热点数据』 可用性保障与候选人进行讨论。 本文聚焦一些关键点技术进行讨论,并总结一些热点场景…

Apache HTTP服务器(Linux离线编译安装)

Apache HTTP服务器&#xff08;Linux离线编译安装&#xff09; Apache是普通服务器&#xff0c;本身只支持html即普通网页。可以通过插件支持PHP,还可以与Tomcat连通(单向Apache连接Tomcat,就是说通过Apache可以访问Tomcat资源。反之不然)。 Apache和Tomcat都可以做为独立的w…

12 Games101 - 笔记 - 几何(网格处理)、阴影图

12 几何&#xff08;网格处理&#xff09;、阴影图 曲面细分 曲面细分是指将一个模型的面合理的分成更多小的面&#xff0c;从而提升模型精度&#xff0c;使模型越来越光滑&#xff0c;提高渲染效果。 Loop细分 Loop细分是指Loop提出来的细分规则&#xff0c;只能针对于三角…

【Canvas与艺术】暗蓝网格汽车速度仪表盘

【关键点】 采用线性渐变色&#xff0c;使上深下浅的圆有凹下效果&#xff0c;使上浅下深的圆有凸起效果&#xff0c;两者结合就有立体圆钮的感觉。 【图例】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type&quo…

计算联合体union的大小

一&#xff1a;联合类型的定义 联合也是一种特殊的自定义类型&#xff0c;这种类型定义的变量也包含一系列的成员&#xff0c;特征是这些成员公用同一块空间&#xff08;所以联合也叫共用体&#xff09; 比如&#xff1a;共用了 i 这个较大的空间 二&#xff1a; 联合的特点 …

matlab实现神经网络检测手写数字

一、要求 1.计算sigmoid函数的梯度&#xff1b; 2&#xff0e;随机初始化网络权重&#xff1b; 3.编写网络的代价函数。 二、算法介绍 神经网络结构&#xff1a; 不正则化的神经网络的代价函数&#xff1a; 正则化&#xff1a; S型函数求导&#xff1a; 反向传播算法&…

阿里云服务器价格表2024,最新报价2核2G/2核4G/4核8G/8核16G/16核32G

2024年腾讯云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新的云服务器优惠券…

项目管理证书有何用?这些PMP考试机会一定要抓住

项目管理证书有何用&#xff1f;这些PMP考试机会一定要抓住&#xff01; PMP认证的中文全称是“项目管理专业人士资格认证”&#xff0c;是目前国际上声誉较高并且含金量比较高的项目管理证书之一&#xff0c;本人有幸考过&#xff0c;也通过PMP认证成功转岗&#xff0c;应该也…

力扣刷题之21.合并两个有序链表

仅做学习笔记之用。 题目&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xf…

进程和线程,线程实现的几种基本方法

什么是进程&#xff1f; 我们这里学习进程是为了后面的线程做铺垫的。 一个程序运行起来&#xff0c;在操作系统中&#xff0c;就会出现对应的进程。简单的来说&#xff0c;一个进程就是跑起来的应用程序。 在电脑上我们可以通过任务管理器可以看到&#xff0c;跑起来的应用程…

几个简单的参数,实现计算特征向量的余弦相似度(java实现,纯手撸)

几个简单的参数&#xff0c;实现计算特征向量的余弦相似度&#xff08;java实现&#xff0c;纯手撸&#xff09; 太狂喽&#xff01;突然高级起来&#x1f9e0;&#x1f9e0;&#x1f9e0;&#x1f9e0;&#x1f9e0;&#x1f9e0;&#x1f9e0;&#x1f9e0;&#x1f9e0;&am…