统计相似字符串对的数目

279 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第27天,点击查看活动详情

问题描述

给你一个下标从 0 开始的字符串数组 words 。

如果两个字符串由相同的字符组成,则认为这两个字符串 相似 。

  • 例如,"abca" 和 "cba" 相似,因为它们都由字符 'a''b''c' 组成。
  • 然而,"abacba" 和 "bcfd" 不相似,因为它们不是相同字符组成的。

请你找出满足字符串 words[i] **和 **words[j] 相似的下标对 **(i, j) **,并返回下标对的数目,其中 0 <= i < j <= word.length - 1 。

示例 1:

输入: words = ["aba","aabb","abcd","bac","aabc"]
输出: 2
解释: 共有 2 对满足条件:
- i = 0 且 j = 1 :words[0] 和 words[1] 只由字符 'a' 和 'b' 组成。 
- i = 3 且 j = 4 :words[3] 和 words[4] 只由字符 'a'、'b' 和 'c' 。 

示例 2:

输入: words = ["aabb","ab","ba"]
输出: 3
解释: 共有 3 对满足条件:
- i = 0 且 j = 1 :words[0] 和 words[1] 只由字符 'a' 和 'b' 组成。 
- i = 0 且 j = 2 :words[0] 和 words[2] 只由字符 'a' 和 'b' 组成。 
- i = 1 且 j = 2 :words[1] 和 words[2] 只由字符 'a' 和 'b' 组成。 

示例 3:

输入: words = ["nba","cba","dba"]
输出: 0
解释: 不存在满足条件的下标对,返回 0 。

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 100
  • words[i] 仅由小写英文字母组成

思路分析

首先我们先要理解一下题意,题目会给我们一个字符串数组words,我们需要统计数组中相似字符串的数目,相似字符串的定义为:由相同的字符组成,如"abca" 和 "cba",这里他们组成的字符是相同的,都为a、b、c

所以我们只需要关注每个字符串的组成字符即可,每个字符出现的次数我们不必关心,所以我们可以先对字符串进行去重,去重我们可以利用Set来快速完成:

words[i] = [...new Set(words[i].split(''))]

去重后相似字符串中拥有的字符是一样的,所以我们可以对每个字符串进行排序,排序后的相似字符串就会成为两个一模一样的字符串了,这时候我们可以直接判断两个字符串是否相等来得出两个字符串是否相似:

words[i] = [...new Set(words[i].split(''))].sort().join('');
  • 1、双重遍历求解

因为是要统计相似字符串对的数目,所以我们直接进行进行两次遍历,两两匹配一次判断是否满足要求即可:

for(let i = 0; i < words.length; i++){
    for(let j = i + 1; j < words.length; j++){
        if(words[i] == words[j]) res++;
    }
}
  • 2、哈希+求组合数

我们可以先统计每种相似字符串出现的个数:

let map = {};
for(let i = 0; i < words.length; i++){
    let word = words[i];
    words[i] = [...new Set(word.split(''))].sort().join('');
    map[words[i]] = (map[words[i]] || 0) + 1
}

统计完每种相似字符串出现的个数之后,我们可以通过求每种相似字符串中两两组合的组合数量:

const C = (n,m) => {
    let a = 1, b = 1;
    while(n > 0){
        a *= m--;
        b *= n--;
    }
    return a / b;
} ;
for(let key in map){
    res += C(2,map[key]);
}

AC代码

完整代码如下:

  • 1、双重循环求解
/**
 * @param {string[]} words
 * @return {number}
 */
var similarPairs = function(words) {
    let res = 0;
    for(let i = 0; i < words.length; i++){
        let word = words[i];
        words[i] = [...new Set(word.split(''))].sort().join('');
    }
    for(let i = 0; i < words.length; i++){
        for(let j = i + 1; j < words.length; j++){
            if(words[i] == words[j]) res++;
        }
    }
    return res;
};
  • 2、哈希+求组合数 求解
/**
 * @param {string[]} words
 * @return {number}
 */
var similarPairs = function(words) {
    let res = 0;
    let map = {};
    for(let i = 0; i < words.length; i++){
        let word = words[i];
        words[i] = [...new Set(word.split(''))].sort().join('');
        map[words[i]] = (map[words[i]] || 0) + 1
    }
    const C = (n,m) => {
        let a = 1, b = 1;
        while(n > 0){
            a *= m--;
            b *= n--;
        }
        return a / b;
    } ;
    for(let key in map){
        res += C(2,map[key]);
    }
    return res;
};

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。