该题目来源于Robert Sedgewick 的《算法》。
1.1.32 Histogram. Suppose that the standard input stream is a sequence of double values. Write a program that takes an integer N and two double values l and r from the command line and uses StdDraw to plot a histogram of the count of numbers in the standard input stream that fall in each of the N intervals defined by dividing (l, r) into N equal-sized intervals.
1.1.32 直方图。 假设标准输入流中是一系列double值。写一个程序从命令行接受一个整数 N 和两个double值 l 和 r ,将(l,r) 分成N段,并使用StdDraw画出输入流的值落入每段的数量的直方图。
在统计学中,直方图是一种对数据分布情况的图形表示,是一种二维统计图表,它的两个坐标分别是统计样本和该样本对应的某个属性的度量。 直方图是品质管理七大工具之一。【来源于维基百科】
首先做一个柱状图,了解一下 StdDraw类中filledRectangle的方法:
/**
* bar chart example
*/
public static void barChart(){
int N = 5;
double[] a = new double[N];
for (int i = 0; i < N; i++) {
a[i] = StdRandom.random();
}
for (int i = 0; i < N; i++) {
//矩形一半的宽
double rw = 0.5 / N;
// 矩形一半的高
double rh = a[i] /2.0;
//矩形中心点x轴的坐标
double x = 1.0 * i / N + 1.0 / N / 2;
// 矩形中心点y轴的坐标
double y = rh;
System.out.println("x=" + x + ",y=" + y + ",rw=" + rw + ",rh=" + rh);
StdDraw.filledRectangle(x, y, rw, rh);
}
}
在main方法中调用上面的方法,会展示下面的视图:
本道题的解决如下:
/**
* solution
* @param N the numbers of intervals
* @param l interval left value
* @param r interval right value
* @param a double stream
*/
public static void histogramSolution(int N, double l, double r, double[] a){
// double stream的组距
Arrays.sort(a);
double interval = (r -l) / N;
// histogram 的组距
double histogramInterval = 1.0 / N;
for (int i = 0; i < N; i++) {
// double stream 组距左边的值
double dsLeft = interval * i + l;
// double stream 组距右边的值
double dsRight = interval * (i+1) + l;
// 矩形中心位置x轴的坐标
double x = histogramInterval *i +histogramInterval / 2;
// 频次,代表直方图的高
int countTemp = 0;
for (int j = 0; j < a.length; j++) {
// 频次
if (a[j] > dsLeft && a[j] < dsRight ) {
countTemp ++;
}
}
double p = (countTemp * 1.0) / a.length;
//double p = (countTemp * 1.0) / N;
// 矩形中心位置y周的坐标
double y = p / 2;
StdDraw.filledRectangle(x, y, histogramInterval / 2, y);
}
}
比如,用main方法模拟调用:
public static void main(String[] args) {
//barChart();
// represent argument N
int N = 3;
// represent argument l
// represent argument r
double l = 1.09;
double r = 23.32;
// represent double stream
double[] a = {1.08, 1.21, 2.33, 3.35, 8.78, 6.98, 7.99, 10.21, 15.22, 21.23, 14.51, 16.77, 18.23};
histogramSolution(N, l, r, a);
}
展示的结果如下: