Codewors刷题思路分享——js篇2
1.位计数(Bit Counting)
描述:编写一个函数,该函数将整数作为参数,并返回在该数字的二进制表示形式中等于 1 的位的个数。您可以保证输入是非负数。
示例:1234(10011010010) -> 5
思路解析:
先将作为输入的整形参数转化为二进制数,由于是非负数,所以不需要考虑补码的问题。将10进制数转化为2进制数可以从低位到高位一点一点得到这个数。示例中的10011010010 = 2^10 + 2^7 + 2^6 + 2^4 + 2^1 = 1024 + 128 + 64 + 16 + 2 = 1234。
10进制转2进制可以参考以下流程: 18 => 10010
18 % 2 = 0; (18 - 1*0)/2 = 9; 最低位为0
9 % 2 = 1; (9 - 1*1)/2 = 4; 第二位为1
4 % 2 = 0; (4 - 0)/2 = 2; 第三位为0
2 % 2 = 0; 2/2 = 1; 第四位为0
1 % 2 = 1; 0/2 = 0; 最高位为1
这样得到了整形参数的二进制字符串,就可以遍历来获得这个字符串里含有1的个位数的个数了。
代码:
var countBits = function(n) {
let currentnum = n;
let bit;
let counter = 0;
while(currentnum>0){
bit = currentnum % 2;
if(bit === 1)counter++;
currentnum = (currentnum - bit)/2;
}
return counter;
};
需要注意的是,如果使用位运算符>>可能会导致精度丢失,如使用 currentnum = currentnum >> 1;
代替 currentnum = (currentnum - bit)/2;
这是因为js在对整数进行位运算时会使用32位2进制数,导致高位丢失。
2.计算重复项(Counting Duplicates)
描述:编写一个函数,该函数将返回输入字符串中出现一次以上的字符或数字的个数。不区分大小写,可以假定输入字符串仅包含字母(大写和小写)和数字。
示例: "abcde" -> 0 "aabbcde" -> 2 "aabBcde" -> 2 "indivisibility" -> 1 "Indivisibilities" -> 2 "aA11" -> 2 "ABBA" -> 2
思路解析:
代码:
function duplicateCount(text){
let dictionary = [];
let textarray = text.toLowerCase().split('');
let counter = 0;
for(let i = 0 ; i<textarray.length;i++){
if(typeof(dictionary[textarray[i]]) == 'undefined'){
dictionary[textarray[i]] = 1;
}else{
dictionary[textarray[i]] += 1;
}
if(dictionary[textarray[i]] === 2)counter++;
}
return counter;
}
这里遍历字符串,将没有的字母或数字写进字典dictionary中,如果之前出现过就在之前基础上加1,如果这个字母或数字出现了2次,计算器加1。注意不要重复计数,出现第三次及以上时计数器不用加了。
3.查找奇偶校验异常值(Find The Parity Outlier)
描述:给你一个包含整数的数组(长度至少为 3,但可能非常大)。数组有两种情况,一种基本全是奇数但包含一个偶数,一种基本全是偶数但包含一个奇数。返回这个格格不入的异常数字的值。
示例: [2, 4, 0, 100, 4, 11, 2602, 36] -> 11 [160, 3, 1719, 19, 11, 13, -21] -> 160
思路解析:
本题首先要确定异常值的类型,然后遍历数组就可以找到异常值了。可以先记录数组中奇数和偶数的个数,哪种数的个数为1哪种数就是异常值类型。
代码:
function findOutlier(integers){
var arr = integers;
var oddcounter = 0;
var evencounter = 0;
for(let i = 0;i<arr.length;i++){
if(arr[i]%2 === 0){
evencounter++;
}else{
oddcounter++;
}
}
if(evencounter === 1){
for(let i = 0;i<arr.length;i++){
if(arr[i]%2 === 0) return arr[i];
}
}else{
for(let i = 0;i<arr.length;i++){
if(arr[i]%2 !== 0) return arr[i];
}
}
}
需要注意的是数组中的数字可能为负数,负奇数模2的余数为-1。所以判断一个数是否为奇数应该判断它模2余数是否不为0。
4.皮特,面包师(Pete, the baker)
描述:皮特喜欢烤一些蛋糕。他有一些食谱和成分。不幸的是,他的数学不好。你能帮他找出来,考虑到他的食谱,他能烤多少蛋糕吗?
编写一个函数,该函数的参数为配方(对象)和可用成分(也是一个对象),并返回 Pete 可以烘焙的最大蛋糕数(整数)。为简单起见,没有数量单位(例如,1磅面粉或200克糖只是1或200)。物体中不存在的成分可以被视为 0。
示例: cakes({flour: 500, sugar: 200, eggs: 1}, {flour: 1200, sugar: 1200, eggs: 5, milk: 200}); // 返回 2 cakes({apples: 3, flour: 300, sugar: 150, milk: 100, oil: 100}, {sugar: 500, flour: 2000, milk: 2000});// 返回 0
思路解析:
这里考查了json对象的使用,通过for in来遍历json对象。遍历配方的json对象,然后每次在可用成分中找到对应的成分的含量,将可用成分/配方成分可用成分/配方成分可用成分/配方成分的商记录到一个数组里面,数组中最小的值就是答案。同时如果在可用成分中没找到配方需要的成分,就返回0。
代码:
function cakes(recipe, available) {
let arr = [];
let result = 0;
for(let recipeitem in recipe){
if(typeof(available[recipeitem]) !== "undefined"){
arr.push(available[recipeitem]/recipe[recipeitem])
}else{
arr.push(0);
}
}
result = arr[0];
for(let i = 0;i<arr.length;i++){
if(arr[i] === 0) return 0;
if(result > Math.floor(arr[i]))result = Math.floor(arr[i])
}
return result;
}
这里注意typeof(available[recipeitem]) !== "undefined"
的undefined要用字符串,这是因为typeof的返回值类型为string。我们可以打印一下这个类型:console.log(typeof(typeof("test"))) //string
5.函数计算(Calculating with Functions)
描述:定义一些函数,这些函数需要满足以下条件:
- 从 0(“零”)到 9(“九”)的每个数字必须有一个函数
- 以下每个数学运算都必须有一个函数:加、减、乘、除以
- 每个计算只包含一个运算和两个数字
- 最外层函数表示左操作数,最内层函数表示右操作数
- 除法应为整数除法。比如1÷3应该返回0。
示例:
seven(times(five()));
// must return 35four(plus(nine()));
// must return 13eight(minus(three()));
// must return 5six(dividedBy(two()));
// must return 3
思路解析:
看描述可能没看明白,看下编辑框就知道要干啥了。
就是让定义这14个函数,然后满足加减乘除的需求就可以了。
仔细看实例,发现加减乘除的函数的参数只有数字函数一种情况,而数字的参数有两种情况(符号函数或者啥也没有)。
- 符号函数基本就确定了,它需要返回的值就是符号的类型和它参数上的数字,很自然能想到用字符串或者数组保存这些返回值。
- 而数字函数的参数如果为数组,那么说明它是最外层的函数,需要拿到参数进行计算;如果啥也没有,那么就返回对应的值就行了。
代码:
function zero(args) {return number(0,args)}
function one(args) {return number(1,args)}
function two(args) {return number(2,args)}
function three(args) {return number(3,args)}
function four(args) {return number(4,args)}
function five(args) {return number(5,args)}
function six(args) {return number(6,args)}
function seven(args) {return number(7,args)}
function eight(args) {return number(8,args)}
function nine(args) {return number(9,args)}
function plus(arg) {return symbol(0,arg)}
function minus(arg) {return symbol(1,arg)}
function times(arg) {return symbol(2,arg)}
function dividedBy(arg) {return symbol(3,arg)}
function number(n,args){
if(typeof(args) === "object"){
switch(args[0]){
case 0:return n + args[1];
case 1:return n - args[1];
case 2:return n*args[1];
case 3:return Math.floor(n/args[1]);
}
}else{
return n;
}
}
function symbol(n,arg){
let arr = [];
arr.push(n);
arr.push(arg)
return arr;
}
这里可以发现js这种弱类型语言的的一个特点,就是形参如果没有的话也不会报错,因为js会自动给形参一个undefined的值。
function a(arg){
console.log(typeof(arg))
}
a();//undefined
同时在观察高手的题解的时候发现了一个现象,就是js在运行函数时如果参数中嵌套了函数,那么它会以一种类似递归的方式来运行这些函数。
function a(arg){
console.log('a');
}
function b(arg){
console.log('b');
}
function c(arg){
console.log('c');
}
function d(arg){
console.log('d');
}
c(b(a())) //a b c
c(b(a()),d()) //a b d c
这是一个比较精简漂亮的题解 Calculating with Functions (JavaScript)
转载自:https://juejin.cn/post/7172772365641154597