For example, if coins = [1, 2, 5] and N = 11, return true if coins = [3, 77] and N = 100, return - objective-c

wait online。~
Given a number of coins with different denominations, e.g. [1, 2, 5] and test if they could be used to make up a certain amount (N), assuming you can use unlimited number of coins in each denomination. For example, if coins = [1, 2, 5] and N = 11, return true if coins = [3, 77] and N = 100, return

The idea is use a recursive function (here it will calculate with one first coin vs array of other coins then recursively reduce size of coin array ).
But sr I'm not familiar with Objective-C so I write one using C#. Use should convert it to Objective-C.
bool CanDo(int n, int [] arr)
{
if (arr.Length == 1)
{
if (n % arr[0] == 0)
{
return true;
}
}
else
{
var ls = new List<int>(arr);
ls.RemoveAt(0);
int [] newarr = ls.ToArray(); //Create New array by deleting first element(current calculated element) of old array
for(int i = 0; i <= n/arr[0]; i++)
{
int next_n = n - i * arr[0];
if (next_n == 0)
{
return true;
}
else if (next_n < 0)
{
break;
}
else if(next_n > 0)
{
if( CanDo(next_n, newarr) )
{
return true;
}
}
}
}
return false;
}
This is full code in C# that can print to console first found solution.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static List<string> resultString = new List<string>();
static bool CanDo(int n, int [] arr)
{
if (arr.Length == 1)
{
if (n % arr[0] == 0)
{
resultString.Add(n/ arr[0] + "*" + arr[0]);
return true;
}
}
else
{
var ls = new List<int>(arr);
ls.RemoveAt(0);
int [] newarr = ls.ToArray(); //Create New array by deleting first element of old array
for(int i = 0; i <= n/arr[0]; i++)
{
if (resultString.Count > 0)
{
resultString.RemoveAt(resultString.Count - 1);
}
int next_n = n - i * arr[0];
if (next_n == 0)
{
resultString.Add(i + "*" + arr[0]);
return true;
}
else if (next_n < 0)
{
break;
}
else if(next_n > 0)
{
if (i != 0)
{
resultString.Add(i + "*" + arr[0] + " + ");
}
if( CanDo(next_n, newarr) )
{
return true;
}
}
}
}
return false;
}
static void Main(string[] args)
{
try
{
int[] arr = { 3, 5, 7 };
int N = 20;
resultString = new List<string>();
if (CanDo(N, arr))
{
resultString.ForEach(Console.WriteLine);
Console.Read();
}
else
{
Console.Write("Can't do");
Console.Read();
}
}
catch (Exception ex)
{
//handle exception
}
}
}
}

Related

Roman Numerals. Could you point out my mistakes further down the road?

Beginner here. This piece of code converts number into roman numerals in multiples of 50 if not 10 if not 9 and down to 0. Methods are so intertwined. Is there something (just at a glance) you could suggest I should avoid doing? Thank You.
public static void main(String[] args) {
System.out.println(fiftyAndAbove(37));
}
public static String nineAndDown(int number) {
String one = "I", five = "V", ten = "X", sum = "";
if(number == 5) {
return five;
} else if(number == 9) {
return one + ten;
}
else if(number > 5) {
for(int i=1; i<=number-5; i++) {
sum += one;
}
return five + sum;
} else {
if(number == 4 ) {
return one + five;
} else
for(int i=1; i <=number; i++) {
sum += one;
}
} return sum;
}
public static String tenAndAbove(int number) {
int remainder = number % 10, numberOftens = number/10;
String ten = "X", sum = "";
if(numberOftens > 0) {
while(numberOftens > 0) {
sum += ten;
numberOftens -= 1;
}
}
return sum + nineAndDown(remainder);
}
public static String fiftyAndAbove(int number) {
int remainder = number % 50, numberOfFifty = number/50;
String fifty = "L", sum = "";
if(numberOfFifty > 0) {
while(numberOfFifty > 0) {
sum += fifty;
numberOfFifty -= 1;
}
}
return sum + tenAndAbove(remainder);
}
Is there something (just at a glance) you could suggest I should avoid doing?
I'd not unnecessarily complicate the logic as with
if(numberOfFifty > 0) {
while(numberOfFifty > 0) {
…
}
}
which is equivalent to
while (numberOfFifty > 0)
{
…
}
You could also have a look at this implementation and see what you prefer:
import java.util.Arrays;
…
public static String fiftyAndAbove(int number)
{
int remainder = number%50, numberOfFifty = number/50;
char [] Ls = new char [numberOfFifty];
Arrays.fill(Ls, 'L');
return new String(Ls) + tenAndAbove(remainder);
}
You have four places like this in your program where you need a string of a character repeated. If you're willing to require a certain Java version or above, you can also use one of the methods described at Java: String - add character n-times; otherwise I'd suggest to use a function to do it.
You could also think about whether you find
String one = "I", five = "V", ten = "X", sum = "";
if(number == 5) {
return five;
} else if(number == 9) {
return one + ten;
}
really better than
if (number == 5) return "V";
if (number == 9) return "IX";

