leetcode刷题记录20(2023-09-04)【数值的整数次方(快速幂、正整数幂、负整数幂) | 打印从1到最大的n位数(字符串、递归、全排列) | 除链表的节点 | 整数反转(正负数取余)】

剑指 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<=2311
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,2311] ,就返回 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<=2311

值得注意的是,如果反转后整数超过 32 位的有符号整数的范围 [ − 2 31 , 2 31 − 1 ] [−2^{31}, 2^{31} − 1] [231,2311] ,就返回 0,因此,我们要添加一个if判断,由于下面紧接着就要进行一个 × 10 的操作,因此,我们需要和 INT_MIN / 10INT_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;
}
  • 30
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cherries Man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值