package org.example.통계학;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.*;
/* *
*
*
*
*
*
*
* N 개의 수
* N 은 홀수
* 1<= N <= 500000
* 입력되는 정수 => -4000 ~ 4000
* */
public class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
int N = Integer.parseInt(br.readLine());
if (!(N % 2 == 1)) {
String errorMessage = MessageFormat.format("N =>{0} 는 홀수여야 합니다.", N);
throw new IllegalArgumentException(errorMessage);
}
if (!(1 <= N && N <= 500_000)) {
String errorMessage = MessageFormat.format("N =>{0} 는 1 이상 500,000 이하여야 합니다.", N);
throw new IllegalArgumentException(errorMessage);
}
List<Number> numbers = new ArrayList<>();
for (int i = 0; i < N; i++) {
int inputNumber = Integer.parseInt(br.readLine());
Number number = new Number(inputNumber);
numbers.add(number);
}
// 산술 평균 구하기
numbers.stream()
.mapToInt(Number::getValue)
.average()
.ifPresent(i -> System.out.println(Math.round(i)));
// 중앙값 구하기
numbers.stream()
.sorted()
.skip(N / 2)
.findFirst()
.ifPresent(number -> System.out.println(number.getValue()));
// 최빈값
HashMap<Number, Integer> numberCountMap = new HashMap<>();
for (Number number : numbers) {
int count = numberCountMap.getOrDefault(number, 0);
numberCountMap.put(number, count + 1);
}
int maxCount = 0;
List<Number> modeNumbers = new ArrayList<>();
for (Map.Entry<Number, Integer> entry : numberCountMap.entrySet()) {
if (entry.getValue() == maxCount) {
modeNumbers.add(entry.getKey());
continue;
}
if (entry.getValue() > maxCount) {
modeNumbers.clear();
maxCount = entry.getValue();
modeNumbers.add(entry.getKey());
}
}
if (modeNumbers.size() > 1) {
Collections.sort(modeNumbers);
System.out.println(modeNumbers.get(1)
.getValue());
} else {
System.out.println(modeNumbers.get(0)
.getValue());
}
// 범위 ( 최댓값과 최솟값의 차이)
int max = numbers.stream()
.mapToInt(Number::getValue)
.max()
.orElseThrow();
int min = numbers.stream()
.mapToInt(Number::getValue)
.min()
.orElseThrow();
System.out.println(max - min);
} catch (IOException e) {
e.printStackTrace();
}
}
public static class Number implements Comparable<Number> {
private final int value;
public Number(int value) {
if (!(-4_000 <= value && value <= 4_000)) {
String errorMessage = MessageFormat.format("value =>{0} 는 -4000 이상 4000 이하여야 합니다.", value);
throw new IllegalArgumentException(errorMessage);
}
this.value = value;
}
public int getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Number)) return false;
Number number = (Number) o;
return value == number.value;
}
@Override
public int compareTo(Number o) {
return Integer.compare(this.value, o.value);
}
@Override
public int hashCode() {
return value;
}
@Override
public String toString() {
return "Number{" +
"value=" + value +
'}';
}
}
}
- 일단 클래스로 뽑아낸다고 하더라도 유틸성 클래스가 될거같아서 메인문에서 전부 수행했다.
Stream 사용
- 개요
- Java 8 부터 도입되었습니다.
- 함수형 프로그래밍의 접근 방식을 사용하고 있습니다.
- 주로 컬렉션에 대한 연산을 비동기적이거나 병렬적으로 처리하는 데 유용하게 쓰인다고 합니다.
- 생성 방법
Arrays.stream(array)
← 배열에 대한 스트림 생성
Collection.stream()
← 컬렉션에 대한 스트림 생성
- 등등이 있는데 대표적으로 이 2가지가 많이 사용됩니다.
- 중간 연산법
- 스트림을 다른 스트림으로 변환하는 연산법입니다.
lazy
하게 연산이 수행됩니다.- 종료 연산이 호출될 때까지는 실제로 수행되지 않는 연산이라는 의미입니다!
- 예시
filter(predicate)
: 해당 조건에 맞는 요소만 선택할때 사용
map(function)
: 각 요소를 다른 형태로 변환할 때 사용
sorted()
: 스트림의 요소를 정렬
distinct()
: 중복되는 요소를 제거합니다.
skip(n)
: 처음n
개의 요소를 무시합니다.
- 종료 연산
- 스트림을 최종적으로 소비하여 결과를 생성합니다!
- 예시
collect()
: 결과를 컬렉션으로 변환시 사용합니다.
forEach(consumer)
: 각 요소에 대해 작업을 수행할 수 있습니다 consumer 에 로직을 주입할 수 있습니다.
reduce()
: 스트림의 요소를 하나의 값으로 축약할 수 있습니다.
average()
,max()
,min()
,sum()
: 산술 연산입니다.
findFirst()
,findAny()
: 조건을 만족하는 첫 번째, 임의 요소 반환
산술평균의 경우
numbers.stream()
.mapToInt(Number::getValue)
.average()
.ifPresent(i -> System.out.println(Math.round(i)));
numbers.stream()
: 리스트numbers
로부터 스트림 생성
mapToInt(Number::getValue)
:Number
객체의getValue
메서드를 호출하여 int로 변환
average()
: 평균 계산
ifPresent()
: 평균 값이 존재하면 출력
중앙값 구하기
numbers.stream()
.sorted()
.skip(N / 2)
.findFirst()
.ifPresent(number -> System.out.println(number.getValue()));
sorted()
: 숫자를 정렬
skip(N / 2)
: 처음N / 2
개의 요소를 무시
findFirst()
: 남은 요소 중 첫 번째 요소를 찾음
ifPresent()
: 값이 존재하면 출력
HashMap 에서 EntrySet이란..
- entrySet() 의 원리
entrySet()
메서드는 HashMap 내부 데이터에 접근하여 , 키-값 쌍을Set
형태로 반환합니다.
왜
Set()
형태로 반환하는 걸까? (HashSet 을 예시로 설명)- 일단 Set 인터페이스는 중복값을 허용하지 않는다는 특징이 있습니다.
- 그래서 contains ( 해당 값을 가지고 있는지 체크 ) … 등의 수행을 하는 경우
- 내가 찾고자 하는 인자의 객체나 값을 ⇒ 해시 값으로 변환
- 그 해시 값은 Set 자료구조 키값이 되겠죠
- 그 키값에 value 가 있는지 확인한다면 ⇒ 찾을 객체의 존재여부를 쉽게 파악할 수 있습니다.
- 해당 행위는 어떠한 반복을 수행하지 않기에
상수시간이 가능한 장점이 있어서 Set 으로 HashMap 을 순회하게 되는 것입니다.
Uploaded by N2T
'자바 > 알고리즘' 카테고리의 다른 글
[알고리즘] 바이러스 (0) | 2023.08.28 |
---|---|
[알고리즘]수 찾기 (0) | 2023.08.27 |
[알고리즘]문자열 집합 (0) | 2023.08.25 |
[알고리즘]스택 수열 (0) | 2023.08.23 |
[알고리즘]소수 구하기 (0) | 2023.08.19 |