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;

}

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

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

* 异或的办法可以作为”抓一放一”的手段,比如设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;

}

时间: 2024-10-29 06:54:09

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

LeetCode算法题-License Key Formatting(Java实现)

这是悦乐书的第241次更新,第254篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第108题(顺位题号是482).您将获得一个表示为字符串S的许可证密钥,该字符串仅包含字母数字字符和短划线.该字符串被N个破折号分成N + 1个组. 给定数字K,我们希望重新格式化字符串,使得每个组包含正好的K个字符,但第一个组可能比K短,但仍然必须包含至少一个字符.此外,必须在两个组之间插入短划线,并且所有小写字母都应转换为大写.给定非空字符串S和数字K,根据上述规则格式化字符串.例

LeetCode算法题-Find Mode in Binary Search Tree(Java实现)

这是悦乐书的第246次更新,第259篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第113题(顺位题号是501).给定具有重复项的二叉搜索树(BST),找到给定BST中的所有模式(最常出现的元素).假设BST定义如下: 节点的左子树仅包含键小于或等于节点键的节点. 节点的右子树仅包含键大于或等于节点键的节点. 左右子树也必须是二叉搜索树. 例如: 鉴于BST [1,null,2,2], 1 2 / 2 返回[2]. 注意:如果树有多个模式,您可以按任何顺序返回它们.

LeetCode算法题-Longest Uncommon Subsequence I(Java实现)

这是悦乐书的第252次更新,第265篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第119题(顺位题号是521).给定一组两个字符串,您需要找到这组两个字符串中最长的不同子序列.最长的不同子序列被定义为这些字符串之一的最长子序列,并且此子序列不应该是其他字符串的任何子序列. 子序列是可以通过删除一些字符而不改变其余元素的顺序从一个序列导出的序列.任何字符串都是其自身的子序列,空字符串是任何字符串的子序列.输入将是两个字符串,输出需要是最长的不同子序列的长度.如果最长

LeetCode算法题-Shortest Unsorted Continuous Subarray(Java实现)

这是悦乐书的第267次更新,第281篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第134题(顺位题号是581).给定一个整数数组,找到一个连续的子数组,按升序对该子数组进行排序,使得整个数组也按升序排序.找到最短的无序连续子数组并输出其长度.例如: 输入:[2,6,4,8,10,9,15] 输出:5 说明:按升序对[6,4,8,10,9]子数组进行排序,以使整个数组按升序排序. 注意: 数组的长度在[1,100]范围内. 数组可能包含重复项,因此这里的升序表示<=

LeetCode算法题-Average of Levels in Binary Tree(Java实现)

这是悦乐书的第277次更新,第293篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第145题(顺位题号是637).给定一个非空二叉树,以数组的形式返回每一层节点值之和的平均值.例如: 3 / 9 20 / 15 7 输出:[3,14.5,11] 说明:第一层上的节点的平均值为3,第二层上的节点的平均值为14.5,第三层上的节点的平均值为11.因此返回[3,14.5,11]. 注意:节点值的范围在32位有符号整数的范围内. 本次解题使用的开发工具是eclipse,jd

LeetCode算法题-Maximum Average Subarray I(Java实现)

这是悦乐书的第278次更新,第294篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第146题(顺位题号是643).给定由n个整数组成的数组,找到具有最大平均值的长度为k的连续子数组,并输出最大平均值.例如: 输入:[1,12,-5,-6,50,3],k = 4 输出:12.75 说明:最大平均值为(12-5-6 + 50)/ 4 = 51/4 = 12.75 注意: 1 <= k <= n <= 30,000. 给定数组的元素将在[-10,000,10,00

LeetCode算法题-Count Binary Substrings(Java实现)

这是悦乐书的第293次更新,第311篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第161题(顺位题号是696).给定一个字符串s,计算具有相同数字0和1的非空且连续子串的数量,并且这些子串中的所有0和所有1都是连续的.重复出现的子串也计算在内.例如: 输入:"00110011" 输出:6 说明:有6个子串具有相同数量的连续1和0:"0011","01","1100","10"

Leetcode 算法题--ReverseWordsInString

翻转字符串,想到什么写什么...我的做法是先trim掉空格,然后从字符串尾部开始扫描,遇到空格则认为一个单词结束,然后copy这个单词.需要注意的地方在于当扫描到最后一个单词的第一个字母时(譬如the sky is blue的t字母),注意单词长度的自增逻辑. 网上还有人的做法是反转整个字符串,然后逐个翻转单词. 1 package edu.hust.sse.Problems; 2 3 //Given s = "the sky is blue", 4 //return "bl

【算法】LeetCode算法题-Count And Say

这是悦乐书的第153次更新,第155篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第12题(顺位题号是38).count-and-say序列是整数序列,前五个术语如下: 1 11 21 1211 111221 1被读作"一个一"或者11.第二项的值是第一项的读法. 11被读作"两个一"或者21.第三项的值是第二项的读法. 21被读作"一个二,两个一"或者1211.第四项的值是第三项的读法. 给定整数n,其中1≤n≤3

【算法】LeetCode算法题-Length Of Last Word

这是悦乐书的第155次更新,第157篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第14题(顺位题号是58).给定一个字符串,包含戴尔字母.小写字母和空格,返回最后一个单词的长度,如果最后一个单词不存在则返回0.另外,单词不包含空格.例如: 输入: "Hello World" 输出: 5 说明:最后一个单词为world,其长度为5 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试. 0