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
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ann's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值