Python 2 Pointers Solution


  • 12
    class Solution(object):
        def reverseVowels(self, s):
            vowels = set(list("aeiouAEIOU"))
            s = list(s)
            ptr_1, ptr_2 = 0, len(s) - 1
            while ptr_1 < ptr_2:
                if s[ptr_1] in vowels and s[ptr_2] in vowels:
                    s[ptr_1], s[ptr_2] = s[ptr_2], s[ptr_1]
                    ptr_1 += 1
                    ptr_2 -= 1
                if s[ptr_1] not in vowels:
                    ptr_1 += 1
                if s[ptr_2] not in vowels:
                    ptr_2 -= 1
            return ''.join(s)
    

    The idea is really simple. But I think my code is somewhat ugly in two ways:

    1. Convert string to list then convert back
    2. Pointer processing is verbose.

    Any suggestion? Thanks.


  • 0
    S

    I did not know ''.join(s) before, I used a for loop to convert back to string and got time limit exceeded. Thank you. I was wondering if it's OK that I use a for loop in an interview?


  • 0
    A
    This post is deleted!

  • 11
    R

    What about this:

    class Solution(object):
        def reverseVowels(self, s):
            """
            :type s: str
            :rtype: str
            """
            vowel = 'AEIOUaeiou'
            s = list(s)
            i,j = 0, len(s)-1
            while i<j:
                while s[i] not in vowel and i<j:
                    i = i + 1
                while s[j] not in vowel and i<j:
                    j = j - 1
                s[i], s[j] = s[j], s[i]
                i, j = i + 1, j - 1
            return ''.join(s)
    

  • 1
    B

    Create a new list instead of transforming s into a list, this may save some time but leads to O(n) space.

    def reverseVowels(self, s):
        v = 'aeiouAEIOU'
        i, j = 0, len(s) - 1
        l = [0] * (j + 1)
        while i <= j:
            while i < j and s[i] not in v: 
                l[i] = s[i]; i += 1
            while i < j and s[j] not in v: 
                l[j] = s[j]; j -= 1
            l[i], l[j] = s[j], s[i]
            i += 1; j -= 1
        return ''.join(l)
    

  • 0
    Y

    Hello. I have a question about this line. "vowels = set(list("aeiouAEIOU"))"
    Why not just set vowels = 'aeiouAEIOU'?
    Thank you!


  • 1

    @yangliu-1989
    As other comments posted, use the string directly should be fine.

    I was using set here for better performance, however the performance difference between vowels = 'aeiouAEIOU' and vowels = set(list("aeiouAEIOU")) seems really marginal.

    I prefer vowels = "aeiouAEIOU" for simplicity now.


  • 0
    Y

    @waigx Thank you for your reply~~Make sense.


  • 0
    S

    @Robin_Chen

    like your code and have a question hoping to get your answer:
    why is ...and i<j necessary in the internal loop? havent we already checked i<j in outer loop?


  • 0
    Z

    @swengzju Of course, it's ok.But use 'join' make you look more Pythonic.


  • 0
    A
    1. swapping in list is faster than string, as string is immutable
    2. find all vowels before swapping to avoid verbose pointers and logical expressions
        def reverseVowels(self, s):
            """
            :type s: str
            :rtype: str
            """
            vowels = [i for i in range(len(s)) if s[i] in 'aeiouAEIOU']
            s1 = list(s)
            for i in range(len(vowels)//2):
                s1[vowels[i]], s1[vowels[-i-1]] = s1[vowels[-i-1]], s1[vowels[i]]
            return ''.join(s1)
    

  • 0
    A

    @swengzju If you're writing in Python, it would be pretty strange for you not to use ''.join(list).


Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.