I've been trying to learn algorithms and as part of this I have been trying to code binary search and the logic seems fine. The code doesn't terminate and the IDE stays idle forever. I don't understand what I'm doing wrong. Any help is appreciated. Thanks in advance!
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
int no = 5;
System.out.print(binSearch(arr, no, 0, arr.length - 1));
}
private static boolean binSearch(int[] arr, int no, int start, int end) {
while(start <= end) {
int mid = (start + end) / 2;
if (arr[mid] == no) {
return true;
} else if (no > arr[mid]) {
binSearch(arr, no, mid + 1, end);
} else if(no < arr[mid]) {
binSearch(arr, no, start, mid - 1);
}
}
return false;
}
}
You are missing the return on the two recursive calls:
private static bool binSearch(int[] arr, int no, int start, int end) {
while(start <= end) {
int mid = (start + end) / 2;
if (arr[mid] == no) {
return true;
} else if (no > arr[mid]) {
return binSearch(arr, no, mid + 1, end);
} else if(no < arr[mid]) {
return binSearch(arr, no, start, mid - 1);
}
}
return false;
}
You could also consider writing it in a non-recursive loop.
okay so i think we review recursion a bit
binSearch(arr, num, start, end){
while (start<=end){
int mid = (start+end)/2;
if (arr[mid] == no) {
return true #when it finally matches return true
}
else if (arr[mid] > no) {
binSearch(arr, no, start, mid-1) #call binSearch for new value
}
}
}
Just to illustrate recursion, imagine we want some value B for an input A. Now imagine a node or some point as an origin that represents our input A. For every point or node that follows after A is some step we take towards finding the value B.
Once we find the value that we want, the structure of our approach can be illustrated as a single graph with one direction. A --> C --> --> D --> B
That is essentially how recursion works. Now first, lets take a look at your else if statement. When your parameters meet one of the else if conditions you make a call to your binSearch method.
What this does is basically create a new point of origin rather than working off the initial one. So lets say at iteration number 3 you finally meet your boolean condition and it returns true. But where does it return true to?
Only the last call or the most recent call that was made to binSearch. Lets call it iteration 2.
Now once the return value is made it simply moves on to the next block of code which brings us to your while loop. The only way your code can move on to the next block of code (which is returning the false value), is to break out of the while loop, ie. have your start value be greater than your end value.
But remember, we are on iteration 2. And iteration 2 was given the values for start and end that satisfied the while-loop so it loops again and whatever else-if statement iteration 2 landed on before the final iteration that returned true, it will keep repeating indefinitely.
The obvious solution as mentioned above is to put 'return' before the call is made as that will return all the way back to the original call to binSearch.
Also, the while loop is not necessary unless you are doing it without recursion.
Related
I have written an algorithm to return whether a subset of a group of numbers will sum to a given target using backtracking and recursion (returns true/false)
Ex: {5, 2, 3, 6} with Target = 8 ==> True ||
{5, 2, 3, 6} with Target = 20 ==> False
I want to modify my algorithm so that it includes all 5's that maybe present in the set. I am having a hard time how to figure this out using backtracking and recursion. Any advice is appreciated
Ex: {5, 2, 3, 6} with Target 8 ==>True ||
{6, 2, 3, 5, 5} with Target 8 ==> False
I have written an algorithm that recursively includes a number and checks the sum and then omits the number from the sum but I don't know how to modify my algorithm to only pick a certain numbers and include them in the sum
public static void main(String argv[]) {
int[] ints = { 10, 1, 3, 2 };
int target = 5;
int start = 0;
System.out.println(groupSum(ints, target, 0, start));
}
public static boolean groupSum(int[] arr, int target, int sum, int start) {
if (sum > target) {
return false;
}
if (sum == target) {
return true;
}
if (start >= arr.length) {
return false;
}
//choose
sum = sum + arr[start];
//explore
if (groupSum(arr, target, sum, start + 1))
return true;
//un-choose
sum = sum - arr[start];
return groupSum(arr, target, sum, start + 1);
}
Force it to only look at including 5 if it sees it, and only check = sum at the end. Like this:
public static void main(String argv[]) {
int[] ints = { 10, 1, 3, 2 };
int target = 5;
int start = 0;
System.out.println(groupSum(ints, target, 0, start));
}
public static boolean groupSum(int[] arr, int target, int sum, int start) {
if (sum > target) {
return false;
}
// NOTE: sum == target inside of end of array check so all 5s are found.
if (start >= arr.length) {
return sum == target;
}
//choose
sum = sum + arr[start];
//explore
if (groupSum(arr, target, sum, start + 1))
return true;
//un-choose
// NOTE: can't unchoose 5
if (5 == arr[start]) {
return false;
}
sum = sum - arr[start];
return groupSum(arr, target, sum, start + 1);
}
Update: Here is advice on how to solve problems like this.
Very clearly state what you want the function to do.
Very clearly state what the base case or cases are where you know the answer.
In the complex case, figure out how to reduce it to one or more simpler problems.
As long as you've done that, your recursive code should work. And if you're in doubt about how to modify, start over from scratch, only copying code from before where you've noticed that it can be left alone.
So for the first step, the statement is, We want groupSum to take an array arr of positive integers, a target target, a partial sum sum and an int start and to return whether it is possible to get the rest of the array to sum to target when you take a subset that has to include all 5s.
For the second step, base cases are:
We've already exceeded target, then it is false.
We've reached the end of the array and are at target, then it is true.
We've reached the end of the array and are blow target, then it is false. (I combined this with the last in the code by returning a comparison.)
For the third step, the reductions are as follows.
If we can add the current value and make it, the answer is true.
If the current value is not 5, we don't add it, and can make it, the answer is true.
Otherwise it is false.
I was trying to write the code in the way that looked most like what you already had. But to write it exactly according to this logic it would be like this:
public static boolean groupSumWithAll5s(int[] arr, int target, int sum, int start) {
// Base cases
if (sum > target) {
return false;
}
else if ((start >= arr.length) && (sum == target)) {
return true;
}
else if (start >= arr.length) {
return false;
}
// Recursive cases.
if (groupSumWithAll5s(arr, target, sum + arr[start], start + 1)) {
return true;
}
else if ((arr[start] != 5) && groupSumWithAll5s(arr, target, sum, start + 1)) {
return true;
}
else {
return false;
}
}
I am trying to solve above problem. Below is my solution. Appreciate feedback/comments.
public static boolean areMoreVowels(String str, int c, int v){
String vowels = "aeiou";
if(vowels.indexOf(str.charAt(0))>=0){
v++;
}else{
c++;
}
if(str.length()==1){
return v > c;
}
return areMoreVowels(str.substring(1), c, v);
}
public static void main(String[] args) {
System.out.println(areMoreVowels("aeiouttrrrrr", 0, 0));
}
I think your code it's ok! But if you look for other way, another idea could be
Int areMoreVowels(string str, int pos)
if pos == str.length()
return 0
k = areMoreVowels(str, pos+1)
if str[pos] == Vowel()
return k + 1
return k - 1
main()
if areMoreVowels("aeiouttrrrrr", 0) > 0
print "Yes"
else
print "No"
Personally I'd split this up into two separate problems for simplicity:
counting vowels
verifying whether the number of vowels is greater than that of vowels
Something along these lines:
count_vowels(str, p):
if p == len(str) return 0
return count_vowels(str, p + 1) + (is_vowel(str[p]) ? 1 : 0)
more_vowels(str):
return count_vowels(str, 0) > (len(str) / 2)
Assigning a single, simple purpose to each method is generally a better approach than creating a conditional structure to squeeze separate functionality into a single method.
Your approach is fine. I don't know if you are aware of it or not, but you used tail recursion which really matters in some languages (like Scala), and can reduce chance for stack overflow. Also your method already return your answer, what I would consider as an advantage.
You can consider reducing amount of variables:
public static boolean areMoreVowels(String str, int v){
String vowels = "aeiou"; //do you consider 'y' as a vovel?
if (vowels.indexOf(str.charAt(0)) >= 0) {
v++;
} else {
v--;
}
if (str.length() == 1) {
return v > 0;
}
return areMoreVowels(str.substring(1), v);
}
public static void main(String[] args) {
System.out.println(areMoreVowels("aeiouttrrrrr", 0, 0));
}
My Q is similar to the one asked on stack overflow in the past
http://www.geeksforgeeks.org/dynamic-programming-set-32-word-break-problem/
The solution I wrote, I am not able to understand that since I do not use DP but still how is it that my sol is solving overlapping problems. I think it is not. Can someone clarify?
my dicitonary that i use is {"cat", "catdog", "dog", "mouse"} and test string as "catdogmouse"
Here is the method i wrote
public static boolean recursiveWordBreak2(String s, int start) {
System.out.println("s is:"+s.substring(start));
if (s.isEmpty() || start >= s.length()) {
return true;
}
for (int i = start; i <= s.length(); i++) {
String str = s.substring(start, i);
System.out.println("substr:" + str);
if (dictSet.contains(str)) {
return recursiveWordBreak2(s, i);
}
}
return false;
}
Your solution uses recursion -only-. recognising that that problem is DP allows you to MEMOIZE (remember) previous results so that you can reuse them without doing the recursion again.
in the link you provided if the dictionary is {a,b,c,d,e} and the input is "abcde", you would need to check if "cde" is valid twice with recursive code, where a DP solution would remember "cde" is valid and only have to check once.
edit: dictionary {a,b,c,d,e} should be {a, ab, cde} to illustrate checking 'cde' twice
edit2 (see comment on algo having logic issue):
if (dictSet.contains(str)) {
return recursiveWordBreak2(s, i);
}
should be
if (dictSet.contains(str) && recursiveWordBreak2(s, i)) { return true }
that way if contains = true but recursiveWB = false, the outer loop will continue to check length+1 instead of returning false
It's a Google interview question. There's a list of "T" and "F" only. All denotes a position such that T means position is occupied by a flower pot and F means pot is not there, so you can put another pot at this position. Find the number of pots that can be placed in a given arrangement such that no two pots are adjacent to each other(they can be adjacent in the given arrangement). If a position at the beginning is unoccupied then a pot can be placed if second position is also unoccupied and if the last position is unoccupied than a pot can be placed if second last position is also unoccupied. For ex.
TFFFTFFTFFFFT - returns 2
FFTTFFFFFTTFF - returns 4
I tried solving it by looking at adjacent values for every position with value F. Increased the counter if both adjacent positions were F and set this position as T. I need a better solution or any other solution(if any).
Let's analyse what has to be done.
So first we probably need to visit and examine each place. That suggests loop of some sort. E.g.:
for (int i = 0; i < myPlaces.Length; ++i)
When we are at a spot we have to check if it's occupied
if (place[i] == 'F')
but that's not enough to place the flower pot there. We have to check if the next and previous place is free
place[i-1]
place[i+1]
If all tree contain F you can put the flower pot there and move to next field
Now, we also have some exceptions from the rule. Beginning and end of the list. So you have to deal with them separately. E.g
if (i == 0)
{
// only check current position and next position
}
if (i == myPlaces.Length - 1) // minus 1 because indexing usually starts from 0
{
// only check current position and previous position
}
After that you can perform the checks mentioned previously.
Now let's think of the input data. Generally, it's a good habit not to modify the input data but make a copy and work on the copy. Also some data structures work better than the others for different tasks. Here you can use simple string to keep entry values. But I would say an array of chars would be a better option because then, when you find a place where you can put a flower pot you can actually replace the F with the T in an array. Then when you move to new spot your data structers knows that there is already a pot in the previous position so your algorithm won't put an adjacent one.
You would not be able to do that with string as strings are immutable and you would need to generate a new string each time.
Note that it's only a naive algorithm with a lot of scope for improvement and optimization. But my goal was rather to give some idea how to approach this kind of problems in general. I'll leave implementing of the details to you as an afternoon exercise before targeting a job at Google.
You may be able to do this with a modified Mergesort. Consider the flowerpots that can be placed in the singletons, then the flowerpots that can be placed in the doubleton merges of those singletons, up the tree to the full arrangement. It would complete in O(n lg n) for a list of n flowerpots.
There is certainly a way to do this with a modified Rod Cutting algorithm with complexity O(n^2). The subproblem is whether or not an open "false set" exists in the substring being considered. The "closed false sets" already have some maximum value computed for them. So, when a new character is added, it either increases the amount of flowerpots that can be inserted, or "locks in" the maximum quantity of available flowerpots for the substring.
Also, you know that the maximum flowerpots that can be placed in a set of n open positions bound by closed positions is n - 2 (else n-1 if only bracketed on one side, i.e. the string begins or ends with a "false set". The base condition (the first position is open, or the first position is closed) can calculated upon reaching the second flowerpot.
So, we can build up to the total number of flowerpots that can be inserted into the whole arrangement in terms of the maximum number of flowerpots that can be inserted into smaller subarrangements that have been previously calculated. By storing our previous calculations in an array, we reduce the amount of time necessary to calculate the maximum for the next subarrangement to a single array lookup and some constant-time calculations. This is the essence of dynamic programming!
EDIT: I updated the answer to provide a description of the Dynamic Programming approach. Please consider working through the interactive textbook I mentioned in the comments! http://interactivepython.org/runestone/static/pythonds/index.html
I would approach the problem like this. You need FFF to have one more pot, FFFFF for two pots, etc. To handle the end cases, add an F at each end.
Because this is very similar to a 16-bit integer, the algorithm should use tricks like binary arithmetic operations.
Here is an implementation in Python that uses bit masking (value & 1), bit shifting (value >>= 1) and math ((zeros - 1) / 2) to count empty slots and calculate how many flower pots could fit.
#value = 0b1000100100001
value = 0b0011000001100
width = 13
print bin(value)
pots = 0 # number of flower pots possible
zeros = 1 # number of zero bits in a row, start with one leading zero
for i in range(width):
if value & 1: # bit is one, count the number of zeros
if zeros > 0:
pots += (zeros - 1) / 2
zeros = 0
else: # bit is zero, increment the number found
zeros += 1
value >>= 1 # shift the bits to the right
zeros += 1 # add one trailing zero
pots += (zeros - 1) / 2
print pots, "flower pots"
The solution is really simple, check the previous and current value of the position and mark the position as plantable (or puttable) and increment the count. Read the next value, if it is already is planted, (backtrack and) change the previous value and decrement the count. The complexity is O(n). What we really want to check is the occurrence of 1001. Following is the implementation of the algorithm in Java.
public boolean canPlaceFlowers(List<Boolean> flowerbed, int numberToPlace) {
Boolean previous = false;
boolean puttable = false;
boolean prevChanged = false;
int planted = 0;
for (Boolean current : flowerbed) {
if (previous == false && current == false) {
puttable = true;
}
if (prevChanged == true && current == true) {
planted--;
}
if (puttable) {
previous = true;
prevChanged = true;
planted++;
puttable = false;
} else {
previous = current;
prevChanged = false;
}
}
if (planted >= numberToPlace) {
return true;
}
return false;
}
private static void canPlaceOneFlower(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 1);
System.out.println("Can place 1 flower");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceTwoFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 2);
System.out.println("Can place 2 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceThreeFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 3);
System.out.println("Can place 3 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceFourFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 4);
System.out.println("Can place 4 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
public static void main(String[] args) {
List<Boolean> flowerbed = makeBed(new int[] { 0, 0, 0, 0, 0, 0, 0 });
FlowerBed fb = new FlowerBed();
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
flowerbed = makeBed(new int[] { 0, 0, 0, 1, 0, 0, 0 });
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
canPlaceTwoFlowers(flowerbed, fb);
flowerbed = makeBed(new int[] { 1, 0, 0, 1, 0, 0, 0, 1 });
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
canPlaceTwoFlowers(flowerbed, fb);
canPlaceOneFlower(flowerbed, fb);
}
My solution using dynamic programming.
ar is array in the form of ['F','T','F'].
import numpy as np
def pot(ar):
s = len(ar)
rt = np.zeros((s,s))
for k in range(0,s):
for i in range(s-k):
for j in range(i,i+k+1):
left = 0
right = 0
if ar[j] != 'F':
continue
if j-1 >= i and ar[j-1] == 'T':
continue
else:
left = 0
if j+1 <= i+k and ar[j+1] == 'T':
continue
else:
right = 0
if j-2 >= i:
left = rt[i][j-2]
if j+2 <= i+k:
right = rt[j+2][i+k]
rt[i][i+k] = max(rt[i][i+k], left+right+1)
return rt[0][len(ar)-1]
My solution written in C#
private static int CheckAvailableSlots(string str)
{
int counter = 0;
char[] chrs = str.ToCharArray();
if (chrs.FirstOrDefault().Equals('F'))
if (chrs.Length == 1)
counter++;
else if (chrs.Skip(1).FirstOrDefault().Equals('F'))
counter++;
if (chrs.LastOrDefault().Equals('F') && chrs.Reverse().Skip(1).FirstOrDefault().Equals('F'))
counter++;
for (int i = 1; i < chrs.Length - 2; i++)
{
if (chrs[i - 1].Equals('T'))
continue;
else if (chrs[i].Equals('F') && chrs[i + 1].Equals('F'))
{
chrs[i] = 'T';
counter++;
i++;
}
else
i++;
}
return counter;
}
// 1='T'
// 0='F'
int[] flowerbed = new int[] {1,0,0,0,0,1};
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int tg = 0;
for (int i = 0, g = 1; i < flowerbed.length && tg < n; i++) {
g += flowerbed[i] == 0 ? flowerbed.length - 1 == i ? 2 : 1 : 0;
if (flowerbed[i] == 1 || i == flowerbed.length - 1) {
tg += g / 2 - (g % 2 == 0 ? 1 : 0);
g = 0;
}
}
return tg >= n;
}
Most of these answers (unless they alter the array or traverse and a copy) dont consider the situation where the first 3 (or last 3) pots are empty. These solutions will incorrectly determine that FFFT will contain 2 spaces, rather than just one. We therefore need to start at the third element (rather than then second) and end at index length - 3 (rather than length - 2). Also, while looping through the array, if an eligible index is found, the index just be incremented by 2, otherwise TTFFFFT would give 2 available plots instead of one. This is true unless you alter the array while looping or use a copy of the array and alter it.
Edit: this holds true unless the question is how many spaces are available for planting, rather than how many total plants can be added
public static int sqrt(int x) {
if( x == 0 || x == 1){
return x;
}
long start = 0;
long end = x;
while ( end-start > 1){
long mid = (int)(end + start) / 2;
long s = mid * mid;
if(s == x){
return (int)mid;
}
else if(s > x){
end = mid;
}
else {
start = mid;
}
}
return (int)start;
}
Above is the working code snippet. I have questions as below. Thank you in advance for helping. ;-)
While(end-start > 1) why we need 1 here? just because the return signiture is int?
If we change while loop from while(end-start > 1) to while(end > start), we have to make end = mid-1; and start = mid + 1, correct? Still one step move, i wonder if this is also due to return type is integer?
Why we cannot return end? or (int)(start+end)/2?? I saw almost 99% answer return to the left bound of binary search. I just want to know if return to right boundry or the middle one is fine?
The return type int simply means you are return a result which is of type int. It has nothing to do with the algorithm inside the method body. Below I have tried to answer your questions:
While(end-start > 1) is used to make sure end is always greater than start. if end-start is 1 or less than 1, that means you have reached end of binary search.
You can go ahead and change while(end-start > 1) to while(end > start), it will still work. Don't have to make end = mid-1 and start = mid+1.
It all depends where you answer lies. It can be different for each problem.
You should try the link below to understand binary search algorithm better.
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binarySearch
Hope it helps.