From 461f8a9a5d33558a55d6dec65eff3d14378af55c Mon Sep 17 00:00:00 2001
From: YDZ
Date: Fri, 6 Dec 2019 11:48:35 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20problem=20991?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Algorithms/0887. Super Egg Drop/README.md | 32 +++++++----
.../911. Online Election.go | 38 +++++++++++++
.../911. Online Election_test.go | 28 ++++++++++
Algorithms/0911. Online Election/README.md | 53 +++++++++++++++++++
4 files changed, 140 insertions(+), 11 deletions(-)
create mode 100644 Algorithms/0911. Online Election/911. Online Election.go
create mode 100644 Algorithms/0911. Online Election/911. Online Election_test.go
create mode 100755 Algorithms/0911. Online Election/README.md
diff --git a/Algorithms/0887. Super Egg Drop/README.md b/Algorithms/0887. Super Egg Drop/README.md
index 7ea30b87..dc1d32ec 100755
--- a/Algorithms/0887. Super Egg Drop/README.md
+++ b/Algorithms/0887. Super Egg Drop/README.md
@@ -59,7 +59,8 @@ What is the minimum number of moves that you need to know with certainty what
- 这一题如果按照题意正向考虑,动态规划的状态转移方程是 `searchTime(K, N) = max( searchTime(K-1, X-1), searchTime(K, N-X) )`。其中 `X` 是丢鸡蛋的楼层。随着 `X` 从 `[1,N]`,都能计算出一个 `searchTime` 的值,在所有这 `N` 个值之中,取最小值就是本题的答案了。这个解法可以 AC 这道题。不过这个解法不细展开了。时间复杂度 `O(k*N^2)`。
-
+
+
- 换个角度来看这个问题,定义 `dp[k][m]` 代表 `K` 个鸡蛋,`M` 次移动能检查的最大楼层。考虑某一步 `t` 应该在哪一层丢鸡蛋呢?一个正确的选择是在 `dp[k-1][t-1] + 1` 层丢鸡蛋,结果分两种情况:
1. 如果鸡蛋碎了,我们首先排除了该层以上的所有楼层(不管这个楼有多高),而对于剩下的 `dp[k-1][t-1]` 层楼,我们一定能用 `k-1` 个鸡蛋在 `t-1` 步内求解。因此这种情况下,我们总共可以求解无限高的楼层。可见,这是一种非常好的情况,但并不总是发生。
2. 如果鸡蛋没碎,我们首先排除了该层以下的 `dp[k-1][t-1]` 层楼,此时我们还有 `k` 个蛋和 `t-1` 步,那么我们去该层以上的楼层继续测得 `dp[k][t-1]` 层楼。因此这种情况下,我们总共可以求解 `dp[k-1][t-1] + 1 + dp[k][t-1]` 层楼。
@@ -68,33 +69,42 @@ What is the minimum number of moves that you need to know with certainty what
1. 如果在更低的楼层丢鸡蛋也能保证找到安全楼层。那么得到的结果一定不是最小步数。因为这次丢鸡蛋没有充分的展现鸡蛋和移动次数的潜力,最终求解一定会有鸡蛋和步数剩余,即不是能探测的最大楼层了。
2. 如果在更高的楼层丢鸡蛋,假设是第 `dp[k-1][t-1] + 2` 层丢鸡蛋,如果这次鸡蛋碎了,剩下 `k-1` 个鸡蛋和 `t-1` 步只能保证验证 `dp[k-1][t-1]` 的楼层,这里还剩**第** `dp[k-1][t-1]+ 1` 的楼层,不能保证最终一定能找到安全楼层了。
- 用反证法就能得出每一步都应该在第 `dp[k-1][t-1] + 1` 层丢鸡蛋。
-- 这道题还可以用二分搜索来解答。回到上面分析的状态转移方程:`dp[k][m] = dp[k-1][m-1] + dp[k][m-1] + 1` 。用数学方法来解析这个递推关系。令 `f(t,k)` 为 `t` 和 `k` 的函数,题目所要求能测到最大楼层是 `N` 的最小步数,即要求出 `f(t,k) ≥ N` 时候的最小 `t`。由状态转移方程可以知道:`f(t,k) = f(t-1,k) + f(t-1,k-1) + 1`,当 `k = 1` 的时候,对应一个鸡蛋的情况,`f(t,1) = t`,当 `t = 1` 的时候,对应一步的情况,`f(1,k) = 1`。有状态转移方程得:
+- 这道题还可以用二分搜索来解答。回到上面分析的状态转移方程:`dp[k][m] = dp[k-1][m-1] + dp[k][m-1] + 1` 。用数学方法来解析这个递推关系。令 `f(t,k)` 为 `t` 和 `k` 的函数,题目所要求能测到最大楼层是 `N` 的最小步数,即要求出 `f(t,k) ≥ N` 时候的最小 `t`。由状态转移方程可以知道:`f(t,k) = f(t-1,k) + f(t-1,k-1) + 1`,当 `k = 1` 的时候,对应一个鸡蛋的情况,`f(t,1) = t`,当 `t = 1` 的时候,对应一步的情况,`f(1,k) = 1`。有状态转移方程得:
-
- 令 `g(t,k) = f(t,k) - f(t,k-1)`,可以得到:
+
+
+- 令 `g(t,k) = f(t,k) - f(t,k-1)`,可以得到:
+
-
- 可以知道 `g(t,k)` 是一个杨辉三角,即二项式系数:
+
+
+- 可以知道 `g(t,k)` 是一个杨辉三角,即二项式系数:
+
- 利用裂项相消的方法:
+
+- 利用裂项相消的方法:
- 于是可以得到:
+
+- 于是可以得到:
- 其中:
+
+- 其中:
- 于是针对每一项的二项式常数,都可以由前一项乘以一个分数得到下一项。
+
+- 于是针对每一项的二项式常数,都可以由前一项乘以一个分数得到下一项。
- 利用二分搜索,不断的二分 `t`,直到逼近找到 `f(t,k) ≥ N` 时候最小的 `t`。时间复杂度 `O(K * log N)`,空间复杂度 `O(1)`。
+
+- 利用二分搜索,不断的二分 `t`,直到逼近找到 `f(t,k) ≥ N` 时候最小的 `t`。时间复杂度 `O(K * log N)`,空间复杂度 `O(1)`。
diff --git a/Algorithms/0911. Online Election/911. Online Election.go b/Algorithms/0911. Online Election/911. Online Election.go
new file mode 100644
index 00000000..cd6b5751
--- /dev/null
+++ b/Algorithms/0911. Online Election/911. Online Election.go
@@ -0,0 +1,38 @@
+package leetcode
+
+import (
+ "sort"
+)
+
+// TopVotedCandidate define
+type TopVotedCandidate struct {
+ persons []int
+ times []int
+}
+
+// Constructor911 define
+func Constructor911(persons []int, times []int) TopVotedCandidate {
+ leaders, votes := make([]int, len(persons)), make([]int, len(persons))
+ leader := persons[0]
+ for i := 0; i < len(persons); i++ {
+ p := persons[i]
+ votes[p]++
+ if votes[p] >= votes[leader] {
+ leader = p
+ }
+ leaders[i] = leader
+ }
+ return TopVotedCandidate{persons: leaders, times: times}
+}
+
+// Q define
+func (tvc *TopVotedCandidate) Q(t int) int {
+ i := sort.Search(len(tvc.times), func(p int) bool { return tvc.times[p] > t })
+ return tvc.persons[i-1]
+}
+
+/**
+ * Your TopVotedCandidate object will be instantiated and called as such:
+ * obj := Constructor(persons, times);
+ * param_1 := obj.Q(t);
+ */
diff --git a/Algorithms/0911. Online Election/911. Online Election_test.go b/Algorithms/0911. Online Election/911. Online Election_test.go
new file mode 100644
index 00000000..e2ee112c
--- /dev/null
+++ b/Algorithms/0911. Online Election/911. Online Election_test.go
@@ -0,0 +1,28 @@
+package leetcode
+
+import (
+ "fmt"
+ "testing"
+)
+
+func Test_Problem911(t *testing.T) {
+ obj := Constructor911([]int{0, 1, 1, 0, 0, 1, 0}, []int{0, 5, 10, 15, 20, 25, 30})
+ fmt.Printf("obj.Q[3] = %v\n", obj.Q(3)) // 0
+ fmt.Printf("obj.Q[12] = %v\n", obj.Q(12)) // 1
+ fmt.Printf("obj.Q[25] = %v\n", obj.Q(25)) // 1
+ fmt.Printf("obj.Q[15] = %v\n", obj.Q(15)) // 0
+ fmt.Printf("obj.Q[24] = %v\n", obj.Q(24)) // 0
+ fmt.Printf("obj.Q[8] = %v\n", obj.Q(8)) // 1
+
+ obj = Constructor911([]int{0, 0, 0, 0, 1}, []int{0, 6, 39, 52, 75})
+ fmt.Printf("obj.Q[45] = %v\n", obj.Q(45)) // 0
+ fmt.Printf("obj.Q[49] = %v\n", obj.Q(49)) // 0
+ fmt.Printf("obj.Q[59] = %v\n", obj.Q(59)) // 0
+ fmt.Printf("obj.Q[68] = %v\n", obj.Q(68)) // 0
+ fmt.Printf("obj.Q[42] = %v\n", obj.Q(42)) // 0
+ fmt.Printf("obj.Q[37] = %v\n", obj.Q(37)) // 0
+ fmt.Printf("obj.Q[99] = %v\n", obj.Q(99)) // 0
+ fmt.Printf("obj.Q[26] = %v\n", obj.Q(26)) // 0
+ fmt.Printf("obj.Q[78] = %v\n", obj.Q(78)) // 0
+ fmt.Printf("obj.Q[43] = %v\n", obj.Q(43)) // 0
+}
diff --git a/Algorithms/0911. Online Election/README.md b/Algorithms/0911. Online Election/README.md
new file mode 100755
index 00000000..19b8607e
--- /dev/null
+++ b/Algorithms/0911. Online Election/README.md
@@ -0,0 +1,53 @@
+# [911. Online Election](https://leetcode.com/problems/online-election/)
+
+
+## 题目:
+
+In an election, the `i`-th vote was cast for `persons[i]` at time `times[i]`.
+
+Now, we would like to implement the following query function: `TopVotedCandidate.q(int t)` will return the number of the person that was leading the election at time `t`.
+
+Votes cast at time `t` will count towards our query. In the case of a tie, the most recent vote (among tied candidates) wins.
+
+**Example 1:**
+
+ Input: ["TopVotedCandidate","q","q","q","q","q","q"], [[[0,1,1,0,0,1,0],[0,5,10,15,20,25,30]],[3],[12],[25],[15],[24],[8]]
+ Output: [null,0,1,1,0,0,1]
+ Explanation:
+ At time 3, the votes are [0], and 0 is leading.
+ At time 12, the votes are [0,1,1], and 1 is leading.
+ At time 25, the votes are [0,1,1,0,0,1], and 1 is leading (as ties go to the most recent vote.)
+ This continues for 3 more queries at time 15, 24, and 8.
+
+**Note:**
+
+1. `1 <= persons.length = times.length <= 5000`
+2. `0 <= persons[i] <= persons.length`
+3. `times` is a strictly increasing array with all elements in `[0, 10^9]`.
+4. `TopVotedCandidate.q` is called at most `10000` times per test case.
+5. `TopVotedCandidate.q(int t)` is always called with `t >= times[0]`.
+
+
+## 题目大意
+
+在选举中,第 i 张票是在时间为 times[i] 时投给 persons[i] 的。
+
+现在,我们想要实现下面的查询函数: TopVotedCandidate.q(int t) 将返回在 t 时刻主导选举的候选人的编号。
+
+在 t 时刻投出的选票也将被计入我们的查询之中。在平局的情况下,最近获得投票的候选人将会获胜。
+
+提示:
+
+1. 1 <= persons.length = times.length <= 5000
+2. 0 <= persons[i] <= persons.length
+3. times 是严格递增的数组,所有元素都在 [0, 10^9] 范围中。
+4. 每个测试用例最多调用 10000 次 TopVotedCandidate.q。
+5. TopVotedCandidate.q(int t) 被调用时总是满足 t >= times[0]。
+
+
+
+
+## 解题思路
+
+- 给出一个 2 个数组,分别代表第 `i` 人在第 `t` 时刻获得的票数。需要实现一个查询功能的函数,查询在任意 `t` 时刻,输出谁的选票领先。
+- `persons[]` 数组里面装的是获得选票人的编号,`times[]` 数组里面对应的是每个选票的时刻。`times[]` 数组默认是有序的,从小到大排列。先计算出每个时刻哪个人选票领先,放在一个数组中,实现查询函数的时候,只需要先对 `times[]` 数组二分搜索,找到比查询时间 `t` 小的最大时刻 `i`,再在选票领先的数组里面输出对应时刻领先的人的编号即可。