Files
2020-11-23 22:17:33 +08:00

116 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [1664. Ways to Make a Fair Array](https://leetcode.com/problems/ways-to-make-a-fair-array/)
## 题目
You are given an integer array `nums`. You can choose **exactly one** index (**0-indexed**) and remove the element. Notice that the index of the elements may change after the removal.
For example, if `nums = [6,1,7,4,1]`:
- Choosing to remove index `1` results in `nums = [6,7,4,1]`.
- Choosing to remove index `2` results in `nums = [6,1,4,1]`.
- Choosing to remove index `4` results in `nums = [6,1,7,4]`.
An array is **fair** if the sum of the odd-indexed values equals the sum of the even-indexed values.
Return the ***number** of indices that you could choose such that after the removal,* `nums` *is **fair**.*
**Example 1:**
```
Input: nums = [2,1,6,4]
Output: 1
Explanation:
Remove index 0: [1,6,4] -> Even sum: 1 + 4 = 5. Odd sum: 6. Not fair.
Remove index 1: [2,6,4] -> Even sum: 2 + 4 = 6. Odd sum: 6. Fair.
Remove index 2: [2,1,4] -> Even sum: 2 + 4 = 6. Odd sum: 1. Not fair.
Remove index 3: [2,1,6] -> Even sum: 2 + 6 = 8. Odd sum: 1. Not fair.
There is 1 index that you can remove to make nums fair.
```
**Example 2:**
```
Input: nums = [1,1,1]
Output: 3
Explanation: You can remove any index and the remaining array is fair.
```
**Example 3:**
```
Input: nums = [1,2,3]
Output: 0
Explanation: You cannot make a fair array after removing any index.
```
**Constraints:**
- `1 <= nums.length <= 105`
- `1 <= nums[i] <= 104`
## 题目大意
给你一个整数数组 nums 。你需要选择 恰好 一个下标(下标从 0 开始并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。
比方说如果 nums = [6,1,7,4,1] ,那么:
- 选择删除下标 1 剩下的数组为 nums = [6,7,4,1] 。
- 选择删除下标 2 剩下的数组为 nums = [6,1,4,1] 。
- 选择删除下标 4 剩下的数组为 nums = [6,1,7,4] 。
如果一个数组满足奇数下标元素的和与偶数下标元素的和相等,该数组就是一个 平衡数组 。请你返回删除操作后剩下的数组 nums  平衡数组 的 方案数 。
## 解题思路
- 给定一个数组 nums要求输出仅删除一个元素以后能使得整个数组平衡的方案数。平衡的定义是奇数下标元素总和等于偶数下标元素总和。
- 这一题如果暴力解答,会超时。原因是每次删除元素以后,都重新计算奇偶数位总和比较耗时。应该利用前面计算过的累加和,推导出此次删除元素以后的情况。这样修改以后就不超时了。具体的,如果删除的是元素是奇数位,这个下标的前缀和不变,要变化的是后面的。删除元素后面,原来偶数位的总和变成了奇数位了,原来奇数位的总和变成偶数位了。删除元素后面这半段的总和可以用前缀和计算出来,奇数位的总和减去删除元素的前缀和,就得到了删除元素后面的后缀和。通过这个办法就可以得到删除元素后面的,奇数位总和,偶数位总和。注意这个后缀和是包含了删除元素的。所以最后需要判断删除元素是奇数位还是偶数位,如果是奇数位,那么在计算出来的偶数和上再减去这个删除元素;如果是偶数位,就在计算出来的奇数和上再减去这个删除元素。代码见解法二。
- 这一题还有一种更简洁的写法,就是解法一了。通过了解法二的思考,我们可以知道,每次变换以后的操作可以抽象出来,即三步,减去一个数,判断是否相等,再加上一个数。只不过这三步在解法二中都去判断了奇偶性。如果我们不判断奇偶性,那么代码就可以写成解法一的样子。为什么可以不用管奇偶性呢?因为每次删除一个元素以后,下次再删除,奇偶就发生颠倒了,上次的奇数和到了下次就是偶数和了。想通这一点就可以把代码写成解法一的样子。
## 代码
```go
// 解法一 超简洁写法
func waysToMakeFair(nums []int) int {
sum, res := [2]int{}, 0
for i := 0; i < len(nums); i++ {
sum[i%2] += nums[i]
}
for i := 0; i < len(nums); i++ {
sum[i%2] -= nums[i]
if sum[i%2] == sum[1-(i%2)] {
res++
}
sum[1-(i%2)] += nums[i]
}
return res
}
// 解法二 前缀和,后缀和
func waysToMakeFair1(nums []int) int {
evenPrefix, oddPrefix, evenSuffix, oddSuffix, res := 0, 0, 0, 0, 0
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix += nums[i]
} else {
oddSuffix += nums[i]
}
}
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix -= nums[i]
} else {
oddSuffix -= nums[i]
}
if (evenPrefix + oddSuffix) == (oddPrefix + evenSuffix) {
res++
}
if i%2 == 0 {
evenPrefix += nums[i]
} else {
oddPrefix += nums[i]
}
}
return res
}
```