贪心算法
- 最自然智慧的算法
- 用一种局部最功利的标准,总是做出在当前看来是最好的选择
- 难点在于证明局部最功利的标准可以得到全局最优解
- 对于贪心算法的学习主要以增加阅历和经验为主
给定一个由字符串组成的数组strs, 必须把所有的字符串拼接起来,返回所有可能的拼接结果中,字典序最小的结果
需要证明这两个点。太难了,证明麻烦
- a b c 表示 3 个字符串,a + b 表示 a 拼接上 b
若 a + b <= b + c, b + c <= c + b 证明:a + c <= c + a - 数据按照 1 的方式进行排序后得到的字符串是最小的字符串,交换任意两个位置,都会导致字典序变大
public String minDictStr(List<String> strs) {
List<String> strs2 = strs.stream()
.filter(it -> !"".equals(it))
.sorted((a, b) -> (a + b).compareTo(b + a))
.collect(Collectors.toList());
return String.join("", strs2);
}
public String minDictStrCompare(List<String> strs) {
if (strs.size() == 0) {
return "";
}
Stack<String> vals = new Stack<>();
List<String> res = new ArrayList<>();
process(strs, vals, res);
res.sort(String::compareTo);
return res.get(0);
}
private void process(List<String> strs, Stack<String> vals, List<String> res) {
if (strs.size() == 0) {
res.add(String.join("", vals));
return;
}
for (int i = 0; i < strs.size(); i++) {
String str = strs.get(i);
strs.remove(i);
vals.add(str);
process(strs, vals, res);
strs.add(i, str);
vals.pop();
}
}
@Test
public void test1() {
for (int i = 0; i < 10000; i++) {
List<String> strs = Reduce.stringList(8, 10);
List<String> strs1 = new ArrayList<>(strs);
String r1 = minDictStr(strs);
String r2 = minDictStrCompare(strs);
if (!r1.equals(r2)) {
System.out.println(strs);
System.out.println(r1);
System.out.println(r2);
r1 = minDictStr(strs1);
r2 = minDictStrCompare(strs1);
return;
}
}
}