3.最大数(medium)

1.题目链接:

179. 最大数 - 力扣(LeetCode)179. 最大数 - 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。 示例 1:输入:nums = [10,2]输出:"210"示例 2:输入:nums = [3,30,34,5,9]输出:"9534330" 提示: * 1 <= nums.length <= 100 * 0 <= nums[i] <= 109https://leetcode.cn/problems/largest-number/description/2.题目描述:

    给定一组非负整数 nums ,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。​注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
示例 1:​
        输入:nums = [10,2] 输出:"210"​
示例 2:​
        输入:nums = [3,30,34,5,9] 输出:"9534330"​
 ​
提示:

1 <= nums.length <= 100

0 <= nums[i] <= 10(9)

3. 解法(贪心):
可以先优化:
将所有的数字当成字符串处理,那么两个数字之间的拼接操作以及比较操作就会很方便。

贪心策略:
按照题目的要求,重新定义一个新的排序规则,然后排序即可。

排序规则:
a. 「A 拼接 B」 大于 「B 拼接 A」,那么 A 在前,B 在后;

b. 「A 拼接 B」 等于 「B 拼接 A」,那么 A B 的顺序无所谓;​

c. 「A 拼接 B」 小于 「B 拼接 A」,那么 B 在前,A 在后;​

Java算法代码:

class Solution {
    public String largestNumber(int[] nums) {
        //优化:把所有的数转化成字符串
        int n = nums.length;
        String[] strs = new String[n];
        for(int i = 0; i < n; i++) strs[i] = "" + nums[i];

        //排序 --- 字符串排序
        Arrays.sort(strs,(a,b) ->
        {
            return (b+a).compareTo(a + b);
        });

        //提取结果
        StringBuffer ret = new StringBuffer();
        for( String s : strs) ret.append(s);

        if(ret.charAt(0) == '0') return "0";
        return ret.toString();
    }
}

运行结果:

贪心思想:

细节补充:读者,读完前面应该还是没有找到贪心算法,贪在哪里。

先要知道,得了解Arrays.sort,以及lambda表达式。

这里有排序和比较逻辑

这里笔者对代码进行改版:

class Solution {
    public String largestNumber(int[] nums) {
        // 1. 将整数转换为字符串数组
        int n = nums.length;
        String[] strs = new String[n];
        for (int i = 0; i < n; i++) {
            strs[i] = String.valueOf(nums[i]);
        }

        // 2. 手动实现冒泡排序,使用自定义比较规则
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - 1 - i; j++) {
                String a = strs[j];
                String b = strs[j + 1];
                // 比较 (b + a) 和 (a + b)
                if ((b + a).compareTo(a + b) > 0) {
                    // 如果 b 应排在 a 之前,交换
                    String temp = strs[j];
                    strs[j] = strs[j + 1];
                    strs[j + 1] = temp;
                }
            }
        }

        // 3. 拼接结果
        StringBuilder ret = new StringBuilder();
        for (String s : strs) {
            ret.append(s);
        }

        // 4. 处理前导零
        if (ret.charAt(0) == '0' && ret.length() > 1) {
            return "0";
        }
        return ret.toString();
    }
}

这里笔者使用了,冒泡排序,来看看。

注意,这里的排序规则是,和我们正常对一组数来进行大小排序不一样。

这里只有排序规则不一样(AB 和BA的大小关系来进行的)。

所以这里的贪心呢??

贪心算法的核心

a. 什么是贪心算法?
  • 贪心算法(Greedy Algorithm)是一种通过局部最优选择来期望获得全局最优解的算法。
  • 特点:
    • 局部最优:在每一步选择当前看起来最好的方案。
    • 无回溯:不撤销之前的选择,依赖局部决策的累积效应。
    • 适用性:需要在问题中证明局部最优可以导致全局最优。
b. 本题的贪心策略
  • 问题分解:将最大数字构造问题分解为对字符串数组的排序问题。
  • 局部最优选择:在每次比较两个字符串 a 和 b 时,选择使 b + a 字典序更大的排列(即 b 排在 a 之前),因为这可能导致最终拼接结果更大。
  • 全局最优目标:通过这种排序规则,确保拼接后的数字字符串最大。

贪心体现

  • 每次比较时,选择 b + a > a + b 的顺序,相当于在当前局部位置优先选择“拼接后更大的结果”。
  • 这种选择是局部的,不考虑后续的排列,只关注当前两个字符串的拼接效果。

贪心还有个最重要的一步,是要证明贪心策略的正确性(这里笔者暂时跳过)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值