1.bitOperation(位运算)
无符号右移>>>
b>>1用符号位补
b>>>1符号位用0补
2 Demo1 位运算
3 Demo2 求n的阶乘
4 Demo3 如果一个数组arr有会非常高频词的查询数组中索引l~r上的累加和,问如何实现这个需求
4.1 答案一
设置一个数组这是二位数组,将每个索引的累加和提前插入此二维数组中,每次返回即可这种做法每次大概会浪费(n的平方除以2)的空间
4.2 答案二
设置一个前缀和数组sum,数组中0~n每个元素分别为arr数组上0~n的累加和,这样如果计算arr上l~r的累加和如果l为0那么直接返回sum中R索引下标,如果l不为0,那么直接返回sum(r)-sum(l-1)的值
4.3方案优缺点
总体来说答案二比答案一要好很多,但是在查询频率很高很高的情况,左程云推荐答案一还是好点,理由是不用进行一个减的操作
5 Demo4测试math.rondom()函数,
6.Demo5某个f函数返回的是12345等概率返回,让他等概率返回1234567,
先等概率返回0-1,在等概率返回0-7等概率返回0-6,在等概率返回1-7,推广到a~b随机到c~d随机
a~b随机假设是f1函数等概率返回8-19之间的数字,求如何使用这个函数等概率21-36返回之间的数字
1,将f1函数返回8-19变为返回0,1等概率,将8-20中一共13个数字去掉一个偶数,然后对2取余返回,就得到之后0,1的等概率返回函数
2.将0,1返回变成0-36随即返回,2的5次方|2的2就是36,那么就返回f2()<<5+f2<<2
3.dowhile循环 ,剔除掉<21的数字就重新进入循环,
7.Demo6f函数p概率返回0,(1-p)概率返回1如何让他变为等概率返回0,1
1,有四种情况00,01,10,11,其中01,和10的概率为p(1-p)相等,所以返回的时候剔除掉非01的情况(两次异或为1)重新循环抽取即可,
8.Demo7二分查找在有序数组中,寻找一个数num在不在数组中
1设置L为0,R为数组长度减一,p=(l+r)/2,如果p点的数小于num说明要寻找的数在数组的右侧此时l=p+1,如果大于num说明要寻找的数在p的左侧,r=p-1,如果刚好相等返回true
9.Demo8二分查找在有序数组中,寻找一个数num在在数组中的最左位置,该数一定要存在,如果这个数不存在,左程云的算法有问题
10.Demo9局部最小值问题.在一个无序并且数组相邻值不同的数组中找到局部最小值,局部最小值定义1232这个例子中的索引0和索引3代表的都是局部最小值,注意32323数组中的边界值问题
使用二分法,如果我的mid小于左边的数并且小于右边的数,那我直接返回mid,如果mid大于左边的数,那左边的数全部砍掉,l=mid+1重新循环,如果mid小大于右边的数那右边全部砍掉r=mid-1重新进行循环,这里有个点是32323数组会导致越界需要考虑这种情况
11.Demo10单链表,和反转链表
12.Demo11双链表,和反转链表
13.Demo13链表实现队列和栈
14.Demo14k个节点内的组内逆序调整
LeetCode35题 reverse nodes in K-Group
1.先确定整个链表的反转后整个链表的head,即第k个节点
2.获取k数字内的start节点和end节点(边界当在k的范围内但是start节点为空时说明边界条件最后一组不够k个不调整)
3.反转start-end节点内的所有节点,然后将start节点的指针指向end.next节点
4.周而复始以上操作然后进行2.3当获取第二步中的end节点为空,或者lastend(比如k=3链表为123456,这块lastend指的是6)
15.Demo15 俩个链表相加
1.分别为三种情况
(1)长短链表都有值的情况
(2)长链表有值
(3)长短链表都没有值
考虑最后如果进位还有值的情况,要记住长链表的最后一个节点并给长链表加上一个节点1用来进位
16.Demo16 俩个有序链表的合并合并后的链表仍然有序
1.选出合并后链表的头结点
2.比较两个链表
17.Demo17,使用位图bitmap存储知道最大值的数字(位图非常省空间)
18.Demo18位运算实现加减乘除
^运算就是无进位相加
加:a+b=a^b+a&b<<1循环到进位b为0为止
减:a-b=a+(-b)=add(a,~b)
乘:a*b=用b的每一个二进制为去&a,每&一次,b左移一次,将所有的结果加起来就是乘的结果
19.Demo19合并k个有序链表复杂度n*log(m)
1.将k个有序链表加入到priorityqueue里面
2.每弹出一个节点将节点的下一个节点加入到priorityqueue
3.界限1是当一个链表的下一个节点是null的时候不用再添加到queue里面
4.界限二是queue里面没有元素的时候整个程序退出
20.Demo20什么叫做二叉树
遍历:
先序:头左右
中序:左头右
后续左右头
递归序
21:Demo21判断两个二叉树是否相等
递归运算,判断左右树相同节点是不是都为空,判断都不为空,在判断值是否相同
22:Demo22判断二叉树是否是镜面树
判断左右节点是否相等,可以升级为判断两个二叉树,1的左是否和2的右相等
23:Demo23返回一棵树的最大深度
24:Demo24用先序和中序数组建树
25:Demo25看一棵树是不是平衡二叉树
平衡搜索二叉树概念:
整颗树的左右高度不超过2
26:Demo26看一棵树是不是搜索二叉树
什么是搜索二叉树,某个二叉树它所有节点的左树值都比他自身值大,所有节点的右树值都比他自身小
1.中序遍历后如果是有序(小到大)就说明是搜索二叉树
2.用递归
27:Demo27看一棵树是不是平衡搜索二叉树
既是平衡二叉树又是搜索二叉树就是平衡搜索二叉树
28,Demo28能否组成路径和
29,Demo29返回能组成路径和的节点集合
30,Demo30归并排序(递归和非递归)
思想:{5,9,1,3,8,7,9,3,5,4,6, 1, 3}
0 1 2 3 4 5 6 7 8 9 10 11 12
先用step步长为1的数组去排序,完成后数组保持不变{5,9,1,3,8,7,9,3,5,4,6,1}
再用step步长为2的数组去排序
1.分配步长数组
a1,{5,9};a2,{1,3};b1,{8,7};b2,{9,3};c1,{5,4};c2,{6,1};d1,{3};
2.在单个数组内有序
a1,{5,9};a2,{1,3};b1,{7,8};b2,{3,9};c1,{4,5};c2,{1,6};d1,{3};
3.将左右数组合并,合并规则是按照谁小谁先放
a,{1,3,5,9};b,{3,7,8,9};c,{1,4,5,6};d1,{3};(这是拆分供阅读方便实际上数组是这样{1,3,5,9,3,7,8,9,1,4,5,6,3})
再用step步长为4的数组去排序
...(此处省略)
什么时候排序完成?
当步长大于数组最大长度除以2的时候终止
递归的base case是当数组递归到长度只有1的时候
31,Demo31快速排序(递归和非递归)
思想:{5,9,1,3,8,7,9,3,5,4,6, 1, 3}
0 1 2 3 4 5 6 7 8 9 10 11 12
快排以数组当中的最后一位数字为基准(p)将数组变为比p小的区域,和p相等的区域,比p大的区域
partation
p等于3指针为index
l区域大的右刚开始等于-1,r区域边界为包含3的区域就是p-1,设l=-1,r=p-1
index指到5
用5比较3,5大于3,所以用0位置和r位置的前一个位置进行交换也就是r-1,大于区域扩容,r--,index不动,交换后位置{1,9,1,3,8,7,9,3,5,4,6, 5, 3}
用1比较3,1小于于3,所以用0位置和0位置进行交换也就是l+1,小于区域扩容,l++,index++交换后位置{1,9,1,3,8,7,9,3,5,4,6, 5, 3}
用9比较3,9大于3,所以用1位置和r位置的前一个位置进行交换也就是r-1,大于区域扩容,r--,index不动,交换后位置{1,6,1,3,8,7,9,3,5,4,9, 5, 3}
..
交换完成后将会排列为数组变为比p小的区域,和p相等的区域,比p大的区域
在数组的小于区域和大于区域重复这个操作(递归)
直到数组中的L>=R是排序终止
32,Demo32选择排序
思想:{5,9,1,3,8,7,9,3,5,4,6, 1, 3}
0 1 2 3 4 5 6 7 8 9 10 11 12
1.从0-12的位置找到最小值将它放在把他和0位置交换
2.从1-12的位置找到最小值将它放在把他和1位置交换
3.从2-12的位置找到最小值将它放在把他和2位置交换
...
33,Demo33插入排序
思想:{5,9,1,3,8,7,9,3,5,4,6, 1, 3}
0 1 2 3 4 5 6 7 8 9 10 11 12
1.0-0范围上有序
2.0-1范围上有序,看1是不是小于0位置的数如果小于0位置的数交换,如果大于就什么也不干
3.0-2范围上有序,看2是不是小于1位置的数如果小于1位置的数交换,再看2是不是小于0位置的数如果小于0位置的数交换,如果大于就什么也不干
...
34,Demo34冒泡排序
思想:{5,9,1,3,8,7,9,3,5,4,6, 1, 3}
0 1 2 3 4 5 6 7 8 9 10 11 12
1.0,1位置比较大小谁大谁后移(交换位置),1,2,位置比较大小谁大谁后移...11 ,12比较大小谁大谁后移(此步完成,最后一个位置的数是当前数组最大的数)
2.0,1位置比较大小谁大谁后移(交换位置),1,2,位置比较大小谁大谁后移...10 ,11比较大小谁大谁后移(此步完成,数组倒数第二个位置的数是当前数组第二大的数)
....
35,提取一个数二进制中最右的1
int a
result=a & (~a+1) =a & (-a)
36,有一种数,在数组当中出现奇数次,其他种数出现偶数次,请找出出现奇数次的数,
思想
异或运算:符合交换律即a^b=b^a
0^a=a
a^a=0
所以此算法核心思想就是设置一个变量为result用result去异或数组中的每一个数
37,有两种数,在数组当中出现奇数次,其他种数出现偶数次,请找出出现奇数次的数,
思想:
设出现的两种数为x,y,设置额外变量为result=0
用result将数组中所有数异或一遍,得到结果x^y,因为 x!=y 所以此结果!=0
所以x^y的二进制结果中一定有一位上为1,而异或的结果某一位上为1即说明x上该位与y该位不同,
设最右位置的数为z
找出X^y上最右位置为1的位:设置eor=X^y
则z=eor&(~eor+1)=eor&(-eor)
找出z之后,那么可以用z将原数组分为两种一种是&上z为0的,一种是&上z不为0的,并且x,y肯定不是同一种
那么我们把数组中&上z==0的取出来全部异或一遍就会得到x值
将x^eor=x^y^x=y得到y值
38,有一种数出现k次,其他种数出现m次,求出现k次的数(k<m,m>1)
思想
已知此数组arr,和k,m
开辟一个长度为32的数组tmp,此数组用来存储arr中元素的所有二进制,有相同位置的进行++操作,比如有个数字为7,存到数组中为0000...00111(32位)
将此数存到tmp中
将所有数字存储完毕
将tmp中所有元素去%m,如果为0,说明出现k次的元素没有出现在此位置,如果不为0,说明出现k次的元素出现在此位置
将所有的位置找出来拼凑出二进制就是要找的k次的数字
39,链表反转,(单链表和双链表)
单链表反转
1->2->3->4->5->null
设置pre=null
next=null
head=1(刚开始就是1所在的节点)
1. next=head.next; 保存原始链表中head的下一个节点(如果不保存这个节点在最后一步head.next只会找到pre节点)
head.next=pre; 将head的下一个节点指向pre节点
pre=head; pre节点向下移动
head=next; head节点向下移动
双链表反转
null<-1->2->3->4->5->null
<- <- <- <-
设置pre=null
next=null
head=1(刚开始就是1所在的节点)
1. next=head.next; 保存原始链表中head的下一个节点(如果不保存这个节点在最后一步head.next只会找到pre节点)
head.next=pre; 将head的下一个节点指向pre节点
head.last=next
pre=head; pre节点向下移动
head=next; head节点向下移动
40,用链表和数组实现栈和队列
41,实现一个特殊的栈,在基本栈功能的基础上,再实现返回栈中最小元素的功能
1.pop,push,getMin操作的时间复杂度都是O(1)
2.可以使用现成的栈结构
思想
1.设置栈中有两个栈,一个叫做data栈,用来存储正常的栈值,另一个叫做min栈用来存储栈中的最小值
入栈
当data中没有值的时候,push 1入栈 data和min都正常入栈 data[1] min[1]
当data中有值的时候,push 8 入栈 data入栈8,min入栈上次的栈顶1 data[1,8] min[1,1]
当data中有值的时候,push 0 入栈 data入栈0,0小于min的栈顶min入栈0 data[1,8,0] min[1,1,0]
当data中有值的时候,push 7 入栈 data入栈7,7大于min的栈顶.min入栈上次的栈顶0 data[1,8,0,7] min[1,1,0,0]
...如此循环往复
出栈
当栈不为空时,data和min同时出栈
getMin
直接获取min栈的栈顶
42,用两个栈实现队列和用两个队列实现栈
两个栈实现队列
思想:
push栈和pop栈
push栈入栈[1,2,3,4,5
pop时先将push栈中的数据全部导到pop栈中,此时 pop栈[5,4,3,2,1;再次pop就是从1开始
如果pop1之后pop栈中[5432,push栈中[;此时再进入67两个元素
pop[5432;push[6,7此时不用管,等待pop中数据pop完成在进行将push中数据导到pop中去
两个队列实现栈
思想,一个queue队列,一个help队列
queue=12345,help=;
poll时将queue中的数据导入help中直到剩下1个元素queue=5,help=1234
弹出queue中的 5此时queue=,help=1234
queue和help交换
即help=,queue=1234
此时队列加入67,help=,queue=123467
queue导入help只剩下最后一个元素7然后pop
43,master公式