FreeCodeCamp 算法題 3

比較字符串 (Mutations)

題目:www.freecodecamp.cn/challenges/…正則表達式

參考博客:singsing.io/blog/fcc/ba…數組

若是數組第一個字符串元素包含了第二個字符串元素的全部字符,函數返回 true 。 舉例,["hello", "Hello"]應該返回 true,由於在忽略大小寫的狀況下,第二個字符串的全部字符均可以在第一個字符串找到。app

思路:函數

  • 由於忽略大小寫,因此咱們所有轉成小寫字母:String.toLowerCase()
  • 而後找字符串是否存在字符:String.indexOf()
  • 遍歷
function mutation(arr) {
  const s1 = arr[0].toLowerCase()
  const s2 = arr[1].toLowerCase()
  let result = true
  for (let i of s2) {
    if (s1.indexOf(i) === -1) {
      result = false
      return result
    }
  }
  return result;
}

mutation(["hello", "hey"]);
// 能夠不用 result
function mutation(arr) {
  const s1 = arr[0].toLowerCase()
  const s2 = arr[1].toLowerCase()
  for (let i of s2) {
    if (s1.indexOf(i) === -1) {
      return false
    }
  }
  return true
}

mutation(["hello", "hey"])
複製代碼

博客的思路:利用 filter測試

function mutation(arr) {
    var sourceStr = arr[0].toLowerCase();
    var targetArr = arr[1].toLowerCase().split("");

    var filteredArr = targetArr.filter(function (char) {
        return sourceStr.indexOf(char) === -1;
    })

    return filteredArr.length === 0;
}
複製代碼

filter 的思路就是利用數組的遍歷,那麼咱們也能夠用數組的 every優化

// 試一試
function mutation(arr) {
 const s = arr[0].toLowerCase()
 const a = arr[1].toLowerCase().split('')
 return a.every(item => s.indexOf(item) !== -1)
}
// 簡潔點
function mutation(arr) {
 return arr[1].toLowerCase().split('').every(item => arr[0].toLowerCase().indexOf(item) !== -1)
}

mutation(["hello", "hey"]);
複製代碼

過濾數組假值 (Falsy Bouncer)

題目:www.freecodecamp.cn/challenges/…ui

參考博客:singsing.io/blog/fcc/ba…spa

刪除數組中的全部假值。code

思路: 遍歷數組的元素,判斷是否爲真,爲真的話放進一個數組內,最後返回該數組。regexp

function bouncer(arr) {
  return arr.reduce((arr, item) => item ? arr.concat(item) : arr, [])
}

bouncer([7, "ate", "", false, 9]);

複製代碼

後面想一想,上一題的 filter ,這裏更應該用過濾的

function bouncer(arr) {
  return arr.filter(item => item)
  // 博客裏的是用了 !! 去作隱式轉換,不知道有沒有必要這樣作。
  // return arr.filter
}

bouncer([7, "ate", "", false, 9]);
// 而後 Boolean 是接受一個參數返回布爾值的構造函數,filter 接受的也是一個函數,該函數返回布爾值。
const bouncer = arr => arr.filter(Boolean)
複製代碼

摧毀數組 (Seek and Destroy)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/ba…

// 初次解法
function destroyer(...arr) {
  const a1 = arr[0]
  const a2 = arr.slice(1)
  return a1.reduce((arr, val) => a2.indexOf(val) === -1 ? arr.concat(val) : arr, [])
}

destroyer([1, 2, 3, 1, 2, 3], 2, 3);
複製代碼

再理解下題意,發現應該用的是 filter

function destroyer(...arr) {
  const a1 = arr[0]
  const a2 = arr.slice(1)
  return a1.filter(item => a2.indexOf(item) === -1)
}

destroyer([1, 2, 3, 1, 2, 3], 2, 3);
複製代碼

數組排序並找出元素索引 (Where Do I belong)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/ba…

題意: 一個數組,一個數字,而後這個數字在這個數組中,按小到大排序,它的下標應該是多少。

解法一:

  • 把數字添加到數組中 push, concat
  • 排序新的數組 sort
  • 找數組的位置 indexOf, findIndex

note:

  • indexOf:expects a value as first parameter.
  • findIndex:expects a callback as first parameter.
  • 若是是複雜的查找的話就用 findIndex,好比是查找 item.xx 這樣的話就要用 findIndex
