面试题45. 把数组排成最小的数 暴力dfs法+排序法

题目描述

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例 1:
输入: [10,2]
输出: “102”
示例 2:
输入: [3,30,34,5,9]
输出: “3033459”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法1

解题思路

初看题目,最直接的想法是,使用排列组合的方法,暴力枚举所有情况,取其最小值。
题目可以视为:将数组中的数,按照字典顺序排序,从排列,其对应数值即为,最小值。
关键在于如何定义偏序关系。本题规律在于定义为字典顺序
比如:
x < = y 等 价 于 ( x + y ) − ( y + x ) < = 0 x<=y等价于(x+y)-(y+x)<=0 x<=y(x+y)(y+x)<=0 x > y 等 价 于 ( x + y ) − ( y + x ) > 0 x>y等价于(x+y)-(y+x)>0 x>y(x+y)(y+x)>0

代码

class Solution {
    public String minNumber(int[] nums) {

        String[] strings = new String[nums.length];
        for(int i=0; i<nums.length; i++){
            strings[i] = String.valueOf(nums[i]);
        }
        quitSort(strings, 0, strings.length-1);
        StringBuilder res = new StringBuilder();
        for(String s: strings){
            res.append(s);
        }
        return res.toString();

    }

    public static void quitSort(String[] strings, int low, int high){
        if(low>=high)
            return;
        int pivot_index = partion(strings, low, high);
        quitSort(strings, low, pivot_index-1);
        quitSort(strings, pivot_index+1, high);
    }

    public static int partion(String[] strings, int low, int high){

        var pivot = strings[low];
        int i=low, j=high;
        while(i<j){
            while(i<j&&((pivot+strings[j]).compareTo(strings[j]+pivot)<=0))
                j--;
            strings[i] = strings[j];
            while(i<j&&((strings[i]+pivot).compareTo(pivot+strings[i])<=0))
                i++;
            strings[j] = strings[i];
        }
        strings[i] = pivot;
        return i;
    }
}

方法2

解题思路

使用dfs方法,搜索全部组合情况,使用全局变量min_value,保存所有组合中最小值。

代码

   // 保持最小值
    private String min_value = "999999999999999999999999999999";

    public static void main(String[] args){

        int[] nums = new int[]{3,30,34,5,9};

        var t = new tmp();

        System.out.println(t.minNumber(nums));

    }

    public String minNumber(int[] nums) {

        int len = nums.length;
        List<String> path = new ArrayList<>();
        boolean[] used = new boolean[len];

        Arrays.sort(nums);
        dfs(nums, len, 0, path, used);
        return min_value;
    }


    public void dfs(int[] n, int len, int depth, List<String> path, boolean[] used){

        // 返回条件
        if(depth>len){
            return;
        }
        if(depth==len){
            StringBuilder s = new StringBuilder();
            for(String p:path){
                s.append(p);
            }
            if(s.toString().compareTo(min_value)<0)
                min_value = s.toString();
        }

        // 深度优先搜索
        for(int i=0; i<n.length; i++){
            if(!used[i]){

                if(i>0&&n[i]==n[i-1]&&used[i-1]==false)
                    continue;
                path.add(String.valueOf(n[i]));
                used[i] = true;

                dfs(n, len, depth+1, path, used);

                used[i] = false;
                path.remove(path.size()-1);
            }
        }
    }

问题

在深度较深时会,超出时间限制。我想在不考虑时间限制条件下,并且min_value字符长度足够长时,问题应该是可解的。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值