Union of two array, but time complexity is the issue - java

Multiple solutions available online for union of arrays, I came up with one of my own which is working fine but again it has significant time complexities (which I obviously don't know). So in order to use similar logic in a better way I am asking here. Any suggestion would be great!
Initially there are two arrayList with different sizes and numbers in it.
First step is to append both of them in a single List
Second step is to sort the new array using Collections.sort()
method.
Third is to use .remove() to remove the duplicates from it.
Below is the code
//initial two arrays
array1[0, 2, 3, 4, 5] and array2[0, 1, 2, 3, 5, 7, 8]
//for loop to append them in one arrayList and sort
for(k = 0; k< array1.size();k++){
array3.add(array1.get(k));
}
for(k = 0; k< array2.size();k++){
array3.add(array2.get(k));
}
Collections.sort(array3);
//Now removing the duplicates
for(k=0; k<array3.size();k++){
if(k != array3.size()-1){
if(Objects.equals(array3.get(k), array3.get(k + 1))){
array3.remove(k);
}
}
}

You can do this optimally via hash sets
int[] array1 = {0, 2, 3, 4, 5};
int[] array2 = {0, 1, 2, 3, 5, 7, 8};
HashSet<Integer> union = new HashSet<>();
for (int element : array1) {
union.add(element);
}
// Add all the elements of the second array to the HashSet
for (int element : array2) {
union.add(element);
}
this solution does not guarantee the order of the elements in the union set.

IntStream.distinct
You can use distinct() operation, which maintains a LinkedHashSet under the hood to guarantee uniqueness of elements and preserve their order, to obtain the union of the given arrays:
int[] array1 = {0, 2, 3, 4, 5};
int[] array2 = {0, 1, 2, 3, 5, 7, 8};
int[] union = IntStream
.concat(Arrays.stream(array1), Arrays.stream(array2))
.distinct().toArray();
System.out.println(Arrays.toString(union));
Output:
[0, 2, 3, 4, 5, 1, 7, 8]

Related

I was attempting this question of rotate array and getting TLE

I was attempting this question of rotate array and getting TLE
Here is my code
class Solution
{
//Function to rotate an array by d elements in a counter-clockwise direction.
static void rotateArr(int arr[], int d, int n)
{
`// add your code here
for(int i=0;i<d;i++){
int left,j;
left=arr[0];
for(j=0;j<n-1;j++){
arr[j]=arr[j+1];
}
arr[n-1]=left;
}
}
}
The time complexity of your algorithm is O(d*n) or O(n^2) if d=n. You should do something more efficient than O(n^2). I think O(n) is the best you can do. I know an O(n) solution for this problem,
First, reverse all the elements in the array. Then reverse the first n-d element and then reverse the last d element. The length of the array is n
For example,
rotate the array A[] = {1, 2, 3, 4, 5, 6, 7} by 5 elements in a counter-clockwise direction.
first reverse all the elements,
A[] = {7, 6, 5, 4, 3, 2, 1}
then reverse first n-d or (7-5) or 2 elements,
A[] = {6, 7, 5, 4, 3, 2, 1}
now reverse the last d or 5 elements,
A[] = {6, 7, 1, 2, 3, 4, 5}

Find minimum peak elements in an array

Question: Given an array numbers = {2, 7, 8, 5, 1, 6, 3, 9, 4}. Check the below conditions, both the conditions should be satisfied.
a[i] > a[i-1] or if first element a[i] > a[i+1]
a[i] > a[i+1] or if last element a[lastelement] > a[lastelement - 1]
Therefore:
1st Iteration - 8, 6, 9 are peak values. Remove the smallest ele. Remove 6. New arr {2, 7, 8, 5, 1, 3, 9, 4}. Output Arr - {6}
2nd Iteration - 8, 9 are peak values. Remove the smallest ele. Remove 8. New arr {2, 7, 5, 1, 3, 9, 4}. Output Arr - {6, 8}
3rd Iteration - 7, 9 are peak values. Remove the smallest ele. Remove 7. New arr {2, 5, 1, 3, 9, 4}. Output Arr - {6, 7, 8}
4th Iteration - 5, 9 are peak values. Remove the smallest ele. Remove 5. New arr {2, 1, 3, 9, 4}. Output Arr - {6, 7, 8, 5}
5th Iteration - 2, 9 are peak values. Remove the smallest ele. Remove 2. New arr {1, 3, 9, 4}. Output Arr - {6, 7, 8, 5, 2}
6th Iteration - 9 are peak values. Remove the smallest ele. Remove 9. New arr {1, 3, 4}. Output Arr - {6, 7, 8, 5, 2, 9}
7th Iteration - 4 are peak values. Remove the smallest ele. Remove 4. New arr {1, 3}. Output Arr - {6, 7, 8, 5, 2, 9, 4}
8th Iteration - 3 are peak values. Remove the smallest ele. Remove 3. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3}
9th Iteration - 1 are peak values. Remove the smallest ele. Remove 1. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3, 1}
Output: {6, 8, 7, 5, 2, 9, 4, 3, 1}
My solution is working but I am looking for optimized solution. Please let me know.
Here is my code:
public int[] findMinimumPeaks(int[] arr){
List<Integer> list1 = new ArrayList<Integer>(arr.length);
int[] output = new int[arr.length];
for(int i: arr)
list1.add(i);
for(int i =0; i<arr.length; i++){
int minIndex = minimumPeakElement(list1);
output[i] = list1.get(minIndex);
list1.remove(minIndex);
}
return output;
}
public int minimumPeakElement(List<Integer> list1){
int minIndex = 0, peakStart = Integer.MAX_VALUE, peakEnd = Integer.MAX_VALUE;
int peak = Integer.MAX_VALUE, minPeak = Integer.MAX_VALUE;
if(list1.size() >= 2){
if(list1.get(0) > list1.get(1)) peakStart = list1.get(0);
if(list1.get(list1.size() - 1) > list1.get(list1.size() - 2)) peakEnd = list1.get(list1.size() - 1);
if(peakStart < peakEnd){
minPeak = peakStart;
minIndex = 0;
}
else if(peakEnd < peakStart){
minPeak = peakEnd;
minIndex = list1.size() - 1;
}
}
for(int i=1; i<list1.size() - 1; i++){
if(list1.get(i) > list1.get(i + 1) && list1.get(i) > list1.get(i-1)) peak = list1.get(i);
if(peak < minPeak){
minPeak = peak;
minIndex = i;
}
}
return minIndex;
}
Here is an idea how to optimize asymptotic complexity.
Use single pass over elements of your initial array to split it into "up-down" "slopes" or "hills", i.e. subsequence of elements in ascending order, followed by subsequence in descending order.
Store these slopes in the following datastructure:
val slopes = MinPriorityQueue<Slope>()
class Slope(
var first: Int, // first element of the slope
var last: Int, // last element of the slope
var peak: Int, // max or peak element
var els: MaxPriorityQueue<Int>(), // all elements of the slope
var prev: Slope?, // link to the previous slope in the list or null if first
var next: Slope? // link to the next slope in the list or null if last
)
Slopes should be comparable by their peak value.
Now, having this data structure, you can poll the slope that has minimal peak value in O(log(N)). After you polled the slope, you should update the slope by removing it's peak element (i.e. poll els, then update first, last, peak), also, slope might become eligible to be merged with the previous or next slope:
Admittedly, this solution is not an easy one, having a lot of things to maintain and large number of corner cases. However, it's much better in terms of asymptotic complexity.
Initial data structure build: O(n log(n))
Polling elements while maintaining slopes: O(n log (n))
Overall complexity: O(n log(n))
Notes:
One of the corner cases, if array can have duplicate elements, then inner priority queue (els) becomes MaxPriorityQueue<Pair<Int,Int>>, i.e. you need to store the number of potentially duplicate elements along with the element value.
MinPriorityQueue and MaxPriorityQueue is an abstract heap-based data structure with min and max element at the head respectively. Can be implemented with PriorityQueue in java

Is it possible to find the original sequence of integers from its prefix sums and suffix sums?

Is there a way to find the initial sequence from its prefix sums and suffix sums?
Prefix sum at ith position is the sum of all elements from beginning to ith position.
Suffix sum at ith position is the sum of all elements from last to ith position in reverse order.
For an example, the combined (prefix sums and suffix sums) sequence is as follows:
{1, 3, 3, 5, 6, 6}
The initial sequence was: {1, 2, 3}
Prefix sums: {1, 3, 6}, Suffix sums: {6, 5, 3}
In combined: {1, 3, 3, 5, 6, 6}
May be in some cases there are multiple possibilities.
Prefix Sum:
original array : {1, 2, 3}
prefix sum array : {1, 1+2, 1+2+3}
Suffix Sum:
original array : {1, 2, 3}
suffix sum array : {3+2+1, 3+2, 3}
As per your question, the combined array seems to be sorted. Therefore
Let combined array be c[] = {1, 1+2, 3, 3+2, 1+2+3, 3+2+1} = {1, 3, 3, 5, 6, 6}
Now, finding the original sequence:
If original array has n elements then combined array will have 2*n elements
Split the array like array1 = {c[0], c[2], c[4]} and array2 = {c[1], c[3], c[5]}
array1 will now have prefix sum and array2 will have suffix sum
Now array1 is sufficient to find the original sequence (as combined array is sorted
as per your question). Therefore original array would be {c[0], c[2]-c[0], c[4]-c[2]}
int length = combined_array.length/2;
int []prefix_breakup = new int[length];
int []original = new int[length];
for(int i=0; i<length ; i++){
if( i%2 == 0 ){
prefix_breakup[i] = combined_array[i];
}
}
original[0] = prefix_breakup[0];
for(int i=1; i<length ; i++){
original[i] = prefix_breakup[i] - prefix_breakup[i-1];
}

Is it possible to remove an index from a object array?

I have seen you can do this using ArrayLists, but is it possible to do this using a normal object array?
deleting an object from an array [java]
At the start of each the player is given 3 random dice from a cup.
The cup has 13 dice in total.
When the player is given the 3 dice from the cup the cup should have only 10 dice in left. I was trying to set the value to null but this still counts as a index in the array so the length does not change.
// Removing the 3 dice which were picked form the cup of the current player, the diceToTakeOut is a String array with a length of 3 the newTurnCup is a Object array with a length of 13
public static Dice [] cup(String [] diceTotakeOut, Dice [] newTurnCup){
for (int i = 0; i < diceTotakeOut.length; i++) {
if (diceTotakeOut.length > 0) {
if (diceTotakeOut[i] == newTurnCup[i].getName()) {
newTurnCup[i] = null;
}
}
}
return newTurnCup;
}
I have tried a few different ways which I could think of:
newTurnCup[i] = null;
newTurnCup[i] = newTurnCup[i - 1];
The result would be after each turn the array holding the dice would have 3 index less.
It's not doable since the array has a fixed size.
But try using an ArrayList which allow you to remove elements dynamically using the method remove(int index)
or:
shift the content of the array starting from the targeted index to the end. (shift: left to right).
An array variable in Java is a pointer to a zone of memory directly proportionate to it's capacity and the size of the type it contains. This area cannot be dynamically modified. The only way to do what you want is to create a new array variable that has allocated the new size of array you want. This is what happens behind the scenes also in the Collections that implement this functionality just that there are optimisations in place in order to do this (potentially very costly) operations only when it is needed.
So my best suggestion would be to change your design to use Lists, ArrayLists for example. LinkedLists, althought they came out as a nice idea, in practice are generally avoided because they are in fact slower (they don't take advantage of hardware memory caching).
You can't do this cleanly with an array; you would have to recreate a shorter array every time.
You can do it with other data structures, for example a LinkedList.
Since you are working with array and not ArrayList, you can achieve this by creating a work around.
public static Dice[] removeTheElement(Dice[] arr, int index) {
// If the array is empty
// or the index is not in array range
// return the original array
if (arr == null
|| index < 0
|| index >= arr.length) {
return arr;
}
// Create another array of size one less
Dice[] anotherArray = new Dice[arr.length - 1];
// Copy the elements except the index
// from original array to the other array
for (int i = 0, k = 0; i < arr.length; i++) {
// if the index is
// the removal element index
if (i == index) {
continue;
}
// if the index is not
// the removal element index
anotherArray[k++] = arr[i];
}
// return the resultant array
return anotherArray;
}
So in here, we pass as a parameter the Object that we are working with, and the index of the array that we like to remove. We create a temporary Object inside to our function and return it without the element with the index number that we provided.
You can't do that. In Java an array is an immutable object. Once created, the size of this array cannot be changed (sure you could modify array items).
To have a collection with the various size you should use List collection: ArrayList - this is based on an internal array with additional property - size, LinkedList.
List<Dice> dices = new ArrayList<>(); // dices.size() -> 0
dices.add(null); // dices.size() -> 1
dices.add(null); // dices.size() -> 2
dices.remove(0); // dices.size() -> 1
To make array immutability clear, this is an example of how manually remove an item from an array:
public static Dice[] removeItem(Dice[] dices, int i) {
if (dices == null || dices.length == 0)
return dices;
if (i < 0 || i >= dices.length)
throw new ArrayIndexOutOfBoundsException();
Dice[] res = new Dice[dices.length - 1];
System.arraycopy(dices, 0, res, 0, i);
System.arraycopy(dices, i + 1, res, i, dices.length - i - 1);
return res;
}
Dice[] arr = null;
arr = removeItem(arr, 5);
As mentioned in other answers, you cannot remove an element from an array directly. You need to write a custom method which will copy all the elements except the one which you need to remove.
However, I suggest you should use ArrayUtils from Apache Commons.
ArrayUtils.remove(array, index)
Some examples from the docs:
ArrayUtils.remove(["a", "b"], 0) = ["b"]
ArrayUtils.remove(["a", "b"], 1) = ["a"]
Refer: ArrayUtils Documentation
Your best bet is to use ArrayList and then after manipulating getting array out of it.
If you want to get your hands dirty and are accepting that you have to create new array, you can do the following:
private static String[] removeIndex(String[] inputArray, int indexToRemove){
if (indexToRemove >= inputArray.length) {
throw new IndexOutOfBoundsException("index " + indexToRemove + " is not allowed for array with size=" + inputArray.length);
}
String[] resultArray = new String[inputArray.length - 1 ];
System.arraycopy(inputArray, 0, resultArray, 0, indexToRemove);
System.arraycopy(inputArray, indexToRemove + 1, resultArray, indexToRemove, resultArray.length - indexToRemove);
return resultArray;
}
And then consuming it:
String[] inputArray = new String[]{"1","2","3","4","5","6","7","8","9","10"};
System.out.println(Arrays.toString(removeIndex(inputArray, 0)));
System.out.println(Arrays.toString(removeIndex(inputArray, 1)));
System.out.println(Arrays.toString(removeIndex(inputArray, 2)));
System.out.println(Arrays.toString(removeIndex(inputArray, 3)));
System.out.println(Arrays.toString(removeIndex(inputArray, 4)));
System.out.println(Arrays.toString(removeIndex(inputArray, 5)));
System.out.println(Arrays.toString(removeIndex(inputArray, 6)));
System.out.println(Arrays.toString(removeIndex(inputArray, 7)));
System.out.println(Arrays.toString(removeIndex(inputArray, 8)));
System.out.println(Arrays.toString(removeIndex(inputArray, 9)));
System.out.println(Arrays.toString(removeIndex(inputArray, 10)));
produces:
[2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Exception in thread "main" java.lang.IndexOutOfBoundsException: index 10 is not allowed for array with size=10
at Scratch.removeIndex(scratch.java:81)
at Scratch.main(scratch.java:73)

how to use each value of an array for each different element

I have an array of 3 elements arraylist = {10000, 7000, 2000}.
I have 3 more elements {1,2,5,7}, {1,3,4,5,7} and {1,3,4,6,7}, where each of them are also arrays and I will get each of them from a loop. Each time the loop executes I will get an array like [1,2,5,7].
Now I want to execute each array {1,2,5,7}, {1,3,4,5,7} or {1,3,4,6,7} for only one value of array.
For example:
I want to execute
[1,2,5,7] for the value 10000,
[1,3,4,5,7] for 7000
and [1,3,4,6,7] for 2000.
I have tried to use for each loop but it does not fullfill my requirement.
Can anyone give me any solution or hint how to solve this problem??
int array[] = {10000, 7000, 2000};
int paths[][] = {
{1, 2, 5, 7},
{1, 3, 4, 5, 7},
{1, 3, 4, 6, 7}
};
for(int i = 0; i < array.length; i++){
int arrayElm = array[i]; // Here you will get array Element e.g. 10000, 2000 etc..
int pathElm[] = paths[i]; // Here you will get a path array e.g. [1, 2, 5, 7] etc..
// Do your operation here...
}
Code should look like this, it will read and print on console.
tempPath should be an array.
for(int i=0;i<array.length;i++)
{
System.out.println(array[i]) // Prints element of array.
tempPath = paths[i];
for(int j=0;j<tempPath.length;j++)
{
System.out.println(tempPath[j]); //prints individual elements from Path Array
}
}
Based on your example, you want some map, where arraylist contain keys, and paths is values.
For example you can use something like that:
List array = Arrays.asList(10000, 7000, 2000);
int paths[][] = {
{1, 2, 5, 7},
{1, 3, 4, 5, 7},
{1, 3, 4, 6, 7}
};
int requiredKey = 7000;
int[] result = paths[array.indexOf(requiredKey)];
but better just keep all this data into some Map

Categories