LeetCode --- 字符串系列 --- 特殊等价字符串组

特殊等价字符串组

注释:这道题目题意太过难理解,理解题意花了几小时... 下面将对题目进行括号注释....


题目

你将得到一个字符串数组 A。比如 (["a2cd","ac2d","2acd", "c2ad"])

如果经过任意次数的移动,S == T,那么两个字符串 S 和 T 是特殊等价的。

(比如上面给出的字符串数组,若其中两个数组元素字符串,自身的字符发生任意次数的移动,
移动次数不用相等,最后这两个字符串可以相等,那么就说这两个字符串是等价的。
在这个字符串数组中,可以存在多个等价字符串)

一次移动包括选择两个索引 i 和 j,且 i % 2 == j % 2,交换 S[j] 和 S [i]。

(这里意思是上面所说到的任意次移动,每次移动,需要移动字符串中的两位,这两位互相交换位置;
移动的这两位位置要满足条件 i % 2 == j % 2。即 i 和 j 都是偶数或者奇数。
换个说法,对字符串进行奇数位交换操作,或者偶尔位交换操作或者奇数位交换完成后,进行偶数位交换,次数不限)

拿上面的例子:

每个数组字符串元素各经过一次(实际可以交换多次)偶数位和奇数位交换:

`a2cd` 偶数变化-> adc2 -> 偶数位再变一次(变回来了) `a2cd`
       奇数变化-> `c2ad`
      
ac2d   偶数变化-> 2cad
       奇数变化-> ad2c

2acd   偶数变化-> ca2d
       奇数变化-> 2dca

`c2ad` 偶数变化-> `a2cd`
       奇数变化-> cda2`

观察发现 a2cdc2ad 经过上面的变化之后可以相等,那么这两个就是等价的



原字符串 经过任意次数变化可以变回自己,所以每个字符串跟自己是特殊等价


现在规定,A 中的特殊等价字符串组是 A 的非空子集 S

这样不在 S 中的任何字符串与 S 中的任何字符串都不是特殊等价的。

(这里加了一个限制条件:不在 S 中的任何字符串与 S 中的任何字符串都不是特殊等价的

应该为 不在 S 中任何的字符串(即在 A 中刨去 S 字符串之后的剩下字符串)与 S 中的任何字符串都不是特殊等价的)

(上面我说,每个字符串跟自己是特殊等价的, 单个字符串 如果没有其他字符串和他自己等价,那么他自己就组成了一个等价字符串数组,保证了 S 是 A 的非空子集。

但是也可以这么想,是不是因为有了这条规定:A 中的特殊等价字符串组是 A 的非空子集 S,才限制我们若 单个字符串 没有其他字符串和他自己等价,他自己就组成了一个等价字符串数组)

返回 A 中特殊等价字符串组的数量。


示例

示例 1:

输入:["a","b","c","a","c","c"]
输出:3
解释:3 组 ["a","a"],["b"],["c","c","c"]
示例 2:

输入:["aa","bb","ab","ba"]
输出:4
解释:4 组 ["aa"],["bb"],["ab"],["ba"]
示例 3:

输入:["abc","acb","bac","bca","cab","cba"]
输出:3
解释:3 组 ["abc","cba"],["acb","bca"],["bac","cab"]
示例 4:

输入:["abcd","cdab","adcb","cbad"]
输出:1
解释:1 组 ["abcd","cdab","adcb","cbad"]

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/groups-of-special-equivalent-strings/

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


解题思路

1、字符串数组中的元素可以进行任意次偶数、奇数位移动,产生多个排列组合
若有另外一个字符串也经过这样的操作产生排列组合,这两个排列组合中有相等的一对,那么这两个 `原字符串` 就是特殊等价的

2、所以第一步对字符串进行排列

3、第二步找出两个排列组合中相等的一对

或者

较好力扣题解

1、
字符串切割,过滤奇数位字符串,排序拼接
加上
字符串切割,过滤偶数位字符串,排序拼接

2、若是等价字符,则经过此操作将会相等

3、最后利用 Set 的去重特性,转换成数组,可以得到最终长度

题解

let numSpecialEquivGroups = function (A) {
    let obj = {}
    // 遍历字符串数组
    for (let i = 0; i < A.length; i++) {
        // 匹配计数,偶数字符串,奇数字符串
        let count = 0, evens = '', odds = ''
        A[i].replace(/\w/g, w => {
            count++
            // 匹配到字符 count 就加 1
            // 分别收集偶数位和奇数位的字符串
            if (count % 2 === 0) {
                evens += w
            } else {
                odds += w
            }
        })
        // 排序
        evens = evens.split('').sort()
        odds = odds.split('').sort()
        let key = ''
        // 以奇数字符串开始,顺序插入偶数位
        odds.forEach((w, index) => {
            key += w + (evens[index] ? evens[index] : '')
        })
        // 将排列后相同的原字符串归类收集起来
        obj[key] = obj[key] || []
        obj[key].push(A[i])
    }
    // 最后返回 obj 的属性长度
    return Object.keys(obj).length
}

或者

较好力扣题解

const numSpecialEquivGroups = (A) =>
    [
    ...new Set(
        A.map(
        (item) =>
            // 字符串切割,过滤奇数位字符串,排序拼接
            // 加上
            // 字符串切割,过滤偶数位字符串,排序拼接
            // 若是等价字符,则经过此操作将会相等
            // 最后利用 Set 的去重特性,转换成数组,可以得到最终长度
            item
            .split('')
            .filter((t, i) => i % 2 === 1)
            .sort()
            .join('') +
            item
            .split('')
            .filter((t, i) => i % 2 === 0)
            .sort()
            .join('')
        )
    ),
    ].length

posted @ 2020-04-10 23:13  青S衫%  阅读(332)  评论(0编辑  收藏  举报