专题:回溯算法专题(已完结)

回溯四部曲
1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)
2.确定遍历顺序(有返回值接的需要接住)
3.确定结束条件(注意是否存在中途直接return)
4.确定单层循环逻辑

1.组合

class Solution {vector<vector<int>>  result;vector<int>  path;void backtracking(int n,int k,int startindex){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(path.size()==k){result.push_back(path);return;}for(int i =startindex;i<=n;i++){path.push_back(i);backtracking(n,k,i+1);path.pop_back();}}
public:vector<vector<int>> combine(int n, int k) {backtracking(n,k,1);return result;}
};

当然也有剪枝

for(int i =startindex;i<=n;i++){

剪枝思考过程 当遍历到i的时候 可以发现已经有path.size()个元素了 还缺 k-path.size()个元素 1…n的时候 也就是从后到前至少有 k-path.size()的元素的才行 因此值是 n-(k-path.size())+1

        for(int i =startindex;i<= n-(k-path.size())+1;i++){path.push_back(i);backtracking(n,k,i+1);path.pop_back();}

2.组合总和III

class Solution {vector<vector<int>> result;vector<int> path;void backtracking(int n,int k,int currentsum,int startindex){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑// cout<<"startindex:"<<startindex<<"   currentsum:   "<<currentsum<<endl;if(path.size()==k){if(currentsum == n){result.push_back(path);}return;}//  下面用了剪枝 原本是 for(int i=startindex;i<=9;i++){for(int i=startindex;i<=9-(k-path.size())+1;i++){currentsum = i + currentsum;path.push_back(i);backtracking(n,k,currentsum,i+1);path.pop_back();currentsum = currentsum - i;}}
public:vector<vector<int>> combinationSum3(int k, int n) {backtracking(n,k,0,1);return result;}
};

3.电话号码的字母组合

class Solution {
public:vector<string> result;string path;unordered_map <char, string>  mymap{{'2', "abc"},{'3', "def"},{'4', "ghi"},{'5', "jkl"},{'6', "mno"},{'7', "pqrs"},{'8', "tuv"},{'9', "wxyz"},};void backtracking(string digits,int index){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(index ==digits.size()){result.push_back(path);return;}string item = mymap[digits[index]];for(int i =0;i<item.size();i++){char zimu = item[i];path.push_back(zimu);backtracking(digits, index+1);path.pop_back();}}vector<string> letterCombinations(string digits) {if(digits=="") return {};backtracking(digits, 0);return result;}
};

4.组合总和

class Solution {
public:vector<vector<int>> result;vector<int> path;// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑void backtracking(vector<int>& candidates, int target,int startindex,int currentsum){// 剪枝if(currentsum>target){return;}if(currentsum == target){result.push_back(path);return;}// cout<<"currentsum:"<<currentsum<<" value:"<<candidates[startindex]<<endl;for(int i= startindex;i<candidates.size();i++){currentsum = currentsum + candidates[i];// 这里也可以直接剪枝 效果比上面剪枝要好 因为不用进入递归函数内部// if(currentsum>target){//     currentsum = currentsum - candidates[i];//     continue;// }path.push_back(candidates[i]);backtracking(candidates,target,i,currentsum);path.pop_back();currentsum = currentsum - candidates[i];}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {backtracking(candidates,target,0,0);return result;}
};

5.组合总和II

方法一:先排序 用uses去重数层

class Solution {
private:
vector<vector<int>> result;
vector<int> path;
// vector<bool> used; // 下面可以直接赋值
void backtracking(vector<int>& candidates, int target,int currentsum,int startindex,vector<bool>& used){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(currentsum>=target){if(currentsum==target){result.push_back(path);}return;}// cout<<"currentsum:"<<currentsum<<"  startindex:"<<startindex<<endl;for(int i=startindex;i<candidates.size();i++){// 树层去重if(i-1>=0 &&candidates[i]==candidates[i-1]&&used[i-1]==false){continue;}used[i]=true;path.push_back(candidates[i]);currentsum=currentsum+candidates[i];backtracking(candidates,target,currentsum,i+1,used);currentsum=currentsum-candidates[i];path.pop_back();used[i]=false;}
}public:vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(),candidates.end());vector<bool> used(candidates.size(),false);backtracking(candidates,target,0,0,used);return result;}
};

