-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
4-YIM2UL2ET #12
4-YIM2UL2ET #12
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ 흠잡을 곳 없는 좋은 코드라고 생각합니다.
✔️ 2번과 3번 기능에 대하여 main함수에 바로 작성해주셨지만, 따로 함수를 빼서 작성해보시는 것도 추천합니다!!
더 코드가 직관적이고 보기 좋아질 수도 있을 것 같아요!!
수고하셨습니다.😁
for (int i = 0; i < n;) { | ||
dq.push_back(++i); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for문에서 증감식을 쓰지 않는 형태는 되게 오랜만에 보는 것 같습니다 ㅎㅎ
우와!! 하면서 오랜만에 눈이 뜨였던 코드인거 같네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (int i = 0; i < n; i++) {
dq.push_back(i+1);
}
이렇게 적어도 무방하지만 이게 더 가독성이 더 좋지 않을까 싶어 적어보았습니다. 둘 중에 어떤게 더 나으신 것 같나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ 좋은 코드인거 같아요!
❓ 문제 설명에서 보면 덱이 아니라 배열로 구현을 하고 시작 인덱스만 옮겨다니는 방법으로도 가능할 것 같은데 어떻게 생각하시는지 궁금합니다!
전 문제 해석을 잘못해서 입력 순서대로가 아니라 한번에 입력받고 원하는 위치의 원소를 모두 얻는 최단 방법을 구하느라 삽질했네요 ㅎㅎ.. |
저도 문제를 풀고 조금 생각해 보니 이 방법이 조금 더 좋겠다고 생각했었습니다. #include <iostream>
#include <algorithm>
#include <vector>
int main(void)
{
int n, m, k, front, result;
std::vector <int> vec;
std::cin >> n >> m;
for (int i = 0; i < n;) vec.push_back(++i);
result = 0, front = 0;
for (int i = 0; i < m; i++) {
std::cin >> k;
int idx = std::distance(vec.begin(), std::find(vec.begin(), vec.end(), k));
int distance = abs(front - idx);
if (distance < vec.size() - distance) result += distance;
else result += vec.size() - distance;
vec.erase(vec.begin()+idx);
if (vec.size() > 0) front = idx % vec.size();
}
std::cout << result;
return 0;
} 덱을 벡터로 바꾸고, 지울 원소의 인덱스인
추가적으로 vec.erase(vec.begin()+idx);
if (vec.size() > 0) front = idx % vec.size(); 이 부분을 vec.erase(vec.begin()+idx);
front = idx; 이렇게 바꿔도 값은 같게 나오지만, |
저도 항상 문제 풀 때마다 문제 이해를 잘 못 할 때가 많아서 공감이 됩니다.. |
#include <iostream>
#include <algorithm>
#include <deque>
void op_2(std::deque <int> * dq);
void op_3(std::deque <int> * dq);
int main(void)
{
int n, m, k, idx, result;
std::deque <int> dq;
std::cin >> n >> m;
for (int i = 0; i < n;) dq.push_back(++i);
result = 0;
for (int i = 0; i < m; i++) {
std::cin >> k;
int idx = std::distance(dq.begin(), std::find(dq.begin(), dq.end(), k));
if (idx < dq.size() - idx) {
result += idx;
for (int j = 0; j < idx; j++) op_2(&dq);
}
else {
result += dq.size() - idx;
for (int j = 0; j < dq.size() - idx; j++) op_3(&dq);
}
dq.pop_front();
}
std::cout << result;
return 0;
}
void op_2(std::deque <int> * dq)
{
int temp = dq->front();
dq->pop_front();
dq->push_back(temp);
}
void op_3(std::deque <int> * dq)
{
int temp = dq->back();
dq->pop_back();
dq->push_front(temp);
} 조언 해주신 대로 2번 연산과 3번 연산을 함수로 짜서 코드를 수정해보았습니다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이름처럼 선형 큐가 바로 떠오르는 문제네요.
문제에서 큐의 길이를 먼저 지정해주기 때문에 포인터를 움직이면서 접근하는게 좋을 것 같다고 생각했는데 이미 위에서 코드구현까지 다 하셨네요 😄
연산방법과 인덱스접근 각각 깔끔하게 잘 설명하시고 풀이하셔서 이해하기 매우 쉬웠습니다. 수고하셨습니다. 👍 👍
int temp = dq.front(); | ||
dq.pop_front(); | ||
dq.push_back(temp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위 코드에서 front()
와 pop_front()
를 각각 사용하셨는데 temp=dq.pop_front()
로 삭제와 대입을 동시에 하면 안되는 이유가 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cpp에서 pop
에 관련된 멤버 함수는 return
값이 없는 void
형 함수밖에 없는 것으로 알고 있습니다.
실제로 저 두 줄을 지우고 temp = dq.pop_front()
를 적으면 오류가 납니다.
무조건 먼저 값을 가져온 후에 pop
을 해줘야 합니다. (STL 공부를 안 해서 틀릴 수도 있어요..)
🔗 문제 링크
1021 - 회전하는 큐
✔️ 소요된 시간
30m + α
✨ 수도 코드
1. 문제 설명
이 문제는 1부터
n
까지의 숫자 원소를 가지고 있는queue
에서m
개의 수를 차례대로 입력 받아 3가지 연산을 이용하여 순서대로queue
에서 빼내고, 그중에서 2번, 3번의 연산 횟수의 최솟값을 구하는 문제입니다. 다음은 큐의 초기 상태와 각 3가지 연산입니다.초기 큐의 상태는 이렇습니다.
1번 연산은 첫번째로 가리키는 원소를 빼내는 연산입니다.
2번 연산은 첫번째로 가리키는 원소를 왼쪽으로 한칸씩 옮기는 연산입니다.
3번 연산은 첫번째로 가리키는 원소를 오른쪽으로 한칸씩 옮기는 연산입니다.
2. 문제 분석
1. 큐를 이용한 연산 구현 시도
보자마자 바로 원형 큐가 생각나시죠? 하지만 조금은 다릅니다.
우선 그림을 보면서 3가지 연산에 대한 구현을 생각을 해봅시다. (코드 구현은 나중에)
1번 연산은 queue에서 첫번째로 가리키는 원소를 빼는 작업입니다.
간단하게 첫번째 원소를
pop
해주면 되겠지요.2번 연산은
queue
에서 원소들을 한칸씩 왼쪽으로 옮기는 작업입니다.우리는 큐를 쓰기 때문에
queue
에서 첫번째 원소를 뒤쪽으로 옮겨주면 되겠지요?간단하게 맨 앞에 있는 원소를 임시 변수에 저장해 둔 후에
pop
하고, 이를 다시 뒤에서push
하면 됩니다.3번 연산은
queue
에서 원소들을 한칸씩 오른쪽으로 옮기는 작업입니다.이 때는 2번 연산처럼 맨 뒤에 있는 원소를 임시 변수에 저장해 둔 후에
pop
하고, 이를 앞에서push
해야 합니다.그러나 여기서 문제가 생깁니다. 큐에서는
push
를 뒤쪽에만 할 수 있고,pop
은 앞쪽에서만 가능하기 때문입니다.따라서 이 문제는 큐를 써야 할 것이 아니라 덱을 사용하여 앞과 뒤 양쪽에서 값을
pop
하고push
할 수 있도록 해야 합니다.2. 덱을 이용한 연산 구현
그렇다면 덱을 이용하여 3가지 연산을 코드로 구현해 보도록 하겠습니다.
dq
는 임의로 1 ~n
까지 숫자를 차례대로 원소로 가지고 있다고 가정합시다.큐가 아닌 덱을 사용하면 1번과 2번 연산은 물론이고 3번 연산까지도 깔끔하게 구현 할 수 있음을 확인할 수 있습니다.
3.
result
값 구하기그럼 이제 문제의 본질로 돌아와 봅시다. 문제가 원하는 값은 2번과 3번 연산을 가능한 최소로 사용한 횟수입니다.
어떻게 구할까 머릿속으로 생각하지 말고 그림을 보고 편하게 생각해봅시다.
만약 덱의 크기가
8
이라고 할 때 첫 번째로 가리키는 원소가a1
이고,a7
을 꺼내고 싶으면 어떻게 하면 좋을까요?2번 연산을
6
회 사용한 후에 1번 연산을 하는 것과, 3번 연산을2
회 사용한 후에 1번 연산을 하는 것이 있겠지요?또한
result
값에는 더 작은 값을 더해주어야 하므로2
를 더해주어야 할 것입니다.이를 선형으로 봐봅시다.
a1
과a7
의 거리 차는 2번 연산을 활용하면6
의 거리를 갖게 되고, 3번 연산을 활용하면2
의 거리를 갖게 됩니다.이 때 각각의 거리 (= 연산 횟수)는
a7
의 인덱스와 덱의 크기 간의 관계식으로 나타낼 수 있습니다.이 그림에서는
2번 연산 횟수
=a7의 인덱스
이고,3번 연산 횟수
=덱의 크기
-a7의 인덱스
로 나타낼 수 있지요.이를 일반화 하면 꺼내고 싶은 원소의 위치를
idx
, 덱의 사이즈를size
라고 할 때 다음과 같이 정리할 수 있습니다.idx
size
-idx
이를 총
m
번의 입력 값에 따라 if문을 활용하여 더 적은 연산 횟수를 구하여 그에 따른 연산 횟수를result
값에 더하고, 연산하는 것을 반복해 나가면 될 것입니다. 이제 수도코드를 짜봅시다.3. 수도코드
4. 최종 코드
📚 새롭게 알게된 내용
스택에 이어서 큐를 공부해 보았습니다. 생각하는 과정을 쓰는 것은 여전히 쉽지가 않네요. (문제 푸는데 30분, PR 쓰는데 4시간..)
다음은 도움을 받은 자료들 입니다.
deque container 정리
find 함수 사용법