持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情
1、前言
每天一个算法小练习,本篇使用Java实现。
2、题目描述
字符串 s1 和 s2 是 k 相似的(对于某些非负整数 k ),如果我们可以交换 s1 中两个字母的位置正好 k 次,使结果字符串等于 s2 。给定两个字符串 s1 和 s2 ,返回 s1 和 s2 与 k 相似的最小 k 。
提示:
- 1 <= s1.length <= 20
- s2.length == s1.length
- s1 和 s2 只包含集合 {'a', 'b', 'c', 'd', 'e', 'f'} 中的小写字母
2.1、示例1
输入:s1 = "ab", s2 = "ba"
输出:1
2.2、示例2
输入:s1 = "abc", s2 = "bca"
输出:2
3、解题思路
广度优先搜索实现,在每一次循环处理时,从源字符串中寻找目标串的当前字符,找到后则替换。为了不超时,我们需要进一步改进:
- 1、判断两个字符串相同位置的字符是否相同,是则移除该字符不予考虑,减少计算量;
- 2、用于交换的源字符串在每次迭代时长度会减少1,不需要挨个元素交换
3.1、实现代码
public int kSimilarity(String str1, String str2) {
Queue<String> queue = new ArrayDeque<>();
queue.offer(str1);
int step = 0;
while (!queue.isEmpty()) {
//每次迭代的size次中输出的全是父结点
int size = queue.size();
while (size-- > 0) {
String currStr = queue.poll();
if (currStr.equals(str2)) {
//若队首cur与目标相同,则返回step
return step;
}
// 接近目标的结果
int firstIdx = 0;
// 忽略相同元素(匹配区间)找到str2与str1的第一个不相同元素str2x
for(; firstIdx < currStr.length(); ++ firstIdx) {
if (currStr.charAt(firstIdx) != str2.charAt(firstIdx)) {
break;
}
}
// 找到str1的不匹配区间中与str2x相同的元素str1x
for (int secondIdx = firstIdx + 1; secondIdx < currStr.length(); ++secondIdx) {
if (currStr.charAt(secondIdx) == str2.charAt(firstIdx)) {
char[] tmp = currStr.toCharArray();
swap(tmp, firstIdx, secondIdx);
// 把str1的str1x和str2x下标互换后放入队列中
queue.offer(new String(tmp));
swap(tmp, firstIdx, secondIdx);
}
}
}
// 每层结束后step+1
step++;
}
return step;
}
/**
* 交换下标
* @param temp
* @param i
* @param j
*/
void swap(char[] temp, int i, int j) {
char tmp = temp[i];
temp[i] = temp[j];
temp[j] = tmp;
}
3.2、执行结果
好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