-
Notifications
You must be signed in to change notification settings - Fork 2
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
37-pknujsp #149
37-pknujsp #149
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.
def solution(coin, cards):
n = len(cards)
now = set(cards[:n//3])
now_can_make = set()
keep = set()
for element in now:
if (n-element+1) in now and (n-element+1,element) not in now_can_make:
now_can_make.add((element,n-element+1))
for idx, start_idx in enumerate(range(n//3,n,2)):
first = cards[start_idx]
second = cards[start_idx+1]
# 먼저 두 카드에 대한 구매 여부 결정
if ((n-first+1) in now) and ((n-first+1, first) not in now_can_make) and (coin > 0):
now_can_make.add((first,n-first+1))
now.add(first)
coin -= 1
else: keep.add(first)
if ((n-second+1) in now) and ((n-second+1, second) not in now_can_make) and (coin > 0):
now_can_make.add((second,n-second+1))
now.add(second)
coin -= 1
else: keep.add(second)
# 다음 라운드 수명 연장을 위해서 카드 제출
if now_can_make:
for pair_1, pair_2 in now_can_make:
now.discard(pair_1)
now.discard(pair_2)
now_can_make.discard((pair_1, pair_2))
break
# 제출할 카드가 없을 경우 keep 목록에서 탐색
elif coin >= 2:
for element in keep:
if n-element+1 in keep:
keep.discard(element)
keep.discard(n-element+1)
coin -= 2
break
else: return idx+1
# 만약 제출할 게 없으면 게임 종료
else: return idx+1
else: return idx+2
준성님이랑 완전 똑같은 로직으로 풀었네요.
저는 이거 그리디인줄 알았는데 구현일까요..?
당장 라운드를 통과하기 위해서 최적의 해만 찾으면 되니까...
"그리디 + 구현" 인 것 같기도 하고..
이 문제는 딱 이걸로만 풀릴 것 같아요. 정해가 정해져 있는?!
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.
수도 코드랑 주석을 깔끔하게 적어두셔서 쉽게 이해할 수 있었습니다!
그 때문인지 문제가 재밌게 느껴지던데 얼른 이 유형의 알고리즘 문제들도 풀어보고 싶네요 🔥🔥!!
@@ -0,0 +1,53 @@ | |||
def solution(coin, cards): | |||
a = set(cards[:len(cards) // 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.
준성님 수도 코드보면서 코드 작성하다가 궁금한게 생겨서 코멘트 남깁니당
set이 아니라 list로 구현해도 통과는 되던데 집합으로 구현하신 이유가 시간 복잡도 때문일까요?
for ~ in에서 list의 경우에는 시간복잡도가 O(n), set의 경우에는 O(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.
네네 말씀하신 그대로 입니다
카드 목록에서 n + 1
이 되는 조합을 확인해볼때
리스트로 한다면 모든 카드를 두 쌍으로 만들어서 일일히 다 비교해야 하는데
집합이라면 쌍으로 비교할 필요없이 카드 하나씩만 확인해보면서 n + 1
이 가능한 카드의 존재여부를 한번에 확인가능하니까요.
removed = False | ||
# 현재 가지고 있는 카드 목록 중 n + 1이 가능한 경우 확인 | ||
for x in list(a): | ||
if t - x in a: |
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.
t - x를 따로 변수로 담을 필요 없이 구현이 가능하군요 .. 이렇게 변수 하나를 또 줄일 수 있군요.. 👍
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 <string>
#include <vector>
#include <unordered_map>
using namespace std;
int solution(int coin, vector<int> cards) {
int n = cards.size();
int index = 0;
int pair = 0;
unordered_map<int, bool> hands, needed;
for (; index < n / 3; index++) {
int card = cards[index];
if (needed[card]) {
needed.erase(card);
hands.erase(n + 1 - card);
pair++;
continue;
}
hands[card] = true;
needed[n + 1 - card] = true;
}
int sparePair = 0;
int answer = 1;
unordered_map<int, bool> spares, spareNeeded;
for (; index < n; index += 2) {
for (int card : {cards[index], cards[index + 1]}) {
if (coin && needed[card]) {
coin--;
needed.erase(card);
hands.erase(n + 1 - card);
pair++;
continue;
}
if (spareNeeded[card]) {
spareNeeded.erase(card);
spares.erase(n + 1 - card);
sparePair++;
continue;
}
spares[card] = true;
spareNeeded[n + 1 - card] = true;
}
if (pair == 0 && coin >= 2 && sparePair) {
coin -= 2;
sparePair--;
pair++;
}
if (pair == 0) {
break;
}
pair--;
answer++;
}
return answer;
} 이 문제의 포인트는
인 것 같아요. 저는 초기에 가진 카드 중 페어가 있는지, 순서로 확인했어요. |
딕셔너리 for 순회하실 때 리스트로 변환하지 않고 바로 순회할 수 있어요. a,b 변수명은 조금 컹스하네요. |
아니 당신 C++ 로 하면서 왜 파이썬 더 잘 알아
ㅋㅌㅋㅌㅋㅌㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅌㅋㅋ |
딕셔너리를 아니구 세트인데 직접 이 세트를 순회하는 중에는 원소를 이 세트에서 변수명은 이때 코테 시간 때문에 최대한 짧게 짓고 넘기던 습관을 만들고 있었던지라 |
🔗 문제 링크
n + 1 카드게임
✔️ 소요된 시간
1시간 15분
✨ 수도 코드
n
개의 카드 목록에서 순서대로 왼쪽부터 카드n / 3
개를 먼저 뽑은 상태에서 1 라운드를 시작으로, 규칙에 따라 카드를 두 개씩 뽑아가는 게임1. 소유 카드 집합과 뽑은 카드 집합을 생성
n / 3
개의 카드를 담는다2.
n / 3
번째 위치의 카드부터 두 개씩 뽑기를 반복pickedCards
에 뽑은 카드 두개를 담는다ownCards
에서 합이n + 1
인 카드 쌍을 찾는다ownCards
에 해당하는 카드 쌍이 없으면,ownCards
과pickedCards
각각에서 카드를 하나씩 확인하면서n + 1
이 되는 쌍이 있는지 확인한다pickedCards
에서 합이n + 1
인 카드 쌍을 찾는다n + 1
이 되는 쌍이 없다면, 반복을 종료한다예시
[3, 6, 2, 7, 1, 10, 5, 9, 8, 12, 11, 4]
4 라운드를 마지막으로 더 이상 뽑을 수 있는 카드가 없으므로 종료
📚 새롭게 알게된 내용