Median of two sorted array - c++

Here I have written code for finding median of two sorted arrays:
#include<iostream>
using namespace std;
#define L 5
#define M 6
const int N=L+M;
int A[1000];//define 1 indexed aarray
int B[1000];
int max(int c,int d){
return (c>=d)?c:d;
}
int min(int c,int d)
{
return (c<=d)?c:d;
}
void read(){
cout<<" enter A array "<<endl;
for (int i=1;i<=L;i++)
cin>>A[i];
cout<<endl;
cout<<"enter B array "<<endl;
for (int i=1;i<=M;i++)
cin>>B[i];
cout<<endl;
}
int median(int a[],int b[],int left,int right){
if (left>right) {
return median(b,a,max(1,(N/2)-L),min(M,N/2));
}
int i=int(left+right)/2;
int j=int(N/2)+i;
if((j==0 || a[i]>b[j]) && (j==M || a[i]<=b[j+1])){
return a[i];
}
else
{
if((j==0 || a[i]>b[j]) &&(j!=M && a[i]>b[j+1]))
return median(a,b,left,i-1);
}
return median(a,b,i+1,right);
}
int main(){
return 0;
}
My question is what could be left and right values? It is from introduction to algorithms, I just don't understand what are values of left and right variables?
I have defined left and right as 1 and N and tested with following arrays:
3 5 7 9 11 13
1 2 4 8 10
Answer is 13, which is not correct sure, what is wrong?

The homework problem you cited in a comment has what looks to be a pretty good explanation of left and right, including the starting values for them:
Let the default values for left and right be such that calling
MEDIAN-SEARCH(A,B) is equivalent to
MEDIAN-SEARCH(A[1 ..l],B[1 ..m],max(1,ceil(n/2) - m),min(l,ceil(n/2)))
The invariant in MEDIAN-SEARCH(A,B) is that the median is always in
either A[left ..right] or B. This is true for the initial call because
A and B are sorted, so by the definition of median it must be between
max(1,ceil(n/2) - m) and min(l,ceil(n/2)), inclusive. It is also true
the recursive calls on lines 8 and 9, since the algorithm only
eliminates parts of the array that cannot be the median by the
definition of median. The recursive call on line 2 also preserves the
invariant since if left > right the median must be in B be­tween the
new left and right values.
If you work through the algorithm on paper with small arrays, it should become more clear what's going on. The algorithm converges in only a few steps if your arrays are smaller than a total of say 16 elements, so it should be quite workable on paper.

Please consider the following
std::cout << "enter all number separated by a space ending with 'q'"
<< std::endl;
std::vector<int> v(
(std::istream_iterator<int>(std::cin)),
std::istream_iterator<int>());
std::sort(v.begin(), v.end());
std::cout << "median value is: "
<< std::advance(v.begin(), v.size()/2);
<< std::endl;

