返回介绍

solution / 2400-2499 / 2475.Number of Unequal Triplets in Array / README

发布于 2024-06-17 01:03:05 字数 10271 浏览 0 评论 0 收藏 0

2475. 数组中不等三元组的数目

English Version

题目描述

给你一个下标从 0 开始的正整数数组 nums 。请你找出并统计满足下述条件的三元组 (i, j, k) 的数目:

  • 0 <= i < j < k < nums.length
  • nums[i]nums[j]nums[k] 两两不同
    • 换句话说:nums[i] != nums[j]nums[i] != nums[k]nums[j] != nums[k]

返回满足上述条件三元组的数目_。_

 

示例 1:

输入:nums = [4,4,2,4,3]
输出:3
解释:下面列出的三元组均满足题目条件:
- (0, 2, 4) 因为 4 != 2 != 3
- (1, 2, 4) 因为 4 != 2 != 3
- (2, 3, 4) 因为 2 != 4 != 3
共计 3 个三元组,返回 3 。
注意 (2, 0, 4) 不是有效的三元组,因为 2 > 0 。

示例 2:

输入:nums = [1,1,1,1,1]
输出:0
解释:不存在满足条件的三元组,所以返回 0 。

 

提示:

  • 3 <= nums.length <= 100
  • 1 <= nums[i] <= 1000

解法

方法一:暴力枚举

我们可以直接枚举所有的三元组 $(i, j, k)$,统计所有符合条件的数量。

时间复杂度 $O(n^3)$,其中 $n$ 为数组 $nums$ 的长度。空间复杂度 $O(1)$。

class Solution:
  def unequalTriplets(self, nums: List[int]) -> int:
    n = len(nums)
    ans = 0
    for i in range(n):
      for j in range(i + 1, n):
        for k in range(j + 1, n):
          ans += (
            nums[i] != nums[j] and nums[j] != nums[k] and nums[i] != nums[k]
          )
    return ans
class Solution {
  public int unequalTriplets(int[] nums) {
    int n = nums.length;
    int ans = 0;
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        for (int k = j + 1; k < n; ++k) {
          if (nums[i] != nums[j] && nums[j] != nums[k] && nums[i] != nums[k]) {
            ++ans;
          }
        }
      }
    }
    return ans;
  }
}
class Solution {
public:
  int unequalTriplets(vector<int>& nums) {
    int n = nums.size();
    int ans = 0;
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        for (int k = j + 1; k < n; ++k) {
          if (nums[i] != nums[j] && nums[j] != nums[k] && nums[i] != nums[k]) {
            ++ans;
          }
        }
      }
    }
    return ans;
  }
};
func unequalTriplets(nums []int) (ans int) {
  n := len(nums)
  for i := 0; i < n; i++ {
    for j := i + 1; j < n; j++ {
      for k := j + 1; k < n; k++ {
        if nums[i] != nums[j] && nums[j] != nums[k] && nums[i] != nums[k] {
          ans++
        }
      }
    }
  }
  return
}
function unequalTriplets(nums: number[]): number {
  const n = nums.length;
  let ans = 0;
  for (let i = 0; i < n - 2; i++) {
    for (let j = i + 1; j < n - 1; j++) {
      for (let k = j + 1; k < n; k++) {
        if (nums[i] !== nums[j] && nums[j] !== nums[k] && nums[i] !== nums[k]) {
          ans++;
        }
      }
    }
  }
  return ans;
}
impl Solution {
  pub fn unequal_triplets(nums: Vec<i32>) -> i32 {
    let n = nums.len();
    let mut ans = 0;
    for i in 0..n - 2 {
      for j in i + 1..n - 1 {
        for k in j + 1..n {
          if nums[i] != nums[j] && nums[j] != nums[k] && nums[i] != nums[k] {
            ans += 1;
          }
        }
      }
    }
    ans
  }
}

方法二:排序 + 枚举中间元素 + 二分查找

我们也可以先对数组 $nums$ 进行排序。

然后遍历 $nums$,枚举中间元素 $nums[j]$,利用二分查找,在 $nums[j]$ 左侧找到最近的下标 $i$,使得 $nums[i] \lt nums[j]$ 成立;在 $nums[j]$ 右侧找到最近的下标 $k$,使得 $nums[k] \gt nums[j]$ 成立。那么以 $nums[j]$ 作为中间元素,且符合条件的三元组数量为 $(i + 1) \times (n - k)$,累加到答案中。

时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $nums$ 的长度。

class Solution:
  def unequalTriplets(self, nums: List[int]) -> int:
    nums.sort()
    ans, n = 0, len(nums)
    for j in range(1, n - 1):
      i = bisect_left(nums, nums[j], hi=j) - 1
      k = bisect_right(nums, nums[j], lo=j + 1)
      ans += (i >= 0 and k < n) * (i + 1) * (n - k)
    return ans
class Solution {
  public int unequalTriplets(int[] nums) {
    Arrays.sort(nums);
    int ans = 0, n = nums.length;
    for (int j = 1; j < n - 1; ++j) {
      int i = search(nums, nums[j], 0, j) - 1;
      int k = search(nums, nums[j] + 1, j + 1, n);
      if (i >= 0 && k < n) {
        ans += (i + 1) * (n - k);
      }
    }
    return ans;
  }

