https://level.goorm.io/exam/163680/%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95-%EB%A7%8C%EB%93%A4%EA%B8%B0/quiz/1

 

구름LEVEL

구름LEVEL 문제를 풀이하고 부족한 부분을 보완하며 실력을 키워보세요. 구름LEVEL은 코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입

level.goorm.io

 

 

풀이

 

그리디 알고리즘 활용

 

1. 직사각형을 만들기 위해서 필요한 막대는 4개

2. 같은 길이의 막대 2개를 한 세트로, 두 세트가 필요

3. 같은 길이의 막대가 4개 이상이면 정사각형 만들기 가능

 

!! 길이가 긴 막대부터 차례로 직사각형을 만들어 나가는 것이 만들 수 있는 직사각형 넓이의 합의 최대값 !!

 

처음엔 map에 key값에 막대 길이, value값에 막대 개수를 저장하고 iterator로 탐색하며 사각형을 구현하도록 코드를 작성했는데, Time out 발생

 

>> 

입력값의 최대 크기인 10의 6승만큼 크기를 가진 input 배열을 선언하고 해당 배열의 인덱스를 막대기의 길이로, 인덱스의 값을 막대기의 개수로 대입하여 사용

 

** input 배열을 전역변수로 선언하여 Time out 방지

 

input 배열 뒤부터 길이가 긴 순으로 탐색

막대가 2개 이상이라면 킵하고

그 이후에 2개 이상 막대가 발견되면 이전의 막대와 직사각형을 만들어 넓이 계산 후 answer에 더함

-- 반복

 

 

 

long long input[1000000] = { 0, };	// 막대 길이와 막대 개수 정보를 담을 배열 전역변수 선언
// index : 막대 길이
// input[index] : index 길이의 막대 개수
	int main() {

		int n;	// 입력값
		cin >> n;

		long long answer = 0;
		bool flag = true;	// 개수가 2 이상인 막대가 선택됬을 때, 이전에 이미 선택 된 막대가 있는지 판단하는 변수

		int curVal = 0;

		// 반복문으로 input에 막대 개수 정보 입력
		for (int i = 0; i < n; i++) {
			int temp;
			cin >> temp;
			input[temp]++;
		}
		
        // 길이가 긴 순으로 탐색
		for (long long i = 1000000; i > 0; i--) {
			// 만약 막대의 개수가 2개 이상이고
			if (input[i] >= 2) {
				// 이전에 선택된 막대가 없다면
            			if (flag) {
					curVal = i;	// curVal에 막대의 길이 저장
					flag = false;
				}
                // 이전에 선택된 막대가 있다면
				else {
					answer = answer+ (curVal * i);	// 이전에 선택된 막대와 현재 막대를 곱해서 넓이 계산
					flag = true;
				}
				input[i] -= 2;	// 막대의 개수 2개 감소
				i++;	// 예를 들어 현재 막대가 4개일 경우 같은 길이의 막대를 4개 사용하여 사각형을 만들 수 있기 때문에 현재 막대를 한 번 더 탐색하기 위한 i값 1 증가
			}
		}
		cout << answer << endl;
	}

'코딩테스트 > 문제풀이' 카테고리의 다른 글

[백준] 계단 오르기 Java  (0) 2023.08.29
[백준] 가운데를 말해요 Java  (0) 2023.07.17
[구름] 어부의 고기잡이 C++  (0) 2023.07.10
[구름] 단풍나무 C++  (0) 2023.07.10
[구름] 뒤통수가 따가워 C++  (0) 2023.07.07

https://level.goorm.io/exam/49096/%EC%96%B4%EB%B6%80%EC%9D%98-%EA%B3%A0%EA%B8%B0%EC%9E%A1%EC%9D%B4/quiz/1

 

구름LEVEL

구름LEVEL 문제를 풀이하고 부족한 부분을 보완하며 실력을 키워보세요. 구름LEVEL은 코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입

level.goorm.io

 

 

풀이

 

투포인터 알고리즘

start와 end 변수를 각각 시작, 끝 포인터로 활용

 

1. input[start] 부터 input[end]  까지 더한 값 sum이 m보다 작으면 end+ 1

2. m보다 크면 start + 1

3. m과 같으면 answer + 1 (경우의 수 카운트)

