Pow(x, y)
实现 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
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。
思路1:直接乘n次
第一步想到的就是,既然是幂,直接进行循环承即可
class Solution {
public double myPow(double x, int n) {
double result = 1;
if(n == 0) return result;
if(n > 0){
while(n > 0){
result = result * x;
n--;
}
return result;
}else{
n = -n;
while(n > 0){
result = result * x;
n--;
}
return 1.0/result;
}
}
}
无奈,超出了时间限制
上述代码可以简化下:
class Solution {
public double myPow(double x, int n) {
double result = 1.0;
if(n == 0) return result;
boolean isZhengShu = n > 0 ? true : false;
n = isZhengShu ? n : -n;
while(n > 0){
result = result * x;
n--;
}
return isZhengShu ? result : 1.0/result;
}
}
思路2:快速幂
快速幂,其实是利用分治的思想
可以将时间复杂度降为O(logn)
快速幂,可以使用递归,也可以使用迭代
使用递归的空间复杂度为O(logn)
使用迭代的空间复杂度为O(1)
递归
class Solution {
public double myPow(double x, int n) {
if(n == 0) return 1;
if(n == -1) return 1/x;
//判断是否为奇数
boolean odd = n % 2 == 0 ? false : true;
double half = myPow(x, n >> 1);
half *= half;
return odd ? (half * x) : half;
}
}
时间复杂度分析:
T(n) = T(n / 2) + O(1)
T(n) = O(logn);
注意
这道题涉及的知识点挺多,比较能看出一个人的水平
迭代
class Solution {
public double myPow(double x, int n) {
//是否为负数
boolean neg = n < 0;
long y = neg ? -((long)n) : n;
double result = 1.0;
while(y > 0){
if((y & 1) == 1){
//如果最后一个二进制位是1,就累乘上x
result *= x;
}
x *= x;
//舍弃掉最后一个二进制位
y >>= 1;
}
return neg ? 1/result : result;
}
}
看到一个哥们这么写:
真是一个小机灵鬼
试了下,好像被LeetCode禁止调用这个函数了
圆圈中最后剩下的数字
0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
示例 1:
输入: n = 5, m = 3
输出: 3
示例 2:
输入: n = 10, m = 17
输出: 2
限制:
1 <= n <= 10^5
1 <= m <= 10^6
思路:公式
其实就是约瑟夫环问题,看谁活到最后
计算公式:
f(n, m) = (f(n - 1, m) + m) % n
递归
class Solution {
public int lastRemaining(int n, int m) {
if(n == 1) return 0;
return (lastRemaining(n - 1, m) + m) % n;
}
}
非递归
f(5, 3) = (f(4, 3) + 3) % 5;
f(4, 3) = (f(3, 3) + 3) % 4;
f(3, 3) = (f(2, 3) + 3) % 3;
f(2, 3) = (f(1, 3) + 3) % 2;
f(1, 3) = 0;
由上面公式推导出:
class Solution {
public int lastRemaining(int n, int m) {
int result = 0;
for(int i = 2; i <= n; i++){
result = (result + m) % i;
}
return result;
}
}
其实也是根据公式得出来的,只是,不是直接递归调用公式