华为机试-HJ3 明明的随机数
日常刷题记录,欢迎讨论交流。
牛客网题目链接:https://www.nowcoder.com/practice/3245215fffb84b7b81285493eae92ff0
描述
明明生成了N个1到500之间的随机整数。请你删去其中重复的数字,即相同的数字只保留一个,把其余相同的数去掉,然后再把这些数从小到大排序,按照排好的顺序输出。
输入描述:
输出描述:
输出多行,表示输入数据处理后的结果
示例1
3 2 2 1
1 2
输入解释: 第一个数字是3,也即这个小样例的N=3,说明用计算机生成了3个1到500之间的随机整数,接下来每行一个随机数字,共3行,也即这3个随机数字为: 2 2 1 所以样例的输出为: 1 2
方法一:
利用集合存储元素的特点(不含重复元素),将传入的随机数存到集合里面,重复的数据不会添加,这里使用HashSet(散列集,存放到集合里面的元素是无序的),然后使用迭代器遍历集合,把数据存放到一个 int 型数组里面,借助 Arrays 类的 sort() 方法对数组元素进行排序(按自然排序,从小到大),再输出结果。
import java.util.Scanner; import java.util.HashSet; import java.util.Iterator; import java.util.Arrays; //方法一 public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int num = Integer.parseInt(sc.nextLine()); // System.out.println(num); // HashSet<Integer> hs = new HashSet<>(); HashSet hs = new HashSet<>(); int temp = 0; int n = 0; while(sc.hasNext() && n <= num){ temp = Integer.parseInt(sc.nextLine()); hs.add(temp); n++; } int[] arr = new int[hs.size()];//根据集合实际大小创建数组 Iterator<Integer> iter = hs.iterator(); for(int i = 0; i < num && iter.hasNext(); i++){ arr[i] = iter.next().intValue(); } hs.clear(); Arrays.sort(arr); for(int j : arr){ System.out.println(j); } } }
方法二:
同样利用集合存储元素的特点(不含重复元素),这里使用TreeSet(树集,有序集合),特点是每次将一个元素添加到树中时,都会将其放置在正确的排序位置上。因此添加到集合里面的数据都是有序的,可以直接使用迭代器遍历集合输出结果。
import java.util.Scanner; import java.util.TreeSet; import java.util.Iterator; //方法二 public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int num = Integer.parseInt(sc.nextLine()); // System.out.println(num); TreeSet ts = new TreeSet<>(); int temp = 0; int n = 0; while(sc.hasNext() && n <= num){ temp = Integer.parseInt(sc.nextLine()); ts.add(temp); n++; } Iterator iter = ts.iterator(); for(int i = 0; i < ts.size(); i++){ System.out.println(iter.next()); } ts.clear(); } }
方法三:
以空间换时间的思路,根据输入随机数的数字范围(1≤val≤500)创建一个下标足以包含所有随机数的 int 型数组arr(数组大小为501,数组下标取值范围:0-500),每次输入的随机数 val 都当作数组的下标,将数组对应的元素 arr[val] 赋值为1(数组采用动态初始化的方式,只指定数组长度,由系统分配初始值,int 型数组的元素默认初始值为 0),由于重复的随机数都对应到数组的同一个元素,利用了这个特点实现去重。最后数组里面元素值为1的元素对应下标即是输入的随机数(已去重),遍历数组打印对应的下标即可。
import java.util.Scanner; //方法三 public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int num = Integer.parseInt(sc.nextLine()); // System.out.println(num); int[] arr = new int[501]; int n = 0; //使用两个变量来记录随机数的区间(目的是最后遍历数组的时候可以缩小范围) int minindex = 0; int maxindex = 0; while(sc.hasNext() && n <= num){ int index = Integer.parseInt(sc.nextLine()); arr[index] = 1; n++; minindex = Math.min(index,minindex); maxindex = Math.max(index,maxindex); } // System.out.println("minindex: "+minindex); // System.out.println("maxindex: "+maxindex); for(int i = minindex; i <= maxindex; i++){ if(arr[i] == 1){ System.out.println(i); } } } }
总结:
1.方法一需要另外排序,逻辑稍微复杂,优点是元素插入到集合的效率比较高,元素存储到数组之后如果后续需要查找和反向排序都方便一些。
2.方法二利用TreeSet简化了处理过程,元素插入到集合之后就是有序的,但TreeSet 将一个元素添加到树中要比添加到散列表中慢一些。
3.方法三利用数组有序的特点省去了排序操作,但如果随机数的取值范围很大,会导致很大的存储开销,通用性差一些。

浙公网安备 33010602011771号