字符串的排列

题目

输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
限制:
1 <= s 的长度 <= 8

分析

    1.因为题目所给数组存在重复,并且要求结果去重所以选set保存,最后返回的时候返回vector
	2.算法核心其实就是dfs也可以说是回溯法
	3.因为有set可以保证没有重复所以每次交换后需要重新恢复位置
	4.为了提高效率相邻字符如果相同,则跳过。其实主要是固定一部分,然后与其他字符进行交换
#include<vector>
#include<string>
#include<set>

using namespace std;

class MyClass
{
public:
	vector<string> permutation(string s){
		set<string> res;
		permutation(res, s, 0);
		return vector<string>(res.begin(),res.end());
	}

	void permutation(set<string>& res, string s, int pos){
		if (pos == s.size() - 1){
			res.insert(s);
			return;
		}

		for (int i = pos; i < s.size(); ++i){
			if (i != pos && s[i] == s[pos]){
				continue;
			}			
			swap(s[i], s[pos]);
			permutation(res, s, pos + 1);
			swap(s[i], s[pos]);
		}
	}
};

下面是网上看到的另一种方式;

	std::vector<std::string> permutation(std::string s) {
		if(s.empty()){
		return {};
		}

		// 对字符串进行排序
		std::sort(s.begin(), s.end());
		std::vector<std::string> res;
		// 标记字符是否遍历过
		std::vector<bool> visit(s.size(), false);
		std::string track;
		backtrack(res, s, track, visit);

		return res;
		}

		
		* 回溯函数
		* 使用sort函数对字符串排序,使重复的字符相邻,
		* 使用visit数组记录遍历决策树时每个节点的状态,
		* 节点未遍历且相邻字符不是重复字符时,
		* 则将该字符加入排列字符串中,依次递归遍历。
		* *
void backtrack(std::vector<std::string> &res, std::string s, std::string &track, std::vector<bool> &visit) {
	// 回溯结束条件
	if (track.size() == s.size()){
		res.push_back(track);
		return;
	}

	// 选择和选择列表
	for (int i = 0; i < s.size(); i++){
		// 排除不合法的选择
		if (visit[i]){
			continue;
		}

		if (i > 0 && !visit[i - 1] && s[i - 1] == s[i]){
			continue;
		}
		visit[i] = true;

		// 做选择
		track.push_back(s[i]);
		// 进入下一次决策树
		backtrack(res, s, track, visit);
		// 撤销选择
		track.pop_back();
		visit[i] = false;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值