旋转数组
描述
将有序数组的前n个数移到数组最后称为旋转数组。求数组中最小的元素。
思路
顺序查找时间复杂度为O(n),序列分为两段,两段都是有序的,且大多数情况下第一段的数大于第二段,这就可以用二分查找,如[3,4,5,1,2]
,当index1+1=index2时,nums[index2]为所要找的数。但是也有特殊情况,如[0,1,0,0,0],index1,index2和mid指向的数字大小相同,此时只能顺序查找。
代码:
def find_min_num(nums):
if not nums:
return None
index1=0
index2=len(nums)-1
while nums[index1]>=nums[index2]:
mid = int((index1 + index2) / 2) #必须为整数
if index1+1==index2:
return nums[index2]
if nums[index1]==nums[index2] and nums[index1]==nums[mid]:
return find_in_order[nums]
if nums[mid]>nums[index1]:
index1=mid
elif nums[mid]<nums[index2]:
index2=mid
return nums[0]
def find_in_order(nums):
min=nums[0]
for it in nums:
if it<min:
min=it
return min
nums=[3,4,5,6,0,1,2]
nums1=[1,0,0,1]
print(find_min_num(nums))
斐波那契数列
描述
F(1)=1,F(2)=1,F(n)=F(n-1)+F(n-2)
思路:
用递归的方法好理解,但存在时间和空间效率问题。用非递归的方式则情况更好。
青蛙跳台阶的题(青蛙可以跳一阶或二阶,问跳上n阶台阶的方法数目)也可以用斐波那契数列来理解。跳上第n阶台阶可以从第n-2阶往上跳或第n-1阶往上跳。就是F(n)=F(n-1)+F(n-2)
代码:
def fib_for(n):
if n==0:
return 0
elif n==1:
return 1
elif n>=2:
fibN=0
f1=0
f2=1
for i in range(2,n+1):
fibN=f1+f2
f1=f2
f2=fibN
return fibN
#青蛙跳数
def fib(n):
if n==1:
return 1
elif n==2:
return 2
else:
return fib(n-1)+fib(n-2)
比特1的个数
描述:
输入一个整数,求它二进制表示中1的个数
思路:
一个整数减去1再和原数&一下就可以去掉最低位的1如 111000->110111,110111&111000=110000,最后可以去掉所以的1变为000000。而用数向右移动的做法,负数会在左边产生额外的1,陷入死循环。另外二进制向右移动一位,等价于/2,但是位操作的效率远大于/操作
代码:
def cnt_of_bit(n):
cnt=0
while n:
cnt+=1
n=(n-1)&n
return cnt
print(cnt_of_bit(9))