LeetCode--263. Ugly Number & 264. Ugly Number II & 313. Super Ugly Number

问题链接:https://leetcode.com/problems/ugly-number/https://leetcode.com/problems/ugly-number-ii/https://leetcode.com/problems/super-ugly-number/

关于丑陋数,问题比较简单,问题二和三也不难,但值得研究研究。

问题一思路:比较直接没啥好说的,注意丑陋数为正数

class Solution {
    
    public boolean isUgly(int num) {
        if(num<=0)
            return false;
        while(num>1)
        {
            if(num%2==0)
            {
                num/=2;
            }
            else if(num%3==0)
            {
                num/=3;
            }
            else if(num%5==0)
            {
                num/=5;
            }
            else
                return false;
        }
        return true;
    }
}

问题二:优先队列加哈希集合,注意乘法运算溢出的问题,这里使用Long型

class Solution {
    public static int nthUglyNumber(int n) {

        PriorityQueue<Long> pq=new PriorityQueue<>();
        HashSet<Long> set=new HashSet<>();
        set.add(new Long(1));
        pq.add(new Long(1));
        Long ret=new Long(1);
        for(int i=1;i<=n;i++)
        {
            ret=pq.poll();
            if(set.add(ret*2))
                pq.add(ret*2);
            if(set.add(ret*3))
                pq.add(ret*3);
            if(set.add(ret*5))
                pq.add(ret*5);
        }
        return ret.intValue();
    }
}

因为使用了优先队列和集合操作,时间复杂度为O(nlogK),这个效率比较低。

当然上面的思路还可以优化一下,不需要使用集合来判重,代码如下:

public int nthUglyNumber(int n) {
    if(n==1) return 1;
    PriorityQueue<Long> q = new PriorityQueue();
    q.add(1l);
    
    for(long i=1; i<n; i++) {
        long tmp = q.poll();
        while(!q.isEmpty() && q.peek()==tmp) tmp = q.poll();
        
        q.add(tmp*2);
        q.add(tmp*3);
        q.add(tmp*5);
    }
    return q.poll().intValue();
}

其实使用TreeSet可以实现优先队列和集合的功能:

public class Solution {
    public int nthUglyNumber(int n) {
        TreeSet<Long> ans = new TreeSet<>();
        ans.add(1L);
        for (int i = 0; i < n - 1; ++i) {
            long first = ans.pollFirst();
            ans.add(first * 2);
            ans.add(first * 3);
            ans.add(first * 5);
        }
        return ans.first().intValue();
    }
}

有没有更简洁的思路呢?Hint中提示了动态规划的思路:

public int nthUglyNumber(int n) {
		int[] res = new int[n];
		res[0] = 1;
		int t2 = 0, t3 = 0, t5 = 0, idx = 1;
		while (idx < n) {
			res[idx] = Math.min(res[t2] * 2, Math.min(res[t3] * 3, res[t5] * 5));
			t2 += res[idx] == res[t2] * 2 ? 1 : 0;
			t3 += res[idx] == res[t3] * 3 ? 1 : 0;
			t5 += res[idx] == res[t5] * 5 ? 1 : 0;
			++idx;
		}
		return res[n - 1];
	}

时间和空间复杂度都为O(n),简直clean and concise!

问题三:问题二思路是可以应用到问题三的

class Solution {
    public int nthSuperUglyNumber(int n, int[] primes) {
        
        PriorityQueue<Long> pq=new PriorityQueue<>();
        HashSet<Long> set=new HashSet<>();
        pq.add(1L);
        Long tmp=1L;
        for(int i=0;i<n;i++)
        {
            tmp=pq.poll();
            for(int j=0;j<primes.length;j++)
            {
                Long a=primes[j]*tmp;
                if(!set.contains(a))
                {
                    pq.add(a);
                    set.add(a);
                }
            }
        }
        return tmp.intValue();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值