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)
}
// 答案區寫法差不多
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章