본문 바로가기
알고리즘/Java 코딩 테스트 준비

[Java] 친구가 많은 친구를 반장으로 뽑기!

by Dev dreamer 2023. 2. 6.

 

6학년반에서 학생들이 1~5학년동안 어떤 반에 들어갔는지 나타내는 표이다.

반의 수는 총 9개가 있다.

 

각 학생이 다른 학생과 같은 반을 몇번 했는지 수를 구하고

그 수가 최대인 학생을 임시 반장으로 뽑으려고 한다.

 

✨ 첫번째 줄에는 반의 학생수를 나타내는 자연수가 주어진다. 3이상 1000이하이다.

둘째 줄부터는 1번 학생부터 차례대로 각 줄마다 1학년부터 5학년까지 몇 반에 속해있는지

5개의 정수가 빈칸 하나를 사이에 두고 주어진다.

주어지는 정수는 1이상 9이하의 정수이다.(반은 1반부터 9반까지 있다.)

 

✨ 첫 줄에 임시 반장으로 정해진 학생의 번호를 출력한다.

 

단 임시 반장이 될 수 있는 학생이 여러명인 경우에는 그 중 가장 작은 번호만 출력한다.

 

⚡ 예시 입력1.

 

5
2 3 1 7 3
4 1 9 6 8
5 5 2 4 4
6 5 2 6 7
8 4 2 2 2

 

⚡ 예시 출력 1.

 

4

 

 

💡 1. 내 풀이 과정 및 생각 5시간 진짜 5시간 걸림..


 

문제 풀기 전에 잠깐 간단한 잡소리좀 해보자면..

매번 이 문제와 함께 있는 초급이라는 단어가 나를 기죽여왔다.

 

초급푼거 가지고 왜 이렇게 어려워 하고 왜 이렇게기분 좋아함? 

 

하지만 출처를 보고 조금 기분이 좋아졌다..ㅎㅎ 그냥 그렇다고 

 

물론 초반의 쉬운문제겠지만 문제를 풀면서 느끼는건 완벽하게 구상하고 코드를 짜는건 매우 비효율 적이고

 

난 그렇게 똑똑하지 않다 라는 것이다. 오히려 그냥 일단 이렇게 적어놓고 생각해보면 되지 않을까? 하면

 

보통 다 생각이 이어지면서 풀리는 것 같다. 일단 적어라.

 

2차 배열이다? 그럼 일단 이중 for 문을 만들어서 생각해라. 메모장에 뭐라도 쓰면서 생각하다보면 결국 풀리는것 같다.

 


위에 글은 내가 맞은줄 알고 1시간전 쯤 4시간전쯤 쓴 글이다. 🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣

 

생각해보니까 오류가 조금씩 발생했고 콘솔에 찍어보니까 전혀 다른 값을 구하고 있었다.

 

문제를 풀면서 계속 콘솔 찍어보면서 하는 습관을 들이자. 그게 내가 아는 오류의 최소화 방법이다.

 

 

2차 배열을 처음 받은 자연수로 받아서 정리해 넘겨준다.

이때 학년은 총 5개 이므로 [학생수][5학년] 을 배열로 만들어 주면 된다.

 

각 학년별로 반의 정보를 나눠서 기존의 배열과 비교하고자 했다.

일단 내가 가장 착각하고 있던걸 먼저 살펴보자.

ArrayList<ArrayList<Integer>> 이라는 type을 가지는 리스트 안에

ArrayList<Integer>을 구해서 하나씩 넣으려고 했다.

 

처음에 난 위에 코드처럼 i 가 바뀔때마다 ArrayList를 새로 생성하지 않고

그냥 있던 ArrayList에 메소드인 clean을 사용해서 초기화했다.

 

이렇게 하게되면 뭐가문제냐면

 

ArrayList<ArrayList<Integer>> 을 콘솔로 찍어보면

들어가있는 5개 배열 모두다 같은 값을 가지고 있다

 

그 이유는 주소값을 가지는 temp2 를 5번 저장했기 때문이다.

ArrayList<ArrayList<Integer>>에 들어가 있는 5개의 배열값은 그냥 다 temp2의 동일한 주소값이다.

 

