剑指Offer----扩展:有趣的数字(腾讯)

问题描述:


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

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

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

输入例子:
6
45 12 45 32 5 6

输出例子:
1 2

方法一:


分析:使用一个容器,将数组中两两数之差的绝对值放到到map容器中,如果差值相同,则map中对应的值加1,这种方法的缺点就是时间复杂度高,空间复杂度也高!!!双高!!!但是最容易想到!!!


源代码:

#include<iostream>
#include<map>

using namespace std;

int main()
{
	int n;
	while (cin>>n)
	{
		int *arr = new int[n];
		for (int i = 0; i < n; ++i)
			cin >> arr[i];

		map<int, int> mmap;
		int max = -INT_MAX;
		int min = INT_MAX;
		for (int i = 0; i < n - 1; ++i)
		{
			for (int j = i+1; j < n; ++j)
			{
				int result = arr[i] - arr[j];
				result = result >= 0 ? result : -result;
				if (result < min)
					min = result;
				if (result > max)
					max = result;
				
				mmap[result]++;
			}
		}

		cout << mmap[min] << " " << mmap[max] << endl;
		delete[] arr;

	}

	cout << __DATE__ << "  " << __TIME__ << endl;
	system("pause");
	return 0;
}

运行结果:
6
1 2 3 4 5 6
5 1
6
1 1 2 2 3 3
3 4
6
1 1 1 1 1 1
15 15
^Z
Aug 28 2016  16:30:47
请按任意键继续. . .


方法二:

分析:先将数组排序,那么最大的差值肯定就是最大数减去最小数,最小的差值肯定就是 两个相邻数的差值,还有就是特殊情况的处理,当数组中所有的数字都相同的时候的处理,当最小的差值为0的时候的情况的处理!


源代码:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main()
{
	int n;
	while (cin >> n)
	{
		if (n == 1)//如果只有一个数字的话
		{
			cout << 0 << " " << 0 << endl;
			continue;
		}

		if (n == 2)//如果只有两个数字的话
		{
			cout << 1 << " " << 1 << endl;
		}

		//含有3个以上的数字
		vector<int> data;
		while (n--)
		{
			int temp;
			cin >> temp;
			data.push_back(temp);
		}

		int len = data.size();
		sort(data.begin(), data.end());
		int min = data[1] - data[0];//最小的差值不一定是是头两个元素之差,但一定是相邻的元素之差
		for (int i = 2; i < len; ++i)
		{
			if ((data[i] - data[i - 1]) < min)
				min = data[i] - data[i - 1];
		}
		int min_count = 0;
		if (min == 0)//此时,应该找到元素相同的区域块,可能有很多块
		{
			for (int i = 1; i < len; ++i)
			{
				int j = i - 1;
				while (j >= 0 && data[i] == data[j])
				{
					++min_count;
					--j;
				}
			}
		}
		else//此时,应该是两个相邻的元素只差
		{
			for (int i = 1; i < len; ++i)
			{
				if ((data[i] - data[i - 1]) == min)
					min_count++;
			}
		}


		//最大差的数肯定是最右边的数减去最左边的数
		int max = data[len - 1] - data[0];
		int max_count = 0;
		//如果最大的数字不等于最小的数字,则统计最小数字的个数,统计最大数字的个数,相乘既得结果
		if (data[0] != data[len - 1])
		{
			int num_min = 1;
			for (int i = 1; i < len - 1; ++i)
			{
				if (data[i] == data[0])
					num_min++;
				else
					break;
			}

			int num_max = 1;
			for (int i = len - 2; i >= 0; --i)
			{
				if (data[i] == data[len - 1])
					num_max++;
				else
					break;
			}

			max_count = num_min*num_max;
		}
		else//如果最大的数字等于最小的数字
		{
			max_count = len*(len - 1) / 2;
		}
		cout << min_count << " " << max_count << endl;
	}

	cout << __DATE__ << "  " << __TIME__ << endl;
	system("pause");
	return 0;
}

运行结果:
6
1 2 3 4 5 6
5 1
6
1 1 2 2 3 3
3 4
6
1 1 1 1 1 1
15 15
^Z
Aug 28 2016  16:34:42
请按任意键继续. . .






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值