Recursive variation of Bubble Sort - java

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.

Related

Go through the array back and forth

We have an array of some length(say 3) and some counting sequence: 0,1,2,3,4,... to infinity. Out of that input sequence we need to produce sequence that will traverse through array back and forth, like that: 0,1,2,1,0,1,2,1,0,... and so on for a length=3.
I think this task is a very common one in a many programming books, but i was not able to find standard solution, so i created my own solution. Are there any other more efficient and elegant solution, because i dont like my solution???
#define LENGTH 5
int main()
{
char arr[LENGTH] = {'a','b','c','d','e'};
int i;
int base=0;
for(i=0;i<100;i++){
if(i%(LENGTH-1)==0){
if(base==0) base=LENGTH-1;
else base =0;
}
int j = abs(base-i%(LENGTH-1));
printf("%c ",arr[j]);
}
}
Java code (for your convenience):
public static void traverse(){
char arr[] = {'a','b','c','d','e'};
int base=0;
for(int i=0;i<100;i++){
if(i%(arr.length-1)==0){
if(base==0) base=arr.length-1;
else base =0;
}
int j = Math.abs(base-i%(arr.length-1));
System.out.println(arr[j]+" ");
}
}
This solution calculates the index of arr only from i, thus avoiding the need to keep any state (such as current direction). As a result it is a bit more convoluted, but would also work for non-consecutive values of i.
char arr[] = { '0', '1', '2', '3', '4' };
const int LENGTH = sizeof arr / sizeof(*arr); // not necessary for char
assert(LENGTH > 1); // doesn't work for fewer than 2 elements
const int CYCLE = LENGTH - 1;
for (int i = 0; i < 100; ++i) {
printf("%c ", arr[ (i / CYCLE) & 1 ? CYCLE - i % CYCLE : i % CYCLE ]);
}
printf("\n");
Explanation: i / CYCLE is the number of the cycle through the array, and & 1 checks the least significant bit of that number to determine the direction (odd cycles where the bit is 1 go backwards, even cycles – starting from 0 – go forwards). i % CYCLE is the forwards cycle, but since CYCLE = LENGTH - 1, it doesn't reach the last index of the array. CYCLE - i % CYCLE is the backwards cycle, starting from CYCLE - 0, which is the last index that wasn't reached when going forwards, and ending at 1, thus avoiding repetition of index 0 when going forwards again.
In other words, both the forwards and the backwards cycles omit one index to avoid repetition when changing direction, hence CYCLE = LENGTH - 1, which also means that LENGTH must be at least 2 to avoid division by zero.
Maybe something like this:
#define LENGTH 5
int main()
{
char arr[LENGTH] = { 'a','b','c','d','e' };
int current = 0;
int direction = 1;
for (int i = 0; i < 100; i++)
{
printf("%c ", arr[current]);
if (current == 0)
direction = 1;
else if (current == LENGTH - 1)
direction = -1;
current += direction;
}
}

How many times will merge and mergesort be run in mergesort algorithm?

