题目:实现一个算法,确定一个字符串 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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。