I am trying to write a method to perform binary search on an array of persons. The method should return the index that the person is found at, or -1 if it doesn't exist. For some reason, the method seems to return -1 even when the person is in the array. Please help I am a beginner.
public static int binarySearchRecursive(Person[] a, Person p) {
int right = a.length -1;
int left = 0;
return binarySearchRecursive(a, p, left, right);
}
private static int binarySearchRecursive(Person[] a, Person p, int left, int right) {
int mid = (left + right) / 2;
if (a[mid].compareTo(p) == 0)
return mid;
if (left == right)
return -1;
else {
if (a[mid].compareTo(p) > 0) {
return binarySearchRecursive(a, p, left, mid);
}
else {
return binarySearchRecursive(a, p, mid, left);
}
}
}
public static void main(String[] args) {
Person s = new Person("shlomo",13);
Person m = new Person("menachem",15);
Person y = new Person("yehuda",18);
Person a = new Person("atara",20);
Person [] array = {s, m, y, a};
There are 2 problems I can see:
In the second recursive call, you're passing mid for the left bound and left for the right bound. That doesn't seem right.
If you search for the last Person, the calculation of mid never advances, and left never equals right, so it recurses infinitely.
Related
I have an enormous directed graph I need to traverse in search for the shortest path to a specific node from a given starting point. The graph in question does not exist explicitly; the child nodes are determined algorithmically from the parent nodes.
(To give an illustration: imagine a graph of chess positions. Each node is a chess position and its children are all the legal moves from that position.)
So I have a queue for open nodes, and every time I process the next node in the queue I enqueue all of its children. But since the graph can have cycles I also need to maintain a hashset of all visited nodes so I can check if I have visited one before.
This works okay, but since this graph is so large, I run into memory problems. All of the nodes in the queue are also stored in the hashset, which tends to be around 50% of the total number or visited nodes in practice in my case.
Is there some magical way to get rid of this redundancy while keeping the speed of the hashset? (Obviously, I could get rid of the redundancy by NOT hashing and just doing a linear search, but that is out of the question.)
I solved it by writing a class that stores the keys in a list and stores the indices of the keys in a hashtable. The next node "in the queue" is always the the next node in the list until you find what you're looking for or you've traversed the entire graph.
class IndexMap<T>
{
private List<T> values;
private LinkedList<int>[] buckets;
public int Count { get; private set; } = 0;
public IndexMap(int capacity)
{
values = new List<T>(capacity);
buckets = new LinkedList<int>[NextPowerOfTwo(capacity)];
for (int i = 0; i < buckets.Length; ++i)
buckets[i] = new LinkedList<int>();
}
public void Add(T item) //assumes item is not yet in map
{
if (Count == buckets.Length)
ReHash();
int bucketIndex = item.GetHashCode() & (buckets.Length - 1);
buckets[bucketIndex].AddFirst(Count++);
values.Add(item);
}
public bool Contains(T item)
{
int bucketIndex = item.GetHashCode() & (buckets.Length - 1);
foreach(int i in buckets[bucketIndex])
{
if (values[i].Equals(item))
return true;
}
return false;
}
public T this[int index]
{
get => values[index];
}
private void ReHash()
{
LinkedList<int>[] newBuckets = new LinkedList<int>[2 * buckets.Length];
for (int i = 0; i < newBuckets.Length; ++i)
newBuckets[i] = new LinkedList<int>();
for (int i = 0; i < buckets.Length; ++i)
{
foreach (int index in buckets[i])
{
int bucketIndex = values[index].GetHashCode() & (newBuckets.Length - 1);
newBuckets[bucketIndex].AddFirst(index);
}
buckets[i] = null;
}
buckets = newBuckets;
}
private int NextPowerOfTwo(int n)
{
if ((n & n-1) == 0)
return n;
int output = 0;
while (n > output)
{
output <<= 1;
}
return output;
}
}
The old method of maintaining both an array of the open nodes and a hashtable of the visited nodes needed n*(1+a)*size(T) space, where a is the ratio of nodes_in_the_queue over total_nodes_found and size(T) is the size of a node.
This method needs n*(size(T) + size(int)). If your nodes are significantly larger than an int, this can save a lot.
Given a Binary Tree of size N, find size of the Largest Independent Set(LIS) in it. A subset of all tree nodes is an independent set if there is no edge between any two nodes of the subset. Your task is to complete the function LISS(), which finds the size of the Largest Independent Set.
I came up with this recursive solution.
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(t==true)
{
return max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
else
{
return max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
}
int LISS(struct Node *root)
{
int x,y;
y=rec(root,true);
return y;
}
To solve this problem via DP, I modified the code as follows, but then it gives wrong answer.
It doesn't even work with Binary tree with distinct elements.
map<int,int> mm;
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(mm.find(root->data)!=mm.end())
return mm[root->data];
if(t==true)
{
mm[root->data]=max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root->data];
}else
{
mm[root->data]=max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root-s>data];
}
}
int LISS(struct Node *root)
{
//Code here
mm={};
int y=0;
y=rec(root,true);
return max(x,y);
}
What's the mistake?
You have two states in your function but you are memoizing only one state. Let's say for root x,
rec(x,true) = 5 and
rec(x,false) = 10 .
You calculated the rec(x, true) first and saved it in your map "mm" as mm[x] = 5.
So when you are trying to get the value of rec(x, false) it is getting the value of rec(x, true) which is 5.
QUESTION:
I'm having trouble finding the minimum amount of coins needed to reach a specific sum. I'm pretty sure this is done easiest recursively and using the dynamic programming methodology, I should basically get Math.min("takeACoin","leaveACoin");
Unfortunately, My code doesn't terminate though I do have if statements that terminate under the condition that the sum is met, the array of coins is depleted, or if the sum is over. Please look at my code below and let me know what I'm doing wrong and especially why my code continues executing until it receives a stackoverflow error though I have the appropriate terminating conditions.
CODE:
private static final int S = 3;
public static int arr[] = {1,2};
public static void main(String[] args) {
Interview i = new Interview();
i.sumCoins(arr, 0);
}
public int sumCoins(int[] ar, int sum) {
//if the sum is met, dont add any coins, just return 0
if(sum == S){
return 0;
}
//if the sum is greater, then return max value as it is impossible to get less sum
if(sum > S){
return Integer.MAX_VALUE;
}
//if the array is out of coins return max value
if(ar.length == 0){
return Integer.MAX_VALUE;
}
//if the sum is less than S and there is still more coins to use, keep checking
//add the first coin
int tmpSum = sum + ar[0];
//delete the first coin from the list
int[] tmp = Arrays.copyOfRange(ar, 1, ar.length);
//add one coin to the solution
int one = 1+sumCoins(tmp, tmpSum);
//don't add one coin to the solution
int two = sumCoins(ar,sum);
//see which is more minimized
return Math.min(one,two);
}
Requested Stack Trace:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Math.min(Math.java:879)
at java.util.Arrays.copyOfRange(Arrays.java:2623)
at Interview.sumCoins(Interview.java:28)
at Interview.sumCoins(Interview.java:32)
at Interview.sumCoins(Interview.java:32)
The answer to this question is in regards to how I was implementing my dynamic programming. I was using the original array in the case where you left the coin. this is incorrect. In more detail:
If you take the coin: get rid of the first (coin) index of the array, add the sum, add +1 for the number of coins.
If you don't take the coin: get rid of the first (coin) index of the array since you're leaving that coin to not be considered.
In my solution, I received a stackoverflow because I was going through the "leaving the coin" scenario infinite times as the array never decreased and I wasn't actually "leaving the coin".
Correct Code here:
private static final int S = 5;
public static int arr[] = {1,1,1,1,1};
public static void main(String[] args) {
Interview i = new Interview();
System.out.println(i.sumCoins(arr, 0));
}
public int sumCoins(int[] ar, int sum) {
//if the sum is met, dont add any coins, just return 0
if(sum == S){
return 0;
}
//if the sum is greater, then return global array (not local)
//length +1 as it's impossible to get more coins than indices
if(sum > S){
return arr.length+1;
}
//if the array is out of coins return max value
if(ar.length == 0){
return arr.length+1;
}
//if the sum is less than S and there is still more coins to use, keep checking
//add the first coin
int tmpSum = sum + ar[0];
//delete the first coin from the list
int[] tmp = Arrays.copyOfRange(ar, 1, ar.length);
//add one coin to the solution
int one = 1+sumCoins(tmp, tmpSum);
//don't add one coin to the solution
int two = sumCoins(tmp,sum);
//see which is more minimized
return Math.min(one,two);
}
Im working on the collision detection in my 2D Processing 2.2.1 game. Basically what I did was write a class which creates a box by defining the coordinates of its endpoints and which has a method to check if two of these boxes overlap. I did this by introducing a boolean which is set to true as soon two of these boxes overlap. Then basically implementing a get method which creates these boxes, I run into a return a result of type error. It says that the method is not returning the correct type of Box1. I dont really understand since the box which I am returning does fit the constructor. I am pretty sure it is due to the fact that the objects colliding are in an array which generates more and more objects with time, but I sadly do not know how I would have to change my Collider ( Box1) class.
here is the code im getting the error on:
//returning collider info
public Box1 getBox1() {
for (int i =frameCount/600; i >0; i--) {
return new Box1( block[i].x - Blockpic.width/2, block[i].y-Blockpic.height/2, block[i].x+Blockpic.height/2, block[i].y+Blockpic.height/2);
}
}
this is my collider (Box1) class:
public class Box1 {
float x1, x2;
float y1, y2;
Box1( float x1, float y1, float x2, float y2 ) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
boolean isOverlap( Box1 b ) {
if ((( x1 <= b.x1 && b.x1 <= x2 ) || ( x1 <= b.x2 && b.x2 <= x2 ))
&& (( y1 <= b.y1 && b.y1 <= y2 ) || ( y1 <= b.y2 && b.y2 <= y2 ))) {
return true;
}
return false;
}
}
just for complete info my spawning objects class ( where the error is situated) :
public class Blockfield {
private int Blockcount;
private PImage Blockpic;
private Block block[];
//Constructor
public Blockfield (int Blockcount) {
this.Blockcount = Blockcount;
Blockpic = loadImage("block2.png");
//new array
block = new Block [Blockcount];
for ( int i=0; i < Blockcount; i++) {
block[i] = new Block( width+Blockpic.width, random (height),7);
}
}
//Draw method for this class
public void draw () {
for (int i =frameCount/600; i >0; i--) {
pushMatrix();
translate ( block[i].x,block[i].y );
image ( Blockpic, block[i].x, block[i].y);
popMatrix();
}
}
public void update() {
for (int i =frameCount/600; i >0; i--) {
//moves blocks right to left
block[i].x -=(6 * (frameCount/200));
//spawns block when they leave the screen
if (block[i].x < 0 - Blockpic.width) {
block[i] = new Block( width+Blockpic.width, random (height),7);
}
}
}
//returning collider info
public Box1 getBox1() {
for (int i =frameCount/600; i >0; i--) {
return new Box1( block[i].x - Blockpic.width/2, block[i].y-Blockpic.height/2, block[i].x+Blockpic.height/2, block[i].y+Blockpic.height/2);
}
}
}
class Block {
float x, y;
int speed;
Block ( float x, float y, int speed) {
this.x= x;
this.y= y;
this.speed = speed;
}
}
Thanks alot!!!
The problem, as you say, is with this method:
public Box1 getBox1() {
for (int i =frameCount/600; i >0; i--) {
return new Box1( block[i].x - Blockpic.width/2, block[i].y-Blockpic.height/2, block[i].x+Blockpic.height/2, block[i].y+Blockpic.height/2);
}
}
Ignoring for a second that it doesn't make sense to have a return statement inside a for loop like this, the whole problem is that computers are too stupid to know what the value of frameCount is before they run the code. What if frameCount is 0? Or negative?
If frameCount is 0 or negative, then the body of the for loop will never be executed, and this method will never return anything. That's the error.
You might know that frameCount will always be positive, but the computer doesn't.
Edit: Continuing in response to your below comment:
If you want help, you have to provide an MCVE. Note that this should be as few lines as possible, just to get the basics across. We don't need any collision detection, just a function you call. Here's an example:
void setup(){
String s = getString(true);
println(s);
}
String getString(boolean b){
if(b){
return "testing";
}
}
If you try to run this code, you'll get an error telling you that "This method must return a result of type String".
The reason you get this error is because: what will the getString() function return if I pass in a value of false? It won't return anything! This is exactly like what your code is complaining about. We can see that getString() is only ever called with a value of true, but the computer isn't smart enough to figure that out.
You seem to misunderstand the power that a compiler has. It can't see what will happen at runtime. Even if it's obvious to you that the boolean will always be true (or in your case, that frameCount is always positive), the compiler can't know that. And since it can't know that, it's telling you that you might not return a value from a method with a return type, and that's a compiler error.
You need to refactor your code so that it always returns something from methods that have a return type. However, I'm skeptical that the for loop does what you think it does- but you haven't really explained what you think it does, so that's just a guess.
And the reason you didn't encounter this error in your other methods is because none of them contain this logical error. The only other function that has a return type is this one:
boolean isOverlap( Box1 b ) {
if (lotsOfLogic) {
return true;
}
return false;
}
Notice how even if the if statement evaluates to false, you still return something from this function. That's what you need to do with your getBox1() function.
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
int left = getHeight(root.left);
int right = getHeight(root.right);
if (Math.abs(left - right) > 1) return false;
return isBalanced(root.left) && isBalanced(root.right);
}
private int getHeight(TreeNode n) {
if (n == null) return 0;
return Math.max(getHeight(n.left), getHeight(n.right)) + 1;
}
This is the code from leetcode http://discuss.leetcode.com/questions/276/balanced-binary-tree
since the discussion is closed there. I just want to ask why they said this code time complexity is nlogn not O(n)
Thanks
Obviously the complexity of getHeight() is O(logn). And in isBalanced(), it's a recursive function that will traverse the tree once at complexity of O(n), while at each node it call getHeight() function. So the total complexity is O(nlogn).