JavaScript算法编程——2.数组

224 阅读2分钟

NC 两数之和

给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。

image.png

  • 2.方法

  • 3.代码

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

NC41 最长无重复子数组

  • 1.思路 子数组肯定双指针,无重复肯定map,当然这里可以用set代替,因为只需要存一个数据

  • 2.方法

  • 3.代码

function maxLength( arr ) {
    // write code here
    var left = 0, right = 0, max = 0 // 子数组用双指针
    var set = new Set()
    while(right < arr.length) {
        if( set.has(arr[right]) ) {
            set.delete(arr[left++])
        } else {
            set.add(arr[right++])
            max = Math.max(max, set.size)
        }
    }
    return max
}

NC22 合并两个有序的数组

给出一个有序的整数数组 A 和有序的整数数组 B ,请将数组 B 合并到数组 A 中,变成一个有序的升序数组

function merge( A, m, B, n ) {
    // write code here
    // 双指针法
    var p = m + n -1
    var p1 = m - 1 // -1
    var p2 = n - 1 // 0
    // num2全部填充进去,以p2作为条件
    while(p2 >= 0) {
        if (p1 < 0) {
            A[p--] = B[p2--] // 直接用B填补A
        } else if (B[p2] > A[p1])  {// B大于A,采用B填补
            A[p] = B[p2]
            p--
            p2--
        } else { // 反之用A填补
            A[p] = A[p1]
            p--
            p1--
        }
    }
}

NC38 螺旋矩阵

给定一个m x n大小的矩阵(m行,n列),按螺旋的顺序返回矩阵中的所有元素。

image.png

  • 1.思路

image.png

  • 2.方法

  • 3.代码

function spiralOrder( matrix ) {
    // write code here
  if (matrix.length === 0) {
    return [];
  }
  // 1.定义边界
  let top = 0;
  let bottom = matrix.length - 1;
  let left = 0;
  let right = matrix[0].length - 1;

  let direction = "right"; // 定义方向
  let result = [];

  while (left <= right && top <= bottom) {
    if (direction === "right") {
      for (let i = left; i <= right; i++) {
        result.push(matrix[top][i]);
      }
      top++;
      direction = "down";
    } else if (direction === "down") {
      for (let i = top; i <= bottom; i++) {
        result.push(matrix[i][right]);
      }
      right--;
      direction = "left";
    } else if (direction === "left") {
      for (let i = right; i >= left; i--) {
        result.push(matrix[bottom][i]);
      }
      bottom--;
      direction = "top";
    } else if (direction === "top") {
      for (let i = bottom; i >= top; i--) {
        result.push(matrix[i][left]);
      }
      left++;
      direction = "right";
    }
  }

  return result;
}

NC65 斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n≤39

  • 1.思路

从最小的值开始求解,并且把每次求解的值保存在“记忆”(可以是一个数组,下标正好用来对应 n 的解答值)里,下面的值都由记忆中的值直接得出。

这样等到算到 10000 的时候,我们想要求解的值自然也就得到了,直接从 记忆[10000] 里取到值返回即可。

那么这种解法其实只需要一个 for 循环,而不需要任何递归的逻辑。

  • 2.方法

1.初始化缓存,创建一个空数组
2.初始条件:第一项为0,第二项为1
3.从2开始,用循环开始填充数组

  • 3.代码
// 【最佳】缓存方法
function Fibonacci(n)
{
    //动态缓存机制
    let  dp = []
    
    //初始条件
    dp[0] = 0;
    dp[1] = 1;
    
    //从2开始,用前面的不断填充
    for(let i = 2; i<= n; i++){
        dp[i] = dp[i-1] + dp[i-2];
    }
    
    return dp[n]
}
module.exports = {
    Fibonacci : Fibonacci
};

【基础】递归
function Fibonacci(n)
{
    // write code here
    //动态缓存机制
    if (n == 0){
        return 0
    }else if(n == 1 || n == 2){
        return 1;
    }
    
    return Fibonacci(n - 2) + Fibonacci(n - 1);
}
module.exports = {
    Fibonacci : Fibonacci
};

NC54 数组中相加和为0的三元组

  • 1.思路

  • 2.方法

  • 3.代码

NC7 买卖股票的最好时机(一)

假设你有一个数组prices,长度为n,其中prices[i]是股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益

1.你可以买入一次股票和卖出一次股票,并非每天都可以买入或卖出一次,总共只能买入和卖出一次,且买入必须在卖出的前面的某一天
2.如果不能获取到任何利润,请返回0
3.假设买入卖出均无手续费

  • 1.思路 第一种情况就是第i+1天我们即没买也没卖,那么最大利润就是第i天没持有股票的最大利润dp[i-1][0]\

第二种情况就是第i+1天我们卖了一支股票,那么最大利润就是第i天持有股票的最大利润(这个是负的,并且也不一定是第i天开始持有的,有可能在第i天之前就已经持有了)加上第i+1天卖出股票的最大利润,dp[i-1][1]+prices[i]

  • 2.方法
  • 3.代码
function maxProfit( prices ) {
    // write code here
    if(prices== null) return 0
    let len=prices.length
    let dp=[]
    for(let i=0;i<len;i++){
        dp[i]=[]
    }
    dp[0][0]=0
    dp[0][1]=-prices[0]
    for(let i=1;i<len;i++){
        dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i])
        dp[i][1]=Math.max(dp[i-1][1],-prices[i])
    }
    return dp[len-1][0]
}
module.exports = {
    maxProfit : maxProfit
};

NC73 数组中出现次数超过一半的数字

给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

  • 1.思路 两种方式:

1,利用js Map() 对象,通过是否存在进行计数,然后遍历,判断次数大小

2,利用只有一个最大的特性,遍历整个数组,记录次数和当前值,通过前后是否相等进行比较。
如果相等则对次数加一,遍历结束,剩下一个当前值,最后根据当前值进行数组遍历,记录次数进行比较

  • 3.代码
1,js创建map对象
	var map = new Map();
2.将键值对放入map对象
	map.set("key",value)
3.根据key获取map值
	map.get(key)
4.删除map指定对象
	delete map[key]	或	map.delete(key)
5.循环遍历map
    map.forEach(function(key){
      console.log("key",key)  //输出的是map中的value值
    })
1.思路一, 用map如果一个数不在map中,就加上,如果在,就+1,最后遍历找出最大的
function MoreThanHalfNum_Solution(numbers)
{
    // write code here
    const len = numbers.length
    if(len === 0) return 0
    
    var map = new Map()
    for (let i of numbers) {
        if(map.get(i) === undefined) {
            map.set(i, 1)
        }else {
            map.set(i, map.get(i)+1)
        }
    }
    for (let item of map) {
        if (item[1] > Math.floor(len / 2))
            return item[0]
    }
    return 0
}

NC59 矩阵的最小路径和

给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。

function minPathSum( matrix ) {
    // write code here
    const row = matrix[0].length
    const column = matrix.length
    const result = new Array(row).fill(0)
    
    for (let i=0; i< column; ++i) {
        for (let j =0; j<row; ++j) {
            if(i === 0) { // 第一行
                if(j === 0) { // 初始值
                    result[j] = matrix[i][j]
                } else {
                    result[j] = matrix[i][j] + result[j - 1]
                }
            } else {
                if(j === 0) { // 第一列
                    result[j] += matrix[i][j]
                } else {
                    result[j] = matrix[i][j] + Math.min(result[j-1], result[j])
                }
            }
        }
    }
    return result[row -1 ]
}

NC37 合并区间

给出一组区间,请合并所有重叠的区间。 请保证合并后的区间按区间起点升序排列。

  • 1.