力扣算法ing(73 / 100)

5.17 哈希表合集—454.四数相加||

给你四个整数数组 nums1nums2nums3nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

  • 0 <= i, j, k, l < n
  • nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

示例 1:

输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2
解释:
两个元组如下:
1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0

示例 2:

输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1

提示:

  • n == nums1.length
  • n == nums2.length
  • n == nums3.length
  • n == nums4.length
  • 1 <= n <= 200
  • -228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228

我的思路:

四数相加:

[{} , {} ]

两数相加使用的是减法,四数应该也是

nums1[1] nums2[-2] num3[-1] nums4[0]

map里面存的是1,2的(值加次数):1,-1

循环遍历nums3,num4:-1 map:0,-1 map.length=0 return temp

但是这样的话,它怎么进行第二轮呢?第一轮就把map=0了

改变思路:

map:-1 0 0 1

如果想要nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

那么就需要num3+num4=

1或者0或者0或者-1

nums3+nums4 = -1 ans++ | 1 ans++ | 2 4

ans = 2

所以num1加num2放在map里面,遍历num3和num4求sum,map里面是否有-sum

我的代码:

function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
    let addMap :  Map = new Map();
    let ans : number  = 0;
    // 遍历num1,num2
    for(let i of nums1){
        for(let j of nums2){
            // 存储在map里面,如果map没有就新建一个,如果有的话键加一
            let sum = i + j ;
            // 有sum这个键
            if(addMap.has(sum)){
                // 得到对应的值(次数)
                addMap.set(sum , addMap.get(sum) + 1);
            }else {
                 addMap.set(sum ,  1);
            }
        }
    }
    // 遍历num3,num4
    for(let i of nums3){
        for(let j of nums4){
            let sum = - ( i + j )  ;
            // 如果说addMap里面存在-sum,就让它对应的次数-1
            if(addMap.has(sum)){
               ans ++;
            }
        }
    }
    return ans;
};

答案错误!!


nums1 =

[-1,-1]

nums2 =

[-1,1]

nums3 =

[-1,1]

nums4 =

[1,-1]

map:-2 0 -2 0

1+1+1 = 3

如果只是简单的ans++就会损失一部分的答案

-1+1 = 0 ans=2

-1+ -1 = -2 ans += 2 = 4

在进入map的时候我们应该是值加次数的形式,在ans加的时候应该加的是次数

修改代码:

function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
    let addMap :  Map = new Map();
    let ans : number  = 0;
    // 遍历num1,num2
    for(let i of nums1){
        for(let j of nums2){
            // 存储在map里面,如果map没有就新建一个,如果有的话键加一
            let sum = i + j ;
            // 有sum这个键
            if(addMap.has(sum)){
                // 得到对应的值(次数)
                addMap.set(sum , addMap.get(sum) + 1);
            }else {
                 addMap.set(sum ,  1);
            }
        }
    }
    // 遍历num3,num4
    for(let i of nums3){
        for(let j of nums4){
            let sum = - ( i + j )  ;
            // 如果说addMap里面存在-sum,就让它对应的次数-1
            if(addMap.has(sum)){
               ans += addMap.get(sum);
            }
        }
    }
    return ans;

    
};

总结:

四数相加就体现了map的好处,受到之前两数相加的启发,我选择了先计算前面两个数进入map,后遍历后两个数求和看看是否存在与map当中,如果存在我直接ans++,但是第一次提交的时候答案错误了,ans++代表的是map里面只有一个sum,但是有的时候可能会有多个,所以正确方法一个是将次数也要存起来,直接用ans加次数就可以了。

s(t[j])){
return false;
}else {
// 如果有相同的,我们直接把map里面的对应的次数减1,全部移除了就证明两个是相等的
map.set(t[j] , (map.get(t[j]) - 1 ))
// 如果值(出现次数为0),delete这个键
if(map.get(t[j]) === 0){
map.delete(t[j]);
}
}
}
return map.size === 0;
};


总结:这道题考的是对map的敏感度以及map的方法的使用,利用map记录下s字符以及出现的次数,遍历t字符,如果s字符里面有t的其中一个字符,值就要对应减一,当减到值为0的时候,就要消除键。如果最后map的长度等于0就是相等,不等于就是不相同

# 5.15 哈希表合集---349.两个数组的交集