Null pointer exception on Processing (ldrValues)

My code involves both Processing and Arduino. 5 different photocells are triggering 5 different sounds. My sound files play only when the ldrvalue is above the threshold.
The Null Pointer Exception is highlighted on this line
for (int i = 0; i < ldrValues.length; i++) {
I am not sure which part of my code should be changed so that I can run it.
import processing.serial.*;
import processing.sound.*;
SoundFile[] soundFiles = new SoundFile[5];
Serial myPort; // Create object from Serial class
int[] ldrValues;
int[] thresholds = {440, 490, 330, 260, 450};
int i = 0;
boolean[] states = {false, false, false, false, false};
void setup() {
size(200, 200);
println((Object[])Serial.list());
String portName = Serial.list()[3];
myPort = new Serial(this, portName, 9600);
soundFiles[0] = new SoundFile(this, "1.mp3");
soundFiles[1] = new SoundFile(this, "2.mp3");
soundFiles[2] = new SoundFile(this, "3.mp3");
soundFiles[3] = new SoundFile(this, "4.mp3");
soundFiles[4] = new SoundFile(this, "5.mp3");
}
void draw()
{
background(255);
//serial loop
while (myPort.available() > 0) {
String myString = myPort.readStringUntil(10);
if (myString != null) {
//println(myString);
ldrValues = int(split(myString.trim(), ','));
//println(ldrValues);
}
}
for (int i = 0; i < ldrValues.length; i++) {
println(states[i]);
println(ldrValues[i]);
if (ldrValues[i] > thresholds[i] && !states[i]) {
println("sensor " + i + " is activated");
soundFiles[i].play();
states[i] = true;
}
if (ldrValues[i] < thresholds[i]) {
println("sensor " + i + " is NOT activated");
soundFiles[i].stop();
states[i] = false;
}
}
}
You're approach is shall we say optimistic ? :)
It's always assuming there was a message from Serial, always formatted the right way so it could be parsed and there were absolutely 0 issues buffering data (incomplete strings, etc.))
The simplest thing you could do is check if the parsing was successful, otherwise the ldrValues array would still be null:
void draw()
{
background(255);
//serial loop
while (myPort.available() > 0) {
String myString = myPort.readStringUntil(10);
if (myString != null) {
//println(myString);
ldrValues = int(split(myString.trim(), ','));
//println(ldrValues);
}
}
// double check parsing int values from the string was successfully as well, not just buffering the string
if(ldrValues != null){
for (int i = 0; i < ldrValues.length; i++) {
println(states[i]);
println(ldrValues[i]);
if (ldrValues[i] > thresholds[i] && !states[i]) {
println("sensor " + i + " is activated");
soundFiles[i].play();
states[i] = true;
}
if (ldrValues[i] < thresholds[i]) {
println("sensor " + i + " is NOT activated");
soundFiles[i].stop();
states[i] = false;
}
}
}else{
// print a helpful debugging message otherwise
println("error parsing ldrValues from string: " + myString);
}
}
(Didn't know you could parse a int[] with int(): nice!)

Why is my Index was out of range in MVC 4?

I've tried to create some list with increase number after some calculation each month for a year.
For example, in month 1 number = 1, month 2 number = 3, month 3 number = 5.
The calculation is like this number[i] = i + number[i - 1]. Which i is the month.
I want to show all the list like this
Month[1] = 1,
Month[2] = 3,
Month[3] = 5,
Month[4] = 7,
Month[5] = 9,
Month[6] = 11,
Month[7] = 13,
...
Month[12] = 23
Here's my Controller
for (i = 1; i <= 12; i++)
{
List<int> number = new List<int>();
if (i <= 12)
{
number[i] = a(i, number[i - 1]);
}
else
{
//something else
}
}
Here's my a function
public int a(int month, int number)
{
try
{
a = month + number;
}
catch (Exception ex)
{
throw ex;
}
return a;
}
But, when executed i'm getting this error
Index was out of range. Must be non-negative and less than the size of the collection.
I've change the controller into this
for (i = 0; i <= 12; i++)
{
//...
}
But have the same error. Can someone help me? Why I'm getting this error?
Try this
Fiddle demo
int[] number = new int[13];
for (int i = 1; i <= 12; i++)
{
if (i <= 12)
{
number[i] = a(i, number[i - 1]);
}
else
{
//something else
}
}
int j = 1;
List<int> item = new List<int>();
foreach (var a in number)
{
if (j <= 12)
{
item.Add(a);
}
else
{
break;
}
j++;
}
public int a(int month, int number)
{
int a = 0;
try
{
a = month + number;
}
catch (Exception ex)
{
throw ex;
}
return a;
}

java.lang.NullPointerException in JApplet game

new guy to stack and to java.
to start off, here's my code,
AsteroidsGame.java
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.util.*;
public class AsteroidsGame extends JApplet implements Runnable, KeyListener {
Thread thread;
Dimension dim;
Image img;
Graphics g;
long endTime, startTime, framePeriod;
Ship ship;
boolean paused;
// True if the game is paused. Enter is the pause key
Shot[] shots;
int numShots;
boolean shooting;
Asteroid[] asteroids;
int numAsteroids;
double astRadius;
double minAstVel;
double maxAstVel;
int astNumHits;
int astNumSplit;
int level;
private AudioClip audioClip;
public void init() {
resize(500, 500);
shots = new Shot[41];
numAsteroids = 0;
level = 0;
astRadius = 60;
minAstVel = .5;
maxAstVel = 5;
astNumHits = 3;
astNumSplit = 2;
endTime = 0;
startTime = 0;
framePeriod = 25;
addKeyListener(this);
setFocusable(true);
requestFocusInWindow();
dim = getSize();
img = createImage(dim.width, dim.height);
g = img.getGraphics();
thread = new Thread(this);
thread.start();
URL urlAudioClip = getClass().getResource("audio/minorcircuit.wav");
audioClip = Applet.newAudioClip(urlAudioClip);
audioClip.loop();
}
public void start() {
audioClip.loop();
}
public void stop() {
audioClip.stop();
}
public void setUpNextLevel() {
level++;
ship = new Ship(250, 250, 0, .35, .98, .1, 12);
numShots = 0;
paused = false;
shooting = false;
asteroids = new Asteroid[level * (int)Math.pow(astNumSplit, astNumHits - 1) + 1];
numAsteroids = level;
for(int i = 0; i < numAsteroids; i++) {
asteroids[i] = new Asteroid(Math.random() * dim.width, Math.random() * dim.height, astRadius, minAstVel, maxAstVel, astNumHits, astNumSplit);
}
}
public void paint(Graphics gfx) {
g.setColor(Color.black);
g.fillRect(0, 0, 500, 500);
for(int i = 0; i < numShots; i++) {
shots[i].draw(g);
}
for(int i = 0; i < numAsteroids; i++) {
asteroids[i].draw(g);
}
ship.draw(g);
//draw the ship
g.setColor(Color.cyan);
g.drawString("Level " + level, 20, 20);
gfx.drawImage(img, 0, 0, this);
}
public void update(Graphics gfx) {
paint(gfx);
}
public void run() {
for(;;) {
startTime = System.currentTimeMillis();
//start next level when all asteroids are destroyed
if(numAsteroids <= 0) {
setUpNextLevel();
}
if(!paused) {
ship.move(dim.width, dim.height);
//move the ship
for(int i = 0; i < numShots; i++) {
shots[i].move(dim.width, dim.height);
if(shots[i].getLifeLeft() <= 0) {
deleteShot(i);
i--;
}
}
updateAsteroids();
if(shooting && ship.canShoot()) {
//add a shot on to the array
shots[numShots] = ship.shoot();
numShots++;
}
}
repaint();
try {
endTime = System.currentTimeMillis();
if(framePeriod - (endTime - startTime) > 0) {
Thread.sleep(framePeriod - (endTime - startTime));
}
}
catch(InterruptedException e) {
}
}
}
private void deleteShot(int index) {
//delete shot and move all shots after it up in the array
numShots--;
for(int i = index; i < numShots; i++) {
shots[i] = shots[i + 1];
shots[numShots] = null;
}
}
private void deleteAsteroid(int index) {
//delete asteroid and shift ones after it up in the array
numAsteroids--;
for(int i = index; i < numAsteroids; i++) {
asteroids[i] = asteroids[i + 1];
asteroids[numAsteroids] = null;
}
}
private void addAsteroid(Asteroid ast) {
//adds asteroid in at end of array
asteroids[numAsteroids] = ast;
numAsteroids++;
}
private void updateAsteroids() {
for(int i = 0; i < numAsteroids; i++) {
// move each asteroid
asteroids[i].move(dim.width, dim.height);
//check for collisions with the ship
if(asteroids[i].shipCollision(ship)) {
level--;
//restart this level
numAsteroids = 1;
return;
}
//check for collisions with any of the shots
for(int j = 0; j < numShots; j++) {
if(asteroids[i].shotCollision(shots[j])) {
//if the shot hit an asteroid, delete the shot
deleteShot(j);
//split the asteroid up if needed
if(asteroids[i].getHitsLeft() > 1) {
for(int k = 0; k < asteroids[i].getNumSplit(); k++) {
addAsteroid(
asteroids[i].createSplitAsteroid(
minAstVel, maxAstVel));
}
}
//delete the original asteroid
deleteAsteroid(i);
j=numShots;
i--;
}
}
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
if(!ship.isActive() && !paused) {
ship.setActive(true);
}
else {
paused = !paused;
//enter is the pause button
if(paused) {
//grays out the ship if paused
ship.setActive(false);
}
else {
ship.setActive(true);
}
}
}
else if(paused || !ship.isActive()) {
return;
}
else if(e.getKeyCode() == KeyEvent.VK_SPACE) {
ship.setAccelerating(true);
}
else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
ship.setTurningLeft(true);
}
else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
ship.setTurningRight(true);
}
else if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
shooting=true;
}
else if(e.getKeyCode() == KeyEvent.VK_M) {
audioClip.stop();
}
else if(e.getKeyCode() == KeyEvent.VK_S) {
audioClip.loop();
}
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP) {
ship.setAccelerating(false);
}
else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
ship.setTurningLeft(false);
}
else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
ship.setTurningRight(false);
}
else if(e.getKeyCode() == KeyEvent.VK_CONTROL) {
shooting=false;
}
}
public void keyTyped(KeyEvent e) {
}
}
this is a "clone" of Asteroids. Some of you who have been around maybe a little longer than myself have probably played it in an arcade. Anyways, I wrote this for a final project in my Java course, but could never get to work completely. It starts up just fine, you can turn and shoot, but not move forward. I'm not worried about moving right now though. What happens after applet starts is music plays and an "asteroid" travels across the screen. If you shoot the asteroid or shoot 3 times in any direction, a thread exception occurs.
Exception in thread "Thread-3" java.lang.NullPointerException
at AsteroidsGame.updateAsteroids(AseroidsGame.java:161)
at AsteroidsGame.run(AsteroidsGame.java:115)
at java.lang.Thread.run(Thread.java:722)
Having looked around online has benefited me very little. Most of what I have learned was self taught and not as easy to wrap my head around. I'm not exactly sure what to do here to resolve this exception. In another thread on stack, it was mentioned to use an ArrayList because the array was not formerly declared with a size. Tinkered with that; never got it to work.
I need ideas/suggestions/criticism. I want to get this to work just so I can say I finished it.
other classes,
Asteroid.java
import java.awt.*;
public class Asteroid {
double x, y, xVelocity, yVelocity, radius;
int hitsLeft, numSplit;
public Asteroid(double x,double y,double radius,double minVelocity, double maxVelocity,int hitsLeft,int numSplit) {
this.x = x;
this.y = y;
this.radius = radius;
this.hitsLeft = hitsLeft;
this.numSplit = numSplit;
double vel = minVelocity + Math.random() * (maxVelocity - minVelocity);
double dir = 2 * Math.PI * Math.random();
xVelocity = vel * Math.cos(dir);
yVelocity = vel * Math.sin(dir);
}
public void move(int scrnWidth, int scrnHeight) {
x += xVelocity;
y += yVelocity;
if(x < 0 - radius) {
x += scrnWidth + 2 * radius;
}
else if(x > scrnWidth + radius) {
x -= scrnWidth + 2 * radius;
}
if(y < 0 - radius) {
y += scrnHeight + 2 * radius;
}
else if(y > scrnHeight + radius) {
y -= scrnHeight + 2 * radius;
}
}
public void draw(Graphics g) {
g.setColor(Color.gray);
g.fillOval((int)(x - radius + .5), (int)(y - radius + .5), (int)(2 * radius), (int)(2 * radius));
}
public Asteroid createSplitAsteroid(double minVelocity,double maxVelocity) {
return new Asteroid(x, y, radius / Math.sqrt(numSplit), minVelocity, maxVelocity, hitsLeft - 1, numSplit);
}
public boolean shipCollision(Ship ship) {
if(Math.pow(radius + ship.getRadius(), 2) > Math.pow(ship.getX() - x, 2) + Math.pow(ship.getY() - y, 2) && ship.isActive()) {
return true;
}
return false;
}
public boolean shotCollision(Shot shot) {
if(Math.pow(radius, 2) > Math.pow(shot.getX() - x, 2) + Math.pow(shot.getY() - y, 2)) {
return true;
}
return false;
}
public int getHitsLeft() {
return hitsLeft;
}
public int getNumSplit() {
return numSplit;
}
}
Ship.java
import java.awt.*;
public class Ship {
final double[] origXPts = {14,-10,-6,-10}, origYPts = {0,-8,0,8}, origFlameXPts = {-6,-23,-6}, origFlameYPts = {-3,0,3};
final int radius = 6;
double x, y, angle, xVelocity, yVelocity, acceleration, velocityDecay, rotationalSpeed;
//used for movement
boolean turningLeft, turningRight, accelerating, active;
int [] xPts, yPts, flameXPts, flameYPts;
//current location of ship
int shotDelay, shotDelayLeft;
//rate of fire
public Ship(double x, double y, double angle, double acceleration, double velocityDecay, double rotationalSpeed, int shotDelay) {
this.x = x;
this.y = y;
this.angle = angle;
this.acceleration = acceleration;
this.velocityDecay = velocityDecay;
this.rotationalSpeed = rotationalSpeed;
xVelocity = 0;
yVelocity = 0;
turningLeft = false;
turningRight = false;
accelerating = false;
active = false;
xPts = new int[4];
yPts = new int[4];
flameXPts = new int[3];
flameYPts = new int[3];
this.shotDelay = shotDelay;
shotDelayLeft = 0;
}
public void draw(Graphics g) {
if(accelerating && active) {
for(int i = 0; i < 3; i++) {
flameXPts[i] = (int)(origFlameXPts[i] * Math.cos(angle) - origFlameYPts[i] * Math.sin(angle) + x + .5);
flameYPts[i] = (int)(origFlameXPts[i] * Math.sin(angle) + origFlameYPts[i] * Math.cos(angle) + y + .5);
}
g.setColor(Color.red);
//color of flame
g.fillPolygon(flameXPts, flameYPts, 3);
}
for(int i = 0; i < 4; i++) {
xPts[i] = (int)(origXPts[i] * Math.cos(angle) - origYPts[i] * Math.sin(angle) + x + .5);
yPts[i] = (int)(origXPts[i] * Math.sin(angle) + origYPts[i] * Math.cos(angle) + y + .5);
}
if(active) {
g.setColor(Color.white);
}
else {
g.setColor(Color.darkGray);
}
g.fillPolygon(xPts, yPts, 4);
}
public void move(int scrnWidth, int scrnHeight) {
if(shotDelayLeft > 0) {
shotDelayLeft--;
}
if(turningLeft) {
angle -= rotationalSpeed;
}
if(turningRight) {
angle += rotationalSpeed;
}
if(angle > (2 * Math.PI)) {
angle -= (2 * Math.PI);
}
else if(angle < 0) {
angle += (2 * Math.PI);
}
if(accelerating) {
xVelocity += acceleration * Math.cos(angle);
yVelocity += acceleration * Math.sin(angle);
}
x += xVelocity;
y += yVelocity;
xVelocity *= velocityDecay;
yVelocity *= velocityDecay;
if(x<0) {
x += scrnWidth;
}
else if(x > scrnWidth) {
x -= scrnWidth;
}
if(y < 0) {
y += scrnHeight;
}
else if(y > scrnHeight) {
y -= scrnHeight;
}
}
public void setAccelerating(boolean accelerating) {
this.accelerating = accelerating;
//start or stop accelerating the ship
}
public void setTurningLeft(boolean turningLeft) {
this.turningLeft = turningLeft;
//start or stop turning the ship
}
public void setTurningRight(boolean turningRight) {
this.turningRight = turningRight;
}
public double getX() {
return x;
//returns the ship’s x location
}
public double getY() {
return y;
//returns the ship's y location
}
public double getRadius() {
return radius;
//returns radius of circle that approximates the ship
}
public void setActive(boolean active) {
this.active = active;
//used when the game is paused or unpaused
}
public boolean isActive() {
return active;
}
public boolean canShoot() {
if(shotDelayLeft > 0) {
return false;
}
else {
return true;
}
}
public Shot shoot() {
shotDelayLeft=shotDelay;
//set delay till next shot can be fired
//a life of 40 makes the shot travel about the width of the
//screen before disappearing
return new Shot(x, y, angle, xVelocity, yVelocity, 40);
}
}
Shot.java
import java.awt.*;
public class Shot {
final double shotSpeed = 12;
double x, y, xVelocity, yVelocity;
int lifeLeft;
public Shot(double x, double y, double angle, double shipXVel, double shipYVel, int lifeLeft) {
this.x = x;
this.y = y;
xVelocity = shotSpeed * Math.cos(angle) + shipXVel;
yVelocity = shotSpeed * Math.sin(angle) + shipYVel;
this.lifeLeft = lifeLeft;
}
public void move(int scrnWidth, int scrnHeight) {
lifeLeft--;
x += xVelocity;
y += yVelocity;
if(x < 0) {
x += scrnWidth;
}
else if(x > scrnWidth) {
x -= scrnWidth;
}
if(y < 0) {
y += scrnHeight;
}
else if(y > scrnHeight) {
y -= scrnHeight;
}
}
public void draw(Graphics g) {
g.setColor(Color.yellow);
g.fillOval((int)(x - .5), (int)(y - .5), 3, 3);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public int getLifeLeft() {
return lifeLeft;
}
}
thanks for looking.
---------------------Edit 12/9/2012------------------------
Tried debugging with NetBeans IDE 7.2.1. It improperly depicts the turning of ship and gives a completely different error:
Exception in thread "Thread-3" java.lang.NullPointerException
at AsteroidsGame.run(AsteroidsGame.java:122)
at java.lang.Thread.run(Thread.java:722)
It is directing attention to the Shot[] shots array inside the run method.
This could be expected as the array for Asteroid[] and Shot[] are set up the same.

Exporting a non public Type through public API

I am trying to follow Trees tutorial at: http://cslibrary.stanford.edu/110/BinaryTrees.html
Here is the code I have written so far:
package trees.bst;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
*
* #author sachin
*/
public class BinarySearchTree {
Node root = null;
class Node {
Node left = null;
Node right = null;
int data = 0;
public Node(int data) {
this.left = null;
this.right = null;
this.data = data;
}
}
public void insert(int data) {
root = insert(data, root);
}
public boolean lookup(int data) {
return lookup(data, root);
}
public void buildTree(int numNodes) {
for (int i = 0; i < numNodes; i++) {
int num = (int) (Math.random() * 10);
System.out.println("Inserting number:" + num);
insert(num);
}
}
public int size() {
return size(root);
}
public int maxDepth() {
return maxDepth(root);
}
public int minValue() {
return minValue(root);
}
public int maxValue() {
return maxValue(root);
}
public void printTree() { //inorder traversal
System.out.println("inorder traversal:");
printTree(root);
System.out.println("\n--------------");
}
public void printPostorder() { //inorder traversal
System.out.println("printPostorder traversal:");
printPostorder(root);
System.out.println("\n--------------");
}
public int buildTreeFromOutputString(String op) {
root = null;
int i = 0;
StringTokenizer st = new StringTokenizer(op);
while (st.hasMoreTokens()) {
String stNum = st.nextToken();
int num = Integer.parseInt(stNum);
System.out.println("buildTreeFromOutputString: Inserting number:" + num);
insert(num);
i++;
}
return i;
}
public boolean hasPathSum(int pathsum) {
return hasPathSum(pathsum, root);
}
public void mirror() {
mirror(root);
}
public void doubleTree() {
doubleTree(root);
}
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
return sameTree(this.root, bst.getRoot());
}
public void printPaths() {
if (root == null) {
System.out.println("print path sum: tree is empty");
}
List pathSoFar = new ArrayList();
printPaths(root, pathSoFar);
}
///-------------------------------------------Public helper functions
public Node getRoot() {
return root;
}
//Exporting a non public Type through public API
///-------------------------------------------Helper Functions
private boolean isLeaf(Node node) {
if (node == null) {
return false;
}
if (node.left == null && node.right == null) {
return true;
}
return false;
}
///-----------------------------------------------------------
private boolean sameTree(Node n1, Node n2) {
if ((n1 == null && n2 == null)) {
return true;
} else {
if ((n1 == null || n2 == null)) {
return false;
} else {
if ((n1.data == n2.data)) {
return (sameTree(n1.left, n2.left) && sameTree(n1.right, n2.right));
}
}
}
return false;
}
private void doubleTree(Node node) {
//create a copy
//bypass the copy to continue looping
if (node == null) {
return;
}
Node copyNode = new Node(node.data);
Node temp = node.left;
node.left = copyNode;
copyNode.left = temp;
doubleTree(copyNode.left);
doubleTree(node.right);
}
private void mirror(Node node) {
if (node == null) {
return;
}
Node temp = node.left;
node.left = node.right;
node.right = temp;
mirror(node.left);
mirror(node.right);
}
private void printPaths(Node node, List pathSoFar) {
if (node == null) {
return;
}
pathSoFar.add(node.data);
if (isLeaf(node)) {
System.out.println("path in tree:" + pathSoFar);
pathSoFar.remove(pathSoFar.lastIndexOf(node.data)); //only the current node, a node.data may be duplicated
return;
} else {
printPaths(node.left, pathSoFar);
printPaths(node.right, pathSoFar);
}
}
private boolean hasPathSum(int pathsum, Node node) {
if (node == null) {
return false;
}
int val = pathsum - node.data;
boolean ret = false;
if (val == 0 && isLeaf(node)) {
ret = true;
} else if (val == 0 && !isLeaf(node)) {
ret = false;
} else if (val != 0 && isLeaf(node)) {
ret = false;
} else if (val != 0 && !isLeaf(node)) {
//recurse further
ret = hasPathSum(val, node.left) || hasPathSum(val, node.right);
}
return ret;
}
private void printPostorder(Node node) { //inorder traversal
if (node == null) {
return;
}
printPostorder(node.left);
printPostorder(node.right);
System.out.print(" " + node.data);
}
private void printTree(Node node) { //inorder traversal
if (node == null) {
return;
}
printTree(node.left);
System.out.print(" " + node.data);
printTree(node.right);
}
private int minValue(Node node) {
if (node == null) {
//error case: this is not supported
return -1;
}
if (node.left == null) {
return node.data;
} else {
return minValue(node.left);
}
}
private int maxValue(Node node) {
if (node == null) {
//error case: this is not supported
return -1;
}
if (node.right == null) {
return node.data;
} else {
return maxValue(node.right);
}
}
private int maxDepth(Node node) {
if (node == null || (node.left == null && node.right == null)) {
return 0;
}
int ldepth = 1 + maxDepth(node.left);
int rdepth = 1 + maxDepth(node.right);
if (ldepth > rdepth) {
return ldepth;
} else {
return rdepth;
}
}
private int size(Node node) {
if (node == null) {
return 0;
}
return 1 + size(node.left) + size(node.right);
}
private Node insert(int data, Node node) {
if (node == null) {
node = new Node(data);
} else if (data <= node.data) {
node.left = insert(data, node.left);
} else {
node.right = insert(data, node.right);
}
//control should never reach here;
return node;
}
private boolean lookup(int data, Node node) {
if (node == null) {
return false;
}
if (node.data == data) {
return true;
}
if (data < node.data) {
return lookup(data, node.left);
} else {
return lookup(data, node.right);
}
}
public static void main(String[] args) {
BinarySearchTree bst = new BinarySearchTree();
int treesize = 5;
bst.buildTree(treesize);
//treesize = bst.buildTreeFromOutputString("4 4 4 6 7");
treesize = bst.buildTreeFromOutputString("3 4 6 3 6");
//treesize = bst.buildTreeFromOutputString("10");
for (int i = 0; i < treesize; i++) {
System.out.println("Searching:" + i + " found:" + bst.lookup(i));
}
System.out.println("tree size:" + bst.size());
System.out.println("maxDepth :" + bst.maxDepth());
System.out.println("minvalue :" + bst.minValue());
System.out.println("maxvalue :" + bst.maxValue());
bst.printTree();
bst.printPostorder();
int pathSum = 10;
System.out.println("hasPathSum " + pathSum + ":" + bst.hasPathSum(pathSum));
pathSum = 6;
System.out.println("hasPathSum " + pathSum + ":" + bst.hasPathSum(pathSum));
pathSum = 19;
System.out.println("hasPathSum " + pathSum + ":" + bst.hasPathSum(pathSum));
bst.printPaths();
bst.printTree();
//bst.mirror();
System.out.println("Tree after mirror function:");
bst.printTree();
//bst.doubleTree();
System.out.println("Tree after double function:");
bst.printTree();
System.out.println("tree size:" + bst.size());
System.out.println("Same tree:" + bst.sameTree(bst));
BinarySearchTree bst2 = new BinarySearchTree();
bst2.buildTree(treesize);
treesize = bst2.buildTreeFromOutputString("3 4 6 3 6");
bst2.printTree();
System.out.println("Same tree:" + bst.sameTree(bst2));
System.out.println("---");
}
}
Now the problem is that netbeans shows Warning: Exporting a non public Type through public API for function getRoot().
I write this function to get root of tree to be used in sameTree() function, to help comparison of "this" with given tree.
Perhaps this is a OOP design issue... How should I restructure the above code that I do not get this warning and what is the concept I am missing here?
The issue here is that some code might call getRoot() but won't be able to use it's return value since you only gave package access to the Node class.
Make Node a top level class with its own file, or at least make it public
I don't really understand why you even created the getRoot() method. As long as you are inside your class you can even access private fields from any other object of the same class.
So you can change
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
return sameTree(this.root, bst.getRoot());
}
to
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
return sameTree(this.root, bst.root);
}
I would also add a "short path" for the case you pass the same instance to this method:
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
if (this == bst) {
return true;
}
return sameTree(this.root, bst.root);
}