Given as input, a sorted array of floats, I need to find the total number of pairs (i,j)
such as A[i]*A[j]>=A[i]+A[j]
for each i < j
.
I already know the naive solution, using a loop inside other loop, which will give me O(n^2) algorithm, but i was wondering if there is a more optimal solution.
You can try to create a new array of length (arr. length-1) inside the function and append the products of adjacent numbers to this new array. Then find the largest number in the array and return it. This will solve the problem with negative product.
Follow the steps below to solve the given problem: Initialize the count variable with 0 which stores the result. Iterate arr and if the sum of ith and jth [i + 1…..n – 1] element is equal to sum i.e. arr[i] + arr[j] == sum, then increment the count variable. Return the count.
= n(n-1) / 2 which is our formula for the number of pairs needed in at least n statements.
Here's an O(n)
algorithm.
Let's look at A * B >= A + B
.
When A, B <= 0
, it's always true.
When A, B >= 2
, it's always true.
When A >= 1, B <= 1
(or B >= 1, A <= 1
), it's always false.
When 0 < A < 1, B < 0
(or 0 < B < 1, A < 0
), it can be either true or false.
When 1 < A < 2, B > 0
(or 1 < B < 2, A > 0
), it can be either true or false.
Here's a visualization, courtesy of Wolfram Alpha and Geobits:
Now, onto the algorithm.
* To find the pairs where one number is between 0 and 1 or 1 and 2 I do something similar to what is done for the 3SUM problem.
* "Pick 2" here is referring to combinations.
Count all the pairs where both are negative
Do a binary search to find the index of the first positive (> 0) number - O(log n)
.
Since we have the index, we know how many numbers are negative / zero, we simply need to pick 2 of them, so that's amountNonPositive * (amountNonPositive-1) / 2
- O(1)
.
Find all the pairs where one is between 0 and 1
Do a binary search to find the index of the last number < 1 - O(log n)
.
Start from that index as the right index and the left-most element as the left index.
Repeat this until the right index <= 0: (runs in O(n)
)
While the product is smaller than the sum, decrease the left index
Count all the elements greater than the left index
Decrease the right index
Find all the pairs where one is between 1 and 2
Do a binary search to find the index of the first number > 1 - O(log n)
.
Start from that index as the left index and the right-most element as the right index.
Repeat this until the left index >= 2: (runs in O(n)
)
While the product is greater than the sum, decrease the right index
Count all the elements greater than the right index
Increase the left index
Count all the pairs with both numbers >= 2
At the end of the last step, we're at the first index >= 2.
Now, from there, we just need to pick 2 of all the remaining numbers,
so it's again amountGreaterEqual2 * (amountGreaterEqual2-1) / 2
- O(1)
.
You can find and print the pairs (in a shorthand form) in O(n log n)
.
For each A[i]
there is a minimum number k
that satisfies the condition(1).
All values greater than k will also satisfy the condition.
Finding the lowest j
such that A[j] >= k using binary search is O(log n)
.
So you can find and print the result like this:
(i, j)
(1, no match)
(2, no match)
(3, >=25)
(4, >=20)
(5, >=12)
(6, >6)
(7, >7)
...
(n-1, n)
If you want to print all combinations, then it is O(n^2), because the number of combinations are O(n^2).
(*) To handle negative numbers it actually needs to be a bit more complex, because the numbers that satify the equation can be more that one range. I'm not absolutely sure how it behaves for small negative numbers, but if the number of ranges is not absolutely limited then my solution is no longer better than O(n^2).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With