Reduced execution time when using long instead of int - java

I have been solving competitive coding questions for a brief period of time now, and I have observed something. Sometimes, in any solution involving array manipulations or addition or multiplication, some of the test cases gave me TLE (time limit exceeded).
I used integer variables. When I change such variables to the long type, the execution time for that test case reduces, and sometimes, makes my solution excepted 100% instead of partial acceptance.
My question is, how, and why, is this the case? And in which scenarios would this (long over int) not hold true? The only disadvantage I can think of for not using long over int in such scenarios would be higher memory consumption.
UPDATE - Code Example: Here is a sample code I wrote to rotate a given array of numbers to the right by K places and display the output.
public static void main(String [] args)
{
Scanner sc = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
int numTestCases = sc.nextInt();
for(int i = 0; i< numTestCases;i++)
{
int arraySize = sc.nextInt();
int offset = sc.nextInt();
int [] array = new int[arraySize];
if(offset>=arraySize)
offset = offset%arraySize;
int count = 0;
while(count<arraySize)
{
array[offset] = sc.nextInt();
offset = (offset+1)%arraySize;
count++;
}
for(int j = 0; j< arraySize; j++) {
sb.append(array[j]);
sb.append(" ");
}
sb.append("\n");
}
System.out.println(sb.toString());
sc.close();
}
One of the test cases gave a TLE for this code. However, when changed the array type to long, that test case passed.
The test case contained an array of 89384 integers (all less than 100 - or atleast within int range) and had to be rotated right by 930886 places.

Related

How to multiply two long values in java

I am trying to multiply two largest numbers from an array of numbers. Its working fine for small numbers.
Correct input / output - this is working:
3 10 2 8
80
Correct input / output - this is failing:
2 100000 90000
9000000000
My output is however 10000000000 instead.
Can someone tell me what is wrong in my code?
public static Long sumPairwise(Long[] numbers){
int index=0;
int n = numbers.length;
for(int i=1;i<n;i++){
if(numbers[i]>numbers[index])
index=i;
}
numbers[n-1]= numbers[index];
index=0;
for(int j=1;j<n-1;j++){
if(numbers[j]>numbers[index])
index=j;
}
numbers[n-2]=numbers[index];
Long product = (numbers[n-2])*(numbers[n-1]);
return product ;
}
public static void main(String [] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Long numbers[] = new Long[n];
for (int i=0;i<n;i++)
numbers[i]= sc.nextLong();
System.out.println(sumPairwise(numbers));
}
There is a bug in your code: numbers[n-1] may well contain the second highest number. You are overwriting that number with the highest number in your code, before you try and put it at the first to last position.
One way to overcome this is to sort the array using Arrays.sort, this way you are sure that the last two numbers are the highest and second highest number.
public static long multiplyLargestTwoNumbers(long[] numbers) {
long[] sortedNumbers = numbers.clone();
Arrays.sort(sortedNumbers);
int size = numbers.length;
// multiply highest and second highest number
return sortedNumbers[size - 1] * sortedNumbers[size - 2];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long numbers[] = new long[n];
for (int i = 0; i < n; i++) {
numbers[i] = sc.nextLong();
}
System.out.println(multiplyLargestTwoNumbers(numbers));
}
Other changes:
using long instead of Long: try and use primitive types when the objective reference types are not needed (you need Long if you want to use e.g. a List because a List can only hold object references);
spaced out for loops, please use white space;
renamed method, as it does't add anything pairwise;
used curly braces for for loop in main method;
removed spurious parentheses in part that performs multiplication.
You might also introduce an if statement that first checks if the numbers array does indeed contain at least two elements. This is called a guard statement.
Finally remember that byte, short and long all contain signed numbers of a specific bit size. Basically you are performing calculations modulus 2^n where n is the bit size. If the value is too large it may overflow and return an incorrect result. For that you need BigInteger.
You are replacing the original number in that index with another number.
That is causing the issue.
Please just simply find the max 2 numbers from below logic and multiply.
Also, remember to close scanner.
Here the simple solution. This will work only for positive integers.
import java.util.Scanner;
public class Snippet {
public static long multiplyHighestTwoValues(Long[] numbers) {
long maxOne = 0;
long maxTwo = 0;
for (long n : numbers) {
if (maxOne < n) {
maxTwo = maxOne;
maxOne = n;
} else if (maxTwo < n) {
maxTwo = n;
}
}
long product = maxOne * maxTwo;
return product;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Long numbers[] = new Long[n];
for (int i = 0; i < n; i++)
numbers[i] = sc.nextLong();
System.out.println(sumPairwise(numbers));
sc.close();
}
}
Instead of Long try to use BigInteger to multiply larger values that fit into long, otherwise your result may overflow.
Use BigDecimal instead for multiplying floating point numbers.

How to manipulate arrays?

I have an array with 2 spots in it(it must have 2 spots in the beginning ). i need to get user input and double the array when user enters more than the array can hold. Also Upon entering -1 the user input should stop. The array must also not accept duplicates.
i don't know how to have the not accept duplicates and end the program when the user entters -1 while still doubling the array every time it fills up.
Here's what i have so far but its flawed and wont run properly.
public class GroupArrays {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
int [] numbers = new int[2];
int x;
int n=0;
for( int i = 0; i<numbers.length; i++){
System.out.println("Please enter number");
int number = input.nextInt();
while ( input.hasNextInt() )
{
x = input.nextInt();
if ( n == numbers.length )
{
int[] h;
h = new int[ 2*numbers.length ];
for ( int i1 = 0; i1 < numbers.length; i1++ )
h[i1] = numbers[i1];
numbers = h;
}
if(x == -1){
break;
}
numbers[n] = x;
n++;
}
for ( int i1 = 0; i1 < numbers.length; i1++ )
System.out.println( numbers[i1] );
}
}
I can figure out how to do all the things individually but it becomes difficult when i have to do them all to 1 array and do user input.
PS. I feel like i have made this more complicated than it needs to be.
I'm only give you hints on how to solve the problem, and on how to write code that is easier to understand and maintain, even (and most importantly) by yourself.
Split the code in methods, doing simple tasks. Don't try to write everything as a giant piece of code.
The pseudo code of the algorithm would be
loop
ask and get input number
if (number is -1)
break out of the loop
else if array already contains number
print error message
else
if no space left in array
array = copy of array with doubled length
store number in next available index in array and increment the next available spot index
end of loop
print the array
Now, you can see that there are things that can be implemented easily as separate methods:
ask and get input number
check if array already contains number
copy of array with doubled length
print the array
Start by writing the signature of these simple methods, without implementing them. Then write the algorithm by calling these methods.
Then implement the simple methods one by one and test them one by one. You can do that, for now, by just writing a main method that calls them with hard-coded arguments, and see if they do what you expect them to do.
Once every of them is written and tested, test the main algorithm. If you made a mistake, iterate, by re-testing the methods you had to modify.
While coding all the methods, choose names that indicate clearly what the variables represent, and what the methods do, even if they're long. For example, nextAvailableIndex is much much clearer than x. Using good names helps everyone, including you, to understand the code and find bugs.
Also, indent the code strictly, as you type. The code you posted is not indented correctly, which makes it difficult to understand its structure. Stick to 4 spaces as indentation level, and always use curly braces around the body of your if, for, etc. ALways place them after the if/for, and not on the next line. Be consistent.
public class GroupArrays {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
int [] numbers = new int[2];
int x;
int n=0;
for( int i = 0; i<numbers.length; i++){
System.out.println("Please enter number");
int number = input.nextInt();
while ( input.hasNextInt() )
{
x = input.nextInt();
if ( n == numbers.length )
{
int[] h;
h = Arrays.copyOf[numbers,2*numbers.length ]; //change
}
if(x == -1){
break;
}
numbers[n] = x;
n++;
}
for ( int i1 = 0; i1 < numbers.length; i1++ )
System.out.println( numbers[i1] );
}
}
Use Arrays.copyOf(array_name,array_length); to create new arrays with varying lengths.

Two smallest numbers in a set

