Getting incorrect sort order - java

Failing test case:
Input:
[-2147483648,1,1]
Output:
-2147483648
Expected:
1
Why is the output expected as 1 when -2147483648 is the 2nd max number here?
public int thirdMax(int[] nums) {
PriorityQueue<Integer> pq = new PriorityQueue(new Comparator<Integer>(){
public int compare(Integer a, Integer b){return b-a;}
});
int res=0;
for(int num : nums){
if(!pq.contains(num) )
pq.add(num);
}
if(pq.size()<=2){
for(int i=0; i<pq.size(); i++){
res=pq.poll();
}
}
else {
for(int i=0; i<3; i++){
res=pq.poll();
}
}
return res;
}

Your method of comparing isn't correct for int.
Rather than:
return b - a;
you should do:
return Integer.compare(b, a);
An int can only hold values of up to Integer.MAX_VALUE. But if you do 1 - -2147483648, the result is greater than Integer.MAX_VALUE, which makes it negative again - and you get wrong sort orders as a result. Basically, return b - a; is only safe if you know that all numbers are positive (or if the numbers won't be further apart than Integer.MAX_VALUE).
In other cases, you can use the API method Integer.compare.
Note that, since you are comparing by the inverse of the natural order of integers, you can also shorten your code with:
PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());

Related

Code Optimize : Shifting a List of Integers in Java

Requirement : There's an input List and an input shift no.
The first line contains two space-separated integers that denote :
n, the number of integers, and
d, the number of left rotations to perform.
The second line contains space-separated integers that describe arr[].
Constraints
1 <= n <= 10^5
1 <= d <= n
1 <= arr[i] <= 10^6
Sample Input
5 , 4
1 2 3 4 5
Sample Output
5 1 2 3 4
I have written this code which is working correctly but getting timeout while large operation. So I need to optimize my code to successfully run all the test cases. How to achieve that.
public static List<Integer> rotateLeft(int d, List<Integer> arr) {
int size = arr.size();
while(d>0) {
int temp = arr.get(0);
for(int i = 0; i<size; i++){
if(i != size-1){
arr.set(i,arr.get(i+1));
} else {
arr.set(i,temp);
}
}
d--;
}
return arr;
}
Failing for this input :
n = 73642
d = 60581
And a huge Integer List of size 73642.
Instead of using nested loops, this can be done in one loop. The final index of an element at index i after n shifts, can be calculated as (i + n) % listLength, this index can be used to populate a shifted list. Like this:
import java.util.*;
class HelloWorld {
public static void main(String[] args) {
List<Integer> arr = Arrays.asList(1,2,3,4,5);
System.out.println(rotateLeft(4, arr));
}
public static List<Integer> rotateLeft(int d, List<Integer> arr) {
List<Integer> rotatedList = new ArrayList<>(arr.size());
int i=0;
for(i=0; i< arr.size(); i++) {
int rotatedElementIndex = ((i+d) % arr.size());
rotatedList.add(arr.get(rotatedElementIndex));
}
return rotatedList;
}
}
Never liked hackerrank puzzles. What does "and a huge Integer array" mean? May we create a new list or we need to modify existing one? If we ought to modify existing one why our method is not void?
If we may create new list the optimal solution would be creating new Integer[] array and call System.arraycopy() twice.
In case of inline modifications the solution is:
public static List<Integer> rotateLeft(int d, List<Integer> arr) {
int i = 0, first = arr.get(0);
int n = arr.size();
while (true) {
int source = (i + d) % n;
if (source == 0) {
arr.set(i, first);
break;
}
arr.set(i, arr.get(source));
i = source;
}
return arr;
}
For an in-place solution:
reverse the subarrays arr[0, d) and arr[d, n) in-place. This is done by swapping the elements in symmetric pairs.
reverse the whole array.
E.g., abcdefghijk, d=4
abcd|efghijk -> dcba|kjihgfe -> efghijk|abcd

BigInteger in ForLoop and Lists in Java

