문제 : 백준 3078 좋은 친구 👭
난이도 : 골드 4
1️⃣ 상근이네 반의 N명 학생들의 이름이 성적순으로 주어진다.
2️⃣ 좋은 친구는 등수의 차이가 K보다 작거나 같으면서 이름의 길이가 같은 친구이다.
3️⃣ 좋은 친구가 몇 쌍이나 있는지 구한다.
이때, 좋은 친구는 등수의 차이가 K보다 작거나 같은 조건을 만족해야 한다.
즉, K=2라면 1등~3등까지의 사람들 사이에서 이름의 길이가 같은 친구가 있는지 살펴보면 된다. 이처럼 배열의 길이가 3으로 고정된 채 비교해보는 슬라이딩 윈도우를 사용하여 이번 문제를 해결해보아야 한다!!
#include <iostream>
using namespace std;
int main() {
std::ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int N = 0, K = 0; //학생의 수, 좋은 친구가 되는 조건(K)
int friends[300001];
string friend1 = "";
long long ans = 0; //좋은 친구쌍의 수
cin>>N>>K;
//1등부터 차례대로 이름을 입력받는다.
for(int i=1; i<=N; i++){
cin>>friend1;
friends[i] = friend1.size();
}
//처음에는 겹치는 부분을 고려하지 않고, 1등부터 K+1등까지 길이가 같은지 살펴본다.
for(int i=1; i<=K; i++){
for(int j=i+1; j<=K+1; j++){
if(friends[i] == friends[j]){
ans++;
}
}
}
//겹치는 부분을 고려하여 끝에 추가되는 부분을 기준으로 길이가 같은 친구가 있는지 살펴본다.
for(int i=K+2; i<=N; i++){
for(int j=1; j<=K; j++){
if(friends[i] == friends[i-j]){
ans++;
}
}
}
cout<<ans<<"\n";
}
다른 블로그들을 참고하여 문제를 해결했다 🥲
하나씩 비교하는 것이 아니라 계수 정렬처럼 이름의 길이 배열을 선언하여 이름의 길이가 같은지를 확인하는 방법을 사용한다!
#include <iostream>
using namespace std;
int main() {
std::ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int N = 0, K = 0; //학생의 수, 좋은 친구가 되는 조건(K)
int friends[1000000];
int cnt[23]={0,}; //이름의 길이 배열
string friend1 = "";
long long ans = 0; //좋은 친구쌍의 수
cin>>N>>K;
for(int i=1; i<=N; i++){
cin>>friend1;
friends[i] = friend1.size();
}
//처음에는 겹치는 부분을 고려하지 않고, 1등부터 K+1등까지 길이를 cnt배열에 개수를 넣는다.
for(int i=1; i<=K+1; i++){
cnt[friends[i]]++;
}
//겹치는 부분을 고려하여, 윈도우의 끝에 추가될 friends[i+k+1]만 추가해준다.
for(int i=1; i<=N; i++){
cnt[friends[i]]--; //자기 자신의 길이는 제외한다.
ans += cnt[friends[i]]; //좋은 친구쌍의 수을 더해준다.
cnt[friends[i+K+1]]++; //슬라이딩 윈도우를 오른쪽으로 이동시킨다.
}
cout<<ans<<"\n";
}
참고한 블로그 : https://wantchicken.tistory.com/75