ココアホテルの部屋を手配します
質問:https://programmers.co.kr/learn/courses/30/lessons/64063
[1.理解]
近いホテルの部屋が手配されている場合は、それより大きくて手配されていない部屋を選ぶことができます.
[2.近接]
まず、可能なホテルの部屋数は最大20万個で、この時の番号は0から10^12です.この場合はホテルの部屋番号の並びでは表示できません.したがって,資料構造では,ハッシュツリーベースのコンテナに値を格納するか,リストを使用するか,動的配列ベースのコンテナを使用するかが正しい.通常のフルアクセス(シーケンスアクセス)シーケンスアクセスを使用して空き部屋を探す場合は、時間の複雑さを通過できないため、検索の効率が重要です.大まかに二つの方法を考える.
- 1. ダイナミック配列+二分ナビゲーション
実装ロジックは次のとおりです.手配した部屋番号は昇順に並べられています.
1.まず部屋のレイアウトでお客様が望む部屋を探す
2.お客様が希望する部屋が空いていれば、その部屋を手配します.
3.部屋が空いていなければ、その部屋を起点に、空き部屋があるかどうかを並べて探します.
4.手配した部屋を並べる.
この場合、配列された該当点に空き部屋があるかどうかを判断するために、容量(範囲内に入ることができる部屋の数)とsize(実際に入る部屋の数)が使用される.例:
roomの[0,2]には、room[0]=1、room[1]=2、room[2]=4がある.
このときsizeは3です.(この範囲に3つの値を入力できます.)
そして容量は4です.[[room[0],room[2]であるため、1、2、3、および4個の値を含むことができる.)
すなわち、容量と大きさが異なる場合はその範囲内に空き部屋が存在し、同じ場合は空き部屋は存在しない.
ぶんせき
まず,空き部屋を探すのに要する時間の複雑さはO(logn)である.しかし,動的配列の中間点挿入に必要な複雑さはO(N)である.また,2回の二分検索を用いたため,コードの複雑さも高い.
- 2. ハッシュマッピング+Union Find
ハッシュマッピングpmapの場合、keyは部屋の番号であり、valueは部屋の親部屋、すなわちその部屋に近づくと押し出される部屋の番号である.例:pMap[4]は5を指し、割り当てられた部屋が1,2,4で同期していると仮定する.
論理全体は次のとおりです.
1.お客様が希望する部屋がある場合(pMapに該当するキー値がない場合)
割り当て、pMap[num]=+num.△次の部屋の場所を教えてあげます.
2.お客様が自分の希望する部屋がない場合は、ユニオンフィールドで空き部屋があるまで再探索します.同期します.見つかった部屋について1番のレッスンを行います.
ぶんせき
Union Findでは、ナビゲートするたびに、ナビゲートしたノードを同期します.DPのメモリ割り当てのように、次の手順を実行する必要があります.1号に空き部屋があるか確認する際、探索中にHashMapを使うのはO(1)です.また、空き部屋がなければ、その空き部屋を探す過程はユニオンツリーのDepthに比例する.一度のブラウズでは,Depthに属するブラウズ中のノードが一度に同期し,Memorizationの効果が見られる.このことから,すべての部屋を割り当てるのに要する時間はO(N)に比例することが分かる.
[3.実施]ダイナミックアレイ+デュアルナビゲーション 海図+Union Find
[1.理解]
近いホテルの部屋が手配されている場合は、それより大きくて手配されていない部屋を選ぶことができます.
[2.近接]
まず、可能なホテルの部屋数は最大20万個で、この時の番号は0から10^12です.この場合はホテルの部屋番号の並びでは表示できません.したがって,資料構造では,ハッシュツリーベースのコンテナに値を格納するか,リストを使用するか,動的配列ベースのコンテナを使用するかが正しい.通常のフルアクセス(シーケンスアクセス)シーケンスアクセスを使用して空き部屋を探す場合は、時間の複雑さを通過できないため、検索の効率が重要です.大まかに二つの方法を考える.
- 1. ダイナミック配列+二分ナビゲーション
実装ロジックは次のとおりです.手配した部屋番号は昇順に並べられています.
1.まず部屋のレイアウトでお客様が望む部屋を探す
2.お客様が希望する部屋が空いていれば、その部屋を手配します.
3.部屋が空いていなければ、その部屋を起点に、空き部屋があるかどうかを並べて探します.
4.手配した部屋を並べる.
この場合、配列された該当点に空き部屋があるかどうかを判断するために、容量(範囲内に入ることができる部屋の数)とsize(実際に入る部屋の数)が使用される.例:
roomの[0,2]には、room[0]=1、room[1]=2、room[2]=4がある.
このときsizeは3です.(この範囲に3つの値を入力できます.)
そして容量は4です.[[room[0],room[2]であるため、1、2、3、および4個の値を含むことができる.)
すなわち、容量と大きさが異なる場合はその範囲内に空き部屋が存在し、同じ場合は空き部屋は存在しない.
ぶんせき
まず,空き部屋を探すのに要する時間の複雑さはO(logn)である.しかし,動的配列の中間点挿入に必要な複雑さはO(N)である.また,2回の二分検索を用いたため,コードの複雑さも高い.
- 2. ハッシュマッピング+Union Find
ハッシュマッピングpmapの場合、keyは部屋の番号であり、valueは部屋の親部屋、すなわちその部屋に近づくと押し出される部屋の番号である.例:pMap[4]は5を指し、割り当てられた部屋が1,2,4で同期していると仮定する.
論理全体は次のとおりです.
1.お客様が希望する部屋がある場合(pMapに該当するキー値がない場合)
割り当て、pMap[num]=+num.△次の部屋の場所を教えてあげます.
2.お客様が自分の希望する部屋がない場合は、ユニオンフィールドで空き部屋があるまで再探索します.同期します.見つかった部屋について1番のレッスンを行います.
ぶんせき
Union Findでは、ナビゲートするたびに、ナビゲートしたノードを同期します.DPのメモリ割り当てのように、次の手順を実行する必要があります.1号に空き部屋があるか確認する際、探索中にHashMapを使うのはO(1)です.また、空き部屋がなければ、その空き部屋を探す過程はユニオンツリーのDepthに比例する.一度のブラウズでは,Depthに属するブラウズ中のノードが一度に同期し,Memorizationの効果が見られる.このことから,すべての部屋を割り当てるのに要する時間はO(N)に比例することが分かる.
[3.実施]
#include <bits/stdc++.h>
using namespace std;
#define ll long long
vector<ll> hotel; //고객이 예약한 방이 번호별 정렬되있음.
bool isRange(int end, int start); //해당 범위에 빈방이 있는지 체크
pair<int, bool> process1(ll &room); //고객이 원하는 지점에 빈방이 있는지 체크및 없다면 방의 위치 반환
ll process2(int start); //해당지점의 방위치부터 이분탐색으로 빈방의 위치를 찾음
bool isRange(int end, int start)
{
ll capacity_ = hotel[end] - hotel[start]; //수용가능공간
ll size_ = end - start; //현재 차있는공간
return capacity_ != size_; //빈방이있다면
}
pair<int, bool> process1(ll &room) //int=위치 bool=true일시 작업끝남(방에들어감),false:방 위치 찾지못함
{
pair<int, bool> result;
int left = 0;
int right = hotel.size() - 1;
while (left < right)
{
int mid = (left + right) >> 1;
if (hotel[mid] >= room)
right = mid;
else
left = mid + 1;
}
if (hotel.empty() || hotel.back() < room) //비어있거나 더큰값일시
{
hotel.push_back(room);
result = {0, true};
}
else //비어있지않을시
{
if (hotel[left] == room) //방이있을시
{
result = {left, false}; //있다면 해당방의 [위치,true] return
}
else
{
if (hotel[left] > room)
{
hotel.insert(hotel.begin() + left, room);
}
else
{
hotel.push_back(room);
}
result = {0, true}; //없다면 hotel에 집어넣고 [0,true] return
}
}
return result;
}
ll process2(int start)
{
ll result;
int left = start;
int right = hotel.size() - 1;
while (left < right)
{
int mid = (left + right) / 2;
if (isRange(mid, start)) //해당범위안에 남은 방이있을경우
right = mid;
else
left = mid + 1;
}
if (isRange(left, start))
{
result = hotel[left - 1] + 1;
hotel.insert(hotel.begin() + left, result);
}
else{
result=hotel[left]+1;
hotel.push_back(result);
}
return result;
}
vector<ll> solution(ll k, vector<ll> room_number)
{
vector<ll> answer;
for (auto room : room_number)
{
pair<int, bool> info = process1(room);
if (!info.second) //해당지점에 빈방이 없다면
{
room = process2(info.first); //고객원하는지점부터 빈방찾기
}
answer.push_back(room); //새로찾은 방위치 집어넣기
}
hotel.clear();
return answer;
}
#include<bits/stdc++.h>
#define ll long long
using namespace std;
unordered_map<ll,ll> P;
ll find(ll room){
if(P[room]==0) return room;
else return P[room]=find(P[room]);
}
vector<ll> solution(ll k, vector<ll> room_number)
{ vector<ll> answer;
for(auto number:room_number){
ll room=find(number);
P[room]=room+1;
answer.push_back(room);
}
return answer;
}
Reference
この問題について(ココアホテルの部屋を手配します), 我々は、より多くの情報をここで見つけました https://velog.io/@geunwoobaek/카카오호텔방-배정テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol