Strange expression in the return statement - c

I found a recursive function that left me a little surprised this function counts all negative numbers which appear in an array :
int count_negative(int arr[], int n)
{
if ( n > 0 )
return (*arr < 0) + count_negative( ++arr, n - 1 );
return 0;
}
Can someone explain this line :
return (*arr < 0) + count_negative( ++arr, n-1 );
Thank you

(*arr < 0) compares first element of the array with zero. The result of the expression can be either 1 (first element is negative) or 0 (first element is positive or zero). So, the number of negative elements is the sum of this expression and the number of negative elements in the tail of the array.

*arr points to the first element of arr array (or, more precisely, the part of the arr that has been passed to the function in this particular call).
count_negative( ++arr, n-1 ) is a recursive call but because of ++arr, inside this call we count the next element of the array and n-1 argument, togeher with the if ( n > 0 ) guarantees that we will count only elements inside the arr array.

The principle is that instead of keeping an index on the element being inspected, since arr is a pointer and modifying it will not change the data, one may instead use arr itself as the iterator on the array data.
So, *arr < 0 checks if the current pointed element is negative (it will yield 1 if so, 0 if not), and ++arr increments the cursor to the next place in the array, which is then passed on recursively to check the rest of the array.
This is a very well known idea in functional languages working with lists, where you often work on the first element of the list (the head) and recurse on the remaining of the list (the tail).

Related

Recursively iterate over an array without changing its size

