【问题标题】:K-th Smallest in Lexicographical Order按字典顺序排列的第 K 个最小的
【发布时间】:2016-10-23 19:10:58
【问题描述】:

给定整数 n 和 k,找出从 1 到 n 范围内按字典顺序排列的第 k 个最小整数。

注: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;

}

}

【问题讨论】:

  • 为什么它的字典顺序使它独一无二?为什么不查看代码以获取有效的订单统计信息,并使用字典顺序进行比较?
  • TLE 是因为 N 很大。鉴于 N 很大,您应该查看 log N 解决方案。

标签: algorithm data-structures


【解决方案1】:

您可以使用快速排序来查找位置。这会给你 nlogn 但会更快更简单。

伪代码 -> 选择列表中的随机数。 -> 将所有元素小于一侧,高于另一侧。
->如果较小元素的数量是k-1,你就得到了答案。 -> 如果较小的元素小于 k-1,则在右侧应用相同的算法。 -> 如果较少数量的元素大于 k,则在左侧应用相同的算法。

您可以就地执行此操作 最佳时间复杂度为 o (1) 最差时间复杂度为 o (n*n) 但它为多次迭代提供了非常稳定的性能 随机性适用于所有类型的数据

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

【讨论】:

  • 谢谢!它有帮助!
  • 注意:您可以使用 Quicksort 的近亲 Quickselect 将平均运行时间从 nlogn 提高到简单的 n。快速选择的递归公式是 T(n) = T(n/2) + O(n)
【解决方案2】:

对于这么小的数字,您可以在一个数组中生成所有字符串,对其进行排序并返回第 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();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 2022-11-19
    • 1970-01-01
    相关资源
    最近更新 更多