For some reason, my solution is not complete. I got 80/100 from hidden spec tests.
What's wrong with my solution? There is probably a certain use case that I'm not thinking of.
How would space/time complexity change using an ArrayList instead of an array?
Is there a better way to tackle this problem?
My current solution handles:
an empty input array
negative/positive integer values in the input array
duplicates in the input array
sorted/unsorted input array
Instructions:
Write a Java method removeLastOccurrence(int x, int[] arr), which removes the last occurrence of a given integer element x from a given array of integer elements arr.
The method should return a new array containing all elements in the given array arr except for the last occurrence of element x. The remaining elements should appear in the same order in the input and the returned arrays.
The code on the right shows you a code framework in which the implementation of one static method is still missing. Provide this implementation and check that it is correct by either writing more tests yourself or using the provided tests and specification tests.
My code:
class RemoveLastOccurrenceArray {
/**
* Takes the array and the last occurring element x,
* shifting the rest of the elements left. I.e.
* [1, 4, 7, 9], with x=7 would result in:
* [1, 4, 9].
*
* #param x the entry to remove from the array
* #param arr to remove an entry from
* #return the updated array, without the last occurrence of x
*/
public static int[] removeLastOccurrence(int x, int[] arr) {
// if arr == null return null;
if (arr == null || arr.length == 0) return arr;
// return a new array which will be size arr.legnth-1
int[] res = new int[arr.length - 1];
// introduce an int tracker which keep tracks of the index of the last occurrence of x
int last_index = -1;
// traverse through the array to get the index of the last occurrence
for (int i = 0; i < arr.length; i++) if (arr[i] == x) last_index = i;
int i = 0, j = 0;
// copying elements of array from the old one to the new one except last_index
while (i < arr.length) {
if (i == last_index) {
if (i++ < res.length) {
res[j++] = arr[i++];
}
} else res[j++] = arr[i++];
}
// if we pass in x which is not in the array just return the original array
if (last_index == -1) return arr;
// are there duplicates in the array? - WORKS
// does the array have negative numbers? - WORKS
// Is the array sorted/unsorted - WORKS
return res;
}
}
Passing Unit Tests
import static org.junit.Assert.*;
import org.junit.*;
public class RemoveLastOccurrenceArrayTest {
#Test
public void testRemoveArray_Empty() {
int[] array = new int[0];
assertEquals(0, RemoveLastOccurrenceArray.removeLastOccurrence(5, array).length);
}
#Test
public void testFirstSimple() {
int[] input = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] result = {2, 3, 4, 5, 6, 7, 8, 9, 10};
assertArrayEquals(result, RemoveLastOccurrenceArray.removeLastOccurrence(1, input));
}
#Test
public void testLastSimple() {
int[] input = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] result = {1, 2, 3, 4, 5, 6, 7, 8, 9};
assertArrayEquals(result, RemoveLastOccurrenceArray.removeLastOccurrence(10, input));
}
#Test
public void testPositiveInMiddleDuplicate() {
int[] input = {1, 2, 3, 3, 4, 5};
int[] result = {1, 2, 3, 4, 5};
assertArrayEquals(result, RemoveLastOccurrenceArray.removeLastOccurrence(3, input));
}
#Test
public void testNegativeFirst() {
int[] input = {-3, -1, 2, -3, 3, 4, 5, 0};
int[] result = {-3, -1, 2, 3, 4, 5, 0};
assertArrayEquals(result, RemoveLastOccurrenceArray.removeLastOccurrence(-3, input));
}
#Test
public void testLasttoRemove() {
int[] input = {1, 4, 7, 9};
int[] result = {1, 4, 7};
assertArrayEquals(result, RemoveLastOccurrenceArray.removeLastOccurrence(9, input));
}
}
Why not try iterating backwards?
for(int i = arr.length; i => 0; i--)
{
if (arr[i] == x)
{
return ArrayUtils.remove(arr, i)
}
}
Then, after you find the index, you can use the Apache Commons ArrayUtils remove command to remove the item at the
This is the answer thank you very much!
Also, if there is no x to find, yours crashes ... mine doesn't. Maybe that's where the twenty marks went?
I was already checking for this but too late in my code. So I just had to move
if (last_index == -1) return arr; before the while loop, and I got 100/100 scores.
Would your prof prefer this? Just another way, and I don't think any more efficient than your answer. But maybe they like to see the java classes used ...
Does your prof not tell you where you lost marks? You can't improve if they don't tell you what they were expecting for full marks. But here was another way ... again, no better in my opinion, and not worth twenty more marks. I'll just post it, because it is 'another way.'
public int[] removeLastOccurrence2(int x, int[] arr) {
// if arr == null return null;
if (arr == null || arr.length == 0) return arr;
// Fill an ArrayList with your initial array ...
java.util.List list = new java.util.ArrayList(arr.length);
for (int i=0; i<arr.length; i++) {
list.add(arr[i]);
}
int[] res;
// Now ... use ArrayList methods to do the work.
// Also, if there is no x to find, yours crashes ... mine doesn't.
// Maybe that's where the twenty marks went?
if ( list.lastIndexOf(x) != -1 ) { // This screens for no x found at all ...
list.remove( list.lastIndexOf(x) ); // Done!
// Make a new array to return.
res = new int[list.size()];
for (int i=0; i<list.size(); i++) {
res[i] = (int) list.get(i);
}
} else {
// No 'x' found, so just return the original array.
res = arr;
}
return res;
}
How about reverse(), remove(), reverse()? Sorry if this is already mentioned in here somewhere and I missed it.
Related
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 need to write a program which defines two arrays of int's and prints all elements of the first array which do not appear in the second, but each value once only, without repetitions (the order of printed values is irrelevant).
For example for arrays:
int[] arr = { 4, 3, 4, 3, 6, 7, 4, 8, 2, 9 };
int[] brr = { 2, 3, 6, 8, 1, 5 };
The result should be:
7 4 9
It only use the java.lang. package and it can't create any arrays, collections or Strings.
This prints all elements of the first array which do not appear in the second, now you just have to check for repetitions.
public static void compareArrays(int[] arr1, int[] arr2) {
boolean equal = false;
int[] printed = null;
for (int i = 0; i < arr1.length; i++) {
for (int x = 0; x < arr2.length; x++) {
if (arr1[i] == arr2[x]) {
equal = true;
break;
} else {
equal = false;
}
}
if (equal != true) {
System.out.println(arr1[i]);
}
}
}
public static void main(String[] args) {
int[] arr = { 4, 3, 4, 3, 6, 7, 4, 8, 2, 9 };
int[] brr = { 2, 3, 6, 8, 1, 5 };
compareArrays(arr, brr);
}
I will give you some pointers, but will not provide any code as I've not seen any attempt from your side. You can tackle this problem several ways, have a look and try to implement this yourself. You will learn much more during the process, rather than if someone gives you a complete full-code answer. So here goes:
First method:
Create a new ArrayList that will hold your output.
Iterate through the first array, iterate through the second array. Compare each value.
If value is not present and is not present in the output list (you would need to check for that specifically, so you dont have repetition of values), then add it to output list.
Print output list.
Second method:
Convert both arrays into an ArrayList.
Use the removeAll() method provided with Lists to get difference between the arrays. This will be stored in one of the lists you created earlier.
Remove repetitive items from the list (e.g. using Streams).
Third method:
Create a new ArrayList that will hold your output.
Iterate through values of array1.
Initialize a boolean variable (e.g. call it contains) that will determine whether a value from array1 is present in array2 using an IntStream.
Create if statement - if contains is true, add the value to your output list. Check that your output List already doesn't have the value and only add if it doesn't. Print output list.
Try using this instead:
String[] unique = new HashSet<String>(Arrays.asList(arr)).toArray(new String[0]);
for (int uEach : unique) {
for (int bEach : brr) {
if (unique[uEach] == brr[bEach]) {
ArrayUtils.removeElement(unique, uEach);
}
}
};
System.out.print(unique);
You can use to get distanct value from an array:
int[] unique = Arrays.stream(arr).distinct().toArray();
Then loop over both arrays and match strings if not found print that:
int i, j, occ;
int[] arr = { 4, 3, 4, 3, 6, 7, 4, 8, 2, 9 };
int[] brr = { 2, 3, 6, 8, 1, 5 };
arr = Arrays.stream(arr).distinct().toArray();
for (i = 0; i < arr.length; i++) {
occ = 0;
for (j = 0; j < brr.length; j++) {
if (arr[i] == brr[j]) {
occ++;
}
}
if (occ == 0) {
System.out.println(arr[i]);
}
}
static void findMissing(int a[], int b[]) {
for (int i = 0; i < a.length; i++) {
int j;
for (j = 0; j < b.length; j++) {
if (a[i] == b[j]) {
break;
}
}
if (j == b.length) {
System.out.print(a[i] + " ");
}
}
}
I'm trying to solve a problem on CodeFights called firstDuplicate, that states -
Given an array a that contains only numbers in the range from 1 to
a.length, find the first duplicate number for which the second
occurrence has the minimal index. In other words, if there are more
than 1 duplicated numbers, return the number for which the second
occurrence has a smaller index than the second occurrence of the other
number does. If there are no such elements, return -1.
Example
For a = [2, 3, 3, 1, 5, 2], the output should be firstDuplicate(a) =
3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3
has a smaller index than than second occurrence of 2 does, so the
answer is 3.
For a = [2, 4, 3, 5, 1], the output should be firstDuplicate(a) = -1.
My solution -
public class FirstDuplicate {
private static HashMap<Integer, Integer> counts = new HashMap<>();
private static void findSecondIndexFrom(int[] num, int n, int i) {
// given an array, a starting index and a number, find second occurrence of that number beginning from next index
for(int x = i; x < num.length; x++) {
if(num[x] == n) {
// second occurrence found - place in map and terminate
counts.put(n, x);
return;
}
}
}
private static int firstDuplicate(int[] a) {
// for each element in loop, if it's not already in hashmap
// find it's second occurrence in array and place number and index in map
for(int i = 0; i < a.length; i++) {
if(!counts.containsKey(a[i])) {
findSecondIndexFrom(a, a[i], i+1);
}
}
System.out.println(counts);
// if map is empty - no duplicate elements, return -1
if(counts.size() == 0) {
return -1;
}
// else - get array of values from map, sort it, find lowest value and return corresponding key
ArrayList<Integer> values = new ArrayList<>(counts.values());
Collections.sort(values);
int lowest = values.get(0);
//System.out.println(lowest);
for(Map.Entry<Integer, Integer> entries: counts.entrySet()) {
if(entries.getValue() == lowest) {
return entries.getKey();
}
}
return -1;
}
public static void main(String[] args) {
// int[] a = new int[]{2, 3, 3, 1, 5, 2};
//int[] a = new int[]{2, 4, 3, 5, 1};
//int[] a = new int[]{8, 4, 6, 2, 6, 4, 7, 9, 5, 8};
//int[] a = new int[]{1, 1, 2, 2, 1};
int[] a = new int[]{10, 6, 8, 4, 9, 1, 7, 2, 5, 3};
System.out.println(firstDuplicate(a));
}
}
This solution passes only for about 4 of the 11 test cases on CodeFights. However, I manually executed each one of the test cases in my IDE, and each one produces the right result.
I can't figure out why this won't work in CodeFights. Does it have something to do with the use of the static HashMap?
Edited: Since adding and checking if element is present in Set can be done in one step, code can be simplified to:
public static int findDuplicateWithLowestIndex(int... a){
Set<Integer> set = new HashSet<>();
for(int num : a){
if(!set.add(num)){
return num;
}
}
return -1;
}
You're completly right Patrick.
Use this solution: here duplicateIndex should be very large number.
package sample;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Duplicate {
public static Integer secondIndex(Integer[] arr) {
List<Integer> arrlist = new ArrayList<>(Arrays.asList(arr));
int duplicateIndex = 999;
int ele = 0;
for (int i = 0; i < arrlist.size(); i++) {
int secondIndex = getSecondIndex(arrlist, arrlist.get(i));
if (secondIndex >= 0 && duplicateIndex > secondIndex) {
duplicateIndex = secondIndex;
ele = arrlist.get(i);
}
}
return duplicateIndex == 999 ? -1 : ele;
}
public static int getSecondIndex(List<Integer> arr, int ele) {
List<Integer> var0 = new ArrayList<>(arr);
var0.set(var0.indexOf(ele), -1);
return var0.indexOf(ele);
}
public static void main(String[] str) {
// Integer[] arr = new Integer[] { 2, 3, 3, 1, 5, 2 };
// Integer[] arr = new Integer[] { 2, 4, 3, 5, 1 };
// Integer[] arr = new Integer[] { 8, 4, 6, 2, 6, 4, 7, 9, 5, 8 };
// Integer[] arr = new Integer[]{1, 1, 2, 2, 1};
Integer[] arr = new Integer[] { 10, 6, 8, 4, 9, 1, 7, 2, 5, 3 };
System.out.println(secondIndex(arr));
}
}
Solution in Javascript
function solution(a) {
const duplicates = [];
for (const i of a) {
if (duplicates.includes(i))
return i;
else
duplicates.push(i);
}
return -1;
}
console.log(solution([2, 1, 3, 5, 3, 2])); // 3
console.log(solution([2, 2])); // 2
console.log(solution([2, 4, 3, 5, 1])); // -1
Here is the program task:
Write a method called collapse that accepts an array of integers as a parameter and returns a new array containing the result of replacing each pair of integers with the sum of that pair.
For example, if an array called list stores the values
{7, 2, 8, 9, 4, 13, 7, 1, 9, 10}
then the call of collapse(list) should return a new array containing:
{9, 17, 17, 8, 19}.
The first pair from the original list is collapsed into 9 (7 + 2), the second pair is collapsed into 17 (8 + 9), and so on. If the list stores an odd number of elements, the final element is not collapsed.
For example, if the list had been {1, 2, 3, 4, 5}, then the call would return {3, 7, 5}. Your method should not change the array that is passed as a parameter.
Here is my currently-written program:
public static int[] collapse(int[] a1) {
int newArrayLength = a1.length / 2;
int[] collapsed = new int[newArrayLength];
int firstTwoSums = 0;
for (int i = 0; i < a1.length-1; i++) {
firstTwoSums = a1[i] + a1[i+1];
collapsed[collapsed.length-1] = firstTwoSums;
}
return collapsed;
}
I pass in an array of {7, 2, 8, 9, 4, 13, 7, 1, 9, 10} and I want to replace this array with {9, 17, 17, 8, 19}.
Note:{9, 17, 17, 8, 19} will be obtained through the for-loop that I have written.
Currently, I am having trouble with adding the integers I obtained to my "collapsed" array. It'd be a great help if you could help me or at least give me some guidance on how to do this.
Thanks in advance!
First you have to understand what is going on.
You have an array of certain size where size can either be even or odd. This is important because you are using a1.length/2 to set the size for new array, so you will also have to check for odd and even values to set the size right else it won't work for odd sized arrays. Try a few cases for better understanding.
Here's a way of doing it.
public static int[] collapseThis(int[] array) {
int size = 0;
if(isEven(array.length))
size = array.length/2;
else
size = array.length/2+1;
int[] collapsedArray = new int[size];
for(int i=0, j=0; j<=size-1; i++, j++) {
if(j==size-1 && !isEven(array.length)) {
collapsedArray[j] = array[2*i];
}
else {
collapsedArray[j] = array[2*i]+array[2*i+1];
}
}
return collapsedArray;
}
private static boolean isEven(int num) {
return (num % 2 == 0);
}
Using
collapsed[collapsed.length-1] = firstTwoSums;
The sum of your numbers will be always be put in the same index of the collapsed array, because collapsed.length - 1 is a constant value.
Try creating a new variable starting at zero, that can be incremented each time you add a sum to collapsed. For instance,
int j = 0;
for(...) {
...
collapsed[j++] = firstTwoSums;
}
I think this is a convenient answer.
public static void main(String[] args){
int[] numbers = {1,2,3,4,5};
int[] newList = collapse(numbers);
System.out.println(Arrays.toString(newList));
}
public static int[] collapse(int[] data){
int[] newList = new int[(data.length + 1)/2];
int count = 0;
for (int i = 0; i < (data.length / 2); i++){
newList[i] = data[count] + data[count + 1];
System.out.println(newList[i]);
count = count + 2;
}
if (data.length % 2 == 1){
newList[(data.length / 2)] = data[data.length - 1];
}
return newList;
}
i would combine the cases for the array with either odd or even elements together as below:
public static int[] collapse(int[] a1) {
int[] res = new int[a1.length/2 + a1.length % 2];
for (int i = 0; i < a1.length; i++)
res[i/2] += a1[i];
return res;
}
public static int[] collapse(int[] a1) {
int newArrayLength = a1.length / 2;
int[] collapsed;
if(a1.length%2 == 0)
{
collapsed = new int[newArrayLength];
}
else
{
collapsed = new int[newArrayLength+1];
collapsed[newArrayLength] = a1[a1.length-1];
}
int firstTwoSums = 0;
for (int i = 0; i < newArrayLength; i++) {
firstTwoSums = a1[i*2] + a1[i*2+1];
collapsed[i] = firstTwoSums;
}
return collapsed;
}
I modified your code and you may try it first.
i have array values as like
String[] value = {"1","2","3", "4","5","6","7","8","9","10"};
suppose if i pass value "5" to tat array, it should be ordered as like
{"5","6","7","8","9","10",1","2","3","4"};...
how to do?plz anyone help?
thank u
What you need is called rotation. You can use Collections.rotate() method. Convert the array to a list and pass it to the method. This will rotate the array in place since the list is backed by the array:
String[] value = {"1","2","3", "4","5","6","7","8","9","10"};
Collections.rotate(Arrays.asList(value), 5);
The above code will rotate the array by a distance of 5. The resulting value array:
[6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
Your question has two interpretations:
Rotate 5 steps, or
rotate the array so that 5 is the first element (regardless of where it is in the array).
Here is a solution for both alternatives:
import java.util.Arrays;
public class Test {
public static String[] rotateArray(String[] arr, int n) {
String[] rotated = new String[arr.length];
System.arraycopy(arr, n-1, rotated, 0, arr.length-n+1);
System.arraycopy(arr, 0, rotated, arr.length-n+1, n-1);
return rotated;
}
public static String[] rotateArrayTo(String[] arr, String head) {
for (int i = 0; i < arr.length; i++)
if (arr[i].equals(head))
return rotateArray(arr, i + 1);
throw new IllegalArgumentException("Could not find " + head);
}
public static void main(String[] args) {
String[] value = {"1","2","3","4","5","6","7","8","9","10"};
// Rotate so that it starts at 5:th element
value = rotateArray(value, 5);
System.out.println(Arrays.toString(value));
// Rotate so that it starts with element "7"
value = rotateArrayTo(value, "7");
System.out.println(Arrays.toString(value));
}
}
Output:
[5, 6, 7, 8, 9, 10, 1, 2, 3, 4]
[7, 8, 9, 10, 1, 2, 3, 4, 5, 6]
(ideone.com link)
first find the index of the entered value from the array..
and then in a loop move from the index to the final position.. and store these values in a new array.
after that, in the same result array, store the values from index 0 to the index of the entered value - 1.
You really don't need to store the values in a different array. Just find the index [say idx] of the value passed. And then start a loop from the start of the array and swap the values starting from idx.
For example -
idx = [some-value]
while [idx < arr.length]
temp = arr[i]
arr[i] = arr[idx]
arr[idx] = t
idx += 1
i += 1
Update:
I stand corrected by #aioobe. I simply worked out something for the 5th index - my bad. Here's something that works, if in case, you want to stay away from library functions -
private void slideLeft(String[] arr)
{
String t = arr[arr.length - 1];
String temp = null;
int next = -1;
for (int i = arr.length - 1; i >= 0; i--)
{
next = ( i == 0 ) ? arr.length - 1 : i - 1;
temp = arr[next];
arr[next] = t;
t = temp;
}
}
you'll need to call this method the number of times you need to shift the array members.
note: O(n^2) alert. not suitable for large shifts/arrays.