前端从零开始刷leetCode-持续更新

1,091 阅读4分钟

场景

  • 很多人会说刷题是为了面试这是结果导向型的没毛病。
  • 更多时候我们要明白为什么要考算法,核心考点是什么?
  • 我自己作为面试官考算法有哪些考核点
  1. 对应异常情况以及边界值的考虑
  2. 算法的执行效率,算法之所以称之为算法,就是一种之前高效执行程序的总结
  3. 发散性创造性不拘泥现在,对事情有更多创造性的想法
  4. 最重要的一点先解决这个问题,再去想优化解决,不管工作和生活都是一定程度的结果导向,先解决眼前的问题,后面再优化一定是在这个阶段最好的方式,而不是上来就放弃!!!
  • 这些品质在开发过程中,都是难能可贵的,对应一个需求开发,一个架构设计都需要这些底层的品质与思维方式

前端有必要学习吗?

  • 首先场景上是有可能的,之前自己就做过一个需求:最大匹配度的场景,其实抽象到最后就是一个最大共有字符串的这样算法。
  • 如果是多端的场景还是服务端实现会更合适一点
  • 学海无涯,持续学习是开发者,也是人生最重要一件事情,拥抱变化,畅想未来。

方法论及算法索引

言归正传

zhuangb.jpeg

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target请,你在该数组中找出和为目标值 target的那两个整数并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。

示例

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

解题思路一:两层循环求和跟目标值比较,显然不够高效,复杂度为O(n2)O(n^2)

  1. 代码如下
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
     for(let i = 0 ; i<nums.length;i++){
         let child1 = nums[i];
         for(let k = i+1 ; k<nums.length;k++){
         let child2 = nums[k];
            if(child1+child2 === target){
                return [i,k]
            }
        }

     }
     return []
};
  1. 执行结果:执行用时: 132 ms;内存消耗: 38.6 MB

  2. 图解

两层循环 (3).png

解题思路二:一次循环缓,存有效数据,比较差值,效果更佳

  1. 思路 其实我们都清楚,一次循环的时候,我们知道当前的索引值,以及当前值,目标值减去当前值是不是在我们之前缓存的数据当中,如果不在就把当前值缓存

  2. 代码如下

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    var map = {};
    for (let i = 0; i < nums.length; i++) {
      var child1 = nums[i];
      var key = target - child1;
      if (map[key] !== undefined) {
        return [map[key], i];
      }
      map[child1] = i;
    }
    return [];
};
  1. 执行结果: 执行用时: 80 ms;内存消耗: 39.6 MB

  2. 图解

一层循环.png

3. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。

示例

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3

解题思路一:两层循环求,第一层循环字符串与第二次字符串拼接,第二层判断字符串是否已经包含在之前的拼接数据中,比较每个不重复字符串的长度,复杂度为O(n2)O(n^2)

  1. 代码如下
/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
 if(s.length ==0){
     return 0
 }else{
     var array = s.split("")
     var num = 0
     if(array.length == 1){
         return 1
     }
     for(let i=0;i<array.length;i++){
        var map = array[i]
        var cn = 1
        for(let k=i+1;k<array.length;k++){
            var child1 = array[k]
            if(!map.includes(child1)){
                map = map+child1
                cn++
            }else{
                break;
            }
        }
        num = num > cn?num:cn
     }
     return num
 }
};
  1. 执行结果:执行用时: 352 ms;内存消耗: 44.2 MB

  2. 图解

两层循环 (4).png

解题思路二:一层循环,字符串拼接,进入缓存,发现后面字符串已经在前面拼接中出现,截取出前面已经出现的字符串位置后面的字符串,加上当前的字符串,更新缓存字符串,继续循环,这样效率更高。

  1. 代码如下
/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function (s) {
    if (s.length == 0) {
      return 0;
    } else {
      var array = s.split("");
      var num = 0;
      var cn = 0;
      var map = "";
      for (let i = 0; i < array.length; i++) {
        var str = array[i];
        if (!map.includes(str)) {
          map = map + str;
          cn++;
        } else {
          var index = map.indexOf(str);
          map = map.substring(index + 1) + str;
          cn = map.length;
        }
        num = num > cn ? num : cn;
      }
      return num;
    }
};
  1. 执行结果:执行用时: 128 ms;内存消耗: 43.7 MB

  2. 图解

公用字符串一层循环 (1).png

总结

  • 持续学习,每天都要有驱动力,不能间歇性踌躇满志,持续性坐吃等死!
  • 算法小程序加入动画模式是自己的todo
  • 35岁之后学习分享不失为我人生一个选择的方向