LeetCode刷题记录(JavaScript)——数组

目录

53. 最大子序和(easy)—03/12

66. 加一(easy)——03/21

35. 搜索插入位置(easy)——03/22

914. 卡牌分组(easy)——03/27

1. 两数之和(easy)——04/02


53. 最大子序和(easy)—03/12

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

解题思路:

动态规划思想,动态规划方程:dp[i] = Max(dp[i-1]+A[i], A[i]) ( 0

法一直接使用动态规划方程,但是会开辟dp数组,内存占用更大

法二直接更改原数组,不开辟新的数组空间,内存小一点

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let dp = [];
    dp[0]= nums[0];
    let max = nums[0];
    for (let i= 1; i= 0 ){
            nums[i] += nums[i-1];
        }
        max = Math.max(nums[i],max);
    }

    return max;
};

66. 加一(easy)——03/21

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。

示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。 

解题思路:

1.最直接的思路肯定是 数组—>字符串—>数字—> +1 —>字符串—>数组 ,但是需要注意的是,数组是不限位数的,所以要是转化为整数Int,那么就存在溢出的情况,但是在JS中,ES6提供了新的数字类型BigInt来处理这个问题,它可以支持任意长度的整数。

注意:

创建BigInt: 可以在整数后面加n 或者 显式调用BigInt()函数

运算:不可以和普通number混合运算!

2.正经思路: 因为输入数组格式严格,其实每一位都是0~9的数字,并且开头不会是0,那么我们逆序从最后一位开始进行+1判断,如果 +1 后不得 0 ,那么运算结束了,直接返回即可,如果+1 后得 0,那么就是需要进位,下一位继续+1后判断……

直到 索引 0 ,如果还是得 0 ,那么代表 类似 99 +1 =100 的情况, 在0 位添加一个1 即可!

1. 好直接好懒惰的解法
/**
 * @param {number[]} digits
 * @return {number[]}
 */
var plusOne = function(digits) {
    let num = BigInt(digits.join(''));
    return [...(num+1n).toString()];
};

2.正经解法
/**
 * @param {number[]} digits
 * @return {number[]}
 */
var plusOne = function(digits) {
    for (let i = digits.length-1; i>= 0 ;i--){
        digits[i] = (digits[i]+1) %10;
        if ( digits[i] != 0) return digits;
    }
    digits.unshift(1);
    return digits;
};

35. 搜索插入位置(easy)——03/22

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5
输出: 2

示例 2:

输入: [1,3,5,6], 2
输出: 1

示例 3:

输入: [1,3,5,6], 7
输出: 4

 解题思路:

1.暴力法 复杂度O(n)

2.二分查找 复杂度O(logN)

和普通二分法差不多,但是最后循环出去的时候,left就是要插入的地方。

注意:

Js不区分整数和浮点数!!! 所以直接(left + right )/2 会算出浮点数,需要用Math.floor来取整!

1.暴力法
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    for (let i = 0; i= target) return i;
    }
    return nums.length;
};

2.二分法
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    let left = 0, right = nums.length-1;
    while(left <= right){
        mid = Math.floor((left + right)/2);
        if( nums[mid] === target ){
            return mid;
        }else if(nums[mid] < target){
            left = mid + 1;
        }else {
            right = mid - 1;
        }
    }
    return left;
};

914. 卡牌分组(easy)——03/27

给定一副牌,每张牌上都写着一个整数。

此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:

每组都有 X 张牌。
组内所有的牌上都写着相同的整数。
仅当你可选的 X >= 2 时返回 true。

 

示例 1:

输入:[1,2,3,4,4,3,2,1]
输出:true
解释:可行的分组是 [1,1],[2,2],[3,3],[4,4]
示例 2:

输入:[1,1,1,2,2,2,3,3]
输出:false
解释:没有满足要求的分组。

给定一副牌,每张牌上都写着一个整数。

此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:

每组都有 X 张牌。
组内所有的牌上都写着相同的整数。
仅当你可选的 X >= 2 时返回 true。

 

示例 1:

输入:[1,2,3,4,4,3,2,1]
输出:true
解释:可行的分组是 [1,1],[2,2],[3,3],[4,4]
示例 2:

输入:[1,1,1,2,2,2,3,3]
输出:false
解释:没有满足要求的分组。

提示:

  1. 1 <= deck.length <= 10000
  2. 0 <= deck[i] < 10000

解题思路:

1.应该先统计相同数字的数量:

  1. 可以用计数数组,但是因为数字0~10000,那这个数组太长了!要优化一下
  2. 使用Map,数字作为key,数量作为value。这样节省一下空间

2.这个分组规则实质上是在为所有数字的数量计算 最大公约数

最大公约数计算方法: gcd辗转相除法:https://blog.csdn.net/weixin_41183791/article/details/79610183

/**
 * @param {number[]} deck
 * @return {boolean}
 */
var hasGroupsSizeX = function(deck) {
    // 求最大公约数的函数!!!
    function gcd(a,b){
        return b === 0 ? a : gcd( b , a%b );
    }

    // 使用map来计数,数是key,数量是value
    let map = new Map();
    deck.forEach(num=>{
        map.set(num , map.has(num) ? map.get(num)+1 : 1);
    })
    // [...map.values()]把map里面的value都取出来作为一个数组
    // [...new Set()]把得到的数组去个重,减少计算量
    let arr = [...new Set([...map.values()])];
    // 迭代一下,挨个计算最大公约数
    let result = arr.reduce((pre,current)=>  gcd(pre,current),arr[0])
    return result>=2;
};

1. 两数之和(easy)——04/02

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

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解题思路:

 1.暴力解法会需要两层循环,为了减少复杂度,可以使用Map来减少查询时间:

可以使用一层循环,遍历元素,然后在Map中查询target和元素的差值,如果查询到,则返回,如果没查到,将当前元素加入Map,key是索引值

2.很简洁的方法,利用差值来寻找,倒序遍历数组,每次pop尾巴是为了不查询到重复的,使用数组的indexOf()方法来寻找差值索引,如果存在则返回,如果不存在就继续pop,直到数组只剩一个元素,则失败了

注意:

遍历使用forEach()里面的return只是forEach的return,不是函数的return啊!!!!

要函数return还是得用for循环

1.
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let map = new Map();
    for(let i = 0; i 1){
        let last = nums.pop();
        if (nums.indexOf(target-last) > -1){
            return [ nums.indexOf(target-last),nums.length];
        }
        length--;
    }
    return [];
};

 

你可能感兴趣的:(Leetcode)