음악 장르 별로 음악 재생 수의 합을 구해서 내림차순으로 정리하기 위한 map<string, int> sumGenre; vector<pair<string, int>> v;
음악 장르 별로 음악을 저장하고, 음악의 index 번호와 재생 수를 저장하는 map<string, vector<Music>> groupByGenre;
음악의 index 번호와 재생 수를 한꺼번에 저장하고, operator 함수를 선언하기 위해 선언한 객체 struct Music{};
새로 배운 내용은 볼드 처리 하였습니다.
기
struct Music
struct Music{
int index;
int play;
Music(int b, int c){
index = b;
play = c;
}
bool operator < (const Music & b) const {
if(play == b.play){
return index < b.index;
}
return play > b.play;
}
};
sumGenre와 groupByGenre에 값을 채워넣는다.
for(int i = 0; i < numMusic; i++){
sumGenre[genres[i]] += plays[i];
groupByGenre[genres[i]].push_back(Music(i, plays[i]));
}
문제에서 활용된 map의 pair는 <string, int>로 하여, string에는 옷의 종류 이름이, int에는 옷의 종류에 해당하는 옷의 가짓수를 저장하였습니다.
전부 다 벗은 경우를 제외해야 하고, 최소한 하나의 옷을 입어야 합니다. 옷의 종류가 아래와 같다면,
a : 3, b : 2, c : 1, d : 7
(3 + 1) * (2 + 1) * (1 + 1) * (7 + 1) - 1이 문제의 답이 됩니다. 괄호 안의 + 1 은 그 옷의 종류를 입지 않은 경우를 넣은 것이고, 괄호 밖의 - 1 은 전부 다 벗은 경우를 제외한 것입니다.
코드
#include <bits/stdc++.h>
using namespace std;
int solution(vector<vector<string>> clothes) {
int answer = 1;
map<string, int> m;
// 옷의 종류에 해당하는 map value를 하나씩 늘려줍니다.
for(int i = 0; i < clothes.size(); i++){
m[clothes[i][1]]++;
}
// map을 순회하면서 (k.second + 1)를 곱해줍니다.
for(auto & k : m){
answer *= (k.second + 1);
}
// 전부 다 벗은 경우를 빼주고 반환해줍니다.
return answer - 1;
}
우선, vector string을 sort했을 때 어떤 식으로 나열되는지 알아야 문제를 쉽게 풀 수 있었습니다. phone_book의 vector type이 int인 경우와 vector type이 string인 경우의 sort 결과가 다릅니다.
입출력 예제에서 준 vector string sort의 결과는 아래와 같습니다.
string은 int와 달리 문자로 취급되므로 사전순으로 나열 됩니다. 사전을 펼쳐서 가 다음에 가나 가 나오듯이, phone_book을 sort하면 119 다음엔 1195524421 이 나옵니다. sort한 vector를 앞 원소와 바로 뒤 원소를 비교하여 접두어가 있는지 없는지를 판단하면 되겠습니다.
접두어가 있는지 어떻게 판단하느냐. 저는 string의 substr() 함수를 사용했습니다. substr()은 문자열의 일부분을 문자열로 반환하는 함수로, 파라미터를 1개, 2개를 넣을 수 있습니다.
1개일 경우 : ( 시작위치 ) : 시작위치부터 끝까지의 문자들을 문자열로 반환합니다.
2개일 경우 : ( 시작위치, 개수 ) : 시작위치부터 개수만큼의 문자를 문자열로 반환합니다.
이 점을 활용해서 앞의 원소의 string length만큼 뒤의 원소를 substr한 값을 앞의 원소와 비교합니다. 같다면 return false, 다르다면 다음 원소를 비교합니다. phone_book을 모두 비교해도 return false되지 않았다면, 접두어가 없는 phone_book이므로 return true해주시면 되겠습니다.
코드
#include <bits/stdc++.h>
using namespace std;
bool solution(vector<string> phone_book) {
sort(phone_book.begin(), phone_book.end());
// 출력을 위한 코드
// for(auto k : phone_book){
// cout << k << endl;
// }
for(int i = 1; i < phone_book.size(); i++){
string temp = phone_book[i].substr(0, phone_book[i - 1].length());
if(temp == phone_book[i - 1])
return false;
}
return true;
}
문제의 조건 중 "단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다."와 "마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때"를 보고, participant와 completion을 sort하여 앞에서부터 비교해나가야겠다 는 생각을 했습니다.
코드
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
string solution(vector<string> participant, vector<string> completion) {
string answer = "";
// participant와 completion을 sort
sort(participant.begin(), participant.end());
sort(completion.begin(), completion.end());
// 앞에서부터 비교
for(int i = 0; i < completion.size(); i++){
// 비교해서 같으면 무시
if(participant[i] == completion[i]) continue;
// 비교해서 다르면, participant[i]는 완주하지 못한 선수
else{
answer = participant[i];
break;
}
}
// answer에 무언가가 지정되어 있지 않다면, participant의 맨 마지막 선수가 완주하지 못한 선수
if(answer == ""){
answer = *(participant.end() - 1);
}
return answer;
}
cin과 cout 등의 C++ 표준 스트림 버퍼와 printf와 scanf 등의 C 표준 버퍼를 병행 및 동기화해서 사용하게 됨
sync_with_stdio(false)
cin과 cout 등의 C++ 표준 스트림 버퍼만 사용하겠다. -> 속도 C 표준 버퍼보다 빨라지게 됨.
cin.tie(NULL);
cin을 cout으로부터 untie한다. stream을 tie하면 다른 stream에서 입출력 요청이 오기 전에 stream을 flush한다.
cout << "Enter name:";
cin >> name;
위의 예시에서 cin과 cout이 tie된 상태라면, 프로그램이 user에게 입력을 요구하기 전에 output이 flush된다. stream을 untie하면 output이 flush되지 않은 채로 user에게 입력을 요구하게 되고, 따라서 "Enter name" 메시지는 출력되지 않을 것이다. 그러므로 untie가 되어있다면 cin으로 입력을 받기 전에 수동적으로 cout을 flush 시켜주어야 한다.