一.剑指 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;
}
};