C++ O(NM) Time, O(1) Auxiliary space, beat 95% runtime solution w/ Detailed explanation
Intuition\nJust considering a single type (where nums1 is the "target" and nums2 is the "combinations" vector). We may make a few observations:\n\nObservations:
# Intuition\nJust considering a single type (where nums1 is the "target" and nums2 is the "combinations" vector). We may make a few observations:\n\nObservations:\n- The values of the numbers are **non-negative**, limited to the range 1~100,000\n    - If we deal with **sorted** nums1 and nums2, we can we can do some left-right pointer shenanigans as they traverse closer to some centre-point\n- There can be duplicates\n    - We need to account for these possibilities\n    - Possible runtime optimization here\n\n# Approach\nWith that in mind, intuitively, we want to approach some solution that iterates upon the "combinations" with two pointers that try to keep the product as close to the target as possible.\n\nFor example:\nnums1 = [1 1 3 **4** 6 8]\n("4" is our current "target")\nnums2 = [**1** 2 2 3 4 4 8 **12**]\n(leftInd is 0 and rightInd is 7)\n1 x 12 < 4 x 4\ntherefore increment leftInd to increase our product\n\n[1 1 3 **4** 6 8]\n[1 **2** 2 3 4 4 8 **12**]\n2 x 12 > 4 x 4\ntherefore decrement rightInd to decrease our product\n\n[1 1 3 **4** 6 8]\n[1 **2** 2 3 4 4 **8** 12]\n2 x 8 == 4 x 4\nfound possible product, process duplicates accordingly \n\netc...\n\nIn terms of finding the combinations, if there are no duplicates, the solution is trivial (you just increment count by 1)\n\nHowever, if there are duplicates, we need 2 ways of handling it:\n- If the leftNum (num2[leftInd]) is different from the rightNum\n    - We find all combinations for our quantity of leftNums for every rightNum, which is simply a product of the two quantities\n- If the leftNum is the same as the rightNum (in other words, our leftNum == rightNum == target)\n    - Then we need to find all possible combinations of any pair of these number\'s indices, which is a simple combinations operation (quantity Choose 2, or qC2)\n\nHere is the pseudocode implementation:\n- First, sort the nums1 and num2 vectors\n    - We are assuming mutations are ok, this allows us to reduce additional space to O(1) for our function\n- Conduct our combination-counting process twice\n    - swap nums1 and nums2 for type1 and type2 triplets\n    - Traverse over nums1:\n        - count duplicate nums1[i] values and assign to variable "multiplier"\n        - compute our "target" value from the square of nums1[i]\n            - note that we\'ll need to use long long here since unsigned int caps at 4 x 10^9\n        - double-pointer traverse through nums2 with "j" and "k" being a leftInd and rightInd respectively\n            - if product of nums2[leftInd] and nums2[rightInd] == target\n                - count the number of duplicates on the left\n                - count the number of duplicates on the right\n                - if the left and right numbers are different, simply multiply together to find # of possible combunations\n                - if the left and right numbers are the same, use find all possible combinations using nC2 where n = leftCount + rightCount\n            - if the product is greater than the target\n                - the rightInd value is too high, decrement rightInd\n            - if the product is less than the target\n                - the leftInd value is too low, increment leftInd\n- return our count at the end\n\n# Complexity\n- Time complexity:\n**O(nlog(n))** for sorting, where n is the max length between nums1 and nums2\n**O(nm)** for iterating over nums1 while looking for possible products in nums2\n**O(1)** for computing combinations (since any number\'s value is restricted to 1~10^5)\nTotal complexity = O(2 * (nlog(n) + O(nm) * O(1)))\n\u2248 **O(nm)**\n\n- Space complexity:\n**NOTE:** We don\'t auxillary space that scales with the input, making this an extremely space-efficient solution.\n**O(n + m)** for nums1 and nums2 vectors\n**O(1)** for all other local variables that we store\nAuxillary space = **O(1)**\nTotal space = **O(n + m)**\n\n# Code\n```cpp []\n// helper function to compute combinations of nCk O(N)\ntemplate <typename T>\nT combinations(T n, T k) {\n    if (k > n) return 0;  // If k is greater than n, there are no valid combinations\n    if (k == 0 || k == n) return 1;  // Base cases: nC0 = nCn = 1\n\n    T result = 1;\n    for (T i = 1; i <= k; ++i) {\n        result *= n - i + 1;\n        result /= i;\n    }\n    return result;\n}\n\nclass Solution {\npublic:\n    int numTriplets(vector<int>& nums1, vector<int>& nums2) {\n        // sort our nums1/2 vectors\n        std::sort(nums1.begin(), nums1.end());  // >> O(nlog(n)) where "n" is length of nums1\n        std::sort(nums2.begin(), nums2.end());  // >> O(nlog(n)) where "m" is length of nums2\n\n        // iterate and perform count twice\n        unsigned int count = 0;\n        for (int rep = 0; rep < 2; rep++) {\n            // iterate over targets\n            unsigned short int i = 0;\n            while (i < nums1.size()) {         // O(n+m)\n                unsigned short int multiplier = 1;\n                // if the current integer is the same as the next one, increment multiplier\n                while (i + 1 < nums1.size() && nums1[i] == nums1[i + 1]) {\n                    multiplier++;\n                    i++;\n                }\n\n                // iterate through other vector, checking multiple\n                unsigned short int leftInd = 0;\n                unsigned short int rightInd = nums2.size() - 1;\n                unsigned long long target = static_cast<unsigned long long>(nums1[i]) \n                                                * static_cast<unsigned long long>(nums1[i]);\n                while (leftInd < rightInd) {\n                    unsigned long long product = static_cast<unsigned long long>(nums2[leftInd]) \n                                                * static_cast<unsigned long long>(nums2[rightInd]);\n                    if (product == target) {\n                        // product same as target\n                        bool leftRightSame = nums2[leftInd] == nums2[rightInd];\n\n                        // count number of duplicates on "right side" of our multiplication\n                        unsigned short int rightSameCount = 1;\n                        while (rightInd - 1 > leftInd\n                                && nums2[rightInd] == nums2[rightInd - 1]) {\n                            rightSameCount++;\n                            rightInd--;\n                        }\n                        \n                        // count number of duplicates on "left side" of our multiplication\n                        unsigned short int leftSameCount = 1;\n                        while (leftInd + 1 < rightInd\n                                && nums2[leftInd] == nums2[leftInd + 1]) {\n                            leftSameCount++;\n                            leftInd++;\n                        }\n\n                        // find all possible combinations\n                        if (leftRightSame) {\n                            // use mathematical combination function\n                            count += multiplier * combinations(leftSameCount + rightSameCount, 2);\n                        } else {\n                            // use simple product to find all combinations \n                            count += multiplier * leftSameCount * rightSameCount;\n                        }\n\n                        // decrement right index by default, since that is traversed first\n                        rightInd--;\n                    } else if (product > target) {\n                        // product greater than target, move rightInd left\n                        rightInd--;\n                    } else {\n                        // product less than target, move leftInd right\n                        leftInd++;\n                    }\n                }\n                i++;\n            }\n\n            // swap nums1 and nums2 and repeat process\n            std::swap(nums1, nums2);\n        }\n\n        return count;\n    }\n};\n```
['C++']