01.01. 判定字符是否唯一 (散列表,位运算)

题目:

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

示例1:

输入: s = "leetcode"
输出: false 

示例2:

输入: s = "abc"
输出: true

限制

  • 0 <= len(s) <= 100
  • 如果你不使用额外的数据结构,会很加分。

知识补充

1.试试散列表?

散列表(js数据结构)

哈希算法使用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

};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值