0014数位成本和为目标值的最大数字

数位成本和为目标值的最大数字

编号:0014

试题来源:leetcode

文章目录

  • 题目描述
  • 解答算法
    • 算法思路
    • 代码实现
    • 复杂度分析

题目描述

给定整数数组cost和一个整数target。返回满足如下规则的可以得到的最大整数

  • 给当前结果添加一个数位i+1的成本为cost[i](cost数组的下标从0开始)
  • 总成本必须恰好等于target
  • 添加的位数中没有数字0

返回类型string

如果无法得到任何整数,那么返回0

解答算法

算法思路

很显然这是一个0-1完全背包问题

我用的是暴力做法,时间复杂度太高,失败了

参考代码

target是目标的花费,显然,cost数组中的每一个值都是正数,因为一旦存在0,那么可以无穷添加,就没有最大值了。所以 c o s t [ i ] ≥ 1 cost[i]\geq 1 cost[i]1。因此可以设置一个temp数组,其中元素是string类型,temp[i]存储当总花费为i的时候产生的最大string

显然有如下递推公式

temp[target] = max{temp[target - cost[i]]+cost[i],cost[i] + temp[target - cost[i]]},如果 t a r g e t − c o s t [ i ] = = 0 target - cost[i] == 0 targetcost[i]==0说明这是第一个添加的元素。如果 t a r g e t − c o s t [ i ] < 0 target - cost[i] < 0 targetcost[i]<0说明,该target没有满足条件的string;如果temp[target - cost[i]]对应的string为空,说明它不存在,那么自然不能在一个不存在的字符串上加数位因此也不存在。

通过递推公式,一个个遍历temp[i],最后就能够解决问题

代码实现

class Solution {
public:
    string largestNumber(vector<int>& cost, int target) {
        int len = cost.size();
        unordered_map<int, int> cost2num;  //key存放的是花费,对应得是下标
        for(int i = 0; i < len; i++) {   //更新花费map
            if(cost2num.find(cost[i]) == cost2num.end() || cost2num[cost[i]] < i + 1) {
                cost2num[cost[i]] = i + 1;
            }
        }   
        vector<string> temp(target + 1, "");  //vector数组得长度为target+1,初始值均为空字符串
        for(int i = 1; i <= target; i++) {  //从1开始,逐渐提升target的值
            for(const auto& [cost, num]: cost2num) {
                int index = i - cost;       //如果添加了当前数位,是在temp[i-cost]的基础上添加的
                if(index == 0 || index > 0 && temp[index] != "") { //如果index == 0说明当前添加的i是第一个数位;如果index>0,那么需要temp[i-cost]有合适的取值,才能添加新的数位
                    string second = to_string(num);
                    string new_str = temp[index] > second? temp[index] + second: second + temp[index];  //产生添加数位之后的string
                    if(new_str.size() > temp[i].size() || new_str.size() == temp[i].size() && new_str > temp[i]) {  //和当前temp[i]进行对比,谁大选谁
                        temp[i] = new_str;
                    }
                }
            }
        }
        return temp[target] == ""? "0": temp[target];  //非空返回string,否则返回0
    }
};

复杂度分析

  • 时间复杂度:整个过程中遍历了 O ( t a r g e t ) O(target) O(target)的时间,同时每一次都进行了比较操作以及对9个可以添加的数位的比较,最终的时间复杂度为 O ( n ) O(n) O(n)
  • 空间复杂度:申请了 O ( t a r g e t ) O(target) O(target)的额外空间,时间复杂度为 O ( n ) O(n) O(n)

你可能感兴趣的:(每天一道算法题,算法)