回溯算法例题(剪枝策略)

news2024/9/23 7:28:09

目录

  • 1.组合
    • 1.77. 组合
    • 2.216. 组合总和 III
    • 3.17. 电话号码的字母组合
    • 4.39. 组合总和
    • 5.40. 组合总和 II
  • 2.分割
    • 1.131. 分割回文串
    • 2.*93. 复原 IP 地址
  • 3.子集
    • 1.78. 子集
    • 2.90. 子集 II
  • 4.排列
    • 1.46. 全排列
    • 2.47. 全排列 II
  • 5.棋盘问题
    • 1.51. N 皇后
    • 2.37. 解数独
  • 6.其他
    • 1.491. 递增子序列

1.组合

1.77. 组合

链接: 77. 组合
在这里插入图片描述

class Solution {
    List<List<Integer>> result=new ArrayList<List<Integer>>();
    List<Integer> path=new ArrayList<Integer>();
    public void tracking(int n,int k,int start){
        if(n-start+1<(k-path.size())){//剪枝操作
            return;
        }
        if(path.size()==k){
            List<Integer> temp=new ArrayList<Integer>(path);
            result.add(temp);
            return;
        }
        for(int i=start;i<=n;i++){
            path.add(i);
            tracking(n,k,i+1);
            path.remove(path.size()-1);
        }
    }
    public List<List<Integer>> combine(int n, int k) {
        tracking(n,k,1);
        return result;
    }
}

2.216. 组合总和 III

链接: 216. 组合总和 III
在这里插入图片描述

class Solution {
    int sum=0;
    List<List<Integer>> result=new ArrayList<List<Integer>>();
    List<Integer> path=new ArrayList<Integer>();
    public void tracking(int n,int k,int start,int sum){
        if(sum>n){//剪枝操作
            return;
        }
        if(path.size()==k&&n==sum){
            List<Integer> temp=new ArrayList<Integer>(path);
            result.add(temp);
            return;
        }
        for(int i=start;i<=9;i++){
            sum+=i;
            path.add(i);
            tracking(n,k,i+1,sum);
            sum-=i;
            path.remove(path.size()-1);
        }
    }
    public List<List<Integer>> combinationSum3(int k, int n) {
        tracking(n,k,1,sum);
        return result;
    }
}

3.17. 电话号码的字母组合

链接: 17. 电话号码的字母组合
在这里插入图片描述

class Solution {
    //定义全局变量
    //定义一个字符串集合存放结果
    List<String> list=new ArrayList<>();
    //字符需要多次添加删除使用StringBuilder存放临时字符串
    StringBuilder temp=new StringBuilder();


    public List<String> letterCombinations(String digits) {
        if(digits==null||digits.length()==0){//如果digits为空
            return list;
        }
        //定义每个数字对应的字符串
        String numString[]={"","","abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
        backTracking(digits,numString,0);
        return list;
    }
    
    //index记录数字序列,每次调用函数index+1
    public void backTracking(String digits,String[] numString,int index){
        if(index==digits.length()){//到达叶子结点
            list.add(temp.toString());
            return;
        }
        int num=digits.charAt(index)-'0';// 将index指向的数字转为int
        String words=numString[num];//获得index对应字符串
        for(int i=0;i<words.length();i++){
            temp.append(words.charAt(i));// 处理
            backTracking(digits,numString,index+1);// 递归,注意index+1,下层要处理下⼀个数字了
            temp.deleteCharAt(temp.length()-1);//回溯
        }
    }
}

4.39. 组合总和

链接: 39. 组合总和
在这里插入图片描述
注:使用剪枝必须对原数组进行排序

class Solution {
    List<List<Integer>> result=new ArrayList<List<Integer>>();
    List<Integer> path=new ArrayList<Integer>();
    //int sum=0;
    public void tracking(int[] candidates,int target,int sum,int strat){
        
        if(sum>target){
            return;
        }
        if(sum==target){
            List<Integer> temp=new ArrayList<Integer>(path);
            result.add(temp);
            return;
        }
        for(int i=strat;i<candidates.length;i++){
            // 如果 sum + candidates[i] > target 就终止遍历
            if (sum + candidates[i] > target)//使用剪枝必须对candidates进行排序
                return;
            path.add(candidates[i]);
            sum+=candidates[i];
            tracking(candidates,target,sum,i);
            sum-=candidates[i];
            path.remove(path.size()-1);
        }
    }
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
    	 // 排序是剪枝的前提
        Arrays.sort(candidates);
        tracking(candidates,target,0,0);
        return result;
    }
}