  private int search(int[] nums, int x, int left, int right) {
    while (left < right) {
      int mid = (left + right) >> 1;
      if (nums[mid] >= x) {
        right = mid;
      } else {
        left = mid + 1;
      }
    }
    return left;
  }
}
class Solution {
public:
  int unequalTriplets(vector<int>& nums) {
    sort(nums.begin(), nums.end());
    int ans = 0, n = nums.size();
    for (int j = 1; j < n - 1; ++j) {
      int i = lower_bound(nums.begin(), nums.begin() + j, nums[j]) - nums.begin() - 1;
      int k = upper_bound(nums.begin() + j + 1, nums.end(), nums[j]) - nums.begin();
      if (i >= 0 && k < n) {
        ans += (i + 1) * (n - k);
      }
    }
    return ans;
  }
};
func unequalTriplets(nums []int) (ans int) {
  sort.Ints(nums)
  n := len(nums)
  for j := 1; j < n-1; j++ {
    i := sort.Search(j, func(h int) bool { return nums[h] >= nums[j] }) - 1
    k := sort.Search(n, func(h int) bool { return h > j && nums[h] > nums[j] })
    if i >= 0 && k < n {
      ans += (i + 1) * (n - k)
    }
  }
  return
}
function unequalTriplets(nums: number[]): number {
  const n = nums.length;
  const cnt = new Map<number, number>();
  for (const num of nums) {
    cnt.set(num, (cnt.get(num) ?? 0) + 1);
  }
  let ans = 0;
  let a = 0;
  for (const b of cnt.values()) {
    const c = n - a - b;
    ans += a * b * c;
    a += b;
  }
  return ans;
}
use std::collections::HashMap;
impl Solution {
  pub fn unequal_triplets(nums: Vec<i32>) -> i32 {
    let mut cnt = HashMap::new();
    for num in nums.iter() {
      *cnt.entry(num).or_insert(0) += 1;
    }
    let n = nums.len();
    let mut ans = 0;
    let mut a = 0;
    for v in cnt.values() {
      let b = n - a - v;
      ans += v * a * b;
      a += v;
    }
    ans as i32
  }
}

方法三:哈希表

我们还可以使用哈希表 $cnt$ 来统计数组 $nums$ 中每个元素的数量。

然后遍历哈希表 $cnt$,枚举中间元素的个数 $b$,左侧元素个数记为 $a$,那么右侧元素个数有 $c = n - a - b$,此时符合条件的三元组数量为 $a \times b \times c$,累加到答案中。接着更新 $a = a + b$,继续枚举中间元素的个数 $b$。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。

class Solution:
  def unequalTriplets(self, nums: List[int]) -> int:
    cnt = Counter(nums)
    n = len(nums)
    ans = a = 0
    for b in cnt.values():
      c = n - a - b
      ans += a * b * c
      a += b
    return ans
class Solution {
  public int unequalTriplets(int[] nums) {
    Map<Integer, Integer> cnt = new HashMap<>();
    for (int v : nums) {
      cnt.merge(v, 1, Integer::sum);
    }
    int ans = 0, a = 0;
    int n = nums.length;
    for (int b : cnt.values()) {
      int c = n - a - b;
      ans += a * b * c;
      a += b;
    }
    return ans;
  }
}
class Solution {
public:
  int unequalTriplets(vector<int>& nums) {
    unordered_map<int, int> cnt;
    for (int& v : nums) {
      ++cnt[v];
    }
    int ans = 0, a = 0;
    int n = nums.size();
    for (auto& [_, b] : cnt) {
      int c = n - a - b;
      ans += a * b * c;
      a += b;
    }
    return ans;
  }
};
func unequalTriplets(nums []int) (ans int) {
  cnt := map[int]int{}
  for _, v := range nums {
    cnt[v]++
  }
  a, n := 0, len(nums)
  for _, b := range cnt {
    c := n - a - b
    ans += a * b * c
    a += b
  }
  return
}
use std::collections::HashMap;

impl Solution {
  pub fn unequal_triplets(nums: Vec<i32>) -> i32 {
    let cnt = nums.iter().fold(HashMap::new(), |mut map, &n| {
      *map.entry(n).or_insert(0) += 1;
      map
    });

    let mut ans = 0;
    let n = nums.len();
    let mut a = 0;
    for &b in cnt.values() {
      let c = n - a - b;
      ans += a * b * c;
      a += b;
    }

    ans as i32
  }
}

方法四

impl Solution {
  pub fn unequal_triplets(nums: Vec<i32>) -> i32 {
    let mut ans = 0;
    let mut nums = nums;
    nums.sort();
    let n = nums.len();

    for i in 1..n - 1 {
      let mut l = 0;
      let mut r = i;
      while l < r {
        let mid = (l + r) >> 1;
        if nums[mid] >= nums[i] {
          r = mid;
        } else {
          l = mid + 1;
        }
      }
      let j = r;

      let mut l = i + 1;
      let mut r = n;
      while l < r {
        let mid = (l + r) >> 1;
        if nums[mid] > nums[i] {
          r = mid;
        } else {
          l = mid + 1;
        }
      }
      let k = r;

      ans += j * (n - k);
    }

    ans as i32
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文