programmers.co.kr/learn/courses/30/lessons/60060

 

코딩테스트 연습 - 가사 검색

 

programmers.co.kr

 

 

 

해당 코드로는 정확성은 전부 맞지만 효율성 테스트에서 1,2,3을 통과하지 못했다.

무슨 문제인지 검색해보니 선형 탐색의 방식으로는 1,2,3을 통과할 수 없다고 한다.

Tries 구조를 공부해야 풀 수 있는 문제 였다. 

 

아래는 내가 풀어서 효율성 테스트를 통과하지 못한 코드

int FindMatch(string& words, string& queries, int dir)
{
	int words_size = words.size();
	int queries_size = queries.size();

	if (words_size != queries_size)
		return 0;
        
	switch (dir)
	{
	case 0:
		// 뒤에서부터
		for (int i = words_size - 1; i >= 0; --i)
		{
			if (queries[i] != '?') {
				if (words[i] == queries[i])
					continue;
				else
					return 0;
			}
			else
				return 1;
		}
		break;
	case 1:
		// 앞에서부터
		for (int i = 0; i < words_size; ++i)
		{
			if (queries[i] != '?') {
				if (words[i] == queries[i])
					continue;
				else
					return 0;
			}
			else
				return 1;
		}
		break;
	}
}

vector<int> solution(vector<string> words, vector<string> queries) {
	vector<int> answer;
	int words_size = words.size();
	int queries_size = queries.size();
	int idx = 0;
	while (idx < queries_size)
	{
		int cnt = 0;
		for (int i = 0; i < words_size; ++i)
		{
			if (queries[idx][0] == '?')
				cnt += FindMatch(words[i], queries[idx], 0);
			else
				cnt += FindMatch(words[i], queries[idx], 1);
		}
		idx += 1;
		answer.push_back(cnt);
	}
	return answer;
}

 

이게 내가 해결한 방식이었다. 

 

 

tech.kakao.com/2019/10/02/kakao-blind-recruitment-2020-round1/

 

2020 신입 개발자 블라인드 채용 1차 코딩 테스트 문제 해설

올해에도 2020이라는 멋진 숫자와 함께, 카카오의 신입 개발자 채용을 시작했습니다! 그 여정 중 첫 단계로 1차 코딩 테스트가 지난 9월 7일 토요일 오후 2시부터 오후 7시까지 5시간 동안 진행됐는

tech.kakao.com

다음의 공식 해설을 보면 출제 의도에 문자열을 다룰 수 있는지 파악과 함께 트라이 자료구조 또는 이분 탐색 등 보다 효율적인 방법을 이용해 코드를 작성할 수 있는지 파악하고자 했다고 써있다.

 

공식적인 해설은 다음과 같다. 정확성 풀이같은 경우는 하나하나 비교해가면서 개수를 세면 되지만 효율성 풀이 같은 경우는 좀 길다. 

 

 

 

 

programmers.co.kr/learn/courses/30/lessons/12951

 

코딩테스트 연습 - JadenCase 문자열 만들기

JadenCase란 모든 단어의 첫 문자가 대문자이고, 그 외의 알파벳은 소문자인 문자열입니다. 문자열 s가 주어졌을 때, s를 JadenCase로 바꾼 문자열을 리턴하는 함수, solution을 완성해주세요. 제한 조건

programmers.co.kr

 

처음에는 그냥 공백 구분해서 제일 앞글자만 대문자로 바꿔주면 되는 줄 알았더니 다른 조건들이 있었다.

1. 문자열 중간에 있는 대문자를 소문자로 바꾸기

2. 공백이 길게 있는 경우 그 공백도 answer에 그대로 추가해야 함

 

그러니까 hello    woRld 같은 경우에 Hello WoRld로 출력하면 안되고 Hello    World로 출력해야 한다.

ssstream으로 풀고 테스트 실행했는데 눈이 침침했는지 분명 똑같은 결과인데 뭐가 다르다는 거야; 하면서 한참 고민했다.

웃기네 

 

 

string solution(string s) {
	string answer = "";

	int index = 0;
	bool prev_blank = true;
	while (index < s.size())
	{
		if (prev_blank && s[index] != ' ')
		{
			s[index] = toupper(s[index]);
			prev_blank = false; 
		}
		else if (s[index] == ' ')
		{
			prev_blank = true;
		}
		else if(isupper(s[index]))
		{
			s[index] = tolower(s[index]);
		}

		answer += s[index];
		index += 1;
	}

	return answer;
}

 

 

