(Java)【深基9.例1】选举学生会


)

一、题目描述

学校正在选举学生会成员,有 n ( n ≤ 999 ) n(n\le 999) n(n999) 名候选人,每名候选人编号分别从 1 到 n n n,现在收集到了 m ( m < = 2000000 ) m(m<=2000000) m(m<=2000000) 张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。

二、输入格式

输入 n n n m m m 以及 m m m 个选票上的数字。

三、输出格式

求出排序后的选票编号。

四、样例输入

5 10
2 5 2 2 5 2 2 2 1 2

五、样例输出

1 2 2 2 2 2 2 2 5 5

六、失败经历

  • 乍一看这个题目,感觉好简单啊,一个Arrays类的sort方法就可以解决了,结果并不然,第一次尝试虽然对了,但没有完全对,用sort方法超时了啊啊啊!
import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] number = new int[m];
        for (int i = 0; i < m; i++) {
            number[i] = sc.nextInt();
        }
        Arrays.sort(number);
        for (int i = 0; i < m; i++) {
            System.out.print(number[i] + " ");
        }
    }
}

在这里插入图片描述

  • 然后使用了StringBuffer解决了超时问题,结果又超内存了。。。。。。我炸了
    其实这次已经接近正确答案了,只需将数组的大小再变小一点点就行了
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n + 1];
        int m = sc.nextInt();
        for (int i = 0; i < m; i++) {
            a[sc.nextInt()]++;
        }
        StringBuffer s = new StringBuffer();
        for (int i = 1; i < n + 1; i++) {
            while (a[i]-- != 0){
                s.append(i + " ");
            }
        }
        System.out.println(s);
    }
}

在这里插入图片描述

七、正确代码

经过多次试错,正确答案出现啦!

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int[] a = new int[sc.nextInt()];
        int m = sc.nextInt();
        for (int i = 0; i < m; i++) {
            a[sc.nextInt() - 1]++;
        }
        StringBuffer s = new StringBuffer();
        for (int i = 0; i < a.length; i++) {
            while (a[i]-- != 0){
                s.append(( i + 1 ) + " ");
            }
        }
        System.out.println(s);
    }
}

在这里插入图片描述

八、正确思路及易错点

(1)题目分析

看题目要求:把选票按照投票数字从小到大排序,而投票数字就是候选人的编号,故该题的意思可理解为把选票按照候选人编号从小到大排序

(2)思路分析

①定义一个数组,数组的下标减去一对应了候选人的编号,数组的内容用来存储每个候选人获得了多少票数。

注意点:由于候选人的编号是从1开始的,而数组下标是从0开始的,我们用a[0]存储1号候选人的得票数,a[1]存储2号候选人的得票数,a[n - 1]存储n号候选人的得票数。此时数组的大小为n

int[] a = new int[sc.nextInt()];

②使用循环进行遍历,统计每个候选人获得的票数

具体思路:每读到某个候选人的编号,就将此编号减一作为下标,读取数组中此下标对应的内容,使其自增1,起到统计候选人票数的效果,题目中提供了一共有m张选票,故总共需要读取m次。

for (int i = 0; i < m; i++) {
    a[sc.nextInt() - 1]++;
}

此时就完成了数组的下标减一对应候选人的编号,数组的内容存储以该下标作为编号的候选人获得了多少票数

③创建字符串缓冲区对象,用于存储数据(StringBuffer类的具体使用在下方)

StringBuffer s = new StringBuffer()

④由于上面数组采取一一对应的存储方式,使得数组下标减去一就是候选人的编号,所以我们只需从下标0到下标n利用for循环遍历数组,再利用while循环控制存储次数。

例如下标1对应的数组内容是7,即2号候选人有7票,即a[1] = 7,满足a[1] – != 0 条件的情况有7种,即可以循环7次, s.append(( i + 1 ) + " ")也就可以执行7次,s中也就存储了7次2

关于存储,是利用了字符串缓冲区对象s来存储选票以及追加空格,用StringBuffer才不会超时和超内存

        for (int i = 0; i < a.length; i++) {
            while (a[i]-- != 0){
                s.append(( i + 1 ) + " ");
            }
        }

⑤最后输出就可以啦

System.out.println(s);

(3)StringBuffer: 线程安全的可变字符串

①StringBuffer类概述

  • 当对字符串进行拼接操作时,每次拼接都会构成一个新的String对象,既耗费时间又浪费空间。故当一个字符串的内容需要被经常改变时就要使用StringBuffer。
  • StringBuffer与String的不同在于:String类是字符串常量,是不可更改的常量。而StringBuffer是字符串变量,它的对象是可以扩充和修改的。

②StringBuffer对象的初始化

StringBuffer s = new StringBuffer();

③StringBuffer类支持的主要方法

方法作用
public StringBuffer append(String s)将指定的字符串追加到此字符序列
public StringBuffer reverse()将此字符序列用其反转形式取代
public delete(int start, int end)移除此序列的子字符串中的字符
replace(int start, int end, String str)使用给定String中的字符替换此序列的子字符串中的字符

④StringBuffer类中和 String 类类似的方法

方法作用
int capacity()返回当前容量
char charAt(int index)返回此序列中指定索引处的char值
void ensureCapacity(int minimumCapacity)确保容量至少等于指定的最小值
replace(int start, int end, String str)将指定的字符串追加到此字符序列。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)将字符从此序列复制到目标字符数组dst
int indexOf(String str, int fromIndex)从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引
int lastIndexOf(String str)返回最右边出现的指定子字符串在此字符串中的索引
int lastIndexOf(String str, int fromIndex)返回 String 对象中子字符串最后出现的位置
int length()将给定索引处的字符设置为ch
void setLength(int newLength)设置字符序列的长度
CharSequence subSequence(int start, int end)返回一个新的字符序列,该字符序列是此序列的子序列
String substring(int start)返回一个新的String,它包含此字符序列当前所包含的字符子序列
String substring(int start, int end)返回一个新的String,它包含此序列当前所包含的字符子序列
String toString()返回此序列中数据的字符串表示形式
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呦呦呦欸哟哟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值