您的位置:首页 > 编程语言 > Java开发

2.java笔记之多组输入,去重,排序(华为)

lzh_hahaha 2020-04-23 11:27 92 查看 https://blog.csdn.net/lzh_haha

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作(同一个测试用例里可能会有多组数据,希望大家能正确处理)。

Input Param

n : 输入随机数的个数

inputArray : n个随机整数组成的数组

Return Value

OutputArray : 输出处理后的随机整数

注:测试用例保证输入参数的正确性,答题者无需验证。测试用例不止一组。

样例输入解释:
样例有两组测试
第一组是3个数字,分别是:2,2,1。
第二组是11个数字,分别是:10,20,40,32,67,40,20,89,300,400,15。

输入描述:
输入多行,先输入随机整数的个数,再输入相应个数的整数

输出描述:
返回多行,处理后的结果

示例1
输入
3
2
2
1
11
10
20
40
32
67
40
20
89
300
400
15
输出
1
2
10
15
20
32
40
67
89
300
400

我的解:
import java.util.Scanner;
import java.util.Collections;
import java.util.ArrayList;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
ArrayList<Integer> al=new ArrayList<Integer>();
int n=sc.nextInt();
for(int i=0;i<n;i++)
al.add(sc.nextInt());
Collections.sort(al);
for(int i=0;i<al.size()-1;){
if(al.get(i)==al.get(i+1))al.remove(i+1);
else i++;
}
for(int i=0;i<al.size();i++)
System.out.println(al.get(i));
}
}
}

我的问题:

  1. 依据测试示例,我觉得这个题目的意思是要我们输入多组数据然后把这些数据合起来放入一个数组,排序,然后删除重复的,一次性全输出。卡了一个下午,问了别人才知道是各组数据分别排序去重,再每组输出一次。

  2. List、Set、Map的区别:

    List:是一个继承于Collection的接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
    Set:是一个继承于Collection的接口,Set是一种不包括重复元素的Collection。它维持它自己的内部排序,所以随机访问没有任何意义。与List一样,它同样运行null的存在但是仅有一个。由于Set接口的特殊性,所有传入Set集合中的元素都必须不同,关于API方面。Set的API和Collection完全一样。实现了Set接口的集合有:HashSet、TreeSet、LinkedHashSet、EnumSet。
    TreeSet是二叉树实现的,基于TreeMap,生成一个总是处于排序状态的set,内部以TreeMap来实现,不允许放入null值。它是使用元素的自然顺序对元素进行排序,或者根据创建Set时提供的 Comparator 进行排序,具体取决于使用的构造方法。(所以这题我做复杂了。。。见一号大佬解法)
    Map:与List、Set接口不同,它是由一系列键值对组成的集合,提供了key到Value的映射。在Map中它保证了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它不能存在相同的key值,当然value值可以相同。实现map的集合有:HashMap、HashTable、TreeMap、WeakHashMap。
    总结:
    ①、List、Set都是继承自Collection接口,Map则不是。

    ②、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)

    ③、Set和List对比:

    Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

    List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

    ④、Map适合储存键值对的数据。

    ⑤、线程安全集合类与非线程安全集合类 :

    LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
    HashMap是非线程安全的,HashTable是线程安全的;
    StringBuilder是非线程安全的,StringBuffer是线程安全的。

    详见链接: https://www.cnblogs.com/jxxblogs/p/11561629.html.
    另外:关于list与set的有序无序不是指内容值大小。
    按元素存取顺序来说,List是有序的,Set是无序的。(即list存储位置连在一块,set随意存储)按照元素和元素之间的关系来说,List是无序的,TreeSet是有序的(tree的性质)。而HashSet怎么说都是无序的。
    详见链接: List有序,Set无序,真的是这样嘛?.

  3. 泛型编程:泛型,即“参数化类型”。在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
    泛型类:泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map。注意掌握泛型类的基本写法。可以不传入泛型类型实参。泛型的类型参数只能是类类型,不能是简单类型。不能对确切的泛型类型使用instanceof操作。
    泛型接口:泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中。
    泛型方法:在java中,泛型类的定义非常简单,但是泛型方法就比较复杂了。泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。

