题目列表
第一题:数组连续数相加求最大和
题目
maxSequence([-2, 1, -3, 4, -1, 2, 1, -5, 4])
// should be 6: [4, -1, 2, 1]
如果最大和小于零就返回零
代码
// 原始思路:遍历相加,如果遇到更大和值,就替换掉当前最大和
var maxSequence = function(arr){
// ...
var total = 0;
for (var i = 0; i < arr.length; i++) {
for (var j = i,sum=0; j < arr.length; j++) {
sum += arr[j];
total = Math.max(sum,total)
}
}
return total
}
// 答案区代码
/**
一、有点不太好懂
解析:
sum 值和目前最小值比较,更小的为最小值,这个最小值就是也就是目前累加的值
以相加的和想象为折线图作为理解方式,最大的和应该是最大峰值减去最小低谷的值
*/
var maxSequence = function(arr){
var min = 0, ans = 0, i, sum = 0;
for (i = 0; i < arr.length; ++i) {
sum += arr[i];
min = Math.min(sum, min);
ans = Math.max(ans, sum - min);
}
return ans;
}
第二题:根据字符串中的数字排序
题目
Examples
“is2 Thi1s T4est 3a” --> “Thi1s is2 3a T4est”
“4of Fo1r pe6ople g3ood th5e the2” --> “Fo1r the2 g3ood 4of th5e pe6ople”
“” --> “”
代码
// 原始思路
function order(words){
// ...
return words.split(' ').sort((a,b) =>
a.replace(/[a-z]/gi,'') - b.replace(/[a-z]/gi,'')
).join(' ')
}
// 答案区正则有更简单的写法
function order(words){
return words.split(' ').sort(function(a, b){
return a.match(/\d/) - b.match(/\d/);
}).join(' ');
}
第三题:数字处理后排序
题目
“56 65 74 100 99 68 86 180 90” ordered by numbers weights becomes: “100 180 90 56 65 74 68 86 99”
56 = 5+6=11 这样计算完之后再进行排序,比较规则难受的地方在于如果如果遇到前后两个相等的情况,需要用字符串的比较规则再对其进行排序
代码
// 原始思路
function orderWeight(strng) {
// your code
return strng.split(' ').sort((a,b) => {
let ta = a.split('').reduce((c,d)=>(c-(-d))) - b.split('').reduce((e,f)=>(e-(-f)))
switch(true){
case ta < 0: return -1;break;
case ta > 0: return 1;break;
case ta == 0: return a < b ? -1 : 1
}
}).join(' ')
}
// 答案区解决方法
// 一、localeCompare 比较字符串
function orderWeight(strng) {
const sum = (str)=>str.split('').reduce((sum,el)=>(sum+(+el)),0);
function comp(a,b){
let sumA = sum(a);
let sumB = sum(b);
return sumA === sumB ? a.localeCompare(b) : sumA - sumB;
};
return strng.split(' ').sort(comp).join(' ');
}
第四题:正则匹配
题目
至少六个字符
包含小写字母
包含大写字母
包含数字
有效密码只能是字母数字字符。
代码
// 原始思路
function validate(password) {
console.log(password)
return /.{6,}/.test(password)
&& /[A-Z]+/.test(password)
&& /[a-z]+/.test(password)
&& /[0-9]+/.test(password)
&& !/[^0-9A-z]+/.test(password);
}
// 答案区的正则
/**
[^abc] 查找任何不在方括号之间的字符。
^n 匹配任何开头为 n 的字符串。
n$ 匹配任何结尾为 n 的字符串。
?=n 匹配任何其后紧接指定字符串 n 的字符串。
这个举例如下方便理解:
var str="Is this all there is";
var patt1=/is(?= all)/g;
匹配到的是 this 中的 is
所以下面的正则意味着不论匹配到什么都会返回到初始位置
*/
function validate(password) {
return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])\w{6,}$/.test(password);
}
第五题:数组比较与去重
题目
有一个序列u,其中u的定义如下:
u[0]= 1是u中的第一个数字。
对于u中的每个x,y = 2 * x + 1和z = 3 * x + 1也必须在u中。
例如:u = [1、3、4、7、9、10、13、15、19、21、22、27,…]
求出 u[n] 的值
代码
// 原始思路
/**
这里有个问题就是 i < 5*n 这一块有待优化,当查询的n更大时,5就不够用了
*/
function dblLinear(n) {
// your code
let arr = [1];
for(let i=0;i<5*n;i++){
// 实验push返回值为数组长度
arr[arr.push(arr[i]*2 + 1)] = arr[i]*3 + 1;
}
// 去重并过滤
arr = arr.sort((a,b)=>a-b).filter((e,i,arr) => e !== arr[i-1])
return arr[n]
}
// 答案区优秀算法
// 一、为 2x+1 和 3x+1 分别设置标识,这里的 eq 用于保证 ai 和 bi 相等时继续运行
function dblLinear(n) {
var ai = 0, bi = 0, eq = 0;
var sequence = [1];
while (ai + bi < n + eq) {
var y = 2 * sequence[ai] + 1;
var z = 3 * sequence[bi] + 1;
if (y < z) { sequence.push(y); ai++; }
else if (y > z) { sequence.push(z); bi++; }
else { sequence.push(y); ai++; bi++; eq++; }
}
return sequence.pop();
}
// 二、这里为源代码补充了相邻数字去重,然而实际上运行不到需要去重的那一步,
// 比如 2*15+1 = 3*10+1;当 n 为 20 时,i 运行到 14 就已经停下了
function dblLinear(n) {
var h = [];
var x2 = 1, x3 = 1;
var i = 0, j = 0;
for (var index = 0; index < n+1; index++)
{
h[index] = x2 < x3 ? x2 : x3;
if (h[index] == x2) x2 = 2 * h[i++] + 1;
if (h[index] == x3) x3 = 3 * h[j++] + 1;
}
h=h.filter((e,i,arr) => e !== arr[i-1])
return h[n];
}
第六题:处理连续数字
题目
对连续的数字进行处理
Example:
solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]);
// returns “-6,-3-1,3-5,7-11,14,15,17-20”
代码
// 原始思路,使用map拷贝成新数组
// 从后往前检查,有几个连续的数,就对这几个数进行替换
// 使用变量 a 作为连续数字数量判断标识
function solution(list){
// TODO: complete solution
var a=0;
var c = list.map(item=>item);
for(var i=list.length-1;i>=0;i--){
if(list[i] - list[i-1] == 1){
a++;
}else {
if(a>1){c.splice(i,a+1,(list[i])+'-'+(list[i+a]))}
a=0;
}
}
return c.toString()
}
// 答案区处理方式差不多
return c.join()
第七题:将零移动到数组末尾
题目
将所有零移动到末尾的算法,同时保留其他元素的顺序
moveZeros([false,1,0,1,2,0,1,3,“a”]) // returns[false,1,1,2,1,3,“a”,0,0]
代码
// 原始思路
var moveZeros = function (arr) {
// TODO: Program me
var i = 0;
arr = arr.filter((item) => {
if(item !== 0) return true;
i++; return false
})
while(i>0){
arr.push(0);
i--
}
return arr
}
// 答案区代码
// 一、先取出非零的,在取出为零的,进行拼接
var moveZeros = function (arr) {
return arr.filter(function(x) {return x !== 0}).concat(arr.filter(function(x) {return x === 0;}));
}
第八题:求数组差值和
题目
[
[1,4],
[7, 10],
[3, 5]
]
这些间隔的长度之和为7。由于[1,4]和[3,5]重叠,我们可以将间隔视为[1,5],其长度为4。
Examples:
sumIntervals( [
[1,2],
[6, 10],
[11, 15]
] ); // => 9
sumIntervals( [
[1,4],
[7, 10],
[3, 5]
] ); // => 7
代码
// 原始思路,循环比较,计算差值再相加,简直是代码区的泥石流
// 可读性差,也不如代码区的思路简单
function sumIntervals(intervals){
//TODO
var newArr = intervals.map(item=>item);
if(intervals.length > 1){
for(var i=0;i<newArr.length;i++){
for(var j=i+1;j<newArr.length;j++){
if(newArr[i][1] <= newArr[j][1] && newArr[i][1] >= newArr[j][0]){
if(newArr[i][0] < newArr[j][0]){
newArr[j][0] = newArr[i][0];
}
newArr[i] = [0,0]
}else if(newArr[j][1] <= newArr[i][1] && newArr[j][1] >= newArr[i][0]){
if(newArr[j][0] < newArr[i][0]){
newArr[i][0] = newArr[j][0];
}
newArr[j] = [0,0]
}
}
}
console.log(intervals,newArr)
return newArr.map(a=>a[1]-a[0]).reduce((a,b)=>a+b)
}else{
return newArr[0][1] - newArr[0][0]
}
}
// 答案区代码
// 一、创建一个新数组,用于存储区间内数字
// 重复的数字不会存储进去,这样最终计算数组的长度就是要求的值
// 美中不足速度有待提高
function sumIntervals(intervals){
var numbers = [];
intervals.forEach(([a,b])=>{
for (a; a<b; a++) {
if (numbers.indexOf(a) == -1) numbers.push(a);
}
});
return numbers.length;
}
第九题:字符串高位补零
题目
Examples:
foo -> foo1
foobar23 -> foobar24
foo0042 -> foo0043
foo9 -> foo10
foo099 -> foo100
代码
// 原始思路,把数字部分抽出来加一,并对其长度进行高位补零
function incrementString (strng) {
// return incrementedString
const num = strng.split('').filter(item=>/[0-9]$/.test(item)).join('');
return strng.split('').filter(item=>/[^0-9]$/.test(item)).join('')
.concat((''+(+num+1)).length > num.length
? (+num+1)
: (Array(num.length).join(0)+(+num+1)).slice(-num.length))
}
// 答案区的写法
// 一、一个有趣的写法
function incrementString(str){
var c = str[str.length-1];
switch(c){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8': return str.substring(0, str.length-1) + (parseInt(c)+1);
case '9': return incrementString(str.substring(0, str.length-1)) + 0;
default: return str+"1";
}
}
// 二、最简单的写法,我想我得好好研究一下正则了
let incrementString = str => str.replace(/([0-8]|\d?9+)?$/, (e) => e ? + e + 1 : 1)
第十题:数组累加
题目
4 * (1 + 1 + 2 + 3 + 5 + 8) = 4 * 20 = 80
perimeter(5) should return 80
perimeter(7) should return 216
代码
// 原始想法
function perimeter(n) {
let arr = [1,1],i=1;
if(n<1) return 4;
while(i<n){
arr.push(arr[i] + arr[i-1])
i++
}
return 4 * arr.reduce((a,b)=>a+b)
}
// 答案区写法差不多