Skip to content

Commit 86d7f8d

Browse files
committed
✨feat: Add 462
1 parent 69aacc7 commit 86d7f8d

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

Index/数学.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
| [446. 等差数列划分 II - 子序列](https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/solution/gong-shui-san-xie-xiang-jie-ru-he-fen-xi-ykvk/) | 困难 | 🤩🤩🤩🤩🤩 |
3232
| [453. 最小操作次数使数组元素相等](https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-tt3zu/) | 中等 | 🤩🤩🤩 |
3333
| [458. 可怜的小猪](https://leetcode-cn.com/problems/poor-pigs/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/poor-pigs/solution/gong-shui-san-xie-jin-zhi-cai-xiang-xian-69fl/) | 困难 | 🤩🤩🤩🤩 |
34+
| [462. 最少移动次数使数组元素相等 II](https://leetcode.cn/problems/minimum-moves-to-equal-array-elements-ii/) | [LeetCode 题解链接](https://leetcode.cn/problems/minimum-moves-to-equal-array-elements-ii/solution/by-ac_oier-db44/) | 中等 | 🤩🤩🤩 |
3435
| [470. 用 Rand7() 实现 Rand10()](https://leetcode-cn.com/problems/implement-rand10-using-rand7/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/implement-rand10-using-rand7/solution/gong-shui-san-xie-k-jin-zhi-zhu-wei-shen-zmd4/) | 中等 | 🤩🤩🤩🤩 |
3536
| [477. 汉明距离总和](https://leetcode-cn.com/problems/total-hamming-distance/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/total-hamming-distance/solution/gong-shui-san-xie-ying-yong-cheng-fa-yua-g21t/) | 简单 | 🤩🤩🤩 |
3637
| [479. 最大回文数乘积](https://leetcode-cn.com/problems/largest-palindrome-product/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/largest-palindrome-product/solution/by-ac_oier-t8j7/) | 困难 | 🤩🤩🤩 |
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[462. 最少移动次数使数组元素相等 II](https://leetcode.cn/problems/minimum-moves-to-equal-array-elements-ii/solution/by-ac_oier-db44/)** ,难度为 **简单**
4+
5+
Tag : 「数学」
6+
7+
8+
9+
给你一个长度为 $n$ 的整数数组 $nums$,返回使所有数组元素相等需要的最少移动数。
10+
11+
在一步操作中,你可以使数组中的一个元素加 $1$ 或者减 $1$ 。
12+
13+
示例 1:
14+
```
15+
输入:nums = [1,2,3]
16+
17+
输出:2
18+
19+
解释:
20+
只需要两步操作(每步操作指南使一个元素加 1 或减 1):
21+
[1,2,3] => [2,2,3] => [2,2,2]
22+
```
23+
示例 2:
24+
```
25+
输入:nums = [1,10,2,9]
26+
27+
输出:16
28+
```
29+
30+
提示:
31+
* $n == nums.length$
32+
* $1 <= nums.length <= 10^5$
33+
* $-10^9 <= nums[i] <= 10^9$
34+
35+
---
36+
37+
### 数学
38+
39+
假定所有的 $nums[i]$ 均位于数轴上的 $nums[i]$ 的位置,题目要求我们在数轴上找出一个点 $t$,使得所有 $nums[i]$ 到 $t$ 的距离之和最小。
40+
41+
**首先,容易证明 $t$ 不可能位于最小的 $nums[i]$ 的左侧,也不可能位于最大的 $nums[i]$ 的右侧,否则我们「至少」能够将目标点调整为 最小的 $nums[i]$ 或 最大的 $nums[i]$ 来得到更小的距离总和。**
42+
43+
> 其实由上述这一点进行推广,已经可以证明最优点必然是在中间点($nums$ 数量为奇数时)或者中间两点形成的闭区间中的任意点($nums$ 数量为偶数时)。
44+
但为了证明更加直观,我们仍从「反证法」的角度进行证明。
45+
46+
我们根据每个 $nums[i]$ 位于 $t$ 的左侧还是右侧进行划分:假设位于 $t$ 左侧的 $nums[i]$ 对答案的贡献为 $A$,位于 $t$ 右侧的 $nums[i]$ 对答案的贡献为 $B$,最终目的是为了让 $A + B$ 最小。
47+
48+
我们猜想当 $t$ 取中位数时,$A + B$ 取得最小值,并通过「反证法」进行证明:
49+
50+
* 假设真实最优解 $t'$ 位于中位数 $t$ 的 左侧:假设调整距离为 $d$,导致变化的点数为 $x$,则有左边总和为 $A - xd$,右边总和为 $B + (n - x)d$,总和为 $A + B - 2xd + nd$,如果要使得结果更好,需要满足 $nd - 2xd < 0$,即满足 $x > \frac{n}{2}$,这与我们本身 $t$ 为中位数,即左右两边数的个数均为 $\frac{n}{2}$ 冲突(特别地,当 $nums$ 为偶数时,且目标点位于中间两点中的任一点时,左右数的个数并非为 $\frac{n}{2}$,但距离总和情况与 $t$ 位于两点间的其余点的情况一致);
51+
52+
* 假设真实最优解 $t'$ 位于中位数 $t$ 的 右侧:同理。
53+
54+
代码:
55+
```Java
56+
class Solution {
57+
public int minMoves2(int[] nums) {
58+
Arrays.sort(nums);
59+
int n = nums.length, t = nums[(n - 1) / 2], ans = 0;
60+
for (int i : nums) ans += Math.abs(t - i);
61+
return ans;
62+
}
63+
}
64+
```
65+
* 时间复杂度:$O(n\log{n})$
66+
* 空间复杂度:$O(\log{n})$
67+
68+
---
69+
70+
### 最后
71+
72+
这是我们「刷穿 LeetCode」系列文章的第 `No.462` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
73+
74+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
75+
76+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
77+
78+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
79+

LeetCode/721-730/729. 我的日程安排表 I(中等).md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
这是 LeetCode 上的 **[729. 我的日程安排表 I](https://leetcode-cn.com/problems/my-calendar-i/solution/by-ac_oier-1znx/)** ,难度为 **中等**
44

5-
Tag : 「模拟」、「红黑树」、「线段树」、「动态开点」
5+
Tag : 「模拟」、「红黑树」、「线段树动态开点
66

77

88

@@ -102,7 +102,7 @@ class MyCalendar {
102102

103103
由于存在「懒标记」,线段树的插入和查询都是 $\log{n}$ 的,因此我们在单次操作的时候,最多会创建数量级为 $\log{n}$ 的点,因此空间复杂度为 $O(m\log{n})$,而不是 $O(4 \times n)$,而开点数的预估需不能仅仅根据 $\log{n}$ 来进行,还要对常数进行分析,才能得到准确的点数上界。
104104

105-
动态开点相比于原始的线段树实现,本质仍是使用「满二叉树」的形式进行存储,只不过是按需创建区间,如果我们是按照连续段进行查询或插入,最坏情况下仍然会占到 $4 * n$ 的空间,因此盲猜 $\log{n}$ 的常数在 $4$ 左右,保守一点可以直接估算到 $6$,因此我们可以估算点数为 $6 * m * \log{n}$,其中 $n = 1e9$ 和 $m = 1e3$ 分别代表值域大小和查询次数。
105+
动态开点相比于原始的线段树实现,本质仍是使用「满二叉树」的形式进行存储,只不过是按需创建区间,如果我们是按照连续段进行查询或插入,最坏情况下仍然会占到 $4 \times n$ 的空间,因此盲猜 $\log{n}$ 的常数在 $4$ 左右,保守一点可以直接估算到 $6$,因此我们可以估算点数为 $6 \times m \times \log{n}$,其中 $n = 1e9$ 和 $m = 1e3$ 分别代表值域大小和查询次数。
106106

107107
当然一个比较实用的估点方式可以「尽可能的多开点数」,利用题目给定的空间上界和我们创建的自定义类(结构体)的大小,尽可能的多开( `Java` 的 $128M$ 可以开到 $5 \times 10^6$ 以上)。
108108

0 commit comments

Comments
 (0)