I am trying to find the two smallest numbers in a set WITHOUT USING ARRAYS. Here is the code:
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int min = in.nextInt();
for(int i = 1; i < N; i++){
int a = in.nextInt();
if(a < min){
min = a;
}
}
System.out.println(min);
It find the smallest number but there is nothing about the second smallest number.
How do I do that?
Please, note that I am a complete beginner to Java so easy explanation and help will be much appreciated)
It´s very very easy:
Scanner in= new Scanner(System.in);
int N = in.nextInt();
int min,min2 = Integer.MAX_VALUE,Integer.MAX_VALUE;
for(int i = 0; i < N; i++){
int a = in.nextInt();
if( a < min){
min = a;
min2 = min;
}
else if( a < min2){
min2 = a;
}
}
System.out.println(min);
System.out.println(min2);
It is about one condition you have to add:
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int min = Integer.MAX_VALUE;
int secondMin = Integer.MAX_VALUE;
for(int i = 0; i < N; i++){
int a = in.nextInt();
if(a < min){
secondMin = min; // the current minimum must be the second smallest
min = a; // allocates the new minimum
}
else if (a < secondMin) {
secondMin = a; // if we did not get a new minimum, it may still be the second smallest number
}
}
System.out.println(min);
System.out.println(secondMin);
General hint: You should call the close method of your Scanner, preferably in a try-with-ressources block:
try(Scanner in = new Scanner(System.in)) {
// other code here
}
That way the stream gets closed, which you should do, if you open a stream.
Solution 1:
The easiest way, that uses your existing code, would be also tracking the second smallest number:
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int min = in.nextInt();
int sMin = Integer.MAX_VALUE;
for(int i = 1; i < N; i++){
int a = in.nextInt();
if(a < min){
sMin = min;
min = a;
} else if(a < sMin) {
sMin = a;
}
}
System.out.println(min);
System.out.println(sMin);
Explanation 1:
The two cases, that can occure with a new Value are:
The new value is smaller than min and sMin. Then you have to set the value of min into smin and afterwards set min to the new min value.
The new value is larger than min and smaller than sMin. Then you only have to set the value of sMin to the new value.
Both min-values are smaller. Then nothing is to do.
Solution 2:
Another, more generic approach would be using a PriorityQueue:
int N = in.nextInt();
PriorityQueue<Integer> minQueue = new PriorityQueue<>();
for(int i = 0; i < N; i++) {
int value = in.nextInt();
minQueue.add(value);
}
int minValue = minQueue.poll();
int secondMinValue = minQueue.poll();
This way you can get the n smallest numbers given by using a loop in which you call the poll() method. (n may be a number < N).
Explanation 2:
The Priority Queue is a datastructure, that internally orders the given elements by the natural order. In the case of Integers this order is given by <,> and =. So when calling poll() you remove the smallest element, that the PriorityQueue has yet encountered.
Try this:
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int min2 = in.nextInt();
int min1 = min2;
for(int i = 1; i < n; i++){
int a = in.nextInt();
if( a < min2){
if(a < min1){
min2 = min1;
min1 = a;
}
else{
min2 = a;
}
}
}
System.out.println(min1 + " " + min2);
This problem can be solved in multiple ways, and the first step in choosing the right solution is to decide what is the most important for you:
Space efficiency, that is, use the minimum possible amount of storage. ThreeFx does this, (s)he only uses constant additional space for the variables N, a, min, and secondMin. "Constant space" means that the amount of data that you store does not depend on how many numbers you are going to read from the stream. In contrast, Tarlen uses linear space, storing all the numbers read from the stream. This means that the amount of space required is directly proportional to N instead of being constant.
Time efficiency, that is, perform as few computations as possible. I believe that ThreeFx's solution is one of the most efficient from this point of view. Tarlen's solution will be a bit slower, because managing the priority queue might require more comparisons.
Extensibility, that is, how easily you could adapt your code when the requirements change slightly. Say that your boss makes you solve the problem that you just posted, to find the two smallest numbers. The next day, he wants the first three, and so on, until the end of the week. You get tired of changing your code every day, so you write a general solution, that will work for any number of elements that he asks for. This is where Tarlen's solution is better.
Readability, that is, how short and easy to understand your code is. I will introduce my own solution here, which is based on a simple idea: put all the numbers in a list, sort it, and take out the first two numbers. Note that this is quite wasteful when it comes to resources: the space is linear (I am storing N numbers), and the time efficiency is O(N log N) at best. Here is my code:
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < N; i++) list.add(in.nextInt());
Collections.sort(list);
System.out.println(list.get(0));
System.out.println(list.get(1));

Numbers I can get by adding an array in java