4. m보다 작으면서 end 포인터가 input의 길이를 벗어날 경우 >> 더이상 정답이 나올 수 없는 경우

 

 

 

	int main() {

		int n;
		int m;
		cin >> n >> m;

		vector<int> input;

		// input vector에 입력 값 저장
		for (int i = 0; i < n; i++) {

			int temp;
			cin >> temp;
			input.push_back(temp);
		}

		int start=0;		// 왼쪽 포인터
		int end=0;			// 오른쪽 포인터
		int answer = 0;		// 정답 카운트

		// end가 input 의 범위 안일 경우 반복
		while (end<n) {

			// start ~ end 의 합
			int sum=0;
			for (int i = start; i <= end; i++)
				sum += input[i];
			
			// sum == m 일 경우 정답 카운트 + 1
			if (sum == m) {
				answer++;
                
                // start 포인터 1 증가
				start += 1;
			}

			// sum < m 일 경우
			else if (sum < m)
            	// 다른 수를 더해서 m을 만들어야 하므로 end 포인터 증가
				end += 1;
                
            // sum > m 일 경우
			else if (sum > m)
            	// 수를 작게 만들어야 하므로 start 포인터 증가
				start += 1;
		}
		cout << answer << endl;
	}

https://level.goorm.io/exam/167345/%EB%8B%A8%ED%92%8D%EB%82%98%EB%AC%B4/quiz/1

 

구름LEVEL

구름LEVEL 문제를 풀이하고 부족한 부분을 보완하며 실력을 키워보세요. 구름LEVEL은 코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입

level.goorm.io

 

 

풀이

 

 

처음엔 단순하게 타일 하나하나 탐색하면서 인접타일의 값이 0이라면 현재 타일의 값을 -1 해봤는데

하루 단위에서 인접한 타일의 값이 1에서 0으로 바뀐 경우 해당 타일을 0으로 인식하여 값이 변동되는 문제 발생

 

-- 큐에 좌표값을 담아서 따로 한번에 값 변경하는 방식으로 해결

 

 

1. 모든 타일을 탐색

2. 0이 아닌 타일 발견 시, 해당 타일의 4방향으로 인접한 타일들의 값이 0이라면, 해당 타일의 x, y 좌표를 큐에 삽입

3. 큐에서 하나하나 꺼내면서 해당 타일의 값을 -1, 0보다 작아진다면 0으로

4. answer 변수 +1 (하루가 지남)

 

-- 반복

 

 

queue<pair<int, int>> inputSearch(vector<vector<int>> input, int n) {
	
    // input vector 값을 update하기 위한 좌표 정보를 담을 큐
	queue<pair<int, int>> q;
	int xdir[4] = { 0, 0, 1, -1 };	// 인접노드 탐색 x방향
	int ydir[4] = { 1, -1, 0, 0 };	// 인접노드 탐색 y방향

	// 모든 타일 하나하나 방문하며
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			int curX = i;
			int curY = j;

			// 현재 타일이 0이 아니라면 (물들 수 있다면)
			if (input[curX][curY] != 0) {
				// 현재 타일과 인접한 4개의 타일 탐색
				for (int k = 0; k < 4; k++) {
					int nextX = curX + xdir[k];
					int nextY = curY + ydir[k];

					// 인접한 타일이 전체 범위 안이면서
					if (nextX >= 0 && nextY >= 0 && nextX < n && nextY < n) {
						// 인접한 타일의 값이 0이라면 q에 삽입
                        if (input[nextX][nextY] == 0) {
							q.push(make_pair(curX, curY));
						}
					}
				}
			}
		}

	}

	// 인접한 타일의 영향을 받아 물들어갈 타일의 좌표를 담은 큐를 return
	return q;
}


vector<vector<int>> inputUpdate(queue<pair<int, int>> q, vector<vector<int>> input) {

	// 큐 안의 좌표를 하나하나 꺼내면서 값을 -1
	while (!q.empty()) {

		int x = q.front().first;
		int y = q.front().second;

		q.pop();
		input[x][y] -= 1;

		if (input[x][y] < 0)
			input[x][y] = 0;
	}
	
    // 변경된 input vector를 return
	return input;
}


