diff --git a/solution/2000-2099/2063.Vowels of All Substrings/README.md b/solution/2000-2099/2063.Vowels of All Substrings/README.md index 2653b85def8e6..36b9dd813a5eb 100644 --- a/solution/2000-2099/2063.Vowels of All Substrings/README.md +++ b/solution/2000-2099/2063.Vowels of All Substrings/README.md @@ -85,9 +85,9 @@ tags: ### 方法一:枚举贡献 -我们可以枚举字符串的每个字符 $word[i]$,如果 $word[i]$ 是元音字母,那么 $word[i]$ 一共在 $(i + 1) \times (n - i)$ 个子字符串中出现,将这些子字符串的个数累加即可。 +我们可以枚举字符串的每个字符 $\textit{word}[i]$,如果 $\textit{word}[i]$ 是元音字母,那么 $\textit{word}[i]$ 一共在 $(i + 1) \times (n - i)$ 个子字符串中出现,将这些子字符串的个数累加即可。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为字符串 $word$ 的长度。 +时间复杂度 $O(n)$,其中 $n$ 为字符串 $\textit{word}$ 的长度。空间复杂度 $O(1)$。 @@ -163,6 +163,40 @@ function countVowels(word: string): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn count_vowels(word: String) -> i64 { + let n = word.len() as i64; + word.chars() + .enumerate() + .filter(|(_, c)| "aeiou".contains(*c)) + .map(|(i, _)| (i as i64 + 1) * (n - i as i64)) + .sum() + } +} +``` + +#### JavaScript + +```js +/** + * @param {string} word + * @return {number} + */ +var countVowels = function (word) { + const n = word.length; + let ans = 0; + for (let i = 0; i < n; ++i) { + if (['a', 'e', 'i', 'o', 'u'].includes(word[i])) { + ans += (i + 1) * (n - i); + } + } + return ans; +}; +``` + diff --git a/solution/2000-2099/2063.Vowels of All Substrings/README_EN.md b/solution/2000-2099/2063.Vowels of All Substrings/README_EN.md index f7c07bc373390..1a5b421d1cba6 100644 --- a/solution/2000-2099/2063.Vowels of All Substrings/README_EN.md +++ b/solution/2000-2099/2063.Vowels of All Substrings/README_EN.md @@ -33,12 +33,12 @@ tags:
 Input: word = "aba"
 Output: 6
-Explanation: 
+Explanation:
 All possible substrings are: "a", "ab", "aba", "b", "ba", and "a".
 - "b" has 0 vowels in it
 - "a", "ab", "ba", and "a" have 1 vowel each
 - "aba" has 2 vowels in it
-Hence, the total sum of vowels = 0 + 1 + 1 + 1 + 1 + 2 = 6. 
+Hence, the total sum of vowels = 0 + 1 + 1 + 1 + 1 + 2 = 6.
 

Example 2:

@@ -46,7 +46,7 @@ Hence, the total sum of vowels = 0 + 1 + 1 + 1 + 1 + 2 = 6.
 Input: word = "abc"
 Output: 3
-Explanation: 
+Explanation:
 All possible substrings are: "a", "ab", "abc", "b", "bc", and "c".
 - "a", "ab", and "abc" have 1 vowel each
 - "b", "bc", and "c" have 0 vowels each
@@ -75,7 +75,11 @@ Hence, the total sum of vowels = 1 + 1 + 1 + 0 + 0 + 0 = 3.
 
 
 
-### Solution 1
+### Solution 1: Enumerate Contribution
+
+We can enumerate each character $\textit{word}[i]$ in the string. If $\textit{word}[i]$ is a vowel, then $\textit{word}[i]$ appears in $(i + 1) \times (n - i)$ substrings. We sum up the counts of these substrings.
+
+The time complexity is $O(n)$, where $n$ is the length of the string $\textit{word}$. The space complexity is $O(1)$.
 
 
 
