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;
}
Related
I need to convert this recursive function into tail recursive function but i am getting the wrong output can any help me out with this.
Here is the function definition:
f(n) = 3f(n − 1) - f(n − 2) + n,
with initial conditions f(0) = 1 and f(1) = 2.
#include <iostream>
using namespace std;
int headRecursion(int n) {
if(n == 0) {
return 1;
}
if (n == 1) {
return 2;
}
return 3 * headRecursion(n - 1) - headRecursion(n - 2) + n;
}
int main(){
cout << endl << headRecursion(3);
return 0;
}
This is kind of an interesting problem. We can start with how to implement as a loop:
int minus2 = 1;
int minus1 = 2;
if (n == 0) return minus2;
if (n == 1) return minus1;
for( int i = 2; i <= n; i++)
{
int next = minus1 * 3 - minus2 + i;
minus2 = minus1;
minus1 = next;
}
return minus1;
The takeaway is we need to count UP. In order to make this tail recursive we need to pass in our accumulators (there is no reason to do this other than to show off, but it adds nothing to readability or efficiency)
int tailRecursive(int minus2, int minus1, int step, int n)
{
if (step == n) return minus1;
return tailRecursive(minus1, minus1*3 - minus2 + step+1, step+1, n);
}
you can use an intermediate to set it up and handle the n==0 case.
int calcIt(int n) {
if (n == 0) return 1;
// step must start with 1, since we handled 0 above
return tailRecursive(1, 2, 1, n);
}
Something along these lines:
std::pair<int, int> next_result(std::pair<int, int> prev_result, int n) {
return {3*prev_result.first - prev_result.second + n, prev_result.first};
}
std::pair<int, int> tailRecursion(int n) {
if (n == 0) {
return {1, 0};
}
if (n == 1) {
return {2, 1};
}
return next_result(tailRecursion(n-1), n);
}
int compute(int n) {
return tailRecursion(n).first;
}
int main(){
std::cout << compute(3) << std::endl;
}
Demo
The key is that you need a function that computes a pair {f(n), f(n-1)} given the previously computed pair {f(n-1), f(n-2)}
Can anybody take a look at my CPP code?
It's from this problem: https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/
I feel very frustrated cuz though my python code works, my cpp code doesn't work as always. :pensive: Same idea, different results. It drives me crazy.
The correct output should be 15.
My Python code returns the right output 15 while my CPP code returns the wrong output 10.
My python code:
def cnt_days(weights, k):
total, cnt = 0, 1
for w in weights:
if total + w > k:
total = 0
cnt += 1
total += w
print(total, cnt)
return cnt
def shipWithinDays(weights, D):
left = max(weights)
right = max(weights) * len(weights) // D + 1
while left < right:
mid = left + (right - left) // 2
if cnt_days(weights, mid) > D:
left = mid + 1
else:
right = mid
return left
if __name__ == "__main__":
print(shipWithinDays([1,2,3,4,5,6,7,8,9,10], 5))
My cpp code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int cnt_days(vector<int>& weights, int K)
{
int total = 0, cnt = 1;
for (int w: weights)
{
if (total + w > K)
{
total = 0;
cnt++;
}
else total += w;
}
cout << total <<" "<< cnt << endl;
return cnt;
}
int shipWithinDays(vector<int>& weights, int D)
{
int maximum = *max_element(weights.begin(), weights.end());
int left = maximum;
int right = maximum * weights.size() / D + 1;
while (left < right)
{
int mid = left + (right - left)/2;
if (cnt_days(weights, mid) > D)
left = mid + 1;
else
right = mid;
}
return left;
}
int main()
{
vector<int> weights = {1,2,3,4,5,6,7,8,9,10};
int D = 5;
cout << shipWithinDays(weights, D) << endl;
return 0;
}
Maybe, you could binary search much simple for your c++ solution:
#include <vector>
class Solution {
public:
int shipWithinDays(std::vector<int>& weights, int d) {
int lo = 0;
int hi = INT_MAX;
for (int weight : weights) {
lo = max(lo, weight);
}
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
int required = 1;
int cur = 0;
for (int index = 0; index < weights.size() && required <= d; cur += weights[index++])
if (cur + weights[index] > mid) {
cur = 0;
required++;
}
if (required > d) {
lo = mid + 1;
} else {
hi = mid;
}
}
return lo;
}
};
Or with basic bitwise operations:
class Solution {
public:
int shipWithinDays(vector<int> &weights, int d) {
int lo = 0;
int hi = INT_MAX;
for (int weight : weights)
lo = max(lo, weight);
while (lo < hi) {
int mid = lo + ((hi - lo) >> 1);
int required = 1;
int cur = 0;
for (int index = 0; index < weights.size() && required <= d; cur += weights[index++])
if (cur + weights[index] > mid)
cur = 0, required++;
if (required > d)
lo = -~mid;
else
hi = mid;
}
return lo;
}
};
Similarly for python:
from typing import List
class Solution:
def shipWithinDays(self, weights: List[int], d: int) -> int:
lo, hi = max(weights), sum(weights)
while lo < hi:
mid = lo + ((hi - lo) >> 1) # or mid = (lo + hi) // 2 || mid = lo + (hi - lo) // 2
cur, required = 0, 1
for weight in weights:
if cur + weight > mid:
required += 1
cur = 0
cur += weight
if required > d:
lo = -~mid # simply lo = mid + 1
else:
hi = mid
return lo
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions, explanations, efficient algorithms with a variety of languages, and time/space complexity analysis in there.
remove the else
else total += w;
should be
total += w;
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.
Below is my C++ code for inserting into a heap. The value for k is inserted but it's inserted at the bottom. I expected it to heapify with that while loop.
void Insert(heap1* myHeap, int k)
{
(myHeap->size)++;
int i = myHeap->size;
while (i > 1 && myHeap->H[i/2].key < k)
{
myHeap->H[i].key = myHeap->H[i/2].key;
i = i/2;
}
myHeap->H[i].key = k;
}
I do have a heapify procedure that I tried to use for this before this attempt that I know works within my other heap procedures. I just can't get it to work within Insert so I went with the above route. Below is heapify just in case its useful:
void heapify(heap1* myHeap, int i)
{
int l = 2 * i;
int r = 2 * i + 1;
int largest;
if (l <= myHeap->size && myHeap->H[l].key > myHeap->H[i].key)
largest = l;
else
largest = i;
if (r <= myHeap->size && myHeap->H[r].key > myHeap->H[largest].key)
largest = r;
if (largest != i)
{
myHeap->H[i].key = myHeap->H[i].key + myHeap->H[largest].key;
myHeap->H[largest].key = myHeap->H[i].key - myHeap->H[largest].key;
myHeap->H[i].key = myHeap->H[i].key - myHeap->H[largest].key;
heapify(myHeap, largest);
}
}
If someone could lead me in the right direction on how to get it to restore its heap properties, I would largely appreciate it.
try using this code:
void insert(int heap[], int *n, int item){
(*n)++;
heap[*n] = item;
reheapify_upward(heap, *n);
}
void reheapify_upward(int heap[],int start){
int temp,parent;
if(start>1){
parent=start/2;
if(heap[parent]<heap[start]){
temp=heap[start];
heap[start]=heap[parent];
heap[parent]=temp;
reheapify_upward(heap,parent);
}
}
}
Hi I'm trying to implement a 2D range tree for rmq-ing, here's my code, i think it's not efficient enough, is there anything i can do for optimation.
ls contain list of y sorted on every node
rt contain a segment tree
p.fi.fi contain x coordinate
p.fi.se contain y coordinate
p.se contain id of the point
loc contain x node and y node for each id
vector<pii> ls[400005];
vector<int> rt[400005];
pair<pii,int> p[100005];
vector<pii> loc[100005];
inline void merge(int id,vector<pii> &res,vector<pii> &a,vector<pii> &b)
{
int la = 0;
int lb = 0;
int sa = SIZE(a);
int sb = SIZE(b);
while(la < sa || lb < sb)
{
if (la >= sa) {res.pb(b[lb]);loc[b[lb].se].pb(mp(id,SIZE(res)-1));lb++;}
else if (lb >= sb) {res.pb(a[la]);loc[a[la].se].pb(mp(id,SIZE(res)-1));la++;}
else
{
if (a[la] < b[lb]) {res.pb(a[la]);loc[a[la].se].pb(mp(id,SIZE(res)-1));la++;}
else {res.pb(b[lb]);loc[b[lb].se].pb(mp(id,SIZE(res)-1));lb++;}
}
}
}
inline void build_x(int n,int l,int r)
{
if (l == r)
{
ls[n].clear();
ls[n].pb(mp(p[l].fi.se,p[l].se));
rt[n].assign(SIZE(ls[n])<<2,0);
loc[p[l].se].pb(mp(n,0));
return;
}
int m = (l+r)>>1;
build_x((n<<1),l,m);
build_x((n<<1)+1,m+1,r);
ls[n].clear();
merge(n,ls[n],ls[(n<<1)],ls[(n<<1)+1]);
rt[n].assign(SIZE(ls[n])<<2,0);
}
inline int query_y(int nx,int n,int l,int r,int ly,int ry)
{
if (ly > ls[nx][r].fi || ry < ls[nx][l].fi) return 0;
if (ly <= ls[nx][l].fi && ls[nx][r].fi <= ry)
{
return rt[nx][n];
}
int res = 0;
int m = (l+r)>>1;
if (ly <= ls[nx][m].fi) MAX(res,query_y(nx,(n<<1),l,m,ly,min(ls[nx][m].fi,ry)));
if (ls[nx][m+1].fi <= ry) MAX(res,query_y(nx,(n<<1)+1,m+1,r,max(ls[nx][m+1].fi,ly),ry));
return res;
}
inline int query_x(int n,int l,int r,int lx,int rx,int ly,int ry)
{
if (lx > p[r].fi.fi || rx < p[l].fi.fi) return 0;
if (lx <= p[l].fi.fi && p[r].fi.fi <= rx)
{
return query_y(n,1,0,SIZE(ls[n])-1,ly,ry);
}
int res = 0;
int m = (l+r)>>1;
if (lx <= p[m].fi.fi) MAX(res,query_x((n<<1),l,m,lx,min(p[m].fi.fi,rx),ly,ry));
if (p[m+1].fi.fi <= rx) MAX(res,query_x((n<<1)+1,m+1,r,max(p[m+1].fi.fi,lx),rx,ly,ry));
return res;
}
int nx;
inline void update_y(int n,int l,int r,int fy,int v)
{
if (l == r)
{
MAX(rt[nx][n],v);
return;
}
int m = (l+r)>>1;
if (fy <= m) update_y((n<<1),l,m,fy,v);
else update_y((n<<1)+1,m+1,r,fy,v);
rt[nx][n] = max(rt[nx][(n<<1)],rt[nx][(n<<1)+1]);
}
i'm sorry if the code was a mess since it's my first implementation of range tree
My current implementation run for about 4s, but i need it to run less than 3s, here's my full implementation
Thanks :)