江苏省政府要统计下近期省内的罚款数据,有两个需求:
按人员id升序统计每人缴纳的罚款总额。取所有id中间的那个。一共x个人交过罚款,就取下标为x/2的人的id。
统计缴纳罚款金额的中位数(简化下,只需要下标为x/2的即可,不需要考虑偶数个数求中位数的求平均的情况)。
大端模式的byte文件,全按int读即可。 如00000001表示1,0000000a表示10,00bc4ff2表示12341234 。
第一个int表示记录的条数,后面的int表示缴纳罚款的人的id,罚款金额,乱序。
两行结果,均为int
如5 1 20 9 200 111222333 100086 1 50 8 300
表示一共5条记录,id为1的人交了20块罚款,9交了200块罚款...
9
300
第一步的结果为
1,70;
8,300;
9,200;
111222333,100086;
4/2 = 2
输出第三个id 9
罚款中位数为排序后第三个数 300
import java.io.IOException; import java.io.PrintStream; import java.io.RandomAccessFile; import java.nio.IntBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; //示例代码,应该会比较慢吧,本题采用文件io接口,可以直接new File("in"),new File("out")这样调用 public class Main { public static void main(String[] args) throws Exception { RandomAccessFile fs = new RandomAccessFile("in", "r"); FileChannel fc = fs.getChannel(); MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); IntBuffer intBuffer = buffer.asIntBuffer(); PrintStream stream = new PrintStream("out"); int size = intBuffer.get(); hashGroup(intBuffer, stream, size); fc.close(); stream.close(); } public static void hashGroup( IntBuffer intBuffer, PrintStream stream, int size) throws IOException { long t = System.currentTimeMillis(); Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < size; i++) { int id = intBuffer.get(); int fee = intBuffer.get(); Integer value = map.get(id); value = value == null ? fee : value + fee; map.put(id, value); } List<Integer> keys = new ArrayList<>(); List<Integer> values = new ArrayList<>(); for (Map.Entry<Integer, Integer> entry : map.entrySet()) { keys.add(entry.getKey()); values.add(entry.getValue()); } Collections.sort(keys); Collections.sort(values); stream.println(keys.get(keys.size() / 2)); stream.println(values.get(values.size() / 2)); } }
人员id是国家统一认证的缴纳罚款人的id,id的范围大约与中国人口数量相当,即【0,15亿】,罚款金额都是整数,有罚站街指挥交通但是罚款金额0的,有骑电动车带人罚20的,也有超速违停罚几百上千的,还有偷税漏税罚款几百万的,总罚款没有超过20亿的。