小米今年招了4000名应届生,用10年的时间让其佼佼者成为技术专家或总经理。...

4bd92acd295afc7b6ce898c0eeca524d.gif

精品推荐

《征服数据结构》专栏:50多种数据结构彻底征服

《经典图论算法》专栏:50多种经典图论算法全部掌握

本周三小米举办2024届小米应届生迎新典礼,小米CEO雷军出席典礼并发表演讲。据雷军介绍,2024年小米一共招募了4000名应届生,明年至少还会招募4000-5000名。

小米“应届生计划”的目标就是10年时间让其中的佼佼者成为技术专家,或者成为总经理。

cd69f47dabbef17f5039ddfe7afbe5ee.png

--------------下面是今天的算法题--------------

来看下今天的算法题,这题是LeetCode的第556题:下一个更大元素 III。

问题描述

来源:LeetCode第556题

难度:中等

给你一个正整数 n ,请你找出符合条件的最小整数,其由重新排列 n 中存在的每位数字组成,并且其值大于 n 。如果不存在这样的正整数,则返回 -1 。

注意 ,返回的整数应当是一个 32 位整数 ,如果存在满足题意的答案,但不是 32 位整数 ,同样返回 -1 。

示例1:

输入:n = 12

输出:21

示例2:

输入:n = 21

输出:-1

  • 1 <= n <= 2^31 - 1

问题分析

这题和前面讲的《下一个排列》基本完全一样,都是求下一个更大的值,只不过他们给的参数不一样,前面那道题直接给了一个数组,而这题是给了一个数字。但不影响,我们可以先把数字中的每一位都提取出来,构成一个数组,那么这题就和前面那道题完全一样了。具体实现原理可以参考前面的《下一个排列》,这里就不在重复介绍。

JAVA:

public int nextGreaterElement(int n) {
    String str = String.valueOf(n);
    int[] nums = new int[str.length()];
    // 把数字 n 的每一位转成数组
    for (int i = 0; i < str.length(); i++)
        nums[i] = str.charAt(i) - '0';
    // 如果不存在下一个,返回 -1 。
    if (!nextPermutation(nums))
        return -1;
    // 把数组转化为数字
    long ans = 0;
    for (int num : nums) {
        ans = ans * 10 + num;
        if (ans > Integer.MAX_VALUE)
            return -1;
    }
    return (int) ans;
}

public boolean nextPermutation(int[] nums) {
    int left = nums.length - 2;
    // 两两比较,从后面往前找第一个降序的
    while (left >= 0 && nums[left] >= nums[left + 1])
        left--;
    // 如果都是逆序的,也就是没有下一个更大的元素。
    if (left < 0)
        return false;
    int right = nums.length - 1;
    // 从后面查找第一个比nums[left]大的值
    while (nums[right] <= nums[left])
        right--;
    swap(nums, left, right);
    // 反转后面升序的数字
    reverse(nums, left + 1, nums.length - 1);
    return true;
}

// 反转子数组[left,right]中的元素
private void reverse(int[] nums, int left, int right) {
    while (left < right)
        swap(nums, left++, right--);
}

// 交换数组中的两个数字
private void swap(int[] nums, int left, int right) {
    int tmp = nums[left];
    nums[left] = nums[right];
    nums[right] = tmp;
}

C++:

public:
    int nextGreaterElement(int n) {
        vector<int> nums;
        while (n != 0) {
            nums.push_back(n % 10);
            n /= 10;
        }
        reverse(nums.begin(), nums.end());
        // 如果不存在下一个,返回 -1 。
        if (!nextPermutation(nums))
            return -1;
        // 把数组转化为数字
        long ans = 0;
        for (int num: nums) {
            ans = ans * 10 + num;
            if (ans > INT_MAX)
                return -1;
        }
        return (int) ans;
    }

    bool nextPermutation(vector<int> &nums) {
        int left = nums.size() - 2;
        // 两两比较,从后面往前找第一个降序的
        while (left >= 0 && nums[left] >= nums[left + 1])
            left--;
        // 如果都是逆序的,也就是没有下一个更大的元素。
        if (left < 0)
            return false;
        int right = nums.size() - 1;
        // 从后面查找第一个比nums[left]大的值
        while (nums[right] <= nums[left])
            right--;
        swap(nums[left], nums[right]);
        // 反转后面升序的数字
        reverse(nums.begin() + left + 1, nums.end());
        return true;
    }

Python:

def nextGreaterElement(self, n: int) -> int:
    nums = []
    while n != 0:
        nums.append(n % 10)
        n //= 10
    nums.reverse()  # 反转列表,使其从高位到低位
    # 如果不存在下一个更大的排列,返回 -1
    if not self.next_permutation(nums):
        return -1
        # 把列表转化为数字,同时检查是否超出int的范围
    ans = 0
    INT_MAX = 2 ** 31 - 1  # 模拟C++的INT_MAX
    for num in nums:
        ans = ans * 10 + num
        if ans > INT_MAX:
            return -1
    return ans

def next_permutation(self, nums: list[int]) -> bool:
    left = len(nums) - 2
    # 从后往前找第一个降序的位置
    while left >= 0 and nums[left] >= nums[left + 1]:
        left -= 1
        # 如果整个列表都是降序的,则没有下一个更大的排列
    if left < 0:
        return False
    right = len(nums) - 1
    # 从后往前找第一个比nums[left]大的数
    while nums[right] <= nums[left]:
        right -= 1
        # 交换nums[left]和nums[right]
    nums[left], nums[right] = nums[right], nums[left]
    # 反转left+1及其之后的部分
    nums[left + 1:] = reversed(nums[left + 1:])
    return True

aa2c8713a6ca87e8a9e891318cd56ea8.gif

笔者简介

博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解800多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以下载我整理的1000多页的PDF算法文档。

《征服数据结构》专栏

数组稀疏表(Sparse Table)单向链表双向链表块状链表跳表队列和循环队列双端队列单调队列单调栈双端栈散列表字典树(Trie树)ArrayMapSparseArray二叉树二叉搜索树(BST)笛卡尔树AVL树树堆(Treap)FHQ-Treap

……

《经典图论算法》专栏

图的介绍图的表示方式邻接矩阵转换广度优先搜索(BFS)深度优先搜索(DFS)A*搜索算法迭代深化深度优先搜索(IDDFS)IDA*算法双向广度优先搜索迪杰斯特拉算法(Dijkstra)贝尔曼-福特算法(Bellman-Ford)SPFA算法弗洛伊德算法(Floyd)

……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

数据结构和算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值