From a45c4936351b015c6928135a377e752b5037c08b Mon Sep 17 00:00:00 2001 From: yanglbme Date: Fri, 5 Aug 2022 11:49:24 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.1409 No.1409.Queries on a Permutation With Key --- .../README.md | 306 +++++++++++++++--- .../README_EN.md | 291 ++++++++++++++--- .../Solution.cpp | 23 +- .../Solution.go | 26 +- .../Solution.java | 19 +- .../Solution.py | 15 +- 6 files changed, 555 insertions(+), 125 deletions(-) diff --git a/solution/1400-1499/1409.Queries on a Permutation With Key/README.md b/solution/1400-1499/1409.Queries on a Permutation With Key/README.md index cccaebcb5654f..f3e8c26039ac6 100644 --- a/solution/1400-1499/1409.Queries on a Permutation With Key/README.md +++ b/solution/1400-1499/1409.Queries on a Permutation With Key/README.md @@ -55,7 +55,24 @@ -题目数据规模不大,直接模拟即可。 +**方法一:模拟** + +题目数据规模不大,可以直接模拟。 + +**方法一:树状数组** + +树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作: + +1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta; +1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。 + +这两个操作的时间复杂度均为 `O(log n)`。 + +树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。 + +比如给定数组 `a[5] = {2, 5, 3, 4, 1}`,求 `b[i] = 位置 i 左边小于等于 a[i] 的数的个数`。对于此例,`b[5] = {0, 1, 1, 2, 0}`。 + +解决方案是直接遍历数组,每个位置先求出 `query(a[i])`,然后再修改树状数组 `update(a[i], 1)` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。 @@ -66,13 +83,55 @@ ```python class Solution: def processQueries(self, queries: List[int], m: int) -> List[int]: - nums = list(range(1, m + 1)) - res = [] - for num in queries: - res.append(nums.index(num)) - nums.remove(num) - nums.insert(0, num) - return res + p = list(range(1, m + 1)) + ans = [] + for v in queries: + j = p.index(v) + ans.append(j) + p.pop(j) + p.insert(0, v) + return ans +``` + +```python +class BinaryIndexedTree: + def __init__(self, n): + self.n = n + self.c = [0] * (n + 1) + + @staticmethod + def lowbit(x): + return x & -x + + def update(self, x, delta): + while x <= self.n: + self.c[x] += delta + x += BinaryIndexedTree.lowbit(x) + + def query(self, x): + s = 0 + while x > 0: + s += self.c[x] + x -= BinaryIndexedTree.lowbit(x) + return s + +class Solution: + def processQueries(self, queries: List[int], m: int) -> List[int]: + n = len(queries) + pos = [0] * (m + 1) + tree = BinaryIndexedTree(m + n) + for i in range(1, m + 1): + pos[i] = n + i + tree.update(n + i, 1) + + ans = [] + for i, v in enumerate(queries): + j = pos[v] + tree.update(j, -1) + ans.append(tree.query(j)) + pos[v] = n - i + tree.update(n - i, 1) + return ans ``` ### **Java** @@ -82,18 +141,74 @@ class Solution: ```java class Solution { public int[] processQueries(int[] queries, int m) { - List nums = new LinkedList<>(); - for (int i = 0; i < m; ++i) { - nums.add(i + 1); + List p = new LinkedList<>(); + for (int i = 1; i <= m; ++i) { + p.add(i); } - int[] res = new int[queries.length]; + int[] ans = new int[queries.length]; int i = 0; - for (int num : queries) { - res[i++] = nums.indexOf(num); - nums.remove(Integer.valueOf(num)); - nums.add(0, num); + for (int v : queries) { + int j = p.indexOf(v); + ans[i++] = j; + p.remove(j); + p.add(0, v); + } + return ans; + } +} +``` + +```java +class BinaryIndexedTree { + private int n; + private int[] c; + + public BinaryIndexedTree(int n) { + this.n = n; + c = new int[n + 1]; + } + + public void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += lowbit(x); + } + } + + public int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= lowbit(x); + } + return s; + } + + public static int lowbit(int x) { + return x & -x; + } +} + +class Solution { + public int[] processQueries(int[] queries, int m) { + int n = queries.length; + BinaryIndexedTree tree = new BinaryIndexedTree(m + n); + int[] pos = new int[m + 1]; + for (int i = 1; i <= m; ++i) { + pos[i] = n + i; + tree.update(n + i, 1); + } + int[] ans = new int[n]; + int k = 0; + for (int i = 0; i < n; ++i) { + int v = queries[i]; + int j = pos[v]; + tree.update(j, -1); + ans[k++] = tree.query(j); + pos[v] = n - i; + tree.update(n - i, 1); } - return res; + return ans; } } ``` @@ -104,24 +219,82 @@ class Solution { class Solution { public: vector processQueries(vector& queries, int m) { - vector nums(m); - iota(nums.begin(), nums.end(), 1); - vector res; - for (int num : queries) + vector p(m); + iota(p.begin(), p.end(), 1); + vector ans; + for (int v : queries) { - int idx = -1; + int j = 0; for (int i = 0; i < m; ++i) { - if (nums[i] == num) { - idx = i; + if (p[i] == v) + { + j = i; break; } } - res.push_back(idx); - nums.erase(nums.begin() + idx); - nums.insert(nums.begin(), num); + ans.push_back(j); + p.erase(p.begin() + j); + p.insert(p.begin(), v); + } + return ans; + } +}; +``` + +```cpp +class BinaryIndexedTree { +public: + int n; + vector c; + + BinaryIndexedTree(int _n): n(_n), c(_n + 1){} + + void update(int x, int delta) { + while (x <= n) + { + c[x] += delta; + x += lowbit(x); + } + } + + int query(int x) { + int s = 0; + while (x > 0) + { + s += c[x]; + x -= lowbit(x); + } + return s; + } + + int lowbit(int x) { + return x & -x; + } +}; + +class Solution { +public: + vector processQueries(vector& queries, int m) { + int n = queries.size(); + vector pos(m + 1); + BinaryIndexedTree* tree = new BinaryIndexedTree(m + n); + for (int i = 1; i <= m; ++i) + { + pos[i] = n + i; + tree->update(n + i, 1); + } + vector ans; + for (int i = 0; i < n; ++i) + { + int v = queries[i]; + int j = pos[v]; + tree->update(j, -1); + ans.push_back(tree->query(j)); + pos[v] = n - i; + tree->update(n - i, 1); } - return res; + return ans; } }; ``` @@ -130,24 +303,75 @@ public: ```go func processQueries(queries []int, m int) []int { - nums := make([]int, m) - for i := 0; i < m; i++ { - nums[i] = i + 1 + p := make([]int, m) + for i := range p { + p[i] = i + 1 } - var res []int - for _, num := range queries { - idx := -1 - for i := 0; i < m; i++ { - if nums[i] == num { - idx = i + ans := []int{} + for _, v := range queries { + j := 0 + for i := range p { + if p[i] == v { + j = i break } } - res = append(res, idx) - nums = append(nums[:idx], nums[idx+1:]...) - nums = append([]int{num}, nums...) + ans = append(ans, j) + p = append(p[:j], p[j+1:]...) + p = append([]int{v}, p...) + } + return ans +} +``` + +```go +type BinaryIndexedTree struct { + n int + c []int +} + +func newBinaryIndexedTree(n int) *BinaryIndexedTree { + c := make([]int, n+1) + return &BinaryIndexedTree{n, c} +} + +func (this *BinaryIndexedTree) lowbit(x int) int { + return x & -x +} + +func (this *BinaryIndexedTree) update(x, delta int) { + for x <= this.n { + this.c[x] += delta + x += this.lowbit(x) + } +} + +func (this *BinaryIndexedTree) query(x int) int { + s := 0 + for x > 0 { + s += this.c[x] + x -= this.lowbit(x) + } + return s +} + +func processQueries(queries []int, m int) []int { + n := len(queries) + pos := make([]int, m+1) + tree := newBinaryIndexedTree(m + n) + for i := 1; i <= m; i++ { + pos[i] = n + i + tree.update(n+i, 1) + } + ans := []int{} + for i, v := range queries { + j := pos[v] + tree.update(j, -1) + ans = append(ans, tree.query(j)) + pos[v] = n - i + tree.update(n-i, 1) } - return res + return ans } ``` diff --git a/solution/1400-1499/1409.Queries on a Permutation With Key/README_EN.md b/solution/1400-1499/1409.Queries on a Permutation With Key/README_EN.md index d3aadac812495..efe5bdd9142e0 100644 --- a/solution/1400-1499/1409.Queries on a Permutation With Key/README_EN.md +++ b/solution/1400-1499/1409.Queries on a Permutation With Key/README_EN.md @@ -62,13 +62,9 @@ Therefore, the array containing the result is [2,1,2,1].

