1.实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/powx-n
思路一:快速幂+递归:基于分治的思想,例如求x的8次幂,只需求4次幂和2次幂即可。
class Solution {
public:
double quickMul(double x, long long N) {
if (N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;//如果除以2没有余数,直接y*y,如果有余数,额外再乘一个x
}
double myPow(double x, int n) {
long long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
};思路二:快速幂+迭代
class Solution {
public:
double quickMul(double x, long long N) {
double ans = 1.0;
// 贡献的初始值为 x
double x_contribute = x;
// 在对 N 进行二进制拆分的同时计算答案
while (N > 0) {
if (N % 2 == 1) {
// 如果 N 二进制表示的最低位为 1,那么需要计入贡献
ans *= x_contribute;
}
// 将贡献不断地平方
x_contribute *= x_contribute;
// 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可
N /= 2;
}
return ans;
}
double myPow(double x, int n) {
long long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
};2.连续子数组的最大和
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
思路:设置一个res,一个cur,一个存储当前最大结果,一个存储总的计算结果,从头开始遍历,如果cur小于等于0,就再次从头开始计算,否则,加入一个数,每次循环都让cur与res作比较,res取其中最大值。
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
int len=array.size();
if(len<=0) return 0;
int cur=0;
int res=0x80000000;//最小负数
for(int i=0;i<len;i++)
{
if(cur<=0)
cur=array[i];//小于等于0,舍去记录的序列
else
{
cur+=array[i];//否则序列加一个数
}
res=max(res,cur);//比较
}
return res;
}
};3.整数中1出现的次数
求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
if(n<=0)
return 0;
char strN[50];
sprintf(strN,"%d",n);//转换成字符串
return NumberOf1(strN);
}
int NumberOf1(const char* strN)
{
if(!strN||*strN<'0'||*strN>'9'||*strN=='\0')
return 0;//结束条件
int first=*strN-'0';//最高位
unsigned int length=static_cast<unsigned int>(strlen(strN));
if(length==1&&first==0)
return 0;
if(length==1&&first>0)
return 1;//0-9
int numFirstDigit=0;//最高位
if(first>1)
numFirstDigit=pow(10,length-1);
else if(first==1)
numFirstDigit=atoi(strN+1)+1;//10000-12345
int numOtherDigits=first*(length-1)*pow(10,length-2);//剩余位数排列组合
int numRecursive=NumberOf1(strN+1);//递归
return numFirstDigit+numOtherDigits+numRecursive;
}
};4.把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
思路:定义一个新的排序规则,然后将数字转化为字符串。
class Solution {
public:
string PrintMinNumber(vector<int> numbers) {
int len=numbers.size();
if(len<=0) return "";
string s="";
sort(numbers.begin(),numbers.end(),cmp);//基于新的排序规则,给数组排序
for(int i=0;i<len;i++)
{
s+=to_string(numbers[i]);//数字转字符串
}
return s;
}
static bool cmp(int a,int b)
{
string s1=to_string(a)+to_string(b);
string s2=to_string(b)+to_string(a);
return s1<s2;//a+b若小于b+a,就不换
}
};
京公网安备 11010502036488号