第5课 - 外企笔试题精选三
- 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下的顺序排序。请实现一个函数用于判断数组中是否含有指定的数。
函数原型:
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;
}
- 写一个函数,打印二叉树中某层的所有结点。
二叉树结点定义:
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的所有结点。
要求:
结点删除后其唯一的子结点代替它的位置。
答案:
#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;
}
- 输入一个数组,数组里面可能有正数也有负数。数组中一个或连续的多个元素组成一个子数组。求所有子数组的和的最大值。
要求:
时间复杂度为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;
}
- 在一个整型数组中只可能有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+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;
}