These are homework questions, but I would like to understand the concepts behind them, not just get the answers.
I know that the running time of MergeSort is O(nlogn). It seems that the merge method would have to run n times (because it has to merge all of the arrays, and there ends up being n arrays). Therefore, I thought I could deduce that the MergeSort() method would be called logn times. I also thought that made sense because it is dividing the array, so it would keep dividing itself by 2, so logn.
Therefore, I feel that the answers are C and A, respectively. But I am a bit skeptical because of the note saying the questions are asking how many times the method is called, not the running time. I would appreciate some advice and an explanation of counting vs running time. Thank you.
The questions are as follows:
18.
We defined a recursive method MergeSort() to divide the input array in the middle and recursively sort each part.
Suppose we have an array of length n, and we apply this merge sort algorithm. How many times will the MergeSort() method be called?
A. O(n)
B. O(n2)
C. O( log(n) )
D. O( n log(n) )
[[[
Note that this and the next question ask to count how many times the methods are called. This is NOT about the running time; it is about the counting.
]]]
19.
Suppose we have an array of length n, and we apply this merge sort algorithm. How many times will the merge() method be called?
A. O(n)
B. O(n2)
C. O( log(n) )
D. O( n log(n) )
Source code:
import java.util.Arrays;
public class MergeSort
{
public static void merge(int[] data, int first, int last)
{
int[] temp = new int[last - first + 1]; // A new array to hold the merged result
int mid = (first + last) / 2;
int i = first, j = mid + 1, k = 0;
// Copy smaller item from each subarray into temp until one
// of the subarrays is exhausted
while (i <= mid && j <= last)
{
if (data[i] < data[j])
temp[k++] = data[i++];
else
temp[k++] = data[j++];
}
// Copy remaining elements from first subarray, if any
while (i <= mid)
temp[k++] = data[i++];
// Copy remaining elements from second subarray, if any
while (j <= last)
temp[k++] = data[j++];
// Copy merged data back into original array
for (i = first; i <= last; i++)
data[i] = temp[i - first];
}
public static void merge2(int[] data, int first, int last)
{
int mid = (first + last) / 2;
int i = first, j = mid + 1;
int len = last - first + 1;
int[] temp = new int[len];
for (int k = 0; k < len; k++)
{
if (i == mid + 1) // The left part is done
temp[k] = data[j++];
else if (j == last + 1) // The right part is done
temp[k] = data[i++];
else if (data[i] < data[j]) // Get one from the left
temp[k] = data[i++];
else // Get one from the right
temp[k] = data[j++];
}
// Copy merged part back into the original array
for (i = first; i <= last; i++)
data[i] = temp[i - first];
}
public static void mergeSort(int[] data, int first, int last)
{
// intermediate result
System.out.println(Arrays.toString(Arrays.copyOfRange(data, first, last + 1)));
if (first >= last)
return;
int mid = (first + last) / 2;
mergeSort(data, first, mid);
System.out.println("testingMerge");
mergeSort(data, mid + 1, last);
System.out.println("testingMerge");
// merge two sorted parts
merge(data, first, last); //merge2(data, first, last);
// intermediate result
}
public static void main(String[] args)
{
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
System.out.println("begin with: \n" + Arrays.toString(array));
System.out.println("------------------");
mergeSort(array, 0, array.length - 1);
System.out.println("------------------");
System.out.println("end with: \n" + Arrays.toString(array));
}
}
Your answer appears to be correct.
We defined a recursive method MergeSort() to divide the input array in the middle and recursively sort each part.
So we expect to call MergeSort log n times. Since each recursive step is one half the length of n.
Since we know that merge sort is O(n log n) could stop here as MergeSort is called log n times, the merge must be called n times. But we can also reason that we must subdivide the n items until each input consists of one element. Clearly we must merge n such one item lists to arrive at a final out consisting of n items.

How to reverse an ArrayList without the reverse method?

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.

Recursive Word Wrap Algorithm

I am working on an algorithm that has three parts. The first is a recursive method that will wrap words to a specific length with the least penalty. The second is an algorithm that is a Dynamic implementation of the recursive method. The last one is a Greedy Algorithm of the problem. I already have the Greedy one coded but I'm struggling on the Recursive solution. I'm not quite sure where exactly I'm running into an issue with my Recursive method but I know it should be something similar to the Knuth-Plass Algorithm. The recursive algorithm is supposed to have a factorial running time, and used more to help with the dynamic solution. If anyone has a link to a Knuth-Plass implementation or can spot something huge in my code, any help would be appreciated.
Recursive Algorithm:
public static ArrayList<String> recursive(ArrayList<String> input, int size) {
if(input.size() <= 1)
return input;
ArrayList<String> temp1 = input;
ArrayList<String> temp2 = input;
for(int i = 0; i < input.size(); i++) {
if(input.size() - 1 >= size)
break;
else {
for(int j = 0; j < input.size(); j++) {
temp1.set(j, temp1.get(j) + " " + temp1.get(j + 1));
temp1.remove(j + 1);
if(totalPenalty(blankChars(temp1, size)) < totalPenalty(blankChars(temp2, size))) {
input = recursive(temp1, size);
} else {
input = recursive(temp2, size);
}
}
}
}
return input;
}
The totalPenalty() and blankChars return the amount of penalty at the end of each line.
EDIT: I'm still not seeing any immediate solutions. Any help would be appreciated.
That looks like Java, and in Java there is no implicit copy-constructor.
ArrayList<String> temp1 = input; <-- this will not create another object with the same content, but instead a reference to the same object.
You need to change line 4 and 5 to:
ArrayList<String> temp1 = new ArrayList<String>(input);
ArrayList<String> temp2 = new ArrayList<String>(input);
I haven't looked for any other mistakes, so try this out and update the question if you have any more problems.
About the Knuth-Pass breaking algorithm; You can find a Python implementation at http://oedipus.sourceforge.net/texlib/. I haven't looked closer at it, but the description seems to be what you are looking for.
I hope the following code runs. Here I have added the cost for the last line as well. Though word processors use greedy algorithms most of the time and they neglect the cost of the last line. Let me know if this is clear to you.
import java.lang.Math;
public int RCS(int[] l , int n , int m , int index) {
// first base condition - if index gets beyond the array 'l' , then return 0;
if (index > n - 1) return 0;
// second base condition - if index is the last word i.e there is only one word left in the
// array to be inserted in the line then return the cost if added in that line.
if (index == n - 1) return (m - l[n - 1]) * (m - l[n - 1]) * (m - l[n - 1]);
// make a global cost variable to be returned
int cost = Integer.MAX_VALUE;
// Here , we try to select words from the array and apply RCS on the rest of the array.
// From index to last element , we iteratvely select first , or first two and so on.
for (int i = index ; i < n ; i++) {
int current_space_sum = 0 ;
// we add the length of the selected word. We have selected words in array from index to i.
for (int k = index ; k <= i ; k++) {
current_space_sum = current_space_sum + l[k] ;
}
// Adding the space between the words choses. If 2 words are chosen , there is one space and so on
current_space_sum = current_space_sum + i - index;
// If the length of the chosen words is greater than the line can accept , no need of looking beyond.
if (current_space_sum > m) break;
// Iteratively find the minimum cost
cost = Math.min(cost , (m - current_space_sum) * (m - current_space_sum) * (m - current_space_sum) + RCS(l , n , m , i + 1));
}
return cost;
}
public static void main(String[] args) {
WordWrap w = new WordWrap();
int[] l = {3, 2 , 2 , 5};
int n = l.length;
int m = 6;
int result = w.RCS(l , n , m , 0);
System.out.println(result);
}