方法二:先排序 用startindex去重数层

class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& candidates, int target,int currentsum,int startindex){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(currentsum>=target){if(currentsum==target){result.push_back(path);}return;}// cout<<"currentsum:"<<currentsum<<"  startindex:"<<startindex<<endl;for(int i=startindex;i<candidates.size();i++){// 树层去重if(i>startindex &&candidates[i]==candidates[i-1]){continue;}path.push_back(candidates[i]);currentsum=currentsum+candidates[i];backtracking(candidates,target,currentsum,i+1);currentsum=currentsum-candidates[i];path.pop_back();}
}public:vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(),candidates.end());backtracking(candidates,target,0,0);return result;}
};

方法三:不排序 直接用set查询该数层之前是否使用过


class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& candidates, int target,int currentsum,int startindex){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(currentsum>=target){if(currentsum==target){result.push_back(path);}return;}// cout<<"currentsum:"<<currentsum<<"  startindex:"<<startindex<<endl;unordered_set<int> myset;for(int i=startindex;i<candidates.size();i++){if(myset.count(candidates[i])>0){continue;}myset.insert(candidates[i]);path.push_back(candidates[i]);currentsum=currentsum+candidates[i];backtracking(candidates,target,currentsum,i+1);currentsum=currentsum-candidates[i];path.pop_back();// 要特别注意myset不需要回溯 这个是树层的的变量 同意树层需要用这个判断的// myset.erase(candidates[i]);}
}public:vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(),candidates.end());backtracking(candidates,target,0,0);return result;}
};

6.分割回文串

class Solution {public:vector<vector<string>> result;vector<string> path;bool IsValid(string newstr) {int i=0;int j = newstr.size()-1;while(i<=j) {if(newstr[i]!=newstr[j]){return false;}i++;j--;}return true;}void backtracking(string s, int startindex) {// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(startindex == s.size()){result.push_back(path);return;}for(int i=startindex;i<s.size();i++){string newstr=s.substr(startindex,i-startindex+1);if(!IsValid(newstr)){continue;}path.push_back(newstr);backtracking(s,i+1);path.pop_back();}}vector<vector<string>> partition(string s) {backtracking(s,0);return result;}
};

7.复原IP地址

这里终止条件

