I'm trying to write an insertion sort, and I pass several test cases, but I fail one. My code is:
static void insertionSort1(int n, int[] arr) {
int copy = arr[n-1];
int i = n - 1;
while (copy < arr[i-1]){
arr[i] = arr[i-1];
for(int k = 0; k < arr.length; k++){
System.out.print(arr[k] + " ");
}
System.out.println();
i--;
}
arr[i] = copy;
for(int m = 0; m < arr.length; m++){
System.out.print(arr[m] + " ");
}
}
where n is the size of the array, and arr is the array. My algo fails this test case in particular:
10
2 3 4 5 6 7 8 9 10 1
I get index out of bounds on that but not on
5
2 4 6 8 3
or others. what's going on?
That is an index out of bound exception of the array because of minus value of the arr. It is not an algorithm issue but a language.
while (i > 0 && copy < arr[i - 1])
Source:
public class InsertionSort {
static void insertionSort1(int n, int[] arr) {
int copy = arr[n - 1];
int i = n - 1;
while (i > 0 && copy < arr[i - 1]) {
arr[i] = arr[i - 1];
for (int k = 0; k < arr.length; k++) {
System.out.print(arr[k] + " ");
}
System.out.println();
i--;
}
arr[i] = copy;
System.out.println("#### RESULT ####");
for (int m = 0; m < arr.length; m++) {
System.out.print(arr[m] + " ");
}
System.out.println("\n#### END ####\n");
}
public static void main(String[] args)
{
//10
//2 3 4 5 6 7 8 9 10 1
int[] arr ={2, 3, 4, 5, 6, 7, 8, 9, 10, 1};
int n = arr.length;
insertionSort1(n, arr);
//5
//2 4 6 8 3
arr= new int[5];
n = arr.length;
arr[0] = 2;
arr[1] = 4;
arr[2] = 6;
arr[3] = 8;
arr[4] = 3;
insertionSort1(n, arr);
}
}
Result:
2 3 4 5 6 7 8 9 10 10
2 3 4 5 6 7 8 9 9 10
2 3 4 5 6 7 8 8 9 10
2 3 4 5 6 7 7 8 9 10
2 3 4 5 6 6 7 8 9 10
2 3 4 5 5 6 7 8 9 10
2 3 4 4 5 6 7 8 9 10
2 3 3 4 5 6 7 8 9 10
2 2 3 4 5 6 7 8 9 10
#### RESULT ####
1 2 3 4 5 6 7 8 9 10
#### END ####
2 4 6 8 8
2 4 6 6 8
2 4 4 6 8
#### RESULT ####
2 3 4 6 8
#### END ####
Have a good day.
First, you should review what an insertion sort is. You should be building a sorted list on one end of the array, expanding it one element at a time by "inserting" the next value in the correct place. It should be much like sorting a hand of cards if you are given them one at a time. You will need a nested loop to do it correctly.
Carefully consider what your program is really doing and see why it fails -- a shorter test case that fails in the same way would be [3, 2, 1]. Or [2, 1], for that matter.
Related
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 2 years ago.
Improve this question
1
2 3
4 5 4
3 2 1 2
3 4 5 4 3
I want to make a triangle like that. I have tried making the triangle and the numbers but the numbers doesn't fit the triangle so the output isn't as expected. Please help.
Example input: n = 5;
1) This is the code to make the triangle.
int k = 1;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (j <= i) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
2) This is the code to make the numbers.
int k = 1;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i % 2 == 0) {
if (k == 5) {
break;
}
System.out.print(k + " ");
k++;
} else if (i % 2 != 0) {
if (k == 1) {
break;
}
System.out.print(k + " ");
k--;
}
}
}
We need to print a number of rows, with each row printed having the same number of values as the row number. If we were printing *'s, it would be easy:
static void printTriangle(int rowCount) {
for (int row = 1; row <= rowCount; row++) {
for (int i = 0; i < row; i++)
System.out.print("* ");
System.out.println();
}
}
printTriangle(5)
*
* *
* * *
* * * *
* * * * *
Instead of printing *'s, we want the values to come from a repeating sequence of 1 2 3 4 5 4 3 2 ....
The sequence is 8 long, so if we take an ever-increasing number a, starting at 0, and calculate remainder when dividing by 8, i.e. b = a % 8, we get a repeating sequence of 0 1 2 3 4 5 6 7 .... If we then calculate distance from 4, using c = Math.abs(4 - b), we get 4 3 2 1 0 1 2 3 .... If we subtract that from 5, i.e. d = 5 - c, we get 1 2 3 4 5 4 3 2 ..., i.e. the desired sequence.
static void printTriangle(int rowCount) {
int a = 0;
for (int row = 1; row <= rowCount; row++) {
for (int i = 0; i < row; i++) {
int b = a % 8;
int c = Math.abs(4 - b);
int d = 5 - c;
System.out.print(d + " ");
a++;
}
System.out.println();
}
}
The code can be reduced to:
static void printTriangle(int rowCount) {
for (int seq = 0, row = 1; row <= rowCount; row++) {
for (int i = 0; i < row; i++, seq++)
System.out.print((5 - Math.abs(4 - seq % 8)) + " ");
System.out.println();
}
}
printTriangle(10)
1
2 3
4 5 4
3 2 1 2
3 4 5 4 3
2 1 2 3 4 5
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
4 3 2 1 2 3 4 5 4 3
For the advanced version, we can make the max value printed be dynamic too:
static void printTriangle(int rowCount, int maxValue) {
String fmt = "%" + String.valueOf(maxValue).length() + "s ";
for (int row = 1, seq = 0; row <= rowCount; row++) {
for (int i = 0; i < row; i++, seq++)
System.out.printf(fmt, (maxValue - Math.abs(maxValue - 1 - seq % (maxValue * 2 - 2))));
System.out.println();
}
}
printTriangle(5, 5)
1
2 3
4 5 4
3 2 1 2
3 4 5 4 3
printTriangle(20, 14)
1
2 3
4 5 6
7 8 9 10
11 12 13 14 13
12 11 10 9 8 7
6 5 4 3 2 1 2
3 4 5 6 7 8 9 10
11 12 13 14 13 12 11 10 9
8 7 6 5 4 3 2 1 2 3
4 5 6 7 8 9 10 11 12 13 14
13 12 11 10 9 8 7 6 5 4 3 2
1 2 3 4 5 6 7 8 9 10 11 12 13
14 13 12 11 10 9 8 7 6 5 4 3 2 1
2 3 4 5 6 7 8 9 10 11 12 13 14 13 12
11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6
7 8 9 10 11 12 13 14 13 12 11 10 9 8 7 6 5
4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 13
12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
9 10 11 12 13 14 13 12 11 10 9 8 7 6 5 4 3 2 1 2
i want devide matrix into four sub-blocks equally by vertically and horizontallty in java (Here, we suppose that m and nare even numbers) .
for example we have matrix:
1 2 3 4 5 6
7 8 9 1 2 8
1 2 3 4 5 6
4 5 6 7 8 9
1 4 7 2 5 8
3 6 9 7 2 5
I want to display the last block that is:
7 8 9
2 5 8
7 2 5
how i can resolve this problem in java.
Iterate over the lower-right part of the matrix. Here is an example for a square matrix. I am sure you will be able to make it more generic for non-square quadrants or to get other quadrants than the lower-right one.
public int[][] getQuadrantOfSquareMatrix(int[][] matrix) {
int newDimension = matrix.length / 2;
int[][] toReturn = new int[newDimension][newDimension];
for (int i = 0; i < newDimension; i++) {
for (int j = 0; j < newDimension; j++) {
toReturn[i][j] = matrix[i + newDimension][j + newDimension];
}
}
return toReturn;
}
I'm trying to split the array into odd and even numbers. Note that sorting numbers in the final result does not matter. I'm compiling the code and the output contains some bug. My code arranges odd numbers correctly while the even numbers are giving me some trouble. Could somebody please help me out with the arrangement of even numbers?
Basically, I arrange odd numbers in the left side of the array and have oddPos = 0 in the beginning; even numbers are in the right side and the positioning starts from the very end of the array evenPos = myArray.length - 1.
public class EvenOddArray {
public static void main(String[] args){
int[] myArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int oddPos = 0;
int evenPos = myArray.length - 1;
for(int i = 0; i < myArray.length; i++){
if(myArray[i] % 2 == 0){
myArray[evenPos] = myArray[i];
evenPos--;
}
else{
myArray[oddPos] = myArray[i];
oddPos++;
}
}
for(int i = 0; i < myArray.length; i++){
System.out.print(myArray[i] + " ");
}
}
}
Output:
1 3 5 7 2 4 6 6 4 2
int current = 0;
int evenPos = myArray.Length - 1;
while (current < evenPos) {
if (myArray[current] % 2 == 0) {
swap(myArray, evenPos, current);
evenPos--;
} else {
current++;
}
}
A squeezed funny version:
for (int curPos=0, evenPos=myArray.length-1; curPos < evenPos;)
if (myArray[curPos] % 2 == 0)
swap(myArray, evenPos--, curPos);
else
curPos++;
More fun version:
for (int curPos=0, evenPos=myArray.length-1; curPos < evenPos;)
swap(myArray, curPos, myArray[curPos]%2==0 ? evenPos-- : curPos++);
explanation:
You don't have to swap values when the number is odd. you only
increase the current counter.
you can't use the for loop counter as an index to the array too. to
not miss the numbers that gets swapped to the counter index not
processed. this is the mistake that other answers didn't cover.
Actually you are editing the same myArray array while reading from it. So what happens is,
You insert 6 into the myArray[7] th position, in the 6th iteration of the loop. So, during the 7th iteration when you read the myArray[7], it is 6. Not 8. Because, you have over written 8 with 6 in the previous iteration.
Therefore, use a separate array to hold the results. Hope you get the point.
You can do something like this,
int[] myArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] resultArray = new int[myArray.length];
int oddPos = 0;
int evenPos = myArray.length - 1;
for(int i = 0; i < myArray.length; i++){
if(myArray[i] % 2 == 0){
resultArray[evenPos] = myArray[i];
evenPos--;
}
else{
resultArray[oddPos] = myArray[i];
oddPos++;
}
}
Lets see what happens with each Iteration of your for loop.
Original: 1 2 3 4 5 6 7 8 9 10
1st Iter: 1 2 3 4 5 6 7 8 9 10
2nd Iter: 1 2 3 4 5 6 7 8 9 2
3rd Iter: 1 3 3 4 5 6 7 8 9 2
4th Iter: 1 3 3 4 5 6 7 8 4 2
5th Iter: 1 3 5 4 5 6 7 8 4 2
6th Iter: 1 3 5 4 5 6 7 6 4 2
7th Iter: 1 3 5 7 5 6 7 6 4 2
8th Iter: 1 3 5 7 5 6 6 6 4 2
9th Iter: 1 3 5 7 5 4 6 6 4 2
10th Iter: 1 3 5 7 2 4 6 6 4 2
As you can see, you are modifying the array "inplace". You are modifying the array without using all the values. For example, look at 9, It gets over written before it is ever accessed. So, your algo is wrong.
Suggestions:
Use a new array to hold the results as in tibzon's answer
Use swapping instead of overwriting. You have to update your algo accordingly. I was going to provide one. But Murenik already provided one.
Here is my optimized version, which uses around half of the swaps compared to the #hasan83 version.
int n = myArray.length;
int oddPos = 0;
int evenPos = n - 1;
while (true) {
while (oddPos < n && myArray[oddPos] % 2 == 1) {
oddPos++;
}
while (evenPos >= 0 && myArray[evenPos] % 2 == 0) {
evenPos--;
}
if (oddPos >= evenPos) break;
swap(myArray, oddPos, evenPos);
}
I need my matrices to look exactly like this.(with numbers lined up under text)
Here are the two matrices, and the result when added:
2 2 7 4 3 4 3 3 5 6 10 7
4 4 8 8 6 8 5 5 10 12 13 13
1 9 3 7 6 8 6 9 7 17 9 16
2 3 2 9 + 4 4 7 1 = 6 7 9 10
2 9 1 1 9 8 2 5 11 17 3 6
6 1 8 4 4 8 2 2 10 9 10 6
The results I am currently getting look like.
Here are the two matrices, and the result when added:
8 5 6 6 3 8 2 3 11 13 8 9
7 7 4 5 4 9 2 1 11 16 6 6
9 4 4 8 5 1 1 1 14 5 5 9
4 2 7 7 + 7 9 1 3 = 11 11 8 10
4 3 5 3 5 6 8 7 9 9 13 10
4 2 2 1 3 9 5 5 7 11 7 6
As you can see the code for the arrays sum is shifted to the right, and I am not quite sure how to fix this.
public static void printResult(int [][]array1, int [][]array2, int[][]sum, char arithmetic)
{
if (arithmetic == '+') {
// Text for two matrices when added
System.out.print("Here are the two matrices, and the result when added:\n");
// For loop to print array1 + array2 = sum with format
for (int i = 0; i < array1.length; i++) {
// For loop to print out array 1 and add string, if to place +
for (int j = 0; j < array1[i].length; j++) {
System.out.printf("%4s", array1[i][j]);
if (i == array1.length / 2 && j == array1[i].length-1) {
System.out.printf("%4s", '+');
}
}
System.out.print("\t");
// For loop to print out array2 and equals string, if to place =
for (int j = 0; j < array1[i].length; j++) {
System.out.printf("%2s", array2[i][j] + " ");
if (i == array1.length / 2 && j == array1[i].length-1) {
System.out.printf("%1s", '=');
}
}
System.out.print(" ");
// For loop to print out sum of array1 + array2
for (int j = 0; j < array1[i].length; j++) {
System.out.printf("%4s", sum[i][j]);
}
System.out.print("\n");
}
}
else if (arithmetic == '-') {
}
else if (arithmetic == '*') {
}
else if (arithmetic == '/') {
}
else if (arithmetic == '%') {
}
}
Also a 3x3 array when printed out looks like.
Here are the two matrices, and the result when added:
2 2 7 3 4 3 5 6 8
4 4 8 + 6 8 5 = 7 9 13
1 9 3 6 8 6 7 7
I think this is meant to insure that numbers, when printed, always take up 2 spaces:
System.out.printf("%2s", array2[i][j] + " ");
But because of the added (technically, concatenated) " ", you get a string that is bigger than the %2s field, so there is no padding of short numbers.
Plus, you have code to decide when to print the + & =, but each should be deciding between printing the symbol and printing a space, to keep everything lined up.
Here is one solution to the Josephus problem (where people are arranged in a circle and every other person is killed until only one remains):
import java.util.ArrayList;
public class test {
public static void main(String[] args) {
ArrayList<Integer> chairArr = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) {
chairArr.add(i);
}
int result = 0;
for (int i = 1; i < chairArr.size() - 1; i = i + 2) {
chairArr.add(chairArr.get(i));
result = i;
}
System.out.print("Result: " + chairArr.get(result));
}
}
But what if, instead of skipping every other person, we increased the number skipped as we went through? That is, if 10 people were arranged in the circle, persons 1, 3, 6, 10, etc. were killed in that order. I think the modification would come in the i = i + 2 in the for loop, but I'm not sure.
I worked it out on paper, and this is the order of elimination, where asterisks denote the number to be removed:
0 *1* 2 3 4 5 6 7 8 9 10
1 2 *3* 4 5 6 7 8 9 10
2 2 4 5 *6* 7 8 9 10
3 2 4 5 7 8 9 *10*
4 2 4 5 7 *8* 9
5 2 4 5 7 *9*
6 2 4 *5* 7
7 *2* 4 7
8 *4* 7
9 7 <-- Result
Thoughts?
Edit: Tried this modification of the for loop:
for (int j = 2; j < chairArr.size() - 1; j++) {
for (int i = 1; i < chairArr.size() - 1; i = i + j) {
chairArr.add(chairArr.get(i));
result = i;
}
}
This won't work because after the initial pass where j = 2, the inner loop will already have narrowed the list down to one candidate so the outer loop never completes.