全文共14056字,预计学习时长36分钟

图源:unsplash

字符串是一系列字符,由常数或变量构成。它是编程语言中必不可少的数据类型。本文中将重点关注JavaScript字符串操作,但其原理和算法也可应用于其他语言。

参加技术面试时,面试官常常会关注以下内容:

· 编程技术

· 语言能力

· 解题技巧

本文不仅可以让你成功通过技术面试,对日常编码也很有用。代码要点格式中,我们列出了JavaScript字符串的几点重要特性,这是编程技能的基础。其中包括存在了20年的属性和方法,也涵盖ES2021中的特性。如有不清楚之处,可以有针对性地查漏补缺。JavaScript编程语言可以解决许多应用问题。这些算法或其变体,经常出现在真实的面试场景中。

字符串属性和方法

字符串用于表示和操作字符序列。字符串属性和方法有很多。以下是可供参考的代码示例,包括ES2020中的“matchAll”和ES2021中的“replaceAll”。

const str ='Today is a nice day!';        console.log(str.length); // 20      console.log(str[2]); // "d"      console.log(typeof str); // "string"      console.log(typeof str[2]); // "string"      console.log(typeofString(5)); //"string"      console.log(typeofnewString(str)); //"object"      console.log(str.indexOf('is')); // 6      console.log(str.indexOf('today')); // -1      console.log(str.includes('is')); // true      console.log(str.includes('IS')); // false      console.log(str.startsWith('Today')); // true      console.log(str.endsWith('day')); // false      console.log(str.split(' ')); // ["Today", "is", "a", "nice","day!"]      console.log(str.split('')); // ["T", "o", "d", "a","y", " ", "i", "s", " ","a", " ", "n", "i", "c","e", " ", "d", "a", "y","!"]      console.log(str.split('a')); // ["Tod", "y is ", " nice d","y!"]      console.log(str +1+2); // "Today is a nice day!12"      console.log(str + str); // "Today is a nice day!Today is a niceday!"      console.log(str.concat(str)); // "Today is a nice day!Today is a niceday!"      console.log(str.repeat(2)); // "Today is a nice day!Today is a nice day!"      console.log('abc'

映射和集合

对于字符串操作,我们需要在某处存储中间值。数组、映射和集合都是需要掌握的常用数据结构,本文主要讨论集合和映射。

集合

Set是存储所有类型的唯一值的对象。以下是供参考的代码示例,一目了然。

const set =newSet('aabbccdefghi');                        console.log(set.size); // 9                       console.log(set.has('d')); // true                       console.log(set.has('k')); // false                       console.log(set.add('k')); // {"a", "b", "c", "d","e" "f", "g", "h", "i","k"}                       console.log(set.has('k')); // true                       console.log(set.delete('d')); // true                       console.log(set.has('d')); // false                       console.log(set.keys()); // {"a", "b", "c","e" "f", "g", "h", "i","k"}                       console.log(set.values()); // {"a", "b", "c","e" "f", "g", "h", "i","k"}                       console.log(set.entries()); // {"a" => "a","b" => "b", "c" => "c","e" => "e",                       // "f"=> "f", "g" => "g", "h" =>"h"}, "i" => "i", "k" =>"k"}                       const set2 =newSet();                       set.forEach(item => set2.add(item.toLocaleUpperCase()));                       set.clear();                       console.log(set); // {}                       console.log(set2); //{"A", "B", "C", "E", "F","G", "H", "I", "K"}                       console.log(newSet([{ a: 1, b: 2, c: 3 }, { d: 4, e: 5 }, { d: 4, e: 5 }]));                       // {{a: 1, b: 2,c: 3}, {d: 4, e: 5}, {d: 4, e: 5}}                       const item = { f: 6, g: 7 };                       console.log(newSet([{ a: 1, b: 2, c: 3 }, item, item]));                       // {{a: 1, b: 2,c: 3}, {f: 6, g: 7}}

