知识点总结

本文探讨了时间复杂度的衡量方法,介绍了对数器在算法验证中的应用,重点分析了递归的效率提升,包括堆排序和稳定性排序的概念,以及如何通过比较器实现高效排序。最后,布隆过滤器在大数据过滤中的独特角色也被提及。
摘要由CSDN通过智能技术生成
  1. 时间复杂度
  2. 对数器
  3. 分析递归思想
  4. 递归时间复杂度
  5. 堆相关知识点
  6. 排序算法的穩定性概念、意义
  7. 比较器 意义和概念
  8. 布隆过滤器

1.时间复杂度

常数时间操作:
如果一个操作跟数据量大小没有关系,每次都是固定时间完成的操作,称之为常数时间操作。
如:数组寻址、判断值、比较大小、数组赋值…

时间复杂度为:
在一个算法中,在最坏情况下,用 常数操作数量 来作为评判指标。在常书操作数量的表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分表达式记为 f(N),则时间复杂度为O(f(N))

例子;
一个有序数组A长度为N,一个无序数组B长度为M,打印B中的所有不在A中的数

算法1:对于B中的每一个数都在A中通过遍历方式找一下
算法2:读于B中的每一个数,都通过二分的方式找一下
算法3:先把数组B排序,然后用外排的方式打印所有A中没出现的数

算法1:
B中的每一个数都要在A中比对一次,为O(M*N)
算法2:
B中的每一个数,先找到A中中间数大小进行比较,则每次可以排除一半的数,为O(M*logN)   【A数组中,最多比对logN次,2^x = N -> logN = x】
算法3:
先对B排序,为O(M*logM);外排为O(M+N)
总时间复杂度为:O(M*logM) + O(M+N)
这时候需要根据数据量大小M,N来判断

2.对数器

作用:
用来测试自己的算法是否正确;若不正确,可以找到代码错在哪里

使用:
1.有一个需要测试的方法
2.实现一个绝对正确,但是时间复杂度不好的方法
3.实现一个随机样本产生器
4.实现比对方法
5.把方法A和方法B比对很多次来验证方法A是否正确
6.如果有一个样本使得比对出错,打印样本分析是哪个方法出错
7.当样本数量很多时比对依然正确,则可以确定方法A正确

3.分析递归思想
递归即为:自己调用自己
底层逻辑:压栈
一个函数在调用子过程之前,会将当前所有信息放到栈里,信息完全保存;子过程返回之后,会利用这些信息还原现场

**由于
1.递归时,系统压栈是将所有信息(有用的没用的)全部压栈,当样本量大时,消耗内存很多,且有栈满的风险
2.所有递归函数都可以转换为迭代函数
所以,最好将递归函数改为迭代函数**

例子:

		//测试
        int arr[] = {9,8,3,0,2,1,5,7};
        int max = getMax(arr,0,arr.length-1);
        Log.d("jiang", String.valueOf(max));

	//递归得到最大值
    public static int getMax(int[] arr,int L,int R){
        if (L == R){
            return arr[L];
        }else{
            int mid = L + (R-L)/2;

            int maxLeft = getMax(arr,L,mid);
            int maxRight = getMax(arr,mid+1,R);

            return Math.max(maxLeft,maxRight);
        }
    }

时间复杂度:
O(N^d * logN)

4.递归时间复杂度:
master公式:T(N) = aT(N/b) + O(N^d)

N:样本量
a:子过程发生的次数
b:样本被分为几次研究
d:剩下的常数操作数量大小

在这里插入图片描述
5. 堆相关知识点
(1)堆为完全二叉树(满二叉树/从左向右依次补齐的二叉树)
(2)堆可以用数组的思想实现
堆的一个结点的左孩子为2i+1
堆的一个结点的右孩子为2i+2
堆的一个结点的父结点为(i-1)/2
其中对于根结点 他的父结点为(0-1)/2 = 0
(3)堆可以分为大根堆和小根堆
大根堆:对于任意一个子树,他的根结点都是最大值
小根堆:对于任意一个子树,他的根结点都是最小值

