题目

设计一个算法,找出只含素因子357 的第 k 大的数。

符合条件的数如:3,5,7,9,15......

样例

如果k=4, 返回 9

挑战

要求时间复杂度为O(nlogn)或者O(n)

解题

法一:直接暴力,逐次判断一个数是不是丑数

下面只对其中的奇数判断是否是丑数,加不加奇数都超时。

class Solution {
/**
* @param k: The number k.
* @return: The kth prime number as description.
*/
public long kthPrimeNumber(int k) {
// write your code here
int i = 0;
int num = 3;
while( i < k){
if(isUgly(num)){
i++;
}
num += 2;
}
return num - 2;
}
public boolean isUgly(long num){
while(num%3 == 0){
num = num/3;
}
while(num%5 ==0){
num = num/5;
}
while(num%7==0){
num = num/7;
}
return num==1;
}
};

法二:直接求丑数

参考链接

最小的连续三个丑数是:3,5,7.以后的每个丑数其因子也只能是3 5 7 那么我们就可以看作:每个丑数可以写成num = 3i* 5j*7k   ,每个丑数也一定是其前面的丑数乘以 3 或5 或7 得到的数,这样我们可以以3 5 7 作为丑数的基数数组,这个丑数数组中的每个数分别乘以 3, 5, 7,得到三个丑数数组,当然其中也一定会有重复的,选取不在原丑数数组中的最小的那个数,加入的丑数数组中,丑数数组的元素就增加一个。

问题是:对三个数字,如何分别找乘以3 5 7 的最小值?

假设先找乘以3 的最小值,由于原始丑数数组是有序的,则第一个不在丑数数组中的那个数字就是最小的,对于 5 7 同理,第一个不在丑数数组中的那个数就是最小的丑数,或者说是第一个大于所有丑数的那个数就是最小的丑数,这样,我们就找到了三个丑数。最小的丑数加入的丑数数组中。

class Solution {
/**
* @param k: The number k.
* @return: The kth prime number as description.
*/
public long kthPrimeNumber(int k) {
// write your code here
long u[] = new long[k+1];
u[0] = 1;
int index = 1;
int i1 = 0,i2 = 0,i3 = 0;
long MIN = 0;
while(index <= k){
MIN = Math.min(u[i1] * 3 ,Math.min(u[i2] * 5,u[i3] * 7));
u[index++] = MIN;
i1 = 0;
i2 = 0;
i3 = 0;
while( u[i1] *3 <= MIN){
i1++;
}
while(u[i2] *5 <= MIN){
i2++;
}
while(u[i3] *7 <= MIN){
i3++;
}
}
return u[k];
}
};

Java Code

总耗时: 752 ms

但是通过上面程序中,每次都要遍历一遍丑数数组,时间复杂度比较长,但是也竟然AC了,同时里面重读的数也很多。我们可以记录中间的某个丑数的下标 ui来实现,现在其之前的数乘以3都会小于于最大的丑数,其之后的数乘以3都大于最大的丑数。5 7 同理。这样,我们可以在原先找到的满足最小大于丑数数组最大值的那个原始的下标来考虑。

设 3 5 7对应的下标是:i1  i2 i3 这里的下标意思:u[i1]*2是第一个大于最大丑数数组最大值的数。i1 i2 i3 可以理解为不同步的三个指针

当 i1是三个最小丑数中的最小值,则u[i1]*3 加入到丑数数组中,u[i1]*3 就是当前丑数数组的最大值,同时i1+=1 这里进行加1 处理,因为其i1之前的数乘以2的值一定小于u[i1]*3 ,并且这个元素已经在丑数数组u中了,u[i1 + 1] * 3 也就是第一个大于丑数数组最大值的数组。此时对于  i2 i3 不做处理。其他情况类似。

class Solution {
/**
* @param k: The number k.
* @return: The kth prime number as description.
*/
public long kthPrimeNumber(int k) {
// write your code here
long u[] = new long[k+1];
u[0] = 1;
int index = 1;
int i1 = 0,i2 = 0,i3 = 0;
long MIN = 0;
while(index <= k){
MIN = Math.min(u[i1] * 3 ,Math.min(u[i2] * 5,u[i3] * 7));
u[index++] = MIN;
if(MIN == u[i1] * 3){
i1 += 1;
}
if(MIN == u[i2] * 5){
i2 +=1;
}
if(MIN == u[i3] * 7){
i3 +=1;
}
}
return u[k];
}
};

Java Code

总耗时: 1241 ms

用ArrayList

class Solution {
/**
* @param k: The number k.
* @return: The kth prime number as description.
*/
public long kthPrimeNumber(int k) {
// write your code here
int i1 = 1;
int i2 = 1;
int i3 = 1;
List<Long> list = new ArrayList<Long>(); list.add((long)1);
while(list.size() <= k){
long u1 = list.get(i1-1) * 3;
long u2 = list.get(i2-1) * 5;
long u3 = list.get(i3-1) * 7;
long min = Math.min(u1,Math.min(u2,u3));
if(min == u1)
i1++;
if(min == u2)
i2++;
if(min == u3)
i3++;
list.add(min);
} return (long)list.get(k);
} };

Java Code

总耗时: 557 ms

