I've been working on a program that is supposed to test the performance of quick select algorithm under different group size setting. You find the pivot, the algorithm will divide all the elements into group of 5. Its supposed to find the median of each group and use the median of medians from all group as pivot. I'm having an issue with the smallest kth part. The errors that I'm getting is that n is not a constant variable so it cannot allocate the array and that it causes median to have an unknown size. What should I do to correct this?
int smallestKth(int ray[], int l, int r, int k)
{
if (k > 0 && k <= r - l + 1)
{
int n = r-l+1;
int i, median[(n+4)/5];
for (i=0; i<n/5; i++)
median[i] = medianFind(ray+l+i*5, 5);
if (i*5 < n)
{
median[i] = medianFind(ray+l+i*5, n%5);
i++;
}
int medOfMed = (i == 1)? median[i-1]:
smallestKth(median, 0, i-1, i/2);
int pivotPosition = part(ray, l, r, medOfMed);
if (pivotPosition-l == k-1)
return ray[pivotPosition];
if (pivotPosition-l > k-1)
return smallestKth(ray, l, pivotPosition-1, k);
return smallestKth(ray, pivotPosition+1, r, k-pivotPosition+l-1);
}
return INT_MAX;
}
int median[(n+4)/5]; is a nonstandard declaration supported by some compilers as an extension. Rather than using a Variable Length Array (VLA), you should use std::vector.
std::vector median((n+4)/5);
You don't need to make a new array to hold the medians. Just use a fifth of the original array.
One way to do that is to stride the array; represent the array as a starting pointer, a number of elements, and a stride, which is the distance between two consecutive elements. For example, once you've finished putting tbe median of each group of five in the right place in the array [start, n, stride], you can recurse on the array [start+2, (n+2)/5, 5*stride].
This was solved by creating a pointer for the median array.
int n = right-left+1;
int *median = new int[(n+4)/5];
Related
How can I count the number of longest increasing LIS by evolving my recursive solution for example [1,3,5,4,7] returns 2 where the LIS is 1,3,5,7 and 1,3,4,7similarly for [3,3,3,3] it will be 4 where LIS is 3 and there are 4 of them
I compute LIS recursively as follows: (I can optimize this using memoisation and go further to DP and then to a segmented tree as per various solutions but I would like to intuitively lead myself to them)
int numberOfLis(vector<int>& nums)
{
//Set the size of count to the size of num, since there cannot be an LIS greater than the size of nums
vector<int> count(nums.size(), 0);
//Get the size of the maximum LIS and update the frequency of how many similar sizes have been encountered in the count array
int maxcount = LIS(nums, INT32_MIN, 0, count);
//Return the number of occurances by looking it up in our count.
return count[maxcount];
}
int LIS(vector<int>& nums, int prev, int index, vector<int>& count)
{
if (index == nums.size()) return 0;
int with = 0;
//Increasing sequence, lets select it.
if (nums[index] > prev) with = 1 + helper(nums, nums[index], index + 1, count);
//See if we can do better without the current number
int without = helper(nums, prev, index + 1, count);
//Get the maximum seen so far and update the frequency in count array
int maxcount = max(with, without);
++count[maxcount];
return maxcount;
}
I used a count array vector<int>(nums.size(), 0) to increment the max value as I encounter it as ++count[max(with,without)] where the count of the returned max value would be the answer. This lead the count array to have 4 a count of 1 not 2 which is wrong. I am looking for a way to move forward from here.
Updated: Added code for the count array and added comments
The count for a subsequence is more than an increment, as there can be multiple subsequences that end up with the same length.
Working with your example data, when index is 1, both with and without are 3. count[3] is only incremented once, though, even though there are two subsequences with this length, and 3 is returned as the maximum length. When this is used by the previous call (when index is 0), with will be 4 and without 3. count[4] is only increased by 1, even though there are two subsequences of length 4.
You need to change helper to return not just the length of the longest subsequence, but the number of subsequences that have that length.
First, calculate the longest increasing subsequence length starting at kth element of the array.
Then, using this data use something like:
int numberoflis(int k){
if(LIS(k)==1) return 1;
int ret = 0;
for(int i=k+1; i<N; ++i){
if(A[i] > A[k] && LIS(i) == LIS(k)-1){
ret += numberoflis(i);
}
}
return ret;
}
Now you have number of longest increasing subsequences starting at point k. Use a simple loop to figure out the total number of LISs. Also, you should memoize this - but it is easy.
At the dynamic programming chapter in my algorithms textbook I have an example of how to solve the maximum sub array sum problem using this technique. I am not sure if I got the idea behind the algorithm so I will describe here how I think it works (after reading several times about it and doing several examples).
Basically, you have an array A of size n, and you want to find the maximum sub array sum of that array. The sub array with maximum sum can be somewhere in the right half of the array, left half, or somewhere in the middle. So you recursively call the function to compute the maximum sub array sum from the left and, then, from the right side of the array. Then, you compute the maximum sub array sum that from the middle of the array to the end, then compute the maximum sub array sum from the middle to the beginning of the array (it's length is not necessarily n/2). Then, if the sum of maximum sub array sum form left plus maximum sub array sum from the right is bigger than the maximum sub array sum from the left half (the one computed recursively ) and the maximum sub array sum from the right half (also computed recursively), then the maximum sub array sum is in the one in middle. Otherwise is the maximum of the one from left half and the one from right half (those were computed recursively).
Did I got the working mechanism of the algorithm?
This is the function that I was analyzing:
int maxSubArraySum(int* arr, int n)
{
if(n == 1)
{
return arr[0];
}
int m = n / 2;
int left = maxSubArraySum(arr, m);
int right = maxSubArraySum(arr + m, n - m);
int leftsum = INT_MIN, rightsum = INT_MIN, sum = 0;
for(int i = m; i < n; i++)
{
sum += arr[i];
rightsum = std::max(rightsum, sum);
}
sum = 0;
for(int i = (m - 1); i >= 0; i--)
{
sum += arr[i];
leftsum = std::max(leftsum, sum);
}
int retval = std::max(left, right);
return std::max(retval, leftsum + rightsum);
}
One does not need always Recursion to achieve dynamic programming. The Kadane's algorithm is a simple example of dynamic programming by breaking down the problem into subproblems reused n-1 times (compare the last so far maximum sub array to the current one n-1 times).
I have an array with n elements ,i need to calculate all n*n sum of pair of two elements (array[i]+array[j]).All sums are arranged in ascending order.I need to find Kth sum
for example:
array[] = {3,4,5}
all sums: {(3+3),(3+4),(4+3),(3+5),(5+3),(4+4),(4+5),(5+4),(5+5)}
K = 6
I need to find value for Kth sum ( in this case 6th sum is 4+4 ,i will return 8);
Solution might be very optimal
this is my solution; it isn't optimal:
for(i=0;i<n;i++)
fin>>a[i];
qsort(a, n, sizeof(int), int_cmp);
for(i=0;i<n;i++)
for(j=i;j<n;j++)
{
sum[k]=a[i]+a[j];
if(i!=j)
sum[++k]=a[i]+a[j];
k++;
}
qsort(sum, n*n, sizeof(int), int_cmp);
cout<<sum[nrs-1];
I have seen a similar kind of question from google interview question in that they use two sorted array instead of one but the solution works.One optimization which will work in O(klogk) can be given here.
To find the maximum value in such a case it is necessary to have calculated all the values lesser than it,ie let i,j be the maximum values in your case 5,5 to consider 5,5 to be max it is necessary to have evaluated both 4,5and 5,4.that is i-1,j and i,j-1 So a working code will be to use a heap in c++ it is a priority queue. The code is as follows
#include <iostream>
#include <queue>
using namespace std;
for(i=0;i<n;i++)
fin>>a[i];
qsort(a, n, sizeof(int), int_cmp);
std::priority_queue<int > heap;
heap.add(pair(n-1, n-1)); // biggest pair n=array size
// remove max k-1 times
for (int i = 0; i < k - 1; ++i) {
// get max and remove it from the heap
max = heap.pop();
// add next candidates
heap.push(pair(max.i - 1, max.j));
heap.push(pair(max.i, max.j - 1));
}
// get k-th maximum element
max = heap.pop();
maxVal = a[max.i] + a[max.j];
Now this one is optimized upto O(k.logk) there is another one which gives O(k).You can find it here.Kth sum in O(k)
So in my textbook there is this block of code to find the maximum element in an array by using the divide and conquer recursive algorithm:
Item max(Item a[], int l, int r)
{
if (l == r) return a[1];
int m = (l+r)/2;
Item u = max(a, l, m);
Item v = max(a, m+1, r);
if (u > v) return u; else return v;
}
For one of the questions following the code, it asks me to modify that program so that I find the maximum element in an array by dividing an array of size N into one part of size k = 2^((lgN)-1) and another of size N-k (so that the size of at least one of the parts is a power of 2.
So I'm trying to solve that, and I just realized I wouldn't be able to do an exponent in code. How am I supposed to implement dividing one array into size k = 2^((lgN)-1)?
Both logs and exponentials can be computed using functions in the standard library.
But a simple solution would be to start at 1 and keep doubling until you reach a number bigger than desired. Going back one step then give you your answer.
(Of course the whole idea is mad - this algorithm is much more complex and slower than the obvious linear scan. But I'll assume there is some method in the madness.)
This finds maximum k being a power of 2 and less than the number of array items (so the array part is divided into two non-empty parts):
Item max(Item a[], int l, int r)
{
if (l == r) return a[r];
int s = r-l, k = 1;
while (2*k <= s)
k = 2*k;
Item u = max(a, l, l+k-1);
Item v = max(a, l+k, r);
return u > v ? u : v;
}
However this is not necessarily the best possible choice. For example you might want to seek such k which is closest to the half of the array's length (for 10 items that would be k=4 instead of 8).
Or you may try to partition the array into two parts both with lengths being powers of 2 (if possible, for 10 items it would be 8+2)...
Given an array of values of length n, is there a way to count the number of swaps that would be performed by insertion sort to sort that array in time better than O(n2)?
For example :
arr[]={2 ,1, 3, 1, 2}; // Answer is 4.
Algorithm:
for i <- 2 to N
j <- i
while j > 1 and a[j] < a[j - 1]
swap a[j] and a[j - 1] //I want to count this swaps?
j <- j - 1
If you want to count the number of swaps needed in insertion sort, then you want to find the following number: for each element, how many previous elements inn the array are smaller than it? The sum of these values is then the total number of swaps performed.
To find the number, you can use an order statistic tree, a balanced binary search tree that can efficiently tell you how many elements in the tree are smaller then some given element. Specifically, an orde statistic tree supports O(log n) insertion, deletion, lookup, and count of how many elements in the tree are less than some value. You can then count how many swaps will be performed as follows:
Initialize a new, empty order statistic tree.
Set count = 0
For each array element, in order:
Add the element to the order statistic tree.
Add to count the number of elements in the tree less than the value added.
Return count,
This does O(n) iterations of a loop that takes O(log n) time, so the total work done is O(n log n), which is faster than the brute-force approach.
If you want to count the number of swaps in selection sort, then you can use the fact that insertion sort will only perform a swap on the kth pass if, after processing the first k-1 elements of the list, the element in position k is not the kth smallest element. If you can do this efficiently, then we have the following basic sketch of an algorithm:
Set total = 0
For k = 1 to n:
If the element at index k isn't the kth largest element:
Swap it with the kth largest element.
Increment total
Return total
So how do we implement this efficiently? We need to efficiently be able to check whether the element at a given index is the correct element, and also need to efficiently find the position of the element that really does belong at a given index otherwise. To do this, begin by creating a balanced binary search tree that maps each element to its position in the original array. This takes time O(n log n). Now that you have the balanced tree, we can augment the structure by assigning to each element in the tree the position in the sorted sequence that this element belongs. One way to do this is with an order statistic tree, and another would be to iterate over the tree with an inorder traversal, annotating each value in the tree with its position.
Using this structure, we can check in O(log n) time whether or not an element is in the right position by looking the element up in the tree (time O(log n)), then looking at the position in the sorted sequence at which it should be and at which position it's currently located (remember that we set this up when creating the tree). If it disagrees with our expected position, then it's in the wrong place, and otherwise it's in the right place. Also, we can efficiently simulate a swap of two elements by looking up those two elements in the tree (O(log n) time total) and then swapping their positions in O(1).
As a result, we can implement the above algorithm in time O(n log n) - O(n log n) time to build the tree, then n iterations of doing O(log n) work to determine whether or not to swap.
Hope this helps!
The number of interchanges of consecutive elements necessary to arrange them in their natural order is equal to the number of inversions in the given permutation.
So the solution to this problem is to find the number of inversions in the given array of numbers.
This can be solved in O(n log n) using merge sort.
In the merge step, if you copy an element from the right array, increment a global counter (that counts inversions) by the number of items remaining in the left array. This is done because the element from the right array that just got copied is involved in an inversion with all the elements in present in the left array.
I'm not sure, but I suspect finding the minimum number is a difficult problem. Unless there's a shortcut, you'll just be searching for optimal sorting networks, which you should be able to find good resources on with your favorite search engine (or Wikipedia).
If you only care about the big-O complexity, the answer is O(n log n), and you can probably get more concrete bounds (some actual constants in there) if you look at the analysis of some efficient in-place sorting algorithms like heapsort or smoothsort.
package insertoinSortAnalysis;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Solution {
private int[] originalArray;
public static void main(String[] args) {
Scanner sc;
try {
sc = new Scanner(System.in);
int TestCases = sc.nextInt();
for (int i = 0; i < TestCases; i++) {
int sizeofarray = sc.nextInt();
Solution s = new Solution();
s.originalArray = new int[sizeofarray];
for (int j = 0; j < sizeofarray; j++)
s.originalArray[j] = sc.nextInt();
s.devide(s.originalArray, 0, sizeofarray - 1);
System.out.println(s.count);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int[] devide(int[] originalArray, int low, int high) {
if (low < high) {
int mid = (low + high) / 2;
int[] result1 = devide(originalArray, low, mid);
int[] result2 = devide(originalArray, mid + 1, high);
return merge(result1, result2);
}
int[] result = { originalArray[low] };
return result;
}
private long count = 0;
private int[] merge(int[] array1, int[] array2) {
int lowIndex1 = 0;
int lowIndex2 = 0;
int highIndex1 = array1.length - 1;
int highIndex2 = array2.length - 1;
int result[] = new int[array1.length + array2.length];
int i = 0;
while (lowIndex2 <= highIndex2 && lowIndex1 <= highIndex1) {
int element = array1[lowIndex1];
while (lowIndex2 <= highIndex2 && element > array2[lowIndex2]) {
result[i++] = array2[lowIndex2++];
count += ((highIndex1 - lowIndex1) + 1);
}
result[i++] = element;
lowIndex1++;
}
while (lowIndex2 <= highIndex2 && lowIndex1 > highIndex1) {
result[i++] = array2[lowIndex2++];
}
while (lowIndex1 <= highIndex1 && lowIndex2 > highIndex2) {
result[i++] = array1[lowIndex1++];
}
return result;
}
}
Each swap in the insertion sort moves two adjacent elements - one up by one, one down by one - and `corrects' a single crossing by doing so. So:
Annotate each item, X, with its initial array index, Xi.
Sort the items using a stable sort (you can use quicksort if you treat the `initial position' annotation as a minor key)
Return half the sum of the absolute differences between each element's annotated initial position and its final position (i.e. just loop through the annotations summing abs(Xi - i)).
Just like most of the other answers, this is O(n) space and O(n*log n) time. If an in-place merge could be modified to count the crossings, that'd be better. I'm not sure it can though.
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[200001];
int te[200001];
unsigned long long merge(int arr[],int temp[],int left,int mid,int right)
{
int i=left;
int j=mid;
int k=left;
unsigned long long int icount=0;
while((i<=mid-1) && (j<=right))
{
if(arr[i]<=arr[j])
temp[k++]=arr[i++];
else
{
temp[k++]=arr[j++];
icount+=(mid-i);
}
}
while(i<=mid-1)
temp[k++]=arr[i++];
while(j<=right)
temp[k++]=arr[j++];
for(int i=left;i<=right;i++)
arr[i]=temp[i];
return icount;
}
unsigned long long int mergesort(int arr[],int temp[],int left,int right)
{
unsigned long long int i=0;
if(right>left){
int mid=(left+right)/2;
i=mergesort(arr,temp,left,mid);
i+=mergesort(arr,temp,mid+1,right);
i+=merge(arr,temp,left,mid+1,right);
}
return i;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
printf("%llu\n",mergesort(a,te,0,n-1));
}
return 0;
}