映射

映射是保存键值对的对象。任何值都可以用作键或值。映射会记住键的原始插入顺序。以下是供参考的代码示例:

const map =newMap();         console.log(map.set(1, 'first')); // {1 =>"first"}      console.log(map.set('a', 'second')); // {1 =>"first", "a" => "second"}      console.log(map.set({ obj: '123' }, [1, 2, 3]));      // {1 => "first", "a" =>"second", {obj: "123"} => [1, 2, 3]}      console.log(map.set([2, 2, 2], newSet('abc')));      // {1 => "first", "a" => "second",{obj: "123"} => [1, 2, 3], [2, 2, 2] => {"a","b", "c"}}      console.log(map.size); // 4      console.log(map.has(1)); // true      console.log(map.get(1)); // "first"      console.log(map.get('a')); // "second"      console.log(map.get({ obj: '123' })); // undefined      console.log(map.get([2, 2, 2])); // undefined      console.log(map.delete(1)); // true      console.log(map.has(1)); // false      const arr = [3, 3];      map.set(arr, newSet('xyz'));      console.log(map.get(arr)); // {"x", "y", "z"}      console.log(map.keys()); // {"a", {obj: "123"}, [2, 2,2], [3, 3]}      console.log(map.values()); // {"second", [1, 2, 3], {"a","b", "c"}, {"x", "y", "z"}}      console.log(map.entries());      // {"a" => "second", {obj: "123"}=> [1, 2, 3], [2, 2, 2] => {"a", "b", "c"},[3, 3] => {"x", "y", "z"}}      const map2 =newMap([['a', 1], ['b', 2], ['c', 3]]);      map2.forEach((value, key, map) => console.log(`value = ${value}, key = ${key}, map = ${map.size}`));      // value = 1, key = a, map = 3      // value = 2, key = b, map = 3      // value = 3, key = c, map = 3      map2.clear();      console.log(map2.entries()); // {}

应用题

面试中有英语应用题,我们探索了一些经常用于测试的算法。

等值线

等值线图是指所含字母均只出现一次的单词。

· dermatoglyphics (15个字母)

· hydropneumatics (15个字母)

· misconjugatedly (15个字母)

· uncopyrightable (15个字母)

· uncopyrightables (16个字母)

· subdermatoglyphic (17个字母)

如何写一个算法来检测字符串是否是等值线图?有很多方法可以实现。可以把字符串放在集合中,然后自动拆分成字符。由于集合是存储唯一值的对象,如果它是一个等值线图,它的大小应该与字符串长度相同。

const map =newMap();         console.log(map.set(1, 'first')); // {1 =>"first"}      console.log(map.set('a', 'second')); // {1 =>"first", "a" => "second"}      console.log(map.set({ obj: '123' }, [1, 2, 3]));      // {1 => "first", "a" =>"second", {obj: "123"} => [1, 2, 3]}      console.log(map.set([2, 2, 2], newSet('abc')));      // {1 => "first", "a" => "second",{obj: "123"} => [1, 2, 3], [2, 2, 2] => {"a","b", "c"}}      console.log(map.size); // 4      console.log(map.has(1)); // true      console.log(map.get(1)); // "first"      console.log(map.get('a')); // "second"      console.log(map.get({ obj: '123' })); // undefined      console.log(map.get([2, 2, 2])); // undefined      console.log(map.delete(1)); // true      console.log(map.has(1)); // false      const arr = [3, 3];      map.set(arr, newSet('xyz'));      console.log(map.get(arr)); // {"x", "y", "z"}      console.log(map.keys()); // {"a", {obj: "123"}, [2, 2,2], [3, 3]}      console.log(map.values()); // {"second", [1, 2, 3], {"a","b", "c"}, {"x", "y", "z"}}      console.log(map.entries());      // {"a" => "second", {obj: "123"}=> [1, 2, 3], [2, 2, 2] => {"a", "b", "c"},[3, 3] => {"x", "y", "z"}}      const map2 =newMap([['a', 1], ['b', 2], ['c', 3]]);      map2.forEach((value, key, map) => console.log(`value = ${value}, key = ${key}, map = ${map.size}`));      // value = 1, key = a, map = 3      // value = 2, key = b, map = 3      // value = 3, key = c, map = 3      map2.clear();      console.log(map2.entries()); // {}

