目录
53. 最大子序和(easy)—03/12
66. 加一(easy)——03/21
35. 搜索插入位置(easy)——03/22
914. 卡牌分组(easy)——03/27
1. 两数之和(easy)——04/02
给定一个整数数组 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;
};
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 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;
};
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 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;
};
给定一副牌,每张牌上都写着一个整数。
此时,你需要选定一个数字 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 <= deck.length <= 10000
0 <= deck[i] < 10000
解题思路:
1.应该先统计相同数字的数量:
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;
};
给定一个整数数组 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 [];
};