leecode更新
This commit is contained in:
parent
b531d06a02
commit
ee4c7618f8
|
|
@ -0,0 +1,146 @@
|
||||||
|
package com.markilue.leecode.hot100;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-04-06 10:04
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣394 字符串解码:
|
||||||
|
* 给定一个经过编码的字符串,返回它解码后的字符串。
|
||||||
|
* 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
|
||||||
|
* 你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
|
||||||
|
* 此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T86_DecodeString {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
String s = "3[a]2[bc]";
|
||||||
|
System.out.println(decodeString(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test1() {
|
||||||
|
String s = "3[a2[c]]";
|
||||||
|
System.out.println(decodeString(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test2() {
|
||||||
|
String s = "3[z]2[2[y]pq4[2[jk]e1[f]]]ef";
|
||||||
|
System.out.println(decodeString(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public String decodeString(String s) {
|
||||||
|
return decodeSubString(s.toCharArray(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String decodeSubString(char[] chars, int count) {
|
||||||
|
if (chars[start] == '[') start++;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int sum = 0;
|
||||||
|
while (start < chars.length && Character.isDigit(chars[start])) {
|
||||||
|
sum = sum * 10 + (chars[start] - '0');
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
//如果前面没有数字,返回1次
|
||||||
|
if (sum == 0) {
|
||||||
|
while (start < chars.length && chars[start] >= 'a' && chars[start] <= 'z') {
|
||||||
|
sb.append(chars[start++]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append(decodeSubString(chars, sum));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (start < chars.length && Character.isDigit(chars[start])) {
|
||||||
|
// sb.append(decodeSubString(chars, 1));
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (start < chars.length && chars[start] == ']') {
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
if (count > 1) {
|
||||||
|
String k = sb.toString();
|
||||||
|
for (int i = 0; i < count - 1; i++) {
|
||||||
|
sb.append(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start < chars.length && chars[start] != ']') {
|
||||||
|
sb.append(decodeSubString(chars, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String src;
|
||||||
|
int ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方递归法:
|
||||||
|
* 思路和本人一致,但是思路更清晰和简洁
|
||||||
|
* 速度击败100% 内存击败76.28%
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String decodeString1(String s) {
|
||||||
|
src = s;
|
||||||
|
ptr = 0;
|
||||||
|
return getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString() {
|
||||||
|
if (ptr == src.length() || src.charAt(ptr) == ']') {
|
||||||
|
// String -> EPS
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
char cur = src.charAt(ptr);
|
||||||
|
int repTime = 1;
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
|
||||||
|
if (Character.isDigit(cur)) {
|
||||||
|
// String -> Digits [ String ] String
|
||||||
|
// 解析 Digits
|
||||||
|
repTime = getDigits();
|
||||||
|
// 过滤左括号
|
||||||
|
++ptr;
|
||||||
|
// 解析 String
|
||||||
|
String str = getString();
|
||||||
|
// 过滤右括号
|
||||||
|
++ptr;
|
||||||
|
// 构造字符串
|
||||||
|
while (repTime-- > 0) {
|
||||||
|
ret.append(str);
|
||||||
|
}
|
||||||
|
} else if (Character.isLetter(cur)) {
|
||||||
|
// String -> Char String
|
||||||
|
// 解析 Char
|
||||||
|
ret.append(String.valueOf(src.charAt(ptr++)));
|
||||||
|
}
|
||||||
|
ret.append(getString());
|
||||||
|
|
||||||
|
return ret.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDigits() {
|
||||||
|
int ret = 0;
|
||||||
|
while (ptr < src.length() && Character.isDigit(src.charAt(ptr))) {
|
||||||
|
ret = ret * 10 + src.charAt(ptr++) - '0';
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
package com.markilue.leecode.hot100;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.hot100
|
||||||
|
*@Author: markilue
|
||||||
|
*@CreateTime: 2023-04-06 11:47
|
||||||
|
*@Description:
|
||||||
|
* TODO 力扣399 除法求值:
|
||||||
|
* 给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi = values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。
|
||||||
|
* 另有一些以数组 queries 表示的问题,其中 queries[j] = [Cj, Dj] 表示第 j 个问题,请你根据已知条件找出 Cj / Dj = ? 的结果作为答案。
|
||||||
|
* 返回 所有问题的答案 。如果存在某个无法确定的答案,则用 -1.0 替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用 -1.0 替代这个答案。
|
||||||
|
* 注意:输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T87_CalcEquation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方题解:并查集解法
|
||||||
|
* 速度击败100% 内存击败85.81% 0ms
|
||||||
|
* @param equations
|
||||||
|
* @param values
|
||||||
|
* @param queries
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
|
||||||
|
|
||||||
|
int equationSize = equations.size();
|
||||||
|
UnionFind unionFind = new UnionFind(2 * equationSize);
|
||||||
|
//第一步:预处理,将变量的值与id进行映射,是的并查集的底层使用数组实现,方便编码
|
||||||
|
HashMap<String, Integer> hashMap = new HashMap<>(2 * equationSize);
|
||||||
|
int id = 0;
|
||||||
|
for (int i = 0; i < equationSize; i++) {
|
||||||
|
List<String> equation = equations.get(i);
|
||||||
|
String var1 = equation.get(0);
|
||||||
|
String var2 = equation.get(1);
|
||||||
|
if (!hashMap.containsKey(var1)) {
|
||||||
|
hashMap.put(var1, id);
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
if (!hashMap.containsKey(var2)) {
|
||||||
|
hashMap.put(var2, id);
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
unionFind.union(hashMap.get(var1), hashMap.get(var2), values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//第二部:做查询
|
||||||
|
int queriesSize = queries.size();
|
||||||
|
double[] res = new double[queriesSize];
|
||||||
|
for (int i = 0; i < queriesSize; i++) {
|
||||||
|
String var1 = queries.get(i).get(0);
|
||||||
|
String var2 = queries.get(i).get(1);
|
||||||
|
Integer id1 = hashMap.get(var1);
|
||||||
|
Integer id2 = hashMap.get(var2);
|
||||||
|
if (id1 == null || id2 == null) {
|
||||||
|
res[i] = -1.0d;
|
||||||
|
} else {
|
||||||
|
res[i] = unionFind.isConnected(id1, id2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class UnionFind {
|
||||||
|
|
||||||
|
private int[] parent;
|
||||||
|
|
||||||
|
private double[] weight;
|
||||||
|
|
||||||
|
public UnionFind(int n) {
|
||||||
|
this.parent = new int[n];
|
||||||
|
this.weight = new double[n];
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
parent[i] = i;
|
||||||
|
weight[i] = 1.0d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void union(int x, int y, double value) {
|
||||||
|
int rootX = find(x);
|
||||||
|
int rootY = find(y);
|
||||||
|
if (rootX == rootY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parent[rootX] = rootY;
|
||||||
|
weight[rootX] = weight[y] * value / weight[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径压缩
|
||||||
|
* @param x
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int find(int x) {
|
||||||
|
if (x != parent[x]) {//存在引用链,至少是第一次遍历到才会不相等
|
||||||
|
int origin = parent[x];
|
||||||
|
parent[x] = find(parent[x]);
|
||||||
|
weight[x] *= weight[origin];
|
||||||
|
}
|
||||||
|
return parent[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
public double isConnected(int x, int y) {
|
||||||
|
int rootX = find(x);
|
||||||
|
int rootY = find(y);
|
||||||
|
if (rootY == rootX) {
|
||||||
|
return weight[x] / weight[y];
|
||||||
|
} else {
|
||||||
|
return -1.0d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方DFS法:本质上就是把数据加入子集当中,然后如果存在引用链就一定能够被连接上,则可以计算
|
||||||
|
* 速度击败54.5% 内存击败29.67% 1ms
|
||||||
|
* @param equations
|
||||||
|
* @param values
|
||||||
|
* @param queries
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public double[] calcEquation1(List<List<String>> equations, double[] values, List<List<String>> queries) {
|
||||||
|
double[] result = new double[queries.size()];
|
||||||
|
Map<String, Map<String, Double>> graph = buildGraph(equations, values);
|
||||||
|
|
||||||
|
for (int i = 0; i < queries.size(); i++) {
|
||||||
|
//dfs寻找对应的引用
|
||||||
|
String start = queries.get(i).get(0);
|
||||||
|
String end = queries.get(i).get(1);
|
||||||
|
|
||||||
|
if (!graph.containsKey(start) || !graph.containsKey(end)) {
|
||||||
|
result[i] = -1;//有一个没有就肯定计算不出来
|
||||||
|
} else {
|
||||||
|
Set<String> visited = new HashSet<>();
|
||||||
|
result[i] = dfs(graph, start, end, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//构建引用链
|
||||||
|
private Map<String, Map<String, Double>> buildGraph(List<List<String>> equations, double[] values) {
|
||||||
|
Map<String, Map<String, Double>> graph = new HashMap<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < equations.size(); i++) {
|
||||||
|
String v1 = equations.get(i).get(0);
|
||||||
|
String v2 = equations.get(i).get(1);
|
||||||
|
graph.putIfAbsent(v1, new HashMap<String, Double>());
|
||||||
|
graph.get(v1).put(v2, values[i]);
|
||||||
|
|
||||||
|
graph.putIfAbsent(v2, new HashMap<String, Double>());
|
||||||
|
graph.get(v2).put(v1, 1.0 / values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double dfs(Map<String, Map<String, Double>> graph, String start, String end, Set<String> visited) {
|
||||||
|
visited.add(start);
|
||||||
|
Map<String, Double> next = graph.get(start);
|
||||||
|
for (Map.Entry<String, Double> entry : next.entrySet()) {
|
||||||
|
if (entry.getKey().equals(end)) {
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
if (!visited.contains(entry.getKey())) {
|
||||||
|
double nextValue = dfs(graph, entry.getKey(), end, visited);
|
||||||
|
if (nextValue > 0) {//即不可能是-1就正常返回
|
||||||
|
return entry.getValue() * nextValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue