每日题解——2021-8-19

1,226 阅读1分钟

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

345. 反转字符串中的元音字母

给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。

元音字母包括 'a'、'e'、'i'、'o'、'u',且可能以大小写两种形式出现。

 

示例 1:

输入:s = "hello"
输出:"holle"

示例 2:

输入:s = "leetcode"
输出:"leotcede"

 

提示:

1 <= s.length <= 3 * 105
s 由 可打印的 ASCII 字符组成

345. Reverse Vowels of a String

Given a string s, reverse only all the vowels in the string and return it.

The vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in both cases.

Example 1:

Input: s = "hello"
Output: "holle"

Example 2:

Input: s = "leetcode"
Output: "leotcede"

Constraints:

1 <= s.length <= 3 * 105
s consist of printable ASCII characters.

解题思路

双指针 我们可以使用两个指针 ii 和 jj 对字符串相向地进行遍历。

具体地,指针 ii 初始时指向字符串 ss 的首位,指针 jj 初始时指向字符串 ss 的末位。在遍历的过程中,我们不停地将 ii 向右移动,直到 ii 指向一个元音字母(或者超出字符串的边界范围);同时,我们不停地将 jj 向左移动,直到 jj 指向一个元音字母。此时,如果 i<ji<j,那么我们交换 ii 和 jj 指向的元音字母,否则说明所有的元音字母均已遍历过,就可以退出遍历的过程。

代码

var reverseVowels = function(s) {
    const n = s.length;
    const arr = Array.from(s);
    let i = 0, j = n - 1;
    while (i < j) {
        while (i < n && !isVowel(arr[i])) {
            ++i;
        }
        while (j > 0 && !isVowel(s[j])) {
            --j;
        }
        if (i < j) {
            swap(arr, i, j);
            ++i;
            --j;
        }
    }
    return arr.join('');
}

const isVowel = (ch) => {
    return "aeiouAEIOU".indexOf(ch) >= 0;
}

const swap = (arr, i, j) => {
    const temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}


复杂度分析

时间复杂度:O(n)O(n),其中 nn 是字符串 ss 的长度。在最坏的情况下,两个指针各遍历整个字符串一次。

空间复杂度:O(1)O(1) 或 O(n)O(n),取决于使用的语言中字符串类型的性质。如果字符串是可修改的,那么我们可以直接在字符串上使用双指针进行交换,空间复杂度为 O(1)O(1),否则需要使用 O(n)O(n) 的空间将字符串临时转换为可以修改的数据结构(例如数组),空间复杂度为 O(n)O(n)。