JavaScript 刷题 —— 二

第一题:数组连续数相加求最大和

题目

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)
}
// 答案区写法差不多
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值