2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现一次。 如果通过以下操作之一,我们可以
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现一次。
如果通过以下操作之一,我们可以从 s1 的字母集合得到 s2 的字母集合,那么我们称这两个字符串为 关联的 :
往 s1 的字母集合中添加一个字母。
 从 s1 的字母集合中删去一个字母。
 将 s1 中的一个字母替换成另外任意一个字母(也可以替换为这个字母本身)。
 数组 words 可以分为一个或者多个无交集的 组 。如果一个字符串与另一个字符串关联,那么它们应当属于同一个组。
注意,你需要确保分好组后,一个组内的任一字符串与其他组的字符串都不关联。可以证明在这个条件下,分组方案是唯一的。
请你返回一个长度为 2 的数组 ans :
ans[0] 是 words 分组后的 总组数 。
 ans[1] 是字符串数目最多的组所包含的字符串数目。
输入:words = [“a”,“b”,“ab”,“cde”]。
 输出:[2,3]。
 解释:
- words[0] 可以得到 words[1] (将 ‘a’ 替换为 ‘b’)和 words[2] (添加 ‘b’)。所以 words[0] 与 words[1] 和 words[2] 关联。
- words[1] 可以得到 words[0] (将 ‘b’ 替换为 ‘a’)和 words[2] (添加 ‘a’)。所以 words[1] 与 words[0] 和 words[2] 关联。
- words[2] 可以得到 words[0] (删去 ‘b’)和 words[1] (删去 ‘a’)。所以 words[2] 与 words[0] 和 words[1] 关联。
- words[3] 与 words 中其他字符串都不关联。
 所以,words 可以分成 2 个组 [“a”,“b”,“ab”] 和 [“cde”] 。最大的组大小为 3 。