5.40. 组合总和 II

链接: 40. 组合总和 II
在这里插入图片描述


class Solution {
    List<List<Integer>> result=new ArrayList<List<Integer>>();
    List<Integer> path=new ArrayList<Integer>();
    //int sum=0;
    public void tracking(int[] candidates,int target,int sum,int strat,boolean used[]){
        
        if(sum>target){
            return;
        }
        if(sum==target){
            List<Integer> temp=new ArrayList<Integer>(path);
            result.add(temp);
            return;
        }
        for(int i=strat;i<candidates.length;i++){
            // 如果 sum + candidates[i] > target 就终止遍历
            if (sum + candidates[i] > target)//使用剪枝必须对candidates进行排序
                return;
            // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
            // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
            // 要对同一树层使用过的元素进行跳过
            if (i>0&&candidates[i]==candidates[i-1] &used[i - 1] == false) {
                continue;
            }
            path.add(candidates[i]);
            sum+=candidates[i];
            used[i]=true;
            // 和39.组合总和的区别1,这里是i+1,每个数字在每个组合中只能使用一次
            tracking(candidates,target,sum,i+1,used);
            used[i]=false;
            sum-=candidates[i];
            path.remove(path.size()-1);
        }
    }
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    	 // 排序是剪枝的前提
         // ⾸先把给candidates排序,让其相同的元素都挨在⼀起。
        Arrays.sort(candidates);
        boolean used[]=new boolean[candidates.length];
        tracking(candidates,target,0,0,used);
        return result;
    }
}

2.分割

1.131. 分割回文串

链接: 131. 分割回文串
在这里插入图片描述

class Solution {
    List<List<String>>result=new ArrayList<>();
    List<String> path = new ArrayList<>();// 放已经回⽂的⼦串
    //回溯函数
    public void backTracking(String s,int startIndex) {
        // 如果起始位置已经⼤于s的⼤⼩,说明已经找到了⼀组分割⽅案了
        if(startIndex>=s.length()){
            result.add(new ArrayList(path));
            return;
        }
        for(int i=startIndex;i<s.length();i++){
            if(isPalindrome(s,startIndex,i)){// 是回⽂⼦串
                // 获取[startIndex,i]在s中的⼦串
                String str=s.substring(startIndex,i+1);
                path.add(str);
            }else{// 不是回⽂,跳过
                continue;
            }
            backTracking( s,i+1); // 寻找i+1为起始位置的⼦串
            path.remove(path.size()-1); // 回溯过程,弹出本次已经填在的⼦串
        }

    }
    //判断是否是回文串
    public boolean isPalindrome(String s,int start,int end){
        for(int i=start,j=end;i<j;i++,j--){
            if(s.charAt(i)!=s.charAt(j)){
                return false;
            }
        }
        return true;
    }
    public List<List<String>> partition(String s) {
        backTracking(s,0);
        return result;
    }
}

2.*93. 复原 IP 地址

链接: 93. 复原 IP 地址
在这里插入图片描述

class Solution {
    List<String> result = new ArrayList<>();

    public List<String> restoreIpAddresses(String s) {
        if (s.length() > 12) return result; // 算是剪枝了
        backTrack(s, 0, 0);
        return result;
    }

    // startIndex: 搜索的起始位置, pointNum:添加逗点的数量
    private void backTrack(String s, int startIndex, int pointNum) {
        if (pointNum == 3) {// 逗点数量为3时,分隔结束
            // 判断第四段⼦字符串是否合法,如果合法就放进result中
            if (isValid(s,startIndex,s.length()-1)) {
                result.add(s);
            }
            return;
        }
        for (int i = startIndex; i < s.length(); i++) {
            if (isValid(s, startIndex, i)) {
                s = s.substring(0, i + 1) + "." + s.substring(i + 1);    //在str的后⾯插⼊⼀个逗点
                pointNum++;
                backTrack(s, i + 2, pointNum);// 插⼊逗点之后下⼀个⼦串的起始位置为i+2
                pointNum--;// 回溯
                s = s.substring(0, i + 1) + s.substring(i + 2);// 回溯删掉逗点
            } else {
                break;
            }
        }
    }

