中级之回溯算法

总结:回溯算法实际上是一个类似枚举的搜索尝试过程,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,其特点就是走不通就退回再选另一条路走。 在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。在使用回溯法的时候要注意一点,一定要设置一个向前搜索的终结条件,否则函数就会无限向前搜索从而无法“退回”重新选择。

题目1:电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例:

输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

思路:这个问题实质上就是不同数组间元素的排列组合。用一个map记录不同数字对应的字母集,然后根据所给出的字符串中的数字找到相对应的字母集,最后将各个字母集中的字母排列组合即可。

//用来存储键盘个数字所对应的字母 
map<char,vector<char>> board;
//res是结果集,len是字符串长度,count是子集的长度 
void helper(vector<string> &res,string digits,int len,string s,int count)
{
	if(count==len)
	{
		res.push_back(s);
		return;
	}
	else
	{
		vector<char> temp = board[digits[count]];
		int temp_len = temp.size();
		for(int i=0;i<temp_len;i++)
			helper(res,digits,len,s+temp[i],count+1);	
	}
}
vector<string> letterCombinations(string digits) 
{
	vector<string> res;
	int len = digits.size();
	if(len==0)
		return res;
	board['2'] = {'a','b','c'};
	board['3'] = {'d','e','f'};
	board['4'] = {'g','h','i'};
	board['5'] = {'j','k','l'};
	board['6'] = {'m','n','o'};
	board['7'] = {'p','q','r','s'};
	board['8'] = {'t','u','v'};
	board['9'] = {'w','x','y','z'};
	helper(res,digits,len,"",0);
	return res;      
}

题目2:生成括号

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

思路:每次在字符串中插入新字符有两种选择:一.如果插入的"("没有到达规定数目,可以继续插入"(";二.如果插入的"("数量大于插入的")"的数量可以插入")"。我们只需要在每次插入的时候进行判断,并且根据所判断的结果向下进行递归就可以得到所有情况。

//rCount代表已经放入字符串的'('的数量,lCount代表已经放入的')'的数量 
void helper(vector<string> &res,string s,int n,int rCount,int lCount)
{
	if(rCount==n&&lCount==n)
	{
		res.push_back(s);
		return;
	}	
	else
	{
		if(rCount<n)
			helper(res,s+"(",n,rCount+1,lCount);
		//放入")"数量必须小于放入"("数量 
		if(lCount<rCount)
			helper(res,s+")",n,rCount,lCount+1);
	}
}
vector<string> generateParenthesis(int n) 
{
     vector<string> result;
     if(n==0)
     	return result;
	 helper(result,"",n,0,0);
	 return result;   
}

题目3:全排列

给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

思路:全排列实质上就是nums[i]与nums[j](j>=i)依次进行互换所得到的新的数组。

void swap(int &num1,int &num2)
{
	int temp = num1;
	num1 = num2;
	num2 = temp;
}
void solve(vector<vector<int> > &result,vector<int> &nums,int len,int count)
{
	if(count==len)
	{
		result.push_back(nums);
		return;
	}
	else
	{
		for(int i=count;i<len;i++)
		{
			swap(nums[count],nums[i]);
			solve(result,nums,len,count+1);
			//这里如果不换回来后面会产生很多重复的数组 
			swap(nums[count],nums[i]);
		}
	}
}
vector<vector<int> > permute(vector<int> &nums) 
{
	vector<vector<int> > result;
	int len = nums.size();
	solve(result,nums,len,0);
	return result;
}

题目4:子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

思路:得到一个数组的所有子集实质上就是从数组中抽取长度为i(0=<i<=len)的所有子集。