力扣2157. 字符串分组。
答案2022-05-08:
并查集。
代码用rust编写。代码如下:
use std::collections::HashMap;
fn main() {
    let words: Vec<&str> = vec!["a", "b", "ab", "cde"];
    let answer = group_strings2(&words);
    println!("answer = {:?}", answer);
}
fn group_strings2(words: &Vec<&str>) -> Vec<isize> {
    let n = words.len() as isize;
    let mut uf: UnionFind = UnionFind::new(n);
    let mut strs: Vec<isize> = vec![];
    for _i in 0..n {
        strs.push(0);
    }
    let mut stands: HashMap<isize, isize> = HashMap::new();
    for i in 0..n {
        let mut status: isize = 0;
        for c in words[i as usize].chars() {
            status |= 1 << (c as u8 - 'a' as u8);
        }
        strs[i as usize] = status;
        let mut isnone = false;
        match stands.get(&status) {
            Some(value) => uf.union(*value, i),
            None => isnone = true,
        }
        if isnone {
            stands.insert(status, i);
        }
    }
    for i in 0..n {
        let yes = strs[i as usize];
        let no = (!yes) & ((1 << 26) - 1);
        let mut tmp_yes = yes;
        let mut tmp_no = no;
        let mut right_one_yes;
        let mut right_one_no;
        // 0....0 0110011
        //
        // 0....0 0110011
        // 0....0 0000001 -> 用
        // 0....0 0110010
        // 0....0 0000010 -> 用
        // 0....0 0110000
        while tmp_yes != 0 {
            right_one_yes = tmp_yes & (-tmp_yes);
            let isok: bool;
            match stands.get(&(yes ^ right_one_yes)) {
                Some(_value) => isok = true,
                None => isok = false,
            }
            if isok {
                uf.union(i, *stands.get(&(yes ^ right_one_yes)).unwrap());
            }
            tmp_yes ^= right_one_yes;
        }
        // tmpNo = 该去试试什么添加!
        while tmp_no != 0 {
            right_one_no = tmp_no & (-tmp_no);
            let isok: bool;
            match stands.get(&(yes | right_one_no)) {
                Some(_value) => isok = true,
                None => isok = false,
            }
            if isok {
                uf.union(i, *stands.get(&(yes | right_one_no)).unwrap());
            }
            tmp_no ^= right_one_no;
        }
        tmp_yes = yes;
        while tmp_yes != 0 {
            right_one_yes = tmp_yes & (-tmp_yes);
            tmp_no = no;
            while tmp_no != 0 {
                right_one_no = tmp_no & (-tmp_no);
                let isok: bool;
                match stands.get(&((yes ^ right_one_yes) | right_one_no)) {
                    Some(_value) => isok = true,
                    None => isok = false,
                }
                if isok {
                    uf.union(
                        i,
                        *stands.get(&((yes ^ right_one_yes) | right_one_no)).unwrap(),
                    );
                }
                tmp_no ^= right_one_no;
            }
            tmp_yes ^= right_one_yes;
        }
    }
    let ans: Vec<isize> = vec![uf.sets(), uf.max_size()];
    return ans;
}
pub struct UnionFind {
    pub parent: Vec<isize>,
    pub size: Vec<isize>,
    pub help: Vec<isize>,
}
impl UnionFind {
    pub fn new(n: isize) -> UnionFind {
        let mut parent: Vec<isize> = vec![];
        let mut size: Vec<isize> = vec![];
        let mut help: Vec<isize> = vec![];
        for i in 0..n {
            parent.push(i);
            size.push(1);
            help.push(0);
        }
        UnionFind {
            parent: parent,
            size: size,
            help: help,
        }
    }
    pub fn find(&mut self, i: isize) -> isize {
        let mut i = i;
        let mut hi: isize = 0;
        while i != self.parent[i as usize] {
            self.help[hi as usize] = i;
            hi += 1;
            i = self.parent[i as usize];
        }
        hi -= 1;
        while hi >= 0 {
            self.parent[self.help[hi as usize] as usize] = i;
            hi -= 1;
        }
        return i;
    }
    pub fn union(&mut self, i: isize, j: isize) {
        let f1 = self.find(i);
        let f2 = self.find(j);
        if f1 != f2 {
            if self.size[f1 as usize] >= self.size[f2 as usize] {
                self.size[f1 as usize] += self.size[f2 as usize];
                self.parent[f2 as usize] = f1;
            } else {
                self.size[f2 as usize] += self.size[f1 as usize];
                self.parent[f1 as usize] = f2;
            }
        }
    }
    pub fn sets(&mut self) -> isize {
        let mut ans: isize = 0;
        for i in 0..self.parent.len() {
            ans += if self.parent[i] == i as isize { 1 } else { 0 };
        }
        return ans;
    }
    pub fn max_size(&mut self) -> isize {
        let mut ans: isize = 0;
        for i in 0..self.size.len() {
            ans = if ans > self.size[i as usize] {
                ans
            } else {
                self.size[i as usize]
            };
        }
        return ans;
    }
}
执行结果如下:

2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现一次。 如果通过以下操作之一,我们可以的更多相关文章
- 给定两个字符串 s 和 t,它们只包含小写字母。 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。 请找出在 t 中被添加的字母。
		给定两个字符串 s 和 t,它们只包含小写字母.字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母.请找出在 t 中被添加的字母. 示例: 输入: s = "abcd" ... 
- 获取页面中任意一个元素距离body的偏移量
		//offSet:等同于jQuery中的offSet方法,获取页面中任意一个元素距离body的偏移量function offSet(curEle) { var totalLeft = null; va ... 
- 【剑指offer】找出数组中任意一个重复的数字,C++实现
		原创博文,转载请注明出处! # 题目 # 思路 对于长度为n的数组,范围为0~n-1的数字而言,如果不粗在重复数字,则排序后数组元素和数组角标相同.如果存在重复数字,则在排序的过程中会出现不同下标对应 ... 
- 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3
		// test14.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ... 
- [Robot Framework] 校验字符串中是否包含某个子字符串,校验同时满足两个条件中任意一个
		${tWarningMessage} Run Keyword If ${tIfExist} AutoItLibrary.Win Get Text Generate Fee Data warning m ... 
