“有些事情本来很遥远,你争取,它就会离你越来越近”
11. 猫和架子(Cats and shelves)
描述
无数个货架以交错的方式排列在另一个之上。
根据插图,猫可以同时跳到 3 个架子:从架子 1 跳到架子 2 或 4(猫不能爬到头顶正上方的架子上):
┌────────┐
│-6------│
└────────┘
┌────────┐
│------5-│
└────────┘ ┌─────► OK!
│ ┌────────┐
│ │-4------│
│ └────────┘
┌────────┐ │
│------3-│ │
BANG!────┘ ├─────► OK!
▲ |_/| │ ┌────────┐
│ ("^-^) │ │-2------│
│ ) ( │ └────────┘
┌─┴─┴───┴┬──┘
│------1-│
└────────┘
输入:
开始和结束货架编号(始终为正整数,完成时间不小于开始)
任务
找到从开始到结束的最小跳跃次数
思路
首先考虑开始(start)和结束(finish)相同的情况,此时次数为0。 当不相同时,定义一个 now 记录猫现在所在的货架编号,定义一个 sum 记录跳跃次数。再用 while 循环,当 结束货架和现在所在货架的差大于等于3时,继续循环,每次循环中,猫跳三格,跳跃次数加一,直到不满足,此时有三种可能,差为0,猫不用再跳;差为1,猫跳一次;差为2,猫跳两次。最后相加就行。
代码
function solution(start, finish)
{
if(start === finish) {
return 0;
}
let now = start;
let sum = 0;
while((finish - now) >= 3) { //还可以每次跳三格
now += 3;
sum ++;
}
return sum + (finish - now) % 3;
}
优化思路
在声明中再定义一个参数 difference,值为 finish - start, 只要 difference >= 3,猫就会跳三格,可以直接用 difference 除以 3, 再向下取整,就可以得到猫需要跳三格的次数,剩下的difference 只有三种可能----0, 1, 2,和前面思路一样对 3 求余就行,再把两个相加。
优化代码
const solution = (start, finish, difference = finish - start) => Math.floor(difference / 3) + difference % 3;
12. 下一个回文数( Next Palindromic Number)
描述
CW 中关于回文数和回文弦的问题过去和现在都存在。(设n是一任意自然数。若将n的各位数字反向排列所得自然数n1与n相等,则称n为一回文数。)
在本题中,你会得到一个正整数,你必须创建一个函数(Javascript),它将输出高于的最小回文数。
思路
首先应该要得到每个数的各位数反向排列的数,要颠倒首先想到数组的 reverse() 方法,可以先用 toString() 方法将数字类型变为字符串类型,再用 split("") 方法将字符串类型变为数组类型, 再用数组的 reverse() 方法将数组颠倒,再用 join() 方法将颠倒的数组变为字符串类型,再用Number() 方法将字符串类型变回数字类型。这样就得到了颠倒之后的数。
直接进入do while 循环,每次循环让输入的数 val ++,再得到它的颠倒之后的数,循环判断 这个数跟他的颠倒数是否相等,若不相等继续循环,若相等,结束循环,这个数就是回文数。
代码
const nextPal = (val) => {
do
{
val ++;
var str = val.toString();
var arr = str.split("");
var num = Number(arr.reverse().join(""));
} while(num !== val)
return val;
}
13. 寻找奇数(Find the odd int)
描述
给定一个整数数组,找到出现奇数次的整数。
始终只有一个整数出现奇数次。
示例
输入:[0] 输出: 0
输入:[1, 1, 2] 输出: 2
输入:[0, 1, 0, 1, 0] 输出: 0
输入:[1, 2, 2, 2, 4, 2, 1] 输出: 4
思路
先用 sort() 方法给数组排序,声明变量 sum 记录每个元素出现的次数,sum 初始值为1, 声明 char 记录每个元素,char 初始值为数组的第一个元素,for 循环遍历数组,每一次循环中,判断相邻元素是否相等,若不相等,先判断 sum 是否为奇数(奇数可用对2求余来判断),如果是,则 return char,否则将下一项的数组元素存到 char 中,并将 sum 重置为1; 若相邻元素相等,则令 sum 加一。这时候还有个小bug,就是如果数组的最后一个元素出现次数是奇数,前面的元素出现次数都是偶数,则不会返回,故在 for 循环结束后,如果还没有任何返回,则在函数的最后 返回数组的最后一项。
代码
function findOdd(A) {
let arr = A.sort();
let sum = 1;
let char = arr[0];
for(let i = 0; i < arr.length - 1; i ++) {
if(arr[i] !== arr[i+1]) {
if(sum%2 === 1) { //出现次数 sum 是奇数
return char;
}
char = arr[i+1];
sum =1;
} else { // 相邻两个元素相等
sum ++;
}
}
return arr[arr.length-1]; // 返回最后一个数组元素
}
14. 找到高于给定值的最小功率(Find the smallest power higher than a given a value)
描述
我们有号码12385。我们想知道最接近但高于 12385 的立方体的值。答案是13824。 现在,另一个案例。我们有号码1245678。我们想知道 5 次方,最接近且高于该数字。值将为1419857。
我们需要一个函数(在 JavaScript、CoffeeScript 和 Haskell 中),它接收两个参数、一个值和幂的指数,并输出我们想要查找的值。 findNextPower (val,pow_)
示例
findNextPower(12385, 3) == 13824
findNextPower(1245678, 5) == 1419857
思路一(有个小Bug)
不是要求比 val 更高的 pow_ 次方数吗,我们可以先求 val 的 1 / pow_ 次方数,设它为 a,再判断 a 是否为整数,如果是整数, 返回(a+1)的 pow_ 次方,如果不是,则让 a 向上取整,再返回它的 pow_ 次方。
代码一
const findNextPower = (val,pow_) => {
var a = Math.pow(val, 1/pow_);
if(a % 1 == 0) {
return (a + 1) ** pow_;
} else {
return Math.ceil(a) ** pow_;
}
}
解法一的bug
当输入的是 findNextPower(4782969, 7), 其中 4782969 是 9 的 7 次方,按理说,那么 4782969 的 1 / 7 次方应该等于 9,但是打印结果发现它等于 8.999999999999998,用在这里的话,最后返回结果为 4782969,这是不正确的。
这是为什么呢?
因为精度丢失问题,计算机能读懂的是二进制数,当进行计算时,实际上是把数字转换为了二进制进行的,这个过程中丢失了精度
优化思路一
对于上面的问题,可以进一步改进,要求的是比 val 高的次方数(一定是整数),那就至少要比 val 大 1, 我们可以先让得到的 val 加一, 再求它的 1 / pow_ 次方,这样得到的数,肯定是比 val 的 1 / pow_ 次方大,就不用判断 1 / pow_ 是否为整数的情况, 而且也避免了精度丢失问题。
优化代码一
const findNextPower = (val,pow_) => Math.pow(Math.ceil(Math.pow(val + 1, 1 / pow_)), pow_)
思路二
直接用暴力破解法,直接进入 for 循环,从 1 开始遍历每个整数,每次循环中判断它的 pow_ 次方是否大于 val
代码二
const findNextPower = (val,pow_) => {
for(let i = 1; i <= val; i ++) {
if(Math.pow(i, pow_) > val) {
return Math.pow(i, pow_)
}
}
}
15. 创建电话号码(Create Phone Number)
描述
编写一个接受 10 个整数(介于 0 和 9 之间)的数组的函数,该数组以电话号码的形式返回这些数字的字符串。
返回的格式必须正确才能完成此质询。 不要忘记右括号后面的空格!
思路
只要返回的格式正确就可以,故有很多种方法,我认为其中最简单的方法就是用模板字符串。
代码
const createPhoneNumber = (numbers) => {
numbers = numbers.join("");
return `(${numbers.substr(0,3)}) ${numbers.substr(3,3)}-${numbers.substr(6)}`
}
16. 偶数斐波那契和(Even Fibonacci Sum)
描述
给出斐波那契数列中所有偶数的总和,直到(但不包括)传递给函数的数字。或者,换句话说,将所有小于给定数 n 的偶数斐波那契数(n 不是斐波那契数列的第 n 个元素)求和,而不包括 n。
fibonacci(max)
斐波那契数列是一系列数字,其中下一个值是前两个值的相加。该系列以 0 和 1 开头:
0 1 1 2 3 5 8 13 21...
示例
fibonacci(0)==0
fibonacci(33)==10
fibonacci(25997544)==19544084
思路
定义两个变量 x, y 初始值为斐波那契数列的第一项和第二项(也就是0和1)(要保证 x 始终是小的那个, y 始终是大的那个,之后会说),定义一个变量 sum 用来存放偶数和,初始值等于 x(也就是0),用 while 循环,当满足 y < max 时,进入 while 循环,循环内部,先判断 y 是否为偶数,若是,则让 sum += y,若不是则往下执行,将 x + y 的值给 y ,而原来的 y 的值给 x(这里的实现可以看代码),这样,y始终是较大的那个,x始终是较小的那个,故循环条件只需要比较 y 和 max 的大小。最后出循环返回 sum。
始终保持 y 是较大的数,这样每次 if, while 只需要对 y 进行判断。 不然 x, y 交叉着来,想想就头大
代码
const fibonacci = (max) => {
let x = 0;
let y = 1;
let sum = x;
while(y < max) {
if(y % 2 ===0){ // 判断 y 是否为偶数
sum += y;
}
let z = x + y; // 把 x + y 的值给变量 z
x = y; // 将 y 原来的值赋值给 x
y = z; // 再将原来的两个相加和 z 赋值给 y
}
return sum;
}
17. 谁喜欢它?(Who likes it?)
描述
您可能从Facebook和其他页面上知道“喜欢”系统。人们可以“喜欢”博客文章、图片或其他项目。我们希望创建应该显示在此类项目旁边的文本。 实现一个函数,该函数采用一个数组,其中包含喜欢某个项目的人的姓名。它必须返回显示文本,如示例中所示:
示例
[] --> "no one likes this"
["Peter"] --> "Peter likes this"
["Jacob", "Alex"] --> "Jacob and Alex like this"
["Max", "John", "Mark"] --> "Max, John and Mark like this"
["Alex", "Jacob", "Mark", "Max"] --> "Alex, Jacob and 2 others like this"
思路
就是跟前面第 16 题差不多,直接字符串模板就行,很简单,但我为什么要再拿出来呢?虽然有点水题目的嫌疑,但是!!我想说的是! 这道题我提交的时候前前后后改了五六遍, 因为!又是 like后面少了 s ,后面又有些 likes 后面多了一个 s,注意看前面两个是 likes ,后面的是 like,我英语不太好,这是第三人称单数复数的意思,我就看了第一行的 like, 后面都用的 like。
补充
我想说的是! 之后看题的时候,敲代码的时候,一定要细心认真读题看题,认真敲代码,经常有时候因为一个类名写错,或者单词写错了个字母,导致效果无法实现,以至于重新去排查哪里出错,浪费了很多时间。
认真读题! 认真敲代码!
代码
function likes(names) {
if(names.length == 0) {
return "no one likes this"
}
if (names.length == 1) {
return `${names[0]} likes this`
}
if (names.length == 2) {
return `${names[0]} and ${names[1]} like this`
}
if (names.length == 3) {
return `${names[0]}, ${names[1]} and ${names[2]} like this`
}
if (names.length > 3){
let a = names.length - 2;
return `${names[0]}, ${names[1]} and ${a} others like this`
}
}
18. 数字是其数字总和的幂(Numbers that are a power of their sum of digits)
描述
数字81有一个特殊的性质,其数字之和的一定幂等于81(九的平方)。八十一 (81) 是具有此属性的第一个数字(不考虑一位数)。 下一个,是512。 让我们看看这两种情况的细节
8 + 1 = 9 和 9^2 = 81
512 = 5 + 1 + 2 = 8 和 8^3 = 512
我们需要创建一个函数,它接收一个数字作为参数并返回这个数字序列。powerSumDigTerm(n)
示例
1 --> 81
2 --> 512
思路
可以先声明一个空数组 arr,然后将符合要求的数都 push 进去,再用 sort() 方法给数组排序,最后根据输入的 n ,来返回 arr[n - 1]。(因为数组元素下标从0开始)
现在问题就来到了怎么找符合要求的数。这种数,只要足够大,就会有无穷多个,我们只需要考虑部分就行。用两层 for 循环,初始 i, j 都为2(1和0不考虑),外层循环98次,内层循环40次,每次 i, j自增。每次循环中,求 i 的 j 次方,再求得到的乘积的各项数字和,判断和是否等于i,若等于,则将乘积 push 进数组。最后能得到拥有一些元素的数组。
此方法只能考虑部分情况,若给的 n 过大,则无法输出
代码
let arr = [];
for(let i = 2; i < 100; i ++) {
for(let j = 2; j < 42; j ++) {
let product = Math.pow(i, j)
if(product.toString().split("").reduce((total,current) => total + parseInt(current),0) === i) {
arr.push(product)
}
}
}
arr = arr.sort((a, b) => a - b);
const powerSumDigTerm = (n) => arr[n - 1];
19. 数字总和或数字根(Sum of Digits / Digital Root)
描述
数字根是数字中所有数字的递归和。
给定,取数字的总和。如果该值有多个数字,请继续以这种方式减小,直到生成个位数数字。输入将为非负整数。
示例
16 --> 1 + 6 = 7
942 --> 9 + 4 + 2 = 15 --> 1 + 5 = 6
132189 --> 1 + 3 + 2 + 1 + 8 + 9 = 24 --> 2 + 4 = 6
493193 --> 4 + 9 + 3 + 1 + 9 + 3 = 29 --> 2 + 9 = 11 --> 1 + 1 = 2
思路
首先要得到这个数的各位数相加的和,声明一个变量 sum = 0 用来记录各项和,
可以用 toString() 和 split("") 将数字的每一项存入数组中,此时数组的每一项都是字符串类型,再用 map() 方法为每一项调用 Number() 将将其转为数字类型,再调用一次 map() 让每一项都加到 sum 中。
再判断比较 sum 和 9 的大小,若大于,继续递归调用函数本身,否则返回 sum
代码
const digitalRoot = (n) =>{
// console.log("执行一次函数")
let sum = 0;
n.toString().split("").map((item) => Number(item)).map((item) => sum+=item)
// console.log('此时sum=' + sum);
if(sum > 9) {
return (digitalRoot(sum)); // 这里要加 return ,不然没有返回值
}
return sum;
}
20. 建造一堆立方体(Build a pile of Cubes)
描述
你的任务是建造一座由n个立方体组成的建筑。 底部的立方体的体积为n^3,上面的立方体 将具有(n−1)^3依此类推,直到顶部的体积为1^3
您将获得建筑物的总体积m。 给定 m 你能找到你必须构建的立方体的数量 n 个吗?
函数 findNb 的参数将是一个整数 m 并且您必须返回整数 n,例如(find_nb, find-nb, findNb, ...)n^3+(n−1)^3+(n−2)^3+...+1^3=m, 如果存在这样的 n,如果没有这样的 n,则为 -1。
findNb(m)
示例
findNb(1071225) --> 45
findNb(91716553919377) --> -1
思路
我们可以从建筑的顶端开始从上往下,这样问题就变成了 1^3 + 2^3 + ... + n^3, 用 for 循环即可,比较总和 sum 和体积 m 的值,相等时,返回此时的 i,如果大于则返回 -1,否则继续循环。
代码
function findNb(m) {
let sum = 0;
for(let i = 1; ;i ++) {
sum += i ** 3;
if(sum === m) {
return i;
}
if(sum > m) {
return -1;
}
}
}