I need to get a minimum number that I cant get by adding different numbers of an array. Basically if I have these numbers:1,1,1,5; I can get 1,2,3,5,6... but I cant get 4 so that is the number I am looking for. Now this is my code:
import java.util.Scanner;
public class Broj_6 {
public static void main(String[] args) {
Scanner unos = new Scanner(System.in);
int k;
int n = unos.nextInt();
int niz []= new int [n];
for(int i = 0;i<n;i++){
niz[i]=unos.nextInt();
}
BubbleSort(niz);
for(int i = 0;i<n;i++){
System.out.print(niz[i] + " ");
}
for(int br = 1;br<=10000;br++){
for(k = 1;k<n;k++){
if(niz[k]>br){
break;
}
}
int podniz [] = new int [k];
for(int i=0;i<podniz.length;i++){
niz[i] = podniz[i];
}
//This is where I will need my logic to go
}
}
static void BubbleSort (int [] niz){
int pom;
for(int i = 0;i<niz.length-1;i++){
for(int j = 0;j<niz.length-1-i;j++){
if(niz[j]>niz[j+1]){
pom = niz[j];
niz[j] = niz[j+1];
niz[j+1] = pom;
}
}
}
}
}
So the code goes by testing each number individually from 1 to 100000 and makes a subarray of all numbers given that are less than the number itself. Now here is the problem,I dont know how to mix and match the numbers in the subarray so it can get(or not get) the desired number. When every combination is tested and there is no desired number,I will break; the loop and print i. Just to clarify,I can only use addition,and each number can only go in once
You can achieve this as below:
Use two nested loops, like below to calculate the sum of different numbers:
List<Integer> additionList = new ArrayList<Integer>();
int []inputNumbers = .... // Logic to read inputs
for(int _firstIndex = 0; _firstIndex < totalInputs; _firstIndex++){
for(int _secondIndex = _firstIndex + 1; _secondIndex < totalInputs; _secondIndex++){
additionList.add(inputNumbers[_firstIndex]); // only because you have 1 in the sample output
additionList.add(inputNumbers[_firstIndex] + inputNumbers[_secondIndex ]);
}
}
Then sort additionList and look for any missing entry. The first missing entry will be your answer,
Sorting the whole array and then finding sum of all subarrays does solve the problem, but is costly: O(2n^2) ~ O(n^2).
More efficient way to solve this will be Kadane's Algorithm: http://en.wikipedia.org/wiki/Maximum_subarray_problem
What the algo does:
Start from first element and increase the array size (sub array) till you reach the sum you're desiring.
my_num = 1;
while(true){
if(sum_subarray) > my_num){
current position = new subarray;
}
and this subarray concept is calculated through Kadane's approach:
def sum_subarray(A):
sum_ending_here = sum_so_far = 0
for x in A:
sum_ending_here = max(0, max_ending_here + x)
sum_so_far = max(sum_so_far, sum_ending_here)
return sum_so_far
I couldn't solve the problem completely. 'my_num' mentioned here needs to be incremented from 1, and break when my_num > max_sum. I hope someone can add to it and make it compilable.
Note:
This will also take care if negative elements are present in array.

Calculate average in java

