Baekjun—統計学[java]
5192 ワード
質問元:https://www.acmicpc.net/problem/2108
処理数は統計学においてかなり重要なことである.統計学では、N個の数を表す基本統計値は以下のとおりである.しかし、Nは奇数であると仮定する.
算術平均:N個の数の和をNで割った値
中心値:N個の数字が順次に出たときの中央にある値.
最も頻繁な値:N個の数字の中で最も多い値を表示します
範囲:N個の数字の中で最も高い値と最も高い値の差
N個の数値が与えられた場合、4つのデフォルト統計値を求めるプログラムを作成します.
入力例
5
1
3
8
-2
2
サンプル出力
2
2
1
10
私が見つけた方法.
各数字の周波数を求めるために、配列を負数と正数に設定し、周波数を記録します.
negative Frequency[4001]
positive Frequency[4001]
記録後の最適値が負の場合は、負の値の頻度を確認して繰り返し値を検索します.
indexの設定が重要です.たとえば、-10が最も頻繁な値である場合、負の周波数配列のインデックス10~1がスキャンされます.このように、負数を逆さまにスキャンし、負数を昇順にスキャンすればよい.
問題の説明
処理数は統計学においてかなり重要なことである.統計学では、N個の数を表す基本統計値は以下のとおりである.しかし、Nは奇数であると仮定する.
算術平均:N個の数の和をNで割った値
中心値:N個の数字が順次に出たときの中央にある値.
最も頻繁な値:N個の数字の中で最も多い値を表示します
範囲:N個の数字の中で最も高い値と最も高い値の差
N個の数値が与えられた場合、4つのデフォルト統計値を求めるプログラムを作成します.
入力例
5
1
3
8
-2
2
サンプル出力
2
2
1
10
問題を解く
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
public static void main(String [] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int total = Integer.parseInt(br.readLine());
int [] arr = new int[total];
double avg = 0;
for(int i = 0; i < total; i++) {
arr[i] = Integer.parseInt(br.readLine());
avg += arr[i];
}
avg /= total;
//산술평균
avg = Math.round(avg);
int av = (int) avg;
sb.append(av).append("\n");
Arrays.sort(arr);
//중앙값
sb.append(arr[total / 2]).append("\n");
// 최빈값 구하기
int [] frequency = new int [4001];
int [] negFrequency = new int [4001];
for(int elem : arr) {
if(elem < 0)
negFrequency[Math.abs(elem)]++;
else
frequency[elem]++;
}
int max = 0;
int num = 0;
int second = num;
for(int i = negFrequency.length - 1; i > 0; i--) {
if(negFrequency[i] > max){
max = negFrequency[i];
num = -i;
second = num;
}
}
for(int i = 0; i < frequency.length; i++) {
if(frequency[i] > max){
max = frequency[i];
num = i;
second = num;
}
}
int minusEliminatedIndex = num < 0 ? -num : num;
if(num < 0) {
for (int i = minusEliminatedIndex - 1; i > 0; i--) {
if (negFrequency[i] == max) {
second = -i;
break;
}
}
}
if(second != num)
sb.append(second).append("\n");
else {
int x = num < 0 ? 0 : num + 1;
for(int i = x; i < frequency.length; i++) {
if(frequency[i] == max){
second = i;
break;
}
}
sb.append(second).append("\n");
}
//범위
sb.append(Math.abs(arr[total - 1] - arr[0])).append("\n");
System.out.println(sb);
}
}
平均値、中央値、範囲を求めるのは難しくありませんが、最も貧しい値を求める部分は考えなければならない問題です.私が見つけた方法.
各数字の周波数を求めるために、配列を負数と正数に設定し、周波数を記録します.
negative Frequency[4001]
positive Frequency[4001]
記録後の最適値が負の場合は、負の値の頻度を確認して繰り返し値を検索します.
indexの設定が重要です.たとえば、-10が最も頻繁な値である場合、負の周波数配列のインデックス10~1がスキャンされます.このように、負数を逆さまにスキャンし、負数を昇順にスキャンすればよい.
別の解釈
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
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[] countSort = new int[8001]; // 넣은 숫자들, 최빈값
int median = 100000; // 중앙값
int max = Integer.MIN_VALUE; // 최소값
int min = Integer.MAX_VALUE; // 최대값 범위
int sum = 0;
int range = 0;
int count = 0;
double avg = 0.0;
int mode_max = 0;
int mode_value = 10000;
boolean flag = false;
for (int i = 0; i < N; i++) {
int input = Integer.parseInt(br.readLine());
countSort[input + 4000]++; // 4000이 기준(==0)
sum += input;
if(input > max) {
max = input;
}
if(input < min) {
min = input;
}
}
// 산술평균
avg = Math.rint((double)sum / N);
for (int i = min + 4000; i <= max + 4000; i++) { // counting sort는 인덱스가 값이니까
if(countSort[i] > 0) {
// 중앙값
if(count <(N + 1) / 2) {
count += countSort[i];
median = i -4000;
}
// 최빈값
// 중복이 없는 경우
if(countSort[i] > mode_max){
mode_max = countSort[i];
mode_value = i - 4000;
flag = true;
}
// 중복되는 경우
else if(mode_max == countSort[i] && flag == true) {
mode_value = i - 4000;
flag = false;
}
}
}
// 범위
range = max + min*-1;
sb.append((int)avg).append("\n");
sb.append(median).append("\n");
sb.append(mode_value).append("\n");
sb.append(range).append("\n");
System.out.println(sb);
}
}
8000を頻度として並べ、4000を数値としてインデックスを見つけます.考えてみましたが、ちょっと直感的ではないので、そうしなかったほうがいい方法のようです.Reference
この問題について(Baekjun—統計学[java]), 我々は、より多くの情報をここで見つけました https://velog.io/@davidko/백준-통계학javaテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol