java print list of items using recursion seems inefficient - java

I am doing a pretty basic assignment. "Use recursion to print the values of a list" and I came up with the code below, but as it passes the list EVERY time it calls itself I wondered if there is a better way. Any advice please?
public class RecurList {
public static void main(String[] args) {
int[] list = {8,7,9,10,56};
int ix = list.length;
int sumNow = ShowNext(ix, 0, list); // initial call -> sum is 0
System.out.println("Recursion total is " + sumNow);
}
public static int ShowNext(int inx, int sum, int[] lst) {
if (inx == 0) return sum;
int item = lst[inx - 1];
sum += item;
System.out.println("inx:" + inx + " item:" + item + " sum:" + sum);
return ShowNext(inx - 1, sum, lst);
}
}

Please read and follow Java Naming Conventions. Start your method names with a lowercase letter.
"Use recursion to print the values of a list"
You failed that assignment since you're using an array instead of a list.
it passes the list EVERY time it calls itself I wondered if there is a better way.
There are two solutions to this problem.
The more intentional approach is what #Prune suggested: shorten the list (which is an array in your case) by one element. The utility class Arrays has methods to do this.
The lesser "recursive" style is to make the array a class member and remove it from the methods parameter list:
public class RecurList {
static int[] list;
public static void main(String[] args) {
list = {8,7,9,10,56};
int ix = list.length;
int sumNow = ShowNext(ix, 0); // initial call -> sum is 0
System.out.println("Recursion total is " + sumNow);
}
public static int ShowNext(int inx, int sum) {
if (inx == 0) return sum;
int item = lst[inx - 1];
sum += item;
System.out.println("inx:" + inx + " item:" + item + " sum:" + sum);
return ShowNext(inx - 1, sum);
}
}

Related

Making a recursive method to print a text in java

I have to make a program which works like this. first it gets a number from input and then it gets (number) * strings.
for example:
2
a b
or
3
x1 x2 x3
then in the output it prints something like this:
Math.max(a, b)
or
Math.max(x1, Math.max(x2, x3))
I want to make Math.max method syntax with this code. I hope you understood!
Another Sample Input & output:
Input =
4
a b c d
Output =
Math.max(a, Math.max(b, Math.max(c, d)))
can someone help me?
The code I've wrote for it, can you suggest me some changes to make it better?
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
String[] r = new String[n];
for (int i = 0; i < n; i++) {
r[i] = input.next();
}
printmax(r);
}
public static int i = 0 , j = 0;
public static boolean last = false;
public static void printmax(String [] r){
if (last == true) {
System.out.print(r[r.length - 1]);
while (j < r.length - 1){ System.out.print(")");
j++;
}
}
if (r.length == 2) System.out.print("Math.max(" +r[0] + ", " + r[1] + ")");
if (r.length > 2) {
while (i < r.length -1) {
if (i == r.length -2) last = true;
System.out.print("Math.max(" + r[i] + ", ");
i++;
printmax(r);
}
}
}
}
You can use the following code to achieve the above, here m calling maxElement() function recursively to achieve somthing like this Math.max(a, Math.max(b, Math.max(c, d)))
public static void main(String args[]){
int length = 2; //here read the input from scanner
String[] array = {"a", "b"}; //here read this input from scanner
String max = maxElement(array,0,length);
System.out.println(max);
}
public static String maxElement(String[] start, int index, int length) {
if (index<length-1) {
return "Math.max(" + start[index] + ", " + maxElement(start, index+1, length)+ ")";
} else {
return start[length-1];
}
}
Output:
Math.max(a, b)
You need to do something like this.
First you define a function maxElement which takes your variable array as a parameter.
public static maxElement(String[] variables) {
return maxElementBis(variables,0);
}
Then you call a second function : maxElementBis which takes an additional argument which represents the index of the variable we are processing.
public static String maxElementBis(String[] variables, int index) {
if (variables.length < 2)
return "not enought variables";
if (variables.length - index == 2)
return "Math.max("+ variables[index]+","+variables[index + 1]+")";
return "Math.max("+ variables[index]+","+maxElementBis(variables,index + 1)+")";
}
If the array contains less than two variables you cannot do what you want.
If you only have two variables left, this is your stop condition and you can directly return Math.max(v1,v2).
Otherwise you recursively call your function maxElementBis.

Getting concurrent modification exception on multi threaded merge

