Day07 JavaScript(Algorithm)

Free Code Camp的JavaScript算法

翻轉字符串(Reverse a String

實現(xiàn):先把字符串轉化成數(shù)組,再借助數(shù)組的reverse方法翻轉數(shù)組順序,最后把數(shù)組轉化成字符串。

function reverseString(str) {
  newStr = str.split("");    //將字符串分割為單個字符,并且每個字符作均作為數(shù)組的一個元素
  newStrReverse = newStr.reverse();      //翻轉數(shù)組元素順序
  strUnordered = newStrReverse.join("");    //連接數(shù)組的每個元素,沒有分隔符,組成一個字符串
  return strUnordered;
}
reverseString("hello");

計算一個整數(shù)的階乘(Factorialize a Number

使用n表示一個整數(shù),階乘代表所有小于或等于n的整數(shù)的乘積,階乘寫成n!
n! = 1 * 2 * 3 * ... * (n-1) * n。

function factorialize(num) {
  if(num <= 1) {
    return 1;            //處理num為0和1的情況,0!等于1。
  } else {
     return num * factorialize(num - 1);     //遞歸調用factorialize()函數(shù)
  }
}
factorialize(5);

字符串回文(Check for Palindromes

01、搗鼓了一下午,終于把回文數(shù)弄出來了。之前一直卡在怎么匹配出不帶標點和空白的字符串上,finally還是找到了,就是個枚舉的正則表達式...順帶看了點正則表達式的知識,明、后天好好看看正則表達式的內容。
02、就是找到了效率高一點的判斷回文數(shù)的方法

  • 如果一個字符串忽略標點符號、大小寫和空格,順著讀和倒著讀相同,則這個字符串是回文palindrome
  • 需要去掉字符串的標點符號和空格,并且將字符串全部轉化為小寫(或大寫)來驗證字符串是否回文。
function palindrome(str) {
    //匹配所有標點符號(英文的),并且匹配所有空白符(/s)
    var expression = /[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|<|\.|>|\/|\?|\s]+/g; 

    //使用replace()方法將所有標點和空白替換為空,相當于將所有文本字符連接在一起;并且將所有字符轉化為小寫(不會改變原字符串)
    var allChar = str.replace(expression, "").toLowerCase(); 

    //將字符串分割為單子字符數(shù)組,反轉數(shù)組,再合并數(shù)組成一個字符串
    var allLowerChar = allChar.split("").reverse().join("");  、

    //比較原字符串與反轉后字符串是否相同,相同返回true,不同返回false
    if(allLowerChar === allChar) {
      return true;
    } else {
      return false;
    }
}
palindrome("woca");     //調用

注:使用正則表達式expression = /[\~|\|!|@|#|$|%|^|&|*|(|)|-|_|+|=|||\|[|]|{|}|;|:|"|'|,|<|.|>|/|?]+/g`可以匹配字符串中的所有標點符號。

去掉開頭的\ |,用于匹配空格,使用后面的\s來匹配所有的空白符。

  • 使用上述方法判斷回文字符串,方便簡單,但是效率不高,字符串的split()、reverse()、join()需要很多額外的操作。
  • 回文字符串的特點:第一個字符和最后一個字符相同,第二個字符和倒數(shù)第二個字符相同...(回文字符串從左向右或是從右向左讀都相同

  • 遞歸方法判斷--推薦方法
    遞歸的作用在于不斷減小所處理問題的規(guī)模,直到可以解決為止。
    回文字符串問題:可以每次比較端部的字符,如果相同則去掉,再次比較端部字符;如果不同則返回false。直到只剩中間的字符、或不剩下字符時,返回true。
function isPalindrome(str) {
    var expression = /[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|<|\.|>|\/|\?|\s]*/g; 
    var allChar = str.replace(expression, "").toLowerCase(); 
  
    for(var i = 0, j = allChar.length - 1; i < j; i++, j--) {
      if(allChar.charAt(i) !== allChar.charAt(j)) {
        return false;
      }       //.charAt(i)返回字符串索引為i位置的字符
    } 
    return true;    //如果執(zhí)行完循環(huán)沒有退出,`str`為回文字符串
}
isPalindrome("ooaaoo");

找到句子中最長的單詞(Find the longest world in a string

  • 找到提供的英文句子(字符串)中最長的單詞,并計算它的長度;函數(shù)返回值是一個數(shù)組。
  • 自己的思路:將整個字符串以空格分割,構建以每個單詞為元素的數(shù)組(字符串的.split( )方法);在根據(jù)單詞的長度排序整個數(shù)組,最長的字符串在數(shù)組的端部。
function findLongestWord(str) {
    var strArray = str.split(" ");   //轉化為以單詞為元素的數(shù)組,以空格為分隔符
    var strSort = strArray.sort(function(a, b) {
      return b.length - a.length;      //遞減排序(如果a-b則是遞增排序),看看`sort(a, b)`的文檔
   });
  
    var lenMax = strSort[0].length;
  
    return lenMax;
}
findLongestWord("The quick brown fox jumped over the lazy dog");
  • 可能存在的問題
    1、沒有去掉句子中的標點符號
    2、當一個句子中有多個單詞長度相同時如何處理
function titleCase(str) {
    return str.toLowerCase().split(' ').map(function(word) {
      return word.charAt(0).toUpperCase() + word.slice(1);
    }).join(' ');     //先將字符串全部轉化為小寫,再以空格分割為以單詞為元素的數(shù)組,然后將每個單詞的首字母大寫,最后以空格連接每個元素,重新組合為字符串。
}
titleCase("I'm a little tea pot");

返回數(shù)組中的最大值(Return Largest Numbers in Arrays

  • 數(shù)組的元素是數(shù)值數(shù)組,分別找到每個子數(shù)組的最大值,將其串聯(lián)起來形成一個新的數(shù)組。
  • 思路:寫一個函數(shù)largeOne(arr1),其功能是找到一個數(shù)組中的最大值,并將其返回;再寫另一個函數(shù),分別將每個數(shù)組作為參數(shù)傳入largeOne,最后將得到的值添加到一個新的數(shù)組中.push()方法。
//返回一個數(shù)組中的最大值
function largeOne(arr) {
    var max = 0;
    for(var i = 0; i < arr.length; i++) {
      if(arr[i] > max) {
        max = arr[i];
      }
    }
    return max;
}
//分別迭代每個數(shù)組,把最大值添加到新的數(shù)組中
function largestOfFour(arr) {
    var newArr = [];
    for(var i = 0; i < arr.length; i++) {
      newArr.push(largeOne(arr[i]));       //選出最大的值并添加到新的數(shù)組中
    }
    return newArr;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);

檢查一個字符串的結尾(Confirm the Ending

  • 檢查一個字符串str是否以指定的字符串target結尾。
  • 思路:利用.slice()方法,根據(jù)target的長度,提取出str的末尾部分,將之與target比較,如果相同返回true
function confirmEnding(str, target) {
    if(str.slice(str.length - target.length, str.length) === target) {   //忽略slice()的第二個參數(shù),默認提取到字符串的末尾
      return true;
    } else {
    return false;
    }
}
confirmEnding("Bastian", "n");
  • 使用.substr()方法,類似于slice()方法。
function confirmEnding(str, target) {
    if(str.substr(str.length - target.length) === target) {
      return true;
    } else {
      return false;
    }
}
confirmEnding("Bastian", "n");

重復一個字符串(Repeat a String

  • 重復一個字符串num次,如果num為負,則返回一個空字符串。
  • 思路:采用+操作符,可以連接+左右兩邊的字符串,之間沒有空格。使用一個for循環(huán)實現(xiàn)疊加。
  function repeat(str, num) {
    var newStr = "";
    if(num <= 0) {
      return "";
    } else {
        for(var i = 0; i < num; i++) {
          newStr += str;
        }
      }  
    return newStr;
}
repeat("abc", 3);

截斷字符串(Truncate a String

  • 問題描述:如果字符串長度大于指定的參數(shù)num,則將多余的部分用...表示。(插入帶字符串尾部的三個.也會計入字符串長度,但是如果參數(shù)num <= 3,則添加的三個.不會計入字符串長度
  • 思路:用一個if判斷字符串長度是否大于num,如果false則返回原字符串;如果true,在繼續(xù)判斷num與3的關系,大于3時,.計入字符串的長度;小于3時,.不計入字符串長度。
function truncate(str, num) {
    //如果字符串長度大于指定參數(shù)num
    if(str.length > num) {
      //如果參數(shù)num > 3
      if(num > 3) {
        return str.slice(0, num - 3) + "...";    //-3是三個.會計入字符串的長度
      } else {
        return str.slice(0, num) + "...";      //三個.不計入字符串長度
      }
    } else {
      return str;
    }
}
truncate("A-tisket a-tasket A green and yellow basket", 11);

將數(shù)組分割為若干塊(Chunky Monkey

  • 把數(shù)組arr按照指定的size分割成若干個數(shù)組塊,例如chunk([1,2,3,4],2)=[[1,2],[3,4]];,chunk([1,2,3,4,5],2)=[[1,2],[3,4],[5]];。
  • 思路:先分離arr.length < sizesize <= 0的情況,再利用.slice().push()操作,利用for循環(huán)迭代提取arr的數(shù)組塊,并添加到新數(shù)組中。
function chunk(arr, size) {
  var newStr = [];
  var temp = [];
  var len = arr.length;
  
  if(len < size || size <= 0) {
    return arr;
    } else {
    for(var i = 0; i < len; i += size) {
      temp = arr.slice(i, i + size);
      newStr.push(temp);
      }
    return newStr;
    }
}
chunk(["a", "b", "c", "d"], 2);

注意:參考資料

Slasher Flick

  • 返回一個數(shù)組被截斷n個元素后還剩余的元素,截斷從索引0開始。
  • 思路:直接采用數(shù)組的.slice()方法獲取元素組的后n個元素,賦值給新的空數(shù)組。
function slasher(arr, howMany) {
    if(arr.length < howMany) {
      return [];
    } else {
      var newArr = arr.slice(-(arr.length-howMany));  //采用負索引,訪問數(shù)組的倒數(shù)元素
      return newArr;
    }
  }
slasher([1, 2, 3], 2);

注:采用.splice()方法,可以刪除原數(shù)組中的前n個元素。.splice()會直接修改原數(shù)組。

function slasher(arr, howMany) {
    if(arr.length < howMany) {
      return [];
    } else {
      arr.splice(0, howMany);   //參考MDNjs的文檔
      return arr;
    }
}
slasher([1, 2, 3], 2);

Mutations

  • 如果數(shù)組第一個字符串元素包含了第二個字符串元素的所有字符(忽略大小寫),函數(shù)返回true,否則返回false。
  • 采用[indexOf()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf)方法,返回指定值在字符串對象中首次出現(xiàn)的位置。如果不存在,則返回-1`。
function mutation(arr) {
    var str1 = arr[0].toLowerCase();
    var str2 = arr[1].toLowerCase();
    var len = str2.length;
  
    //遍歷str2的每個字符,如果有一個字符不在str1中,則返回false,如果全部通過,則返回true
    for(var i = 0; i < len; i++){
      if(str1.indexOf(str2[i]) === -1) {
        return false;
      }
    }
    return true;
}
mutation(["hello", "hey"]);

Falsy Bouncer

  • 刪除數(shù)組中的所有假值(false、null、0、undefined、NaN)。
  • 思路:采用.filter()方法,過濾掉返回值為false的數(shù)組元素,不會改變原數(shù)組。參考Boolean Object
function isFake(element) {
   if(element) {
     return true;
   } else {
     return false;
   }
}
function bouncer(arr) {
   var newArr = arr.filter(isFake);  
   return newArr;        //filter()方法不會改變原數(shù)組
}
bouncer([7, "ate", "", false, 9]);

Seek and Destroy

  • 實現(xiàn)一個摧毀destroy()函數(shù),第一個參數(shù)是待摧毀的數(shù)組,其余的參數(shù)是待摧毀的值。
  • 思路:使用arguments.length獲得傳入的參數(shù)個數(shù),去掉第一個,剩下的為需要摧毀的值。使用.includes()方法作為過濾函數(shù),判斷第一個數(shù)組參數(shù)中的每個元素是否出現(xiàn)在后面的參數(shù)中,出現(xiàn)則過濾掉;其余分別.push()到新的孔數(shù)組中。
function destroyer(arr) {
    var tempArr = [];
    var newArr = [];
    var len = arguments.length;
    //構建其余參數(shù)數(shù)組
    for(var i = 1; i < len; i++) {
      tempArr.push(arguments[i]);       //使用arguments.length可以獲得傳入的參數(shù)數(shù)量
    }
  
    //遍歷第一個數(shù)組參數(shù),如果數(shù)組元素在tempArr中,則淘汰;如果不在,則增加到newArr中,最后得到淘汰后的數(shù)組
    for(var j = 0; j < arguments[0].length; j++) {
      if(!tempArr.includes(arguments[0][j])) {
         newArr.push(arguments[0][j]);
         }
    }
    return newArr;               //使用arguments.length可以獲得傳入的參數(shù)個數(shù)
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);

注:.filter()方法沒有想出怎么實現(xiàn)。。。

Where Do I Belong

  • 先給數(shù)組排序,然后找到指定值在數(shù)組中的位置,最后返回位置的索引。
  • 野路子:先將元素添加到數(shù)組后面,再對數(shù)組排序,然后遍歷數(shù)組,找到插入的元素,最后循環(huán)變量i即是索引。
function where(arr, num) {
  // Find my place in this sorted array.
    arr.push(num);
    arr.sort(function(a, b) {
      return a - b;
    });
  
    for(var i = 0; i < arr.length; i++) {
      if(arr[i] === num) {
        return i;   //返回第一個值得索引
      }
    }
}
where([5, 3, 20, 3], 5);

Caesars Cipher

  • Caesars Cipher又稱凱撒碼(位移碼),密碼中的字母按照指定的位數(shù)來做位移,密碼中的字母按照指定的數(shù)量來做位移。ROT13密碼:字母向后移動13個位置,A->NB->ON->A...,ROT13(ROT13(x)) == x。
  • 思路:先將字符串.split("")方法,將字符串中的每個字符分給為一個數(shù)組元素,然后遍歷數(shù)組元素。如果Unicode碼在[97, 122]之間(只有大寫字母),則按照算法向后推算;如果不在,則保持原狀(空格和標點不處理)。
  • 方法:當Unicode碼在[65-77]之間時,直接每個加上13然后重新賦值;在[78-90]之間時,每個加上13,再減去26,最后賦值。
function rot13(str) { // LBH QVQ VG!
    var newArr = str.split("");
    var arr = [];
  
    //大寫字母的Unicode碼從65到90
    //如果在78-90之間,Unicode值減去13,;在65-77之間,Unicode值加上13
    //最后轉化為字符。
    for(var i = 0; i < newArr.length; i++) {
      if(newArr[i].charCodeAt() <= 90 && newArr[i].charCodeAt() >= 78) {
        arr[i] = String.fromCharCode(newArr[i].charCodeAt() - 13);
      } else if(newArr[i].charCodeAt() <= 77 && newArr[i].charCodeAt() >= 65) {
        arr[i] = String.fromCharCode(newArr[i].charCodeAt() + 13);
      } else {
        arr[i] = newArr[i];      //不在65-90之間的不處理,略去空格和標點
      }
    } 
    return arr.join("");      //組合回字符串
}
// Change the inputs below to test
rot13("SERR PBQR PNZC");

居然做完了

哈哈,花了也不知道幾天的空余時間,終于刷完了這點兒題,其中大部分都是自己完成,有些參考了網(wǎng)上的代碼,不過都是親手敲出來的碼,哈哈哈哈,自己居然能想出來!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容