One of the methods that I need to write for an assignment is supposed to remove the first n elements from an array. However, I am not getting the correct output. I believe I'm having an off by one error, but I am not exactly sure how to fix it.
Solutions should try to maintain the format of the code as closely as possible.
for (int i = n; i >= 0; i--) {
elementData[i] = elementData[i + 1];
size--;
}
What the code is saying is that, for every element n and below, replace it with whatever is in the index higher than it. Then reduce the size variable for every time that you do this, which should result in it looking like a remove operation when printed.
I expected the output of [0, 1, 2, 4, 6, 4, 7] to be [4, 7].
However, I got [7].
n is passed as 5 in the above case.
I realize this is an assignment question looking for an implementation, but anyone doing this in Java should use the provided APIs. For example:
public int[] trimArray(int[] source, int trimBy) {
if (trimBy > source.length) return source;
return Arrays.copyOfRange(source, trimBy, source.length);
}
trimArray(new int[]{0, 1, 2, 4, 6, 4, 7}, 5) // -> [4, 7]
You can just use this:
int[] result = new int[elementData.length - n];
for (int i = 0; i < result.length; i++) {
result[i] = elementData[n + i];
}
Which is an extended form of this:
int[] result = new int[elementData.length - n];
System.arraycopy(elementData, n, result, 0, result.length);
You can use filter:
let a = [0, 1, 2, 4, 6, 4, 7]
you want to obtain [4, 7] removing 5 first elements so type
a = a.filter((_, i) => i >= 5)
Now
a = [4, 7]
elementData = Arrays.copyOfRange( elementData, n, elementData.length ); // originalArray, startIndex, end
Related
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.
I have a single array populated with some values that I receive from another method, and I want to populate a bidimensional array with values from the first, example:
int[] singleArray; // there's no values here to demonstrate,
// let's think that's populated
int[][] bidimArray = new int[80][80];
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
for (int x = 0; x < singleArray.length; x++) {
bidimArray[i][j] = singleArray[x];
}
}
}
I thought in the solution above, besides it seems very ugly solution, it only saves the last position of singleArray in bidimArray[][]. May anyone help me, please?
There is no need for the third for loop here. This is where you went wrong. The change to your code is to simply increment x for every value entered into the new 2D array and omitting the third for loop.
int[] singleArray;
int[][] bidimArray = new int[80][80];
int x = 0;
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
bidimArray[i][j] = singleArray[x];
x++;
}
}
You can also combine the two inner lines in the loop like this:
bidimArray[i][j] = singleArray[x++];
As pointed out in the comments, you should not hard code array sizes. For your approach, you will have to make sure that the singleArray contains at least 80*80 elements. If this is not given, you should make sure to check that constraint beforehand.
Circular populating of a 2d array 8x7 with values from a 1d array 6. It works the same with larger and smaller arrays regardless of size:
int[] arr1 = {1, 2, 3, 4, 5, 6};
int m = 8;
int n = 7;
int[][] arr2 = IntStream.range(0, m)
.mapToObj(i -> IntStream.range(0, n)
.map(j -> arr1[(j + i * n) % arr1.length])
.toArray())
.toArray(int[][]::new);
// output
Arrays.stream(arr2).map(Arrays::toString).forEach(System.out::println);
[1, 2, 3, 4, 5, 6, 1]
[2, 3, 4, 5, 6, 1, 2]
[3, 4, 5, 6, 1, 2, 3]
[4, 5, 6, 1, 2, 3, 4]
[5, 6, 1, 2, 3, 4, 5]
[6, 1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 1]
[2, 3, 4, 5, 6, 1, 2]
See also: Copying a 1d array to a 2d array
I want to make a function that takes as parameters an array and a boolean. The boolean tells the function if the rest of the division of the array is to be included. It then returns a new array which is the copy of the second half of the first:
secondHalf({1, 2, 3, 4, 5}, true) → {3, 4, 5}
secondHalf({1, 2, 3, 4, 5}, false) → {4, 5}
For this assignment, I'm not supposed to use any other classes.
Here's what I've attempted:
static int[] secondHalf(int[] vector, boolean include) {
int size = vector.length/2;
if(vector.length%2 == 0)
include = false;
if(include)
size ++;
int[] vector_2 = new int[size];
int i = 0;
while(i < size){
if(include)
vector_2[i] = vector[i+size-1];
vector_2[i] = vector[i+size+1];
i++;
}
return vector_2;
To find the size of vector_2, I've decided to use compound assignment operators. So the first part of this solution checks for the required condition and assigns a value to size in a single statement.
Since we know how many times to iterate over the loop, I think a for loop would be more appropriate than a while loop.
The loop retrieves all the values in vector from the middle of the array to the end of the array and places each value into vector_2.
static int[] secondHalf(int[] vector, boolean include) {
int size = vector.length/2 + (include && vector.length%2 != 0 ? 1 : 0);
int[] vector_2 = new int[size];
for(int i = 0; i < size; i++)
vector_2[i] = vector[vector.length - size + i];
return vector_2;
}
People have hinted at System#arraycopy, but with Arrays.copyOfRange there is an even simpler method, where you only have to define the proper start index and directly receive the copy.
The start index is array.length / 2 by default. Iff the include flag is true, then you have to add the remainder of dividing the array length by 2 to that.
An MCVE:
import java.util.Arrays;
public class ArrayPartCopy
{
public static void main(String[] args)
{
int array0[] = { 1, 2, 3, 4, 5 };
System.out.println("For " + Arrays.toString(array0));
System.out.println(Arrays.toString(secondHalf(array0, true)));
System.out.println(Arrays.toString(secondHalf(array0, false)));
int array1[] = { 1, 2, 3, 4 };
System.out.println("For " + Arrays.toString(array1));
System.out.println(Arrays.toString(secondHalf(array1, true)));
System.out.println(Arrays.toString(secondHalf(array1, false)));
}
static int[] secondHalf(int[] array, boolean include)
{
int start = array.length / 2;
if (include)
{
start += array.length % 2;
}
return Arrays.copyOfRange(array, start, array.length);
}
}
The output is
For [1, 2, 3, 4, 5]
[4, 5]
[3, 4, 5]
For [1, 2, 3, 4]
[3, 4]
[3, 4]
I have the following array list which contains the following
point ids (1,2,3,4,1,8,5,6,8,9,7,9). I am using Java 7
I was wondering how it could be split into sublists i.e the sublists below
(1,2,3,4,1)
(8,5,6,8)
(9,7,9)
I have had problems trying to use a loop within a loop (i.e check each point
from the outer loop with each of the other points in the inner loop) to get
index positions (starPosIndex and endPosIndex) where there are duplicate point ids and ArrayList.sublist(startPosIndex,endPosIndex) to get the correct sublist
int startPos = 0;
int endPos = 0;
for (int j = 0; j < polygonList3.size(); j++){
Point pointToCheck = polygonList3.get(j);
for (int k = 1; k < polygonList3.size(); k++){
Point pointToCheck2 = polygonList3.get(k);
if (pointToCheck.getID() == pointToCheck2.getID()){
startPos = startPos + endPos;
endPos = endPos + k;
//startPos = startPos + endPos;
//for (int startPos = j; startPos < polygonList3.size(); startPos = (startPos) + endPos) {
//endPos = Math.min(startPos + endPos, polygonList3.size());
finalPolygonLists.add(new ArrayList<Point>(polygonList3.subList(startPos, endPos)));//originalPtsSublist2);
//}
}
}
I would solve it in the following manner:
Allocate a HashSet to contain unique values encountered
Allocate a new list for the first sublist
Iterate over the whole list, adding each value to the set. When we encounter a value that is already in the set, we are done with the first sublist, so clear the set, and allocate a new sublist
After iteration, you will have your list of sublists, obtained in O(n) runtime
You can walk along the list, and create slices of the list (using List#subList) as you go. This can be done efficiently, by always checking whether the first element of the current segment of the list appears somewhere else in the list. If it does, you can store this "slice", and continue with the "tail" of the list. If it doesn't, you are finished (and the tail of the list may or may not be part of the result - that's up to you)
Implemented here as an example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListSlicing
{
public static void main(String[] args)
{
runTest(1,2,3,4,1,8,5,6,8,9,7,9);
runTest(1,2,3,4);
runTest(1,1,1,1);
runTest(1,2,1,2,1,2,1,2,1,2,1,2);
runTest();
}
private static void runTest(Integer ... numbers)
{
List<Integer> list = Arrays.asList(numbers);
System.out.println("Input: "+list);
System.out.println("Output: "+slices(list));
}
private static <T> List<List<T>> slices(List<T> input)
{
List<List<T>> slices = new ArrayList<List<T>>();
List<T> current = input;
while (current.size() > 0)
{
T first = current.get(0);
int appearance = current.subList(1, current.size()).indexOf(first);
if (appearance == -1)
{
slices.add(current);
return slices;
}
List<T> slice = current.subList(0, appearance+2);
slices.add(slice);
current = current.subList(appearance+2, current.size());
}
return slices;
}
}
The output is
Input: [1, 2, 3, 4, 1, 8, 5, 6, 8, 9, 7, 9]
Output: [[1, 2, 3, 4, 1], [8, 5, 6, 8], [9, 7, 9]]
Input: [1, 2, 3, 4]
Output: [[1, 2, 3, 4]]
Input: [1, 1, 1, 1]
Output: [[1, 1], [1, 1]]
Input: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
Output: [[1, 2, 1], [2, 1, 2], [1, 2, 1], [2, 1, 2]]
Input: []
Output: []
The following code tracks the last position for each number and as soon as it founds a duplicate, it will create the sublist and clears all previously tracked entries.
List<Integer> list = Arrays.asList( 1,2,3,4,1,8,5,6,8,9,7,9);
List<List<Integer>> sublists = new ArrayList<>();
Map<Integer,Integer> lastPos = new HashMap<>();
for(int i = 0; i < list.size(); i++) {
Integer current = list.get(i);
if(lastPos.containsKey(current)){
sublists.add(list.subList(lastPos.get(current), i+1));
lastPos.clear();
} else {
lastPos.put(current, i);
}
}
System.out.println(sublists);
I have had a problem when I am doing my java program. I want to generate all the possible combinations of the element in a String array, and store each possible one into an overall ArrayList.
I used a for loop to go through all the possible combinations and use ArrayList.add to add each String array. However, when I was trying to print out the ArrayList to check, it only have the last String array at all the positions.
If I move the System.out.println to the inside of for loop, everything looks just fine. If I move the print to the outsides the loop, it just show that I only have the same String array at all positions.
Problem related to two parts of code:
String[] inputs = {"1", "2", "3", "4", "5", "6"};
int maxLength = 4;
//Get the total number of all combinations with replacement, used for the for loop
int total = (int) Math.pow(inputs.length, maxLength);
ArrayList<String[]> allList = new ArrayList<>();
System.out.println(total);
String[] subSets = new String[maxLength];
int [] index = new int [maxLength];
Arrays.fill(index, 0);
for (int i = 0; i < total; i++)
{
for (int j = 0; j < maxLength; j++)
{
subSets[j] = inputs[index[j]];
}
allList.add(i, subSets);
if (i != (total - 1))
index = nextIndex (index, maxLength, inputs.length);
// Set the print here everything looks fine
System.out.println(Arrays.toString(allList.get(i)));
}
// However, if you pit it here to check if you get the correct ArrayList, problem happens
//for (int g = 0; g < total; g++)
//System.out.println(Arrays.toString(allList.get(g)));
Another part is:
// Get the index of the next possible combination
public static int[] nextIndex (int[] index, int maxLength, int siZe)
{
for (int i = (maxLength - 1); i > 0; i--)
{
if (index[i] == (siZe - 1))
{
index[i] = 0;
if(index[i-1] == (siZe - 1)){
continue;
}
index[i - 1]++;
break;
}else{
index[i]++;
break;
}
}
The idea of this part of my program is to generate all possible combinations (with replacement) from the String array "inputs" and store the combinations into an overall ArrayList. Printing them out just my habit to check whether each step is correct or not.
The wrong output that I keep getting (just part of the output):
[6, 6, 6, 6]
[6, 6, 6, 6]
[6, 6, 6, 6]
[6, 6, 6, 6]
[6, 6, 6, 6]
[6, 6, 6, 6]
The correct output that I want to get:
[1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 1, 3]
[1, 1, 1, 4]
[1, 1, 1, 5]
[1, 1, 1, 6]
You are creating the subsets array just outside the for loops, so you are always updating the same array. this is the reason why, at the end you get the last permutation.
move the "String[] subSets = new String[maxLength];" just inside the for loop related to "i"
for (int i = 0; i < total; i++)
{
//create the new array here
String[] subSets = new String[maxLength];
...
}
and you will get the right output:
1296
[1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 1, 3]
[1, 1, 1, 4]
[1, 1, 1, 5]
.....
[6, 6, 6, 4]
[6, 6, 6, 5]
[6, 6, 6, 6]
You are creating the subSets Array outside your for loop and hence everything in the list is referring to the last updated subSets object i.e. [6, 6, 6, 6]. You are adding the same object to your list again and again and hence it will update the latest values at all the places in your list.
Move it inside your for loop as follows:
for (int i = 0; i < total; i++)
{
/* Move It Here */
String[] subSets = new String[maxLength];
for (int j = 0; j < maxLength; j++)
{
subSets[j] = inputs[index[j]];
}
allList.add(subSets);
if (i != (total - 1))
index = nextIndex (index, maxLength, inputs.length);
}