leetcode算法题3:分组,让每个组的极度小者,相加后和极其充分。想了解桶排序是何等的啊?LeetCode 1. Two Sum

/*
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.

Given an array of integers, return indices of the two numbers such that
they add up to a specific target.
You may assume that each input would have exactly one solution, and you
may not use the same element twice.

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

Example:

Given nums = [2, 7, 11, 15], target = 9,Because nums[0] + nums[1]
= 2 + 7 = 9,return [0,1].

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].

翻译:

受得一个平头频繁组,返回两只数之目,使其的及也一个靶价。
汝得要每个输入还只有发生一个答案,且一个素只能采取同样浅。

*/

Solution 1: 双重循环

采用还循环,遍历所有的情事,时间复杂度为 O(n^2) 。
以内层的大循环中,索引从 i + 1 开始。

//Kotlin
class Solution {
    fun twoSum(nums: IntArray, target: Int): IntArray {
        for (i in 0..(nums.size - 1))
            for (j in (i + 1)..(nums.size - 1))
                if (nums[i] + nums[j] == target)
                    return intArrayOf(i, j)
        return intArrayOf()
    }
}

int arrayPairSum(int* nums, int numsSize) {

Solution 1.1:

对地方的代码做一些细的优化,在率先又循环中计算另一个屡屡底价值,可以减少加减乘除次数。时间复杂度仍为
O(n^2) 。

//Kotlin
class Solution {
    fun twoSum(nums: IntArray, target: Int): IntArray {
        for (i in 0..(nums.size - 1)) {
            val remain = target - nums[i]
            for (j in (i + 1)..(nums.size - 1))
                if (nums[j] == remain)
                    return intArrayOf(i, j)
        }
        return intArrayOf()
    }
}

}

Solution 2:

另一样种艺术是对此已排序的一再组,从少端向中档查找。
将数组从小至非常排序,两单目录分别吗数组的率先独与末段一个素,如果简单单价值的胜出目标价,第二只寻引减1,反的第一个索引加1,直到片单数的及也目标价。

//Kotlin
class Solution {
    fun twoSum(nums: IntArray, target: Int): IntArray {
        val ns = nums.mapIndexed { index, i -> Pair(index, i) }.sortedBy { p -> p.second }
        var a = 0
        var b = ns.size - 1
        while (a != b) {
            val sum = ns[a].second + ns[b].second
            when {
                sum == target -> return intArrayOf(ns[a].first, ns[b].first)
                sum > target -> b--
                sum < target -> a++
            }
        }
        return intArrayOf()
    }
}

题意:两个别划分组,然后拿走每组的顶小值来求和,让与太充分。


Solution 3: 使用HashMap

遍历数组,每个循环中,尝试在HashMap中搜索第二单数之想值,如果找到,返回结果,否则将当前数字放入HashMap,用于下次查找。时间复杂度为O(n)。

//Kotlin
class Solution {
    fun twoSum(nums: IntArray, target: Int): IntArray {
        val map = HashMap<Int, Int>()
        nums.forEachIndexed { index, i ->
            val a = map.get(target - i)
            if (a != null) {
                return intArrayOf(a, index)
            }
            map.put(i, index)
        }
        return intArrayOf()
    }
}

办法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;
}

相关文章

Leave a Comment.