位右移 字母大小寫全排列

pardon110發表於2020-12-11

本文介紹了go在字元方面的一些處理技巧,比如使用位元組32異或實現大小寫轉換,以及二進位制狀態序列

題面

給定一個字串S,通過將字串S中的每個字母轉變大小寫,我們可以獲得一個新的字串。返回所有可能得到的字串集合。

示例:

輸入:S = "a1b2"
輸出:["a1b2", "a1B2", "A1b2", "A1B2"]

S 的長度不超過12。
S 僅由數字和字母組成。

來源:力扣(LeetCode)
連結:leetcode-cn.com/problems/letter-ca...

分析

  • 序列每個字元位置不發生變換,只是字母大小有改變
  • 字母大小寫轉換前後兩個狀態,可以用二進位制數0與1表示
  • 假定初始串 abca 表示為 0000二進位制狀態數,那麼 0100則表示串 aBca
  • 換而言之,可用二進位制數 0 - 1111表示 abca 所有字母大小寫轉換全排列

位運算

func letterCasePermutation(S string) []string {
    N := len(S)
    rs := []string{S}

    // 字母轉換後的狀態表
    m := make(map[int]byte,0)
    // 提取字母大小寫轉化後的1值狀態表
    for i:=0;i< N;i++ {
        if num := int(S[i] - '0'); num > 9 {
            m[i]= translate(S[i]) // 或 S[i]^32
        }
    }

    // 字母大小寫轉換全排列 產生的個數(如二進位制數 0 至 111 產生2的3次冪全排列數)
    binary := int(math.Pow(2,float64(len(m))))

    for k:=1;k < binary;k++ {
        s := []byte(S)  // 維護大小寫轉換前狀態
        for i,j:=N-1,k;i>=0;i-- {
            if v, ok := m[i];ok {
                if j % 2 != 0 { // 狀態1轉換大小,狀態0不轉
                    s[i] = v 
                }
                j>>=1  // 右移,以便下次獲取低位值
                if j == 0 {
                    break  // 已至最高位跳出
                }
            }
        }
        rs = append(rs, string(s))
    }
    return rs
}

大小寫轉換

  • 查表可知字母a 97, A 65, 空格 32
  • byte 實際是 uint 型別的別名,因此可進行運算
    func translate(b byte) byte {
      if b >= 'a' {
          return b - ' '
      }
      return  b + ' '
    }
    其實,還有一個裝逼方法, 將大小寫字母與 32 進行異或運算,如下
    a := uint(97)
    A := uint(65)
    fmt.Println(string(a),string(A),string(a^32),string(A^32))
    // 輸出 a A A a
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章