按照这个写法,一个博客会写4个题目
9.走台阶问题
f(0)=0;
f(1)=1;
f(2)=1+1=2;
递推公式:
f(n)=f(n-1)+f(n-2)+f(n-3)
面试金典第221页原题。
#include <iostream>
using namespace std;
int count_steps(int n, int *map);
int main()
{
const int N=10;
int map[N];
for(int i=0;i<N;++i)
{
map[i]=-1;
}
for(int i =0; i<N;++i)
{
cout<<i<<"\t"<<count_steps(i, map)<<endl;
}
return 0;
}
int count_steps(int n, int *map)
{
if(n<0) return 0;
else if(!n) return 1;
else if(map[n]>=0) return map[n];
else
{
map[n] = count_steps(n-1, map) + count_steps(n-2, map) + count_steps(n-3, map);
return map[n];
}
}
动态规划算法对每个子问题只求解一次,将其结果保存起来,从而避免每次遇到各个子问题时重新计算答案。这里还用到了递归
10.10进制转成2进制
求所有表示方法数
例如
1 -> 1
2 -> 10, 02
3 -> 11
4 -> 100, 020, 012
5 -> 101, 021
6 -> 110,022,102
F(0)=0
F(1)=1
F(2)=2
F(3)=1=F(1)
F(4)=3=F(1)+F(2)
F(5)=2=F(2)
F(6)=F(2)+F9(3)=1+2=3
归纳出表达式:
F(0)=0
F(1)=1
F(2)=2
F(n)=F((n-1)/2) if n is odd
F(n)=F(n/2)+F((n-2)/2) if n is even
代码略
也是一个递归解法
11.递增数列中每一项都可表示为
3^i*5^j*7^k
(i,j,k>=0)
求数列第n项
1,3,5,7,9,15,21,25,27
此为面试金典第188页原题
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
int getMagicNumber(int n);
int getNextNum(queue<int> &q3, queue<int> &q5, queue<int> &q7, int *nextQ);
int main()
{
for(int i=0;i<11;++i)
cout<<i<<":\t"<<getMagicNumber(i)<<endl;
return 0;
}
int getMagicNumber(int n)
{
if(n<=0) return 0;
queue<int> q3,q5,q7;
stack<int> s;
int cnt=0;
int nextNum, nextQ;
while(cnt<n)
{
nextNum = getNextNum(q3,q5,q7,&nextQ);
s.push(nextNum);
++cnt;
}
return s.top();
}
int getNextNum(queue<int> &q3, queue<int> &q5, queue<int> &q7, int *nextQ)
{
int min;
if(q3.empty())
{
min=1;
*nextQ=3;
}else
{
if(q3.front()<q5.front() && q3.front()<q7.front())
{
min = q3.front();
q3.pop();
*nextQ=3;
}else if(q5.front()<q3.front() && q5.front()<q7.front())
{
min = q5.front();
q5.pop();
*nextQ=5;
}else{
min = q7.front();
q7.pop();
*nextQ=7;
}
switch(*nextQ)
{
case 3: q3.push(min*3);
case 5: q5.push(min*5);
default:q7.push(min*7);
}
return min;
}
}
可以优化的地方: stack只在back函数取得末尾元素,因此可以换成queue,同时函数的接口可以简化为3个参数.
这个题目也展示了如何使用stl的queue和stack等模块
12.为二叉树找右侧邻居节点
要求递归和非递归都实现
这个问题非递归可以做一次层序遍历
在每一层都输出其右邻结点
#include <iostream>
#include <queue>
using namespace std;
typedef struct Node* NodePointer;
struct Node
{
int data;
int depth;
NodePointer lChild;
NodePointer rChild;
NodePointer rBrother;
};
struct myQueue{};
void findRBrother(NodePointer root);
void addToQueue(NodePointer root, myQueue q);
void findRBrotherRecursive(NodePointer root);
int main()
{
NodePointer root=0;
findRBrother(root);
findRBrotherRecursive(root);
return 0;
}
void findRBrother(NodePointer root)
{
if(!root) return;
root->depth = 0;
queue<NodePointer> q;
NodePointer last=0, next;
while(!q.empty())
{
next = q.front();
q.pop();
q.push(next->lChild);
q.push(next->rChild);
if(last->depth == next->depth)
{
last->rBrother = next;
}
last = next;
}
}
void findRBrotherRecursive(NodePointer root)
{
int front=0,rear=0;
NodePointer left,right;
left = root;
right = root->lChild;
queue<NodePointer> q;
if(!root) return;
if(root->lChild)
q.push(root->lChild);
if(root->rChild)
q.push(root->rChild);
while(right)
{
left->rBrother = right;
left = right;
right=right->lChild;
if(left->lChild)
q.push(left->lChild);
if(left->rChild)
q.push(left->rChild);
}
if(q.empty()) return;
left = q.front();
q.pop();
findRBrotherRecursive(left);
}
这个代码体现了数据结构的扩展能力。
这里再附上层序遍历的代码加深一下印象:
void levelOrder(NodePointer root)
{
int front=0, rear = 0;
queue<NodePointer> q;
if(!root) return;
q.push(root);
while(1)
{
root = q.front();
q.pop();
if(!root) break;
cout<<root->data<<endl;
if(root->lChild)
q.push(root->lChild);
if(root->rChild)
q.push(root->rChild);
}
}