Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d326d43

Browse files
committed
clean code & 850 (1)
1 parent 11e11f8 commit d326d43

File tree

10 files changed

+443
-35
lines changed

10 files changed

+443
-35
lines changed

‎leetcode/leetcode-04/src/main/java/Solution386.java

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,48 @@
22
import java.util.List;
33

44
public class Solution386 {
5-
public List<Integer> lexicalOrder(int n) {
6-
List<Integer> resList = new ArrayList<>();
7-
int num = 1;
8-
// 保证最多不超过 n 个数
9-
for (int i = 0; i < n; i++) {
10-
resList.add(num);
11-
if (num * 10 <= n) {
12-
num *= 10;
13-
} else {
14-
while (num % 10 == 9 || num + 1 > n) {
15-
num /= 10;
5+
// 迭代
6+
static class V1 {
7+
public List<Integer> lexicalOrder(int n) {
8+
List<Integer> ans = new ArrayList<>();
9+
int num = 1;
10+
// 保证最多不超过 n 个数
11+
for (int i = 0; i < n; i++) {
12+
ans.add(num);
13+
if (num * 10 <= n) {
14+
num *= 10;
15+
} else {
16+
while (num % 10 == 9 || num + 1 > n) {
17+
num /= 10;
18+
}
19+
num++;
1620
}
17-
num++;
21+
}
22+
return ans;
23+
}
24+
}
25+
26+
// 递归
27+
static class V2 {
28+
int n;
29+
List<Integer> ans;
30+
31+
public List<Integer> lexicalOrder(int n) {
32+
this.n = n;
33+
ans = new ArrayList<>();
34+
for (int i = 1; i <= 9; i++) {
35+
dfs(i);
36+
}
37+
return ans;
38+
}
39+
40+
private void dfs(int cur) {
41+
if (cur > n) return;
42+
ans.add(cur);
43+
for (int i = 0; i <= 9; i++) {
44+
dfs(cur * 10 + i);
1845
}
1946
}
20-
return resList;
2147
}
2248
}
2349
/*
@@ -29,5 +55,6 @@ public List<Integer> lexicalOrder(int n) {
2955
提示:
3056
1 <= n <= 5 * 10^4
3157
32-
迭代。
58+
迭代 / 递归。
59+
时间复杂度 O(n)。
3360
*/

‎leetcode/leetcode-04/src/test/java/Solution386Tests.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,22 @@
44
import java.util.List;
55

66
public class Solution386Tests {
7-
private final Solution386 solution386 = new Solution386();
7+
private final Solution386.V1 solution386_v1 = new Solution386.V1();
8+
private final Solution386.V2 solution386_v2 = new Solution386.V2();
89

910
@Test
1011
public void example1() {
1112
int n = 13;
1213
List<Integer> expected = List.of(1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9);
13-
Assertions.assertEquals(expected, solution386.lexicalOrder(n));
14+
Assertions.assertEquals(expected, solution386_v1.lexicalOrder(n));
15+
Assertions.assertEquals(expected, solution386_v2.lexicalOrder(n));
1416
}
1517

1618
@Test
1719
public void example2() {
1820
int n = 2;
1921
List<Integer> expected = List.of(1, 2);
20-
Assertions.assertEquals(expected, solution386.lexicalOrder(n));
22+
Assertions.assertEquals(expected, solution386_v1.lexicalOrder(n));
23+
Assertions.assertEquals(expected, solution386_v2.lexicalOrder(n));
2124
}
2225
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
4+
import java.util.Map;
5+
import java.util.TreeMap;
6+
7+
public class Solution850 {
8+
private static final int MOD = (int) (1e9 + 7);
9+
10+
public int rectangleArea(int[][] rectangles) {
11+
int m = 0;
12+
TreeMap<Integer, Integer> mp = new TreeMap<>();
13+
// for (int[] sq : squares) {
14+
// mp.put(sq[0], 1);
15+
// mp.put(sq[0] + sq[2], 1);
16+
// }
17+
for (int[] re : rectangles) {
18+
mp.put(re[0], 1);
19+
mp.put(re[2], 1);
20+
}
21+
for (Map.Entry<Integer, Integer> p : mp.entrySet()) p.setValue(m++);
22+
int[] A = new int[m];
23+
for (Map.Entry<Integer, Integer> p : mp.entrySet()) A[p.getValue()] = p.getKey();
24+
// 离散化结束
25+
26+
// 把正方形的上下边界取出来
27+
List<int[]> vec = new ArrayList<>();
28+
// for (int[] sq : squares) {
29+
// vec.add(new int[]{sq[1], mp.get(sq[0]) + 1, mp.get(sq[0] + sq[2]), 1});
30+
// vec.add(new int[]{sq[1] + sq[2], mp.get(sq[0]) + 1, mp.get(sq[0] + sq[2]), -1});
31+
// }
32+
for (int[] re : rectangles) {
33+
vec.add(new int[]{re[1], mp.get(re[0]) + 1, mp.get(re[2]), 1});
34+
vec.add(new int[]{re[3], mp.get(re[0]) + 1, mp.get(re[2]), -1});
35+
}
36+
vec.sort(Arrays::compare);
37+
38+
// 求总的面积并
39+
long tot = 0;
40+
LazySegmentTree seg = new LazySegmentTree(m);
41+
seg.build(A, 1, 1, m - 1);
42+
for (int i = 0; i + 1 < vec.size(); i++) {
43+
// 考虑水平线 y = vec[i][0] 和 y = vec[i + 1][0] 之间的情况
44+
seg.modify(1, 1, m - 1, vec.get(i)[1], vec.get(i)[2], vec.get(i)[3]);
45+
// 求横截长度
46+
int len = A[m - 1] - A[0];
47+
// 如果最小覆盖数是 0,那么扣掉相应的长度
48+
if (seg.info[1].mn == 0) len -= seg.info[1].len;
49+
// 面积 = 横截长度 * 高度差
50+
tot += (long) len * (vec.get(i + 1)[0] - vec.get(i)[0]);
51+
}
52+
return (int) (tot % MOD);
53+
}
54+
55+
// 线段树模板,只需要实现 mergeInfo 和 _do,其余都是固定的
56+
static class LazySegmentTree {
57+
static class Info {
58+
// mn:当前节点的最小覆盖数
59+
// len:满足覆盖数 = 最小覆盖数的 A[i] 之和
60+
// lazy:加法的懒标记
61+
int mn, len, lazy;
62+
63+
public Info(int mn, int len, int lazy) {
64+
this.mn = mn;
65+
this.len = len;
66+
this.lazy = lazy;
67+
}
68+
}
69+
70+
Info mergeInfo(Info a, Info b) {
71+
int mn = Math.min(a.mn, b.mn);
72+
return new Info(mn, (a.mn == mn ? a.len : 0) + (b.mn == mn ? b.len : 0), 0);
73+
}
74+
75+
// 对节点的覆盖数整个增加 qv,只影响 mn,不影响 len
76+
void _do(int p, int qv) {
77+
info[p].mn += qv;
78+
info[p].lazy += qv;
79+
}
80+
81+
int n;
82+
Info[] info;
83+
84+
public LazySegmentTree(int n) {
85+
this.n = n;
86+
info = new Info[4 * n];
87+
Arrays.fill(info, new Info(0, 0, 0));
88+
}
89+
90+
void build(int[] A, int p, int l, int r) {
91+
if (l == r) {
92+
info[p] = new Info(0, A[r] - A[r - 1], 0);
93+
return;
94+
}
95+
int m = (l + r) >> 1;
96+
build(A, p << 1, l, m);
97+
build(A, p << 1 | 1, m + 1, r);
98+
maintain(p);
99+
}
100+
101+
void maintain(int p) {
102+
info[p] = mergeInfo(info[p << 1], info[p << 1 | 1]);
103+
}
104+
105+
void spread(int p) {
106+
if (info[p].lazy == 0) return;
107+
_do(p << 1, info[p].lazy);
108+
_do(p << 1 | 1, info[p].lazy);
109+
info[p].lazy = 0;
110+
}
111+
112+
void modify(int p, int l, int r, int ql, int qr, int qv) {
113+
if (ql <= l && r <= qr) {
114+
_do(p, qv);
115+
return;
116+
}
117+
spread(p);
118+
int m = (l + r) >> 1;
119+
if (ql <= m) modify(p << 1, l, m, ql, qr, qv);
120+
if (qr > m) modify(p << 1 | 1, m + 1, r, ql, qr, qv);
121+
maintain(p);
122+
}
123+
}
124+
}
125+
/*
126+
850. 矩形面积 II
127+
https://leetcode.cn/problems/rectangle-area-ii/description/
128+
129+
给你一个轴对齐的二维数组 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中 (xi1, yi1) 是该矩形 左下角 的坐标, (xi2, yi2) 是该矩形 右上角 的坐标。
130+
计算平面中所有 rectangles 所覆盖的 总面积 。任何被两个或多个矩形覆盖的区域应只计算 一次 。
131+
返回 总面积 。因为答案可能太大,返回 10^9 + 7 的 模 。
132+
提示:
133+
1 <= rectangles.length <= 200
134+
rectanges[i].length = 4
135+
0 <= xi1, yi1, xi2, yi2 <= 10^9
136+
xi1 <= xi2
137+
yi1 <= yi2
138+
所有矩阵面积不为 0。
139+
140+
矩形面积并。
141+
Lazy 线段树 + 扫描线。
142+
相似题目: 3454. 分割正方形 II
143+
https://leetcode.cn/problems/separate-squares-ii/description/
144+
*/
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution850Tests {
5+
private final Solution850 solution850 = new Solution850();
6+
7+
@Test
8+
public void example1() {
9+
int[][] rectangles = UtUtils.stringToInts2("[[0,0,2,2],[1,0,2,3],[1,0,3,1]]");
10+
int expected = 6;
11+
Assertions.assertEquals(expected, solution850.rectangleArea(rectangles));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int[][] rectangles = UtUtils.stringToInts2("[[0,0,1000000000,1000000000]]");
17+
int expected = 49;
18+
Assertions.assertEquals(expected, solution850.rectangleArea(rectangles));
19+
}
20+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /