[心得]面试题分析与整理3

按照这个写法,一个博客会写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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值