Skip to content

Commit

Permalink
2179
Browse files Browse the repository at this point in the history
  • Loading branch information
lzl124631x committed Feb 19, 2022
1 parent 259b79a commit 80ad10a
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,10 @@ Now I'm using a Chrome Extension I developed -- [LeetCoder](https://chrome.googl
2170 | Minimum Operations to Make the Array Alternating | Medium | [Solution](leetcode/2170.%20Minimum%20Operations%20to%20Make%20the%20Array%20Alternating)
2171 | Removing Minimum Number of Magic Beans | Medium | [Solution](leetcode/2171.%20Removing%20Minimum%20Number%20of%20Magic%20Beans)
2172 | Maximum AND Sum of Array | Hard | [Solution](leetcode/2172.%20Maximum%20AND%20Sum%20of%20Array)
2176 | Count Equal and Divisible Pairs in an Array | Easy | [Solution](leetcode/2176.%20Count%20Equal%20and%20Divisible%20Pairs%20in%20an%20Array)
2177 | Find Three Consecutive Integers That Sum to a Given Number | Medium | [Solution](leetcode/2177.%20Find%20Three%20Consecutive%20Integers%20That%20Sum%20to%20a%20Given%20Number)
2178 | Maximum Split of Positive Even Integers | Medium | [Solution](leetcode/2178.%20Maximum%20Split%20of%20Positive%20Even%20Integers)
2179 | Count Good Triplets in an Array | Hard | [Solution](leetcode/2179.%20Count%20Good%20Triplets%20in%20an%20Array)


# FAQ
Expand Down
130 changes: 130 additions & 0 deletions leetcode/2179. Count Good Triplets in an Array/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# [2179. Count Good Triplets in an Array (Hard)](https://leetcode.com/problems/count-good-triplets-in-an-array/)

<p>You are given two <strong>0-indexed</strong> arrays <code>nums1</code> and <code>nums2</code> of length <code>n</code>, both of which are <strong>permutations</strong> of <code>[0, 1, ..., n - 1]</code>.</p>

<p>A <strong>good triplet</strong> is a set of <code>3</code> <strong>distinct</strong> values which are present in <strong>increasing order</strong> by position both in <code>nums1</code> and <code>nums2</code>. In other words, if we consider <code>pos1<sub>v</sub></code> as the index of the value <code>v</code> in <code>nums1</code> and <code>pos2<sub>v</sub></code> as the index of the value <code>v</code> in <code>nums2</code>, then a good triplet will be a set <code>(x, y, z)</code> where <code>0 &lt;= x, y, z &lt;= n - 1</code>, such that <code>pos1<sub>x</sub> &lt; pos1<sub>y</sub> &lt; pos1<sub>z</sub></code> and <code>pos2<sub>x</sub> &lt; pos2<sub>y</sub> &lt; pos2<sub>z</sub></code>.</p>

<p>Return <em>the <strong>total number</strong> of good triplets</em>.</p>

<p>&nbsp;</p>
<p><strong>Example 1:</strong></p>

<pre><strong>Input:</strong> nums1 = [2,0,1,3], nums2 = [0,1,2,3]
<strong>Output:</strong> 1
<strong>Explanation:</strong>
There are 4 triplets (x,y,z) such that pos1<sub>x</sub> &lt; pos1<sub>y</sub> &lt; pos1<sub>z</sub>. They are (2,0,1), (2,0,3), (2,1,3), and (0,1,3).
Out of those triplets, only the triplet (0,1,3) satisfies pos2<sub>x</sub> &lt; pos2<sub>y</sub> &lt; pos2<sub>z</sub>. Hence, there is only 1 good triplet.
</pre>

<p><strong>Example 2:</strong></p>

<pre><strong>Input:</strong> nums1 = [4,0,1,3,2], nums2 = [4,1,0,2,3]
<strong>Output:</strong> 4
<strong>Explanation:</strong> The 4 good triplets are (4,0,3), (4,0,2), (4,1,3), and (4,1,2).
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
<li><code>n == nums1.length == nums2.length</code></li>
<li><code>3 &lt;= n &lt;= 10<sup>5</sup></code></li>
<li><code>0 &lt;= nums1[i], nums2[i] &lt;= n - 1</code></li>
<li><code>nums1</code> and <code>nums2</code> are permutations of <code>[0, 1, ..., n - 1]</code>.</li>
</ul>


