記錄一道使用位操做符的字符串比較算法

原題目
給定一個字符串數組,找到長度的最大值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
};
相關文章
相關標籤/搜索