Skip to content

Commit 77f926c

Browse files
committed
588-711-781-1121-1933 (5)
1 parent 6ddbdcc commit 77f926c

File tree

10 files changed

+429
-0
lines changed

10 files changed

+429
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import java.util.ArrayList;
2+
import java.util.Collections;
3+
import java.util.HashMap;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
public class Solution588 {
8+
static class FileSystem {
9+
private final File root;
10+
11+
public FileSystem() {
12+
root = new File();
13+
}
14+
15+
public List<String> ls(String path) {
16+
File f = root;
17+
List<String> files = new ArrayList<>();
18+
if (!path.equals("/")) {
19+
String[] dirs = path.split("/");
20+
for (int i = 1; i < dirs.length; i++) {
21+
f = f.files.get(dirs[i]);
22+
}
23+
if (f.isFile) {
24+
files.add(dirs[dirs.length - 1]);
25+
return files;
26+
}
27+
}
28+
files = new ArrayList<>(f.files.keySet());
29+
Collections.sort(files);
30+
return files;
31+
}
32+
33+
public void mkdir(String path) {
34+
File f = root;
35+
String[] dirs = path.split("/");
36+
for (int i = 1; i < dirs.length; i++) {
37+
if (!f.files.containsKey(dirs[i])) {
38+
f.files.put(dirs[i], new File());
39+
}
40+
f = f.files.get(dirs[i]);
41+
}
42+
}
43+
44+
public void addContentToFile(String filePath, String content) {
45+
File f = root;
46+
String[] dirs = filePath.split("/");
47+
for (int i = 1; i < dirs.length - 1; i++) {
48+
f = f.files.get(dirs[i]);
49+
}
50+
if (!f.files.containsKey(dirs[dirs.length - 1])) {
51+
f.files.put(dirs[dirs.length - 1], new File());
52+
}
53+
f = f.files.get(dirs[dirs.length - 1]);
54+
f.isFile = true;
55+
f.content = f.content + content;
56+
}
57+
58+
public String readContentFromFile(String filePath) {
59+
File f = root;
60+
String[] dirs = filePath.split("/");
61+
for (int i = 1; i < dirs.length - 1; i++) {
62+
f = f.files.get(dirs[i]);
63+
}
64+
return f.files.get(dirs[dirs.length - 1]).content;
65+
}
66+
67+
// 字典树 使用统一的文件夹文件列表
68+
private static class File {
69+
boolean isFile = false;
70+
Map<String, File> files = new HashMap<>();
71+
String content = "";
72+
}
73+
}
74+
}
75+
/*
76+
$588. 设计内存文件系统
77+
https://leetcode.cn/problems/design-in-memory-file-system/
78+
79+
设计一个内存文件系统,模拟以下功能:
80+
实现文件系统类:
81+
- FileSystem() 初始化系统对象
82+
- List<String> ls(String path)
83+
- 如果 path 是一个文件路径,则返回一个仅包含该文件名称的列表。
84+
- 如果 path 是一个目录路径,则返回该目录中文件和 目录名 的列表。
85+
答案应该 按字典顺序 排列。
86+
- void mkdir(String path) 根据给定的路径创建一个新目录。给定的目录路径不存在。如果路径中的中间目录不存在,您也应该创建它们。
87+
- void addContentToFile(String filePath, String content)
88+
- 如果 filePath 不存在,则创建包含给定内容 content的文件。
89+
- 如果 filePath 已经存在,将给定的内容 content附加到原始内容。
90+
- String readContentFromFile(String filePath) 返回 filePath下的文件内容。
91+
注意:
92+
1 <= path.length, filePath.length <= 100
93+
path 和 filePath 都是绝对路径,除非是根目录 ‘/’ 自身,其他路径都是以 ‘/’ 开头且 不 以 ‘/’ 结束。
94+
你可以假定所有操作的参数都是有效的,即用户不会获取不存在文件的内容,或者获取不存在文件夹和文件的列表。
95+
你可以假定所有文件夹名字和文件名字都只包含小写字母,且同一文件夹下不会有相同名字的文件夹或文件。
96+
1 <= content.length <= 50
97+
ls, mkdir, addContentToFile, and readContentFromFile 最多被调用 300 次
98+
99+
字典树 使用统一的文件夹文件列表
100+
*/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
import java.util.List;
5+
6+
public class Solution588Tests {
7+
@Test
8+
public void example1() {
9+
Solution588.FileSystem fileSystem = new Solution588.FileSystem();
10+
11+
// 返回 []
12+
Assertions.assertEquals(List.of(), fileSystem.ls("/"));
13+
14+
fileSystem.mkdir("/a/b/c");
15+
16+
fileSystem.addContentToFile("/a/b/c/d", "hello");
17+
18+
// 返回 ["a"]
19+
Assertions.assertEquals(List.of("a"), fileSystem.ls("/"));
20+
21+
// 返回 "hello"
22+
Assertions.assertEquals("hello", fileSystem.readContentFromFile("/a/b/c/d"));
23+
}
24+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.HashSet;
4+
import java.util.List;
5+
import java.util.Set;
6+
7+
public class Solution711 {
8+
private int[][] grid;
9+
private int M;
10+
private int N;
11+
private boolean[][] visited;
12+
private List<Integer> shape;
13+
14+
public int numDistinctIslands2(int[][] grid) {
15+
this.grid = grid;
16+
M = grid.length;
17+
N = grid[0].length;
18+
visited = new boolean[M][N];
19+
Set<String> shapes = new HashSet<>();
20+
21+
for (int i = 0; i < M; i++) {
22+
for (int j = 0; j < N; j++) {
23+
shape = new ArrayList<>();
24+
explore(i, j);
25+
if (!shape.isEmpty()) {
26+
shapes.add(canonical(shape));
27+
}
28+
}
29+
}
30+
return shapes.size();
31+
}
32+
33+
private void explore(int i, int j) {
34+
if (i >= 0 && i < M && j >= 0 && j < N && grid[i][j] == 1 && !visited[i][j]) {
35+
visited[i][j] = true;
36+
shape.add(i * N + j);
37+
explore(i + 1, j);
38+
explore(i - 1, j);
39+
explore(i, j + 1);
40+
explore(i, j - 1);
41+
}
42+
}
43+
44+
// 规范化哈希
45+
private String canonical(List<Integer> shape) {
46+
int sz = shape.size();
47+
String ans = "";
48+
int lift = M + N;
49+
int[] out = new int[sz];
50+
int[] xs = new int[sz];
51+
int[] ys = new int[sz];
52+
53+
for (int c = 0; c < 8; c++) {
54+
int t = 0;
55+
for (int s : shape) {
56+
int x = s / N;
57+
int y = s % N;
58+
// [x,y] [x,-y] [-x,y] [-x,-y]
59+
// [y,x] [y,-x] [-y,x] [-y,-x]
60+
xs[t] = c <= 1 ? x : (c <= 3 ? -x : (c <= 5 ? y : -y));
61+
ys[t] = c <= 3 ? (c % 2 == 0 ? y : -y) : (c % 2 == 0 ? x : -x);
62+
t++;
63+
}
64+
65+
int mx = Arrays.stream(xs).min().orElseThrow();
66+
int my = Arrays.stream(ys).min().orElseThrow();
67+
68+
for (int j = 0; j < sz; j++) {
69+
out[j] = (xs[j] - mx) * lift + (ys[j] - my);
70+
}
71+
Arrays.sort(out);
72+
String candidate = Arrays.toString(out);
73+
if (ans.compareTo(candidate) < 0) {
74+
ans = candidate;
75+
}
76+
}
77+
return ans;
78+
}
79+
}
80+
/*
81+
$711. 不同岛屿的数量 II
82+
https://leetcode.cn/problems/number-of-distinct-islands-ii/
83+
84+
给定一个 m x n 二进制数组表示的网格 grid ,一个岛屿由 四连通 (上、下、左、右四个方向)的 1 组成(代表陆地)。你可以认为网格的四周被海水包围。
85+
如果两个岛屿的形状相同,或者通过旋转(顺时针旋转 90°,180°,270°)、翻转(左右翻转、上下翻转)后形状相同,那么就认为这两个岛屿是相同的。
86+
返回 这个网格中形状 不同 的岛屿的数量 。
87+
提示:
88+
m == grid.length
89+
n == grid[i].length
90+
1 <= m, n <= 50
91+
grid[i][j] 不是 0 就是 1.
92+
93+
难度升级,可以旋转,翻转。
94+
规范性哈希。枚举 旋转+翻转 8 种情况的可能,用一个最小的矩形框住岛屿。
95+
相似题目: $694. 不同岛屿的数量
96+
https://leetcode.cn/problems/number-of-distinct-islands/
97+
*/
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
4+
public class Solution781 {
5+
public int numRabbits(int[] answers) {
6+
Map<Integer, Integer> cntMap = new HashMap<>();
7+
for (int x : answers) {
8+
cntMap.put(x, cntMap.getOrDefault(x, 0) + 1);
9+
}
10+
11+
int res = 0;
12+
for (Map.Entry<Integer, Integer> entry : cntMap.entrySet()) {
13+
int x = entry.getKey();
14+
int y = entry.getValue();
15+
// ceil(y/(x+1)) * (x+1)
16+
res += (y + x) / (x + 1) * (x + 1);
17+
}
18+
return res;
19+
}
20+
}
21+
/*
22+
781. 森林中的兔子
23+
https://leetcode.cn/problems/rabbits-in-forest/
24+
25+
森林中有未知数量的兔子。提问其中若干只兔子 "还有多少只兔子与你(指被提问的兔子)颜色相同?" ,将答案收集到一个整数数组 answers 中,其中 answers[i] 是第 i 只兔子的回答。
26+
给你数组 answers ,返回森林中兔子的最少数量。
27+
提示:
28+
1 <= answers.length <= 1000
29+
0 <= answers[i] < 1000
30+
31+
HashMap 统计后分组,由于可能存在没有回答的兔子,需要向上取值。
32+
*/
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 Solution711Tests {
5+
private final Solution711 solution711 = new Solution711();
6+
7+
@Test
8+
public void example1() {
9+
int[][] grid = UtUtils.stringToInts2("[[1,1,0,0,0],[1,0,0,0,0],[0,0,0,0,1],[0,0,0,1,1]]");
10+
int expected = 1;
11+
Assertions.assertEquals(expected, solution711.numDistinctIslands2(grid));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int[][] grid = UtUtils.stringToInts2("[[1,1,0,0,0],[1,1,0,0,0],[0,0,0,1,1],[0,0,0,1,1]]");
17+
int expected = 1;
18+
Assertions.assertEquals(expected, solution711.numDistinctIslands2(grid));
19+
}
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution781Tests {
5+
private final Solution781 solution781 = new Solution781();
6+
7+
@Test
8+
public void example1() {
9+
int[] answers = {1, 1, 2};
10+
int expected = 5;
11+
Assertions.assertEquals(expected, solution781.numRabbits(answers));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int[] answers = {10, 10, 10};
17+
int expected = 11;
18+
Assertions.assertEquals(expected, solution781.numRabbits(answers));
19+
}
20+
21+
// 补充用例
22+
@Test
23+
public void example3() {
24+
// https://leetcode.cn/submissions/detail/396407981/
25+
int[] answers = {0, 0, 1, 1, 1};
26+
int expected = 6;
27+
Assertions.assertEquals(expected, solution781.numRabbits(answers));
28+
}
29+
30+
@Test
31+
public void example4() {
32+
// https://leetcode.cn/submissions/detail/396407870/
33+
int[] answers = {1, 0, 1, 0, 0};
34+
int expected = 5;
35+
Assertions.assertEquals(expected, solution781.numRabbits(answers));
36+
}
37+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
public class Solution1121 {
2+
public boolean canDivideIntoSubsequences(int[] nums, int k) {
3+
if (k == 1) {
4+
return true;
5+
}
6+
int max = 0;
7+
int cnt = 0;
8+
int pre = -1;
9+
for (int num : nums) {
10+
if (num != pre) {
11+
cnt = 1;
12+
} else {
13+
cnt++;
14+
}
15+
max = Math.max(max, cnt);
16+
pre = num;
17+
}
18+
return max * k <= nums.length;
19+
}
20+
}
21+
/*
22+
$1121. 将数组分成几个递增序列
23+
https://leetcode.cn/problems/divide-array-into-increasing-sequences/
24+
25+
给你一个 非递减 的正整数数组 nums 和整数 K,判断该数组是否可以被分成一个或几个 长度至少 为 K 的 不相交的递增子序列。
26+
提示:
27+
1 <= nums.length <= 10^5
28+
1 <= K <= nums.length
29+
1 <= nums[i] <= 10^5
30+
31+
贪心,设最大频次为 c,c * k 需小于等于 n
32+
*/
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 Solution1121Tests {
5+
private final Solution1121 solution1121 = new Solution1121();
6+
7+
@Test
8+
public void example1() {
9+
int[] nums = {1, 2, 2, 3, 3, 4, 4};
10+
int k = 3;
11+
Assertions.assertTrue(solution1121.canDivideIntoSubsequences(nums, k));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int[] nums = {5, 6, 6, 7, 8};
17+
int k = 3;
18+
Assertions.assertFalse(solution1121.canDivideIntoSubsequences(nums, k));
19+
}
20+
}

0 commit comments

Comments
 (0)