I am trying to figure out a seemingly simple problem with this program. The goal is to rearrange the array in ascending order using a recursive method. I wrote the main method as well as the recursive method as shown below. The issue is that for some reason, I can't stop the method, despite having a condition to prevent it from continuing.
import java.util.Arrays;
public static void main(String[] args){
int[] a = {9,8,7,6,1,2,5,4};
recursiveSelectionSort(a, 0);
System.out.println(Arrays.toString(a));
}
public static void recursiveSelectionSort(int[] a, int start){
int minpos, temp;
//this condition is meant to stop the method
if (start==(a.length-1))
return;
minpos = start;
for (int i = start; i < a.length; i++) {
if (a[i] < a[minpos])
minpos = i;
}
temp = a[start];
a[start] = a[minpos];
a[minpos] = temp;
//this line causes the stack overflow error
recursiveSelectionSort(a, start++);
}
When I delete the recursiveSelectionSort(a,start++) statement, I get an output of {1,8,7,6,9,2,5,4}, which is correct. However, I want this process to continue so they will all eventually be sorted. When I keep the recursion statement, I get the error.
Don't use
recursiveSelectionSort(a, start++);
Doing it this way causes you to first pass start to recursiveSelectionSort and then increment start. start will remain the same in every recursive call.
Use
recursiveSelectionSort(a, start+1);
or if you really like to increment start (even if there is no reason to do so), use
recursiveSelectionSort(a, ++start);
to increment first.
Related
I tried to solve
https://leetcode.com/problems/maximum-subarray/submissions/
using Java
I usually try these things using Eclipse before submit on online.
Here I attached codes in Eclipse
public class PrintAnnotationExample{
public static void main(String[] args) {
int index = 0;
int max =0;
int temp = 0;
int[] test = new int[] {-2,1,-3,4,-1,2,1,-5,4};
while(index<test.length) {
temp+= test[index];
if(temp <0) {
while(index<test.length-1 && test[index]<0) {
++index;
}
temp = 0;
}
max = (max >= temp ) ? max : temp;
++index;
}
///
System.out.println(max);
}
}
It worked! the expected output is 6, and it makes 6 either.
However,
In Leetcode submission page, It doesn't work
class Solution {
public int index = 0;
public int max =0;
public int temp = 0;
public int maxSubArray(int[] nums) {
while(index<nums.length) {//아직 배열범위 안에 있을경우
temp+= nums[index];
if(temp <0) {
while(index<nums.length-1 && nums[index]<0) {
++index;
}
temp = 0;
}
max = (max >= temp ) ? max : temp;
++index;
}
return max;
}
}
It shows me 1, not 6...
weird, may be I got something wrong in my head about Java semantics..
The codes you are executing in Eclipse and Leetcode are clearly different, so you need to focus on the differences between them ... rather than concluding (incorrectly) that there are compiler / language differences.
One of the differences is that in the Eclipse version index, max and temp are local variables. In the Leetcode version they are instance variables that don't get initialized each time your method is called. If LeetCode instantiates your class once and calls the method multiple times, this will lead to incorrect behavior.
may be I got something wrong in my head about Java semantics.
Maybe. Or it could just be a mistake.
But either way, it is inadvisable to use instance variables to hold the state of a method call. Use local variables for instead:
Using local variables for this avoids the mistake you made; i.e. forgetting to reinitialize.
Using instance variables for this makes the method non-reentrant; i.e. concurrent or overlapping calls to the method will interfere with each other. This will be problematic if the method is called recursively, or if it is called from multiple threads.
I was trying to implement the coin change problem using recursion. I have written the following code and am facing a problem with the static class variable. 'answer' is a class variable and i am trying to add the return value to it in the loop. This works fine within the while loop but after the while loop ends the answer is reset to 0;
while (i * currentCoin <= sum) {
System.out.println("inside while; answer is " + answer);
answer = answer
+ findCombinations(
sum - i * currentCoin,
new ArrayList<Integer>(denominations.subList(1,
denominations.size())));
i++;
}
Below is all the code that I have written. You can copy and run it to check.
import java.util.ArrayList;
import java.util.Collections;
public class CoinChangeHashMap {
static int answer = 0;
public static void main(String[] args) {
int[] array = new int[] { 7, 3, 2 };
ArrayList<Integer> input = new ArrayList<Integer>();
getList(array, input);
findCombinations(12, input);
System.out.println(answer);
}
private static void getList(int[] array, ArrayList<Integer> input) {
for (int i : array) {
input.add(i);
}
}
public static int findCombinations(int sum, ArrayList<Integer> denominations) {
if (denominations.size() == 1) {
if (sum % denominations.get(0) == 0) {
return 1;
}
return 0;
}
int i = 0;
int currentCoin = denominations.get(0);
while (i * currentCoin <= sum) {
System.out.println("inside while; answer is " + answer);
answer = answer
+ findCombinations(
sum - i * currentCoin,
new ArrayList<Integer>(denominations.subList(1,
denominations.size())));
i++;
}
return 0;
}}
**The output that I get is 0. but the expected output is 4. While debugging the output that I got is **
inside while; answer is 0
inside while; answer is 0
inside while; answer is 1
inside while; answer is 1
inside while; answer is 2
inside while; answer is 2
inside while; answer is 0
inside while; answer is 0
inside while; answer is 0
0
Any Help is appreciated.
The problem is related to your odd code structure, in which you convey the outcome of your recursive call sometimes by modifying static variable answer, and sometimes via the method's return value.
If you analyzed the problem more closely, you would discover that it is not upon exit from the loop that the partial results are lost, but rather some time after return from the method. Therefore, consider carefully the way you update the answer:
answer = answer + findCombinations( /* ... */ );
At the top-most level of your recursion, answer is initially 0. When Java evaluates the above expression, it evaluates first the left operand and then the right operand, then it adds them. That is, it evaluates answer, getting the result 0, before it performs the recursive call. The value of answer may be updated in the course of the recursive call, but those changes come too late. Only the bottom-most level of the recursion ever returns a value different from zero, so if the recursive call itself recurses at least one level deeper then it will return zero. In that case, the sum is computed as 0 + 0, and assigned to answer, clobbering any update the method performed.
You could resolve the problem by swapping the order of the operands in your sum, but it would be better, and not much harder, to get rid of the static variable altogether. Use a local variable within the method to accumulate results, and in all cases convey the total back to the caller via the method's return value.
In this class, I defined a constructor that initializes an array and fill it with Point2D.Double. I want to define a toString method that outputs the Point2D.Double in the array. So inside the toString method, I make a for loop that returns every Point2D.Double in the array. The problem is, I don't know why Eclipse tells me that the update in the for statement is dead code.
import java.awt.geom.Point2D;
public class SimplePolygon {
public int n; // number of vertices of the polygon
public Point2D.Double[] vertices; // vertices[0..n-1] around the polygon
// boundary
public SimplePolygon(int size) {
n = size;
vertices = new Point2D.Double[n]; // creates array with n size. Elements are doubles.
for(int i = 0; i < n; i++)
{
Point2D.Double point = new Point2D.Double(Math.random() * 6, Math.random() * 6);
vertices[i] = point;
}
}
public String toString() {
for(int i = 0 ; i < n ; i++)
{
return "" + vertices[i];
}
return "";
}
I too was puzzled by this. (And the other answers!) So I cut-and-pasted it into Eclipse to see what it actually says.
And what Eclipse is actually says is that i++ is unreachable in this line.
for(int i = 0 ; i < n ; i++)
And in fact, that is correct! If you ever enter the loop body, the body will unconditionally return. Hence the i++ can never be executed.
Note also that this is a warning not an error. This code is not invalid according to the JLS rules about unreachability.
You are right to be puzzled by the other explanations. The final return statement is reachable. Consider the case where the class is instantiated with a negative value for n (or size). In that case, the for loop body will never be executed, and control will go to the final return.
However, their suggestions as to how to fix the problem are correct. You should not have a return in the loop body.
The problem is because of the return statement in the for loop. Remember, whenever you use return, you immediately end the method and stop running any code. That means that your toString method will loop exactly only once, returning only vertices[0]. The second return below the loop never has a chance to execute, so is considered dead code.
This is actually incorrect! See Stephan's answer for a better/accurate explanation of what's going on.
Regardless, you still need to fix your code. Instead of returning something inside the loop, you probably want to combine the values and return them all at once at the very end. An easy way to do this might be:
public String toString() {
String output = "";
for(int i = 0 ; i < n ; i++)
{
output += vertices[i] + " ";
}
return output;
}
Now, instead of returning immediately, we're accumulating values in the loop and returning at the very end.
(Note that the code here isn't very efficient -- you'd probably want to use something like String.join or StringBuilder instead, but if you're a beginner, this works for now)
Hi I'm currently working on getting my Quick Sort program working but cannot figure out where I'm going wrong, i have spent hours trying to find out why it's not working but no luck,when I run my code nothing happens. I have four other sorting algorithms working in a similar fashion which is what's confusing me the most.
Below is my code for the Quick Sort program
import java.io.IOException;
public class QuickSort {
public static int[] compute(int[] array, int lower, int higher )throws IOException{
if(lower<higher){
int pivot=split(array,lower,higher);
if(pivot>1)
compute(array, lower, pivot-1);
if(pivot+1<higher)
compute(array, pivot+1, higher);
}
return array;
}
public static int split(int[] array, int lower, int higher){
while(true){
int pivot=array[lower];
while(array[lower]<pivot)
lower++;
while(array[higher]>pivot)
higher--;
if(lower<higher){
int temp=array[higher];
array[higher]=array[lower];
array[lower]=temp;
}
else{
return higher;
}
}
}
}
Here is my Test class that's running the code:
import java.io.IOException;
import java.util.Scanner;
public class Test extends ReadIn{
static BubbleSort bubble=new BubbleSort();
public static void main(String[] args) throws IOException{
System.out.println("Enter 1 for BubbleSort\nEnter 2 for Insertion Sort\nEnter 3 for Selection Sort\nEnter 4 for Merge Sort\nEnter 5 for QuickSort\nPlease input sorting algorithm to use for sorting:");
Scanner input=new Scanner(System.in);
int number=input.nextInt();
final long startTime = System.currentTimeMillis();
int[] Array=read();
if(number==1){
Array=BubbleSort.compute(Array);
for(int i=0;i<BubbleSort.compute(Array).length;i++){
System.out.println(Array[i]);
}
}
if(number==2){
Array=InsertionSort.compute(Array);
for(int i=0;i<InsertionSort.compute(Array).length;i++){
System.out.println(Array[i]);
}
}
if(number==3){
Array=SelectionSort.compute(Array);
for(int i=0;i<SelectionSort.compute(Array).length;i++){
System.out.println(Array[i]);
}
}
if(number==4){
Array=MergeSort.compute(Array);
for(int i=0;i<MergeSort.compute(Array).length;i++){
System.out.println(Array[i]);
}
}
if(number==5){
Array=QuickSort.compute(Array,0,Array.length-1);
for(int i=0;i<QuickSort.compute(Array,0,Array.length-1).length;i++){
System.out.print(Array[i]);
}
}
final long endTime = System.currentTimeMillis();
System.out.println("Total execution time: " + (endTime - startTime) );
}
}
When I press 5 nothing happens, the rest work perfectly.
I cant figure out whatsoever what the problem is so any help or input would be appreciated.
Your Quicksort code loops forever if there's duplicate numbers in the input, since the numbers can just keep swapping with each other. As mentioned in the comment, you should manually try out your code with a sample array, or check the code running with a debugger. See the example array below.
You might want to switch the while(true) loop to a recursive call to make the code a little clearer. Also, you can practice going through the different steps of Quicksort on my Quicksort online tutorial.
Say the array = {3,1,2,3} and the pivot is 3. Nothing will change and the code will loop forever.
while(true){
int pivot=array[lower];
while(array[lower]<pivot)
lower++;
while(array[higher]>pivot)
higher--;
if(lower<higher){ //this will just swap the 3's with each other.
int temp=array[higher];
array[higher]=array[lower];
array[lower]=temp;
}
else{
return higher;
}
}
While it looks like your program is doing nothing, it probably just loops infinitely inside this loop:
while(true){
int pivot=array[lower];
while(array[lower]<pivot)
lower++;
while(array[higher]>pivot)
higher--;
if(lower<higher){
int temp=array[higher];
array[higher]=array[lower];
array[lower]=temp;
// I recommend adding this line for you to see what's going on
System.out.println("lower="+lower+", higher="+higher+", pivot="+pivot);
}
else{
return higher;
}
}
for example, if you have equal values in your Array, say value 65 is there twice, that loop will run forever...
int[] Array={1,41,2,90,32,65,12,43,78,65,46,67};
Also, in your loop above I added and extra printout of higher, lower, and pivot values - it will help you see what is happening inside that devious loop.
In general writing a while(true) loop is not a good practice, because it's so easy to hang your system on it.
I am a newbie Computer Science high school student and I have trouble with a small snippet of code. Basically, my code should perform a basic CLI search in an array of integers. However, what happens is I get what appears to be an infinite loop (BlueJ, the compiler I'm using, gets stuck and I have to reset the machine). I have set break points but I still don't quite get the problem...(I don't even understand most of the things that it tells me)
Here's the offending code (assume that "ArrayUtil" works, because it does):
import java.util.Scanner;
public class intSearch
{
public static void main(String[] args)
{
search();
}
public static void search()
{
int[] randomArray = ArrayUtil.randomIntArray(20, 100);
Scanner searchInput = new Scanner(System.in);
int searchInt = searchInput.nextInt();
if (findNumber(randomArray, searchInt) == -1)
{
System.out.println("Error");
}else System.out.println("Searched Number: " + findNumber(randomArray, searchInt));
}
private static int findNumber(int[] searchedArray, int searchTerm)
{
for (int i = 0; searchedArray[i] == searchTerm && i < searchedArray.length; i++)
{
return i;
}
return -1;
}
}
This has been bugging me for some time now...please help me identify the problem!
I don't know about the infinite loop but the following code is not going to work as you intended. The i++ can never be reached so i will always have the value 0.
for (int i = 0; searchedArray[i] == searchTerm && i < searchedArray.length; i++)
{
return i;
}
return -1;
You probably mean this:
for (int i = 0; i < searchedArray.length; i++)
{
if (searchedArray[i] == searchTerm)
{
return i;
}
}
return -1;
I don't know what is the class ArrayUtil (I can not import is using my Netbeans). When I try to change that line with the line int[] randomArray = {1 , 2, 3, 5, 7, 10, 1 , 5}; It works perfectly.
And you should change the loop condition. I will not tell you why but try with my array and you will see the bug soon. After you see it, you can fix it:)
There are 4 basic issues here.
1. Putting searchedArray[i] == searchTerm before i < searchedArray.length can result in an out-of-bounds exception. You must always prevent that kind of code.
2. Your intention seems to be the opposite of your code. Your method name implies finding a search term. But, your code implies that you want to continue your loop scan until the search term is not found, although your loop won't do that either. Think of "for (; this ;) { that } " as "while this do that".
3. Place a break point at the beginning of "search". Then, with a small array, step through the code line by line with the debugger and watch the variables. They don't lie. They will tell you exactly what's happening.
4. Please use a standard IDE and compiler, such as Eclipse and Sun's JDK 6 or 7. Eclipse with JDK 7 is a serious combination that doesn't exhibit a strange "infinite loop" as you describe above.