题目一:青蛙跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。
求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
解题步骤
选用递归的方法解决该问题!
使用递归只需要考虑清楚边界条件/终止条件,再写清楚单层循环逻辑
剩下的交给程序就好啦!
那么如果顺着一级一级去想会非常麻烦,
不妨倒着想想,青蛙以什么姿势跳上第n级台阶
是优雅的迈了一步?还是急速蹦了两级?
以jump(n)为求步数的函数,
根据该思路则有:jump(n)=jump(n-1)+jump(n-2)
此外jump(0)=1,jump(1)=1
这是按照规律得到的边界条件
整合到一起就是
cpp
int jump(int n){
if(n==0 || n==1){
return 1;
}
return jump(n-1)+jump(n-2);
}
那么主函数里只需要加一些输入输出,再用上我们的jump就好啦
cpp
int main(){
int n;
cin>>n;
cout<<jump(n);
return 0;
}
code
cpp
#include<bits/stdc++.h>
using namespace std;
int jump(int n){
if(n==0 || n==1){
return 1;
}
return jump(n-1)+jump(n-2);
}
int main(){
int n;
cin>>n;
cout<<jump(n);
return 0;
}
题目二:丢失的数字
题目描述
给定一个包含 [0, n]
中 n
个数的数组 nums
,找出 [0, n]
这个范围内没有出现在数组中的那个数。
解题步骤
1.小笨方法
利用排序和数组下标
排序后数组按照大小顺序排列,数组内元素值与数组下标一致
遍历数组依次比对检查
不符合就返回
还有一种情况是缺少最后一个,故在循环外return该值,即nums.size()
cpp
class Solution {
public:
int missingNumber(vector<int>& nums) {
sort(nums.begin(),nums.end());//对整个数组做排序
for(int i=0;i<nums.size();i++){//利用下标检查
if(nums[i] !=i)//不符合则返回该下标
return i;
}
return nums.size();//都符合那就是少了最后一个!
}
};
2.逆向思维+数学方法
反过来想如果没少,那么这个无序数组有什么特点?
虽然没有顺序但它完全就是一个等差数组,等差数组可以使用求和公式得到所有值的和
那么与当前数组的和取差值,就是丢失的数字
需要注意的是该数组首项为0,尾项为n,一共n+1个!!!
cpp
int n=nums.size();//获取数组大小
int sum=n*(n+1)/2;//没少的数组之和,首项为0,尾项为n,一共n+1个!
int s=0;//当前数组之和
for(int i=0;i<n;i++){
s=s+nums[i];//累加统计
}
return sum-s;//相减得出丢失值
也可以用accumulate函数替代遍历累加求和的代码
cpp
int s=accumulate(nums.begin(),nums.end(),0);
参数说明:
-
vec.begin()
:起始迭代器。 -
vec.end()
:结束迭代器。 -
0
:初始值(求和的起点)
题目三:只出现一次的数字
题目描述
给你一个 非空 整数数组 nums
,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
解题步骤
如果正向去做这题,那么就是进行遍历,统计每一个元素出现次数,对出现次数为1的元素进行返回,但这样占用空间,不符合线性时间复杂度
那么如何逆向想一想呢?从找一次到出现一次的元素,变为任务是消去出现两次的元素
每个元素均出现两次可以进行什么操作配对消除呢?
采用位运算中的异或运算,两者相同为0,不同为1
对nums数组中的所有元素逐个进行异或,最终结果就是只出现一次的元素
code
cpp
class Solution {
public:
int singleNumber(vector<int>& nums) {
int temp=nums[0];
for(int i=1;i<nums.size();i++){
temp^=nums[i];
}
return temp;
}
};