Finding all possible pairs of square numbers in an arrayStringed musical instrument classMissing element from...
What are the basics of commands in Minecraft Java Edition?
Why don't commercial aircraft adopt a slightly more seaplane-like design to allow safer ditching in case of emergency?
What is this green alien supposed to be on the American covers of the "Hitchhiker's Guide to the Galaxy"?
Credit card details stolen every 1-2 years. What am I doing wrong?
Strategy to pay off revolving debt while building reserve savings fund?
Did 007 exist before James Bond?
When designing an adventure, how can I ensure a continuous player experience in a setting that's likely to favor TPKs?
Interviewing with an unmentioned 9 months of sick leave taken during a job
Finding all possible pairs of square numbers in an array
Cauchy reals and Dedekind reals satisfy "the same mathematical theorems"
Alphanumeric Line and Curve Counting
A verb to describe specific positioning of three layers
Cover a cube with four-legged walky-squares!
Is this Android phone Android 9.0 or Android 6.0?
What happens if a company buys back all of its shares?
Wordplay addition paradox
''Habitable'' planet close to a star
How possible is a successful landing just with 1 wing?
Optimising the Selection of MaxValue in Association
Why are there no polls of Tom Steyer yet?
How to honestly answer questions from a girlfriend like "How did you find this place" without giving the impression I'm always talking about my exes?
What details should I consider before agreeing for part of my salary to be 'retained' by employer?
Is it legal for a supermarket to refuse to sell an adult beer if an adult with them doesn’t have their ID?
Did Voldemort kill his father before finding out about Horcruxes?
Finding all possible pairs of square numbers in an array
Stringed musical instrument classMissing element from array (D&C) - code design/aesthetic improvementAll permutations of the pairs that add to squaresOptimizing puzzle game involving sequence numbersQuick Sum TopCoder (Brute Force solution)Find two numbers that add up to a given total, from a formatted stringPushdown-stack: Test if a pop order is legal or notFill 2D array recursivelySimple Java program - Coding bat sumNumbersFind primes faster (Java)
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
$begingroup$
I am writing a program that allows me to find all possible pairs of square numbers.
e.g an array of {5,25,3,25,4,2,25} will return [5,25],[5,25],[2,4],[5,25]
since 25 is square of 5
currently, i am using a nested for loop to find the squares. I'm just wondering if there is a better way to do this?
import java.lang.Math.*;
public static void main(String args[])
{
int arr[] = {5,25,3,25,4,2,25};
String s = "";
for(int i =0; i < arr.length;i++)
{
for(int j = 0;j < arr.length;j++)
{
if(Math.sqrt(arr[i]) == arr[j])
{
s += arr[j] + "," + arr[i] + " ";
}
}
}
System.out.println(s);
}
java algorithm array
New contributor
$endgroup$
add a comment |
$begingroup$
I am writing a program that allows me to find all possible pairs of square numbers.
e.g an array of {5,25,3,25,4,2,25} will return [5,25],[5,25],[2,4],[5,25]
since 25 is square of 5
currently, i am using a nested for loop to find the squares. I'm just wondering if there is a better way to do this?
import java.lang.Math.*;
public static void main(String args[])
{
int arr[] = {5,25,3,25,4,2,25};
String s = "";
for(int i =0; i < arr.length;i++)
{
for(int j = 0;j < arr.length;j++)
{
if(Math.sqrt(arr[i]) == arr[j])
{
s += arr[j] + "," + arr[i] + " ";
}
}
}
System.out.println(s);
}
java algorithm array
New contributor
$endgroup$
add a comment |
$begingroup$
I am writing a program that allows me to find all possible pairs of square numbers.
e.g an array of {5,25,3,25,4,2,25} will return [5,25],[5,25],[2,4],[5,25]
since 25 is square of 5
currently, i am using a nested for loop to find the squares. I'm just wondering if there is a better way to do this?
import java.lang.Math.*;
public static void main(String args[])
{
int arr[] = {5,25,3,25,4,2,25};
String s = "";
for(int i =0; i < arr.length;i++)
{
for(int j = 0;j < arr.length;j++)
{
if(Math.sqrt(arr[i]) == arr[j])
{
s += arr[j] + "," + arr[i] + " ";
}
}
}
System.out.println(s);
}
java algorithm array
New contributor
$endgroup$
I am writing a program that allows me to find all possible pairs of square numbers.
e.g an array of {5,25,3,25,4,2,25} will return [5,25],[5,25],[2,4],[5,25]
since 25 is square of 5
currently, i am using a nested for loop to find the squares. I'm just wondering if there is a better way to do this?
import java.lang.Math.*;
public static void main(String args[])
{
int arr[] = {5,25,3,25,4,2,25};
String s = "";
for(int i =0; i < arr.length;i++)
{
for(int j = 0;j < arr.length;j++)
{
if(Math.sqrt(arr[i]) == arr[j])
{
s += arr[j] + "," + arr[i] + " ";
}
}
}
System.out.println(s);
}
java algorithm array
java algorithm array
New contributor
New contributor
edited 9 hours ago
JanB
New contributor
asked 9 hours ago
JanBJanB
133 bronze badges
133 bronze badges
New contributor
New contributor
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
$begingroup$
Avoid string addition
String addition is not good for building up strings from many pieces ... especially inside of loops. You should use StringBuilder
instead.
StringBuilder sb = new StringBuilder();
// ... omitted ...
sb.append(arr[j]).append(',').append(arr[j]).append(' ');
// ... omitted ...
String s = sb.toString();
System.out.println(s);
Avoid square-roots
Checking $sqrt x == y$ is ... dangerous.
- The results of the square-root are a float-point number, and may not exactly equal your integer value.
- If you have a negative number in your list,
Math.sqrt()
will raise an exception, yet{ -5, 25 }
is a valid pair.
Testing x == y*y
is safer, as long as there is no danger of y*y
overflowing.
Avoid repeated calculations
for(int i =0; i < arr.length;i++) {
for(int j = 0;j < arr.length;j++) {
if(Math.sqrt(arr[i]) == arr[j]) {
...
In the inner-loop, i
is constant. Yet you are computing Math.sqrt(arr[i])
every time through the loop. The value should not be changing, so you could compute it once, outside of the inner loop.
for(int i =0; i < arr.length;i++) {
double sqrt_arr_i = Math.sqrt(arr[i]);
for(int j = 0;j < arr.length;j++) {
if(sqrt_arr_i == arr[j]) {
...
Formatting
Consistent and liberal use of white space is always recommended. Add white space after every semicolon inside of for(...)
, on both sides of operators (i = 0
not i =0
), and after every comma in {5,25,3,25,4,2,25}
.
With the above recommendations, your function body would become:
int arr[] = { 5, 25, 3, 25, 4, 2, 25 };
StringBuilder sb = new StringBuilder();
for(int i = 0; i < arr.length; i++)
{
for(int j = 0; j < arr.length; j++)
{
if(arr[i] == arr[j] * arr[j])
{
sb.append(arr[j]).append(',').append(arr[i]).append(" ");
}
}
}
String s = sb.toString();
System.out.println(s);
Additional considerations
You have a trailing space in your resulting string. There are several tricks you can use to remove it. However, and interesting alternative is to use StringJoiner
:
StringJoiner sj = new StringJoiner(" ");
// ... omitted ...
sj.add(arr[j] + "," + arr[j]);
// ... omitted ...
String s = sj.toString();
System.out.println(s);
When StringJoiner
adds the second and successive strings, it automatically adds the delimiter
specified in the constructor.
$endgroup$
1
$begingroup$
A binary search requires a sorted list. If you are willing to sort your list, $O(n log n)$, then you are better off moving two index (i
&j
) through the list from one end to the other. Ifarr[i] > arr[j]*arr[j]
, increasej
. Ifarr[i] < arr[j]*arr[j]
, then increasei
. Note: you'll need a different approach to handle negative numbers.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
However, if i were to sort ( O(n^2) ) and then uses binary search ( O(nlogn) ), the performance of the new algorithm will be slower than what my code ( O(n^2) ) is doing now right?
$endgroup$
– JanB
8 hours ago
$begingroup$
Arrays.sort(int[])
is $O(n log n)$, not $O(n^2)$. If you sort, and the loop over every index ($O(n)$), and did a binary search ($O(log n)$), you'd end up with $O(n log n)$. But sort & n binary searches is $O(n log n + n log n)$ where as sort & a single pass scan is $O(n log n + n)$, so slightly faster.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
Alright, thank you so much for your help.
$endgroup$
– JanB
8 hours ago
add a comment |
$begingroup$
rather than writing all the loops by hand, can I suggest you use a different data structure? (I'm a C# programmer, hopefully my code will be easy to translate into Java.)
If the output order doesn't matter and you aren't interested in duplicates, you could get away with something like this:
var arr = new [] {5, 25, 3, 25, 4, 2, 25};
var set = new HashSet<int>(arr);
var roots = arr.Where(x => set.Contains(x * x));
foreach (var root in roots) Console.WriteLine($"{root}, {root * root}");
The set construction cost is O(n log n), which dominates the running time here (compare this to the nested loops approach which will costs O(n^2)). Also, as @AJNeufeld points out, you definitely want to avoid calculating square roots when you can get away with simple integer multiplication.
$endgroup$
$begingroup$
The set construction cost is O(n log n)
docs.microsoft.com:This constructor is an O(n) operation
.If the output order doesn't matter
good catch, I might have missed that one.… and you aren't interested in duplicates
big if, judging from the example output of three pairs given one instance of5
and three instances of its square.
$endgroup$
– greybeard
1 hour ago
add a comment |
$begingroup$
From eyeballing it, your code doesn't quite produce the format shown after will return
(pairs separated by ","
instead of "], ["
.
An alternative to building a String
and then printing it is printing its parts immediately -
I'd define a method like long squares(Appendable destination)
:
works with both StringBuilder
and OutputStream
. (Returning the count of pairs.)
Just a sketch how to reduce run time machine operations:
- determine
max
as the maximum input value (terminate with no pairs if negative), and maxRoot = floor(sqrt(max
+1)) - establish the count of every number from -maxRoot to maxRoot
(assuming [5, 25] was be reported six times if another five was in the example input -
specifying required output by example is hard, by a single example sub-optimal) - for every non-negative input number that has integer roots in the input, report as many pairs for each of its roots as there are occurrences of it
(assuming the order didn't matter between, say,[2,4]
and[-2,4]
.
If that mattered, too, you'd need to keep positions instead of counts, increasing additional space to O(n))
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
JanB is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f224365%2ffinding-all-possible-pairs-of-square-numbers-in-an-array%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Avoid string addition
String addition is not good for building up strings from many pieces ... especially inside of loops. You should use StringBuilder
instead.
StringBuilder sb = new StringBuilder();
// ... omitted ...
sb.append(arr[j]).append(',').append(arr[j]).append(' ');
// ... omitted ...
String s = sb.toString();
System.out.println(s);
Avoid square-roots
Checking $sqrt x == y$ is ... dangerous.
- The results of the square-root are a float-point number, and may not exactly equal your integer value.
- If you have a negative number in your list,
Math.sqrt()
will raise an exception, yet{ -5, 25 }
is a valid pair.
Testing x == y*y
is safer, as long as there is no danger of y*y
overflowing.
Avoid repeated calculations
for(int i =0; i < arr.length;i++) {
for(int j = 0;j < arr.length;j++) {
if(Math.sqrt(arr[i]) == arr[j]) {
...
In the inner-loop, i
is constant. Yet you are computing Math.sqrt(arr[i])
every time through the loop. The value should not be changing, so you could compute it once, outside of the inner loop.
for(int i =0; i < arr.length;i++) {
double sqrt_arr_i = Math.sqrt(arr[i]);
for(int j = 0;j < arr.length;j++) {
if(sqrt_arr_i == arr[j]) {
...
Formatting
Consistent and liberal use of white space is always recommended. Add white space after every semicolon inside of for(...)
, on both sides of operators (i = 0
not i =0
), and after every comma in {5,25,3,25,4,2,25}
.
With the above recommendations, your function body would become:
int arr[] = { 5, 25, 3, 25, 4, 2, 25 };
StringBuilder sb = new StringBuilder();
for(int i = 0; i < arr.length; i++)
{
for(int j = 0; j < arr.length; j++)
{
if(arr[i] == arr[j] * arr[j])
{
sb.append(arr[j]).append(',').append(arr[i]).append(" ");
}
}
}
String s = sb.toString();
System.out.println(s);
Additional considerations
You have a trailing space in your resulting string. There are several tricks you can use to remove it. However, and interesting alternative is to use StringJoiner
:
StringJoiner sj = new StringJoiner(" ");
// ... omitted ...
sj.add(arr[j] + "," + arr[j]);
// ... omitted ...
String s = sj.toString();
System.out.println(s);
When StringJoiner
adds the second and successive strings, it automatically adds the delimiter
specified in the constructor.
$endgroup$
1
$begingroup$
A binary search requires a sorted list. If you are willing to sort your list, $O(n log n)$, then you are better off moving two index (i
&j
) through the list from one end to the other. Ifarr[i] > arr[j]*arr[j]
, increasej
. Ifarr[i] < arr[j]*arr[j]
, then increasei
. Note: you'll need a different approach to handle negative numbers.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
However, if i were to sort ( O(n^2) ) and then uses binary search ( O(nlogn) ), the performance of the new algorithm will be slower than what my code ( O(n^2) ) is doing now right?
$endgroup$
– JanB
8 hours ago
$begingroup$
Arrays.sort(int[])
is $O(n log n)$, not $O(n^2)$. If you sort, and the loop over every index ($O(n)$), and did a binary search ($O(log n)$), you'd end up with $O(n log n)$. But sort & n binary searches is $O(n log n + n log n)$ where as sort & a single pass scan is $O(n log n + n)$, so slightly faster.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
Alright, thank you so much for your help.
$endgroup$
– JanB
8 hours ago
add a comment |
$begingroup$
Avoid string addition
String addition is not good for building up strings from many pieces ... especially inside of loops. You should use StringBuilder
instead.
StringBuilder sb = new StringBuilder();
// ... omitted ...
sb.append(arr[j]).append(',').append(arr[j]).append(' ');
// ... omitted ...
String s = sb.toString();
System.out.println(s);
Avoid square-roots
Checking $sqrt x == y$ is ... dangerous.
- The results of the square-root are a float-point number, and may not exactly equal your integer value.
- If you have a negative number in your list,
Math.sqrt()
will raise an exception, yet{ -5, 25 }
is a valid pair.
Testing x == y*y
is safer, as long as there is no danger of y*y
overflowing.
Avoid repeated calculations
for(int i =0; i < arr.length;i++) {
for(int j = 0;j < arr.length;j++) {
if(Math.sqrt(arr[i]) == arr[j]) {
...
In the inner-loop, i
is constant. Yet you are computing Math.sqrt(arr[i])
every time through the loop. The value should not be changing, so you could compute it once, outside of the inner loop.
for(int i =0; i < arr.length;i++) {
double sqrt_arr_i = Math.sqrt(arr[i]);
for(int j = 0;j < arr.length;j++) {
if(sqrt_arr_i == arr[j]) {
...
Formatting
Consistent and liberal use of white space is always recommended. Add white space after every semicolon inside of for(...)
, on both sides of operators (i = 0
not i =0
), and after every comma in {5,25,3,25,4,2,25}
.
With the above recommendations, your function body would become:
int arr[] = { 5, 25, 3, 25, 4, 2, 25 };
StringBuilder sb = new StringBuilder();
for(int i = 0; i < arr.length; i++)
{
for(int j = 0; j < arr.length; j++)
{
if(arr[i] == arr[j] * arr[j])
{
sb.append(arr[j]).append(',').append(arr[i]).append(" ");
}
}
}
String s = sb.toString();
System.out.println(s);
Additional considerations
You have a trailing space in your resulting string. There are several tricks you can use to remove it. However, and interesting alternative is to use StringJoiner
:
StringJoiner sj = new StringJoiner(" ");
// ... omitted ...
sj.add(arr[j] + "," + arr[j]);
// ... omitted ...
String s = sj.toString();
System.out.println(s);
When StringJoiner
adds the second and successive strings, it automatically adds the delimiter
specified in the constructor.
$endgroup$
1
$begingroup$
A binary search requires a sorted list. If you are willing to sort your list, $O(n log n)$, then you are better off moving two index (i
&j
) through the list from one end to the other. Ifarr[i] > arr[j]*arr[j]
, increasej
. Ifarr[i] < arr[j]*arr[j]
, then increasei
. Note: you'll need a different approach to handle negative numbers.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
However, if i were to sort ( O(n^2) ) and then uses binary search ( O(nlogn) ), the performance of the new algorithm will be slower than what my code ( O(n^2) ) is doing now right?
$endgroup$
– JanB
8 hours ago
$begingroup$
Arrays.sort(int[])
is $O(n log n)$, not $O(n^2)$. If you sort, and the loop over every index ($O(n)$), and did a binary search ($O(log n)$), you'd end up with $O(n log n)$. But sort & n binary searches is $O(n log n + n log n)$ where as sort & a single pass scan is $O(n log n + n)$, so slightly faster.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
Alright, thank you so much for your help.
$endgroup$
– JanB
8 hours ago
add a comment |
$begingroup$
Avoid string addition
String addition is not good for building up strings from many pieces ... especially inside of loops. You should use StringBuilder
instead.
StringBuilder sb = new StringBuilder();
// ... omitted ...
sb.append(arr[j]).append(',').append(arr[j]).append(' ');
// ... omitted ...
String s = sb.toString();
System.out.println(s);
Avoid square-roots
Checking $sqrt x == y$ is ... dangerous.
- The results of the square-root are a float-point number, and may not exactly equal your integer value.
- If you have a negative number in your list,
Math.sqrt()
will raise an exception, yet{ -5, 25 }
is a valid pair.
Testing x == y*y
is safer, as long as there is no danger of y*y
overflowing.
Avoid repeated calculations
for(int i =0; i < arr.length;i++) {
for(int j = 0;j < arr.length;j++) {
if(Math.sqrt(arr[i]) == arr[j]) {
...
In the inner-loop, i
is constant. Yet you are computing Math.sqrt(arr[i])
every time through the loop. The value should not be changing, so you could compute it once, outside of the inner loop.
for(int i =0; i < arr.length;i++) {
double sqrt_arr_i = Math.sqrt(arr[i]);
for(int j = 0;j < arr.length;j++) {
if(sqrt_arr_i == arr[j]) {
...
Formatting
Consistent and liberal use of white space is always recommended. Add white space after every semicolon inside of for(...)
, on both sides of operators (i = 0
not i =0
), and after every comma in {5,25,3,25,4,2,25}
.
With the above recommendations, your function body would become:
int arr[] = { 5, 25, 3, 25, 4, 2, 25 };
StringBuilder sb = new StringBuilder();
for(int i = 0; i < arr.length; i++)
{
for(int j = 0; j < arr.length; j++)
{
if(arr[i] == arr[j] * arr[j])
{
sb.append(arr[j]).append(',').append(arr[i]).append(" ");
}
}
}
String s = sb.toString();
System.out.println(s);
Additional considerations
You have a trailing space in your resulting string. There are several tricks you can use to remove it. However, and interesting alternative is to use StringJoiner
:
StringJoiner sj = new StringJoiner(" ");
// ... omitted ...
sj.add(arr[j] + "," + arr[j]);
// ... omitted ...
String s = sj.toString();
System.out.println(s);
When StringJoiner
adds the second and successive strings, it automatically adds the delimiter
specified in the constructor.
$endgroup$
Avoid string addition
String addition is not good for building up strings from many pieces ... especially inside of loops. You should use StringBuilder
instead.
StringBuilder sb = new StringBuilder();
// ... omitted ...
sb.append(arr[j]).append(',').append(arr[j]).append(' ');
// ... omitted ...
String s = sb.toString();
System.out.println(s);
Avoid square-roots
Checking $sqrt x == y$ is ... dangerous.
- The results of the square-root are a float-point number, and may not exactly equal your integer value.
- If you have a negative number in your list,
Math.sqrt()
will raise an exception, yet{ -5, 25 }
is a valid pair.
Testing x == y*y
is safer, as long as there is no danger of y*y
overflowing.
Avoid repeated calculations
for(int i =0; i < arr.length;i++) {
for(int j = 0;j < arr.length;j++) {
if(Math.sqrt(arr[i]) == arr[j]) {
...
In the inner-loop, i
is constant. Yet you are computing Math.sqrt(arr[i])
every time through the loop. The value should not be changing, so you could compute it once, outside of the inner loop.
for(int i =0; i < arr.length;i++) {
double sqrt_arr_i = Math.sqrt(arr[i]);
for(int j = 0;j < arr.length;j++) {
if(sqrt_arr_i == arr[j]) {
...
Formatting
Consistent and liberal use of white space is always recommended. Add white space after every semicolon inside of for(...)
, on both sides of operators (i = 0
not i =0
), and after every comma in {5,25,3,25,4,2,25}
.
With the above recommendations, your function body would become:
int arr[] = { 5, 25, 3, 25, 4, 2, 25 };
StringBuilder sb = new StringBuilder();
for(int i = 0; i < arr.length; i++)
{
for(int j = 0; j < arr.length; j++)
{
if(arr[i] == arr[j] * arr[j])
{
sb.append(arr[j]).append(',').append(arr[i]).append(" ");
}
}
}
String s = sb.toString();
System.out.println(s);
Additional considerations
You have a trailing space in your resulting string. There are several tricks you can use to remove it. However, and interesting alternative is to use StringJoiner
:
StringJoiner sj = new StringJoiner(" ");
// ... omitted ...
sj.add(arr[j] + "," + arr[j]);
// ... omitted ...
String s = sj.toString();
System.out.println(s);
When StringJoiner
adds the second and successive strings, it automatically adds the delimiter
specified in the constructor.
edited 8 hours ago
answered 8 hours ago
AJNeufeldAJNeufeld
10.1k1 gold badge8 silver badges33 bronze badges
10.1k1 gold badge8 silver badges33 bronze badges
1
$begingroup$
A binary search requires a sorted list. If you are willing to sort your list, $O(n log n)$, then you are better off moving two index (i
&j
) through the list from one end to the other. Ifarr[i] > arr[j]*arr[j]
, increasej
. Ifarr[i] < arr[j]*arr[j]
, then increasei
. Note: you'll need a different approach to handle negative numbers.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
However, if i were to sort ( O(n^2) ) and then uses binary search ( O(nlogn) ), the performance of the new algorithm will be slower than what my code ( O(n^2) ) is doing now right?
$endgroup$
– JanB
8 hours ago
$begingroup$
Arrays.sort(int[])
is $O(n log n)$, not $O(n^2)$. If you sort, and the loop over every index ($O(n)$), and did a binary search ($O(log n)$), you'd end up with $O(n log n)$. But sort & n binary searches is $O(n log n + n log n)$ where as sort & a single pass scan is $O(n log n + n)$, so slightly faster.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
Alright, thank you so much for your help.
$endgroup$
– JanB
8 hours ago
add a comment |
1
$begingroup$
A binary search requires a sorted list. If you are willing to sort your list, $O(n log n)$, then you are better off moving two index (i
&j
) through the list from one end to the other. Ifarr[i] > arr[j]*arr[j]
, increasej
. Ifarr[i] < arr[j]*arr[j]
, then increasei
. Note: you'll need a different approach to handle negative numbers.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
However, if i were to sort ( O(n^2) ) and then uses binary search ( O(nlogn) ), the performance of the new algorithm will be slower than what my code ( O(n^2) ) is doing now right?
$endgroup$
– JanB
8 hours ago
$begingroup$
Arrays.sort(int[])
is $O(n log n)$, not $O(n^2)$. If you sort, and the loop over every index ($O(n)$), and did a binary search ($O(log n)$), you'd end up with $O(n log n)$. But sort & n binary searches is $O(n log n + n log n)$ where as sort & a single pass scan is $O(n log n + n)$, so slightly faster.
$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
Alright, thank you so much for your help.
$endgroup$
– JanB
8 hours ago
1
1
$begingroup$
A binary search requires a sorted list. If you are willing to sort your list, $O(n log n)$, then you are better off moving two index (
i
& j
) through the list from one end to the other. If arr[i] > arr[j]*arr[j]
, increase j
. If arr[i] < arr[j]*arr[j]
, then increase i
. Note: you'll need a different approach to handle negative numbers.$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
A binary search requires a sorted list. If you are willing to sort your list, $O(n log n)$, then you are better off moving two index (
i
& j
) through the list from one end to the other. If arr[i] > arr[j]*arr[j]
, increase j
. If arr[i] < arr[j]*arr[j]
, then increase i
. Note: you'll need a different approach to handle negative numbers.$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
However, if i were to sort ( O(n^2) ) and then uses binary search ( O(nlogn) ), the performance of the new algorithm will be slower than what my code ( O(n^2) ) is doing now right?
$endgroup$
– JanB
8 hours ago
$begingroup$
However, if i were to sort ( O(n^2) ) and then uses binary search ( O(nlogn) ), the performance of the new algorithm will be slower than what my code ( O(n^2) ) is doing now right?
$endgroup$
– JanB
8 hours ago
$begingroup$
Arrays.sort(int[])
is $O(n log n)$, not $O(n^2)$. If you sort, and the loop over every index ($O(n)$), and did a binary search ($O(log n)$), you'd end up with $O(n log n)$. But sort & n binary searches is $O(n log n + n log n)$ where as sort & a single pass scan is $O(n log n + n)$, so slightly faster.$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
Arrays.sort(int[])
is $O(n log n)$, not $O(n^2)$. If you sort, and the loop over every index ($O(n)$), and did a binary search ($O(log n)$), you'd end up with $O(n log n)$. But sort & n binary searches is $O(n log n + n log n)$ where as sort & a single pass scan is $O(n log n + n)$, so slightly faster.$endgroup$
– AJNeufeld
8 hours ago
$begingroup$
Alright, thank you so much for your help.
$endgroup$
– JanB
8 hours ago
$begingroup$
Alright, thank you so much for your help.
$endgroup$
– JanB
8 hours ago
add a comment |
$begingroup$
rather than writing all the loops by hand, can I suggest you use a different data structure? (I'm a C# programmer, hopefully my code will be easy to translate into Java.)
If the output order doesn't matter and you aren't interested in duplicates, you could get away with something like this:
var arr = new [] {5, 25, 3, 25, 4, 2, 25};
var set = new HashSet<int>(arr);
var roots = arr.Where(x => set.Contains(x * x));
foreach (var root in roots) Console.WriteLine($"{root}, {root * root}");
The set construction cost is O(n log n), which dominates the running time here (compare this to the nested loops approach which will costs O(n^2)). Also, as @AJNeufeld points out, you definitely want to avoid calculating square roots when you can get away with simple integer multiplication.
$endgroup$
$begingroup$
The set construction cost is O(n log n)
docs.microsoft.com:This constructor is an O(n) operation
.If the output order doesn't matter
good catch, I might have missed that one.… and you aren't interested in duplicates
big if, judging from the example output of three pairs given one instance of5
and three instances of its square.
$endgroup$
– greybeard
1 hour ago
add a comment |
$begingroup$
rather than writing all the loops by hand, can I suggest you use a different data structure? (I'm a C# programmer, hopefully my code will be easy to translate into Java.)
If the output order doesn't matter and you aren't interested in duplicates, you could get away with something like this:
var arr = new [] {5, 25, 3, 25, 4, 2, 25};
var set = new HashSet<int>(arr);
var roots = arr.Where(x => set.Contains(x * x));
foreach (var root in roots) Console.WriteLine($"{root}, {root * root}");
The set construction cost is O(n log n), which dominates the running time here (compare this to the nested loops approach which will costs O(n^2)). Also, as @AJNeufeld points out, you definitely want to avoid calculating square roots when you can get away with simple integer multiplication.
$endgroup$
$begingroup$
The set construction cost is O(n log n)
docs.microsoft.com:This constructor is an O(n) operation
.If the output order doesn't matter
good catch, I might have missed that one.… and you aren't interested in duplicates
big if, judging from the example output of three pairs given one instance of5
and three instances of its square.
$endgroup$
– greybeard
1 hour ago
add a comment |
$begingroup$
rather than writing all the loops by hand, can I suggest you use a different data structure? (I'm a C# programmer, hopefully my code will be easy to translate into Java.)
If the output order doesn't matter and you aren't interested in duplicates, you could get away with something like this:
var arr = new [] {5, 25, 3, 25, 4, 2, 25};
var set = new HashSet<int>(arr);
var roots = arr.Where(x => set.Contains(x * x));
foreach (var root in roots) Console.WriteLine($"{root}, {root * root}");
The set construction cost is O(n log n), which dominates the running time here (compare this to the nested loops approach which will costs O(n^2)). Also, as @AJNeufeld points out, you definitely want to avoid calculating square roots when you can get away with simple integer multiplication.
$endgroup$
rather than writing all the loops by hand, can I suggest you use a different data structure? (I'm a C# programmer, hopefully my code will be easy to translate into Java.)
If the output order doesn't matter and you aren't interested in duplicates, you could get away with something like this:
var arr = new [] {5, 25, 3, 25, 4, 2, 25};
var set = new HashSet<int>(arr);
var roots = arr.Where(x => set.Contains(x * x));
foreach (var root in roots) Console.WriteLine($"{root}, {root * root}");
The set construction cost is O(n log n), which dominates the running time here (compare this to the nested loops approach which will costs O(n^2)). Also, as @AJNeufeld points out, you definitely want to avoid calculating square roots when you can get away with simple integer multiplication.
answered 6 hours ago
RafeRafe
1,1458 silver badges12 bronze badges
1,1458 silver badges12 bronze badges
$begingroup$
The set construction cost is O(n log n)
docs.microsoft.com:This constructor is an O(n) operation
.If the output order doesn't matter
good catch, I might have missed that one.… and you aren't interested in duplicates
big if, judging from the example output of three pairs given one instance of5
and three instances of its square.
$endgroup$
– greybeard
1 hour ago
add a comment |
$begingroup$
The set construction cost is O(n log n)
docs.microsoft.com:This constructor is an O(n) operation
.If the output order doesn't matter
good catch, I might have missed that one.… and you aren't interested in duplicates
big if, judging from the example output of three pairs given one instance of5
and three instances of its square.
$endgroup$
– greybeard
1 hour ago
$begingroup$
The set construction cost is O(n log n)
docs.microsoft.com: This constructor is an O(n) operation
. If the output order doesn't matter
good catch, I might have missed that one. … and you aren't interested in duplicates
big if, judging from the example output of three pairs given one instance of 5
and three instances of its square.$endgroup$
– greybeard
1 hour ago
$begingroup$
The set construction cost is O(n log n)
docs.microsoft.com: This constructor is an O(n) operation
. If the output order doesn't matter
good catch, I might have missed that one. … and you aren't interested in duplicates
big if, judging from the example output of three pairs given one instance of 5
and three instances of its square.$endgroup$
– greybeard
1 hour ago
add a comment |
$begingroup$
From eyeballing it, your code doesn't quite produce the format shown after will return
(pairs separated by ","
instead of "], ["
.
An alternative to building a String
and then printing it is printing its parts immediately -
I'd define a method like long squares(Appendable destination)
:
works with both StringBuilder
and OutputStream
. (Returning the count of pairs.)
Just a sketch how to reduce run time machine operations:
- determine
max
as the maximum input value (terminate with no pairs if negative), and maxRoot = floor(sqrt(max
+1)) - establish the count of every number from -maxRoot to maxRoot
(assuming [5, 25] was be reported six times if another five was in the example input -
specifying required output by example is hard, by a single example sub-optimal) - for every non-negative input number that has integer roots in the input, report as many pairs for each of its roots as there are occurrences of it
(assuming the order didn't matter between, say,[2,4]
and[-2,4]
.
If that mattered, too, you'd need to keep positions instead of counts, increasing additional space to O(n))
$endgroup$
add a comment |
$begingroup$
From eyeballing it, your code doesn't quite produce the format shown after will return
(pairs separated by ","
instead of "], ["
.
An alternative to building a String
and then printing it is printing its parts immediately -
I'd define a method like long squares(Appendable destination)
:
works with both StringBuilder
and OutputStream
. (Returning the count of pairs.)
Just a sketch how to reduce run time machine operations:
- determine
max
as the maximum input value (terminate with no pairs if negative), and maxRoot = floor(sqrt(max
+1)) - establish the count of every number from -maxRoot to maxRoot
(assuming [5, 25] was be reported six times if another five was in the example input -
specifying required output by example is hard, by a single example sub-optimal) - for every non-negative input number that has integer roots in the input, report as many pairs for each of its roots as there are occurrences of it
(assuming the order didn't matter between, say,[2,4]
and[-2,4]
.
If that mattered, too, you'd need to keep positions instead of counts, increasing additional space to O(n))
$endgroup$
add a comment |
$begingroup$
From eyeballing it, your code doesn't quite produce the format shown after will return
(pairs separated by ","
instead of "], ["
.
An alternative to building a String
and then printing it is printing its parts immediately -
I'd define a method like long squares(Appendable destination)
:
works with both StringBuilder
and OutputStream
. (Returning the count of pairs.)
Just a sketch how to reduce run time machine operations:
- determine
max
as the maximum input value (terminate with no pairs if negative), and maxRoot = floor(sqrt(max
+1)) - establish the count of every number from -maxRoot to maxRoot
(assuming [5, 25] was be reported six times if another five was in the example input -
specifying required output by example is hard, by a single example sub-optimal) - for every non-negative input number that has integer roots in the input, report as many pairs for each of its roots as there are occurrences of it
(assuming the order didn't matter between, say,[2,4]
and[-2,4]
.
If that mattered, too, you'd need to keep positions instead of counts, increasing additional space to O(n))
$endgroup$
From eyeballing it, your code doesn't quite produce the format shown after will return
(pairs separated by ","
instead of "], ["
.
An alternative to building a String
and then printing it is printing its parts immediately -
I'd define a method like long squares(Appendable destination)
:
works with both StringBuilder
and OutputStream
. (Returning the count of pairs.)
Just a sketch how to reduce run time machine operations:
- determine
max
as the maximum input value (terminate with no pairs if negative), and maxRoot = floor(sqrt(max
+1)) - establish the count of every number from -maxRoot to maxRoot
(assuming [5, 25] was be reported six times if another five was in the example input -
specifying required output by example is hard, by a single example sub-optimal) - for every non-negative input number that has integer roots in the input, report as many pairs for each of its roots as there are occurrences of it
(assuming the order didn't matter between, say,[2,4]
and[-2,4]
.
If that mattered, too, you'd need to keep positions instead of counts, increasing additional space to O(n))
answered 3 mins ago
greybeardgreybeard
1,7711 gold badge7 silver badges23 bronze badges
1,7711 gold badge7 silver badges23 bronze badges
add a comment |
add a comment |
JanB is a new contributor. Be nice, and check out our Code of Conduct.
JanB is a new contributor. Be nice, and check out our Code of Conduct.
JanB is a new contributor. Be nice, and check out our Code of Conduct.
JanB is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f224365%2ffinding-all-possible-pairs-of-square-numbers-in-an-array%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown