leetcode算法题3:分组,让每个组的最小者,相加之后和最大。想知道桶排序是怎么样的吗?...

/* Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1, b1), (a2, b2), ..., (an, bn) which makes sum of min(ai, bi) for all i from 1 to n as large as possible.

Example 1: Input: [1,4,3,2]

Output: 4 Explanation: n is 2, and the maximum sum of pairs is 4. Note: n is a positive integer, which is in the range of [1, 10000]. All the integers in the array will be in the range of [-10000, 10000].

*/

int arrayPairSum(int* nums, int numsSize) {

}

###题意:两两分组,然后取每组的最小值来求和,让和最大。


###办法1: * 把数组排序,升序。邻近的两个数作为一组。

* i=0开始,取nums[i*2]来相加,i=numsSize/2时结束。相加出来的值就是目标值。

* 时间复杂度O(nlogn)。

###办法2: * 桶排序

   以每个元素的值+10000作为索引。

   * 需要多大的空间?

      因为已知每个数的范围为[-10000,10000],所以需要20001长度的数组才能绝对容纳这些数。

   * 具体如何排序?

      * 初始化长度为20001的数组v,每个元素为 0。

      * 遍历nums,假设每个数为i,以i+10000作为索引,命中数组中的某一个vi(bucket),使vi++。

* 排序后,如何求和?

   遍历v,在vi不为0的情况下,取一个,放一个,取出来的加至sum。最终sum为目标值。i-10000为原数值。

* 时间复杂度O(n),使用空间换时间。


   * 基础概念

* c提供的快排的函数为qsort,4个参数,第1参数为void*表示数组,第2个参数为元素的个数,第3个参数为每个元素的大小,最后一个参数为比较函数。比较函数为自定义函数,形式如下:

int comp(const void* l, const void* r) {
	int lv = *((int*)l);
	int rv = *((int*)r);
	if (lv > rv) {
		return 1;
	}
	else if (lv < rv) {
		return -1;
	}
	return 0;
}

* 桶排序,是一种非比较的排序,比快排要快,但空间消耗也多。要求是,能事先确定每个数值的范围,保持创建的数组能够容纳所有的数。一般以数的值(或运算后的值)作为数组的索引,之后根据索引也能反算出原值。

* 桶排序后的结构可能是:

bucket_sort

* 异或的办法可以作为”抓一放一”的手段,比如设j=1,每次j^=1,那j就会从1跟0间变化。


#include <stdio.h>
#include <stdlib.h>

int comp(const void* l, const void* r) {
	int lv = *((int*)l);
	int rv = *((int*)r);
	if (lv > rv) {
		return 1;
	}
	else if (lv < rv) {
		return -1;
	}
	return 0;
}
int arrayPairSum(int* nums, int numsSize) {
	qsort(nums, numsSize, sizeof(int), comp);    
	int i=0;
	int sum = 0;
	while (i < numsSize>>1) {
		sum += nums[i++*2];	
	}
	return sum;
}

int main(int argc, char *argv[])
{
	int arr[] = {1, 4, 3, 2};
	printf("%d\n", arrayPairSum(arr, sizeof arr/sizeof *arr));
	return 0;
}

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

class Solution {
public:
    int arrayPairSum(vector<int>& nums) {
		vector<int> buckets(20001, 0);
		for (auto i : nums) {
			buckets[i+10000] ++;	
		}
		int sum = 0;
		for (int i = 0, j=1; i < 20001;) {
			if (buckets[i] > 0) {
				if (j==1) {
					sum += i-10000;
				}
				j^=1;
				buckets[i]--;
			}
			else {
				i ++;
			}
		}
		return sum;
    }

    int arrayPairSum2(vector<int>& nums) {
		vector<int> buckets(20001, 0);
		for (auto i : nums) {
			buckets[i+10000] ++;	
		}
		int sum = 0;
		for (int i = 0, j=1; i < 20001; i++) {
			while (buckets[i] > 0) {
				if (j==1) {
					sum += i-10000;
				}
				j^=1;
				buckets[i]--;
			}
		}
		return sum;
    }
};

int main(int argc, const char *argv[])
{
	Solution so;
	int arr[] = {1,4,3,2};
	vector<int> v(arr, arr+sizeof arr/sizeof *arr);
	cout << so.arrayPairSum2(v) << endl;
	return 0;
}

转载于:https://my.oschina.net/u/3613477/blog/1417340

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值