编写一个函数,以字符串做为输入,反转该字符串中的元音字母。javascript
示例 1: 输入: "hello" 输出: "holle" 前端
示例 2: 输入: "leetcode" 输出: "leotcede" java
说明: 元音字母不包含字母"y"。 正则表达式
个人思路是先把字符串中的元音字母找出来,而后翻转插入一个新的字符串中。
算法
对于给定字符串s,利用正则表达式筛选出元音字母,express
写出正则表达式api
var reg = /['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']/
数组
使用上述正则,利用s.match(reg)
去匹配,发现每次只能匹配一个,且',
也会被匹配上浏览器
修正: var reg = /aeiou/ig
函数
s.match(reg)
会返回一个匹配结果的数组,示例:
'leetcode'.match(reg) // ['e', 'e', 'o', 'e']
var reg = /[aeiou]/ig
var arr = s.match(reg)
if(!arr) return s; // 结果为null,则无元音字母
var res = '' // 结果字符串
var index = arr.length - 1 // 元音数组索引,倒序省去reverse操做
while(i < s.length) {
if(reg.test(s[i])) { // 若是是元音字母
res += arr[index] // 替换
index += 1
} else {
res += s[i]
}
i += 1;
}
复制代码
代码看上去没什么问题,可是在浏览器中运行却怎么都不成功
如上图,指望的结果应该是'leotcede'....................
反复看了一个多小时,最后发现是reg.test()
的问题,这个api有点坑爹,当reg中的检索是全局检索时,即加了g修饰符,test()若是连续使用结果会不一样,举个栗子:
如上图所示,没有全局修饰符和加上全局修饰符时检索结果彻底不一样。
经过查阅MDN:
若是正则表达式设置了全局标志,test()
的执行会改变正则表达式lastIndex
属性。连续的执行test()
方法,后续的执行将会从 lastIndex 处开始匹配字符串,(一样改变正则自己的
exec()
lastIndex属性值
).
原来是lastIndex搞得鬼,由于使用时我都是对单个字符去匹配,因此若是匹配到了的时候,lastIndex就会变为1,下一个若是出现连续的匹配,就会没法匹配成功。
咱们在每一次匹配成功时重置lastIndex就行了,即设置reg.lastIndex = 0
因此最终代码为:
var reverseVowels = function(s) {
var reg = /[aeiou]/ig
var arr = s.match(reg)
if(!arr) return s;
var res = ''
var index = arr.length - 1
var i = 0
while(i < s.length) {
if(reg.test(s[i])) {
res += arr[index]
reg.lastIndex = 0 // 重置lastIndex
index -= 1
} else {
res += s[i]
}
i += 1;
}
return res;
};复制代码
但回归开头,这是算法题,我写出的这个方法并非优质解法,好吧,看了大佬的解法后,能够用双指针来解决这个问题。
思路以下:
题目的要求是翻转字符串中的元音字母,因此咱们只要找出头尾的元音字母依次交换就行了,根据大佬的思路写出以下代码:
var reverseVowels = function(s) {
var reg = /[aeiou]/i
var i = 0
var len = s.length - 1
while(i < len) {
if(reg.test(s[i]) && reg.test(s[len])) { // 首尾都为元音,交换
[s[i], s[len]] = [s[len], s[i]]
i += 1;
len -= 1;
} else if(!reg.test(s[i])) { // 首不是元音,比较下一位
i += 1;
} else if(!reg.test(s[len])) { // 尾不是元音,比较上一位
len -= 1;
}
}
return s;
};复制代码
运行的时候发现s并无被改变,???这是为何,又是一个坑人的问题,明明一切看起来是那么有道理。。百思不得其解,后来发现问题就出在字符串,字符串一旦初始化是没法被修改的,而我却使用了[s[i], s[len]] = [s[len], s[i]]
去试图修改字符串。举个栗子:
var str = 'str'
str[0] = 'a'
str // 'str'
str = 'aaa'
str // 'aaa'复制代码
为何字符串经过下标没法修改,而赋值能够“修改”,上面看起来是赋值修改了字符串,实际上并无被修改,
字符串是基本数据类型, 基本数据类型的值一旦建立,便没法修改
建立字符串的时候,实际上在栈内开辟了一块内存空间来存放该字符串值,内存空间大小在初始化时已经固定了,没法修改。
进行赋值时,实际上开辟了另外一块内存空间来存放要赋值的新值,将变量指向了这个栈空间。
而原来的字符串值内存会被垃圾回收机制回收,由于没有变量指向这个字符串了。
总结
本身的基础仍是太薄弱了啊,看似一道小小的算法题,牵扯出这么多小的知识点,都是本身不懂了,慢慢加油吧。~~~