ํ’€์ด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์ธ ์ƒํ™ฉ์—์„œ ํƒ์ƒ‰์„ ๊ณ„์†ํ•  ์ˆ˜ ์—†๋‹ค. ๊ฐ™์•„์ง€๋Š” ์ˆœ๊ฐ„ ์ข…๋ฃŒํ•œ๋‹ค.

๊ธฐ๋ณธ์ ์ธ ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•ต์‹ฌ์€,

  1. ์›ํ•˜๋Š” ์ˆ˜๋ฅผ ์ฐพ๋Š”๋‹ค.
  2. ์›ํ•˜๋Š” ์ˆ˜๋ฅผ ์ฐพ์•˜์œผ๋ฉด ๊ทธ ์ˆ˜๋ฅผ 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๋กœ ๋‹ต์„ ๋‚ด๋ ค๋Š” ๊ฐ€์ •์ด ๊น”๋ ค์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด๋‹ค. ๊ทธ๊ฒŒ ๊ฐ€์žฅ ์ค‘์š”ํ•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ์ค‘์•™๊ฐ’์„ ์ œ์•ˆํ–ˆ์„ ๋•Œ ๋ฌธ์ œ์˜ ๋ชฉ์ ์— ๋งž๊ฒŒ ํ›„๋ณด๊ฐ€ ๋˜๋Š”์ง€๋งŒ ํŒ๋‹จํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ๋‘ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๊ณตํ†ต์ ์œผ๋กœ ๊ฐ€์ •ํ•˜๋Š” ๊ฒƒ์„ ์ •๋ฆฌํ•ด๋ณด์ž.

  1. right index๋กœ ๋‹ต์•ˆ์„ ๋‚ผ ๊ฒƒ์ด๋‹ค.
  2. ๋‚˜์ค‘์— while๋ฌธ์„ ํ†ต๊ณผํ•˜๊ธฐ ์œ„ํ•ด ์–‘์ชฝ index(left, right)๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ๋•Œ๋Š” leftํ•œ์ชฝ์œผ๋กœ๋งŒ ์ด๋™ํ•œ๋‹ค.
    • ์ฆ‰ ์ด๋ง์€ right index๋Š” ์—…๋ฐ์ดํŠธ ์‹œ mid๋ฅผ ๊ทธ๋Œ€๋กœ ๋‘๊ณ , left๋งŒ mid+1๋กœ ๊ธฐ์กด ๊ฐ’์„ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š์•„ ์ตœ์ข…์ ์œผ๋กœ while (left < right) ๋ฌธ์„ ํ†ต๊ณผํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.
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)

Reference