java算法题刷题常用工具(updating...)

Comparator

1.简介

顾名思义,这是一个比较器,用这个比较器可以自定义比较规则。自定义一个比较器的第一步是要实现java.util.Comparator接口,同时实现其中的int compare(Object o1, Object o2)方法:

public class CustomizedComparator implements Comparator<Object> {
    @Override
    public int compare(Object o1, Object o2) {
        return 0;
    }
}

2.关键方法:int compare()

这个方法就是实现自定义比较规则的地方。先来看下源码中它的定义:
在这里插入图片描述
可以看到,如果返回负数表示o1 < o2,返回0表示o1 = o2,返回正数表示o1 > o2。换种说法:如果我们在o1<o2的时候返回一个负数,那就是升序排列
下面我定义一个int[]数组的欧式距离比较器,比较其距离原点(0,0)的距离:

public class CustomizedComparator implements Comparator<int[]> {
    
    @Override
    public int compare(int[] o1, int[] o2) {
        int euDistance1 = 0, euDistance2 = 0;
        // 欧氏距离计算. 因为不影响结果,所以只取平方和,不进行开根号操作了。
        for (int i = 0; i < o1.length; i++) {
            euDistance1 += o1[i] * o1[i];
        }
        for (int i = 0; i < o2.length; i++) {
            euDistance2 += o2[i] * o2[i];
        }
        if (euDistance1 < euDistance2) {
            return -1;
        } else if (euDistance1 > euDistance2) {
            return 1;
        } else {
            return 0;
        }
//        return euDistance1 - euDistance2;
    }
}

3.常见使用场景

既然叫做比较器,那什么地方需要比较,什么地方就可能用得上Comparator。刷题的时候,最常见的就是排序了。使用到comparator的地方主要有两个:

Arrays.sort(T[],Comparator<? super T> c);
Collections.sort(List<T> list,Comparator<? super T> c);

结合上面的欧氏距离比较器,如果有一些以二维数组表示的点,按照其距离原点的欧氏距离排序:

public void test() {
        int[][] points = {{1,2},{0,1},{2,3},{0,0}};
        Arrays.sort(points, new CustomizedComparator());// 排序后points = {{0,0},{0,1},{1,2},{2,3}}
        // 默认是升序的,如果要降序排列,改变int compare(Object o1, Object o2)方法实现即可
    }

PriorityQueue

1.简介

顾名思义,这是一个队列。PriorityQueue——“优先级队列”,除了具有队列“先进先出”的典型特点之外,还常常和上面所讲的Comparator(或是java的Comparable接口)一起,实现排序功能:自动将进入PriorityQueue的元素进行有序排列(或者说插入新元素时,自动插入到合适的位置保证队列有序)。

2.常见使用场景

结合上面对PriorityQueue特点的介绍,很容易想到它的用武之地:求最大n个元素或者最小n个元素的问题。结合上面的CustomizedComparator来举例:

public void test() {
        int[][] points = {{1,2},{0,1},{2,3},{0,0}};
        PriorityQueue<int[]> queue = new PriorityQueue<>(new CustomizedComparator());
        for (int i = 0; i < points.length; i++) {
        	// 有序插入
            queue.add(points[i]);
        }
        // 输出距离原点最近的前k个点
        int k = 2;
        for (int i = 0; i < k; i++) {
            int[] point = queue.poll();  // 依次输出:{0,0} {0,1}
        }
    }

3.常用方法

PriorityQueue的常用方法和普通队列Queue是类似的,下面几个是刷题时的常用方法:
boolean add(E e):添加一个元素e
boolean offer(E e):添加一个元素e(和Queue不同,PriorityQueue中的add和offer完全一样)
E peek():获取队首元素(没有弹出)
E element():功能和peek()一样,区别在于方法失败时element()抛异常,peek()返回null
E poll():弹出队首元素
E remove():功能和poll()一样,区别在于方法失败时remove()抛异常,poll()返回null
boolean remove(Object o):删除队列中跟o相等的某一个元素(如果有多个相等,只删除一个)

位运算总结

1. x&(x-1)

表示将x的最后一个1变成0,例如4&(4-1)表示将100变成000、3&(3-1)表示将11变成10

String可以当成“栈”

有很多操作String的题目(例如leetcode1047)。别忘了StringBuffer和StringBuilder自带的方法,可以实现和栈相同的操作,但是比栈更省时间:
sb.charAt(end) -> stack.peek()
sb.append() -> stack.push() 或 stack.add()
sb.charAt(end) + sb.deleteCharAt(end) -> stack.pop()
其中sb是一个StringBuffer/StringBuilder实例

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值