算法和数据结构 (哔哩哔哩-左神算法学习笔记-持续更新)

马士兵-左神算法-哔哩哔哩地址

1.复杂度、二分、对数器、异或运算

1.评估算法的优劣的核心指标

1.时间复杂度(流程决定)

分析过程,得出表达式,忽略掉系数、常数项、低阶项,只留下最高阶,最高阶系统去掉

例如:表达式-> ax^3+bx+c 时间复杂度就是:O(x^3)

为什么:当样本量达到一定的次数的时候,就会发现系数、低阶项、常数项都不重要了。

100万*N^2+200万*N +600万,当N->∞, 系数和常数算个毛线啊

2.空间复杂度(流程决定)

3.常数项时间(流程决定)

定义:如果一个操作的执行时间不以样本量转移,每次都是固定时间,就叫做常数操作。

常见的固定时间操作:

    常见的算术预算(加减乘除)
    常见的位运算(>>,>>> ,<<,|,&,^)
    赋值,比较,自增,自减操作
    数组寻址操作

>> 带符号右移   右移的时候,左边部位用符号位补位,如果正数就用0补位,负数1补位

>>> 不带符号右移  都用0补位

时间复杂度的意义

抹掉了好多东西,只剩下了一个最高阶项啊…那这个东西有什么意义呢?

当我们要处理的样本量很大很大时,我们会发现低阶项是什么不是最重要的;
每一项的系数是什么,不是最重要的。真正重要的就是最高阶项是什么。

这就是时间复杂度的意义,它是衡量算法流程的复杂程度的一种指标,
该指标只与数据量有关,与过程之外的优化无关。

如何确定算法流程的总操作数量和样本数量之间的表达式关系?

1.想象该算法流程所处理的数据状况,要按照最差情况来

2.把整个流程彻底拆分为一个个基本动作,保证每个动作都是常数时间的操作

3.把整个流程彻底拆分为一个个基本动作,保证每个动作都是常数时间的操作

选择排序流程:

arr[0~n-1] 范围上找到最小值,交换到0位置

arr[1~n-1] 范围上找到最小值,交换到1位置

arr[2~n-1] 范围上找到最小值,交换到2位置

arr[n-2~n-1] 范围上找到最小值,交换到n-2位置

选择排序图解

 选择排序时间复杂度:

 等差数列  1+2+3...+n-1,n*(n-1)/2   O(n^2)​

选择排序代码

 /**
     * 选择排序
     * @param arr
     */
    public static void SelectSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minindex = i;
            for (int j = i + 1; j < arr.length; j++) {
                minindex=arr[j]<arr[minindex]?j:minindex;
            }
            swap(arr, i, minindex);
        }

    }

    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

 冒泡排序流程:

1.在arr[0~n-1]:arr[0]和arr[1]谁大来到1位置,arr[1]和arr[2]谁大谁来到2位置...
arr[n-2]和arr[n-1],谁大来到n-1位置

2.在arr[0~n-2]:arr[0]和arr[1]谁大来到1位置,arr[1]和arr[2]谁大谁来到2位置...
arr[n-3]和arr[n-2],谁大来到n-2位置

3.在arr[0~n-3]:arr[0]和arr[1]谁大来到1位置,arr[1]和arr[2]谁大谁来到2位置...
arr[n-4]和arr[n-3],谁大来到n-3位置

....

最后在arr[0~1]范围上,重复上面操作,arr[0]和arr[1],谁大来到1位置

时间复杂度: 等差数列 O(N^2)

 冒泡排序代码

    /**
     * 冒泡排序
     *
     * @param arr
     */
    public static void BubbleSort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        for (int i = arr.length-1; i >=0; i--) {
            for (int j = 0; j < i; j++) {
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                }
            }

        }

    }

    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

插入排序流程

1.想让arr[0~0]上有序,只有一个数,当然有序

2.想让arr[0~1]上有血,所有从arr[1]开始往前看,如果arr[1]<arr[0],

