Array Remove middle terms - java

For my AP Computer Science AB class, we are required to make a program that is able to remove the middle term(s) from an array and my code constently returns an out of place 0 how can I fix this?
For example: [6, 2, 10, 2, 0] returns [6, 0, 2, 0] when the desired output is [6, 2, 2, 0]
if (arrayE.length % 2 == 0) {
int[] newArray = new int[arrayE.length - 2];
for (int i = 0; i < (arrayE.length / 2) - 1; i++) {
newArray[i] = arrayE[i];
}
for (int i = (arrayE.length / 2); i < newArray.length; i++) {
newArray[i] = arrayE[i + 2];
}
arrayE = newArray;
} else if (arrayE.length % 2 != 0) {
int[] newArray = new int[arrayE.length - 1];
for (int i = 0; i < (arrayE.length / 2) - 1; i++) {
newArray[i] = arrayE[i];
}
for (int i = (arrayE.length / 2); i < newArray.length; i++) {
newArray[i] = arrayE[i + 1];
}
arrayE = newArray;
}

This is because when you take arrayE.length /2 the int it returns would be 2. You are then subtracting - 1 for two. Effectively you have 2 - 1. so your array in this case is basically
for(int i = 0; i < 1; i++){
System.out.println("ran");
}
That only prints it out. The error is that you are never actually modifying the second index. Remove the -1.
This code should work fine.
if (arrayE.length%2!=0)
{
int[] newArray = new int[arrayE.length - 1];
boolean pastMidPoint = false;
for(int i = 0; i < arrayE.length; i++){
if(i == (arrayE.length / 2)) {
pastMidPoint = true;
continue;
}
if(!pastMidPoint)
newArray[i] = arrayE[i];
if(pastMidPoint)
newArray[i - 1] = arrayE[i];
}
arrayE = newArray;
}

So if you just want to remove the middle term from the array, you can try the following approach. In the case of an odd numbered size array:
public static int[] getOddLengthArray(int arrayE[]) {
int size = arrayE.length;
int indexToRemove = ((size+1)/2)-1;
int[] newArray = new int[size-1];
int newArrayIndex = 0;
for(int oldArrayIndex=0;oldArrayIndex<size-1; oldArrayIndex++) {
if(oldArrayIndex!=indexToRemove) {
newArray[newArrayIndex] = arrayE[oldArrayIndex];
newArrayIndex++;
}
}
return newArray;
}
Try and figure out the even numbered one for yourself!

The error in your code is this expression: (arrayE.length / 2) - 1
For the "odd" case you need to use the same boundary arrayE.length / 2 in the both loops.

Related

How to print the longest sequence of numbers from int[] array (Java)