6. 排序算法的穩定性 以及 意义

概念:
	在一系列数据中,有多个重复值,排序后,原本在前面的元素还是在前面,并没有因为排序的原因,使得原本在前面的元素排到了后边。
意义:
	在业务上,比如excel表格既想按照各个学生按班级排序,又想按照学生成绩排序。那么,先点击班级排序,所有学生会按照班级排好序,但是学生成绩还是乱序。再点击成绩排序,期望的成果是,学生按照班级排序的同时,又能按照成绩排序。这时候就需要算法具有稳定性,可以将上一次排序的信息保留下来。

汇总:

  • 冒泡排序:可以稳定
  • 选择排序:可以稳定
  • 插入排序:可以稳定
  • 归并排序:可以稳定
  • 改进经典排序:做不到稳定
  • 随机排序:做不到稳定
  • 堆排序:做不到稳定

7.比较器
(1)意义:
如果在面试中,排序不是重点,排完序之后的操作才是重点,那么可以调用系统的函数快速进行排序,就可以不用浪费大量的时间在排序上

(2)概念:
调用系统的Arrays.sort()函数

如果是基础类型 						-> 会根据值得大小排序
如果是自己定义的数组类型     -> 会根对象的内存地址排序(没有意义)

所以想要排序自己定义的数组类型,要给Arrays.sort()函数传两个参数,一个是数组,一个是排序的方法

对象

public static class Student{
        public int id;
        public String name;
        public int age;

        public Student(int id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }

排序方法

public static class IdAscendingComparator implements Comparator<Student> {

        //告诉怎么比大小
        //如果返回负数 -> 第一个参数应该排在前面
        //如果返回整数 -> 第一个参数应该排在后面
        //入股返回0   -> 认为一样大


        @Override
        public int compare(Student student1, Student student2) {
            //按照id从小到大排序
            //小的数应该排在前面
//            if (student1.id < student2.id){
//                return -1;
//            }else if (student2.id < student1.id){
//                return 1;
//            }else {
//                return 0;
//            }

            //优化
            return student1.id - student2.id;
        }
    }

运行

        public static void main(String[] args) {
            Student student3 = new Student(3,"C",3);
            Student student2 = new Student(2,"B",20);
            Student student1 = new Student(1,"A",18);

            Student[] students = new Student[]{student3,student2,student1};
            for (Student student : students){
                System.out.println(student.toString());
            }


            Arrays.sort(students,new IdAscendingComparator());
            for (Student student : students){
                System.out.println(student.toString());
            }
        }
优先级队列就是 堆
!!!系统提供的非常方便的有序结构,都需要提供一个比较器让系统排序
//            PriorityQueue<Student> heap = new PriorityQueue<>(); 不给比较器就会按照内存地址排序 没有意义
            PriorityQueue<Student> heap = new PriorityQueue<>(new IdAscendingComparator());
            heap.add(student3);
            heap.add(student2);
            heap.add(student1);

            while (!heap.isEmpty()){
                Student student = heap.poll();
                System.out.println(student.toString());
            }

8.布隆过滤器

解决的问题:有100亿个URL黑名单,每个URL是64字节的,用户搜索时需要在黑名单
中进行排查

可以用hash表实现,但是空间复杂度很高

布隆过滤器是一种集合(bit类型的map,每个位置是0或者1)

布隆过滤器有很小的失误率
如果一个URL在黑名单中,一定不会出错
如果一个URL不在黑名单中,有可能被认为在黑名单中
        int[] arr = new int[1000];  //实际可以表示 1000 * 4字节 * 8比特 = 32000bit

        int index = 30000; //假设通过hashcode算出来的值

        int intIndex = index / 32;  //定位来自哪个整数(桶)

        int bitIndex = index % 32;  //定位这个整数(桶)哪个比特位

        //               来自哪个桶         1左移到bitIndex位置
        arr[intIndex] = (arr[intIndex] | (1 << bitIndex));  //

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值