Set集合操作
ES6新加Set集合:无序且唯一
// 数组去重:先放入Set集合中去重,再解构回数组中
let arr = [1, 1, 2, 3, 3]
let set1 = new Set(arr) // 无序且唯一
let arr1 = [...set1] // 再将Set展开放回数组中
console.log(arr1)
// 判断是否在集合中:Set.has()
let set2 = new Set(arr)
let has = set2.has(5)
console.log(has)
// 求交集:利用数组的filter()遍历一个,判断另外一个里有没有它
let arr3 = [3, 4]
let set3 = new Set(arr3); // 求set1与set3的交集
let set4 = new Set([...set1].filter(item => set3.has(item)))
console.log(set4)
// 添加add 删除delete 判断是否包含has
let mySet = new Set()
mySet.add(1) // add向Set中添加元素
mySet.add(5)
mySet.add(5)
// 添加重复元素会自动去掉,map元素:1, 5
mySet.add('lsy')
// 可以添加字符串
let obj = { a: 1 }
mySet.add(obj)
mySet.add({ a: 1 }) // 地址不同,成功添加
// 对于对象是判断对象在内存的地址来判断是否是同一个
let has = mySet.has(obj)
// has()快速判断是否包含元素
mySet.delete(5)
// delete()删除元素
// 遍历Set:for..of..直接迭代Set、Set.keys()、Set.values()结果都一样:Set的key和value一样
for (let item of mySet) console.log(item) // 直接迭代
for (let item of mySet.keys()) console.log(item) // 遍历keys
for (let item of mySet.values()) console.log(item) // 遍历values
for (let [key, value] of mySet.entries()) console.log([key, value]) // entries()遍历[keys, values]
// Set 和 数组互转
let myArr = [...mySet] // Set解构到数组
let myArr1 = Array.from(mySet) // Array.from转为数组
let mySet1 = new Set([1, 2]) // 数组转为Set
// 求交集 同时在两个集合中
let jiaoji = new Set([...mySet].filter(item => mySet1.has(item)))
// 求差集 一个集合中有,另一个没有
let chaji = new Set([...mySet].filter(item => !mySet1.has(item)))
new Set()创建一个 Set 对象
add()添加元素delete()删除元素has()判断 Set 中是否包含- 遍历 Set(
for..of..)- 直接遍历
Set - 遍历
Set.keys() - 遍历
Set.values() Set.entries(),获取[key, value]k-v值相同
- 直接遍历
- Set 和 数组互转:
[...Set]解构到数组、Array.from(Set)转为数组new Set([1, 2])数组转为Set
- 求交集:
let jiaoji = new Set([...Set1].filter(item => Set2.has(item))) - 求并集:
let chaji = new Set([...Set1].filter(item => !Set2.has(item)))
Map字典操作
// 键值对的一一映射
const m = new Map()
// 添加键值对:set
m.set('a', 'aa')
m.set('b', 'bb')
// 查:get
let v = m.get('b')
// 改
m.set('a', 'new aa') // 重新赋值
// 删除键值对:delete
m.delete('b') // 键值
m.clear() //删除所有元素
set()添加,重新set()赋值:修改get()查:获取delete(k)删除、clear()删除全部
基础知识
- 用来快速判断元素是否出现集合内
- 哈希函数,把值映射为哈希表的索引
- 哈希碰撞,映射到同一个索引时
- 拉链法
- 线性探测:表的大小 > 数据总大小,多的放到冲突的下一个
- 常见的三种哈希结构
- 数组
- set(集合)
- map(映射)
哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法 面试题目中,需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!
242.有效的字母异位词
242. 有效的字母异位词 两个字符串,字母出现的次数相同√,不同就×
数组哈希表映射
技巧,先遍历
s数组,记录到函数中++,再遍历t数组,函数值--,如果函数值还全为0,就说明全相等
用数组映射
- 字母的ASCII码映射到数组下标
'字符串'.chatCodeAt()获取ASCII码映for of循环遍历获取元素- 技巧:遍历第一个时数组对应位置
+1,第二个时-1,如果最后全为0说明相同
返回字符串给定index索引的 UTF-16 码 默认index为0 超出长度返回NaN
"ABC".charCodeAt(0) // returns 65:"A"
"ABC".charCodeAt(1) // returns 66:"B"
"ABC".charCodeAt(2) // returns 67:"C"
"ABC".charCodeAt(3) // returns NaN
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isAnagram = function(s, t) { // 判断两个字符串出现的字母次数相同
let hash = new Array(26).fill(0) // 数组=>哈希表:映射为26个字母数组
let base = 'a'.charCodeAt() // 得到a的ASCII码,charCodeAt()获取ASCII码
for (let i of s) { // for of遍历字符串,直接得到元素
hash[i.charCodeAt() - base]++
}
for (let i of t) { // let有块级作用域所以可以重复用i
hash[i.charCodeAt() - base]--
}
for (let i of hash) { // 遍历最后得到的数组
if (i !== 0) return false // 有不为0的直接false
}
return true
};
349. 两个数组的交集
用Set存
- 把
nums1指向大的那个,放到Set里可以少遍历元素 - 遍历
nums2用Set.has()快速判断元素是也在Set里,如果在就加入新Set - 将最后新
Set再转为数组
- 技巧:
数组.filter()直接会遍历每个元素,执行回调函数,将过滤后(return返回值为true)的元素放到一个新数组中返回
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function(nums1, nums2) {
if (nums1.length < nums2.length) {
let temp = nums1
nums1 = nums2
nums2 = temp
} // 把nums1指向大的那个,放到Set里可以少遍历元素
let set = new Set(nums1)
let arr = new Array(0) // 数组存结果
for (let i = 0; i < nums2.length; i++) {
if (set.has(nums2[i])) { // 如果在set集合中就加入result集合
arr.push(nums2[i])
}
}
let res = new Set(arr)
return Array.from(res) // 把集合转为数组Array.from
};
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function(nums1, nums2) {
if (nums1.length > nums2.length) {
let temp = nums1
nums1 = nums2
nums2 = temp
}
let set = new Set(nums1);
return [...new Set(nums2.filter(item => set.has(item)))]
};
202.快乐数
202. 快乐数 用每个位置上数字的平方和替换这个数,如果最后为1,则为快乐数,如果无限循环就不是
- **无限循环:**计算出的
sum值和之前已经算过的一样-->会进入循环 - 把每次计算的
sum值都存入set集合- 如果集合中已经有这个数,说明会死循环!false
- 如果没有这个数
**sum==1**:为快乐数,true- 不为1:加入
**set集合**
- 想到用哈希表:可以快速找集合里面是不是已经有
这个sum值
用Set存
/**
* @param {number} n
* @return {boolean}
*/
function getSum (n) {
let sum = 0
while (n) {
let x = n % 10 // 取数
sum += x * x
n = Math.floor(n / 10) // 去掉已经取的
}
return sum
}
var isHappy = function(n) { // 用Set求,如果sum值出现过就说明会无限循环
let sum = getSum(n)
let set = new Set()
while (sum !== 1) { // 不是快乐数,就重复操作
if (set.has(sum)) {
return false // 如果sum值出现过就说明会无限循环=不是快乐数
} else {
set.add(sum) // 加入集合,再更新sum
sum = getSum(sum)
}
} // 出循环=1是快乐数
return true
};