剑指offer刷题总结

快速幂

求a的b次方(b为整型):

不妨记b的二进制为 bnbn1...b0 ,其中 bi=0 or 1 ,则:

ab=abn2n+...+b020=(a20)b0...(a2n)bn

可以看到新的底数 a2i+1=a2ia2i ,根据这个规律可以写出快速幂的代码(仅考虑 b>0 的情况):

public double Power(double a, int b) {
    double base = a;
    double result = 1;
    while(b != 0){
        //判断b二进制末位是1,即bi是1的情况下,result需要乘上新的底数
        if((b & 1) == 1) result * = base; 
        //按照规律更新底数
        base * = base;
        //将b的二进制右移1位,即删掉原始末位
        b >> = 1;
    }   
    return result;
}

相比于循环 b 次做乘法,快速幂的时间复杂度仅为O(logb)

字典序全排列

以元素互异的字符集{ p1 , p2 ,…, pn }为例,输出它的全排列
假设字符元素之间存在某种偏序关系,例如整数集可以利用数值大小进行排序。全排列可以看成由字符集所有元素组成的字符串,如何不重复有序地输出该字符集的所有全排列,关键在于如何根据给定的全排列有规则地输出下一个全排列。

以{1,2,3}为例,其全排序为123,132,213,231,312,321,可以看到这里全排列的枚举方式保证了全排列的递增趋势,我们可以将这个递增的规则抽象出全排列生成的规则,从而避免重复枚举,或者遗漏。

根据上述例子,可以简述一下字典序全排列的步骤:

  • 记当前的全排列 p=p1...pn
  • 找到 j=max{i|pi<pi+1} , k=max{i|pi>pj}
  • 交换换 pj,pk
  • pj+1...pn 这部分后缀进行翻转

可以证明一下这样得到的全排列,是大于当前全排列的最小的全排列(不妨假设字符集为正整数集):

  1. i>j , 则 pi>pi+1 ,且 k>j(pj+1>pj)
  2. 因为下标为 j 之前的部分没有发生改变,不妨忽略,记后缀部分为p=pj..pk...pn, pj+1...pn 为递减列, p>pj() ,其中 pj() 是指以 pj 开头的任意后缀,当然后面的字符为 pj+1...pn 的全排列
  3. pk 为后续字符中大于 pj 的最小字符, 下一个全排列应为 pk()
  4. pj pk 交换后,后面仍为递减列,将其翻转则为递增列,为这些字符组成的最小的全排列
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值