I have a question in the solution I'm referring for the below question
A magic index in an array A[l.. .n-l] is defined to be an index such
that A[i] = i. Given a sorted array of distinct integers, write a
method to find a magic index, if one exists, in array A.
The solution I'm referring looks like. Assume 's' stands for start and 'e' stands for end.
int fun(int a[], int s, int e)
{
if(s > e || s < 0 || e >= array.length)
return -1;
mid = (s + e)/2;
if(mid == a[mid])
return mid;
else if(mid < a[mid])
return fun(a, s, mid-1);
else
return fun(a, mid+1, e);
}
I'm not sure about the ending condition here.
I feel the ending condition should just be
if(s > e)
return -1;
Let's consider the two extreme cases when the magic index is not present
CASE 1 - going left till index 0
Say the array looks as follows a[] = {2,10,20,30,40,50}
mid = (0+6)/2 = 3 , call fun(0,2)
mid = (0+2)/2 = 1 , call fun(0,0)
mid = (0+0)/2 = 0 , call fun(0,-1)
since start > end, -1 is returned
CASE 2 - going right till the last element
Say the array looks as follows a[] = {-20,-10,-5,-4,-3,30,80}
mid = (0+6)/2 = 3 , call fun(4,6)
mid = (4+6)/2 = 5 , call fun(6,6)
mid = (6+6)/2 = 6 , call fun(7,6)
since start > end, -1 is returned
Moreover, I feel the extra conditions given in the solution can never be reached.
I feel s<0 cannot be reached because we are never subtracting anything from 's'. I feel the smallest value that 's' can take is 0. Maybe 'e' can be < 0, but not 's'
Also I feel e >= array.length is not possible since we are never adding anything to 'e'. Maybe 's' can be greater than or equal to array.length but not 'e'
Youre right s>e is enough. S can never be below zero since it's either preserved or equal to (s+e)/2+1>=s+1 (since e>=s), so it's always larger or equal to the initial value passed, which is zero. Similarly it can be shown that e<=n-1 always, so the extra conditions are redundant.
Related
I hope everyone is doing well.
I know there are a lot of questions whose title is very much similar to my question but I have a doubt regarding start and end values :-
If I use stopping condition as start<=end then, whether start=0 ,end=n/n-1|start=-1,end=n-1/n|start=-2 to end=n-2| start=-3 to end=n-3 **the output is same in all these cases for the below code
while(l<=r)
{
int mid=(l+r)/2;
if(arr[mid]==k)
return mid;
else if(k>arr[mid])
l=mid+1;
else
r=mid-1;
}
From start=-4 to end=-4 the result is wrong.
I've read the other questions and learned the fact that changing the stopping condition changes the range of start and end (inclusive/ exclusive ) but,
Why is binary search working for start=0/-1/-2/-3 to end=n/n+1/n+2/n+3? I mean apart from starting mid=(n-2+2)/2<=> n/2, there may be a condition when the target element appears at arr[0].
Thanks for spending your precious time in solving my query.
I hope I've written clearly.
If I use stopping condition as start<=end then, whether start=0 ,end=n/n-1|start=-1,end=n-1/n|start=-2 to end=n-2| start=-3 to end=n-3 the output is same in all these cases for the below code.
This is not true. start and end must start at precisely the first and last index of the array, or there will be cases where the algorithm you provided fails. So assuming zero-based array indexing, start = 0, end = n - 1 is the only correct initialisation for this algorithm.
Here are counter examples for some alternatives:
start = 0, end = n: if k is a value that is greater than the greatest value in arr, then eventually mid will become equal to n and arr[mid] will be an invalid reference. Depending on the language this may trigger an exception.
start = -1, end = n - 1: if k is a value that is less than the least value in arr, then eventually mid will become equal to -1 and arr[mid] will be an invalid reference.
start = -2, end = n - 2. if k == arr[0] and n == 3, the element will not be found, as mid will get the value -1.
start = -2, end = n + 2. if k == arr[0] and n == 3, the element will not be found, as mid will get the value 1 and in the next iteration it will be -1, so skipping for ever the index 0.
...etc
I was given the following question in an interview, and couldn't find the solution.
Given is an array of chars length n, and "important section" (all chars in this section must be saved) length m where n >= m >= 0 as follows:
Without extra space, perform the following process:
Remove all occurrences of A and duplicate all occurrences of B, return a sub array of the mutated array. For example, for the above array [C,A,X,B,B,F,Q] n=7, m=5 ,output will be [C,X,B,B,B,B]. Note that the mutated array length is 6, since Q was in the redundant section and B was duplicated.
Return -1 if the operation can't be performed.
Examples:
n=2, m=2 , [A,B] => [B,B]
n=2, m=2 , [B,B] => -1 (since the result [B,B,B,B] is larger then the array)
n=3, m=2 , [A,B,C] => [B,B]
n=3, m=3 , [A,B,C] => [B,B,C]
n=3, m=2 , [Z,B,A] => [Z,B,B] (since A was in the redundant section)
Looking for a code example, Could this be done in O(n) time complexity?
Scan array to determine if is it possible to store mutated array in available space -- count As and B, and check N-M >= numB-numA
Walk array left to right: Shift elements to the left by the number of As so far (filling places of A)
Walk array right to left: Shift elements to the right by numB-B_so_far, inserting additional Bs
Start from the end of the input array. We will figure out from the back to the front what to fill in.
Look at the last significant character in the input (position m). If it is a, ignore it. Otherwise, add the symbol. Repeat until you read all the input.
This removes as. Now we will duplicate bs.
Start from the beginning of the array. Find the last value you wrote during the above steps. If it is a b, write two bs. If it is something else, just write one of them. Repeat. NOTE: if you ever "catch up", needing to write where you need to read, you don't have enough room and you output -1. Otherwise, return the part of the array from position 1 to the last read position.
Example:
Phase 1: removing A
CAXBBFQ
CAXBBFB
CAXBBBB
CAXBXBB
CAXCXBB
Phase 2: duplicating B
CAXCXBB
CXXCXBB
CXBBXBB
CXBBBBB
^^^^^^
Phase 1 is linear (we read m symbols and write no more than m).
Phase 2 is linear (we read fewer than m symbols and write no more than 2m).
m is less than n so everything is O(m) and O(n).
The code, with some optimizations, would look something like this, O(n):
// returns length of the relevant part of the mutated array or -1
public static int mutate(char[] a, int m) {
// delete As and count Bs in the relevant part
int bCount = 0, position = 0;
for (int i = 0; i < m; i++) {
if (a[i] != 'A') {
if (a[i] == 'B')
bCount++;
a[position++] = a[i];
}
}
// check if it is possible
int n = bCount + position;
if (n > a.length)
return -1;
// duplicate the Bs in the relevant part
for (int i = position - 1, index = n - 1; i >= 0; i--) {
if (a[i] != 'B') {
a[index--] = a[i];
} else {
a[index--] = 'B';
a[index--] = 'B';
}
}
return n;
}
Given a sorted array of integers with possibly duplicates, how do you find an index i such that A[i]=i
This is a problem in one of the programming books I read (Cracking the code interview). The solution is outlined as follows:
public static int magicFast(int[] array, int start, int end) {
if (end < start || start < 0 || end >= array.length) {
return -1;
}
int midlndex = (start + end) / 2;
int midValue = array[midlndex];
if (midValue == midlndex) {
return midlndex;
}
/* Search left */
int leftlndex = Math.min(midlndex - 1, midValue);
int left = magicFast(array, start, leftlndex);
if (left >= 0) {
return left;
}
/* Search right */
int rightlndex = Math.max(midlndex + i, midValue);
int right = magicFast(array, rightlndex, end);
return right;
}
The author does not comment on the time complexity. However, this seems to be O(n) solution since we need to look at both sides of the 'mid' point unlike the problem where array elements are distinct. The recurrence relation being T(n) = 2T(n/2) + c (c - constant time to check if the middle element is the answer)
How is this better than a simple linear scan then? This seems overly complicated just to achieve linear time efficiency. Am I missing something here?
No, you're not missing anything. There's a short-circuit for the first branch, but the worst case is that both calls will be made, which results in a linear-time recurrence.
In fact, this problem has no sublinear-time algorithm by a simple cell probe lower bound. Consider the family of arrays a where
a(i) = i + 1 for i ≠ j
a(j) = j
for some j. These arrays are only distinguishable by examining the specific entry that is the fixed point, which implies a lower bound of n - 1 probes.
The original CTCI question I'm assuming did not allow duplicates -- then the modified array a(i) - i is nondecreasing, which allows binary search for the zero element.
I am trying to solve a variant of Knapsack Problem and have written a recursive solution for it. But my solution is returning a wrong value. I guess my algo is flawed. Can you please help me find the glitch.
Here is my code.
int calc_budget(int b, int i){
// If we have reached the end
if(i >= nParty){
tbl[b][i] = 0;
return tbl[b][i];
}
//If remaining capacity is not able to hold the ith capacity, move on to next element
if(budget[i] > b){
if(tbl[b][i+1] == 0){
tbl[b][i+1] = calc_budget(b,i+1);
}
return tbl[b][i+1];
}
else{ //If the ith capacity can be accomodated
//Do not include this item
if(tbl[b][i+1] == 0){
tbl[b][i] = calc_budget(b,i+1);
}
// Include this item and consider the next item
if(tbl[b-budget[i]][i+1] == 0){
tbl[b-budget[i]][i] = fun[i] + calc_budget(b-budget[i], i+1);
}
// We have the results for includinng ith item as well as excluding ith item. Return the best ( max here )
return max(tbl[b][i], tbl[b-budget[i]][i]);
}
}
Objective of the problem: To find the maximum fun by optimally using the given max budget
Following are my input.
budget[3] = {19,12,19}
fun[3] = {2,4,5}
calc_budget(30,0)
allowed budget: 30
The correct answer to the program should be 5. Mine is returning 7. I have drawn the recursion tree in the attempt to debug. My findings: While choosing item 0 ( right sub-tree), val = 2 + (11,1). This (11,1) will lead to max ( (11,2) and 0 ). (11,2) is 5 so the final result is 2+5 = 7. In this DP technique my algo should not have chosen 11,2 as sum of the budget exceeds the given one. But this is the basic skeleton I found for a recursive DP. Is this algo flawed or I have mistaken it.
Thanks
Chidambaram
The problem is that during the call calc_budget(b, i) you write fields of tbl for other indices than [b][i]. I will try to explain the issue by using the recursive definition of calc_budget(b, i).
We start by defining the recurrence relation. Let F(b, i) be the maximum fun you can have with the parties i, ..., n and the maximum budget b. Then,
F(b, n+1) = 0
F(b, i) = F(b, i+1) // if budget[i] > b
= max( F(b, i+1), fun[i] + F(b - budget[i], i+1) ) // otherwise
So far so good.calc_budget(b, i) should exactly calculate this number, and it should use tbl as a cache for already computed values. In other words, after the first time the call calc_budget(b, i) is made, tbl[b][i] == F(b, i) must be true.
Here's some pseudocode that achieves this:
initialize tbl[b][i] = -1 for all b, i.
def calc_budget(b, i):
if tbl[b][i] != -1: return tbl[b][i]
if i == n + 1:
tbl[b][n+1] = 0
else:
if budget[i] > b:
tbl[b][i] = calc_budget(b, i+1)
else:
tbl[b][i] = max(
calc_budget(b, i+1),
fun[i] + calc_budget(b - budget[i], i+1)
)
return tbl[b][i]
I hope you now agree that since tbl is really just a cache for already computed values, it would seem very odd to write e.g. tbl[b-budget[i]][i] in a call to calc_budget(b, i).
First, I do not think 0 is good enough to indicate weather a sub problem has been calculated before, because there are some sub problems whose answer is actually 0.
Second, there are a mistake in your code,you should have set the value of tbl[b][i] before you return the value.
Try this:
// We have the results for includinng ith item as well as excluding ith item. Return the best ( max here )
tbl[b][i]=max(tbl[b][i], tbl[b-budget[i]][i]);
return tbl[b][i];
Hope it helps!
Saw this question recently:
Given 2 arrays, the 2nd array containing some of the elements of the 1st array, return the minimum window in the 1st array which contains all the elements of the 2nd array.
Eg :
Given A={1,3,5,2,3,1} and B={1,3,2}
Output : 3 , 5 (where 3 and 5 are indices in the array A)
Even though the range 1 to 4 also contains the elements of A, the range 3 to 5 is returned Since it contains since its length is lesser than the previous range ( ( 5 - 3 ) < ( 4 - 1 ) )
I had devised a solution but I am not sure if it works correctly and also not efficient.
Give an Efficient Solution for the problem. Thanks in Advance
A simple solution of iterating through the list.
Have a left and right pointer, initially both at zero
Move the right pointer forwards until [L..R] contains all the elements (or quit if right reaches the end).
Move the left pointer forwards until [L..R] doesn't contain all the elements. See if [L-1..R] is shorter than the current best.
This is obviously linear time. You'll simply need to keep track of how many of each element of B is in the subarray for checking whether the subarray is a potential solution.
Pseudocode of this algorithm.
size = bestL = A.length;
needed = B.length-1;
found = 0; left=0; right=0;
counts = {}; //counts is a map of (number, count)
for(i in B) counts.put(i, 0);
//Increase right bound
while(right < size) {
if(!counts.contains(right)) continue;
amt = count.get(right);
count.set(right, amt+1);
if(amt == 0) found++;
if(found == needed) {
while(found == needed) {
//Increase left bound
if(counts.contains(left)) {
amt = count.get(left);
count.set(left, amt-1);
if(amt == 1) found--;
}
left++;
}
if(right - left + 2 >= bestL) continue;
bestL = right - left + 2;
bestRange = [left-1, right] //inclusive
}
}