Here is the code for finding the median of two sorted arrays of unequal length using the merge method of mergesort
package FindMedianBetween2SortedArrays;
import java.util.Scanner;
public class UsingMergeMethodOfMergeSort {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try{
System.out.println("Enter the number of elements in the first SORTED array");
int n = in.nextInt();
int[] array1 = new int[n];
System.out.println("Enter the elements of the first SORTED array");
for(int i=0;i<n;i++)
array1[i]=in.nextInt();
System.out.println("Enter the number of elements in the second SORTED array");
int m = in.nextInt();
int[] array2 = new int[m];
System.out.println("Enter the elements of the second SORTED array");
for(int i=0;i<m;i++)
array2[i]=in.nextInt();
System.out.println("Median of the two SORTED arrays is: "+findMedianUsingMergeOfMergeSort(array1,array2));
}
finally{
in.close();
}
}
private static int findMedianUsingMergeOfMergeSort(int[] a, int[] b) {
/* a1 array and a2 array can be of different lengths.
For Example:
1.
a1.length = 3
a2.length = 6
totalElements = 3+6=9 (odd number)
2.
a1.length = 4
a2.length = 4
totalElements = 4+4=8 (even number)
*/
int totalElements = a.length+b.length; // totalElements is the addition of the individual array lengths
int currentMedian = 0;
int prevMedian = 0;
int i=0; // Index for traversing array1
int j=0; // Index for traversing array2
for(int k=0;k<totalElements;k++){ // k is index for traversing the totalElements of array1 and array2
/*NOTE: In this entire for loop, the "if", "else" and "else if" is VERY IMP. DONOT interchange among them*/
// if array1 is exhausted
if(i==a.length)
currentMedian=b[j++]; // elements of the second array would be considered
// if array2 is exhausted
else if(j==b.length)
currentMedian=a[i++]; // elements of the first array would be considered
else if(a[i]<b[j])
currentMedian=a[i++];
else //(b[j]<=a[i]) // this condition is ONLY "else" and not "if" OR "else if"
currentMedian=b[j++];
if(k==totalElements/2) // we reached the middle of the totalElements where the median of the combined arrays is found
break;
prevMedian = currentMedian;
}
// if the totalElements are odd
if(totalElements%2!=0)
return currentMedian;
else
return (prevMedian+currentMedian)/2;
}
}
/*
Analysis:
Time Complexity = Linear Time, O((m+n)/2)
Space Complexity = O(1)
*/

class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
double median;
for(int i = 0; i<nums2.size();++i){
nums1.push_back(nums2[i]);
};
sort(nums1.begin(),nums1.end());
if(nums1.size()%2 == 0){
median = (double)(nums1[(nums1.size()/2)-1] + nums1[nums1.size()/2])/2;
}else{
if(nums1.size() == 1) median = nums1[0];
median = nums1[((nums1.size()/2) + (nums1.size()%2)) - 1];
}
return median;
};
};

Related

I don't understand how to calculate the sum of the sums of every possible sub-array using nested loops

The question the homework asks is:
Write a function, secondSmallestSum that when passed an int array of any length greater than 1 will calculate the sum of the elements of every possible sub-array and then return the second smallest sum found. It is possible for the smallest and second smallest sums to have the same value.
Sub-arrays are contiguous ranges of elements within an array. For example, if you have an array of length 4, {1,2,3,4}, then the complete set of sub-arrays is:
{1}, {1,2}, {1,2,3}, {1,2,3,4}, {2}, {2,3}, {2,3,4}, {3}, {3,4}, {4}
the sum of each sub-array is then:
1, 3, 6, 10, 2, 5, 9, 3, 7, 4
The main function for this problem must call your readNumbers function, then pass the new array to your secondSmallestSum function, display the second smallest sum found and finally delete the array.
My code so far prints numbers that the user inputs.
#include <iostream>
int *readNumbers(int n)
{
int *a = new int[n];
for (int i = 0; i < n; i++){
std::cin >> a[i];
}
return a;
}
int main()
{
int length = 5;
int *ptr = readNumbers(length);
printNumbers(ptr, length);
return 0;
}
I expect this array (AN EXAMPLE) {4,0,9} to output the sub-arrays of {4}, {4,0}, {4,0,9}, {0}, {0,9} and {9}. The sums for each array would output as: 4,4,13,0,9 and 9. The total sum is 39.
With a first look, it definitely occurs that let's run a double loop till the end of the array for each element and find the sums of element along with it.
That gives you the complexity of O(n2) roughly speaking
Now, do you want to add 3+4 for the 2nd iteration (when you're looping for 2) while you have already calculated for 1st iteration? I wouldn't...
So instead I would save those incremental additions like this:
for (int *i = ptr + l - 2; i >= ptr; i--) {
*i = *i + *(i+1);
}
This would give me {1,2,3,4} -> {10,9,7,4}
Now run the double loop:
for (int *i = ptr; i < ptr + l; i++) {
cout << *i << " ";
for (int *j = i+1; j < ptr + l; j++) {
cout << *i - *j << " ";
}
}
Now you have all the sums. and you can do all the required operations. For your example the second smallest: You can add the following code in that double loop
if (secondsmallest >= x) {
if (smallest >= x) {
secondsmallest = smallest;
smallest = x;
}else{
secondsmallest = x;
}
}
Find the correct place to add it and replace x with suitable notation :)
Cheers...
If you find this answer helpful - consider upvoting :)

