LeetCode:描述輪廓線和最長子數組長度
目錄:
- 輸出整體輪廓線
- 返回最長子數組長度
- 求數組中奇數和偶數個數相同的最長子數組
1. 輸出整體輪廓線
給定一個N行3列二維數組, 每一行表示有一座大樓, 一共有N座大樓。 所有大樓的底部都坐落在X軸上, 每一行的三個值(a,b,c)代表每座大樓的從(a,0)點開始, 到 (b,0)點結束, 高度爲c。 輸入的數據可以保證a<b,且a, b, c均爲正數。 大樓之間可以有重合。 請輸出整體的輪廓線。
例子: 給定一個二維數組 [ [1, 3, 3], [2, 4, 4], [5, 6,1] ]
輸出爲輪廓線 [ [1, 2, 3], [2, 4, 4], [5, 6, 1] ]
public static class Node {
public boolean isUp;
public int posi;
public int h;
public Node(boolean bORe, int position, int height) {
isUp = bORe;
posi = position;
h = height;
}
}
public static class NodeComparator implements Comparator<Node> {
@Override
public int compare(Node o1, Node o2) {
if (o1.posi != o2.posi) {
return o1.posi - o2.posi;
}
if (o1.isUp != o2.isUp) {
return o1.isUp ? -1 : 1;
}
return 0;
}
}
public static List<List<Integer>> buildingOutline(int[][] buildings) {
Node[] nodes = new Node[buildings.length * 2];
for (int i = 0; i < buildings.length; i++) {
nodes[i * 2] = new Node(true, buildings[i][0], buildings[i][2]);
nodes[i * 2 + 1] = new Node(false, buildings[i][1], buildings[i][2]);
}
Arrays.sort(nodes, new NodeComparator());
TreeMap<Integer, Integer> htMap = new TreeMap<>();
TreeMap<Integer, Integer> pmMap = new TreeMap<>();
for (int i = 0; i < nodes.length; i++) {
if (nodes[i].isUp) {
if (!htMap.containsKey(nodes[i].h)) {
htMap.put(nodes[i].h, 1);
} else {
htMap.put(nodes[i].h, htMap.get(nodes[i].h) + 1);
}
} else {
if (htMap.containsKey(nodes[i].h)) {
if (htMap.get(nodes[i].h) == 1) {
htMap.remove(nodes[i].h);
} else {
htMap.put(nodes[i].h, htMap.get(nodes[i].h) - 1);
}
}
}
if (htMap.isEmpty()) {
pmMap.put(nodes[i].posi, 0);
} else {
pmMap.put(nodes[i].posi, htMap.lastKey());
}
}
List<List<Integer>> res = new ArrayList<>();
int start = 0;
int height = 0;
for (Entry<Integer, Integer> entry : pmMap.entrySet()) {
int curPosition = entry.getKey();
int curMaxHeight = entry.getValue();
if (height != curMaxHeight) {
if (height != 0) {
List<Integer> newRecord = new ArrayList<Integer>();
newRecord.add(start);
newRecord.add(curPosition);
newRecord.add(height);
res.add(newRecord);
}
start = curPosition;
height = curMaxHeight;
}
}
return res;
}
2. 返回最長子數組長度
題目描述:給定一個數組arr, 和一個整數num, 求在arr中, 累加和等於num的最長子數組的長度
例子:
arr = {7,3,2,1,1,7,7,7} num = 7
其中有很多的子數組累加和等於7, 但是最長的子數組是{3,2,1,1}, 所以返回其長度4
題解:創建一個HashMap,key保存從0位置開始到每個位置的長度,value 保存出現長度的位置。如果sum-aim的結果出現在map中,則說明有這個長度,獲取長度即可。如果沒有出現過,保存在 map 中即可。
public static int maxLength(int[] arr, int aim) {
if (arr == null || arr.length == 0) {
return 0;
}
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, -1); // important
int len = 0;
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
if (map.containsKey(sum - aim)) {
len = Math.max(i - map.get(sum - aim), len);
}
if (!map.containsKey(sum)) {
map.put(sum, i);
}
}
return len;
}
3. 求數組中奇數和偶數個數相同的最長子數組
用動態劃分思想,最後一個位置的數肯定會被劃分,那麼就有兩種可能
- 最後一個數所在部分不是異或和爲 0 的子數組,那麼 dp[i] = dp[i-1]
- 最後一個數所在部分是異或和爲 0 的子數組,那麼 dp[i] = dp[k-1] +1
public static int mostEOR(int[] arr) {
int ans = 0;
int xor = 0;
int[] dp = new int[arr.length];
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, -1);
for (int i = 0; i < arr.length; i++) {
xor ^= arr[i];
if (map.containsKey(xor)) {
int pre = map.get(xor);
dp[i] = pre == -1 ? 1 : (dp[pre] + 1);
}
if (i > 0) {
dp[i] = Math.max(dp[i - 1], dp[i]);
}
map.put(xor, i);
ans = Math.max(ans, dp[i]);
}
return ans;
}