一、题目
二、思路(自己)
- 题目要求是字典序排列,即按照字符串比较一样进行排列,前几天刚好面过类似的题,为了降低时间复杂度,我们可以采用红黑树进行排序。
- 使用TreeSet来存储里面的数组,重写比较器即可。
class Solution {
public int findKthNumber(int n, int k) {
Set<Integer> set=new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
String s1=o1+"";
String s2=o2+"";
return s1.compareTo(s2);
}
});
for (int i = 1; i <=n ; i++) {
set.add(i);
}
Integer[] a=new Integer[n];
set.toArray(a);
return a[k-1];
}
}
- 这么写时间复杂度还是高了,我觉得用红黑树没错,不过后面可能有点问题。
class Solution {
public int findKthNumber(int n, int k) {
Set<Integer> set=new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
String s1=o1+"";
String s2=o2+"";
return s1.compareTo(s2);
}
});
for (int i = 1; i <=n ; i++) {
set.add(i);
}
// Integer[] a=new Integer[n];
// set.toArray(a);
// return a[k-1];
List<Integer> list=new ArrayList<>(set);
return list.get(k-1);
}
}
- 把后面取指定元素转换为list还是超出时间限制,说明此题不是用红黑树解。说明题解的解法比O(n)还小。
三、题解(官方)
- 官方题解就是给力,真的挺难想到的。我按照自己的理解加了注释
class Solution {
public int findKthNumber(int n, int k) {
int curr = 1;
k--;
while (k > 0) {
int steps = getSteps(curr, n);
if (steps <= k) {
//如果以curr为首的数字数量小于k
k -= steps;
curr++;
} else {
//以curr为首的数字数量大于k,k已经减去之前小于的数量了,当k为0时即已经找到了
curr = curr * 10;
k--;
}
}
return curr;
}
//获取curr为根节点的树的子节点数量
public int getSteps(int curr, long n) {
int steps = 0;
long first = curr;
long last = curr;
while (first <= n) {
steps += Math.min(last, n) - first + 1;
first = first * 10;
last = last * 10 + 9;
}
return steps;
}
}