순열, 조합 구현

C++로 순열과 조합을 구현해보았다.

 

 

 

순열은 STL의 next_permutation과 prev_permutation을 쓰면 쉽게 구현할 수 있긴 하다. 하지만 하다보면 해당 원리를 이용해 조금 변형할 일이 생기기 마련...... 

순열과 조합은 보통 재귀를 이용해 구현한다. 

 

◎ 조합

조합은 순열과 다르게 순서가 없는 나열이다. 그러니까 원소들을 중복 없이 뽑는다.

조합을 먼저 쓴 이유는 조합을 먼저 구해야 순열을 구할 수 있다. 

우선 조합은 nCr로 n개 중에 r개를 뽑는 것이다.

 

만약 배열 {1,2,3,4,5}의 원소 중 3개씩 뽑는 조합을 만든다 했을 때 나올 수 있는 경우의 수는

(1,2,3) (1,2,4) (1,2,5) (1,3,4) (1,3,5) (1,4,5)

(2,3,4) (2,3,5) (2,4,5)

(3,4,5)
로 총 10개가 된다.

 

조합의 공식이 nPr / r! 임을 생각해보면 10개가 맞다. 

 

 

#include <iostream>
using namespace std;


void Combination(int arr[], int n, int r,  int index,int target, int comb_arr[])
{
	if (r == 0)
	{
		// r개를 뽑기로 했는데 r개를 다 뽑은 경우
		for (int i = 0; i < index; ++i)
		{
			cout << comb_arr[i];
		}
		cout << endl;
	}
	else if (target == n)
	{
		// target이 index를 초과=>종료 
		return;
	}
	else
	{
		//target 인덱스의 원소를 저장
		comb_arr[index] = arr[target];
		Combination(arr, n, r - 1, index + 1, target + 1, comb_arr); // 해당 원소를 선택
		Combination(arr, n, r, index, target + 1, comb_arr); // 해당 원소를 선택하지 않음
	}
}

int main()
{
	int arr[5] = { 1,2,3,4,5 };
	int n = 5;
	int r = 3;

	int* comb_arr = new int[5];
	
	Combination(arr, 5, 3, 0,0 , comb_arr);
}

 

조합을 하기 위해서 배열을 돌면서 뽑는 경우와 안 뽑는 경우를 조사한다. 

comb_arr는 빈 배열로 Combination 함수를 돌면서 뽑은 원소를 저장하는 배열이다.

 

Combination(arr, n, r - 1, index + 1, target + 1, comb_arr); // 해당 원소를 선택
Combination(arr, n, r, index, target + 1, comb_arr); // 해당 원소를 선택하지 않음

 

왜 두번 호출을 하냐면..

더보기

간단하게 말하면 다음 숫자를 선택하기 위해서라고 말할 수 있다.

먼저 해당 원소를 선택하는 함수를 1번, 선택하지 않는 함수를 2번 함수라고 했을 때 1,2,3과 1,2,4를 예를 들어보면

처음 호출 시 comb_arr[index] = arr[target]에는 index 초기값인 0, target 초기값인 0의 값이 들어가

comb_arr[0]에 1이, 그 다음 1번 함수를 호출하게 되면서 r은 2, index는 1, taget 은 1인 상태로 comb_arr[1]에는 2가 들어가게 된다.

 

그 다음 1번 함수의 호출로 인해 들어간 상태에는

index와 target은 2, r은 1이 된다. 따라서 arr[2]의 값인 3이 comb_arr[2]에 들어가게 되며 

한 번 더 1번 함수를 호출하게 되면 r이 0이므로 123이 출력된다.

여기서 알아둘 것은 재귀함수 호출이므로 아직까지 2번 함수는 한 번도 실행되지 않았다.

출력이 끝난 해당 함수는 종료되고 그때 이제 2번 함수가 호출이 되는데 가장 마지막의 r값인 1의 값을 가지고 있으며 index는 2, target이 2인 상태의 Combination상태가 호출되는 것이다. 

이 상황에서 2번 함수가 호출되면 target의 값만 1 증가하기 때문에 

