ν’€μŠ€νƒ μ›ΉπŸŒ 개발자 지망생 πŸ§‘πŸ½β€πŸ’»
βž• 인곡지λŠ₯ 관심 πŸ€–


Categories


Recent views

  • 1
  • 2
  • 3
  • 4
  • 5

Python for Algorithms-etc

Python for Algorithms-etc

μŠ€μœ„ν•‘

κ³΅κ°„μ˜ ν•œμͺ½ 끝뢀터 λ‚˜λ¨Έμ§€ λκΉŒμ§€ ν›‘μœΌλ©΄μ„œ λ§ˆμ£ΌμΉ˜λŠ” 뢀뢄을 μ²˜λ¦¬ν•˜λŠ” 방식
μ •λ ¬, κΈ°μ€€μž‘κΈ°, μƒνƒœ λ³€ν™”λ₯Ό μ €μž₯ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€.

🧾️ μŠ€μœ„ν•‘ μ˜ˆμ‹œ

컨벑슀 헐

CCW(Counter Clock Wise)

λ²‘ν„°μ˜ 외적(Cross Product)λ₯Ό μ΄μš©ν•΄ 점의 μŒμ„ κΈ°μ€€μœΌλ‘œ λ‹€λ₯Έ 점의 μƒλŒ€μ  μœ„μΉ˜λ₯Ό μ•Œμ•„λƒ„

🧾️ CCW μ˜ˆμ‹œ
def ccw(fr_point, to_point, target_point):
    fr_x, fr_y = fr_point
    to_x, to_y = to_point
    tg_x, tg_y = target_point
    
    result = (to_x - fr_x)*(tg_y - fr_y) - (tg_x - fr_x)*(to_y - fr_y)
    if result > 0:
        return 1 # λ°˜μ‹œκ³„ λ°©ν–₯
    elif result < 0: 
        return -1 # μ‹œκ³„ λ°©ν–₯
    else:
        return 0 # 평행

그라함 μŠ€μΊ”

🧾️ 그라함 μŠ€μΊ” $O(n\log n)$ μ˜ˆμ‹œ
def ccw(a, b, c):
    t = (b['x']-a['x'])*(c['y']-a['y']) - (c['x'] - a['x'])*(b['y'] - a['y'])
    if t > 0:
        return 1
    elif t < 0:
        return -1
    else :
        return 0
def comp_by_ccw(a, b):
    global firstPoint
    return -ccw(firstPoint,a,b)
def comp_by_pos(a, b):
    if a['y'] == b['y']:
        return 1 if a['x'] > b['x'] else -1 
    else:
        return 1 if a['y'] > b['y'] else -1

firstPoint = {'x':0, 'y':9999099} # 정렬을 μœ„ν•œ κΈ°μ€€
points.sort(key=functools.cmp_to_key(comp_by_pos)) # 맨 μ™Όμͺ½ μœ„ 지점뢀터 μž‘ μœ„ν•œ μ •λ ¬
points.sort(key=functools.cmp_to_key(comp_by_ccw)) # κΈ°μ€€μ—μ„œ μ™ΈλΆ€ 껍질 μš°μ„ μœΌλ‘œ μ •λ ¬ 
st = [points[0], points[1]] # 첫 두 μ‹œμž‘ 지점 μž…λ ₯
for point in points[2:]: # λͺ¨λ“  μ§€μ μ—μ„œ
    while(len(st) >=2): 
        if (ccw(st[-2], st[-1], point) > 0): # λ‹€μŒ 점이 더 μ™ΈλΆ€ 껍질 뢀뢄에 μžˆλŠ”μ§€ 확인
            break # while λ¬Έμ΄λ―€λ‘œ μŠ€νƒ λ‚΄μ˜ λͺ¨λ“  점에 λŒ€ν•΄μ„œ 검사함 
        st.pop() # λ§Œμ•½ 더 μ™ΈλΆ€ 껍질이면 2번째 기쀀점을 내보냄
    st.append(point) # μƒˆλ‘œμš΄ 기쀀점 집어 λ„£μŒ
print(len(st))

λˆ„μ ν•©

갱신이 μ—†λŠ” κ²½μš°μ— μ ν•©ν•˜λ©°, 갱신이 μž¦μ„ 경우 λˆ„μ ν•©μ„ 계속 λ‹€μ‹œ κ΅¬ν•΄μ•Όν•˜λ―€λ‘œ 차라리 μ„Έκ·Έλ¨ΌνŠΈ 트리λ₯Ό μ΄μš©ν•˜μž.

