简单题全部刷完了,这是最后一篇简单题的记录。64,2的6次方,简单题就结束在这吧
1.阶乘尾数
题目:设计一个算法,算出 n 阶乘有多少个尾随零
思路:分析可知,因子有多少个5,就有多少个0
暴力法:
/**
* @param {number} n
* @return {number}
*/
var trailingZeroes = function(n) {
let c = 0;
for (let i = 1; i <= n; i++) {
let v = i;
while (!(v % 5)) {
c++;
v /= 5;
}
}
return c;
};
换个思路,有几个5,除以5即可
/**
* @param {number} n
* @return {number}
*/
var trailingZeroes = function(n) {
let res = 0
while(n >= 5) {
res += (n /= 5)|0
}
return res
};
2.跳水板
题目:
你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为shorter,长度较长的木板长度为longer。你必须正好使用k块木板。编写一个方法,生成跳水板所有可能的长度。
返回的长度需要从小到大排列。
思路:先看一下递归或者迭代的实现
/**
* @param {number} shorter
* @param {number} longer
* @param {number} k
* @return {number[]}
*/
var divingBoard = function(shorter, longer, k) {
const set = new Set();
if(!k)return []
const dfs = (pre, k) => {
if (!k) {
set.add(pre);
return;
}
dfs(pre + shorter, k - 1);
dfs(pre + longer, k - 1);
};
dfs(0, k);
return [...set];
};
/**
* @param {number} shorter
* @param {number} longer
* @param {number} k
* @return {number[]}
*/
var divingBoard = function(shorter, longer, k) {
let set = new Set([0]);
if (!k) return [];
if (shorter === longer) return [shorter * k];
while (k--) {
const tempv = [...set];
const short = tempv.map((item) => item + shorter);
const long = tempv.map((item) => item + longer);
set = new Set([...short, ...long]);
}
return [...set];
};
这两种方式都可以,不过时间复杂度太高了,稍微大一点的数据就超时
换个思路,选取了i个shorter,那么就有k-i个longer,所以一一枚举即可
/**
* @param {number} shorter
* @param {number} longer
* @param {number} k
* @return {number[]}
*/
var divingBoard = function(shorter, longer, k) {
if(!k)return []
if(shorter==longer)return [k*shorter]
const list = new Array(k + 1);
for (let i = 0; i <= k; i++) {
list[i] = longer * i + shorter * (k - i);
}
return list;
};
3.珠玑妙算
题目:
珠玑妙算游戏(the game of master mind)的玩法如下。
计算机有4个槽,每个槽放一个球,颜色可能是红色(R)、黄色(Y)、绿色(G)或蓝色(B)。例如,计算机可能有RGGB 4种(槽1为红色,槽2、3为绿色,槽4为蓝色)。作为用户,你试图猜出颜色组合。打个比方,你可能会猜YRGB。要是猜对某个槽的颜色,则算一次“猜中”;要是只猜对颜色但槽位猜错了,则算一次“伪猜中”。注意,“猜中”不能算入“伪猜中”。
给定一种颜色组合solution
和一个猜测guess
,编写一个方法,返回猜中和伪猜中的次数answer
,其中answer[0]
为猜中的次数,answer[1]
为伪猜中的次数。
思路:用map记录两个字符串各个字符的出现次数,并记录有几个位置是相同的,然后取guess的key,找出所有字符相同的次数,伪猜中就是两个之差
/**
* @param {string} solution
* @param {string} guess
* @return {number[]}
*/
var masterMind = function(solution, guess) {
const l = solution.length;
let c = 0;
const map1 = new Map();
const map2 = new Map();
for (let i = 0; i < l; i++) {
if (solution[i] == guess[i]) {
c++;
}
map1.set(solution[i], (map1.get(solution[i]) || 0) + 1);
map2.set(guess[i], (map2.get(guess[i]) || 0) + 1);
}
let v = 0;
for (const key of map2.keys()) {
v += Math.min(map2.get(key), map1.get(key) || 0);
}
return [c, v - c];
};
4.连续数列
题目:给定一个整数数组,找出总和最大的连续数列,并返回总和。
思路:这题之前做过好几次。两个变量,一个变量记录最大和,另一个变量记录已当前元素为结尾的数列的最大和
/**
* @param {number[]} nums
* @return {number}
*/
var maxSubArray = function(nums) {
let sum = -Infinity;
let pre = -Infinity;
for (const item of nums) {
pre = Math.max(item, pre + item);
sum = Math.max(sum, pre);
}
return sum;
};
5.按摩师
题目:
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
思路:和打家劫舍基本一样,用动态规划的思路去做,dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i])
/**
* @param {number[]} nums
* @return {number}
*/
var massage = function(nums) {
const l = nums.length;
if (!l) return 0;
if (l == 1) return nums[0];
const res = new Array(l).fill(0);
res[0] = nums[0];
res[1] = Math.max(nums[0], nums[1]);
for (let i = 2; i < l; i++) {
res[i] = Math.max(res[i - 1], res[i - 2] + nums[i]);
}
return res[l - 1];
};