算法逻辑题整理-中级(1)

中级算法中,多循环解题思路多数优化会应用到指针算法,经典就是双指针(vue的diff也采用了双指针对比),注意中级算法题禁止双for无优化处理-经不住测试用例方案
算法逻辑题整理-初级(1)
1.最长回文子串

// 这里用了双for,因为我目前没发现其他方案,指针当然不适合
回文就是一段字符正与反时他们都一样,如abcba 
var longestPalindrome = function (s) {
    let num = s.length;
    if (num <= 1) return s;
    let maxStr = "";
    for (let i = 0; i < num; i++) {
        for (let j = 1; j < num; j++) {
            let str = s.substring(i, j + 1);
            let ceArr = str.split("").reverse().join("");
            if (ceArr === str && str.length > maxStr.length) {
                maxStr = str;
            }
        }
    }
    return maxStr == "" ? "" : maxStr;
};
// 后期出新解决方案

2.给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
在这里插入图片描述
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

根据解析循环+双指针
[1,8,6,2,5,4,8,3,7]左右各取出元素计算面积,然后再对比两个元素哪个小,
左边1小那么左指针向中间移动一位,右指针不动,依次循环计算并移动指针
var maxArea = function (height) {
      let num = height.length;
      let sum = 0; // 最大面积
      let end = num - 1; // 右指针
      let start = 0; // 左指针
      for (let i = 0; i < num; i++) {
        let H = height[start] > height[end] ? height[end] : height[start]; // 容器高度当然以小的一方为准才能装水,取出高
        let S = H * Math.abs(end - start); // 这里直接取到宽计算面积
        sum = sum > S ? sum : S; //保留最大面积
        // 判定移动指针
        if (height[start] > height[end]) {
          end--;
        } else {
          start++;
        }
      }
      return sum;
    };

3.给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
// 这道题我也是错了好多次才写出,主要应用技术点,循环,双指针,去重,进行层次化处理过滤
var threeSum = function (nums) {
      // 数组排序这步非常重要,将会作用在去重上
      nums = nums.sort((a, b) => {
        return a - b;
      });
      let num = nums.length;
      let arr = [];//接收结果值
      if (num < 3 || nums[0] > 0) return [];//不满足题目条件的数组直接返回空数组,避免不必要/错误计算
      for (let a = 0; a < num; a++) {
        if (nums[a] > 0) return arr;//这体现了排序的作用,如果最小的数都大于0就没必要计算了
        if (a > 0 && nums[a] == nums[a - 1]) continue;// 循环中去除外循环第一参数重复值
        let b = a + 1;//左指针
        let c = num - 1;//右指针
        while (b < c) {//二级循环作用到指针移动这里注意使用的while更为合适,
          let sum = nums[a] + nums[b] + nums[c];// 计算和
          // 得出结果将对值进行(=,<,>)3种可能进行处理
          if (sum == 0) {
            let newarr = [nums[a], nums[b], nums[c]];
            arr.push(newarr);
            // 此次循环拿到合适的值必定移动左右指针,为了去重因此使用do while的特性,跳过重复的元素
            do {
              b++;
            } while (b < c && nums[b] == nums[b - 1]);
            do {
              c--;
            } while (b < c && nums[c] == nums[c + 1]);
          } else if (sum > 0) {
          // 和值大于0右指针是大到小,移动一次减小值再进入while循环
            c--;
          } else {
          // 和值小于0左指针是小到大,移动一次增加值再进入while循环
            b++;
          }
        }
      }
      return arr;
    };

4.给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
//这道题与第三题解法类似,但要注意细节
var threeSumClosest = function (nums, target) {
      // 数组排序这步非常重要,将会作用在去重上
      nums = nums.sort((a, b) => {
        return a - b;
      });
      let num = nums.length;
      let result = 0;// 结果值
      let diff = 0; // 结果值与目标值的差异
      for (let a = 0; a < num; a++) {
        if (a > 0 && nums[a] == nums[a - 1]) continue; // 循环中去除外循环第一参数重复值
        let b = a + 1; //左指针
        let c = num - 1; //右指针
        while (b < c) {
          //二级循环作用到指针移动这里注意使用的while更为合适
          let sum = nums[a] + nums[b] + nums[c]; // 计算和
          let news = Math.abs(sum - target); // 计算当前sum与目标的差异
          if (sum == target) {
            return sum;
          }  else if ((a == 0 && b == 1 && c == num - 1) || news < diff) {
          //第一次循环与比上次更符合目标值的结果都将获取
            diff = news;
            result = sum;
          }
          // 根据和值与目标值的差异情况移动指针
          if (b < c && sum < target) {
            b++;
          } else {
            c--;
          }
        }
      }
      return result;
    };

5.电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

var letterCombinations = function (digits) {
    if (!digits) {
        return [];
    }
    const strMap = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"];//空格占位用,校准2-9
    let result = [""]; //初始化一个空字符,作为中间储存值
    for (let num of digits) {
        //遍历输入的数字
        let nextResult = [];
        let str = strMap[num]; //找到数字可能对应的字符
        for (let t of result) {
            //遍历上一循环生成的字符串列表
            for (let s of str) {
                //遍历当前数字可能对应的字符
                nextResult.push(t + s); //拼接字符串
            }
        }
        result = nextResult; //替换原字符串列表
    }
    return result;
};

6.四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

待定,空时间完成
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值