λˆ„μ ν•©

미리 $(0\sim n)$ 수의 λ°°μ—΄($n$)을 톡해 λˆ„μ ν•© λ°°μ—΄($p$)을 μ €μž₯ν•΄λ†“λŠ”λ‹€.
μ΄λ•Œ $p[i] = p[i-1] + n[i]$ 이며, 즉, $p[i]$λŠ” $(0,i)$κΉŒμ§€μ˜ 합이닀.
이λ₯Ό $O(n)$의 μ‹œκ°„μ•ˆμ— λ§Œλ“€ 수 μžˆλ‹€.
이후 μ›ν•˜λŠ” ꡬ간 $(i, j)$의 κ΅¬κ°„ν•©λ§Œ κ΅¬ν•˜κ³  μ‹Άλ‹€λ©΄ $p[j]-p[i]$둜 $O(1)$으둜 λΉ λ₯΄κ²Œ ꡬ할 수 μžˆλ‹€.

2차원 λˆ„μ ν•©

ν–‰ λ°©ν–₯의 λˆ„μ ν•©μ„ λ¨Όμ € 각 ν–‰λ§ˆλ‹€ κ΅¬ν•œ λ’€, 기둝 ν›„,
μ—΄ λ°©ν–₯의 λˆ„μ ν•©μ„ κ΅¬ν•˜λ©΄ 2차원 λˆ„μ ν•©μ„ $O(n^2)$의 μ†λ„λ‘œ ꡬ할 수 μžˆλ‹€.

2차원 ꡬ간 합은 $(x_1, y_1) \sim (x_2, y_2)$의 합을 κ΅¬ν•˜κ³  μ‹Άλ‹€λ©΄
\(p(x_2,y_2)-p(x_1, y_2)-p(x_2, y_1) + p(x_1, y_1)\)
으둜 $O(1)$으둜 λΉ λ₯΄κ²Œ ꡬ할 수 μžˆλ‹€.

imos

imosλŠ” λˆ„μ ν•©μ˜ ν™•μž₯으둜, κ°±μ‹  μ‹œμž‘κ³Ό 끝 κ΅¬κ°„λ§Œμ„ κΈ°λ‘ν•˜μ—¬ 갱신이 μž¦μ€ ꡬ간 값을 λΉ λ₯΄κ²Œ κ°±μ‹ ν•  수 μžˆλ‹€.
λ°°μ—΄μ˜ 크기λ₯Ό $N$, ꡬ간 ν•©μ˜ 갯수λ₯Ό $M$이라고 ν• λ•Œ, 기쑴의 μ‹œκ°„ λ³΅μž‘λ„ $O(M\times N)$μ—μ„œ $O(M+N)$으둜 λ°”κΏ€ 수 μžˆλ‹€.

🧾️ imos μ˜ˆμ‹œ
def solution(board, sums):
	# λˆ„μ ν•©μ€ λ§ˆμ§€λ§‰ 인덱슀 + 1에 λ³€ν™”κ°’μ˜ 항등원을 λ”ν•˜κΈ° λ•Œλ¬Έμ—
	# κΈ°μ‘΄ 배열보닀 크기가 1컀야 ν•œλ‹€.
    new_board = board + [0]
    for props in sums:
        # x1 ~ x2κΉŒμ§€ degree κ°’λ§ŒνΌ λ³€ν™”μ‹œν‚¨λ‹€.
        x1, x2, degree = props
		# λˆ„μ ν•©μ€ 첫 μΈλ±μŠ€μ™€ λ§ˆμ§€λ§‰ 인덱슀 + 1 뢀뢄을 각각 λ³€ν™”λ˜μ•Όν•  κ°’κ³Ό κ·Έ κ°’μ˜ 항등원을 더해야 ν•œλ‹€. 
		# 예λ₯Ό λ“€μ–΄ 인덱슀 0 ~ 2κΉŒμ§€ 값을 X 만큼 λ³€ν™”μ‹œν‚¨λ‹€λ©΄ λ‹€μŒκ³Ό 같이 μ„€μ •ν•œλ‹€.
		#     0  1  2  3 
		#   [+X, 0, 0, -X]
		new_board[x1] += degree
		new_board[x2] -= degree
            
	# 이후 각 μ›μ†Œμ— 적용될 λˆ„μ ν•©μ„ κ΅¬ν•œλ‹€. 이전 인덱슀 값을 순차적으둜 더해주면 λœλ‹€.
    for i in range(1, len(new_board)):
        new_board[i] += new_board[i-1]
        
	# ν•΄λ‹Ή λˆ„μ ν•©μ„ μ›λž˜ 배열에 μ μš©μ‹œν‚€κΈ°
    for i in range(len(board)):
        board[i] += new_board[i]
            
    return board 