class Solution:
"""
@param k: The number k.
@return: The kth prime number as description.
"""
def kthPrimeNumber(self, k):
# write your code here
i1 = 1
i2 = 1
i3 = 1
u = []
u.append(1)
while len(u) <= k:
u1 = u[i1 - 1] * 3
u2 = u[i2 - 1] * 5
u3 = u[i3 - 1] * 7
minu = min(u1,min(u2,u3))
if minu == u1:
i1 += 1
if minu == u2:
i2 += 1
if minu == u3:
i3 += 1
u.append(minu)
return u[k]

Python Code

总耗时: 108 ms

输出第10个丑数的计算过程:

[1]
-------------------
3 5 7
[1, 3]
-------------------
9 5 7
[1, 3, 5]
-------------------
9 15 7
[1, 3, 5, 7]
-------------------
9 15 21
[1, 3, 5, 7, 9]
-------------------
15 15 21
[1, 3, 5, 7, 9, 15]
-------------------
21 25 21
[1, 3, 5, 7, 9, 15, 21]
-------------------
27 25 35
[1, 3, 5, 7, 9, 15, 21, 25]
-------------------
27 35 35
[1, 3, 5, 7, 9, 15, 21, 25, 27]
-------------------
45 35 35
[1, 3, 5, 7, 9, 15, 21, 25, 27, 35]
-------------------
45 45 49
[1, 3, 5, 7, 9, 15, 21, 25, 27, 35, 45]
-------------------
45

lintcode :Ugly Numbers 丑数的更多相关文章

  1. Humble Numbers(丑数) 超详解!

    给定一个素数集合 S = { p[1],p[2],...,p[k] },大于 1 且素因子都属于 S 的数我们成为丑数(Humble Numbers or Ugly Numbers),记第 n 大的丑 ...

  2. Ugly number丑数2,超级丑数

    [抄题]: [思维问题]: [一句话思路]:Long.valueOf(2)转换为long型再做 [输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况(不合法不合理的输入): [画图 ...

  3. [LintCode] Ugly Number 丑陋数

    Write a program to check whether a given number is an ugly number`. Ugly numbers are positive number ...

  4. 263 Ugly Number 丑数

    编写程序判断给定的数是否为丑数.丑数就是只包含质因子 2, 3, 5 的正整数.例如, 6, 8 是丑数,而 14 不是,因为它包含了另外一个质因子 7.注意:    1 也可以被当做丑数.    输 ...

  5. LeetCode OJ:Ugly Number II(丑数II)

    Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose prime factors ...

  6. LeetCode OJ:Ugly Number(丑数)

    Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers ...

  7. 丑数(Ugly Numbers, UVa 136)

    丑数(Ugly Numbers, UVa 136) 题目描述 我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因 ...

  8. UVA - 136 Ugly Numbers(丑数,STL优先队列+set)

    Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9 ...

  9. NYOJ1097 Ugly Numbers 【丑数】

    Ugly Numbers 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描写叙述 Ugly numbers are numbers whose only prime fact ...

随机推荐

  1. 【Qt】Qt之进程间通信(共享内存)【转】

    简述 上一节中,我们分享下如何利用Windows消息机制来进行不同进程间的通信.但是有很多局限性,比如:不能跨平台,而且必须两个进程同时存在才可以,要么进程A发了消息谁接收呢? 下面我们来分享另外一种 ...

  2. 【Qt】Qt Creator介绍【转】

    简介 Qt Creator是使用Qt开发的IDE.Qt支持Windows.Linux/Unix.Mac OS X.Android.BlackBerry.QNX等多种平台,Qt Creator为不同平台 ...

  3. php保存base64数据

    php保存base64数据 if(isset($param['cover_pic']) && !empty($param['cover_pic'])) {
 if (preg_matc ...

  4. Hadoop管理员的十个最佳实践(转)

    前言 接触Hadoop有两年的时间了,期间遇到很多的问题,既有经典的NameNode和JobTracker内存溢出故障,也有HDFS存储小文件问题,既有任务调度问题,也有MapReduce性能问题.遇 ...

  5. keyboard

    一 按键驱动程序的简单实现 下面是基于中断和消息的按键驱动程序,其工作原理是:当应用程序读取键值时,会调用按键驱动程序的read函数,而我们实现的read函数检测完读取长度后没有直接读取键值而是等待按 ...

  6. 关闭ios虚拟键盘的几种方法

    在iOS应用开发中,有三类视图对象会打开虚拟键盘,进行输入操作,但如何关闭虚拟键盘,却没有提供自动化的方法.这个需要我们自己去实现.这三类视图对象分别是UITextField,UITextView和U ...

  7. c 标签

    1 . c:out  -- Like <%= ... >, but for expressions. =out.println(String) <c:out value=" ...

  8. Windows程序消息机制浅析

    1.消息  消息是由MSG结构体来表示的.如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lPar ...

  9. inputstream和outputstream读写数据模板代码

    //读写数据模板代码 byte buffer[] = new byte[1024]; int len=0; while((len=in.read(buffer))>0){ out.write(b ...

  10. cocos2dx中的实现地图卷动的两种方式

    在游戏当中,实现地图卷动是最基本的功能,具体的实现的方法,大致有两类: 方法一:加载两张图片,轮流显示, 优点: 1.无论是地图上下卷动,还是左右卷动都可以 2.支持各种图片,(png,jpg...) ...