笔试面试题目1

1. 求重合段的长度

size_t foo(unsigned int *a1, size_t al1, unsigned int* a2, size_t al2)

其中a1和a2都为无符号数组,al1和al2为数组的长度,数组的长度为偶数。

无符号数组由一对数字区间组成。如下例:
a1 为 0,1,3,6,10,20
a2 为 0,1,20,50,4,5
则 a1表示以下区间[0,1] [3,6] [10,20]
     a2表示以下区间[0,1] [20,50] [4,5]
  
则a1,a2的重叠部分为[0,1] [4,5],其长度为2,函数foo要求返回重叠区间的长度。上例中为2。

要求:
详细说明自己的解题思路,说明自己实现的一些关键点。
写出函数foo原代码,另外效率尽量高,并给出代码的复杂性分析。

限制:
al1和al2的长度不超过100万。而且同一个数组的区间可能出现重重叠。
如a1可能为 0,5,  4,8,  9,100,  70,80

使用的存储空间尽量小。

#include <iostream>
#include <algorithm>
using namespace std;

class data
{
public:
    unsigned int first;
    unsigned int second;
    friend bool operator<( const data & d1, const data& d2);
};

inline bool operator<( const data & d1, const data& d2)
{
    return d1.first < d2.first;
}

int foo(unsigned int *a1, int al1, unsigned int* a2, int al2)
{
    data * d1 = (data*) a1;
    data * d2 = (data*) a2;

    sort(d1, d1+al1/2, less<data>());
    sort(d2, d2+al2/2, less<data>());

    int len = 0;
    for( int i =0, j = 0; (i < al1/2 && j < al2/2);)
    {
        if(d1[i].second <= d2[j].first)
        {
            i++;
        }
        else if(d1[i].first >= d2[j].second)
        {
            j++;
        }
        else
        {
            if(d1[i].first <= d2[j].first && d2[j].second <= d1[i].second)
            {
                len += d2[j].second - d2[j].first;
                j++;
            }
            else if(d2[j].first <= d1[i].first && d2[j].second >= d1[i].second)
            {
                len += d1[i].second - d1[i].first;
                i++;
            }
            else if( d1[i].first >= d2[j].first && d1[i].first < d2[j].second && d1[i].second >= d2[j].second)
            {
                len += d2[j].second - d1[i].first;
                j++;
            }
            else if( d2[j].first >= d1[i].first && d2[j].first < d1[i].second && d2[j].second >= d1[i].second)
            {
                len += d1[i].second - d2[j].first;
                i++;
            }
        }
    }

    return len;
}

int main()
{
    unsigned int a1[] = { 0, 1, 3, 6, 10, 20};
    unsigned int a2[] = { 0, 1, 20,50, 4, 5};
    int len = foo( a1, 6, a2, 6);
    cout << "len: " << len << endl;
    return 0;
}

2. 多人排成一个队列,我们认为从低到高是正确的序列,但是总有部分人不遵守秩序。如果说,前面的人比后面的人高(两人身高一样认为是合适的)

        那么我们就认为这两个人是一对“捣乱分子”,
        比如说,现在存在一个序列:
                176, 178, 180, 170, 171
        这些捣乱分子对为 <176, 170>,<176, 171>,<178, 170>,<178, 171>,<180, 170>,<180, 171>
        那么,现在给出一个整型序列,请找出这些捣乱分子对的个数(仅给出捣乱分子对的数目即可,不用具体的对)

要求:
输入:
为一个文件(in),文件的每一行为一个序列。序列全为数字,数字间用”,”分隔。
输出:
为一个文件(out),每行为一个数字,表示捣乱分子的对数。

详细说明自己的解题思路,说明自己实现的一些关键点。并给出实现的代码 ,并分析时间复杂度。

限制:
输入每行的最大数字个数为100000个,数字最长为6位。程序无内存使用限制。

归并的方法求数组的逆序数。

#include <iostream>
using namespace std ;

void merge(int * a, int *p, int start, int mid, int end, int & count)
{
	int i = 0, j = 0;
	for(i = start; i <= mid; i++)   // 将数据复制到辅助空间
		p[i] = a[i] ;
	for(j = mid + 1; j <= end; j++)
		p[j] = a[j];

	i = start;
	j = mid + 1;
	int w = start;
	while( i <= mid && j <= end)
	{
		if(p[i] <= p[j])
		{
			a[w++] = p[i++];
		}
		else
		{
			count +=  mid - i + 1;     //注意此处的处理
			a[w++] = p[j++];
		}
	}

	while(i <= mid)
	{
		a[w++] = p[i++];
	}

	while(j <= end)
	{
		a[w++] = p[j++];
	}
}

void mergeSort(int *a, int *p, int start, int end, int &count)
{
	if(start < end)
	{
		int mid = ( start + end) / 2;
		mergeSort( a, p, start, mid, count);
		mergeSort( a, p, mid + 1, end, count);
		merge( a, p, start, mid, end, count);
	}
}

int main()
{
	int a[5];
    int n = 5;
    int * p = new int[5];
	if(n > 0)
	{
		int count = 0;
		for(int i = 0; i < n; i++)
		{
            a[i] = rand();
            cout << a[i] << " ";
        }
        cout << endl;

		mergeSort( a, p, 0, n - 1, count);
		cout << count << endl;
    }

    delete [] p;
	return 0;
}