给定两个数组 `nums1` 和 `nums2` ,返回 *它们的 交集* 。输出结果中的每个元素一定是 **唯一** 的。我们可以 **不考虑输出结果的顺序** 。

 

**示例 1:**

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]


**示例 2:**

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的


 我的思路:

返回交集
nums1 = [1,2,2,1], nums2 = [2,2]
map [{1 , 1} , { 2 , 2}]
map.has
解决问题:去重问题 =>set


我的代码:

function intersection(nums1: number[], nums2: number[]): number[] {
// 存储的set
let set = new Set();
let set2 = new Set();
let ans = [];
let i = 0 ;
// 遍历数组当set当中
for(let i = 0 ; i < nums1.length ; i++){
set.add(nums1[i]);
}
for(let i = 0 ; i < nums2.length ; i++){
set2.add(nums2[i]);
}
// 遍历set2判断set2的值set1是否有
set2.forEach((item) => {
if(set.has(item)){
ans[i] = item;
i++;
}
})
return ans;
};


虽然我的代码可以成功解答,但是从时间来看耗费的时长很大,而且耗费的空间也很大。

看了一下其他人的代码对我的代码进行了更新迭代:

ts语法+答案数组最开始为set后面转化为数组

let resSet : Set = new Set(nums1);//生成有nuns1的数字且不相同的set
let ansSet : Set = new Set();
for( let i of nums2){
if(resSet.has(i)){
ansSet.add(i);
}
}
return Array.from(ansSet);


注意!

ts声明的方式:

let resSet : Set = new Set(nums1);


转化为数组的方式:

Array.from(ansSet);


总结:本道题考的是对set的敏感度,我们知道set最大的优点就是不含重复的值,这对于本道题目有大大滴好处,先初始化一个对比set,后nums2是否在set中,在处理nums2进答案数组的时候,也是为了去重,我们事先将答案数组转化为set,后转化为数组的。

1. **new Set()** : 创建一个新的 Set 对象。
2. **add(value)** : 添加一个指定的值到 Set 对象中。
3. **delete(value)** : 从 Set 对象中删除一个指定的值。
4. **has(value)** : 判断 Set 对象中是否包含一个指定的值。
5. **clear()** : 清除 Set 对象中的所有元素。
6. **forEach(callback[, thisArg])** : 对 Set 对象中的每一个值应用一个回调函数。
7. **values() / keys()** : 返回一个新的迭代器对象,包含 Set 对象中的所有值(因为 Set 对象中的值是唯一的,所以 keys 和 values 返回的结果相同)。
8. **entries()** : 返回一个新的迭代器对象,包含 Set 对象中的所有成员的键值对数组。
9. **size** : 返回 Set 对象中的值的数量。


# 5.16 哈希表合集---202快乐数

编写一个算法来判断一个数 `n` 是不是快乐数。

**「快乐数」** 定义为:

- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 **无限循环** 但始终变不到 1。
- 如果这个过程 **结果为** 1,那么这个数就是快乐数。

如果 `n` 是 *快乐数* 就返回 `true` ;不是,则返回 `false` 。

 

**示例 1:**

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1


**示例 2:**

输入:n = 2
输出:false


n = 2 

sum = 4

sum = 16

sum = 1 + 36 = 37

sum = 9 + 49 = 58

sum = 25 + 64 = 89

sum = 64 + 81 = 145

sum = 1 + 14 + 25 = 40

sum = 16 + 0 = 16

与第二个sum相等了,一直循环->return false

所以map一直存存存,得到的数要与map里面的sum进行比较,如果map里面有sum就证明又要重新循环

这个时候直接返回false

我的思路:

先一直循环,将sum存入set当中,然后将sum的数重新平方后相加,如此循环。一直到出现原来的sum或者出现sum=1的时候为止

**出现的错误:**

它是一个数字,但是进行相加要把它拆分为数组:

 //    数字转化为字符并用split分割得到数组
let number  = n.toString().split('');;

数组里面就是字符串,一定在相乘的时候要转化为数字

for(let item of number){
sum += Number(item) * Number(item);
}


**我的代码:**

