当前位置: 首页 > news >正文

将字符串编码成数值,求数值最大和问题

           这几天参加了很多公司的笔试,碰到了一些很有意思的题目,下面是我解决问题的算法,分享给大家,绝对是自己原创

           如果大家要转载,请注明出处,附加原文地址链接,否则将追究其法律责任。请尊重作者的劳动成果!

问题描述:输入n个字符串,每个字符串只出现A-J之间的字符,可以出现重复的字符,要求将A-J对应的字符编码为0-9的数字,给出编码方案,使得所有编码后的字符串加起来和最大。

例如:输入两个字符串“ABC”和“BCA”,将B编码为9,A编码为8,C编码为7,D编码为6,E编码为5,F编码为4,G编码为3,H编码为2,I编码为1,J编码为0。

         则两个字符串对应的数值分别为:897和978,使得和最大为1875.

 分析:第一次看到这道题,首先想到的是搜索的方法,然后贪心地去处理,这种方法确实可以实现,但是时间复杂度太高了,呈指数级增长,经过考虑后,想出了一个新的办法,可以降低时间复杂度。

           先说下整体的思路,再编写实际的代码,可以结合代码看,代码写法比较通用,读者可以很容易的转换为其他语言。

          1. 先求出所有的字符串中最长的长度,假设为maxLength,然后在长度不够最长长度的字符串前面补上A-J之外的任意字符(代码中我补的是‘@’),使得所有的字符串长度都相等,等于最长的长度。

          2.然后开辟一个10*maxLength的二维数组,并全部初始化为0,行代表的是每个字符,列代表的是每个位置,然后依次扫描每个字符串的每一位,统计出各个字符出现的频率。如下图所示,

             其中最上面一行代表的是权值,最左边的一列代表的是每个字符。格子里的数字表示每个字符在每一位出现的频率,为了简单起见,空代表0.

                                    

           3. 统计完之后,把每个字符对应的位置的频率乘以对应的权值,计算出每个字符的基数和。存到另外一个数组b[]中,

           4.然后将b[]进行排序,把最大的元素对应的字符编码为9,第二大的元素对应的字符编码为8,依次类推,对于没有出现过的字符可以任意编码,编码完成。

           5. 把对应的元素乘以编码后的数字,再把所有的结果进行累加,即可得出最大的和。

           具体的Java代码如下:

 1 import java.util.*;
 2 public class Main {
 3     public static void main(String[] args) {
 4         // TODO 自动生成的方法存根
 5         Scanner scan=new Scanner(System.in);
 6         int n=Integer.parseInt(scan.nextLine());        //读入n
 7         String str[]=new String[n];
 8         int maxLength=0;
 9         for(int i=0;i<n;i++)                            //读入每个字符串,并统计出最长的字符串的长度
10             {
11                str[i]=scan.nextLine();
12                if(str[i].length()>maxLength)maxLength=str[i].length();
13             }
14         int a[][]=new int[10][maxLength];              //开出一个10*最大长度的二维数组
15         for(int i=0;i<n;i++)
16             {
17                if(str[i].length()<maxLength)
18                {   int length=str[i].length();
19                 for(int j=0;j<maxLength-length;j++)   //把长度不够最大长度的字符串的前面补上无关的任意字符,这里我补的是@字符
20                     str[i]="@"+str[i];
21                }
22                for(int j=0;j<maxLength;j++)          //统计每个字符串每个位上出现字符的频率,放到频率数组a[][]中
23                    if(str[i].charAt(j)!='@')         //如果是我之前补得无关字符,则忽略
24                    a[str[i].charAt(j)-'A'][j]++;
25             }
26         int b[]=new int[10];                         //开辟一个用来存储每个字符的单位和
27         char ch[]={'A','B','C','D','E','F','G','H','I','J'};  //用来和b[]绑定,用来记忆每个字符的位置,因为后面要对b[]排序
28         for(int i=0;i<=9;i++)                        //统计出每个字符出现的基数综合
29             for(int j=0;j<maxLength;j++)
30                 b[i]=b[i]*10+a[i][j];
31     
32         
33         for(int i=0;i<9;i++)                        //把每个字符的基数值总和进行排序
34             for(int j=i+1;j<10;j++)
35                 if(b[i]>b[j]){
36                     int t=b[i];
37                     b[i]=b[j];
38                     b[j]=t;
39                     char c=ch[i];
40                     ch[i]=ch[j];
41                     ch[j]=c;
42                 }
43         
44         int sum=0;                                //用来计算最终的总和
45         for(int i=0;i<=9;i++)
46             {
47               System.out.print(i+"对应"+ch[i]+", ");    //输出每个数字对应的字符
48               sum=sum+b[i]*i;
49             }
50         System.out.println();
51         System.out.println("总和为:"+sum);           
52     }
53 
54 }

输出结果为:

2
ABC
BCA
0对应D, 1对应E, 2对应F, 3对应G, 4对应H, 5对应I, 6对应J, 7对应C, 8对应A, 9对应B,
总和为:1875

转载于:https://www.cnblogs.com/guozhenqiang/p/5441137.html

相关文章:

  • crontab 安装 和一些 简单的命令
  • eclipse 编译的时候 自动把SDK需要放入libs里面的so文件给删除了
  • 事件处理
  • 实测可用的宽度优先爬虫的实现
  • c语言描述简单的线性表,获取元素,删除元素,
  • 用两个栈实现一个队列
  • 将C#文档注释生成.chm帮助文档
  • 【VS开发】CListCtrl控件使用方法总结
  • python之路之正则表达式
  • 水平方向瀑布流
  • log4j配置概要
  • [Assignment] C++1
  • linux之GDB常用命令汇总
  • uva1368DNA consensus string统计
  • static关键字的使用总结
  • Google 是如何开发 Web 框架的
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • javascript面向对象之创建对象
  • Java应用性能调优
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • mockjs让前端开发独立于后端
  • MySQL用户中的%到底包不包括localhost?
  • PAT A1050
  • Vue 动态创建 component
  • Zepto.js源码学习之二
  • 关于for循环的简单归纳
  • 开源地图数据可视化库——mapnik
  • NLPIR智能语义技术让大数据挖掘更简单
  • 阿里云服务器购买完整流程
  • 数据库巡检项
  • 选择阿里云数据库HBase版十大理由
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​插件化DPI在商用WIFI中的价值
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #1015 : KMP算法
  • #define 用法
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (三)elasticsearch 源码之启动流程分析
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (正则)提取页面里的img标签
  • (转)负载均衡,回话保持,cookie
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • **PHP分步表单提交思路(分页表单提交)
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • @Import注解详解
  • @Pointcut 使用
  • []Telit UC864E 拨号上网
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [AIGC] 如何建立和优化你的工作流?
  • [BZOJ 1040] 骑士