comb_arr[index] = arr[target]; 줄을 수행하고 나면 comb_arr[2]에는 arr[3]의 값이 들어가게 된다.

그 후 다시 1번 함수를 호출해서 들어간 함수 내부에서 r이 0이 되므로 출력을 하는 것이다. 

 

이 부분을 보면 위의 줄은 target에 위치한 원소를 원소를 뽑는 부분, 밑의 줄은 원소를 선택하지 않는 부분이다.

또한 target은 함수 호출 시 항상 1을 증가시켜서 넘겨야 순회하는 역할을 할 수 있다.

 

선택할 때는 r을 1 감소시키고 index를 1 증가시키며 선택하지 않을 때는 r을 그대로, index도 그대로 넣고 호출한다.

index를 증가시키는 이유는 현재 target이 가리키는 원소를 선택하고 다음 index를 선택하기 위함이며

증가시키지 않는 것은 현재 target이 가리키는 원소를 선택하지 않고 현재 index에 다른 원소를 선택하기 위함이다. 

 

이렇게 순회를 하는 도중, 다 뽑은 경우인 r=0과 r개를 다 뽑았지만 arr의 모든 원소를 다 검사했을 때인 target = n일 때이다. 후자의 경우 실패이므로 아무것도 하지 않고 return하게 된다. 

 

 

 

◎ 순열

순열은 순서가 있는 나열이다. 

우선 n개 중에 n개를 뽑는 순열을 보면 

 

void Swap(int arr[], int num1, int num2)
{
	int temp = arr[num1];
	arr[num1] = arr[num2];
	arr[num2] = temp;
}
void Permutation(int arr[], int index, int arr_size)
{
	// 탈출!
	if (arr_size - 1 == index)
	{
		for (int i = 0; i < arr_size; ++i)
		{
			cout << arr[i];
		}
		cout << endl;
		return;
	}

	for (int i = index; i < arr_size; ++i)
	{
		Swap(arr, index, i);
		Permutation(arr,index + 1, arr_size);
		Swap(arr, index, i);
	}
}


int main()
{
	int arr[5] = { 1,2,3,4,5 };
	Permutation(arr, 0, sizeof(arr) / sizeof(int));
}

 

(1,2,3,4,5) 의 배열에서 5개 중 5개를 뽑는 순열을 구하면 순열 공식에 의해 총 120개가 나오게 된다. 

arr배열 자체를 위에서 구한 조합을 이용해 정렬하는 것이다. 

 

먼저 swap을 이용해서 index번째의 자리 수가 1,2,3,4,일 때를 조사한다. index번째 자리를 선택한 후에 재귀를 통해 그 다음 자리를 선택하다가 arr의 마지막을 가리키면 끝이 난다.

 

재귀 후 다시 swap으로 바꿔준 값을 원상복구를 하면 다시 각 자리 수가 1일 때, 2일 때, 3일 때, 4일 때를 모두 조사할 수 있다. 

 

n개에서 n개를 뽑는 경우를 구했으니 이제 n개 중 r개를 뽑는 경우를 구하면 되는데 

이건 위에서 구한 조합을 이용하면 된다. 먼저 nCr을 이용해 n개 중에 r개를 뽑은 후에 r개의 수로 이루어진 숫자들을 permutation을 이용해서 정렬해주면 된다. 

 

void Swap(int arr[], int num1, int num2)
{
	int temp = arr[num1];
	arr[num1] = arr[num2];
	arr[num2] = temp;
}
void Permutation(int arr[], int index, int arr_size)
{
	// 탈출!
	if (arr_size - 1 == index)
	{
		for (int i = 0; i < arr_size; ++i)
		{
			cout << arr[i];
		}
		cout << endl;
		return;
	}

	for (int i = index; i < arr_size; ++i)
	{
		Swap(arr, index, i);
		Permutation(arr,index + 1, arr_size);
		Swap(arr, index, i);
	}
}
void Combination(int arr[], int n, int r, int index, int target, int comb_arr[])
{
	if (r == 0)
	{
		Permutation(comb_arr, 0, 3);
		cout << endl;
	}
	else if (target == n)
	{
		return;
	}
	else
	{
		comb_arr[index] = arr[target];
		Combination(arr, n, r - 1, index + 1, target + 1, comb_arr); 
		Combination(arr, n, r, index, target + 1, comb_arr); 
	}
}