- java 正则表达式 验证字符串 只包含汉字英文数字
		String content = “testContent”; String regex="^[a-zA-Z0-9\u4E00-\u9FA5]+$"; Pattern patter ... 
- 让android系统中任意一个view变成进度条
		1.效果 2.进度条背景drawable文件 结束后可以恢复原背景. <?xml version="1.0" encoding="utf-8"?> ... 
- VIM 用正则表达式,非贪婪匹配,匹配竖杠,竖线, 匹配中文,中文正则,倒数第二列, 匹配任意一个字符 :
		VIM 用正则表达式 批量替换文本,多行删除,复制,移动 在VIM中 用正则表达式 批量替换文本,多行删除,复制,移动 :n1,n2 m n3 移动n1-n2行(包括n1,n2)到n3行之下: ... 
- 只包含schema的dll生成和引用方法
		工作中,所有的tools里有一个project是只包含若干个schema的工程,研究了一下,发现创建这种只包含schema的dll其实非常简单. 首先,在visual studio-new proje ... 
- 面试题:编写一个函数来查找字符串数组中的最长公共前缀。  如果不存在公共前缀,返回空字符串 ""。(c++实现)
		实例说明 示例 1: 输入: ["flower","flow","flight"] 输出: "fl" 示例 2: 输入: ... 
随机推荐
- File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent
			IDEA编译报以下错误 File encoding has not been set, using platform encoding UTF-8, i.e. build is platform de ... 
- 查看服务器cpu 核心数
			cpu相关信息所在文件是 /proc/cpuinfo 物理cpu数 # grep "physical id" /proc/cpuinfo | sort | uniq | wc -l ... 
- 配置环境变量在history中显示时间
			1.1.临时显示(断电丢失) 配置变量HISTTIMEFORMAT,加入"%F %T ". 示例: [root@CentOS8 ~]# HISTTIMEFORMAT='%F %T ... 
- Python学习笔记--布尔类型和比较运算符、if判断语句以及相关案例的实现
			布尔类型和比较运算符 代码: 结果: 主要有以下几类: 注意:bool类型的真假表示开头必须大写,例如:True和False 而要是想要得到布尔类型,除了直接定义,还可以通过比较运算得到布尔类型: i ... 
- 53.cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
			1.cin 用法1:最基本,也是最常用的用法,输入一个数字: #pragma warning(disable:4996) #define _CRT_SECURE_NO_WARNINGS 1 #incl ... 
- 自己动手从零写桌面操作系统GrapeOS系列教程——16.封装打印字符串函数
			学习操作系统原理最好的方法是自己写一个简单的操作系统. 在上一讲中我们向屏幕打印字符串"GrapeOS"用了十几行汇编代码,如果要输出的字符比较多,这种方法太繁琐了.本讲我们将打印 ... 
- Java面试——TCP与HTTP
			更多内容,移步 IT-BLOG 一.Session 和 Cookie 的区别 [1]Cookie 保存在客户端,未设置存储时间的 Cookie,关闭浏览器会话 Cookie 就会被删除:设置了存储时间 ... 
- Java面试——数据库
			一.数据库隔离级别 [1]Read Uncommitted(读取未提交内容):出现脏读,也就是可能读取到其他会话中未提交事务修改的数据.[2]Read Committed(读取已提交内容):不可重复读 ... 
- jq-ajax-get
			get有三个参数,第一个时候url,第二个是数据,第三个是回调函数(可以用返回值表示,如下所示) 执行正确时,返回的依次是res,type,xhr. 执行错误连接不上的的依次是xhr,type,res ... 
- c++与linux详细计划,精确到每一天(仅80天)
			好的,以下是三个月中每一天的学习计划: 第一个月: 第1天:阅读C++教程,熟悉环境,了解基本语法和数据类型 第2天:编写Hello World程序,加深对C++环境的了解 第3天:学习函数的定义和调 ... 
