modify code

master
algorithmzuo 1 year ago
parent d2d9e9f059
commit 702a13417e

@ -2,11 +2,13 @@ package class03;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeSet;
// 本题测试链接 : https://leetcode.com/problems/freedom-trail/
public class Code07_FreedomTrail {
public static int findRotateSteps(String r, String k) {
// 提交时把findRotateSteps1方法名字改成findRotateSteps可以直接通过
public static int findRotateSteps1(String r, String k) {
char[] ring = r.toCharArray();
int N = ring.length;
HashMap<Character, ArrayList<Integer>> map = new HashMap<>();
@ -59,4 +61,80 @@ public class Code07_FreedomTrail {
return Math.min(Math.abs(i1 - i2), Math.min(i1, i2) + size - Math.max(i1, i2));
}
// 以下方法来自陆振星同学
// 可以省掉枚举行为
// 提交时把findRotateSteps2方法名字改成findRotateSteps可以直接通过
// 来龙去脉 : https://www.mashibing.com/question/detail/67299
// 例 :
// ring = aaca
// key = ca
// 首先来到 2 位置的 c, 下一步有 0 1 3 三个位置的 a 可以选择
// 只需要在 1 3 里面选择最优的即可, 因为 0 位置的 a 在任何情况下都不会比 1 位置的 a 更优
// 这是对的
// 应该是可以的,课上讲述的方法根据数据量能过,就没有继续优化了。
// 如下的贪心方式不对:
// 当前来到的位置,然后要去下一个字符,左边离下一个字符近就选左边,左边离下一个字符近就选右边。
// 两条路只选1条彻底的每一步都选当前步最优。
// 但陆振星同学的贪心方式是:
// 1当前来到的位置然后要去下一个字符左边离下一个字符最近的位置去往左边然后可能性展开选最好的解
// 2当前来到的位置然后要去下一个字符右边离下一个字符最近的位置去往右边然后可能性展开选最好的解
// 1和2中最好的解选出来返回。
// 这是对的,因为如果去往离左右两边都更远的位置,那么为什么不在走的过程中,顺带就满足了下一个字符呢?
// 这样还能省掉枚举行为
// 如下所有代码都提交再次注意提交时把findRotateSteps2方法名字改成findRotateSteps可以直接通过
private int ringLength;
private char[] key;
private ArrayList<TreeSet<Integer>> ringSet;
private final HashMap<Integer, Integer> dp = new HashMap<>();
public int findRotateSteps2(String ring, String key) {
char[] chars = ring.toCharArray();
this.key = key.toCharArray();
ringLength = chars.length;
ringSet = new ArrayList<>();
for (int i = 0; i < 26; i++) {
ringSet.add(new TreeSet<>());
}
for (int i = 0; i < chars.length; i++) {
ringSet.get(chars[i] - 'a').add(i);
}
return findRotateSteps(0, 0);
}
// kIndex : 当前要搞定的字符
// cur : 当前所在的位置
private int findRotateSteps(int kIndex, int cur) {
if (kIndex == key.length) {
return 0;
}
// kIndex 和 cur 的最大值为 100, 所以用 十进制的低两位 表示 cur, 用高两位表示 kIndex
int k = kIndex * 100 + cur - 1;
Integer v = dp.get(k);
if (v != null) {
return v;
} else {
v = Integer.MAX_VALUE;
}
// key[kIndex] 的所有位置
TreeSet<Integer> treeSet = ringSet.get(key[kIndex] - 'a');
// 从 cur 向左走, 最近的符合 key[kIndex] 的位置
Integer floor = treeSet.floor(cur);
if (floor == null) {
floor = treeSet.last();
}
int len = Math.abs(cur - floor);
len = Math.min(len, ringLength - len);
v = Math.min(v, len + 1 + findRotateSteps(kIndex + 1, floor));
// 从 cur 向右走, 最近的符合 key[kIndex] 的位置
Integer ceiling = treeSet.ceiling(cur);
if (ceiling == null) {
ceiling = treeSet.first();
}
len = Math.abs(cur - ceiling);
len = Math.min(len, ringLength - len);
v = Math.min(v, len + 1 + findRotateSteps(kIndex + 1, ceiling));
dp.put(k, v);
return v;
}
}

Loading…
Cancel
Save