DevLog ๐Ÿ“จ

[DevLog] 2์ง„์ˆ˜ ํ‘œํ˜„์—์„œ 1์˜ ๊ฐœ์ˆ˜ ์„ธ๊ธฐ

cece00 2023. 8. 30. 18:34

2์ง„์ˆ˜ ํ‘œํ˜„์—์„œ 1์˜ ๊ฐœ์ˆ˜๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 2๋กœ ๋‚˜๋ˆ„์–ด์ฃผ๊ณ , ๊ทธ ๋‚˜๋จธ์ง€๋ฅผ ์นด์šดํŒ…ํ•˜๋ฉฐ ์…€ ์ˆ˜ ์žˆ๋‹ค. ์‹œ๊ฐ„๋ณต์žก๋„ $O(logN)$

def func(N):
    cnt = 0
    while N:
        cnt += N % 2
        N //= 2

    return cnt

bitwise ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด์™€ ์œ ์‚ฌํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ 1์˜ ๊ฐœ์ˆ˜๋ฅผ ์…€ ์ˆ˜ ์žˆ๋‹ค. ์ฃผ์–ด์ง„ ์ˆ˜ N์˜ ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ ๋น„ํŠธ๊ฐ€ 1์ธ์ง€ ํ™•์ธํ•˜๊ณ , N์„ ํ•˜๋‚˜์”ฉ right shiftํ•˜๋ฉด์„œ 1์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ผ๋‹ค. ์ด๋Š” N์˜ ๋น„ํŠธ์ˆ˜๋งŒํผ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค. ์‹œ๊ฐ„๋ณต์žก๋„ $O(logN)$

def func(N):
    cnt = 0

    while N:
        cnt += N & 1  # ํ˜„์žฌ ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ ๋น„ํŠธ๊ฐ€ 1์ธ์ง€ ํ™•์ธ
        N >>= 1       # N์„ ์˜ค๋ฅธ์ชฝ์œผ๋กœ 1 ๋น„ํŠธ์”ฉ ์ด๋™ํ•˜์—ฌ ๋‹ค์Œ ๋น„ํŠธ ํ™•์ธ

    return cnt

์ด๋ณด๋‹ค ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์€ Brian Kernighan์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๋ฐฉ์‹์ด๋‹ค. N = N & (N-1) ์„ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ ๋น„ํŠธ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ํšŸ์ˆ˜๋ฅผ ์„ผ๋‹ค. N์„ ์ด์ง„์ˆ˜๋กœ ๋‚˜ํƒ€๋‚ด์—ˆ์„ ๋•Œ 1์˜ ๊ฐœ์ˆ˜๋งŒํผ ๋ฐ˜๋ณตํ•˜๋ฏ€๋กœ, ์ด์ง„ ํ‘œํ˜„์—์„œ 1์ด ์ ์€ ๊ฒฝ์šฐ ์œ„ ๋‘ ๊ฒฝ์šฐ๋ณด๋‹ค ๋” ๋น ๋ฅด๋‹ค. ์‹œ๊ฐ„๋ณต์žก๋„ $O(k)$ (k๋Š” 1์˜ ๊ฐœ์ˆ˜)

def func(N):
    cnt = 0
    while N:
        N = N & (N-1)
        cnt += 1
    return cnt

์‹œ๋„ํ•ด ๋ณธ ๋ฐฉ๋ฒ• ์ค‘ ๊ฐ€์žฅ ๋น ๋ฅธ ๊ฒƒ์€ ํŒŒ์ด์ฌ์˜ bin ๋‚ด์žฅํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋‚ด๋ถ€์ ์ธ ์ตœ์ ํ™”๋กœ ์ธํ•ด ์‹คํ–‰ ์‹œ๊ฐ„์ด ๋‚˜๋จธ์ง€ ์„ธ ๋ฐฉ๋ฒ•๋ณด๋‹ค ๊ฐ€์žฅ ๋นจ๋ž๋‹ค.

def func(N):
    binary = bin(N)[2:]  # 2์ง„์ˆ˜๋กœ ๋ณ€ํ™˜ ํ›„ 'Ob' ์ œ๊ฑฐ
    cnt = binary.count('1')
    return cnt

