JavaScript 字符串 经典面试算法

需掌握的概念

①回文
②子串(连续)
③子序列(不连续)
④前缀树(Trie树)
⑤后缀树和后缀数组
⑥匹配
⑦字典序


1.互为变形词

给定两个字符串str1和str2,如果str1和str2中出现的字符种类一样且每种字符出现的次数也一样,那么str1与str2互为变形词,请实现函数判断两个字符串是否互为变形词。

举例

str1=”123″,str2=”231″。返回true

str1=”123″,str2=”2331″。返回fals

设置两个数组存储两个字符串的内容,最后对比两个数组即可。

在这里插入图片描述

			function deformed(s1, s2) {
				if (s1.length !== s2.length) {
					return false
				}
				let a1 = [],
					a2 = []
				for (let i = 0; i < s1.length; i++) {
					if (a1[s1[i]] === undefined) {
						a1[s1[i]] = 1
					} else {
						a1[s1[i]]++
					}
				}
				for (let i = 0; i < s2.length; i++) {
					if (a2[s2[i]] === undefined) {
						a2[s2[i]] = 1
					} else {
						a2[s2[i]]++
					}
				}
				if (a1.length !== a2.length) {
					return false
				}
				for (let i = 0; i < a1.length; i++) {
					if (a1[i] !== a2[i]){
						return false
					}
				}
				return true
			}
复制代码

2.互为旋转词

如果一个字符串str,把字符串str前面任意的部分挪到后面去形成的字符串叫做str的旋转词。比如str=”1234“,str的旋转词有“1234″、“2341”、“3412”、“4123”。

给定两个字符串a和b,请判断a和b是否互为旋转词。

举例:

a=“cdab”,b=“abcd”。返回true。
a=“1ab2”,b=“ab12”。返回false。
a=“2ab1”,b=“ab12”。返回true。

思路

最优解时间复杂度为O(N)

1、判断str1与str2是否长度相等

2、如果长度相等,生成str1+str1的大字符串

3、用KMP算法判断大字符串中是否含有str2

例如strl = “1234”,将两个str1合并,str1+str1=“12341234”如果str1长度为N,在str1+str1的字符串中任意一个长度为N的子串都是str1的旋转词。因此用str2进行匹配,匹配成功则str2是str1的旋转词。

//好好进行模式匹配!不要用方法好吧。
			function foo(s1,s2) {
				s1 = s1.repeat(2)
				let res = s1.includes(s2)
				return res
			}
复制代码

3.字符串逆序

3.1

给定一个字符串str,请在单词间做逆序调整。

举例:

“pig loves dog”逆序成”dog loves pig

“I’m a student.”逆序成”student. a I’m”

思路

这个题不是考什么高深的算法,仅仅是考写代码的能力。常规思路如下

  1. 实现将字符串局部所有字符逆序的函数f
  2. 利用f将字符串所有字符逆序:pig loves dog”–>”god sevol gip”
  3. 找到逆序后的字符串中每一个单词的区域利用f将每一个单词的区域逆序”god sevol gip”–>”dog loves pig”
//js的Array对象实现起来就很简单的了。
function foo(s) {
	s = s.split(' ').reverse().join(' ')
	return s
}
复制代码

3.2

给定一个字符串str和一个整数i。i代表str中的位置。即s[0]-s[i]移到右边,s[i+1]-s[N-1]移到左半边。要求,时间复杂度为O(N),额外空间复杂度为O(1)
举例:ABCDEF,i = 2,将str调整为DEFABC

			function foo(s, n) {
				if(n>=s.length){
					n %=s.length
				}
				s = s.split('')
				reverse(s, 0, n)
				reverse(s, n + 1, s.length-1)
				reverse(s,0,s.length)
				function reverse(s, start, end) {
					for (let i = start; i <= Math.floor((end + start) / 2); i++) {
						[s[end - i + start], s[i]] = [s[i], s[end + start - i]]
					}
				}
				return s.join('')
			}
复制代码

4.字符串数组拼接

给定一个字符串类型的数组strs,请找到一种拼接顺序,使得将所有字符串拼接起来组成的大字符串是所有可能性中字典顺序最小的,并返回这个大字符串举例:

strs=[“abc”,”de”]。可以拼成”abcde”,也可以拼成”deabc”,但前者字典顺序更小,所以返回”abcde”
strs=[“b”,”ba”]。可以拼成”bba”,也可以拼成”bab”,但后者字典顺序更小,所以返回”bab”。

例子2可以看出这题有坑哦,你得自己写比较过程。str1和str2按照如下方式比较如果str1+str2 < str2+str1,则str1放在前面否则,str2放在前面。
过程不写了。

5.填充字符串

给定一个字符串str,将其中所有空格字符替换成”%20″,假设str后面有足够的空间。

			function foo(s) {
				s = str.split('')
				for(let i= 0;i<s.length ;i++){
					if(s[i]===' '){
						s[i]="%20"
					}
				}
				s = s.join('')
				return s
			}
复制代码

6.二叉树子树的判断

在这里插入图片描述

普通解法:二叉树遍历+匹配问题

考察t1中以每个节点为头的子树是否与t2一致,普通解法的时间复杂度为O(N*M) N代表t1节点数,M代表t2节点数

最优解法

在这里插入图片描述

7.括号匹配

给定一个字符串str,判断是不是整体有效的括号字符串。

举例:

str=“()”,返回true

str=“()()”,返回true

str=“(())”,返回true

str=“())”返回 false

str=“()(”,返回 false。

str=“()a()”,返回 false。

			function foo(s) {
				let num = 0
				for(let i =0 ;i<s.length;i++){
					if(s[i]==='('){
						num++
					}else if(s[i]===')'){
						num--
					}else{
						return false
					}
				}
				return num===0?true:false
			}
复制代码

8.最长无重复子串

给定一个字符串str返回str的最长无重复字符子串的长度。

举例

str=”abcd”,返回4。

str=”abcb”,最长无重复字符子串为abc,返回3。


function foo(s) {
	let l = 0 //最长子串长度
	let cl = 0 //当前存储的最长子串长度
	let cs = '' //当前存储的最长子串
	for (let i = 0; i < s.length; i++) {
		if (cs.indexOf(s[i]) === -1) {
			cs += s[i];
			cl++;
			l = l < cl ? cl : l
		} else {
			cs += s[i];
			cs = cs.slice(cs.indexOf(s[i]) + 1);
			cl = cs.length;
		}
	}
	// for (let item of s) {
	// 	if (cs.indexOf(item) === -1) {
	// 		cs += item;
	// 		cl++;
	// 		l = l < cl ? cl : l
	// 	} else {
	// 		cs += item;
	// 		cs = cs.slice(cs.indexOf(item) + 1);
	// 		cl = cs.length;
	// 	}
	// }
	return l
};
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享