public class GenericTest {
//这个类是个泛型类
public class Generic<T>{
private T key;

public Generic(T key) {
this.key = key;
}

//我想说的其实是这个,虽然在方法中使用了泛型,但是这并不是一个泛型方法。
//这只是类中一个普通的成员方法,只不过他的返回值是在声明泛型类已经声明过的泛型。
//所以在这个方法中才可以继续使用 T 这个泛型。
public T getKey(){
return key;
}

/**
* 这个方法显然是有问题的,在编译器会给我们提示这样的错误信息"cannot reslove symbol E"
* 因为在类的声明中并未声明泛型E,所以在使用E做形参和返回值类型时,编译器会无法识别。
public E setKey(E key){
this.key = keu
}
*/
}

/**
* 这才是一个真正的泛型方法。
* 首先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且声明了一个泛型T
* 这个T可以出现在这个泛型方法的任意位置.
* 泛型的数量也可以为任意多个
*    如:public <T,K> K showKeyName(Generic<T> container){
*        ...
*        }
*/
public <T> T showKeyName(Generic<T> container){
System.out.println("container key :" + container.getKey());
//当然这个例子举的不太合适,只是为了说明泛型方法的特性。
T test = container.getKey();
return test;
}

//这也不是一个泛型方法,这就是一个普通的方法,只是使用了Generic<Number>这个泛型类做形参而已。
public void showKeyValue1(Generic<Number> obj){
Log.d("泛型测试","key value is " + obj.getKey());
}

//这也不是一个泛型方法,这也是一个普通的方法,只不过使用了泛型通配符?
//同时这也印证了泛型通配符章节所描述的,?是一种类型实参,可以看做为Number等所有类的父类
public void showKeyValue2(Generic<?> obj){
Log.d("泛型测试","key value is " + obj.getKey());
}

/**
* 这个方法是有问题的,编译器会为我们提示错误信息:"UnKnown class 'E' "
* 虽然我们声明了<T>,也表明了这是一个可以处理泛型的类型的泛型方法。
* 但是只声明了泛型类型T,并未声明泛型类型E,因此编译器并不知道该如何处理E这个类型。
public <T> T showKeyName(Generic<E> container){
...
}
*/

/**
* 这个方法也是有问题的,编译器会为我们提示错误信息:"UnKnown class 'T' "
* 对于编译器来说T这个类型并未项目中声明过,因此编译也不知道该如何编译这个类。
* 所以这也不是一个正确的泛型方法声明。
public void showkey(T genericObj){

}
*/

public static void main(String[] args) {

}
}

泛型通配符:类型通配符一般是使用?代替具体的类型实参,注意了,此处’?’是类型实参,而不是类型形参 。重要说三遍!此处’?’是类型实参,而不是类型形参 ! 此处’?’是类型实参,而不是类型形参 !再直白点的意思就是,此处的?和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类。是一种真实的类型。

详见链接: java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一.
4. java的数据类型:
链接: link.

Java不仅支持上述8种基本数据类型,还为这8种基本数据类型提供了对应的包装类,通过这些包装类,我们就可以将上述基本数据类型当做Java中的类对象来处理了。值得说明的是,Java程序中可以直接操作基本数据类型,但是某些情况下需要将它们看成对象来处理,这些情况下就需要借助于Java API中基本数据类型对应的包装类来处理了。
链接: link
5. Collections.sort(al);//针对一个ArrayList内部的数据排序,需要导入Collections包。
6. 掌握ArrayList类的一些常用方法,如size(),get(),remove(),add()和上面说的排序。
详见链接: https://blog.csdn.net/weixin_43457668/article/details/98850712.

一号大佬的解:
import java.util.Scanner;
import java.util.TreeSet;

public class Main
{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){

TreeSet<Integer> set=new TreeSet<Integer>();
int n=sc.nextInt();
if(n>0){
for(int i=0;i<n;i++){
set.add(sc.nextInt());
}
}
for(Integer i:set){
System.out.println(i);
}
}
}
}
二号大佬的解:(Python)
while True:
try:

a,res=int(input()),set()
for i in range(a):res.add(int(input()))
for i in sorted(res):print(i)

except:
break

链接: 明明的随机数.

  • 点赞
  • 收藏
  • 分享
  • 文章举报
紫柳 发布了4 篇原创文章 · 获赞 1 · 访问量 184 私信 关注
标签: 
相关文章推荐