记录一道使用位操做符的字符串比较算法

原题目
给定一个字符串数组,找到长度的最大值length(word[i]) * length(word[j]),其中两个单词中的字母无相同。您能够假定每一个单词只包含小写字母。若是没有这两个词,返回0。数组

例:编码

Input: ["abcw","baz","foo","bar","xtfn","abcdef"]
Output: 16 
Explanation: The two words can be "abcw", "xtfn".

解析:
这题确定要进行交叉对比(2个for循环),但最关键的就是对比过程,也就是判断2个字符串是否存在相同的字符。code

若是使用indexOf或者数组下标记录都会形成时间复杂度大幅提高,看了他人的答案发现使用的是位操做符<<|&,并且是在交叉对比以前进行预处理,交叉对比的时候只须要简单的判断pretreate[i] & pretreate[j]===0即可,leetcode

由于使用后效率提高太多,解析而且记录一下。字符串

先解释val |= (1 << (word.charCodeAt(i)-aCode))get

  • word.charCodeAt(i)-aCode这个很好懂,也就是a对应0,b对应1...这里的0,1数字表明的是
    二进制1后面的位数。
  • 1<<01<<1是什么呢?

    1在二进制中(32位)就是00000000000000000000000000000001<<是左移1位,string

    那么1<<0仍是11<<1就是(前面的零省略)101<<2就是1001<<3就是1000io

    因而可知for循环

    a就是1function

    b10

    c100...

    z10000000000000000000000000(25个0)。

  • |是按位或:二进制编码中,每一位二者其中一个为1,则为1,不然,则为0,

    所以 val |=就是对每个字符合并,例如

    ab00010|00001=>00011

    f100000

    ffff 也是 100000

    big101000010

    axdg100000000000000001001001

  • &,按位与,二进制编码中,每一位二者都为1,则为1,不然,则为0,

    例1:axdgoigd要判断是否有重复:

    axdg是:100000000000000001001001
    
    oifd是:         100000100101000
    
    & 后:  000000000000000000001000

    由于第4位都为1,因此最后不为0,也可得知重复的就是字母表第4位:d
     
    例2:axdglkmk要判断是否有重复:

    结果为0,说明无重复。

    axdg是:100000000000000001001001
    
    lkmk是:           1110000000000
    
    & 后:  000000000000000000000000

总结:这种方法使用了二进制数字的位数做为保存字符的手段,相比起数组,散列表等,速度更快,在保存量较小(<=32)优点很是明显。

代码:

/**
 * @param {string[]} words
 * @return {number}
 */
var maxProduct = function(words) {
    let aCode='a'.charCodeAt(0)
    function compute(word){
        let val=0
        for(let i=0;i<word.length;i++){
            val |= (1 << (word.charCodeAt(i)-aCode))
        }
        return val
    }
    let pretreatment=[]
    for(let i=0;i<words.length;i++){
        pretreatment[i]=compute(words[i])
    }
    let maxSum=0
    for(let i=0;i<words.length-1;i++){
        for(let j=i+1;j<words.length;j++){
            let len1=words[i].length,len2=words[j].length
            if(len1*len2>maxSum && (pretreatment[i] & pretreatment[j])===0){
                 maxSum=len1*len2
            }
        }
    }
    return maxSum
};
相关文章
相关标签/搜索