function where(arr, num) {
  arr.push(num)
  arr.sort((a, b) => a - b)
  return arr.indexOf(num)
}

where([40, 60], 50);
複製代碼

解法二:不去排序,咱們去遍歷,而後計數

function where(arr, num) {
  var count = 0;
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] < num) {
      count++;
    }
  }
  return count;
}


where([40, 60], 50);

// 一樣是遍歷,只不過用的是 filter
function where(arr, num) {
  return arr.filter(item => item < num).length;
}
// 固然你用 map, reduce 也行,map 麻煩一些,其實仍是用了遍歷 + 計數的方式
const where = (arr, num) => arr.reduce((acc, item) => item > num ? acc.concat(item) : acc, []).length

where([40, 60], 50);
複製代碼

凱撒密碼 (Caesars Cipher)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/ba…

題意: 給你一個大寫字母的字符串,而後你把字符串的每個字母向右移動13位,超出了再循環回來,組成一個新的字符串返回。

須要用到的:

  • String.charCodeAt()

  • String.fromCharCode()

  • 分割成數組再遍歷,最後拼接字符串

function rot13(str) { // LBH QVQ VG!
  var arr = str.split('');
  return arr.map(item => /[A-Z]/.test(item) ? String.fromCharCode(item.charCodeAt() % 26 + 65) : item).join('');
}

rot13("SERR PBQR PNZC");  // 你能夠修改這一行來測試你的代碼

// /[A-Z]/.test(item) 只替換大寫字符
// item.charCodeAt() % 26 + 65 只是由於 'A'.charCodeAt() => 65, x % n = [0, n - 1]
複製代碼
  • replace() 替換
function rot13(str) { // LBH QVQ VG!
 return str.replace(/[A-Z]/g, char => {
   return String.fromCharCode(char.charCodeAt() % 26 + 65)
 })
}

rot13("SERR PBQR PNZC");  // 你能夠修改這一行來測試你的代碼
複製代碼

給定範圍內的數字總和 (Sum All Numbers in a Range)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/in…

題意:給一個數組,而後返回給定範圍的數字總和。

例如:[1, 4] => 1+2+3+4=10 返回 10

數學公式解法:n + n+1 + n+2 + ... + m = (n+m)(m-n+1)/2 = (m^2-n^2+n+m)/2

function sumAll(arr) {
  var a = arr[0], b = arr[1];
  return (Math.abs(a*a - b*b) + a+b) / 2;
}

sumAll([1, 4]);
複製代碼

循環疊加解法:首先要判斷兩數的大小,再循環疊加

function sumAll(arr) {
  var a = arr[0], b = arr[1], result = 0;
  if (a > b) {
    // 交換
    [a, b] = [b, a];
  }
  while(b >= a) {
    result += a;
    a++;
  }
  return result;
}

sumAll([1, 4]);
複製代碼

博客的另外一種解法:生成一個數組[n, n+1, n+2, ... , m],再遍歷求和。

function sumAll(arr) {
    var numArr = Array.from({length: Math.abs(arr[0] - arr[1]) + 1}, (_, i) => i + Math.min.apply(null, arr));
    return numArr.reduce((prev, next) => prev + next);
}
// 上面每次都要拿一次最小值,其實能夠提取出來的

// 也能夠用 Array() + Array.fill()
function sumAll(arr) {
  var min = Math.min(...arr); // var min = Math.min.apply(null, arr);
  var numArr = Array(Math.abs(arr[0] - arr[1]) + 1).fill(min);
  return numArr.reduce((acc, val, index) => acc + val + index);
}
複製代碼

比較兩數組差別 (Diff Two Arrays)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/in…

題意:比較兩個數組,而後返回一個新數組,該數組的元素爲兩個給定數組中全部獨有的數組元素。換言之,返回兩個數組的差別。

按照數學上集合來說就是,兩個集合並集減去它們的交集。

function diff(arr1, arr2) {
  var sum = [...new Set([...arr1, ...arr2])];
  return sum.filter(item => arr1.indexOf(item) === -1 || arr2.indexOf(item) === -1);
}

diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);
複製代碼

上面那個感受有點麻煩,又是拼接數組,又是集合轉數組,雖然能夠去除,可是看起來複雜了。

