题目描述

大意:求解第kkk小的组合数

算法一:set+组合数

算法思路

  • 以下是1-12的组合数的图

图片说明

  • 通过图片我们可以发现C(i,0)=C(i,i)=1C(i,0)=C(i,i)=1C(i,0)=C(i,i)=1
  • 因为还有的组合数重复,所以我们用setsetset来去重
  • 故我们可以用一个setsetset来维护这些组合数的大小,但是计算的时候就不重复插入111
  • 将所有的组合数插入到setsetset中,最后返回setsetset中第kkk小的数
  • 计算组合数时,我们只需要计算底数i\leq ii的即可
  • 求解单个组合数,CnkC_n^kCnk分子分母约分后,可以在O(k)O(k)O(k)的复杂度求出来

代码实现

class Solution {
public:
  int C(int n, int k) //计算组合数C(n,k),n个里面取k个
  {//时间复杂度O(k)
      long long res = 1;
      for (int i = n; i >= n - k + 1; i -- ) //计算分子
          res *= i;
      for (int i = 1; i <= k; i ++ ) //除去分母
          res /= i;
      return res; //返回答案
  }
  int kthSamllest(int k) {
      set<int> s;
      s.insert(1);
      for (int i = 2; i <= k; i ++ ) //插入所有底小于等于k的组合数
          for (int j = 1; j <= i / 2; j ++ ) //C(i,0)=C(i,i)=1
            //故不需要重复插
              s.insert(C(i,j));
      int cnt = 0;
      for(auto it : s)
      {
          cnt ++ ;
          if(cnt == k) return it; //第k小的组合数
      }
      return 0;
  }
};

复杂度分析

  • 时间复杂度,求解单个组合数的时间复杂度为O(j)O(j)O(j),对于数iii,需要求解<mstyle displaystyle="true" scriptlevel="0">i2</mstyle>\cfrac{i}{2}2i个组合数,i=2kj=1<mstyle displaystyle="true" scriptlevel="0">i2</mstyle>j=2i=1ki(ki)=2ki2i2=2k<mstyle displaystyle="true" scriptlevel="0">k(k+1)2</mstyle>2<mstyle displaystyle="true" scriptlevel="0">k(k+1)(2k+1)6</mstyle>=O(k3)\sum_{i=2}^{k} \sum_{j=1}^{\lfloor \cfrac{i}{2}\rfloor} j=2\sum_{i=1}^{k}i(k-i)=2k\sum i - 2\sum i^2=2k*\cfrac{k(k+1)}{2}-2*\cfrac{k(k+1)(2k+1)}{6}=O(k^3)i=2kj=12ij=2i=1ki(ki)=2ki2i2=2k2k(k+1)26k(k+1)(2k+1)=O(k3),计算所有的组合数的时间复杂度为O(k3)O(k^3)O(k3)setsetset中插入的复杂度为logn\log nlogn,所以将所有组合数放入set中的复杂度为O(k3logk3)=O(3k3logk)=O(k3logk)O(k^3 \log k^3)=O(3k^3 \log k)=O(k^3 \log k)O(k3logk3)=O(3k3logk)=O(k3logk),set中查询的复杂度为O(logn)O(\log n)O(logn),但是遍历的复杂度为O(n)O(n)O(n),我们只遍历了前kkk个数,所以时间复杂度为O(k)O(k)O(k),总得时间复杂度为O(k3logk+k)=O(k3logk)O(k^3\log k+k)=O(k^3\log k)O(k3logk+k)=O(k3logk)级别
  • 空间复杂度,为set内元素的规模,为O(k3)O(k^3)O(k3)级别。

算法二:数学分析法

算法思路

  • 我们再仔细分析这张图片……………… 图片说明
  • 其实这题很好发现Ck1=Ckk1=kC_k^1=C_k^{k-1}=kCk1=Ckk1=k
  • 所以,其实我们直接return k;即可

代码实现

class Solution {
public:
    int kthSamllest(int k) {
        return k;
    }
};

复杂度分析

  • 时间复杂度,O(1)O(1)O(1)
  • 空间复杂度,O(1)O(1)O(1).