function isHappy(n: number): boolean {
const set = new Set();
let sum = n;
while(sum != 1){
sum = getSum(sum);
if(set.has(sum)){
return false;
}else {
set.add(sum);
}

}
return true;

};
function getSum( n : number ) : number {
// 数字转化为字符并用split分割得到数组
let number = n.toString().split(‘’);;
let sum = 0 ;
for(let item of number){
sum += Number(item) * Number(item);
}

return sum;

}


**总结:**

最开始拿到这道题,我一头雾水,无限暴力循环???一直没有1怎么办。然后我就开始遍历实例2,发现它一直没有1的原因其实是一直在循环,这便是一个很大的突破口,如果sum之前已经出现了,那么一定会一直循环,便是解题方法。

# 5.17 哈希表合集---454.四数相加||

给你四个整数数组 `nums1`、`nums2`、`nums3` 和 `nums4` ,数组长度都是 `n` ,请你计算有多少个元组 `(i, j, k, l)` 能满足:

- `0 <= i, j, k, l < n`
- `nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0`

**示例 1:**

输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2
解释:
两个元组如下:

  1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
  2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0

**示例 2:**

输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1


 

  **提示:**

- `n == nums1.length`
- `n == nums2.length`
- `n == nums3.length`
- `n == nums4.length`
- `1 <= n <= 200`
- `-228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228`

**我的思路:**

四数相加:

[{} , {} ]

两数相加使用的是减法,四数应该也是

nums1[1] nums2[-2] num3[-1] nums4[0]

map里面存的是1,2的(值加次数):1,-1

循环遍历nums3,num4:-1 map:0,-1 map.length=0 return temp

但是这样的话,它怎么进行第二轮呢?第一轮就把map=0了

**改变思路:**

map:-1 0 0 1

如果想要nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

那么就需要num3+num4=

1或者0或者0或者-1

nums3+nums4 = -1 ans++ | 1 ans++ | 2 4 

ans = 2

所以num1加num2放在map里面,遍历num3和num4求sum,map里面是否有-sum

**我的代码:**

function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
let addMap : Map = new Map();
let ans : number = 0;
// 遍历num1,num2
for(let i of nums1){
for(let j of nums2){
// 存储在map里面,如果map没有就新建一个,如果有的话键加一
let sum = i + j ;
// 有sum这个键
if(addMap.has(sum)){
// 得到对应的值(次数)
addMap.set(sum , addMap.get(sum) + 1);
}else {
addMap.set(sum , 1);
}
}
}
// 遍历num3,num4
for(let i of nums3){
for(let j of nums4){
let sum = - ( i + j ) ;
// 如果说addMap里面存在-sum,就让它对应的次数-1
if(addMap.has(sum)){
ans ++;
}
}
}
return ans;
};


**答案错误!!**

nums1 =

[-1,-1]

nums2 =

[-1,1]

nums3 =

[-1,1]

nums4 =

[1,-1]

map:-2 0 -2 0

1+1+1 = 3

如果只是简单的ans++就会损失一部分的答案

-1+1 = 0 ans=2

-1+ -1 = -2 ans += 2 = 4

在进入map的时候我们应该是值加次数的形式,在ans加的时候应该加的是次数


**修改代码:**

function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
let addMap : Map = new Map();
let ans : number = 0;
// 遍历num1,num2
for(let i of nums1){
for(let j of nums2){
// 存储在map里面,如果map没有就新建一个,如果有的话键加一
let sum = i + j ;
// 有sum这个键
if(addMap.has(sum)){
// 得到对应的值(次数)
addMap.set(sum , addMap.get(sum) + 1);
}else {
addMap.set(sum , 1);
}
}
}
// 遍历num3,num4
for(let i of nums3){
for(let j of nums4){
let sum = - ( i + j ) ;
// 如果说addMap里面存在-sum,就让它对应的次数-1
if(addMap.has(sum)){
ans += addMap.get(sum);
}
}
}
return ans;

};


**总结:**

四数相加就体现了map的好处,受到之前两数相加的启发,我选择了先计算前面两个数进入map,后遍历后两个数求和看看是否存在与map当中,如果存在我直接ans++,但是第一次提交的时候答案错误了,ans++代表的是map里面只有一个sum,但是有的时候可能会有多个,所以正确方法一个是将次数也要存起来,直接用ans加次数就可以了。

你可能感兴趣的:(小白学习算法,算法,leetcode,职场和发展)