๋ฐฑ์ค€ 2098: ์™ธํŒ์› ์ˆœํšŒ ๋ฅผ ํ’€๋‹ค๊ฐ€ ์ ‘ํ•œ ๋น„ํŠธ๋งˆ์Šคํ‚น ๊ฐœ๋…์„ ๊ณต๋ถ€ํ•˜๋ฉด์„œ, ๋Š˜ ํ—ท๊ฐˆ๋ ธ๋˜ ๋น„ํŠธ ์—ฐ์‚ฐ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ๊ณต๋ถ€ํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ (์ฝ”์น˜๋‹˜์˜ ํ”ผ๋“œ๋ฐฑ)๊ฐ€ ์ƒ๊ฒจ ์–•๊ฒŒ๋‚˜๋งˆ ํŒŒ๋ณด์•˜๋‹ค.. ๋น„ํŠธ๋งˆ์Šคํ‚น์„ ์ด์šฉํ•ด ๋ฐฉ๋ฌธํ•œ ๋„์‹œ (0..N)๋ฅผ ๋‚˜ํƒ€๋‚ผ ๊ฒฝ์šฐ ์ตœ๋Œ€ 63๊ฐœ์˜ ๋„์‹œ๊นŒ์ง€ ๋ฐฉ๋ฌธ์„ ์ฒดํฌํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋Š” ํŒŒ์ด์ฌ์—์„œ ์ •์ˆ˜ํ˜•์ด 8๋ฐ”์ดํŠธ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 8๋ฐ”์ดํŠธ๋Š” 64๋น„ํŠธ์ง€๋งŒ ์–‘์ˆ˜/์Œ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์‚ฌ์ธ ๋น„ํŠธ๊ฐ€ 1๋น„ํŠธ๋ฅผ ์ฐจ์ง€ํ•˜๋ฏ€๋กœ ์ตœ๋Œ€ 63๋น„ํŠธ๊นŒ์ง€๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

๋น„ํŠธ์—ฐ์‚ฐ์ž | & << >> ์— ๋”์šฑ ์ต์ˆ™ํ•ด์ง€๊ณ  ์‹ถ๋‹ค.. ๋น„ํŠธ ์—ฐ์‚ฐ์„ ์ž˜ ์ดํ•ดํ•˜๋ฉด ์ดํ•ดํ• ์ˆ˜๋ก, ์ปดํ“จํ„ฐ์˜ ๋™์ž‘ ๋ฐฉ์‹์— ๋Œ€ํ•ด์„œ๋„ ์ž˜ ์ดํ•ดํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. (ํ•˜๋‚˜๊ฐ€ ๋‹ค๋ฅธ ํ•˜๋‚˜์˜ ์›์ธ์ด ๋œ๋‹ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ  ์ดํ•ด๋„๊ฐ€ ๊นŠ์–ด์ง€๋Š” ๋ฐฉํ–ฅ์ด ๊ฐ™๋‹ค๋Š” ์˜๋ฏธ์—์„œ)

random_numbers = []
for _ in range(100):
    num = random.randint(2**62, 2**63 - 1)
    random_numbers.append(num)

์œ„ ์ธํ’‹์—์„œ ์ˆœ์„œ๋Œ€๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ฑ‰๋Š”๋‹ค. 1์€ ๋‚ด์žฅํ•จ์ˆ˜, 2๋Š” ์ปค๋‹ˆํ•ธ, 3์€ ๋‚˜๋ˆ„๊ธฐ ๋ฐ˜๋ณต, 4๋Š” ๋น„ํŠธ ์‹œํ”„ํŠธ. ์˜๋ฌธ์ ์€: 3๊ณผ 4๊ฐ€ ๋งค๋ฒˆ ๊ทผ์‚ฌํ•˜์ง€๋งŒ ๋Š˜ 3์ด 4๋ณด๋‹ค ๋น ๋ฅธ ์‹คํ–‰์‹œ๊ฐ„์„ ๋ณด์˜€๋Š”๋ฐ, ๋น„ํŠธ ์‹œํ”„ํŠธ๋ณด๋‹ค ๋‚˜๋ˆ„๊ธฐ๊ฐ€ ์™œ ๋” ์„ฑ๋Šฅ์ด ์ข‹์€์ง€๊ฐ€ ๊ถ๊ธˆํ•˜๋‹ค. ๋‹ต์„ ์ฐพ๊ฒŒ ๋˜๋ฉด ๋ง๋ถ™์—ฌ ๋‘์–ด์•ผ๊ฒ ๋‹ค.

func 1: 32, 0.00006 sec
func 2: 32, 0.00020 sec
func 3: 32, 0.00041 sec
func 4: 32, 0.00043 sec