三道面试题

一、给定一个N个整数元素的数组,元素分别为A1, A2, A3....AN,每个元素分别对应一个权重W1(小于1的float), W2,W3....WN,其和为1,找出其中一个元素Ak,使所有小于Ak的元素的权重之和小于1/2,所有大于Ak的元素的权重之和>=1/2。
思路:首先将该数组按元素值的大小进行升序排列,同样的那个权值数组也要对应的进行排序,因为原先的那个数组的下标和权值数组的下标是相对应的,如果权值数组不跟着变化的,那么就无法知道某一个数的权值是多少了,就无法对应起来了。。
核心代码如下:

sum = w[1];//小于Ak的元素的权重之和
for(k=2;k<=n;k++)
{
	if(sum>1/2)
		return -1;          //没有找到符合要求的元素Ak
	if(sum < 1/2 && sum + w[k] <= 1/2)    //sum < 1/2 保证使所有小于Ak的元素的权重之和小于1/2。     sum + w[k] <= 1/2,使得小于等于Ak的元素权重之和小于等于1/2,也就是所有大于Ak的元素的权重之和>=1/2。
		return A[k];
	sum += w[k];
}

二、给定一个N个元素的整数,元素分别为A1,A2,A3....AN,将数组变为A1<A2>A3<A4......的锯齿状数组,时间复杂度?
这个题目比排序更好点,将数组分为两部分,前半部分的值全部小于后半部分的值,接下来从两个起始位置逐个取数就可以了。

首先用nth_element把数组划分,以中位数为分界点,所有小于中位数(x)的元素在x之前,大于x的元素在x之后。
然后从两头分别取一个小于x的数,大小x的数,保存到另一数组中。
nth_element的时间复杂度是O(n)的。

例如:
原数组 1 5 3 7 4 2 6
nth_后 1 3 2 4 7 6 5 (只保证4在中间,前三个不一定有序,但都比4小)
新数组 1 7 3 6 2 5 4

代码如下:

#include "iostream"
#include "algorithm"
using namespace std;

int main(void)
{
    int a[] = { 1, 5, 3, 7, 4, 2, 6 };
    int b[100];
    int size = sizeof( a ) / sizeof( a[0] );
    int mid = size / 2;
    nth_element( a, a+mid, a+size );
    int index1, index2, index3 = 0;
    for( index1 = 0, index2 = mid+1; index1 < mid; ++index1, ++index2 )
    {
        b[index3++] = a[index1];
        if( index2 < size )
            b[index3++] = a[index2];
    }
    b[index3] = a[mid];

    for( int i1 = 0; i1 < size; ++i1 )
    {
        cout << b[i1] << " ";
    }
	system("pause");
    return 0;
}

三、10个人去看电影,其中5个人每人只有5元的钞票,另外5个人每个人只有10元的钞票,电影票的票价是5元,现在10个人排队去买票,问有多少种排列的方法,使得每个人在买票的时候售票员都有钱找。



你可能感兴趣的:(面试题)