This is a program to find median of two sorted arrays.
A divide and conquer based efficient solution to find median of two sorted arrays of same size.
#include<bits/stdc++.h>
using namespace std;
int median(int [], int); /* to get median of a sorted array */
/* This function returns median of ar1[] and ar2[].
Assumptions in this function:
Both ar1[] and ar2[] are sorted arrays
Both have n elements */
int getMedian(int ar1[], int ar2[], int n)
{
/* return -1 for invalid input */
if (n <= 0)
return -1;
if (n == 1)
return (ar1[0] + ar2[0])/2;
if (n == 2)
return (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1])) / 2;
int m1 = median(ar1, n); /* get the median of the first array */
int m2 = median(ar2, n); /* get the median of the second array */
/* If medians are equal then return either m1 or m2 */
if (m1 == m2)
return m1;
/* if m1 < m2 then median must exist in ar1[m1....] and
ar2[....m2] */
if (m1 < m2)
{
if (n % 2 == 0)
{
return getMedian(ar1 + n/2 - 1, ar2, n - n/2 +1);
}
return getMedian(ar1 + n/2, ar2, n - n/2);
}
/* if m1 > m2 then median must exist in ar1[....m1] and
ar2[m2...] */
if (n % 2 == 0)
return getMedian(ar2 + n/2 - 1, ar1, n - n/2 + 1);
return getMedian(ar2 + n/2, ar1, n - n/2);
}
/* Function to get median of a sorted array */
int median(int arr[], int n)
{
if (n%2 == 0)
return (arr[n/2] + arr[n/2-1])/2;
else
return arr[n/2];
}
/* Driver program to test above function */
int main()
{
int ar1[] = {1, 2, 3, 6};
int ar2[] = {4, 6, 8, 10};
int n1 = sizeof(ar1)/sizeof(ar1[0]);
int n2 = sizeof(ar2)/sizeof(ar2[0]);
if (n1 == n2)
printf("Median is %d", getMedian(ar1, ar2, n1));
else
printf("Doesn't work for arrays of unequal size");
return 0;
}
My question is how can I add a array variable to an integer. I means whether it is referring to memory when we do like this (ar1 + n/2 - 1) here in the getmedian function call ?
In expressions an array designator is implicitly converted to the pointer to its first element. Adding an integer to a pointer you will get again a pointer. It is so called the pointer arithmetic.
Thus for example if you have an array
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
then expression
a + N / 2
will point to the sixth element of the array.
Here is a demonstrative program
#include <stdio.h>
int main(void)
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ ) printf( "%p: %d\n", a + i, *( a + i ) );
return 0;
}
Its output might look like
0xbfd3d9c8: 0
0xbfd3d9cc: 1
0xbfd3d9d0: 2
0xbfd3d9d4: 3
0xbfd3d9d8: 4
0xbfd3d9dc: 5
0xbfd3d9e0: 6
0xbfd3d9e4: 7
0xbfd3d9e8: 8
0xbfd3d9ec: 9
Also a function parameter declared like an array is also adjusted to pointer. So for example these function declarations
int median(int a[100], int n);
int median(int a[10], int n);
int median(int a[], int n);
int median(int *a, int n);
are equivalent and declare the same one function.
Related
#include <bits/stdc++.h>
using namespace std;
/*Prototype for utility functions */
void printArray(int arr[], int size);
void swap(int arr[], int fi, int si, int d);
void leftRotate(int arr[], int d, int n)
{
/* Return If number of elements to be rotated
is zero or equal to array size */
if(d == 0 || d == n)
return;
/*If number of elements to be rotated
is exactly half of array size */
if(n - d == d)
{
swap(arr, 0, n - d, d);
return;
}
/* If A is shorter*/
if(d < n - d)
{
swap(arr, 0, n - d, d);
leftRotate(arr, d, n - d);
}
else /* If B is shorter*/
{
swap(arr, 0, d, n - d);
leftRotate(arr + n - d, 2 * d - n, d); /*This is tricky*/
}
}
/*UTILITY FUNCTIONS*/
/* function to print an array */
void printArray(int arr[], int size)
{
int i;
for(i = 0; i < size; i++)
cout << arr[i] << " ";
cout << endl;
}
/*This function swaps d elements starting at index fi
with d elements starting at index si */
void swap(int arr[], int fi, int si, int d)
{
int i, temp;
for(i = 0; i < d; i++)
{
temp = arr[fi + i];
arr[fi + i] = arr[si + i];
arr[si + i] = temp;
}
}
// Driver Code
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7};
leftRotate(arr, 2, 7);
printArray(arr, 7);
return 0;
}
// This code is contributed by Rath Bhupendra
I found this code on the geek for geeks website. The code is used to rotate the elements of an array. It is mentioned as block swap algorithm in the website, my questions are:
Can we add integers to an array in c++ as given in the else part of the left rotate function while passing the arguments (arr+n-d)?
How can we add integers to an array?
I tried adding an integer to an array in an online compiler and it didn't work. But the above code works perfectly giving the desired output 34567.
The link to the website is https://www.geeksforgeeks.org/block-swap-algorithm-for-array-rotation/.
Can we add integers to an array in c++ as given in the else part of the left rotate function while passing the arguments (arr+n-d)?
How can we add integers to an array?
The answer is you can't, and that's not what's happening here.
int arr[] argument decays to a pointer to the first element of the array. It's the same as having int* arr so what you are doing in arr + n - d is simple pointer arithmetic.
The pointer will be moved n - d positions relative to the position it's at before the expression is evaluated.
Supposing the result of n - d is 4, and arr is pointing to the beginning of the array passed as an argument, that is to &arr[0] (in array notation) or arr + 0 (in pointer notation), which is where it's pointing to in its inicial state, you'll have arr + 4 or &arr[4], after the evaluation, the expression provides access to the address of index 4 (the 5th element of the array). To access the value within that address you'd use *(arr + 4) or arr[4].
On a side note I wouldn't advise the use of geeksforgeeks.com to learn C++, or any other language, for that matter, this should be done by reading a good book.
A function parameter having an array type is adjusted by the compiler to pointer to the array element type. That is these two function declarations are equivalent and declare the same one function.
void leftRotate(int arr[], int d, int n);
and
void leftRotate(int *arr, int d, int n);
You even may write for example
void leftRotate(int arr[100], int d, int n);
void leftRotate(int arr[10], int d, int n);
void leftRotate(int arr[1], int d, int n);
Again these declarations declare the function
void leftRotate(int *arr, int d, int n);
So within the function this expression
arr + n - d
uses the pointer arithmetic applied to the pointer arr.
For example the expression arr + 0 is equivalent to arr and points to the first element of the array. The expression arr + n points to the n-th element of the array.
Here is a demonstrative program where there is used the pointer arithmetic to output elements of an array in a loop.
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
std::cout << *( a + i ) << ' ';
}
std::cout << '\n';
return 0;
}
The program output is
1 2 3 4 5
In the expression *( a + i ) the array designator a is implicitly converted to pointer to its first element.
Here is one more demonstrative program that shows that a function parameter having an array type is adjusted by the compiler to pointer to the array element type.
#include <iostream>
#include <iomanip>
#include <type_traits>
const size_t N = 100;
void f( int a[N] )
{
std::cout << "\nin function\n";
std::cout << "sizeof( a ) = " << sizeof( a ) << '\n';
std::cout << "a is a pointer " << std::boolalpha <<std:: is_same<decltype( a ), int *>::value << '\n';
}
int main()
{
int a[N];
std::cout << "In main\n";
std::cout << "sizeof( a ) = " << sizeof( a ) << '\n';
std::cout << "a is an array " << std::boolalpha <<std:: is_same<decltype( a ), int [N]>::value << '\n';
f( a );
return 0;
}
The program output is
In main
sizeof( a ) = 400
a is an array true
in function
sizeof( a ) = 8
a is a pointer true
I was asked to do sum of numbers in an array using recursion where sample input would be provided and the compiler gave me the following errors (note, I tried three ways and got the corresponding errors). Can someone please explain to me what I was doing wrong here?
Error for Code 1
In file included from Runner.cpp:2:0:
Solution.h: In function 'int sum(int*, int)':
Solution.h:7:32: error: invalid conversion from 'int' to 'int*' [-fpermissive]
totalsum = totalsum + sum(n+1,n-1);
^
Solution.h:1:5: note: initializing argument 1 of 'int sum(int*, int)'
int sum(int input[], int n) {
^
Error for code 2
Solution.h: In function 'int sum(int*, int)':
Solution.h:5:24: error: invalid conversion from 'int' to 'int*' [-fpermissive]
return input[0] + sum(n+1,n-1);
^
Solution.h:1:5: note: initializing argument 1 of 'int sum(int*, int)'
int sum(int input[], int n) {
^
Error for code 3
Runtime error
Code 1
int sum(int input[], int n) {
if (n<=0)
{
return 0;
};
int totalsum;
totalsum = totalsum + sum(n+1,n-1);
return totalsum;
}
Code 2
if (n<=0)
return 0;
return input[0] + sum(n+1,n-1);
Code 3
if (n <= 0)
return 0;
return (sum(input, n +1) + input[n - 1]);
In this function implementation
int sum(int input[], int n) {
if (n<=0)
{
return 0;
};
int totalsum;
totalsum = totalsum + `sum(n+1,n-1)`;
return totalsum;
}
the first parameter declared like int input[] has the type int *. However instead of the array you are passing the integer n + 1 as an argument in the recursive call
sum(n+1,n-1)
The same problem exists in this code snippet
if (n<=0)
return 0;
return input[0] + sum(n+1,n-1);
In the second code snippet it seems there is access memory beyond the array
return (sum(input, n +1) + input[n - 1]);
^^^^
And moreover the call has an infinite recursion because the second argument is always increased: n + 1.
The function can be written like
long long int sum( const int a[], size_t n )
{
return n == 0 ? 0 : a[0] + sum( a + 1, n - 1 );
}
Another approach is the following
long long int sum( const int a[], size_t n )
{
return n == 0 ? 0 :
( n == 1 : a[0] ? sum( a, n / 2 ) + sum( a + n / 2, n - n / 2 ) );
}
Here is a demonstrative program
#include <iostream>
long long int sum( const int a[], size_t n )
{
return n == 0 ? 0
: ( n == 1 ? a[0] : sum( a, n / 2 ) + sum( a + n / 2, n - n / 2 ) );
}
int main()
{
int a[] = { 1, 2,3, 4,5, 6, 7, 8, 9, 10 };
const size_t N = sizeof( a ) / sizeof( *a );
std::cout << sum( a, N ) << '\n';
return 0;
}
Its output is
55
For error for code 1, you are using an integer variable where it is expecting an array. To correct this, you would need to make n an index of some array. so the call would be something like sum(index[n+1], n-1) . Reason being is that arrays are pointers, pointers are arrays. so unless you have a pointer to an int variable, it will not work.
I'm trying to create a recursive function that finds the maximum number in an array between a low and a high integers.
I have tried this function that helps find the maximum element in array recursively. I'm just having trouble on how to add to the function that takes in a low and a high integers to find the max between those 2.
int findMaxRec(int A[], int n)
{
// if n = 0 means whole array has been traversed
if (n == 1)
return A[0];
return max(A[n-1], findMaxRec(A, n-1));
}
the goal is to have a function that looks something like this:
int findMaxBetwen(int A[], int low, int high){
//Here is where I need help integrating if lets say the array is A[] = 5,6,7,8
// Call findMaxBetwen(A[], 5, 8) and the output gives 7 because that is the max between the 3
//integers.
}
update: C++17 now defines a function std::size that can return the size of an array.
#include <iostream>
#include <iterator>
using namespace std;
int findMaxRec(const int[] A, const int &n)
{
if (n <= 0) throw "error: array is empty...";
if (n == 1) return A[0];
return std::max(A[n - 1], findMaxRec(A, (n - 1)));
}
int findMaxRec(const int[] A)
{
return findMaxRec(A, std::size(A));
}
const int& findMaxRec(const int &i)
{
return i;
}
If you dont have C++17, would you consider using a list?
#include <algorithm>
#include <list>
int findMaxRec(const std::list<int> &L)
{
if (L.size() == 0) throw "error: list is empty...";
return (*std::max_element(L.begin(), L.end()));
}
findMaxBetwen can be implemented as a function template:
template<typename T> int findMaxBetwen(const T &data, int low, int high)
{
int i = findMaxRec(data);
if (i <= low) return low;
if (i >= high) return high;
return i;
}
//....
int main(int argc, char** argv)
{
std::list<int> a = {5, 6, 7, 8, 10};
cout << findMaxBetween(a, 5, 8) << '\n'; // output is 8
int b[5] = {5, 6, 7, 8, 10};
cout << findMaxBetween(b, 5, 8) << '\n'; // output is 8
int c = 7;
cout << findMaxBetween(c, 5, 8) << '\n'; // output is 7
}
Learn more about function templates at cppreference
Before replying, please beware that both arrays are of different size and the requested complexity is O(min(log(n),log(m)), this question was never asked on stackoverflow.
I've been trying to modify a O(log(n+m)) solution to work but couldn't, the following solution searches for the kth (median of merged array) element, but the complexity is log(n+m).
In order to solve it in O(min(log(n),log(m))), we need to cut k/2 of the second array members as well on every recursion call.
Updated code:
int select(int *a, int *b, int sa, int sb, int k) {
int ma = sa < k/2 ? sa - 1 : k/2 - 1;
int mb = k - ma - 2;
if (sa + sb < k)
return -1;
if (sa == 0)
return b[k - 1];
if (sb == 0)
return a[k - 1];
if (k == 1)
return a[0] < b[0] ? a[0] : b[0];
if (a[ma] == b[mb])
return a[ma];
if (a[ma] < b[mb])
return select(a + ma + 1, b, sa - ma - 1, mb + 1, k - ma - 1);
return select(a, b + mb + 1, ma + 1, sb - mb - 1, k - mb - 1);
}
/*
median:
uses select to find the median of the union of a and b (where a and b are sorted
positive integer arrays of sizes sa and sb respectively).
*/
int median(int *a, int *b, int sa, int sb) {
int m1, m2;
if ((sa + sb) % 2 == 1)
return select(a, b, sa, sb, (sa + sb)/2 + 1);
return select(a, b, sa, sb, (sa + sb)/2);
}
int main() {
int a[3] = {2, 4, 6};
int b[11] = {1, 3, 5, 7, 13, 17, 22, 23, 24, 25, 31};
printf("\n median is %d\n", median(a, b, 3, 11));
return 0;
}
I'm trying to prove the time complexity and corectness of the algorithm with no luck.
Let's say we have two arrays A and B, of sizes m, and n respectively, with m <= n.
Then we have the following:
Lemma: The median of A and B is the same as the median of A and B', where B' is the middle m or m + 1 elements of B, depending on whether m and n have the same parity or not.
Now it only remains to use your O(log(m + n)) algorithm to find the median of A and B'.
Proof of the lemma: almost obvious ...
Having trouble wrapping my head around this conversion. I want to recursively convert a 2D NxN matrix into its z-order version.
For example given array:
[ 1 2 ]
[ 3 4 ]
The Z-order is
[ 1 2 3 4]
What are the steps recursively for the z-order conversion?
The recursive way is simple:
visit top-left
visit top-right
visit bottom-left
visit bottom-right
In code
#include <iostream>
template<typename M, typename CBACK>
void zorder(const M& m, int y0, int x0, int size,
CBACK cback)
{
if (size == 1) {
// Base case, just one cell
cback(m[y0][x0]);
} else {
// Recurse in Z-order
int h = size/2;
zorder(m, y0, x0, h, cback); // top-left
zorder(m, y0, x0+h, h, cback); // top-right
zorder(m, y0+h, x0, h, cback); // bottom-left
zorder(m, y0+h, x0+h, h, cback); // bottom-right
}
}
void print(int x) {
std::cout << x << " ";
}
int main(int argc, const char *argv[]) {
int x[][4] = {{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9, 10, 11, 12},
{13, 14, 15, 16}};
zorder(x, 0, 0, 4, print);
std::cout << std::endl;
return 0;
}
Output of this program is
1 2 5 6 3 4 7 8 9 10 13 14 11 12 15 16
Note that there is also another non-recursive approach: to visit the elements in z-order you can just iterate over a counter and take odd-bits as y and even-bits as x (counting bits from 0):
int zorder_x_of(int index) {
int x = 0;
for (int b=0,k=0; (1<<b) <= index; b+=2,k++) {
x += ((index & (1<<b)) != 0) << k;
}
return x;
}
int zorder_y_of(int index) {
return zorder_x_of(index>>1);
}
template<typename M, typename CBACK>
void zorder2(const M& m, int size, CBACK cback)
{
for (int i=0; i<size*size; i++) {
cback(m[zorder_y_of(i)][zorder_x_of(i)]);
}
}
Note:
In the above code samples I created a function that accepts a "callback" (named cback) that is something that will be called with the elements of the matrix, one at a time, in z-order.
To allow using both as matrix and as callback anything that supports double [] indexing and anything that can be called I used a C++ template.
In the main program as matrix I've used a bi-dimensional array of integers and a function, but the code would have compiled even for example with an std::vector< std::vector< double > > as matrix and an object instance of a class providing operator()(double) as callback.
A 2D matrix behaves internally as an 1D array i.e. it is already in "Z order".
Just iterate across the pointer that points to the first element up to NxM where N is the number of columns and M the number of rows.
example:
int arr[2][2] = {{2,4},{3,5}};
for (int i=0; i<2 * 2; ++i){
std::cout << *(&arr[0][0] + i); // or *(arr + i)
}