title: Programmers - 스타 수열
date: 2022-08-18
tags:
- Algorithm
https://school.programmers.co.kr/learn/courses/30/lessons/70130
문제 요약
수열이 주어지며, 이 수열의 순서를 유지하되 일부의 서로 다른 수 두 개를 쌍으로 묶어 집합으로 만든다.
모든 집합에 동일한 수가 들어가도록 구성할 때, 구성 가능한 최대의 집합의 개수를 return한다.
문제 풀이
총 500K의 수가 주어진다.
DFS 방식 혹은 Parametric Search
, 모든 수를 이용하여 비교하는 방식은 1분이 주어져도 시간 초과가 생길 가능성이 매우 높다.
시간 내에 정답을 찾기 위해 각 수를 이용하되 개수가 많은 수를 먼저 이용한다.
각 수의 index를 vector
에 저장한 뒤, 각 vector
의 길이를 기준으로 정렬한다.
길이가 긴 vector
부터 집합을 구성하여 최대로 구성 가능한 집합의 개수를 구한다.
이미 구한 최대 집합의 개수가 다음에 비교할 vector
의 길이보다 크거나 같다면, 이후의 vector
는 비교하여도 최대값은 갱신이 되지 않는다.
최대 약 304ms의 성능을 보여주었으며, 현재 알고리즘은 O(n^2)이다.
각 수를 한 번씩만 순회하며 각 수 별로 최근에 구성한 집합의 index와 최대 길이를 저장하면 O(n)의 알고리즘으로 개선할 수 있다는 것을 확인하였다.
프로그램
#include <vector>
#include <unordered_map>
#include <queue>
#include <algorithm>
using std :: vector ;
using std :: unordered_map ;
using std :: priority_queue ;
struct numberInfo
{
int iCount ;
vector < int > vIndexList ;
} ;
struct comp
{
bool operator () ( const numberInfo & n1 , const numberInfo & n2 )
{
return n1.iCount < n2.iCount ;
}
} ;
int solution ( vector < int > a )
{
int answer = 0 ;
unordered_map < int , vector < int > > umNumberIndex ; // < number , vector having index of number
int iNumberSize = a.size () ;
priority_queue < numberInfo , vector < numberInfo > , comp > pqNumber ;
if ( iNumberSize <= 3 )
return 0 ;
for ( int i = 0 ; i < iNumberSize ; ++i )
{
umNumberIndex [ a [ i ] ].emplace_back ( i ) ;
}
for ( auto iter = umNumberIndex.begin () ; iter != umNumberIndex.end () ; ++ iter )
{
pqNumber.push ( { ( int ) ( iter -> second.size () ) , iter -> second } ) ;
}
while ( ! pqNumber.empty () )
{
numberInfo currentNumber = pqNumber.top () ;
pqNumber.pop () ;
if ( currentNumber.iCount << 1 <= answer )
break ;
int iFormerPairIndex = 0 == currentNumber.vIndexList [ 0 ] ? 1 : currentNumber.vIndexList [ 0 ] - 1 ;
int iCount = 1 ;
for ( int i = 1 ; i < currentNumber.iCount ; ++i )
{
int iCurrentNumber = currentNumber.vIndexList [ i ] ;
if ( iFormerPairIndex == iCurrentNumber )
{
continue ;
}
else if ( ( iFormerPairIndex + 1 == iCurrentNumber ) || ( currentNumber.vIndexList [ i - 1 ] + 1 == iCurrentNumber ) )
{
if ( iCurrentNumber + 1 == currentNumber.vIndexList [ i + 1 ] )
continue ;
iFormerPairIndex = iCurrentNumber + 1 ;
if ( iFormerPairIndex == iNumberSize )
break ;
}
else
{
if ( iCurrentNumber - 1 == currentNumber.vIndexList [ i - 1 ] )
continue ;
iFormerPairIndex = iCurrentNumber - 1 ;
}
++ iCount ;
}
answer = std :: max ( answer , iCount << 1 ) ;
}
return answer ;
}
'Judge' 카테고리의 다른 글
Programmers - 스티커 모으기 (0) | 2022.08.19 |
---|---|
Programmers - 기지국 설치 (0) | 2022.08.19 |
Programmers - 매칭 점수 - 포기 (0) | 2022.08.17 |
Programmers - 가장 긴 팰린드롬 (0) | 2022.08.14 |
Programmers - 110 옮기기 (0) | 2022.08.14 |