代码随想录算法训练营第六天 | 242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

73 阅读3分钟

242.有效的字母异位词

文章链接

第一想法

题目要求需要判断两个字符串中各个字母出现的次数是否相同。所以想到了map,set无法判断出现的此时,所以用map,代码如下:

function isAnagram(s: string, t: string): boolean {
 let map=new Map()
 if(s.length!=t.length) return false //如果长度不同直接返回false
 for(let i=0;i<s.length;i++){ //存储第一个字符串
   if(map.has(s[i])){
      map.set(s[i],map.get(s[i])+1)
   }else{
      map.set(s[i],1)
   }
 }
 for(let i=0;i<t.length;i++){
     if(!map.has(t[i])) return false //map中没有t[i],则返回false
     let num=map.get(t[i])
     num-=1
     if(num<0) return false
     map.set(t[i],num)
 }
 return true
};

看完文章后的想法

很简单,感觉用牛刀斩小鸡,直接用数组就行了,话不多说,上代码!

function isAnagram(s: string, t: string): boolean {
   let arr:number[]=new Array(26).fill(0)
   for(let i=0;i<s.length;i++){
       arr[s[i].charCodeAt(0)-'a'.charCodeAt(0)]++
   }
   for(let i=0;i<t.length;i++){
       arr[t[i].charCodeAt(0)-'a'.charCodeAt(0)]--
   }
   if(arr.every(item=>item==0)) return true
   return false
};

思考

接触哈希表后,一定要分清什么情况用什么,这道题用数组就行,我用了map,也能做出来,但是感觉有点浪费了。推荐代码随想录中的哈希表的基础讲解,看完后一定有不同的感触

349. 两个数组的交集

文章链接

第一想法

这道题由例子可知,即使相同的数字重复多次输出结果也只为一次,所以一定时间想到了用set,代码如下:

function intersection(nums1: number[], nums2: number[]): number[] {
 let set=new Set()
 let res=new Set()
 for(let i=0;i<nums1.length;i++){
     set.add(nums1[i])
 }
 for(let i=0;i<nums2.length;i++){
     if(set.has(nums2[i])) res.add(nums2[i])
 }
 return Array.from(res) as number[]
};

看完文章后的想法

看完之后,才发现我对set的方法以及使用不是很了解,可以直接通过new Set(数组)来直接创建set,不用我上面写的代码的第一个for循环,代码如下:

function intersection(nums1: number[], nums2: number[]): number[] {
  let set=new Set(nums1) //第一个for循环由这个代码就可以解决
  let res=new Set()
  for(let i=0;i<nums2.length;i++){
      if(set.has(nums2[i])) res.add(nums2[i])
  }
  return Array.from(res) as number[]
};

还有一种骚操作,这里很考验对js方法的理解程度,上代码:

function intersection(nums1: number[], nums2: number[]): number[] {
//先通过filter查找两个数组相同的元素,通过new Set去重,最后在转变为数组
  return Array.from(new Set(nums1.filter(item=>nums2.includes(item))))
};

思考

对于骚操作的写法确实牛逼,同时也让我明白了要多理解set,map以及数组。同时要熟悉这些方法,这样代码才能写好。推荐在MDN中看set,map的方法以及一些使用.这道题不太难。

202. 快乐数

文章推荐

第一想法

文章有个很重要的限制条件,我感觉没有这个限制条件的话可能不就是easy题了,题目说明了根据规则要不就是无限循环,要不就是最终等于1,所以知道了无限循环,就知道一个判断条件,如果他之前出现过,就肯定不是快乐数,判断一个数是否出现,所以用set,代码如下:

function isHappy(n: number): boolean {
    let set=new Set()
    let num=n+''
    while(true){//进行循环判断
        if(set.has(num)) return false //如果是循环出现,则一定不是快乐数,返回false
        set.add(num)//存储每一步得到的结果
        if(num=="1") return true
        let n=0
        for(let i=0;i<num.length;i++){
           n+=(num[i] as any as number)**2
        }
        num=n+""
    }
}

看完文章后的想法

总体想法和自己刚开始的想法是一样的,就是代码写法不太一样,代码如下:

function isHappy(n: number): boolean {
    let set=new Set()
    let num=n+""
    const foo=(num:string)=>{
        let n=0
        for(let i=0;i<num.length;i++){
           n+=(num[i] as any as number)**2
        }
        return n+""
    }
    while(num!="1"&&!set.has(num)){
       set.add(num)
       num=foo(num)
    }
    return num=="1"
};

思考

这道题也是不难的,只要把题目中的无限循环搞清楚就可以了。如果把无限循环这个条件去掉,则难度绝不会是easy了。

1. 两数之和

文章链接

第一想法

第一想到的数组,因为数组有个indexOf的方法,所以尝试了一下:

function twoSum(nums: number[], target: number): number[] {
        for(let i=0;i<nums.length;i++){
            let index=nums.lastIndexOf(target-nums[i])//这里用lastIndexOf是防止nums=[3,3],target=6这种情况时,返回[0,0]的情况
            if(index!=-1&&index!=i) return [i,index]
        }
};

发现能通过,完美!一看结果,再一看消耗时间,好家伙,252 ms,忒慢了。决定看文章

看完文章后的想法

没想到,确实没想到,可以用map,而且我之前的写法用了for和lastIndexOf(),时间复杂度应该挺高的,不说了直接上代码:

function twoSum(nums: number[], target: number): number[] {
   let map=new Map()
   for(let i=0;i<nums.length;i++){
       if(map.has(target-nums[i])) return [map.get(target-nums[i]),i]
       map.set(nums[i],i)
   }
};

代码思路是在for循环中寻找是否有等于target-nums[i]的数字,循环过的变量就用map存储起来,方便查找。

思考

这道题不难,对于要频繁查询的题要首先想到用哈希表来计算,这道题就是没想到这层含义,有点可惜。

今日总结

代码时间2.30个小时,今天比较忙,就不写那么多了。