백준 - JAVA/정렬
[백준] 2108번 : 통계학 _ JAVA ( 주석 설명 )
wch_s
2023. 2. 7. 16:54
1번
→ Collections.sort(ary)를 이용한 기본 통계값_산술평균, 중앙값, 최빈값, 범위 출력하기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
//시간 복잡도 : O(n(log(n)))
//공간 복잡도 : 입력값의 범위 만큼의 공간 필요
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //빠른 입력을 위해 버퍼를 이용해 입력을 받는다.
StringBuilder sb = new StringBuilder(); //빠른 출력 위함
int N = Integer.parseInt(br.readLine()); //수의 개수를 입력받는다.
List<Integer> ary = new ArrayList<>(N); //수의 개수만큼 ArrayList 공간을 만든다.
double average = 0; //산술평균, 반올림을 위해서 double 로 선언한다.
int middle = 0; //중앙값
int many = 0; //최반값(여러 개 있을 경우 두번째로 작은 값)
int gap = 0; //범위(최댓값 - 최솟값)
double sum = 0; //산술평균 값을 위해 입력받은 모든 정수를 더하기 위한 변수, 반올림 계산을 위해서는 sum/N 에서 한 변수는 double 이어야 한다.
for(int i=0;i<N;++i){
int num = Integer.parseInt(br.readLine()); //기본 통계값을 구하는데 사용되는 정수이다.
ary.add(num); //ArrayList에 저장한다.
sum += num; //입력받은 정수를 합한다.
}
Collections.sort(ary); //오름차순으로 정렬한다.
int second = 1; //최빈값이 중복될 경우 두번째로 작은 값을 찾기 위한 변수
int count = 1; //빈도수 변수
int max = 0; //빈도수 갱신을 위한 변수
many = ary.get(0); //입력하는 수가 1개밖에 없을 경우
for(int i=0;i<N;++i){ //N까지 범위 설정 시, ary.get(i+1) 에서 배열 인덱스가 오버되기 때문에 N-1로 설정한다.
for(int j=i;j<N-1;++j){ //i에 해당하는 수부터 빈도수를 파악한다.
if(ary.get(j).equals(ary.get(j+1))) { //앞 뒤 value 가 같다면 그 빈도수를 count 해준다.
++i; //중복된 수는 계산할 필요가 없기 때문에, 계산을 넘긴다.
++count; //빈도수를 더한다.
}
else // 앞 뒤 value 가 틀리면 i에 해당하는 빈도수 계산을 멈추고, 최빈값 계산과정으로 넘어간다.
break;
}
if(max<count){ //더 큰 빈도수를 가진 정수가 있다면 갱신해준다.
max = count;
many = ary.get(i); //최빈값을 설정한다.
second = 1; //두번째 최빈값을 찾기 위한 변수를 1로 초기화해준다.
}
else if(max == count && second<2){ //같은 빈도수를 가진 정수가 있다면 두번째 최빈값으로 생각한다.
many = ary.get(i); //두번째 최빈값을 설정한다.
++second; // 세번째 최빈값부터는 걸러야하기 때문에 second 변수로 그 범위를 제한한다.
}
count = 1; //해당 정수의 빈도수 파악과 그에 따른 최빈값 갱신이 끝났면 초기값 1로 바꿔준다.
}
average = sum/N; //산술평균 값
middle = ary.get(N/2); //중앙값
gap = ary.get(N-1) - ary.get(0); //범위값
sb.append(Math.round(average)).append('\n'); //반올림을 위해서 round 메서드를 사용한다.
sb.append(middle).append('\n');
sb.append(many).append('\n');
sb.append(gap).append('\n');
System.out.println(sb); //기본 통계값을 모두 출력한다.
}
}
2번
→ Counting 정렬을 이용한 기본 통계값 출력하기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
//시간 복잡도 : O(n(log(n)))
//공간 복잡도 : 입력값의 범위 만큼의 공간 필요
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //빠른 입력을 위해 버퍼를 이용해 입력을 받는다.
StringBuilder sb = new StringBuilder(); //빠른 출력 위함
int N = Integer.parseInt(br.readLine()); //수의 개수를 입력받는다.
int range = 4000; //입력되는 정수값의 범위 num<=|4000|
int[] ary = new int[range*2+1]; //음수도 포함해야 하므로 range*2+1 용량의 배열을 선언한다.
int[] sort_ary = new int[N]; //정렬된 배열은 수의 개수만큼만 필요하므로 N 용량으로 선언한다.
int average = 0; //산술평균
int middle = 0; //중앙값
int many = 0; //최반값(여러 개 있을 경우 두번째로 작은 값)
int gap = 0; //범위(최댓값 - 최솟값)
double sum = 0; //산술평균 값을 위해 입력받은 모든 정수를 더하기 위한 변수, 반올림 계산을 위해서는 sum/N 에서 한 변수는 double 이어야 한다.
for(int i=0;i<N;++i){
int num = Integer.parseInt(br.readLine());
++ary[num+range]; //입력값의 범위에 음수도 있으므로 중심 range 을 더한다. => ary[range] 인덱스는 '0'을 의미한다.
sum += num; //산술평균 계산을 위해 sum을 구한다.
}
int k = 0; //sort_ary 배열에 저장하기 위한 인덱스 변수이다.
int max = -1; //최빈값 i를 찾기 위함으로, 수의 갯수를 의미하는 변수이다.
boolean second = false; //최빈값이 여러개 있을 때 두번째로 작은 최빈값을 찾기 위한 변수이다.
for(int i=0;i<ary.length;++i){ //입력되는 정수값의
if(max<ary[i]) { //더 큰 최빈값이 있을 때
max = ary[i]; //최빈값의 빈도 수를 갱신한다.
many = i-range; //실제 의미하는 num을 최빈값으로 설정한다.
second = true; //두번째로 작은 최빈값을 구하기 위해 true 로 설정한다.
}
else if(max==ary[i] && second == true){
many = i-range; //두번째로 작은 최빈값으로 최빈값을 갱신한다.
second = false; //이 후 동일한 빈도의 최빈값은 무시하도록 한다.
}
while(ary[i]>=1){ //중복된 수까지 전부 저장한다.
sort_ary[k] = i-range; //sort_ary 에 정렬된 값 저장한다.
++k; //sort_ary에 저장할 인덱스 +1 한다.
--ary[i]; //중복된 값 줄인다.
}
}
average = (int)Math.round(sum/N); //소수점 첫째자리에서 반올림한 산술평균
middle = sort_ary[N/2];
gap = sort_ary[N-1]-sort_ary[0];
sb.append(average).append('\n'); //산술평균
sb.append(middle).append('\n'); //중앙값
sb.append(many).append('\n'); //최빈값
sb.append(gap); //범위
System.out.println(sb); //네가지 기본 통계값 출력
}
}
* 짚고 넘어가자!
1> '==' vs 'a.equals(b)'
==
- 주소 비교
- 원시 타입 비교
- Integer 객체에서는 -128~127까지만 == 으로 비교 가능하다.
a.equals(b)
- 값 비교
- 객체 타입 비교
- Integer 객체에서는 equals 로 비교해야 한다!
2> 정수 나눗셈하기
- 유의하기
Math.round()
int num = Math.round(11/3);
1> (11/3) : 몫만 계산하고 나머지는 버린다.
2> 3에서 반올림을 하므로 3이 리턴된다.
int num2 = (int) Math.round(11.0/3);
1> (11.0/3) : 계산 결과가 3.66..으로 나온다.
2> 3.66에서 반올림을 하므로 4로 리턴된다.