剑指offer里的题很经典,我的顺序是从简单题开始刷,并写下我的思路和见解,今天写的是offer09和offer10-1。
offer09 用两个栈实现队列
队列是先进先出类型的结构,栈是后进先出的结构,两个栈实现队列的思路是使用一个栈作为输入栈,一个栈是输出栈,这样一来就把后进先出变成先进先出。具体步骤如下:
(1)定义两个栈s1,s2。s1是输入栈,即把数据先存放在s1中;
(2)s2是输出栈,需要进行判断:如果s2不为空,就先将其中的数据输出;如果为空就把s1的数据存进去(前提是s1中有数据)。
(3)如果s1,s2中都没有数据,就返回-1。
具体代码如下:
class CQueue {
private:
stack<int> s1;//入栈
stack<int> s2;//出栈
public:
CQueue() {
}
void appendTail(int value) {
s1.push(value);
}
int deleteHead() {
if(s2.empty())
{
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
if(s2.empty())
{
return -1;
}
else
{
int res = s2.top();
s2.pop();
return res;
}
}
};
/**
* Your CQueue object will be instantiated and called as such:
* CQueue* obj = new CQueue();
* obj->appendTail(value);
* int param_2 = obj->deleteHead();
*/
offer10-1 斐波那契数列
斐波那契数列数列就是后面的数据是前面两个数据的和,会首先定义前两个数为0,1,后续就是0,1,1,2,3,5,,,等。
这道题在题解中大概有两种解法:一种是递归的算法,一种是动态规划的算法。
(1)递归算法:
就是把发f(n)拆解成f(n-1)、f(n-2)子问题,再将拆解的子问题再细分,递归会有一个终止条件,满足的话就终止。缺点是会有大量的重复计算。
(2)动态规划法:
设置一个数组,数组中的元素存放的就是每一个f(n),f(n-1),f(n-2)等的值,需要提前设置好前两个元素。
我采用的是动态规划的方案。
(1)提前设置好数组的大小,这里要注意数组大小是n+1,因为数组下标是从0开始的。这样就可以使用数组下标。
class Solution {
public:
int fib(int n) {
if(n == 0 || n == 1)
{
return n;
}
vector<int> vec(n+1);
vec[0] = 0;
vec[1] = 1;
for(int i = 2; i <= n; i++)
{
vec[i] = (vec[i-1] + vec[i-2]) % 1000000007;
}
return vec[n];
}
};
(2)不提前设置数组大小,就需要使用push_back进行操作,否则不知道数组大小。
class Solution {
public:
int fib(int n) {
if(n == 0 || n == 1)
{
return n;
}
vector<int> vec;
vec.push_back(0);
vec.push_back(1);
int sum = 0;
for(int i = 2; i <= n; i++)
{
sum = (vec[i-1] + vec[i-2]) % 1000000007;
vec.push_back(sum);
}
return vec[n];
}
};