字符串拼接
给定一个字符串类型的数组strs,找到一种拼接方式,使得把所有字符串拼起来之后形成的字符串具有最低的字典序。
import java.util.Arrays;
import java.util.Comparator;
public class hello {
//定义比较器(利用字典序):a连接b跟b连接a的字符串大小比较
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"};
System.out.println(lowestString(strs1));
String[] strs2 = { "ba", "b" };
System.out.println(lowestString(strs2));
}
}
结果:
jibwji
bab
注:
(1)只能比较str1.str2<=str2.str1,不可以直接比较str1<=str2
例:比较字符串b ba
字符串本身b<ba,但是连接后的字符串 bba>bab
(2)字符串连接比较具有传递性
a.b<=b.a,b.c<=c.b
可以推出a.c<=c.a
切割铜板
一块金条切成两半,是需要花费和长度数值一样的铜板的。比如长度为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铜板。 输入一个数组,返回分割的最小代价。
方法:构造哈夫曼树
给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。
哈夫曼树的构造:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
优先级队列:
如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。
import java.util.PriorityQueue;
public class hello {
//计算最少钱数
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 void main(String[] args) {
// solution
int[] arr = { 6, 7, 8, 9 };
System.out.println(lessMoney(arr));
}
}
结果:60
收益最大
输入: 参数1,正数数组costs ;参数2,正数数组profits ;参数3, 正数k ;参数4 ,正数m
costs[i]表示i号项目的花费
profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润)
k表示你不能并行、只能串行的最多做k个项目
m表示你初始的资金
说明:你每做完一个项目,马上获得的收益,可以支持你去做下 一个 项目。
输出: 你最后获得的最大钱数。
import java.util.Comparator;
import java.util.PriorityQueue;
public class hello {
public static class Node {
public int p; //p是收益
public int c; //c是花费
//node为项目
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;
}
}
//寻找最大收益(k为最多做的项目,w为初始启动资金,profits为利润数组,capital为花费数组)
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]);
}
//cost小根堆
PriorityQueue<Node> minCostQ = new PriorityQueue<>(new MinCostComparator());
//profit大根堆
PriorityQueue<Node> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
//所有项目加入小根堆
for (int i = 0; i < nodes.length; i++) {
minCostQ.add(nodes[i]);
}
//要做的项目最多做k个
for (int i = 0; i < k; i++) {
//花费最少的小于初始启动资金,满足条件的加入profit大根堆(解锁)
while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) {
maxProfitQ.add(minCostQ.poll());
}
//做不到k个项目就提前终止
if (maxProfitQ.isEmpty()) {
return W;
}
W += maxProfitQ.poll().p;
}
return W;
}
}
宣讲场次
一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。 给你每一个项目开始的时间和结束的时间(给你一个数组,里面 是一个个具体的项目),你来安排宣讲的日程,要求会议室进行 的宣讲的场次最多。返回这个最多的宣讲场次。
方法:按结束时间早晚排,早结束优先。
import java.util.Arrays;
import java.util.Comparator;
public class hello {
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) {
}
}