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,就不换 } };