一、前缀树
经典的两种查询:pass代表有几个字符串以当前节点为前缀,end代表某个字符串出现了几次
删除的操作:沿途的P值减减,最后一个end值减减
二、贪心算法
针对每一个题目,如果每次都去证明自己所想的策略能不能行得通,是很慢很繁琐也很容易出错的,很难用严格的数学证明,考场上不适用。
贪心算法的笔试,首先要把暴力的方法写熟了,变成模板,再写对数器
贪心策略,堆和排序是最常用的两个技巧。
最重要的事情是写模板,然后去了解各种各样的贪心策略是啥,贪心算法是一个比较难解决的事情。笔试出现的概率很大,但是占比不大。面试几乎不会考,因为考察不了coding能力。面试考察的题目是要求有区分度的,不同的人会有不同的策略。
1、会议室安排问题(1:03)
结束时间早的会议先安排
public class Code04_BestArrange {
public static class Program {//每个会议都有起始时间和结束时间
public int start;
public int end;
public Program(int start, int end) {
this.start = start;
this.end = end;
}
}
//写个比较器来比较谁的结束时间更早
public static class ProgramComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.end - o2.end;
}
}
public static int bestArrange(Program[] programs, int start) {
Arrays.sort(programs, new ProgramComparator());//按照结束时间排序
int result = 0;
for (int i = 0; i < programs.length; i++) {
if (start <= programs[i].start) {
result++;
start = programs[i].end;
}
}
return result;
}
public static void main(String[] args) {
}
}
2、排序字符串使得整体字典序最低(1:19)
将原来直接比较字典序的方法替换成先组合再比较组合的字典序的方法
public class Code02_LowestLexicography {
public static class MyComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
return (a + b).compareTo(b + a);//组合的字典序比较
}
}
public static String lowestString(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
Arrays.sort(strs, new MyComparator());
String res = "";
for (int i = 0; i < strs.length; i++) {
res += strs[i];
}
return res;
}
public static void main(String[] args) {
String[] strs1 = { "jibw", "ji", "jp", "bw", "jibw" };
System.out.println(lowestString(strs1));
String[] strs2 = { "ba", "b" };
System.out.println(lowestString(strs2));
}
}
3、切金条
典型的哈夫曼编码问题。上来先把所有的数放到小根堆,每次弹出两个数做结合,再扔进小根堆,再弹出两个数做结合,这样循环。
public static int lessMoney(int[] arr) {
PriorityQueue<Integer> pQ = new PriorityQueue<>();
for (int i = 0; i < arr.length; i++) {
pQ.add(arr[i]);
}
int sum = 0;
int cur = 0;
while (pQ.size() > 1) {
cur = pQ.poll() + pQ.poll();//弹出,结合
sum += cur;//代价加上此时的和
pQ.add(cur);//再加到小根堆中
}
return sum;
}
4、挣钱(2:01)
public static int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
Node[] nodes = new Node[Profits.length];
for (int i = 0; i < Profits.length; i++) {
nodes[i] = new Node(Profits[i], Capital[i]);
}
PriorityQueue<Node> minCostQ = new PriorityQueue<>(new MinCostComparator());
PriorityQueue<Node> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
for (int i = 0; i < nodes.length; i++) {
minCostQ.add(nodes[i]);
}
for (int i = 0; i < k; i++) {
while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) {
maxProfitQ.add(minCostQ.poll());
}
if (maxProfitQ.isEmpty()) {
return W;
}
W += maxProfitQ.poll().p;
}
return W;
}