I'm a beginner in programming and I need to print the longest sequence of numbers from int[] array.
For example, if we have:
int[] numbers = {1, 3, 3, 5, 5, 5, 5, 5, 5, 6, 0, 12, 2, 2, 2, 12, 0};
Result should be:
String result = "5, 5, 5, 5, 5, 5";
I wrote some bad code that don't work, but maybe it will give you some ideas.
public String findLargestSequence(int[] numbers) {
int bestStart = 0;
int curStart = 0;
int bestLength = 1;
int curLength = 1;
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > numbers[i - 1]) {
curLength++;
if (curLength > bestLength) {
bestStart = curStart;
bestLength = curLength;
}
} else {
curStart = i;
curLength = 1;
}
}
List<String> identical = new ArrayList<>();
for (int i = 0; i < bestLength; i++) {
identical.add(String.valueOf(numbers[bestStart + i]));
}
return Joiner.on(", ").join(identical);
}
Update.
Thanks to #phatfingers, I've found problem:
(numbers[i] > numbers[i - 1]) should be (numbers[i] == numbers[i - 1]).
But still there is one another problem.
If we have something like:
int[] numbers = {1, 2, 3, 3, 4, 4};
The result of it is:
"3, 3"
I think in this case, we could:
1) say, that we don't have any one longest sequence OR
2) show all that sequences, like:
String result = "Founded sequences: " + sequence1 + ", " + sequence2;
3) do nothing with that code above.
What would you do?
this show the max occurrence, you can also count it and print them
public static int consecutive(int[] array) {
if (array.length <= 1) {
return array.length;
}
int maxRun = 0;
for (int i = 1; i < array.length; i++) {
int thisRun = 1;
while (i < array.length && array[i - 1] + 1 == array[i]) {
thisRun++;
i++;
}
if (maxRun < thisRun) { // checking geater occurance
maxRun = thisRun;
}
}
return maxRun;
}
You have to handle 4 cases in the algorithm that you can divide in two parts:
Setting the state of the current serie :
increment the current serie if it grows
reinit the current serie when it changes
Setting the state of the max serie :
increment the max serie if it grows
reinit the max serie when it changes
In the actual code these conditions are not respected in the loop.
I commented two logic errors to illustrate the problem :
if (numbers[i] > numbers[i - 1]) {
// error : you don't increment the current serie when it grows
// because the condition if true only if the the current value is
// superior to the previous one
curLength++;
if (curLength > bestLength) {
bestStart = curStart;
bestLength = curLength;
}
}
// error : you don't reinit the current serie only when it changes
// because numbers[i] <= numbers[i - 1] is not true if the new number is
// superior to the previous one while it is a change
else {
curStart = i;
curLength = 1;
}
}
Here is the proposed code that handles the 4 conditions two by two:
public static String findLargestSequence(int[] numbers) {
// variables to maintain the max serie found and the number associated
int sizeMaxSerieFound = 0;
int numberMaxFound = numbers[0];
// variables to maintain the current serie found and the number
// associated
int sizeMaxCurrentSerie = 0;
int numberCurrentSerie = numbers[0];
boolean isMaxSerieIsTheCurrent = true;
for (int i = 0; i < numbers.length; i++) {
int currentNumber = numbers[i];
// FIRST STEP : set the state of the current serie
// increment the current serie if it grows or for the first
// iteration
if (currentNumber == numberCurrentSerie) {
sizeMaxCurrentSerie++;
}
// else we reinit to 1 the current serie
else {
sizeMaxCurrentSerie = 1;
numberCurrentSerie = currentNumber;
isMaxSerieIsTheCurrent = false;
}
// SECOND STEP : set the state of the max serie
// we increment the current number of the actual max serie
if (currentNumber == numberMaxFound && isMaxSerieIsTheCurrent) {
sizeMaxSerieFound++;
}
// we reinit the serie because we have found a new greater serie
else if (currentNumber != numberMaxFound && sizeMaxCurrentSerie > sizeMaxSerieFound) {
sizeMaxSerieFound = sizeMaxCurrentSerie;
numberMaxFound = currentNumber;
isMaxSerieIsTheCurrent = true;
}
}
List<String> identical = new ArrayList<>();
for (int i = 0; i < sizeMaxSerieFound; i++) {
identical.add(String.valueOf(numberMaxFound));
}
return Joiner.on(", ").join(identical);
}

Test Cases fail to satisfy

I'm just a beginner. I came across this question for which my code fails to satisfy all/most of the test cases.
Question:
Given an array of numbers, find the number of non-empty sub-arrays in which the minimum and maximum element are identical.
Example:
Input: Array = [1, 1, 3]
Output: 4
Explanation:
The required sub-arrays are [1], [1], [3], [1,1]
My solution:
Sort the array and solve the problem.
Code:
for(int i = 0; i < testCases; i++){
int arraySize = in.nextInt();
int array[] = new int[arraySize];
for(int j = 0; j < arraySize; j++){
array[j] = in.nextInt();
}
temp[i] = (findSubArrays(array));
}
for(int i = 0; i < testCases; i++){
System.out.println(temp[i]);
}
private static int findSubArrays(int[] array) {
Arrays.sort(array);
//Since each element can form a sub-array of its own
int noOfSubArrays = array.length;
for(int i = 0; i < array.length-1; i++){
if(array[i] == array[i+1]){
noOfSubArrays++;
}
}
return noOfSubArrays;
}
So you're sorting the array to keep begin points and end points adjacent so you don't need a nested traversal. That makes sense. The problem is that you're counting adjacent duplicates, but what you really need is T(n), or the triangle number of consecutive duplicates. Consider a simple scenario:
[1, 1, 1]
Your algorithm returns 5, but there are actually 6 subsets (by start & end index):
0, 0
0, 1
0, 2
1, 1
1, 2
2, 2
So let's update the algorithm to calculate the triangle number of each sequence:
private static int findSubArrays(int... array) {
Arrays.sort(array);
int sequenceCount = 0;
int total = 0;
for (int i = 0; i < array.length + 1; i++) {
if (i == array.length || (i > 0 && array[i] != array[i - 1])) {
total += triangle(sequenceCount);
sequenceCount = 0;
}
sequenceCount++;
}
return total;
}
private static int triangle(int n) {
return (n * (n + 1)) / 2;
}
Now calling findSubArrays(1, 1, 1) returns 6 and findSubArrays(1, 1, 3) returns 4.

