diff --git "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md" "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md" index ae46ffafa8e84..d6625e64781cc 100644 --- "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md" +++ "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/README.md" @@ -49,6 +49,16 @@ +**方法一:哈希表** + +根据题目描述,我们可以得到如下结论: + +如果有 $n$ 个人的能力值相同,每个人有 $n$ 种不同的位置,那么每个人在原位的概率是 $\frac{1}{n}$,那么合起来的期望就是 $1$。 + +因此,我们只需要统计不同的能力值的个数,即为答案。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 `scores` 的长度。 + ### **Python3** @@ -56,7 +66,9 @@ ```python - +class Solution: + def expectNumber(self, scores: List[int]) -> int: + return len(set(scores)) ``` ### **Java** @@ -64,7 +76,39 @@ ```java +class Solution { + public int expectNumber(int[] scores) { + Set s = new HashSet<>(); + for (int x : scores) { + s.add(x); + } + return s.size(); + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + int expectNumber(vector& scores) { + unordered_set s(scores.begin(), scores.end()); + return s.size(); + } +}; +``` + +### **Go** +```go +func expectNumber(scores []int) int { + s := map[int]struct{}{} + for _, x := range scores { + s[x] = struct{}{} + } + return len(s) +} ``` ### **...** diff --git "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.cpp" "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.cpp" new file mode 100644 index 0000000000000..e994da8e45030 --- /dev/null +++ "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.cpp" @@ -0,0 +1,7 @@ +class Solution { +public: + int expectNumber(vector& scores) { + unordered_set s(scores.begin(), scores.end()); + return s.size(); + } +}; \ No newline at end of file diff --git "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.go" "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.go" new file mode 100644 index 0000000000000..deb03ee9d14d7 --- /dev/null +++ "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.go" @@ -0,0 +1,7 @@ +func expectNumber(scores []int) int { + s := map[int]struct{}{} + for _, x := range scores { + s[x] = struct{}{} + } + return len(s) +} \ No newline at end of file diff --git "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.java" "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.java" index 3a0dfbb74eab2..1127130a39132 100644 --- "a/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.java" +++ "b/lcp/LCP 11. \346\234\237\346\234\233\344\270\252\346\225\260\347\273\237\350\256\241/Solution.java" @@ -1,9 +1,9 @@ class Solution { public int expectNumber(int[] scores) { Set s = new HashSet<>(); - for (int v : scores) { - s.add(v); + for (int x : scores) { + s.add(x); } return s.size(); } -} +} \ No newline at end of file diff --git "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md" "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md" index b06be816a6a38..5c9228c26fba9 100644 --- "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md" +++ "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/README.md" @@ -44,6 +44,18 @@ +**方法一:贪心 + 二分查找** + +我们可以将题意转换为,将题目最多分成 $m$ 组,每一组去掉最大值后不超过 $T$ ,求最小的满足条件的 $T$。 + +我们定义二分查找的左边界 $left=0$,右边界 $right=\sum_{i=0}^{n-1}time[i]$,二分查找的目标值为 $T$。 + +我们定义函数 $check(T)$,表示是否存在一种分组方案,使得每一组去掉最大值后不超过 $T$,并且分组数不超过 $m$。 + +我们可以用贪心的方法来判断是否存在这样的分组方案。我们从左到右遍历题目,将题目耗时加入当前总耗时 $s$,并更新当前分组的最大值 $mx$。如果当前总耗时 $s$ 减去当前分组的最大值 $mx$ 大于 $T$,则将当前题目作为新的分组的第一题,更新 $s$ 和 $mx$。继续遍历题目,直到遍历完所有题目。如果分组数不超过 $m$,则说明存在这样的分组方案,返回 $true$,否则返回 $false$。 + +时间复杂度 $O(n \times \log S)$,空间复杂度 $O(1)$。其中 $n$ 和 $S$ 分别为题目数量和题目总耗时。 + ### **Python3** @@ -51,7 +63,20 @@ ```python - +class Solution: + def minTime(self, time: List[int], m: int) -> int: + def check(t): + s = mx = 0 + d = 1 + for x in time: + s += x + mx = max(mx, x) + if s - mx > t: + d += 1 + s = mx = x + return d <= m + + return bisect_left(range(sum(time)), True, key=check) ``` ### **Java** @@ -59,7 +84,106 @@ ```java +class Solution { + public int minTime(int[] time, int m) { + int left = 0, right = 0; + for (int x : time) { + right += x; + } + while (left < right) { + int mid = (left + right) >> 1; + if (check(mid, time, m)) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } + + private boolean check(int t, int[] time, int m) { + int s = 0, mx = 0; + int d = 1; + for (int x : time) { + s += x; + mx = Math.max(mx, x); + if (s - mx > t) { + s = x; + mx = x; + ++d; + } + } + return d <= m; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + int minTime(vector& time, int m) { + int left = 0, right = 0; + for (int x : time) { + right += x; + } + auto check = [&](int t) -> bool { + int s = 0, mx = 0; + int d = 1; + for (int x : time) { + s += x; + mx = max(mx, x); + if (s - mx > t) { + s = x; + mx = x; + ++d; + } + } + return d <= m; + }; + while (left < right) { + int mid = (left + right) >> 1; + if (check(mid)) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } +}; +``` +### **Go** + +```go +func minTime(time []int, m int) int { + right := 0 + for _, x := range time { + right += x + } + return sort.Search(right, func(t int) bool { + s, mx := 0, 0 + d := 1 + for _, x := range time { + s += x + mx = max(mx, x) + if s-mx > t { + s, mx = x, x + d++ + } + } + return d <= m + }) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} ``` ### **...** diff --git "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.cpp" "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.cpp" new file mode 100644 index 0000000000000..4663093630454 --- /dev/null +++ "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.cpp" @@ -0,0 +1,32 @@ +class Solution { +public: + int minTime(vector& time, int m) { + int left = 0, right = 0; + for (int x : time) { + right += x; + } + auto check = [&](int t) -> bool { + int s = 0, mx = 0; + int d = 1; + for (int x : time) { + s += x; + mx = max(mx, x); + if (s - mx > t) { + s = x; + mx = x; + ++d; + } + } + return d <= m; + }; + while (left < right) { + int mid = (left + right) >> 1; + if (check(mid)) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } +}; \ No newline at end of file diff --git "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.go" "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.go" new file mode 100644 index 0000000000000..bce4fdae98bf3 --- /dev/null +++ "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.go" @@ -0,0 +1,26 @@ +func minTime(time []int, m int) int { + right := 0 + for _, x := range time { + right += x + } + return sort.Search(right, func(t int) bool { + s, mx := 0, 0 + d := 1 + for _, x := range time { + s += x + mx = max(mx, x) + if s-mx > t { + s, mx = x, x + d++ + } + } + return d <= m + }) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} \ No newline at end of file diff --git "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.java" "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.java" new file mode 100644 index 0000000000000..ea73404efeb8b --- /dev/null +++ "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.java" @@ -0,0 +1,32 @@ +class Solution { + public int minTime(int[] time, int m) { + int left = 0, right = 0; + for (int x : time) { + right += x; + } + while (left < right) { + int mid = (left + right) >> 1; + if (check(mid, time, m)) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } + + private boolean check(int t, int[] time, int m) { + int s = 0, mx = 0; + int d = 1; + for (int x : time) { + s += x; + mx = Math.max(mx, x); + if (s - mx > t) { + s = x; + mx = x; + ++d; + } + } + return d <= m; + } +} \ No newline at end of file diff --git "a/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.py" "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.py" new file mode 100644 index 0000000000000..941c0d123037c --- /dev/null +++ "b/lcp/LCP 12. \345\260\217\345\274\240\345\210\267\351\242\230\350\256\241\345\210\222/Solution.py" @@ -0,0 +1,14 @@ +class Solution: + def minTime(self, time: List[int], m: int) -> int: + def check(t): + s = mx = 0 + d = 1 + for x in time: + s += x + mx = max(mx, x) + if s - mx > t: + d += 1 + s = mx = x + return d <= m + + return bisect_left(range(sum(time)), True, key=check) diff --git a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README.md b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README.md index c2d09dd30f0ea..ee5282fc95757 100644 --- a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README.md +++ b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README.md @@ -68,6 +68,18 @@ +**方法一:冒泡排序** + +题目实际上等价于判断:将字符串 $s$ 中任意长度为 $2$ 的子字符串采用冒泡排序交换,是否能得到 $t$。 + +因此我们用一个长度为 $10$ 的数组 $pos$ 记录字符串 $s$ 中每个字符数字的下标,其中 $pos[i]$ 表示数字 $i$ 出现的下标列表,按从小到大排序。 + +接下来,我们遍历字符串 $t$,对于 $t$ 中的每个字符 $t[i]$,我们转为数字 $x$,我们判断 $pos[x]$ 是否为空,若是,说明字符串 $s$ 中不存在 $t$ 中的数字,直接返回 `false`。否则,若要将 $pos[x]$ 的第一个位置下标的字符交换到下标 $i$ 的位置,需要满足小于 $x$ 的所有数字的下标均不小于 $pos[x]$ 的第一个位置下标,若不满足,返回 `false`。否则,我们将 $pos[x]$ 的第一个位置下标弹出,然后继续遍历字符串 $t$。 + +遍历结束,返回 `true`。 + +时间复杂度 $O(n \times C)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度,而 $C$ 是数字集的大小,本题中 $C=10$。 + ### **Python3** @@ -75,7 +87,17 @@ ```python - +class Solution: + def isTransformable(self, s: str, t: str) -> bool: + pos = defaultdict(deque) + for i, c in enumerate(s): + pos[int(c)].append(i) + for c in t: + x = int(c) + if not pos[x] or any(pos[i] and pos[i][0] < pos[x][0] for i in range(x)): + return False + pos[x].popleft() + return True ``` ### **Java** @@ -83,7 +105,79 @@ ```java +class Solution { + public boolean isTransformable(String s, String t) { + Deque[] pos = new Deque[10]; + Arrays.setAll(pos, k -> new ArrayDeque<>()); + for (int i = 0; i < s.length(); ++i) { + pos[s.charAt(i) - '0'].offer(i); + } + for (int i = 0; i < t.length(); ++i) { + int x = t.charAt(i) - '0'; + if (pos[x].isEmpty()) { + return false; + } + for (int j = 0; j < x; ++j) { + if (!pos[j].isEmpty() && pos[j].peek() < pos[x].peek()) { + return false; + } + } + pos[x].poll(); + } + return true; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + bool isTransformable(string s, string t) { + queue pos[10]; + for (int i = 0; i < s.size(); ++i) { + pos[s[i] - '0'].push(i); + } + for (char& c : t) { + int x = c - '0'; + if (pos[x].empty()) { + return false; + } + for (int j = 0; j < x; ++j) { + if (!pos[j].empty() && pos[j].front() < pos[x].front()) { + return false; + } + } + pos[x].pop(); + } + return true; + } +}; +``` +### **Go** + +```go +func isTransformable(s string, t string) bool { + pos := [10][]int{} + for i, c := range s { + pos[c-'0'] = append(pos[c-'0'], i) + } + for _, c := range t { + x := int(c - '0') + if len(pos[x]) == 0 { + return false + } + for j := 0; j < x; j++ { + if len(pos[j]) > 0 && pos[j][0] < pos[x][0] { + return false + } + } + pos[x] = pos[x][1:] + } + return true +} ``` ### **...** diff --git a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README_EN.md b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README_EN.md index 98da2718cc2c2..540363c9fc806 100644 --- a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README_EN.md +++ b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/README_EN.md @@ -64,13 +64,95 @@ ### **Python3** ```python - +class Solution: + def isTransformable(self, s: str, t: str) -> bool: + pos = defaultdict(deque) + for i, c in enumerate(s): + pos[int(c)].append(i) + for c in t: + x = int(c) + if not pos[x] or any(pos[i] and pos[i][0] < pos[x][0] for i in range(x)): + return False + pos[x].popleft() + return True ``` ### **Java** ```java +class Solution { + public boolean isTransformable(String s, String t) { + Deque[] pos = new Deque[10]; + Arrays.setAll(pos, k -> new ArrayDeque<>()); + for (int i = 0; i < s.length(); ++i) { + pos[s.charAt(i) - '0'].offer(i); + } + for (int i = 0; i < t.length(); ++i) { + int x = t.charAt(i) - '0'; + if (pos[x].isEmpty()) { + return false; + } + for (int j = 0; j < x; ++j) { + if (!pos[j].isEmpty() && pos[j].peek() < pos[x].peek()) { + return false; + } + } + pos[x].poll(); + } + return true; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + bool isTransformable(string s, string t) { + queue pos[10]; + for (int i = 0; i < s.size(); ++i) { + pos[s[i] - '0'].push(i); + } + for (char& c : t) { + int x = c - '0'; + if (pos[x].empty()) { + return false; + } + for (int j = 0; j < x; ++j) { + if (!pos[j].empty() && pos[j].front() < pos[x].front()) { + return false; + } + } + pos[x].pop(); + } + return true; + } +}; +``` +### **Go** + +```go +func isTransformable(s string, t string) bool { + pos := [10][]int{} + for i, c := range s { + pos[c-'0'] = append(pos[c-'0'], i) + } + for _, c := range t { + x := int(c - '0') + if len(pos[x]) == 0 { + return false + } + for j := 0; j < x; j++ { + if len(pos[j]) > 0 && pos[j][0] < pos[x][0] { + return false + } + } + pos[x] = pos[x][1:] + } + return true +} ``` ### **...** diff --git a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.cpp b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.cpp new file mode 100644 index 0000000000000..db2de3b503d07 --- /dev/null +++ b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.cpp @@ -0,0 +1,22 @@ +class Solution { +public: + bool isTransformable(string s, string t) { + queue pos[10]; + for (int i = 0; i < s.size(); ++i) { + pos[s[i] - '0'].push(i); + } + for (char& c : t) { + int x = c - '0'; + if (pos[x].empty()) { + return false; + } + for (int j = 0; j < x; ++j) { + if (!pos[j].empty() && pos[j].front() < pos[x].front()) { + return false; + } + } + pos[x].pop(); + } + return true; + } +}; \ No newline at end of file diff --git a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.go b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.go new file mode 100644 index 0000000000000..447a9e1ffef5f --- /dev/null +++ b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.go @@ -0,0 +1,19 @@ +func isTransformable(s string, t string) bool { + pos := [10][]int{} + for i, c := range s { + pos[c-'0'] = append(pos[c-'0'], i) + } + for _, c := range t { + x := int(c - '0') + if len(pos[x]) == 0 { + return false + } + for j := 0; j < x; j++ { + if len(pos[j]) > 0 && pos[j][0] < pos[x][0] { + return false + } + } + pos[x] = pos[x][1:] + } + return true +} \ No newline at end of file diff --git a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.java b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.java new file mode 100644 index 0000000000000..2d2a7bcb746d5 --- /dev/null +++ b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.java @@ -0,0 +1,22 @@ +class Solution { + public boolean isTransformable(String s, String t) { + Deque[] pos = new Deque[10]; + Arrays.setAll(pos, k -> new ArrayDeque<>()); + for (int i = 0; i < s.length(); ++i) { + pos[s.charAt(i) - '0'].offer(i); + } + for (int i = 0; i < t.length(); ++i) { + int x = t.charAt(i) - '0'; + if (pos[x].isEmpty()) { + return false; + } + for (int j = 0; j < x; ++j) { + if (!pos[j].isEmpty() && pos[j].peek() < pos[x].peek()) { + return false; + } + } + pos[x].poll(); + } + return true; + } +} \ No newline at end of file diff --git a/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.py b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.py new file mode 100644 index 0000000000000..2412dcf43d079 --- /dev/null +++ b/solution/1500-1599/1585.Check If String Is Transformable With Substring Sort Operations/Solution.py @@ -0,0 +1,11 @@ +class Solution: + def isTransformable(self, s: str, t: str) -> bool: + pos = defaultdict(deque) + for i, c in enumerate(s): + pos[int(c)].append(i) + for c in t: + x = int(c) + if not pos[x] or any(pos[i] and pos[i][0] < pos[x][0] for i in range(x)): + return False + pos[x].popleft() + return True