Related
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]
I have a java problem at codewars.
In this kata, you will write a function that returns the positions and
the values of the "peaks" (or local maxima) of a numeric array.
For example, the array arr = [0, 1, 2, 5, 1, 0] has a peak at
position 3 with a value of 5 (since arr[3] equals 5).
The output will be returned as a Map<String,List>with two key-value pairs:"pos"and"peaks". If there is no peak in the given array, simply
return `{"pos" => [], "peaks" => []}.
Example: pickPeaks([3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3]) should
return {pos: [3, 7], peaks: [6, 3]} (or equivalent in other
languages)
All input arrays will be valid integer arrays (although it could
still be empty), so you won't need to validate the input.
The first and last elements of the array will not be considered as
peaks (in the context of a mathematical function, we don't know what
is after and before and therefore, we don't know if it is a peak or
not).
Also, beware of plateaus! [1, 2, 2, 2, 1] has a peak while [1, 2, 2, 2, 3] and [1, 2, 2, 2, 2] do not. In case of a plateau-peak,
please only return the position and value of the beginning of the
plateau. For example: pickPeaks([1, 2, 2, 2, 1]) returns {pos: [1], peaks: [2]} (or equivalent in other languages)
Here is my answer:
public static Map<String, List<Integer>> getPeaks(int[] arr) {
HashMap<String, List<Integer>> stringListHashMap = new HashMap<>();
List<Integer> positions = new ArrayList<>();
List<Integer> values = new ArrayList<>();
values.add(arr[1]);
positions.add(1);
for (int i = 2; i < arr.length - 1; i++) {
if (values.get(values.size() - 1) < arr[i]) {
values.clear();
positions.clear();
values.add(arr[i]);
positions.add(i);
}
}
stringListHashMap.put("pos", positions);
stringListHashMap.put("peaks", values);
return stringListHashMap;
}
The above code works fine, but I don't pass the unit tests because of this ->
should support finding peaks expected:<{pos=[3, 7], peaks=[6, 3]}> but was:<{pos=[3], peaks=[6]}>
I have narrowed down the problem to this ->
Example: pickPeaks([3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3]) should return {pos: [3, 7], peaks: [6, 3]} (or equivalent in other languages)
There is clearly only one peak which is 6 and its index 3. Then what is the person asking the question trying to say? I feel like I'm missing something.
The question is asking for local maxima, not global maxima. If a value is larger than its neighbours (and is not the first or last value), it's a peak, even if there is another value elsewhere that is even greater. Hence, with the input [3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3], the eighth value (pos 7) is a peak, since the value 3 is greater than both the preceding neighbour (2) and following neighbour (2).
From what I understand, peak is surrounded by valley. So if you go up than down you have a peak, if you again go up and again down you have another peak. If you go up and than horizontal and than down, first position is peak, you just walk on plateau. It's like when you go mountain. You can climb 2 or 3 peaks in one trip.
Here is the solution:
public static Map<String, List<Integer>> getPeaks(int[] arr) {
Map<String, List<Integer>> result = new HashMap<>();
int peak = 0;
for (int i = 1; i < arr.length - 1; i++) {
if (arr[i-1] < arr[i]){
peak = i;
}
if(arr[i] > arr[i+1] && peak !=0) {
result.computeIfAbsent("pos", k -> new ArrayList<>()).add(peak);
result.computeIfAbsent("peaks", k -> new ArrayList<>()).add(arr[i]);
peak = 0;
}
}
return result;
}
I had to keep the current peak, as you can go horizontal and we need first position when you reach peak.
And I reset it when I go down.
So if arr[i-1] < arr[i] it means I reach a peak and if arr[i] > arr[i+1] && peak !=0 it means I went down.
Another mention, use Map as reference instead of HashMap. Same as you proceed for List.
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
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)
I have to introduce 10 integers in an array. For example int A[] = {1,2,3,4,5,6,7,8,9,10}. Then I have to print the array in normal order which is fine, and after I have to make each element of the array hop over to the next position and the last element to the first position. Assuming we have the same integers in the array as before the result would be this: A[] = {10,1,2,3,4,5,6,7,8,9}
Here's my code so far but I get the out of bounds error. Also I don't know how to flip the last element to the first position
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int A[] = new int[10];
System.out.println("Introduce the array numbers");
for (int i = 0; i < 10; i++) {
A[i] = sc.nextInt();
}
//array in normal order
for (int i = 0; i < 10; i++) {
System.out.print("["+A[i]+"]");
}
//here i have to print the modified array
System.out.println("");
for (int i = 0; i < 10; i++) {
System.out.print("["+A[i+1]+"]");
}
}
As stated, the goal is to start with this array:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
And to modify it such that you wind up with this:
[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
What you are doing here, in essence, is pushing every number one spot to the right. The right-most number, when "pushed one spot to the right", will wrap around to the start of the array.
If we start by just taking the first number and copying it to the right, we run into a problem. The start of the array [1, 2] is now [1, 1]... which means we no longer know what number to push forward into the third slot. In other words, if we just blindly started at the beginning of the array and pushed numbers to the right, we'd wind up with this:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
The best way to solve this issue is to do our work starting at the end of the array, and then to work backwards. So first we push the 9 over to the right, then the 8, and so on.
Once we do that, the only problem is what we do with the first position. If we just moved everything over by one, we'd have this:
[???, 1, 2, 3, 4, 5, 6, 7, 8, 9]
To make matters worse, we might actually crash the program by trying to acces the "negative one-th" element to move it over to the zero index.
The best way around this is to break our problem up into three steps:
Save the last number in the array for later
For each position, starting from the end and working back to the second position, set the number to be equal to the number at the position before it
Set the first number in the array to the saved "last" number
Here's what that looks like in code:
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int last = numbers[numbers.length - 1]; // last now stores 10
// for index 9 to index 1, copy numbers to the right
for (int i = numbers.length - 1; i > 0; --i) {
numbers[i] = numbers[i - 1];
}
numbers[0] = last; // the first number is now 10