Skip to content

Commit 3457031

Browse files
committed
555-681-723-742-751-755-776-1059 (8)
1 parent d8cda5d commit 3457031

File tree

16 files changed

+660
-0
lines changed

16 files changed

+660
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
public class Solution555 {
2+
// https://leetcode.cn/problems/split-concatenated-strings/solution/fen-ge-lian-jie-zi-fu-chuan-by-leetcode-solution/
3+
// O(n^2)
4+
public String splitLoopedString(String[] strs) {
5+
int len = strs.length;
6+
// 如果翻转后比原来 字典序更大,先翻转
7+
for (int i = 0; i < len; i++) {
8+
String rev = new StringBuilder(strs[i]).reverse().toString();
9+
if (strs[i].compareTo(rev) < 0) {
10+
strs[i] = rev;
11+
}
12+
}
13+
14+
// 再枚举所有可能的循环起点
15+
String res = "";
16+
for (int i = 0; i < len; i++) {
17+
String rev = new StringBuilder(strs[i]).reverse().toString();
18+
StringBuilder other = new StringBuilder();
19+
for (int j = i + 1; j < len; j++) {
20+
other.append(strs[j]);
21+
}
22+
for (int j = 0; j < i; j++) {
23+
other.append(strs[j]);
24+
}
25+
26+
for (int j = 0; j < strs[i].length(); j++) {
27+
String cur = strs[i].substring(j) + other + strs[i].substring(0, j);
28+
if (res.compareTo(cur) < 0) {
29+
res = cur;
30+
}
31+
}
32+
for (int j = 0; j < strs[i].length(); j++) {
33+
String cur = rev.substring(j) + other + rev.substring(0, j);
34+
if (res.compareTo(cur) < 0) {
35+
res = cur;
36+
}
37+
}
38+
}
39+
return res;
40+
}
41+
}
42+
/*
43+
$555. 分割连接字符串
44+
https://leetcode.cn/problems/split-concatenated-strings/
45+
46+
给定一个字符串列表 strs,你可以将这些字符串连接成一个循环字符串,对于每个字符串,你可以选择是否翻转它。在所有可能的循环字符串中,你需要分割循环字符串(这将使循环字符串变成一个常规的字符串),然后找到字典序最大的字符串。
47+
具体来说,要找到字典序最大的字符串,你需要经历两个阶段:
48+
1.将所有字符串连接成一个循环字符串,你可以选择是否翻转某些字符串,并按照给定的顺序连接它们。
49+
2.在循环字符串的某个位置分割它,这将使循环字符串从分割点变成一个常规的字符串。
50+
你的工作是在所有可能的常规字符串中找到字典序最大的一个。
51+
提示:
52+
1 <= strs.length <= 1000
53+
1 <= strs[i].length <= 1000
54+
1 <= sum(strs[i].length) <= 1000
55+
strs[i] 只包含小写英文字母
56+
57+
贪心 + 枚举
58+
时间复杂度 O(n^2)
59+
空间复杂度 O(n)
60+
*/
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 Solution555Tests {
5+
private final Solution555 solution555 = new Solution555();
6+
7+
@Test
8+
public void example1() {
9+
String[] strs = {"abc", "xyz"};
10+
String expected = "zyxcba";
11+
Assertions.assertEquals(expected, solution555.splitLoopedString(strs));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
String[] strs = {"abc"};
17+
String expected = "cba";
18+
Assertions.assertEquals(expected, solution555.splitLoopedString(strs));
19+
}
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
public class Solution681 {
2+
public String nextClosestTime(String time) {
3+
int mask = 0;
4+
for (int i = 0; i < 5; i++) {
5+
if (i == 2) continue;
6+
mask |= (1 << (time.charAt(i) - '0'));
7+
}
8+
9+
int cur = Integer.parseInt(time.substring(0, 2)) * 60 + Integer.parseInt(time.substring(3));
10+
// 60*24
11+
for (int i = 1; i <= 1440; i++) {
12+
int t = (cur + i) % 1440;
13+
int hh = t / 60, mm = t % 60;
14+
int c1 = hh / 10, c2 = hh % 10, c3 = mm / 10, c4 = mm % 10;
15+
int tMask = (1 << c1) | (1 << c2) | (1 << c3) | (1 << c4);
16+
if ((mask & tMask) == tMask) {
17+
return "" + c1 + c2 + ':' + c3 + c4;
18+
}
19+
}
20+
return "-1";
21+
}
22+
}
23+
/*
24+
$681. 最近时刻
25+
https://leetcode.cn/problems/next-closest-time/
26+
27+
给定一个形如 "HH:MM" 表示的时刻 time ,利用当前出现过的数字构造下一个距离当前时间最近的时刻。每个出现数字都可以被无限次使用。
28+
你可以认为给定的字符串一定是合法的。例如, "01:34" 和 "12:09" 是合法的,“1:34” 和 “12:9” 是不合法的。
29+
提示:
30+
time.length == 5
31+
time 为有效时间,格式为 "HH:MM".
32+
0 <= HH < 24
33+
0 <= MM < 60
34+
35+
枚举 24 * 60 = 1440 种可能
36+
时间复杂度 O(1)
37+
*/
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution681Tests {
5+
private final Solution681 solution681 = new Solution681();
6+
7+
@Test
8+
public void example1() {
9+
String time = "19:34";
10+
String expected = "19:39";
11+
Assertions.assertEquals(expected, solution681.nextClosestTime(time));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
String time = "23:59";
17+
String expected = "22:22";
18+
Assertions.assertEquals(expected, solution681.nextClosestTime(time));
19+
}
20+
21+
// 补充用例
22+
@Test
23+
public void example3() {
24+
// https://leetcode.cn/submissions/detail/397925872/
25+
String time = "00:00";
26+
String expected = "00:00";
27+
Assertions.assertEquals(expected, solution681.nextClosestTime(time));
28+
}
29+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
public class Solution723 {
2+
public int[][] candyCrush(int[][] board) {
3+
int M = board.length;
4+
int N = board[0].length;
5+
6+
boolean flag = false;
7+
for (int i = 0; i < M; i++) {
8+
for (int j = 0; j + 2 < N; j++) {
9+
int val = Math.abs(board[i][j]);
10+
if (val > 0 && val == Math.abs(board[i][j + 1]) && val == Math.abs(board[i][j + 2])) {
11+
board[i][j] = board[i][j + 1] = board[i][j + 2] = -val;
12+
flag = true;
13+
}
14+
}
15+
}
16+
for (int i = 0; i + 2 < M; i++) {
17+
for (int j = 0; j < N; j++) {
18+
int val = Math.abs(board[i][j]);
19+
if (val > 0 && val == Math.abs(board[i + 1][j]) && val == Math.abs(board[i + 2][j])) {
20+
board[i][j] = board[i + 1][j] = board[i + 2][j] = -val;
21+
flag = true;
22+
}
23+
}
24+
}
25+
26+
for (int j = 0; j < N; j++) {
27+
// write
28+
int wr = M - 1;
29+
for (int i = M - 1; i >= 0; i--) {
30+
if (board[i][j] > 0) {
31+
board[wr][j] = board[i][j];
32+
wr--;
33+
}
34+
}
35+
while (wr >= 0) {
36+
board[wr][j] = 0;
37+
wr--;
38+
}
39+
}
40+
return flag ? candyCrush(board) : board;
41+
}
42+
}
43+
/*
44+
$723. 粉碎糖果
45+
https://leetcode.cn/problems/candy-crush/
46+
47+
这个问题是实现一个简单的消除算法。
48+
给定一个 m x n 的二维整数数组 board 代表糖果所在的方格,不同的正整数 board[i][j] 代表不同种类的糖果,如果 board[i][j] == 0 代表 (i, j) 这个位置是空的。
49+
给定的方格是玩家移动后的游戏状态,现在需要你根据以下规则粉碎糖果,使得整个方格处于稳定状态并最终输出:
50+
- 如果有三个及以上水平或者垂直相连的同种糖果,同一时间将它们粉碎,即将这些位置变成空的。
51+
- 在同时粉碎掉这些糖果之后,如果有一个空的位置上方还有糖果,那么上方的糖果就会下落直到碰到下方的糖果或者底部,这些糖果都是同时下落,也不会有新的糖果从顶部出现并落下来。
52+
- 通过前两步的操作,可能又会出现可以粉碎的糖果,请继续重复前面的操作。
53+
- 当不存在可以粉碎的糖果,也就是状态稳定之后,请输出最终的状态。
54+
你需要模拟上述规则并使整个方格达到稳定状态,并输出。
55+
提示:
56+
m == board.length
57+
n == board[i].length
58+
3 <= m, n <= 50
59+
1 <= board[i][j] <= 2000
60+
61+
特殊用途的网络 Ad-Hoc
62+
https://leetcode.cn/problems/candy-crush/solution/fen-sui-tang-guo-by-leetcode/
63+
时间复杂度 O(mn * mn)
64+
*/
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import java.util.ArrayList;
2+
import java.util.HashMap;
3+
import java.util.HashSet;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Queue;
8+
import java.util.Set;
9+
10+
public class Solution742 {
11+
private Map<TreeNode, List<TreeNode>> adj;
12+
13+
public int findClosestLeaf(TreeNode root, int k) {
14+
// 树转图
15+
adj = new HashMap<>();
16+
dfs(root, null);
17+
18+
Queue<TreeNode> queue = new LinkedList<>();
19+
Set<TreeNode> visited = new HashSet<>();
20+
for (TreeNode node : adj.keySet()) {
21+
if (node != null && node.val == k) {
22+
queue.add(node);
23+
visited.add(node);
24+
}
25+
}
26+
while (!queue.isEmpty()) {
27+
TreeNode u = queue.remove();
28+
if (adj.get(u).size() == 1) {
29+
return u.val;
30+
}
31+
32+
for (TreeNode v : adj.get(u)) {
33+
if (v != null && !visited.contains(v)) {
34+
visited.add(v);
35+
queue.add(v);
36+
}
37+
}
38+
}
39+
return -1;
40+
}
41+
42+
private void dfs(TreeNode u, TreeNode fa) {
43+
if (u == null) return;
44+
adj.computeIfAbsent(u, key -> new ArrayList<>()).add(fa);
45+
adj.computeIfAbsent(fa, key -> new ArrayList<>()).add(u);
46+
dfs(u.left, u);
47+
dfs(u.right, u);
48+
}
49+
}
50+
/*
51+
$742. 二叉树最近的叶节点
52+
https://leetcode.cn/problems/closest-leaf-in-a-binary-tree/
53+
54+
给定一个 每个结点的值互不相同 的二叉树,和一个目标整数值 k,返回 树中与目标值 k 最近的叶结点 。
55+
与叶结点最近 表示在二叉树中到达该叶节点需要行进的边数与到达其它叶结点相比最少。而且,当一个结点没有孩子结点时称其为叶结点。
56+
提示:
57+
二叉树节点数在 [1, 1000] 范围内
58+
1 <= Node.val <= 1000
59+
每个节点值都 不同
60+
给定的二叉树中有某个结点使得 node.val == k
61+
62+
树转图 + BFS
63+
时间复杂度 O(n)
64+
*/
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import java.util.ArrayList;
2+
import java.util.List;
3+
4+
public class Solution751 {
5+
public List<String> ipToCIDR(String ip, int n) {
6+
List<String> resList = new ArrayList<>();
7+
long start = ip2Long(ip);
8+
for (int i = 0, mod; i < n; i += mod) {
9+
mod = 1;
10+
long cur = start + i;
11+
while (true) {
12+
if (i + mod > n || cur % mod != 0) {
13+
mod >>= 1;
14+
break;
15+
}
16+
mod <<= 1;
17+
}
18+
// 黑科技
19+
// https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html#numberOfLeadingZeros(int)
20+
// floor(log2(x)) = 31 - numberOfLeadingZeros(x)
21+
// ceil(log2(x)) = 32 - numberOfLeadingZeros(x - 1)
22+
int floorLog2x = 31 - Integer.numberOfLeadingZeros(mod);
23+
String res = long2Ip(cur) + "/" + (32 - floorLog2x);
24+
resList.add(res);
25+
}
26+
return resList;
27+
}
28+
29+
private long ip2Long(String ip) {
30+
long res = 0;
31+
for (String x : ip.split("\\.")) {
32+
res = (res << 8) + Integer.parseInt(x);
33+
}
34+
return res;
35+
}
36+
37+
private String long2Ip(long x) {
38+
return (x >> 24) + "." + (x >> 16) % 256 + "." + (x >> 8) % 256 + "." + (x % 256);
39+
}
40+
}
41+
/*
42+
$751. IP 到 CIDR
43+
https://leetcode.cn/problems/ip-to-cidr/
44+
45+
IP地址 是一个格式化的 32位 无符号整数,每组 8位 被打印为一个十进制数字和,点字符 '.' 起到了分组的作用。
46+
- 例如,二进制数 00001111 10001000 11111111 01101011 ( 为清晰起见增加了空格)被格式化为IP地址将是 “15.136.255.107” 。
47+
CIDR块 是一种用来表示一组特定IP地址的格式。字符串形式,由基础IP地址、斜杠和前缀长度 k 组成。它所覆盖的地址是所有IP地址的 前 k 位 与基础IP地址相同的IP地址。
48+
- 例如, “123.45.67.89/20” 是一个前缀长度为 20 的 CIDR块。任何二进制表示形式匹配 01111011 00101101 0100xxxx xxxxxxxx 的IP地址,其中 x 可以是 0 或 1 ,都在CIDR块覆盖的集合中。
49+
给你一个起始IP地址 ip 和我们需要覆盖的IP地址数量 n 。你的目标是使用 尽可能少的CIDR块 来 覆盖范围 [ip, ip + n - 1] 内的所有IP地址 。不应该覆盖范围之外的其他IP地址。
50+
返回 包含IP地址范围的 CIDR块 的 最短 列表。如果有多个答案,返回其中 任何 一个 。
51+
提示:
52+
7 <= ip.length <= 15
53+
ip 是一个有效的 IPv4 ,形式为 "a.b.c.d" ,其中 a, b, c, d 是 [0, 255] 范围内的整数
54+
1 <= n <= 1000
55+
每个隐含地址 ip + x ( x < n) 都是有效的 IPv4 地址
56+
57+
求log2(x)黑科技
58+
相似题目: 1483. 树节点的第 K 个祖先
59+
https://leetcode.cn/problems/kth-ancestor-of-a-tree-node/
60+
*/

0 commit comments

Comments
 (0)