牛客选靓号即拼多多20200410笔试第三题

链接:https://www.nowcoder.com/questionTerminal/005af31a10834b3688911463065ab47d?orderByHotValue=0&mutiTagIds=579&page=2&onlyReference=false
来源:牛客网

A 国的手机号码由且仅由 N 位十进制数字(0-9)组成。一个手机号码中有至少 K 位数字相同则被定义为靓号。A 国的手机号可以有前导零,比如 000123456 是一个合法的手机号。
小多想花钱将自己的手机号码修改为一个靓号。修改号码中的一个数字需要花费的金额为新数字与旧数字之间的差值。比如将 1 修改为 6 或 6 修改为 1 都需要花 5 块钱。
给出小多现在的手机号码,问将其修改成一个靓号,最少需要多少钱?

//思路:记录0-9数字分别在字符串中出现的个数,遍历分别换成K个i(0-9)所需要的cost,记录
//最小cost的i取值和cost,再考虑如何把字符串换成K个i获得的字典序列最小,详见代码注释
import java.util.*;
import java.io.*;

public class Main{

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        //pdd 3找最修改数字最多为K个的最小花费问题
        String[] arr = in.readLine().split(" ");
        int N = Integer.valueOf(arr[0]);
        int K = Integer.valueOf(arr[1]);
        char[] cs = in.readLine().toCharArray();
        int[] ns = new int[cs.length];
        int[] count = new int[10];
        for(int i=0;i<cs.length;i++){
            ns[i] = Integer.parseInt(String.valueOf(cs[i]));
            count[ns[i]]++;
        }
        int store = 0;

        int ansCost = Integer.MAX_VALUE;//最小花费
        int mid = -1;//选定的数字中心
        for(int i=0;i<10;i++){
            store = K - count[i];
            int lstep = 1;
            int rstep = 1;
            int tmpCost = 0;
            while (store > 0){//往左右两边搜索需要改变的数字
                if(store != 0 && i+rstep<10){//先换右边字典序列更靠前
                    int minus = Math.min(store,count[i+rstep]);
                    store -= minus;
                    tmpCost += minus * rstep;
                    rstep++;
                }
                if(store != 0 && i-lstep>=0){
                    int minus = Math.min(store,count[i-lstep]);
                    store -= minus;
                    tmpCost += minus * lstep;
                    lstep++;
                }
            }
            if(tmpCost < ansCost) {
                ansCost = tmpCost;
                mid = i;
            }
        }
        //换取需要变动的字符串,为了换取后是最小的字典序列,先从左向右换取比中心值大的字符串,注意这里要先换完所有mid最近的数
        //比如mid是 3 我要先把所有的4先换掉,因为要保证cost最小!!!再换所有的2,直到换的数目得到满足
        store = K - count[mid];
        int step = 1;
        while(store > 0){
            if(mid + step < 10){
                for(int i=0;i<ns.length;i++){
                    if(ns[i] == mid+step){
                        ns[i] = mid;
                        store--;
                        if(store <= 0)break;
                    }
                }
            }
            if(store <= 0)break;
            if(mid - step >= 0){//这里要从右向左换!!!
                for(int i=ns.length-1;i>=0;i--){
                    if(ns[i] == mid-step){
                        ns[i] = mid;
                        store--;
                        if(store <= 0)break;
                    }
                }
            }
            step++;
        }
        System.out.println(ansCost);
        for(int i=0;i<ns.length;i++){
            System.out.print(ns[i]);
        }

    }
}
//393333393333883383337333333933778733383333373
//393333393333883383337333333933778733383333373
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值