剑指 Offer 16. 数值的整数次方
中等
433
相关企业
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3
输出:9.26100
示例 3:
输入:x = 2.00000, n = -2
输出:0.25000
解释:2-2 = 1/22 = 1/4 = 0.25
提示:
−
100.0
<
x
<
100.0
-100.0 < x < 100.0
−100.0<x<100.0
−
2
31
<
=
n
<
=
2
31
−
1
-2^{31} <= n <= 2^{31}-1
−231<=n<=231−1
n 是一个整数
要么 x 不为零,要么 n > 0 。
−
1
0
4
<
=
x
n
<
=
1
0
4
-10^4 <= x^n <= 10^4
−104<=xn<=104
主要利用了一个递归,以log(n)的深度,降低了时间复杂度,避免了一些重复计算。这种方法叫做快速幂算法。
class Solution {
public:
double myPow(double x, int n) {
if (x == 0) return 0;
if (x == 1 || n == 0) {
return 1;
}
if (n == 1) {
return x;
}
if (n > 0) {
double res = myPow(x, n / 2);
if (n % 2 == 1) {
return res * res * x;
}
else {
return res * res;
}
}
else {
long long exp = n;
exp = -exp;
double res = myPow(x, exp / 2);
if (exp % 2 == 1) {
return 1 / (res * res * x);
}
else {
return 1 / (res * res);
}
}
}
};
自己的代码写的有些长,看一下题解的做法,十分简洁:
class Solution {
double quickMul(double x, long long N) {
if (x == 1 || N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
return N % 2 == 1 ? (y * y * x) : (y * y);
}
public:
double myPow(double x, int n) {
long long N = n;
return N > 0 ? quickMul(x, N) : 1 / quickMul(x, -N);
}
};
剑指 Offer 17. 打印从1到最大的n位数
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
说明:
用返回一个整数列表来代替打印
n 为正整数
这道题范围限制在了int范围内,所以直接打印就可以。
class Solution {
public:
vector<int> printNumbers(int n) {
int num = 9;
for(int i=1;i<n;i++){
num = num * 10 + 9;
}
vector<int> res(num);
for(int i=1;i<=num;i++){
res[i-1] = i;
}
return res;
}
};
但剑指offer上是考虑了超过64位的大数的,即不可以用long long类型来表示的数字,需要用字符串来表示。
一种做法是进行模拟,从低位到高位进行模拟。
另外一种简单的方法是,利用递归的方法,求字符串的全排列。
剑指 Offer 18. 删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
说明:
题目保证链表中节点的值互不相同
若使用 C 或 C++ 语言,你不需要 free 或 delete 被删除的节点
代码实现主要利用了一个双指针来进行,如下:
// 自己的代码,中间过程看起来有些绕,因为考虑了特殊情况
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* curNode = head;
ListNode* preNode = nullptr;
while (curNode != nullptr) {
if (curNode->val == val) {
if (preNode == nullptr) {
preNode = curNode->next;
head = preNode;
}
else {
preNode->next = curNode->next;
}
break;
}
preNode = curNode;
curNode = curNode->next;
}
return head;
}
};
题解的做法,较为简洁:
// 题解的代码,较为简洁,提前判断特殊情况,在主体中就不需要考虑特殊情况了
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if (head->val == val) return head->next;
ListNode* pre = head, * cur = head->next;
while (cur != nullptr && cur->val != val) {
pre = cur;
cur = cur->next;
}
if (cur != nullptr) pre->next = cur->next;
return head;
}
};
7. 整数反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [ − 2 31 , 2 31 − 1 ] [−2^{31}, 2^{31} − 1] [−231,231−1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
提示:
− 2 31 < = x < = 2 31 − 1 -2^{31} <= x <= 2^{31} - 1 −231<=x<=231−1
值得注意的是,如果反转后整数超过 32 位的有符号整数的范围
[
−
2
31
,
2
31
−
1
]
[−2^{31}, 2^{31} − 1]
[−231,231−1] ,就返回 0,因此,我们要添加一个if判断,由于下面紧接着就要进行一个 × 10 的操作,因此,我们需要和 INT_MIN / 10
或 INT_MAX / 10
进行比较。
#include <iostream>
#include <limits.h>
using namespace std;
class Solution
{
public:
int reverse(int x)
{
long long res = 0;
while (x != 0)
{
if (res < INT_MIN / 10 || res > INT_MAX / 10)
return 0;
res = res * 10 + x % 10;
x = x / 10;
}
return res;
}
};
int main()
{
Solution sol;
int res = sol.reverse(123);
cout << res;
return 0;
}