For every integer in an array, find the nearest greater integer both before and after it
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
-1
down vote
favorite
The given code gives correct output but exceeds the time limit and I have no idea how to optimize it. I know it is of $O(n^2)$ complexity but I am not able to get anywhere near to optimizing it. Even a few hints would be appreciated.
The question is this:
The problem is given an array $A$ having $N$ integers, for each $i$ $(1le ile N)$, find $x+y$, where $x$ is the largest number less than $i$ such that $A[x]gt A[i]$ and $y$ is the smallest number greater than $i$ such that $A[y]gt A[i]$. If there is no $xlt i$ such that $A[x]gt A[i]$, then take $x=-1$. Similarly, if there is no $ygt i$ such that $A[y]gt A[i]$, then take $y=-1$.
import java.util.*;
import java.io.*;
class Alpha{
public static void main(String args) throws IOException
int n=0,i=0,x=-1,y=-1,sum=0,m1,m2;
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n=Integer.parseInt(st.nextToken());
Stack<Integer> stk=new Stack<>();
long arr = new long[n];
String str=br.readLine().split(" ");
for(i=0;i<n;i++)
arr[i]=Long.parseLong(str[i]);
for(i=n-1;i>=0;i--)
x=-1;
y=-1;
for(int j=i-1;j>=0;j--)
if(arr[j]>arr[i])
x=j+1;
break;
stk.push(x);
for(int j=i+1;j<n;j++)
if(arr[j]>arr[i])
y=j+1;
break;
stk.push(y);
while(!stk.isEmpty())
m1=stk.peek();
stk.pop();
m2=stk.peek();
stk.pop();
sum=m1+m2;
System.out.print(sum+" ");
java time-limit-exceeded complexity
add a comment |Â
up vote
-1
down vote
favorite
The given code gives correct output but exceeds the time limit and I have no idea how to optimize it. I know it is of $O(n^2)$ complexity but I am not able to get anywhere near to optimizing it. Even a few hints would be appreciated.
The question is this:
The problem is given an array $A$ having $N$ integers, for each $i$ $(1le ile N)$, find $x+y$, where $x$ is the largest number less than $i$ such that $A[x]gt A[i]$ and $y$ is the smallest number greater than $i$ such that $A[y]gt A[i]$. If there is no $xlt i$ such that $A[x]gt A[i]$, then take $x=-1$. Similarly, if there is no $ygt i$ such that $A[y]gt A[i]$, then take $y=-1$.
import java.util.*;
import java.io.*;
class Alpha{
public static void main(String args) throws IOException
int n=0,i=0,x=-1,y=-1,sum=0,m1,m2;
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n=Integer.parseInt(st.nextToken());
Stack<Integer> stk=new Stack<>();
long arr = new long[n];
String str=br.readLine().split(" ");
for(i=0;i<n;i++)
arr[i]=Long.parseLong(str[i]);
for(i=n-1;i>=0;i--)
x=-1;
y=-1;
for(int j=i-1;j>=0;j--)
if(arr[j]>arr[i])
x=j+1;
break;
stk.push(x);
for(int j=i+1;j<n;j++)
if(arr[j]>arr[i])
y=j+1;
break;
stk.push(y);
while(!stk.isEmpty())
m1=stk.peek();
stk.pop();
m2=stk.peek();
stk.pop();
sum=m1+m2;
System.out.print(sum+" ");
java time-limit-exceeded complexity
1
Does it exceed the time limit for any input, or for what inputs does it complete successfully?
â Sam Onela
May 24 at 19:27
2
Welcome to Code Review! Links can rot. Please include a description of the challenge here in your question.
â Dannnno
May 24 at 19:47
add a comment |Â
up vote
-1
down vote
favorite
up vote
-1
down vote
favorite
The given code gives correct output but exceeds the time limit and I have no idea how to optimize it. I know it is of $O(n^2)$ complexity but I am not able to get anywhere near to optimizing it. Even a few hints would be appreciated.
The question is this:
The problem is given an array $A$ having $N$ integers, for each $i$ $(1le ile N)$, find $x+y$, where $x$ is the largest number less than $i$ such that $A[x]gt A[i]$ and $y$ is the smallest number greater than $i$ such that $A[y]gt A[i]$. If there is no $xlt i$ such that $A[x]gt A[i]$, then take $x=-1$. Similarly, if there is no $ygt i$ such that $A[y]gt A[i]$, then take $y=-1$.
import java.util.*;
import java.io.*;
class Alpha{
public static void main(String args) throws IOException
int n=0,i=0,x=-1,y=-1,sum=0,m1,m2;
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n=Integer.parseInt(st.nextToken());
Stack<Integer> stk=new Stack<>();
long arr = new long[n];
String str=br.readLine().split(" ");
for(i=0;i<n;i++)
arr[i]=Long.parseLong(str[i]);
for(i=n-1;i>=0;i--)
x=-1;
y=-1;
for(int j=i-1;j>=0;j--)
if(arr[j]>arr[i])
x=j+1;
break;
stk.push(x);
for(int j=i+1;j<n;j++)
if(arr[j]>arr[i])
y=j+1;
break;
stk.push(y);
while(!stk.isEmpty())
m1=stk.peek();
stk.pop();
m2=stk.peek();
stk.pop();
sum=m1+m2;
System.out.print(sum+" ");
java time-limit-exceeded complexity
The given code gives correct output but exceeds the time limit and I have no idea how to optimize it. I know it is of $O(n^2)$ complexity but I am not able to get anywhere near to optimizing it. Even a few hints would be appreciated.
The question is this:
The problem is given an array $A$ having $N$ integers, for each $i$ $(1le ile N)$, find $x+y$, where $x$ is the largest number less than $i$ such that $A[x]gt A[i]$ and $y$ is the smallest number greater than $i$ such that $A[y]gt A[i]$. If there is no $xlt i$ such that $A[x]gt A[i]$, then take $x=-1$. Similarly, if there is no $ygt i$ such that $A[y]gt A[i]$, then take $y=-1$.
import java.util.*;
import java.io.*;
class Alpha{
public static void main(String args) throws IOException
int n=0,i=0,x=-1,y=-1,sum=0,m1,m2;
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n=Integer.parseInt(st.nextToken());
Stack<Integer> stk=new Stack<>();
long arr = new long[n];
String str=br.readLine().split(" ");
for(i=0;i<n;i++)
arr[i]=Long.parseLong(str[i]);
for(i=n-1;i>=0;i--)
x=-1;
y=-1;
for(int j=i-1;j>=0;j--)
if(arr[j]>arr[i])
x=j+1;
break;
stk.push(x);
for(int j=i+1;j<n;j++)
if(arr[j]>arr[i])
y=j+1;
break;
stk.push(y);
while(!stk.isEmpty())
m1=stk.peek();
stk.pop();
m2=stk.peek();
stk.pop();
sum=m1+m2;
System.out.print(sum+" ");
java time-limit-exceeded complexity
edited May 25 at 2:43
200_success
123k14143399
123k14143399
asked May 24 at 19:20
Manu Sharma
31
31
1
Does it exceed the time limit for any input, or for what inputs does it complete successfully?
â Sam Onela
May 24 at 19:27
2
Welcome to Code Review! Links can rot. Please include a description of the challenge here in your question.
â Dannnno
May 24 at 19:47
add a comment |Â
1
Does it exceed the time limit for any input, or for what inputs does it complete successfully?
â Sam Onela
May 24 at 19:27
2
Welcome to Code Review! Links can rot. Please include a description of the challenge here in your question.
â Dannnno
May 24 at 19:47
1
1
Does it exceed the time limit for any input, or for what inputs does it complete successfully?
â Sam Onela
May 24 at 19:27
Does it exceed the time limit for any input, or for what inputs does it complete successfully?
â Sam Onela
May 24 at 19:27
2
2
Welcome to Code Review! Links can rot. Please include a description of the challenge here in your question.
â Dannnno
May 24 at 19:47
Welcome to Code Review! Links can rot. Please include a description of the challenge here in your question.
â Dannnno
May 24 at 19:47
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
In the following explanations, I'm going to use 1-based indexes just like the description does, even though it's confusing seeing as Java arrays have zero-based indexes.
Obviously, $x_1=-1$. Also, if $a_i-1gt a_i$, then $x_i=i-1$. So as long as every integer is less than the last one, we can just store the $x$ for every array element one by one.
But what if we encounter an $a_i$ where $a_i-1le a_i$? Do we need to iterate over all the preceding elements to find the nearest greater integer? No, because we already know the position of the next greater integer before $a_i-1$, namely $x_i-1$. Every element between $a_i-1$ and $a_x_i-1$ will be less than or equal to $a_i-1$, and therefore also less than or equal to $a_i$ (since $a_i-1le a_i$), so we can skip all these elements and jump to $a_x_i-1$.
If $a_x_i-1gt a_i$, we have found $x_i=x_i-1$. Otherwise, we repeat the process, i.e. jumping to the next greater integer before $a_x_i-1$ by querying $x_x_i-1$, and so on, until we arrive at an integer that is greater than $a_i$ (or until there are no more array elements).
The same process can be repeated in the other direction of the array to find all $y$ values. So instead of calculating $x$ and $y$ for every array element independently, you can use the already calculated values to speed up the process, based on the relationships explained above.
Apart from that, your code is a bit chaotic. I would suggest separating user interface from program logic, for example writing one method that accepts an
int
(orlong
) as a parameter and returns anint
of equal length containing the sum of $x$ and $y$ for every array element, and another method that reads user input from the command line (or from wherever), converts this input to anint
orlong
, passes this array to the other method, and converts theint
returned by the method to the required output format.Note that $x+y$ may overflow an
int
, but a Java array can only contain a maximum ofInteger.MAX_VALUE
($=2^31-1$) elements (and that's only in theory, I think I've read that, in practice, even with memory implications aside, the maximum length of an array might be slightly lower), so the maximum sum that could ever occur isInteger.MAX_VALUE + Integer.MAX_VALUE - 2
for an element at the one-based indexInteger.MAX_VALUE - 1
, andInteger.MAX_VALUE + Integer.MAX_VALUE - 2
$=2^32-4$ still fits into 32 bits, so no information is lost if you store the value in anint
, it's just that Java treats the highest-order bit of anint
as a sign-bit because Java doesn't support unsigned 32-bit integers.Also, $2^32-4$ overflows to
-4
, and the smallest possible non-overflowing result of $x+y$ is $-2$, so it will always be possible to tell an overflow and a truly negative result apart. Anint
would therefore suffice to store the necessary results.The class
Stack
is antiquated â the documentation recommends to useDeque
implementations instead.Reduce the scope of variables to the smallest extent necessary to make the code less confusing.
x
andy
are only needed in the secondfor
loop (the outerfor
loop), and they also don't need to keep their state from one iteration to the next, so they should not only be initialized, but also declared there. Likewise,sum
,m1
andm2
can be declared in the lastwhile
loop.Also, declaring one
int
variablei
outside thefor
loops and using this variable in both loops gives the illusion that the value ofi
in the secondfor
loop somehow depends on its final value after the first loop. This is not true, as you manually set it ton-1
, so it would be less confusing if you either declared a separatei
in every loop so that thesei
s don't exist outside the loop for which they are relevant, or you don't explicitly seti
ton-1
at the beginning of the second loop. I would prefer the first version because it keeps the loop variables in their loop, even if it takes a few microseconds longer because the newi
has to be initialized ton-1
.Instead of storing an entire input String in memory, you could wrap a
Scanner
around anInputStream
to parse it into along
:Scanner inputScanner = new Scanner(System.in);
int n = inputScanner.nextInt();
inputScanner.nextLine();
long arr = new long[n];
for (int i = 0; i < n; i++)
arr[i] = inputScanner.nextLong();This is not equivalent to your code, because it doesn't require the array elements to be on one line. I doubt that this matters, but theoretically, you could configure the scanner to exlude line terminators from its delimiter pattern after you read the value of
n
and skip the rest of the line by invokingScanner.useDelimiter(String)
and passing a custom regular expression that matches whitespace excluding line terminators (the default delimiter pattern of aScanner
is whitespace).
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
In the following explanations, I'm going to use 1-based indexes just like the description does, even though it's confusing seeing as Java arrays have zero-based indexes.
Obviously, $x_1=-1$. Also, if $a_i-1gt a_i$, then $x_i=i-1$. So as long as every integer is less than the last one, we can just store the $x$ for every array element one by one.
But what if we encounter an $a_i$ where $a_i-1le a_i$? Do we need to iterate over all the preceding elements to find the nearest greater integer? No, because we already know the position of the next greater integer before $a_i-1$, namely $x_i-1$. Every element between $a_i-1$ and $a_x_i-1$ will be less than or equal to $a_i-1$, and therefore also less than or equal to $a_i$ (since $a_i-1le a_i$), so we can skip all these elements and jump to $a_x_i-1$.
If $a_x_i-1gt a_i$, we have found $x_i=x_i-1$. Otherwise, we repeat the process, i.e. jumping to the next greater integer before $a_x_i-1$ by querying $x_x_i-1$, and so on, until we arrive at an integer that is greater than $a_i$ (or until there are no more array elements).
The same process can be repeated in the other direction of the array to find all $y$ values. So instead of calculating $x$ and $y$ for every array element independently, you can use the already calculated values to speed up the process, based on the relationships explained above.
Apart from that, your code is a bit chaotic. I would suggest separating user interface from program logic, for example writing one method that accepts an
int
(orlong
) as a parameter and returns anint
of equal length containing the sum of $x$ and $y$ for every array element, and another method that reads user input from the command line (or from wherever), converts this input to anint
orlong
, passes this array to the other method, and converts theint
returned by the method to the required output format.Note that $x+y$ may overflow an
int
, but a Java array can only contain a maximum ofInteger.MAX_VALUE
($=2^31-1$) elements (and that's only in theory, I think I've read that, in practice, even with memory implications aside, the maximum length of an array might be slightly lower), so the maximum sum that could ever occur isInteger.MAX_VALUE + Integer.MAX_VALUE - 2
for an element at the one-based indexInteger.MAX_VALUE - 1
, andInteger.MAX_VALUE + Integer.MAX_VALUE - 2
$=2^32-4$ still fits into 32 bits, so no information is lost if you store the value in anint
, it's just that Java treats the highest-order bit of anint
as a sign-bit because Java doesn't support unsigned 32-bit integers.Also, $2^32-4$ overflows to
-4
, and the smallest possible non-overflowing result of $x+y$ is $-2$, so it will always be possible to tell an overflow and a truly negative result apart. Anint
would therefore suffice to store the necessary results.The class
Stack
is antiquated â the documentation recommends to useDeque
implementations instead.Reduce the scope of variables to the smallest extent necessary to make the code less confusing.
x
andy
are only needed in the secondfor
loop (the outerfor
loop), and they also don't need to keep their state from one iteration to the next, so they should not only be initialized, but also declared there. Likewise,sum
,m1
andm2
can be declared in the lastwhile
loop.Also, declaring one
int
variablei
outside thefor
loops and using this variable in both loops gives the illusion that the value ofi
in the secondfor
loop somehow depends on its final value after the first loop. This is not true, as you manually set it ton-1
, so it would be less confusing if you either declared a separatei
in every loop so that thesei
s don't exist outside the loop for which they are relevant, or you don't explicitly seti
ton-1
at the beginning of the second loop. I would prefer the first version because it keeps the loop variables in their loop, even if it takes a few microseconds longer because the newi
has to be initialized ton-1
.Instead of storing an entire input String in memory, you could wrap a
Scanner
around anInputStream
to parse it into along
:Scanner inputScanner = new Scanner(System.in);
int n = inputScanner.nextInt();
inputScanner.nextLine();
long arr = new long[n];
for (int i = 0; i < n; i++)
arr[i] = inputScanner.nextLong();This is not equivalent to your code, because it doesn't require the array elements to be on one line. I doubt that this matters, but theoretically, you could configure the scanner to exlude line terminators from its delimiter pattern after you read the value of
n
and skip the rest of the line by invokingScanner.useDelimiter(String)
and passing a custom regular expression that matches whitespace excluding line terminators (the default delimiter pattern of aScanner
is whitespace).
add a comment |Â
up vote
1
down vote
accepted
In the following explanations, I'm going to use 1-based indexes just like the description does, even though it's confusing seeing as Java arrays have zero-based indexes.
Obviously, $x_1=-1$. Also, if $a_i-1gt a_i$, then $x_i=i-1$. So as long as every integer is less than the last one, we can just store the $x$ for every array element one by one.
But what if we encounter an $a_i$ where $a_i-1le a_i$? Do we need to iterate over all the preceding elements to find the nearest greater integer? No, because we already know the position of the next greater integer before $a_i-1$, namely $x_i-1$. Every element between $a_i-1$ and $a_x_i-1$ will be less than or equal to $a_i-1$, and therefore also less than or equal to $a_i$ (since $a_i-1le a_i$), so we can skip all these elements and jump to $a_x_i-1$.
If $a_x_i-1gt a_i$, we have found $x_i=x_i-1$. Otherwise, we repeat the process, i.e. jumping to the next greater integer before $a_x_i-1$ by querying $x_x_i-1$, and so on, until we arrive at an integer that is greater than $a_i$ (or until there are no more array elements).
The same process can be repeated in the other direction of the array to find all $y$ values. So instead of calculating $x$ and $y$ for every array element independently, you can use the already calculated values to speed up the process, based on the relationships explained above.
Apart from that, your code is a bit chaotic. I would suggest separating user interface from program logic, for example writing one method that accepts an
int
(orlong
) as a parameter and returns anint
of equal length containing the sum of $x$ and $y$ for every array element, and another method that reads user input from the command line (or from wherever), converts this input to anint
orlong
, passes this array to the other method, and converts theint
returned by the method to the required output format.Note that $x+y$ may overflow an
int
, but a Java array can only contain a maximum ofInteger.MAX_VALUE
($=2^31-1$) elements (and that's only in theory, I think I've read that, in practice, even with memory implications aside, the maximum length of an array might be slightly lower), so the maximum sum that could ever occur isInteger.MAX_VALUE + Integer.MAX_VALUE - 2
for an element at the one-based indexInteger.MAX_VALUE - 1
, andInteger.MAX_VALUE + Integer.MAX_VALUE - 2
$=2^32-4$ still fits into 32 bits, so no information is lost if you store the value in anint
, it's just that Java treats the highest-order bit of anint
as a sign-bit because Java doesn't support unsigned 32-bit integers.Also, $2^32-4$ overflows to
-4
, and the smallest possible non-overflowing result of $x+y$ is $-2$, so it will always be possible to tell an overflow and a truly negative result apart. Anint
would therefore suffice to store the necessary results.The class
Stack
is antiquated â the documentation recommends to useDeque
implementations instead.Reduce the scope of variables to the smallest extent necessary to make the code less confusing.
x
andy
are only needed in the secondfor
loop (the outerfor
loop), and they also don't need to keep their state from one iteration to the next, so they should not only be initialized, but also declared there. Likewise,sum
,m1
andm2
can be declared in the lastwhile
loop.Also, declaring one
int
variablei
outside thefor
loops and using this variable in both loops gives the illusion that the value ofi
in the secondfor
loop somehow depends on its final value after the first loop. This is not true, as you manually set it ton-1
, so it would be less confusing if you either declared a separatei
in every loop so that thesei
s don't exist outside the loop for which they are relevant, or you don't explicitly seti
ton-1
at the beginning of the second loop. I would prefer the first version because it keeps the loop variables in their loop, even if it takes a few microseconds longer because the newi
has to be initialized ton-1
.Instead of storing an entire input String in memory, you could wrap a
Scanner
around anInputStream
to parse it into along
:Scanner inputScanner = new Scanner(System.in);
int n = inputScanner.nextInt();
inputScanner.nextLine();
long arr = new long[n];
for (int i = 0; i < n; i++)
arr[i] = inputScanner.nextLong();This is not equivalent to your code, because it doesn't require the array elements to be on one line. I doubt that this matters, but theoretically, you could configure the scanner to exlude line terminators from its delimiter pattern after you read the value of
n
and skip the rest of the line by invokingScanner.useDelimiter(String)
and passing a custom regular expression that matches whitespace excluding line terminators (the default delimiter pattern of aScanner
is whitespace).
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
In the following explanations, I'm going to use 1-based indexes just like the description does, even though it's confusing seeing as Java arrays have zero-based indexes.
Obviously, $x_1=-1$. Also, if $a_i-1gt a_i$, then $x_i=i-1$. So as long as every integer is less than the last one, we can just store the $x$ for every array element one by one.
But what if we encounter an $a_i$ where $a_i-1le a_i$? Do we need to iterate over all the preceding elements to find the nearest greater integer? No, because we already know the position of the next greater integer before $a_i-1$, namely $x_i-1$. Every element between $a_i-1$ and $a_x_i-1$ will be less than or equal to $a_i-1$, and therefore also less than or equal to $a_i$ (since $a_i-1le a_i$), so we can skip all these elements and jump to $a_x_i-1$.
If $a_x_i-1gt a_i$, we have found $x_i=x_i-1$. Otherwise, we repeat the process, i.e. jumping to the next greater integer before $a_x_i-1$ by querying $x_x_i-1$, and so on, until we arrive at an integer that is greater than $a_i$ (or until there are no more array elements).
The same process can be repeated in the other direction of the array to find all $y$ values. So instead of calculating $x$ and $y$ for every array element independently, you can use the already calculated values to speed up the process, based on the relationships explained above.
Apart from that, your code is a bit chaotic. I would suggest separating user interface from program logic, for example writing one method that accepts an
int
(orlong
) as a parameter and returns anint
of equal length containing the sum of $x$ and $y$ for every array element, and another method that reads user input from the command line (or from wherever), converts this input to anint
orlong
, passes this array to the other method, and converts theint
returned by the method to the required output format.Note that $x+y$ may overflow an
int
, but a Java array can only contain a maximum ofInteger.MAX_VALUE
($=2^31-1$) elements (and that's only in theory, I think I've read that, in practice, even with memory implications aside, the maximum length of an array might be slightly lower), so the maximum sum that could ever occur isInteger.MAX_VALUE + Integer.MAX_VALUE - 2
for an element at the one-based indexInteger.MAX_VALUE - 1
, andInteger.MAX_VALUE + Integer.MAX_VALUE - 2
$=2^32-4$ still fits into 32 bits, so no information is lost if you store the value in anint
, it's just that Java treats the highest-order bit of anint
as a sign-bit because Java doesn't support unsigned 32-bit integers.Also, $2^32-4$ overflows to
-4
, and the smallest possible non-overflowing result of $x+y$ is $-2$, so it will always be possible to tell an overflow and a truly negative result apart. Anint
would therefore suffice to store the necessary results.The class
Stack
is antiquated â the documentation recommends to useDeque
implementations instead.Reduce the scope of variables to the smallest extent necessary to make the code less confusing.
x
andy
are only needed in the secondfor
loop (the outerfor
loop), and they also don't need to keep their state from one iteration to the next, so they should not only be initialized, but also declared there. Likewise,sum
,m1
andm2
can be declared in the lastwhile
loop.Also, declaring one
int
variablei
outside thefor
loops and using this variable in both loops gives the illusion that the value ofi
in the secondfor
loop somehow depends on its final value after the first loop. This is not true, as you manually set it ton-1
, so it would be less confusing if you either declared a separatei
in every loop so that thesei
s don't exist outside the loop for which they are relevant, or you don't explicitly seti
ton-1
at the beginning of the second loop. I would prefer the first version because it keeps the loop variables in their loop, even if it takes a few microseconds longer because the newi
has to be initialized ton-1
.Instead of storing an entire input String in memory, you could wrap a
Scanner
around anInputStream
to parse it into along
:Scanner inputScanner = new Scanner(System.in);
int n = inputScanner.nextInt();
inputScanner.nextLine();
long arr = new long[n];
for (int i = 0; i < n; i++)
arr[i] = inputScanner.nextLong();This is not equivalent to your code, because it doesn't require the array elements to be on one line. I doubt that this matters, but theoretically, you could configure the scanner to exlude line terminators from its delimiter pattern after you read the value of
n
and skip the rest of the line by invokingScanner.useDelimiter(String)
and passing a custom regular expression that matches whitespace excluding line terminators (the default delimiter pattern of aScanner
is whitespace).
In the following explanations, I'm going to use 1-based indexes just like the description does, even though it's confusing seeing as Java arrays have zero-based indexes.
Obviously, $x_1=-1$. Also, if $a_i-1gt a_i$, then $x_i=i-1$. So as long as every integer is less than the last one, we can just store the $x$ for every array element one by one.
But what if we encounter an $a_i$ where $a_i-1le a_i$? Do we need to iterate over all the preceding elements to find the nearest greater integer? No, because we already know the position of the next greater integer before $a_i-1$, namely $x_i-1$. Every element between $a_i-1$ and $a_x_i-1$ will be less than or equal to $a_i-1$, and therefore also less than or equal to $a_i$ (since $a_i-1le a_i$), so we can skip all these elements and jump to $a_x_i-1$.
If $a_x_i-1gt a_i$, we have found $x_i=x_i-1$. Otherwise, we repeat the process, i.e. jumping to the next greater integer before $a_x_i-1$ by querying $x_x_i-1$, and so on, until we arrive at an integer that is greater than $a_i$ (or until there are no more array elements).
The same process can be repeated in the other direction of the array to find all $y$ values. So instead of calculating $x$ and $y$ for every array element independently, you can use the already calculated values to speed up the process, based on the relationships explained above.
Apart from that, your code is a bit chaotic. I would suggest separating user interface from program logic, for example writing one method that accepts an
int
(orlong
) as a parameter and returns anint
of equal length containing the sum of $x$ and $y$ for every array element, and another method that reads user input from the command line (or from wherever), converts this input to anint
orlong
, passes this array to the other method, and converts theint
returned by the method to the required output format.Note that $x+y$ may overflow an
int
, but a Java array can only contain a maximum ofInteger.MAX_VALUE
($=2^31-1$) elements (and that's only in theory, I think I've read that, in practice, even with memory implications aside, the maximum length of an array might be slightly lower), so the maximum sum that could ever occur isInteger.MAX_VALUE + Integer.MAX_VALUE - 2
for an element at the one-based indexInteger.MAX_VALUE - 1
, andInteger.MAX_VALUE + Integer.MAX_VALUE - 2
$=2^32-4$ still fits into 32 bits, so no information is lost if you store the value in anint
, it's just that Java treats the highest-order bit of anint
as a sign-bit because Java doesn't support unsigned 32-bit integers.Also, $2^32-4$ overflows to
-4
, and the smallest possible non-overflowing result of $x+y$ is $-2$, so it will always be possible to tell an overflow and a truly negative result apart. Anint
would therefore suffice to store the necessary results.The class
Stack
is antiquated â the documentation recommends to useDeque
implementations instead.Reduce the scope of variables to the smallest extent necessary to make the code less confusing.
x
andy
are only needed in the secondfor
loop (the outerfor
loop), and they also don't need to keep their state from one iteration to the next, so they should not only be initialized, but also declared there. Likewise,sum
,m1
andm2
can be declared in the lastwhile
loop.Also, declaring one
int
variablei
outside thefor
loops and using this variable in both loops gives the illusion that the value ofi
in the secondfor
loop somehow depends on its final value after the first loop. This is not true, as you manually set it ton-1
, so it would be less confusing if you either declared a separatei
in every loop so that thesei
s don't exist outside the loop for which they are relevant, or you don't explicitly seti
ton-1
at the beginning of the second loop. I would prefer the first version because it keeps the loop variables in their loop, even if it takes a few microseconds longer because the newi
has to be initialized ton-1
.Instead of storing an entire input String in memory, you could wrap a
Scanner
around anInputStream
to parse it into along
:Scanner inputScanner = new Scanner(System.in);
int n = inputScanner.nextInt();
inputScanner.nextLine();
long arr = new long[n];
for (int i = 0; i < n; i++)
arr[i] = inputScanner.nextLong();This is not equivalent to your code, because it doesn't require the array elements to be on one line. I doubt that this matters, but theoretically, you could configure the scanner to exlude line terminators from its delimiter pattern after you read the value of
n
and skip the rest of the line by invokingScanner.useDelimiter(String)
and passing a custom regular expression that matches whitespace excluding line terminators (the default delimiter pattern of aScanner
is whitespace).
answered May 25 at 1:09
Stingy
1,888212
1,888212
add a comment |Â
add a comment |Â
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
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195109%2ffor-every-integer-in-an-array-find-the-nearest-greater-integer-both-before-and%23new-answer', 'question_page');
);
Post as a guest
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
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
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
1
Does it exceed the time limit for any input, or for what inputs does it complete successfully?
â Sam Onela
May 24 at 19:27
2
Welcome to Code Review! Links can rot. Please include a description of the challenge here in your question.
â Dannnno
May 24 at 19:47