728x90
오늘도 자바 알고리즘 문제 중 3052번 1546번 총 2문제 풀이를 완료했다.
사실 예전처럼 한번에 모아서 싹! 올리고 싶었는데 점점 문제도 뭔가 어려워지고, 코드도 길어져서 이제 풀고 바로바로 올리려고 한다.
1. 3052번 : 서로 다른 나머지는 몇 개?
10개의 수를 입력받고 42 로 나누었을 때 서로 다른 나머지값은 몇 개 일까?
import java.io.*;
import java.util.Arrays;
public class Q11_2 {
public static void main(String[] args) throws IOException {
Q_3052();
}
static void Q_3052() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int[] array = new int[10]; // 10개의 값을 갖는 배열 생성
int num = 0; // 입력받는 num 값 초기화
int result = 1; // 나머지는 최소 1개 존재
for(int i=0; i<array.length; i++) { // 배열 끝까지 반복
num = Integer.parseInt(br.readLine()); // 입력받음
if(0<num && num<1000) { // 입력받는 값은 0 초과 1000 미만
array[i] = num%42;
}else {
break; // 다른값 들어오면 끝!
}
}
// bw.write(Arrays.toString(array)+"\n"); // 기존 배열
Arrays.sort(array); // 배열을 오름차순으로 자동 정렬
// bw.write(Arrays.toString(array)); // 정렬 후
// bw.newLine();
// bw.flush();
// 버블 정렬 사용해서 0번째와 1번째 비교, 1번째와 2번째 비교 ---- 8번째와 9번째까지 비교!
for(int j=0; j<array.length; j++) {
for(int k=j+1; k<array.length; k++) {
if(array[j]!=array[k]) {
// bw.write("j 값 : "+j+"\n"); // 몇 번째 배열의 값이 동일하지 않은지 확인하기 위해
// bw.write("k 값 : "+k+"\n"); // 몇 번째 배열의 값이 동일하지 않은지 확인하기 위해
// bw.newLine();
// bw.flush();
result+=1; // 다를 경우 result +1
}
break;
}
}
bw.write(result+"\n"); // total 출력
br.close();
bw.flush();
bw.close();
}
- 이번 문제는 다음 단계를 통해 풀었다. 먼저 기본 변수 생성 -> 숫자 입력 받음 & 입력받은 숫자를 바로 array 배열에 저장 -> arrays.sort 메소드를 사용해 배열을 오름차순으로 정렬! -> 이후 버블정렬 방식으로 0번째와 1번째 비교, 1번째와 2번째와 비교 하면서 끝까지 비교하고 다른 값을 발견할때마다 result+1 실행
- 요렇게 풀었는데 자세한 내용은 코드를 보면서 작성하도록 하겠다.
1) 기본 변수 생성 & 입력받은 숫자를 바로 array 배열에 저장
- 여기서 중요한 것은 result 값을 1로 초기화했다는 점이다. 이는 입력받은 숫자를 42로 나누었을 때 나머지가 모두 똑같다고 해도 나머지가 최소 1개는 존재 한다는 점에서 초기값을 1로 두었다.
- 그 외에는 num 값에 따라서 지정된 값이 안들어오면 반복문을 끝낸다는 정도?
int[] array = new int[10]; // 10개의 값을 갖는 배열 생성
int num = 0; // 입력받는 num 값 초기화
int result = 1; // 나머지는 최소 1개 존재
for(int i=0; i<array.length; i++) { // 배열 끝까지 반복
num = Integer.parseInt(br.readLine()); // 입력받음
if(0<num && num<1000) { // 입력받는 값은 0 초과 1000 미만
array[i] = num%42;
}else {
break; // 다른값 들어오면 끝!
}
}
2) arrays.sort 메소드를 사용해 배열을 오름차순으로 정렬!
- 사실 여기가 가장 중요하다고 생각되는 부분인데 42로 나누었을 때의 나머지는 array 배열에 저장되어 있는 상태이다. 다만 입력받을때 숫자가 오름차순 / 내림차순으로 입력받는 것이 아니기 때문에 동일하게 42를 입력받아서 42로 나누어서 배열에 1 이라는 숫자가 저장되어 있다고해도 결국 순서대로 있지 않다.
- 사실 처음에는 모든 값을 하나하나 비교해서 갯수를 세어야하나? 라고 생각했었다. 하지만 그렇게 되면 결국 2중 for문을 돌리고 어쩌고하면서 오히려 복잡해지고, 뭣보다 아무리해도 서로 비교하게 놔두었을 때 중복되는 값들끼리 빅하는 것을 한번만 하도록 하는 방법을 찾지 못했다.
- 결국 아침 잠결에 일어나서!!(정말로 잠자다가 일어났는데 불현듯 떠올랐다ㅋㅋㅋ) 생각해본 결과 배열에 저장된 값을 오름차순으로 정렬해두면 같은 값끼리는 이웃하게 되어 비교가 훨씬 편해지게 되었다.
- 이렇게 정렬하여 비교하면 모든 값을 서로서로 비교할 필요가 없다는 점이다. 즉 버블 정렬을 활용하여 0번째와 1번째 1번째와 2번째 --- 8번째와 9번째 까지만 비교하면 된다. 왜냐하면 결국 동일한 숫자는 이웃하게 존재하는 배열이기에 서로 같은 값을 가지면 result 값이 올라가지 않는 상활이 된다. 이는 중복되는 값이 배열에는 존재하되, 다른 값을 확인 할 때는 존재하지 않는 것처럼 만들 수 있다(아래 코드로 좀 더 자세하게)
// 버블 정렬 사용해서 0번째와 1번째 비교, 1번째와 2번째 비교 ---- 8번째와 9번째까지 비교!
for(int j=0; j<array.length; j++) {
for(int k=j+1; k<array.length; k++) {
if(array[j]!=array[k]) {
bw.write("j 값 : "+j+"\n"); // 몇 번째 배열의 값이 동일하지 않은지 확인하기 위해
bw.write("k 값 : "+k+"\n"); // 몇 번째 배열의 값이 동일하지 않은지 확인하기 위해
bw.newLine();
bw.flush();
result+=1; // 다를 경우 total +1
}
break;
// j 값이 1이상이 될때부터는 비교 하지 않고 바로 종료하게
// 이를 통해 0번째값과 1번째 값, 1번째 값과 2번째 값 이렇게 비교할 수 있게 됨
}
}
- 코드를 보면서 조금 더 자세하게 확인할 수 있는데, 결국 우리에게 필요한 것은 서로 다른 값이 몇 개나 있는지 확인하는 것이다. 이 때문에 오름차순으로 정렬된 상태에서 비교하면 동일한 값은 비교할때 +1 되지도 않아서 사실상 ㅈ 중복된 값이 제거된 듯한 상황을 만들 수 있다.
- 중간에 break를 사용하는 이유는 k for 문을 멈추기 위함인데 이는 array j 와 k 를 비교할때 딱 j와 k 까지만 비교하고, 그 이상이되는 k+1 +2 +3 +4 +5 이런식의 증가를 멈추는 것이라고 생각하면 된다. 결국 j = 0 , k = 0+1 과 비교하고 break, j= 1 , k= 1+1 하여 비교하고, break 같은 방식이다.
2. 1546 : 점수 조작해서 평균 구하기
N 개의 점수를 입력받고 , 점수 중 가장큰 최대값으로 각 점수를 나누고 * 100 을 한 후 그 점수로 다시 평균을 계산하여 기말고자 평균 구하기( 이 정도 노력이면 그냥 두었으면 합니다ㅎ)
여튼 문제풀이 시작!
static void Q_1546() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
float result = 0;
int max = 0;
int num = Integer.parseInt(br.readLine()); // N개의 숫자 입력받음
String score = br.readLine(); // 점수 입력 받음
String[] array = score.split(" "); // 입력받은 점수를 배열로 만들어버림
System.out.println(Arrays.toString(array)); // 기존 점수 배열 한번 출력
for(int i=0; i<num; i++) { // 몇 개의 점수를 입력받던지 num 개까지의 점수를 갖고 계산
if(Integer.parseInt(array[i])>max) { // 최댓값 max 구함
max = Integer.parseInt(array[i]); // 최댓값 구하기
}
}
for(int j=0; j<num; j++) { // num 개 까지만 갖고 계산
result += ((float)Integer.parseInt(array[j])/max*100)/num;
}
// System.out.println("big : "+big); // 최댓값 출력
// System.out.println(Arrays.toString(n_score)); // 새로운 점수 배열 출력
bw.write(result+"\n"); // result 출력
br.close();
bw.flush();
bw.close();
}
- 이번 문제는 이전 문제보다 오히려 간단한 편이었다. 코드도 훨씬 간단한데, 변수 초기화 -> 최대값 구하기 -> 각 점수를 최댓값으로 나눈 후 *100 -> 이후 점수 평균 순서였다.
- 사실상 최댓값 구하는 것은 전에 많이 풀었었고, 평균을 구하는 것도 이미 했던 부분이라 설명할 것도 거의 없을 듯하다.
- 그나마 어려웠던 것은 num개만 입력받은 점수를 배열에 담는 부분정도였던것 같은데 저번과 달리 따로 나누고 어쩌고 하지 않고 그냥 몇 개의 점수던지 입력 받아 배열로 만들되, 내가 맨 처음에 입력받았던 num개 까지의 숫자만 갖고 계산을 진행하게 된다.
- 또한 평균은 실수이기 때문에 int 가 아닌 float 타입으로 해야했고, result 에 float 타입의 값으로 저장하기 위해 Integer.parseInt(array[j]) 할 때 앞에 float 로 붙여서 형변환하여 실수로 계산 될 수 있도록 해주었다.
for(int j=0; j<num; j++) {
int plus+= (float)Integer.parseInt(array[j])/max*100
// 각 배열의 인덱스값을 max 값으로 나누고 100을 곱하고 모두 더함
int average = plus/num;
// 모두 더한 값을 num 으로 나눔(num 개의 과목 점수기 때문에)
// 위의 코드를 한 줄로 줄이면
result += ((float)Integer.parseInt(array[j])/max*100)/num;
}
이번 문제들은 내가 설명하는게 사실 많이 힘들었다. 정석대로 푼 게 아니라 뭔가 내가 꼼수로? 푼 듯한 느낌이 많아서 오히려 힘들었던 것 같다.
고로 이글을 보시는 분들께서는 가능한 이클립스던 VS던 실행 후 직접 코드를 넣으셔서 실행해보시면서 설명해놓은 것을 보시면 훨씬!!! 많이 도움이 될 것이라고 생각합니다.
'Java - 알고리즘' 카테고리의 다른 글
백준 Java - 문자열 단계(1) : 11720번, 10809번 , 2675번, 1157번 (0) | 2021.11.02 |
---|---|
백준 Java - 4단계 1차원 배열 활용하기(3) : 8958번, 4344번 (0) | 2021.10.25 |
백준 JAVA - 4단계 1차원 배열 활용하기(1) (0) | 2021.10.15 |
백준 JAVA - 3단계 for 활용하기 (2) (feat. 별 찍기, x보다 작은 수) (0) | 2021.10.08 |
백준 JAVA - 3단계 for 활용하기 (1) (feat.Buffer, StringTokenizer, String.split 사용) (0) | 2021.09.29 |
댓글