[英]Find Nth number from a sorted array formed by multiplying any two or more consecutive natural numbers
我最近遇到了這個問題:
通過將任意兩個或多個連續自然數相乘形成一個(遞增)排序數組。
2, 6, 12, 20, 24, 30, 42, 56, 60, 72...
前任。 2 由兩個連續的自然數 1 和 2 組成:2 = 1×2。 並且 6 = 2×3 或 1×2×3,20 = 4×5。
is given as a parameter, find the th number from the above array and return.如果作為參數給出,則從上述數組中找到第個數字並返回。
局限性
- ≤ 1000000
- is given only when the answer is smaller than 10 12僅當答案小於 10 12時才給出
2 ) solution, but I want to know if there is a better solution.所以在這里我能夠找到 O( 2 ) 解決方案,但我想知道是否有更好的解決方案。
2 ) JS solution:我的 O( 2 ) JS 解決方案:
function solution(n) {
// Find all possible product subsets of [1, ..., n] = [1x2, 2x3, 4x5, ..., 1x2x...xn]
// return Nth index of this product subset array
// 1 ~ n+1 array
const nums = Array.from({ length: n+1 }, (_, i) => i + 1);
const set = new Set();
// Find all possible product subsets
for (let i = 0; i < nums.length; i++) {
let accu = 1;
for (let j = i; j < nums.length; j++) {
accu *= nums[j];
if( i !== j) set.add(accu);
}
}
// Sort and return n-1 index value
return Array.from(set).sort((a,b) => a - b)[n-1];
}
謝謝您的幫助:)
以下實現基於最小堆(C++ 中的std::priority_queue
),它可以記住“最好的”未來候選者。
重要的一點是區別對待基本解k *(k+1)
。 由於這些數字很可能占多數,因此可以大大減小堆的大小。
在每個給定時間,我們要么決定使用k(k+1)
數,要么使用最小堆的當前頂部值。 每個使用的值都會導致在最小堆中插入一個新的候選者。
另一方面是僅在堆中插入小於估計最大值n(n+1)
的值。
復雜度估計為 O(n log M),其中 M 是堆的平均大小。
對於n = 10^6
,程序測量堆的最大大小等於 9998,遠小於n
。
在我的 PC 上,我在 11 毫秒內得到n = 10^6
的結果。 結果:977410038240
這是 C++ 代碼。
這段代碼記住了所有的序列,主要用於調試。 在實踐中,如果我們只需要第 n 個值,就可以避免這種記憶。 如果效率仍然是一個問題,也可以刪除最大堆(對調試有用)大小的測量。
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <chrono>
template <typename T>
void print (const std::vector<T> &A , const std::string &s = "") {
std::cout << s;
for (const T& val: A) {
std::cout << val << " ";
}
std::cout << "\n";
}
struct Prod {
long long p; // product
int last; // last integer in the product
};
long long int consecutive_products (int n) {
std::vector<long long> products; // not strictly needed, for debugging
products.reserve(n);
products.push_back (2); products.push_back (6);
long long max_val = (long long) n * (n+1);
auto comp = [] (const Prod& x1, const Prod& x2) {
if (x1.p == x2.p) return x1.last > x2.last;
return x1.p > x2.p;
};
std::priority_queue<Prod, std::vector<Prod>, decltype(comp)> candidates(comp);
if (n <= 2) return products[n-1];
candidates.push ({24, 4}); // 2*3*4 -> extension of 2*3
long long int prod_simple = 12; // = 3*4 - simple products k(k-1) are dealt with differently
int rank_simple = 4;
int index = 2;
long long current_val = products[index - 1];
Prod best;
long long minval;
int max_size = 0;
while (index < n) {
if (candidates.empty()) {
minval = max_val;
} else {
best = candidates.top();
minval = best.p;
}
if (minval <= prod_simple) {
candidates.pop();
long long new_product = minval * (best.last + 1);
if (new_product < max_val) {
candidates.push ({new_product, best.last + 1});
}
} else {
minval = prod_simple;
long long new_product = prod_simple * (rank_simple + 1);
if (new_product < max_val) {
candidates.push ({new_product, rank_simple + 1});
}
prod_simple = (long long) rank_simple * (rank_simple + 1);
rank_simple++;
}
if (minval > current_val) {
products.push_back(minval);
current_val = minval;
index++;
}
int size = candidates.size();
if (size > max_size) max_size = size;
}
if (n <= 20) print (products, "Products: ");
std::cout << "max heap size = " << max_size << std::endl;
return minval;
}
int main() {
int n;
std::cout << "Enter n: ";
std::cin >> n;
auto t1 = std::chrono::high_resolution_clock::now();
auto ans = consecutive_products (n);
auto t2 = std::chrono::high_resolution_clock::now();
std::cout << ans << std::endl;
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
std::cout << "duration = " << duration << " micro-s" << std::endl;
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.