C++面试题5

第5课 - 外企笔试题精选三

  1. 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下的顺序排序。请实现一个函数用于判断数组中是否含有指定的数。

函数原型:

         bool find_in_matrix(int matrix[N][M], int value);

说明:

         查找成功时返回true,失败时返回false。

答案:

#include <iostream>

using namespace std;

template<typename T, int N, int M>

bool find_in_matrix(T matrix[N][M], T value) // O(N + M)

{

    if( (matrix[0][0] <= value) && (value <= matrix[N-1][M-1]) )

    {

        int r = 0;

        int c = M - 1;

        while( (r < N) && (c >= 0) )

        {

            if( value == matrix[r][c] )

            {

                return true;

            }

            else if( value < matrix[r][c] )

            {

                c--;

            }

            else

            {

                r++;

            }

        }

    }

    return false;

}

int main()

{

    int matrix[4][4] =

    {

        {1, 2, 8, 9},

        {2, 4, 9, 12},

        {4, 7, 10, 13},

        {6, 8, 11, 15},

    };

    cout<<find_in_matrix<int, 4, 4>(matrix, 7)<<endl;

    return 0;

}

  1. 写一个函数,打印二叉树中某层的所有结点。

二叉树结点定义:

struct Node

{

         int v;

         Node* left;

         Node* right;

};

函数原型:

void print_node_at_level(Node* node, int level)

说明:将level层的结点中所保存的值打印在同一行。

分析:二叉树的题是离不开递归的

#include <iostream>

#include <list>

using namespace std;

struct Node

{

    int v;

    Node* left;

    Node* right;

};

void print_node_at_level(Node* node, int level)  //递归的答案,答案简介,但是耗费函数调用栈

{

    if( node != NULL )

    {

        if( level == 0 ) //若是第0层,直接打印

        {

            cout<<node->v<<" ";

        }

        else //若不是第0层,递归的打印

        {

            print_node_at_level(node->left, level-1);

            print_node_at_level(node->right, level-1);

        }

    }

}

void print_node_at_level_ex(Node* node, int level)  //非递归的方式,广度优先算法

{

    if( node != NULL )  //为每个元素编号

    {

        list<Node*> nl; 

        list<int> ll;

        nl.push_back(node);

        ll.push_back(0);

        while( nl.size() > 0 )

        {

            Node* n = nl.front();

            int cl = ll.front();

            nl.pop_front();

            ll.pop_front();

            if( cl == level )

            {

                cout<<n->v<<" ";

            }

            else if( cl < level )

            {

                if( n->left != NULL )

                {

                    nl.push_back(n->left);

                    ll.push_back(cl+1);

                }              

                if( n->right != NULL )

                {

                    nl.push_back(n->right);

                    ll.push_back(cl+1);

                }

            }

        }

    }

}

int main()

{

    Node nodes[] =

    {

        {0, NULL, NULL},  //0层

        {1, NULL, NULL},  //1层

        {2, NULL, NULL},  //1层

        {3, NULL, NULL},  //2层

        {4, NULL, NULL},  //2层

        {5, NULL, NULL},  //2层

        {6, NULL, NULL},  //3层

        {7, NULL, NULL},  //3层

    };

   

    nodes[0].left  = &nodes[1]; //0指向1,2   ,0层

    nodes[0].right = &nodes[2];

    nodes[1].left  = &nodes[3];  //1指向3,4 ,1层

    nodes[1].right = &nodes[4];

    nodes[2].left  = &nodes[5];  //2左指5,右指向空, 1层

    nodes[2].right = NULL;

    nodes[4].left  = &nodes[6]; //4指向4,5   ,2层

    nodes[4].right = &nodes[7];

    print_node_at_level(nodes, 3);  //6,7

    cout<<endl;

    //print_node_at_level_ex(nodes, 3);

    cout<<endl;

    return 0;

}

  1. 编写一个函数用于删除二叉树中的度数为1的所有结点。

要求:

结点删除后其唯一的子结点代替它的位置。

 

答案:

#include <iostream>

using namespace std;

struct Node

{

    int v;

    Node* left;

    Node* right;

};

void print_div(int p)

{

    for(int i=0; i<p; i++)

    {

        cout<<"-";

    }

}

void print_tree(Node* node, int p)

{

    if( node != NULL )

    {

        print_div(p);

        cout<<node->v<<endl;

        if( (node->left != NULL) || (node->right != NULL) )

        {

            print_tree(node->left, p+1);

            print_tree(node->right, p+1);

        }

    }

    else

    {

        print_div(p);

        cout<<endl;

    }

}

void print_tree(Node* node)

{

    print_tree(node, 0);

}

void delete_one_degree_node(Node*& node)

{

    if( node != NULL )

    {

        if( (node->left != NULL) && (node->right != NULL) )  //度数为2

        {

            delete_one_degree_node(node->left);  //删除左子树的单度结点

            delete_one_degree_node(node->right); //删除右子树的单度结点

        }

        else if( (node->left != NULL) && (node->right == NULL) )   //度数为1

        {

            node = node->left;

            delete_one_degree_node(node); //新的结点也要进行单度删除

        }

        else if( (node->left == NULL) && (node->right != NULL) )   //度数为1

        {

            node = node->right;         

            delete_one_degree_node(node); //新的结点也要进行单度删除

        }

    }

}

int main()

