跳到主要内容

5 篇博文 含有标签「FreeCodeCamp」

查看所有标签

题目描述

image.png image.png

测试案例

image.png

题目分析

由于本题是我使用Chrome浏览器直接对题目进行的翻译,难免造成一些翻译上的错误。所以接下来,我们首先对题目进行一个分析,明确题目想要解决什么样的问题。

题目接收的参数是什么?

本题给出的函数,总共接收三个参数。

  • 参数1:顾客所有产品的总价。
  • 参数2:顾客给的钱数。
  • 参数3:是一个二维数组,每一个小数组中的第一个元素是面值,第二个元素是收银机中该面额的总值(美元)。

解题思路

1. 建立一个面值和美元对应的二维数组。

const cashMap = [
["PENNY", 0.01],
["NICKEL", 0.05],
["DIME", 0.1],
["QUARTER", 0.25],
["ONE", 1],
["FIVE", 5],
["TEN", 10],
["TWENTY", 20],
["ONE HUNDRED", 100]
]

2. 计算出应找零多少

// 首先计算出应找零多少钱
const shouldGive = cash - price;

3. 使用指针指向第一个小于等于找零金额的面值

// 定义遍历指针,这个指针指向第一个小于等于需要找零金额的面值
let pointer;
for (let i = 0; i < cashMap.length; i++) {
if (cashMap[i][1] > shouldGive) {
pointer = i - 1;
break;
} else if (cashMap[i][1] === shouldGive) {
pointer = i;
break;
}
}

4. 使用一个临时变量和临时指针保存需要找零的数字和第三步我们找到的指针。

let tempGive = shouldGive;
let Tpointer = pointer;
// 定义最终返回的数组
let result = []

5. 找出指针指向的面额需要从收银机中拿出几张(下面的sub变量表示张数)

let sub = Math.floor(tempGive / cashMap[Tpointer][1])
while (Tpointer >= 0) {
if (sub * cashMap[Tpointer][1] > cid[Tpointer][1]) {
sub = cid[Tpointer][1] / cashMap[Tpointer][1];
result.push([cid[Tpointer][0], sub * cashMap[Tpointer][1]])
tempGive = (tempGive - sub * cashMap[Tpointer][1]).toFixed(2)
Tpointer--;
if (Tpointer < 0) return { status: "INSUFFICIENT_FUNDS", change: [] };
sub = Math.floor(tempGive / cashMap[Tpointer][1]);
} else {
result.push([cid[Tpointer][0], sub * cashMap[Tpointer][1]])
tempGive = (tempGive - sub * cashMap[Tpointer][1]).toFixed(2)
Tpointer--;
if (Tpointer < 0) break;
sub = Math.floor(tempGive / cashMap[Tpointer][1]);
}
}

6. 如果找零后,收银机中没有钱了,此时返回close的状态

const cidSum = cid.reduce((pre,item) => pre + item[1],0)
for (let i = 0; i < result.length; i++) {
if (cidSum === shouldGive) {
let test = [];
for (let v of cashMap) {
if (v[0] === result[i][0]) {
test.push([v[0],result[i][1]])
} else {
test.push([v[0],0])
}
}
return {
status: 'CLOSED',
change: test
}
}
}

全部代码

function checkCashRegister(price, cash, cid) {
// 建立面值哈希表
const cashMap = [
["PENNY", 0.01],
["NICKEL", 0.05],
["DIME", 0.1],
["QUARTER", 0.25],
["ONE", 1],
["FIVE", 5],
["TEN", 10],
["TWENTY", 20],
["ONE HUNDRED", 100]
]
// 1:首先计算出应找零多少钱
const shouldGive = cash - price;
// 2. 定义遍历指针,这个指针指向第一个小于等于需要找零金额的面值
let pointer;
for (let i = 0; i < cashMap.length; i++) {
if (cashMap[i][1] > shouldGive) {
pointer = i - 1;
break;
} else if (cashMap[i][1] === shouldGive) {
pointer = i;
break;
}
}

let tempGive = shouldGive;
let Tpointer = pointer;
// 定义最终返回的数组
let result = []


// * 下面是需要反复修改的代码
// sub 表示Tpointer指向的这个面值应该出几张
let sub = Math.floor(tempGive / cashMap[Tpointer][1])
while (Tpointer >= 0) {
if (sub * cashMap[Tpointer][1] > cid[Tpointer][1]) {
sub = cid[Tpointer][1] / cashMap[Tpointer][1];
result.push([cid[Tpointer][0], sub * cashMap[Tpointer][1]])
tempGive = (tempGive - sub * cashMap[Tpointer][1]).toFixed(2)
Tpointer--;
if (Tpointer < 0) return { status: "INSUFFICIENT_FUNDS", change: [] };
sub = Math.floor(tempGive / cashMap[Tpointer][1]);
} else {
result.push([cid[Tpointer][0], sub * cashMap[Tpointer][1]])
tempGive = (tempGive - sub * cashMap[Tpointer][1]).toFixed(2)
Tpointer--;
if (Tpointer < 0) break;
sub = Math.floor(tempGive / cashMap[Tpointer][1]);
}
}
result = result.filter(item => item[1] !== 0)

const cidSum = cid.reduce((pre,item) => pre + item[1],0)
for (let i = 0; i < result.length; i++) {
if (cidSum === shouldGive) {
let test = [];
for (let v of cashMap) {
if (v[0] === result[i][0]) {
test.push([v[0],result[i][1]])
} else {
test.push([v[0],0])
}
}
return {
status: 'CLOSED',
change: test
}
}
}
return { status: "OPEN", change: result }
}

checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]);