Pseudo code needed if possible?

I was wondering if I could have some pseudo code for working out the following
i need to loop through a 2d array(the method i am working on takes an int). It starts at the position of the value passed in and then goes down until it hits the same value on the left hand side. As its doing this every int in the 2d array is added to a local variable.
Now we are at position (x,x) i guess? Then from here i need to loop across to the right adding all variables to the same previous local var and then return that number
The 2d array for illustration purposed looks something like this for example
1 2 3 4
2 3 4 5
1 2 3 4
3 2 1 4
So if i were to pass in 2 we would start at the number 3 top line i guess, we would loop down until position 3,3 ( 3 + 4 + 3) and then loop to the right until the end (+ 4)
those numbers would be added and returned.
I hope pseudo code is possible and I haven't just given it already myself lol (thus proving i cant actually code it lol :D )
if not any examples you could provide me with that my help me out :D
thanks guys
I think this pseudocode should do what you're looking for:
array[][] := ...
position := ...
sum := 0
//add the contents of the outer array
for i := 0 to array.length do
sum := sum + array[i][position]
//if we're at (pos, pos) then start looping over the inner array
if i = position then
//note we start at pos + 1 so as not to count array[i][position] twice
for j := position + 1 to array[j].length do
sum := sum + array[i][j]
end
break from loop
end
end
Not sure what you are trying to achieve, I assume this is just an assignment.
If you are looping to the right, shouldn't 1 be included if not the 2 as well?
i.e. then loop to the right until the end (+1 + 4)
The answer depends on whether you store the columns or the rows of matrix. Assuming you have a n * n size matrix and you store the rows, so
A = [[1,2,3,4], [2,3,4,5], [1,2,3,4], [3,2,1,4]]
and the starting point is i, you should go from the array no. m = i div n (the integer part of the division, rounding down), and inside the array, the staring element should be the no. p = i mod n (the modulus). And from that point, you can select every array from m to n, and in every array, the pth element, until the most recent element is the same as your original.
In Java-like code:
int n = 4;
int[][] A = new int[n][n];
... // initialize A
int sumValues(int i) {
int original = A[i/n][i%n];
int sum = original;
int p = i % n;
for (m = i/n + 1, m<n, ++m) {
if (A[m][p] != orginal) sum += A[m][p];
else break;
}
return sum;
}
If you are storing the columns, so
A = [[1,2,1,3], [2,3,2,2], [3,4,3,1], [4,5,4,4]]
then m and p are inversed, meaning that from A you should select array no. m = i mod n and inside that array, element no. p = i div n. After this, you stay in your selected array, and just increase p until A[m][p] equals to the originally selected value.
In Java-like code:
int n = 4;
int[][] A = new int[n][n];
... // initialize A
int sumValues(int i) {
int original = A[i%n][i/n];
int sum = original;
int p = i / n;
for (p = i/n +1, p<n, ++p) {
if (A[m][p] != orginal) sum += A[m][p];
else break;
}
return sum;
}
But correct me, if I'm wrong :)

Categories