'Is it possible to further optimize the time complexity this piece of calculation "(y^x)>(y&x)" in c++?(you are allowed to change the Boolean operation into other forms, for example this can also be written as log2(y)!=log2(x) and this gives the same Boolean output but this has a higher time complexity with c++ compiler)'enter code here
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int t;cin>>t;
while(t--){
int n;cin>>n;int A[n];
for(int i=0;i<n;i++){cin>>A[i];}
int q;cin>>q;
while(q--){
int l,r,x;
cin>>l>>r>>x;int count=0;
for(int i=l-1;i<r;i++){
if((A[i]^x)>(A[i]&x)){count++;}
}
cout<<count<<endl;
}
}
return 0;
}
'This is the code im trying to optimize.... Please help in any way possible (number of inputs cant be changed)'
(y^x)>(y&x) is equivalent to nlz(y) != nlz(x) where nlz is a function that returns the number of leading zeroes of its input.
Therefore in order to count how often (A[i]^x)>(A[i]&x) is true for items in the array A, we could make a small array N where N[j] is the number of elements with nlz(A[i]) == j in array A. Then the number of times that (A[i]^x)>(A[i]&x) is true is equivalent to n - N[nlz(x)].
That way there is no loop over A where it really matters. Creating the array N still requires a loop over A, but only once for each iteration of the outer loop, not for each individual x.
C++20 has the nlz function built in under the name std::countl_zero.
Related
I am trying to find the third highest number in the array with O(n) space and time complexity.
MY program is obviously wrong but that is not the problem.
My for loop in the thirdhighestnum function seem to running only 2 times. I can't seem to find the reason for it. Can anyone help me. Sorry for such basic question I am a beginner here.
#include<iostream>
using namespace std;
int thirdhighestnum(int a[],int size)
{
cout<<" "<<size<<endl;
int first=a[0],second=0,third=0;
for(int i=1;i<size;i++)
{
cout<<a[i]<<";"<<endl;
if(a[i]>first)
{
first=a[i];
if(a[i+1]>first)
{
second=first;
first=a[i+1];
if(a[i+2]>first)
{ third=second;
second=first;
first=a[i+2];
}
}
cout<<i<<endl
return third;
}
}
}
int main()
{ int num,a[10];
cout<<"Enter the elements in the array"<<endl;
for(int i=0;i<10;i++)
cin>>a[i];
cout<<"Third highest number is "<<thirdhighestnum(a,10)<<endl;
return 0;
}
It's the location of your return third statement. The moment any number is larger than the first number, it exits the thirdhighestnum function and returns a value. Put it outside your for loop and it should be fine.
Actually it is executing only one time i.e. the first iteration only. When i=1 then it prints a[1] i.e. 2; after that it prints i i.e. 1 so it appears as 2;1 here you think it is printing 2 numbers.
The main problem is your return third statement which terminates your for loop in first iteration only.
This is known as nth_element and library function can do this for you.
As for why your code fails, there is a flaw in your logic
for(int i=1;i<size;i++)
{
// some code
if(a[i]>first)
{
// some more code
cout<<i<<endl
return third;
}
}
So your code exits the first time a[i] is greater than first.
[edit - After reading comments]
The generic name for this type of algorithm is a QuickSelect. It is unlikely you will find a faster algorithm, as this has been the subject of years of academic study.
I have made a simple program of rotation of integers in a given array.
#include <iostream>
using namespace std;
int main()
{
int t;
cin>>t;
long i,j,n,k,l,m,x;
long a[1000000];
for(i=0;i<t;i++){
cin>>n;
cin>>k;
for(j=0;j<n;j++){
cin>>a[j];
}
for(m=0;m<k;m++){
x=a[0];
for(j=1;j<n;j++){
x=a[j]+x;
a[j]=x-a[j];
x=x-a[j];
}
a[0]=x;
}
for(j=0;j<n;j++){
cout<<a[j]<<" ";
}
cout<<endl;
}
return 0;
}
The question can be found here. My code processes the small inputs easily, but when the input reaches to the order of thousands it takes well over a second and it fails due to that. Any suggestions on how to solve this problem?
Some notes that can be used to speed things up:
Rotating by K, when K>N, is equivalent to rotating by K%N (as each rotation of N is an expensive no-op).
You don't actually need to generate the rotated array; you just need to print the values as they would appear in the rotated array.
In fact, you don't (necessarily) need to store all of the input in an array, but just the part that can't be printed until the last value in the array is read. (This would get the input and output intermingled if both were through the console, but not if at least one were a file.)
These can be used to turn your O(N^2) solution into an O(N) one.
I am learning dynamic programming.i'm trying to solve the following question :
Problem Introduction :
You are given a primitive calculator that can perform the following three operations with the current number
x: multiply x by 2, multiply x by 3, or add 1 to x. Your goal is given a positive integer n, find the minimum number of operations needed to obtain the number n starting from the number 1.
Task
Given an integer n, compute the minimum number of operations needed to obtain the number n
starting from the number 1.
The input consists of a single integer 1 < n < 10^6.
code
#include <iostream>
#include <climits>
#include<vector>
#include<list>
void primitive_calculator(int number)
{
std::vector<int> min_steps(number+1,INT_MAX);
std::list<int> path[number+1];
min_steps[0]=0; min_steps[1]=0;
path[0].push_back(0);
path[1].push_back(1);
for (int i=2 ; i<=number ; i++)
{
if(i%3==0)
{
if(min_steps[i/3] < min_steps[i])
{
min_steps[i]=min_steps[i/3]+1;
path[i]=path[i/3];
path[i].push_back(i);
}
}
if(i%2==0)
{
if( min_steps[i/2] < min_steps[i])
{
min_steps[i]=min_steps[i/2]+1;
path[i]=path[i/2];
path[i].push_back(i);
}
}
if( min_steps[i-1] < min_steps[i])
{
min_steps[i]=min_steps[i-1]+1;
path[i]=path[i-1];
path[i].push_back(i);
}
}
std::cout<<min_steps[number]<<"\n";
while(!path[number].empty())
{
std::cout<<path[number].front()<<" ";
path[number].pop_front();
}
}
int main()
{
int number;
std::cin>>number;
primitive_calculator(number);
return 0;
}
This program is failing for input number greater than 10^5 .Why so?
And how can i improve the code?
Your issue is on line:
std::list<int> path[number+1];
It creates an array of std::list variable on stack, so if the number is huge, the stack overflows and gets segment fault.
This code gets warning from GCC:
warning: ISO C++ forbids variable length array 'path' [-Wvla]
It is rejected by clang as well:
error: variable length array of non-POD element type 'std::list'
So do NOT define huge variables on stack.
Instead, what you should do is use std::vector, e.g. change the line to:
std::vector<std::list<int>> path(number+1);
Then your problem is solved.
i'm new to posting questions here but have been looking for answers for a long time. I've created this code to return the maximum element in the array x[]. I did get results but not all the test cases are passed. I have checked it multiple times, but got no clue ion what is to be done to correct it.
I'm doing this on part of my online training so the test case values aren't openly visible. This code generated 85.71% positive outcome. Please help me do 100%. Thank you.
The question is to create a function findMax(int n,int *a) to return the maximum element. WHERE
The first argument corresponds to the number of elements in the array.
The second argument corresponds to the pointer to an array.
#include<stdio.h>
int findMax(int n,int *a)
{
int i,max=a[0]=0;
for(i=1;i<=n;i++)
{
if(a[i]>max)
max=a[i];
}
return(max);
}
int main()
{
int i,x[16],k,max;
printf("Enter the number of elements in the array\n");
scanf("%d",&k);
printf("Enter the elements in the array\n");
for(i=1;i<=k;i++)
{
scanf("%d",&x[i]);
}
max=findMax(k,x);
printf("The maximum element in the array is %d",max);
return 0;
}
I'm a beginner in coding, so a simpler explanation might help. Thanks again
max=a[0]=0;
This sets both a[0] and max to 0.
The loop in main() populates the array starting with index 1. Setting a[0] to 0 here accomplishes absolutely nothing. That, in itself, is not a problem, but setting max to 0 is. This is because if all elements in the array that main() initializes are negative, then because max is initially set to 0, the returned maximum value will be 0 instead of the highest negative value in the array.
You should make the following changes.
1) Instead of populating x[1] through x[k], the loop in main() should populate x[0] through x[k-1]. Arrays in C and C++ are, traditionally, 0-based.
2) The loop in your function should be adjusted accordingly as well, and it should not set a[0] to 0, of course. It should simply set max=a[0].
#include<stdio.h>
int findMax(int i,int *a)
{
max=a[0]; // you were setting a[0] to zero
for(i=1;i<n;i++) // there are n numbers beginning from position 0
{
if(a[i]>max)
max=a[i];
}
return(max);
}
int main()
{
int i,x[16],k,max;
printf("Enter the number of elements in the array\n");
scanf("%d",&k);
printf("Enter the elements in the array\n");
for(i=0;i<k;i++)
{
scanf("%d",&x[i]);
}
max=findMax(k,x);
printf("The maximum element in the array is %d",max);
return 0;
}
In your code, you have set max=0. Consider the test case when all the numbers are negative, then your code will return 0 which is not correct.
Correct Approach:
Assign max to first element of array and check the condition for remaining elements.
If first element is maximum then it will be returned otherwise the updated maximum is returned (after being checked through loop).
as the title explains this is a program to find lcm of numbers between 1 to 20. i found an algorithm to do this, here's the link
http://www.cut-the-knot.org/Curriculum/Arithmetic/LCM.shtml
there is a java applet on the webpage that might explain the algorithm better
Problem: i wrote the code compiler shows no error but when i run the code the program goes berserk, i guess may be some infinite loopig but i can't figure it out for the life of me. i use turbo c++ 4.5 so basically if anyone can look at the code and help me out it would be great . thanks in advance
Algorithm:
say we need to find lcm of 2,6,8
first we find the least of the series and add to it the number above it, i.e the series become
4,6,8
now we find the least value again and add to it the intitial value in the column i.e 2
6,6,8
so the next iteration becomes
8,6,8
8,12,8
10,12,8
10,12,16
12,12,16
14,12,16
14,18,16
16,18,16
18,18,16
18,18,24
20,18,24
20,24,24
22,24,24
24,24,24
as you can see at one point all numbers become equal which is our lcm
#include<iostream.h>
/*function to check if all the elements of an array are equal*/
int equl(int a[20], int n)
{
int i=0;
while(n==1&&i<20)
{
if (a[i]==a[i+1])
n=1;
else
n=0;
i++;
}
return n;
}
/*function to calculate lcm and return that value to main function*/
int lcm()
{
int i,k,j,check=1,a[20],b[20];
/*loading both arrays with numbers from 1 to 20*/
for(i=0;i<20;i++)
{
a[i]=i+1;
b[i]=i+1;
}
check= equl(a,1);
/*actual implementation of the algorith*/
while(check==0)
{
k=a[0]; /*looks for the least value in the array*/
for(i=0;i<20;i++)
{
if(a[i+1]<k)
{
k=a[i+1]; /*find the least value*/
j=i+1; /*mark the position in array */
}
else
continue;
}
a[j]=k+b[j]; /*adding the least value with its corresponding number*/
check= equl(a,1);
}
return (a[0]);
/*at this point all numbers in the array must be same thus any value gives us the lcm*/
}
void main()
{
int l;
l=lcm();
cout<<l;
}
In this line:
a[j]=k+b[j];
You use j but it is unitialized so it's some huge value and you are outside of the array bounds and thus you get a segmentation fault.
You also have some weird things going on in your code. void main() and you use cout without either saying std::cout or using namespace std; or something similar. An odd practice.
Also don't you think you should pass the arrays as arguments if you're going to make lcm() a function? That is int lcm(int a[], int b[]);.
You might look into using a debugger also and improving your coding practices. I found this error within 30 seconds of pasting your code into the compiler with the help of the debugger.
Your loop condition is:
while(n==1&&i<20)
So your equl function will never return 1 because if n happens to be 1 then the loop will just keep going and never return a 1.
However, your program still does not appear to return the correct result. You can split the piece of your code that finds the minimum element and replace it with this for cleanliness:
int least(int a[], int size){
int minPos = 0;
for(int i=0; i<size ;i++){
if (a[i] < a[minPos] ){
minPos = i;
}
}
return minPos;
}
Then you can call it by saying j = least(a, 20);. I will leave further work on your program to you. Consider calling your variables something meaningful instead of i,j,k,a,b.
Your equl function is using array indices from 0-20, but the arrays only have 1-19
j in lcm() is uninitialized if the first element is the smallest. It should be set to 0 at the top of the while loop
In the following code, when i=19, you are accessing a[20], which is out of the bounds of the array. Should be for(i=0;i<19;i++)
for(i=0;i<20;i++) {
if(a[i+1]<k)
You are not actually using the std namespace for the cout. this should be std::cout<<l
Your are including iostream.h. The standard is iostream without the .h, this may not work on such an old compiler tho
instead of hard-coding 20 everywhere, you should use a #define. This is not an error, just a style thing.
The following code does nothing. This is the default behavior
else
continue;