I am trying to create and return a BigInteger list that computes a given integer, n, as a sum of Fibonacci numbers in descending order. For example, if given the integer n = 8000, the result would return [6765, 987, 233, 13, 2].
I have written a code that computes the Fibonacci numbers into a list while the said number is less than n, but I'm not quite how to implement the rest.
The fib function seems too complicated to me. Just compute next element from sum of two last elements:
public static List<BigInteger> fib(BigInteger n) {
List<BigInteger> fibs = new ArrayList<>(asList(ONE, ONE));
for (BigInteger last = ONE; last.compareTo(n) < 0; ) {
last = last.add(fibs.get(fibs.size() - 2));
fibs.add(last);
}
return fibs;
}
Then go backwards in the list and keep elements which fit into sum:
public static void main(String[] args) {
BigInteger n = BigInteger.valueOf(8000);
List<BigInteger> fib = fib(n);
BigInteger remaining = n;
for (int i = fib.size() - 1; i >= 0; i--) {
if (fib.get(i).compareTo(remaining) > 0) {
fib.remove(i);
} else {
remaining = remaining.subtract(fib.get(i));
}
}
Collections.reverse(fib);
System.out.println(fib);
}
If you print fibs you'll realize that you loop adds two 1's, so you should remove the {fibs.add(BigInteger.ONE); fibs.add(BigInteger.ONE);} line.
Now that you have all the Fibonacci number's, you start at the end of the list, and subtract numbers from n as long as the value doesn't go negative.
Easiest way to iterate a list backwards, is to reverse the list and iterate it normally.
Collections.reverse(fibs);
for (BigInteger fib : fibs) {
...
}
You can also do it without reversing the list, by using a ListIterator to iterate backwards.
for (ListIterator<BigInteger> iter = fibs.listIterator(fibs.size()); iter.hasPrevious(); ) {
BigInteger fib = iter.previous();
...
}
To find the numbers you can subtract from n, just keep a running value of what still need to be reduced, i.e. how much of the original b remains.
BigInteger remain = n;
for (BigInteger fib : fibs) {
if (fib.compareTo(remain) <= 0) { // if (fib <= remain)
remain = remain.subtract(fib); // remain -= fib;
}
}
Add the values you subtract to a result list, and you're done.

How to improve efficiency