    // 判断字符串s在左闭⼜闭区间[start, end]所组成的数字是否合法
    private Boolean isValid(String s, int start, int end) {
        if (start > end) {
            return false;
        }
        if (s.charAt(start) == '0' && start != end) { // 0开头的数字不合法
            return false;
        }
        int num = 0;
        for (int i = start; i <= end; i++) {
            if (s.charAt(i) > '9' || s.charAt(i) < '0') { // 遇到⾮数字字符不合法
                return false;
            }
            num = num * 10 + (s.charAt(i) - '0');
            if (num > 255) { // 如果⼤于255了不合法
                return false;
            }
        }
        return true;
    }
}

3.子集

1.78. 子集

链接: 78. 子集
在这里插入图片描述

class Solution {
    List<List<Integer>>result=new ArrayList<>();
    List<Integer>path=new ArrayList<>();
    public void backTracking(int []nums,int startIndex){
        // 收集⼦集,要放在终⽌添加的上⾯,否则会漏掉⾃⼰{}
        result.add(new ArrayList<Integer>(path));
        if(startIndex>=nums.length){// 终⽌条件可以不加
            return;
        }
        for(int i=startIndex;i<nums.length;i++){
            path.add(nums[i]);//处理节点;
            backTracking(nums,i+1);//递归
            path.remove(path.size()-1);//回溯
        }
    }
    public List<List<Integer>> subsets(int[] nums) {
        backTracking(nums,0);
        return result;
    }
}

2.90. 子集 II

链接: 90. 子集 II
在这里插入图片描述

class Solution {
    List<List<Integer>>result=new ArrayList<>();
    List<Integer>path=new ArrayList<>();
    public void backTracking(int []nums,int startIndex,boolean []used){
        // 收集⼦集,要放在终⽌添加的上⾯,否则会漏掉⾃⼰{}
        result.add(new ArrayList<Integer>(path));
        if(startIndex>=nums.length){// 终⽌条件可以不加
            return;
        }
        for(int i=startIndex;i<nums.length;i++){
            // 对同一树层使用过的元素进行跳过
            if(i>0&&nums[i]==nums[i-1]&&used[i-1]==false)
            // 如果发现出现过就pass
                continue;
            used[i]=true;
            path.add(nums[i]);//处理节点;
            backTracking(nums,i+1,used);//递归
            path.remove(path.size()-1);//回溯
            used[i]=false;
        }
    }
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        boolean used[]=new boolean[nums.length];
        Arrays.sort(nums);//这里的排序是去重的关键
        backTracking(nums,0,used);
        return result;
    }
}

4.排列

1.46. 全排列

链接: 46. 全排列
在这里插入图片描述

