854. K-Similar Strings
问题:
给定一个字符串A,每次交换其中两个字符,
最后使得到字符串B,求最少交换次数。
Example 1: Input: A = "ab", B = "ba" Output: 1 Example 2: Input: A = "abc", B = "bca" Output: 2 Example 3: Input: A = "abac", B = "baca" Output: 2 Example 4: Input: A = "aabc", B = "abca" Output: 2 Note: 1 <= A.length == B.length <= 20 A and B contain only lowercase letters from the set {'a', 'b', 'c', 'd', 'e', 'f'}
解法:BFS
状态:每次交换后得到的字符串。
使用unordered_set来避免重复得到的字符串。
最终要求的交换次数,即为queue的展开层数。
本题中,重点:剪枝
对下一个交换的字符 i,j 的选择:
我们目的是最终找到字符串B
那么尽量向B靠近的选择交换。
- 首先确定 i:找到当前字符串cur和B不一致的字符。
1 while(cur[i]==B[i]) i++;
- 然后确定 j:j 从 i+1 开始,直到字符串结尾n
- 其中,若要交换的 cur[j] -> i 却 != B[i],就没有靠近B去交换,那么不选择这种交换。
- 另外,若要交换的两个字符 i 和 j 相同,那么交换没意义,也不选择这种交换。
1 if(cur[j]!=B[i] || cur[i]==cur[j]) continue;
代码参考:
1 class Solution { 2 public: 3 void getidx(int mask, vector<int>& idx, int n) { 4 idx.clear(); 5 for(int k=0; k<n; k++) { 6 if((mask>>k)&1) idx.push_back(k); 7 if(idx.size()==2) return; 8 } 9 return; 10 } 11 int kSimilarity(string A, string B) { 12 int level = 0; 13 int n = A.length(); 14 queue<string> q; 15 unordered_set<string> visited; 16 q.push(A); 17 visited.insert(A); 18 string cur, next; 19 while(!q.empty()) { 20 int sz = q.size(); 21 for(int k=0; k<sz; k++) { 22 cur = q.front(); 23 q.pop(); 24 if(cur == B) return level; 25 int i = 0; 26 while(cur[i]==B[i]) i++; 27 for(int j=i+1; j<n; j++) { 28 if(cur[j]!=B[i] || cur[i]==cur[j]) continue; 29 //only swap j which == target j 30 //can't swap i==j (Useless) 31 next = cur; 32 swap(next[i], next[j]); 33 if(visited.insert(next).second) { 34 q.push(next); 35 } 36 } 37 } 38 level++; 39 } 40 return -1; 41 } 42 };