【剑指offer题解】leetcode 10,11

12 篇文章 0 订阅
10 篇文章 0 订阅

10- I 斐波那契数列

在这里插入图片描述
思路一:打表,O(1)时间复杂度值得拥有;

思路二:每次计算出新的值判断是否大于100000007,若大于求余;

思路三:求余时间较长,可改为若大于100000007,则减掉100000007。因为前面的两个数也都小于100000007,所以新的数不会大于100000007的二倍,放心的做减法就可以了。

代码三:

class Solution:
    def mod(self, val):
        if val >= 1000000007:
            return val - 1000000007
        else:
            return val

    def fib(self, n: int) -> int:
        if n == 0:
            return 0
        elif n == 1 or n == 2:
            return 1
        pre, cur, nex = 1, 1, 0
        for i in range(2, n):
            nex = self.mod(pre + cur)
            pre = self.mod(cur)
            cur = self.mod(nex)  
        return nex

10- II. 青蛙跳台阶问题

在这里插入图片描述
思路:与上题斐波那契非常相似,简单的动态规划问题。因为一次只能走1步或2步,所以某一个台阶 i 的的走法仅仅由 i-1 和 i-2决定,即 i-1 走一步到达 i,i-2 走两格到达 i,所有就构成了状态转移关系:dp[i]=dp[i-1]+dp[i-2]

代码:

class Solution:
    def mod(self, val):
        if val >= 1000000007:
            return val - 1000000007
        else:
            return val

    def numWays(self, n: int) -> int:
        if n == 0:
            return 1
        elif n == 1 or n == 2:
            return n
        dp = [0 for _ in range(n+1)]
        dp[1], dp[2] = 1, 2
        for i in range(3, n+1):
            dp[i] = self.mod(dp[i-1] + dp[i-2])
        return dp[n]

11. 旋转数组的最小数字

在这里插入图片描述

思路一:遍历一遍,找到第一个打破「非递减」规则的元素即可,时间复杂度O(n);

思路二:二分法,时间复杂度为O(log n)。设最左侧的索引为l,右侧索引为r,中间的mid=(l+r)/2,输入数组为a。分以下几种情况:

  1. 如果 a[mid] < a[r],表明右半部分的数组是单调递增的,此时最小元素在mid或左半部分数组,此时应该让 r=mid;
  2. 如果 a[mid] > a[r],表明右侧数并非单调递增的,其实右侧可以看作两个单调递增的序列的拼接,从mid到最小值前面一个元素单调,最小值到最后单调,因此最小值在数组的右侧部分,此时令 l=mid+1(mid不可能是最小值)
  3. 如果 a[mid] == a[r],此时不能推断出 l,r,mid三者一定相等,因为数组中可能存在重复的元素。此时也存在两种情况:(1)最右侧元素不是最小值,最小值存在于数组左侧或右侧(非最后一个元素),此时做 r-- 筛除掉这个右侧元素即可;(2)最右侧元素是最小值,因为 a[mid] 等于 a[r],所以也可以直接筛掉 a[r]。综上,这种情况下直接做 r-- 筛除掉最右侧元素即可。

代码二:

class Solution:
    def minArray(self, numbers: List[int]) -> int:
        n = len(numbers)
        left, right = 0, n-1
        
        while left < right:
            mid = int((left + right) / 2)
            if numbers[mid] > numbers[right]:
                left = mid + 1
            elif numbers[mid] < numbers[right]:
                right = mid
            else:
                right -= 1
        return numbers[left]
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值