class Solution {
    List<List<Integer>> result=new ArrayList<List<Integer>>();
    List<Integer> path=new ArrayList<Integer>();
    public void backTracking(int []nums,boolean used[]){
        if(path.size()==nums.length){// 此时说明找到了一组
            result.add(new ArrayList<Integer>(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(used[i]==true){
                continue;// path里已经收录的元素,直接跳过
            }
            path.add(nums[i]);
            used[i]=true;
            backTracking(nums,used);
            used[i]=false;
            path.remove(path.size()-1);
        }
    }
    public List<List<Integer>> permute(int[] nums) {
        boolean used[]=new boolean[nums.length];
        backTracking(nums,used);
        return result;
    }
}

2.47. 全排列 II

链接: 47. 全排列 II
在这里插入图片描述

class Solution {
    List<List<Integer>> result=new ArrayList<List<Integer>>();
    List<Integer> path=new ArrayList<Integer>();
    public void backTracking(int []nums,boolean used[]){
        if(path.size()==nums.length){// 此时说明找到了一组
            result.add(new ArrayList<Integer>(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
            // used[i - 1] == true,说明同⼀树⽀nums[i - 1]使⽤过
            // used[i - 1] == false,说明同⼀树层nums[i - 1]使⽤过
            if(i>0&&nums[i]==nums[i-1]&&used[i-1]==false){
                continue;//树层去重(同一层取过的元素不能再取)
            }
            if(used[i]==true){
                continue;// path里已经收录的元素,直接跳过
            }
            path.add(nums[i]);
            used[i]=true;
            backTracking(nums,used);
            path.remove(path.size()-1);//回溯,
            used[i]=false;//说明同⼀树层nums[i]使⽤过,防止下一树层重复
        }
    }
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);//排序,数层去重的前提
        boolean used[]=new boolean[nums.length];
        backTracking(nums,used);
        return result;
    }
}

5.棋盘问题

1.51. N 皇后

链接: 51. N 皇后
在这里插入图片描述

class Solution {
    List<List<String>>res=new ArrayList<>();
    public List<List<String>> solveNQueens(int n) {
        char [][]chessboard=new char[n][n];
        for(char[]c:chessboard){
            Arrays.fill(c,'.');
        }
        backTrack(n,0,chessboard);
        return res;
    }
    // n 为输入的棋盘大小
    // row 是当前递归到棋盘的第几行了
    public void backTrack(int n,int row,char[][]chessboard){
        if(n==row){
            res.add(Array2List(chessboard));
        }
        for(int col=0;col<n;col++){// 验证合法就可以放
            if(isValid(row,col,n,chessboard)){
                chessboard[row][col]='Q';// 放置皇后
                backTrack(n,row+1,chessboard);
                chessboard[row][col]='.';// 回溯,撤销皇后
            }
        }
    }
    public boolean isValid(int row,int col,int n,char[][]chessboard){
        //判断列
        for(int i=0;i<row;i++){
            if(chessboard[i][col]=='Q'){
                return false;
            }
        }
        //判断45°角
        for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--){
            if(chessboard[i][j]=='Q'){
                return false;
            }
        }
        //判断135°角
        for(int i=row-1,j=col+1;i>=0&&j<n;i--,j++){
            if(chessboard[i][j]=='Q'){
                return false;
            }
        }
        return true;
    }
    public List<String> Array2List(char[][]chessboard){
        List<String> list=new ArrayList<>();
        for(char []c:chessboard){
            String str=String.copyValueOf(c);
            list.add(str);
        }
        return list;
    }
}

2.37. 解数独

链接: 37. 解数独
在这里插入图片描述

class Solution {
    public void solveSudoku(char[][] board) {
        backTracking(board);
    }
    public boolean backTracking(char[][]board){
        //「一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,
        // 一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!」
        int len=board.length;
        for(int i=0;i<len;i++){// 遍历行
            for(int j=0;j<len;j++){// 遍历列
                if(board[i][j]!='.')// 跳过原始数字
                    continue;
                for(char val='1';val<='9';val++){
                    if(isValid(board,i,j,val)){// (i, j) 这个位置放val是否合适
                        board[i][j]=val;
                        if(backTracking(board)){// 如果找到合适一组立刻返回
                            return true;
                        }
                        //backTracking(board);//递归
                        board[i][j]='.';//回溯
                    }
                }
                // 9个数都试完了,都不行,那么就返回false
                return false;
                // 因为如果一行一列确定下来了,这里尝试了9个数都不行,说明这个棋盘找不到解决数独问题的解!
                // 那么会直接返回, 「这也就是为什么没有终止条件也不会永远填不满棋盘而无限递归下去!」
            }
        }
        // 遍历完没有返回false,说明找到了合适棋盘位置了
        return true;
    }
    