Java MergeSort Algorithm recursive

i have a small question.
I try to implement the merge sort algorithm recursive.
int sort_list[] = {5, 9, 7, 8, 3, 4, 5, 6, 1, 0};
int[] left = new int[sort_list.length];
int[] right = new int[sort_list.length];
public Mergesort() {
int[] lv_sorted_list = mergeSort(sort_list);
for (int i = 0; i < lv_sorted_list.length; i++) {
System.out.print(" " + lv_sorted_list[i] + ", ");
}
}
int[] mergeSort(int[] iv_sort_list) {
for (int i = 0; i < iv_sort_list.length; i++) {
System.out.print("Divide: " + iv_sort_list[i] + " ");
}
System.out.println("");
if (iv_sort_list.length > 1) {
left = mergeSort(Arrays.copyOfRange(iv_sort_list, 0, iv_sort_list.length / 2));
right = mergeSort(Arrays.copyOfRange(iv_sort_list, iv_sort_list.length / 2, iv_sort_list.length));
}
int i = 0;
int j = 0;
int[] sorted_list = new int[left.length + right.length];
while (i < left.length && j < right.length) {
if (left[i] > right[j]) {
int tmp = left[i];
left[i] = right[j];
right[j] = tmp;
System.arraycopy(left, 0, sorted_list, 0, left.length);
System.arraycopy(right, 0, sorted_list, left.length, right.length);
i++;
j++;
}else{
break;
}
return sorted_list;
}
Now my Question:
left = mergeSort(Arrays.copyOfRange(iv_sort_list, 0, iv_sort_list.length));
right = mergeSort(Arrays.copyOfRange(iv_sort_list, iv_sort_list.length, iv_sort_list.length));
If i try to assign my left / right array "mergeSort(...)", then it will be assign only a new array with new length, which contains in every position the value 0.
Thank you very much for your help :)
I think you are missing the base case iv_sort_list.length = 1 or iv_sort_list.length = 2 (depends on your implementation) in your recursion function.
Your left[] and right[] should be declare inside each recursion call? As you are using there length property a lot, you will get wrong if you declare as global with a fixed length.
Also your merging code seems a bit messy, I have modified a bit and now it should work, please see the example here: Merge Sort (Java) demo

complete a method that swaps the first and second half of an array of integers

I keep getting an out of bounds error whenever i try to run my code. Does anyone know what is wrong with it? I can't seem to figure it out.
public class Swapper{
/**
This method swaps the first and second half of the given array.
#param values an array
*/
public void swapFirstAndSecondHalf(int[] values) {
// your work here
int[] first = new int[values.length/2];
int[] second = new int[values.length/2];
for(int i = 0; i < values.length / 2; i++) {
second[i] = values[i];
}
for (int j = values.length / 2; j < values.length; j++) {
first[j] = values[j];
}
for(int k = 0; k < values.length / 2; k++) {
values[k] = first[k];
}
for(int l = values.length / 2; l < values.length; l++) {
values[l] = second[l];
}
}
// This method is used to check your work
public int[] check(int[] values) {
swapFirstAndSecondHalf(values);
return values;
}
}
int[] first = new int[values.length/2];
So indexes [0..values.length/2 - 1] are valid for first.
for (int j=values.length/2; j<values.length; j++)
{
first[j] = values[j];
}
So with the first value of j being values.length/2, it's already out of bounds.
You need to practice debugging, placing a break point and tracing the code as it executes.
You could have used System.arraycopy() instead of all the for looping.
public static void main(String[] args) throws Exception {
int[] values = {1, 2, 3, 4, 5};
values = swapFirstAndSecondHalf(values);
System.out.println(Arrays.toString(values));
values = new int[]{1, 2, 3, 4, 5, 6};
values = swapFirstAndSecondHalf(values);
System.out.println(Arrays.toString(values));
}
public static int[] swapFirstAndSecondHalf(int[] values) {
boolean evenSize = values.length % 2 == 0;
int half = values.length / 2;
int[] swapper = new int[values.length];
System.arraycopy(values, evenSize ? half : half + 1, swapper, 0, half);
System.arraycopy(values, 0, swapper, evenSize ? half : half + 1, half);
// The middle number stays the middle number
if (!evenSize) {
swapper[half] = values[half];
}
return swapper;
}
Results:
[4, 5, 3, 1, 2]
[4, 5, 6, 1, 2, 3]
If you're wanting the middle number, for an odd sized array, to be part of the second half then the swapFirstAndSecondHalf() would look like this:
public static int[] swapFirstAndSecondHalf(int[] values) {
boolean evenSize = values.length % 2 == 0;
int half = values.length / 2;
int[] swapper = new int[values.length];
System.arraycopy(values, half, swapper, 0, evenSize ? half : half + 1);
System.arraycopy(values, 0, swapper, evenSize ? half : half + 1, half);
return swapper;
}
Results:
[4, 5, 3, 1, 2]
[4, 5, 6, 1, 2, 3]
Allocating new arrays is a waste of space. Just swap the halves in-place:
public static void swapFirstAndSecondHalf(int[] values) {
final int len = values.length / 2;
final int offset = values.length - len;
for (int i = 0; i < len; i++) {
int temp = values[i];
values[i] = values[offset + i];
values[offset + i] = temp;
}
}
The code allows odd length, and will leave center value alone.

