나의 발자취

[Two Pointers] 345. Reverse Vowels of a String 본문

알고리즘

[Two Pointers] 345. Reverse Vowels of a String

달모드 2025. 1. 4. 16:32

문제 링크

https://leetcode.com/problems/reverse-vowels-of-a-string

문제 접근 방법

일단 주어진 예시를 가지고 어떻게 해야 효율적으로 모음을 바꿔서 리턴할 수 있을지 패턴을 분석해봤다.

 

reverse가 들어간다는 것은, 가장자리에 있는 것들은 저들끼리 바뀌고, 안쪽에 있는 것들은 저들끼리 바뀌기 때문에

-> swap 의 개념이 들어가지 않을까.. 하고

-> swap이라면 각각 좌/우에서 포인터가 존재해서 점점 인덱스를 늘려/줄여가면서 가운데에서 만나면 연산 횟수가 효율적이라고 생각되었다.

 

고민한 부분

1) 루프 순회 방법

위의 패턴을 분석하기 전에는 루프 순회를 어떻게 할지 고민이 되었는데, 마지막 생각을 했던 부분에서 루프의 조건을 left < right 로 하면 될것같다고 생각했고, ex2에서 생각한 바처럼 모음의 갯수가 홀수인 경우에는 가운데 글자는 그대로 두어도 무방하므로 등호는 조건으로 넣지 않아도 될 것 같았다.

 

2) swap을 어떻게 처리할 것인가

두 포인터 모두 다 모음을 만났을 때 스왑을 해줘야 하므로 이걸 조건문으로 따로 빼고,

두 포인터 각각의 경우에 한하여 모음이 아닌 경우에는 포인터 연산을 해주는 걸로 처리를 하는걸로 생각

 

주의사항

파이썬에서 문자열은 불변이므로, 리스트 형태로 바꿔서 연산했다가 나중에 반환은 다시 리스트를 합친 문자열으로 반환해줘야 한다는것? (join으로)

 

코드

class Solution:
    def reverseVowels(self, s: str) -> str:
        vowels = "aeiouAEIOU"
        left = 0
        right = len(s) - 1
        s = list(s)

        while left < right:  
            if s[left] not in vowels:
                left += 1
            elif s[right] not in vowels:
                right -= 1
            else: # if s[left] in vowels and s[right] in vowels
                s[left],s[right] = s[right],s[left]
                left += 1
                right -= 1
                                  
        return "".join(s)

 

 

풀고 나서 (접근법, 사용되는 알고리즘 개념)

더 아름다운 코드를 찾았다.

class Solution:
    def reverseVowels(self, s: str) -> str:
        vowels=[i for i in s if i in "aeiouAEIOU"]
        result=[i if i not in "aeiouAEIOU" else vowels.pop() for i in s]
        return "".join(result)

 

list comprehension을 사용해서 s안의 모음들을 담는 리스트를 뽑고(vowels)

result에는 s의 캐릭터를 하나씩 담으면서 만약에 캐릭터가 모음에 해당되면 vowels 리스트의 마지막 요소를 집어넣는다 <<< 

나도 이렇게 처음에 s의 vowels를 따로 리스트로 만들어서 이걸 마지막 원소{[-1])부터 집어넣으면 되지 않을까 생각은 했었는데 그럼 loop iteration을 해야하니까,, 어차피 reverse고 뒤에서부터 하나씩 꺼내쓰는거면 pop을 쓰면 되는건데 이 생각은 못했다.

 

댓글에서 갤럭시 브레인이라고 찬양하는 중 ㅎ

Comments