Same Occurrence of two numbers in sub arrays (contiguous)

Given an array of integers ,find total number of contiguous sub-sequence that has same number of x and y.
For example array [1,2,1] for x=1 and y=2
ans = 2 for its two sub arrays [1,2] and [2,1].
Checking every contiguous sub-sequence is O(n^2) which is too inefficient. Any idea for improvements?
this is the code i have written
int get_total(int* a,int x,int y,int n){
int result=0;
for(int i=0;i<n;i++){
int x_c=0,y_c=0;
for(int j=i;j<n;j++){
if(a[j]==x){
x_c++;
}
if(a[j]==y){
y_c++;
}
if(x_c==y_c){
result++;
}
}
}
return result;
}
int main(){
int n,q;
cin >>n >>q;
int a[n];
for(int i=0;i<n;i++){
cin >>a[i];
}
while(q--){
int x,y;
cin >>x >>y;
cout <<get_total(a,x,y,n)<<"\n";
}
}
it runs in n^2 for every query.
max array size is 8*10^3 and max number of query is 10^5
Create an auxillary array x_y_diffs, which is essentially:
#(times_x_appeared_thus_far) - #(times_y_appeared_thus_far)
And can be calculated as:
x_y_diffs[0] = 0
x_y_diffs[i] = x_y_diffs[i-1] + 1 if array[i-1] == x
x_y_diffs[i-1] - 1 if array[i-1] == y
x_y_diffs[i-1] otherwise
It is easy to see it can be calculated in linear time.
Now, observe that a "good" subsequence (i,j) begins and ends where x_y_diffs[i+1] == x_y_diffs[j+1].
So, you can simply iterate the array and maintain a histogram counting how many times each value occurd.
std::map<int, int> histogram;
int count = 0;
for (int x : x_y_diffs) {
count += histogram[x];
histogram[x] = histogram[x] + 1;
}
This takes O(nlogn) time to calculate (each map insert/seek is O(logn)), and can be improved to O(n) average case by switching from std::map to std::unordred_map.
So, the algorithm is total O(n) or O(nlogn) time (based on map selection) - and O(n) additional space.
Demo on ideone

a function that takes an array A and index i and rearrange it

