bsearch is pretty good for direct search, but what should I use if I need for example search range?
update
for example if i want to find range of values between a and b ( a >= x < b ).
update
range values can be not equal.
so if i have array(10,20,30) and i'm trying to find "15" i want to get address (pointer) to minimal range that is closest, in this example this is range (10,20)
One of the parameters bsearch takes is the number of elements to search. So instead of, for example, 100, make it search in 42 ...
bsearch("foo", data, /*100*/42, sizeof *data, cmpfx);
After the update
What I'd do is a manual (meaning I'd write the code) binary search.
The idea is to compare the middle element of the (remaining) array to both the lower and upper limit. If it's smaller then the lower limit search again in the small half; if it's larger than the upper limit search again in the big half; otherwise you've found an element in range.
After the 2nd update
You want to return a pair of pointers?
You have to wrap them inside a struct, or pass the addresses of the pointers to the functions ... or something.
But now you have a simpler search: search until you find the value (and return a 0-length range) or until you are about to fail. The range is between the array value you last looked at and, depending on exactly how you got to the fail situation, the value to one of the sides or EMPTY if you're at the end of the array.
The bsearch() function is designed to find a single element matching some condition. According to the man page:
RETURN VALUE
The bsearch() function returns a pointer to a matching member of the
array, or NULL if no match is found. If there are multiple elements
that match the key, the element returned is unspecified.
The key here is that if there are multiple elements that match the key, the element returned is unspecified. So you don't know if the element you get is the first, last, or somewhere in the middle of the range.
If you can change your requirements so that you're looking for elements in the array between A and B, and you can guarantee that there is exactly one A and exactly one B in the array, then you could first search for A then search for B.
start = bsearch(A, array, N, sizeof(*array), compare);
end = bsearch(B, array, N, sizeof(*array), compare);
You'll probably have to write your own function to do exactly what you're wanting.
Related
You are given a string array named strs with length n, when each string can have the value "good" or "bad". It is also known that exists index i so that:
0<=i<=n-1, strs[0]=strs[1]=...=strs[i-1]="good", strs[i]=strs[i+1]=...=strs[n-1]="bad".
Pay attention that if i=0, it means that strs has only strings with the value "bad".
Write an algorithm to find index i.
Desired run time: O(logn)
My attempt:
I'm sure you need to use binary search here, but for some reason I have a problem with the check of the middle element.
I thought of checking if the middle element has a value of "good" and the middle+1 element has a value of "bad", but this can give out of bounce error.
Any idea how to solve it?
In this answer over here, I explain that when you write a binary search, it's usually better to do a real binary search (making real binary decisions) to find the index where the element you're searching for belongs, and then check to see if it's actually there:
How can I simplify this working Binary Search code in C?
In your case, the index is your desired result, so you don't even need to check:
int findIndex(string[] array)
{
int minpos=0; //smallest possible answer (array is all bad)
int limit=array.length; //largest possible answer (array is all good)
while(minpos<limit)
{
//testpos is guaranteed to be >= minpos and < limit
int testpos = minpos+((limit-minpos)/2);
if (array[testpos].equals("good")) //test index is too low
minpos=testpos+1; //minpos always increases here
else
limit=testpos; //limit always decreases here
}
return minpos;
}
I have a general question in programming.
Suppose I have an array, I need to find the index K that divides the array into two parts L, R so that the value
|max (L) -max (R)| Is maximal.
max(L) is the highest number in the L part
K points to the first member in R
This seems to be a problem that reduces to only 2 viable candidates for a solution: either K splits off the first value from the rest, or the last value from the rest, giving you a small part of just one value, and a large part with the remaining values, including the maximum value.
Suppose the maximum value in the array can be found at index M, then one of the two parts will have that value and it will be Max(Part). The other part should have a maximum value that is as small as possible. Consequently that part should be reduced to just one value: adding one more value to that part could never decrease its maximum value.
If the overall maximum value is at one of the ends of the array, then there is no choice, and the small part will be chopped off the array at the other end of it.
When the overall maximum value is not at an end of the array, there are two possibilities: choose the one where the chopped off value will be the lowest. In other words, K will be either 1 or n-1 (in zero-based indexing), and this can be determined in constant time, i.e. O(1).
Actually to solve this question we can do it in constant time.
1.Since the list must be divided in two either list A or list B will contain the leftmost or rightmost element.
Adding values to our list can only increase the maximum element of a list, so it is never desirable to have a list of size larger than 1
So all we need to do is look at the head and tail, take the smallest A, and make the rest of the list B
For example consider 6,7,7,3,2,6,4
A = [4], (smallest head/tail), B = [6,7,7,3,2,6]
You can solve it in O(n) with some preparation:
Make two arrays, maxL[] and maxR[] equal in size to the original array
Walk the original array starting from the left, setting maxL[i] to the max value so far
Walk the original array again starting from the right, setting maxR[i] to the max value so far
Now walk both maxL[] and maxR[] in any direction, looking for k such that the value of ABS(maxL[k] - maxR[k]) is maximized; return k.
Im beginner in programming. My question is how to count number sequences in input array? For example:
input array = [0,0,1,1,1,1,1,1,0,1,0,1,1,1]
output integer = 3 (count one-sequences)
And how to calculate number sequences first and last indexes in input array? For example:
input array = [0,0,1,1,1,1,1,1,0,1,0,1,1,1]
output array = [3-8,10-10,12-14] (one first and last place in a sequence)
I tried to solve this problem in C with arrays. Thank you!
Your task is a good exercise to familiarize you with the 0-based array indexes used in C, iterating arrays, and adjusting the array indexes to 1-based when the output requires.
Taking the first two together, 0-based arrays in C, and iterating over the elements, you must first determine how many elements are in your array. This is something that gives new C programmers trouble. The reason being is for general arrays (as opposed to null-terminated strings), you must either know the number of elements in the array, or determine the number of elements within the scope where the array was declared.
What does that mean? It means, the only time you can use the sizeof operator to determine the size of an array is inside the same scope (i.e. inside the same block of code {...} where the array is declared. If the array is passed to a function, the parameter passing the array is converted (you may see it referred to as decays) to a pointer. When that occurs, the sizeof operator simply returns the size of a pointer (generally 8-bytes on x86_64 and 4-bytes on x86), not the size of the array.
So now you know the first part of your task. (1) declare the array; and (2) save the size of the array to use in iterating over the elements. The first you can do with int array[] = {0,0,1,1,1,1,1,1,0,1,0,1,1,1}; and the second with sizeof array;
Your next job is to iterate over each element in the array and test whether it is '0' or '1' and respond appropriately. To iterate over each element in the array (as opposed to a string), you will typically use a for loop coupled with an index variable ( 'i' below) that will allow you to access each element of the array. You may have something similar to:
size_t i = 0;
...
for (i = 0; i< sizeof array; i++) {
... /* elements accessed as array[i] */
}
(note: you are free to use int as the type for 'i' as well, but for your choice of type, you generally want to ask can 'i' ever be negative here? If not, a choice of a type that handles only positive number will help the compiler warn if you are misusing the variable later in your code)
To build the complete logic you will need to test for all changes from '0' to '1' you may have to use nested if ... else ... statements. (You may have to check if you are dealing with array[0] specifically as part of your test logic) You have 2 tasks here. (1) determine if the last element was '0' and the current element '1', then update your sequence_count++; and (2) test if the current element is '1', then store the adjusted index in a second array and update the count or index for the second array so you can keep track of where to store the next adjusted index value. I will let you work on the test logic and will help if you get stuck.
Finally, you need only print out your final sequence_count and then iterate over your second array (where you stored the adjusted index values for each time array was '1'.
This will get you started. Edit your question and add your current code when you get stuck and people can help further.
You are given an unsorted array of n integers, and you would like to find if there are any duplicates in the array (i.e. any integer appearing more than once).
Describe an algorithm (implemented with two nested loops) to do this.
The question that I am stuck at is:
How can you limit the input data to achieve a better Big O complexity? Describe an algorithm for handling this limited data to find if there are any duplicates. What is the Big O complexity?
Your help will be greatly appreciated. This is not related to my coursework, assignment or coursework and such. It's from the previous year exam paper and I am doing some self-study but seem to be stuck on this question. The only possible solution that i could come up with is:
If we limit the data, and use nested loops to perform operations to find if there are duplicates. The complexity would be O(n) simply because the amount of time the operations take to perform is proportional to the data size.
If my answer makes no sense, then please ignore it and if you could, then please suggest possible solutions/ working out to this answer.
If someone could help me solve this answer, I would be grateful as I have attempted countless possible solution, all of which seems to be not the correct one.
Edited part, again.. Another possible solution (if effective!):
We could implement a loop to sort the array so that it sorts the array (from lowest integer to highest integer), therefore the duplicates will be right next to each other making them easier and faster to be identified.
The big O complexity would still be O(n^2).
Since this is linear type, it would simply use the first loop and iterate n-1 times as we are getting the index in the array (in the first iteration it could be, for instance, 1) and store this in a variable names 'current'.
The loop will update the current variable by +1 each time through the iteration, within that loop, we now write another loop to compare the current number to the next number and if it equals to the next number, we can print using a printf statement else we move back to the outer loop to update the current variable by + 1 (next value in the array) and update the next variable to hold the value of the number after the value in current.
You can do linearly (O(n)) for any input if you use hash tables (which have constant look-up time).
However, this is not what you are being asked about.
By limiting the possible values in the array, you can achieve linear performance.
E.g., if your integers have range 1..L, you can allocate a bit array of length L, initialize it to 0, and iterate over your input array, checking and flipping the appropriate bit for each input.
A variance of Bucket Sort will do. This will give you complexity of O(n) where 'n' is the number of input elements.
But one restriction - max value. You should know the max value your integer array can take. Lets say it as m.
The idea is to create a bool array of size m (all initialized to false). Then iterate over your array. As you find an element, set bucket[m] to true. If it is already true then you've encountered a duplicate.
A java code,
// alternatively, you can iterate over the array to find the maxVal which again is O(n).
public boolean findDup(int [] arr, int maxVal)
{
// java by default assigns false to all the values.
boolean bucket[] = new boolean[maxVal];
for (int elem : arr)
{
if (bucket[elem])
{
return true; // a duplicate found
}
bucket[elem] = true;
}
return false;
}
But the constraint here is the space. You need O(maxVal) space.
nested loops get you O(N*M) or O(N*log(M)) for O(N) you can not use nested loops !!!
I would do it by use of histogram instead:
DWORD in[N]={ ... }; // input data ... values are from < 0 , M )
DWORD his[M]={ ... }; // histogram of in[]
int i,j;
// compute histogram O(N)
for (i=0;i<M;i++) his[i]=0; // this can be done also by memset ...
for (i=0;i<N;i++) his[in[i]]++; // if the range of values is not from 0 then shift it ...
// remove duplicates O(N)
for (i=0,j=0;i<N;i++)
{
his[in[i]]--; // count down duplicates
in[j]=in[i]; // copy item
if (his[in[i]]<=0) j++; // if not duplicate then do not delete it
}
// now j holds the new in[] array size
[Notes]
if value range is too big with sparse areas then you need to convert his[]
to dynamic list with two values per item
one is the value from in[] and the second is its occurrence count
but then you need nested loop -> O(N*M)
or with binary search -> O(N*log(M))
Here's the stumper:
Start with three arrays A, B and C with a total of 2n+1 entries.
Write an algorithm to sort all of the entries from all of the arrays
using only the following two methods:
X = sort(X) replaces the array X with the sorted version.
(X , Y) = doubleUp(X , Y) does nothing if X has more elements
than Y, otherwise it removes the first length(X) entries from Y
and appends them to the end of X.
Here's what I've tried so far. If two of the arrays are empty, then just use sort on the nonempty array.
If one of the arrays is empty, then I think I can use doubleUp to get one array to have just one thing and the other array to have everything else, and if that singleton array has the smallest (or largest) element, then that works. So I can use sort after I use doubleUp each time to make sure this happens. I coded this up in Maple and it worked for all the cases I checked.
I have no idea how to do it with 3 arrays though. Anyone have any ideas?
Sounds like nonsense. The total number of entries is odd. The only way to increase the length of an array is to make it the smaller first argument of doubleUp, in which case it ends up with an even number of elements. So unless all the elements are in one array to begin with there's no way to make one array contain all the elements, sorted or otherwise.
So, the desired final result is not a single array containing all the elements in order. Or if it is, then the answer to the question is "it cannot be done".