Switching from Python to Java and decided to code an insertionsort method. I have written this in Python and tried to switch over the code one-to-one, it all seems good to go but it is not functioning correctly. I cut out all the other class methods/data fields to converse space and tried to limit this code only to that which is relevant to this question:
public class test1 {
static final int NOT_FOUND = -1; // A constant
// Attributes (just one)
private double data[];
// Constructor
test1 (double data[]) {
this.data = data.clone();
}
double getItem (int key) {
return data[key];
}
void insertionSort () {
for (int i = 1;i >= data.length;i++){
double currentElement = data[i];
int k = i - 1;
while(k>=0 & data[k] > currentElement){
data[k+1] = data[k];
k -= 1;
data[k + 1] = currentElement;
}
}
}
public static void main(String[] arg){
double testData[] = {1,4,32,5,673,145,68,14,757};
test1 b = new test1 (testData);
b.insertionSort();
//See how array has changed
for (int i = 0; i < 9; i++) {
System.out.print(b.getItem(i) + ", ");
}
}
}
Change
for (int i = 1; i >= data.length; i++)
to
for (int i = 1; i < data.length; i++)
The reason behind it is that you are retrieving an item from the array data for the index of i. The loop did not work because i was initialized to 1 and the condition i >= data.length was returning false because i is actually smaller than the length of the data array in your example, hence the loop did not run.
There are other troubles with this kind of check in the for loop when retrieving an element from an array because if an index for which you are returning the element is >= than the length of the array you will get an IndexOutOfBoundsException.
I am sure this is not what you meant:
for (int i = 1;i >= data.length;i++){
This will be either an infinite(actually up to overflow) or an empty cycle.
I know that is not exactly what are you asking, but if you are learning Java, maybe you could find useful:
In Java you can use Arrays.sort() :
void insertionSort () {
Arrays.sort(data);
}
Related
Got method which takes two dimensional String array as parametr, size of array must be 4x4, next method() check if size is not correct, method() throw new MyArraySizeException(arr), after method() must sum all elements of array, and if in array cell contains not digital value method() must throw MyArrayDataException - with detalization, in which cell contains incorect values.
Method:
private static final int COLUMNS = 4;
private static final int ROWS = 4;
private static int convertString(String[][] arr){
int result = 0;
for (int i = 0; i < arr.length ; i++) {
for (int j = 0; j < arr[i].length ; j++) {
if (arr.length != 4 || arr[i].length != 4){
throw new MyArraySizeException(arr);
}
}
}
for (int i = 0; i < arr.length ; i++) {
for (int j = 0; j < arr[i].length ; j++) {
if (arr[i][j].matches("[0-9]+")) {
result += Integer.parseInt(arr[i][j]);
}else {
throw new MyArrayDataException(arr);
}
}
}
return result;
}
exception: MyArrayDataException(arr):
private String[][]arr;
public MyArrayDataException(String[][]arr){
this.arr = arr;
for (int i = 0; i < arr.length ; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j].matches("[a-zA-Z]+")){
System.out.println("Incorrect values in: " +"[" + i + "]" + "" + "[" + j + "] is " + arr[i][j]);
}
}
}
}
}
Method() work fine exception also work, problem is I don't like sout, and I want change
realization of MyArrayDataException(arr). I want to use super() constructor, instead sout.
To pass incorect cell in super() constructor, how can I achieve it?
Something like this:
I want this exception in another class
//it's not work
private String[][]arr;
int test;
int test1;
public MyArrayDataException(String[][]arr){
super(String.format("Incorrect values in '%d'", arr[test][test1]));
this.arr = arr;
}
}
Yes, printing to sysout in an exception constructor is indeed quite silly. You've got the right instinct.
The easiest way to get what you want is to make a static method which converts the string array into a printable value:
public MyArrayDataException(String[][] arr) {
super(String.format("Incorrect values in '%s'", arrToString(arr));
this.arr = arr;
}
private static String arrToString(String[][] arr) {
// write code here
}
Note that this method more or less already exists: Arrays.deepToString(arr) will do it. However, that prints e.g. [["Hello", "World"], ["Second", "Array"]], if you want a multiline aligned matrix bonanza you would have to use the above trick. If deepToString works for you, then you can just call that and forego writing arrToString yourself.
One remark on your MyArrayDataException:
At the place where you detect that the array content isn't a valid positive number, you already know the indices where this happens. I'd make them (i and j) additional parameters to the exception constructor, so you don't need to re-scan through all the array searching for the error position:
public MyArrayDataException(String[][]arr, int i, int j) {
super(String.format("Incorrect value '%s' at [%d][%d]",
arr[i][j], i, j));
this.arr = arr;
}
By the way, the logic in your re-scan is flawed: what about an element being "abc123"? This is illegal of course, but it doesn't match "[a-zA-Z]+". The check had better been:
if (! arr[i][j].matches("[0-9]+"))
This question already has answers here:
What is a StackOverflowError?
(16 answers)
Closed 3 years ago.
I'm basically trying implement merge sort in Java. For doing so, I've created a class called Array, which has an integer array a[]. The class also has a method called slice(int left, int right) that produces the slice of array and returns the object. Henceforth , there is a sort() method that recursively calls itself and breaks down the array and returns an Array object at the end.
import java.util.*;
class Array
{
int a[];
public Array()
{
a = null;
}
public Array(int x)
{
a = new int[x];
}
public void input()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < a.length; i++)
{
System.out.print("Enter a No. = ");
a[i] = sc.nextInt();
}
}
public void display()
{
for(int i = 0; i < a.length; i++)
System.out.print(a[i] + "\t");
System.out.println();
}
public Array slice(int left, int right)
{
Array ob = new Array(left + right + 1);
for(int i = left; i <= right; i++)
ob.a[i] = this.a[i];
return ob;
}
public static Array merge(Array A, Array B)
{
Array C = new Array(A.a.length + B.a.length);
int i, j, k;
i = j = k = 0;
while(i < A.a.length && j < B.a.length)
{
if(A.a[i] < B.a[j])
C.a[k++] = A.a[i++];
else if(A.a[i] > B.a[j])
C.a[k++] = B.a[j++];
else
{
C.a[k++] = A.a[i++]; j++;
}
}
while(i < A.a.length)
C.a[k++] = A.a[i++];
while(j < B.a.length)
C.a[k++] = B.a[j++];
return C;
}
public Array sort()
{
if(this.a.length == 1)
return this;
else
{
return merge(this.slice(0, (this.a.length - 1) / 2).sort(), this.slice(1 + (this.a.length - 1) / 2, this.a.length - 1).sort());
}
}
public static void main()
{
Array x;
Scanner sc = new Scanner(System.in);
System.out.print("Enter the No. of Elements = ");
Array ob = new Array(sc.nextInt());
ob.input();
System.out.println("\n ORIGINAL ARRAY");
ob.display();
System.out.println("\n SORTED ARRAY");
x = ob.sort();
x.display();
}
}
Suppose if I have an object A, which has an integer array a[], then on calling A.sort() must return an object in which all the array elements will be sorted in ascending order.
Error(s) I Got: java.lang.StackOverflowError: null
Firstly, your slice should be implemented like this. I suspect this is the main problem. The way you did it, the slices aren't getting smaller, so the recursion never bottoms out.
public Array slice(int left, int right)
{
int length = right - left; // this is the proper length
Array ob = new Array(length);
for(int i = 0; i < length; i++)
ob.a[i] = this.a[i + left];
return ob;
}
Secondly, merge should be like this.
public static Array merge(Array A, Array B)
{
Array C = new Array(A.a.length + B.a.length);
int i = 0, j = 0, k = 0;
while(i < A.a.length && j < B.a.length)
{
if(A.a[i] < B.a[j])
C.a[k++] = A.a[i++];
else if(A.a[i] > B.a[j])
C.a[k++] = B.a[j++];
else
{
C.a[k++] = A.a[i++];
C.a[k++] = B.a[j++]; // this preserves duplicates
}
}
while(i < A.a.length)
C.a[k++] = A.a[i++];
while(j < B.a.length)
C.a[k++] = B.a[j++];
return C;
}
Then sort becomes
public Array sort()
{
if(a.length < 2)
return this;
int half = a.length / 2;
Array left = slice(0, half).sort();
Array right = slice(half, a.length).sort();
return merge(left, right);
}
The stack is a region of memory of finite size. It's often not that big. When you call a recursive function, each recursive call is placed on the stack. When the recursion finishes, the calls on the stack are popped off and executed.
The problem is if your array is big, and the recursion goes to deep (many calls), you might run out of space on the stack to put the next recursive call. This is a stack overflow.
I made exactly the same mistake at uni once. :)
To fix your program you can:
increase the stack size (this is a hack, there is still a limit to how many recursive calls you can make, it's just higher now)
decrease the memory use of each call (still kind of a hack, probably not very effective either, unless you're storing large data in a local variable)
implement your merge sort iteratively so that you only deal with small pieces of data at a time, instead of putting it all on the stack first, then dealing with it at the end.
Every recursive algorithm can be implemented with iteration (a loop).
So right now I am trying to code a function that will remove the highest value in an unsorted array.
Currently the code looks like this:
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
}
/*int max = array.get(0);
for (int i = 1; i < array.length; i++) {
if (array.get(i) > max) {
max = array.get(i);
}*/
}
tailIndex = tailIndex - 1;
}
Here I have my attempt at this:
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
The program runs no bother but still deletes the first item in the array instead of the highest number. This code was given my my college lecturer for a different solution but unfortunately it doesn't work here.
Would this solution work with enough altercations? Or is there another solution I should try?
Thanks.
The code snippet in the question can be updated to below code, while keeping the same data structure i.e. queue and this updated code has 3 steps - finding the index of largest element, shifting the elements to overwrite the largest element and finally set the tailIndex to one less i.e. decrease the size of the queue.
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
int largeIndex = 0;
for (int i = 0; i < tailIndex; i++) {
if (((PriorityItem<T>) storage[i]).getPriority() > priority) {
priority = ((PriorityItem<T>) storage[i]).getPriority();
largeIndex = i ;
}
}
for(int i = largeIndex; i < (tailIndex - 1) ; i++)
storage[i] = storage[i + 1];
}
tailIndex = tailIndex - 1;
}
Hope it helps.
Step 1
Find the highest index.
int[] array;
int highIndex = 0;
for (int i = 1; i < highIndex.size(); i++)
if (array[highIndex] < array[highIndex])
highIndex = i;
Step 2
Create new array with new int[array.size() - 1]
Step 3
Move all values of array into new array (except the highest one).
My hint: When its possible, then use a List. It reduces your complexity.
You can find the largest Number and it's index then copy each number to its preceding number. After that, you have two options:
Either add Length - 1 each time you iterate the array.
Or copy the previous array and don't include removed number in it.
Working Code:
import java.util.Arrays;
public class stackLargest
{
public static void main(String[] args)
{
int[] unsortedArray = {1,54,21,63,85,0,14,78,65,21,47,96,54,52};
int largestNumber = unsortedArray[0];
int removeIndex = 0;
// getting the largest number and its index
for(int i =0; i<unsortedArray.length;i++)
{
if(unsortedArray[i] > largestNumber)
{
largestNumber = unsortedArray[i];
removeIndex = i;
}
}
//removing the largest number
for(int i = removeIndex; i < unsortedArray.length -1; i++)
unsortedArray[i] = unsortedArray[i + 1];
// now you have two options either you can iterate one less than the array's size
// as we have deleted one element
// or you can copy the array to a new array and dont have to add " length - 1" when iterating through the array
// I am doing both at once, what you lke you can do
int[] removedArray = new int[unsortedArray.length-1];
for(int i =0; i<unsortedArray.length-1;i++)
{
System.out.printf(unsortedArray[i] + " ");
removedArray[i] = unsortedArray[i];
}
}
}
Note: Use List whenever possible, it will not only reduce complexity, but, comes with a very rich methods that will help you a big deal.
I have this code sample with a method which returns the sum of array values. But instead of the sum, I'm getting 0.
This is my code sample
class Calculation {
int answer;
public int SumOfArrays(int data[], int size) {
answer = 0;
for (int i = data[0]; i < size; i++) {
answer += data[i];
//System.out.println(data[i]);
}
return answer;
}
class Main {
public static void main(String[] args) {
Calculation cal = new Calculation();
int data[]={10,20};
System.out.println(cal.SumOfArrays(data, 2));
}
}
can anyone tell me what;s wrong with my code?
The loop doesn't run at all - the condition data[0] < size is false, so the initial value of answer = 0 is returned.
To make it work, change the statement to (int i = 0; i < size; i++). Also, size might be replaced with data.length.
This is your code with minor corrections. Try it.
class Calculation {
public int SumOfArrays(int data[]) {
int answer = 0; // this is just better
for (int i = 0; i < data.length; i++) {
answer += data[i];
}
return answer;
}
class Main {
public static void main(String[] args) {
Calculation cal = new Calculation();
int data[]={10,20};
System.out.println(cal.SumOfArrays(data));
}
}
The counter i for the for loop is incorrectly initialized. You have initialized it to the value of first element in the array instead of 0. Initialize it to 0 as shown below:
for (int i = 0; i < size; i++) {
answer += data[i];
//System.out.println(data[i]);
}
As you can see from your loop
for(int i = data[0]; i < size; i++)
the variable i is equals to the first element in the data array which means that is greater then the size variable ..so the loop will not begin at all
to fix the problem change your loop to this
for (int i = 0; i < size; i++) {
answer += data[i];
//System.out.println(data[i]);
}
Here is my ArrayList:
[1,2,1,0,3,4]
I'm trying to return this:
[1,2,3,4]
Here is my current attempt:
for (int i = 0; i < myArray.size() - 1; i++) {
if (myArray.get(i) < myArray.get(i + 1)) {
System.out.println("Increasing sequence...");
}
}
However, this is not returning the desired output, any ideas?
You'll have to maintain an index (or value) of the last element that you had printed and store it in some variable. Then, you'll have to use the stored element for every new element and check if is greater than the stored element.
As you have mentioned, the first element has to be anyway printed, no matter what.
Something like this might work:
List<Integer> myArray = Arrays.asList(new Integer[]{1,2,1,0,3,4});
System.out.println(myArray.get(0));
int prevPrint = myArray.get(0);
for (int i = 1; i < myArray.size();i++) {
if (myArray.get(i) > prevPrint) {
System.out.println(myArray.get(i));
prevPrint = myArray.get(i);
}
}
The reason why your program was failing was because you were comparing the adjacent two values only and it was possible that you might have already printed a value which is greater than any of the two adjacent values.
A similar question, but a totally different approach (LIS) exists and can be found here
A slight variant on Parijat's answer to avoid repeating the System.out.println:
for (int j = 0; j < myArray.size();) {
System.out.println(myArray.get(j));
int start = j;
do {
++j;
while (j < myArray.size() && myArray.get(j) <= myArray.get(start));
}
Try this,
public static List<Integer> findIncreasingOrder(int[] nums) {
List<Integer> result = new ArrayList<>();
int MAX = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
int value = nums[i];
if (value >MAX){
System.out.println(value);
MAX = value;
result.add(value);
}
}
return result;
}