牛客 菲波那切数列
题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n<=39
思路:
递归解法:效率低,重复计算和函数调用耗费多。
迭代解法
代码:
//这就是一份Dp的代码,迭代
class Solution {
public:
int Fibonacci(int n) {
//f(n-2) + f(n-1) = f(n)
if(0 == n){
return n;
}
int first = 1;
int second = 1;
int third = 1;//流氓啊,第一项和第二项不需要迭代。
while(n > 2){
third = first + second;
first = second;//更新first
second = third;//更新second
--n;
}
return third;
}
};
//这就是一份剪枝的代码
class Solution {
unordered_map<int, int> filter;
public:
int Fibonacci(int n) {
//f(n-2) + f(n-1) = f(n)
if(n ==0 || n == 1)
return n;
if(n == 2)
return 1;
int ppre = 0;
if(filter.find(n-2) == filter.end()){
ppre = Fibonacci(n-2);
filter.insert({
n-2,ppre});
}
else{
ppre = filter[n-2];
}
int pre = 0;
if(filter.find(n-1) == filter.end()){
pre = Fibonacci(n-1);
filter.insert({
n-1,pre});
}
else{
pre = filter[n-1];
}
return pre + ppre;
}
};
牛客 跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路:
采用DP来进行处理,三步:
- 定义状态
f(n):青蛙跳上第n级台阶的总跳法 - 状态转移方程
f(n) = f(n-1) + f(n-2) - 设置初始值
f(0) = 1,到0台阶的方法是1
f(1) = 1
f(2) = 2
代码:
class Solution {
public:
int jumpFloor(int number) {
//f(n) = f(n-1) + f(n-2)
//f(0) =1 ,f(1) =1,f(2)= 2
vector<int> dp(number+1);
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for(int i =2;i<=number;++i){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[number];
}
};
优化空间:
本质就是:斐波那契数列
什么时候用Dp?
- 找一批动态规划的题,练习3个步骤
- 一般使用动归的时候,必定要使用数组(一维的或者二维的)
3+1(3个过程+一个数组)
牛客 矩形覆盖
题目描述
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
比如n=3时,2*3的矩形块有3种覆盖方法:
代码:
//斐波那契数列变形,但是表现形式是不一样的
class Solution {
public:
int rectCover(int number) {
//f(n)总的方法数
//f(n) = f(n-1)最后一次竖着放和f(n-1)本身方法数相同 + f(n-2)最后一次横着放
//f(1) =1 ,f(2) = 2;
int * dp = new int [number + 1];
dp[1] =1;
dp[2] = 2;
for(int i = 3; i<=number;++i){
dp[i] = dp[i-1] + dp[i-2];
}
int result = dp[number];
delete dp;
return result;
}
};
牛客 二进制中的1的个数
题目描述
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示
思路:
位运算处理
代码:
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while(n){
n = n & (n-1);
++count;
}
return count;//返回个数count
}
};
牛客 链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
思路:
有一些细节。
代码:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead == nullptr){
return nullptr;
}
ListNode *front = pListHead;
ListNode *rear = pListHead;
while(k>0 && front){
--k;
front = front->next;
}
while(front){
front = front->next;
rear = rear->next;
}
return k > 0 ? nullptr : rear;
}
};
力扣
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
层序遍历,BFS,加上控制每一层的个数
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if (root == nullptr) {
return {
};
}
vector<vector<int>> res;
queue<TreeNode*> Q;
TreeNode *temp;
Q.push(root);
while (!Q.empty()) {
vector<int> T;
int size = Q.size();
for(int i = 0; i < size; ++i) {
//控制每层的个数
temp = Q.front();
Q.pop();
T.push_back(temp->val);
if (temp->left != nullptr) {
Q.push(temp->left);
}
if (temp->right != nullptr) {
Q.push(temp->right);
}
}
res.push_back(T);
}
return res;
}
};