1.前缀树
public class Trie {
Node root;
public Trie(){
root = new Node();
}
//向树种插入字符串
public void Insert(String str){
if(str==null) return;
root.pass++;
Node node = root;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(node.nexts[c - 'a']==null){
node.nexts[c-'a'] = new Node();
}
node = node.nexts[c-'a'];
node.pass++;
}
node.end++;
}
//查询字符串出现了几次
public int search(String str){
if(str==null) return 0;
Node node = root;
int index = 0;
for (int i = 0; i < str.length(); i++) {
index = str.charAt(i) - 'a';
if(node.nexts[index]==null || node.nexts[index].pass==0){
return 0;
}
node = node.nexts[index];
}
return node.end>0?node.end:0;
}
//查询以str作为前缀的字符串数量
public int searchPre(String str){
if(str==null) return root.pass;
Node node = root;
int index = 0;
for (int i = 0; i < str.length(); i++) {
index = str.charAt(i) - 'a';
if(node.nexts[index]==null || node.nexts[index].pass==0){
return 0;
}
node = node.nexts[index];
}
return node.pass;
}
//删除字符串
public void delete(String str){
if(str==null || search(str)==0) return;
Node node = root;
int index = 0;
node.pass--;
for (int i = 0; i < str.length(); i++) {
index = str.charAt(i)-'a';
if(--node.nexts[index].pass==0){
node.nexts[index] = null;
return;
}
node = node.nexts[index];
}
node.end--;
}
}
2.贪心算法经典题目
//给定一个数组,数组中每个元素为一个会议,会议中记录了开始时间和结束时间。给定一个整型上班开始时间。
// 返回一天最多可以安排的会议数
public class Meeting implements Comparator<Meeting> {
int startTime;
int endTime;
@Override
public int compare(Meeting o1, Meeting o2) {
return o1.endTime - o2.endTime;
}
}
public static int maxMeetingNum(Meeting[] meetings, int startTime) {
//按照会议结束时间先后排序
Arrays.sort(meetings);
int res = 0;
for (int i = 0; i < meetings.length; i++) {
if (meetings[i].startTime >= startTime) {
res++;
startTime = meetings[i].endTime;
}
}
return res;
}
/* 分金条问题:给定数组nums代表最终金条要分成这个样子。给定整型length代表金条的长度。
每次分割的代价为当前金条的长度,怎样分最后的代价最小,返回代价。*/
public static int minCost(int[] nums, int length) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
for (int i = 0; i < nums.length; i++) {
queue.add(nums[i]);
}
int sum = 0;
int cur = 0;
while ((!queue.isEmpty())) {
cur = queue.poll() + queue.poll();
sum += cur;
queue.add(cur);
}
return sum;
}
/*投资问题:
给定一个Program数组,每个Program里存放了c:成本和b:利润
给定一个整型k代表最多可以做k个项目
给定一个整型x代表本金,问怎样使所得利益最大,并返回
* */
public class Program {
int c;
int b;
}
public static int getMaxBenifits(Program[] programs, int x, int k) {
//小根堆
PriorityQueue<Program> queue1 = new PriorityQueue<>(new Comparator<Program>() {
@Override
public int compare(Program o1, Program o2) {
return o1.c - o2.c;
}
});
//大根堆
PriorityQueue<Program> queue2 = new PriorityQueue<>(new Comparator<Program>() {
@Override
public int compare(Program o1, Program o2) {
return o2.b - o1.b;
}
});
//将所有项目全部加入到小根堆里
for (int i = 0; i < programs.length; i++) {
queue1.add(programs[i]);
}
//当前可以做的起的项目按照利润全部放入大根堆
while (!queue1.isEmpty()) {
while (queue1.peek().c <= x) {
queue2.add(queue1.poll());
}
//没有能够做的起的项目了,直接返回
if(queue2.isEmpty()){
return x;
}
//弹出能做的起的项目中利润最大的,更新x
Program cur = queue2.poll();
//进行k轮后结束
if(--k<0) break;
x = x+cur.b;
}
return x;
}
/*给定一个数组int[] nums,要求能随时返回其中位数
* */
public static int getMedian(int[] nums){
//大根堆
PriorityQueue<Integer> queue1 = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//小根堆
PriorityQueue<Integer> queue2 = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
queue1.add(nums[0]);
for (int i = 1; i < nums.length; i++) {
//当前元素值
int cur = nums[i];
//当前值比大根堆顶部值小,加入小根堆
if(cur<queue1.peek()){
queue2.add(cur);
//加入小根堆后判断是否小根堆长度超过大根堆长度2个,如果是弹出小根堆堆顶加入大根堆
if(queue2.size()-queue1.size()>=2){
queue1.add(queue2.poll());
}
}
//当前元素比大顶堆顶部值大或者相等,加入大根堆
else {
queue1.add(cur);
//加入大根堆后判断大根堆长度是否超过小根堆长度2个,如果是将大根堆堆顶加入小根堆
if(queue1.size()-queue2.size()>=2){
queue2.add(queue1.poll());
}
}
}
//两个堆长度不一样,返回较长的那个的顶部
if(queue1.size()!=queue2.size()){
return queue1.size()>queue2.size()?queue1.peek():queue2.peek();
}
//两个堆长度相同,返回两个堆顶部和的平均值
return (queue1.peek()+queue2.peek())/2;
}