我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
是前 10 个丑数。
说明:
1
是丑数。n
不超过1690。
注意:本题与主站 264 题相同:https://leetcode-cn.com/problems/ugly-number-ii/
- 哈希表
- 数学
- 动态规划
- 堆(优先队列)
著书三年倦写字,如今翻书不识志,若知倦书悔前程 ,无如渔樵未识时
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
是前 10 个丑数。
说明:
1
是丑数。n
不超过1690。注意:本题与主站 264 题相同:https://leetcode-cn.com/problems/ugly-number-ii/
dp,算是dp吧
此处撰写解题思路
class Solution {
public int nthUglyNumber(int n) {
int[] dp = new int[n];
dp[0] = 1;
int[] numArr = new int[]{2,3,5};
int[] pArr = new int[3];
for (int i = 1; i < n; i++) {
dp[i] = Math.min(Math.min(dp[pArr[0]]*numArr[0],dp[pArr[1]]*numArr[1]),dp[pArr[2]]*numArr[2]);
for (int p = 0; p < pArr.length; p++) {
if (dp[i] == dp[pArr[p]]*numArr[p]){
pArr[p]++;
}
}
}
return dp[n-1];
}
}
输入整数数组 arr
,找出其中最小的 k
个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2 输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1 输出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
堆排序
此处撰写解题思路
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if (k == 0){
return new int[0];
}
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for (int i : arr) {
if (queue.size() < k){
queue.offer(i);
}else if(i < queue.peek()){
queue.poll();
queue.offer(i);
}
}
int[] res = new int[k];
for (int i = 0; i < res.length; i++) {
res[i] = queue.poll();
}
return res;
}
}
给你一个长度为 n
的整数数组 score
,其中 score[i]
是第 i
位运动员在比赛中的得分。所有得分都 互不相同 。
运动员将根据得分 决定名次 ,其中名次第 1
的运动员得分最高,名次第 2
的运动员得分第 2
高,依此类推。运动员的名次决定了他们的获奖情况:
1
的运动员获金牌 "Gold Medal"
。2
的运动员获银牌 "Silver Medal"
。3
的运动员获铜牌 "Bronze Medal"
。4
到第 n
的运动员,只能获得他们的名次编号(即,名次第 x
的运动员获得编号 "x"
)。使用长度为 n
的数组 answer
返回获奖,其中 answer[i]
是第 i
位运动员的获奖情况。
示例 1:
输入:score = [5,4,3,2,1] 输出:["Gold Medal","Silver Medal","Bronze Medal","4","5"] 解释:名次为 [1st, 2nd, 3rd, 4th, 5th] 。
示例 2:
输入:score = [10,3,8,9,4] 输出:["Gold Medal","5","Bronze Medal","Silver Medal","4"] 解释:名次为 [1st, 5th, 3rd, 2nd, 4th] 。
提示:
n == score.length
1 <= n <= 104
0 <= score[i] <= 106
score
中的所有值 互不相同
优先队列
此处撰写解题思路
class Solution {
public String[] findRelativeRanks(int[] score) {
PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o2[0] - o1[0];
}
});
for (int i = 0; i < score.length; i++) {
queue.add(new int[]{score[i],i});
}
String[] arr = new String[score.length];
String[] top = new String[]{"Gold Medal","Silver Medal","Bronze Medal"};
int i = -1;
while (!queue.isEmpty()){
int[] cur = queue.poll();
if (++i < top.length){
arr[cur[1]] = top[i];
}else{
arr[cur[1]] = (i + 1) + "";
}
}
return arr;
}
}
给你一个按递增顺序排序的数组 arr
和一个整数 k
。数组 arr
由 1
和若干 素数 组成,且其中所有整数互不相同。
对于每对满足 0 <= i < j < arr.length
的 i
和 j
,可以得到分数 arr[i] / arr[j]
。
那么第 k
个最小的分数是多少呢? 以长度为 2
的整数数组返回你的答案, 这里 answer[0] == arr[i]
且 answer[1] == arr[j]
。
示例 1:
输入:arr = [1,2,3,5], k = 3 输出:[2,5] 解释:已构造好的分数,排序后如下所示: 1/5, 1/3, 2/5, 1/2, 3/5, 2/3 很明显第三个最小的分数是 2/5
示例 2:
输入:arr = [1,7], k = 1 输出:[1,7]
提示:
2 <= arr.length <= 1000
1 <= arr[i] <= 3 * 104
arr[0] == 1
arr[i]
是一个 素数 ,i > 0
arr
中的所有数字 互不相同 ,且按 严格递增 排序1 <= k <= arr.length * (arr.length - 1) / 2
优先队列两种实现
首先,直接上来一个优先队列,自定义排序。
为了实现这个自定义的排序,我们需要记录几个东西
理解起来也相对比较简单
class Solution {
public int[] kthSmallestPrimeFraction(int[] arr, int k) {
PriorityQueue<double[]> queue = new PriorityQueue<>(new Comparator<double[]>() {
@Override
public int compare(double[] o1, double[] o2) {
if (o1[2] >= o2[2]){
return 1;
}
return -1;
}
});
for (int i : arr) {
for (int j : arr) {
queue.offer(new double[]{(double)i,(double)j,((double)i)/j});
}
}
while (--k > 0){
queue.poll();
}
return new int[]{(int)queue.peek()[0],(int)queue.peek()[1]};
}
}
写完这个之后思考一下,我们真的需要把所有的值都算一遍全都存进优先队列么?答案是否定的,
arr[]
数组长度个分组,arr[]
数组长度个值即可,每当从队列头部取出一个对象时,只需把分子位置往后挪动一位,重新放入队列arr[]
数组尾部,则不再需要往队列中添加class Solution {
public int[] kthSmallestPrimeFraction(int[] arr, int k) {
PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if (((double)arr[o1[0]])/arr[o1[1]] >= ((double)arr[o2[0]])/arr[o2[1]]){
return 1;
}
return -1;
}
});
for (int i = 0; i < arr.length; i++) {
queue.offer(new int[]{0,i});
}
while (--k > 0) {
int[] top = queue.poll();
if (top[0] < arr.length){
top[0]++;
queue.offer(top);
}
}
return new int[]{arr[queue.peek()[0]],arr[queue.peek()[1]]};
}
}