深度优先遍历(DFS)- Letter CasePermutation - Combinations

本文深入解析深度优先遍历(DFS)的概念与特性,通过树的遍历实例展示其工作原理,并提供了两个具体算法问题的解决方案,包括字符串大小写变换组合与组合数生成,帮助读者理解DFS在实际问题解决中的应用。

深度优先遍历(DFS)

思路:从图中一个未访问的顶点V开始,沿着一条路一直走到尽头,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到尽头…,不断递归重复此过程,直到所有顶点都遍历完成。

特点:不撞南墙不回头,先走完一条路,再换另一条路,继续走,和数的前序遍历一样

树的深度优先遍历

在这里插入图片描述
1.从根节点1开始遍历,它的子节点有2,3,4,先遍历节点2,再遍历节点5,之后遍历节点9.
在这里插入图片描述
2.第一条路已经走到底了,9是叶子节点,没有子节点,从9回退到节点5,看节点5是否还有没有遍历的节点,若没有,继续回退,回退到节点2,节点2还是没有未遍历的节点,继续回退,回退到根节点1。
发现根节点1有两个未遍历的子节点3和4,选择节点3,继续向下遍历,
在这里插入图片描述
和步骤2一样,一条路遍历到最后一个叶子节点10,开始回退,回退到6,继续回退到3,发现节点3未遍历,此时遍历节点7.
在这里插入图片描述

从节点7回退,回退到节点3,再回退到根节点1,选择未遍历的子节点4,一直往下遍历,依次遍历节点4,节点8.

完整节点的遍历顺序:1,2,5,9,3,6,10,7,4,8
在这里插入图片描述
综上所述:就会发现树的深度优先遍历就是数的前序遍历

递归实现:前序遍历(根节点,左节点,右节点)


1.题目:Letter CasePermutation

  • English

Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. Return a list of all possible strings we could create.

Examples:
Input: S = “a1b2”
Output: [“a1b2”, “a1B2”, “A1b2”, “A1B2”]

Input: S = “3z4”
Output: [“3z4”, “3Z4”]

Input: S = “12345”
Output: [“12345”]

Note:
S will be a string with length at most 12.
S will consist only of letters or digits.

  • 中文:

给定一个字符串S,我们可以将每个字母分别转换为小写或大写以创建另一个字符串。返回我们可以创建的所有可能字符串的列表。

示例:
输入:S=“a1b2”
输出:[“a1b2”,“a1B2”,“A1B2”,“A1B2”]

输入:S=“3z4”
输出:[“3z4”,“3Z4”]

输入:S=“12345”
输出:[“12345”]

注:
S将是一个长度不超过12的字符串。
S将仅由字母或数字组成。


  • 分析思路:
    由于输入的字符串中只有字母和数字,小写字母的ASCll码范围是:97~ 122,大写字母的ASCll码范围是:65~ 90,数字字符的范围是:49~57。观察到数字字符的ascll码比字母都要小而且小写字母比对应的大写字母大32,采用异或32刚好是2的32次方,所以相当于小写字母的二进制表示ASCll码从右往左的第6位由0变成1就变成了对应的大写字母同理对于大写字母把第六位的1变成0就是大写向小写的转换,这个过程可以用S[i]^32来完成。

  • 代码:


class Solution{
public:
	vector<string> ans; //全局变量
	vector<string> letterCasePermutation(string S){
		dfs(S,0); //搜索所有字符串和当前位 
		return ans;
	}
	void dfs(string S,int u){ //传字符串与当前枚举到第几位 
		if(u==S.size())
		{
			ans.push_back(S);
			return;
		}
		dfs(S,u+1);//当前位不变 
		if(S[u]>='A')//若是字母 
		{
			S[u]^=32; //大写变小写,异或32 ASII:A=65,a=97 
			dfs(S,u+1);
			int main(){
				
			} 
		}
	}
};

2.题目:Combinations

English:

Given two integers n and k, return all possible combinations of k numbers out of 1 … n.

For example,
If n = 4 and k = 2, a solution is:

[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

中文:

给定两个整数n和k,返回1中k个数的所有可能组合…n。

例如,

如果n=4,k=2,则解为:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]


  • 分析思路:

搜组合数(保证不重不漏),从前往后排列1,2,3…n从前往后看每个数是不是要选,从前往后选k个数,保证所选的次序是有序的,从前往后选(从小到大),这样就不用再去考虑顺序问题,因为选好的数都是按顺序排列好的,(顺序不会导致产生新的方案,不会重复)

  • 代码:


class Solution{
public:
	vector<vector<int> > ans;  //全局变量 
	vector<vector<int> > combine(int n,int k){
		vector<int> path;  //方案 
		dfs(path,1,n,k); //传参,方案,1-n,k:需要选的数 
		return ans;
	}
	void dfs(vector<int> &path,int start,int n,int k) //start:当前可选起始位置,n:总数,k:当前需要选的数 
	{
	if(!k){  //出口条件,不需要选任何数 
		ans.push_back(path); //加入计数中 
		return; 
	}
	for(int i=start;i<=n;i++) //可选起始位置 
	{
		path.push_back(i); //更新状态 ,加入i 
		dfs(path,i+1,n,k-1); //递归搜索 ,当前数为i,所以下一个可选数为i+1(保证选得数从小到大),剩余选k-1个数 
		path.pop_back();//回溯,恢复现场,前面加入i,在此处把最后一个元素删掉 
	}
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值