    public boolean isValid(char[][]board,int row,int col,char val){
        int len=board.length;
        for(int i=0;i<len;i++){
            if(board[row][i]==val){//判断行有无重复
                return false;
            }
            if(board[i][col]==val){//判断列有无重复
                return false;
            }
        }
        
        int startRow=(row/3)*3;//计算3*3宫格的起始位
        int startCol=(col/3)*3;
        for(int i=startRow;i<startRow+3;i++){
            for(int j=startCol;j<startCol+3;j++){
                if(board[i][j]==val){// 判断3*3的9方格里是否重复
                    return false;
                }
            }
        }
        return true;
    }
}

6.其他

1.491. 递增子序列

链接: 491. 递增子序列
在这里插入图片描述

class Solution {
    private List<Integer> path = new ArrayList<>();
    private List<List<Integer>> result = new ArrayList<>();
    public void backTracking(int []nums,int startIndex){
        // 收集⼦集
        if(path.size()>1){
            result.add(new ArrayList<>(path));
            // 注意这里不要加return,要取树上的节点
        }
    
        int used[]=new int[201];// 使用used对本层元素进行去重

        for(int i=startIndex;i<nums.length;i++){
            // 对同一树层使用过的元素进行跳过
            if((used[nums[i]+100]==1)||!path.isEmpty()&&nums[i]<path.get(path.size()-1))
                continue;
            used[nums[i]+100]=1;// 记录这个元素在本层用过了,本层后面不能再用了
            path.add(nums[i]);//处理节点;
            backTracking(nums,i+1);//递归
            path.remove(path.size()-1);//回溯
        }
    }
    public List<List<Integer>> findSubsequences(int[] nums) {
        backTracking(nums,0);
        return result;
    }
}

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

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

相关文章

系统移植 5-10

1.进入linux内核源码目录下&#xff0c;打开Makefile文件&#xff0c;搜索vmlinux&#xff0c;找到cmd_link-vmlinux命令&#xff0c; 1179 cmd_link-vmlinux \ 1180 $(CONFIG_SHELL) $< "$(LD)" "…

不同应用场景瑞芯微RK3568主板方案定制

随着物联网和智能设备的迅猛发展&#xff0c;瑞芯微RK3568主板方案作为一种高性能的系统System-on-a-chip&#xff08;SoC&#xff09;&#xff0c;已经成为嵌入式系统、智能家居设备和工业自动化设备等应用场景的首选方案。定制瑞芯微RK3568主板方案可以满足不同应用场景的需求…

科技云报道:ChatGPT应用爆火,安全的大数据底座何处寻?

科技云报道原创。 毫无疑问&#xff0c;AIGC正在给人类社会带来一场深刻的变革。 而剥开其令人眼花缭乱的华丽外表&#xff0c;运行的核心离不开海量的数据支持。 ChatGPT的“入侵”已经引起了各行各业对内容抄袭的担忧&#xff0c;以及网络数据安全意识的提高。 虽然AI技术…

线程的原子性、可见性、有序性及线程安全知识整理

要想保证线程安全&#xff0c;必须同时满足原子性、可见性、有序性。 一、定义 1.1 原子性 一个操作或者多个操作&#xff0c;要么全部执行&#xff0c;并且执行的过程不会被打断&#xff0c; 要么就全部不执行&#xff08;一个操作是不可被分割的&#xff09;。 Java中实现…

JavaScript经典教程(七)-- JavaScript初级

190&#xff1a;JavaScript初级内容 - DOM查询、插入内容、赋予样式等 1、DOM操作 DOM&#xff1a;节点&#xff0c;也就是html中的元素&#xff1b; DOM操作&#xff1a;其实就是节点元素的方法&#xff1b; &#xff08;1&#xff09;innerHTML - 返回元素内容 同时也可以…

【JUC基础】05. Synchronized和ReentrantLock

1、前言 前面两篇中分别讲了Synchronized和ReentrantLock。两种方式都能实现同步锁&#xff0c;且也都能解决多线程的并发问题。那么这两个有什么区别呢&#xff1f; 这个也是一个高频的面经题。 2、相同点 2.1、都是可重入锁 什么是可重入锁&#xff1f; 可重入锁&#xff0…

Mysql查询字符串中某个字符串出现的次数

目录 1.查单个字符出现的次数2.查多个字符出现的次数3.函数讲解 1.查单个字符出现的次数 比如我想查how do you do 字符串当中出现d的次数&#xff1a; 第一眼看上去有点懵&#xff0c;首先mysql并没有直接计算出现字符次数的函数&#xff0c;所以才使用了下面这种方式&#x…

【排错记录】国产航顺HK32F030M驱动TM1624四位数码管显示

问题描述&#xff1a; 航顺单片机 HK32F030MF4P6用数码管显示驱动TM1624问题描述。 航顺单片HK32F030MF4P6的PC3/PC4/PC5引脚分别连接数码管驱动TM1624的DIN/CLK/STB;当单独使用HK32F030MF4P6单片机最小系统和TM1624数码管模块的时候部分最小系统板能驱动数码管正常显示&…

Centos 7 安装系列(11):Kibana

一、系统环境 操作系统&#xff1a;Centos 7 已安装环境&#xff1a;ElasticSearch 8.6.2 二、安装 需要注意的是&#xff1a;Kibana的版本需要和Elasticsearch保持一致。 2.1 下载并解压安装包 cd /opt yum install -y wget wget https://artifacts.elastic.co/downloads…

马哈鱼SQLFLow对SQL Server OUTPUT Clause 的数据血缘分析

SQL Server OUTPUT Clause 会对 SQL 语句的血缘分析产生影响&#xff0c;如果忽略对 OUTPUT Clause 的分析&#xff0c;那么将漏掉一些关键的数据血缘关系&#xff0c;从而影响数据血缘分析的准确性&#xff0c;进而影响组织的数据治理质量。 Gudu SQLFlow 可以对 SQL Server …

Linux下安装MySQL 5.7

安装MySQL 5.7 1、通过命令下载 wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz 2、解压 tar -zxvf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz -C /usr/local/mysql/ 3、简化 cd /usr/local mv mysql-5.7.36-linux-…

Hibernate 基本操作、懒加载以及缓存

前言 上一篇咱们介绍了 Hibernate 以及写了一个 Hibernate 的工具类&#xff0c;快速入门体验了一波 Hibernate 的使用&#xff0c;我们只需通过 Session 对象就能实现数据库的操作了。 现在&#xff0c;这篇介绍使用 Hibernate 进行基本的 CRUD、懒加载以及缓存的知识。 提示…

干货|做实验到底应该选取多少被试?

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 我们都知道心理学实验一般是通过分析被试的一系列数据从而得到相应的结论的。那么&#xff0c;在进行心理学实验的时候需要多少被试&#xff1f;怎么去看实验的被试量够不够呢&#xff1f;…

【Spring Cloud】Spring Cloud Alibaba 实战 Seata (分布式事务)

文章目录 一、Seata 简介简要发展史Seata 设计初衷 二、使用 Docker 快速搭建 Seata 1.4三、在 Spring 项目中使用 Seata 客户端 一、Seata 简介 Seata&#xff08;Simple Extensible Autonomous Transaction Architecture&#xff09; 是一款开源的分布式事务解决方案&#xf…

Datawhale-chatGPT用于句词分类

NLU基础 句子级别的分类 Token级别的分类 相关API chatGPT Style prompt建议 NLU应用 文档问答 分类/实体微调 智能对话

php xdebug配置

1.sublime 火绒 火绒安装插件Xdebug Helper for Firefox 管理插件 -…-选项 填入ide key sublime 第一个插件package control ctrlshifitp 输入install 点击安装第一个包管理 package control 第二个插件 xdebug ctrlshifitp 输入xdebug clinet安装 php配置 这里用的时phps…

网安笔记03 DES概述

DES 概述 分组加密算法 &#xff1a; 明文、密文64位分组长度对称算法 &#xff1a; 加密和解密密钥编排不同&#xff0c;但使用同一算法密钥长度&#xff1a;56位 —— 每个第8位为奇偶校验位密钥为任意的56位数&#xff0c;存在 弱密钥&#xff0c; 容易避开混乱与扩散的组合…

初学者自学Web安全的三个必经阶段(含系统路线脑图+工具笔记)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

React学习1

JSX使得创建虚拟DOM更便捷&#xff0c;纯JS创建虚拟DOM太过繁琐 JSX语法规范&#xff1a; JSX的{}&#xff0c;读变量的时候只能存放表达式&#xff0c;不能写语句&#xff08;代码&#xff09; react可以遍历数组&#xff0c;但是无法遍历对象 react是面向组件编程 函数式…

5月10号软件资讯更新合集....

elementary OS 图像注释工具 Annotator 1.2 发布 Annotator 是一个免费开源图像注释工具&#xff0c;最初是为 elementary OS 设计&#xff0c;但也可用于其他 Linux。近日该工具发布了 1.2 版本&#xff0c;新版本增加了对全屏、当前窗口和选择区域进行截图等功能。 新版本还…