题目
1295. 统计位数为偶数的数字
1296. 划分数组为连续数字的集合
1297. 子串的最大出现次数
1298. 你能从盒子里获得的最大糖果数
完成题数:1295、1296、1298
完成
题解1295. 统计位数为偶数的数字
给你一个整数数组 nums,请你返回其中位数为 偶数 的数字的个数。
示例 1:
输入:nums = [12,345,2,6,7896]
输出:2
解释:
12 是 2 位数字(位数为偶数)
345 是 3 位数字(位数为奇数)
2 是 1 位数字(位数为奇数)
6 是 1 位数字 位数为奇数)
7896 是 4 位数字(位数为偶数)
因此只有 12 和 7896 是位数为偶数的数字
示例 2:
输入:nums = [555,901,482,1771]
输出:1
解释:
只有 1771 是位数为偶数的数字。
我的: 一开始看到题目就是暴力破解,计算出每一个数位数,结果%2看是不是偶数,但是这样的时间复杂度很高,等于你要把每一个数不断除以10来得出它的位数
较优解:①转换成字符串,用它的长度来求解
①考察点:数字如何转字符串>>数据类型的转换
var findNumbers = function(nums) {
let max = 0
for(let i = 0; i < nums.length;i++){
// if(String(nums[i].length % 2 === 0){max++}
if(nums[i].toString().length % 2 === 0){max++}
}
return max
};
题解1296. 划分数组为连续数字的集合
给你一个整数数组 nums 和一个正整数 k,请你判断是否可以把这个数组划分成一些由 k 个连续数字组成的集合。 如果可以,请返回 true;否则,返回 false。
示例 1:
输入:nums = [1,2,3,3,4,4,5,6], k = 4
输出:true
解释:数组可以分成 [1,2,3,4] 和 [3,4,5,6]。
示例 2:
输入:nums = [3,2,1,2,3,4,3,4,5,9,10,11], k = 3
输出:true
解释:数组可以分成 [1,2,3] , [2,3,4] , [3,4,5] 和 [9,10,11]。
示例 3:
输入:nums = [3,3,2,2,1,1], k = 3
输出:true
示例 4:
输入:nums = [1,2,3,4], k = 3
输出:false
解释:数组不能分成几个大小为 3 的子数组。
我的:先将数组排好序,然后创建和解释一样的二维数组,第一个的第一位用Nums[0]来填充,其余都是空数组[],创建一个用来表示当前行数的变量,因为数组是有序的,遍历过程中,如果下一位不是比当前行数的数组最后一位大于1,那么就再判断是不是应该存在下一个数组中,以此循环.当数组长度等于k后,行数就可以加一.
较优解:哈希表查询
我们先将数组排序好,然后将每个数出现的次数存进Map结构中,接着开始遍历排序好的数组,一开始所有的数都会存在map中,从第一位开始,我们在遍历的内部再进行遍历,由于下一位数肯定是上一位大于一,所以我们直接进行K次循环,每次循环都在map中查询是否有这个数,有则在map中将此数的出现次数减一,当为0次时,直接删除.所以如果在map中找不到该数,直接turn false. 而在外部的循环中,我们也需要监测该数是否在map中,不在则证明它已经被用完了,直接跳过continue 在就证明该数为下一次连续数字的集合的开头
var isPossibleDivide = function(nums, k) {
if(nums.length % k !== 0) return false
nums.sort((a,b)=>a-b)
const map = new Map()
nums.forEach(item=>{
map.set(item,(map.get(item) || 0) + 1)
})
for(const item of nums){
if(!map.has(item)){
continue;
}
for(let i = 0; i < k; i++){
const num = item + i
if(!map.has(num)){
return false
}else{
map.set(num,map.get(num) - 1)
if(map.get(num) === 0 ) map.delete(num)
}
}
}
return true
};
题解1298. 你能从盒子里获得的最大糖果数
给你 n 个盒子,每个盒子的格式为 [status, candies, keys, containedBoxes] ,其中:
状态字 status[i]:整数,如果 box[i] 是开的,那么是 1 ,否则是 0 。 糖果数 candies[i]: 整数,表示 box[i] 中糖果的数目。 钥匙 keys[i]:数组,表示你打开 box[i] 后,可以得到一些盒子的钥匙,每个元素分别为该钥匙对应盒子的下标。 内含的盒子 containedBoxes[i]:整数,表示放在 box[i] 里的盒子所对应的下标。 给你一个 initialBoxes 数组,表示你现在得到的盒子,你可以获得里面的糖果,也可以用盒子里的钥匙打开新的盒子,还可以继续探索从这个盒子里找到的其他盒子。
请你按照上述规则,返回可以获得糖果的 最大数目 。
示例 1:
输入:status = [1,0,1,0], candies = [7,5,4,100], keys = [[],[],[1],[]], containedBoxes = [[1,2],[3],[],[]], initialBoxes = [0]
输出:16
解释:
一开始你有盒子 0 。你将获得它里面的 7 个糖果和盒子 1 和 2。
盒子 1 目前状态是关闭的,而且你还没有对应它的钥匙。所以你将会打开盒子 2 ,并得到里面的 4 个糖果和盒子 1 的钥匙。
在盒子 1 中,你会获得 5 个糖果和盒子 3 ,但是你没法获得盒子 3 的钥匙所以盒子 3 会保持关闭状态。
你总共可以获得的糖果数目 = 7 + 4 + 5 = 16 个。
示例 2:
输入:status = [1,0,0,0,0,0], candies = [1,1,1,1,1,1], keys = [[1,2,3,4,5],[],[],[],[],[]], containedBoxes = [[1,2,3,4,5],[],[],[],[],[]], initialBoxes = [0]
输出:6
解释:
你一开始拥有盒子 0 。打开它你可以找到盒子 1,2,3,4,5 和它们对应的钥匙。
打开这些盒子,你将获得所有盒子的糖果,所以总糖果数为 6 个。
示例 3:
输入:status = [1,1,1], candies = [100,1,100], keys = [[],[0,2],[]], containedBoxes = [[],[],[]], initialBoxes = [1]
输出:1
示例 4:
输入:status = [1], candies = [100], keys = [[]], containedBoxes = [[]], initialBoxes = []
输出:0
示例 5:
输入:status = [1,1,1], candies = [2,3,2], keys = [[],[],[]], containedBoxes = [[],[],[]], initialBoxes = [2,1,0]
输出:7
我的:初看这个题目,和之前的2115. 从给定原材料中找到所有可以做出的菜有点类似,但是这个题我没有做出来, 目前也还没有去看.现在的这个题其实不难,慢慢理清思路就可了.
通过了,但是我的方法是错的
首先厘清题目,第一我们有一个状态字,代表着该下标的箱子是否需要钥匙开启,第二是糖果数,这个是我们最后需要返回的结果,只要是能打开的箱子就需要加上该箱子的糖果数,第三是钥匙,代表着当我们打开该下标的箱子后能得到的其他下标的箱子的钥匙,第四个是内含箱子,代表着打开该箱子后能得到的箱子的下标.最后一个是我们初始拥有的箱子.
这个题的关键点:①我们拥有的箱子②我们目前能打开的箱子③我们已经打开过的箱子 思路:首先我们先从初始拥有的箱子中找到我们拥有的箱子,这个值是会随着我们打开的箱子变换的.每打开一次箱子,我们就记录下来,如果能获取到新的箱子,我们就添加到尾部.我退出循环的条件:当拥有的箱子数减去打开的箱子数为1时,退出循环,返回结果.事实上,当我后面在写这个文章的时候,我自己找到了能让自己通过不了的测试数据,就是我们只能打开初始的箱子,后面的箱子都是需要钥匙的,但是我们没有钥匙,这个箱子数是大于一的,我的代码就无法通过了.引以为戒,不要以为测试用例通过就代表代码是正确的
var maxCandies = function(status, candies, keys, containedBoxes, initialBoxes) {
const keyss = new Map()
// 拥有但是没有开过的盒子下标
const yeslist= []
// 已经开过的盒子
const set = new Set()
let sum = 0;
// 初始盒子得到的盒子下标
initialBoxes.forEach(item=>{yeslist.push(item)})
// 拥有的盒子没有为空时
while(yeslist.length){
let p = 0
while(p < yeslist.length){
let i = yeslist[p]
// 开过了
if(set.has(i)){
p++;
continue;
}
// 没开过
else{
// 能打开
if(status[i] === 1 || keyss.has(i)){
set.add(i)
sum += candies[i]
if(containedBoxes[i].length){
containedBoxes[i].forEach(item=>{
yeslist.push(item)
})
}
if(keys[i].length){
keys[i].forEach(item=>{
keyss.set(item)
})
}
}
// 打不开
else{
if(yeslist.length - set.size === 1) return sum
p++;
}
}
}
if(set.size === yeslist.length) return sum
}
return sum
};
较优解:
思路很清晰:首先将已有的箱子存到遍历的数组里,然后每次遍历,将糖果数加上,其次就是查看该箱子里包含了什么箱子,如果该箱子是可以自启的就放进遍历的数组中,如果不是自启的,就是将状态改成-1,代表等待钥匙要开启,最后查看该箱子中有什么钥匙,如果该箱子刚好是-1的状态,就存进遍历数组中,并将状态改成 0, 否则则将该箱子的状态改成1,因为此时已经有钥匙了,等于可以自启
箱子状态:1(自启),0(无法自启),-1(等待钥匙)
var maxCandies = function(status, candies, keys, containedBoxes, initialBoxes) {
const queue = initialBoxes;
let max = 0
for(let i = 0; i < queue.length; i++){
const item = queue[i]
max += candies[item]
containedBoxes[item].forEach(item1=>{
status[item1] === 1 ? queue.push(item1) : (status[item1] = -1)
})
keys[item].forEach(item2=>{
status[item2] === -1 ? (status[item2] = 0 , queue.push(item2)) : (status[item2] = 1)
})
}
return max
};
未完成
题解1297. 子串的最大出现次数
给你一个字符串 s ,请你返回满足以下条件且出现次数最大的 任意 子串的出现次数:
子串中不同字母的数目必须小于等于 maxLetters 。 子串的长度必须大于等于 minSize 且小于等于 maxSize 。
示例 1:
输入:s = "aababcaab", maxLetters = 2, minSize = 3, maxSize = 4
输出:2
解释:子串 "aab" 在原字符串中出现了 2 次。
它满足所有的要求:2 个不同的字母,长度为 3 (在 minSize 和 maxSize 范围内)。
示例 2:
输入:s = "aaaa", maxLetters = 1, minSize = 3, maxSize = 3
输出:2
解释:子串 "aaa" 在原字符串中出现了 2 次,且它们有重叠部分。
示例 3:
输入:s = "aabcabcab", maxLetters = 2, minSize = 2, maxSize = 3
输出:3
示例 4:
输入:s = "abcde", maxLetters = 2, minSize = 3, maxSize = 3
输出:0