How to reverse an ArrayList without the reverse method? - java

Hello I am trying to reverse an ArrayList without the reverse method. I just wanted to make it work without the method. I can't seem to get it right.
This is what i have so far:
for (int x = nums.size()-1; x>=0; x--)
{
for(int z =0; z<nums.size();z++)
{
nums.set(z, x);
}
}
This is my output:
run:
0
1
2
3
1
1
1
1
BUILD SUCCESSFUL (total time: 0 seconds)

You can ascend from the bottom & simultaneously descend from the top (size() - 1) swapping elements, and stop when you meet in the middle.
int i = 0;
int j = nums.size()-1;
while (i < j) {
int temp = nums.get(i);
nums.set( i, nums.get(j));
nums.set( j, temp);
i++; j--;
}

You can swap in pairs at a time, coming in from both ends toward the center:
for (int i = 0; i < nums.size()/2; i++) {
Integer left = nums.get(i);
Integer right = nums.get(nums.size()-1-i);
nums.set(i, right);
nums.set(nums.size()-1-i, left);
}
By using Integer instead of int for left and right, Java doesn't have to keep converting between int and Integer values (the first being a primitive, the second being an actual object). This improves performance.

Related

Recursive variation of Bubble Sort

I'm a student and I'm taking a DSA course. On our latest assignment we were asked to implement a recursive variation of bubble sort. The assignment was alrady submitted but I couldn't make it work and it's frustrating me. I've triple checked everything and I can't find the problem.
The general pseudo-code for the algorithm is:
if (n > 10) // n being the size of array A
sort recursivley the first 2/3 elements in A (from 0 to ceil(2n/3))
sort recursivley the last 2/3 elements in A (from floor(n/3) to n)
sort recursivley the first 2/3 elements in A (from 0 to ceil(2n/3))
else
use bubbleSort
This is the code I wrote:
public static void weirdSort(double[] arr, int start, int end, int size) {
if (size > 10) {
int weirdStart = (size / 3) - 1;
int weirdEnd = (end - weirdStart) - 1;
int weirdSize = (weirdEnd - start + 1);
weirdSort(arr, start, weirdEnd, weirdSize);
weirdSort(arr, weirdStart, end, weirdSize);
weirdSort(arr, start, weirdEnd, weirdSize);
}
else
bubbleSort(arr, start, end);
} // end of method
private static void bubbleSort(double arr[], int start, int end) {
int size = end - start + 1;
boolean noSwaps;
for (int i = start; i < size; i++) {
noSwaps = true;
for (int j = start + 1; j < size - i; j++) {
if (arr[j - 1] > arr[j]) {
swap(arr, j, j - 1);
noSwaps = false;
} // end of condition
} // end of (j) for loop
if (noSwaps) // If no two elements were swapped by inner loop, array is sorted
break;
} // end of (i) for loop
} // end of method
The problem is that it only sorts the array up to 2/3 of the first elements, the last 1/3 are unsorted (bubbleSort by itself works fine). I would really like to solve this on my own but I'm stuck, so I would apreciate any thoughts or suggestions on the matter but not a full solution.
After calling weirdSort for all the 3 parts, those parts will be sorted but it has to be arranged so that the whole array is sorted, just like in a mergesort. So after calling the weirdSort, you have to run a loop and convert those 3 independent sorted arrays into a single sorted array.
Your interpolation is wrong. Take an example,
weirdSort([...], 0, 11, 12):
weirdStart = 12 / 3 - 1 = 3
weirdEnd = 11 - 3 - 1 = 8
weirdSize = 8 - 0 + 1 = 9
// so far so good, but look at the second recursive call
weirdSort([...], 3, 11, 9):
weirdStart = 9 / 3 - 1 = 2 // Wrong!
// Other vars are now also wrong
You need to account for start when determining weirdStart and weirdEnd.
To get you started, you want something like,
third = (end - start + 1) / 3;
weirdStart = start + third;
weirdEnd = end - third;
In fact, don't pass size around at all, just compute it as end - start + 1.
You might want to adjust weirdStart/End by +/-1 depending on your specific needs.