Basically I have this code that is using multiple threads to execute a merge sort algorithm I hope to scale this up to N given threads but currently I'm just trying to get four to work. Basically I create four different threads and pass each of them a subarray of the whole. After they've executed I have 4 different sorted sub-arrays that I then need to merge. Because I'm not really sure how to close threads and clear those resources entirely I am trying to reuse two of those threads to absorb a given array into their internal arrays and then re-run the thread with a boolean which tells the thread to merge the two halves rather than sort everything again. This seems to work the first time when I try with merger 0, and merger 1, but then when I try to do the same thing with 2 and three I get a concurrent modification exception. Now I'm not really sure what I'm doing wrong and if anyone has suggestions on how I could improve this code or reduce the number of array creations and copies that would be greatly appreciated.
import java.util.ArrayList;
import java.util.List;
public class RecursiveSimples {
public static void main(String[] args) throws InterruptedException {
List<Comparable> nums = new ArrayList<Comparable>();
nums.add(7); nums.add(4);
nums.add(8); nums.add(6);
nums.add(1); nums.add(3);
nums.add(4); nums.add(7);
nums.add(2); nums.add(1);
nums.add(5); nums.add(9);
nums.add(8); nums.add(3);
nums.add(2); nums.add(2);
System.out.println(Runtime.getRuntime().availableProcessors());
int r = nums.size() % 4;
int num = nums.size() / 4;
List<Merger> mergers = new ArrayList<Merger>();
mergers.add(new Merger(nums.subList(0, num)));
mergers.add(new Merger(nums.subList(num, num*2)));
mergers.add(new Merger(nums.subList(num*2, num*3)));
mergers.add(new Merger(nums.subList(num*3, (num*4) +r)));
mergers.get(0).start(); mergers.get(1).start();
mergers.get(2).start(); mergers.get(3).start();
mergers.get(0).join(); mergers.get(1).join();
mergers.get(2).join(); mergers.get(3).join();
System.out.println(mergers.get(0).getNums());
System.out.println(mergers.get(1).getNums());
System.out.println(mergers.get(2).getNums());
System.out.println(mergers.get(3).getNums());
mergers.get(0).absorbList(mergers.get(1).getNums());
mergers.get(0).setMerger(true);
mergers.get(0).run();
System.out.println(mergers.get(0).getNums());
mergers.get(2).absorbList(mergers.get(3).getNums());
mergers.get(2).setMerger(true);
mergers.get(2).run();
System.out.println(mergers.get(1).getNums());
System.out.println(mergers.get(3).getNums());
int maxThreads = nums.size() / 2;
}
}
class Merger extends Thread {
private List<Comparable> nums;
private boolean merge = false;
public List<Comparable> getNums() {
return nums;
}
public void setMerger(boolean bool) {
merge = bool;
}
public void absorbList(List<Comparable> list) {
nums.addAll(list);
}
Merger(List<Comparable> arr) {
nums = arr;
}
public void run() {
if(merge == false) {
mergeSort(nums, 0, nums.size() -1);
}else {
merge(nums, 0, (nums.size() -1)/2, nums.size() -1);
}
}
public static void swap(List<Comparable> nums, int index1, int index2)
{
Comparable temp;
temp = nums.get(index1);
nums.set(index1, nums.get(index2));
nums.set(index2, temp);
}
private static void mergeSort(List<Comparable> nums, int first, int last) {
if (first < last)
{
int m = (first+last)/2;
mergeSort(nums, first, m);
mergeSort(nums, m+1, last);
merge(nums, first, m, last);
}
}
private static void merge(List<Comparable> nums, int first, int mid, int last){
List<Comparable> newList = new ArrayList<Comparable>();
int loopCountA = 0;
int loopCountB = 0;
while(true) {
if(loopCountB == (last - mid)) {
while(first + loopCountA <= mid) {
newList.add(nums.get(first + loopCountA)); loopCountA++;
}
break;
}else if(first + loopCountA > mid) {
while(loopCountB < (last - mid)) {
newList.add(nums.get(mid + (loopCountB + 1))); loopCountB++;
}
break;
}else {
if(nums.get(mid + (loopCountB + 1)).compareTo(nums.get(first + loopCountA)) < 0) {
newList.add(nums.get(mid + (loopCountB + 1)));
loopCountB++;
}else {
newList.add(nums.get(first + loopCountA));
loopCountA++;
}
}
}
for(int i = 0; (i - 1) < (last - first); i++)
nums.set(first + i, newList.get(i));
}
}
I would say the problem here (causing the exception) is the way you create sublists - you are using subList(...) method, but it doesn't create another list, just a view for existing one. When you process these different views of one list in different threads you are causing the exception (as every thread changes the same list).
Possible solution would be to change the method to create a sub list or modify constructor to keep a copy, e.g.:
Merger(List<Comparable> arr) {
nums = new ArrayList<>(arr);
}

