-
[LeetCode] 89. Gray Code알고리즘 문제 풀이 2021. 7. 2. 14:56
문제 출처: https://leetcode.com/problems/gray-code/
Gray Code - LeetCode
Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.
leetcode.com
문제
n-bit Gray Code 시퀀스는 다음의 규칙을 따르는 정수
2^n
개의 시퀀스이다:- 모든 정수는
[0, 2^n - 1]
의 범위의 수이다. - 첫 번째 정수는 0 이다.
- 각 정수는 시퀀스 내에서 한 번만 등장한다.
- 모든 인접한 정수 쌍 사이의 이진수는 정확히 1개의 비트가 다르다.
- 첫 번째와 마지막 정수의 이진수는 정확히 1개의 비트가 다르다.
정수
n
이 주어질 때, 아무 유효한 n-bit Gray Code 시퀀스를 반환하라.예제
Input: n = 2 Output: [0,1,3,2] Explanation: The binary representation of [0,1,3,2] is [00,01,11,10]. - 00 and 01 differ by one bit - 01 and 11 differ by one bit - 11 and 10 differ by one bit - 10 and 00 differ by one bit [0,2,3,1] is also a valid gray code sequence, whose binary representation is [00,10,11,01]. - 00 and 10 differ by one bit - 10 and 11 differ by one bit - 11 and 01 differ by one bit - 01 and 00 differ by one bit
Input: n = 1 Output: [0,1]
풀이
나열된 gray code 사이의 어떤 순서가 존재하는지 여부를 확인해보기 위해서 n = 1, n = 2인 케이스를 이진수로 나열해보자.
n = 1 0: 0 1: 1
n = 2 0: 00 1: 01 3: 11 2: 10
현재까지는 어떤 패턴이 존재하는지 알기 어려우니, n = 3일 때를 추가 나열해보면 아래와 같다.
n = 3 0: 000 1: 001 3: 011 2: 010 6: 110 7: 111 5: 101 4: 100
이제 위 3가지 케이스를 토대로 눈에 보이는 규칙들을 찾아보자.
1차적으로 눈에 보이는 것은
n = 3
일 때의 케이스 중 절반은n = 2
일 때의 케이스와 같고,n = 2
일 때의 케이스 중 절반은n = 1
일 때의 케이스와 동일하다는 것이다.그다음으로 보이는 것은 맨 앞자리의 비트값이다. 순차적으로 2^(n-1)개는 0, 그 다음 2^(n-1)개는 1로 되어 있다는 점이 눈에 들어온다.
또 하나 눈에 들어오는 점은, 맨 앞 자리 비트를 떼어내고 보면, 윗 절반과 아래 절반 사이에 역순이라는 관계가 존재함을 알 수 있다.
현재까지 찾은 규칙을 토대로 해답을 구하는 방식에 대해 생각해보면 다음과 같다.
n-1
비트의 gray code의 시퀀스를 구한다.- 1에서 구한 시퀀스의 각 숫자 맨 앞에
0
을 붙인다. - 1에서 구한 시퀀스의 순서를 뒤집은 배열을 구한다.
- 3에서 구한 시퀀스의 각 숫자 맨 앞에
1
을 붙인다. - 2와 4에서 구한 두 개의 시퀀스를 합치고, 각 값은 10진수로 변경한다.
n-1
비트의 gray code를 찾는 것을 재귀 방식으로 구한다면, 아래와 같은 코드로 문제의 해답을 찾을 수 있다.var grayCode = function(n) { function recursive(n) { if (n == 1) { return ['0', '1']; } const preGrayCode = recursive(n-1); const ans = []; for (let i = 0; i < preGrayCode.length; i++) { ans.push('0' + preGrayCode[i]); } for (let i = preGrayCode.length-1; i >= 0; i--) { ans.push('1' + preGrayCode[i]); } return ans; } return recursive(n).map(val => parseInt(val, 2)); }
이러한 복잡한 방법을 사용하지 않아도 손쉽게 gray code를 계산하는 방법이 있는데, 위키디피디아의 내용을 참조하였으며, 다음과 같이 코드를 간략화시킬 수 있다.
var grayCode = function(n) { const ans = []; for (let i = 0; i < Math.pow(2, n); i++) { ans.push(i ^ (i >> 1)); } return ans; };
짧게나마 정리하자면, 구하고자 하는 결과가 결국
1
~n
까지의 수를 순차적으로 gray code로 변환하는 것과 동일하고 특정 정수 값을 gray code로의 변환하는 과정은num ^ (num >> 1)
을 통해서 구할 수 있으므로 위와 같은 과정을 통해 답을 얻을 수 있는 것이다.Github: 89.js
opwe37/Algorithm-Study
Contribute to opwe37/Algorithm-Study development by creating an account on GitHub.
github.com
'알고리즘 문제 풀이' 카테고리의 다른 글
[LeetCode] 1338. Reduce Array Size to The Half (0) 2021.07.06 [LeetCode] 1220. Count Vowels Permutation (0) 2021.07.05 [LeetCode] 236. Lowest Common Ancestor of a Binary Tree (0) 2021.07.01 [LeetCode] 1004. Max Consecutive Ones III (0) 2021.06.30 [LeetCode] 1047. Remove All Adjacent Duplicates In String (0) 2021.06.29 - 모든 정수는