题目描述

s
'a''e''i''o''u'

示例 1:

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

示例 2:

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

提示:

1 <= s.length <= 3 * 105s

方法一:双指针

思路与算法

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

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

代码

C++

class Solution {
public:
    string reverseVowels(string s) {
        auto isVowel = [vowels = "aeiouAEIOU"s](char ch) {
            return vowels.find(ch) != string::npos;
        };

        int n = s.size();
        int i = 0, j = n - 1;
        while (i < j) {
            while (i < n && !isVowel(s[i])) {
                ++i;
            }
            while (j > 0 && !isVowel(s[j])) {
                --j;
            }
            if (i < j) {
                swap(s[i], s[j]);
                ++i;
                --j;
            }
        }
        return s;
    }
};

Java

class Solution {
    public String reverseVowels(String s) {
        int n = s.length();
        char[] arr = s.toCharArray();
        int i = 0, j = n - 1;
        while (i < j) {
            while (i < n && !isVowel(arr[i])) {
                ++i;
            }
            while (j > 0 && !isVowel(arr[j])) {
                --j;
            }
            if (i < j) {
                swap(arr, i, j);
                ++i;
                --j;
            }
        }
        return new String(arr);
    }

    public boolean isVowel(char ch) {
        return "aeiouAEIOU".indexOf(ch) >= 0;
    }

    public void swap(char[] arr, int i, int j) {
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

C#

public class Solution {
    public string ReverseVowels(string s) {
        int n = s.Length;
        char[] arr = s.ToCharArray();
        int i = 0, j = n - 1;
        while (i < j) {
            while (i < n && !IsVowel(arr[i])) {
                ++i;
            }
            while (j > 0 && !IsVowel(arr[j])) {
                --j;
            }
            if (i < j) {
                Swap(arr, i, j);
                ++i;
                --j;
            }
        }
        return new string(arr);
    }

    public bool IsVowel(char ch) {
        return "aeiouAEIOU".IndexOf(ch) >= 0;
    }

    public void Swap(char[] arr, int i, int j) {
        char temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

Python3

class Solution:
    def reverseVowels(self, s: str) -> str:
        def isVowel(ch: str) -> bool:
            return ch in "aeiouAEIOU"
        
        n = len(s)
        s = list(s)
        i, j = 0, n - 1
        while i < j:
            while i < n and not isVowel(s[i]):
                i += 1
            while j > 0 and not isVowel(s[j]):
                j -= 1
            if i < j:
                s[i], s[j] = s[j], s[i]
                i += 1
                j -= 1
        
        return "".join(s)

JavaScript

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;
}

Golang

func reverseVowels(s string) string {
    t := []byte(s)
    n := len(t)
    i, j := 0, n-1
    for i < j {
        for i < n && !strings.Contains("aeiouAEIOU", string(t[i])) {
            i++
        }
        for j > 0 && !strings.Contains("aeiouAEIOU", string(t[j])) {
            j--
        }
        if i < j {
            t[i], t[j] = t[j], t[i]
            i++
            j--
        }
    }
    return string(t)
}

C

char vowel[] = "aeiouAEIOU";

bool isVowel(char ch) {
    for (int i = 0; vowel[i]; i++) {
        if (vowel[i] == ch) {
            return true;
        }
    }
    return false;
};

char* reverseVowels(char* s) {
    int n = strlen(s);
    int i = 0, j = n - 1;
    while (i < j) {
        while (i < n && !isVowel(s[i])) {
            ++i;
        }
        while (j > 0 && !isVowel(s[j])) {
            --j;
        }
        if (i < j) {
            char* tmp = s[i];
            s[i] = s[j], s[j] = tmp;
            ++i;
            --j;
        }
    }
    return s;
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是字符串 s 的长度。在最坏的情况下,两个指针各遍历整个字符串一次。
  • 空间复杂度:O(1) 或 O(n),取决于使用的语言中字符串类型的性质。如果字符串是可修改的,那么我们可以直接在字符串上使用双指针进行交换,空间复杂度为 O(1),否则需要使用 O(n) 的空间将字符串临时转换为可以修改的数据结构(例如数组),空间复杂度为 O(n)。