1. 问题描述:
给你两个整数数组 nums1 和 nums2 ,请你返回根据以下规则形成的三元组的数目(类型 1 和类型 2 ):
类型 1:三元组 (i, j, k) ,如果 nums1[i]2 == nums2[j] * nums2[k] 其中 0 <= i < nums1.length 且 0 <= j < k < nums2.length
类型 2:三元组 (i, j, k) ,如果 nums2[i]2 == nums1[j] * nums1[k] 其中 0 <= i < nums2.length 且 0 <= j < k < nums1.length
示例 1:
输入:nums1 = [7,4], nums2 = [5,2,8,9]
输出:1
解释:类型 1:(1,1,2), nums1[1]^2 = nums2[1] * nums2[2] (4^2 = 2 * 8)
示例 2:
输入:nums1 = [1,1], nums2 = [1,1,1]
输出:9
解释:所有三元组都符合题目要求,因为 1^2 = 1 * 1
类型 1:(0,0,1), (0,0,2), (0,1,2), (1,0,1), (1,0,2), (1,1,2), nums1[i]^2 = nums2[j] * nums2[k]
类型 2:(0,0,1), (1,0,1), (2,0,1), nums2[i]^2 = nums1[j] * nums1[k]
示例 3:
输入:nums1 = [7,7,8,3], nums2 = [1,2,9,7]
输出:2
解释:有两个符合题目要求的三元组
类型 1:(3,0,2), nums1[3]^2 = nums2[0] * nums2[2]
类型 2:(3,0,1), nums2[3]^2 = nums1[0] * nums1[1]
示例 4:
输入:nums1 = [4,7,9,11,23], nums2 = [3,5,1024,12,18]
输出:0
解释:不存在符合题目要求的三元组
提示:
1 <= nums1.length, nums2.length <= 1000
1 <= nums1[i], nums2[i] <= 10^5
2. 思路分析:
① 其实类型1与类型2是类似的,所以只要我们能够计算出类型1的数目那么使用同样的方法就可以计算出类型2的数目,一个比较容易想到的方法是将其中一个数组中两两元素的乘积放入到一个字典中,然后我们遍历另外一个数组中的元素,使用哈希表检查当前正在遍历的元素的平方是否在字典中能够找到,假如能够找到符合题目的条件,对于类型2我们只需要将之前两个数组的位置换一下即可,思路还是比较容易理解的,关键是需要想到使用字典(哈希表)去解决
② 除了使用这个方法之外,领扣的大佬的题解还有一种比较好的方法使用的是字典 + 双指针的方法去解决的,我们需要使用set来去重,去重之后我们就可以结合双指针只使用元素一次了,比如nums1 = [16,7],nums2 = [2,2,8,8],去重之后nums_1 = [16,7],nums_2 = [2,8],我们需要对数组元素进行排序然后我们结合一头一尾的指针就可以进行指针的移动尽可能逼近当前正在遍历元素的平方,因为去重了所以需要计算出数组中各个元素出现的次数,我们只需要将元素出现的次数相乘起来即可,比如上面的nums1与nums2,nums1中16出现的次数为1,nums2中2与8出现的次数分别是2,2所以他们形成的类型1的数目为1 * 2 * 2 = 4,但是这也会导致nums1与nums2中相等的元素会忽略掉,比如nums1 = [1,1],nums2 = [1,1,1]同样的元素去重使用双指针之后会忽略掉这种元素类型的的计算结果,我们需要检查nums1中与nums2中的元素是否相等而且元素的数目是大于1的,假如是大于1的,我们需要加上这些数目,比如nums1 = [1,1],nums2 = [1,1,1],所以对这些数组进行计数可以得到nums1中1的次数为2,nums2中1的次数3,对于类型1我们可以这样计算,任取nums2中的两个元素(C32 * 1 = 3 * 1 = 3)再乘以nums1中相同元素的数目nums1中的次数为2所以可以得到类型1总的数目为2 * 3 = 6
③ 上面使用双指针 + 字典的方法来求解可以借鉴一下,通过双指针可以逐步逼近当前正在遍历元素的平方,可能会减小一定的时间复杂度
3. 代码如下:
字典:
import collections
from typing import List
class Solution:
def solve(self, nums1: List[int], nums2: List[int]):
res, dic = 0, collections.defaultdict(int)
if len(nums1) < 2: return 0
for i in range(len(nums1) - 1):
for j in range(i + 1, len(nums1)):
# 使用字典将两个数字相乘的结果存储起来
t = nums1[i] * nums1[j]
dic[t] += 1
for i in range(len(nums2)):
t = nums2[i] * nums2[i]
if t in dic:
res += dic[t]
return res
def numTriplets(self, nums1: List[int], nums2: List[int]) -> int:
return self.solve(nums1, nums2) + self.solve(nums2, nums1)
字典 + 双指针(领扣大佬题解的代码):题解网址:https://leetcode-cn.com/problems/number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers/solution/shi-yao-ji-qiao-du-mei-you-de-cai-ji-jie-fa-ke-nen/
from typing import List
class Solution:
def numTriplets(self, nums1: List[int], nums2: List[int]) -> int:
count = 0
nums1_ = {i: nums1.count(i) for i in nums1}
nums2_ = {i: nums2.count(i) for i in nums2}
nums1 = list(set(nums1))
nums2 = list(set(nums2))
nums1.sort()
nums2.sort()
for i in nums1:
cur1 = 0
cur2 = len(nums2) - 1
while cur1 < cur2:
if nums2[cur1] * nums2[cur2] == i ** 2:
count += nums2_[nums2[cur1]] * nums2_[nums2[cur2]] * nums1_[i]
cur1 += 1
cur2 -= 1
elif nums2[cur1] * nums2[cur2] < i ** 2:
cur1 += 1
elif nums2[cur1] * nums2[cur2] > i ** 2:
cur2 -= 1
for j in nums2_.keys():
if nums2_[j] > 1:
if j == i:
count += nums2_[j] * (nums2_[j] - 1) / 2 * nums1_[i]
for i in nums2:
cur1 = 0
cur2 = len(nums1) - 1
while cur1 < cur2:
if nums1[cur1] * nums1[cur2] == i ** 2:
count += nums1_[nums1[cur1]] * nums1_[nums1[cur2]] * nums2_[i]
cur1 += 1
cur2 -= 1
elif nums1[cur1] * nums1[cur2] < i ** 2:
cur1 += 1
elif nums1[cur1] * nums1[cur2] > i ** 2:
cur2 -= 1
for j in nums1_.keys():
if nums1_[j] > 1:
if j == i:
count += nums1_[j] * (nums1_[j] - 1) / 2 * nums2_[i]
return int(count)