CSP真题之灰度直方图202104-1JAVA版

题目:

 分析过程:

一看到这个问题描述我就头疼,长篇大论、虚无缥缈的(对我这样数学比较差的)人来说,简直就是一种折磨。即使它处于csp考试的第一题,超小难度,但若是没有将抽象具体化的能力的话,再简单也是白搭。在做这个题目之前,我先解析下上一个题目:出现次数最多的数-2013-12-1.

解题目的:将抽象问题转化为实际编程需求,需要具备这种能力,没有怎么办,多加锻炼

解题三部曲:

1.看输入,输出。输入什么参数,需要输出什么结果。

2.弄清楚输入和输出参数具体是什么含义,有什么用。

3.将所求问题转化为编程需求实现。

注1:编程时注重选取合适的数据结构和算法,但有时候解题出来就行,毕竟是考试,只需要对就行,不过最好是在平常编码时就注重编码的好习惯(注释、精简的代码、适合的数据结构和算法)

注2:多注重一下题目的细节要求,有可能掉了条件,就没有满分了,也要多进行边界、特殊值测试,从而使答案更完美。如提交测评显示超出 内存或时间限制,需要事先进行一下渐近复杂度分析,分析一下所使用的的数据结构和算法是不是最好的(肯定是很垃圾的,不然也不会测评不过)

开始上次解题了。

1、输入:有两行,第一行是要输入的数字的个数n(循环的次数)

第二行是以空格隔开的n个数字

2、输出:求出出现次数最多的那个数,并且如果次数最多的有多个,需要输出数值最小的那个。

由题意:

用户会有两个输入,第一个输入是n,即数的个数

第二个输入是这n个数本身,要求出出现次数最多的数

1)次数需要存、数本身也要存

2)次数需要累加

自然而然想到Map键值对集合了,数字本身作为key,次数作为value。次数作为value可以实现累加覆盖。但是如果最大的出现次数一样,有多个怎么办?需要取出数值最小的那个,这个怎么实现?我希望集合可以按照key排序,这样最小的就在前面,即时有跟它次数相同的,只要出现次数不超过它,我也舍弃掉,这样就可以取出出现次数相同情况下比较小的那个了。

想要排序很简单,使用TreeMap即可实现,默认按照key升序排序,小的就在前面。【如果需要降序,自己实现自定义比较器即可

有了实现思路下面就直接上代码,谁都不可能一蹴而就,需要大量的练习和编码实践。

package practice_20210831;
 
import java.util.*;
 
public class Main {
    public static void main(String[] args) {
 
//        问题描述
//  给定n个正整数,找出它们中出现次数最多的数。如果这样的数有多个,请输出其中最小的一个。
//        输入格式
//  输入的第一行只有一个正整数n(1 ≤ n ≤ 1000),表示数字的个数。
//  输入的第二行有n个整数s1, s2, …, sn (1 ≤ si ≤ 10000, 1 ≤ i ≤ n)。相邻的数用空格分隔。
//        输出格式
//  输出这n个次数中出现次数最多的数。如果这样的数有多个,输出其中最小的一个。
//        样例输入
//        6
//        10 1 10 20 30 20
//        样例输出
//        10
 
        run();
 
 
    }
 
 
    public static void run() {
        //输入数字的个数n
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
 
        int[] nums = new int[n];
 
        //循环输入数字,将其存入数组
        for (int i = 0; i < n; i++) {
            nums[i] = sc.nextInt();
        }
 
        //构建Map,且要求能排序的Map,选取TreeMap,用以储存数字和数字的个数,number:cnt
        Map<Integer,Integer> map=new TreeMap<Integer, Integer>();//默认按照key的升序排序
        int cnt=0;
        for (int num : nums) {
            Integer value = map.getOrDefault(num, 0);
            value++;
            map.put(num,value);
        }
        //遍历map找出出现次数最多的数字,且需要满足 如果次数最多的一样,要取最小的数
        Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
 
        int max_num=0;
        int max_cnt=0;
        for (Map.Entry<Integer, Integer> entry : entries) {
            Integer key = entry.getKey();
            Integer value = entry.getValue();
            if(value>max_cnt)
            {
                max_cnt=value;
                max_num=key;
            }
        }
        System.out.println(max_num);
    }
}

测评结果:100分

额,,肯定没有c++执行效率快和占用内存小的~

 接下来,我们来看下今天这道题,灰度直方图

说实话,我刚开始读题目,读了三遍,没读懂o(╥﹏╥)o

咱还是按照三部曲走:题目里面其他什么扯淡的白话懂最好,不懂就算了

1、第一步,看输入:

输入一共n+1行

第一行是是三个数字,空格隔开,n、m、L

从第二行到n+1行输入的是矩阵

每一行是m个数字

n和m是什么?

n是矩阵(可以理解为坐标系)的纵坐标轴

m是矩阵的横坐标轴

n和m的范围----->面积n*m即组成了这个大矩阵

这每行的m个数字究竟是什么呢?由题意(需要多看几遍、理解)

可知,用户每行输入的这m个数字,即代表那一点(m、n组成的矩阵)像素的灰度值 

L:就是一个数组的长度

2、输出什么:

需要输出数组h[0]、h[1].......h[L-1]的值,并以空格隔开。

那这个数组h[x]所带表的含义是什么呢?

由题意可知,h[x]即直方图中灰度值为x的像素的个数,灰度值是什么,灰度值不就是用户输入的那每行的m个数嘛?

3、理解了输入输出代表的含义,转化为编程需求很简单,不就是要求输入的这m*n个数里面,我给的这个数组的每个下表值在这个m*n的矩阵里面有多少个嘛,计数问题,双层for循环,搞定!

代码如下:

package prac_20210401;

import java.util.*;

/**
 * @author:tom
 * @Date:Created in 9:23 2021/9/4
 */
public class Main {
    public static void main(String[] args) {
        run();
    }

    //灰度直方图
    public static void run() {

        //第一行输入的三个值:n、m、l
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();//矩阵长
        int m = sc.nextInt();//矩阵宽
        int l = sc.nextInt();//数组长度
        int[] h = new int[l];


        int[] zhiFangTu=new int[n*m];
        for (int i = 0; i < n * m; i++) {
            //存入m*n个元素
            zhiFangTu[i]=sc.nextInt();
        }

        //计算h[0]~h[l-1]
        for (int i = 0; i < h.length; i++) {
            int cnt=0;
            for (int i1 = 0; i1 < zhiFangTu.length; i1++) {
                if(i==zhiFangTu[i1])
                    cnt++;
            }
            h[i]=cnt;
        }
        for (int i = 0; i < h.length; i++) {
            if(i==h.length-1)
                System.out.print(h[i]);
            else
                System.out.print(h[i]+" ");
        }



    }

}

经过多次输入测试,发现代码符合题目要求。

测评结果:100分。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值