Comparable接口位于java.lang包下,Comparator位于java.util包下。
Comparable接口只提供了一个compareTo()方法,Comparator接口不仅提供了compara()方法,还提供了其他默认方法,如reversed()、thenComparing(),使我们可以按照更多的方式进行排序
如果要用Comparable接口,则必须实现这个接口,并重写comparaTo()方法;但是Comparator接口可以在类外部使用,通过将该接口的一个匿名类对象当做参数传递给Collections.sort()方法或者Arrays.sort()方法实现排序。Comparator体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。
9.1Comparable
Collections类中包含很多对实现Collection接口的容器各种操作的静态方法。当然, 其中最长用的莫过于排序了(Collections.sort(List l)。但是当List容器添加的元素对象是属于自己写的类时, 就可能出问题了。
总而言之, 如果你想1个类的对象支持比较(排序), 就必须实现Comparable接口。Comparable 接口内部只有1个要重写的关键的方法。就是 int compareTo(T o) 这个方法返回1个Int数值,
class Student implements Comparable{
private String name;
private int ranking;
public Student(String name, int ranking){
this.name = name;
this.ranking = ranking;
}
public String toString(){
return this.name + ":" + this.ranking;
}
public int compareTo(Object o){
Student s = (Student)(o);
return this.ranking - s.ranking;
}
}
9.2Comparator
// 1.对学生集合按年龄进行排序
Collections.sort(stus, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 升序
//return s1.getAge()-s2.getAge();
return s1.getAge().compareTo(s2.getAge());
// 降序
// return s2.getAge()-s1.getAge();
// return s2.getAge().compareTo(s1.getAge());
}
});
// 2.对学生集合按姓名首字母排序
Comparator comparator = Collator.getInstance(Locale.CHINA);
Collections.sort(stus, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return comparator.compare(s1.getName(), s2.getName());
}
});
https://www.cnblogs.com/jwthong/p/12762326.html
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
if (i == size - 1) { //将当前层的最后一个节点放入结果列表
res.add(node.val);
}
}
}
return res;
}
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
public int findDuplicate(int[] nums) {
int fast=0;
int slow=0;
while(true){
fast=nums[nums[fast]];
slow = nums[slow];
if(fast==slow)break;
}
int k=0;
while(true){
slow=nums[slow];
k=nums[k];
if(slow==k)break;
}
return slow;
}
static int cha(int target,int[] arr,int low,int high) {
if(target>arr[high]||target<arr[low]||low>high) {
return -1;
}
int m=(low+high)/2;
if(arr[m]>target) {
return cha(target,arr,low,m-1);
}else if(arr[m]<target){
return cha(target,arr,m+1,high);
}else {
return m;
}
}
7.看不懂
给定一个含有正整数和负整数的环形数组 nums。 如果某个索引中的数 k 为正数,则向前移动 k 个索引。相反,如果是负数 (-k),则向后移动 k 个索引。因为数组是环形的,所以可以假设最后一个元素的下一个元素是第一个元素,而第一个元素的前一个元素是最后一个元素。
确定 nums 中是否存在循环(或周期)。循环必须在相同的索引处开始和结束并且循环长度 > 1。此外,一个循环中的所有运动都必须沿着同一方向进行。换句话说,一个循环中不能同时包括向前的运动和向后的运动。
示例 1:
输入:[2,-1,1,2,2]
输出:true
解释:存在循环,按索引 0 -> 2 -> 3 -> 0 。循环长度为 3 。
public boolean circularArrayLoop(int[] nums) {
int len =nums.length;
for(int i=0;i<nums.length;i++) {
nums[i]=nums[i]%len;
}
for(int i=0;i<len;i++){
int f=nums[i];
if(f>=len)continue;
int j=i;
int flag = len+i;
int last = j;
while(nums[j]<len) {
if(f*nums[j]<0)break;
int next=(j+nums[j]+len)%len;
nums[j]=flag;
last = j;
j=next;
}
if(nums[j]==flag&&j!=last)return true;
}
return false;
}
class Solution {
/*
One step right and then always left
*/
public int successor(TreeNode root) {
root = root.right;
while (root.left != null) root = root.left;
return root.val;
}
/*
One step left and then always right
*/
public int predecessor(TreeNode root) {
root = root.left;
while (root.right != null) root = root.right;
return root.val;
}
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return null;
// delete from the right subtree
if (key > root.val) root.right = deleteNode(root.right, key);
// delete from the left subtree
else if (key < root.val) root.left = deleteNode(root.left, key);
// delete the current node
else {
// the node is a leaf
if (root.left == null && root.right == null) root = null;
// the node is not a leaf and has a right child
else if (root.right != null) {
root.val = successor(root);
root.right = deleteNode(root.right, root.val);
}
// the node is not a leaf, has no right child, and has a left child
else {
root.val = predecessor(root);
root.left = deleteNode(root.left, root.val);
}
}
return root;
}
}
static int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
}
static int lcm(int a,int b) {
return a*b/gcd(a,b);
}
题目:输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
解题:对于一个长度为 n 的字符串(假设字符互不重复),其排列共有n×(n−1)×(n−2)…×2×1 种方案。
class Solution {
List<String> res = new LinkedList<>();
char[] c;
public String[] permutation(String s) {
c = s.toCharArray();
dfs(0);
return res.toArray(new String[res.size()]);
}
void dfs(int x) {
if(x == c.length - 1) {//注意这里,只需要到len-1
res.add(String.valueOf(c)); // 添加排列方案
return;
}
HashSet<Character> set = new HashSet<>();//这里重点:记录重复的(很巧妙)
for(int i = x; i < c.length; i++) {
if(set.contains(c[i])) continue; // 重复,因此剪枝
set.add(c[i]);
swap(i, x); // 交换,将 c[i] 固定在第 x 位
dfs(x + 1); // 开启固定第 x + 1 位字符
swap(i, x); // 恢复交换
}
}
void swap(int a, int b) {
char tmp = c[a];
c[a] = c[b];
c[b] = tmp;
}
}