【计数】【字符串】
1657. 确定两个字符串是否接近
你可以进行以下两种操作:
aacabb -> bbcbaa
,将所有的 a
转化为 b
,所有的 b
转化为 a
。如果两个字符串使用以上操作可以从将一个字符串转化成另一个字符串,则认为两个字符串 接近。
现在有两个字符串 word1
和 word2
,问这两个字符串是否接近,如是返回 true
,否则返回 false
。
思路
首先需要明确,两种操作都不会产生新的字符,因此如果某个字符串中出现了另一个字符串没有出现的字符,那么这两个字符串一定不会 接近。
其次,无论是进行字符交换的操作 1 的还是进行字符转换操作 2,都不应改变原来字符出现的次数数组(排序后应相等),比如字符串 "aacabb"
原来的字符次数数组为 [3, 1, 2]
经过任意次的操作之后,形成的与原字符串 接近 的一种字符串为 "bbcbaa"
,对应的字符数组为 [3, 1, 2]
。
同时满足以上两个条件的字符串才是 接近 的。
于是,需要统计两个字符串中字符出现的数量。因为字符串仅包含小写英文字符,所以可以使用长度为 26
的数组来统计字符出现的数量,字符 a
出现的数量为数组下标 'a' - 'a' = 0
对应的数值,字符 b
出现的数量为数组下标 'b' - 'a' = 1
对应的数值,…,字符 z
出现的数量为数组下标 'z' - 'a' = 25
对应的数值。
具体实现
判断是否接近过程为:
word1
和 word2
,更新统计字符串中字符出现数量的数组 cnt1
和 cnt2
;cnt1
和 cnt2
中某一个字符出现次数为 0
,而另一个数组中对应字符出现次数不为 0
,则返回 false
;cnt1
和 cnt2
排序后不相等,返回 false
;false
,最后直接返回 true
。在统计两个字符串中出现的字符是否一致还可以使用集合来判断(只提供思路,具体实现请读者自行完成),集合我们可以使用 STL
中的 set
,也可以使用二进制数利用位运算来模拟集合。这里对用二进制数来模拟集合简单说一说,字符串 "aacabb"
的字符集合使用二进制表示为 111
,具体实现过程请参考 位运算基础与应用。
实现代码
class Solution {
public:
bool closeStrings(string word1, string word2) {
vector<int> cnt1(26), cnt2(26);
for (char c : word1) {
++cnt1[c- 'a'];
}
for (char c : word2) {
++cnt2[c - 'a'];
}
for (int i = 0; i < 26; ++i) {
if (cnt1[i] > 0 && cnt2[i] == 0 || cnt2[i] > 0 && cnt1[i] == 0) {
return false;
}
}
sort(cnt1.begin(), cnt1.end());
sort(cnt2.begin(), cnt2.end());
return cnt1 == cnt2;
}
};
复杂度分析
时间复杂度: O ( m a x n 1 , n 2 + C l o g C ) O(max{n_1, n_2} + ClogC) O(maxn1,n2+ClogC), n 1 n_1 n1 和 n 2 n_2 n2 分别为字符串 word1
和 word2
的长度, C = 26 C = 26 C=26 是字符集的大小。
空间复杂度: O ( C ) O(C) O(C)。
class Solution:
def closeStrings(self, word1: str, word2: str) -> bool:
return Counter(word1).keys() == Counter(word2).keys() and sorted(Counter(word1).values()) == sorted(Counter(word2).values())
下面对代码中的关键部分进行解释:
Counter(word1)
和 Counter(word2)
:这两个语句使用 Python 的 collections
模块中的 Counter
类,用于统计字符串中每个字符的出现次数,返回一个字典,其中键是字符,值是该字符在字符串中出现的次数;Counter(word1).keys()
:获取字符串 word1
中所有字符的集合,即字符的唯一集合;sorted(Counter(word1).values())
:获取字符串 word1
中字符出现次数的有序列表。如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 。
如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。
最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 哦。