EDIT: I've written code for the average but I don't know how to make it so that it also uses ints from my args.length rather than the array.
I need to write a java program that can calculate:
the number of integers read in
the average value – which need not be an integer!
NOTE: I don't want to calculate the average from the array but the integers in the args.
Currently I have written this:
int count = 0;
for (int i = 0; i<args.length -1; ++i)
count++;
System.out.println(count);
}
int nums[] = new int[] { 23, 1, 5, 78, 22, 4};
double result = 0; //average will have decimal point
for(int i=0; i < nums.length; i++){
result += nums[i];
}
System.out.println(result/count)
Can anyone guide me in the right direction? Or give an example that guides me in the right way to shape this code?
Thanks in advance.
Just some minor modification to your code will do (with some var renaming for clarity) :
double sum = 0; //average will have decimal point
for(int i=0; i < args.length; i++){
//parse string to double, note that this might fail if you encounter a non-numeric string
//Note that we could also do Integer.valueOf( args[i] ) but this is more flexible
sum += Double.valueOf( args[i] );
}
double average = sum/args.length;
System.out.println(average );
Note that the loop can also be simplified:
for(String arg : args){
sum += Double.valueOf( arg );
}
Edit: the OP seems to want to use the args array. This seems to be a String array, thus updated the answer accordingly.
Update:
As zoxqoj correctly pointed out, integer/double overflow is not taken care of in the code above. Although I assume the input values will be small enough to not have that problem, here's a snippet to use for really large input values:
BigDecimal sum = BigDecimal.ZERO;
for(String arg : args){
sum = sum.add( new BigDecimal( arg ) );
}
This approach has several advantages (despite being somewhat slower, so don't use it for time critical operations):
Precision is kept, with double you will gradually loose precision with the number of math operations (or not get exact precision at all, depending on the numbers)
The probability of overflow is practically eliminated. Note however, that a BigDecimal might be bigger than what fits into a double or long.
int values[] = { 23, 1, 5, 78, 22, 4};
int sum = 0;
for (int i = 0; i < values.length; i++)
sum += values[i];
double average = ((double) sum) / values.length;
This
for (int i = 0; i<args.length -1; ++i)
count++;
basically computes args.length again, just incorrectly (loop condition should be i<args.length). Why not just use args.length (or nums.length) directly instead?
Otherwise your code seems OK. Although it looks as though you wanted to read the input from the command line, but don't know how to convert that into an array of numbers - is this your real problem?
It seems old thread, but Java has evolved since then & introduced Streams & Lambdas in Java 8. So might help everyone who want to do it using Java 8 features.
In your case, you want to convert args which is String[] into double
or int. You can do this using Arrays.stream(<arr>). Once you have stream of String array elements, you can use mapToDouble(s -> Double.parseDouble(s)) which will convert stream of Strings into stream of doubles.
Then you can use Stream.collect(supplier, accumulator, combiner) to calculate average if you want to control incremental calculation yourselves. Here is some good example.
If you don't want to incrementally do average, you can directly use Java's Collectors.averagingDouble() which directly calculates and returns average. some examples here.
System.out.println(result/count)
you can't do this because result/count is not a String type, and System.out.println() only takes a String parameter. perhaps try:
double avg = (double)result / (double)args.length
for 1. the number of integers read in, you can just use length property of array like :
int count = args.length
which gives you no of elements in an array.
And 2. to calculate average value :
you are doing in correct way.
Instead of:
int count = 0;
for (int i = 0; i<args.length -1; ++i)
count++;
System.out.println(count);
}
you can just
int count = args.length;
The average is the sum of your args divided by the number of your args.
int res = 0;
int count = args.lenght;
for (int a : args)
{
res += a;
}
res /= count;
you can make this code shorter too, i'll let you try and ask if you need help!
This is my first answerso tell me if something wrong!
If you're trying to get the integers from the command line args, you'll need something like this:
public static void main(String[] args) {
int[] nums = new int[args.length];
for(int i = 0; i < args.length; i++) {
try {
nums[i] = Integer.parseInt(args[i]);
}
catch(NumberFormatException nfe) {
System.err.println("Invalid argument");
}
}
// averaging code here
}
As for the actual averaging code, others have suggested how you can tweak that (so I won't repeat what they've said).
Edit: actually it's probably better to just put it inside the above loop and not use the nums array at all
I'm going to show you 2 ways. If you don't need a lot of stats in your project simply implement following.
public double average(ArrayList<Double> x) {
double sum = 0;
for (double aX : x) sum += aX;
return (sum / x.size());
}
If you plan on doing a lot of stats might as well not reinvent the wheel. So why not check out http://commons.apache.org/proper/commons-math/userguide/stat.html
You'll fall into true luv!
public class MainTwo{
public static void main(String[] arguments) {
double[] Average = new double[5];
Average[0] = 4;
Average[1] = 5;
Average[2] = 2;
Average[3] = 4;
Average[4] = 5;
double sum = 0;
if (Average.length > 0) {
for (int x = 0; x < Average.length; x++) {
sum+=Average[x];
System.out.println(Average[x]);
}
System.out.println("Sum is " + sum);
System.out.println("Average is " + sum/Average.length);
}
}
}
// question: let, Take 10 integers from keyboard using loop and print their average value on the screen.
// here they ask user to input 10 integars using loop and average those numbers.so the correct answer in my perspective with java is below:-
import java.util.Scanner;
public class averageValueLoop {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
int sum = 0;
for (int i = 0; i < 10; i++){
System.out.print("Enter a number: ");
sum = sum + sc.nextInt();
}
double average = sum / 10;
System.out.println("Average is " + average);
}
}
}

Categories