《剑指offer》练习及解析(C++代码)13-16

一.剑指 Offer 13. 机器人的运动范围

解法:

1.回溯法

一种搜索方法,每次选择一个方向向前搜索,直到到达最优目标或确定无法达到目标时,后退重新向未选择的方向前进。

用二维数组记录是否走过此位置,且每次只需向下或向右行进即可

代码:

//My solution 回溯
//24ms:6.5 ;10mb:100, O(n)
class Solution {
public:
    const vector<vector<int>> step={{1,0},{0,1}};
    int movingCount(int m, int n, int k) {
        vector<vector<int>> ismov(m, vector<int>(n,0));
        ismov[0][0]=1;
        int sum=1;
        move(m,n,k,0,0,ismov, sum);
        return sum;
    }
    //回溯过程
    void move(int m, int n, int k, int r, int c,vector<vector<int>> &ismov, int &sum)
    { 
        for(vector<int> s:step)
        {
            if((r+s[0])<m&&(r+s[0])>=0&&(c+s[1])<n&&(c+s[1])>=0&&ismov[r+s[0]][c+s[1]]==0&&isOvertaking(r+s[0], c+s[1], k))
            {
                sum++;
                ismov[r+s[0]][c+s[1]]=1;
                move(m,n,k,r+s[0], c+s[1],ismov, sum);
            }
        }
        return;
    }
    //计算此坐标是否符合要求
    bool isOvertaking(int r, int c, int k)
    {
        int rsum=0, csum=0;
        int rem=0;
        //数字按位拆开
        while(r!=0)
        {
            rem=r%10;
            rsum = rsum+rem;
            r=(r-rem)/10;
        }
        rem=0;
        while(c!=0)
        {
            rem=c%10;
            csum = csum+rem;
            c=(c-rem)/10;
        }
        if((rsum+csum)<=k)
            return true;
        else
            return false;
    }
};

 

二.剑指Offer 14-I和14-II.剪绳子

(注:I中没有取模要求,数字较小,没有越界情况)

解法:

根据数学推导,将一个整数线段拆分为有最多可能3构成的子线段,其乘积之和最大。(对3取余,=0,=2均可,=1,即剩下4,拆成2*2)

代码:

//my solutin
//0ms:100,O(n);6mb:100,O(1)
class Solution {
public:
    int cuttingRope(int n) {
        long int sum=1;
        if(n<4)
            return n-1;
        while(n>4)
        {
            sum*=3;
            sum = sum<1000000007?sum:sum%1000000007;
            n=n-3;
        }
        return (sum*n)%1000000007;
    }
};

不用取模情况下代码:

class Solution {
public:
    int cuttingRope(int n) {
        return n <= 3? n - 1 : pow(3, n / 3) * 4 / (4 - n % 3);
    }
};

三.剑指Offer15. 二进制中1的个数

解法:

如何将10进制转换2进制,即长除法:

代码:

//My solution
//oms:100; 5.8mb:100;
class Solution {
public:
    int hammingWeight(uint32_t n) {
        int sum=0;
        while(n!=0)
        {
            if(n%2==1)
                sum++;
            n=n/2;
        }
        return sum;
    }
};

四.剑指Offer16. 数值的整数次方

解法:

1.二分法

根据幂计算的性质,x^n等于x^(n/2)^2(n为偶数时),x*x^(n/2)^2(n为奇数时)

因此,可以每次二分的方法进行简化计算,省去重复计算的情况。

注:需要考虑几种特殊情况,

        1.幂为负数时,为节约空间,先计算正数下的值,最后取反;

        2.n=0的情况,为1;

        3.幂为负数,其最大值转换成正数为数值溢出,采用长整型long int替换int;(int类型,正数范围2^32-1;负数范围2^32)

代码:

//Mysolution 二分法
//0ms:100; 5.8mb:100
class Solution {
public:
    double myPow(double x, int n) {
        long int nn=n;
        if(nn==1)
            return x;
        if(nn==-1)
            return 1/x;
        int f=0;
        if(n==0)
            return 1;
        if(n<0)
            nn=-nn;
        double p=0;
        p=myPow(x, n/2);
        if(n%2==0)
            p=p*p;
        else
            p=p*p*x;
        if(f==0)
            return p;
        return 1/p;
    }
};

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值