Question is: write a function that takes an array A of length n and an index i into A, and rearrange the elments such that all elements less than A[i] appear first, followed by elements equal to A[i], followed by elements greater than A[i].
explanation for my code:
Ask user for n numbers, which is 11. And ask him what the index that he wants to rearrange the elements with. It takes it to function1, and creates a for loop and does an if else statement. if A[i] < A{index} , place it in the begining, else if it's less, place it at the end, or place it in the middle:
Here is my code
#include <iostream>
using namespace std;
void function1(int a[], int ind);
int main()
{
int a[11];
int index;
cout << " enter the numbers: " << endl;
for(int i=0; i < 11; i++)
cin >> a[i];
cout << "what is the index ? " << endl;
cin >> index;
function1(a,index);
}
void function1(int a[], int ind)
{
int x = a[ind];
int newArray[11];
for(int i=0; i < 11; i++)
{
if(a[i] < x)
{
newArray[i] = a[i];
}
else if(a[i] > x)
{
newArray[10-i] = a[i];
}
else
{
newArray[10/2] = a[i];
}
}
for(int i=0; i<11; i++)
cout << newArray[i] << " ";
}
The output that I am expecting to get is the rearrangement of the new array which will probably look similar to this:
a[0....x....n-1], where x is the index that represents a[i]
however I am getting incorrect output with numbers randomly scattered across
what is wrong with my logic ?
The problem is that (like Olaf Dietsche pointed out) you take just one index where two are necessary. Further you can't know if the element that is neither smaller not bigger than a[ind] (means equal to a[ind]) is to be inserted in the middle of the new array. (Imagine 3 2 1 and index 3 results in 2 1 3 but 3 isn't in the middle!)
Updated Version (allows for multiple elements with same value as pivot element)
void rearange(int* data, int size, int pivot)
{
int* temp_data = new int[size];
int start_index = 0, end_index = size - 1;
for (int i = 0; i < size; i++)
{
if (data[i] < data[pivot]) // -> insert 'before' pivot element
{
temp_data[start_index] = data[i];
start_index++;
}
else if (data[i] > data[pivot]) // -> insert 'behind' pivot element
{
temp_data[end_index] = data[i];
endIndex--;
}
// else: skip pivot(s)
}
// insert pivot element(s)
for (int i = start_index; i <= end_index; i++)
{
temp_data[i] = data[pivot];
}
for (int i = 0; i < size; i++)
{
std::cout << temp_data[i] << " ";
}
delete[] temp_data;
}
Input:
11 10 9 8 7 7 7 6 5 4 3
5
Output
6 5 4 3 7 7 7 8 9 10 11
As you see, all elements smaller than element 5 (with value of 7) are before, all elements greater are behind the pivot element. All other elements with same value as pivot are wrapped around position 5, wherever there's free space. However the rearranged elements are not yet sorted (apart from being positioned relative to pivot element)!
You use the same index i for the smaller and larger values. This means, if only the last value a[10] is larger than x, you will write it in the first location newArray[10 - 10], even though you already filled all places up to the 10th. Another problem is, when you have multiple middle values. They will all be stored into newArray[5].
What you want to achieve is called partitioning, as used in the quicksort algorithm.
You need to maintain two indexes (pointers), one for the smaller (left) and one for the larger (right) values.
You have to determine the size of your array at the beginning and pass the fixed size of the array to the function as a parameter.

flowchart for the process of a recursive quick sort?

I am trying to make a flow chart for my recursive quick sort. I have got so far but not sure if right.
I am trying to show the detail in just a simple flowchart without any code in the flowchart.
This is what I have made so far but I am not sure it is right. What I am trying to find is that how and when does a quick sort know that it has been sorted. Then I can alter the text in the decision box in the flowchart to make more sense.
Here is my code with commenting if of any relevance.
#include <iostream>
using namespace std;
//this variable is the size of the array (amount of numbers in sort)
int const SIZE = 5;
// This function swaps two numbers, arguments for these 2 numbers
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
// This function prints an array, Arguments for the array to be printed and number of elements in array
void PrintArray(int* array, int n)
{
int i;
for( i = 0; i < n; i++) cout<<array[i]<<',';
}
// This function splits the array around the pivot
// Arguments; array to be split, pivot to be returned, first element and last element
int SplitArray(int* array, int pivot, int startIndex, int endIndex)
{
int leftBoundary = startIndex;
int rightBoundary = endIndex;
//shuffle pivot until both the boundaries meet
while(leftBoundary < rightBoundary)
{
//keep moving until a lesser element is found or until the leftBoundary is reached
while( pivot < array[rightBoundary]
&& rightBoundary > leftBoundary)
{
//shift left through the split section
rightBoundary--;
}
swap(array[leftBoundary], array[rightBoundary]);
//keep moving through the array until a greater or equal element is found or until the section end is reached
while( pivot >= array[leftBoundary]
&& leftBoundary < rightBoundary)
{
//shift right through the split section
leftBoundary++;
}
swap(array[rightBoundary], array[leftBoundary]);
}
//returns the split point of the array because the left and right boundary are equal
return leftBoundary;
}
//This function quicksorts the data with arguments for array and its first and last element
void QuickSort(int* array, int startIndex, int endIndex)
{
//set the pivot as the start of split array
int pivot = array[startIndex];
int splitPoint;
//if they are equal then there is only one element and the sorting has finished
if(endIndex > startIndex)
{
//gets the position of the pivot and sets data in that position to pivot variable
splitPoint = SplitArray(array, pivot, startIndex, endIndex);
array[splitPoint] = pivot;
//**RECURSION - Quick sort first half of the array (left of pivot point)
QuickSort(array, startIndex, splitPoint-1);
//**RECURSION - Quick sort second half of the array (right of pivot point)
QuickSort(array, splitPoint+1, endIndex);
}
}
//beggining of main program, makes use of the functions declared before this
int main()
{
int array[SIZE];
//input unsorted array elements
cout << "This program demonstrates a quick sort using a recursive algorithm" << endl;
for(int i = 0; i < SIZE; i++)
{
cout<<"Enter an integer : ";
cin>>array[i];
}
//output the unsorted list
cout<<endl<<"The list you input is : "<<endl;
PrintArray(array, SIZE);
//sort array from first to last element and output the sorted list
QuickSort(array,0,SIZE - 1);
cout<<endl<<"The list has been sorted, now it is : "<<endl;
PrintArray(array,SIZE);
//refresh the input stream and
cin.sync();
cin.get();
}