int main() {

	int n;		// x, y축 크기
	cin >> n;

	vector<vector<int>> input;		// input 값을 담을 vector 컨테이너

	int answer = 0;
    
    // 반복문으로 input vector에 문제 입력값 삽입
	for (int i = 0; i < n; i++) {
		vector<int> temp;
		for (int j = 0; j < n; j++) {
			int m;
			cin >> m;
			temp.push_back(m);
		}
		input.push_back(temp);
	}

	// while 한 번이 하루
	while (1) {

		queue<pair<int, int>> q = inputSearch(input, n);

		// q에 아무것도 담겨있지 않다면 >> 더이상 물들 단풍나무가 없다면 while 탈출
		if (q.empty())
			break;

		// q에 값이 있다면 하루가 지나고
		answer++;
        
        // input vector의 값을 변경 (물든 상태로)
		input = inputUpdate(q, input);

	}


	cout << answer << endl;

}

 

https://level.goorm.io/exam/167337/%EB%92%A4%ED%86%B5%EC%88%98%EA%B0%80-%EB%94%B0%EA%B0%80%EC%9B%8C/quiz/1

 

구름LEVEL

구름LEVEL 문제를 풀이하고 부족한 부분을 보완하며 실력을 키워보세요. 구름LEVEL은 코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입

level.goorm.io

 

 

풀이

 

스택을 이용하는 문제

 

문제에 나와있는

** A 산봉우리에서 B산봉우리를 보기 위한 조건?

1. A가 B보다 왼쪽에 있어야 하고 (A < B)

2. A와 B 사이에 있는 모든 산봉우리가 A보다 작아야 한다

 

라는 조건을 활용

 

 

산봉우리를 왼쪽부터 순서대로 선택

스택의 top을 살펴보고, 현재 선택된 산봉우리보다 작으면 pop

>> 왜? 현재 선택된 산봉우리보다 작은 산봉우리는 현재 선택된 산봉우리를 포함하여 오른쪽에 있는 모든 산봉우리도 볼 수 없기 때문에

 

현재의 값을 push 하면 스택의 크기가 선택된 산봉우리를 볼 수 있는 산봉우리의 개수가 됨

 

int main() {

	int n;	// 산봉우리 개수
	cin >> n;

	stack<int> s;
	vector<int> answer;		// 정답을 담을 vector

	answer.push_back(0);	// 제일 왼쪽 산봉우리는 바라보는 신선이 없으므로 항상 0

	for (int i = 1; i < n; i++) {
		int input;		// 산봉우리의 높이 입력
		cin >> input;
		
        // 스택이 비어있지 않고, top() 보다 input의 값이 크거나 같다면
		while (!s.empty() && s.top() <= input)
			s.pop();	// 스택의 값을 pop
		
        // 그 후 스택에 현재 input을 push
		s.push(input);
        
        // 스택의 size를 answer vector에 저장
		answer.push_back(s.size());

	}

	// 정답 출력
	for (auto a : answer)
		cout << a << " ";
	
	return 0;

}

 

https://level.goorm.io/exam/152115/%ED%98%84%EB%8C%80%EB%AA%A8%EB%B9%84%EC%8A%A4-%EC%98%88%EC%84%A0-%EC%A3%BC%EC%B0%A8%EC%8B%9C%EC%8A%A4%ED%85%9C/quiz/1

 

구름LEVEL

구름LEVEL 문제를 풀이하고 부족한 부분을 보완하며 실력을 키워보세요. 구름LEVEL은 코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입

level.goorm.io

 

풀이

 

간단한 bfs 탐색문제

처음엔 dfs로 풀었는데, 시간초과로 인해 bfs로 재풀이

 

한 칸 한 칸 탐색하며 방문한적 없고 값이 1이 아닌 좌표들에 대해 bfs 실행 >> 해당 구역의 점수 반환

반환된 점수를 max 함수를 이용하여 maxVal에 저장

값 출력

 

 

 

int n;	// 행
int m;	// 열
int maxVal;	// 구역 점수 중 가장 높은 점수
vector<vector<int>> input;	// 입력값을 저장할 2차원 벡터
int visit[2001][2001] = {};	// bfs 탐색 시 방문 여부
int xdir[4] = {0, 1, 0, -1};	// nextX 를 위한 배열
int ydir[4] = {1, 0, -1, 0};	// nextY 를 위한 배열


