My homework assignment requires me to go through an array of doubles and return true or false depending on whether or not it contains a negative number or not. The catch is that I have to use a recursive function and I can't use loops. I also can't use access any functions or variables outside of the function I am given.
The function takes two parameters: the array, and the number of elements to be inspected.
I'm having trouble making it stop recursing once it has inspected the specified number of elements.
//what I have so far
bool anyNegative(const double a[], int n)
{
if(n <= 0)
return false;
if(*a < 0)
return true;
anyNegative(a + 1, n);
}
First, I thought of using counter, but that doesn't work since it gets reset every time the function recurses.
I also tried to compare pointer indexes with
if(currentElement == &a[n])
where currentElement is a pointer to the first element of array a.
However, I THINK the reason my program didn't work when I did that is because "a" is set to a new value every time the function is recursed so that &a[n] will always be n elements ahead of currentElement.
I'm stuck and if someone could give me a hint, that would be great.
Decrease n, since the array you pass is smaller
anyNegative(a + 1, n - 1);
You need to decrease n, and also return the value of recursive call.
return anyNegative(a + 1, n - 1);
You are missing two things, first you are not decrementing value of n so that terminating condition can be reached. Secondly you are not returning the result of sub-executions to the upper level.
Here is the modified code:
//what I have so far
bool anyNegative(const double a[], int n)
{
if(n <= 0)
return false;
if(*a < 0)
return true;
return anyNegative(a + 1, n - 1);
}
Size of an array can not be negative. So that do not do such a superfluous check as
if(n <= 0)
return false;
it is better to define the second parameter as having type size_t.
Your function has undefined behaviour because it returns nothing when the control will achieve statement
anyNegative(a + 1, n);
and moreover instead of the call above must be
anyNegative(a + 1, n -1);
I would write the function the following way
bool anyNegative( const double a[], size_t n )
{
if ( n == 0 ) return false;
return ( *a < 0 ? true : anyNegative( a + 1, n - 1 ) );
}
Related
I just solved the subset sum problem:
Given an integer array nums of size N. You are also given an integer B, you need to find whether there exists a subset in nums whose sum is B. If there exist a subset then return 1 else return 0.
Constraints are: 1 <= N <= 100; 1 <= nums[i] <= 100; 1 <= B <= 10^5;
The way I solved this problem is as below (0/1 knapsack):
vector<int> n;
int t;
unordered_map<string, long long> m;
int helper(int i, int sum) {
if(i>=n.size()) return sum==t;
string str=to_string(i)+"-"+to_string(sum);
if(m.count(str)) return m[str];
int val=helper(i+1, sum+n[i]);
val=max(val, helper(i+1, sum));
return m[str]=val;
}
int Solution::solve(vector<int> &nums, int B) {
n=nums;
t=B;
m.clear();
return helper(0,0);
}
This gets "Accepted". However, note that all the values in nums are positive; so IMO sum will only remain the same/go on increasing. i goes on increasing, too. So, we will never encounter a value previously stored in the memoization table.
But, if I remove memoization, it results in Wrong Answer for some large test case. What am I missing? Will any recursive call ever encounter a previous state?
You call helper twice, the second time with the lower sum than the first. Therefore a later call to helper could indeed have the same sum as an earlier call.
#user3386109 already gave a concrete set of num that demonstrates this. As for how often, consider the case where nums = [1, 1, ..., 1] 100 times. Then without memoization you'll call helper(100, 50) 100 choose 50 = 100,891,344,545,564,193,334,812,497,256 times. Over 100 octillion calls..takes a while.
An array is said to have a majority element if more than half of its elements are the same. Is there a divide-and-conquer algorithm for determining if an array has a majority element?
I normally do the following, but it is not using divide-and-conquer. I do not want to use the Boyer-Moore algorithm.
int find(int[] arr, int size) {
int count = 0, i, mElement;
for (i = 0; i < size; i++) {
if (count == 0) mElement = arr[i];
if (arr[i] == mElement) count++;
else count--;
}
count = 0;
for (i = 0; i < size; i++) {
if (arr[i] == mElement) count++;
}
if (count > size / 2) return mElement;
return -1;
}
I can see at least one divide and conquer method.
Start by finding the median, such as with Hoare's Select algorithm. If one value forms a majority of the elements, the median must have that value, so we've just found the value we're looking for.
From there, find (for example) the 25th and 75th percentile items. Again, if there's a majority element, at least one of those would need to have the same value as the median.
Assuming you haven't ruled out there being a majority element yet, you can continue the search. For example, let's assume the 75th percentile was equal to the median, but the 25th percentile wasn't.
When then continue searching for the item halfway between the 25th percentile and the median, as well as the one halfway between the 75th percentile and the end.
Continue finding the median of each partition that must contain the end of the elements with the same value as the median until you've either confirmed or denied the existence of a majority element.
As an aside: I don't quite see how Boyer-Moore would be used for this task. Boyer-Moore is a way of finding a substring in a string.
There is, and it does not require the elements to have an order.
To be formal, we're dealing with multisets (also called bags.) In the following, for a multiset S, let:
v(e,S) be the multiplicity of an element e in S, i.e. the number of times it occurs (the multiplicity is zero if e is not a member of S at all.)
#S be the cardinality of S, i.e. the number of elements in S counting multiplicity.
⊕ be the multiset sum: if S = L ⊕ R then S contains all the elements of L and R counting multiplicity, i.e. v(e;S) = v(e;L) + v(e;R) for any element e. (This also shows that the multiplicity can be calculated by 'divide-and-conquer'.)
[x] be the largest integer less than or equal to x.
The majority element m of S, if it exists, is that element such that 2 v(m;S) > #S.
Let's call L and R a splitting of S if L ⊕ R = S and an even splitting if |#L - #R| ≤ 1. That is, if n=#S is even, L and R have exactly half the elements of S, and if n is odd, than one has cardinality [n/2] and the other has cardinality [n/2]+1.
For an arbitrary split of S into L and R, two observations:
If neither L nor R has a majority element, then S cannot: for any element e, 2 v(e;S) = 2 v(e;L) + 2 v(e;R) ≤ #L + #R = #S.
If one of L and R has a majority element m with multiplicity k, then it is the majority element of S only if it has multiplicity r in the other half, with 2(k+r) > #S.
The algorithm majority(S) below returns either a pair (m,k), indicating that m is the majority element with k occurrences, or none:
If S is empty, return none; if S has just one element m, then return (m,1). Otherwise:
Make an even split of S into two halves L and R.
Let (m,k) = majority(L), if not none:
a. Let k' = k + v(m;R).
b. Return (m,k') if 2 k' > n.
Otherwise let (m,k) = majority(R), if not none:
a. Let k' = k + v(m;L).
b. Return (m,k') if 2 k' > n.
Otherwise return none.
Note that the algorithm is still correct even if the split is not an even one. Splitting evenly though is likely to perform better in practice.
Addendum
Made the terminal case explicit in the algorithm description above. Some sample C++ code:
struct majority_t {
int m; // majority element
size_t k; // multiplicity of m; zero => no majority element
constexpr majority_t(): m(0), k(0) {}
constexpr majority_t(int m_,size_t k_): m(m_), k(k_) {}
explicit operator bool() const { return k>0; }
};
static constexpr majority_t no_majority;
size_t multiplicity(int x,const int *arr,size_t n) {
if (n==0) return 0;
else if (n==1) return arr[0]==x?1:0;
size_t r=n/2;
return multiplicity(x,arr,r)+multiplicity(x,arr+r,n-r);
}
majority_t majority(const int *arr,size_t n) {
if (n==0) return no_majority;
else if (n==1) return majority_t(arr[0],1);
size_t r=n/2;
majority_t left=majority(arr,r);
if (left) {
left.k+=multiplicity(left.m,arr+r,n-r);
if (left.k>r) return left;
}
majority_t right=majority(arr+r,n-r);
if (right) {
right.k+=multiplicity(right.m,arr,r);
if (right.k>r) return right;
}
return no_majority;
}
A simpler divide and conquer algorithm works for the case that there exists more than 1/2 elements which are the same and there are n = 2^k elements for some integer k.
FindMost(A, startIndex, endIndex)
{ // input array A
if (startIndex == endIndex) // base case
return A[startIndex];
x = FindMost(A, startIndex, (startIndex + endIndex - 1)/2);
y = FindMost(A, (startIndex + endIndex - 1)/2 + 1, endIndex);
if (x == null && y == null)
return null;
else if (x == null && y != null)
return y;
else if (x != null && y == null)
return x;
else if (x != y)
return null;
else return x
}
This algorithm could be modified so that it works for n which is not exponent of 2, but boundary cases must be handled carefully.
Lets say the array is 1, 2, 1, 1, 3, 1, 4, 1, 6, 1.
If an array contains more than half of elements same then there should be a position where the two consecutive elements are same.
In the above example observe 1 is repeated more than half times. And the indexes(index start from 0) index 2 and index 3 have same element.
I know this is basic CS knowledge, but I still can't grasp the idea of doing a recursive function over a for loop. I'm still confused on the idea of recursion especially with numbers. Lets say there's a numerical sequence 3, 11, 27, 59, 123.... I know how to figure out the mathematical recursive sequence which is just An = An-1 + (8*(n-1)), but don't really know how to put this into a C++ recursive function.
Can someone outline the creation of a recursive function for the above numerical sequence?
Recursive functions have two "parts", the base case and the recursion. The base case is when your function stops recursing (and starts unwinding the call stack). Without the base the function just keeps calling itself until the stack overflow happens and the program is terminated by the OS.
The recursive part takes the initial problem (in your case finding the ith number in a sequence) and shrinks it. This happens until the base case is hit. So for finding the ith number in a sequence, let's say the 4th, you start looking for the 4th number, but that depends on the 3rd, which depends on the 2nd which depends on the first. The initial recursion shrinks the problem from the 4th number to the 3rd.
Here's a stab (not at all tested) at a recursive function for your sequence.
int recursive(int i) {
// This is your base case, it prevents infinite recursion.
if (i == 0) return 0; // Or whatever you base value is
else {
int sum = recursive(i-1) + 8 * (i-1);
return sum;
}
}
Lots of times a recursive function can be done with a loop. However there are functions which require recursion. For instance, Ackermann's Function. A really good video on Computerphile
Basic recursive implementation of said function (proper values for your sequence are 3, 11, 27, 51, 83, 123, … btw):
int seq(int n)
{
if (n <= 1)
return 3;
else
return seq(n-1) + 8 * (n-1);
}
However, this implementation is not tail-recursive (therefore it will use stack, while iterative implementation would not). We can write tail-recursive version by introducing accumulator parameter:
int seq_r(int n, int acc)
{
if (n <= 1)
return acc;
else
return seq_r(n-1, acc + 8 * (n-1));
}
int seq(int n)
{
return seq_r(n, 3);
}
Or, same implementation but with seq_r hidden inside your function using lambda expressions:
#include <functional>
int seq(int n)
{
std::function<int(int, int)> seq_r = [&] (int n, int acc) -> int {
if (n <= 1)
return acc;
else
return seq_r(n-1, acc + 8 * (n-1));
};
return seq_r(n, 3);
}
If your sequence function is defined as: A[n] = A[n-1] + 8*(n-1) then you need two things. 1) A structure to hold the sequence of numbers, and 2) a function or loop to produce those numbers. For the structure I will use a std::vector and the loop or function can be used as below:
Loop
#include <vector>
int main()
{
std::vector<int> storage;
// Seed the storage with a number since the sequence looks back.
storage.push_back(3);
// Define the maximum number count.
int maxNum = 5;
// Create the sequence by starting from n=1 since there are [n-1] terms.
for(int n = 1; n <= maxNum; n++)
storage.push_back(storage[n - 1] + 8*(n - 1));
return 0;
}
Function
#include <vector>
std::vector<int> storage;
void DoSequence(int maxNum, int n = 0)
{
// Check the limit.
if(n > maxNum)
return;
// Check seeding condition if adding the first element,
// otherwise run the equation.
if(n == 0)
storage.push_back(3);
else
storage.push_back(storage[n - 1] + 8*(n-1));
// Call the same function.
DoSequence(maxNum, n + 1);
}
int main()
{
// Call the recursive function with upper limit (n=5).
DoSequence(5);
return 0;
}
There are other ways to implement the details such as how storage is declared or handled but that is personal preference. Note: I did not test this code but hopefully you get the idea. In short, once you have your sequence function defined then create a loop or program function to generate the numbers.
I am trying to create a recursive function as follows.
The function takes a counter k and as long that the counter is larger than zero I would like to call it recursively so that in the end I end up with something like this:
result = 2(2(2n+1)+1)+1
where the last n (when k=0) should be zero.
int pass(int k, int n)
{
if(k==0)
{
n = 0;
}
else
{
k--;
return pass(k, 2*n+1);
}
}
Can someone give me a hint as on how to do it?
Change
n = 0;
To
return n;
To return the result.
The rest of the code is fine
Currently the behaviour of your code is undefined since you don't explicitly return a value on all control paths.
Your code can simplify down to:
int pass(int k, int n)
{
return k ? 2 * pass(k - 1, n) + 1 : 1;
}
Here I've used the ternary conditional operator. 2 * pass(k - 1, n) + 1 is returned if k is non-zero, 1 is returned otherwise.
Take care not to overflow your int in this case. Note that the maximum size of an int can be as small as 32767. Consider using a long type instead.
Also, note that recursion is not normally a good way of solving O(n) type problems; you could get errors at runtime due to a function call stack limit being exceeded: consider folding to a loop instead.
An array is said to have a majority element if more than half of its elements are the same. Is there a divide-and-conquer algorithm for determining if an array has a majority element?
I normally do the following, but it is not using divide-and-conquer. I do not want to use the Boyer-Moore algorithm.
int find(int[] arr, int size) {
int count = 0, i, mElement;
for (i = 0; i < size; i++) {
if (count == 0) mElement = arr[i];
if (arr[i] == mElement) count++;
else count--;
}
count = 0;
for (i = 0; i < size; i++) {
if (arr[i] == mElement) count++;
}
if (count > size / 2) return mElement;
return -1;
}
I can see at least one divide and conquer method.
Start by finding the median, such as with Hoare's Select algorithm. If one value forms a majority of the elements, the median must have that value, so we've just found the value we're looking for.
From there, find (for example) the 25th and 75th percentile items. Again, if there's a majority element, at least one of those would need to have the same value as the median.
Assuming you haven't ruled out there being a majority element yet, you can continue the search. For example, let's assume the 75th percentile was equal to the median, but the 25th percentile wasn't.
When then continue searching for the item halfway between the 25th percentile and the median, as well as the one halfway between the 75th percentile and the end.
Continue finding the median of each partition that must contain the end of the elements with the same value as the median until you've either confirmed or denied the existence of a majority element.
As an aside: I don't quite see how Boyer-Moore would be used for this task. Boyer-Moore is a way of finding a substring in a string.
There is, and it does not require the elements to have an order.
To be formal, we're dealing with multisets (also called bags.) In the following, for a multiset S, let:
v(e,S) be the multiplicity of an element e in S, i.e. the number of times it occurs (the multiplicity is zero if e is not a member of S at all.)
#S be the cardinality of S, i.e. the number of elements in S counting multiplicity.
⊕ be the multiset sum: if S = L ⊕ R then S contains all the elements of L and R counting multiplicity, i.e. v(e;S) = v(e;L) + v(e;R) for any element e. (This also shows that the multiplicity can be calculated by 'divide-and-conquer'.)
[x] be the largest integer less than or equal to x.
The majority element m of S, if it exists, is that element such that 2 v(m;S) > #S.
Let's call L and R a splitting of S if L ⊕ R = S and an even splitting if |#L - #R| ≤ 1. That is, if n=#S is even, L and R have exactly half the elements of S, and if n is odd, than one has cardinality [n/2] and the other has cardinality [n/2]+1.
For an arbitrary split of S into L and R, two observations:
If neither L nor R has a majority element, then S cannot: for any element e, 2 v(e;S) = 2 v(e;L) + 2 v(e;R) ≤ #L + #R = #S.
If one of L and R has a majority element m with multiplicity k, then it is the majority element of S only if it has multiplicity r in the other half, with 2(k+r) > #S.
The algorithm majority(S) below returns either a pair (m,k), indicating that m is the majority element with k occurrences, or none:
If S is empty, return none; if S has just one element m, then return (m,1). Otherwise:
Make an even split of S into two halves L and R.
Let (m,k) = majority(L), if not none:
a. Let k' = k + v(m;R).
b. Return (m,k') if 2 k' > n.
Otherwise let (m,k) = majority(R), if not none:
a. Let k' = k + v(m;L).
b. Return (m,k') if 2 k' > n.
Otherwise return none.
Note that the algorithm is still correct even if the split is not an even one. Splitting evenly though is likely to perform better in practice.
Addendum
Made the terminal case explicit in the algorithm description above. Some sample C++ code:
struct majority_t {
int m; // majority element
size_t k; // multiplicity of m; zero => no majority element
constexpr majority_t(): m(0), k(0) {}
constexpr majority_t(int m_,size_t k_): m(m_), k(k_) {}
explicit operator bool() const { return k>0; }
};
static constexpr majority_t no_majority;
size_t multiplicity(int x,const int *arr,size_t n) {
if (n==0) return 0;
else if (n==1) return arr[0]==x?1:0;
size_t r=n/2;
return multiplicity(x,arr,r)+multiplicity(x,arr+r,n-r);
}
majority_t majority(const int *arr,size_t n) {
if (n==0) return no_majority;
else if (n==1) return majority_t(arr[0],1);
size_t r=n/2;
majority_t left=majority(arr,r);
if (left) {
left.k+=multiplicity(left.m,arr+r,n-r);
if (left.k>r) return left;
}
majority_t right=majority(arr+r,n-r);
if (right) {
right.k+=multiplicity(right.m,arr,r);
if (right.k>r) return right;
}
return no_majority;
}
A simpler divide and conquer algorithm works for the case that there exists more than 1/2 elements which are the same and there are n = 2^k elements for some integer k.
FindMost(A, startIndex, endIndex)
{ // input array A
if (startIndex == endIndex) // base case
return A[startIndex];
x = FindMost(A, startIndex, (startIndex + endIndex - 1)/2);
y = FindMost(A, (startIndex + endIndex - 1)/2 + 1, endIndex);
if (x == null && y == null)
return null;
else if (x == null && y != null)
return y;
else if (x != null && y == null)
return x;
else if (x != y)
return null;
else return x
}
This algorithm could be modified so that it works for n which is not exponent of 2, but boundary cases must be handled carefully.
Lets say the array is 1, 2, 1, 1, 3, 1, 4, 1, 6, 1.
If an array contains more than half of elements same then there should be a position where the two consecutive elements are same.
In the above example observe 1 is repeated more than half times. And the indexes(index start from 0) index 2 and index 3 have same element.