刷题记录--11/16

学习内容:

每日三题
1、 旋转数组输出最小值
2、 斐波那契数列的第 n n n
3、 链表的反序


一、旋转数组的最小值

	问题:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。

这道题主要考察了我们对于二分查找知识点的掌握
       作为一个小白,我最初的想法很简单:这就是一个简单的排序问题,直接用冒泡排序对数组进行排序,然后输出最小值即可。毫无疑问, O ( n 2 ) O(n^{2}) O(n2)的时间复杂度是难以满足要求的。在重新阅读题目之后,我发现旋转数组的条件是没有用到的,简单来说一个非递减排序额的旋转数组是有两部分:非递减的 l i s t [ R o t a t e _ P o s : ] list[Rotate\_Pos:] list[Rotate_Pos:]以及 l i s t [ 0 : R o t a t e _ P o s ] list[0:Rotate\_Pos] list[0:Rotate_Pos],结合已知信息我们怎样利用二分搜索的方法来实现需求呢?

分析过程:
       二分查找的思路我们是很清楚的,每次查找后,确定目标值所在的位置即在 m i d mid mid的哪一侧,从而减少搜索的长度。这道题二分查找难就难在 l i s t [ m i d ] list[mid] list[mid]跟谁比.
一般的比较原则有:

  1. 如果有目标值target,那么直接让 l i s t [ m i d ] list[mid] list[mid] t a r g e t target target 比较即可。;
  2. 如果没有目标值,一般可以考虑端点

这里我们把target 看作是右端点,来进行分析,那就要分析以下三种情况,看是否可以达到上述的目标。
c a s e 1 case1 case1 :[4,5,6,1,2,3] l i s t [ m i d ] = 6 > t a r g e t = 1 list[mid]=6> target=1 list[mid]=6>target=1
根据数组的非递减性质,说明 [ f i r s t . . . m i d ] [first ... mid] [first...mid]都是 ≥ t a r g e t \geq target target 的所以可以确定答案为 [ m i d + 1... l a s t ] [mid+1...last] [mid+1...last]区间,所以 f i r s t = m i d + 1 first = mid + 1 first=mid+1

c a s e 2 case2 case2 : [5,6,1,2,3,4] l i s t [ m i d ] = 1 < t a r g e t = 4 list[mid]=1< target=4 list[mid]=1<target=4
说明答案肯定不在[mid+1…last],但是 l i s t [ m i d ] list[mid] list[mid]有可能是答案,所以答案在 [ f i r s t , m i d ] [first, mid] [first,mid]区间,所以 l a s t = m i d last = mid last=mid

c a s e 3 case3 case3 : l i s t [ m i d ] = t a r g e t list[mid]= target list[mid]=target
这种情况是比较特殊的,我们需要逐步缩小区间去搜索目标值,也就是每次所
如果是 [ 1 , 0 , 1 , 1 , 1 ] [1,0,1,1,1] [1,0,1,1,1] l i s t [ m i d ] = t a r g e t = 1 list[mid]=target=1 list[mid]=target=1, 显然答案在左边;
如果是 [ 1 , 1 , 1 , 0 , 1 ] [1,1,1,0,1] [1,1,1,0,1] l i s t [ m i d ] = t a r g e t = 1 list[mid]=target=1 list[mid]=target=1, 显然答案在右边;
所以这种情况,不能确定答案在左边还是右边,那么就让 l a s t = l a s t − 1 last = last - 1 last=last1;慢慢缩少区间,同时也不会错过答案。

代码

class Solution:
	def minNumberInRotateArray(self, rotateArray):
		if len(rotateArrary)==0 :
			return 0
		#长度为0 返回0
		elif len(rotateArrary)==1 :
			return rotateArrary[0]
		else:
			left = 0
			right = len(rotaArray)-1
			start = 0
			while left<right:
				mid = (left+right)//2
				if rotaArray[start] == rotaArray[mid]:
				#中间点大于左端点  first = mid+1  处于递增序列中
					start = strat+1
					left = strat
				elif rotaArray[start] < roraArray[mid]:
					left = mid+1
				else:
					right = mid
		return rotaArray[left]