    if(doccount >=4){if(startindex == s.size() && doccount==4){cout<<"path:"<<path<<endl;result.push_back(path.substr(0,path.size()-1));}return;}

完整代码

class Solution {public:
vector<string> result;
// string path; 添加字符串后 还得再次移除 因此不用全局 直接用临时的
bool IsValid(string newstr){if(newstr[0]=='0'&&newstr.size()>1){return false;}int intValue = stoi(newstr);if(intValue>255){return false;}return true;
}
void backtracking(string s,int startindex,string path,int doccount){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(doccount >=4){if(startindex == s.size() && doccount==4){cout<<"path:"<<path<<endl;result.push_back(path.substr(0,path.size()-1));}return;}for(int i=startindex;i<s.size();i++){string newstr = s.substr(startindex,i-startindex+1);if(!IsValid(newstr)){break;}doccount++;//path+(newstr)+"."不会改变本层的值 而用path.append(newstr).append(".");  这种会改变本层path的值 backtracking(s,i+1, path+(newstr)+".",doccount);doccount--;}
}vector<string> restoreIpAddresses(string s) {backtracking(s,0,"",0);return result;}
};

8.子集

求子集的时候 注意收获结果的位置是 二叉树中的每个节点位置 并且终止条件可以不写 因为即使不写终止条件也进入不了for的循环中

class Solution {public:
vector<vector<int>> result;
vector<int> path{};
void backtracking(vector<int>& nums, int startindex){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑result.push_back(path);// 下面这个终止条件在求子集问题中没有必要 因为进入不了for的循环中// if(path.size()>=nums.size()){//     return;// }for(int i=startindex;i<nums.size();i++){path.push_back(nums[i]);backtracking(nums,i+1);path.pop_back();}
}vector<vector<int>> subsets(vector<int>& nums) {backtracking(nums,0);return result;}
};

9.子集II

有元素存在重复需要树层剪枝 这里使用 先排序然后用used判断进行剪枝

class Solution {
public:vector<vector<int>> result;vector<int> path{};void backtracking(vector<int>& nums,int startindex,vector<int> & used){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑result.push_back(path);for(int i=startindex;i<nums.size();i++){if(i-1>=0&&nums[i]==nums[i-1]&&used[i-1]==false){continue;}path.push_back(nums[i]);used[i]=true;backtracking(nums,i+1,used);used[i]=false;path.pop_back();}}vector<vector<int>> subsetsWithDup(vector<int>& nums) {sort(nums.begin(),nums.end());vector<int>  used(nums.size(),false);backtracking(nums,0,used);return result;}
};

10.递增子序列

1.这里需要注意树枝去重 并且不能按照题目的意思不能使用排序 因此去重使用set查询是否在同一层去重

        // 树层去重if(myset.count(nums[i])>0){continue;}myset.insert(nums[i]);

2如果不满足递增 应该continue .

        if(!path.empty() && path.back()>nums[i]){continue;}

完整代码

class Solution {
public:vector<vector<int>> result;vector<int> path;
void backtracking(vector<int>& nums,int startindex){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(path.size()>=2){result.push_back(path);}unordered_set<int> myset{};for(int i=startindex;i<nums.size();i++){// 树层去重if(myset.count(nums[i])>0){continue;}myset.insert(nums[i]);if(!path.empty() && path.back()>nums[i]){continue;}path.push_back(nums[i]);backtracking(nums,i+1);path.pop_back();}
}vector<vector<int>> findSubsequences(vector<int>& nums) {backtracking(nums,0);return result;}
};

11.全排列

排列问题 不能依靠startindex了 只能靠used看判断是否使用过避免取重复数字了

class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums,vector<bool>& used){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(path.size()==nums.size()){result.push_back(path);return;}for(int i = 0;i<nums.size();i++){if(used[i] == true) {continue;}used[i]=true;path.push_back(nums[i]);backtracking(nums,used);path.pop_back();used[i]=false;}}vector<vector<int>> permute(vector<int>& nums) {vector<bool> used(nums.size(),false);backtracking(nums, used);return result;}
};

12.全排列 II

注意这里树层去重和全排列避免取到相同位置的数字 可以直接共用一个used

class Solution {
public:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& nums,vector<bool>& used){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(path.size()==nums.size()){result.push_back(path);return;}for(int i =0;i<nums.size();i++){if(i-1>=0&&nums[i]==nums[i-1]&&used[i-1]==false){continue;}if(used[i]==true){continue;}used[i]=true;path.push_back(nums[i]);backtracking(nums,used);path.pop_back();used[i]=false;}}vector<vector<int>> permuteUnique(vector<int>& nums) {sort(nums.begin(),nums.end());vector<bool> used(nums.size(),false);backtracking(nums, used);return result;}
};

13.重新安排行程

14.N皇后

这里可以递归内部控制列填的位置 递归透传行(深度)的大小 当行等于棋盘的大小的时候 可以认为 找到了符合条件的棋盘方法 也就是递归结束
注意下vector初始化

        vector<string> temp(n, string(n, '.'));chessboard = temp;

完整代码

