判定字符是否唯一

题目:实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例1:
输入: s = "leetcode"
输出: false

示例2:
输入: s = "abc"
输出: true

解决方法:

  • 暴力解决(双重循环)
  • Set(ES6新增)
  • 散列思想
  • 位运算

具体实现:

1.暴力解决(双重循环)


2.Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构。

思路:比较去重后的字符串长度和初始字符串的长度是否相等

代码实现:

  function isUnique(astr) {
      return new Set(astr).size === astr.length
  }

注解:Set数组去重:

    const arr = ['a', 'b', 'c', 'b', 'd', 'a']
    // 方法一:...将一个数组转为用逗号分隔的参数序列
    const unique = [...new Set(arr)]  // ['a','b','c','d']
    // 方法二:Array.from 方法可以将 Set 结构转为数组
    const unique = Array.from(new Set(arr)) // ['a','b','c','d']

3.散列思想

思路:定义一个对象用来存储当前遍历的值,若值存在则说明有重复,返回false,没有则把当前值置1。

代码实现:

  function isUnique(astr) {
    let obj = {}
    for (let i of astr) {
      if (obj[i]) {
            return false
      } else {
          obj[i] = 1
      }
  }
    return true
  }

4.位运算

思路:假设有一个全为0的数mark:000000…000,共26位,每一位代表一个字母

0 0 0 0 0 0 0 … 0 0 0

z y x w v u t… c b a

当前位置为0,代表没出现过这个字母;如果为1,代表出现过这个字母。

// 每一个位置代表一个字母,如:
000000...0001 代表有字母a,没有其它字母
000000...0011 代表有字母a和b,没有其它字母
100000...0111 代表有字母a、b、c和z,没有其他字母

当我们遍历字符串'abcbda'时,如果之前没出现过当前字符,则把00000...0000对应位置设置为1,出现过返回false

实现步骤:
1.遍历把字符串中每个字符转化为一个二进制数
2.计算这个字符距离'a'即97('a'.charCodeAt() = 97)的距离,这个距离代表我们要位移的距离,用move_bit表示

例如:
char = 'a', 和'a'的距离为0, 位移0位
char = 'b', 和'a'的距离为1, 位移1位
3.再使用左移运算符 1 << move_bit
例如:
char = 'a', 位移0位,1 << 0,得到 000000...0001
char = 'b', 位移1位,1 << 1,得到 000000...0010

4.做与运算,比如:'a':000000...0001与'b':000000...0010结果为0;若有重复,比如'a':000000...0001与'a':a000000...0001结果为1,返回false

代码实现:

  function isUnique(astr) {
    var mark = 0
    for(var char of astr) {
      var move_bit = char.charCodeAt() - 97
      if ((mark & (1 << move_bit)) !== 0) {
        return false
      }
      mark = mark | (1 << move_bit)
    }
    return true
  }

参考:
作者:h-jia-jun
链接:https://leetcode-cn.com/problems/is-unique-lcci/solution/yi-ti-duo-jie-by-h-jia-jun-kw69/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(判定字符是否唯一)