以下是验证测试:

/**    * An algorithm to verify whethera given string is an isogram    * @param {string} str The string to be verified    * @return {boolean} Returns whether it is an isogram    */   functionisIsogram(str) {    if (!str) {       returnfalse;    }           const set =newSet(str);    return set.size=== str.length;   }

全字母短句

全字母短句是包含字母表中所有26个字母的句子,不分大小写。理想情况下,句子越短越好。以下为全字母短句:

· Waltz, bad nymph, for quick jigs vex. (28个字母)

· Jived fox nymph grabs quick waltz. (28个字母)

· Glib jocks quiz nymph to vex dwarf. (28个字母)

· Sphinx of black quartz, judge my vow. (29个字母)

· How vexingly quick daft zebras jump! (30个字母)

· The five boxing wizards jump quickly. (31个字母)

· Jackdaws love my big sphinx of quartz. (31个字母)

· Pack my box with five dozen liquor jugs. (32个字母)

· The quick brown fox jumps over a lazy dog. (33个字母)

还有很多方法可以验证给定的字符串是否是全字母短句。这一次,我们将每个字母(转换为小写)放入映射中。如果映射大小为26,那么它就是全字母短句。

console.log(isIsogram('')); // false                             console.log(isIsogram('a')); // true                            console.log(isIsogram('misconjugatedly')); // true                            console.log(isIsogram('misconjugatledly')); // false

以下是验证测试:

