LeetCode/주제별 보충

Bit: 338. Counting Bits

hyunkookim 2024. 11. 9. 14:38

338. Counting Bits

 

Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1's in the binary representation of i.

 

Example 1:

Input: n = 2
Output: [0,1,1]
Explanation:
0 --> 0
1 --> 1
2 --> 10

Example 2:

Input: n = 5
Output: [0,1,1,2,1,2]
Explanation:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

 

Constraints:

  • 0 <= n <= 105

 

Follow up:

  • It is very easy to come up with a solution with a runtime of O(n log n). Can you do it in linear time O(n) and possibly in a single pass?
  • Can you do it without using any built-in function (i.e., like __builtin_popcount in C++)?

문제 해설

이 문제는 0부터 nn까지의 정수를 2진수로 변환했을 때, 각 숫자의 1의 개수를 계산하여 배열로 반환하는 문제입니다.


문제 조건

  1. 입력: 정수 nn (0≤n≤1050 \leq n \leq 10^5).
  2. 출력: 길이가 n+1n + 1인 배열 ansans로, ans[i]ans[i]는 정수 ii의 이진 표현에서 1의 개수를 나타냅니다.

제한 조건

  1. O(nlog⁡n)의 복잡도로는 간단하게 해결 가능하지만, 이 문제는 O(n) 시간 복잡도로 해결해야 합니다.
  2. 내장 함수 (예: __builtin_popcount)를 사용하지 않고 구현해야 합니다.

 

https://youtu.be/CNHIHRofKdk?si=OnEJ32ZRkdzzE47g

 

 

Code

class Solution:
    def countBits(self, n: int) -> List[int]:
        # DP 배열 초기화: dp[i]는 i의 이진 표현에서 1의 개수를 저장
        dp = [0] * (n + 1)
        # offset: 현재 참조 중인 가장 큰 2의 거듭제곱
        offset = 1

        # 1부터 n까지 순회하면서 dp 배열 계산
        for i in range(1, n + 1):
            # i가 새로운 2의 거듭제곱일 때, offset 업데이트
            if offset * 2 == i:
                offset = i

            # dp[i]는 i의 1의 개수 = dp[i - offset] + 1
            # offset은 가장 가까운 2의 거듭제곱
            dp[i] = 1 + dp[i - offset]

        # 결과 반환: dp 배열
        return dp

 

 

===============================================================================

 

class Solution:
    def countBits(self, n: int) -> List[int]:        
        """
        0 ->   0

        1 ->  01 -> 1
        2 ->  10 -> 1

        3 ->  11 -> 2

        4 -> 100 -> 1
        5 -> 101 -> 2
        6 -> 110 -> 2
        7 -> 111 -> 3

        8 ->1000 -> 1    
        """
        if n == 0:
            return [0]
            
        dp = [0]*(n+1)
        dp[1] = 1

        for i in range(2, n+1):
            dp[i] = dp[i//2] + dp[i%2] 
        return dp

 

class Solution:
    def countBits(self, n: int) -> List[int]:        
        """
        0 ->   0

        1 ->  01 -> 1
        2 ->  10 -> 1

        3 ->  11 -> 2

        4 -> 100 -> 1
        5 -> 101 -> 2
        6 -> 110 -> 2
        7 -> 111 -> 3

        8 ->1000 -> 1    
        """
        # if n == 0:
        #     return [0]

        dp = [0]*(n+1)
        # dp[1] = 1

        for i in range(1, n+1):
            dp[i] = dp[i//2] + i%2
        return dp

 

191 번 활용

class Solution:
    def countBits(self, n: int) -> List[int]:
        res = []

        def getBits(num):
            cnt = 0
            while num:
                num &= (num-1)
                cnt+=1
            return cnt

        for i in range(n+1):
            res.append(getBits(i))

        return res

 

https://youtu.be/RyBM56RIWrM?si=sAnUKsuTKn0gekal

 

코드 풀이

class Solution:
    def countBits(self, n: int) -> List[int]:
        """       1개수
        1 - 0001    1 = 1+dp[n-1]
        2 - 0010    1 = 1+dp[n-2]
        3 - 0011    2 = 1+dp[n-2]
        4 - 0100    1 = 1+dp[n-4]
        5 - 0101    2 = 1+dp[n-4] 
        6 - 0110    2 = 1+dp[n-4]
        7 - 0111    3
        8 - 1000    1 = 1+dp[n-8]
        9 - 1001    2
        """
        dp = [0] * (n+1)        
        offset = 1

        for i in range(1, n+1):
            if offset *2 == i:
                offset = i
            dp[i] = 1 + dp[i-offset]
        return dp

'LeetCode > 주제별 보충' 카테고리의 다른 글

Tree: 1448. Count Good Nodes in Binary Tree  (2) 2024.11.15
Tree: 104. Maximum Depth of Binary Tree  (2) 2024.11.15
DP2D: 1143. Longest Common Subsequence  (0) 2024.11.08
DP2D: 62. Unique Paths  (0) 2024.11.08
DP1D: 198. House Robber  (6) 2024.11.07