C++ 查找不在1和10000000之间的丑陋数字
我在试图找出那个不难看的数字时遇到了一些问题。 丑陋的数字是唯一的素数为2、3或5的数字。那么,不丑陋的数字呢? 我试图找出介于1和100000000之间的不难看的数字。我的程序可以解决这个问题,但似乎有点慢。如何使它更快? 代码如下:C++ 查找不在1和10000000之间的丑陋数字,c++,C++,我在试图找出那个不难看的数字时遇到了一些问题。 丑陋的数字是唯一的素数为2、3或5的数字。那么,不丑陋的数字呢? 我试图找出介于1和100000000之间的不难看的数字。我的程序可以解决这个问题,但似乎有点慢。如何使它更快? 代码如下: #include <iostream> #include <queue> using namespace std; typedef pair<unsigned long,int> node_type; main() {
#include <iostream>
#include <queue>
using namespace std;
typedef pair<unsigned long,int> node_type;
main()
{
//generates 1500 ugly numbers into result[];
unsigned long result[1500];
priority_queue<node_type,vector<node_type>,greater<node_type> > Q;
Q.push(node_type(1,2));
for(int i=0;i<1500;i++)
{
node_type node = Q.top();
Q.pop();
switch(node.second)
{
case 2:Q.push(make_pair(node.first*2,2));
case 3:Q.push(make_pair(node.first*3,3));
case 5:Q.push(make_pair(node.first*5,5));
}
result[i]=node.first;
}
/*****************************************************
//Here is the approach I used:
//The initial value of the integer k is 1;
//and will increase by 1 every time
//k will be checked if it's a ugly number,if not increase by 1,keep doing
//this till k is not a ugly number,then count how much ugly number(we may
//call it n) is less the the
//current value of k.The result of (k-n) is the order number of this (k) not ugly
//for example:the 1st not ugly number is 7.
// there are 6 ugly number less than 7,which are 1 2 3 4 5 6,
// k=1-->k==2-->.....k=7, k-n=7-6=1,so 7 is the 1st not ugly number
***************************************************************/
int T; // The amount of cases
cin>>T;
while(T--)
{
int n;
int k=0,i=0,count=0;
cin>>n;
while(n)
{
if((k+1)==result[i]) {k++;i++;count++;}
else
{
k++;
if(k-count==n) {cout<<k<<endl;break;}
}
}
}}
#包括
#包括
使用名称空间std;
typedef对节点\ u类型;
main()
{
//将1500个丑陋的数字生成结果[];
无符号长结果[1500];
优先级队列Q;
Q.push(节点_型(1,2));
对于(inti=0;i理解代码,我知道您真正想要的是快速找到
第n个非丑陋数字
你找到第n个非丑数的算法是O(n),你可以用二进制搜索找到它们,它是O(log(n))
有T种情况,如果T很大,我的方法可以节省很多时间
这是我的密码,换成你的
#include <iostream>
#include <queue>
using namespace std;
typedef pair<unsigned long,int> node_type;
int main()
{
//generates 1500 ugly numbers into result[];
unsigned long result[1500];
priority_queue<node_type,vector<node_type>,greater<node_type> > Q;
Q.push(node_type(1,2));
for(int i=0;i<1500;i++)
{
node_type node = Q.top();
Q.pop();
switch(node.second)
{
case 2:Q.push(make_pair(node.first*2,2));
case 3:Q.push(make_pair(node.first*3,3));
case 5:Q.push(make_pair(node.first*5,5));
}
result[i]=node.first;
}
int T; // The amount of cases
cin>>T;
//b_search_data[i] mean the count of non ugly number blow or equal i, i start from 1
unsigned long b_search_data[1501];
for (int i=0; i<1500; i++)
{
b_search_data[i] = result[i] - i - 1;
}
vector<int> search_data(b_search_data, b_search_data+1500);
while(T--)
{
int n;
int k=0,i=0,count=0;
cin>>n;
// use binary search here to find the n-th non ugly number instead your approach
int position = upper_bound(search_data.begin(), search_data.end(), n-1) - search_data.begin();
// position means
cout<<position + n<<endl;
}
}
#包括
#包括
使用名称空间std;
typedef对节点\ u类型;
int main()
{
//将1500个丑陋的数字生成结果[];
无符号长结果[1500];
优先级队列Q;
Q.push(节点_型(1,2));
对于(int i=0;i>T;
//b_search_data[i]是指非丑陋数字blow或等于i的计数,i从1开始
无符号长b_搜索_数据[1501];
对于(int i=0;i>n;
//在这里使用二进制搜索来查找第n个非丑陋数字,而不是您的方法
int position=上限(search_data.begin(),search_data.end(),n-1)-search_data.begin();
//职位意味着
cout好吧,我咬一口。根据这个定义,测试一个数字是否丑陋实际上在计算上相当简单。用暴力测试1亿个数字
#include <iostream>
bool is_ugly(unsigned n) {
while(n % 5 == 0) n /= 5;
while(n % 3 == 0) n /= 3;
while(n % 2 == 0) n /= 2;
return n == 1;
}
int main() {
unsigned counter = 0;
for(unsigned i = 1; i <= 100000000; ++i) {
if(!is_ugly(i)) {
++counter;
}
}
std::cout << counter << std::endl;
}
这个报告回来了,嗯
$ time ./a.out
1105
real 0m0.001s
user 0m0.000s
sys 0m0.000s
你可以使用这个函数,希望num.find(n)=num.end()
比is_丑陋(n)
(使用以前的is_丑陋
函数)更快地测试非丑陋性,但在我的基准测试中,差异可以忽略不计,而使用std::unordered_set
实际上要慢2-3倍
附录:可以节省一些时间的是将丑陋的数字生成一个std::vector
,包含1亿个元素,如下所示:
// num is to have the wanted size in advance and be full of false
void generate_uglies(unsigned n, std::vector<bool> &num) {
if(n < num.size() && !num[n]) {
num[n] = true;
generate_uglies(n * 2, num);
generate_uglies(n * 3, num);
generate_uglies(n * 5, num);
}
}
//num是预先拥有想要的大小,并且充满false
void generate_uglies(无符号n,std::vector&num){
如果(n
然后用!num[i]
测试非难看的数字。!num[i]
测试比是难看的
函数快得多(对于平均低于1亿的值,测试速度是~5倍)1.出于上述原因,如果要打印它们,这并不重要,但在不同的上下文中,这可能会产生明显的差异。请注意,此表需要12.5 MB RAM
1由于您的机器不是我的,因此您的里程数会有所不同。我使用的是一台1.5年的i7。生成难看的数字可以通过递归函数实现
实际上,如果N
是丑陋的,那么2*N
、3*N
和5*N
也是丑陋的
实际上,2*N
、3*N
和5*N
都是丑陋的数字大于N,因此您可以确定一个最大值,比如说MAX
,并通过添加2*N
、3*N
和5*N
(这是递归部分)来查看比N
更丑陋的数字
为了停止重复搜索,我们可以将所有找到的数字存储在一组丑陋的数字中,因此,例如,当我们得到6作为3*2
的乘积时,当我们找到2*3
时,我们不添加它(并研究它所有丑陋的后代)(也等于6--我们称之为冲突)
该计划最终将实现:
#include <cstdio>
#include <set>
using namespace std;
const unsigned N = 10000000;
set<unsigned> uglys;
unsigned n_collis = 0;
void srch_ugly(unsigned n)
{
if (uglys.find(n) != uglys.end()) { /* found in set */
++n_collis;
} else {
uglys.insert(n);
if (2*n < N) srch_ugly(2*n);
if (3*n < N) srch_ugly(3*n);
if (5*n < N) srch_ugly(5*n);
} /* if */
} /* srch_ugly(unsigned) */
int main()
{
unsigned col = 0; /* printing column */
srch_ugly(1);
/* print results */
printf("%lu uglys. %u collissions.\n", uglys.size(), n_collis);
for (set<unsigned>::iterator i = uglys.begin();
i != uglys.end();
++i)
{
if (col >= 72) {
puts("");
col = 0;
} /* if */
col += printf("%s%i", col ? " " : "", *i);
} /* for */
if (col) puts("");
} /* main */
#包括
#包括
使用名称空间std;
常数无符号N=10000000;
设置uglys;
无符号n_collis=0;
void srch_丑陋(未签名n)
{
如果(uglys.find(n)!=uglys.end()){/*在集合中找到*/
++n_collis;
}否则{
uglys.插入(n);
如果(2*n=72){
认沽权(“”);
col=0;
}/*如果*/
col+=printf(“%s%i”,col?”:“”,*i);
}/*用于*/
若(col)以(“”)号填列;
}/*主要*/
注
很抱歉使用了printf
stdio函数,但我想在72个字符处剪切行,而printf
函数返回打印的字符数(我不知道如何从ostream
类中获取实际打印的字符数),所以我使用了它们。定义“更快”?需要多快?现在有多快?这个问题可能更适合。它甚至不编译。我希望至少有一个名为isught()的函数;你实际上需要做什么?找到所有不难看的数字,或者确定某个特定的数字是否难看?你说你需要前者,但从你的代码来看,你实际上需要后者。两个词:。你有多少可用内存?是的,你希望它有多快?谢谢你的回答!我花了很多时间才弄明白站起来,因为我只是一个初学者……不管怎样,我从你的分析中学到了很多。:)很好的解决方案!我也在考虑使用二进制搜索来找到答案,但我不知道怎么做……你告诉我在这个问题中使用二进制搜索的方法。谢谢!
#include <cstdio>
#include <set>
using namespace std;
const unsigned N = 10000000;
set<unsigned> uglys;
unsigned n_collis = 0;
void srch_ugly(unsigned n)
{
if (uglys.find(n) != uglys.end()) { /* found in set */
++n_collis;
} else {
uglys.insert(n);
if (2*n < N) srch_ugly(2*n);
if (3*n < N) srch_ugly(3*n);
if (5*n < N) srch_ugly(5*n);
} /* if */
} /* srch_ugly(unsigned) */
int main()
{
unsigned col = 0; /* printing column */
srch_ugly(1);
/* print results */
printf("%lu uglys. %u collissions.\n", uglys.size(), n_collis);
for (set<unsigned>::iterator i = uglys.begin();
i != uglys.end();
++i)
{
if (col >= 72) {
puts("");
col = 0;
} /* if */
col += printf("%s%i", col ? " " : "", *i);
} /* for */
if (col) puts("");
} /* main */