Arrays类位于java.util 包中:
Arrays包含用于操作数组的各种方法,比如二分查找等等,但是今天介绍其中的sort方法,sort()方法用于对数组进行排序,但排序的情况有所不同:
1.Arrays.sort(int[] a)
上面是对int类型的数组a进行升序排序,比如一个数组送的元素是:[8,3,6,9,1,7],用上面的方法进行排序的结果是:[1,3,6,7,8,9].数组的类型可以是8种基本类型中的任意类型.
2.Arrays.sort(Object[] a)
这个方法还可以为引用类型的数组进行排序,比如对某个字符串数组进行排序.
3.Arrays.sort(int[] a,int fromIndex,int toIndex)
对int类型的数组,从下标为fromIndex,到下标为toIndex-1的元素进行升序排序,需要注意的是,结束的位置不是toIndex,而是toIndex-1.数组的类型可以是8种基本类型中的任何一种类型.
4.Arrays.sort(Object[] a,int fromIndex,int toIndex)
对引用类型的数组进行排序,从下标为fromIndex,到下标为toIndex-1的元素进行排序,比如对字符串数组的排序.
5.Arrays.sort(T[] a, Comparator<? super T> c)
根据指定的比较器引发的顺序对指定的对象数组进行排序, 数组中的所有元素必须通过指定的比较器相互比较 .也就是说,通过参数2的比较方法,实现对参数1数组的排序.
这个方法的使用,以力扣的第720道题为例:
720. 给出一个字符串数组 words 组成的一本英语词典。返回 words 中最长的一个单词,该单词是由 words 词典中其他单词逐步添加一个字母组成。
若其中有多个可行的答案,则返回答案中字典序最小的单词。若无答案,则返回空字符串。
示例 1:
输入:words = ["w","wo","wor","worl", "world"]
输出:"world"
解释: 单词"world"可由"w", "wo", "wor", 和 "worl"逐步添加一个字母组成。
示例 2:
输入:words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
输出:"apple"
解释:"apply" 和 "apple" 都能由词典中的单词组成。但是 "apple" 的字典序小于 "apply"
提示:
1 <= words.length <= 1000
1 <= words[i].length <= 30
所有输入的字符串 words[i] 都只包含小写字母。
本题的核心代码:
import java.util.*;
class Solution {
public String longestWord(String[] words) {
Arrays.sort(words, (a, b) -> {
if (a.length() != b.length()) {
return a.length() - b.length();
} else {
return b.compareTo(a); //compareTo(String str);按字典顺序比较两个字符串
}
//lambda函数
});
String longest = ""; //最后要返回的满足条件的字符串
Set<String> candidates = new HashSet<String>(); //不允许重复,无序
candidates.add(""); //添加了一个null,现在那就是一个空串了,我把它理解为初始化这个HashSet()
int n = words.length; //数组的长度
for (int i = 0; i < n; i++) {
String word = words[i]; //用word记录当前的字符串
if (candidates.contains(word.substring(0, word.length() - 1))) {
//subString()用来截取字符串
candidates.add(word); //
longest = word;
}
}
return longest;
}
}
思路和算法
定义「符合要求的单词」如下:
空字符串是符合要求的单词;
在符合要求的单词的末尾添加一个字母,得到的新单词是符合要求的单词。
这道题要求返回数组 \textit{words}words 中的最长的符合要求的单词,如果有多个最长的符合要求的单词则返回其中字典序最小的单词。以下将返回值称为「答案」。
为了方便处理,需要将数组 \textit{words}words 排序,排序的规则是首先按照单词的长度升序排序,如果单词的长度相同则按照字典序降序排序。排序之后,可以确保当遍历到每个单词时,比该单词短的全部单词都已经遍历过,且每次遇到符合要求的单词一定是最长且字典序最小的单词,可以直接更新答案。
将答案初始化为空字符串。使用哈希集合存储所有符合要求的单词,初始时将空字符串加入哈希集合。遍历数组 \textit{words}words,对于每个单词,判断当前单词去掉最后一个字母之后的前缀是否在哈希集合中,如果该前缀在哈希集合中则当前单词是符合要求的单词,将当前单词加入哈希集合,并将答案更新为当前单词。
遍历结束之后,返回答案。
上面的算法和思路是复制,力扣的官方解题法,我们重点看下面以部分:
Arrays.sort(words, (a, b) -> {
if (a.length() != b.length()) {
return a.length() - b.length();
} else {
return b.compareTo(a);
}
});
//排序的规则是首先按照单词的长度升序排序,如果单词的长度相同则按照字典序降序排序。
用到了Arrays.sort(T[] a, Comparator<? super T> c),前面的数组是一个字符串数组,后面先理解为一种排序规则,根据后面的排序规则对前面的数组排序.
其实Arrays.aort()里的第二个超长参数,它是一个lambda表达式,只用下面这一段,保证你可以理解lambda表达式:
可以简单的理解为:定义了一个接口,接口的名字叫做:MyCompare(自己随意起),这个接口继承了Comparator接口,在这个接口中定义了一个用于比较的方法myCompare (参数1,参数2),这个方法只有定义,没有实现,并且这个接口只能定义这一个唯一的方法,不能再定义其他方法,那这个我自己定义的方法是在哪里实现的呢?就是在上面的Arrays.sort()中的第二个参数的位置实现的,(a,b),就是我定义的参数1和参数2,{}当中的部分,相当于我这个方法的方法体.可以把这个lambda表达式理解为实现了前面接口中的方法,只不过,方法名,返回值类型以及参数类型省略了,为啥能省略??因为接口里面就一个方法,根本就不会产生歧义,可以放心大胆的省略.
其中的compareTo()方法是String类中的方法,用于按字典顺序排列两个字符串(说实话欧文也不会啥叫字典顺序,但是使用这个方法的结果就是按字典顺序比较的).返回值是int类型,通过这个Arrays.sort(T[] a, Comparator<? super T> c)方法实现了按字典序排序.