@@ -873,235 +873,150 @@ func lcse(str1, str2 string) int {
873873例题:给定一个数组,代表每个人喝完咖啡准备刷杯子的时间,只有一台咖啡机,一次只能洗一个杯子,时间耗费a,洗完才能洗下一杯。每个咖啡杯也可以自己挥发干净,时间耗费b,咖啡杯可以并行挥发。返回让所有咖啡杯变干净的最早完成时间。三个参数:int[ ] arr , int a , int b(京东)
874874
875875
876- ``` Java
877- package class12 ;
876+ ``` Go
877+ package main
878878
879- import java.util.Arrays ;
880- import java.util.Comparator ;
881- import java.util.PriorityQueue ;
879+ import " math"
882880
883- // 题目
884881// 数组arr代表每一个咖啡机冲一杯咖啡的时间,每个咖啡机只能串行的制造咖啡。
885882// 现在有n个人需要喝咖啡,只能用咖啡机来制造咖啡。
886883// 认为每个人喝咖啡的时间非常短,冲好的时间即是喝完的时间。
887884// 每个人喝完之后咖啡杯可以选择洗或者自然挥发干净,只有一台洗咖啡杯的机器,只能串行的洗咖啡杯。
888885// 洗杯子的机器洗完一个杯子时间为a,任何一个杯子自然挥发干净的时间为b。
889886// 四个参数:arr, n, a, b
890887// 假设时间点从0开始,返回所有人喝完咖啡并洗完咖啡杯的全部过程结束后,至少来到什么时间点。
891- public class Code06_Coffee {
892888
893- // 方法一:暴力尝试方法
894- public static int minTime1 (int [] arr , int n , int a , int b ) {
895- int [] times = new int [arr. length];
896- int [] drink = new int [n];
897- return forceMake(arr, times, 0 , drink, n, a, b);
898- }
899-
900- // 方法一,每个人暴力尝试用每一个咖啡机给自己做咖啡
901- public static int forceMake (int [] arr , int [] times , int kth , int [] drink , int n , int a , int b ) {
902- if (kth == n) {
903- int [] drinkSorted = Arrays . copyOf(drink, kth);
904- Arrays . sort(drinkSorted);
905- return forceWash(drinkSorted, a, b, 0 , 0 , 0 );
906- }
907- int time = Integer . MAX_VALUE ;
908- for (int i = 0 ; i < arr. length; i++ ) {
909- int work = arr[i];
910- int pre = times[i];
911- drink[kth] = pre + work;
912- times[i] = pre + work;
913- time = Math . min(time, forceMake(arr, times, kth + 1 , drink, n, a, b));
914- drink[kth] = 0 ;
915- times[i] = pre;
889+ // 方法二,每个人暴力尝试用每一个咖啡机给自己做咖啡,优化成贪心
890+ func minTime2 (arr []int , n , a , b int ) int {
891+ heap := &Machines{
892+ Machines: make ([]*Machine, 0 ),
916893 }
917- return time;
918- }
919894
920- // 方法一,暴力尝试洗咖啡杯的方式
921- public static int forceWash (int [] drinks , int a , int b , int index , int washLine , int time ) {
922- if (index == drinks. length) {
923- return time;
895+ // 构造洗碗机加入堆中
896+ for i := 0 ; i < len (arr); i++ {
897+ heap.Push (&Machine{
898+ TimePoint: 0 ,
899+ WorkTime: arr[i],
900+ })
924901 }
925- // 选择一:当前index号咖啡杯,选择用洗咖啡机刷干净
926- int wash = Math . max(drinks[index], washLine) + a;
927- int ans1 = forceWash(drinks, a, b, index + 1 , wash, Math . max(wash, time));
928-
929- // 选择二:当前index号咖啡杯,选择自然挥发
930- int dry = drinks[index] + b;
931- int ans2 = forceWash(drinks, a, b, index + 1 , washLine, Math . max(dry, time));
932- return Math . min(ans1, ans2);
902+
903+ drinks := make ([]int , n)
904+ for i := 0 ; i<n; i++ {
905+ cur := heap.Pop ().(*Machine)
906+ cur.TimePoint += cur.WorkTime
907+ drinks[i] = cur.TimePoint
908+ heap.Push (cur)
933909 }
934910
935- // 方法二:稍微好一点的解法
936- public static class Machine {
937- public int timePoint;
938- public int workTime;
911+ return processMachineTime (drinks, a, b, 0 , 0 )
912+ }
939913
940- public Machine (int t , int w ) {
941- timePoint = t;
942- workTime = w;
943- }
944- }
914+ // 方法二,洗咖啡杯的方式和原来一样,只是这个暴力版本减少了一个可变参数
915+ // process(drinks, 3, 10, 0,0)
916+ // a 洗一杯的时间 固定变量
917+ // b 自己挥发干净的时间 固定变量
918+ // drinks 每一个员工喝完的时间 固定变量
919+ // drinks[0..index-1]都已经干净了,不用你操心了
920+ // drinks[index...]都想变干净,这是我操心的,washLine表示洗的机器何时可用
921+ // drinks[index...]变干净,最少的时间点返回
922+ func processMachineTime (drinks []int , a , b , index , washLine int ) int {
923+ if index == len (drinks) - 1 {
924+ return int (math.Min (math.Max (float64 (washLine), float64 (drinks[index] + a)), float64 (drinks[index] + b)))
925+ }
926+
927+ // 剩不止一杯咖啡
928+ // wash是我当前的咖啡杯,洗完的时间
929+ wash := int (math.Max (float64 (washLine), float64 (drinks[index]))) + a // 洗,index一杯,结束的时间点
930+ // index+1...变干净的最早时间
931+ next1 := processMachineTime (drinks, a, b, index + 1 , wash)
932+ // index....
933+ p1 := int (math.Max (float64 (wash), float64 (next1)))
934+ dry := drinks[index] + b // 挥发,index一杯,结束的时间点
935+ next2 := processMachineTime (drinks, a, b, index + 1 , washLine)
936+
937+ p2 := int (math.Max (float64 (dry), float64 (next2)))
938+ return int (math.Min (float64 (p1), float64 (p2)))
939+ }
945940
946- public static class MachineComparator implements Comparator<Machine > {
941+ // Machines 洗咖啡的机器构造堆结构
942+ type Machines struct {
943+ Machines []*Machine
944+ }
947945
948- @Override
949- public int compare ( Machine o1 , Machine o2 ) {
950- return (o1 . timePoint + o1 . workTime) - (o2 . timePoint + o2 . workTime);
951- }
946+ type Machine struct {
947+ TimePoint int
948+ WorkTime int
949+ }
952950
953- }
951+ func (c Machines ) Len () int {
952+ return len (c.Machines )
953+ }
954954
955- // 方法二,每个人暴力尝试用每一个咖啡机给自己做咖啡,优化成贪心
956- public static int minTime2 (int [] arr , int n , int a , int b ) {
957- PriorityQueue<Machine > heap = new PriorityQueue<Machine > (new MachineComparator ());
958- for (int i = 0 ; i < arr. length; i++ ) {
959- heap. add(new Machine (0 , arr[i]));
960- }
961- int [] drinks = new int [n];
962- for (int i = 0 ; i < n; i++ ) {
963- Machine cur = heap. poll();
964- cur. timePoint += cur. workTime;
965- drinks[i] = cur. timePoint;
966- heap. add(cur);
967- }
968- return process(drinks, a, b, 0 , 0 );
955+ // Less i对应的利润P的值大于j对应的值为true,则从大到小排序,即大根堆
956+ func (c Machines ) Less (i , j int ) bool {
957+ return (c.Machines [i].TimePoint + c.Machines [i].WorkTime ) < (c.Machines [j].TimePoint + c.Machines [j].WorkTime )
958+ }
959+
960+ func (c Machines ) Swap (i , j int ) {
961+ c.Machines [i], c.Machines [j] = c.Machines [j], c.Machines [i]
962+ }
963+
964+ func (c *Machines ) Push (h interface {}) {
965+ c.Machines = append (c.Machines , h.(*Machine))
966+ }
967+
968+ func (c *Machines ) Pop () (x interface {}) {
969+ n := len (c.Machines )
970+ x = c.Machines [n-1 ]
971+ c.Machines = c.Machines [:n-1 ]
972+ return x
973+ }
974+
975+ // 方法三:最终版本,把方法二洗咖啡杯的暴力尝试进一步优化成动态规划
976+ func minTime3 (arr []int , n , a , b int ) int {
977+ heap := &Machines{
978+ Machines: make ([]*Machine, 0 ),
969979 }
970980
971- // 方法二,洗咖啡杯的方式和原来一样,只是这个暴力版本减少了一个可变参数
972-
973- // process(drinks, 3, 10, 0,0)
974- // a 洗一杯的时间 固定变量
975- // b 自己挥发干净的时间 固定变量
976- // drinks 每一个员工喝完的时间 固定变量
977- // drinks[0..index-1]都已经干净了,不用你操心了
978- // drinks[index...]都想变干净,这是我操心的,washLine表示洗的机器何时可用
979- // drinks[index...]变干净,最少的时间点返回
980- public static int process (int [] drinks , int a , int b , int index , int washLine ) {
981- if (index == drinks. length - 1 ) {
982- return Math . min(Math . max(washLine, drinks[index]) + a, drinks[index] + b);
983- }
984- // 剩不止一杯咖啡
985- // wash是我当前的咖啡杯,洗完的时间
986- int wash = Math . max(washLine, drinks[index]) + a;// 洗,index一杯,结束的时间点
987- // index+1...变干净的最早时间
988- int next1 = process(drinks, a, b, index + 1 , wash);
989- // index....
990- int p1 = Math . max(wash, next1);
991- int dry = drinks[index] + b; // 挥发,index一杯,结束的时间点
992- int next2 = process(drinks, a, b, index + 1 , washLine);
993- int p2 = Math . max(dry, next2);
994- return Math . min(p1, p2);
981+ // 构造洗碗机加入堆中
982+ for i := 0 ; i < len (arr); i++ {
983+ heap.Push (&Machine{
984+ TimePoint: 0 ,
985+ WorkTime: arr[i],
986+ })
995987 }
996988
997- public static int dp (int [] drinks , int a , int b ) {
998- if (a >= b) {
999- return drinks[drinks. length - 1 ] + b;
1000- }
1001- // a < b
1002- int N = drinks. length;
1003- int limit = 0 ; // 咖啡机什么时候可用
1004- for (int i = 0 ; i < N ; i++ ) {
1005- limit = Math . max(limit, drinks[i]) + a;
1006- }
1007- int [][] dp = new int [N ][limit + 1 ];
1008- // N-1行,所有的值
1009- for (int washLine = 0 ; washLine <= limit; washLine++ ) {
1010- dp[N - 1 ][washLine] = Math . min(Math . max(washLine, drinks[N - 1 ]) + a, drinks[N - 1 ] + b);
1011- }
1012- for (int index = N - 2 ; index >= 0 ; index-- ) {
1013- for (int washLine = 0 ; washLine <= limit; washLine++ ) {
1014- int p1 = Integer . MAX_VALUE ;
1015- int wash = Math . max(washLine, drinks[index]) + a;
1016- if (wash <= limit) {
1017- p1 = Math . max(wash, dp[index + 1 ][wash]);
1018- }
1019- int p2 = Math . max(drinks[index] + b, dp[index + 1 ][washLine]);
1020- dp[index][washLine] = Math . min(p1, p2);
1021- }
1022- }
1023- return dp[0 ][0 ];
989+ drinks := make ([]int , n)
990+ for i := 0 ; i < n; i++ {
991+ cur := heap.Pop ().(*Machine)
992+ cur.TimePoint += cur.WorkTime
993+ drinks[i] = cur.TimePoint
994+ heap.Push (cur)
1024995 }
1025996
1026- // 方法三:最终版本,把方法二洗咖啡杯的暴力尝试进一步优化成动态规划
1027- public static int minTime3 (int [] arr , int n , int a , int b ) {
1028- PriorityQueue<Machine > heap = new PriorityQueue<Machine > (new MachineComparator ());
1029- for (int i = 0 ; i < arr. length; i++ ) {
1030- heap. add(new Machine (0 , arr[i]));
1031- }
1032- int [] drinks = new int [n];
1033- for (int i = 0 ; i < n; i++ ) {
1034- Machine cur = heap. poll();
1035- cur. timePoint += cur. workTime;
1036- drinks[i] = cur. timePoint;
1037- heap. add(cur);
1038- }
1039- if (a >= b) {
1040- return drinks[n - 1 ] + b;
1041- }
1042- int [][] dp = new int [n][drinks[n - 1 ] + n * a];
1043- for (int i = 0 ; i < dp[0 ]. length; i++ ) {
1044- dp[n - 1 ][i] = Math . min(Math . max(i, drinks[n - 1 ]) + a, drinks[n - 1 ] + b);
1045- }
1046- for (int row = n - 2 ; row >= 0 ; row-- ) { // row 咖啡杯的编号
1047- int washLine = drinks[row] + (row + 1 ) * a;
1048- for (int col = 0 ; col < washLine; col++ ) {
1049- int wash = Math . max(col, drinks[row]) + a;
1050- dp[row][col] = Math . min(Math . max(wash, dp[row + 1 ][wash]), Math . max(drinks[row] + b, dp[row + 1 ][col]));
1051- }
1052- }
1053- return dp[0 ][0 ];
997+ if a >= b {
998+ return drinks[n - 1 ] + b
1054999 }
10551000
1056- // for test
1057- public static int [] randomArray (int len , int max ) {
1058- int [] arr = new int [len];
1059- for (int i = 0 ; i < len; i++ ) {
1060- arr[i] = (int ) (Math . random() * max) + 1 ;
1061- }
1062- return arr;
1001+ dp := make ([][]int , n)
1002+ for i := 0 ; i < n; i++ {
1003+ dp[i] = make ([]int , drinks[n - 1 ] + n * a)
10631004 }
10641005
1065- // for test
1066- public static void printArray (int [] arr ) {
1067- System . out. print(" arr : " );
1068- for (int j = 0 ; j < arr. length; j++ ) {
1069- System . out. print(arr[j] + " , " );
1070- }
1071- System . out. println();
1006+ for i := 0 ; i < len (dp[0 ]); i++ {
1007+ dp[n - 1 ][i] = int (math.Min (math.Max (float64 (i), float64 (drinks[n - 1 ])) + float64 (a), float64 (drinks[n - 1 ] + b)))
10721008 }
10731009
1074- public static void main (String [] args ) {
1075- int [] test = { 1 , 1 , 5 , 5 , 7 , 10 , 12 , 12 , 12 , 12 , 12 , 12 , 15 };
1076- int a1 = 3 ;
1077- int b1 = 10 ;
1078- System . out. println(process(test, a1, b1, 0 , 0 ));
1079- System . out. println(dp(test, a1, b1));
1080-
1081- int len = 5 ;
1082- int max = 9 ;
1083- int testTime = 50000 ;
1084- for (int i = 0 ; i < testTime; i++ ) {
1085- int [] arr = randomArray(len, max);
1086- int n = (int ) (Math . random() * 5 ) + 1 ;
1087- int a = (int ) (Math . random() * 5 ) + 1 ;
1088- int b = (int ) (Math . random() * 10 ) + 1 ;
1089- int ans1 = minTime1(arr, n, a, b);
1090- int ans2 = minTime2(arr, n, a, b);
1091- int ans3 = minTime3(arr, n, a, b);
1092- if (ans1 != ans2 || ans2 != ans3) {
1093- printArray(arr);
1094- System . out. println(" n : " + n);
1095- System . out. println(" a : " + a);
1096- System . out. println(" b : " + b);
1097- System . out. println(ans1 + " , " + ans2 + " , " + ans3);
1098- System . out. println(" ===============" );
1099- break ;
1100- }
1010+ for row := n - 2 ; row >= 0 ; row-- { // row 咖啡杯的编号
1011+ washLine := drinks[row] + (row + 1 ) * a
1012+ for col := 0 ; col < washLine; col++ {
1013+ wash := int (math.Max (float64 (col), float64 (drinks[row]))) + a
1014+ dp[row][col] = int (math.Min (math.Max (float64 (wash), float64 (dp[row + 1 ][wash])),
1015+ math.Max (float64 (drinks[row] + b), float64 (dp[row + 1 ][row]))))
11011016 }
1102-
11031017 }
1104-
1018+
1019+ return dp[0 ][0 ]
11051020}
11061021```
11071022
0 commit comments