package com.zuoshen.jichurumen.class07;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* @author ShiZhe
* @create 2022-03-08 23:14
*/
public class code01 {
/**
* 前缀数节点结构
*/
public static class TrieNode {
// 通过次数
public int pass;
// 作为结尾节点的次数
public int end;
// 可能包涵的节点数组
public TrieNode[] nexts;
public TrieNode() {
pass = 0;
end = 0;
// 题目是26个字母的小写
nexts = new TrieNode[26];
}
}
/**
* 前缀树
*/
public static class Trie {
// 头结点
public TrieNode root;
// 初始化
public Trie() {
root = new TrieNode();
}
// 字符串插入
public void insert(String word) {
if (word == null) {
return;
}
// 将字符串转为字符数组
char[] chars = word.toCharArray();
// 将前缀树根节点赋值给node
TrieNode node = root;
// 节点数组的下标
int index = 0;
// 循环
for (int i = 0; i < chars.length; i++) {
index = chars[i] - 'a';
if (node.nexts[index] == null) {
node.nexts[index] = new TrieNode();
}
node = node.nexts[index];
node.pass++;
}
node.end++;
}
// 查看某字符串是否存在,存在返回字符串插入次数即end
public int search(String word) {
if (word == null) {
return 0;
}
char[] chars = word.toCharArray();
TrieNode node = root;
int index = 0;
for (int i = 0; i < chars.length; i++) {
index = chars[i] - 'a';
if (node.nexts[index] == null) {
return 0;
}
node = node.nexts[index];
}
return node.end;
}
// 删除某字符串
public void delete(String word) {
if (search(word) != 0) {
char[] chars = word.toCharArray();
TrieNode node = root;
int index = 0;
for (int i = 0; i < chars.length; i++) {
index = chars[i] - 'a';
// 当该路径只有该字符串时,后面不需要遍历,直接删除
if (--node.nexts[index].pass == 0) {
node.nexts[index] = null;
return;
}
node = node.nexts[i];
}
node.end--;
}
}
// 查找以某字符串为前缀的数量
public int prefixNumber(String pre) {
if (pre == null) {
return 0;
}
char[] chars = pre.toCharArray();
TrieNode node = root;
int index = 0;
for (int i = 0; i < chars.length; i++) {
index = chars[i] - 'a';
if (node.nexts[index] == null) {
return 0;
}
node = node.nexts[index];
}
return node.pass;
}
}
/**
* 字符串拼接的最小字典序问题——贪心
* 字典序:字符串在字典中的位置
* @param strings
* @return
*/
public static String lowestString(String[] strings) {
if (strings == null || strings.length == 0) {
return "";
}
Arrays.sort(strings, new MyComparator());
String result = "";
for (int i = 0; i < strings.length; i++) {
result += strings[i];
}
return result;
}
/**
* 字符串拼接问题的比较器
*/
public static class MyComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return (o1 + o2).compareTo(o2 + o1);
}
}
/**
* 切金条问题
* 哈弗曼编码
* @param arr
* @return
*/
public static int lessMoney(int[] arr) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
for (int i = 0; i < arr.length; i++) {
priorityQueue.add(arr[i]);
}
int sum = 0;
int cur;
while (priorityQueue.size() > 1) {
cur = priorityQueue.poll() + priorityQueue.poll();
sum += cur;
priorityQueue.add(cur);
}
return sum;
}
/**
* 会议室安排问题的项目结构
*/
public static class Program {
// 开始时间
public int start;
// 结束时间
public int end;
// 构造函数
public Program(int start, int end) {
this.start = start;
this.end = end;
}
}
/**
* 会议室安排——贪心
* 按照结束时间排序,持续时间越短,安排越多
* @param programs
* @param start
* @return
*/
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;
}
/**
* 会议室安排问题定义的比较器,按照end排列
*/
public static class ProgramComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.end - o2.end;
}
}
/**
* IPO对应的节点结构
*/
public static class CostNode {
// 花费
public int cost;
// 利润
public int profit;
// 构造函数
public CostNode(int cost, int profit) {
this.cost = cost;
this.profit = profit;
}
}
/**
* 每做完一个项目,马上获得的收益,可以支持你去做下一个项目
* @param costs 表示i号项目的花费
* @param profits 表示i号项目在扣除花费之后还能挣到的钱(利润)
* @param k 表示你只能串行的最多做k个项目
* @param m 表示你初始的资金
* @return 最后获得的最大钱数
*/
public static int findMaximizedCapital(int[] costs, int[] profits, int k, int m) {
// 节点初始化
CostNode[] costNodes = new CostNode[costs.length];
// 节点填充数据
for (int i = 0; i < costs.length; i++) {
costNodes[i] = new CostNode(costs[i], profits[i]);
}
// 项目的cost小根堆
PriorityQueue<CostNode> minCostQueue = new PriorityQueue<>(new MinCostComparator());
// 可进行项目的profit大根堆
PriorityQueue<CostNode> maxProfitQueue = new PriorityQueue<>(new MaxProfitComparator());
// 小根堆初始化
for (int i = 0; i < costNodes.length; i++) {
minCostQueue.add(costNodes[i]);
}
// k个项目限制
for (int i = 0; i < k; i++) {
// peek()获取堆顶元素但是不弹出
while (!minCostQueue.isEmpty() && minCostQueue.peek().cost <= m) {
maxProfitQueue.add(minCostQueue.poll());
}
// 无满足当前资金的花费的项目
if (maxProfitQueue.isEmpty()) {
return m;
}
// 利润叠加
m += maxProfitQueue.poll().profit;
}
return m;
}
/**
* cost从小到大排序
*/
public static class MinCostComparator implements Comparator<CostNode> {
@Override
public int compare(CostNode o1, CostNode o2) {
return o1.cost - o2.cost;
}
}
/**
* profit从大到小排序
*/
public static class MaxProfitComparator implements Comparator<CostNode> {
@Override
public int compare(CostNode o1, CostNode o2) {
return o2.profit - o1.profit;
}
}
/**
* 一个数据流中,随时可以取得中位数
* 2个堆,一个从小到大,一个从大到小
*/
public static class MedianHolder {
// 小根堆保存的是大值
private PriorityQueue<Integer> minQueue = new PriorityQueue<>(new MinHeapComparator());
// 大根堆保存的是小值
private PriorityQueue<Integer> maxQueue = new PriorityQueue<>(new MaxHeapComparator());
// 调整,保证2个堆的size差不大于2
private void modifyTwoHeapsSize() {
if (this.minQueue.size() == this.maxQueue.size() + 2) {
this.maxQueue.add(this.minQueue.poll());
}
if (this.maxQueue.size() == this.minQueue.size() + 2) {
this.minQueue.add(this.maxQueue.poll());
}
}
// 添加数
private void addNumber(int num) {
if (maxQueue.isEmpty() || num <= maxQueue.peek()) {
maxQueue.add(num);
} else {
minQueue.add(num);
}
modifyTwoHeapsSize();
}
// 获取中位数
public Integer getMedian() {
int maxSize = this.maxQueue.size();
int minSize = this.minQueue.size();
// 无数
if (maxSize + minSize == 0) {
return null;
}
Integer maxHead = this.maxQueue.peek();
Integer minHead = this.minQueue.peek();
// 总数为偶数,中位数是中间2个数之和的一半
// 条件为maxSize == minSize也行
if (((maxSize + minSize) & 1) == 0) {
return (maxHead + minHead) / 2;
}
return maxSize > minSize ? maxHead :minHead;
}
}
/**
* 小根堆
*/
public static class MinHeapComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
/**
* 大根堆
*/
public static class MaxHeapComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o2 -o1;
}
}
public static void main(String[] args) {
// 前缀树
Trie trie = new Trie();
System.out.println(trie.search("zuo"));
trie.insert("zuo");
System.out.println(trie.search("zuo"));
trie.delete("zuo");
System.out.println(trie.search("zuo"));
trie.insert("zuo");
trie.insert("zuo");
trie.delete("zuo");
System.out.println(trie.search("zuo"));
trie.delete("zuo");
System.out.println(trie.search("zuo"));
trie.insert("zuoa");
trie.insert("zuoac");
trie.insert("zuoab");
trie.insert("zuoad");
trie.delete("zuoa");
System.out.println(trie.search("zuoa"));
System.out.println(trie.prefixNumber("zuo"));
// 字符串拼接最小字典序
String[] strs1 = { "jibw", "ji", "jp", "bw", "jibw" };
System.out.println(lowestString(strs1));
String[] strs2 = { "ba", "b" };
System.out.println(lowestString(strs2));
// 切金条问题
int[] arr = { 6, 7, 8, 9 };
System.out.println(lessMoney(arr));
}
}