按字典顺序排列最小的

时间:2016-10-23 19:10:58

标签: algorithm data-structures

给定整数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;

}

}

2 个答案:

答案 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) 但它为多次迭代提供了非常稳定的性能 随机性适用于所有类型的数据

如果有任何步骤不清楚,请告诉我。)