I'm struggling with quite interesting assignment and looking for advice.
The case is to find the longest sublist from the given list of pairs. First elements from these pairs should be in ascending order and second ones - in descending.
For example for {{1,3},{3,1},{2,0},{4,4},{5,3},{6,2}} answer is {{4,4},{5,3},{6,2}}
So, how I see this:
Go via array and check condition for two pairs, if condition is true, save value somewhere and increase sublist elements count. Otherwise check if current sublist recording is empty and add the last element to current sublist, then check if this sublist is the longest among others.
And I encountered two major problems - duplicates and absence of the last element.
For this moment I came to this:
public static void findLagrestList() {
int arr[][] = {{1,3},{3,1},{2,0},{4,4},{5,3},{6,2}};
ArrayList<int[]> currentSublist = new ArrayList<>();
ArrayList<int[]> resultSublist = new ArrayList<>();
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr[i].length-1; j++) {
if (arr[i][j] < arr[i + 1][j] && arr[i][j + 1] > arr[i + 1][j + 1]) {
if(!currentSublist.contains(arr[i])){
currentSublist.add(arr[i]);
}
} else {
currentSublist.add(arr[i]);//the last one
if(currentSublist.size()>resultSublist.size()){
resultSublist.clear();
resultSublist.addAll(currentSublist);
currentSublist.clear();
}
break;
}
}
}
System.out.println(resultSublist.size());
printList(resultSublist);
}
private static void printList(ArrayList<int[]> list) {
for (int[] is : list) {
System.out.println();
for (int i : is) {
System.out.print(i + " ");
}
}
}
output:
2
1 3
3 1
Thanks in advance for any clue or hint.
I Wrote for you this algorithm it Does exactly what you want.
1) i create a results ArrayList;
2) initialize variable sum to 0;
3) loop through all values of array[][]; for each array value get the sum of its components
4) if the sum of the components of thhe array value is less or equal to sum then insert the array value in the results array
5) but if the sum of the components of the array value is greater than sum, then check the results array. if its empty then insert the array value. if its not empty check the sum of the components of each value of the results Arraylist with the sum of the components of the value of the soucrce array.Any value with sum less than that of source array component is removed then insert this particular value to the results arraylist.
import java.util.ArrayList;
class lists{
public static void findLagrestList() {
int arr[][] = {{1,3},{3,1},{2,0},{4,4},{5,3},{6,2}};
//ArrayList<int[]> currentSublist = new ArrayList<>();
ArrayList<int[]> resultSublist = new ArrayList<>();
int result_arr[][]={};
int sum =0;
for(int i=0;i<arr.length;i++)
{
int [] inner_arr =arr[i];
int valuesum =arr[i][0]+arr[i][1];
if(valuesum>sum)
{
if(resultSublist.size()>0)
{
for(int k=0;k<resultSublist.size();k++)
{
int [] cvalue = resultSublist.get(k);
int summ=cvalue[0]+cvalue[1];
if(valuesum>summ)
{
resultSublist.remove(k) ;
}
}
resultSublist.add(inner_arr);
}else{
resultSublist.add(inner_arr);
sum = valuesum;
}
}
}
System.out.println(resultSublist.size());
printList(resultSublist);
}
private static void printList(ArrayList<int[]> list) {
for (int[] is : list) {
System.out.println();
for (int i : is) {
System.out.print(i + " ");
}
}
}
public static void main(String [] oo)
{
lists.findLagrestList();
}
}
the output is
3
4 4
5 3
6 2
Okay, a hint first.
For every pair (x, y) for a given x, you're only interested in the one with the greatest y.
For every pair (x, y) for a given y, you're only interested in the one with the smallest x.
Try building maps of respective least/greater values for the x's and y's and see where you get from there (you will need two copies of the pair list, one sorted lexicographically x -> y and one sorted lexicographically y -> x).
Related
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
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;
}
I have a list of numbers: [10, 13, 15]. I am trying to find the combinations of numbers in the list that add up to or are less than the target of 28.
Currently I have a recursive method:
public void combinations(ArrayList<Integer>data,int fromIndex, int endIndex)
{
int sum = 0;
int target = 28;
ArrayList<Integer>results = new ArrayList<Integer>();
if(fromIndex == endIndex)
{
return;
}
for(int currentIndex = fromIndex; currentIndex < endIndex; currentIndex++)
{
if(sum + data.get(currentIndex) <= target)
{
results.add(data.get(currentIndex));
sum +=data.get(currentIndex);
}
}
System.out.println(results);
combinations(data, fromIndex + 1, endIndex);
}
Currently this outputs:
[10, 13],[13, 15],[15] which are correct and I understand why I am getting these solutions as my recursive method has a +1. However other solutions such as [10],[13],[10,10] ect are not included and I was wondering how I would go about implementing this, would I need to change my increments in my recursive method?
public static void combinations(ArrayList<Integer> arr, ArrayList<ArrayList<Integer>> ans, int startIndex, int endIndex, int sum) {
if(startIndex > endIndex) {
for(ArrayList<Integer> x : ans) {
System.out.println(x);
}
return;
}
ArrayList<Integer> newTemp;
ArrayList<ArrayList<Integer>> newAns = new ArrayList<ArrayList<Integer>>();
for(ArrayList<Integer> x : ans) {
newAns.add(x);
}
for(ArrayList<Integer> x : ans) {
int s = 0;
newTemp = new ArrayList<Integer>();
for(Integer v : x) {
newTemp.add(v);
s+=v;
}
if(s + arr.get(startIndex) <= sum) {
newTemp.add(arr.get(startIndex));
newAns.add(newTemp);
}
}
if(arr.get(startIndex) <= sum ) {
newTemp = new ArrayList<Integer>();
newTemp.add(arr.get(startIndex));
newAns.add(newTemp);
}
combinations(arr,newAns, startIndex+1, endIndex, sum);
}
I have to rewrite your code as I was unable to think through your code.
Secondly, I have to make a newArrayList all time to avoid ConcurrentModificationException which I have faced the first time and will overcome later after gaining some knowledge about it.
Now, this method should be called as
public static void main (String[] args) {
ArrayList<Integer> arr = new ArrayList<Integer>();
arr.add(10);
arr.add(15);
arr.add(13);
arr.add(-5);
arr.add(28);
combinations(arr, new ArrayList<ArrayList<Integer>>(), 0, 4, 28);
}
Explanation: I have generalized your question's answer to fit any sum in int range.
I have made ArrayList of ArrayList which will print all the combinations at the base case.
I have first added an ArrayList containing single element i.e current element if the current element is the <= sum.
Then with all remaining ArrayList, I have calculated the sum of each and then check whether adding the current element into the previous ArrayList holds the above condition.
At the same time I have made new ArrayList and copied all elements while I was calculating the sum of each ArrayList and then if the second case holds good then I added the current element into temp ArrayList and then added the temp ArrayList to the answer ArrayList of ArrayLists.
Then I called the recursion by incrementing the startIndex by 1.
I'm trying to write an algorithm that will let me iterate over all desired points within an n-dimensional space to find the minimum of a function f(x) where x is a vector of size n.
Obviously, searching a 2-d or 3-d space is fairly straightforward, you can simply do:
for(int i = 0; i < x; i++) {
for(int j = 0; j < y; j++) {
//and so on for however many dimensions you want
Unfortunately, for my problem, the dimensionality of the space is not fixed (I'm writing a generalised minimum finder for many functions in a statistical program) and so I'd have to write loops for each value of n I want to use - which might ultimately be rather large.
I've been trying to get my head around how I could do this using recursion but can't quite see the solution - although I'm sure there is one there.
The solution doesn't have to be recursive, but it must be general and efficient (the inner most line in that nested loop is going to get called an awful lot...).
The way I'm representing the volume to search is a 2d array of double:
double[][] space = new double[2][4];
This would represent a 4d space with the minimum and maximum bound in each dimension in position 0 or 1 of the array, respectively. Eg:
dim 0 1 2 3
min(0):-10 5 10 -0.5
max(1): 10 55 99 0.2
Any ideas?
Here is the general idea:
interface Callback {
void visit(int[] p); // n-dimensional point
}
// bounds[] - each number the limits iteration on i'th axis from 0 to bounds[i]
// current - current dimension
// callback - point
void visit(int[] bounds, int currentDimension, int[] p, Callback c) {
for (int i = 0; i < bounds[currentDimension]; i++) {
p[currentDimension] = i;
if (currentDimension == p.length - 1) c.visit(p);
else visit(bounds, currentDimension + 1, p, c);
}
}
/// now visiting
visit(new int[] {10, 10, 10}, 0, new int[3], new Callback() {
public void visit(int[] p) {
System.out.println(Arrays.toString(p));
}
});
I'd stick with reucrsion, and use Object as a parameter, with an extra parameter of dim, and cast it when you reach a depth of 1 to the relevant array [in my example, it is an int[]]
public static int getMin(Object arr, int dim) {
int min = Integer.MAX_VALUE;
//stop clause, it is 1-dimensional array - finding a min is trivial
if (dim == 1) {
for (int x : ((int[])arr)) {
min = Math.min(min,x);
}
//else: find min among all elements in an array of one less dimenstion.
} else {
for (Object o : ((Object[])arr)) {
min = Math.min(min,getMin(o,dim-1));
}
}
return min;
}
example:
public static void main(String[] args) {
int[][][] arr = { { {5,4},{2}, {35} } , { {2, 1} , {0} } , {{1}}};
System.out.println(getMin(arr, 3));
}
will produce:
0
The advantage of this approach is no need for any processing of the array - you just send it as it is, and send the dimension as a parameter.
The downside - is type [un]safety, since we dynamically cast the Object to an array.
Another option is to iterate from 0 to x*y*z*... like you do when converting a number between binary and decimal representations. This is a non-recursive solution, so you won't run into performance issues.
ndims = n;
spacesize = product(vector_sizes)
int coords[n];
for (i = 0; i < spacesize; i++) {
k = i;
for (j = 0; j < ndims; j++ ) {
coords[j] = k % vector_sizes[j];
k /= vector_sizes[j];
}
// do something with this element / these coords
}
n-dimensional arrays can be flattened into one-dimensional arrays. What you need is to do the math for these things:
Calculate the size of the unidimensional array needed.
Figure out the formulas needed to translate back from the n-dimensional index to the unidimensional one.
This is what I'd do:
Represent n-dimensional array sizes and indexes as int[]. So, the size of a 5x7x13x4 4-dimensional array represented as the 4-element array `{ 5, 7, 13, 4 }'.
An n-dimensional array is represented as a unidimensional array whose size is the product of the sizes of each of the dimensions. So a 5x7x13x4 array would be represented as a flat array of size 1,820.
An n-dimensional index is translated into a unique index in the flat array by multiplication and addition. So, the index <3, 2, 6, 0> into the 5x7x13x4 array is translated as 3 + 2*5 + 6*5*7 + 0*5*7*13 == 223. To access that 4-dimensional index, access index 223 in the flat array.
You can also translate backwards from flat array indexes to n-dimensional indexes. I'll leave that one as an exercise (but it's basically doing n modulo calculations).
Isn't the function just:
Function loopDimension(int dimensionNumber)
If there is no more dimension, stop;
for(loop through this dimension){
loopDimension(dimensionNumber + 1);
}
This runs through a List of List of values (Integers) and picks the minimum of each List:
import java.util.*;
/**
MultiDimMin
#author Stefan Wagner
#date Fr 6. Apr 00:37:22 CEST 2012
*/
public class MultiDimMin
{
public static void main (String args[])
{
List <List <Integer>> values = new ArrayList <List <Integer>> ();
Random r = new Random ();
for (int i = 0; i < 5; ++i)
{
List<Integer> vals = new ArrayList <Integer> ();
for (int j = 0; j < 25; ++j)
{
vals.add (100 - r.nextInt (200));
}
values.add (vals);
}
showAll (values);
List<Integer> res = multiDimMin (values);
show (res);
}
public static int minof (List <Integer> in)
{
int res = in.get (0);
for (int v : in)
if (res > v) res = v;
return res;
}
public static List<Integer> multiDimMin (List <List <Integer>> in)
{
List<Integer> mins = new ArrayList <Integer> ();
for (List<Integer> li : in)
mins.add (minof (li));
return mins;
}
public static void showAll (List< List <Integer>> lili)
{
for (List <Integer> li : lili) {
show (li);
System.out.println ();
}
}
public static void show (List <Integer> li)
{
for (Integer i: li) {
System.out.print (" " + i);
}
System.out.println ();
}
}
I've just been looking at the following piece of code
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(final String[] args) {
final int sizeA = 3;
final int sizeB = 5;
final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);
int counter = 1;
for(final int[] combo : combos) {
System.out.println("Combination " + counter);
System.out.println("--------------");
for(final int value : combo) {
System.out.print(value + " ");
}
System.out.println();
System.out.println();
++counter;
}
}
private static List<int[]> getAllCombinations(final int maxIndex, final int size) {
if(maxIndex >= size)
throw new IllegalArgumentException("The maximum index must be smaller than the array size.");
final List<int[]> result = new ArrayList<int[]>();
if(maxIndex == 0) {
final int[] array = new int[size];
Arrays.fill(array, maxIndex);
result.add(array);
return result;
}
//We'll create one array for every time the maxIndex can occur while allowing
//every other index to appear, then create every variation on that array
//by having every possible head generated recursively
for(int i = 1; i < size - maxIndex + 1; ++i) {
//Generating every possible head for the array
final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);
//Combining every head with the tail
for(final int[] head : heads) {
final int[] array = new int[size];
System.arraycopy(head, 0, array, 0, head.length);
//Filling the tail of the array with i maxIndex values
for(int j = 1; j <= i; ++j)
array[size - j] = maxIndex;
result.add(array);
}
}
return result;
}
}
I'm wondering, how do I eliminate recursion from this, so that it returns a single random combination, rather than a list of all possible combinations?
Thanks
If I understand your code correctly your task is as follows: give a random combination of numbers '0' .. 'sizeA-1' of length sizeB where
the combination is sorted
each number occurs at least once
i.e. in your example e.g. [0,0,1,2,2].
If you want to have a single combination only I'd suggest another algorithm (pseudo-code):
Randomly choose the step-up positions (e.g. for sequence [0,0,1,1,2] it would be steps (1->2) & (3->4)) - we need sizeA-1 steps randomly chosen at sizeB-1 positions.
Calculate your target combination out of this vector
A quick-and-dirty implementation in java looks like follows
// Generate list 0,1,2,...,sizeB-2 of possible step-positions
List<Integer> steps = new ArrayList<Integer>();
for (int h = 0; h < sizeB-1; h++) {
steps.add(h);
}
// Randomly choose sizeA-1 elements
Collections.shuffle(steps);
steps = steps.subList(0, sizeA - 1);
Collections.sort(steps);
// Build result array
int[] result = new int[sizeB];
for (int h = 0, o = 0; h < sizeB; h++) {
result[h] = o;
if (o < steps.size() && steps.get(o) == h) {
o++;
}
}
Note: this can be optimized further - the first step generates a random permutation and later strips this down to desired size. Therefore it is just for demonstration purpose that the algorithm itself works as desired.
This appears to be homework. Without giving you code, here's an idea. Call getAllCombinations, store the result in a List, and return a value from a random index in that list. As Howard pointed out in his comment to your question, eliminating recursion, and returning a random combination are separate tasks.