I am currently trying to solve this problem in Java, but I do not want to set myself onto a specific language since I think of this as a "general" problem.
The conditions for the function I am looking for are:
the only values that can be modified are the values inside the array to be iterated over. Thus, for example, you can not use other variables that store any kind of information, such as indices (which by the way also eliminates the possibility of looping through the array). This also applies to function parameters. The only argument that is passed to the function is the array itself.
additionally to the previous point: memory space must be consistent. Therefore, you cannot copy the current array onto a bigger/smaller array.
However:
the array is an integer array
the function might return an integer value
the elements inside the array might be changed, but only after they are iterated over
the array does not have to be iterated in any kind of order, but every element has to be "reached" exactly once.
there exists a function that returns the length of the array
the signature might look like this (again, no specific language, but since I am currently working in Java, the signature is in Java syntax):
int iterate(int[] integerArray)
Is it possible to write such a function?
One attempt of mine was to traverse the array from index 0 to length(array) - 1, storing the current index at array[0], and exit if array[0] (or array[prev]) is length(array) - 1. So, in order to get the next array element, I would do something like array[array[0]] and increment the counter in array[0]. The major problem with this is that I have to somehow catch the first function call to iterate() in order to initialize array[0] with 0.
This is not a variable but a parameter (the only thing we can work with, otherwise I don't see how it could work), here an example to find max:
function findMax(arr, index = 0, max = Number.MIN_VALUE) {
if (index < arr.length)
return findMax(arr, index + 1, arr[index] > max ? arr[index] : max)
return max
}
console.log(findMax([7,9,2,8,6]))
Or another example with modification, reverse array (without variable for the swap, alternatively you could just write a helper function to do the swapping):
function reverseArray(arr, index = 0, value = arr[0]) {
if (index < arr.length) {
reverseArray(arr, index + 1, arr[index + 1]) // iterate over the whole array
// any modification here will happen after the whole array was iterated
if (index < arr.length / 2) {
arr[index] = arr[arr.length - index - 1]
arr[arr.length - index - 1] = value
}
}
return arr
}
console.log(reverseArray([7,9,2,8,6]))
If you are using a language where you cannot specify predefined values, then you can just overload the method or create a helper, e.g. java:
public int findMax(int[] arr) {
findMax(arr, 0, arr[0]);
}
private int findMax(int[] arr, int i, int max) {
if (i < arr.length)
return findMax(arr, i + 1, arr[i] > max ? arr[i] : max);
return max;
}

Algorithm Recursion Sorting

I have an algorithm :
ALGORITHM F_min1(A[0..n-1])
//Input: An array A[0..n-1] of real numbers
If n = 1
return A[0]
else
temp ← F_minl(A[0..n-2])
If temp ≤ A[n-1]
return temp
else
return A[n-1]
I suspect it sorts the array, but I don't know how exactly. I think it looks at the minimum element of the array except the last, compares them, and prints the greater one.
Almost; it returns the lesser, not the greater.
Also, it doesn't sort the array at all: it merely returns the smallest element.
In words, this reads something like:
If there is only one element, it must be the right one -- return it.
Otherwise,
recur: find the smallest element in all but the last one.
compare the last element to that minimum; return the smaller one.
When you return all the way to the initial call, you have the smallest element of the array.

How do you reorganize an array within O(n) runtime & O(1) space complexity?

I'm a 'space-complexity' neophyte and was given a problem.
Suppose I have an array of arbitrary integers:
[1,0,4,2,1,0,5]
How would I reorder this array to have all the zeros at one end:
[1,4,2,1,5,0,0]
...and compute the count of non-zero integers (in this case: 5)?
... in O(n) runtime with O(1) space complexity?
I'm not good at this.
My background is more environmental engineering than computer science so I normally think in the abstract.
I thought I could do a sort, then count the non-zero integers.
Then I thought I could merely do a element-per-element copy as I re-arrange the array.
Then I thought something like a bubble sort, switching neighboring elements till I reached the end with the zeroes.
I thought I could save on the 'space-complexity' via shift array-members' addresses, being that the array point points to the array, with offsets to its members.
I either enhance the runtime at the expense of the space complexity or vice versa.
What's the solution?
Two-pointer approach will solve this task and keep within the time and memory constraints.
Start by placing one pointer at the end, another at the start of the array. Then decrement the end pointer until you see the first non-zero element.
Now the main loop:
If the start pointer points to zero, swap it with the value pointed
by the end pointer; then decrement the end pointer.
Always increment the start pointer.
Finish when start pointer becomes greater than or equal to the end
pointer.
Finally, return the position of the start pointer - that's the number of nonzero elements.
This is the Swift code for the smart answer provided by #kfx
func putZeroesToLeft(inout nums: [Int]) {
guard var firstNonZeroIndex: Int = (nums.enumerate().filter { $0.element != 0 }).first?.index else { return }
for index in firstNonZeroIndex..<nums.count {
if nums[index] == 0 {
swap(&nums[firstNonZeroIndex], &nums[index])
firstNonZeroIndex += 1
}
}
}
Time complexity
There are 2 simple (not nested) loops repeated max n times (where n is the length of input array). So time is O(n).
Space complexity
Beside the input array we only use the firstAvailableSlot int var. So the space is definitely a constant: O(1).
As indicated by the other answers, the idea is to have two pointers, p and q, one pointing at the end of the array (specifically at the first nonzero entry from behind) and the other pointing at the beginning of the array. Scan the array with q, each time you hit a 0, swap elements pointed to by p and q, increment p and decrement q (specifically, make it point to the next nonzero entry from behind); iterate as long as p < q.
In C++, you could do something like this:
void rearrange(std::vector<int>& v) {
int p = 0, q = v.size()-1;
// make q point to the right position
while (q >= 0 && !v[q]) --q;
while (p < q) {
if (!v[p]) { // found a zero element
std::swap(v[p], v[q]);
while (q >= 0 && !v[q]) --q; // make q point to the right position
}
++p;
}
}
Start at the far end of the array and work backwards. First scan until you hit a nonzero (if any). Keep track of the location of this nonzero. Keep scanning. Whenever you encounter a zero -- swap. Otherwise increase the count of nonzeros.
A Python implementation:
def consolidateAndCount(nums):
count = 0
#first locate last nonzero
i = len(nums)-1
while nums[i] == 0:
i -=1
if i < 0:
#no nonzeros encountered
return 0
count = 1 #since a nonzero was encountered
for j in range(i-1,-1,-1):
if nums[j] == 0:
#move to end
nums[j], nums[i] = nums[i],nums[j] #swap is constant space
i -=1
else:
count += 1
return count
For example:
>>> nums = [1,0,4,2,1,0,5]
>>> consolidateAndCount(nums)
5
>>> nums
[1, 5, 4, 2, 1, 0, 0]
The suggested answers with 2 pointers and swapping are changing the order of non-zero array elements which is in conflict with the example provided. (Although he doesn't name that restriction explicitly, so maybe it is irrelevant)
Instead, go through the list from left to right and keep track of the number of 0s encountered so far.
Set counter = 0 (zeros encountered so far).
In each step, do the following:
Check if the current element is 0 or not.
If the current element is 0, increment the counter.
Otherwise, move the current element by counter to the left.
Go to the next element.
When you reach the end of the list, overwrite the values from array[end-counter] to the end of the array with 0s.
The number of non-zero integers is the size of the array minus the counted zeros.
This algorithm has O(n) time complexity as we go at most twice through the whole array (array of all 0s; we could modify the update scheme a little to only go through at most exactly once though). It only uses an additional variable for counting which satisfies the O(1) space constraint.
Start with iterating over the array (say, i) and maintaining count of zeros encountered (say zero_count) till now.
Do not increment the iterative counter when the current element is 0. Instead increment zero_count.
Copy the value in i + zero_count index to the current index i.
Terminate the loop when i + zero_count is greater than array length.
Set the remaining array elements to 0.
Pseudo code:
zero_count = 0;
i = 0;
while i + zero_count < arr.length
if (arr[i] == 0) {
zero_count++;
if (i + zero_count < arr.length)
arr[i] = arr[i+zero_count]
} else {
i++;
}
while i < arr.length
arr[i] = 0;
i++;
Additionally, this also preserves the order of non-zero elements in the array,
You can actually solve a more generic problem called the Dutch national flag problem, which is used to in Quicksort. It partitions an array into 3 parts according to a given mid value. First, place all numbers less than mid, then all numbers equal to mid and then all numbers greater than mid.
Then you can pick the mid value as infinity and treat 0 as infinity.
The pseudocode given by the above link:
procedure three-way-partition(A : array of values, mid : value):
i ← 0
j ← 0
n ← size of A - 1
while j ≤ n:
if A[j] < mid:
swap A[i] and A[j]
i ← i + 1
j ← j + 1
else if A[j] > mid:
swap A[j] and A[n]
n ← n - 1
else:
j ← j + 1

Question about a recursive function?

I have a recursive function from a C book as follows:
void print(int a[], int n)
{ if (n<=0) return ;
printf("%d\n", a[0]);
print(&a[1], n-1);
}
I have run and this function prints all the element of the specified array. But I really do not understand how this function works so that I can print all elements of an array.
Can anyone give me a clear explanation, please?
&a[1] is the address of the second element of the array, which is effectively the address of the portion of the array after the first element. So after printing the first element of the parameter array,
print(&a[1], n-1);
passes itself the remaining portion of the array, decreasing the length by one as well.
For example, if you call print with the array {1, 2, 3, 4, 5} and n == 5, the chain of events and calls is the following:
print the first element (1)
call itself with the remaining portion of the array, i.e. {2, 3, 4, 5} and n == 4
print the first element (2)
call itself with the remaining portion of the array, i.e. {3, 4, 5} and n == 3
print the first element (3)
call itself with the remaining portion of the array, i.e. {4, 5} and n == 2
print the first element (4)
call itself with the remaining portion of the array, i.e. {5} and n == 1
print the first element (5)
call itself with the remaining portion of the array, i.e. {} and n == 0
n<=0 -> return
return
return
return
return
return
This function takes as arguments the remaining part of the array and how many elements it contains. Every time you print the first element and then call recursively of the remaining part. Here is an example:
array: 1, 2, 3, 4, 5, 6; N = 6
array: 2, 3, 4, 5, 6; N = 5
array: 3, 4, 5, 6; N = 4
array: 4, 5, 6; N = 3
array: 5, 6; N = 2
array: 6; N = 1
array: ; N = 0 return;
Arrays are basically pointers to the start of the first element, so you code is essentially this:
void print(int *a, int n)
{ if (n<=0) return ;
printf("%d\n", *a);
print(a+1, n-1);
}
The recursive call is passing in a pointer to the next item in the array and decreasing the count, which is your used in your recursive termination condition.
So it does the following:
Check if there are any elements in the array, if not, just return.
Print the first element in the array since we know we have atleast one.
Calls itself again pointing to the 2nd element in the array, and subtracting 1 from the size, thus starting at #1 again.
A good way to understand recursion IMHO is to run the code in a debugger, and watch the call stack and variables.
How do you print a zero-sized array? Easy: you don't
That's your if (n<=0) return;
How do you print an array with 1 element? Easy: just print the element and remove it from the array and print the resulting zero-sized array as before
That's your printf("%d\n", a[0]);
How do you print an array with 2 elements? Easy: print the first element and remove it from the array and print the resulting one-sized array as before
That's your print(&a[1], n-1);
How do you print an array with N elements?
Easy: print the first element, remove it from the array, and print the resulting smaller array
If n is zero (or less), it does nothing, so recursion stops. If n > 0, then it prints a[0] and calls itself recursively with n-1 for n (so that goes to 0 as the recursion proceeds) and &a[1] for a, i.e. it increments the pointer a in each recursive call. Remember that an array argument in C is syntactic sugar for a pointer argument.
So, the code you posted is equivalent to:
void print(int *a, int n)
{
if (n > 0) {
printf("%d\n", *a);
print(a+1, n-1);
}
}
If you can verify to yourself that the following algorithm works to print an array, you should be able to understand why the C code works, since it's a direct translation.
To print n elements of an array:
If you're asked to print no elements, just stop.
Otherwise:
Print the first element, and then
Print n-1 elements of the rest of the array (using this same recipe).
it is equivalent to a loop:
int i ;
for (i = 0 ; i< n ; i++) {
printf("%d\n",a[i]);
}
why? well, the recursion always looks at the first element and prints it, and them advances to the next element by looking at the array from the 2nd element (which will now be the 'first', in the next iteration).
your stop condition is when no more elements are left - i.e. an array of length 0.
The function accepts an array and the length of the array.
if(n<=0) return;
If the length of the array is <=0 the function returns.
printf("%d\n", a[0]);
The first element of the array, element 0 is printed.
print(&a[1], n-1);
&a[1] gets a pointer to the first element of the array. Arrays and pointers are usable interchangably so when this is passed to the function the function can treat it as a new array, starting from the second element of the previous array, and with a length one less.
Each call to print do this :
print the n-th element of the array a and decrement the remaining elements (n) count to print.(Look at n like it means: how many elements remain to print).
Call it self decrementing (n - 1 : one less element to print) passing a pointer to the second element of the array (&a[1]) because the first element (a[0])has already be printed.
What exactly don't you understand?

Puzzle : finding out repeated element in an Array

Size of an array is n.All elements in the array are distinct in the range of [0 , n-1] except two elements.Find out repeated element without using extra temporary array with constant time complexity.
I tried with o(n) like this.
a[]={1,0,0,2,3};
b[]={-1,-1,-1,-1,-1};
i=0;
int required;
while(i<n)
{
b[a[i]]++;
if(b[a[i]==1)
required=a[i];
}
print required;
If there is no constraint on range of numbers i.e allowing out of range also.Is it possible get o(n) solution without temporary array.
XOR all the elements together, then XOR the result with XOR([0..n-1]).
This gives you missing XOR repeat; since missing!=repeat, at least one bit is set in missing XOR repeat.
Pick one of those set bits. Iterate over all the elements again, and only XOR elements with that bit set. Then iterate from 1 to n-1 and XOR those numbers that have that bit set.
Now, the value is either the repeated value or the missing value. Scan the elements for that value. If you find it, it's the repeated element. Otherwise, it's the missing value so XOR it with missing XOR repeat.
Look what is first and last number
Calculate SUM(1) of array elements without duplicate (like you know that sum of 1...5 = 1+2+3+4+5 = 15. Call it SUM(1)). As AaronMcSmooth pointed out, the formula is Sum(1, n) = (n+1)n/2.
Calculate SUM(2) of the elements in array that is given to you.
Subtract SUM(2) - SUM(1). Whoa! The result is the duplicate number (like if a given array is 1, 2, 3, 4, 5, 3, the SUM(2) will be 18. 18 - 15 = 3. So 3 is a duplicate).
Good luck coding!
Pick two distinct random indexes. If the array values at those indexes are the same, return true.
This operates in constant time. As a bonus, you get the right answer with probability 2/n * 1/(n-1).
O(n) without the temp array.
a[]={1,0,0,2,3};
i=0;
int required;
while(i<n)
{
a[a[i] % n] += n;
if(a[a[i] % n] >= 2 * n)
required = a[i] % n;
}
print required;
(Assuming of course that n < MAX_INT - 2n)
This example could be useful for int, char, and string.
char[] ch = { 'A', 'B', 'C', 'D', 'F', 'A', 'B' };
Dictionary<char, int> result = new Dictionary<char, int>();
foreach (char c in ch)
{
if (result.Keys.Contains(c))
{
result[c] = result[c] + 1;
}
else
{
result.Add(c, 1);
}
}
foreach (KeyValuePair<char, int> pair in result)
{
if (pair.Value > 1)
{
Console.WriteLine(pair.Key);
}
}
Console.Read();
Build a lookup table. Lookup. Done.
Non-temporary array solution:
Build lookup into gate array hardware, invoke.
The best I can do is O(n log n) in time and O(1) in space:
The basic idea is to perform a binary search of the values 0 through n-1, passing over the whole array of n elements at each step.
Initially, let i=0, j=n-1 and k=(i+j)/2.
On each run through the array, sum the elements whose values are in the range i to k, and count the number of elements in this range.
If the sum is equal to (k-i)*(k-i+1)/2 + i*(k-i+1), then the range i through k has neither the duplicate nor the omitted value. If the count of elements is less than k-i+1, then the range has the omitted value but not the duplicate. In either case, replace i by k+1 and k by the new value of (i+j)/2.
Else, replace j by k and k by the new value of (i+j)/2.
If i!=j, goto 2.
The algorithm terminates with i==j and both equal to the duplicate element.
(Note: I edited this to simplify it. The old version could have found either the duplicate or the omitted element, and had to use Vlad's difference trick to find the duplicate if the initial search turned up the omitted value instead.)
Lazy solution: Put the elements to java.util.Set one by one by add(E) until getting add(E)==false.
Sorry no constant-time. HashMap:O(N), TreeSet:O(lgN * N).
Based on #sje's answer. Worst case is 2 passes through the array, no additional storage, non destructive.
O(n) without the temp array.
a[]={1,0,0,2,3};
i=0;
int required;
while (a[a[i] % n] < n)   
a[a[i++] % n] += n;
required = a[i] % n;
while (i-->0)
a[a[i]%n]-=n;
print required;
(Assuming of course that n < MAX_INT/2)

Resources