Radix Sort implemented in C++

I am trying to improve my C++ by creating a program that will take a large amount of numbers between 1 and 10^6. The buckets that will store the numbers in each pass is an array of nodes (where node is a struct I created containing a value and a next node attribute).
After sorting the numbers into buckets according to the least significant value, I have the end of one bucket point to the beginning of another bucket (so that I can quickly get the numbers being stored without disrupting the order). My code has no errors (either compile or runtime), but I've hit a wall regarding how I am going to solve the remaining 6 iterations (since I know the range of numbers).
The problem that I'm having is that initially the numbers were supplied to the radixSort function in the form of a int array. After the first iteration of the sorting, the numbers are now stored in the array of structs. Is there any way that I could rework my code so that I have just one for loop for the 7 iterations, or will I need one for loop that will run once, and another loop below it that will run 6 times before returning the completely sorted list?
#include <iostream>
#include <math.h>
using namespace std;
struct node
{
int value;
node *next;
};
//The 10 buckets to store the intermediary results of every sort
node *bucket[10];
//This serves as the array of pointers to the front of every linked list
node *ptr[10];
//This serves as the array of pointer to the end of every linked list
node *end[10];
node *linkedpointer;
node *item;
node *temp;
void append(int value, int n)
{
node *temp;
item=new node;
item->value=value;
item->next=NULL;
end[n]=item;
if(bucket[n]->next==NULL)
{
cout << "Bucket " << n << " is empty" <<endl;
bucket[n]->next=item;
ptr[n]=item;
}
else
{
cout << "Bucket " << n << " is not empty" <<endl;
temp=bucket[n];
while(temp->next!=NULL){
temp=temp->next;
}
temp->next=item;
}
}
bool isBucketEmpty(int n){
if(bucket[n]->next!=NULL)
return false;
else
return true;
}
//print the contents of all buckets in order
void printBucket(){
temp=bucket[0]->next;
int i=0;
while(i<10){
if(temp==NULL){
i++;
temp=bucket[i]->next;
}
else break;
}
linkedpointer=temp;
while(temp!=NULL){
cout << temp->value <<endl;
temp=temp->next;
}
}
void radixSort(int *list, int length){
int i,j,k,l;
int x;
for(i=0;i<10;i++){
bucket[i]=new node;
ptr[i]=new node;
ptr[i]->next=NULL;
end[i]=new node;
}
linkedpointer=new node;
//Perform radix sort
for(i=0;i<1;i++){
for(j=0;j<length;j++){
x=(int)(*(list+j)/pow(10,i))%10;
append(*(list+j),x);
printBucket(x);
}//End of insertion loop
k=0,l=1;
//Linking loop: Link end of one linked list to the front of another
for(j=0;j<9;j++){
if(isBucketEmpty(k))
k++;
if(isBucketEmpty(l) && l!=9)
l++;
if(!isBucketEmpty(k) && !isBucketEmpty(l)){
end[k]->next=ptr[l];
k++;
if(l!=9) l++;
}
}//End of linking for loop
cout << "Print results" <<endl;
printBucket();
for(j=0;j<10;j++)
bucket[i]->next=NULL;
cout << "End of iteration" <<endl;
}//End of radix sort loop
}
int main(){
int testcases,i,input;
cin >> testcases;
int list[testcases];
int *ptr=&list[0];
for(i=0;i<testcases;i++){
cin>>list[i];
}
radixSort(ptr,testcases);
return 0;
}
I think you're severely overcomplicating your solution. You can implement radix using the single array received in the input, with the buckets in each step represented by an array of indices that mark the starting index of each bucket in the input array.
In fact, you could even do it recursively:
// Sort 'size' number of integers starting at 'input' according to the 'digit'th digit
// For the parameter 'digit', 0 denotes the least significant digit and increases as significance does
void radixSort(int* input, int size, int digit)
{
if (size == 0)
return;
int[10] buckets; // assuming decimal numbers
// Sort the array in place while keeping track of bucket starting indices.
// If bucket[i] is meant to be empty (no numbers with i at the specified digit),
// then let bucket[i+1] = bucket[i]
for (int i = 0; i < 10; ++i)
{
radixSort(input + buckets[i], buckets[i+1] - buckets[i], digit+1);
}
}
Of course buckets[i+1] - buckets[i] will cause a buffer overflow when i is 9, but I omitted the extra check or readability's sake; I trust you know how to handle that.
With that, you just have to call radixSort(testcases, sizeof(testcases) / sizeof(testcases[0]), 0) and your array should be sorted.
To speed up the process with better memory management, create a matrix for the counts that get converted into indices by making a single pass over the array. Allocate a second temp array the same size as the original array, and radix sort between the two arrays until the array is sorted. If an odd number of radix sort passes is performed, then the temp array will need to be copied back to the original array at the end.
To further speed up the process, use base 256 instead of base 10 for the radix sort. This only takes 1 scan pass to create the matrix and 4 radix sort passes to do the sort. Example code:
typedef unsigned int uint32_t;
uint32_t * RadixSort(uint32_t * a, size_t count)
{
size_t mIndex[4][256] = {0}; // count / index matrix
uint32_t * b = new uint32_t [COUNT]; // allocate temp array
size_t i,j,m,n;
uint32_t u;
for(i = 0; i < count; i++){ // generate histograms
u = a[i];
for(j = 0; j < 4; j++){
mIndex[j][(size_t)(u & 0xff)]++;
u >>= 8;
}
}
for(j = 0; j < 4; j++){ // convert to indices
m = 0;
for(i = 0; i < 256; i++){
n = mIndex[j][i];
mIndex[j][i] = m;
m += n;
}
}
for(j = 0; j < 4; j++){ // radix sort
for(i = 0; i < count; i++){ // sort by current lsb
u = a[i];
m = (size_t)(u>>(j<<3))&0xff;
b[mIndex[j][m]++] = u;
}
std::swap(a, b); // swap ptrs
}
delete[] b;
return(a);
}
Since your values are ints in the range of 0 ... 1,000,000
You can create a int array of of size 1,000,001, and do the whole thing in two passes
Init the second array to all zeros.
Make a pass through your input array, and use the value as a subscript
to increment the value in the second array.
Once you do that then the second pass is easy.
walk through the second array, and each element tells you how many times that
number appeared in the original array. Use that information to repopulate
your input array.