package class14;
import java.util.Arrays;
import java.util.Comparator;
public class Code03_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 int bestArrange1(Program[] programs) {
if (programs == null || programs.length == 0) {
return 0;
}
return process(programs, 0, 0);
}
// 还剩下的会议都放在programs里
// done之前已经安排了多少会议的数量
// timeLine目前来到的时间点是什么
// 目前来到timeLine的时间点,已经安排了done多的会议,剩下的会议programs可以自由安排
// 返回能安排的最多会议数量
public static int process(Program[] programs, int done, int timeLine) {
if (programs.length == 0) {
return done;
}
// 还剩下会议
int max = done;
// 当前安排的会议是什么会,每一个都枚举
for (int i = 0; i < programs.length; i++) {
if (programs[i].start >= timeLine) {
Program[] next = copyButExcept(programs, i);
max = Math.max(max, process(next, done + 1, programs[i].end));
}
}
return max;
}
public static Program[] copyButExcept(Program[] programs, int i) {
Program[] ans = new Program[programs.length - 1];
int index = 0;
for (int k = 0; k < programs.length; k++) {
if (k != i) {
ans[index++] = programs[k];
}
}
return ans;
}
// 会议的开始时间和结束时间,都是数值,不会 < 0
public static int bestArrange2(Program[] programs) {
Arrays.sort(programs, new ProgramComparator());
int timeLine = 0;
int result = 0;
// 依次遍历每一个会议,结束时间早的会议先遍历
for (int i = 0; i < programs.length; i++) {
if (timeLine <= programs[i].start) {
result++;
timeLine = programs[i].end;
}
}
return result;
}
public static class ProgramComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.end - o2.end;
}
}
// for test
public static Program[] generatePrograms(int programSize, int timeMax) {
Program[] ans = new Program[(int) (Math.random() * (programSize + 1))];
for (int i = 0; i < ans.length; i++) {
int r1 = (int) (Math.random() * (timeMax + 1));
int r2 = (int) (Math.random() * (timeMax + 1));
if (r1 == r2) {
ans[i] = new Program(r1, r1 + 1);
} else {
ans[i] = new Program(Math.min(r1, r2), Math.max(r1, r2));
}
}
return ans;
}
public static void main(String[] args) {
int programSize = 12;
int timeMax = 20;
int timeTimes = 1000000;
for (int i = 0; i < timeTimes; i++) {
Program[] programs = generatePrograms(programSize, timeMax);
if (bestArrange1(programs) != bestArrange2(programs)) {
System.out.println("Oops!");
}
}
System.out.println("finish!");
}
}
给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有可能的拼接结果中字典序最小的结果
package class13;
import java.util.Arrays;
import java.util.Comparator;
import java.util.TreeSet;
public class Code05_LowestLexicography {
public static String lowestString1(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
TreeSet<String> ans = process(strs);
return ans.size() == 0 ? "" : ans.first();
}
// strs中所有字符串全排列,返回所有可能的结果
public static TreeSet<String> process(String[] strs) {
TreeSet<String> ans = new TreeSet<>();
if (strs.length == 0) {
ans.add("");
return ans;
}
for (int i = 0; i < strs.length; i++) {
String first = strs[i];
String[] nexts = removeIndexString(strs, i);
TreeSet<String> next = process(nexts);
for (String cur : next) {
ans.add(first + cur);
}
}
return ans;
}
// {"abc", "cks", "bct"}
// 0 1 2
// removeIndexString(arr , 1) -> {"abc", "bct"}
public static String[] removeIndexString(String[] arr, int index) {
int N = arr.length;
String[] ans = new String[N - 1];
int ansIndex = 0;
for (int i = 0; i < N; i++) {
if (i != index) {
ans[ansIndex++] = arr[i];
}
}
return ans;
}
public static class MyComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
return (a + b).compareTo(b + a);
}
}
public static String lowestString2(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;
}
// for test
public static String generateRandomString(int strLen) {
char[] ans = new char[(int) (Math.random() * strLen) + 1];
for (int i = 0; i < ans.length; i++) {
int value = (int) (Math.random() * 5);
ans[i] = (Math.random() <= 0.5) ? (char) (65 + value) : (char) (97 + value);
}
return String.valueOf(ans);
}
// for test
public static String[] generateRandomStringArray(int arrLen, int strLen) {
String[] ans = new String[(int) (Math.random() * arrLen) + 1];
for (int i = 0; i < ans.length; i++) {
ans[i] = generateRandomString(strLen);
}
return ans;
}
// for test
public static String[] copyStringArray(String[] arr) {
String[] ans = new String[arr.length];
for (int i = 0; i < ans.length; i++) {
ans[i] = String.valueOf(arr[i]);
}
return ans;
}
public static void main(String[] args) {
int arrLen = 6;
int strLen = 5;
int testTimes = 10000;
System.out.println("test begin");
for (int i = 0; i < testTimes; i++) {
String[] arr1 = generateRandomStringArray(arrLen, strLen);
String[] arr2 = copyStringArray(arr1);
if (!lowestString1(arr1).equals(lowestString2(arr2))) {
for (String str : arr1) {
System.out.print(str + ",");
}
System.out.println();
System.out.println("Oops!");
}
}
System.out.println("finish!");
}
}
一块金条切成两半,是需要花费和长度数值一样的铜板
比如长度为20的金条,不管怎么切都要花费20个铜板,一群人想整分整块金条,怎么分最省铜板?
例如,给定数组{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铜板
输入一个数组,返回分割的最小代价
package class14;
import java.util.PriorityQueue;
public class Code02_LessMoneySplitGold {
// 纯暴力!
public static int lessMoney1(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
return process(arr, 0);
}
// 等待合并的数都在arr里,pre之前的合并行为产生了多少总代价
// arr中只剩一个数字的时候,停止合并,返回最小的总代价
public static int process(int[] arr, int pre) {
if (arr.length == 1) {
return pre;
}
int ans = Integer.MAX_VALUE;
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
ans = Math.min(ans, process(copyAndMergeTwo(arr, i, j), pre + arr[i] + arr[j]));
}
}
return ans;
}
public static int[] copyAndMergeTwo(int[] arr, int i, int j) {
int[] ans = new int[arr.length - 1];
int ansi = 0;
for (int arri = 0; arri < arr.length; arri++) {
if (arri != i && arri != j) {
ans[ansi++] = arr[arri];
}
}
ans[ansi] = arr[i] + arr[j];
return ans;
}
public static int lessMoney2(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;
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * (maxValue + 1));
}
return arr;
}
public static void main(String[] args) {
int testTime = 100000;
int maxSize = 6;
int maxValue = 1000;
for (int i = 0; i < testTime; i++) {
int[] arr = generateRandomArray(maxSize, maxValue);
if (lessMoney1(arr) != lessMoney2(arr)) {
System.out.println("Oops!");
}
}
System.out.println("finish!");
}
}
输入:
正数数组costs正数数组profits正数k
正数m含义:
costs[i] 表示 i 号项目的花费
profits[i] 表示 i 号项目在扣除花费之后还能挣到的钱(利润) k 表示你只能串行的最多做k个项目
m表示你初始的资金
说明:
你每做完一个项目,马上获得的收益,可以支持你去做下一个项目。
输出:
你最后获得的最大钱数。
package class14;
import java.util.Comparator;
import java.util.PriorityQueue;
public class Code04_IPO {
// 最多K个项目
// W是初始资金
// Profits[] Capital[] 一定等长
// 返回最终最大的资金
public static int findMaximizedCapital(int K, int W, int[] Profits, int[] Capital) {
PriorityQueue<Program> minCostQ = new PriorityQueue<>(new MinCostComparator());
PriorityQueue<Program> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
for (int i = 0; i < Profits.length; i++) {
minCostQ.add(new Program(Profits[i], Capital[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;
}
public static class Program {
public int p;
public int c;
public Program(int p, int c) {
this.p = p;
this.c = c;
}
}
public static class MinCostComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.c - o2.c;
}
}
public static class MaxProfitComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o2.p - o1.p;
}
}
}
给定一个字符串str,只由’X’和’.'两种字符构成
‘X’表示墙,不能放灯,也不需要点亮;’.'表示居民点,可以放灯,需要点亮
如果灯放在i位置,可以让i-1,i和i+1三个位置被点亮
返回如果点亮str中所有需要点亮的位置,至少需要几盏灯
package class14;
import java.util.HashSet;
public class Code01_Light {
public static int minLight1(String road) {
if (road == null || road.length() == 0) {
return 0;
}
return process(road.toCharArray(), 0, new HashSet<>());
}
// str[index....]位置,自由选择放灯还是不放灯
// str[0..index-1]位置呢?已经做完决定了,那些放了灯的位置,存在lights里
// 要求选出能照亮所有.的方案,并且在这些有效的方案中,返回最少需要几个灯
public static int process(char[] str, int index, HashSet<Integer> lights) {
if (index == str.length) { // 结束的时候
for (int i = 0; i < str.length; i++) {
if (str[i] != 'X') { // 当前位置是点的话
if (!lights.contains(i - 1) && !lights.contains(i) && !lights.contains(i + 1)) {
return Integer.MAX_VALUE;
}
}
}
return lights.size();
} else { // str还没结束
// i X .
int no = process(str, index + 1, lights);
int yes = Integer.MAX_VALUE;
if (str[index] == '.') {
lights.add(index);
yes = process(str, index + 1, lights);
lights.remove(index);
}
return Math.min(no, yes);
}
}
public static int minLight2(String road) {
char[] str = road.toCharArray();
int i = 0;
int light = 0;
while (i < str.length) {
if (str[i] == 'X') {
i++;
} else {
light++;
if (i + 1 == str.length) {
break;
} else { // 有i位置 i+ 1 X .
if (str[i + 1] == 'X') {
i = i + 2;
} else {
i = i + 3;
}
}
}
}
return light;
}
// 更简洁的解法
// 两个X之间,数一下.的数量,然后除以3,向上取整
// 把灯数累加
public static int minLight3(String road) {
char[] str = road.toCharArray();
int cur = 0;
int light = 0;
for (char c : str) {
if (c == 'X') {
light += (cur + 2) / 3;
cur = 0;
} else {
cur++;
}
}
light += (cur + 2) / 3;
return light;
}
// for test
public static String randomString(int len) {
char[] res = new char[(int) (Math.random() * len) + 1];
for (int i = 0; i < res.length; i++) {
res[i] = Math.random() < 0.5 ? 'X' : '.';
}
return String.valueOf(res);
}
public static void main(String[] args) {
int len = 20;
int testTime = 100000;
for (int i = 0; i < testTime; i++) {
String test = randomString(len);
int ans1 = minLight1(test);
int ans2 = minLight2(test);
int ans3 = minLight3(test);
if (ans1 != ans2 || ans1 != ans3) {
System.out.println("oops!");
}
}
System.out.println("finish!");
}
}