@@ -151,6 +155,40 @@ function countVowels(word: string): number {
 }
 ```
 
+#### Rust
+
+```rust
+impl Solution {
+    pub fn count_vowels(word: String) -> i64 {
+        let n = word.len() as i64;
+        word.chars()
+            .enumerate()
+            .filter(|(_, c)| "aeiou".contains(*c))
+            .map(|(i, _)| (i as i64 + 1) * (n - i as i64))
+            .sum()
+    }
+}
+```
+
+#### JavaScript
+
+```js
+/**
+ * @param {string} word
+ * @return {number}
+ */
+var countVowels = function (word) {
+    const n = word.length;
+    let ans = 0;
+    for (let i = 0; i < n; ++i) {
+        if (['a', 'e', 'i', 'o', 'u'].includes(word[i])) {
+            ans += (i + 1) * (n - i);
+        }
+    }
+    return ans;
+};
+```
+
 
 
 
diff --git a/solution/2000-2099/2063.Vowels of All Substrings/Solution.js b/solution/2000-2099/2063.Vowels of All Substrings/Solution.js
new file mode 100644
index 0000000000000..1cb57ec60dda5
--- /dev/null
+++ b/solution/2000-2099/2063.Vowels of All Substrings/Solution.js	
@@ -0,0 +1,14 @@
+/**
+ * @param {string} word
+ * @return {number}
+ */
+var countVowels = function (word) {
+    const n = word.length;
+    let ans = 0;
+    for (let i = 0; i < n; ++i) {
+        if (['a', 'e', 'i', 'o', 'u'].includes(word[i])) {
+            ans += (i + 1) * (n - i);
+        }
+    }
+    return ans;
+};
diff --git a/solution/2000-2099/2063.Vowels of All Substrings/Solution.rs b/solution/2000-2099/2063.Vowels of All Substrings/Solution.rs
new file mode 100644
index 0000000000000..55243247dd45f
--- /dev/null
+++ b/solution/2000-2099/2063.Vowels of All Substrings/Solution.rs	
@@ -0,0 +1,10 @@
+impl Solution {
+    pub fn count_vowels(word: String) -> i64 {
+        let n = word.len() as i64;
+        word.chars()
+            .enumerate()
+            .filter(|(_, c)| "aeiou".contains(*c))
+            .map(|(i, _)| (i as i64 + 1) * (n - i as i64))
+            .sum()
+    }
+}
diff --git a/solution/2000-2099/2080.Range Frequency Queries/README.md b/solution/2000-2099/2080.Range Frequency Queries/README.md
index 3e5f7b21a2f5c..4e064fa154100 100644
--- a/solution/2000-2099/2080.Range Frequency Queries/README.md	
+++ b/solution/2000-2099/2080.Range Frequency Queries/README.md	
@@ -68,7 +68,7 @@ rangeFreqQuery.query(0, 11, 33); // 返回 2 。33 在整个子数组中出现 2
 
 
 
-### 方法一:哈希表
+### 方法一:哈希表 + 二分查找
 
 我们用一个哈希表 $g$ 来存储每个值对应的下标数组。在构造函数中,我们遍历数组 $\textit{arr}$,将每个值对应的下标加入到哈希表中。
 
@@ -215,20 +215,8 @@ class RangeFreqQuery {
         if (!idx) {
             return 0;
         }
-        const search = (x: number): number => {
-            let [l, r] = [0, idx.length];
-            while (l < r) {
-                const mid = (l + r) >> 1;
-                if (idx[mid] >= x) {
-                    r = mid;
-                } else {
-                    l = mid + 1;
-                }
-            }
-            return l;
-        };
-        const l = search(left);
-        const r = search(right + 1);
+        const l = _.sortedIndex(idx, left);
+        const r = _.sortedIndex(idx, right + 1);
         return r - l;
     }
 }
@@ -240,6 +228,111 @@ class RangeFreqQuery {
  */
 ```
 
