leecode2475.数组中不等三元组的数目
(第320场周赛 Q1)1256
给你一个下标从 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] 。
返回满足上述条件三元组的数目。
初始思路,3重for循环
//时间复杂度:O(n^3)
//空间复杂度:O(1)
public int unequalTriplets(int[] nums) {
int ans = 0;
for(int i = 0; i < nums.length; i++) {
for(int j = i + 1; j < nums.length; j++) {
if(nums[i] == nums[j]){
continue;
}
for(int k = j + 1; k < nums.length; k++) {
if(nums[i] != nums[k] && nums[j] != nums[k]){
ans++;
}
}
}
}
return ans;
}
思路优化,排序
排序,由题意可知,数组元素的相对顺序不影响结果,因此可以将数组 nums 从小到大进行排序。
排序后,数组中的相同元素一定是相邻的。
当以某一堆相同的数 [i,j) 作为三元组的中间元素时,这堆相同的元素的左边元素数目为 i,右边元素数目为 n−j,
那么符合条件的三元组数目为: i x (j - i) x (n - j),对以上结果求和并返回最终结果。
//时间复杂度:O(nlogn),其中 nnn 是数组 nums 的大小。主要为排序所需的时间。
//空间复杂度:O(logn),排序所需的栈空间。
ublic int unequalTriplets(int[] nums) {
Arrays.sort(nums);
int ans = 0, n = nums.length;
for(int i = 0, j = 0; i < n; i = j) {
while(j < n && nums[j] == nums[i]) {
j++;
}
ans += i * (j - i) * (n - j);
}
return ans;
}
哈希
方法三:哈希表,类似于方法二,可以使用哈希表 count记录各个元素的数目,
然后遍历哈希表(此时数组元素按照哈希表的遍历顺序进行排列),记当前遍历的元素数目 v
先前遍历的元素总数目为 t,那么以当前遍历的元素为中间元素的符合条件的三元组数目为:t×v×(n−t−v)
对以上结果求和并返回最终结果。
public int unequalTriplets(int[] nums) {
Map<Integer, Integer> count = new HashMap<>();
for(int x : nums) {
count.merge(x, 1, Integer::sum);
}
int ans = 0, n = nums.length, t = 0;
for(Map.Entry<Integer, Integer> entry : count.entrySet()) {
ans += t * entry.getValue() * (n - t - entry.getValue());
t += entry.getValue();
}
return ans;
}