字符串的反向元音

时间:2016-09-02 00:39:17

标签: swift

问题是反转字符串的元音,就像输入“hello”一样,输出应该是“holle”。

我在swift中搜索没有这样的问题,所以我想把它作为讨论发布。

我编写了如下代码,事实证明需要12毫秒来反转这个“你好”,任何人都可以通过使用swift功能获得更好的解决方案吗?

class Solution {
    func reverseVowels(s: String) -> String {
        if s == "" { return "" }
        let vowels = ["a","e","i","o","u","A","E","I","O","U"]
        var sVowels = [Character]()
        var reversedStr = ""
        for vChar in s.characters {
            if vowels.contains(String(vChar)) {
                sVowels.append(vChar)
            }
        }
        for char in s.characters {
            if !vowels.contains(String(char)) {
                reversedStr = reversedStr + String(char)
            } else if vowels.contains(String(char)) {
                reversedStr = reversedStr + String(sVowels.removeLast())
            }
        }

       return reversedStr
    }
}

4 个答案:

答案 0 :(得分:4)

添加到vacawama's answer解决方案:

与其他流行语言(即C#和Java)不同,Swift并不要求所有函数都在类中。 Solution是一个相当随意的类,不需要存在。在Swift中,您可以将您的函数编写为自己的独立实体。

然而,有一个更好的快速方法。您可以将函数放入String的扩展中,这会产生一些非常好的语法:

extension String {

    static let vowels: Set<Character> = ["a","e","i","o","u","A","E","I","O","U"]

    func reverseVowels() -> String {
        if self == "" { return "" }

        var chars = Array(self.characters)

        let indices = chars.enumerate().filter{ String.vowels.contains($0.1) }.map{ $0.0 }

        let count = indices.count
        for i in 0 ..< count/2 {
            swap(&chars[indices[i]], &chars[indices[count - i - 1]])
        }

        return String(chars)
    }
}

"A test string".reverseVowels() //you can call your method directly on a string

我在答案上做了其他改进:

    现在可以将
  1. vowels移动为String类的静态成员,以便在reverseVowels()的每次调用时都不会重新生成它(尽管编译器可能会将其优化为这一点)。
  2. vowels现在是Set,而不是Array,以便使用其contains()的更快版本。通过我的测试,这使得 1.4x 的功能更快。
  3. 切换为以功能,不可变的方式生成indices数组。

答案 1 :(得分:3)

您的问题更多的是算法问题,而不是Swift问题。我对Swift一无所知。

所以这是我用Java编写的算法解决方案。以下是您可以在代码中使用的要点:

  1. 使用哈希表存储元音。然后,您可以在O(1)时间内执行查找。我认为在您的Swift代码中,您使用的是一个数组,可能需要花费O(n)时间进行搜索。
  2. 将输入字符串转换为数组,以便您可以直接在数组中操作(交换)字符,而不是重新构建新字符串。在我的代码中,我只在最后创建一个新字符串。
  3. import java.util.Set;
    import java.util.HashSet;
    import java.util.Arrays;
    
    public class ReverseVowels {
    
      public static String reverseVowels(String s) {
    
        // Create a hash table for vowels.
        Set<Character> vowels =
            new HashSet<Character>(
                Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'));
        // Convert input string to array so that we can write into it.
        char[] result = s.toCharArray();
    
        int i = 0;
        int j = result.length-1;
        while (i < j) {
            if (!vowels.contains(result[i])) {
                i++;
            }
            else if (!vowels.contains(result[j])) {
                j--;
            }
            else {
                // Both are vowels.
                char temp = result[i];
                result[i] = result[j];
                result[j] = temp;
                i++;
                j--;
            }
        }
        return new String(result);
      }
    
      public static void main(String argv[]) {
          System.out.printf("%s\n", reverseVowels("hello"));
          System.out.printf("%s\n", reverseVowels("qwetupoabt"));
      }
    }
    

    输出:

    % java ReverseVowels
    holle
    qwatopuebt
    

    迅速翻译:

    func reverseVowels(s: String) -> String {
        // Create a set for vowels.
        let vowels: Set<Character> = ["a","e","i","o","u","A","E","I","O","U"]
    
        // Convert input string to array so that we can write into it.
        var result = Array(s.characters)
    
        var i = 0
        var j = result.count - 1
        while i < j {
            if !vowels.contains(result[i]) {
                i += 1
            }
            else if !vowels.contains(result[j]) {
                j -= 1
            }
            else {
                // Both are vowels.
                let temp = result[i]
                result[i] = result[j]
                result[j] = temp
                i += 1
                j -= 1
            }
        }
        return String(result)
    }
    

答案 2 :(得分:3)

试试这个:

func reverseVowels(s: String) -> String {
    if s == "" { return "" }
    let vowels: Set<Character> = ["a","e","i","o","u","A","E","I","O","U"]
    var indices = [Int]()
    var chars = Array(s.characters)
    for (index, vChar) in chars.enumerate() {
        if vowels.contains(vChar) {
            indices.append(index)
        }
    }
    let count = indices.count
    for i in 0 ..< count/2 {
        swap(&chars[indices[i]], &chars[indices[count - i - 1]])
    }

    return String(chars)
}

算法:

  1. vowels成为Set<Character>以减少转化次数并加快contains(感谢@AlexMomchliov提出Set提示)
  2. 将字符串转换为[Character]
  3. 查找元音的位置
  4. 交换元音
  5. [Character]
  6. 重新创建字符串

答案 3 :(得分:1)

另一种方式:

1拿起所有元音,并将它们反转。

2使用反向元音映射原始字符串中的所有元音。

func reverseVowels(s: String) -> String {
    let vowelSet: Set<Character> = ["a","e","i","o","u","A","E","I","O","U"]
    var reversedVowelIterator = s.characters.filter{vowelSet.contains($0)}.lazy.reverse().generate()
    return String(s.characters.map{vowelSet.contains($0) ? reversedVowelIterator.next()! : $0})
}

print(reverseVowels("hello")) //->holle
print(reverseVowels("Reverse Vowels of a String")) //->Rivarso Vewols ef e Streng