int main()
{
	int arr[5] = { 1,2,3,4,5 };

	int* comb_arr = new int[5];

	Combination(arr, 5, 3, 0,0 , comb_arr);
}

 

 

혹시 이 포스팅을 보시는 분께..

더보기

순열 함수를 호출하는 부분에서 원래 배열의 '크기' 즉 인자가 몇 개있는지를 구해야 하는데 나는 포인터로 넘겨받고 있어 sizeof를 쓸 수 없고 comb_arr의 사이즈를 구하는 다른 방법을 쓰기 귀찮아서 그냥 3개를 뽑을 거라 위의 코드에는 3을 arr_size로 넘겨줬다.

 

 

 

 

참고 자료;

 

it-earth.tistory.com/53


onsil-thegreenhouse.github.io/programming/algorithm/2018/04/05/permutation_combination/


 

 

 

 

Permutation

순열

 

 

 

◎ 수학에서 순열 구하기

n개에서 r개를 택하는 순열이란 서로 다른 n개의 원소에서 r개를 중복없이 골라 순서에 상관있게 나열하는 것이다. 

여기서 중요한 것은 '순서 있게'다. 왜냐하면 개념이 헷갈리는 조합은 '순서'가 없이 나열하는 것이기 때문에 구분을 잘 해야 한다. 

표현은 주로 nPr로 한다. (n개에서 r개를 택하는 Permutation)

 

이 순열을 구하는 방법은 간단하다. 바로 팩토리얼을 이용하면 된다.

 

nPr = n x (n-1) x (n-2) x ... x (n-r+1)

 

식을 간단하게 표현하면 위와 같다. 

 

 

◎ Permutation 사용

순열을 구하기 위해서는 재귀를 통해서 직접 구현할 수도 있다. 하지만 stl에 있는 기능을 가져다가 사용하면 빠르고 간단하게 순열을 만들 수 있다.

 

std::prev_permutation과 std::next_permutation은 현재 범위가 현재보다 더 작은 순열(이전 순열) 또는 더 큰 순열(다음순열)이 되도록 요소들을 정리한다. 이전 순열이나 다음 순열이 있으면 true, 없으면 false를 리턴한다

 

이때 순열이 끝나 false를 리턴하는 경우는 완전히 역순이 되는 경우다. 이 때 다시 원래 순서대로 바꾼뒤에 false를 리턴하는 것이다. 

ex) 1234의 경우 return 하기 직전 4321였다가 false를 리턴할때 다시 1234로 만들어준다. 

 

단 permutation은 중복이 있는 경우에는 중복을 제외하고 순열을 만들어준다. 

 

permutation 기능의 원리는 다음과 같다.

1. 우선 뒤에서부터 탐색을 시작한다. 오름차순의 형태를 띄는 구간이 나올 때까지 진행하며 작은 쪽은 i, 큰 쪽은 ii라고 가정한다. 

2. 그 다음에는 뒤에서부터 i보다 큰 j를 찾아 i와 j를 바꿔준다.

3. 그 후 ii를 포함해 뒷부분을 모두 reverse한다. 

 

 

범위를 이전 순열로 만드는 것

bool prev_permutation(BiIt first, BiIt last) 

 

 

범위를 다음 순열로 만드는 것

bool next_permutation(Bilt first, BiIt last)

 

 

 

위의 인자에 정렬 기준을 명시적으로 사용할 수 있다. 기본적으로는 std::less가 사용된다.

두 알고리즘 중 어떤 것을 사용하든, 주어진 범위의 모든 순열을 손쉽게 생성할 수 있다. 

 

 

 

ex ) permutation을 사용한 예시 

#include <algorithm>

std::vector<int> Init{1,2,3};
do{
	for(auto i:Init) std::cout << i;
	std::Cout << " ";
} while(std::next_permutation(Init.begin(), Init.end())); 

// 출력 예시 123 132 213 231 312 321 

std::reverse(Init.begin(), Init.end());
do{
	for(auto i:Init) std::cout << i;
    std::cout << " ";
 } while(std::prev_permutation(Init.begin(), Init.end()));
 
 // 출력 예시 321 312 231 213 132 123

 

 

 

