ipqtjmqj 2020-01-23
何为前缀树?如何生成前缀树?
例子:一个字符串类型的数组arrl,另一个字符串类型的数组arr2。arr2中有哪些字符,是arr 1中 出现的?请打印。arr2中有哪些字符,是作为arr 1中某个字符串前缀出现的?请打印。arr2 中有哪些字符,是作为arr1中某个字符串前缀出现的?请打印arr2中出现次数最大的前缀。
public class TrieTree { public static class TrieNode { public int path; public int end; public TrieNode[] nexts; public TrieNode() { path = 0; end = 0; nexts = new TrieNode[26]; } } public static class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } public void insert(String word) { if (word == null) { return; } char[] chs = word.toCharArray(); TrieNode node = root; int index = 0; for (int i = 0; i < chs.length; i++) { index = chs[i] - 'a'; if (node.nexts[index] == null) { node.nexts[index] = new TrieNode(); } node = node.nexts[index]; node.path++; } node.end++; } public void delete(String word) { if (search(word) != 0) { //确定树中确定加入过word,才删除 char[] chs = word.toCharArray(); TrieNode node = root; int index = 0; for (int i = 0; i < chs.length; i++) { index = chs[i] - 'a'; if (--node.nexts[index].path == 0) { //C++要遍历到底去析构 node.nexts[index] = null; return; } node = node.nexts[index]; } node.end--; } } public int search(String word) { //word这个单词之前加入过几次 if (word == null) { return 0; } char[] chs = word.toCharArray(); TrieNode node = root; int index = 0; for (int i = 0; i < chs.length; i++) { index = chs[i] - 'a'; if (node.nexts[index] == null) { return 0; } node = node.nexts[index]; } return node.end; } public int prefixNumber(String pre) { if (pre == null) { return 0; } char[] chs = pre.toCharArray(); TrieNode node = root; int index = 0; for (int i = 0; i < chs.length; i++) { index = chs[i] - 'a'; if (node.nexts[index] == null) { return 0; } node = node.nexts[index]; } return node.path; } } 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")); } }
在某一个标准下,优先考虑最满足标准的样本,最后考虑最不满足标准的样本,最终得到 一个答案的算法,叫作贪心算法。也就是说,不从整体最优上加以考虑,所做出的是在某种意义上的局部最优解。
局部最优-?->整体最优
1, 实现一个不依靠贪心策略的解法X,可以用最暴力的尝试
2, 脑补出贪心策略A、贪心策略B、贪心策略C...
3, 用解法X和对数器,去验证每一个贪心策略,用实验的方式得知哪个贪心策略正确
4,不要去纠结贪心策略的证明
例子:给定一个字符串类型的数组strs,找到一种拼接方式,使得把所有字符串拼起来之后形成的 字符串具有最小的字典序。证明贪心策略可能是件非常腌心的事情。平时当然推荐你搞清楚所有的来龙去脉,但是笔试 时用对数器的方式!
比较策略,要有传递性
import java.util.Arrays; import java.util.Comparator; public class 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" }; }
1, 根据某标准建立一个比较器来排序
2, 根据某标准建立一个比较器来组成堆
一块金条切成两半,是需要花费和长度数值一样的铜板的。比如长度为20的金 条,不管切成长度多大的两半,都要花费20个铜板。一群人想整分整块金条,怎么分最省铜板?
例如,给定数组{10,20,30},代表一共三个人,整块金条长度为10+20+30=60。金条要分成10,20,30三个部分。如果先把长度60的金条分成10和50,花费60; 再把长度50的金条分成20和30,花费50; 一共花费110铜板。但是如果先把长度60的金条分成30和30,花费60;再把长度30金条分成10和20, 花费30; 一共花费90铜板。输入一个数组,返回分割的最小代价。
import java.util.Comparator; import java.util.PriorityQueue; public class LessMoneySplitGold { 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; } public static class MinheapComparator implements Comparator<Integer> { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; // < 0 o1 < o2 负数 } } public static class MaxheapComparator implements Comparator<Integer> { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; // < o2 < o1 } } public static void main(String[] args) { // solution int[] arr = { 6, 7, 8, 9 }; System.out.println(lessMoney(arr)); int[] arrForHeap = { 3, 5, 2, 7, 0, 1, 6, 4 }; // min heap PriorityQueue<Integer> minQ1 = new PriorityQueue<>(); for (int i = 0; i < arrForHeap.length; i++) { minQ1.add(arrForHeap[i]); } while (!minQ1.isEmpty()) { System.out.print(minQ1.poll() + " "); } System.out.println(); // min heap use Comparator PriorityQueue<Integer> minQ2 = new PriorityQueue<>(new MinheapComparator()); for (int i = 0; i < arrForHeap.length; i++) { minQ2.add(arrForHeap[i]); } while (!minQ2.isEmpty()) { System.out.print(minQ2.poll() + " "); } System.out.println(); // max heap use Comparator PriorityQueue<Integer> maxQ = new PriorityQueue<>(new MaxheapComparator()); for (int i = 0; i < arrForHeap.length; i++) { maxQ.add(arrForHeap[i]); } while (!maxQ.isEmpty()) { System.out.print(maxQ.poll() + " "); } } }
一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。 给你每一个项目开始的时间和结束的时间(给你一个数组,里面是一个个具体 的项目),你来安排宣讲的日程,要求会议室进行的宣讲的场次最多。返回这个最多的宣讲场次。
import java.util.Arrays; import java.util.Comparator; 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) { } }
输入:正数数组costs 正数数组profits 正数k 正数m
含义:costs [i]表示i号项目的花费 profits [i]表示i号项目在扣除花费之后还能挣到的钱(利润)
k表示你只能串行的最多做k个项目 m表示你初始的资金
说明:你每做完一个项目,马上获得的收益,可以支持你去做下一个项目。
输出:你最后获得的最大钱数。
import java.util.Comparator; import java.util.PriorityQueue; public class IPO { public static class Node { public int p; public int c; public Node(int p, int c) { this.p = p; this.c = c; } } public static class MinCostComparator implements Comparator<Node> { @Override public int compare(Node o1, Node o2) { return o1.c - o2.c; } } public static class MaxProfitComparator implements Comparator<Node> { @Override public int compare(Node o1, Node o2) { return o2.p - o1.p; } } 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; } }
import java.util.Arrays; import java.util.Comparator; import java.util.PriorityQueue; public class MadianQuick { public static class MedianHolder { private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new MaxHeapComparator()); private PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(new MinHeapComparator()); private void modifyTwoHeapsSize() { if (this.maxHeap.size() == this.minHeap.size() + 2) { this.minHeap.add(this.maxHeap.poll()); } if (this.minHeap.size() == this.maxHeap.size() + 2) { this.maxHeap.add(this.minHeap.poll()); } } public void addNumber(int num) { if (maxHeap.isEmpty() || num <= maxHeap.peek()) { maxHeap.add(num); } else { minHeap.add(num); } modifyTwoHeapsSize(); } public Integer getMedian() { int maxHeapSize = this.maxHeap.size(); int minHeapSize = this.minHeap.size(); if (maxHeapSize + minHeapSize == 0) { return null; } Integer maxHeapHead = this.maxHeap.peek(); Integer minHeapHead = this.minHeap.peek(); if (((maxHeapSize + minHeapSize) & 1) == 0) { return (maxHeapHead + minHeapHead) / 2; } return maxHeapSize > minHeapSize ? maxHeapHead : minHeapHead; } } public static class MaxHeapComparator implements Comparator<Integer> { @Override public int compare(Integer o1, Integer o2) { if (o2 > o1) { return 1; } else { return -1; } } } public static class MinHeapComparator implements Comparator<Integer> { @Override public int compare(Integer o1, Integer o2) { if (o2 < o1) { return 1; } else { return -1; } } } // for test public static int[] getRandomArray(int maxLen, int maxValue) { int[] res = new int[(int) (Math.random() * maxLen) + 1]; for (int i = 0; i != res.length; i++) { res[i] = (int) (Math.random() * maxValue); } return res; } // for test, this method is ineffective but absolutely right public static int getMedianOfArray(int[] arr) { int[] newArr = Arrays.copyOf(arr, arr.length); Arrays.sort(newArr); int mid = (newArr.length - 1) / 2; if ((newArr.length & 1) == 0) { return (newArr[mid] + newArr[mid + 1]) / 2; } else { return newArr[mid]; } } public static void printArray(int[] arr) { for (int i = 0; i != arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } public static void main(String[] args) { boolean err = false; int testTimes = 200000; for (int i = 0; i != testTimes; i++) { int len = 30; int maxValue = 1000; int[] arr = getRandomArray(len, maxValue); MedianHolder medianHold = new MedianHolder(); for (int j = 0; j != arr.length; j++) { medianHold.addNumber(arr[j]); } if (medianHold.getMedian() != getMedianOfArray(arr)) { err = true; printArray(arr); break; } } System.out.println(err ? "Oops" : "beautiful ^_^"); } }