publicclassMain{ publicstaticvoidmain(String[] args){ // 处理输入 Scanner scanner = new Scanner(System.in); int m = scanner.nextInt(); long[] v = newlong[m]; for (int i = 0; i < v.length; i++) { v[i] = scanner.nextLong(); } scanner.close(); // 使用java内置小根堆 PriorityQueue PriorityQueue<Long> heap = new PriorityQueue<>(); // 数组中的值都放入小根堆 for (int i = 0; i < v.length; i++) { heap.add(v[i]); } // 初始化代价 long cost = 0; while (heap.size() != 1) { long temp = heap.poll()+heap.poll(); cost += temp; heap.add(temp); } System.out.println(cost); } }
4. 做项目的最大收益问题
【题目】输入: 参数1,正数数组costs;参数2,正数数组profits;参数3,正数k;参数4,正数 m costs[i] 表示 i 号项目的花费 profits[i] 表示 i 号项目在扣除花费之后还能挣到的钱(利润);k表示你不能并行、只能串行的最多做 k 个项目 m 表示你初始的资金 说明:你每做完一个项目,马上获得的收益,可以支持你去做下一个 项目。 输出: 你最后获得的最大钱数。
publicclassMain{ // 建立大根堆存放前 2/n 个数,小根堆存放后 2/n 个数 static PriorityQueue<Integer> maxH = new PriorityQueue<>(new Comparator<Integer>() { publicintcompare(Integer o1, Integer o2){return o2 - o1;} }); static PriorityQueue<Integer> minH = new PriorityQueue<>(); // 处理输入 publicstaticvoidmain(String[]args)throws IOException{ BufferedReader b = new BufferedReader(new InputStreamReader(System.in)); int q = Integer.parseInt(b.readLine()); for (int i = 0; i < q; i++){ String[] strs = b.readLine().trim().split(" "); if (Integer.parseInt(strs[0]) == 1) { addToMedianHolder(Integer.parseInt(strs[1])); } elseif (Integer.parseInt(strs[0]) == 2) { System.out.println(peekMedianHolder()); } } } publicstaticvoidaddToMedianHolder(Integer n){ if (!maxH.isEmpty()) { if (n >= maxH.peek()) { minH.offer(n); while (Math.abs(maxH.size() - minH.size()) > 1) { maxH.offer(minH.poll()); } } else { maxH.offer(n); while (Math.abs(maxH.size() - minH.size()) > 1) { minH.offer(maxH.poll()); } } } else { maxH.offer(n); } } publicstatic String peekMedianHolder(){ if (minH.isEmpty() && maxH.isEmpty()) { return"-1"; } if (Math.abs(maxH.size() - minH.size()) == 1) { return maxH.size() > minH.size() ? String.format("%.1f", (double)maxH.peek()) : String.format("%.1f", (double)minH.peek()) ; } double mid =(double)(minH.peek()+maxH.peek())/2; return String.format("%.1f", mid); } }
6. 递归和动态规划
暴力递归
把问题转化为规模缩小了的同类问题的子问题
有明确的不需要继续进行递归的条件(base case)
有当得到了子问题的结果之后的决策过程,不记录每一个子问题的解
动态规划
从暴力递归中来
将每一个子问题的解记录下来,避免重复计算
把暴力递归的过程,抽象成了状态表达
并且存在化简状态表达,使其更加简洁的可能
N!问题
普通版本直接相乘
递归版本划分子问题,要想解决 N!就要先解决(N-1)!,baseCase 为 N=1 时
7. 如何去尝试
汉诺塔问题(递归)
先将 1 - (n-1) 移到中间
再将 n 移到右边
最后将 1 - (n-1) 移到右边
1 2 3 4 5 6 7 8 9
publicstaticvoidprocess(int N, String from, String to, String help){ if (N == 1) { System.out.println("Move 1 from" + from + "to" + to); } else { process(N-1, from, help, to); System.out.println("Move" + N +"from" + from + "to" + to); process(N-1, help, to, from); } }
打印字符串所有子序列
针对字符串的每个位置上都有两个决策,要或者不要
1 2 3 4 5 6 7 8
publicstaticvoidprintAllSub(char[] str, int i, String res){ if (i == str.length) { System.out.println(res); return; } printAllSub(str, i+1, res); printAllSub(str, i+1, res + String.valueOf(str[i])); }
开始有一只母牛,母牛每年下一只奶牛,奶牛三年后成熟为母牛,也开始每年产一只奶牛,假设牛不会死,问第 N 年共有几只奶牛?
// 暴力递归 publicstaticintprocess(int[][] matrix, int i, int j){ if (i == matrix.length - 1 && j == matrix[0].length - 1 ) { return martix[i][j]; } if (i == matrix.length - 1) { return matrix[i][j] + process(matrix, i, j+1); } if (i == matrix[0].length - 1) { return matrix[i][j] + process(matrix, i+1, j); } int right = process(matrix, i, j + 1); int down = process(matrix, i + 1, j); return Math.min(right, down); }
近期评论