This question already has answers here:
How to get the least number after deleting k digits from the input number
(11 answers)
Closed 6 years ago.
I am trying to code a program that can do something like this:
in:
5 4
1 9 9 9 0
out:
9990
and i have a problem. It doesnt work on any set of numbers. For example it works for the one above, but it doesnt work for this one:
in:
15 9
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
out: 988887814
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
I did this with a vector approach and it works for any set of numbers, but i'm trying to do it a stack for a better complexity.
EDIT ---- MODIFIED FOR STD::STACK
Code for method using stack:
#include <iostream>
#include <fstream>
#include <stack>
using namespace std;
ifstream in("trompeta.in");
ofstream out("trompeta.out");
void reverseStack(stack<char> st) {
if(!st.empty())
{
char x = st.top();
st.pop();
reverseStack(st);
out<<x;
}
return;
}
int main()
{
int n,m,count=1;
stack <char> st;
char x;
in>>n>>m;
in>>x;
st.push(x);
for(int i=1; i<n; i++)
{
in>>x;
if(st.top()<x && count+n-i-1>=m)
{
st.pop();
st.push(x);
}
else
{
st.push(x);
count++;
if (count>m-1) break;
}
};
reverseStack(st);
}
Code for method using vectors:
#include <iostream>
#include <fstream>
using namespace std;
ifstream in ( "trompeta.in" );
ofstream out ( "trompeta.out" );
int main ()
{
int i = 0, N, M, max, j, p = 0, var;
in >> N >> M;
char* v = new char[N];
char* a = new char[M];
in >> v;
var = M;
max = v[0];
for ( i = 0; i < M; i++ )
{
for ( j = p ; j < N-var+1; j++ )
{
if ( v[j] > max )
{
max = v[j];
p = j;
}
}
var--;
a[i] = max;
max = v[p+1];
p = p+1;
}
for ( i = 0; i < M; i++ )
out << a[i]-'0';
}
Can any1 help me to get the STACK code working?
Using the fact that the most significant digit completely trumps all other digets except in place of a tie, I would look at the first (N-M+1) digits, find the largest single digit in that range.
If it occurs once, the first digit is locked in. Discard the digits which occur prior to that position, and you repeat for "maximum value of M-1 numbers of out N-position" to find the remaining digits of the answer. (or N-position-1, if position is zero based)
If it occurs multiple times, then recursively find "maximum value of M-1 numbers out of N-position" for each, then select the largest single result from these. There can be at most N such matches.
I forgot to mention, if N==M, you are also done.
proof of recursion:
Computing the value of the sub-match will always select M-1 digits. When M is 1, you only need to select the largest of a few positions, and have no more recursion. This is true for both cases. Also the "select from" steps always contain no more than N choices, because they are always based on selecting one most significant digit.
------------------ how you might do it with a stack ----------------
An actual implementation using a stack would be based on an object which contains the entire state of the problem, at each step, like so:
struct data { // require: n == digits.size()
int n, m;
std::string digits;
bool operator<(const data &rhs){ return digits < rhs.digits; }
};
The point of this is not just to store the original problem, but to have a way to represent any subproblem, which you can push and pop on a stack. The stack itself is not really important, here, because it is used to pick the one best result within a specific layer. Recursion handles most of the work.
Here is the top level function which hides the data struct:
std::string select_ordered_max(int n, int m, std::string digits) {
if (n < m || (int)digits.size() != n)
return "size wrong";
data d{ n, m, digits };
data answer = select_ordered_max(d);
return answer.digits;
}
and a rough pseudocode of the recursive workhorse
data select_ordered_max(data original){
// check trivial return conditions
// determine char most_significant
// push all subproblems that satisfy most_significant
//(special case where m==1)
// pop subproblems, remembering best
return answer {original.m, original.m, std::string(1, most_significant) + best_submatch.digits };
}
String comparison works on numbers when you only compare strings of the exact same length, which is the case here.
Yes, I know having n and m is redundant with digits.size(), but I didn't want to work too hard. Including it twice simplified some recursion checks. The actual implementation only pushed a candidate to the stack if it passed the max digit check for that level of recursion. This allowed me to get the correct 9 digit answer from 15 digits of input with only 28 candidates pushed to the stack (and them popped during max-select).
Now your code has quite a few issues, but rather than focusing on those lets answer the question. Let's say that your code has been corrected to give us:
const size_t M where M is the number of digits expected in our output
const vector<int> v which is the input set of numbers of size N
You just always want to pick the highest value most significant number remaining. So we'll keep an end iterator to prevent us from picking a digit that wouldn't leave us with enough digits to finish the number, and use max_element to select:
const int pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
auto maximum = 0;
auto end = prev(cend(v), M - 1);
auto it = max_element(cbegin(v), end);
for (auto i = M - 1; i > 0; --i) {
maximum += *it * pow10[i];
advance(end, 1);
it = max_element(next(it), end);
}
maximum += *it;
Live Example
This code depends upon M being greater than 0 and less than N and less than log10(numeric_limits<int>::max())
EDIT: Sad to say this solves the consecutive digits problem, after edits the question wants subsequent digits, but not necessarily consecutive
So the little known numeric library provides inner_product which seems like just the tool for this job. Now your code has quite a few issues, but rather than focusing on those lets answer the question. Let's say that your code has been corrected to give us:
vector<int> foo(M) where M is the number of digits expected in our output
const vector<int> v which is the input set of numbers of size N
We'll use foo in the inner_product, initializing it with decreasing powers of 10:
generate(begin(foo), end(foo), [i=int{1}]() mutable {
auto result = i;
i *= 10;
return result; });
We can then use this in a loop:
auto maximum = 0;
for (auto it = prev(rend(v), size(foo) + 1); it != rbegin(v); advance(it, -1)) {
maximum = max<int>(inner_product(cbegin(foo), cend(foo), it, 0), maximum);
}
maximum = max<int>(inner_product(cbegin(foo), cend(foo), rbegin(v), 0), maximum);
Live Example
To use it's initialization requires that your initial M was smaller than N, so you may want to assert that or something.
--EDITED--
here's my suggestion with STACK based on my previous suggestion using vector
findMaxValueOutOfNDigits(stackInput, M, N)
{
// stackInput = [2, 9, 3, 6, 5, 8, 8, 8, 8, 7, 2, 2, 8, 1, 4]
// *where 4 was the first element to be inserted and 2 was the last to be inserted
// if the sequence is inverted, you can quickly fix it by doing a "for x = 0; x < stack.length; x++ { newStack.push(stack.pop()) }"
currentMaxValue = 0
for i = 0; i < (M - N + 1); i++
{
tempValue = process(stackInput, M, N)
stackInput.pop()
if (tempValue > currentMaxValue)
currentMaxValue = tempValue
}
return currentMaxValue
}
process(stackInput, M, N)
{
tempValue = stackInput.pop() * 10^(N - 1)
*howManyItemsCanILook = (M - N + 1)
for y = (N - 2); y == 0; y++
{
currentHowManyItemsCanILook = *howManyItemsCanILook
tempValue = tempValue + getValue(stackInput, *howManyItemsCanILook) * 10^(y)
*howManyItemsCanILook = *howManyItemsCanILook - 1
for x = 0; x < (currentHowManyItemsCanILook - *howManyItemsCanILook); x++
{
stackInput.pop()
}
}
return tempValue
}
getValue(stackInput, *howManyItemsCanILook)
{
currentMaxValue = stackInput.pop()
if (currentMaxValue == 9)
return 9
else
{
goUntil = *howManyItemsCanILook
for i = 0; i < goUntil; i++
{
*howManyItemsCanILook = *howManyItemsCanILook - 1
tempValue = stackInput.pop()
if (currentMaxValue < tempValue)
{
currentMaxValue = tempValue
if (currentMaxValue == 9)
return currentMaxValue
}
}
return currentMaxValue
}
}
note: where *howManyItemsCanILook is passed by reference
I hope this helps
Related
I have worked out a O(n square) solution to the problem. I was wondering about a better solution to this. (this is not a homework/interview problem but something I do out of my own interest, hence sharing here):
If a=1, b=2, c=3,….z=26. Given a string, find all possible codes that string
can generate. example: "1123" shall give:
aabc //a = 1, a = 1, b = 2, c = 3
kbc // since k is 11, b = 2, c= 3
alc // a = 1, l = 12, c = 3
aaw // a= 1, a =1, w= 23
kw // k = 11, w = 23
Here is my code to the problem:
void alpha(int* a, int sz, vector<vector<int>>& strings) {
for (int i = sz - 1; i >= 0; i--) {
if (i == sz - 1) {
vector<int> t;
t.push_back(a[i]);
strings.push_back(t);
} else {
int k = strings.size();
for (int j = 0; j < k; j++) {
vector<int> t = strings[j];
strings[j].insert(strings[j].begin(), a[i]);
if (t[0] < 10) {
int n = a[i] * 10 + t[0];
if (n <= 26) {
t[0] = n;
strings.push_back(t);
}
}
}
}
}
}
Essentially the vector strings will hold the sets of numbers.
This would run in n square. I am trying my head around at least an nlogn solution.
Intuitively tree should help here, but not getting anywhere post that.
Generally, your problem complexity is more like 2^n, not n^2, since your k can increase with every iteration.
This is an alternative recursive solution (note: recursion is bad for very long codes). I didn't focus on optimization, since I'm not up to date with C++X, but I think the recursive solution could be optimized with some moves.
Recursion also makes the complexity a bit more obvious compared to the iterative solution.
// Add the front element to each trailing code sequence. Create a new sequence if none exists
void update_helper(int front, std::vector<std::deque<int>>& intermediate)
{
if (intermediate.empty())
{
intermediate.push_back(std::deque<int>());
}
for (size_t i = 0; i < intermediate.size(); i++)
{
intermediate[i].push_front(front);
}
}
std::vector<std::deque<int>> decode(int digits[], int count)
{
if (count <= 0)
{
return std::vector<std::deque<int>>();
}
std::vector<std::deque<int>> result1 = decode(digits + 1, count - 1);
update_helper(*digits, result1);
if (count > 1 && (digits[0] * 10 + digits[1]) <= 26)
{
std::vector<std::deque<int>> result2 = decode(digits + 2, count - 2);
update_helper(digits[0] * 10 + digits[1], result2);
result1.insert(result1.end(), result2.begin(), result2.end());
}
return result1;
}
Call:
std::vector<std::deque<int>> strings = decode(codes, size);
Edit:
Regarding the complexity of the original code, I'll try to show what would happen in the worst case scenario, where the code sequence consists only of 1 and 2 values.
void alpha(int* a, int sz, vector<vector<int>>& strings)
{
for (int i = sz - 1;
i >= 0;
i--)
{
if (i == sz - 1)
{
vector<int> t;
t.push_back(a[i]);
strings.push_back(t); // strings.size+1
} // if summary: O(1), ignoring capacity change, strings.size+1
else
{
int k = strings.size();
for (int j = 0; j < k; j++)
{
vector<int> t = strings[j]; // O(strings[j].size) vector copy operation
strings[j].insert(strings[j].begin(), a[i]); // strings[j].size+1
// note: strings[j].insert treated as O(1) because other containers could do better than vector
if (t[0] < 10)
{
int n = a[i] * 10 + t[0];
if (n <= 26)
{
t[0] = n;
strings.push_back(t); // strings.size+1
// O(1), ignoring capacity change and copy operation
} // if summary: O(1), strings.size+1
} // if summary: O(1), ignoring capacity change, strings.size+1
} // for summary: O(k * strings[j].size), strings.size+k, strings[j].size+1
} // else summary: O(k * strings[j].size), strings.size+k, strings[j].size+1
} // for summary: O(sum[i from 1 to sz] of (k * strings[j].size))
// k (same as string.size) doubles each iteration => k ends near 2^sz
// string[j].size increases by 1 each iteration
// k * strings[j].size increases by ?? each iteration (its getting huge)
}
Maybe I made a mistake somewhere and if we want to play nice we can treat a vector copy as O(1) instead of O(n) in order to reduce complexity, but the hard fact remains, that the worst case is doubling outer vector size in each iteration (at least every 2nd iteration, considering the exact structure of the if conditions) of the inner loop and the inner loop depends on that growing vector size, which makes the whole story at least O(2^n).
Edit2:
I figured out the result complexity (the best hypothetical algoritm still needs to create every element of the result, so result complexity is like a lower bound to what any algorithm can archieve)
Its actually following the Fibonacci numbers:
For worst case input (like only 1s) of size N+2 you have:
size N has k(N) elements
size N+1 has k(N+1) elements
size N+2 is the combination of codes starting with a followed by the combinations from size N+1 (a takes one element of the source) and the codes starting with k, followed by the combinations from size N (k takes two elements of the source)
size N+2 has k(N) + k(N+1) elements
Starting with size 1 => 1 (a) and size 2 => 2 (aa or k)
Result: still exponential growth ;)
Edit3:
Worked out a dynamic programming solution, somewhat similar to your approach with reverse iteration over the code array and kindof optimized in its vector usage, based on the properties explained in Edit2.
The inner loop (update_helper) is still dominated by the count of results (worst case Fibonacci) and a few outer loop iterations will have a decent count of sub-results, but at least the sub-results are reduced to a pointer to some intermediate node, so copying should be pretty efficient. As a little bonus, I switched the result from numbers to characters.
Another edit: updated code with range 0 - 25 as 'a' - 'z', fixed some errors that led to wrong results.
struct const_node
{
const_node(char content, const_node* next)
: next(next), content(content)
{
}
const_node* const next;
const char content;
};
// put front in front of each existing sub-result
void update_helper(int front, std::vector<const_node*>& intermediate)
{
for (size_t i = 0; i < intermediate.size(); i++)
{
intermediate[i] = new const_node(front + 'a', intermediate[i]);
}
if (intermediate.empty())
{
intermediate.push_back(new const_node(front + 'a', NULL));
}
}
std::vector<const_node*> decode_it(int digits[9], size_t count)
{
int current = 0;
std::vector<const_node*> intermediates[3];
for (size_t i = 0; i < count; i++)
{
current = (current + 1) % 3;
int prev = (current + 2) % 3; // -1
int prevprev = (current + 1) % 3; // -2
size_t index = count - i - 1; // invert direction
// copy from prev
intermediates[current] = intermediates[prev];
// update current (part 1)
update_helper(digits[index], intermediates[current]);
if (index + 1 < count && digits[index] &&
digits[index] * 10 + digits[index + 1] < 26)
{
// update prevprev
update_helper(digits[index] * 10 + digits[index + 1], intermediates[prevprev]);
// add to current (part 2)
intermediates[current].insert(intermediates[current].end(), intermediates[prevprev].begin(), intermediates[prevprev].end());
}
}
return intermediates[current];
}
void cleanupDelete(std::vector<const_node*>& nodes);
int main()
{
int code[] = { 1, 2, 3, 1, 2, 3, 1, 2, 3 };
int size = sizeof(code) / sizeof(int);
std::vector<const_node*> result = decode_it(code, size);
// output
for (size_t i = 0; i < result.size(); i++)
{
std::cout.width(3);
std::cout.flags(std::ios::right);
std::cout << i << ": ";
const_node* item = result[i];
while (item)
{
std::cout << item->content;
item = item->next;
}
std::cout << std::endl;
}
cleanupDelete(result);
}
void fillCleanup(const_node* n, std::set<const_node*>& all_nodes)
{
if (n)
{
all_nodes.insert(n);
fillCleanup(n->next, all_nodes);
}
}
void cleanupDelete(std::vector<const_node*>& nodes)
{
// this is like multiple inverse trees, hard to delete correctly, since multiple next pointers refer to the same target
std::set<const_node*> all_nodes;
for each (auto var in nodes)
{
fillCleanup(var, all_nodes);
}
nodes.clear();
for each (auto var in all_nodes)
{
delete var;
}
all_nodes.clear();
}
A drawback of the dynamically reused structure is the cleanup, since you wanna be careful to delete each node only once.
I have done a test in C++ asking for a function that returns one of the indices that splits the input vector in 2 parts having the same sum of the elements, for eg: for the vec = {1, 2, 3, 5, 4, -1, 1, 1, 2, -1}, it may return 3, because 1+2+3 = 6 = 4-1+1+1+2-1. So I have done the function that returns the correct answer:
int func(const std::vector< int >& vecIn)
{
for (std::size_t p = 0; p < vecin.size(); p++)
{
if (std::accumulator(vecIn.begin(), vecIn.begin() + p, 0) ==
std::accumulator(vecIn.begin() + p + 1, vecIn.end(), 0))
return p;
}
return -1;
}
My problem was when the input was a very long vector containing just 1 (or -1), the return of the function was slow. So I have thought of starting the search for the wanted index from middle, and then go left and right. But the best approach I suppose is the one where the index is in the merge-sort algorithm order, that means: n/2, n/4, 3n/4, n/8, 3n/8, 5n/8, 7n/8... where n is the size of the vector. Is there a way to write this order in a formula, so I can apply it in my function?
Thanks
EDIT
After some comments I have to mention that I had done the test a few days ago, so I have forgot to put and mention the part of no solution: it should return -1... I have updated also the question title.
Specifically for this problem, I would use the following algorithm:
Compute the total sum of the vector. This gives two sums (empty vector, and full vector)
for each element in order, move one element from full to empty, which means adding the value of next element from sum(full) to sum(empty). When the two sums are equal, you have found your index.
This give a o(n) algorithm instead of o(n2)
You can solve the problem much faster without calling std::accumulator at each step:
int func(const std::vector< int >& vecIn)
{
int s1 = 0;
int s2 = std::accumulator(vecIn.begin(), vecIn.end(), 0);
for (std::size_t p = 0; p < vecin.size(); p++)
{
if (s1 == s2)
return p;
s1 += vecIn[p];
s2 -= vecIn[p];
}
}
This is O(n). At each step, s1 will contain the sum of the first p elements, and s2 the sum of the rest. You can update both of them with an addition and a subtraction when moving to the next element.
Since std::accumulator needs to iterate over the range you give it, your algorithm was O(n^2), which is why it was so slow for many elements.
To answer the actual question: Your sequence n/2, n/4, 3n/5, n/8, 3n/8 can be rewritten as
1*n/2
1*n/4 3*n/4
1*n/8 3*n/8 5*n/8 7*n/8
...
that is to say, the denominator runs from i=2 up in powers of 2, and the nominator runs from j=1 to i-1 in steps of 2. However, this is not what you need for your actual problem, because the example you give has n=10. Clearly you don't want n/4 there - your indices have to be integer.
The best solution here is to recurse. Given a range [b,e], pick a value middle (b+e/2) and set the new ranges to [b, (b+e/2)-1] and [(b+e/2)=1, e]. Of course, specialize ranges with length 1 or 2.
Considering MSalters comments, I'm afraid another solution would be better. If you want to use less memory, maybe the selected answer is good enough, but to find the possibly multiple solutions you could use the following code:
static const int arr[] = {5,-10,10,-10,10,1,1,1,1,1};
std::vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
// compute cumulative sum
std::vector<int> cumulative_sum( vec.size() );
cumulative_sum[0] = vec[0];
for ( size_t i = 1; i < vec.size(); i++ )
{ cumulative_sum[i] = cumulative_sum[i-1] + vec[i]; }
const int complete_sum = cumulative_sum.back();
// find multiple solutions, if there are any
const int complete_sum_half = complete_sum / 2; // suggesting this is valid...
std::vector<int>::iterator it = cumulative_sum.begin();
std::vector<int> mid_indices;
do {
it = std::find( it, cumulative_sum.end(), complete_sum_half );
if ( it != cumulative_sum.end() )
{ mid_indices.push_back( it - cumulative_sum.begin() ); ++it; }
} while( it != cumulative_sum.end() );
for ( size_t i = 0; i < mid_indices.size(); i++ )
{ std::cout << mid_indices[i] << std::endl; }
std::cout << "Split behind these indices to obtain two equal halfs." << std::endl;
This way, you get all the possible solutions. If there is no solution to split the vector in two equal halfs, mid_indices will be left empty.
Again, you have to sum up each value only once.
My proposal is this:
static const int arr[] = {1,2,3,5,4,-1,1,1,2,-1};
std::vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
int idx1(0), idx2(vec.size()-1);
int sum1(0), sum2(0);
int idxMid = -1;
do {
// fast access without using the index each time.
const int& val1 = vec[idx1];
const int& val2 = vec[idx2];
// Precompute the next (possible) sum values.
const int nSum1 = sum1 + val1;
const int nSum2 = sum2 + val2;
// move the index considering the balanace between the
// left and right sum.
if ( sum1 - nSum2 < sum2 - nSum1 )
{ sum1 = nSum1; idx1++; }
else
{ sum2 = nSum2; idx2--; }
if ( idx1 >= idx2 ){ idxMid = idx2; }
} while( idxMid < 0 && idx2 >= 0 && idx1 < vec.size() );
std::cout << idxMid << std::endl;
It does add every value only once no matter how many values. Such that it's complexity is only O(n) and not O(n^2).
The code simply runs from left and right simultanuously and moves the indices further if it's side is lower than the other.
You want nth term of the series you mentioned. Then it would be:
numerator: (n - 2^((int)(log2 n)) ) *2 + 1
denominator: 2^((int)(log2 n) + 1)
I came across the same question in Codility tests. There is a similar looking answer above (didn't pass some of the unit tests), but below code segment was successful in tests.
#include <vector>
#include <numeric>
#include <iostream>
using namespace std;
// Returns -1 if equilibrium point is not found
// use long long to support bigger ranges
int FindEquilibriumPoint(vector<long> &values) {
long long lower = 0;
long long upper = std::accumulate(values.begin(), values.end(), 0);
for (std::size_t i = 0; i < values.size(); i++) {
upper -= values[i];
if (lower == upper) {
return i;
}
lower += values[i];
}
return -1;
}
int main() {
vector<long> v = {-1, 3, -4, 5, 1, -6, 2, 1};
cout << "Equilibrium Point:" << FindEquilibriumPoint(v) << endl;
return 0;
}
Output
Equilibrium Point:1
Here it is the algorithm in Javascript:
function equi(arr){
var N = arr.length;
if (N == 0){ return -1};
var suma = 0;
for (var i=0; i<N; i++){
suma += arr[i];
}
var suma_iz = 0;
for(i=0; i<N; i++){
var suma_de = suma - suma_iz - arr[i];
if (suma_iz == suma_de){
return i};
suma_iz += arr[i];
}
return -1;
}
As you see this code satisfy the condition of O(n)
I'm currently learning C++.
I am looking for Hamming numbers (numbers whose prime divisors are less or equal to 5).
When I input a number n, the program should output the n-th Hamming number.
Following numbers are input, and output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 ...
Finding Hamming numbers looks easy, but increasing the input number increases run time cost exponentially.
If I input over 1000, it almost costs over 1 second,
and over 1200, it almost costs over 5 seconds.
This is the code I wrote:
while (th > 1)
{
h++;
x = h;
while (x % 2 == 0)
x /= 2;
while (x % 3 == 0)
x /= 3;
while (x % 5 == 0)
x /= 5;
if (x == 1)
th--;
}
So I would like to know how I can find the answer faster.
This algorithm doesn't seem to be very good.
Thanks in advance.
Your code is good if you want to check whether one particular number is a hamming number. When you want to build a list of hamming numbers, it is inefficient.
You can use a bottom-up approach: Start with 1 and then recursively multiply that with 2, 3, and 5 to get all hamming numbers up to a certain limit. You have to take care of duplicates, because you can get to 6 by way of 2·3 and 3·2. A set can take care of that.
The code below will generate all hamming numbers that fit into a 32-bit unsigned int. It fills a set by "spreading" to all hamming numbers. Then it constructs a sorted vector from the set, which you can use to find a hamming number at a certain index:
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
typedef unsigned int uint;
const uint umax = 0xffffffff;
void spread(std::set<uint> &hamming, uint n)
{
if (hamming.find(n) == hamming.end()) {
hamming.insert(n);
if (n < umax / 2) spread(hamming, n * 2);
if (n < umax / 3) spread(hamming, n * 3);
if (n < umax / 5) spread(hamming, n * 5);
}
}
int main()
{
std::set<uint> hamming;
spread(hamming, 1);
std::vector<uint> ordered(hamming.begin(), hamming.end());
for (size_t i = 0; i < ordered.size(); i++) {
std::cout << i << ' ' << ordered[i] << '\n';
}
return 0;
}
This code is faster than your linear method even if you end up creating more hamming numbers than you need.
You don't even need a set if you make sure that you don't construct a number twice. Every hamming number can be written as h = 2^n2 + 3^n3 + 5^n5, so if you find a means to iterate through these uniquely, you're done:
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
typedef unsigned int uint;
int main()
{
const uint umax = 0xffffffff;
std::vector<uint> hamming;
for (uint k = 1;; k *= 2) {
for (uint l = k;; l *= 3) {
for (uint m = l;; m *= 5) {
hamming.push_back(m);
if (m > umax / 5) break;
}
if (l > umax / 3) break;
}
if (k > umax / 2) break;
}
std::sort(hamming.begin(), hamming.end());
for (size_t i = 0; i < hamming.size(); i++) {
std::cout << i << ' ' << hamming[i] << '\n';
}
return 0;
}
The strange break syntax for the loops is required, because we have to check the size before the overflow. If umax*5 were guananteed not to overflow, these conditions could be written in the condition part of the loop.
The code examples in the Rosetta Code link Koshinae posted use similar strategies, but I'm surprised how lengthy some of them are.
In this link you can find two different solutions for finding the nth hamming number. The second method is the optimized one which can get the result in a few seconds.
/* Function to get the nth ugly number*/
unsigned getNthUglyNo(unsigned n)
{
unsigned ugly[n]; // To store ugly numbers
unsigned i2 = 0, i3 = 0, i5 = 0;
unsigned next_multiple_of_2 = 2;
unsigned next_multiple_of_3 = 3;
unsigned next_multiple_of_5 = 5;
unsigned next_ugly_no = 1;
ugly[0] = 1;
for (int i=1; i<n; i++)
{
next_ugly_no = min(next_multiple_of_2,
min(next_multiple_of_3,
next_multiple_of_5));
ugly[i] = next_ugly_no;
if (next_ugly_no == next_multiple_of_2)
{
i2 = i2+1;
next_multiple_of_2 = ugly[i2]*2;
}
if (next_ugly_no == next_multiple_of_3)
{
i3 = i3+1;
next_multiple_of_3 = ugly[i3]*3;
}
if (next_ugly_no == next_multiple_of_5)
{
i5 = i5+1;
next_multiple_of_5 = ugly[i5]*5;
}
} /*End of for loop (i=1; i<n; i++) */
return next_ugly_no;
}
Given an array , how would you return the number of pairs which sum to an even number?
For example:
a[] = { 2 , -6 , 1, 3, 5 }
In this array , the nos which pair to an even sum are
(2,-6), (1,3) , (1,5), (3,5)
Function should return 4 as there are 4 pairs or -1 if none.
Expected time complexity - O(N) worst case
Expected space complexity - O(N) worst case
Approach 1:
Brute force
Start with the first number
Start with second number
assign the sum to a temp variable
check if the temp is even
If it is increment evenPair count
else
increment the second index
Here the time complexity is O(N2)
int odd = 0, even = 0;
for (int i = 0; i < n; i++) {
if (a[i] % 2 == 0) {
even++;
} else {
odd++;
}
}
int answer = (odd * (odd - 1) + even * (even - 1)) / 2;
If a and b are even, a + b is even.
If they're odd, a + b is also even.
If one is odd and one is even, a + b is odd.
This means that we don't need to perform any additions, we only need to know how many numbers there are of each kind.
Finding this out takes linear time.
If you have k numbers, there are k - 1 pairs that include the first number, k - 2 involving the second, and so on.
Using the familiar summation formula, sum(1 .. n) = (n * (n + 1)) / 2,
let
ne = number of even numbers
no = number of odd numbers
then,
number of pairs = (ne-1) * ne / 2 + (no-1) * no / 2
= ((ne-1)*ne + (no-1)*no) / 2
That computation runs in constant time, so the time complexity is still linear.
And we only need a constant amount of extra space, which is better than the requirements.
Possible followup interview questions possibly worth thinking about:
What happens to the complexities (both in time and space) if:
duplicates are only counted once, i.e. {1,1,1,2} only has two such pairs?
we disregard order, i.e. (1,2) and (2,1) are the "same" pair?
If to use standard algorithms then the code can look the following way
#include <iostream>
#include <utility>
#include <numeric>
#include <iterator>
int main()
{
int a[] = { 2 , -6 , 1, 3, 5 };
typedef size_t Odd, Even;
auto p = std::accumulate( std::begin( a ), std::end( a ),
std::pair<Odd, Even>( 0, 0 ),
[]( std::pair<Odd, Even> &acc, int x )
{
return x & 1 ? ++acc.first : ++acc.second, acc;
} );
std::cout << "There are "
<< ( p.first * ( p.first - 1 ) + p.second * ( p.second - 1 ) ) / 2
<< " even sums" << std::endl;
return 0;
}
The output is
There are 4 even sums
Take into account that n! / ( 2! * ( n - 2 )! ) is equivalent to ( n - 1 ) * n / 2
The advantage of using the standard algorithm is that you can use any subrange of a sequence. Also you can use a standard stream input because std::accumulate uses input iterator.
Also it would be much better if in the description of the assignment there would be written that the function should return 0 instead of -1 if there is no even sums among elements of an array.
It is not shameful to show this code in an interview though I advice never do any assignments in an interview. Interview is not an exam.
A different approach would be compute the number of sums by even and odds, and then sum then together
int sumO = 0 , sumE = 0 , numO = 0 , numE = 0;
for (int i=0; i < 5; i++)
{
if (a[i] % 2 == 0)
{
sumE += numE;
numE ++;
}
else
{
sumO += numO;
numO ++;
}
}
printf ("Total: %d\n", sumO + sumE);
I got this question from an interview.
No need to total even and odd both separate.
public static int evenTotalPairs(int[] A) {
int size = A.length;
int evens = 0;
for(int i = 0; i < size; i++ ){
if(A[i] % 2 == 0){
evens++;
}
}
return evens*(evens-1)/2 + (size-evens)*(size-evens-1)/2;
}
The sequence of triangle numbers is
generated by adding the natural
numbers. So the 7th triangle number
would be 1 + 2 + 3 + 4 + 5 + 6 + 7 =
28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55,
...
Let us list the factors of the first
seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first
triangle number to have over five
divisors.
Given an integer n, display the first
triangle number having at least n
divisors.
Sample Input: 5
Output 28
Input Constraints: 1<=n<=320
I was obviously able to do this question, but I used a naive algorithm:
Get n.
Find triangle numbers and check their number of factors using the mod operator.
But the challenge was to show the output within 4 seconds of input. On high inputs like 190 and above it took almost 15-16 seconds. Then I tried to put the triangle numbers and their number of factors in a 2d array first and then get the input from the user and search the array. But somehow I couldn't do it: I got a lot of processor faults. Please try doing it with this method and paste the code. Or if there are any better ways, please tell me.
Here's a hint:
The number of divisors according to the Divisor function is the product of the power of each prime factor plus 1. For example, let's consider the exponential prime representation of 28:
28 = 22 * 30 * 50 * 71 * 110...
The product of each exponent plus one is: (2+1)*(0+1)*(0+1)*(1+1)*(0+1)... = 6, and sure enough, 28 has 6 divisors.
Now, consider that the nth triangular number can be computed in closed form as n(n+1)/2. We can multiply numbers written in the exponential prime form simply by adding up the exponents at each position. Dividing by two just means decrementing the exponent on the two's place.
Do you see where I'm going with this?
Well, you don't go into a lot of detail about what you did, but I can give you an optimization that can be used, if you didn't think of it...
If you're using the straightforward method of trying to find factors of a number n, by using the mod operator, you don't need to check all the numbers < n. That obviously would take n comparisons...you can just go up to floor(sqrt(n)). For each factor you find, just divide n by that number, and you'll get the conjugate value, and not need to find it manually.
For example: say n is 15.
We loop, and try 1 first. Yep, the mod checks out, so it's a factor. We divide n by the factor to get the conjugate value, so we do (15 / 1) = 15...so 15 is a factor.
We try 2 next. Nope. Then 3. Yep, which also gives us (15 / 3) = 5.
And we're done, because 4 is > floor(sqrt(n)). Quick!
If you didn't think of it, that might be something you could leverage to improve your times...overall you go from O(n) to O(sqrt (n)) which is pretty good (though for numbers this small, constants may still weigh heavily.)
I was in a programming competition way back in school where there was some similar question with a run time limit. the team that "solved" it did as follows:
1) solve it with a brute force slow method.
2) write a program to just print out the answer (you found using the slow method), which will run sub second.
I thought this was bogus, but they won.
see Triangular numbers: a(n) = C(n+1,2) = n(n+1)/2 = 0+1+2+...+n. (Formerly M2535 N1002)
then pick the language you want implement it in, see this:
"... Python
import math
def diminishing_returns(val, scale):
if val < 0:
return -diminishing_returns(-val, scale)
mult = val / float(scale)
trinum = (math.sqrt(8.0 * mult + 1.0) - 1.0) / 2.0
return trinum * scale
..."
First, create table with two columns: Triangle_Number Count_of_Factors.
Second, derive from this a table with the same columns, but consisting only of the 320 rows of the lowest triangle number with a distinct number of factors.
Perform your speedy lookup to the second table.
If you solved the problem, you should be able to access the thread on Project Euler in which people post their (some very efficient) solutions.
If you're going to copy and paste a problem, please cite the source (unless it was your teacher who stole it); and I second Wouter van Niferick's comment.
Well, at least you got a good professor. Performance is important.
Since you have a program that can do the job, you can precalculate all of the answers for 1 .. 320.
Store them in an array, then simply subscript into the array to get the answer. That will be very fast.
Compile with care, winner of worst code of the year :D
#include <iostream>
bool isPrime( unsigned long long number ){
if( number != 2 && number % 2 == 0 )
return false;
for( int i = 3;
i < static_cast<unsigned long long>
( sqrt(static_cast<double>(number)) + 1 )
; i += 2 ){
if( number % i == 0 )
return false;
}
return true;
}
unsigned int p;
unsigned long long primes[1024];
void initPrimes(){
primes[0] = 2;
primes[1] = 3;
unsigned long long number = 5;
for( unsigned int i = 2; i < 1024; i++ ){
while( !isPrime(number) )
number += 2;
primes[i] = number;
number += 2;
}
return;
}
unsigned long long nextPrime(){
unsigned int ret = p;
p++;
return primes[ret];
}
unsigned long long numOfDivs( unsigned long long number ){
p = 0;
std::vector<unsigned long long> v;
unsigned long long prime = nextPrime(), divs = 1, i = 0;
while( number >= prime ){
i = 0;
while( number % prime == 0 ){
number /= prime;
i++;
}
if( i )
v.push_back( i );
prime = nextPrime();
}
for( unsigned n = 0; n < v.size(); n++ )
divs *= (v[n] + 1);
return divs;
}
unsigned long long nextTriNumber(){
static unsigned long long triNumber = 1, next = 2;
unsigned long long retTri = triNumber;
triNumber += next;
next++;
return retTri;
}
int main()
{
initPrimes();
unsigned long long n = nextTriNumber();
unsigned long long divs = 500;
while( numOfDivs(n) <= divs )
n = nextTriNumber();
std::cout << n;
std::cin.get();
}
def first_triangle_number_with_over_N_divisors(N):
n = 4
primes = [2, 3]
fact = [None, None, {2:1}, {3:1}]
def num_divisors (x):
num = 1
for mul in fact[x].values():
num *= (mul+1)
return num
while True:
factn = {}
for p in primes:
if p > n//2: break
r = n // p
if r * p == n:
factn = fact[r].copy()
factn[p] = factn.get(p,0) + 1
if len(factn)==0:
primes.append(n)
factn[n] = 1
fact.append(factn)
(x, y) = (n-1, n//2) if n % 2 == 0 else (n, (n-1)//2)
numdiv = num_divisors(x) * num_divisors(y)
if numdiv >= N:
print('Triangle number %d: %d divisors'
%(x*y, numdiv))
break
n += 1
>>> first_triangle_number_with_over_N_divisors(500)
Triangle number 76576500: 576 divisors
Dude here is ur code, go have a look. It calculates the first number that has divisors greater than 500.
void main() {
long long divisors = 0;
long long nat_num = 0;
long long tri_num = 0;
int tri_sqrt = 0;
while (1) {
divisors = 0;
nat_num++;
tri_num = nat_num + tri_num;
tri_sqrt = floor(sqrt((double)tri_num));
long long i = 0;
for ( i=tri_sqrt; i>=1; i--) {
long long remainder = tri_num % i;
if ( remainder == 0 && tri_num == 1 ) {
divisors++;
}
else if (remainder == 0 && tri_num != 1) {
divisors++;
divisors++;
}
}
if (divisors >100) {
cout <<"No. of divisors: "<<divisors<<endl<<tri_num<<endl;
}
if (divisors > 500)
break;
}
cout<<"Final Result: "<<tri_num<<endl;
system("pause");
}
Boojum's answer motivated me to write this little program. It seems to work well, although it does use a brute force method of computing primes. It's neat how all the natural numbers can be broken down into prime number components.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <vector>
//////////////////////////////////////////////////////////////////////////////
typedef std::vector<size_t> uint_vector;
//////////////////////////////////////////////////////////////////////////////
// add a prime number to primes[]
void
primeAdd(uint_vector& primes)
{
size_t n;
if (primes.empty())
{
primes.push_back(2);
return;
}
for (n = *(--primes.end()) + 1; ; ++n)
{
// n is even -> not prime
if ((n & 1) == 0) continue;
// look for a divisor in [2,n)
for (size_t i = 2; i < n; ++i)
{
if ((n % i) == 0) continue;
}
// found a prime
break;
}
primes.push_back(n);
}
//////////////////////////////////////////////////////////////////////////////
void
primeFactorize(size_t n, uint_vector& primes, uint_vector& f)
{
f.clear();
for (size_t i = 0; n > 1; ++i)
{
while (primes.size() <= i) primeAdd(primes);
while (f.size() <= i) f.push_back(0);
while ((n % primes[i]) == 0)
{
++f[i];
n /= primes[i];
}
}
}
//////////////////////////////////////////////////////////////////////////////
int
main(int argc, char** argv)
{
// allow specifying number of TN's to be evaluated
size_t lim = 1000;
if (argc > 1)
{
lim = atoi(argv[1]);
}
if (lim == 0) lim = 1000;
// prime numbers
uint_vector primes;
// factors of (n), (n + 1)
uint_vector* f = new uint_vector();
uint_vector* f1 = new uint_vector();
// sum vector
uint_vector sum;
// prime factorize (n)
size_t n = 1;
primeFactorize(n, primes, *f);
// iterate over triangle-numbers
for (; n <= lim; ++n)
{
// prime factorize (n + 1)
primeFactorize(n + 1, primes, *f1);
while (f->size() < f1->size()) f->push_back(0);
while (f1->size() < f->size()) f1->push_back(0);
size_t numTerms = f->size();
// compute prime factors for (n * (n + 1) / 2)
sum.clear();
size_t i;
for (i = 0; i < numTerms; ++i)
{
sum.push_back((*f)[i] + (*f1)[i]);
}
--sum[0];
size_t numFactors = 1, tn = 1;
for (i = 0; i < numTerms; ++i)
{
size_t exp = sum[i];
numFactors *= (exp + 1);
while (exp-- != 0) tn *= primes[i];
}
std::cout
<< n << ". Triangle number "
<< tn << " has " << numFactors << " factors."
<< std::endl;
// prepare for next iteration
f->clear();
uint_vector* tmp = f;
f = f1;
f1 = tmp;
}
delete f;
delete f1;
return 0;
}