/**       * An algorithm to verify whethera given string is a pangram    * @param {string} str The string to be verified    * @return {boolean} Returns whether it is a pangram    */   functionisPangram(str) {    const len = str.length;    if (len <26) {       returnfalse;    }               const map =newMap();    for (let i =0; i < len; i++) {       if (str[i].match(/[a-z]/i)) { // if it is letter a to z, ignoring the case         map.set(str[i].toLocaleLowerCase(), true); // use lower case letter as a key       }    }    return map.size===26;   }

同构字符串

给定两个字符串s和t,如果可以替换掉s中的字符得到t,那么这两个字符串是同构的。s中的所有字符转换都必须应用到s中相同的字符上,例如,murmur与tartar为同构字符串,如果m被t替换,u被a替换,r被自身替换。以下算法使用数组来存储转换字符,也适用于映射。

console.log(isPangram('')); // false                             console.log(isPangram('Bawds jog, flick quartz, vex nymphs.')); // true                            console.log(isPangram('The quick brown fox jumped over the lazy sleepingdog.')); // true                            console.log(isPangram('Roses are red, violets are blue, sugar is sweet,and so are you.')); // false

以下是验证测试:

/**    * An algorithm to verify whethertwo given strings are isomorphic    * @param {string} s The first string    * @param {string} t The second string    * @return {boolean} Returns whether these two strings are isomorphic    */   functionareIsomorphic(s, t) {    // strings with different lengths are notisomorphic    if (s.length !== t.length) {         returnfalse;    }               // the conversion array    const convert = [];    for (let i =0; i < s.length; i++) {         // if the conversioncharacter exists         if (convert[s[i]]) {             // apply the conversion and compare             if (t[i] === convert[s[i]]) { // so far so good                 continue;             }             returnfalse; // not isomorphic         }                   // set the conversion character for future use         convert[s[i]] = t[i];    }               // these two strings are isomorphic since there are no violations    returntrue;   };

相同字母异构词

相同字母异构词是通过重新排列不同单词的字母而形成的单词,通常使用所有原始字母一次。从一个池中重新排列单词有很多种可能性。例如,cat的相同字母异构词有cat、act、atc、tca、atc和tac。我们可以添加额外的要求,即新单词必须出现在源字符串中。如果源实际上是actually,则结果数组是[“act”]。

areIsomorphic('atlatl', 'tartar')); // true                                    console.log(areIsomorphic('atlatlp', 'tartarq')); // true                                    console.log(areIsomorphic('atlatlpb', 'tartarqc')); // true                                    console.log(areIsomorphic('atlatlpa', 'tartarqb')); // false

以下是验证测试:

/**    * Given a pool to compose ananagram, show all anagrams contained (continuously) in the source    * @param {string} source A source string to draw an anagram from    * @param {string} pool A pool to compose an anagram    * @return {array} Returns an array of anagrams that are contained by the source string    */   functionshowAnagrams(source, pool) {    // if source is not long enough to hold theanagram    if (source.length< pool.length) {       return [];    }               const sourceCounts = []; // an array tohold the letter counts in source    const poolCounts = []; // an array tohold the letter counts in pool               // initialize counts for 26 letters to be 0    for (let i =0; i <26; i++) {       sourceCounts[i] =0;       poolCounts[i] =0;    }               // convert both strings to lower cases    pool = pool.toLocaleLowerCase();    const lowerSource = source.toLocaleLowerCase();               for (let i =0; i < pool.length; i++) {        // calculatepoolCounts for each letter in pool, mapping a - z to 0 - 25       poolCounts[pool[i].charCodeAt() -97]++;    }               const result = [];    for (let i =0; i < lowerSource.length; i++) {       // calculatesourceCounts for each letter for source, mapping a - z to 0 - 25       sourceCounts[lowerSource[i].charCodeAt() -97]++;       if (i >= pool.length-1) { // if source islong enough         // if sourceCountsis the same as poolCounts         if (JSON.stringify(sourceCounts) ===JSON.stringify(poolCounts)) {           // save the found anagram, using the original source to make stringcase-preserved           result.push(source.slice(i - pool.length+1, i +1));         }         // shift thestarting window by 1 index (drop the current first letter)         sourceCounts[lowerSource[i - pool.length+1].charCodeAt() -97]--;       }    }          // removeduplicates by a Set    return [...newSet(result)];   }

回文

回文是从前往后读和从后往前读读法相同的单词或句子。有很多回文,比如A,Bob,还有 “A man, a plan, a canal — Panama”。检查回文的算法分为两种。使用循环或使用递归从两端检查是否相同。下列代码使用递归方法:

console.log(showAnagrams('AaaAAaaAAaa', 'aa')); // ["Aa", "aa", "aA", "AA"]                                        console.log(showAnagrams('CbatobaTbacBoat', 'Boat'));  //["bato", "atob", "toba", "obaT","Boat"]                                        console.log(showAnagrams('AyaKkayakkAabkk', 'Kayak'));                                        // ["AyaKk", "yaKka", "aKkay", "Kkaya","kayak", "ayakk", "yakkA"] 

以下是验证测试:

console.log(isPalindrome('')); // true                               console.log(isPalindrome('a')); // true                               console.log(isPalindrome('Aa')); // true                               console.log(isPalindrome('Bob')); // true                               console.log(isPalindrome('Odd or even')); // false                               console.log(isPalindrome('Never odd or even')); // true                               console.log(isPalindrome('02/02/2020')); // true                               console.log(isPalindrome('2/20/2020')); // false                               console.log(isPalindrome('A man, a plan, a canal – Panama')); // true

回文面试题有很多不同的变形题,下面是一个在给定字符串中寻找最长回文的算法。

/**                                           * An algorithm to find thelongest palindrome in a given string    * @param {string} source The source to find the longest palindrome from    * @return {string} Returns the longest palindrome    */   functionfindLongestPalindrome(source) {    // convert to lower cases and only keep lettersand digits    constlettersAndDigits = source.replace(/[^A-Za-z0-9]/g, '');    const str = lettersAndDigits.toLocaleLowerCase();               const len = str.length;              // empty string or one letter is a defecto palindrome    if (len <2) {       return str;    }               // the first letter is the current longest palindrome    let maxPalindrome = lettersAndDigits[0];               // assume that the index is the middle of a palindrome    for (let i =0; i < len; i++) {                 // try the case that the palindrome has one middle       for (         let j =1; // start with onestep away (inclusive)         j < len &&// end with the len end (exclusive)         i - j >= 0&&// cannot pass the start index (inclusive)         i + j < len &&// cannot exceed end index (exclusive)         Math.min(2 * i +1, 2 * (len - i) -1) > maxPalindrome.length; // potential max length should be longer than thecurrent length         j++       ) {         if (str[i - j] !== str[i + j]) { // if j stepsbefore the middle is different from j steps after the middle           break;         }         if (2 * j +1> maxPalindrome.length) { // if it is longerthan the current length           maxPalindrome = lettersAndDigits.slice(i - j, i + j +1); // j steps before, middle, and j steps after         }       }                 // try the case that the palindrome has two middles       if (i < len -1&& str[i] === str[i +1]) { // if two middles are the same         if (maxPalindrome.length<2) { // the string withtwo middles could be the current longest palindrome           maxPalindrome = lettersAndDigits.slice(i, i +2);         }         for (           let j =1; // start with one step away (inclusive)           j < len -1&&// end with the len - 1 end (exclusive)           i - j >= 0&&// cannot pass the start index (inclusive)           i + j +1< len &&// cannot exceed end index (exclusive)           Math.min(2 * i +2, 2 * (len - i)) > maxPalindrome.length; // potential max length should be longer than thecurrent length           j++         ) {           if (str[i - j] !== str[i + j +1]) { // if j stepsbefore the left middle is different from j steps after the right middle             break;           }           if (2 * j +2> maxPalindrome.length) { // if it is longer than the current length             maxPalindrome = lettersAndDigits.slice(i - j, i + j +2); // j steps before, middles, and j steps after           }         }       }    }    return maxPalindrome;   } 

以下是验证测试:

console.log(findLongestPalindrome('')); // ""                                         console.log(findLongestPalindrome('abc')); // "a"                                        console.log(findLongestPalindrome('Aabcd')); // "Aa"                                        console.log(findLongestPalindrome('I am Bob.')); // "Bob"                                        console.log(findLongestPalindrome('Odd or even')); // "Oddo"                                        console.log(findLongestPalindrome('Never odd or even')); // "Neveroddoreven"                                        console.log(findLongestPalindrome('Today is 02/02/2020.')); // "02022020"                                        console.log(findLongestPalindrome('It is 2/20/2020.')); // "20202"                                        console.log(findLongestPalindrome('A man, a plan, a canal – Panama')); // "AmanaplanacanalPanama"

熟能生巧。享受编码!

留言点赞关注

我们一起分享AI学习与发展的干货

如转载,请后台留言,遵守转载规范

字符串includes_字符串操作大全:面试准备和日常编码所需一文打尽相关推荐

  1. c语言字符串的一般操作有,面试必备——常见的C语言字符串操作

    原标题:面试必备--常见的C语言字符串操作 面试中常见的C语言字符串操作,快来看看,是否对你有帮助! 字符串倒序输出 实现逻辑,通过strlen获取字符串长度,然后通过 len/2 进行交叉赋值,这里 ...

  2. python中列表、字典、元组、字符串对应的操作大全

    1.列表 2.字典 3.元组 4.字符串 1)字符串判断 2)查找和替换 3)拆分和连接 4)大小写转换 5)文本对齐 6)去除空白字符

  3. python字符串拼接数字_python字符串和数值操作函数大全(非常全)

    字符串和数值型数字的操作大全 1.反斜杠\的使用规则:一般使用表示续行的操作,可以其他符号相结合组成其他的一些使用符号,转义字符\'的使用会识别引号,使得字符串中的引号和外面本来的啊引号相区分. (1 ...

  4. python string 方法,python字符串的方法与操作大全

    一:字符串的方法与操作 *注意:首字母为l的为从左边操作,为r的方法为从右边操作 1.__contains__()判断是否包含 判断指定字符或字符串是否包含在一个字符串内,返回值为true或者fals ...

  5. python字符串函数的find方法_python字符串的方法与操作大全

    一:字符串的方法与操作 *注意:首字母为l的为从左边操作,为r的方法为从右边操作 1.__contains__()判断是否包含 判断指定字符或字符串是否包含在一个字符串内,返回值为true或者fals ...

  6. [转载] Python字符串操作大全(一)

    参考链接: Python字符串 字符串增删改查[strap()函数, split()函数 , find()函数 , 切片等] 学习一门编程语言一般从基础的数据类型开始 ,python中的数据类型有:整 ...

  7. Python字符串操作大全(一)

    字符串增删改查[strap()函数, split()函数 , find()函数 , 切片等] 学习一门编程语言一般从基础的数据类型开始 ,python中的数据类型有:整型.浮点.布尔.字符串.列表.元 ...

  8. el replace 表达式_EL表达式截取字符串 各种字符串操作的方式全解 泽0715新浪博客...

    下面是JSTL中自带的方法列表以及其描述 函数名 函数说明 使用举例 fn:contains 判定字符串是否包含另外一个字符串 fn:containsIgnoreCase 判定字符串是否包含另外一个字 ...

  9. [PY3]——内置数据结构(3)——字符串及其常用操作

    字符串及其常用操作xmind图 字符串的定义 1. 单引号/双引号 In [1]: s1='hello world' In [2]: s1="hello world" 2. 三对单 ...