class Solution {vector<vector<string>> result;vector<string> chessboard;bool IsValid(vector<string> &chessboard, int n,int low,int col){// 检查列 也就是列固定 行变化for(int i = low;i>=0;i--){if(chessboard[i][col] == 'Q'){return false;}}// 不用检查行 因为backtracking已经保证行只能有一个// 检查斜角45°for(int i=low,j=col;i>=0&&j<=n;i--,j++){if(chessboard[i][j] == 'Q'){return false;}}// 检查斜角135°for(int i=low,j=col;i>=0&&j>=0;i--,j--){if(chessboard[i][j] == 'Q'){return false;}}return true;}void backtracking( int n,int startlow){// 1.确定是否需要返回值(和题目的递归函数函数是否有返回值无关)// 2.确定遍历顺序(有返回值接的需要接住)// 3.确定结束条件(注意是否存在中途直接return)// 4.确定单层循环逻辑if(startlow == n){result.push_back(chessboard);return;}for(int col=0;col<n;col++){if(!IsValid( chessboard,n, startlow, col)){continue;}chessboard[startlow][col] = 'Q';backtracking(n,startlow+1);chessboard[startlow][col] = '.';}}
public:vector<vector<string>> solveNQueens(int n) {vector<string> temp(n, string(n, '.'));chessboard = temp;backtracking(n,0);return result;}
};

15.解数独

注意点 这里题目帮填了一部分 自己也填了一部分 自己填的一部分 一定要检查所在的这整行 以及整列(N皇后是检查自己填的即可 不用检查整列)

bool IsValid(vector<vector<char>> &board,int n,int m,int row,int col,char k){// cout<<"row:"<<row<<" col:"<<col<<" k:"<<k<<endl;for(int i =  board.size()-1;i>=0;i--){if(board[i][col]==k){return false;}}for(int j =  board[0].size()-1;j>=0;j--){if(board[row][j]==k){return false;}}// 九宫格内只能出现一次for(int i =  row/3 * 3;i<row/3 * 3+3;i++){for(int j =  col/3 * 3;j<col/3 * 3+3;j++){if(board[i][j]==k){return false;}}}return true;
}

完整代码

class Solution {
public:bool IsValid(vector<vector<char>> &board,int n,int m,int row,int col,char k){// cout<<"row:"<<row<<" col:"<<col<<" k:"<<k<<endl;for(int i =  board.size()-1;i>=0;i--){if(board[i][col]==k){return false;}}for(int j =  board[0].size()-1;j>=0;j--){if(board[row][j]==k){return false;}}// 九宫格内只能出现一次for(int i =  row/3 * 3;i<row/3 * 3+3;i++){for(int j =  col/3 * 3;j<col/3 * 3+3;j++){if(board[i][j]==k){return false;}}}return true;
}bool backtracking(vector<vector<char>>& board,int n,int m){for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(board[i][j]!='.'){continue;}for(char k='1';k<='9';k++){if(!IsValid(board,n,m,i,j,k)){continue;}board[i][j]=k;if(backtracking(board,n,m)){for(int i =0;i<9;i++){for(int j =0;j<9;j++){cout<<board[i][j];}}return true;};board[i][j]='.';}return false;}}return true;}void solveSudoku(vector<vector<char>>& board) {int n = board.size();int m = board[0].size();backtracking(board,n,m);}
};

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

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

相关文章

1.项目初始化

目录 1.相关联的数据库表 2.使用gorm操作数据库 使用gen生成model和对数据库的操作 3.使用viper进行配置管理 读取配置文件 进行热更新 4.使用Pflag来进行命令行参数解析 5.使用日志slog 日志轮转与切割功能 6.错误码和http返回格式标准化 提供错误码 提供错误类型…

vue3中swiper11的使用

