蓝桥杯 统计单词数(Java)

1.题目

统计输入英文文章段落中不同单词(单词有大小写之分,  但统计时忽略大小写)各自出现的次数。 输入段落中所含单词的总数不超过100,最长单词的长度不超过20个字母.
输入
一个包含若干句子的段落, 每个句子由若干英文单词组成. 除空格,  逗号和句号外, 这些输入的句子中不含其他非字母字符, 并且, 逗号和句号紧跟在它前面的英文单词后面, 中间没有空格. 段落最后一个字符是回车符,  表示输入结束.
输出
若段落中共有M个不同的英文单词,则按照其在段落中出现的先后顺序输出M行,各行的格式为:  单词中所有字母均用大写形式输出(最长的单词顶格输出,它前面没有多余的空格;  其余单词与其右对齐)+冒号+N个*号+该单词在段落中的出现次数N
样例输入
This is a test. This test is easy. This is a test. This test is easy.
样例输出
THIS:****4
IS:****4
A:**2
TEST:****4
EASY:**2

2.参考

链接: 传送门.
思路:由于知识的匮乏,没能写出来,刚开始想的也是用split函数将字符串分割出来,然后存储到Map集合里面去,最后再输出,看着短短的几个字,却想了好几天。
遇到的问题:
1.用split函数函数分割出来的字符,在这样的时候“ test. This ”,始终分割后会残留一个空格,然后想的是在字符串里面将空格删除,但这是数组嘛,删一个代表会有大量的数据移动,首先这样就是不好的,其次也没写出来(写了下就不想用这个方法了)
2.又打算在Map集合里用remove方法删除,但是自己始终遍历不出空格,用了\t," ",还有ascall码都没遍历出来
3.在从控制台获取数据的时候,只能用nextLine而不能用next,因为对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符next() 不能得到带有空格的字符串。
4.对Map中value值得更新,遍历Map集合,正则表达式等知识点都非常模糊。
5.如果直接遍历Map集合时,它的输出顺序是字典顺序,就与此题不符了,所以网上部分大神还用到了ArrayList集合,但是本篇博客参考的代码利用原字符串数组巧妙的规避了这个问题。

3.思路

然后看了刚才那位大神写的题解之后,发现贼厉害。他最开始是没有用split方法,先用字符串的replace方法,把所有的,.全部替换成空格,再用split方法,传入正则表达式“\s+”,+就表示多个空格,此时刚开始直接split之后的多余空格困扰就解决了。

4.代码

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class TongJi {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		solution(s);
	}
	public static void solution(String s) {
		Map<String, Integer> m = new HashMap<String, Integer>();
		s = s.toUpperCase();// 全部转换成大写字母,便于符合“单词有大小写之分,但统计时忽略大小写”的条件,也可方便最后输出,记得还要重新赋值给s,不然白干,主要还是不太了解这个API
		// String[] ss = s.split("[\\s,\\.,\\,]");// 此处需要用到正则表达式,空格,逗号,句号
		// 如何用Map遍历输出,
		// Integer count = m.get(ss[i]);是之前在韩顺平老师哈夫曼编码的时候学的,如何存储。
//但此处如果直接用HashMap输出,它是按照字典的顺序输出的,所以可以用ArrayList集合
		s = s.replace(".", "");
		s = s.replace(",", "");
		String[] ss = s.split("\\s+");// "+"号表示一个或多个空格
		for (int i = 0; i < ss.length; ++i) {
			if (ss[i] != null) {
				Integer count = m.get(ss[i]);
				if (count == null) {// 此时说明Map还没有这个字符数据
					m.put(ss[i], 1);// 第一次
				} else {
					m.put(ss[i], count + 1);
				}
			}
		}
		//遍历数组,找出最长的单词长度
		int maxLength = ss[0].length();//保存第一个单词的长度

		for (int i = 1; i < ss.length; i++) {
			
				if(ss[i].length() > maxLength) {
					maxLength = ss[i].length();
				}//通过循环找到最长的
		}
		// 遍历Map集合,但是要经过特殊处理
		//1.遍历s数组
		for (int i = 0; i < ss.length; ++i) {
			int record = 0;
			int space = 0;// space清零
			for(Map.Entry<String, Integer> entry : m.entrySet()) {
				if (entry.getKey() == ss[i] && entry.getValue() != 0) {
					record = entry.getValue();
					// 打印单词前面的空格
					space = maxLength - ss[i].length();
					for (int j = 0; j < space; ++j) {
						System.out.print(" ");
					}
					System.out.print(ss[i]);
					// 打印:
					System.out.print(":");
					// 打印**
					for (int j = 0; j < record; ++j) {
						System.out.print("*");
					}
					// 打印次数record
					System.out.print(record);
					// 将已经输出过的字符的value值置为0
					m.put(ss[i], 0);
					// 换行
					System.out.println();
				}
			}
		}
	}
}

5.学习心得:
刚开始看别的答案时,用到了输入流,ArrayList集合,还有很多更模糊的知识点。都看不大懂,这篇答案能很好的理解。一会儿再去继续理解消化别的答案。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值