题目反思

  • 遇到难题不要怕,首先要学会将难题分解成一个一个的小问题。
  • 通过解决一个又一个的小问题,大的困难问题自然而解。
  • 必须熟练掌握四舍五入,保留小数,求和,去重等常见的API操作方法。

JustinFreeCodeCamp阅读需 4 分钟

题目描述

image.png

解题思路

  • 本题我采用的是正则的方法,通过考虑多种情况,因为所有的测试案例都已经给出,只要能够将所有情况考虑全面,通过正则表达式就可以通过测试。
  • 本题可能不是最优解,如果读者有其他更优解,欢迎留言评论。

解题代码

function telephoneCheck(str) {
let reg = /^1\s?\(\d{3}\).?\d{3}.?\d{4}|^1\s\d{3}[\(|-]\d{3}[-]\d{4}|^\d{10}$|\d{3}\s\d{3}\s\d{4}|^\(\d{3}\)\d{3}-\d{4}|^\d{3}-\d{3}-\d{4}$/
const bol = reg.test(str);
return bol
}

题目反思

熟练掌握正则表达式将极大的提高你的开发效率。


JustinFreeCodeCamp阅读需 1 分钟

题目描述

image.png

解题思路

  1. 首先遍历每一个字符。
  2. 通过charCodeAt()来判断字符的ASCII码值,如果该值在A-Z之间继续判断-13之后是否还在这个范围,如果还在这个范围直接通过charCodeAt()进行转换字符即可。
  3. 如果该值不在A-Z之间,直接进行拼接原字符即可。

实现代码

function rot13(str) {
let temp = '';
for (let v of str) {
if (v.charCodeAt() < 65 || v.charCodeAt() > 90) {
temp = temp + v
} else {
if (v.charCodeAt()-13 < 65) {
temp = temp + String.fromCharCode(91 - (65 - v.charCodeAt() + 13))
} else {
temp = temp + String.fromCharCode(v.charCodeAt()-13)
}
}
}
temp
return temp;
}

rot13("SERR CVMMN!");

题目链接

凯撒密码

题目反思

  • 学会使用charCodeAt()将字符转换为对应的ASCII码值。
  • 学会使用fromCharCode将ASCII码值转换为对应的字符。
  • 学会使用new Map(数组),来将一个数组转换为对应的Map,这样比一个一个的添加进Map要方便的多。

JustinFreeCodeCamp阅读需 1 分钟

题目描述

image.png

测试实例

解题思路

  • 构造罗马数字和整数的基本元素对应哈希表
  • 将目标整数依次除以哈希表的每一个元素,并向下取整,如果取整后结果大于0,则拼接上述结果个数个罗马数字,然后对哈希表中的对应整数取余赋值给num
  • 如何构造这个哈希表是本题的关键难点。

解题代码

function convertToRoman(num) {
const map = new Map([['M',1000],['CM',900],['D',500],['CD',400],['C',100],['XC',90],['L',50],['XL',40],['X',10],['IX',9],['V',5],['IV',4],['I',1]]);
let result = '';
for (let v of map) {
const temp = parseInt(num/v[1],0);
if (temp > 0) {
for (let i = 0; i < temp; ++i) {
result += v[0]
}
}
num = num % v[1]
}
return result
}

convertToRoman(44);

启示

  • 学会使用parseInt向下取整

FreeCodeCamp阅读需 1 分钟

今天我在练习FreeCodeCamp的时候,发现一道很有意思的初级算法题目,特地和大家分享一下。

题目描述

找到可以被两者以及这些参数之间范围内的所有序列号均分的所提供参数的最小公倍数。

该范围将是一个由两个数字组成的数组,不一定按数字顺序排列。

例如,如果给定 1 和 3,请找出 1 和 3 的最小公倍数,该倍数也可以被1 和 3之间的所有数字整除。 这里的答案是 6。

测试实例

解题思路

当我刚刚看到这道题目的时候,我在想求最小公倍数这还不简单?但是事情仿佛没那么容易,原因在于题目中让我们求的不是两个数字的最小公倍数,而是这个区间范围内的最小公倍数,所以看懂题目很关键。

难点:如何求两个数的最小公倍数

思路

  1. 首先默认两个数字中较大的那个为最小公倍数。
  2. 通过while循环,只要默认的最小公倍数小于等于两数的乘积便进入循环,如果这个默认的最小公倍数对左边的数趋于为零,说明这个是最小公倍数直接返回即可,反之,让这个默认的最小公倍数加上右边的值继续循环。

代码

// 获取最小公倍数的函数
function getSCM(left, right) {

// 首先默认最小公倍数为right
let SCM = right;

while (SCM <= right * left) {
if (SCM % left === 0) {
return SCM
} else {
SCM = SCM + right;
}
}
}

解题代码

function smallestCommons(arr) {
arr.sort((next, pre) => next - pre);

// 获取最小公倍数的函数
function getSCM(left, right) {

// 首先默认最小公倍数为right
let SCM = right;

while (SCM <= right * left) {
if (SCM % left === 0) {
return SCM
} else {
SCM = SCM + right;
}
}
}

// 生成数组
const newArr = [];
for (let i = arr[0]; i <= arr[1]; i++) {
newArr.push(i);
}
let result = arr[0] * (arr[0] + 1);
// 通过循环不断更新最小公倍数
for (let i = 2; i < newArr.length; i++) {
result = getSCM(newArr[i], result);
}
return result;
}


smallestCommons([1, 5]);

本题给我们的启示

  1. 学会通过循环的方式来求两个数字的最小公倍数。
  2. 学会通过更新的方式来获取,范围内的最小公倍数。

参考链接


FreeCodeCamp阅读需 3 分钟