+#### Rust
+
+```rust
+use std::collections::HashMap;
+
+struct RangeFreqQuery {
+    g: HashMap>,
+}
+
+impl RangeFreqQuery {
+    fn new(arr: Vec) -> Self {
+        let mut g = HashMap::new();
+        for (i, &value) in arr.iter().enumerate() {
+            g.entry(value).or_insert_with(Vec::new).push(i);
+        }
+        RangeFreqQuery { g }
+    }
+
+    fn query(&self, left: i32, right: i32, value: i32) -> i32 {
+        if let Some(idx) = self.g.get(&value) {
+            let l = idx.partition_point(|&x| x < left as usize);
+            let r = idx.partition_point(|&x| x <= right as usize);
+            return (r - l) as i32;
+        }
+        0
+    }
+}
+```
+
+#### JavaScript
+
+```js
+/**
+ * @param {number[]} arr
+ */
+var RangeFreqQuery = function (arr) {
+    this.g = new Map();
+
+    for (let i = 0; i < arr.length; ++i) {
+        if (!this.g.has(arr[i])) {
+            this.g.set(arr[i], []);
+        }
+        this.g.get(arr[i]).push(i);
+    }
+};
+
+/**
+ * @param {number} left
+ * @param {number} right
+ * @param {number} value
+ * @return {number}
+ */
+RangeFreqQuery.prototype.query = function (left, right, value) {
+    const idx = this.g.get(value);
+    if (!idx) {
+        return 0;
+    }
+    const l = _.sortedIndex(idx, left);
+    const r = _.sortedIndex(idx, right + 1);
+    return r - l;
+};
+
+/**
+ * Your RangeFreqQuery object will be instantiated and called as such:
+ * var obj = new RangeFreqQuery(arr)
+ * var param_1 = obj.query(left,right,value)
+ */
+```
+
+#### C#
+
+```cs
+public class RangeFreqQuery {
+    private Dictionary> g;
+
+    public RangeFreqQuery(int[] arr) {
+        g = new Dictionary>();
+        for (int i = 0; i < arr.Length; ++i) {
+            if (!g.ContainsKey(arr[i])) {
+                g[arr[i]] = new List();
+            }
+            g[arr[i]].Add(i);
+        }
+    }
+
+    public int Query(int left, int right, int value) {
+        if (g.ContainsKey(value)) {
+            var idx = g[value];
+            int l = idx.BinarySearch(left);
+            int r = idx.BinarySearch(right + 1);
+            l = l < 0 ? -l - 1 : l;
+            r = r < 0 ? -r - 1 : r;
+            return r - l;
+        }
+        return 0;
+    }
+}
+
+/**
+ * Your RangeFreqQuery object will be instantiated and called as such:
+ * RangeFreqQuery obj = new RangeFreqQuery(arr);
+ * int param_1 = obj.Query(left, right, value);
+ */
+```
+
 
 
 
diff --git a/solution/2000-2099/2080.Range Frequency Queries/README_EN.md b/solution/2000-2099/2080.Range Frequency Queries/README_EN.md
index 7945cfe3ed4ee..2cd33bf0b4d26 100644
--- a/solution/2000-2099/2080.Range Frequency Queries/README_EN.md	
+++ b/solution/2000-2099/2080.Range Frequency Queries/README_EN.md	
@@ -67,7 +67,7 @@ rangeFreqQuery.query(0, 11, 33); // return 2. The value 33 occurs 2 times in the
 
 
 
-### Solution 1: Hash Table
+### Solution 1: Hash Table + Binary Search
 
 We use a hash table $g$ to store the array of indices corresponding to each value. In the constructor, we traverse the array $\textit{arr}$, adding the index corresponding to each value to the hash table.
 
@@ -214,20 +214,8 @@ class RangeFreqQuery {
         if (!idx) {
             return 0;
         }
-        const search = (x: number): number => {
-            let [l, r] = [0, idx.length];
-            while (l < r) {
-                const mid = (l + r) >> 1;
-                if (idx[mid] >= x) {
-                    r = mid;
-                } else {
-                    l = mid + 1;
-                }
-            }
-            return l;
-        };
-        const l = search(left);
-        const r = search(right + 1);
+        const l = _.sortedIndex(idx, left);
+        const r = _.sortedIndex(idx, right + 1);
         return r - l;
     }
 }