Swiper官网 vue中使用方法 我使用的是 “vue”: “3.5.11”&#xff0c;swiper版本为 “swiper”: “11.1.14”&#xff0c; “less”: “4.2.0” 1. 属性介绍 属性名作用slidesPerView设置slider容器能够同时显示的slides数量(carousel模式)。可以设置为数字&#xff08;小…

立志最细,FreeRtos中的任务通知(Task Notification)详解!!!

目录 基本概念 任务通知特性 函数原型 简化版函数 专业版函数 前言&#xff1a;本篇参考&#xff0c;韦东山开发文档&#xff0c;连接放在最后 基本概念 在FreeRtos操作系统里面&#xff0c;任务通知(Task Notification)是一种专门用在任务间的任务通信机制&#xff0c;被…

linux解决resolv.conf重启之后会自动还原的问题的几种方法

在 Ubuntu 系统中&#xff0c;/etc/resolv.conf 文件的内容在重启后会被自动还原&#xff0c;通常是因为该文件由系统的网络管理服务&#xff08;如 NetworkManager 或 systemd-resolved&#xff09;动态生成和管理。要防止其重启后被自动还原&#xff0c;你可以尝试以下几种解…

Leetcode—1115. 交替打印 FooBar【中等】(多线程)

2024每日刷题&#xff08;180&#xff09; Leetcode—1115. 交替打印 FooBar C实现代码 class FooBar { private:int n;sem_t fooSem;sem_t barSem;public:FooBar(int n) {this->n n;sem_init(&fooSem, 0, 1);sem_init(&barSem, 0, 0);}~FooBar() {sem_destroy(&…

免杀对抗—内存加载UUID标识IPV4地址MAC地址

前言 试想我们开辟一块内存,然后直接将shellcode写入到对应的内存中并且该内存是可读可写可执行的状态,那么这种方式太容易被AV所查杀,因此当我们如果是利用Windows自身提供的API来将加密或者封装好的shellcode写入到内存执行的话,将会大大增加查杀的难度。 参考文章&#xf…

Linux的pinctrl和gpio子系统

上一章我们编写了基于设备树的 LED 驱动&#xff0c;但是驱动的本质还是没变&#xff0c;都是配置 LED 灯所使用的 GPIO 寄存器&#xff0c;驱动开发方式中硬件初始化这一部分和裸机基本没啥区别。Linux 是一个庞大而完善的系统&#xff0c;尤其是驱动框架&#xff0c;像 GPIO …

【HuggingFace 如何上传数据集】快速上传图片、文本等各种格式的数据

【HuggingFace 下载】diffusers 中的特定模型下载&#xff0c;access token 使用方法总结【HuggingFace 下载中断】Git LFS 如何下载指定文件、单个文件夹&#xff1f; 如果只是为了上传备份、或者迁移数据&#xff0c;可以不用 huggingface dataset&#xff0c;而是直接使用 …

k8s权限控制RBAC中的clusterrole serviceaccount rolebinding 有什么作用