//solve函数是用于从nums中抽取长度为aim的子集,index是为了保证抽取的数字在上一次抽取数字的后面,保证不重复 
void solve(vector<vector<int> > &result,vector<int> &subset,vector<int> nums,int len,int aim,int index,int count)
{
	if(count==aim)
	{
		result.push_back(subset);
		return;
	}
	else
	{
		for(int i=index;i<len;i++)
		{
			subset.push_back(nums[i]);
			solve(result,subset,nums,len,aim,i+1,count+1);
			subset.pop_back();
		}
		return;
	}
}
vector<vector<int> > subsets(vector<int>& nums) 
{
	vector<vector<int> > result;
	int len = nums.size();
	if(len==0)
		return result;
	//抽取长度不同的子集 
	for(int i=0;i<=len;i++)
	{
		vector<int> subset;
		solve(result,subset,nums,len,i,0,0);
	} 
	return result; 
}

题目5:单词搜索

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.

思路:遍历二维数组,当遍历到和给定字符串首字母相同的字母时,向其上下左右四个方向搜索,寻找是否有与给定字符串第二个字母相同的字母与其相连,如果有则重复上述过程,直到找到全部字符串,如果没有找到全部字符串则继续向后遍历二维数组。要注意的是遍历过的字符要做标记,否则会产生重复遍历的情况。

//rlen和clen是二维网格的宽和长,len是字符串的长度,x和y是字符的位置 
bool judge(vector<vector<char> > &board,int rlen,int clen,string word,int len,int count,int x,int y)
{
	if(count==len)
		return true;
	else
	{
		char temp = board[x][y];
		//为了避免重复遍历 
		board[x][y] = '#';
		if(x>0&&board[x-1][y]==word[count]&&judge(board,rlen,clen,word,len,count+1,x-1,y))
			return true;
		if(x<rlen-1&&board[x+1][y]==word[count]&&judge(board,rlen,clen,word,len,count+1,x+1,y))
			return true;	
		if(y>0&&board[x][y-1]==word[count]&&judge(board,rlen,clen,word,len,count+1,x,y-1))
			return true;
		if(y<clen-1&&board[x][y+1]==word[count]&&judge(board,rlen,clen,word,len,count+1,x,y+1))
			return true;
		board[x][y] = temp;
		return false;
	}
} 
bool exist(vector<vector<char> > &board, string word) 
{
    int rlen = board.size();
    int clen = board[0].size();
    int len = word.size();
    if(rlen==0||clen==0||len==0)
    	return false;
    for(int i=0;i<rlen;i++)
    {
    	for(int j=0;j<clen;j++)
    	{
    		if(board[i][j]==word[0])
    		{
    			if(judge(board,rlen,clen,word,len,1,i,j))
    				return true;
    		}
    	}
    }
    return false;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中级数据结构与算法是指在Java编程语言中,用于组织和处理大量数据的方法以及对算法运行时间进行估计的技术。这些技术的应用可以提高程序的效率和性能。 在Java中,数据结构是指用于存储和组织数据的方式,例如数组、链表、栈、队列、树、图等。这些数据结构可以帮助我们更有效地管理和操作数据。 而算法分析则是对算法运行时间的估计和分析。通过对算法的分析,我们可以确定某个特定解法的可行性,并评估其在处理大量数据时的效率。在Java中,我们可以通过巧妙的实现和优化来减少程序处理大量数据的时间限制。 Java中级数据结构与算法的学习对于那些希望开发复杂程序并提高程序效率的学生和开发人员来说非常重要。通过学习这些技术,他们可以掌握良好的程序设计技巧和算法分析能力,从而能够以最高的效率开发出高性能的程序。 总之,Java中级数据结构与算法是一门涉及组织大量数据的方法和算法运行时间估计的课程,适用于高级数据结构课程或第一年研究生的算法分析课程。学生需要具备一定的中级编程知识和离散数学背景。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [数据结构与算法分析 Java语言描述(原书第3版)pdf](https://blog.csdn.net/weixin_36202127/article/details/114036568)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [数据结构与算法分析Java语言描述](https://blog.csdn.net/weixin_43322764/article/details/116333283)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值