需掌握的概念
①迴文
②子串(連續)
③子序列(不連續)
④前綴樹(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”
思路:
這個題不是考什麼高深的算法,僅僅是考寫代碼的能力。常規思路如下
- 實現將字符串局部所有字符逆序的函數f
- 利用f將字符串所有字符逆序:pig loves dog"–>“god sevol gip”
- 找到逆序後的字符串中每一個單詞的區域利用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
};