在 Kubernetes 的权限控制模型中,RBAC(基于角色的访问控制,Role-Based Access Control)用于管理对集群资源的访问权限。ClusterRole、ServiceAccount 和 RoleBinding 是其中的关键概念。下面是它们的作用: 1. ClusterRole 作用: ClusterRole 定义了一组权限(可以访问或操…

Stm32+Esp8266连接阿里云程序移植教程(MQTT协议)

Stm32Esp8266连接阿里云程序移植教程&#xff08;MQTT协议&#xff09; 一、前期准备二、移植过程三、程序的使用3.1 连接上阿里云3.2 传输用户数据到阿里云3.3 解析从阿里云下发给用户的数据3.4 关于调试接口 一、前期准备 自己要的工程文件移植所需的文件&#xff08;如下图&…

python实现:两个自然数 X,Y 相除,商 3 余 10,被除数、除数、商、余数的和是 163。求被除数、除数分别是多少?

题目&#xff1a; 两个自然数 X&#xff0c;Y 相除&#xff0c;商 3 余 10&#xff0c;被除数、除数、商、余数的和是 163。求被除数、除数分别是多少 答案&#xff1a; y1 while y<163:if (3*y10)y310163:x163-3-10-ybreakyy1 print(f"被除数为&#xff1a;{x}、除…

消息展示区(二)

消息展示区&#xff08;二&#xff09; 前言 在上一集我们初始化了右窗口的消息展示区&#xff0c;对每一条消息我们创建了对象和布局管理器&#xff0c;并且在这个布局管理器中添加了发送者的头像&#xff0c;并分类讨论了左侧消息和右侧消息&#xff0c;那么我们这一集将会…

新手必看!手把手教你打造10W+爆款文章

自定义 GPTs 的引入彻底改变了博主、营销人员和内容创作者在 ChatGPT 高级版本中的写作方式。这些自定义 GPTs 提供个性化的 AI 工具&#xff0c;旨在执行特定任务&#xff0c;使写作过程更顺畅、迅速且高效。从主题头脑风暴到撰写 SEO 友好的内容&#xff0c;自定义 GPTs 满足…

ES6扩展运算符

1.介绍&#xff1a; ... 扩展运算符能将数组转换为逗号分隔的参数序列&#xff1b; 扩展运算符&#xff08;spread&#xff09;也是三个点&#xff08;...&#xff09;。它好比 rest 参数的逆运算&#xff0c;将一个数组转为用逗号分隔的 参数序列&#xff0c;对数组进…

解决 Jupyter Notebook 环境问题:一步一步指南

Jupyter Notebook 是一个强大的工具&#xff0c;广泛用于数据科学、机器学习和交互式计算。然而&#xff0c;确保它在正确的 Python 环境中运行可能会带来一些挑战。本文将为您提供一个详细的步骤指南&#xff0c;帮助您解决 Jupyter Notebook 环境问题&#xff0c;确保它能够在…

mysql学习教程,从入门到精通,SQL 注入(42)

1、 SQL 注入 SQL 注入是一种严重的安全漏洞&#xff0c;它允许攻击者通过操纵 SQL 查询来访问、修改或删除数据库中的数据。由于 SQL 注入的潜在危害&#xff0c;我不能提供具体的恶意代码示例。然而&#xff0c;我可以向你展示如何防御 SQL 注入&#xff0c;并解释其工作原理…

使用verilog设计实现数字混响效果器及其仿真

以下是一个使用Verilog实现简单数字混响效果器的示例。数字混响效果器通过对输入音频信号进行延迟、衰减和混合等操作来模拟声音在不同空间中的反射效果。 整体架构设计 数字混响效果器主要包括延迟线模块、衰减模块和混音模块。延迟线模块用于存储音频样本并产生延迟效果。衰减…

方波信号发生器(完整SCL源代码)

正弦和余弦信号发生器请参考下面文章链接: 1、博途PLC平台 PLC信号发生器(博途SCL)_博图软件波形发生器怎么用-CSDN博客文章浏览阅读1.1k次。本文介绍了如何使用博途SCL编程实现不同周期和幅值的信号发生器,包括余弦和正弦信号。通过信号发生器,可以用于验证PLC的滤波器效…

Android Framework AMS(06)startActivity分析-3(补充:onPause和onStop相关流程解读)

该系列文章总纲链接&#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节主要解读AMS通过startActivity启动Activity的整个流程的补充&#xff0c;更新了startActivity流程分析部分。 一般来说&#xff0c;有Activ…

ZBrush入门使用介绍——17、FiberMesh

大家好&#xff0c;我是阿赵。   继续介绍ZBrush的使用。这次来看看FiberMesh功能。这是一个可以模仿毛发的功能。 一、 使用FiberMesh的预览功能 先准备一个模型&#xff0c;并生成多边形网格 然后按着Ctrl&#xff0c;在模型的表面画一个遮罩。 找到FiberMesh功能&#…