ํ์ด1
์ค๋ฒ4 : ์ด๋ถ ํ์ ๋ฌธ์ ์ด๋ค.
์๊ฐ
ํน์ ์ซ์๊ฐ ๋ฑ์ฅํ๋ lowerBound์ UpperBound๋ฅผ ์ก์๋ด๋ฉด ๋๋๋ ๋ฌธ์ ์ด๋ค.
LowerBound
์ํ๋ ์ซ์๊ฐ ์ฒ์์ผ๋ก ๋ฑ์ฅํ๋ ๊ณณ์ ๋ฒ์งธ
๊ธฐ๋ณธ์ ์ธ ์ด๋ถ ํ์์, ๋ด๊ฐ ํ์ํ index๋ฅผ ํฌํจํ์ง ์์ ์ํ๋ก ๋ค์ index๋ฅผ ํ์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐพ์ผ๋ฉด returnํ๋ค. ํ์ง๋ง, ์ด๋ฒ์ ์ฐ๋ฆฌ๊ฐ ํ ๊ฒ์, ํด๋น ์ซ์์ ๋ฒ์๋ฅผ ํ์ํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ์ฐพ์๋ค๊ณ ํด์ ํ์์ ๋๋ผ ์ ์๋ค. ๋ค๋ง, ๋ด๊ฐ ์ํ๋ ๊ฐ๊ณผ ๊ฐ์ ๊ฐ์ด ์๋ค๋ฉด, ๊ทธ index๋ ๋ต์ ํ๋ณด๊ฐ ๋ ์ ์๋ค. ์ต์ข ์ ์ธ ๋ต์ ๋๊น์ง ํ์ํ ํ์ ๋์ถ๋๋๋ก ๋ง๋ค์ด์ผ ํ๋ค. ์์๋ฅผ ๋ณด์.
0 1 2 3 4 5 6 7 8 9 10
-10 -10 2 3 3 6 7 10 10 10 13
์ ๋ ฌ์ด ๋ ์ํ์์ 10์ lowerBound๋ฅผ ์ฐพ์๋ณด์.
#1
start : 0 end : 11 mid : 5 a[5] : 6
์ด ์ํฉ์์ ๋ต์ ๋ฌด์กฐ๊ฑด 5๋ณด๋ค ํฐ index์์ ๋์ฌ ์ ๋ฐ์ ์๋ค. ๋ฐ๋ผ์ start = mid + 1
ํด์ค๋ค.
#2
start : 6 end : 11 mid : 8 a[8] : 10
8์ index์์ ์ฐพ๋ ๊ฐ์ด ๋์๋ค. ํด๋น index๋ ๋ต์ ํ๋ณด์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ํฌํจํ ์ํ๋ก ๋ค์ ๊ฐ์ผ๋ก ๋์ด๊ฐ์ผ ํ๋ค. end = mid
#3
start : 6 end : 8 mid : 7 a[7] : 10
๋ ํ๋ณด๊ฐ์ด ๋์๋ค. ์ด ๋ index๊ฐ ๋ ์์ผ๋ฉด์ 10์ ๋ง์กฑํ๊ธฐ ๋๋ฌธ์ end = mid
ํด์ค๋ค.
#4
start : 6 end : 7 mid : 6 a[6] : 7
7๋ณด๋ค ํฐ๊ณณ์์ 10์ ๋์จ๋ค. ๋ฐ๋ผ์ start = mid + 1
ํด์ค๋ค.
#5
start : 7 end : 7 mid : 7 a[7] : 10
start์ end๊ฐ ๊ฐ์์ก๋ค. ์๋ ์ด๋ถํ์๊ณผ ๋ค๋ฅด๊ฒ ์ด๋ฌํ ์กฐ๊ฑด ๋๋ฌธ์ start = end์ธ ์ํฉ์์ ํ์์ ๊ณ์ํ ์ ์๋ค. ๊ฐ์์ง๋ ์๊ฐ ์ข ๋ฃํ๋ค.
๊ธฐ๋ณธ์ ์ธ ์ด ์๊ณ ๋ฆฌ์ฆ์ ํต์ฌ์,
- ์ํ๋ ์๋ฅผ ์ฐพ๋๋ค.
- ์ํ๋ ์๋ฅผ ์ฐพ์์ผ๋ฉด ๊ทธ ์๋ฅผ end์ ๋ฐ์๋๊ณ ๊ณ์ ํ์ํ๋ค.
์ด๋ ๊ฒ ์์ถํ ์ ์๋ค. ๋ง์ฝ ์ํ๋ ์๊ฐ ์๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ํ ์ซ์์ value๊ฐ ์ํ๋ ๊ฐ๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ ๊ฒฝ์ฐ, end = mid
ํ๊ธฐ ๋๋ฌธ์ ์๋ค๋ฉด ์ํ๋ ๊ฐ๋ณด๋ค ํฐ ์์ค์์ ๊ฐ์ฅ ์์ ์์ ์์น๋ฅผ returnํ ๊ฒ์ด๋ค. ์ฆ, 1 3 5 7
์์ 4๋ฅผ ์ฐพ๋๋ค๋ฉด, ์๊ธฐ ๋๋ฌธ์ lowerBound๋ 3(index = 2)๋ฅผ ๋ฆฌํดํ๋ค.
Code
int lowerBound(int num){
int start = 0, end = N, mid = 0;
while (start < end) {
mid = (start+end)/2;
if (a[mid] < num) {
start = mid + 1;
} else {
end = mid;
}
}
return end + 1;
}
UpperBound
์ํ๋ ์ซ์๋ณด๋ค ์ฒ์์ผ๋ก ํฌ๊ฒ๋๋ ์์น
lowerBound์ ๋ค๋ฅด๊ฒ, 10์ ์ฐพ๋๋ค๋ฉด, 10๋ณด๋ค ์ฒ์์ผ๋ก ํฌ๊ฒ๋๋ ์์น๋ฅผ ๋ฆฌํดํ๊ฒ ๋๋ค.
์ด๋ถ ํ์์ผ๋ก๋ถํฐ ์๊ฐํด๋ณด์. ์๋ ๊ฐ์ผ๋ฉด ๊ฐ์ ๋, ํ์ถํ์ฌ ๋ต์ ์ ์ํ๋ค. ํ์ง๋ง, ๋ด๊ฐ ์ํ๋ ๊ฒ์ ์ฐพ์ ๋ค์ ์ด๋ ํ ์กฐ์น๊ฐ ํ์ํ๋ค. ์ฐพ์ ๊ฐ์, lowerBound์์์ ๋ค๋ฅด๊ฒ, ๋ต์ ํ๋ณด๊ฐ ๋ ์ ์๋ค. ์๋ฅผ ๋ค์ด, ๋ด๊ฐ 10์ด๋ผ๋ ๊ฐ์ ์ฐพ์๋ค. ํ์ง๋ง ์์ ์ ํ ์ ์๋ 10์ ์ฐพ์ ๊ฒ์ด ์ค์ํ ๊ฒ์ด ์๋๊ณ , 10๋ณด๋ค ์ธ์ ์ฒ์์ผ๋ก ์ปค์ง๋๊ฐ ๊ถ๊ธํ๋ค. ๋ฐ๋ผ์ ์ฐพ์๋ค๋ฉด, ํด๋น ์ ์ํ ์์น๋ ๋ต์ด ๋ ์ ์๋ค. ๋ฐ๋ผ์ ์ด ๊ฐ์ ํฌํจํ์ง ์๊ณ ํ์ํด์ผ ํ๋ค. ์์๋ฅผ ๋ณด์.
#1
start : 0 end : 11 mid : 5 a[5] : 6
6์ 10๋ณด๋ค ์์ผ๋ฏ๋ก ์ด ๊ณณ์์ ๋ต์ด ๋์ฌ ์๋ ์๋ค. start = mid + 1
#2
start : 6 end : 11 mid : 8 a[8] : 10
8์์น์์ 10์ด ๋์์ง๋ง, ์ด 10์ ๋ด๊ฐ ์ํ๋ ๋ต์ด ์๋๋ค. start = mid + 1
#3
start : 9 end : 11 mid : 10 a[10] : 13
10์ ์์น์์ 13์ด ๋์๊ณ , 10์ upperBound๋ ์ด ๊ฐ์ ํฌํจํ ์๋ ์์ญ์์ ๋์จ๋ค. ๋ฐ๋ผ์ ํด๋น 10 index๋ ํฌํจํ ์ํ๋ก ํ์์ ์งํํ๋ค. end = mid
#4
start : 9 end : 10 mid : 9 a[9] : 10
9์์น์์ 10์ด ๋์์ง๋ง, ์ด 10์ ๋ด๊ฐ ์ํ๋ ๋ต์ด ์๋๋ค. start = mid + 1
#5
start : 10 end : 10 mid : 10 a[10] : 13
start = end๊ฐ ๋์ด ์ข ๋ฃํ๋ค. upperBound๋ 10์ด๋ค.
๊ฒฐ๊ตญ, ์ด๋ ๋ฒ์์์ ๋ต์ด ๋ํ๋ ์ ์๋์ง๋ฅผ ๋ช ํํ๊ฒ ๊ท๋ช ํ๋ ๊ฒ์ด ์ค์ํ๋ค. upperBound๋ lowerBound์ ๋ง์ฐฌ๊ฐ์ง๋ก ํ์ํ๋ ๊ฐ์ด ์๋ค๋ฉด ์ด ๊ฐ๋ณด๋ค ํฐ ์๋ค ์ค ๊ฐ์ฅ ์์ ์์ ์์น๋ฅผ ๋ฆฌํดํ๋ค. ์, ์ ์๊ฐํด์ผ ํ๋ ๋ถ๋ถ์ด ์๋๋ฐ, ํ์ ๋ฒ์๋ฅผ 0~N-1๋ก ํ๋ฉด ์๋๋ค. ๊ทธ๋ ๊ฒ ๋ ๊ฒฝ์ฐ, ๋งจ ๋์ ๋ด๊ฐ ์ฐพ๊ณ ์ถ์ ๊ฐ์ด ์์ ๋, ์ํ๋ index๋ฅผ ๋ฐํํ ์ ์๋ค.
1 10 10 10
์ด๋ฐ ๊ฒฝ์ฐ์ 10์ upperBound๋ฅผ ์ฐพ๋๋ค๊ณ ํด๋ณด์. ์ ์์ ์ํ๋ฉด ๋ต์ ๋น์ฐํ 5์ด๋ค. ํ์ง๋ง ๋ด๊ฐ ํ์์ ์งํํ ๋, start = 0, end = 3์ด๋ผ๊ณ ๋๊ณ ์๊ฐํ๋ฉด, ์ต์ข ํ์ ๊ฒฐ๊ณผ๋ 3์ ๋์ง ๋ชปํ๊ณ return ๊ฐ์ 1์ ๋ํ 4์ด๋ค. ์ฆ ์ ๋๋ก 4๋ฅผ ๋์ ๊ฐ์ด ๋์ฌ ์๊ฐ ์๋ค. ์์ ์ ์ํ upperBound ์ ์์ ์ผ๊ด์ฑ์ ์์ง ์๊ธฐ ์ํด์๋ end์ index๋ฅผ ํ๋ ๋๋ ค์ ์ ํด๋๋ ๊ฒ์ด ๋ฐ๋์งํ๋ค.
Code
int upperBound(int num){
int start = 0, end = N, mid = 0;
while (start < end) {
mid = (start+end)/2;
if (a[mid] <= num) { // ๋ฑํธ๋ง ๋ค๋ฅด๋ค.
start = mid + 1;
} else {
end = mid;
}
}
return end + 1;
}
Code
#include<iostream>
#include<vector>
#include<algorithm>
#include<list>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<queue>
#include<functional>
using namespace std;
typedef long long ll;
int N, M;
int a[500001];
int lowerBound(int num){
int start = 0, end = N, mid = 0;
while (start < end) {
mid = (start+end)/2;
if (a[mid] < num) {
start = mid + 1;
} else {
end = mid;
}
}
return end + 1;
}
int upperBound(int num){
int start = 0, end = N, mid = 0;
while (start < end) {
mid = (start+end)/2;
if (a[mid] <= num) {
start = mid + 1;
} else {
end = mid;
}
}
return end + 1;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> N;
for (int i = 0; i < N; i++) cin >> a[i];
sort(a, a+N);
cin >> M;
for (int i = 0; i < M; i++) {
int num, ans = 0;
cin >> num;
int low = lowerBound(num);
int high = upperBound(num);
if (low != high) ans = high-low;
cout << ans << " ";
}
return 0;
}
STL upperBound, lowerBound๋ฅผ ์ด์ฉํ ํ์ด
#include<iostream>
#include<vector>
#include<algorithm>
#include<list>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<queue>
#include<functional>
using namespace std;
typedef long long ll;
int N, M;
int a[500001];
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> N;
for (int i = 0; i < N; i++) cin >> a[i];
sort(a, a+N);
cin >> M;
for (int i = 0; i < M; i++) {
ll num, ans = 0;
cin >> num;
ll low = lower_bound(a, a+N, num)-a;
ll high = upper_bound(a, a+N, num)-a;
if (low != high) ans = high-low;
cout << ans << " ";
}
return 0;
}
ํ์ด2
์ค๋ฒ2 : ์ ๋ ฌ ๋ฌธ์ ์ด๋ค.
์ด์ ์ upper bound, lower bound๊ฐ ์ ๋ช ํํ ์ดํด๊ฐ ์๋์ด์ ๋ค์ ํ์ด์ฌ์ผ๋ก ํ์ด๋ณด์ํ๊ณ ๋์ ํ๋ค.
lower bound
์ํ๋ ๊ฐ๋ณด๋ค ํฐ ๊ฐ์ ์์ index
์ผ๋จ ๋จผ์ ์์๋ฌ์ผ ํ๋ ๊ฒ์, lower bound๋ upper bound๋ ์ค๋ฅธ์ชฝ index๋ก ๋ต์ ๋ด๋ ค๋ ๊ฐ์ ์ด ๊น๋ ค์๋ค๋ ์ฌ์ค์ด๋ค. ๊ทธ๊ฒ ๊ฐ์ฅ ์ค์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋์ ์ค์๊ฐ์ ์ ์ํ์ ๋ ๋ฌธ์ ์ ๋ชฉ์ ์ ๋ง๊ฒ ํ๋ณด๊ฐ ๋๋์ง๋ง ํ๋จํด์ฃผ๋ฉด ๋๋ค. ๋ ์๊ณ ๋ฆฌ์ฆ์ด ๊ณตํต์ ์ผ๋ก ๊ฐ์ ํ๋ ๊ฒ์ ์ ๋ฆฌํด๋ณด์.
- right index๋ก ๋ต์์ ๋ผ ๊ฒ์ด๋ค.
- ๋์ค์ while๋ฌธ์ ํต๊ณผํ๊ธฐ ์ํด ์์ชฝ index(left, right)๋ฅผ ์
๋ฐ์ดํธ ํ ๋๋ leftํ์ชฝ์ผ๋ก๋ง ์ด๋ํ๋ค.
- ์ฆ ์ด๋ง์ right index๋ ์
๋ฐ์ดํธ ์ mid๋ฅผ ๊ทธ๋๋ก ๋๊ณ , left๋ง mid+1๋ก ๊ธฐ์กด ๊ฐ์ ๊ฒ์ฌํ์ง ์์ ์ต์ข
์ ์ผ๋ก
while (left < right)
๋ฌธ์ ํต๊ณผํ๊ธฐ ์ํจ์ด๋ค.
- ์ฆ ์ด๋ง์ right index๋ ์
๋ฐ์ดํธ ์ mid๋ฅผ ๊ทธ๋๋ก ๋๊ณ , left๋ง mid+1๋ก ๊ธฐ์กด ๊ฐ์ ๊ฒ์ฌํ์ง ์์ ์ต์ข
์ ์ผ๋ก
def lower_bound(a, v): # v์ดํ ์ต๋ ์ธ๋ฑ์ค
left = 0
right = len(a)
print("left right mid value action")
while left < right:
temp = []
mid = (left+right)//2
temp.extend(list(map(str, [left, right, mid, v])))
if a[mid] < v:
left = mid + 1
temp.append(f'update left to {mid+1}')
else:
right = mid
temp.append(f'update right to {mid}')
print(" ".join(temp))
return right
index 0 1 2 3 4 5 6 7 8
list 2 4 5 5 5 7 9 9 9
find 5
์์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์ฃผ์ด์ก๋ค๊ณ ์๊ฐํด๋ณด์.
left right mid value action
0 9 4 5 update right to 4
0 4 2 5 update right to 2
0 2 1 5 update left to 2
2
์ 0๊ณผ 8์ ๋ณด๊ณ ์ค๊ฐ๊ฐ์ธ 4๊ฐ ์ฑํ๋๋ค. ๋ฆฌ์คํธ์์ ํด๋น๋๋ ๊ฐ์ 5, ์ํ๋ ๊ฐ๊ณผ ๊ฐ๋ค. ๊ทธ๋ฐ๋ฐ ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ถ์๊ฒ ๋ฌด์์ธ๊ฐ? ์ด 5๊ฐ ์ฒ์์ผ๋ก ๋ฑ์ฅํ๋ ๊ณณ์ ์๊ณ ์ถ์ ๊ฒ์ด๋ค. ๊ทธ๋ผ ์ด๋ ์์ ๋ต์ด ๋ ์ ์๋ ํ๋ณด ์ด๋ค. ๊ทธ๋ฐ๋ฐ ์ด 5๋ณด๋ค ์์ ๊ณณ์์ ๋ต์ด ๋์ค๋ฉด ์ด๋กํ์ง? ๊ทธ๋ฌ๋๊น right ์ธ๋ฑ์ค์ ์๋ฅผ ๋ถ์ก์๋๊ณ ๊ทธ ์ฌ์ด์ ๊ฐ์ ๋ค์ ํ์ํ๋ค. ์ด ์์ ์ ๊ฒฐ๊ณผ๊ฐ ๋๋ฒ์งธ ๋ผ์ธ์ด๋ค. ๋๋ฒ์จฐ์์๋ ์ฐ๋ฆฌ๋ 5๋ฅผ ์ฐพ์๋ค. ์ฌ์ ํ ์๋ก์ด ํ๋ณด์ด๋ ๋ถ์ก์ ๋๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ ๋ค์์ผ๋ก ๊ฐ๋ณด๋ ๊ฐ์ด 4๊ฐ ๋์๋ค. ์๋ ํ๋ณด๊ฐ ๋ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ด 4๋ณด๋ค ํฐ์ชฝ์์ 5๋ผ๋ ๊ฐ์ ์ฐพ์์ผ ํ๋๊น +1ํ์ฌ left๋ฅผ ์ ๋ฐ์ดํธ ํ๋ค. ์ด์ right์ left๊ฐ ๊ฐ์ด 2๋ก ๊ฐ์์ก๊ธฐ ๋๋ฌธ์ ๋ฐ๋ณต๋ฌธ์ ํ์ถํ๊ณ , ๋๋๋ค.
์ฌ๊ธฐ์ ํต์ฌ์, ๊ฐ์ ๊ฒ์ด ๋์์ ๋ ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผ ํ๋๋์์ ํ๋จ์ด๋ค. ๊ฐ์ ๊ฐ์ด ๋์ค๊ฒ ๋์์ ๋, lower bound์ ๊ฒฝ์ฐ ์ผ์ชฝ์ ํ์ํด์ผ ํ๋ค.(๋ ์์ ๊ณณ์ ํ๋ณด๊ฐ ์๋์ง) ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ right๋ฅผ ๋ก๊ฒจ์ค๋ ๊ฒ.
upper bound
์ํ๋ ๊ฐ๋ณด๋ค ํฐ (์ด๊ณผ) ์ฒซ๋ฒ์งธ index
def upper_bound(a, v): # v์ดํ ์ต๋ ์ธ๋ฑ์ค
left = 0
right = len(a)
print("left right mid value action")
while left < right:
temp = []
mid = (left+right)//2
temp.extend(list(map(str, [left, right, mid, v])))
if a[mid] <= v:
left = mid + 1
temp.append(f'update left to {mid+1}')
else:
right = mid
temp.append(f'update right to {mid}')
print(" ".join(temp))
return right
index 0 1 2 3 4 5 6 7 8
list 2 4 5 5 5 7 9 9 9
find 5
๊ฐ์ฅ ์ค์ํ ๊ฒ์ ๋ญ๋ค? ๊ฐ์์ ๋ ์ด๋๋ฅผ ํ์ํด์ผ ํ๋์ง์ด๋ค. ๊ฐ์ ๊ฒฝ์ฐ, ์ด๋ฒ์๋ ์ค๋ฅธ์ชฝ์ ํ์ํด์ผ ํ๋ค. ์๋ํ๋ฉด ์ผ๋จ 5๊ฐ ๋์๋ค. ๊ทธ๋ผ ์๋ณด๋ค ์ผ๋จ ํฐ ๋ถ๋ถ์์ ๋ต์ด ๋์ฌ๊ฑฐ์๋๊ฐ? ๊ทธ๋ฌ๋ mid+1๋ก left๋ฅผ ์ ๋ฐ์ดํธ ํ๋ค. ๋ง์ฝ์ ๊ทธ ๋ค์ ์คํ ์์ ์กฐ์ฌํ ๊ฐ์ด ๋ด๊ฐ ์ํ๋ ๊ฐ๋ณด๋ค ํฌ๋ฉด, ๊ทธ๋ผ ๋ต์ ๋ ์์ ๊ณณ์ ์์ผ๋ ์ด๋ ์์ ๋ถ์ก์ ๋๊ณ (๋ต์ด ๋ ์ ์๋ ํ๋ณด์ด๋ค.) ๋ค์์ผ๋ก ๋์ด๊ฐ๋ค.
left right mid value action
0 9 4 5 update left to 5
5 9 7 5 update right to 7
5 7 6 5 update right to 6
5 6 5 5 update right to 5
5
Code
def lower_bound(a, v): # v์ดํ ์ต๋ ์ธ๋ฑ์ค
left = 0
right = len(a)
print("left right mid value action")
while left < right:
temp = []
mid = (left+right)//2
temp.extend(list(map(str, [left, right, mid, v])))
if a[mid] < v:
left = mid + 1
temp.append(f'update left to {mid+1}')
else:
right = mid
temp.append(f'update right to {mid}')
print(" ".join(temp))
return right
def upper_bound(a, v): # v์ดํ ์ต๋ ์ธ๋ฑ์ค
left = 0
right = len(a)
print("left right mid value action")
while left < right:
temp = []
mid = (left+right)//2
temp.extend(list(map(str, [left, right, mid, v])))
if a[mid] <= v:
left = mid + 1
temp.append(f'update left to {mid+1}')
else:
right = mid
temp.append(f'update right to {mid}')
print(" ".join(temp))
return right
a = [2,4,5,5,5,7,9,9,9]
lower_bound(a, 5)
upper_bound(a, 5)