Can someone code and explain the merge portion of mergesort? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
Ive been trying to understand the merge portion of mergesort for a few hours now, and Ive looked at a bunch of tutorials and walkthroughs. And im not understanding the merge part of mergesort. Theoretically, I understand it. But trying to implement it through code is where Im having a hard time. It's not like I dont understand any of the merge portion of it. I get why you need a couple pointers to keep track of the indices and the reasoning behind the conditional statement in the while loop. But after that I get stuck. I wrote a comment in the merge method on where im stuck. If anyone could just explain to me what I need to code in Java and the reasoning behind it, it'd be great.
EDIT: Added two new while loops the the merge method. All thats left I think for me to do is how to copy the sorted partitions into the input array. I think after that it should be working fine... hopefully.
EDIT2: Nevermind the above, I just saw that its not sorting it correctly. Hopefully someone can just modify my code and explain there process
public static void merge(int[] input, int start, int mid, int end) {
if (input[mid - 1] <= input[mid]) {
return;
}
int i = start;
int j = mid;
int tempIndex = 0;
int[] temp = new int[end - start];
//If i is greater than mid or j is greater than end, that means that half of the array is sorted
while (i < mid && j < end) {
temp[tempIndex++] = input[i] <= input[j] ? input[i++] : input[j++];
}
//added the two loops below
while(i < mid){
temp[tempIndex++] = input[i++];
}
while(j < end){
temp[tempIndex++] = input[j++];
}
}
```
MergeSort is a divide and conquor strategy.
Let's say you have 8 elements.
The 8 elements get split into 4 elements each (left/right) and mergeSort is invoked on each of them. We'll ignore merge for now and delve deeper.
The 4 elements are further split into 2 elements each, and mergeSort is invoked on the 2 element array.
The 2 elements are further split into 1 elements each, and mergeSort is invoked on each of these at which time, it returns without doing anything.
So we are finally at the first invocation of merge. So what does merge do? Merge joins 2 SORTED lists. When they are 1 element each, it's just a matter of picking one over the other. So lets skip forward to the 4 elements and provide an example below:
By the time the 4 element sub-list invokes merge, it may have the following:
1 3 2 4
Each sub-array (1, 3) and (2, 4) are already sorted by the previous merge. So we now need to sort the array while merging them like this (I will use a separate output array to demonstrate what should be happening but it can be done in place):
for (int i = 0, j = 2, k = 0; k < 4; k++)
{
int idx;
if ((j >= 4) || (i < 2 && inputArray[i] < inputArray[j]))
{
idx = i++;
}
else // j < 4 && (i > 2 || inputArray[j] < inputArray[i])
{
idx = j++;
}
outputArray[k] = inputArray[idx];
}
As you can see, initially we have i pointing to 1, j pointing to 2. Because 1 < 2, i is selected, and the 1 is output. Because i was selected, i gets incremented. Now, we have i pointing to 3 and j pointing to 2. Because 2 < 3, j gets selected... and so on until we run out of elements.
And after the merge, it will get called on the larger array with 2 4-element sides, repeating the above.
Below is the generalized code without hard coding
public void Merge(int[] input, int start, int mid, int end)
{
if (input[mid - 1] <= input[mid])
{
}
else
{
int[] tmp = new int[end - start];
for (int i = start, j = mid, k = 0; k < tmp.Length; k++)
{
int idx;
if ((j >= end) || (i < mid && input[i] < input[j]))
{
idx = i++;
}
else // j < end && (i > mid || inputArray[j] < inputArray[i])
{
idx = j++;
}
tmp[k] = input[idx];
}
for (int i = start, j = 0; i < end; i++, j++)
{
input[i] = tmp[j];
}
}
}

Maximum Sum Subarray O(n) not Kadane's

I'm reading Cormen's "Introduction to Algorithms".
For the linear algorithm for Max Sum Subarray problem I came up with my own solution. Didn't check existing one (Kadena's) before implementing.
Now I'm testing it with different test scenarios and always have better results than Kadena's. I don't believe in such a luck, but can't find what have I missed. Could you take a look whether it is a working solution?
public void findMaxSubarray(Number[] numbers) {
int maxSum = Integer.MIN_VALUE;
int left = 0;
int right = numbers.length - 1;
int i = 0;
int j = i + 1;
int sum = numbers[i].intValue();
while (i < numbers.length) {
if (maxSum < sum) {
maxSum = sum;
left = i;
right = j - 1;
}
if (j >= numbers.length)
return;
sum = sum + numbers[j].intValue();
if (sum <= 0) {
// ignoring "first" negative numbers. shift i to first non-negative
while (numbers[j].intValue() <= 0) {
if (maxSum < numbers[j].intValue()) {
maxSum = numbers[j].intValue();
left = j;
right = j;
}
if (++j >= numbers.length)
return;
}
i = ++j;
sum = 0;
}
j++;
}
System.out.println(String.format("Max subarray is %d, [%d; %d]", maxSum, left, right));
}
Update
The idea of code is to keep in track only one subarray, and adding to its' tail numbers, when numbers are that low that sum becomes negative - set beginning of array after the tail.
Additionally negative items in the beginning are being ignored. head of subarray is just shifted forward.
Everytime sum appears to be maximum - maxSum and limits are updated.
shift i() --to first non negative number
from j = i+1 up to N.length
sum + N[j]
if sum <= 0
i = j+1
if N[i] < 0
shift i()
sum = 0
I think your algorithm is basically sound, but it has two bugs that I can see:
On the input 1 -2 10 3, it will skip over the 10 and output 3. I think you can fix this by changing i = ++j; to i = j;.
In 2 different places you return if j goes past the end, which will cause no output to be produced at all! (This will happen if, e.g., a long list of negative numbers appears at the end of the list.)
Also I don't expect it to be faster (or slower, for that matter) than Kadane's. Summing two numbers is a fast operation, as fast as copying one variable to another, which is what you are doing when you shift the start of the subarray.

Out of Bounds of an Array [Bubble Selection with ArrayList]

I'm coding a Bubble Selection method, which should work with these credentials:
/* Write code for a Bubble Sort algorithm that starts at the right side of
* of ArrayList of Comparable objects and "bubbles" the largest item to the
* left of the list. The result should be an ArrayList arranged in descending
* order.
*/
#SuppressWarnings("unchecked")
void bubbleSort(ArrayList <Comparable> list) {
int end = list.size();
for (int i = 0 ; i < end; i++){
for (int j = end; j > 0; j--){
if ( list.get(j).compareTo(list.get(j-1)) > 0 ){
//swap
Comparable temp = list.get(j);
list.set(j,list.get(j - 1));
list.set(j - 1, temp);
//System.out.println(list);
}
}
end--;
}
}
The problem is, Java will then tell me it is out of bounds.
If I instead use
for (int j = end - 1; j > 0; j--)
the code will then run, however it does not run the number of times it needs to run for the list to completely finish sorting (aka it stops one loop ahead)
As explained, you need to start in end-1, or else you'll be accessing out of bounds of the array.
Let's say you have an array of integers: 5 1 4
Your algorith will do this:
1st iteration -> i = 0 / j starting at 2
1 5 4
2nd iteration -> i = 1 / j starting at 1
It will now only compare 5 and 1 and not switching them, because 5 is higher. So, and the 4 and 5? They should be swapped. Your algorithm implementation is wrong.
If you remove the end--; it should work.
However, this can be optimized
Use this code it will work for your requirement in array implementation where size is your array length.
for (int i = 0; i < size - 1; j++) {
for (int j = i + 1; j < size - 1; k++){
if (array[i] > array[j]) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
If the array is long 3, array[3] is out of bound.
Since you start with array[lenght] you have to decrement it before entering in the for cycle like the code you provide.
Using end - 1 will compare last and second last values in list
if you use end it will try to compare last value and value at index after last which will give ArrayOutOfBound Exception.
Now For correct output you have to remove end--; line as per shown below
for (int i = 0 ; i < end; i++){
for (int j = end -1; j > 0; j--){
if ( list.get(j).compareTo(list.get(j-1)) > 0 ){
//swap
Comparable temp = list.get(j);
list.set(j,list.get(j - 1));
list.set(j - 1, temp);
}
}
//remove below line
end--;
}
This will short the list by one value from right side also. So removing This will work

Iterating an array from both ends using two indices

This is more of an self defined programming exercise than a real problem. I have an array of java.lang.Comparable items. I need to maintain two pointers (an index into the array i.e., int values) i,j . i starts at the beginning of array and moves right until it encounters an element which is less than or equal to the previous element. When it does it stops moving right and ends up pointing to the element which is out of order(element which is not greater than the previous). Similarly j starts at the end of the array and moves left until it finds an element which is not less than the previous.
Also, I need to make sure that the indices don't run out of the array i.e., i cannot go below 0 and j cannot go above arraylength-1
lets say we have an array of 5 elements.
i = 0;
j = 4;(which is the arraylength-1 )
if C,D,E,F,G is the array ,the final values of i and j will be
i = 4 and j = 0
if array is J,D,E,F,G ,the final values of i, j will be
i = 0 , j = 0
if array is B,C,A,D,G , final values of i,j will be
i = 2 , j = 1
I tried to code the logic for moving i to the right, using a while loop as below. I was able to get it working for the i pointer in two cases.
public class PointerMovement{
public static void ptrsPointToOutOfOrderElements(Comparable[] a){
int lo = 0;
int hi = a.length-1;
int i = lo;
int t=i+1;
int j = hi;
//only for moving i to the right .
while(less(a[i],a[t])){
if(t == hi){
i=t;
break;
}
i++;
t++;
}
i=t;
for(Comparable x:a){
System.out.print(x+",");
}
System.out.println();
System.out.println("bad element or end of array at i="+i+"==>"+a[i]);
}
private static boolean less(Comparable x,Comparable y){
return x.compareTo(y) < 0;
}
public static void main(String[] args) {
String[] a = new String[]{"C","D","E","F","G"};//works
//String[] a = new String[]{"B","C","A","D","G"};//works
//String[] a = new String[]{"J","D","E","F","G"};//fails!
ptrsPointToOutOfOrderElements(a);
}
}
My line of reasoning given below
I maintain i=0; and another variable t=i+1
when the while loop fails, less(a[i],a[t]) is false .We need to return a pointer to a[t] which is out of order. so i=t and return i.
if we reach right end of array, the test if(t == hi) passes and we assign i=t and now i points to end of array.
However, the code fails when the out of order element is in the 0th position in the array.
J,D,E,F,G
Instead of i (=0) we get i=1 because i=t is assgined.i ends up pointing to D instead of J.
Can someone point me in the right direction?
update:
this seems to work
public static void ptrsPointToOutOfOrderElements(Comparable[] a){
int lo = 0;
int hi = a.length-1;
int i = lo;
while(less(a[i],a[i+1])){
if(i+1 == hi){
break;
}
i++;
}
i++;
int j = hi;
while(less(a[j-1],a[j])){
if(j-1 == lo){
break;
}
j--;
}
j--;
for(Comparable x:a){
System.out.print(x+",");
}
System.out.println();
if(i>=j){
System.out.println("pointers crossed");
}
System.out.println("bad element or end of array at i="+i+"==>"+a[i]);
System.out.println("bad element or end of array at j="+j+"==>"+a[j]);
}
I do not think you have a problem:
String[] a = new String[]{"C","D","E","F","G"};//works, index should be 4 (but should it be so? It would indicate that G is out of order while it is not. I think you should return 5, indicating that none is out of order.
String[] a = new String[]{"B","C","A","D","G"};//works, index should be 2 as A is out of order
String[] a = new String[]{"J","D","E","F","G"};//works since the first out of order element is indeed D, with index 1
I have tried using simple for loop.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (var i = 0, j = arr.length - 1; i <= j; i++, j--) {
console.log(arr[i] + ' , ' + arr[j]);
}
Output :
1 , 10
2 , 9
3 , 8
4 , 7
5 , 6

Categories