class Solution1:#递归写法
	def minNumberInRotateArray(self, rotateArray):
		if len(rotaArray)==1:
			return rotaArray[0]
		elif len(rotaArray)==2:
			if rotaArray[0]>rotaArray[1]
				return rotaArray[1]
			else:
				return rotaArray[0]
		else:
			mid = len(rotaArray)//2
			target = rotaArray[-1] #右端点
			if rotaArray[mid]>target:
				return self.minNumberInRotateArray(rotateArray[mid+1:])
			elif rotaArray[mid]==target:
				return self.minNumberInRotateArray(rotateArray[:-1])
			else:
				return self.minNumberInRotateArray(rotateArray[:mid+1])


二、斐波那契数列

	问题:现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。

这个问题废话不多说直接上代码

class Solution:
#递归写法 简介明了 缺点慢 真的慢
    def Fibonacci(self, n):
    	if n==0:
    		return 0
    	elif n ==1 or n==2:
    		return 1
    	else:
    		return self.Fibonacci(n-1)+self.Fibonacci(n-2)

class Solution:
#递归实际上做了多次重复计算 所以我们设计自底向上的计算 依次计算每项
    def Fibonacci(self, n):
    	if n==0:
    		return 0
    	elif n ==1 or n==2:
    		return 1
    	else:
    		a,b = 0 ,1
    		sums = 0
    		i = 1
    		while i <n:
    			sums = a+b
    			a,b = b,sums
    			i = i+1
    	return sums

#矩阵方法 https://blog.csdn.net/lamusique/article/details/89161831

表达式方法:在这里插入图片描述

class Solution:
    def Fibonacci(self, n):
        a = math.sqrt(5)/5
        b = pow((1+math.sqrt(5))/2,n)
        c = pow((1-math.sqrt(5))/2,n)
        result = int(a*(b-c))
        return result
 

三、链表的反序

	输入一个链表,反转链表后,输出新链表的表头。

关于这道题的分析参见博客:https://blog.csdn.net/gongliming_/article/details/88712221
分析的很好
原来的链表
在这里插入图片描述
反转后的链表
在这里插入图片描述
反转过程
在这里插入图片描述
我们需要三个节点来描述每一步的情况, p r e v i o u s − p r e , c u r r e n t − c u r , n e x t − n e x t s previous-pre,current-cur,next-nexts previouspre,currentcur,nextnexts,每次的反转过程都有4个子程序。在开始之前,我们先看一下现在节点的状态: p r e = N o n e , c u r = L i s t . h e a d , n e x t s = L i s t . h e a d . n e x t pre=None,cur=List.head,nexts=List.head.next pre=None,cur=List.head,nexts=List.head.next。接下来进行第一次反转,第一步:指向下一个节点 n e x t s = h e a d . n e x t nexts=head.next nexts=head.next,第二步:将当前头部的下一个节点设置为前一个 h e a d . n e x t = p r e head.next=pre head.next=pre这一步是实现反向的重要步骤,除了第一步外其他步都是将当前的节点指向前一个节点(反向过程),第三步:当前节点设置为前一个节点 p r e = h e a d pre=head pre=head,第四步:将下一个节点设置为头部节点 h e a d = h e a d . n e x t head=head.next head=head.next

代码

class ListNode:
    def __init__(self,item):
        self.val = item
        self.next = None
         
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
    	if pHead ==None or pHead.next==None:
    		return pHead
    	else:
    		pre= None
    		cur=pHead
    		nexts = None
    		while cur!=None:
    			nexts = pHead.next
    			pHead.next = pre
    			pre = pHead
    			pHead = nexts
    	    return  pre#头部节点 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值