Write a function:
class Solution{
public int solution(int[] A);
}
that, given an array A of N integers, returns the smallest positive integer(greater than 0)
that does not occur in A.
For example, given A = [1,3,6,4,1,2], the function should return 5.
Given A = [1,2,3], the function should return 4.
Given A = [-1, -3], the function should return 1.
Write an efficient algorithm for the following assumptions.
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [-1,000,000..1,000,000].
I wrote the following algorithm in Java:
public class TestCodility {
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
//int a[] = {1,2,3};
//int b[] = {-1,-3};
int element = 0;
//checks if the array "a" was traversed until the last position
int countArrayLenght = 0;
loopExtern:
for(int i = 0; i < 1_000_000; i++){
element = i + 1;
countArrayLenght = 0;
loopIntern:
for(int j = 0; j < a.length; j++){
if(element == a[j]){
break loopIntern;
}
countArrayLenght++;
}
if(countArrayLenght == a.length && element > 0){
System.out.println("Smallest possible " + element);
break loopExtern;
}
}
}
}
It does the job but I am pretty sure that it is not efficient. So my question is, how to improve this algorithm so that it becomes efficient?
You should get a grasp on Big O, and runtime complexities.
Its a universal construct for better understanding the implementation of efficiency in code.
Check this website out, it shows the graph for runtime complexities in terms of Big O which can aid you in your search for more efficient programming.
http://bigocheatsheet.com/
However, long story short...
The least amount of operations and memory consumed by an arbitrary program is the most efficient way to achieve something you set out to do with your code.
You can make something more efficient by reducing redundancy in your algorithms and getting rid of any operation that does not need to occur to achieve what you are trying to do
Point is to sort your array and then iterate over it. With sorted array you can simply skip all negative numbers and then find minimal posible element that you need.
Here more general solution for your task:
import java.util.Arrays;
public class Main {
public static int solution(int[] A) {
int result = 1;
Arrays.sort(A);
for(int a: A) {
if(a > 0) {
if(result == a) {
result++;
} else if (result < a){
return result;
}
}
}
return result;
}
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
int b[] = {1,2,3};
int c[] = {-1,-3};
System.out.println("a) Smallest possible " + solution(a)); //prints 5
System.out.println("b) Smallest possible " + solution(b)); //prints 4
System.out.println("c) Smallest possible " + solution(c)); //prints 1
}
}
Complexity of that algorithm should be O(n*log(n))
The main idea is the same as Denis.
First sort, then process but using java8 feature.
There are few methods that may increase timings.(not very sure how efficient java 8 process them:filter,distinct and even take-while ... in the worst case you have here something similar with 3 full loops. One additional loop is for transforming array into stream). Overall you should get the same run-time complexity.
One advantage could be on verbosity, but also need some additional knowledge compared with Denis solution.
import java.util.function.Supplier;
import java.util.stream.IntStream;
public class AMin
{
public static void main(String args[])
{
int a[] = {-2,-3,1,2,3,-7,5,6};
int[] i = {1} ;
// get next integer starting from 1
Supplier<Integer> supplier = () -> i[0]++;
//1. transform array into specialized int-stream
//2. keep only positive numbers : filter
//3. keep no duplicates : distinct
//4. sort by natural order (ascending)
//5. get the maximum stream based on criteria(predicate) : longest consecutive numbers starting from 1
//6. get the number of elements from the longest "sub-stream" : count
long count = IntStream.of(a).filter(t->t>0).distinct().sorted().takeWhile(t->t== supplier.get()).count();
count = (count==0) ? 1 : ++count;
//print 4
System.out.println(count);
}
}
There are many solutions with O(n) space complexity and O(n) type complexity. You can convert array to;
set: array to set and for loop (1...N) check contains number or not. If not return number.
hashmap: array to map and for loop (1...N) check contains number or not. If not return number.
count array: convert given array to positive array count array like if arr[i] == 5, countArr[5]++, if arr[i] == 1, countArr[1]++ then check each item in countArr with for loop (1...N) whether greate than 1 or not. If not return it.
For now, looking more effective algoritm like #Ricola mentioned. Java solution with O(n) time complexity and O(1) space complexity:
static void swap(final int arr[], final int i,final int j){
final int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static boolean isIndexInSafeArea(final int arr[], final int i){
return arr[i] > 0 && arr[i] - 1 < arr.length && arr[i] != i + 1 ;
}
static int solution(final int arr[]){
for (int i = 0; i < arr.length; i++) {
while (isIndexInSafeArea(arr,i) && arr[i] != arr[arr[i] - 1]) {
swap(arr, i, arr[i] - 1);
}
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] != i + 1) {
return i+1;
}
}
return arr.length + 1;
}

java how do i read a negative int as a positive one

