1 dp
2 二分
3 index tree
题目描述
给出一个列表如[[6,7,],[5,4],[3,2]],表示木块的长和宽,当木块的长和宽不大于另个木块的长和宽时,就可以放在上面,此外数组还可以左右翻转。求最多能搭多少层。
输入描述
一个二维数组,里面是每个积木的长和宽,可以左右翻转。
输出描述
最多能搭多少层。
样例
输入
[[5,4],[6,3],[6,7],[6,6],[4,6]]
1
输出
4
————————————————
package com.company; import java.io.FileInputStream; import java.util.*; // 叠积木 public class Solution32 { static int[] lisTree; public static void main(String[] args) throws Exception { System.setIn(new FileInputStream("D:/data.txt")); Scanner sc = new Scanner(System.in); String[] split = sc.nextLine().split("],"); ArrayList<int[]> arr = new ArrayList<>(); for (int i = 0; i < split.length; i++) { String s = split[i].replaceAll("\\[", "").replaceAll("]", ""); String[] strings = s.split(","); int a = Integer.valueOf(strings[0]); int b = Integer.valueOf(strings[1]); arr.add(new int[]{a>b ? a : b, a <= b ? a : b}); // 长的按照长进行组合 } Collections.sort(arr, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { if(o1[0] == o2[0]) return o1[1] - o2[1]; return o1[0] - o2[0]; } }); int len = arr.size(); // method1 dp int ans = 0; int[] dp = new int[len]; Arrays.fill(dp, 1); for (int i = 0; i < len; i++) { int[] cur = arr.get(i); for (int j = 0; j < i; j++) { int[] pre = arr.get(j); if(cur[1] >= pre[1]) { dp[i] = dp[j] + 1; } } if(dp[i] > ans) ans = dp[i]; } System.out.println(ans); ans = 0; // method2 二分法 dp[ans++] = arr.get(0)[1]; for (int i = 1; i < len; i++) { int[] cur = arr.get(i); if(cur[1] >= dp[ans - 1]) { dp[ans++] = cur[1]; } else { int left = 0, right = ans; while(left < right) { int mid = left + (right - left) / 2; int[] c = arr.get(mid); if(cur[i] > c[1]) { left = mid + 1; } if(cur[1] <= c[1]) { right = mid; } } dp[left] = cur[1]; } } System.out.println(ans); // method3 indexTree // 1. 计算构造树需要的的len int size = 1; while (size < len) { size += size; } lisTree = new int[size * 2]; // 2. 构造进行操作计算的数据 Node[] data = new Node[len]; for (int i = 0; i < len; i++) { int[] ints = arr.get(i); data[i] = new Node(i, ints[1]); } // 3. 对索引树进行排序 Arrays.sort(data, new Comparator<Node>() { @Override public int compare(Node o1, Node o2) { if(o1.val == o2.val) { return o1.idx - o2.idx; // 求不递增 索引小在前 } return o1.val - o2.val; } }); // 4. 定义 query 和 update 方法 // 5. 查询和更新索引树 for (int i = 0; i < len; i++) { int val = query(size, data[i].idx + size); update(data[i].idx + size, val + 1); } System.out.println(query(size, size * 2 - 1)); } private static int query(int s, int e) { int ret = 0; while (s <= e) { if(s % 2 == 1) ret = Math.max(ret, lisTree[s]); if(e % 2 == 0) ret = Math.max(ret, lisTree[e]); s = (s+1) >> 1; e = (e-1) >> 1; } return ret; } private static void update(int idx, int val) { while (idx > 0) { lisTree[idx] = val; idx >>= 1; } } static class Node { int idx; int val; public Node(int idx, int val) { this.idx = idx; this.val = val; } } }
标签:val,idx,求解,int,递增,ans,LIS,o2,dp From: https://www.cnblogs.com/ives-xu/p/16878632.html