**Similar Questions**:
* [Count of Smaller Numbers After Self (Hard)](https://leetcode.com/problems/count-of-smaller-numbers-after-self/)
* [Increasing Triplet Subsequence (Medium)](https://leetcode.com/problems/increasing-triplet-subsequence/)
* [Create Sorted Array through Instructions (Hard)](https://leetcode.com/problems/create-sorted-array-through-instructions/)

## Solution 1. Divide and Conquer (Merge Sort)


The first idea is that we pick a number as the middle number in the triplet, and count the common numbers in front of this number and after this number.

For example,

```
A = [4,0,1,3,2]
B = [4,1,0,2,3]
```

For number `1`, there is a single common number (`4`) in front of `1` and two common numbers (`3,4`) after `1`, so the count of triplets with `1` in the middle is `1 * 2 = 2`.

But counting the common numbers is not easy. **Since the numbers are permutations of `[0, N-1]`, we can simplify the problem by mapping on of the array to `[0, N-1]`.**

For example, if we map `A` to `[0, N-1]`.

```
A = [4,0,1,3,2]
A'= [0,1,2,3,4]
mapping = 4->0, 0->1, 1->2, 3->3, 2->4
```

We apply the same mapping to `B`

```
B = [4,1,0,2,3]
B'= [0,2,1,4,3]
```

Now look at the new arrays

```
A = [0,1,2,3,4]
B = [0,2,1,4,3]
```

For the number `1`, we trivially know that in `A`, there is one number `0` before it and 3 numbers `2,3,4` after it. So, we just need to look at `B`. The problem now becomes counting the numbers smaller than `1` before `1` and numbers greater than `1` after `1`.

Let `lt[i]` be the count of numbers smaller than `B[i]`. The count of common numbers before `B[i]` is `min(B[i], lt[i])`. The count of common numbers after `B[i]` in `A` is `N - B[i] - 1`. The count of common numbers after `B[i]` in `B` is `N - i - 1 - (B[i] - lt[i]) = N - B[i] - 1 - i + lt[i]`. Since `i >= lt[i]`, `-i + lt[i] <= 0`, the count of common numbers after `B[i]` in both arrays is `N - B[i] - 1 - i + lt[i]`.

So, the count of triplets with `B[i]` as the middle number is `min(B[i], lt[i]) * (N - B[i] - 1 - i + lt[i])`

```cpp
// OJ: https://leetcode.com/problems/count-good-triplets-in-an-array/
// Author: github.com/lzl124631x
// Time: O(NlogN)
// Space: O(N)
class Solution {
public:
long long goodTriplets(vector<int>& A, vector<int>& B) {
long N = A.size(), ans = 0;
vector<int> m(N), lt(N), tmp(N), tmpLt(N), index(N);
for (int i = 0; i < N; ++i) m[A[i]] = i;
for (int i = 0; i < N; ++i) {
B[i] = m[B[i]];
index[B[i]] = i;
}
function<void(int, int)> merge = [&](int begin, int end) {
if (begin + 1 >= end) return;
int mid = (begin + end) / 2;
merge(begin, mid);
merge(mid, end);
int i = begin, j = mid, k = begin;
for (; k < end; ++k) {
if (j >= end || (i < mid && B[i] < B[j])) {
tmp[k] = B[i];
tmpLt[k] = lt[i];
++i;
} else {
tmp[k] = B[j];
tmpLt[k] = lt[j] + i - begin;
++j;
}
}
for (int i = begin; i < end; ++i) {
B[i] = tmp[i];
lt[i] = tmpLt[i];
}
};
merge(0, N);
for (int i = 0; i < N; ++i) {
ans += (long)min(B[i], lt[i]) * (N - B[i] - 1 - index[B[i]] + lt[i]);
}
return ans;
}
};
```

0 comments on commit 80ad10a

Please sign in to comment.