刷题笔记:牛客腾讯笔试题——有趣的数字

题目

小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,差最小的有多少对呢?差最大呢?

输入描述:

 输入包含多组测试数据。
 对于每组测试数据:
 N - 本组测试数据有n个数
 a1,a2...an - 需要计算的数据
 保证:
 1<=N<=100000,0<=ai<=INT_MAX.

输出描述:

对于每组数据,输出两个数,第一个数表示差最小的对数,第二个数表示差最大的对数。

示例1
输入

6
45 12 45 32 5 6

输出

1 2

思路

该题考察看似简单,实际坑很深。首先吐槽下题目,上厕所也要考虑这么多吗?不过真的是个好题,这就是腾讯崇尚的价值观?害怕。。。。。

求最大值比较容易,对数组排序后,队尾减去队首就是最大差值。需要考虑队首和队尾存在重复数的情况,也就是要分别找数组中最大数和最小数的个数 Nmax N m a x Nmin N m i n ,最大差值对数就等于 NmaxNmin N m a x ∗ N m i n

第一个坑来了:如果输入为常数列,那最大值等于最小值,此时 Nmax=Nmin N m a x = N m i n 就等于数组元素总数N,但最大差值对数实际就等于N的排列组合 N(N1)/2 N ∗ ( N − 1 ) / 2 ,这个坑貌似题目测试用例没有给到,牛客讨论区的一些答案并没有考虑到。

求最小值复杂许多,我是首先对排序后的数组的相邻元素求差值,得到差值列,相比原数列长度-1。然后对差值列再排序,从最左端求最小数的个数 Nmin N m i n ,即为最小差值对数就等于 Nmin+1 N m i n + 1 的排列组合 (Nmin+1)Nmin/2 ( N m i n + 1 ) ∗ N m i n / 2

第二个坑来了:如果输入数组中存在重复数字,比如输入数组为[1 1 1 2 3 3 4],按上面的思路先得到差值列[0 0 1 0 1],排序后为[0 0 0 1 1],最小差值数0有3个,则最小差值对数为6。而实际上,最小差值0是3个1和2个3分别得到的,此时最小差值对数不等于 Nmin+1 N m i n + 1 的排列组合,最小差值对数应为 3+1=4 3 + 1 = 4 个。因此存在于有重复数字时,因此需要找到重复数字并统计其个数,最小差值等于各自数量的排列组合的和。

代码

#include   
#include 
#include 


using namespace std;  

int main()
{
    int n;
    while(cin>>n)
    {
        vector<int> nums(n,0);
        for(int i=0;icin>>nums[i];
        }

        sort(nums.begin(),nums.end());
        int m1 = 1;
        int m2 = 1;
        int max = 0;
        if(nums[n-1]==nums[0])
        {
            max=n*(n-1)/2;
            cout<" "<continue;
        }
        for (int i = 0; i < n-1; ++i)
        {
                if (nums[i + 1] != nums[i])
                        break;
                ++m1;
        }
        for (int i = n - 1; i > 0; --i)
        {
                if (nums[i - 1] != nums[i])
                        break;
                ++m2;
        }
        max = m1*m2;

        int min=0;
        int temp=INT32_MAX;

        for(int i=1;i1]=nums[i]-nums[i-1];
            if(temp>nums[i-1])
                temp=nums[i-1];
        }
        nums.erase(nums.end()-1);
        int count=1;
        if(temp==0)
        {
            for(int i=0;i1;i++)
            {
                if(nums[i]==0)
                {
                    count++;
                }
                else
                {
                    min+=count*(count-1)/2;
                    count=1;
                }
            }
            if(nums[n-2]==0)
                min+=count*(count-1)/2;
        }
        else
        {
            min++;
            sort(nums.begin(),nums.end());
            for(int i=1;i1;i++)
            {
                if(nums[i]==nums[0])
                    min++;
                else
                {
                    break;
                }
            }
        }
        cout<" "<

你可能感兴趣的:(刷题,刷题笔记)