The question at hand is:
The method should compute for each row the sum of the absolute values
of the elements of that row. The method should return the maximum of
these sums. For example, if applied to the test array, the method
should return the value max (3+1+4+0,5+9+2+6, 5+3+7+8) = max (8,22,23)
= 23.
The test array:
3 -1 4 0
5 9 -2 6
5 3 7 -8
so far i have made a method that gets the value of all the rows and returns to me the sum in a list; however, i want it to turn negative integers into positive ones.
here's my code so far:
public static int[] rowSums(int[][]array) {
int[] a = new int[array.length];
for (int i = 0;i<array.length;i++){
int sum = IntStream.of(array[i]).sum();
a[i]=sum;
} return a;}
Output:
[6,18,7]
You can use Math#abs(standing for absolute value) which converts any negative number into a positive number:
int sum = IntStream.of(array[i]).map(Math::abs).sum();
If you'd like to lose those for-loops, you can even just stick with streams:
public static int[] rowSums(int[][] array) {
return Arrays.stream(array)
.mapToInt(i -> Arrays.stream(i).map(Math::abs).sum())
.toArray();
}
Here you can use the Map. So The code will be like this.
public static int[] rowSums(int[][]array) {
int[] a = new int[array.length];
for (int i = 0;i<array.length;i++){
int sum = IntStream.of(array[i]).map(n->{
if(n<0) {
return n*-1;
}
else {
return n;
}
}).sum();
a[i]=sum;
} return a;}
Here I just make all the negative Integers into Positive.
Update this line
int sum = IntStream.of(array[i]).sum();
to
int sum = IntStream.of(array[i]).map(Math::abs).sum();
And solution for whole matrix (this snippet will return 23):
Optional<Integer> maxVal = Arrays.stream(matrix)
.map(array -> Arrays.stream(array).map(Math::abs).sum())
.reduce(Integer::max);
And without Optional
int maxVal = Arrays.stream(matrix)
.map(array -> Arrays.stream(array).map(Math::abs).sum())
.reduce(Integer::max).get();
Use Math.abs() It'll take any number and return it as a positive number. You need it on this line:
int sum = IntStream.of(array[i]).sum();
to take array[i] and make it absolute. So
IntStream.of(Math.abs(array[i]).sum();
Just use:
Math.abs(var)
This will turn var to a positive if it is negative.
Therefore the full answer is as follows:
public static int[] rowSums(int[][]array) {
int[] a = new int[array.length];
for (int i = 0;i<array.length;i++){
int sum = IntStream.of(array[i]).map(Math::abs).sum();
a[i]=sum;
} return a;}
Change all numbers to positive numbers. This can be done using Math.abs(int).Check the link.

Finding closest number in an array

In an array first we have to find whether a desired number exists in that or not?
If not then how will I find nearer number to the given desired number in Java?
An idea:
int nearest = -1;
int bestDistanceFoundYet = Integer.MAX_INTEGER;
// We iterate on the array...
for (int i = 0; i < array.length; i++) {
// if we found the desired number, we return it.
if (array[i] == desiredNumber) {
return array[i];
} else {
// else, we consider the difference between the desired number and the current number in the array.
int d = Math.abs(desiredNumber - array[i]);
if (d < bestDistanceFoundYet) {
// For the moment, this value is the nearest to the desired number...
bestDistanceFoundYet = d; // Assign new best distance...
nearest = array[i];
}
}
}
return nearest;
Another common definition of "closer" is based on the square of the difference. The outline is similar to that provided by romaintaz, except that you'd compute
long d = ((long)desiredNumber - array[i]);
and then compare (d * d) to the nearest distance.
Note that I've typed d as long rather than int to avoid overflow, which can happen even with the absolute-value-based calculation. (For example, think about what happens when desiredValue is at least half of the maximum 32-bit signed value, and the array contains a value with corresponding magnitude but negative sign.)
Finally, I'd write the method to return the index of the value located, rather than the value itself. In either of these two cases:
when the array has a length of zero, and
if you add a "tolerance" parameter that bounds the maximum difference you will consider as a match,
you can use -1 as an out-of-band value similar to the spec on indexOf.
//This will work
public int nearest(int of, List<Integer> in)
{
int min = Integer.MAX_VALUE;
int closest = of;
for (int v : in)
{
final int diff = Math.abs(v - of);
if (diff < min)
{
min = diff;
closest = v;
}
}
return closest;
}
If the array is sorted, then do a modified binary search. Basically if you do not find the number, then at the end of search return the lower bound.
Pseudocode to return list of closest integers.
myList = new ArrayList();
if(array.length==0) return myList;
myList.add(array[0]);
int closestDifference = abs(array[0]-numberToFind);
for (int i = 1; i < array.length; i++) {
int currentDifference= abs(array[i]-numberToFind);
if (currentDifference < closestDifference) {
myList.clear();
myList.add(array[i]);
closestDifference = currentDifference;
} else {
if(currentDifference==closestDifference) {
if( myList.get(0) !=array[i]) && (myList.size() < 2) {
myList.add(array[i]);
}
}
}
}
return myList;
Array.indexOf() to find out wheter element exists or not. If it does not, iterate over an array and maintain a variable which holds absolute value of difference between the desired and i-th element. Return element with least absolute difference.
Overall complexity is O(2n), which can be further reduced to a single iteration over an array (that'd be O(n)). Won't make much difference though.
Only thing missing is the semantics of closer.
What do you do if you're looking for six and your array has both four and eight?
Which one is closest?
int d = Math.abs(desiredNumber - array[i]);
if (d < bestDistanceFoundYet) {
// For the moment, this value is the nearest to the desired number...
nearest = array[i];
}
In this way you find the last number closer to desired number because bestDistanceFoundYet is constant and d memorize the last value passign the if (d<...).
If you want found the closer number WITH ANY DISTANCE by the desired number (d is'nt matter), you can memorize the last possibile value.
At the if you can test
if(d<last_d_memorized){ //the actual distance is shorter than the previous
// For the moment, this value is the nearest to the desired number...
nearest = array[i];
d_last_memorized=d;//is the actual shortest found delta
}
A few things to point out:
1 - You can convert the array to a list using
Arrays.asList(yourIntegerArray);
2 - Using a list, you can just use indexOf().
3 - Consider a scenario where you have a list of some length, you want the number closest to 3, you've already found that 2 is in the array, and you know that 3 is not. Without checking the other numbers, you can safely conclude that 2 is the best, because it's impossible to be closer. I'm not sure how indexOf() works, however, so this may not actually speed you up.
4 - Expanding on 3, let's say that indexOf() takes no more time than getting the value at an index. Then if you want the number closest to 3 in an array and you already have found 1, and have many more numbers to check, then it'll be faster to just check whether 2 or 4 is in the array.
5 - Expanding on 3 and 4, I think it might be possible to apply this to floats and doubles, although it would require that you use a step size smaller than 1... calculating how small seems beyond the scope of the question, though.
// paulmurray's answer to your question is really the best :
// The least square solution is way more elegant,
// here is a test code where numbertoLookFor
// is zero, if you want to try ...
import java.util.* ;
public class main {
public static void main(String[] args)
{
int[] somenumbers = {-2,3,6,1,5,5,-1} ;
ArrayList<Integer> l = new ArrayList<Integer>(10) ;
for(int i=0 ; i<somenumbers.length ; i++)
{
l.add(somenumbers[i]) ;
}
Collections.sort(l,
new java.util.Comparator<Integer>()
{
public int compare(Integer n1, Integer n2)
{
return n1*n1 - n2*n2 ;
}
}
) ;
Integer first = l.get(0) ;
System.out.println("nearest number is " + first) ;
}
}
int[] somenumbers = getAnArrayOfSomenumbers();
int numbertoLookFor = getTheNumberToLookFor();
boolean arrayContainsNumber =
new HashSet(Arrays.asList(somenumbers))
.contains(numbertoLookfor);
It's fast, too.
Oh - you wanted to find the nearest number? In that case:
int[] somenumbers = getAnArrayOfSomenumbers();
int numbertoLookFor = getTheNumberToLookFor();
ArrayList<Integer> l = new ArrayList<Integer>(
Arrays.asList(somenumbers)
);
Collections.sort(l);
while(l.size()>1) {
if(numbertoolookfor <= l.get((l.size()/2)-1)) {
l = l.subList(0, l.size()/2);
}
else {
l = l.subList(l.size()/2, l.size);
}
}
System.out.println("nearest number is" + l.get(0));
Oh - hang on: you were after a least squares solution?
Collections.sort(l, new Comparator<Integer>(){
public int compare(Integer o1, Integer o2) {
return (o1-numbertoLookFor)*(o1-numbertoLookFor) -
(o2-numbertoLookFor)*(o2-numbertoLookFor);
}});
System.out.println("nearest number is" + l.get(0));

Categories