Attaching what I've done; having a problem that the recursion sticks on the left recursive calls and can't continue to the right recursive calls. can't figure out how to return the recursion to the first position and continue the program to run towards the right recursive calls.
void minMax(int A[], int left, int right, int &min, int &max)
{
if (right == 0)
return;
if (A[(left + right) / 2] <= min)
min = A[(left + right) / 2];
if (A[((left + right) / 2)] >= max)
max = A[((left + right) / 2)];
if (right > 0)
minMax(A, left, (right - left) / 2, min, max);
if(left < right)
minMax(A, (right - left) / 2, right, min, max);
}
Similar approach as the merge sort :
Here is the recursive solution in C :
a is your array, i and j your left and right ...
void minmax (int* a, int i, int j, int* min, int* max) {
int lmin, lmax, rmin, rmax, mid;
if (i == j) {
*min = a[i];
*max = a[j];
} else if (j == i + 1) {
if (a[i] > a[j]) {
*min = a[j];
*max = a[i];
} else {
*min = a[i];
*max = a[j];
}
} else {
mid = (i + j) / 2;
minmax(a, i, mid, &lmin, &lmax);
minmax(a, mid + 1, j, &rmin, &rmax);
*min = (lmin > rmin) ? rmin : lmin;
*max = (lmax > rmax) ? lmax : rmax;
}
}
Although there are a lot of different and easier solutions ...
Edit by Question asker: ...because the question was about C++ program, this would be the C++ version
void minMax(int a[], int left, int right, int &min, int& max) {
int lmin, lmax, rmin, rmax, mid;
if (left == right)
{
min = a[left];
max = a[right];
}
else if (right == left + 1)
{
if (a[left] > a[right])
{
min = a[right];
max = a[left];
}
else
{
min = a[left];
max = a[right];
}
}
else
{
mid = (left + right) / 2;
minMax(a, left, mid, lmin, lmax);
minMax(a, mid + 1, right, rmin, rmax);
if (lmin > rmin)
min = rmin;
else
min = lmin;
if (lmax > rmax)
max = lmax;
else
max = rmax;
}
}
A simpler recursion is:
void minMax(int& A[], int index, const int& lenght, int& min, int& max)
{
if (A[index] < min) min = A[index]);
else if (A[index] > max) max= A [index];
if (++index < lenght) minMax(A, index, lenght, min, max);
}
In this case you just iterate through recursively, and not left-right.
Related
According to my calculations , the time complexity of this algorithm/code is O(logN) as it is an enhancement of binary search, but while submitting the code in leetcode and other platforms , it is said that the time limit is exceeded . they are also expecting the time complexity of this algorithm to be O(logN), so please confirm is the complexity of code written below is O(logN) or is it different from that?
class Solution {
public:
int findLast(vector<int> arr, int n, int x)
{
int l = 0;
int h = n - 1;
int mid;
while (h >= l) {
mid = (l + h) / 2;
if (arr[mid] == x) {
if (arr[mid + 1] != x) {
return mid;
}
else {
l = mid + 1;
}
}
else if (arr[mid] > x) {
h = mid;
}
else if (arr[mid] < x) {
l = mid + 1;
}
}
return -1;
}
int findFirst(vector<int> arr, int n, int x)
{
int l = 0;
int h = n - 1;
int mid;
while (h >= l) {
mid = (l + h) / 2;
if (arr[mid] == x) {
if (arr[mid - 1] != x) {
return mid;
}
else {
h = mid;
}
}
else if (arr[mid] > x) {
h = mid;
}
else if (arr[mid] < x) {
l = mid + 1;
}
}
return -1;
}
vector<int> searchRange(vector<int>& nums, int target)
{
int last = findLast(nums, nums.size(), target);
int first = findFirst(nums, nums.size(), target);
vector<int> v1 = { first, last };
return v1;
}
};
Your code's time complexity is O(∞) because it can perform an infinite loop.
Consider what happens when you run findLast on a one-element vector. You will have h, l, and mid equal to 0. If you enter the arr[mid] > x branch then you run h = mid; which leaves the variables unchanged, and repeats indefinitely.
Besides this, you should take the vector parameter by reference to avoid a copy which would make this a linear runtime.
Your code does not handle some corner cases where the input could be [1,1] and the target is 1. In findLast , the low and high variables would come to 1 and segmentation fault would occur when you check for arr[mid+1]. The same explanation would go for findFirst as well.
Try this and see if it helps:
int findLast(vector<int> arr, int n, int x)
{
int l = 0;
int h = n - 1;
int mid;
while (h > l)
{
mid = (l + h) / 2;
if (arr[mid] == x)
{
if (arr[mid + 1] != x)
{
return mid;
}
else
{
l = mid + 1;
}
}
else if (arr[mid] > x)
{
h = mid;
}
else if (arr[mid] < x)
{
l = mid + 1;
}
}
return arr[l] == x ? l : -1;
}
Link to Problem:- https://www.spoj.com/problems/GSS1
I am using Segment tree.
Node Information:-
maxSum --> maximum sum of the segment represented by node.
Sum ---> Total Sum of segment. (Although i think it's not needed)
maxPrefixSum ---> maximum prefix sum possible in segment. i.e starting from first element of segment.
maxSuffixSum ---> same as maxPrefixSum but starting from last element of segment.
Calculation of Node Values:-
("res" is new node, "left" and "right" are its left and right childs respectively)
res.Sum = left.Sum + right.Sum;
res.maxSum = max(max(left.maxSum, right.maxSum), left.maxSuffixSum + right.maxPrefixSum);
res.maxSuffixSum = max(left.maxSuffixSum + right.Sum, right.maxSuffixSum);
res.maxPrefixSum = max(left.maxPrefixSum, left.Sum + right.maxPrefixSum);
CODE
#include<bits/stdc++.h>
using namespace std;
#define int long long int
class node
{
public:
int Sum, maxSuffixSum, maxPrefixSum, maxSum;
node()
{
Sum = maxSuffixSum = maxPrefixSum = maxSum = 0;
}
};
node node_value(node left, node right)
{
node res;
res.Sum = left.Sum + right.Sum;
res.maxSum = max(max(left.maxSum, right.maxSum), left.maxSuffixSum + right.maxPrefixSum);
res.maxSuffixSum = max(left.maxSuffixSum + right.Sum, right.maxSuffixSum);
res.maxPrefixSum = max(left.maxPrefixSum, left.Sum + right.maxPrefixSum);
return res;
}
void makeSegmentTree(vector<int> arr, vector<node> &tree, int idx, int start, int finish)
{
if(finish == start)
{
tree[idx].Sum = tree[idx].maxPrefixSum = tree[idx].maxSuffixSum = tree[idx].maxSum = arr[start];
return;
}
int mid = start + (finish - start)/2;
makeSegmentTree(arr, tree, 2*idx, start, mid);
makeSegmentTree(arr, tree, 2*idx+1, mid+1, finish);
tree[idx] = node_value(tree[2*idx], tree[2*idx + 1]);
}
node queryTree(vector<node> &tree, int idx, int start, int finish, int left, int right)
{
if(start >= left && finish <= right)
{
return tree[idx];
}
else
{
int mid = start + (finish - start)/2;
if(start <= left && right <= mid)
{
return queryTree(tree, 2*idx, start, mid, left, right);
}
else if(left > mid && right <= finish)
{
return queryTree(tree, 2*idx+1, mid+1, finish, left, right);
}
else
{
node ans1 = queryTree(tree, 2*idx, start, mid, left, mid);
node ans2 = queryTree(tree, 2*idx+1, mid+1, finish, mid+1, right);
return node_value(ans1, ans2);
}
}
}
int32_t main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin>>n;
vector<int> arr(n+1, 0);
for(int i=1;i<n+1;i++)
{
cin>>arr[i];
}
vector< node > tree(4*n);
makeSegmentTree(arr, tree, 1, 1, n);
int q;
cin>>q;
while(q--)
{
int x, y;
cin>>x>>y;
cout<<queryTree(tree, 1, 1, n, x, y).maxSum<<endl;
}
return 0;
}
I've been working on this code for hours. The goal is to write an optimized QuickSort (with Insertion sort) on an array of pointers (which point to objects that can be compared). Insertion sort is supposed to be used with array sizes < 4.
So far, I have insertion sort working when I pass in an array < 4.
The quicksort is supposed to use the middle index as a pivot, and move everything < the pivot to the left of pivot, and everything > the pivot to the right of pivot.
I'm not even sure my overall approach to quickSort is correct. This is my first attempt at writing a quick sort. I could really use a nudge in the right direction here. The code that's commented out is something I've already tried.
If anything is unclear, let me know. Thanks for the help!
void quickSort(Comparable ** array, int fromIndex, int toIndex)
{
while (fromIndex < toIndex)
{
if ((toIndex - fromIndex +1 ) < 4)
{
insertionSort(array, fromIndex, toIndex);
break;
}
else
{
int pivotIndex = partition(array, fromIndex, toIndex);
quickSort(array, fromIndex, pivotIndex - 1);
quickSort(array, pivotIndex + 1, toIndex);
}
}
}
int partition(Comparable ** array, int fromIndex, int toIndex)
{
//Comparable *front = array[fromIndex+1];
int midIndex = (toIndex + fromIndex) / 2;
//int frontIndex = fromIndex;
//Comparable *back = array[toIndex - 1];
//int backIndex = toIndex - 1;
//Comparable *compare = front;
//int compareIndex = frontIndex;
SortFirstMiddleLast(array, fromIndex, midIndex, toIndex);
swap(array, midIndex, toIndex - 1);
int pivotIndex = toIndex - 1;
Comparable * pivot = array[pivotIndex];
int indexLeft = fromIndex + 1;
int indexRight = toIndex - 2;
bool sortFinished = false;
while (*array[indexLeft] < *pivot)
{
indexLeft++;
}
while (*array[indexRight] > *pivot)
{
indexRight--;
}
if ((*array[indexLeft] >= *pivot) && (*array[indexRight] <= *pivot))
{
if (indexLeft < indexRight)
{
swap(array, indexLeft, indexRight);
indexLeft++;
indexRight--;
sortFinished = true;
}
}
if (sortFinished == true)
{
swap(array, pivotIndex, indexLeft);
pivotIndex = indexLeft;
return pivotIndex;
}
// ++frontIndex; // advance to next element
// while (*array[frontIndex] < *array[backIndex])
// {
// // search forward for out of order element
// while ((*array[frontIndex] < *array[backIndex]) && (*array[fromIndex] > *array[frontIndex]))
// ++frontIndex;
// //search backward for out of order element
// while ((*array[frontIndex] < *array[backIndex]) && (*array[compareIndex] <= *array[backIndex]))
// --backIndex;
// swap(array, frontIndex, backIndex);
// }
// //insert mid position comparison element
// if (*array[compareIndex] >= *array[frontIndex])
// {
// swap(array, fromIndex, frontIndex);
// returnValue = frontIndex;
// }
// else
// {
// swap(array,fromIndex, (frontIndex - 1));
// returnValue = (frontIndex - 1);
// }
// return returnValue;
}
void swap(Comparable ** array, int swapIndex1, int swapIndex2)
{
Comparable * temp = array[swapIndex1];
array[swapIndex1] = array[swapIndex2];
array[swapIndex2] = temp;
}
void SortFirstMiddleLast(Comparable ** array, int fromIndex, int midIndex, int toIndex)
{
// first must be less than mid, must be less than last
if (*array[fromIndex] > *array[midIndex])
{
swap(array, fromIndex, midIndex);
}
if (*array[fromIndex] > *array[toIndex - 1])
{
swap(array, fromIndex, toIndex - 1);
}
if (*array[midIndex] > *array[toIndex - 1])
{
swap(array, midIndex, toIndex - 1);
}
}
void insertionSort(Comparable ** array, int fromIndex, int toIndex)
{
for (unsigned i = fromIndex + 1; i < toIndex; i++)
{
for (unsigned j = i; j > 0; j--)
{
if (*array[j] < *array[j - 1])
{
swap(array, j, j-1);
}
else
break;
}
}
}
I am trying to solve this question:
http://www.spoj.com/problems/FINDPATH/
Don't know where it's going wrong.
Firstly i am ignoring all the a[i] which are not divisors of destination, i.e., N
I am maintaining a map which maps each number to its parent and distance from root.
Then my idea is that i will be doing a bfs from '1' and then,
I am considering only those (q.top() * a[i]) that are <= N,
Then if queue contains (q.top() * a[i]) update the distance of (q.top() * a[i]) if distance(q.top()) + 1 < distance(q.top() * a[i])
else if the distances are equal then, if (q.top() < parent(q.top() * a[i]))
then update update parent(q.top() * a[i]) = q.top()
else if queue doesn't contain (q.top() * a[i]) then i am simply pushing it in queue.
Finally if a node N is present in the map then i print the distance and then the path using backtracking.
Here is my code:
int main() {
ll int n, m;
ll int x, top;
map<ll int, pair<ll int, ll int> >::iterator it, topit;
while (scanf("%lld %lld", &n, &m) != EOF) {
ve(ll int) v;
lp (i, 0, m) {scanf("%lld", &x); if (n % x == 0) v.pb(x);}
m = v.size();
map<ll int, pair<ll int, ll int> > s;
s.insert(mp(1, mp(1, 0)));
queue<ll int> q;
q.push(1);
while (!q.empty()) {
top = q.front();
q.pop();
topit = s.find(top);
lp (i, 0, m) {
if (top * v[i] <= n) {
it = s.find(top * v[i]);
if (it != s.end()) {
if ((*it).second.second > (*topit).second.second + 1) {
(*it).second.second = (*topit).second.second + 1;
(*it).second.first = top;
} else if ((*it).second.second == (*topit).second.second + 1) {
if (top < (*it).second.first) (*it).second.first = top;
}
} else {
s.insert(mp(top * v[i], mp(top, (*topit).second.second + 1)));
q.push(top * v[i]);
}
}
}
}
it = s.find(n);
ve(ll int) ans;
ans.pb(n);
if (it == s.end()) {
printf("-1\n");
} else {
printf("%lld\n", (*it).second.second);
while ((*it).second.first != 1) {
ans.pb((*it).second.first);
it = s.find((*it).second.first);
}
ans.pb((*it).second.first);
lpd (i, ans.size() - 1, 0) printf("%lld ", ans[i]);
printf("\n");
}
}
return 0;
}
Note: 1) lp (i, 0, m) : for (int i = 0; i < m; i++)
2) pb : push_back
3) ll : long long
4) lpd(i, n, 0) : for (int i = n; i>= 0; i--)
Is there any error in my approach ?
I'm trying to implement QuickSort() using random pivot
When I'm not randomizing pivot, and choosing it to be A[0] everything works fine,
but when I implement the randomization things are going crazy.
Partition:
int Partition(int A[], int left, int right, int pivot = 0)
{
swap(A[left], A[pivot]);
int temp = right;
while (pivot != temp)
{
// make a swap if needed
if (A[pivot] > A[temp] && temp > pivot || A[temp] > A[pivot] && temp < pivot)
{
// swap both data and index
swap(A[pivot], A[temp]);
swap(pivot, temp);
}
// advance the temp towards pivot
if (temp < pivot)
temp++;
else
temp--;
}
return pivot;
}
QuickSort:
void QuickSort(int A[], int left, int right)
{
int pivot;
if (left < right) {
// randomize pivot
srand(time(NULL));
pivot = rand() % (right - left + 1);
// partition and call quicksort
pivot = Partition(A, left, right, pivot);
QuickSort(A, left, pivot - 1);
QuickSort(A, pivot + 1, right);
}
}
Here is an issue:
pivot = rand() % (right - left + 1);
needs to be
pivot = left + rand() % (right - left + 1);