数据结构与算法笔记(一)


常数操作(固定时间):如加减乘除运算,位运算,赋值运算,寻址操作(数组寻址)。

非常数操作(不是固定时间):如单链表(linkedList),没办法算偏移量。(在链表中使用for(){list.get[i]} -> 这个就是O(N^2) )。

评估算法优劣的核心指标是什么?

1)时间复杂度

2)额外空间复杂度

3)常数项时间(细节决定)

复杂度

时间复杂度:把算法流程分解成常数时间的操作,

选择排序

1)

①N个数看一遍(N次),找最小值(N -1 次比较)。

②最小值放0位置(一次交换)。

2)

①N - 1个数看一遍(N - 1次),找最小值(N -2 次比较)。

②最小值放0位置(一次交换)。

3)

等等…

看 + 比较 = aN^2 + bN + c ;(a,b,c 都是常数)

复杂度只要最高阶项

冒泡排序

N 个数之间交换 O(1)

N - 1 个数之间交换

N - 2 个数之间交换

…………

等差数列,直接O(N^2)

插入排序

直到前面没数了或者左边数不比你大了停止

数组:[2,3,3,1,4,0]

1)0~0有序,这是肯定的

2)0~1有序,盯着1位置的数字,大就交换

3)0~2有序,盯着2看,向前比较,大就交换

4)…………

最好情况是 O(N) ,最坏是 O(N^2)。

取最差情况!!! 即时间复杂度也是O(N^2)

额外空间复杂度

看额外开辟空间是否是常数,若是数组,或是一张表,就是O(N),要是只用固定的几个变量,就是O(1)。看具体功能需求,要是要求拷贝数租,这个不算做额外空间。

算法流程的常数项

当两个都是O(N^2)算法,复杂度已经比较不出来了,继续PK,要拼常数相比较。

比如冒泡和插入,一定是插入更好!

放弃理论,直接生成随机数据进行分析。

加减乘除没有位运算快。

面试刷题中,什么是最优解?

先保证时间复杂度尽量低,再尽可能优化空间复杂度降低。不用关心常数项。

常用时间复杂度排名

O(1),O(logN),O(N),O(N*logN),O(n^2), O(N^3), O(N^k)

O(2^n) ,O(3^n), O(K^n) -> 这三个一般是递归用到。

算法和数据结构学习的大脉络

1)知道怎么算的算法

2)知道怎么试的算法

认识二分法

常见题型:

1)一个有序数组中找某个数是否存在?

如果用遍历是O(N)—最差情况。

二分是O(logN)

2)在一个有序数组中找到 >= 某个数最左侧的位置?返回索引

准备一个中间变量mid,mid = L + ((R - L ) / 2),这样写防止溢出,更安全。要是L + R,R 和 L 特别大的时候可能会溢出。

N / 2 == N >> 1 , mid = L + ((R - L ) >> 1),反之乘二左移一位。

while(L < R){
...
}
return sortedArr[L] == num;

while的条件是(L < R),即至少存在两个数才执行循环

最后再去验证最后一个数是否是要找的数。

3)在一个有序数组中找到 <= 某个数最右侧侧的位置?

4)局部最小值问题

问题:在一个无序数组中,值随意,任意两个相邻的数不相等

局部最小是指:[0] < [1],[N - 2] > [N - 1] ,[i - 1] > [i] < [i + 1] ,只要找到一个局部最小就行。

先看[0] < [1],要是符合直接返回 [0];

再看[N - 2] > [N - 1],要是符合直接返回 [N - 1];

否则,二分!!

找中点mid,mid要是符合[i - 1] > [i] < [i + 1],返回 [mid];不符合随便找一侧二分,在比较是否符合!!!

二分法不一定要有序,题目要求要是 能排他的话,类似这个情况既可以二分。

认识异位运算

异或运算:相同为零,不同为一。(可以理解为二进制的无进位相加。)

同或运算:相反。

1)0^N = N

2)N^N = 0;

3)异位运算满足交换律和结合律

题目一:

如何不用额外变量交换链两个数?

要是用临时变量要申请额外空间 int temp;

不用临时变量交换:

a = a ^ b;
b = a ^ b;
a = a ^ b;

题目二:

在数组中有一种数出现了奇数次,其他数出现了偶数次,找到并打印这个数字?

很简单!!!一行代码,全都异或!!!

int eor = 0;
for(int i = 0; i < arr.length; i++){
	eor ^= arr[i];
}
sout(eor);

题目三:

怎么把一个int类型的数,提取出二进制形式下最右边的 1 ?

a ^ (~a + 1) 或者 a ^ ( -a ) ;

得出 ~a + 1 == - a ;

题目四:

一个数组中有两种数出现了奇数次,其他数出现了偶数次,找到并打印这两种数?

思路:

假设这两个数字是a,b

1)引入一个变量 eor,eor 从头异或到尾,eor = a ^ b;因为a,b不相等,所以 eor 不等于零,不妨设 eor 第三位这个位置一定有个1,所以a和b第三位的二进制数字不相等。

2)所有的数字都可以分为两类,一种是第三位是1的,一种是不是1的,假设a在第三位是1的类别中,那么b一定在不是1的类别中。

3)再申请一个 eor’ 变量,让eor’去和第三位是1的类别中遍历异或,最后一定得到 a,另一个数就是 eor ^ eor’

题目五:

一个数组中有一种数出现了K次,其他数出现了M次,M >1 ,K < M,找到出现了K次的数?(要求:额外空间复杂度O(1),时间复杂度O(N))

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

面向丈母娘编程@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值