This is from an old test that I'm using to study.
I need to write a recursive method that returns the number of zeroes on the int[] from position 0 and right.
given int numberOfZeroes(int[] a, int right);
This assumes right < a.length
int numberOfZeroes(int[] a, int right) {
if(right < 0) { // We've gone through all indices
return 0; // So we don't want to recurse anymore
} else if(a[right] == 0) { // The current index has a zero
return 1 + numberOfZeroes(a, right - 1); // Call the function, moving left one. Add one to the returned count since we found a zero
} else { // The current index does not have a zero
return numberOfZeroes(a, right - 1); // Call the function, moving left one. We don't add anything since we didn't find a zero
}
}
int numberOfZeroes(int[] a, int right) {
if (right == 0) return 0;
return numberOfZeros(a, right-1) + a[right] == 0 ? 0 : 1;
}
Do numberOfZeros(a, a.length) to get the number of zeros in the entire array.
Related
I'm working on an assignment and really struggling coming up with a working solution. I will explain the question first and then walk through how I am thinking about the solution.
Question: Input: List<Integer> nums = [1,5,4,6,8,9,2] k = 3
I have to find the minimum number of groups, where no 2 numbers in the same group has a difference more than 3. So, in here, one of the solutions could be [[1,2,4],[5,6,8],[9]]. Note that it can also be [[1,2,4],[5,6],[8,9]]. Either way minimum number of groups is 3.
My Strategy: I am thinking of using binary search recursive way. To briefly explain what I have been trying to do -
- Sort the Array. So it becomes - [1,2,4,5,6,8,9]
- Make left = 0 right = nums.size()-1
- Create base cases
- if size of the array is 0 return 0
- if size of the array is 1 return 1
- if nums.get(right) - nums.get(left) <= k return 1
- While left < right
- Make mid = (left+right)/2
- if (number at mid - number at left) is greater than k
-recursively call the function like this, findMinGroup(nums, left, mid-1, k)
-At one point this recursive call will hit one of the base cases and return - either 0 or 1.
-if it returns 1 that means we found a group. if It returns 0 that means in the left side we can not form any group. So we check the right side.
This is the code I have written so far,
public class GroupNumbers {
static int minNumGroups = 0;
public static int minimumGroups(List<Integer> nums, int k){
Collections.sort(nums);
System.out.println(nums);
int left = 0;
int right = nums.size() == 0 ? nums.size() : nums.size() - 1;
return findMinGroups(nums, left, right, k);
}
private static int findMinGroups(List<Integer> nums, int left, int right, int k){
if((right - left) == 0)
return 0;
if((right - left) == 1 || nums.get(right) - nums.get(left) <= k)
return 1;
while(left < right){
int mid = (left + right)/2;
if(nums.get(mid) - nums.get(left) > k){
int group = findMinGroups(nums, left, mid-1, k);
if(group > 0){
minNumGroups += group;
left = mid;
}else{
left = (left + right)/2;
}
}
}
return minNumGroups;
}
I feel like I have the right idea about the solutions, but due to my lack of experience with these type of algorithms, I am not able to fully articulate my thoughts in code. I would really appreciate some help/insight for solving this problem.
One other simple solution would be iteration over entire list after sorting.
public static int minimumGroups(List<Integer> nums, int k){
int minGrps = 1;
Collections.sort(nums);
int numToCmp = nums.get(0);
for(Integer num : nums) {
if(num > numToCmp + k) {
minGrps++;
numToCmp = num;
}
}
return minGrps;
}
i have a problem in understanding the following:
public int sort(char[] arr, int index)
{
if(!isEmpty())
{
index = leftChild.sort(arr,index);
arr[index++] = getContent().getToken();
index = rightChild.sort(arr,index);
}
return index;
}
Why is that working but not this:
public void sort(char[] arr, int index)
{
if(!isEmpty())
{
leftChild.sort(arr,index);
arr[index++] = getContent().getToken();
rightChild.sort(arr,index);
}
}
And i also dont understand this : index = leftChild.sort(arr,index); What does this do? Can you guys pls give me examples?
Thanks for your help,
Kiimarii
One more question, i have a method that prints the longest way from the root to a leaf of the binaryTree:
public int height()
{
if ( !isEmpty() )
{
int leftHeight = leftChild.height();
int rightHeight = rightChild.height();
if ( leftHeight > rightHeight )
{
return leftHeight + 1;
} else {
return rightHeight + 1;
}
} else {
return 0;
}
}
But how can leftHeight > rightHeight be done, if no one has a value? they are both zero or something so how can he compare that? Thanks !
Your method performs an in-order traversal of a binary search tree.
The first snippet first calls leftChild.sort(arr,index), which assigns the left sub-tree to the input array. It returns the next index to be assigned.
Then you assign getContent().getToken() of the current node to the arr[index]
Then the call to rightChild.sort(arr,index) assigns the right sub-tree to the input array and the next index to be assigned is returned.
If you ignore the index returned by the recursive call (as you do in the second snippet), arr[index++] = getContent().getToken(); will always assign a value to the 0 index of the array (assuming the initial call is (sort(arr,0))).
You must assign the returned index to the local index variable in order to assign getContent().getToken() to the correct index of the array.
The key is that index is a local variable. Let's follow a really simple example:
4
/ \
2 6
/
1
// First call
(4).sort(arr, 0);
// The left child of (4) is (2)
// (Note that each 'index' here
// is a local variable.)
index = (2).sort(arr, 0);
// We've just called sort again
index = (1).sort(arr, 0)
// and again
index = (empty).sort(array, 0)
// isEmpty() is true
// so return index
return 0
<=
index = 0
// assign contents of (1) to
// arr[0] and increment 0
arr[index++] = getContent().getToken();
// Process right child of (1)
// (index returns unchanged)
index = (empty).sort(arr, 1);
return 1
<=
index = 1
...
We're now in the call to (2).sort so its contents get assigned to index 1 of the array. Can you see how the sequence will complete in order?
I was wondering if it is possible to find the closest lower element in a non-empty sorted array for an element that may be there or may not be there. Elements can be repeated also any number of times. All elements of the array +ve.
For example, if we had the values [2,5,6,7,7,8,9] and we are looking for the element closest lower to 6, it should return 5, because 5 is the biggest number in the array, that is smaller than 6.
Similarly, if we're looking for the element closest lower to 9, it should return 8, because 8 is the biggest number in the array, that is smaller than 9.
And if the closest lower element is not found, return -1 like if we're looking for the element closest lower to 1, it should return -1, because there is no such element which can be lower than 1. Here -1 represents that there's no such value is present in the array which is closest lower to the element
I have tried this below code. Is it all right? If I'm missing something, please help me. Java code will be more helpful.
static int find(int[] a, int target)
{
int n = a.length;
if(target <= a[0])
return -1;
if(target > a[n-1])
return a[n-1];
int i=0,j=n,mid=0;
while(i<j)
{
mid = (i+j)/2;
if(target <= a[mid])
{
if( mid >0 & target> a[mid-1] )
{
return a[mid-1];
}
j= mid;
}
else
{
if( mid<(n-1) & target > a[mid+1] )
{
return a[mid+1];
}
i= mid+1;
}
}
return mid;
}
Using streams:
import java.util.stream.IntStream;
public class FindNearestLowestValue {
public final static void main(String[] args) {
int[] array = {2,5,6,7,7,8,9};
int searchVal = 6;
// reverse the order so the first element of the filtered stream is the result
System.out.println(
IntStream.range(0, array.length)
.map(i -> array[array.length - 1 - i])
.filter(n -> n < searchVal)
.findFirst().orElse(-1)
);
}
}
There exists a standard binarySearch function.
static int find(int[] a, int target) {
int position = Arrays.binarySearch(a, target);
if (position >= 0) {
System.out.println("Found at index " + position);
} else {
int insertIndex = ~position;
System.out.println("Insert position at index " + insertIndex);
position = insertIndex;
}
return position;
}
When not found it delives the ones-complement of the insert position, as shown above. This means when the result is negative, the item is not found.
It does more or less what you did, but on not finding, it cleverly return a negative: ~ insert position (or -insert position - 1).
/**
* Search the next smaller array element.
* #param a the array sorted in ascending order.
* #param target the value to keep below.
* #return the greatest smaller element, or -1.
*/
static int findNextSmaller(int[] a, int target) {
int i= Arrays.binarySearch(a, target);
if (i >= 0) {
--i;
while (i>= 0 && a[i] == target) {
--i;
}
} else {
i = ~i;
--i;
}
return i == -1 ? -1 : a[i];
}
Or, as int is discrete:
static int findNextSmaller(int[] a, int target) {
int i= Arrays.binarySearch(a, target - 1);
if (i >= 0) {
return target - 1;
}
i = ~i;
--i;
return i == -1 ? -1 : a[i];
}
class ObjectBinarySearcher{
public static int search(String[] array, String value){
int first = 0, last = array.length-1, position = -1;
boolean found = false;
while(!found && first < last){
int mid = (first+last)/2;
int midValue = array[mid].compareTo(value);
if(midValue==0){
position = mid;
found = true;
}
else if(midValue<0)
last = mid-1;
else
first = mid+1;
}
return position;
}
}
I'm sending an array containing {"love", "hate", "happy", "sad", "neutral"}, and every time I try to use my binary search method to search for "neutral", It tells me it is not found. What is causing this to happen?
Your input array must be sorted in order to use binary search.
As #Libby pointed out, your while loop needs to change to allow first to be less than or equal to last.
You need to be able to exit the loop if there is no match found when first == last.
If midValue < 0 you need to move the lower bound, not the upper bound (and vice versa).
New code:
while (!found && first <= last) { // allow first to be lower or equal to last
int mid = (first + last) / 2;
int midValue = array[mid].compareTo(value);
if (midValue == 0) { // matched!
position = mid;
found = true;
} else if (first == last) { // didn't match and there was only one left to check
break; // so break out of the loop
} else if (midValue < 0) { // current pos is too low
first = mid + 1; // so adjust the lower bound
} else { // current pos is too high
last = mid - 1; // so adjust the upper bound
}
}
Change the while loop to while(!found && first <= last)
I am trying to create a binary search function and I keep getting stuck in a loop. I am confined to using such magnets. The program already gives me elements to search for. The code below creates an infinite loop.
public class Student < T extends Comparable <? super T >> {
public int binarySearchIter(T[] data, T key) {
int first = 0;
int last = data.length - 1;
int mid, result;
mid = (first + last) / 2;
result = key.compareTo(data[mid]);
while (first <= last) {
if (result == -1) {
return -1;
} else if (result > 0) {
first = mid + 1;
} else {
last = mid - 1;
}
}
return mid;
}
The contract of the compareTo method is to return a positive integer, 0 or a negative integer depending on whether the number is greater, equal or less than the given number. Those numbers might or might not be -1, so you must not rely on that.
Therefore, you should change your while loop like this:
If the result is negative, the key is before the middle element so we update last to before the middle index.
If the result is positive, the key is after the middle element so we update first to after the middle index.
If the result is zero, we just found the correct index.
Also, you are not updating the middle element once you have updated the first and last variable so you should move that code inside the while loop.
public static <T extends Comparable <T>> int binarySearchIter(T[] data, T key) {
int first = 0;
int last = data.length - 1;
int mid, result;
while (first <= last) {
mid = (first + last) / 2;
result = key.compareTo(data[mid]);
if (result < 0) {
last = mid - 1;
} else if (result > 0) {
first = mid + 1;
} else {
return mid;
}
}
return -1;
}
If this is supposed to be a binary search, while loop should start just above mid = (first + last) / 2;
Plus the note from Tunaki.