01.01. 判定字符是否唯一
题目:
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
示例1:
输入: s = "leetcode"
输出: false
示例2:
输入: s = "abc"
输出: true
限制
0 <= len(s) <= 100
- 如果你不使用额外的数据结构,会很加分。
知识补充
1.试试散列表?
哈希算法使用31,因为它是一个很好的素数,可以有效的提高效率
reduce()函数
- reduce()函数可以接受4个参数:上一个归并值,当前项,当前项的索引和数组本身。这函数返回的任何值都会作为下一次调用同一个函数的第一个参数。如果没有给这个方法传入可选的第二个参数(作为归并的起点值),则第一次迭代将从数组的第二项开始,因此传给归并函数的第一个参数是数组的第一项,第二个参数是数组的第二项。
- 与reduce()函数对应的还有reduceRight()函数。两者归并的方向不同。reduce()可以用来对数组进行求和。
字符串转为数组
[…string]
for(let item of string){}
代码
/**
* @param {string} astr
* @return {boolean}
*/
var isUnique = function(astr) {
const M = 26;
let slots = new Array(M);
let sum = 0;
let hash = 0;
//上面超链接这里使用的是reduce(),但是这里完全没有必要,简简单单遍历数组即可
for(item of astr){
hash = (31*hash + item.charCodeAt(0))% M; //这里使用的是31,为了更好的性能(其实根本没有必要,这里是为了符合散列表)
if(slots[hash])
{
sum ++;
}
slots[hash]=1;
hash = 0; //可以吧上面的31*hash 删除 ,然后删除这一行
}
return !sum
};
改进:
/**
* @param {string} astr
* @return {boolean}
*/
var isUnique = function(astr) {
//这里是借鉴的别人的方法,和上面的方法有着相同的思想,但是形式更加简单
let obj = {}
for (let item of astr) {
if (obj[item]) {
return false
} else {
obj[item] = 1
}
}
return true
};
2.位向量有用吗?
位向量肯定是有用的。位向量指的是将文字转换为二进制代码,也就是01010的形式,然后进行位运算。
举例 [3, 0, 3] 判断数组有重复元素
-
利用左移运算 1 << 3 是 8 转换二进制 是 ‘1000’
-
当遍历到0时,进行左移运算, 1 << 0 是 1 转换二进制 是 ‘0001’
-
每次都与上一次结果进行或运算,8 | 1 是 9 转换二进制 是 ‘1001’, 这时可以看到我们用二进制中的位数是1来代表出现过。
-
那如何快速判断是否出现过呢,可以采用与运算(位数都是1才会是1)的特性。
-
如果之前没有出现过,那二进制中位数为1的位置对应不上,最后结果应该是0。 例如:9 & (1 << 3)会等于8,说明倒数第四位数,也就是 3重复了。
-
我们将字母计算出左移的长度,即可像上述操作一样,检测是否只出现一次。
/**
* @param {string} astr
* @return {boolean}
*/
var isUnique = function(astr) {
let check = 0;
let i = 0;
for(item of astr){
i = item.charCodeAt(0) - 97; //这里减去的97,指的是a.charCodeAt(0)
if((check & (1 << i)) !== 0){
return false;
}
check = check | 1<<i
}
return true
};
3.其他方法
map数组的键的唯一性
set数组的唯一性
/**
* @param {string} astr
* @return {boolean}
*/
var isUnique = function(astr) {
//1.map数组
let map = new Map();
for(item of astr){
map.set(item,1)
}
return map.size === astr.length
//2.set数组
var strArr = astr.split('');
var newStrArr = new Set(strArr);
//if (strArr.length - newStrArr.size > 0) {
// return false;
//} else {
// return true;
//}
return strArr.length = newStrArr.size
};