就交换,否则什么也不做。

3.想让arr[0~i]上有序,所以从arr[i]往前看,arr[i]这个数不停向左移动,

一直移动到左边的数字不在比自己大,停止移动。

.....

n.最后一步,想让arr[1~n-1]上有序,arr[n-1]不同向左移动,一直移动到

左边的数字不在比自己大,停止移动

估算插入排序时间复杂度,会因为数据状况不同而不同!

如果从左到右,如果是已经升序的,每个数往前看,只看1次,这样是最好的情况O(N)

如果从左到右,如果是已经降序的,每个数往前看,要看i次,这样是最坏的情况O(N^2)

​额外空间复杂度

你要实现一个算法流程,在实现算法流程的过程中,你需要开辟一些空间来支持你的算法流程。

作为输入参数的空间,也不算额外空间。

作为输出结果的空间,也不算额外空间。

因为这些都是必要的和实现目标有关的,所有都不算。

但除此之外,你的流程如果还需要开辟空间才能让你的流程继续下去。这部分空间就是额外空间。

如果你的流程只需要开辟有限几个变量,额外空间复杂度就是O(1).​

 算法流程的常数项

时间复杂度,是忽略低阶项和所有常数系数,

同样时间复杂度的流程,在实际运行中就一样好吗?

当然不是,这个时候还要比拼常数时间,简称拼常数项。

 常数项比拼方式

放弃理论分析,直接生成随机大样本直接测。

为什么不去理论分析?

不是不能纯分析,而是没有必要。因为不同常数时间的操作,虽然都是固定时间,但还是有快慢之分。

如果纯理论分析,往往需要非常多的分析过程。都已经到了具体细节的程度,莫不如交给实验数据好了。

 

 

 

 

 

 

//R L 下标很大的时候 R+L 溢出
//mid= L +((R-L)>>1)  位运算就是比加减乘除快
// n * 2 + 1 ->  (n << 1 ) | 1
二分不一定要有序,只要你构建一种,可以排掉另外一边的逻辑,就可以二分。

 异或

异或相异为1,相同为零
异或就是无进位相加

 ​异或的性质​

1. N^0=N,N^N=0

2.满足交换律和结合率 理解:一批数里,不管顺序,最后结果一样

a  11111102

b  2545454

c  4741215

每个位上的,1或零的奇偶数量 是固定的  奇数个1就是该位结果就是1,偶数个1就是0

交换两个数

a=甲   b=乙

->  a=a^b

     b=a^b

    a=a^b 

注意  使用这种方法,不能用同一个值(不同的内存值),相同内存会变成0

 

提取最右侧的1,  n&(~n +1)

 

 2.链表

 

 java内存泄漏

如果一个超长生命函数,里面有个函数,有个list,里面其他函数调用这个list,往里面add对象,
但是后来没有释放添加的对象,导致后面多次调用,list的空间一直增减,这样内存就爆了。

 JVM释放对象

当一个对象,没有任何引用可以找到,jvm就会释放这个对象。
链表的头部,得让一个引用抓住,否则jvm就可能被释放,在
操作的过程中,就找不到这个链表了。

 

 数组实现栈

11

 

 

 

两个队列实现栈。

两个栈实现队列。

 图

宽度优先遍历->队列

深度优先遍历->栈

问:用栈实现宽度,队列实现深度,面试官憋坏水呢?

答:两个栈拼出一个队列,,,

 

 

任何递归,都可以改成迭代。

递归实际用的系统栈。

递归复杂度

a 子问题 调用了多少次

b 子问题的规模

d 剩下的时间复杂度

 

 HashMap增删改查 时间复杂度都是O(1)

TreeMap增删改查 时间复杂度都是O(logN)

AVL SB 红黑 时间复杂度(logN)只是常数的差别

AVL和SB是各自具备平衡性的搜索二叉树。

选择,插入、冒泡 o(N^2),在大量浪费比较行为

 

求小和,

求逆序对

 

 

 

 

 

111

3.

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值