能夠直接拼接數組再過濾就好了。

function diff(arr1, arr2) {
  return arr1.concat(arr2).filter(item => arr1.indexOf(item) === -1 || arr2.indexOf(item) === -1)
}

diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);
複製代碼

找出對象包含的特定鍵值對 (Where art thou)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/in…

題意:

  • 給你一個對象數組,還有一個對象
  • 數組裏的對象都包含第二個參數裏的對象,還有鍵值相等
  • 返回一個過濾後的數組
// 首先返回的是數組,那麼用 filter
// 其次是數組的元素裏要包含對象的鍵值 Object.keys(obj) 返回給對對象可枚舉屬性(key)的字符串數組。
// 爲何是字符串數組,由於對象屬性都會轉爲字符串。
function where(collection, source) {
  return collection.filter(item => Object.keys(source).every(key => source[key] === item[key]));
}

where([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });
複製代碼

句中查找替換 (Search and Replace)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/in…

題意:

  • 使用給定的參數對句子執行一次查找和替換,而後返回新句子。
  • 第一個參數是將要對其執行查找和替換的句子。
  • 第二個參數是將被替換掉的單詞(替換前的單詞)。
  • 第三個參數用於替換第二個參數(替換後的單詞)。
  • 注意:替換時保持原單詞的大小寫。例如,若是你想用單詞 "dog" 替換單詞 "Book" ,你應該替換成 "Dog"。

思路一:

  • 句子分割成一個個單詞
  • 判斷被替換的單詞是否首字母大寫,修改替換的單詞
  • 找到被替換的單詞並替換掉
  • 再拼接成字符串
function myReplace(str, before, after) {
  var arr = str.split(' ');
  if (before.slice(0, 1).charCodeAt() < 91) {
  // 判斷條件用正則表達式也ok /[A-Z]/.test(before[0])
    after = after[0].toUpperCase() + after.slice(1);
  }
  arr.splice(arr.indexOf(before), 1, after);
  return arr.join(' ');
}

myReplace("A quick brown fox jumped over the lazy dog", "jumped", "leaped");
複製代碼

思路二:直接字符串替換

  • 首先看被替換的字符串首字母是否大寫,是的話修改替換的字符串
  • 匹配替換
function myReplace(str, before, after) {
  if (/[A-Z]/.test(before[0])) {
    after = after[0].toUpperCase() + after.slice(1);
  }
  return str.replace(before, after);
}

myReplace("A quick brown fox jumped over the lazy dog", "jumped", "leaped");
複製代碼

DNA 配對 (DNA Pairing)

題目:www.freecodecamp.cn/challenges/…

參考博客:singsing.io/blog/fcc/in…

題目意思就是:給你一段殘缺的鹼基,返回一段鹼基對,鹼基對有:A => T,C => G

輸入:GCG 輸出:[["G", "C"], ["C","G"],["G", "C"]]

思路:

  • 好像沒有什麼能夠優化的,感受就是寫死的。
  • 由於返回的是數組,那麼咱們先把字符串轉變爲數組。而後字符串長度多少,返回的數組長度就爲多少,因此能夠用 map 去遍歷生成新數組。
  • 以後就是數組去填充的內容了,怎麼對應上,咱們用一個對象去存儲。
// 這樣的話,取的時候方便一些
var obj = {
  'A': ['A', 'T'],
  'T': ['T', 'A'],
  'C': ['C', 'G'],
  'G': ['G', 'C']
};
// 這樣的話就要拼接
var obj = {
    A: 'T',
    T: 'A',
    C: 'G',
    G: 'C'
}
複製代碼
function pair(str) {
// 這個對象的屬性能夠不一樣加引號,它會自動轉換爲字符串的。
  var obj = {
    A: ['A', 'T'],
    T: ['T', 'A'],
    C: ['C', 'G'],
    G: ['G', 'C']
  };
  return str.split('').map(function(item) {
    return obj[item];
  });
}

pair("GCG");

function pair(str) {
  var obj = {
    A: 'T',
    T: 'A',
    C: 'G',
    G: 'C'
  };
  return str.split('').map(function(item) {
    return [item, obj[item]];
  });
}

pair("GCG");
複製代碼
相關文章
相關標籤/搜索