2차원 imos

🧾️ 2차원 imos μ˜ˆμ‹œ
def solution(board, sums):
	# λˆ„μ ν•©μ€ λ§ˆμ§€λ§‰ 인덱슀 + 1에 λ³€ν™”κ°’μ˜ 항등원을 λ”ν•˜κΈ° λ•Œλ¬Έμ—
	# κΈ°μ‘΄ 배열보닀 κ°€λ‘œ μ„Έλ‘œ 크기가 1컀야 ν•œλ‹€.
    new_board = [[0]*(len(board[0])+1) for _ in board] + [[0]*(len(board[0])+1)]
    for props in sums:
        # (x1, y1) ~ (x2, y2)κΉŒμ§€ degree κ°’λ§ŒνΌ λ³€ν™”μ‹œν‚¨λ‹€.
        x1, y1, x2, y2, degree = props

		# 2차원 λˆ„μ ν•©μ€ 1차원과 달리 두 λ°©ν–₯으둜 인덱슀λ₯Ό λˆ„μ ν•©μ„ μ„€μ •ν•΄μ•Ό ν•œλ‹€.
		# 예λ₯Ό λ“€μ–΄ (0,0) ~ (2,2)κΉŒμ§€ 값을 X 만큼 λ³€ν™”μ‹œν‚¨λ‹€λ©΄ λ‹€μŒκ³Ό 같이 μ„€μ •ν•œλ‹€.
		# /   0  1  2  3 
		# 0 (+X, 0, 0, -X)
		# 1 ( 0, 0, 0,  0)
		# 2 ( 0, 0, 0,  0)
		# 3 (-X, 0, 0, +X)
		# 참고둜, (0,0) ~ (0, 2)처럼 ν•œμ€„μ˜ λˆ„μ ν•© λ˜ν•œ 
		# μ˜ˆμ™Έ 없이 λ‹€μŒκ³Ό 같이 λ‹€μŒ 쀄에 인덱슀λ₯Ό μ„€μ •ν•΄μ•Ό ν•œλ‹€.
		# /   0  1  2  3 
		# 0 (+X, 0, 0, -X)
		# 1 (-X, 0, 0, +X)
		# 2 ( 0, 0, 0,  0)
		# 3 ( 0, 0, 0,  0)
        for i, j in [[x1, y1], [x2+1, y2+1]]: 
            new_board[i][j] += degree
        
        for i, j in [[x2+1, y1], [x1, y2+1]]:
            new_board[i][j] -= degree
            
	# 이후 각 κ°€λ‘œ 쀄 λ¨Όμ € κ°€λ‘œ λ°©ν–₯ λˆ„μ ν•©μ„ κ΅¬ν•˜κ³ 
    for i in range(len(new_board)):
        for j in range(1,len(new_board[0])): # μ΄λ•Œ, κ°€λ‘œμ€„μ€ μΈλ±μŠ€κ°€ 1λΆ€ν„° μ‹œμž‘ν•΄μ•Όν•œλ‹€.
            new_board[i][j] += new_board[i][j-1]
        
	# 이후 각 μ„Έλ‘œ μ€„μ˜ μ„Έλ‘œ λ°©ν–₯ λˆ„μ ν•©μ„ λ”ν•˜λ©΄ λœλ‹€.
    for i in range(1,len(new_board)):
        for j in range(len(new_board[0])): # μ΄λ•Œ, μ„Έλ‘œμ€„μ€ μΈλ±μŠ€κ°€ 1λΆ€ν„° μ‹œμž‘ν•΄μ•Όν•œλ‹€.
            new_board[i][j] += new_board[i-1][j]

	# ν•΄λ‹Ή λˆ„μ ν•©μ„ μ›λž˜ 2차원 배열에 μ μš©μ‹œν‚€κΈ°
    for i in range(len(board)):
        for j in range(len(board[0])):
            board[i][j] += new_board[i][j]
            
    return board