My bubble sorting algorithm in Java never stops sorting and doesnt return anything [closed]

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 5 years ago.
Improve this question
I'm trying to make a bubble sorting algorithm in Java however my code just keeps going when It's supposed to sort without returning anything. When the program is run it gets as far as printing the array before the sorting however after that nothing happens but the program doesnt stop it keeps running
package src;
import java.util.Scanner;
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
public class bubbleSort {
public static void main(String[] args) {
int length = getLength();
List<Integer> randomList = createList(length);
System.out.println("The list before sorting:\n" + randomList);
List<Integer> newList = sortList(randomList, length);
System.out.println("The list after sorting:\n" + newList);
}
public static int getLength() {
System.out.println("Please enter how long you want the array to be");
Scanner reader = new Scanner(System.in);
int length = Integer.parseInt(reader.nextLine());
return length;
}
public static List<Integer> createList(int length) {
Random rand = new Random();
List<Integer> randomList = new ArrayList<Integer>();
for(int x = 0 ; x < length ; x++){
int randomnumber = rand.nextInt((100 - 1) + 1) + 1;
randomList.add(randomnumber);
}
return randomList;
}
public static List<Integer> sortList(List<Integer> randomList, int length){
boolean sorted = false;
while(sorted == false){
sorted = true;
for(int x = 0 ; x < (length - 1) ; x++) {
if(randomList.get(x) > randomList.get(x + 1)) {
sorted = false;
int temp = randomList.get(x + 1);
randomList.set((x + 1), (x));
randomList.set((x + 1), temp);
}
}
}
return randomList;
}
}
Create a swap method to make it clearer (both for us and yourself):
private void swap(List<Integer> values, x, y) {
int temp = values.get(x);
values.set(x, values.get(y));
values.set(y, temp);
}
Other suggestions:
name your class BubbleSort rather than bubbleSort. Convention for class names is to start with uppercase.
don't pass the length as a second argument to your sort method. It's redundant and might become incorrect if someone sneakily adds an item to the list.
rename randomList to values or numbers or randomNumbers. No need to repeat the type in the variable name.
replace sorted == false with !sorted. This is the common and more readable notation
getLength and createList can be private
Consider using the main method to create an instance of your sorting class, with the list as a field. In that way the methods won't have to pass the list along to each other. Your code will be more readable and more object-oriented.
EDIT: you could take the separation even further and move all the static methods into a separate class called 'Application' or 'Main'. See edited code below:
Here's roughly how the code would look following my suggestions:
public class BubbleSort {
// a field
private List<Integer> numbers;
public BubbleSort(List<Integer> numbers) {
this.numbers = numbers;
}
public static List<Integer> sort() {
boolean sorted = false;
while(!sorted) {
sorted = true;
for(int x = 0; x < length - 1; x++) {
if(numbers.get(x) > numbers.get(x + 1)) {
sorted = false;
swap(x, x + 1);
}
}
}
return numbers;
}
private void swap(x, y) {
int temp = numbers.get(x);
numbers.set(x, numbers.get(y));
numbers.set(y, temp);
}
}
The Application class. It's purpose is to get the length from the user, create test data and set up and call a BubbleSort instance:
public class Application {
public static void main(String[] args) {
int length = getLength();
List<Integer> unsorted = createList(length);
System.out.println("The list before sorting:\n" + unsorted);
// creating an instance of the BubbleSort class
BubbleSort bubbleSort = new BubbleSort(unsorted );
List<Integer> sorted = bubbleSort.sort();
System.out.println("The list after sorting:\n" + sorted);
}
private static int getLength() {
System.out.println("Please enter how long you want the array to be");
Scanner reader = new Scanner(System.in);
return Integer.parseInt(reader.nextLine());
}
private static List<Integer> createList(int length) {
Random rand = new Random();
List<Integer> numbers = new ArrayList<Integer>();
for(int x = 0 ; x < length ; x++){
int randomnumber = rand.nextInt((100 - 1) + 1) + 1;
numbers.add(randomnumber);
}
return numbers;
}
BTW Good job splitting off those methods getLength and createList. That's the right idea.
you made a couple of mistakes
this:
randomList.set((x + 1), (x));
randomList.set((x + 1), temp);
should be:
randomList.set((x + 1), randomList.get(x));
randomList.set((x), temp);
full method:
public static List<Integer> sortList(List<Integer> randomList, int length){
boolean sorted = false;
while(sorted == false){
sorted = true;
for(int x = 0 ; x < (length - 1) ; x++) {
if(randomList.get(x) > randomList.get(x + 1)) {
sorted = false;
int temp = randomList.get(x + 1);
randomList.set((x + 1), randomList.get(x));
randomList.set((x), temp);
}
}
}
return randomList;
}

Implementation of Radix sort in Java using Nodes instead of integers

I have a final project for my Data Structures class that I can't figure out how to do. I need to implement Radix sort and I understand the concept for the most part. But all the implementations I found online so far are using it strictly with integers and I need to use it with the other Type that I have created called Note which is a string with ID parameter.
Here is what I have so far but unfortunately it does not pass any JUnit test.
package edu.drew.note;
public class RadixSort implements SortInterface {
public static void Radix(Note[] note){
// Largest place for a 32-bit int is the 1 billion's place
for(int place=1; place <= 1000000000; place *= 10){
// Use counting sort at each digit's place
note = countingSort(note, place);
}
//return note;
}
private static Note[] countingSort(Note[] note, long place){ //Where the sorting actually happens
Note[] output = new Note[note.length]; //Creating a new note that would be our output.
int[] count = new int[10]; //Creating a counter
for(int i=0; i < note.length; i++){ //For loop that calculates
int digit = getDigit(note[i].getID(), place);
count[digit] += 1;
}
for(int i=1; i < count.length; i++){
count[i] += count[i-1];
}
for(int i = note.length-1; i >= 0; i--){
int digit = getDigit((note[i].getID()), place);
output[count[digit]-1] = note[i];
count[digit]--;
}
return output;
}
private static int getDigit(long value, long digitPlace){ //Takes value of Note[i] and i. Returns digit.
return (int) ((value/digitPlace ) % 10);
}
public Note[] sort(Note[] s) { //
Radix(s);
return s;
}
//Main Method
public static void main(String[] args) {
// make an array of notes
Note q = new Note(" ", " ");
Note n = new Note("CSCI 230 Project Plan",
"Each person will number their top 5 choices.\n" +
"By next week, Dr. Hill will assign which piece\n" +
"everyone will work on.\n");
n.tag("CSCI 230");
n.tag("final project");
Note[] Note = {q,n};
//print out not id's
System.out.println(Note + " Worked");
//call radix
Radix(Note);
System.out.println(Note);
//print out note_id's
}
}
Instead of
public Note[] sort(Note[] s) { //
Radix(s);
return s;
}
I should have used
public Note[] sort(Note[] s) { //
s = Radix(s);
return s;
}
and change the variable type of Radix from void to Note[].

Java - Using parallel arrays to find common frequent number/s

I have an array and have already sorted it. I want to be able to find which numbers repeat. Following that, I want to be able to count how many times these numbers repeat. For example in a list [1,2,3,3,4,4] 3 and 4 repeats and they both repeats twice. My following code is able to find which numbers repeats but unable to get my mind around on how to count the number of times they each repeat. And I am using ArrayList. Trying to skip that and keep everything to purely just arrays excluding hashmap too. Appreciate any help. Tnks.
public static void main(String[] args) {
int[] num = {1,2,3,3,4,4};
for(int x : num){
System.out.print(x + " ");
}
System.out.println("\n" + freq(num));
}
public static ArrayList<Integer> freq(int[] num){
ArrayList<Integer> list = new ArrayList<>();
for(int x=0; x < num.length-1; x++){
if(num[x] == num[x+1]){
if(!list.contains(num[x])){
list.add(num[x]);
}
}
}
return list;
}
Well, since your array is sorted,you could use another array where each index corresponds to the amount of hits for this number:
int[] count = new int[num[num.length - 1]];
Then you could increment the index of this counter for each match:
count[num[x] - 1] = count[num[x] - 1] + 1;
This would however not compact your representation, just bring it to another form. Since you do not know the result lenght before the computation, a more compact representation without lists or even better maps is however not possible since the size of an array must be known at creation. This solution will only work with numbers bigger than 0. For other ranges, you have to adjust the offset.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
int[] num = {1,2,3,3,4,4};
for(int x : num){
System.out.print(x + " ");
}
System.out.println("\n" + freq(num));
}
static class ValueCountPair {
public ValueCountPair( final int val )
{
value = val;
count = 2;
}
public int value;
public int count;
public String toString() {
return "[" + value + ": " + count + "]";
}
}
public static ArrayList<ValueCountPair> freq(final int[] num){
ArrayList<ValueCountPair> list = new ArrayList<ValueCountPair>();
ValueCountPair last = null;
for(int x=0; x < num.length-1; x++){
if(num[x] == num[x+1]){
if ( last == null || last.value != num[x+1] )
list.add( last = new ValueCountPair( num[x+1] ) );
else
++last.count;
}
}
return list;
}
}

Categories

Resources