算法刷题 week4

1.斐波那契数列

题目

在这里插入图片描述

题解
(递推 + 滚动变量) O(n)

这题的数据范围很小,我们直接模拟即可。
当数据范围很大时,就需要采用其他方式了,可以参考 求解斐波那契数列的若干方法

F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

用两个变量滚动式得往后计算,a 表示第 n−1 项,b 表示第 n 项。
则令 c=a+b 表示第 n+1 项,然后让 a, b 顺次往后移一位。

时间复杂度分析

总共需要计算 n 次,所以时间复杂度是 O(n) ,但空间复杂度变成了 O(1)。

class Solution {
public:
    const int MOD = 1e9 + 7;    //1000000007
    int Fibonacci(int n) {
        int a = 0, b = 1;
        while (n--)  
        {
            int c = (a + b) % MOD;  //取模优先级比加减高,比乘数低
            a = b, b = c;   //逗号运算符,从左到右计算
        }
        return a;
    }
};  
//  	 0 1 1 2 3 5
//第几项  0 1 2 3 4 5 

剑指offer 10 - II 青蛙跳台阶问题

题目

在这里插入图片描述

题解

此类求 多少种可能性 的题目一般都有 递推性质 ,即 f(n) 和 f(n-1)…f(1) 之间是有联系的。

在这里插入图片描述

在这里插入图片描述

计算 f(n) 需循环 n 次,每轮循环内计算操作使用 O(1) ,所以时间复杂度是 O(n) 。

几个标志变量使用常数大小的额外空间,空间复杂度为 O(1)。

class Solution {
public:
    const int MOD = 1e9 + 7;    //1000000007
    int numWays(int n) {
        int a = 1, b = 1;   //只有起始条件不同,其它都与上题相同
        while (n--)  
        {
            int c = (a + b) % MOD;  //取模优先级比加减高,比乘数低
            a = b, b = c;   //逗号运算符,从左到右计算
        }
        return a;
    }
};

10.旋转数组的最小数字

题目

在这里插入图片描述

题解
(二分) O(n)

为了便于分析,我们先将数组中的数画在二维坐标系中,横坐标表示数组下标,纵坐标表示数值, 图中水平的实线段表示相同元素。如下所示:

2.png

我们发现除了最后水平的一段(黑色水平那段)之外,其余部分满足二分性质:竖直虚线左边的数满足 nums[i]≥nums[0];而竖直虚线右边的数不满足这个条件。

二分是二分性而不是单调性。只要满足可以找到一个值一半满足一半不满足即可,而不用满足单调性。

分界点就是整个数组的最小值,所以我们先将最后水平的一段删除即可。

另外,不要忘记处理数组完全单调的特殊情况:

当我们删除最后水平的一段之后,如果剩下的最后一个数大于等于第一个数,则说明数组完全单调。

时间复杂度分析

二分的时间复杂度是 O(logn),删除最后水平一段的时间复杂度最坏是 O(n),所以总时间复杂度是 O(n)。

class Solution
{
public:
    int findMin(vector<int>& nums)
    {
        int n = nums.size() - 1;
        if(n < 0) return -1;
        
        while (n > 0 && nums[n] == nums[0]) n--; //删除最后水平的一段,当n=0时,只有一个数,也要退出循环
        if (nums[n] >= nums[0]) return nums[0]; //当没有元素旋转时,则出现这种情况
        
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r >> 1;  //[l, mid], [mid + 1, r]
		  	if (nums[mid] < nums[0]) r = mid;
            else l = mid + 1;
        }
        return nums[r];
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VengaZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值