@@ -239,6 +227,111 @@ class RangeFreqQuery {
  */
 ```
 
+#### Rust
+
+```rust
+use std::collections::HashMap;
+
+struct RangeFreqQuery {
+    g: HashMap>,
+}
+
+impl RangeFreqQuery {
+    fn new(arr: Vec) -> Self {
+        let mut g = HashMap::new();
+        for (i, &value) in arr.iter().enumerate() {
+            g.entry(value).or_insert_with(Vec::new).push(i);
+        }
+        RangeFreqQuery { g }
+    }
+
+    fn query(&self, left: i32, right: i32, value: i32) -> i32 {
+        if let Some(idx) = self.g.get(&value) {
+            let l = idx.partition_point(|&x| x < left as usize);
+            let r = idx.partition_point(|&x| x <= right as usize);
+            return (r - l) as i32;
+        }
+        0
+    }
+}
+```
+
+#### JavaScript
+
+```js
+/**
+ * @param {number[]} arr
+ */
+var RangeFreqQuery = function (arr) {
+    this.g = new Map();
+
+    for (let i = 0; i < arr.length; ++i) {
+        if (!this.g.has(arr[i])) {
+            this.g.set(arr[i], []);
+        }
+        this.g.get(arr[i]).push(i);
+    }
+};
+
+/**
+ * @param {number} left
+ * @param {number} right
+ * @param {number} value
+ * @return {number}
+ */
+RangeFreqQuery.prototype.query = function (left, right, value) {
+    const idx = this.g.get(value);
+    if (!idx) {
+        return 0;
+    }
+    const l = _.sortedIndex(idx, left);
+    const r = _.sortedIndex(idx, right + 1);
+    return r - l;
+};
+
+/**
+ * Your RangeFreqQuery object will be instantiated and called as such:
+ * var obj = new RangeFreqQuery(arr)
+ * var param_1 = obj.query(left,right,value)
+ */
+```
+
+#### C#
+
+```cs
+public class RangeFreqQuery {
+    private Dictionary> g;
+
+    public RangeFreqQuery(int[] arr) {
+        g = new Dictionary>();
+        for (int i = 0; i < arr.Length; ++i) {
+            if (!g.ContainsKey(arr[i])) {
+                g[arr[i]] = new List();
+            }
+            g[arr[i]].Add(i);
+        }
+    }
+
+    public int Query(int left, int right, int value) {
+        if (g.ContainsKey(value)) {
+            var idx = g[value];
+            int l = idx.BinarySearch(left);
+            int r = idx.BinarySearch(right + 1);
+            l = l < 0 ? -l - 1 : l;
+            r = r < 0 ? -r - 1 : r;
+            return r - l;
+        }
+        return 0;
+    }
+}
+
+/**
+ * Your RangeFreqQuery object will be instantiated and called as such:
+ * RangeFreqQuery obj = new RangeFreqQuery(arr);
+ * int param_1 = obj.Query(left, right, value);
+ */
+```
+
 
 
 
diff --git a/solution/2000-2099/2080.Range Frequency Queries/Solution.cs b/solution/2000-2099/2080.Range Frequency Queries/Solution.cs
new file mode 100644
index 0000000000000..0f675a7a0c951
--- /dev/null
+++ b/solution/2000-2099/2080.Range Frequency Queries/Solution.cs	
@@ -0,0 +1,31 @@
+public class RangeFreqQuery {
+    private Dictionary> g;
+
+    public RangeFreqQuery(int[] arr) {
+        g = new Dictionary>();
+        for (int i = 0; i < arr.Length; ++i) {
+            if (!g.ContainsKey(arr[i])) {
+                g[arr[i]] = new List();
+            }
+            g[arr[i]].Add(i);
+        }
+    }
+
+    public int Query(int left, int right, int value) {
+        if (g.ContainsKey(value)) {
+            var idx = g[value];
+            int l = idx.BinarySearch(left);
+            int r = idx.BinarySearch(right + 1);
+            l = l < 0 ? -l - 1 : l;
+            r = r < 0 ? -r - 1 : r;
+            return r - l;
+        }
+        return 0;
+    }
+}
+
+/**
+ * Your RangeFreqQuery object will be instantiated and called as such:
+ * RangeFreqQuery obj = new RangeFreqQuery(arr);
+ * int param_1 = obj.Query(left, right, value);
+ */
diff --git a/solution/2000-2099/2080.Range Frequency Queries/Solution.js b/solution/2000-2099/2080.Range Frequency Queries/Solution.js
new file mode 100644
index 0000000000000..14b374d0ec9ee
--- /dev/null
+++ b/solution/2000-2099/2080.Range Frequency Queries/Solution.js	
@@ -0,0 +1,35 @@
+/**
+ * @param {number[]} arr
+ */
+var RangeFreqQuery = function (arr) {
+    this.g = new Map();
+
+    for (let i = 0; i < arr.length; ++i) {
+        if (!this.g.has(arr[i])) {
+            this.g.set(arr[i], []);
+        }
+        this.g.get(arr[i]).push(i);
+    }
+};
+
+/**
+ * @param {number} left
+ * @param {number} right
+ * @param {number} value
+ * @return {number}
+ */
+RangeFreqQuery.prototype.query = function (left, right, value) {
+    const idx = this.g.get(value);
+    if (!idx) {
+        return 0;
+    }
+    const l = _.sortedIndex(idx, left);
+    const r = _.sortedIndex(idx, right + 1);
+    return r - l;
+};
+
+/**
+ * Your RangeFreqQuery object will be instantiated and called as such:
+ * var obj = new RangeFreqQuery(arr)
+ * var param_1 = obj.query(left,right,value)
+ */
diff --git a/solution/2000-2099/2080.Range Frequency Queries/Solution.rs b/solution/2000-2099/2080.Range Frequency Queries/Solution.rs
new file mode 100644
index 0000000000000..d9d360c422398
--- /dev/null
+++ b/solution/2000-2099/2080.Range Frequency Queries/Solution.rs	
@@ -0,0 +1,24 @@
+use std::collections::HashMap;
+
+struct RangeFreqQuery {
+    g: HashMap>,
+}
+
+impl RangeFreqQuery {
+    fn new(arr: Vec) -> Self {
+        let mut g = HashMap::new();
+        for (i, &value) in arr.iter().enumerate() {
+            g.entry(value).or_insert_with(Vec::new).push(i);
+        }
+        RangeFreqQuery { g }
+    }
+
+    fn query(&self, left: i32, right: i32, value: i32) -> i32 {
+        if let Some(idx) = self.g.get(&value) {
+            let l = idx.partition_point(|&x| x < left as usize);
+            let r = idx.partition_point(|&x| x <= right as usize);
+            return (r - l) as i32;
+        }
+        0
+    }
+}
diff --git a/solution/2000-2099/2080.Range Frequency Queries/Solution.ts b/solution/2000-2099/2080.Range Frequency Queries/Solution.ts
index 2ff602ed7618b..fb92babdfb118 100644
--- a/solution/2000-2099/2080.Range Frequency Queries/Solution.ts	
+++ b/solution/2000-2099/2080.Range Frequency Queries/Solution.ts	
@@ -15,20 +15,8 @@ class RangeFreqQuery {
         if (!idx) {
             return 0;
         }
-        const search = (x: number): number => {
-            let [l, r] = [0, idx.length];
-            while (l < r) {
-                const mid = (l + r) >> 1;
-                if (idx[mid] >= x) {
-                    r = mid;
-                } else {
-                    l = mid + 1;
-                }
-            }
-            return l;
-        };
-        const l = search(left);
-        const r = search(right + 1);
+        const l = _.sortedIndex(idx, left);
+        const r = _.sortedIndex(idx, right + 1);
         return r - l;
     }
 }