每日算法篇(五)之反转字符串中的元音字母

172 阅读2分钟

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

前言

今天又是算法日,(其实是因为平时做不出来~做出来的那天就有发了)。>/br? 好的,今天又是简单题日,开冲!!!!!!!

题目

编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

  • 示例 1:
输入: "hello"
输出: "holle"
  • 示例 2:
输入: "leetcode"
输出: "leotcede"

题外话

一般有些算法题看不太懂,先不要去搜或者直接看解析,如果连题目都读不懂,就放弃,这属实有点可惜。所以可以尝试看看英文版,毕竟大部分的算法题都是直译过来的(原创除外);看看英文版,很多坑+问题疑惑就会迎刃而解~

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.
Constraints:

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

逻辑思路

  • 看了英文版是不是有种阔然开朗的感觉,本来对于元音字母还有点模糊~现在直接知道了 → 'a', 'e', 'i', 'o','u';
  • 雷点远远不止这里,英文版的敲重点来了 → ASCII,这意味着除了小写,还需要大写;
  • 排雷完毕,就是解析思路了:
    • 一个字符串拆解成char[]的数组
    • 利用双指针方法,从首末分别相向遍历,直至相遇,把分别遇到的元音作为交换;
    • 判断当前字符是否符合元音 → 采用String.indexOf方法,存在返回首次遇到下标,不存在则返回-1

实现

  • 解析元音采用indexOf方法,比较简单粗暴
class Solution {
    public String reverseVowels(String s) {
        char[] a = s.toCharArray();
        int n = a.length;
        int i = 0;
        int j = n-1;
        while (j>i){
            while (i<n && !change(a[i])){
                ++i;
            }
            while (j>0 && !change(a[j])){
                --j;
            }
            if(j>i){
            char c = a[i];
            a[i] = a[j];
            a[j] = c;
            ++i;
            --j;
            }
  

        }
        return new String(a);
    }

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

官方题解

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

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

复杂度分析

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

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

1629356033(1).jpg