Shifting first indexes

I have an array size of 3, and I am trying to shift the first index to the last place, while shifting the others to the left. for example:
{1,2,3} to {2,3,1}
here is my code
int[] nums = {1,2,3};
int[] numsShifted = new int[3];
for(int i = 0; i < nums.length - 1; i++)
{
int tempNum = nums[i];
numsRotated[i] = nums[i + 1];
numsRotated[i+1] = tempNum;
}
The issue I am having is the last index of the array, i get the incorrect value. Thanks.
Just do a simple shift and then copy the first number on the last position:
int[] nums = {1,2,3};
int[] numsShifted = new int[3];
int temp = nums[0];
for(int i = 1; i < nums.length; i++)
{
numsShifted[i - 1] = nums[i];
}
numsShifted[nums.length - 1] = temp;
Edit: You don't actually need to safe the first item, since you are not overwriting the original array.
Well you need to store the first element outside the loop and then begin shifting. After the end of the loop simply put the first element stored as the last element of the array.
you have to save the nums[0] value;
int saved = nums[0];
for(int i = 0; i < nums.length - 1; i++) {
numsShifted[i] = nums[i+1];
}
numsShifted[numsShifted.length - 1] = saved;
int[] nums = {1,2,3};
int[] numsShifted = new int[3];
for(int i = 0; i < nums.length - 1; i++)
{
int tempNum = nums[i]; //tempNum=1, tempNum=2
numsRotated[i] = nums[i + 1]; //numsRotated[0]=2, numsRotated[1]=3
numsRotated[i+1] = tempNum; //numsRotated[1]=1, numsRotated[2]=2 <- this is incorrect and the loop ends
}
at the end, you have 2,3,2. You will need to fix your loop.
int[] a = {1,2,3};
int[] b = new int[3];
for(int j = 0 , i = 2 ; j < a.length ; j++)
{
b[i++] = a[j];
if(i >= 3)
i = 0;
}
Here are some other options, without loops:
public static int[] queueFirst(int[] in) {
int len = in.length;
if (len <= 1) return in;
int[] ret = Arrays.copyOf(Arrays.copyOfRange(in, 1, len), len);
ret[len - 1] = in[0];
return ret;
}
or for references:
public static <T> T[] queueFirst(T[] in) {
if (in.length <= 1) return in;
ArrayList<T> n = new ArrayList<T>(Arrays.asList(in));
n.add(n.remove(0));
return n.toArray(in);
}
If you want to use the code you wrote, just fix it as I did.
Otherwise, the other answers are quite good!
int[] nums = {1, 2, 3};
int[] numsShifted = new int[3];
for (int i = 0; i < nums.length; i++) { //Do one more iteration
if (i + 1 > 2) { //If this is the last element, we take the first one of nums
numsShifted[i] = nums[0];
} else { //Otherwise we do as you did in your code
numsShifted[i] = nums[i + 1];
numsShifted[i + 1] = nums[i];
}
}
System.out.println(Arrays.toString(numsShifted));
EDIT :
Remove tempNum as you don't need it

Categories