解题思路:
此题组合的长度不唯一,最小组合长度为
1
, 最大组合长度为
tiles
的长度。
按照题意
tiles
中每一个位置的字符在组合中只能出现一次, 所以可以用一个标记辅助
当去组合新的组合时,可以与
tiles
中的每一个位置组合,但是如果当前位置已经在当前组合中出现过,则跳过 虽然此题中每一个位置的字符在组合中只能出现一次,但是tiles
中可能有相同的字符,所以需要考虑重复的组合 而unordered_set
可以天然去重,可以用其去重。
DFS +
回溯:
1.
当前组合不为空
,
则插入
set
中
2.
继续给当前组合拼接新的组合,尝试拼接
tiles
每一个位置的字符
3.
如果当前位置已在组合中出现过,返回到
2
,否则标记当前位置,继续拼接更长的组合
4.
回溯,尝试组合其它位置,返回
2
当所有位置都已经使用过时,当前递归就结束了,继续向上层
DFS
回退
最终返回
set
的大小即为组合数目。
class Solution {
public:
void DFS(string& tiles , string curstr , unordered_set<string>& allRet , vector<int>& book)
{
if(!curstr.empty()) //新的组合插入到 allRet中
{
allRet.insert(curstr);
}
for(int i = 0 ; i < tiles.size() ; ++i)
{
if(book[i] == 0) //当前字符未被用过
{
book[i] = 1; //设置用过
DFS(tiles , curstr + tiles[i] , allRet , book);
book[i] = 0; //回溯
}
}
}
int numTilePossibilities(string tiles)
{
if(tiles.size() == 1)
return 1;
unordered_set<string> allRet; //去重
vector<int> book(tiles.size() , 0); //标记
DFS(tiles , "" , allRet , book);
return allRet.size();
}
};