{

    Node n[10] = {0};

    Node* tree = n;

    for(int i=0; i<10; i++)

    {

        n[i].v = i;

    }

    tree[0].left = &tree[1];

    tree[0].right = &tree[2];

    tree[1].left = &tree[3];

    tree[1].right = &tree[4];

    tree[2].left = NULL;

    tree[2].right = &tree[6];

    tree[3].left = &tree[7];

    tree[3].right = &tree[8];

    tree[4].left = &tree[9];

    cout<<"Original:"<<endl;

    print_tree(tree);

    delete_one_degree_node(tree);

    cout<<"After:"<<endl;

    print_tree(tree);

    return 0;

}

  1. 输入一个数组,数组里面可能有正数也有负数。数组中一个或连续的多个元素组成一个子数组。求所有子数组的和的最大值。

要求:

时间复杂度为O(n)。

答案:

#include <iostream>

#include <cstdlib>

#include <ctime>

using namespace std;

template<typename T>

void init(T array[], int len)

{

    srand((unsigned int)(time(NULL)));

    for(int i=0; i<len; i++)

    {

        array[i] = rand() % 10 - 5;    

    }

}

template<typename T>

void print_array(T array[], int len)

{

    for(int i=0; i<len; i++)

    {

        cout<<array[i]<<" ";

    }

    cout<<endl;

}

template<typename T>

bool max_sub_array_sum(T array[], int len, T& max_sum)

{

    int ret = (len > 1);

    if( ret )

    {

        T sum = array[0];

        T cur = array[0];

        for(int i=1; i<len; i++)

        {

            cur = cur + array[i];

            if( cur < array[i] )  //array[i]之前的值是负数的话,直接从array[i]开始

            {//若果部分和比当前的元素小,舍弃部分和

                cur = array[i];

            }

            if( cur > sum )

            {

                sum = cur;

            }

        }   

        max_sum = sum;

    }

    return ret;

}

int main()

{

    int array[10] = {0};

    int max_sum = 0;

    init(array, 10);

    print_array(array, 10);

    if( max_sub_array_sum(array, 10, max_sum) )

    {

        cout<<max_sum<<endl;

    }

    return 0;

}

  1. 在一个整型数组中只可能有0, 1, 2三种数字重复出现,编写一个函数对这样的数组进行排序。

答案:

#include <iostream>

#include <cstdlib>

#include <ctime>

using namespace std;

void init(int array[], int len)//初始化

{

    srand((unsigned int)(time(NULL)));

    for(int i=0; i<len; i++)

    {

        array[i] = rand() % 3;    

    }

}

void print_array(int array[], int len)//打印

{

    for(int i=0; i<len; i++)

    {

        cout<<array[i]<<" ";

    }

    cout<<endl;

}

void swap(int& a, int& b) //交换

{

    int c = a;

    a = b;

    b = c;

}

void three_element_sort(int array[], int len)

{

    int* ts = new int[len];

    int p = 0;

    if( ts != NULL )

    {

        for(int i=0; i<3; i++)

        {

            for(int j=0; j<len; j++)

            {

                if( array[j] == i )

                {

                    ts[p++] = i;

                }

            }

        }

        for(int i=0; i<len; i++)

        {

            array[i] = ts[i];

        }

        delete[]ts;

    }

}

void three_element_sort_ex(int array[], int len)

{

    int p0 = 0;

    int p2 = len - 1;

    while( array[p0] == 0 ) p0++;

    while( array[p2] == 2 ) p2--;

    for(int i=p0; i<=p2;)

    {

        if( array[i] == 0 )

        {

            swap(array[i], array[p0++]);  

            while( array[p0] == 0 ) p0++;

            if( i < p0 ) i = p0;

        }

        else if( array[i] == 2 )

        {

            swap(array[i], array[p2--]);

           

            while( array[p2] == 2 ) p2--;

        }

        else

        {

            i++;

        }

    }

}

int main()

{

    int array[15] = {2, 2, 2, 0, 2, 0, 0, 1, 1, 0, 0, 2, 1, 0, 0};

    init(array, 15);

    print_array(array, 15);

    //three_element_sort(array, 15);

    three_element_sort_ex(array, 15);

    print_array(array, 15);

   

    return 0;

}

  1. 求1+2+3+…n的和。

要求:

不能使用if, while, for, switch, ?:等条件语句,不能使用==, !=, <, <=, >, >=等比较运算符,也不能使用外部库函数。只能使用加减法操作符,不能使用乘除法操作符。

答案一:

#include <iostream>

using namespace std;

class Sum

{

private:

    static int N;

    static int S;

    Sum();

public:

    static int Calculate(int n);

};

int Sum::N = 0;

int Sum::S = 0;

Sum::Sum()

{

    S = S + N;

    N = N - 1;

}

int Sum::Calculate(int n)

{

    int ret = 0;

    Sum* p = NULL; 

    N = n;

    S = 0;

    p = new Sum[N];

    ret = S;      

    delete[]p;

    return ret;

}

int main()

{

    cout<<Sum::Calculate(10)<<endl;

    cout<<Sum::Calculate(100)<<endl;

    return 0;

}

答案二:

#include <iostream>

using namespace std;

typedef int(Func)(int);

int end_func(int n);

int recusive_func(int n);

Func* Array[] =  //函数指针

{

    end_func,     // 0

    recusive_func // 1

};

int end_func(int n)

{

    return n;

}

int recusive_func(int n)

{

    return n + Array[!!(n-1)](n-1);  //!!将不为0的数变成1

}

int sum(int n)

{

    return recusive_func(n);

}

int main()

{

    cout<<sum(10)<<endl;

    cout<<sum(100)<<endl;

    return 0;

}

答案三:

#include <iostream>

using namespace std;

template<int N>

class Sum

{

public:

    static const int Value = N + Sum<N-1>::Value;

};

template<>

class Sum<0>

{

public:

    static const int Value = 0;

};

int main()

{

    cout<<Sum<10>::Value<<endl;

    cout<<Sum<100>::Value<<endl;

   

    return 0;

}

原文地址:https://www.cnblogs.com/free-1122/p/11341969.html