hashmap 1726, 3404

1726. Tuple with Same Product
Medium

Given an array nums of distinct positive integers, return the number of tuples (a, b, c, d) such that a * b = c * d where abc, and d are elements of nums, and a != b != c != d.

 Example 1:

Input: nums = [2,3,4,6]
Output: 8
Explanation: There are 8 valid tuples:
(2,6,3,4) , (2,6,4,3) , (6,2,3,4) , (6,2,4,3)
(3,4,2,6) , (4,3,2,6) , (3,4,6,2) , (4,3,6,2)

Example 2:

Input: nums = [1,2,4,5,10]
Output: 16
Explanation: There are 16 valid tuples:
(1,10,2,5) , (1,10,5,2) , (10,1,2,5) , (10,1,5,2)
(2,5,1,10) , (2,5,10,1) , (5,2,1,10) , (5,2,10,1)
(2,10,4,5) , (2,10,5,4) , (10,2,4,5) , (10,2,5,4)
(4,5,2,10) , (4,5,10,2) , (5,4,2,10) , (5,4,10,2)

Constraints:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 104
  • All elements in nums are distinct.
class Solution {
    public int tupleSameProduct(int[] nums) {
        HashMap<Integer,Integer> map = new HashMap();
        for(int i=0;i<nums.length-1;i++){
            for(int j=i+1;j<nums.length;j++){
                int sum = nums[i]*nums[j];
                map.put(sum, map.getOrDefault(sum,0)+1);
            }
        }
        int result = 0;
        for(int key:map.keySet()){
            result += count(map.get(key));
        }
        return result;
    }
    private int count(int num){
        if(num<2) return 0;
        if(num==2) return 8;
        return count(num-1)+8*(num-1);
    }
}

 

You are given an array nums consisting of positive integers.

A special subsequence is defined as a subsequence of length 4, represented by indices (p, q, r, s), where p < q < r < s. This subsequence must satisfy the following conditions:

  • nums[p] * nums[r] == nums[q] * nums[s]
  • There must be at least one element between each pair of indices. In other words, q - p > 1r - q > 1 and s - r > 1.

A subsequence is a sequence derived from the array by deleting zero or more elements without changing the order of the remaining elements.

Return the number of different special subsequences in nums.

Example 1:

Input: nums = [1,2,3,4,3,6,1]

Output: 1

Explanation:

There is one special subsequence in nums.

  • (p, q, r, s) = (0, 2, 4, 6):
    • This corresponds to elements (1, 3, 3, 1).
    • nums[p] * nums[r] = nums[0] * nums[4] = 1 * 3 = 3
    • nums[q] * nums[s] = nums[2] * nums[6] = 3 * 1 = 3

Example 2:

Input: nums = [3,4,3,4,3,4,3,4]

Output: 3

Explanation:

There are three special subsequences in nums.

  • (p, q, r, s) = (0, 2, 4, 6):
    • This corresponds to elements (3, 3, 3, 3).
    • nums[p] * nums[r] = nums[0] * nums[4] = 3 * 3 = 9
    • nums[q] * nums[s] = nums[2] * nums[6] = 3 * 3 = 9
  • (p, q, r, s) = (1, 3, 5, 7):
    • This corresponds to elements (4, 4, 4, 4).
    • nums[p] * nums[r] = nums[1] * nums[5] = 4 * 4 = 16
    • nums[q] * nums[s] = nums[3] * nums[7] = 4 * 4 = 16
  • (p, q, r, s) = (0, 2, 5, 7):
    • This corresponds to elements (3, 3, 4, 4).
    • nums[p] * nums[r] = nums[0] * nums[5] = 3 * 4 = 12
    • nums[q] * nums[s] = nums[2] * nums[7] = 3 * 4 = 12 

Constraints:

  • 7 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000

 

class Solution {
    /**
    思路:
      nums[p] * nums[r] == nums[q] * nums[s] 可以得到  nums[p] / nums[q] == nums[s] * nums[r]
      为降低时间复杂度,我们可以用找出p/q的配对,以及s/r的配对, 分别存入map
      然后进行匹配
     */
    public long numberOfSubsequences(int[] nums) {
        // 找出p/q的配对,以及s/r的配对, 分别存入map
        Map<Double, List<int[]>> map1 = new HashMap<>();
        Map<Double, List<int[]>> map2 = new HashMap<>();
        Set<Double> set = new HashSet<>();
        for(int i = 0; i < nums.length; i++) {
            for(int j = i + 2; j < nums.length; j++) {
                map1.computeIfAbsent((double)nums[i]/nums[j], key -> new ArrayList<>())
                    .add(new int[]{i, j});
                map2.computeIfAbsent((double)nums[j]/nums[i], key -> new ArrayList<>())
                    .add(new int[]{i, j});
                if(map1.containsKey((double)nums[j]/nums[i])) {
                    set.add((double)nums[j]/nums[i]);
                }
            }
        }
        long result = 0;
        // 对于其中公共的key,即为可以组成满足条件的Subsequences
        for(double key : set) {
            result += count(map1.get(key), map2.get(key));
        }
        return result;
    }
    private long count(List<int[]> list1, List<int[]> list2) {
        long result = 0;
        for(int i = 0; i < list1.size(); i++) {
            int[] curr = list1.get(i);
            // 找到 大于q + 1 的 s,r 配对
            int ind = search(curr[1], list2);
            // 注意,如果ind满足,那么ind之后的配对都满足,因此个数为:list2.size() - ind
            if(ind >= 0) result += list2.size() - ind;
        }
        return result;
    }

    private int search(int target, List<int[]> list) {
        int left = 0, right = list.size() - 1;
        int result = -1;
        while(left <= right) {
            int mid = left + (right - left) / 2;
            if(list.get(mid)[0] > target + 1) {
                result = mid;
                right = mid - 1;
            }
            else {
                left = mid + 1;
            }
        }
        return result;
    }
}

 

posted @ 2022-09-11 00:43  xiaoyongyong  阅读(27)  评论(0)    收藏  举报