3. 合并有序数组的前后段

         数组al[0,mid-1] 和 al[mid,num-1],都分别有序。将其merge成有序数组al[0,num-1],要求空间复杂度O(1)

         思路:就是将前半段比后半段大的元素,在后半段进行插入排序(从前向后插入,而不是从后往前),此处注意一个问题,在拿前面元素向后半段插入时,后半段肯定有空间可用,因为已经将它的一个元素放入了前半段有序数组中。

#include <iostream>
using namespace std ;

void merge(int a[], int len)
{
    int mid = len / 2;

    for( int i = 0, j = mid; i < mid; )
    {
        if( a[i] <= a[j])    // 前半部分的大
        {
            i++;
        }
        else
        {
            int tmp = a[i];
            a[i] = a[j];
            i++;
            int index = j + 1;
            if( tmp <= a[index])
            {
                a[j] = tmp;
            }
            else
            {
                while(tmp > a[index] && index < len)
                {
                    a[index - 1] = a[index];
                    index ++;
                }
                a[index-1] = tmp;
            }
        }// end of else
    }// end of for
}

int main()
{
    int a[10] = {1, 3, 5, 9, 13, 4, 7, 11, 12, 19};
    for( int i = 0; i < 10; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    merge(a, 10);
    for( int i = 0; i < 10; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;

	return 0;
}


4. 随机输入一个数,判断它是不是对称数(回文数)(如3,121,12321,45254)。不能用字符串库函数

思路: 首先将数字转化为字符串(由于只是判断是否是回文数,因此转化为字符串之后的正序逆序并不重要),然后判断字符串是否是对称的。

#include <iostream>
using namespace std ;

bool IsSymmetry(char * str)
{
    int len = strlen(str);
    char * p = str, *q = str+len-1;
    while(p < q)
    {
        if( *p == *q)
        {
            p++;
            q--;
        }
        else
        {
            return false;
        }
    }

    return true;
}

void int2str(int n, char * str)
{
    if(n <= 0 || str == NULL)
    {
        return ;
    }

    int index = 0;
    while(n > 0)
    {
        str[index++] = '0' + n % 10;
        n /= 10;
    }

    return ;
}

int main()
{
    int input;
    cout << "Input a number:";
    cin >> input;
    cout << endl;

    char str[256]; memset(str, 0, sizeof(str));
    int2str(input, str);
    if(IsSymmetry(str))
    {
        cout << "回文数" << endl;
    }
    else
    {
        cout << "非回文数" << endl;
    }
	return 0;
}

5.  A,B,C,D 四个进程,A 向 buf 里面写数据,B,C,D 向 buf 里面读数据,当 A 写完,且B ,C ,D都读一次后,A 才能再写。用PV操作实现。


解答:
        一个生产者,三个消费者,公用 1 个缓冲区
        在这个问题中,不仅生产者与消费者之间要同步,同时每生产一个产品,三个消费者必须并且只能消费一次。


        定义四个信号量:
        mutexB—— 消费者 B 和生产者之间的互斥信号量,初值为 1 。
        mutexC—— 消费者 C 和生产者之间的互斥信号量,初值为 1 。
        mutexD—— 消费者 D 和生产者之间的互斥信号量,初值为 1 。

// 生产者进程
while(TRUE)
{
     生产一个产品 ;
     // 因为这里需要确认三个消费者都已经消费了
     P(mutexB);
     P(mutexC);
     P(mutexD);
     产品送往 buffer();
     // 三个消费者可以消费了
     V(mutexB);
     V(mutexC);
     V(mutexD);
}// 消费者进程 B ,每个产品,该消费者只能消费一次while(TRUE){        P(mutexB);        从 buffer() 中取出产品 ;        V(mutexB);        消费该产品 ;}// 消费者进程 C ,每个产品,该消费者只能消费一次while(TRUE){        P(mutexC);        从 buffer() 中取出产品 ;        V(mutexC);        消费该产品 ;}// 消费者进程 D, 每个产品,该消费者只能消费一次while(TRUE){        P(mutexD);        从 buffer() 中取出产品 ;        V(mutexD);        消费该产品 ;}



By Andy  @ 2013-9-28



CSDN嵌入式笔试面试题系列是CSDN提供的面向嵌入式系统工程师的一系列笔试,旨在评估面试者在嵌入式领域的知识和技能。 这些面试题涵盖了嵌入式系统的各个方面,包括硬件设计、嵌入式软件开发、嵌入式操作系统等。通过回答这些题面试者可以展示他们的专业知识、问题解决能力和团队协作能力。 作为一个嵌入式系统工程师,我会通过以下几个方面来回答这一系列的面试题: 1. 硬件设计:我会解释如何设计一个嵌入式系统的硬件架构,包括选择核心处理器、外设接口的设计和电路设计等。 2. 嵌入式软件开发:我会谈谈自己的嵌入式软件开发经验,包括使用哪些开发工具和编程语言,如何进行软件调试和优化。 3. 嵌入式操作系统:我会介绍我在嵌入式操作系统方面的经验和知识,包括熟悉的操作系统类型,如RTOS和Linux,以及如何进行任务调度和内存管理等。 4. 项经验:我会分享我在嵌入式项中的经验,包括完成的项类型、任务分工和团队合作等。 5. 学习与发展:我会表达自己对嵌入式领域的学习态度和发展意愿,包括对新技术的关注和学习计划等。 综上所述,CSDN嵌入式笔试面试题系列是一系列用来评估嵌入式系统工程师技能的笔试。通过回答这些题面试者可以展示他们的专业知识和技能,并展示自己在嵌入式领域的学习态度和发展潜力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值