문제 설명: 친구 사이인 Jack 과 Daniel 은 대화 내역을 탐정 기관에 도청 당하지 않기 위해 암호화를 하고자 했고, 결국 새로운 암호법을 만들어냈다. 모든 메시지 b 는 이진수 표현(binary representation) 으로 인코딩 하고, 이를 0, 1, ..., k-1 비트만큼씩 이동(shift) 시켜 k 번을 쓴다. 각 열(column) 을 XOR 연산* 처리하면 최종적으로 인코딩된 문자열을 얻게 된다.
(*XOR 연산: 이진수 값의 각 자리수를 비교해서 같으면 0, 다르면 1 을 계산하는 비트 연산자)
만약 b = 1001011 , k = 4 인 경우의 예시는 아래와 같다:

이제 우리는 메시지를 해독(decode) 해야 한다. (설명 중략) 이런 식으로 인코딩된 메시지 s 와 키 k 가 Daniel 에게 보내진다.
Jack 은 이 인코딩 알고리즘을 이용했고, Daniel 에게 디코딩 알고리즘을 구현하라고 했다. Daniel 을 도와주자!
제한 조건:
- 1 <= n <= 10^6 & 1 <= k <= 10^6
- |s| = n + k - 1 , s 는 valid 한 문자열임이 보장됨
------ * ------ * ------ * ------
[풀이 1안]
- 접근법
- 구조적으로, 디코딩 완료된 문자열 b 의 첫번째 / 마지막 문자는 인코딩된 문자열 s 의 첫번째 / 마지막 문자와 동일하므로, 이를 제외한 나머지 문자들만 구하면 됨
- 문자열의 뒤에서부터 디코딩해나간다고 하면, b 의 뒤에서 i 번째 문자는 '직전 (k-1) 개 문자 ref' 와 's 의 뒤에서 i 번째 문자' 정보를 활용하여 구할 수 있음
- 직전 (k-1) 개 문자 ref 와 s 의 뒤에서 i 번째 문자에 대해 XOR 연산을 한 결과 == b 의 뒤에서 i 번째 문자!
- i 가 업데이트 됨에 따라 ref 도 업데이트 되어야 하며, 먼저 들어온 값이 먼저 나가게 되므로 queue 구조 활용
- 코드 구현
from collections import deque
def cipher(k,s):
n = len(s) - k + 1
b = [0] * n
b[0], b[-1] = s[0], s[-1]
ref = deque([int(s[-1])])
ref_sum = int(s[-1])
l = len(s) - 1
for i in range(1, n-1):
if (s[l-i] == '1' and ref_sum%2 == 1) or (s[l-i] == '0' and ref_sum%2 == 0):
b[n-1-i] = '0'
ref.append(0)
else:
b[n-1-i] = '1'
ref.append(1)
ref_sum += 1
if len(ref) > (k-1):
diff = ref.popleft()
ref_sum -= diff
res = ''.join(b)
return res
- 결과
- 처음에는 ref_sum 변수를 안만들고 매 비교시에 sum(ref) 연산을 했더니 타임아웃 에러가 나는 케이스가 있었음
- sum(ref) 연산 시 ref 리스트의 최대 길이 만큼 O(k-1) 시간이 걸리므로 결과적으로 O(n*(k-1)) 가 됨 ㅜ
- 별도로 ref_sum 변수를 만들어 int 값으로 저장 / 업데이트 하도록 수정 --> 시간 복잡도 O(n)
- Bit Manipulation 항목에 있는 문제인 만큼 비트 연산자 (XOR == ^) 를 활용할 수도 있을 듯...!
- 처음에는 ref_sum 변수를 안만들고 매 비교시에 sum(ref) 연산을 했더니 타임아웃 에러가 나는 케이스가 있었음
'algorithms > [실제] ProblemSolving' 카테고리의 다른 글
| [LeetCode 풀이/python] 35. Search Insert Position (easy) (0) | 2021.02.07 |
|---|---|
| [LeetCode 풀이/python] 31. Next Permutation (medium) (0) | 2021.02.06 |
| [HackerRank 풀이/python] Encryption (medium) (0) | 2021.02.05 |
| [LeetCode 풀이/python] 17. Letter Combinations of a Phone Number (medium) (0) | 2021.02.05 |
| [LeetCode 풀이/python] 10. Regular Expression Matching (hard) (0) | 2021.02.03 |