You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
4.0 KiB
196 lines
4.0 KiB
package class_2022_02_4_week;
|
|
|
|
import java.util.HashMap;
|
|
|
|
// 测试链接 : https://leetcode.com/problems/groups-of-strings/
|
|
public class Code05_GroupsOfStrings {
|
|
|
|
// 可能会超时,或者打败比例很低
|
|
// 因为常数优化不到位
|
|
public static int[] groupStrings1(String[] words) {
|
|
int n = words.length;
|
|
// 0 1 2 ... n-1
|
|
UnionFind uf = new UnionFind(n);
|
|
int[] strs = new int[n];
|
|
// abd -> 0..01011 7
|
|
// 0..01011 key value 7
|
|
HashMap<Integer, Integer> stands = new HashMap<>();
|
|
for (int i = 0; i < n; i++) {
|
|
int status = 0;
|
|
for (char c : words[i].toCharArray()) {
|
|
status |= 1 << (c - 'a');
|
|
}
|
|
strs[i] = status;
|
|
if (stands.containsKey(status)) {
|
|
uf.union(stands.get(status), i);
|
|
} else {
|
|
stands.put(status, i);
|
|
}
|
|
}
|
|
for (int i = 0; i < n; i++) {
|
|
// 一个字符串,状态
|
|
int status = strs[i];
|
|
for (int j = 0; j < 26; j++) {
|
|
// 001101
|
|
// a
|
|
// 001101
|
|
// b
|
|
// 001111
|
|
// c
|
|
// 001101
|
|
// z
|
|
//..
|
|
uf.union(i, stands.get(status | (1 << j)));
|
|
}
|
|
// 有的字符,减少一遍
|
|
for (int j = 0; j < 26; j++) {
|
|
if ((status & (1 << j)) != 0) {
|
|
uf.union(i, stands.get(status ^ (1 << j)));
|
|
}
|
|
}
|
|
for (int has = 0; has < 26; has++) {
|
|
if ((status & (1 << has)) != 0) {
|
|
status ^= 1 << has;
|
|
for (int replace = 0; replace < 26; replace++) {
|
|
uf.union(i, stands.get(status | (1 << replace)));
|
|
}
|
|
status |= 1 << has;
|
|
}
|
|
}
|
|
}
|
|
return new int[] { uf.sets(), uf.maxSize() };
|
|
}
|
|
|
|
// 肯定通过
|
|
// 打败比例达标
|
|
// 优化了常数时间
|
|
public static int[] groupStrings2(String[] words) {
|
|
int n = words.length;
|
|
UnionFind uf = new UnionFind(n);
|
|
int[] strs = new int[n];
|
|
HashMap<Integer, Integer> stands = new HashMap<>();
|
|
for (int i = 0; i < n; i++) {
|
|
int status = 0;
|
|
for (char c : words[i].toCharArray()) {
|
|
status |= 1 << (c - 'a');
|
|
}
|
|
strs[i] = status;
|
|
if (stands.containsKey(status)) {
|
|
uf.union(stands.get(status), i);
|
|
} else {
|
|
stands.put(status, i);
|
|
}
|
|
}
|
|
for (int i = 0; i < n; i++) {
|
|
int yes = strs[i];
|
|
int no = (~yes) & ((1 << 26) - 1);
|
|
int tmpYes = yes;
|
|
int tmpNo = no;
|
|
int rightOneYes = 0;
|
|
int rightOneNo = 0;
|
|
|
|
|
|
// 0....0 0110011
|
|
//
|
|
// 0....0 0110011
|
|
// 0....0 0000001 -> 用
|
|
|
|
// 0....0 0110010
|
|
// 0....0 0000010 -> 用
|
|
|
|
// 0....0 0110000
|
|
|
|
while (tmpYes != 0) {
|
|
rightOneYes = tmpYes & (-tmpYes);
|
|
uf.union(i, stands.get(yes ^ rightOneYes));
|
|
tmpYes ^= rightOneYes;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// tmpNo = 该去试试什么添加!
|
|
while(tmpNo != 0) {
|
|
rightOneNo = tmpNo & (-tmpNo);
|
|
uf.union(i, stands.get(yes | rightOneNo));
|
|
tmpNo ^= rightOneNo;
|
|
}
|
|
tmpYes = yes;
|
|
while (tmpYes != 0) {
|
|
rightOneYes = tmpYes & (-tmpYes);
|
|
tmpNo = no;
|
|
while (tmpNo != 0) {
|
|
rightOneNo = tmpNo & (-tmpNo);
|
|
uf.union(i, stands.get((yes ^ rightOneYes) | rightOneNo));
|
|
tmpNo ^= rightOneNo;
|
|
}
|
|
tmpYes ^= rightOneYes;
|
|
}
|
|
}
|
|
return new int[] { uf.sets(), uf.maxSize() };
|
|
}
|
|
|
|
public static class UnionFind {
|
|
private int[] parent;
|
|
private int[] size;
|
|
private int[] help;
|
|
|
|
public UnionFind(int N) {
|
|
parent = new int[N];
|
|
size = new int[N];
|
|
help = new int[N];
|
|
for (int i = 0; i < N; i++) {
|
|
parent[i] = i;
|
|
size[i] = 1;
|
|
}
|
|
}
|
|
|
|
private int find(int i) {
|
|
int hi = 0;
|
|
while (i != parent[i]) {
|
|
help[hi++] = i;
|
|
i = parent[i];
|
|
}
|
|
for (hi--; hi >= 0; hi--) {
|
|
parent[help[hi]] = i;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
public void union(Integer i, Integer j) {
|
|
if (i == null || j == null) {
|
|
return;
|
|
}
|
|
int f1 = find(i);
|
|
int f2 = find(j);
|
|
if (f1 != f2) {
|
|
if (size[f1] >= size[f2]) {
|
|
size[f1] += size[f2];
|
|
parent[f2] = f1;
|
|
} else {
|
|
size[f2] += size[f1];
|
|
parent[f1] = f2;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int sets() {
|
|
int ans = 0;
|
|
for (int i = 0; i < parent.length; i++) {
|
|
ans += parent[i] == i ? 1 : 0;
|
|
}
|
|
return ans;
|
|
}
|
|
|
|
public int maxSize() {
|
|
int ans = 0;
|
|
for (int s : size) {
|
|
ans = Math.max(ans, s);
|
|
}
|
|
return ans;
|
|
}
|
|
}
|
|
|
|
}
|