I have an array e.g. {1,2,4,5,6}. I want my function to find biggest possible number X such that all numbers from 1,2,...,X-1 are in the array. In this case X=3. Numbers in an array could be from 0 to infinitty.
My attempt is:
int array(int* t, int r) {
int* a;
int m=0;
int i;
for(i=0;i<=r;i++){
a[i]=i;
if(a[i]==t[i])
m++;
}
return m;
}
I wanted to create an array from 1 to r, which is the length of an array, full of natural number i.e. {1,2,3...} . Then i wanted to compare it with the actual array t. If there is a match look for another one.
I have no idea why it does not work and how to fix it?
Anyway code does not work and i still have no idea how to fix this.
Still looking for an answer.
Update: I did something like:
int array(int* t, int r) {
for(int x=0;x<r;x++){
for(int y=0; y<r-1;y++){
if(t[y]>t[y+1]){
int temp=t[y+1];
t[y+1]=t[y];
t[y]=temp;
}
}
}
for (int i = 0; i != r; i++) {
if (t[i] != (i + 1)) {
return i + 1;
}
}
return r + 1;
}
However when in input array i have zero at some place e.g. {5,0,1,2} the function always, regardless of where the zero is placed returns 1. Why is that?
There are a number of issues with your code
int array(int* t, int r) {
int* a;
int m=0;
int i;
for(i=0;i<=r;i++){
a[i]=i;
if(a[i]==t[i])
m++;
}
return m;
}
a is uninitialized, i.e. it does not point to valid memory allocated by your program. You need to do int *a = new int[r]. Don't forget to do delete a before your function returns
i should go up to r - 1 not r. So i < r rather than i <= r
Here is some pseudocode which outlines a possible method of solving this. The result is zero if it couldn't find a valid range to start from.
Pseudocode (Fast, thanks to Kenny Ostrom)
let curr = 0
let lookup = std::unordered_set<int>
insert all your elements into lookup
Starting from 0 to n where n is the size of your array of elements
[Loop]
If curr + 1 is not in lookup break out of loop
Else set curr to curr + 1
[Loop End]
Finally return curr + 1
Pseudocode (Kinda fast depending on your sorting algorithm)
Sort the array (std::sort is always a good option)
Set some variable curr to 0
Starting at a0 to an, where ai is an element of your array at index i
[Loop]
If curr + 1 is not equal ai then break out of the loop
Else set curr to ai
[Loop End]
Finally return curr + 1
Pseudocode (Slow)
Set some variable curr to 0
Starting at a0 to an, where ai is an element of your array at index i
[Loop]
Starting at aj to an where j = 0
[Loop]
If curr + 1 is equal to aj then set curr to aj and break out of this loop
[Loop End]
If curr did not change, then break out of this loop
[Loop End]
Finally return curr + 1
You don't need extra array, you may just iterate until index mismatch your expectation:
int find_iota_end(const int* a, int size)
{
std::sort(a, a + size); // if initial array is not sorted.
for (int i = 0; i != size; ++i) {
if (a[i] != (i + 1)) {
return i + 1;
}
}
return size + 1;
}
Upon reflection, I think your original idea was pretty close to a good algorithm, if you fix the bugs, and completely ignore any value a[i] where that value is not in the range [1..r].
You must allocate actual memory for your second vector, and you need two independent loops. The first loop fills in the second vector, if the value is relevant. The second loop looks for the answer.
This gives you space O(n) because you only consider that many possible answers, and time O(n) because it just reads through length, twice.
Related
I'm trying to find runtime functions and corresponding big-O notations for two different algorithms that both find spans for each element on a stack. The X passed in is the list that the span is to be computed from and the S passed in is the list for the span. I think I know how to find most of what goes into the runtime functions and once I know what that is, I have a good understanding of how to get to big-O notation. What I need to understand is how to figure out the while loops involved. I think they usually involve logarithms, although I can't see why here because I've been going through with the worst cases being each element is larger than the previous one, so the spans are always getting bigger and I see no connection to logs. Here is what I have so far:
void span1(My_stack<int> X, My_stack<int> &S) { //Algorithm 1
int j = 0; //+1
for(int i = 0; i < X.size(); ++i) { //Find span for each index //n
j = 1; //+1
while((j <= i) && (X.at(i-j) <= X.at(i))) { //Check if span is larger //???
++j; //1
}
S.at(i) = j; //+1
}
}
void span2(My_stack<int> X, My_stack<int> &S) { //Algorithm 2
My_stack<int> A; //empty stack //+1
for(int i = 0; i < (X.size()); ++i) { //Find span for each index //n
while(!A.empty() && (X.at(A.top()) <= X.at(i))) { //???
A.pop(); //1
}
if(A.empty()) //+1
S.at(i) = i+1;
else
S.at(i) = i - A.top();
A.push(i); //+1
}
}
span1: f(n) = 1+n(1+???+1)
span2: f(n) = 1+n(???+1+1)
Assuming all stack operations are O(1):
span1: Outer loop executes n times. Inner loop upto i times for each value of i from 0 to n. Hence total time is proportional to sum of integers from 1 to n, i.e. O(n2)
span2: We need to think about this differently, since the scope of A is function-wide. A starts as empty, so can only be popped as many times as something is pushed onto it, i.e. the inner while loop can only be executed as many times as A.push is called, over the entirety of the function's execution time. However A.push is only called once every outer loop, i.e. n times - so the while loop can only execute n times. Hence the overall complexity is O(n).
Please help me in optimizing the code. Seems to be working fine for most of the result set, but performance wise its seems to be slow. How can I further optimize the code.
Assuming vector is v{1,3,6,4,1,2};
int solution(vector<int> &v) {
std::vector<int> v2,v3;
sort(begin(v),end(v));
v.erase(unique(begin(v),end(v)),end(v));
std::pair<std::vector<int>::iterator,std::vector<int>::iterator> p1= std::minmax_element(begin(v),end(v));
int last_ = *p1.second;
for(int i=0; i < last_; i++)
v2.push_back(i);
if(v2.size() ==0)
return 1;
set_symmetric_difference(begin(v),end(v),begin(v2),end(v2),std::back_inserter(v3));
auto up=upper_bound(begin(v3),end(v3),0);
return *up;
}
First, you code modifies the original vector which may or not be desirable.
Next as usual, think algorithm before code optimization. Once vector is sorted, find first positive number. If it is not 1, 1 is the solution.
If you have found number 1 in the sorted vector, just move forward:
if next number is number + 1, just iterate
if next number is > number + 1, the solution is number + 1
if you reach end of vector, the solution is last number in vector + 1
Cost: cost of the sort plus N in worst case, average N/2
EDIT: the following code allows to compute the answer in linear time, as opposed algorithms involving sorting. First notice that the answer is less than or equal N+1, where N is a size of V.
So let's create a vector of length N+1 vector<int> count(N+1), and iterate through all values in V, so for v in V such that v<N+1 we increase count[v]++. Finally go through all values in count and return first non zero index greater than 0. If all are more than zero, return N+1.
int solution(vector<int> &V){
int N = V.size();
vector<int> count(N + 1, 0);
for(auto i = V.begin(); i != V.end(); i++){
If (*i <= N) count[*i]++;
}
//now just find minimum value which doesn't occur in V
int answer = 0;
for(int i = 1; i < N + 1; i++){
answer++;
if (count[i] == 0){
break;
}
}
return answer;
}
I have the following pseudocode which a sequential search pseudocode and I am trying to understand what return -1 mean. why would we return -1 could someone please explain.
A[n] <-- K
i <-- 0
while A[i] != K do
i = i + 1
if(i<n)
return i;
else
return -1; //What is this mean ?
Returning -1 is a way of conveying the fact that the code reached the end without returning in the middle. Returning -1 in this case means that the element K does not exist in the array.
Note that returning 0 is not used for this purpose as it could mean the element is present at the 0th index. If your function was something which could return -1 at some point in the middle, some other return value to indicate failure would have been chosen.
If you were to search a sequence for an element, and return the index of that element, you'd want some way to show that the element wasn't found. A negative value is an invalid index in many languages, so returning -1 could only mean the element couldn't be found for one reason or another.
int index_of(const int *array, int sz, int elem) {
for (int i = 0; i < sz; ++i) {
if (array[i] == elem) { // found the element
return i; // return the index of the element
}
}
return -1; // couldn't find it
}
Then in the calling code you might have
int calling() {
int array[N];
// populate array with data ...
int idx = index_of(array, N, 4); // find where 4 is in the array
if (idx < 0) {
// 4 isn't in the array
} else {
// 4 IS in the array !
}
}
Given an array A of integers , I am trying to find out at a given position j , how many times A[j] occurs from every i=0 to i=j in A. I have devised a solution like below
map<int,int> CF[400005];
for(int i=0;i<n;++i)
{
cin>>A[i];
if(i!=0)
CF[i-1] = CF[i];
++CF[i][A[i]];
}
than I can answer each query in logn time. But this procedure uses too much memory. Is there any way of doing it using less memory?
for more clarification , you can see the problem I am trying to solve http://codeforces.com/contest/190/problem/D
Create an array B of the same size as A and a map C. For each j in B[j] keep track of the number of occurrences of A[j] before j. In C keep track of the last occurrence of given element. Then you answer queries in constant time and it requires just O(n) memory.
Sorry for my pseudo-C++.
map<int,int> C;
int B[n]; // zeros
for(int i=0;i<n;++i)
{
cin >> A[i];
int prev = C[A[i]]; // let me assume it gives -1 if no element
if (pref == -1) // this is the fist occurrence of B[i]
B[i] = 1;
else // if not the first, then add previous occurrences
B[i] = B[prev] + 1
C[A[i]] = i; // keep track where the last info about A[j] is
}
Didn't give this too much time, but maybe instead of using a map will all the positions, use a list where for each element you put the points where the count of that element changes, something towards this:
struct count_info
{
int index;
int count;
count_info* next;
};
...
std::map<int, count_info*> data;
, and then look up the right position in that queue. You still need one map, but then underneath you would only have a list of these pointers, and on query you look-up the A[i] in the map, and then go through the list while i > index && next && i < next->index. Of course, if logn is a must then this fails because the list look-up is n at worst.
I'm trying to make a function to get the 3 biggest numbers in a vector. For example:
Numbers: 1 6 2 5 3 7 4
Result: 5 6 7
I figured I could sort them DESC, get the 3 numbers at the beggining, and after that resort them ASC, but that would be a waste of memory allocation and execution time. I know there is a simpler solution, but I can't figure it out. And another problem is, what if I have only two numbers...
BTW: I use as compiler BorlandC++ 3.1 (I know, very old, but that's what I'll use at the exam..)
Thanks guys.
LE: If anyone wants to know more about what I'm trying to accomplish, you can check the code:
#include<fstream.h>
#include<conio.h>
int v[1000], n;
ifstream f("bac.in");
void citire();
void afisare_a();
int ultima_cifra(int nr);
void sortare(int asc);
void main() {
clrscr();
citire();
sortare(2);
afisare_a();
getch();
}
void citire() {
f>>n;
for(int i = 0; i < n; i++)
f>>v[i];
f.close();
}
void afisare_a() {
for(int i = 0;i < n; i++)
if(ultima_cifra(v[i]) == 5)
cout<<v[i]<<" ";
}
int ultima_cifra(int nr) {
return nr - 10 * ( nr / 10 );
}
void sortare(int asc) {
int aux, s;
if(asc == 1)
do {
s = 0;
for(int i = 0; i < n-1; i++)
if(v[i] > v[i+1]) {
aux = v[i];
v[i] = v[i+1];
v[i+1] = aux;
s = 1;
}
} while( s == 1);
else
do {
s = 0;
for(int i = 0; i < n-1; i++)
if(v[i] < v[i+1]) {
aux = v[i];
v[i] = v[i+1];
v[i+1] = v[i];
s = 1;
}
} while(s == 1);
}
Citire = Read
Afisare = Display
Ultima Cifra = Last digit of number
Sortare = Bubble Sort
If you were using a modern compiler, you could use std::nth_element to find the top three. As is, you'll have to scan through the array keeping track of the three largest elements seen so far at any given time, and when you get to the end, those will be your answer.
For three elements that's a trivial thing to manage. If you had to do the N largest (or smallest) elements when N might be considerably larger, then you'd almost certainly want to use Hoare's select algorithm, just like std::nth_element does.
You could do this without needing to sort at all, it's doable in O(n) time with linear search and 3 variables keeping your 3 largest numbers (or indexes of your largest numbers if this vector won't change).
Why not just step through it once and keep track of the 3 highest digits encountered?
EDIT: The range for the input is important in how you want to keep track of the 3 highest digits.
Use std::partial_sort to descending sort the first c elements that you care about. It will run in linear time for a given number of desired elements (n log c) time.
If you can't use std::nth_element write your own selection function.
You can read about them here: http://en.wikipedia.org/wiki/Selection_algorithm#Selecting_k_smallest_or_largest_elements
Sort them normally and then iterate from the back using rbegin(), for as many as you wish to extract (no further than rend() of course).
sort will happen in place whether ASC or DESC by the way, so memory is not an issue since your container element is an int, thus has no encapsulated memory of its own to manage.
Yes sorting is good. A especially for long or variable length lists.
Why are you sorting it twice, though? The second sort might actually be very inefficient (depends on the algorithm in use). A reverse would be quicker, but why even do that? If you want them in ascending order at the end, then sort them into ascending order first ( and fetch the numbers from the end)
I think you have the choice between scanning the vector for the three largest elements or sorting it (either using sort in a vector or by copying it into an implicitly sorted container like a set).
If you can control the array filling maybe you could add the numbers ordered and then choose the first 3 (ie), otherwise you can use a binary tree to perform the search or just use a linear search as birryree says...
Thank #nevets1219 for pointing out that the code below only deals with positive numbers.
I haven't tested this code enough, but it's a start:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> nums;
nums.push_back(1);
nums.push_back(6);
nums.push_back(2);
nums.push_back(5);
nums.push_back(3);
nums.push_back(7);
nums.push_back(4);
int first = 0;
int second = 0;
int third = 0;
for (int i = 0; i < nums.size(); i++)
{
if (nums.at(i) > first)
{
third = second;
second = first;
first = nums.at(i);
}
else if (nums.at(i) > second)
{
third = second;
second = nums.at(i);
}
else if (nums.at(i) > third)
{
third = nums.at(i);
}
std::cout << "1st: " << first << " 2nd: " << second << " 3rd: " << third << std::endl;
}
return 0;
}
The following solution finds the three largest numbers in O(n) and preserves their relative order:
std::vector<int>::iterator p = std::max_element(vec.begin(), vec.end());
int x = *p;
*p = std::numeric_limits<int>::min();
std::vector<int>::iterator q = std::max_element(vec.begin(), vec.end());
int y = *q;
*q = std::numeric_limits<int>::min();
int z = *std::max_element(vec.begin(), vec.end());
*q = y; // restore original value
*p = x; // restore original value
A general solution for the top N elements of a vector:
Create an array or vector topElements of length N for your top N elements.
Initialise each element of topElements to the value of your first element in your vector.
Select the next element in the vector, or finish if no elements are left.
If the selected element is greater than topElements[0], replace topElements[0] with the value of the element. Otherwise, go to 3.
Starting with i = 0, swap topElements[i] with topElements[i + 1] if topElements[i] is greater than topElements[i + 1].
While i is less than N, increment i and go to 5.
Go to 3.
This should result in topElements containing your top N elements in reverse order of value - that is, the largest value is in topElements[N - 1].