星星之火-因题而记(一)排序去重

本文最后更新于:December 5, 2021 pm

积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里,不积小流无以成江海。齐骥一跃,不能十步,驽马十驾,功不在舍。面对悬崖峭壁,一百年也看不出一条裂缝来,但用斧凿,能进一寸进一寸,能进一尺进一尺,不断积累,飞跃必来,突破随之。

目录

题目

  1. 第三大的数
    给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。(样例自行查看)

题目链接

涉及知识点

1.排序方法

自己写排序算法就不说了,这里着重说的是JAVA中的sort方法。

1.1 Arrays类中的sort()

(1)Arrays类中的sort()使用的是“经过调优的快速排序法”;
(2)比如int[],double[],char[]等基数据类型的数组,Arrays类之只是提供了默认的升序排列,没有提供相应的降序排列方法。
(3)要对基础类型的数组进行降序排序,需要将这些数组转化为对应的封装类数组,如Integer[],Double[],Character[]等,对这些类数组进行排序。(其实还不如先进行升序排序,自己在转为将序)。

用法

1
2
3
4
5
int[] a={};
//全部排序
Arrays.sort(a);
//部分排序
Arrays.sort(a,1,5); //[1,5)

2.去重实现

2.1 预知识

Set(集合)

Set中的对象不按特定(HashCode)的方式排序,并且没有重复对象,Set主要有以下两个实现类:

  • HashSet: HashSet按照哈希算法来存取集合中的对象,存取速度比较快。当HashSet中的元素个数超过数组大小 * loadFactor(默认值为0.75)时,就会进行近似两倍扩容(newCapacity = (oldCapacity << 1) + 1)。
  • TreeSet :TreeSet实现了SortedSet接口,能够对集合中的对象进行排序

2.2 去重

2.2.1 使用List集合实现
1
2
3
4
5
6
7
8
int[] str = {5, 6, 6, 6, 8, 8, 7,4};
List<Integer> list = new ArrayList<Integer>();
for (int i=0; i<str.length; i++) {
if(!list.contains(str[i])) {
list.add(str[i]);
}
}
System.out.println("去除重复后的list集合"+list);
2.2.2 使用HashSet或TreeSet实现
1
2
3
4
Integer[] nums = { 5, 5, 6, 2, 6, 8, 8, 7, 11, 12, 12 };
// HashSet hset = new HashSet(Arrays.asList(nums));
TreeSet<Integer> hset = new TreeSet<Integer>(Arrays.asList(nums));
System.out.println(hset);

实现了排序去重。
Arrays.asList() 该方法是将数组转化成List集合的方法。用此方法得到的List的长度是不可改变的。
注意:我在网上搜此知识点的时候,很多都在说,使用这个方法有坑。在自己测试后发现确实有问题,但自己也发现有解决的办法。

使用方法:List<Integer> list = Arrays.asList(“a”,”b”,”c”);

这种使用方法是会和网上说的一样,会出现坑的。如:不支持add()、remove()、clear()等方法。

  • 此方法使用注意:

(1)该方法适用于对象型数据的数组(String、Integer…)

(2)该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)

(3)该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新

(4)不支持add()、remove()、clear()等方法

当你向这个List添加或删除一个元素时(例如 list.add(“d”);)程序就会抛出异常(java.lang.UnsupportedOperationException)。 这个原因是需要看看asList()方法是怎么实现的就行了。

1
2
3
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}

这个ArrayList不是java.util包下的,而是java.util.Arrays.ArrayList。可自行将鼠标移到上面进行查看。它是Arrays类自己定义的一个静态内部类,这个内部类没有实现add()、remove()方法,而是直接使用它的父类AbstractList的相应方法。而AbstractList中的add()和remove()是直接抛出java.lang.UnsupportedOperationException异常的!

总结一下:如果List只是用来遍历,可以用Arrays.asList()。如果List还要添加或删除元素,还是new一个java.util.ArrayList,然后一个一个的添加元素。

  • 自己发现的解决办法
1
2
Integer[] nums = { 5, 5, 6, 2, 6, 18, 8, 7, 11, 12, 12 };
List<Integer> list = new ArrayList<>(Arrays.asList(nums));

这样的list是可以正常使用方法的。

2.2.3 用List和Set实现
1
2
3
4
5
6
7
int[] nums = { 5, 6, 6, 6, 8, 8, 7 };
List<Integer> numList = new ArrayList<Integer>();
for (int i : nums)
numList.add(i);
Set<Integer> numSet = new HashSet<Integer>();
numSet.addAll(numList);
System.out.println(numSet);

实现了排序去重。

3.数组输出(扩充)

1
Arrays.stream(result).forEach(System.out::println); //result 为数组名

这是Java8中的特性。这里只是简单介绍一下,更多用法可自行搜索。
几种常见的获取数据源的方式:

  • Collection.stream(); 从集合获取流。
  • Collection.parallelStream(); 从集合获取并行流。
  • Arrays.stream(T array) or Stream.of(); 从数组获取流。
  • BufferedReader.lines(); 从输入流中获取流。
  • IntStream.of() ; 从静态方法中获取流。
  • Stream.generate(); 自己生成流

着重看Arrays.stream(T array) or Stream.of(); 从数组获取流。

其中,forEach(); 是 Stream 流中的一个重要方法,用于遍历 Stream 流,它支持传入一个标准的 Lambda 表达式。但是它的遍历不能通过 return/break 进行终止。同时它也是一个 terminal 操作,执行之后 Stream 流中的数据会被消费掉。

示例:

1
2
3
4
5
6
7
8
int[] nums = { 5, 8, 8, 6, 6, 8, 7 };
Arrays.stream(nums).forEach(it -> System.out.print(it+","));
System.out.println();
Arrays.stream(nums).forEach(System.out::print);

//输出
5,8,8,6,6,8,7,
5886687

4.对数组排序去重示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class sortArray {
public static void main(String[] args){
/**
思路:
1、使用 HashSet 进行去重
2、将 HashSet 变为 TreeSet
3、使用 TreeSet 进行排序
4、将 Set 变为 Integer 数组
5、将 Integer 数组变为 int 数组
*/
int[] candidates = {1,1,2,2,2,9,8,7,76,84,54,45}; // 初始化一个需要排序、去重的int数组
HashSet<Integer> hashSet = new HashSet<Integer>(); // 去重
for (int i = 0; i < candidates.length; i++){
hashSet.add(candidates[i]);
}
Set<Integer> set = new TreeSet(hashSet); // 利用TreeSet排序
Integer[] integers = set.toArray(new Integer[]{});

int[] result = new int[integers.length]; // 排序、去重后的结果数组
for (int i = 0; i < integers.length; i++){
result[i] = integers[i].intValue();
}

Arrays.stream(result).forEach(System.out::println); // 将结果数组输出
}
}