permutation말고 직접 순열 구하기? 

더보기

 

참고 자료;

namu.wiki/w/%EC%88%9C%EC%97%B4


핵심 C++ 표준 라이브러리 (라이너 그림 지음; 류광 옮김. 인사이트) 


jeonggyun.tistory.com/110

'Study > STL' 카테고리의 다른 글

[STL] erase와 remove의 차이  (0) 2021.10.04

programmers.co.kr/learn/courses/30/lessons/42842

 

코딩테스트 연습 - 카펫

Leo는 카펫을 사러 갔다가 아래 그림과 같이 중앙에는 노란색으로 칠해져 있고 테두리 1줄은 갈색으로 칠해져 있는 격자 모양 카펫을 봤습니다. Leo는 집으로 돌아와서 아까 본 카펫의 노란색과 ��

programmers.co.kr

 

다른분들은 막 수식으로 한 두줄로 정리해서 푸시던데 나는 그냥 풀었다.. 

 

 

우선 brown+yellow를 해서 총 격자의 갯수를 구해서 (all_rect) 그 총 격자의 약수를 구해줬다. 

가로가 세로보다 더 길거나 같다고 했으니 약수는 절반 이상부터 가로의 값으로 비교해보면 된다.

o o o o
o     o
o o o o

총 12칸의 4x3 의 예시가 있을 때 o 표시가 쳐진 부분이 테두리이다.

즉 brown의 개수는 (w*2) + (h*2-4) 로 구할 수 있다.

가로의 길이는 첫 번째 줄과 마지막 줄. 그리고 세로는 첫 번째 열과 마지막 열에서 이미 가로의 길이에 더한 값인 네 꼭짓점 부분을 빼주는 것이다.

그럼 총 격자의 수에서 brown을 빼면 마찬가지로 yellow도 나온다. 

 

 

5분만에 풀었다. 요새 푼 문제 중에 제일 빨리 풀어서 기분이 (아주)좋다. 

 

vector<int> solution(int brown, int yellow) {
	vector<int> answer;

	int all_rect = brown + yellow;
	vector<int> factor; // 약수

	for (int i = 1; i <= all_rect; ++i)
	{
		if (all_rect % i == 0)
		{
			factor.push_back(i);
		}
	}
	int CD_cnt = factor.size();
	

	for (int w_idx = CD_cnt / 2; w_idx < CD_cnt; ++w_idx)
	{
		int h = all_rect / factor[w_idx];

		int temp = ((h * 2) - 4) + (factor[w_idx] *2);
		if (temp == brown)
		{
			answer.push_back(factor[w_idx]);
			answer.push_back(h);
			break;
		}
	}
	return answer;
}

programmers.co.kr/learn/courses/30/lessons/42587

 

코딩테스트 연습 - 프린터

일반적인 프린터는 인쇄 요청이 들어온 순서대로 인쇄합니다. 그렇기 때문에 중요한 문서가 나중에 인쇄될 수 있습니다. 이런 문제를 보완하기 위해 중요도가 높은 문서를 먼저 인쇄하는 프린��

programmers.co.kr

 

 

※ 절대적인 해답은 당연히 아니고 제 마음대로 풀었으니 참고용으로 봐주세요

 

 

어떻게 풀까 고민을 하다 location값을 언제 찾아줘야 하는지가 애매해서 queue에 index값을 넣어주기로 했다.

 

1. q를 만들고 거기에 priorities(vector<int>) 우선순위들이 들어있는 벡터의 사이즈만큼 값을 채워준다. 

 

	for (int i = 0; i < p_size; ++i)
	{
		q.push(i);
	}

 

2. while문을 돌면서 queue의 값을 체크

2-1. q의 제일 앞에 있는 index값을 빼온다 

(여기의 index값이란 priorities 벡터의 index를 가리키는 값임)

2-2. for문을 돌면서 현재의 index값(temp)과 i의 값을 비교해 나보다 더 큰 우선순위가 존재한다면 해당 인덱스 값이 맨 뒤로 가게 큐에서 빼서 다시 넣어준다. 

2-3. 만약에 인덱스 값의 변화가 일어나지 않았다면(=내가 제일 우선순위가 크다면) for문 안에서 IsChange가 true가 되지 않았을 것이므로 false이면 큐에서 인덱스를 빼주고 해당 인덱스값이 가리키는 우선순위 벡터의 값을 0으로 만들어준다. 