最新文章

  1. 【AI参赛经验】深度学习入门指南:从零开始TinyMind汉字书法识别——by:Link
  2. js RegExp用法
  3. typedef函数指针用法
  4. mysql中自增auto_increment功能的相关设置及问题
  5. 排序算法——堆排序(C++)
  6. SVN 本地文件锁/服务端文件锁清除步骤
  7. 计算机启动应用程序的方法,excel的程序_Excel2010中启动应用程序的三种方法
  8. 【Android】1.1 开发环境安装和配置
  9. jQuery.validate 中文API
  10. Mysql启动报错解决方案:Failed to open log (file ‘./mysql-bin.000901‘, errno 2)
  11. hibernate 反向生实体类 and 为什么老是多一个id
  12. Linux V4L2驱动框架分析之(一):架构介绍
  13. c++第二课 输出自定义字符图形
  14. 使用电信光猫加路由器实现内网穿透,外网访问内网
  15. 我为什么花 1 万多买 MacBook Pro,重点是推荐我常用的开发写作相关的工具
  16. python基础程序_Python基础初识
  17. ESP8266模块睡眠模式
  18. vue项目使用LODOP打印小票功能
  19. 青岛方言发音对照表(内附英文释义)
  20. 网络安全——文件上传

热门文章

  1. 从零开始学习mitmproxy源码阅读
  2. flux_Flux建筑模式简介
  3. “ create-react-app”和创建React应用程序的未来
  4. php函数巧用 array_column
  5. Flask-SQLALchemy 连接数据库
  6. 使用Anaconda进行环境和包的管理
  7. button的OnClick与OnClientClick事件
  8. 循环序列模型 —— 1.12 深层循环神经网络
  9. leetcode - 1049. 最后一块石头的重量 II
  10. Arm开发板内核驱动模块--Helloworld及Makefile