Constraints:

    -
  • 1 <= m <= 10^3
  • -
  • 1 <= queries.length <= m
  • -
  • 1 <= queries[i] <= m
  • -
## Solutions @@ -80,13 +76,55 @@ Therefore, the array containing the result is [2,1,2,1]. ```python class Solution: def processQueries(self, queries: List[int], m: int) -> List[int]: - nums = list(range(1, m + 1)) - res = [] - for num in queries: - res.append(nums.index(num)) - nums.remove(num) - nums.insert(0, num) - return res + p = list(range(1, m + 1)) + ans = [] + for v in queries: + j = p.index(v) + ans.append(j) + p.pop(j) + p.insert(0, v) + return ans +``` + +```python +class BinaryIndexedTree: + def __init__(self, n): + self.n = n + self.c = [0] * (n + 1) + + @staticmethod + def lowbit(x): + return x & -x + + def update(self, x, delta): + while x <= self.n: + self.c[x] += delta + x += BinaryIndexedTree.lowbit(x) + + def query(self, x): + s = 0 + while x > 0: + s += self.c[x] + x -= BinaryIndexedTree.lowbit(x) + return s + +class Solution: + def processQueries(self, queries: List[int], m: int) -> List[int]: + n = len(queries) + pos = [0] * (m + 1) + tree = BinaryIndexedTree(m + n) + for i in range(1, m + 1): + pos[i] = n + i + tree.update(n + i, 1) + + ans = [] + for i, v in enumerate(queries): + j = pos[v] + tree.update(j, -1) + ans.append(tree.query(j)) + pos[v] = n - i + tree.update(n - i, 1) + return ans ``` ### **Java** @@ -94,18 +132,74 @@ class Solution: ```java class Solution { public int[] processQueries(int[] queries, int m) { - List nums = new LinkedList<>(); - for (int i = 0; i < m; ++i) { - nums.add(i + 1); + List p = new LinkedList<>(); + for (int i = 1; i <= m; ++i) { + p.add(i); } - int[] res = new int[queries.length]; + int[] ans = new int[queries.length]; int i = 0; - for (int num : queries) { - res[i++] = nums.indexOf(num); - nums.remove(Integer.valueOf(num)); - nums.add(0, num); + for (int v : queries) { + int j = p.indexOf(v); + ans[i++] = j; + p.remove(j); + p.add(0, v); + } + return ans; + } +} +``` + +```java +class BinaryIndexedTree { + private int n; + private int[] c; + + public BinaryIndexedTree(int n) { + this.n = n; + c = new int[n + 1]; + } + + public void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += lowbit(x); } - return res; + } + + public int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= lowbit(x); + } + return s; + } + + public static int lowbit(int x) { + return x & -x; + } +} + +class Solution { + public int[] processQueries(int[] queries, int m) { + int n = queries.length; + BinaryIndexedTree tree = new BinaryIndexedTree(m + n); + int[] pos = new int[m + 1]; + for (int i = 1; i <= m; ++i) { + pos[i] = n + i; + tree.update(n + i, 1); + } + int[] ans = new int[n]; + int k = 0; + for (int i = 0; i < n; ++i) { + int v = queries[i]; + int j = pos[v]; + tree.update(j, -1); + ans[k++] = tree.query(j); + pos[v] = n - i; + tree.update(n - i, 1); + } + return ans; } } ``` @@ -116,24 +210,82 @@ class Solution { class Solution { public: vector processQueries(vector& queries, int m) { - vector nums(m); - iota(nums.begin(), nums.end(), 1); - vector res; - for (int num : queries) + vector p(m); + iota(p.begin(), p.end(), 1); + vector ans; + for (int v : queries) { - int idx = -1; + int j = 0; for (int i = 0; i < m; ++i) { - if (nums[i] == num) { - idx = i; + if (p[i] == v) + { + j = i; break; } } - res.push_back(idx); - nums.erase(nums.begin() + idx); - nums.insert(nums.begin(), num); + ans.push_back(j); + p.erase(p.begin() + j); + p.insert(p.begin(), v); + } + return ans; + } +}; +``` + +```cpp +class BinaryIndexedTree { +public: + int n; + vector c; + + BinaryIndexedTree(int _n): n(_n), c(_n + 1){} + + void update(int x, int delta) { + while (x <= n) + { + c[x] += delta; + x += lowbit(x); + } + } + + int query(int x) { + int s = 0; + while (x > 0) + { + s += c[x]; + x -= lowbit(x); + } + return s; + } + + int lowbit(int x) { + return x & -x; + } +}; + +class Solution { +public: + vector processQueries(vector& queries, int m) { + int n = queries.size(); + vector pos(m + 1); + BinaryIndexedTree* tree = new BinaryIndexedTree(m + n); + for (int i = 1; i <= m; ++i) + { + pos[i] = n + i; + tree->update(n + i, 1); + } + vector ans; + for (int i = 0; i < n; ++i) + { + int v = queries[i]; + int j = pos[v]; + tree->update(j, -1); + ans.push_back(tree->query(j)); + pos[v] = n - i; + tree->update(n - i, 1); } - return res; + return ans; } }; ``` @@ -142,24 +294,75 @@ public: ```go func processQueries(queries []int, m int) []int { - nums := make([]int, m) - for i := 0; i < m; i++ { - nums[i] = i + 1 + p := make([]int, m) + for i := range p { + p[i] = i + 1 } - var res []int - for _, num := range queries { - idx := -1 - for i := 0; i < m; i++ { - if nums[i] == num { - idx = i + ans := []int{} + for _, v := range queries { + j := 0 + for i := range p { + if p[i] == v { + j = i break } } - res = append(res, idx) - nums = append(nums[:idx], nums[idx+1:]...) - nums = append([]int{num}, nums...) + ans = append(ans, j) + p = append(p[:j], p[j+1:]...) + p = append([]int{v}, p...) + } + return ans +} +``` + +```go +type BinaryIndexedTree struct { + n int + c []int +} + +func newBinaryIndexedTree(n int) *BinaryIndexedTree { + c := make([]int, n+1) + return &BinaryIndexedTree{n, c} +} + +func (this *BinaryIndexedTree) lowbit(x int) int { + return x & -x +} + +func (this *BinaryIndexedTree) update(x, delta int) { + for x <= this.n { + this.c[x] += delta + x += this.lowbit(x) + } +} + +func (this *BinaryIndexedTree) query(x int) int { + s := 0 + for x > 0 { + s += this.c[x] + x -= this.lowbit(x) + } + return s +} + +func processQueries(queries []int, m int) []int { + n := len(queries) + pos := make([]int, m+1) + tree := newBinaryIndexedTree(m + n) + for i := 1; i <= m; i++ { + pos[i] = n + i + tree.update(n+i, 1) + } + ans := []int{} + for i, v := range queries { + j := pos[v] + tree.update(j, -1) + ans = append(ans, tree.query(j)) + pos[v] = n - i + tree.update(n-i, 1) } - return res + return ans } ``` diff --git a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.cpp b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.cpp index cd6df852fa70b..0fc8a02e8f86d 100644 --- a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.cpp +++ b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.cpp @@ -1,23 +1,24 @@ class Solution { public: vector processQueries(vector& queries, int m) { - vector nums(m); - iota(nums.begin(), nums.end(), 1); - vector res; - for (int num : queries) + vector p(m); + iota(p.begin(), p.end(), 1); + vector ans; + for (int v : queries) { - int idx = -1; + int j = 0; for (int i = 0; i < m; ++i) { - if (nums[i] == num) { - idx = i; + if (p[i] == v) + { + j = i; break; } } - res.push_back(idx); - nums.erase(nums.begin() + idx); - nums.insert(nums.begin(), num); + ans.push_back(j); + p.erase(p.begin() + j); + p.insert(p.begin(), v); } - return res; + return ans; } }; \ No newline at end of file diff --git a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.go b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.go index b6aad45a44786..598a01f7a7730 100644 --- a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.go +++ b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.go @@ -1,20 +1,20 @@ func processQueries(queries []int, m int) []int { - nums := make([]int, m) - for i := 0; i < m; i++ { - nums[i] = i + 1 + p := make([]int, m) + for i := range p { + p[i] = i + 1 } - var res []int - for _, num := range queries { - idx := -1 - for i := 0; i < m; i++ { - if nums[i] == num { - idx = i + ans := []int{} + for _, v := range queries { + j := 0 + for i := range p { + if p[i] == v { + j = i break } } - res = append(res, idx) - nums = append(nums[:idx], nums[idx+1:]...) - nums = append([]int{num}, nums...) + ans = append(ans, j) + p = append(p[:j], p[j+1:]...) + p = append([]int{v}, p...) } - return res + return ans } \ No newline at end of file diff --git a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.java b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.java index 6f540a5486ed9..bc092fd3f39fc 100644 --- a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.java +++ b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.java @@ -1,16 +1,17 @@ class Solution { public int[] processQueries(int[] queries, int m) { - List nums = new LinkedList<>(); - for (int i = 0; i < m; ++i) { - nums.add(i + 1); + List p = new LinkedList<>(); + for (int i = 1; i <= m; ++i) { + p.add(i); } - int[] res = new int[queries.length]; + int[] ans = new int[queries.length]; int i = 0; - for (int num : queries) { - res[i++] = nums.indexOf(num); - nums.remove(Integer.valueOf(num)); - nums.add(0, num); + for (int v : queries) { + int j = p.indexOf(v); + ans[i++] = j; + p.remove(j); + p.add(0, v); } - return res; + return ans; } } \ No newline at end of file diff --git a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.py b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.py index 9abec3117d571..dee0d0dc14fce 100644 --- a/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.py +++ b/solution/1400-1499/1409.Queries on a Permutation With Key/Solution.py @@ -1,9 +1,10 @@ class Solution: def processQueries(self, queries: List[int], m: int) -> List[int]: - nums = list(range(1, m + 1)) - res = [] - for num in queries: - res.append(nums.index(num)) - nums.remove(num) - nums.insert(0, num) - return res + p = list(range(1, m + 1)) + ans = [] + for v in queries: + j = p.index(v) + ans.append(j) + p.pop(j) + p.insert(0, v) + return ans