왜 0인지? 우선순위는 1~9로 0이면 어떠한 우선순위보다 작게 되므로 for문 안에서 체크 시 제외된다.

2-4. 만약 IsChange가 false일 때 temp값(현재 검사하고 있는 index값)이 location과 같다면 while문을 나와서 결과값을 리턴한다. 

 

int solution(vector<int> priorities, int location) {
	int answer = 0;
	int p_size = priorities.size();
	queue<int> q;

	for (int i = 0; i < p_size; ++i)
	{
		q.push(i);
	}

	while (1)
	{
		int temp = q.front();

		int IsChange = false;
		for (int i = 0; i < p_size; ++i)
		{
			if (i == temp)
			{
				continue;
			}
			if (priorities[temp] < priorities[i])
			{
				q.pop();
				q.push(temp);
				IsChange = true;
				break;
			}
		}

		if (!IsChange)
		{
			
			q.pop();
			priorities[temp] = 0;
			answer += 1;
			if (temp == location)
			{
				break;
			}

		}
	}

	return answer;
}

 

 

programmers.co.kr/learn/courses/30/lessons/60057?language=cpp

 

코딩테스트 연습 - 문자열 압축

데이터 처리 전문가가 되고 싶은 어피치는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자

programmers.co.kr

 

 

 

int solution(string s) {
	int answer = 1001;// s의 길이가 최대 1000이므로
	int s_size = s.length();

	string temp = "";
	int same = 1;

	if (s_size == 1)
	{
		return 1;
	}

	for (int i = 1; i<= s_size / 2; ++i)
	{
		string save = "";
		for (int j = 0; j < s_size; j+=i) {

			temp = s.substr(j, i);

			if (temp.length() % i != 0)
			{
				if (same != 1) {
					save += to_string(same);
				}
				save += temp;
				break;
			}
			string value = s.substr(i + j, i);
			if (temp == value)
			{
				// 같으면
				same += 1;
			}
			else
			{
				// 다르면
				if (same != 1) {
					save += to_string(same);
				}
				save += temp;
				same = 1;
			}
		}

		int temp_length = save.length();

		if (temp_length < answer)
		{
			answer = temp_length;
		}
		
	}

	return answer;
}

 

이.. 이게 생각보다 어려웠다. 이거 레벨2 맞나?

왜.. 왜이렇게 어렵지... 너무 어렵게 생각했나? 계속 고치고 고치다가 맞았는데 앞에 풀었던건 왜 틀렸는지 모르겠음

programmers.co.kr/learn/courses/30/lessons/67258

 

코딩테스트 연습 - 보석 쇼핑

["DIA", "RUBY", "RUBY", "DIA", "DIA", "EMERALD", "SAPPHIRE", "DIA"] [3, 7]

programmers.co.kr

 

 

카카오 블로그의 해설과 질문하기 란을 보니 투포인터 방식으로 해결하라고 했다.

질문하기에서 어떤 분이 링크해주신 블로그 주소인데 깔끔하게 정리가 잘 돼 있어서 한번에 이해했다.

blog.naver.com/kks227/220795165570

 

 

vector<int> solution(vector<string> gems) {
	vector<int> answer;
	int gems_size = gems.size();
	int min_dist = 100001;

	unordered_map<string, int> list;

	unordered_set<string> s_temp;
	for (int i = 0; i < gems_size; ++i)
	{
		s_temp.insert(gems[i]);
	}
	int kind = s_temp.size();

	int idx_r = 0, idx_l = 0;


	while (1)
	{
		if (list.size() >= kind)
		{
			// 해당 key에 있는 value값을 하나 줄여준다.
			list[gems[idx_l]]--;

			if (list[gems[idx_l]] == 0)
			{
				// l의 포인터를 증가시킬 것이므로 지워준다.
				list.erase(gems[idx_l]);
			}
			// 포인터 증가
			idx_l++;
		}
		else if (idx_r == gems_size)
		{
			break;
		}
		else
		{
			list[gems[idx_r]]++;
			idx_r++;
		}

		if (list.size() == kind)
		{
			int temp = idx_r - idx_l;
			if (temp < min_dist)
			{
				answer.clear();
				answer.push_back(idx_l + 1);
				answer.push_back(idx_r);
				min_dist = temp;
			}
		}
	}

	return answer;
}

 

 

