Update 0561 solution

This commit is contained in:
halfrost
2022-08-31 20:20:20 +08:00
parent 5ec282a5c7
commit 56d9c2ba75
6 changed files with 4 additions and 4 deletions

View File

@ -0,0 +1,19 @@
package leetcode
func arrayPairSum(nums []int) int {
array := [20001]int{}
for i := 0; i < len(nums); i++ {
array[nums[i]+10000]++
}
flag, sum := true, 0
for i := 0; i < len(array); i++ {
for array[i] > 0 {
if flag {
sum = sum + i - 10000
}
flag = !flag
array[i]--
}
}
return sum
}

View File

@ -0,0 +1,49 @@
package leetcode
import (
"fmt"
"testing"
)
type question561 struct {
para561
ans561
}
// para 是参数
// one 代表第一个参数
type para561 struct {
nums []int
}
// ans 是答案
// one 代表第一个答案
type ans561 struct {
one int
}
func Test_Problem561(t *testing.T) {
qs := []question561{
{
para561{[]int{}},
ans561{0},
},
{
para561{[]int{1, 4, 3, 2}},
ans561{4},
},
// 如需多个测试,可以复制上方元素。
}
fmt.Printf("------------------------Leetcode Problem 561------------------------\n")
for _, q := range qs {
_, p := q.ans561, q.para561
fmt.Printf("【input】:%v 【output】:%v\n", p, arrayPairSum(p.nums))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,58 @@
# [561. Array Partition](https://leetcode.com/problems/array-partition/)
## 题目
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 = min(1, 2) + min(3, 4).
```
**Note**:
1. **n** is a positive integer, which is in the range of [1, 10000].
2. All the integers in the array will be in the range of [-10000, 10000].
## 题目大意
给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) 使得从1 到 n 的 min(ai, bi) 总和最大。
## 解题思路
- 给定一个 2n 个数组,要求把它们分为 n 组一行,求出各组最小值的总和的最大值。
- 由于题目给的数据范围不大,[-10000, 10000],所以我们可以考虑用一个哈希表数组,里面存储 i - 10000 元素的频次,偏移量是 10000。这个哈希表能按递增的顺序访问数组这样可以减少排序的耗时。题目要求求出分组以后求和的最大值那么所有偏小的元素尽量都安排在一组里面这样取 min 以后,对最大和影响不大。例如,(1 , 1) 这样安排在一起min 以后就是 1 。但是如果把相差很大的两个元素安排到一起,那么较大的那个元素就“牺牲”了。例如,(1 , 10000),取 min 以后就是 1于是 10000 就“牺牲”了。所以需要优先考虑较小值。
- 较小值出现的频次可能是奇数也可能是偶数。如果是偶数,那比较简单,把它们俩俩安排在一起就可以了。如果是奇数,那么它会落单一次,落单的那个需要和距离它最近的一个元素进行配对,这样对最终的和影响最小。较小值如果是奇数,那么就会影响后面元素的选择,后面元素如果是偶数,由于需要一个元素和前面的较小值配对,所以它剩下的又是奇数个。这个影响会依次传递到后面。所以用一个 flag 标记,如果当前集合中有剩余元素将被再次考虑,则此标志设置为 1。在从下一组中选择元素时会考虑已考虑的相同额外元素。
- 最后扫描过程中动态的维护 sum 值就可以了。
## 代码
```go
package leetcode
func arrayPairSum(nums []int) int {
array := [20001]int{}
for i := 0; i < len(nums); i++ {
array[nums[i]+10000]++
}
flag, sum := true, 0
for i := 0; i < len(array); i++ {
for array[i] > 0 {
if flag {
sum = sum + i - 10000
}
flag = !flag
array[i]--
}
}
return sum
}
```