int bfs(int x, int y) {

	queue<pair<int, int>> q;	// bfs를 위한 queue, x, y값 한번에 저장하기 위한 pair 컨테이너
	q.push(make_pair(x, y));	// bfs의 시작좌표 (x, y)를 q에 삽입 
	visit[x][y] = 1;			// 그 후, (x, y)를 방문했는 의미로 1로 값 변경
	int score = 0;				// 구역의 점수를 담을 score 변수 선언

	// q가 비어있지 않다면 반복 >> 이어져 있는 구역이 있담면
	while (!q.empty()) {

        // 현재 탐색하고 있는 x, y 의 좌표값을 curX, curY에 담고
        // queue 맨 앞의 좌표값을 pop()
        int curX = q.front().first;
		int curY = q.front().second;
		q.pop();
        
        
		// 현재 좌표의 값이 0이라면, 즉 비어있는 구역이라면 score + 1
		if (input[curX][curY] == 0)
			score += 1;
            
        // 현재 좌표의 값이 2이라면, 비어있지만 장애인 구역이라면 score - 2
		else if (input[curX][curY] == 2)
			score -= 2;


		// for문으로 현재 좌표의 상, 하, 좌, 우 4방향에 인접한 좌표 탐색
		for (int i = 0; i < 4; i ++) {

			// 인접한 좌표의 x, y 값
			int nextX = curX + xdir[i];
			int nextY = curY + ydir[i];

			// 만약 인접 좌표가 전체 주차장 크기를 벗어나지 않으면서 아직 방문하지 않은 구역이라면
			if (nextX >= 0 && nextY >= 0 && nextX < n && nextY < m && visit[nextX][nextY]==0 && input[nextX][nextY]!=1) {
				
                // 방문으로 표시하고
                visit[nextX][nextY] = 1;
                
                // 좌표를 queue에 삽입
				q.push(make_pair(nextX, nextY));
			}
		}
	}
    
    
    // queue가 비어 반복문이 종료되면 하나의 구역 탐색 완료
    // score 에 그 구역의 점수를 담아 return
	return score;

}


int main() {
	
    // 주차장 구역의 크기 입력
	cin >>n >> m;

	// 반복문을 통해 주차장의 각 좌표값들을 input vector 컨테이너에 저장
	for (int i = 0; i < n; i++) {

		vector<int> temp;
		for (int j = 0; j < m; j++) {

			int value;
			cin >> value;
			temp.push_back(value);
		}
		input.push_back(temp);
	}

	// maxVal 초기화
	maxVal = 0;


	// 주차장 정보가 담겨있는 input vector를 한칸한칸 탐색하며 bfs 실행 >> 하나의 구역 점수 계산
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			
            // 만약 현재 좌표가 아직 방문하지 않았고 값이 1이라면
			if (visit[i][j] == 0 && input[i][j] !=1) {
            
				// maxVal와 bfs를 통해 나온 한 구역의 점수를 비교하여 큰 쪽을 maxVal에 저장
				maxVal = max(maxVal, bfs(i, j));
			}

		}
	}

	// 결과 출력
	cout<< maxVal << endl;
}

 

 

 

 

 

 

 

https://school.programmers.co.kr/learn/courses/30/lessons/12899

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

풀이

 

10진수 > 3진수 변환을 응용하면 간단

 

while문을 통해 처음 인풋값인 n을 3으로 나누고, 나머지를 string s 에 집어 넣고.. 

반복하고 div값이 3보다 작을 시 그 값을 s에 삽입 후 reverse로 s를 뒤집어주면 3진수를 구할 수 있음

 

하지만 124 나라에서는 0을 사용하지 않고 대신 4를 사용하기 때문에 나머지가 0이 나오는 경우에 대해 조건이 필요

9를 예로 들면, 원래의 3진수 대로 하면 100이 나오지만 124 나라에서는 24가 나옴

즉, 3진수에서의 10의 값을 4로 치환한 것

div%3 == 0 일 경우 몫인 div는 -1, 나머지 0은 4로 바꾸어 s에 삽입하면 끝

마지막의 div값이 0일 경우 맨 앞자리의 0을 제거하기 위해 div!=0 일 경우에만 삽입 후 reverse

 

 

    string solution(int n) {
        string s = "";
        int div = n;
        int res = 0;

        while (div>=3) {
            res = div % 3;
            div /= 3;
            if (res == 0) {
                div -= 1;
                res = 4;
            }
            s += to_string(res);
            
        }
        if(div!=0)
            s += to_string(div);

        reverse(s.begin(), s.end());


        return s;
    }

https://school.programmers.co.kr/learn/courses/30/lessons/12909

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

풀이

 

괄호가 완성되려면 '(' 와 ')' 개수가 같아야 하는 점을 이용

 

