You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2022_12_4_week;
import java.util.HashSet;
import java.util.PriorityQueue;
// 对于某些非负整数 k ,如果交换 s1 中两个字母的位置恰好 k 次
// 能够使结果字符串等于 s2 ,则认为字符串 s1 和 s2 的 相似度为 k
// 给你两个字母异位词 s1 和 s2 ,返回 s1 和 s2 的相似度 k 的最小值
// 测试链接 : https://leetcode.cn/problems/k-similar-strings/
public class Code06_KSimilarStrings {
public static class Node {
public int cost; // 代价,已经换了几回了!
public int guess;// 猜测还要换几回,能变对!
public int where;// 有必须去比对的下标,左边不再换了!
public String str; // 当前的字符
public Node(int r, int g, int i, String s) {
cost = r;
guess = g;
where = i;
str = s;
}
}
public static int kSimilarity(String s1, String s2) {
int len = s1.length();
PriorityQueue<Node> heap = new PriorityQueue<>((a, b) -> (a.cost + a.guess) - (b.cost + b.guess));
HashSet<String> visited = new HashSet<>();
heap.add(new Node(0, 0, 0, s1));
while (!heap.isEmpty()) {
Node cur = heap.poll();
if (visited.contains(cur.str)) {
continue;
}
if (cur.str.equals(s2)) {
return cur.cost;
}
visited.add(cur.str);
int firstDiff = cur.where;
while (cur.str.charAt(firstDiff) == s2.charAt(firstDiff)) {
firstDiff++;
}
char[] curStr = cur.str.toCharArray();
for (int i = firstDiff + 1; i < len; i++) {
if (curStr[i] == s2.charAt(firstDiff) && curStr[i] != s2.charAt(i)) {
swap(curStr, firstDiff, i);
add(String.valueOf(curStr), s2, cur.cost + 1, firstDiff + 1, heap, visited);
swap(curStr, firstDiff, i);
}
}
}
return -1;
}
public static void swap(char[] s, int i, int j) {
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
public static void add(String add, String s2, int cost, int index, PriorityQueue<Node> heap,
HashSet<String> visited) {
if (!visited.contains(add)) {
heap.add(new Node(cost, evaluate(add, s2, index), index, add));
}
}
// 估值函数
// 看每周有营养的大厂算法面试题2022年1月第3周
// 估值函数的估计值要绝对 <= 真实距离
// 但又要确保估计值足够大足够接近真实距离,这样效果最好
public static int evaluate(String s1, String s2, int index) {
int diff = 0;
for (int i = index; i < s1.length(); i++) {
if (s1.charAt(i) != s2.charAt(i)) {
diff++;
}
}
return (diff + 1) / 2;
}
}