그리고 다시 풀면서 한 번 헤맸던 부분이 있는데 min_dist의 초기값을 설정할 때 gems의 size보다 큰 값을 줘야 한다. 그러니까 

gems의 size를 구해서 +1한 값을 주던지 아니면 gems는 최대 100000개가 들어올 수 있다고 했으니 그것보다 +1한 값을 설정해주거나. 그러지 않으면 r의 포인터값과 gem의 size를 비교해서 break를 하는 부분에서 마지막 부분에 break를 해버려 answer에 idx를 넣지 않는 경우가 발생한다. 구현방법은 여러가지이니까 다른 방식으로 구현했으면 상관없을 수도

 

 

 

바보 같은 그 전의 기록

더보기

이렇게 생각했던 이유는 vector나 list같은 컨테이너를 생각하며 데이터를 넣지 않으면 안들어가지 않나? 그럼 안에 데이터는 언제 채워넣어?ㅠ 내가 넣어주자ㅠ 

라는 생각을 가지고 문제를 풀려고 했어서였다.

처음 문제 읽을 때 answer에 꽂혀서 분명 vector<int>형 반환임에도 string으로 들어온다고 [1, 1] 로 반환해야 되나? 하면서 10분을 고민했던 것과 같은 맥락이다. 

진짜 여태 많은 오류를 만났지만 오늘같은 이런 신박한 뇌의 오류는 또 처음이다.

 

(미해결)이라고 포스팅한지 30분만에 뇌의 오류를 정정했다. 앞으로도 자주 써먹어야겠다. 

 

 

vector<int> solution(vector<string> gems) {
	vector<int> answer;
	int gems_size = gems.size();
	int min_dist = gems_size;

// 중복없는 unordered로 
	unordered_map<string, int> list;
	unordered_set<string> s_temp;  
	for (int i = 0; i < gems_size; ++i)
	{
		s_temp.insert(gems[i]);
	}
	int kind = s_temp.size();

	auto iter = list.begin();

	int idx_r = 0, idx_l = 0;

	if (kind == 1)
	{
		answer.push_back(1);
		answer.push_back(1);
		return answer;
	}

	while (idx_r < gems_size && idx_l < gems_size)
	{
		iter = list.find(gems[idx_r]);
		if (iter != list.end())
		{
			iter->second += 1;
		}
		else
		{
			list.insert(pair<string, int>(gems[idx_r], 1));
		}

		if (list.size() < kind)
		{
			idx_r += 1;
		}
		else if (list.size() >= kind)
		{
			int temp = idx_r - idx_l;
			if (temp < min_dist)
			{
				answer.clear();
				answer.push_back(idx_l + 1);
				answer.push_back(idx_r + 1);
				min_dist = temp;
			}
			iter = list.find(gems[idx_l]);
			iter->second -= 1;
			if (iter->second == 0)
			{
				list.erase(iter);
			}
			idx_l += 1;
		}
	}
	return answer;
}

이걸 어떻게 고쳐야 할까

문제 1. 보석의 종류를 어떻게 체크해야 될 지 감이 안와서 우선 set으로 (중복x) 넣어두고 size를 받아왔음.

근데 더 좋은 방법은 없나? 

문제 2. 효율성 + 정확성 테스트 57.3 / 100. 어디가 문제인지 모르겠음

 

 

뭐가 문제일까 일단 올려두면 풀다 잊은 다른 문제들처럼 안 까먹을 것 같아서 올려둠. 

혹시 지나가다가 이 난장판인 코드의 문제점을 아시는 분은 저에게 도움을 주세요 

 

 

tech.kakao.com/2020/07/01/2020-internship-test/

 

2020 카카오 인턴십 for Tech developers 문제해설

2020년 카카오의 여름 인턴십이 시작 되었습니다.여름 인턴십의 첫번째 관문인 코딩 테스트가 2020년 5월 9일 오후 2시부터 6시까지 진행되었는데요, 온라인으로 진행되었기 때문에 코로나19로부터

tech.kakao.com

카카오 블로그에 공식 해설이 있습니다!

+ Recent posts