즉 temp2를 clean() 하고 나서 마지막에 넣은 배열 값 5개가 들어가 있는 것이다.

 

이를 해결하기 위해서 clean 대신에 새로운 객체를 생성해줬다(서로다른 주소를 갖게 끔)

그렇게 해서 원하는 데이터를 넣고 ArrayList<ArrayList<Integer>> 에 넣으니 원하는 값들이 출력됐다.

 

 

큰 부분을 깨달았으니 다시 문제 풀이를 설명하자면

 

왜 ArrayList에 담았냐면 ArrayList에 있는 contains() 기능을 쓰고 싶었다.

같은 반이었던 사람이 있었네 오 !! +1 해서 가장 많이 반이 된 친구를 찾으려고 했다.

 

그런데 .. 이것도 내 생각 미쓰였다.

 

왜냐하면 contains() 을 쓰게 되면 어차피 자기자신이 그 내부에 포함되어있어서 항상 true만 나온다.

결국 아무런 판단의 근거를 주지 못한다.

 

그래서 그냥 3중 for 문을 돌렸다.

 

이때 같은 값이 나오는 애들에게만 각자의 학생이 같은 반이었던 학생을 카운터 하는 배열에 추가해줬다.

이때 ! 여기서 체크되는건 자기자신도 체크된다.

 

따라서 카운트 된 값에서 1~5학년동안 총 5번 자기자신을 포함한 값을 빼주면 된다.

그리고 arr 배열에서 가장 큰 값을 갖는 가장 앞친구(뒤와 중복될 경우 앞친구가 반장!)의 순서를 구하면 된다.

이때 i의 값은 index 값이므로 몇번째 친구인지를 확인하기 위해서 결과값에 1을 더해줬다.

 

그래도 머리 쥐어 뜯으면서 오기로 풀긴풀었다.🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {

	public int solution(int[][] a, int num) {
		int answer = 0;
		ArrayList<ArrayList<Integer>> temp = new ArrayList<>();
		ArrayList<Integer> temp2= new ArrayList<>();
		int[] arr = new int[num];
		for (int i = 0; i < 5; i++) {
			 temp2= new ArrayList<>();
			for (int j = 0; j < num; j++) {
				temp2.add(a[j][i]);
				
			}
			temp.add(temp2);
		}
		
		for (int j = 0; j < num; j++) {
			for (int i = 0; i < 5; i++) {
				for(int k=0; k<num; k++) {
					if(temp.get(i).get(k)==a[j][i]) {
						arr[j]++;
					}
				}
			}
		}
		int tmp = 0;
		for (int x : arr) {
			x-=5;
		}
		for (int i = 0; i < arr.length; i++) {
			if (tmp < arr[i]) {
				tmp = arr[i];
				answer = i;
			} else {
			}
		}
		return answer+1;
	}

	public static void main(String[] args) throws NumberFormatException, IOException {

		Main T = new Main();
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int num = Integer.parseInt(br.readLine());
		int[][] arr = new int[num][5];

		StringTokenizer st;

		for (int i = 0; i < num; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < 5; j++) {
				arr[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		System.out.println(T.solution(arr, num));
	}
};

 

💡 2. 강사님 풀이


🔍 강사님은 3중배열로 풀고 가장안쪽 반복문 k를 학년으로 설정했다.

 

즉 i 와 j 는 각각 같은반이었는지 비교할 학생들의 반 정보

k는 학년의 정보다.

 

 

i와 j 는 각 학생의 정보를 나타내며 k의 경우는 학년을 나타낸다

 

이때 break를 해주는 이유는 같은 친구가 같은 반을 여러번 한 횟수를 구하려는게 아닌

 

얼마나 다양한 친구와 같은반을 해봤는지를 따지는 것이다.

 

그리고 최대값을 구해줬다.

 

 

 

 

 

 

 

 


코테 관련해서 많이 부담스러웠는데 강의를 통해 푸는 방법들을 배우니 이 시간이 즐겁습니다.

진짜 기능하나하나 다양한 방법으로 잘 가르쳐주십니다.

출처 : 자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비 대시보드 - 인프런 | 강의 (inflearn.com)

댓글