๋ถํ ์ ๋ณต
-์ฃผ์ด์ง ๋ฌธ์ ๋ฅผ ๋ ์ด์์ ๋ถ๋ถ ๋ฌธ์ ๋ก ๋๋์ด์ ํธ๋ ๋ฐฉ๋ฒ
-๋น์ทํ ํฌ๊ธฐ๋ก ๋ฌธ์ ๋ฅผ ๋๋
-์ฌ๊ทํธ์ถ ์ฌ์ฉ
๋ถํ ์ ๋ณต ๊ณผ์
- Divide :๋ถ๋ถ ๋ฌธ์ ๋ก ๋๋ ์ ์๋ ๊ฒฝ์ฐ 2๊ฐ ์ด์์ ๋ฌธ์ ๋ก ๋๋๋ค.
- Conquer : ๋ ์ด์ ๋๋ ์ ์๋ ๊ฒฝ์ฐ ํ์ฌ ๋ฌธ์ ๋ฅผ ์ ๋ณตํ๋ค.
- Combine : ํด๊ฒฐ๋ ๋ฌธ์ ๋ค์ ๋ณํฉํ์ฌ ๊ธฐ์กด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
๋ถํ ํ์
์ ๋ ฅ์ ํฌ๊ธฐ๊ฐ n์ด๊ณ ์ด ๋ถํ ํ ํ์๊ฐ k๋ผ๋ฉด.
-1๋ฒ ๋ถํ ํ ์ ๋ ฅ ํฌ๊ธฐ : n/2
-2๋ฒ ๋ถํ ํ ์ ๋ ฅ ํฌ๊ธฐ : n/2^2
...
-k๋ฒ ๋ถํ ํ ์ ๋ ฅ ํฌ๊ธฐ : n/2^k
--> n/2^k ๊ฐ 1 ์ด๋ผ๋ฉด ๋ ์ด์ ๋ถํ ๋ถ๊ฐ
๋ถํ ํ์
๋ถํ ์ ๋ณต์ ์ฌ์ฉ
1. ํฉ๋ณ์ ๋ ฌ(Merge Sort)
์ ๋ ฅ์ด 2๊ฐ์ ๋ถ๋ถ๋ฌธ์ ๋ก ํฌ๊ธฐ๊ฐ ๋ฐ์ฉ ์ค์ด๋๋ ๋ถํ ์ ๋ณต ์๊ณ ๋ฆฌ์ฆ
-n๊ฐ์ ์ซ์๋ค์ n/2๊ฐ์ฉ 2๊ฐ์ ๋ถ๋ถ๋ฌธ์ ๋ก ๋ถํ
-2๊ฐ์ ์ ๋ ฌ๋ ๋ถ๋ถ์ ํฉ๋ณํ์ฌ ์ ๋ ฌ(์ ๋ณต)
์๊ฐ๋ณต์ก๋ : O(nlogn)
๊ฐ ์ธต(๋ถํ )์์ ๋น๊ต ๊ณ์ฐ ํ์ = O(n)
์ธต ์=๋ถํ ํ์=log2n
์๊ฐ๋ณต์ก๋=> log2n*O(n)=O(nlogn)
์๊ณ ๋ฆฌ์ฆ ๊ตฌํ(python)
import random
size=15
num=[]
result=[0]*size
#๋๋ค์ผ๋ก ์ซ์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋๋ ํจ์
def makeList(num):
for i in range(size):
num.append(int(random.random()*100+1))
#1๋ถํฐ 100๊น์ง์ ์ ์ค ํ๋
def merge(num,result,left,mid,right):
i=left;j=mid+1;k=left
#ํฉ๋ณ
while(i<=mid and j<=right):
if(num[i]<=num[j]):
result[k]=num[i]
k+=1
i+=1
else:
result[k]=num[j]
k+=1
j+=1
if(i>mid):
for a in range(j,right+1):
result[k]=num[a]
k+=1
else:
for a in range(i,mid+1):
result[k]=num[a]
k+=1
for a in range(left,right+1):
num[a]=result[a]
print(num,result)
##ํฉ๋ณ ํ ๋ค์ ๋์
def mergeSort(num,result,left,right):
if(left<right):
mid=(left+right)//2
mergeSort(num,result,left,mid)
mergeSort(num,result,mid+1,right)
merge(num,result,left,mid,right)
makeList(num)
print(*num)
mergeSort(num,result,0,size-1)
print(*result)
2. ํต์ ๋ ฌ
์ฌ์ค ์ ๋ณต ํ ๋ถํ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๊ฐ ๋ถ๋ถ ๋ฌธ์ ์ ํฌ๊ธฐ๊ฐ ์ผ์ ํ์ง ์์ ํํ์ ๋ถํ ์ ๋ณต ์๊ณ ๋ฆฌ์ฆ
-pivot์ ์ค์ ํ์ฌ pivot๋ณด๋ค ์์ ์์๋ ์ผ์ชฝ์ผ๋ก ํฐ ์์๋ ์ค๋ฅธ์ชฝ์ผ๋ก ๋ถํ ํ๊ณ ์ค๊ฐ์ pivot์ ๋๋๋ค.
-๋ถํ ๋ ๋ถ๋ถ ๋ฌธ์ ๋ค์ ๋ํด์๋ ์๋ก์ด pivot์ ์ค์ ํ์ฌ ์์ ๋์ผํ ๊ณผ์ ์ ์ํํ๋ค.
์๊ฐ๋ณต์ก๋
pivot์ผ๋ก ์ด๋ ๊ฒ์ ์ ํํ๋์ง์ ๋ฐ๋ผ ์ฑ๋ฅ์ด ์ข์ฐ๋๋ค.
-์ต์ ์ ๊ฒฝ์ฐ(๊ฐ์ฅ ์์/ํฐ ์์๊ฐ pivot์ธ ๊ฒฝ์ฐ): (n-1)+(n-2)+...+1=> O(n^2)
-์ต์ ์ ๊ฒฝ์ฐ(์ค๊ฐ ํฌ๊ธฐ์ ์์๊ฐ pivot์ธ ๊ฒฝ์ฐ): ์ธต์ * O(n) = logn*O(n) = O(nlogn)
-ํ๊ท ์ ๊ฒฝ์ฐ(ํญ์ ๋๋คํ๊ฒ ์ ํํ๋ ๊ฒฝ์ฐ): O(nlogn)
์๊ณ ๋ฆฌ์ฆ ๊ตฌํ(python)
import random
size=15
num=[]
result=[0]*size
#๋๋ค์ผ๋ก ์ซ์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋๋ ํจ์
def makeList(num):
for i in range(size):
num.append(int(random.random()*100+1))
#1๋ถํฐ 100๊น์ง์ ์ ์ค ํ๋
def partition(num,left,right):
pivot=num[left] #pivot์ ๋๋ค์ผ๋ก ์ค์ ํด๋ ๋จ
low=left; high=right
while(low<high):
while(num[low]<=pivot and low<right):
low+=1
while(num[high]>=pivot and high>left):
high-=1
if low<high:
##low์์น์ ์์๋ pivot๋ณด๋ค ํฌ๊ณ high์์น์ ์์๋ pivot๋ณด๋ค ์์ผ๋ฏ๋ก swap
num[low],num[high]=num[high],num[low]
num[left],num[high]=num[high],num[left] #pivot์์น ๊ณ
##pivot์ ์์น return
return high
def quickSort(num,left,right):
if(left<right):
q=partition(num,left,right)
quickSort(num,left,q-1)
quickSort(num,q+1,right)
#pivot์ ๊ธฐ์ค์ผ๋ก ๋ ๊ทธ๋ฃน์ผ๋ก ๋ถํ
makeList(num)
print(*num)
quickSort(num,0,size-1)
print(*num)
3.์ด์งํ์(์ด๋ถํ์)
ํ์ ๋ฒ์๋ฅผ ๋ ๋ถ๋ถ์ผ๋ก ๋๋ ๊ฐ๋ฉด์ ์ํ๋ ์์๋ฅผ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํ์ ์ ์์๊ฐ ์ ๋ ฌ๋์ด ์์ด์ผํ๋ค.
-ํ์ ๋ฒ์ ์ค์ ex)[s,e]
-ํ์ ์ง์ (mid) ์ค์ ํ ์ฐพ๋ ๊ฐ๊ณผ ๋น๊ต ex)mid=(s+e)//2
-mid๊ฐ ๋ ํฌ๋ฉด [s,mid-1]์์ ๋ค์ ํ์, ๋ ์์ผ๋ฉด [mid+1,e]์์ ๋ค์ ํ์
-s>e์ผ ๋ ๊น์ง ์์ ๊ณผ์ ๋ฐ๋ณต
์๊ฐ๋ณต์ก๋ : O(logn)
์๊ณ ๋ฆฌ์ฆ ๊ตฌํ(python)
import random
size=15
num=[]
result=[0]*size
#๋๋ค์ผ๋ก ์ซ์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋๋ ํจ์
def makeList(num):
while True:
temp=random.randint(1,20)
#1๋ถํฐ 20์ฌ์ด์ ์ซ์
if temp not in num:
num.append(temp)
if len(num)==size:
break
def binary_search(target,num):
start=0
end=size-1
while(start<=end):
mid=(start+end)//2
if num[mid]==target:
return mid
elif num[mid]>target:
end=mid-1
else:
start=mid+1
return None ##์ฐพ๊ณ ์ ํ๋ ์๊ฐ ์๋ ๊ฒฝ์ฐ
target=random.randint(1,20) #์ฐพ๊ณ ์ํ๋ ์
makeList(num)
num.sort()
print(target)
print(num)
print(binary_search(target,num),"๋ฒ์งธ ์์")
4.์ ํ๋ฌธ์
n๊ฐ์ ์ซ์๋ค ์ค์์ k๋ฒ์งธ๋ก ์์ ์ซ์๋ฅผ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
k๋ฒ์งธ๋ก ์์ ์ซ์๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ์
-์ต์ ์ซ์๋ฅผ k๋ฒ ์ฐพ๋ ๋ฐฉ๋ฒ (O(kn))
-์ซ์๋ฅผ ์ ๋ ฌํ ํ, k๋ฒ์งธ ์ซ์๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ (O(nlogn))
-๋ ๊ทธ๋ฃน์ผ๋ก ๋๋ ์ ๋ ๊ทธ๋ฃน ์ค ์ด๋ ๊ทธ๋ฃน์ ์ํ๋์ง ์ฐพ์๊ฐ๋ ๋ฐฉ๋ฒ
->์ผ์ชฝ ๊ทธ๋ฃน (k๋ฒ์งธ ์์ ์ซ์)
->์ค๋ฅธ์ชฝ ๊ทธ๋ฃน(k-์ผ์ชฝ๊ทธ๋ฃน ํฌ๊ธฐ-1(pivot) ๋ฒ์งธ๋ก ์์ ์ซ์)
์๊ฐ๋ณต์ก๋
์ ๋ ฅ ํฌ๊ธฐ๊ฐ n์์๋ถํฐ ํ๊ท ์ ์ผ๋ก 3/4๋ฐฐ๋ก ๊ฐ์, ํฌ๊ธฐ๊ฐ 1์ผ ๊ฒฝ์ฐ ๋ถํ ์๋ฃ
n+3/4n+(3/4)^2n+...(3/4)^in = n[1+3/4+(3/4)^2+...+(3/4)^i] <= 2n
ํ๊ท 2ํ์ ์ข์ ๋ถํ ์ด ๋๋ฏ๋ก 2*O(n) = O(n)
์๊ณ ๋ฆฌ์ฆ ๊ตฌํ(python)
import random
import sys
sys.setrecursionlimit(10**6)
size=15
num=[]
#๋๋ค์ผ๋ก ์ซ์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋๋ ํจ์
def makeList(num):
for i in range(size):
num.append(int(random.random()*100+1))
#1๋ถํฐ 100๊น์ง์ ์ ์ค ํ๋
def partition(num,left,right):
pivot=num[left] #pivot์ ๋๋ค์ผ๋ก ์ค์ ํด๋ ๋จ
low=left; high=right
while(low<high):
while(num[low]<=pivot and low<right):
low+=1
while(num[high]>=pivot and high>left):
high-=1
if low<high:
##low์์น์ ์์๋ pivot๋ณด๋ค ํฌ๊ณ high์์น์ ์์๋ pivot๋ณด๋ค ์์ผ๋ฏ๋ก swap
num[low],num[high]=num[high],num[low]
num[left],num[high]=num[high],num[left] #pivot์์น ๊ณ
##pivot์ ์์น return
return high
def selection(num,left,right,k):
p=partition(num,left,right)
s=p-left #์ผ์ชฝ ๊ทธ๋ฃน์ ํฌ๊ธฐ
if k<=s:
return selection(num,left,p-1,k)
elif k==s+1:
return num[p]
else:
return selection(num,p+1,right,k-s-1)
makeList(num)
print(*num)
k=int(input())
print(selection(num,0,size-1,k))
์ถ์ฒ : ์๊ธฐ ์ฌ์ด ์๊ณ ๋ฆฌ์ฆ(๊ฐ์ ํ), ์์ฑ๋ด, ์๋ฅ ์ถํ์ฌ
'๐ปAlgorithm > ์ด๋ก ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๊ทธ๋ฆฌ๋(Greedy) - ์ต์์ ์ฅํธ๋ฆฌ(MST) (0) | 2022.04.18 |
---|---|
๋์ ๊ณํ ์๊ณ ๋ฆฌ์ฆ(DP/Dynamic Programming) (0) | 2022.04.18 |
๊ทธ๋ฆฌ๋(Greedy)/ํ์ ๊ธฐ๋ฒ (0) | 2022.04.15 |
๋ถํ ์ ๋ณต(Divide and Conquer) - ์ต๊ทผ์ ์ ์ ์ ์ฐพ๊ธฐ (0) | 2022.04.11 |