专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

高级前端进阶,这几道算法题你会吗?

ins518 2024-09-29 18:29:56 技术文章 17 ℃ 0 评论

前言:

最近在乐扣做了几道算法题,整理了一下分享出来。

题目1:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解法1:

暴力循环

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    for(let i=0;i<nums.length;i++){
        for(let j=i+1;j<nums.length;j++){
            if(nums[i]+nums[j] == target){
                return [i,j]
            }
        }
    }
};

解法2:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let index = nums.length-1;
    while (index > 0) {
        //假定当前循环数组末尾的值为我们所要找的值
        //每次循环时从数组末尾拿出一个值,与目标值相减,所得的值在数组中查找
        //如果能找到,则返回,如果找不到,继续循环
        let firstIndex = nums.indexOf(target - nums.pop());
        if (firstIndex > -1) {
        return [firstIndex,index]
        }
        index--;
    }
};

题目2:

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储一位数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解法

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
    let res = new ListNode();
    //是否进一位
    let s = 0;
    //中转对象,临时存储
    let resTemp = res;
    while(l1 || l2 || !!s ){
        //计算l1/l2的和
        let sum = s + ~~(l1&&l1.val) + ~~(l2&&l2.val);
        //每一位只能储存一位,所以需要判断一下
        let val = (sum>9) ? (sum-10) : sum;
        resTemp.next = new ListNode(val);
        resTemp = resTemp.next;  
        l1 = l1&&l1.next;
        l2 = l2&&l2.next;
        //如果和大于9则记录一下,等下次循环加进去
        if(sum>9){
            s = 1;
        }else{
            s = 0;
        }
    }
    return res.next
};

题目3:

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

示例:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

解法1:

暴力循环

var threeSumClosest = function (nums, target) {
  //设置个默认值  
  let min = nums[0] + nums[1] + nums[2];
  //一层循环
  for (let i = 0; i < nums.length; i++) {
    //二层循环  
    for (let j = i + 1; j < nums.length; j++) {
      //三层循环  
      for (let k = j + 1; k < nums.length; k++) {
        //对比是否比默认值接近  
        if (Math.abs(nums[i] + nums[j] + nums[k] - target) < Math.abs(min - target)) {
          //替换默认值
          min = nums[i] + nums[j] + nums[k];
        }
      }
    }
  }
  return min
};

解法2:

排序后使用循环加头尾双指针

var threeSumClosest = function (nums, target) {
  //从小到大的顺序排序,为接下来头尾指针做准备  
  nums.sort((a, b) => a - b)
  //设置个默认值
  let min = nums[0] + nums[1] + nums[2];
  //定义头尾指针
  let left, right;
  let len = nums.length;
  for (let i = 0; i < len; i++) {
    //设置头尾指针的值  
    left = i + 1;
    right = len - 1;
    //当左侧与右侧重合时停止循环
    while (left < right) {
      //循环中的最小值之和  
      let tempMin = nums[i] + nums[left] + nums[right];
      //如果循环中的之和比默认值更接近则更改默认值
      if (Math.abs(tempMin - target) < Math.abs(min - target)) {
        min = tempMin;
      } else if (tempMin > target) {
        //如果此值比taget大的话则需要把右侧指针左移  
        right--;
      } else if (tempMin < target) {
        //如果此值比taget小的话则需要把左侧指针右移
        left++;
      } else if (tempMin == target) {
        //如果此值跟target一致的话,说明这就是我们需要的  
        return min
      }
    }
  }
  return min
};

最后:

算法题可以提高我们的逻辑思维能力,更能够加深对原生js的理解,了解到自身对js中数组对象方法的掌握程度。总的来说,多做算法题有益身心,希望大家多多难为自己一下,早日JS大成。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表