문제 : 

 

이 문제를 보고 파이썬의 문자열, 리스트 슬라이싱이 생각났다. 슬라이딩 윈도우? 아니면 해시 테이블? 등등 여러가지 자료 구조를 생각해봤다.

 

이 문제는 대략 입력값으로 문자열 s와 정수 k가 주어지면, 주어진 문자열 s를 순회하며, k*2만큼의 파티션을 만들어 그 파티션 안에서 처음 등장하는 k개의 문자 갯수 만큼 문자열을 뒤집는다. 하지만 조건이 있는데, 만약 하나의 파티션의 길이가 k보다 짧다면, 그 파티션의 모든 문자열을 뒤집는다. 반대로 2k보단 작지만 k보다 크거나 같다면, 파티션의 첫 k개의 문자열만 뒤집어서 마지막에 뒤집어진 문자열을 리턴한다. 아래는 내가 제출해 통과한 코드이다.

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        step = k*2
        result = []

        for i in range(0, len(s), step):
            part = s[i:i + step]
            if len(part) < k:
                result.append(part[::-1])
            else:
                result.append(part[:k][::-1] + part[k:])
        return ''.join(result)

 

먼저, step과 result 변수를 각각 초기화를 해 준다. 파이썬에서는 자바의 stringBuilder같은 라이브러리는 제공되지 않으므로, 여기선 result 배열에 .append를 이용해 결괏값을 담은다음 마지막에 string으로 변환해 줄 생각이다. 

 

  • for i in range(0, len(s), step):
    - 내가 한가지 걱정한 부분이 있다. 예를들어, s라는 문자열의 길이가 7이면, 두번째 파티션 생성 당시에 IndexError같은 예외가 발생  하지 않나? 라는 생각을 했다. 검색을 해본 결과, 파이썬의 슬라이싱 기능은 범위를 벗어난 인덱스에 대해 안전하게 동작한다. 예를 들어, s[4:8]과 같이 범위를 벗어난 슬라이싱을 시도하면, 파이썬은 자동으로 s[4:]로 처리하고 남아 있는 부분만 반환한다. 그러므로, 이 for문에선 인덱스 0부터 시작하여 s의길이만큼을 반복하며, step만큼씩 건너뛰며 반복문을 수행한다. 

  • part = s[i : i + step]
    - 이제 파티션을 만들어 준다. 파이썬의 문자열/ 리스트 슬라이싱을 활용해 파티션을 만들어 준다. 여기서는 s라는 변수가 담고있는 문자열에서 인덱스 i 부터 (i + step - 1) 까지의 인덱스를 포함시켜 파티션으로 만들어 준다. 예시에서 s = abcdefg가 있다면, 처음 파티션은 인덱스 [0 : 0 + 4]이므로, 실제 문자열 s에서 인덱스 0부터 3까지를 포함시켜 파티션으로 만든다. 즉, 첫번째 반복문의 파티션은 abcd와 같이 생겼을 것이다.

  •  len(part) < k:
    - 위에서 첫번째 조건이다. 만약, 파티션의 길이가 k보다 작다면, 우리는 파티션의 모든 문자열을 뒤집어야 한다.

  • result.append(part[::-1]):
    맨 위에서 선언한 result라는 빈 리스트에 part를 뒤집어서 append해 준다. [::-1]을 보자마자 저번 포스팅에서 언급한 내용이 번뜩 하고 기억이 났다. 이것도 문자열 슬라이싱 구문을 사용한 것인데, start와 end를 비워주고(여기서 start와 end가 생략되면 기본 디폴트값으로 start는 0으로 설정되고, 현재 비교중인 문자열이나 리스트의 길이를 end로 설정한다.) 마지막에 -1을 넣음으로써 문자열을 역순으로 순회하는 것이다!

  • else:
    - 여기서의 else는 위에서 언급한 두번째 조건과 같다(반대로 2k보단 작지만 k보다 크거나 같다면, 파티션의 첫 k개의 문자열만 뒤집어서 마지막에 뒤집어진 문자열을 리턴한다.) 이 조건에서는, 파티션 전체를 뒤집는게 아니라, 파티션에서 처음 등장한 k개의 문자열만 뒤집어야 한다.

  • result.append(part[:k][::-1] + part[k:])

    - 1. part[:k]
    part 문자열의 처음부터 k 번째 문자까지 슬라이싱한다.
    예를 들어, part = "abcdef"이고 k = 2인 경우, part[:k]는 "ab"이다.


    2. part[:k][::-1]
    위에서 슬라이싱한 문자열을 다시 슬라이싱하여 역순으로 만든다.
    예를 들어, part[:k]가 "ab"라면, part[:k][::-1]는 "ba"이다.

    3. part[k:]
    part 문자열의 k 번째 문자부터 끝까지 슬라이싱한다.
    예를 들어, part = "abcdef"이고 k = 2인 경우, part[k:]는 "cdef"이다.

    4. part[:k][::-1] + part[k:]
    역순으로 만든 첫 번째 k 문자와 나머지 문자를 결합한다.
    예를 들어, part[:k][::-1]가 "ba"이고 part[k:]가 "cdef"라면, 결합한 결과는 "bacdef"이다.

여기서 살짝 헷갈리는 부분은 2번의 part[:k][::-1]인데, 이 부분은 두 부분을 합친 것이다. 여기서의 두 부분은 다음과 같이 표현 할 수 있다.

parted = part[:k]
reversed = parted[::-1]

위의 코드는 part[:k][::-1]과 같다.

 

  • return ''.join(result)
    모든 파티션이 끝난 result 배열을 .join 메서드를 활용해 리스트에서 문자열로 변환시킨후 리턴한다.

+ Recent posts