数学计算
1. 二进制中1的个数
题目描述
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。
题目分析
当一个数减去1 那个这个数最右边的1之后的0将会变成1,最右边的1左边不变,然后这个数和这个数-1进行与运算,那么这个数最右边的1将会0 循环此过程 直到这个数全部变为0;
ex: 10的二进制是 1010 10-1的二进制是1001 相与结果为1000 10这个数最右边的1变为o 以此类推最终10会变为0
C++代码
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while(n!=0)
{
count++;
n = n & (n-1);
}
return count;
}
};
2. 数值的整数次方
题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
题目分析
暴力法
很显然就是n个b相乘。循环n次。
C++代码
class Solution {
public:
double Power(double base, int exponent) {
if(exponent < 0)
{
base = 1 / base;
exponent = -exponent;
}
double ret = 1.0;
for(int i =0; i< exponent; i++)
{
ret *= base;
}
return ret;
}
};
3. 求1-n的和
题目描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
题目分析
-
可知求和公式,
这种方法不行,因为需要用到乘法 -
逻辑与&&连接符。
A&&B,表示如果A成立则执行B,否则如果A不成立,不用执行B
因此我们可以这样。在n>0的时候,执行递归函数。
C++代码
class Solution {
public:
int Sum_Solution(int n) {
return n*(n+1) / 2;
}
};
class Solution {
public:
int Sum_Solution(int n) {
int sum = n;
sum && (sum += Sum_Solution(n-1));
return sum;
}
};
4. 整数中1出现的次数
题目描述
求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
题目分析
需要通过找规律来分析。
假设我们对5014这个数字求解。
(1)个位上1出现的个数:记高位为high=501,当前位为cur=4。
那么高位从0~500变化的过程中,每一个变化中1只出现1次,即(高位1)这样的数字;
高位是501时,因为当前位是4,所以1只能出现一次,即5011。
所以总共出现的次数为high*1+1=502。
(2)十位1出现的个数:记高位high=50,当前位为cur=1,低位为low=4。
那么高位从0~ 49变化的过程中,每一个变化中1出现10次,即(高位10)~(高位19)这样的数字;
高位为50的时候,因为当前位是1,所以我们要看低位来决定出现的次数,因为低位为4,所以此时出现5次,即5010~5014这样的数字。
所以总共出现的次数为high*10+4=504。
(3)百位1出现的个数:记高位high=5,当前位cur=0,低位为low=14。
那么高位从0~ 4的过程中,每一个变化1出现100次,即(高位100)~(高位199)这样的数字;
高位为5的时候,因为当前位为0,所以不存在出现1的可能性。
所以总共出现的次数为high*100+0=500。
(4)千位1出现的次数:记高位high=0,当前位cur=5,低位low=014。
那么因为没有高位所以直接看当前位,因为当前位为5,所以1出现的次数为1000,即1000~1999这样的数字。
所以总共出现的次数为high*1000+1000=1000。
综上,最终的结果将每个位置出现1的次数累加即可。
结论
我们假设高位为high,当前位为cur,低位为low,i代表着需要统计的位置数(1对应个位,10对应十位,100对应百位),则对每一位的个数count有:
cur=0,count = highi;
cur=1,count=highi+low+1;
cur>1,count=high*i+i
最终累加所有位置上的个数即最终答案。
作者:lu-yang-shan-yu
链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/c-cong-ge-wei-bian-li-dao-zui-gao-wei-yi-ci-qiu-ji/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
C++代码
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
long i = 1;
int count = 0;
while((n/i)!= 0)
{
long cur = (n/i)%10;
long high = n/(10*i);
long low = n - (n/i)*i;
if(cur == 0)
{
count += high * i;
}else if(cur == 1)
{
count += high * i + low + 1;
}else{
count += high * i + i;
}
i *= 10;
}
return count;
}
};
5. Fibonacci数列
题目描述
因此,Fibonacci数列就形如:0, 1, 1, 2, 3, 5, 8, 13, …,在Fibonacci数列中的数我们称为Fibonacci数。给你一个N,你想让其变为一个Fibonacci数,每一步你可以把当前数字X变为X-1或者X+1,现在给你一个数N求最少需要多少步可以变为Fibonacci数。
题目分析
本题可以通过先找到距离N最近的两个Fibonacci数,这两个数分别取自距离N的最近的左边一个数L和右边一
个数R,然后通过min(N - L, R - N)找到最小步数。
C++代码
#include<iostream>
using namespace std;
int main()
{
int N ,f, l,r,f0 = 0, f1 = 1;
cin >> N;
while(1)
{
f = f0 + f1;
f0 = f1;
f1 = f;
if(f < N)
{
l = N - f;
}
else{
r = f - N;
break;
}
}
cout << min(l,r) << endl;
return 0;
}