Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I want to sort a 2d int array based on the 2nd element and this is what I came up with. But it doesnt seem to work. I understand there is a Arrays.sort(array, Comparator) which I can use, but I wanted to write my own sorting algorithm for the fun of it. Could anyone help me out please ?
ip = [[5,10],[2,5],[4,7],[3,9]]
Expected op = [[5,10],[3,9],[4,7],[2,5]]
void mergeSort(int[][] boxTypes){
int mid = boxTypes.length / 2;
int[][] left = new int[mid][2];
int[][] right = new int[boxTypes.length - mid][2];
for(int i = 0; i < mid; i++) left[i] = boxTypes[i];
for(int i = mid; i < boxTypes.length; i++) right[i - mid] = boxTypes[i];
mergeSort(left);
mergeSort(right);
merge(left, right, boxTypes);
}
void merge(int[][] left, int[][] right, int[][] boxTypes){
int i = 0; int j = 0; int k = 0;
while(i < left.length && j < right.length){
if(left[i][1] < right[j][1]){
boxTypes[k][0] = left[i][0];
boxTypes[k][1] = left[i++][1];
} else {
boxTypes[k][0] = right[j][0];
boxTypes[k][1] = right[j++][1];
}
k++;
}
while(i < left.length) boxTypes[k++] = left[i++];
while(j < right.length) boxTypes[k++] = right[j++];
}
You never stop the recursion:
in the first step you split boxTypes into two arrays of length 2.
in the second step you split the first array of length 2 into two arrays of length 1.
in the third step you split the first array of length 1 into an array of length 0 and one of length 1.
in the fourth (and every succeeding step) you try to split the array of length 0 into two arrays of length zero.
You need to stop the recursion as soon as the length of boxTypes is 1 or less (since an array of length 0 or 1 is trivially sorted):
void mergeSort(int[][] boxTypes){
if (boxTypes.length <= 1) return;
int mid = boxTypes.length / 2;
int[][] left = new int[mid][2];
int[][] right = new int[boxTypes.length - mid][2];
for(int i = 0; i < mid; i++) left[i] = boxTypes[i];
for(int i = mid; i < boxTypes.length; i++) right[i - mid] = boxTypes[i];
mergeSort(left);
mergeSort(right);
merge(left, right, boxTypes);
}
Related
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];
}
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I was trying to solve a problem in a coding trainer. But, I just could not figure this problem for the life of me.
Here is the problem:
You are given an m x n 2D image matrix where each integer represents a pixel. Flip it in-place along its horizontal axis.
Example:
Input image :
1 1
0 0
Modified to :
0 0
1 1
I tried swapping rows as I traversed 2d array down the row for test case:
1,2,3
4,5,6
7,8,9
But, I end up getting
4,5,6
7,8,9
1,2,3
instead of
{{7,8,9},
{4,5,6},
{1,2,3}}
Here is the answer code.
public static void flipHorizontalAxis(int[][] matrix) {
int r = matrix.length - 1, c = matrix[0].length - 1;
int temp = 0;
for(int i = 0; i <= r/2; i++){
for(int j = 0; j <= c; j++){
temp = matrix[i][j];
matrix[i][j] = matrix[r-i][j];
matrix[r-i][j] = temp;
}
}
}
I still do not understand the answer code. Specifically, why the outer loop has "i <= r/2" and the swap has "matrix[r-i]" in the index. Why r/2 and r-i? I really do not understand why and I am totally stuck.
Can someone explain those lines so I can understand the code?
Here is the expected output for test cases:
1
{{1}}
1,0,0
0,0,1
{{0,0,1},{1,0,0}}
1,0
{{1,0}}
1,2,3
4,5,6
7,8,9
{{7,8,9},{4,5,6},{1,2,3}}
1,0,1
1,0,1
{{1,0,1},{1,0,1}}
Focusing on only the double loop:
for (int i=0; i <= r/2; i++){
for (int j=0; j <= c; j++){
temp = matrix[i][j];
matrix[i][j] = matrix[r-i][j];
matrix[r-i][j] = temp;
}
}
The outer loop in i only ranges up to (and including) one half the height of the matrix because we want to swap each array with its "mirror" image on the other side of the median row. That is, for a 3x3 matrix we want to do the following:
1,2,3 i=0
4,5,6
7,8,9 r-i=matrix.length-1 = 3-1 = 2
(swap these rows, i=i+1)
7,8,9
4,5,6 i=1, r-i=1
1,2,3
(swap the median row with itself, nothing changes)
If we were to allow the outer loop to run the full height of the input matrix, then after the median row we would actually undo the swap already done, and would just end up the original input matrix.
The number of row swaps you need to do is matrix.length/2 - 1. You could have written:
for (int i = 0; i < matrix.length/2; i++)
instead of:
for(int i = 0; i <= r/2; i++)
for matrices with an odd number of rows, matrix.length/2 and r/2 are equal, which means that in the second form, because of the <=, you will swap the middle row with itself, which is useless, so I prefer the first form.
Now the index r-i will go downwards from the index of the last row (r = matrix.length-1). It's the index of the row that must be swapped with the one at index i.
Note that the the rows themselves are array, and it would be more efficient to swap the whole rows instead of each individual element, so here is a better solution:
public static void flipHorizontalAxis(int[][] matrix) {
int r = matrix.length-1;
for (int i = 0; i < matrix.length/2; i++) {
int[] temp = matrix[i];
matrix[i] = matrix[r - i];
matrix[r - i] = temp;
}
}
Or:
public static void flipHorizontalAxis(int[][] matrix) {
int r = matrix.length;
for (int i = 0; i < matrix.length/2; i++) {
--r;
int[] temp = matrix[i];
matrix[i] = matrix[r];
matrix[r] = temp;
}
}
This question already has answers here:
given a set of n integers, return all subsets of k elements that sum to 0
(3 answers)
Closed 6 years ago.
You have an array which has a set of positive and negative numbers, print all the subset sum which is equal to 0.
I can think of approach where i can cam make all powersets of givcen array and check if their sum is 0. BUt that does not llok like optimized solution to
me.
After reading looks a bit similar problem on net , looks like it can be solved with dynamic programming like below program to find if there is combination exist
to make sum 11 just an example ?
public boolean subsetSum(int input[], int total) {
boolean T[][] = new boolean[input.length + 1][total + 1];
for (int i = 0; i <= input.length; i++) {
T[i][0] = true;
}
for (int i = 1; i <= input.length; i++) {
for (int j = 1; j <= total; j++) {
if (j - input[i - 1] >= 0) {
T[i][j] = T[i - 1][j] || T[i - 1][j - input[i - 1]];
} else {
T[i][j] = T[i-1][j];
}
}
}
return T[input.length][total];
}
public static void main(String args[]) {
TestDynamic ss = new TestDynamic();
int arr1[] = {2, 3, 7, 8};
System.out.print(ss.subsetSum(arr1, 11));
}
But i am not sure how to extend above programe to
1) Include negative number
2) find combination of elements whick makes sum as zero( Above program just finds whether its possible to make given sum but does not
find which set of numbers makes it zero)
Here is a full implementation in Javascript. You can run it with node.js.
function target_sum(a, k, x)
{
if (k == a.length) return [];
if (a[k] == x) {
return [[a[k]]];
} else {
var s = target_sum(a, k + 1, x); // not using a[k]
var t = target_sum(a, k + 1, x - a[k]); // using a[k]
for (var i = 0; i < t.length; ++i) {
t[i].unshift(a[k]); // a[k] is part of the solution
s.push(t[i]); // merge t[] into s[]
}
return s;
}
}
var s = target_sum([1,4,5,2,7,8,-3,-5,-6,9,3,-7,-1,5,6], 0, 0);
for (var i = 0; i < s.length; ++i)
console.log(s[i].join(","));
Note that this is an exponential algorithm. Don't use it on large arrays.
Erwin Rooijakkers also pointed to the right direction. In particular, this post gives another algorithm. I could be wrong about the following – I believe that algorithm trades speed for space. It avoids staging arrays into the call stack, but it has to do more recursions to achieve that.
EDIT: about the algorithm you mentioned. It is not exponential, but it only works for positive numbers if I am right. Its time complexity is also proportional to the target sum, which may not be ideal depending on input.
This question already has answers here:
Closed 10 years ago.
I need to reverse an array for example move what ever is in spot 5 to 0, 4 to1, 3 to 2.
int size, length;
System.out.print("how big of a list do you have: ");
size=reader.nextInt();
length=size-1;
int [] array = new int [size];
for (int count=0; count < array.length; count ++){
System.out.println("enter a number: ");
array [count] = reader.nextInt();
}
for (int count=length; count > 0; count --)
array [(length-count)];
}
}
I am doing this in eclipse and I keep getting an error in the last line saying that I am not using an operator/expression : array [(length-count)]; but I dont know why the minus sign is not working? or if my program will work in general it did not get past the build part.
int temp = 0;
for (int i = 0; i < array.length / 2; i++)
{
int temp = array[i];
array[i] = array[array.length - i--];
array[array.length - i--] = temp;
}
temp is used so that numbers don't overwrite each other. Think of it like getting food from a fridge. The milk is behind the water, and you want some milk. In order to get the milk, you take the water and put it in your hand (temp would be the hand). You then put the milk where the water was and the water where the milk was. Without the "hand", you would have lost your water (fallen on the floor, or in the case of temp, lost in memory) and only be left with milk.
Array[(length-count)] doesn't work because it's a value, it's the same as writing
0;
It is not a call to a procedure or an operation, so it is an error.
Try this:
int temp = 0 ;
for(int start=0, end = numbers.length -1 ; start < end; start++, end--){
//swap numbers
temp = array[start];
array[start] = array[end];
array[end] = temp;
}
Is this code correct for perfect shuffle algorithm ? I'm always trying to generate a number from 0 to n and swapping the number with the last element in the array thereby reducing the range of n. However when the n=0, I get an exception. How do I deal with this case ?
int [] array ={1,2,3,4,5};
Random random = new Random();
int n=array.length;
while(n--!=0)
{
int number = random.nextInt(n);
int temp = array[n];
array[n] = array[number];
array[number] = temp;
}
EDIT: if I change it to --n >0 then it works correctly but am I implementing the shuffling algorithm correctly in that case because I never do anything for n=0 ?
In your code segment
while(n--!=0)
if n is 1, it will become 0 and `random.nextInt(0)` will return an error.
Refer this link
I don't think nextInt works if you pass an argument of 0.
The best way to shuffle is by using the Fisher Yates algorithm. It's fast, works in-place, and is unbiased:
int [] array = {1,2,3,4,5};
Shuffle(array, new Random());
// Fisher Yates shuffle - see http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
void Shuffle(int[] array, Random RNG)
{
for (int i = array.length - 1; i >= 1; i -= 1)
{
// get integer in range of j >= 0 && j < i + 1
int j = RNG.nextInt(i + 1);
//assert(j >= 0 && j <= i);
if (i != j)
{
// only swap if i and j are different
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}