学习算法基础

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公式


  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值