** ())( 와 같은 케이스처럼 개수가 같지만, 불완전한 괄호일 경우 탐색을 위해 

'(' , ')' 의 개수가 같은 시점, 즉 모든 괄호가 정상적으로 닫힌 시점에서 ')' 로 시작하는 괄호가 있다면  해당 괄호는 비정상적인 괄호

 

 

 

 

 

 

bool solution(string s)
{
	bool answer = true;
	int lcnt = 0;
	int rcnt = 0;
	for (auto i : s) {
        if (i == ')' && lcnt == rcnt)
			return false;

		if (i == '(')
			lcnt++;
		else
			rcnt++;
	}
	
    return (lcnt - rcnt) == 0;
}

 

 

 

https://school.programmers.co.kr/learn/courses/30/lessons/12906

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

풀이

 

그냥 for문으로 순회하며 현재 값이 앞의 값이랑 같다면 continue

다르다면 answer에 push 해서 answer 리턴

 

 

** unique 함수를 사용해 arr.begin() 부터 arr.end() 까지 중복되는 값을 탐색하여

erase하는 방법을 사용하면 한줄로 풀이 가능

 

 

vector<int> solution(vector<int> arr)
{
	vector<int> answer;
	int cur = -1;


	for (auto i : arr) {
		if (cur == i)
			continue;
		else
			answer.push_back(i);
		cur = i;
	}
	return answer;
}

 

 

Unique 함수 사용

vector<int> solution(vector<int> arr) 
{
    arr.erase(unique(arr.begin(), arr.end()),arr.end());
    return arr;
}

https://school.programmers.co.kr/learn/courses/30/lessons/42584

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

풀이

 

단순 반복

중첩 for문 사용

 

for문을 통해 prices의 값을 자신 이후의 값들과 비교

만약 자신보다 적은 값이 있다면 그 값과 자신 사이의 거리를 answer에 push

 

answer 리턴

 

 

 

vector<int> solution(vector<int> prices) {
	vector<int> answer;
	for (int i = 0; i < prices.size();i++) {
		
		int cur = prices[i];
		int cnt = 0;
        
		for (int j = i; j < prices.size();j++) {
        
			cnt++;
			if (prices[j] < cur) 
				break;
		}
        
		answer.push_back(cnt-1);
		
	}
	return answer;
}

https://school.programmers.co.kr/learn/courses/30/lessons/42583#

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

풀이

 

(차량의 무게, 차량이 다리를 다 건너는 시간)

을 쌍으로 가지는 큐 활용

 

truck_weights 벡터의 맨 처음 값과 그 트럭이 다리를 통과하는데 걸리는 시간(다리길이 +1) 를 먼저 큐에 삽입

>> 그래야 while 문 돌리기 가능하기 때문

 

이후 while문 반복을 통해

큐의 맨 앞과의 값을 비교하여 pop,

현재 도로 위의 차량들 무게와 다음 순서의 차량의 무게를 비교하여 push 수행

 

모든 차량이 지나가면 (q.empty() = true 라면) 반복문 탈출

time 값 리턴

 

int solution(int bridge_length, int weight, vector<int> truck_weights) {

	int sum = 0;	// 현재 다리 위의 무게
	queue<pair<int, int>> q;	// 현재 다리 위 차량 무게, 차량이 다리를 다 건너는 시간
	int idx = 0;	// 인덱스	
	int time = 1;	// 시간
	
	
	q.push(make_pair(truck_weights[idx], bridge_length+1));
	sum += truck_weights[idx++];

	while(!q.empty()){
    
		// 시간 증가
		time++;
		
		// (time == 맨 앞 차량이 통과하는데 걸리는 시간) 이라면
		// q.pop() 으로 도로에서 차량 빼고, sum 에서 해당 차량 무게 제외 
		if (time == q.front().second) {
			sum -= q.front().first;
			q.pop();	
		}

		// 다음 차량과 현재 도로위에 있는 차량의 무게를 더한 값 < 도로가 견딜수 있는 무게
		// 다음 차량이 도로에 들어갈 수 있다
		if (idx< truck_weights.size() && (sum+truck_weights[idx])<= weight) {
        
			// 큐에 차량의 무게, 다 지나가는데 걸리는 소요 시간을 pair로 삽입
			q.push(make_pair(truck_weights[idx], bridge_length+time));
            // 현재 도로위의 무게 증가, idx값 증가
			sum += truck_weights[idx++];
		}
	}
	return time;
}

+ Recent posts