给定整数n和k,找到按字典顺序排列的第k个最小整数,范围从1到n。
注:1≤k≤n≤109。
示例:
输入: n:13 k:2
输出: 10
说明: 字典顺序是[1,10,11,12,13,2,3,4,5,6,7,8,9],所以第二个最小数字是10.
我编写了一个可以正常工作的代码但是当我提供非常高的输入时,它需要花费很多时间来执行并因此超时。有人可以建议我如何提高效率。
谢谢!
public class Solution {
class MyComp implements Comparator<Integer>{
@Override
public int compare(Integer n1, Integer n2) {
return String.valueOf(n1).compareTo(String.valueOf(n2));
}
}
public int findKthNumber(int n, int k) {
if(n==0 || k ==0 || k > n) return 0;
int[] tracker = new int[9];
Arrays.fill(tracker,0);
Map<Integer,TreeSet<Integer>> map = new HashMap<Integer,TreeSet<Integer>>();
for(int i =1;i<=n;i++){
String prefix = String.valueOf(i);
int currIndex = Integer.parseInt(prefix.substring(0,1));
//Update count
tracker[currIndex-1] = tracker[currIndex-1] + 1;
if(map.containsKey(currIndex)){
TreeSet<Integer> set = map.get(currIndex);
set.add(i);
map.put(currIndex,set);
}else{
TreeSet<Integer> set = new TreeSet<Integer>(new MyComp());
set.add(i);
map.put(currIndex,set);
}
}
// counter to check the if we reach near by K
int count =1;
for(int i=0;i<9 ;i++ ){
int lookUp = i+1;
int val = tracker[i];
if( count + map.get(lookUp).size() > k){
for(int res : map.get(lookUp)){
if(count == k) return res;
count++;
}
}
count = count + map.get(lookUp).size();
}
return 0;
}
}
答案 0 :(得分:0)
对于如此小的数字,您可以在数组中生成所有字符串,对其进行排序并返回第k个条目:
String[] arr = new String[n];
for (int i = 0; i < n; i++)
arr[i] = String.valueOf(n + 1);
Arrays.sort(arr);
return Integer.parseInt(arr[k - 1]);
这似乎比计入第k个条目容易得多。你不需要对整个数组进行排序,因为你只需要找到第k个最小的条目,无论如何对于那些小数字并不重要。
甚至更好地使用整数数组和您已创建的比较器:
Integer[] arr = new Integer[n];
for (int i = 0; i < n; i++)
arr[i] = i + 1;
Arrays.sort(arr, MyComp);
return arr[k - 1].intValue();
答案 1 :(得分:0)
您可以使用QuickSort查找位置。这将给你nlogn,但会更快更简单。
Psudo代码
- &GT;挑选出列表的随机数。
- &GT;把所有元素都小于那一边,高于另一边的那个数字。
- &gt;如果较小元素的数量是k-1,你就得到了答案。
- &gt;如果较小的元素小于k-1,则在右侧应用相同的算法。
- &GT;如果较少数量的元素大于k,则在左侧应用相同的算法。
您可以在现场执行此操作 最佳时间复杂度为o(1) 最糟糕的时间复杂度是o(n * n) 但它为多次迭代提供了非常稳定的性能 随机性适用于所有类型的数据
如果有任何步骤不清楚,请告诉我。)