`
tang9140
  • 浏览: 35506 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

平安科技在线编程大赛:一份“奇妙”的银行流水[分享]

 
阅读更多
题目详情

一份银行流水数据,因打印模糊导致部分金额不清楚。

收入、支出、余额满足以下3条规则:

1、收入、支出、余额三列都是数字

2、同一行收入和支出的值不能同时为非零值

3、第N-1行余额(+第N行收入或-第N行支出)=第N行余额

程序语言: java

请按照规则编写算法,修复不清楚的值


输入描述:

输入数据最多25行,每行都包含四个数据,分别是:数据编号,收入、支出、余额,模糊的数据以?表示,

它们之间以;隔开。

以文件结尾。第一组数据为初始数据值,收入、支出、余额数据保留2位小数

输出描述:

以输入的数据顺序输出修复后的数据。


答题说明

输入样例:

流水记录ID;收入;支出;余额

1;0.00;51.90;1945.45

2;0.00;1000.00;?

输出样例:

流水记录ID;收入;支出;余额

1;0.00;51.90;1945.45

2;0.00;1000.00;945.45


试了30次,无法通过。求大神指点。不多说,代码如下

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Scanner;

public class Main {
    
    /**
     * 标志:代表?,即未知数
     */
    private static BigDecimal Flag = new BigDecimal(-1);
    
    /**
     * 代表0
     */
    private static BigDecimal ZERO = new BigDecimal(0);
    
    /**
     * 输入数据最大行数
     */
    private static int MaxLine = 25;
    
    /**
     * <解析为BigDecimal>
     * @param input
     * @return
     */
    private static BigDecimal parse(String input) {
        if (input.equals("?")) {
            return Flag;
        }
        else if (input.equals("0.00") || input.equals("0")) {
            return ZERO;
        }
        return new BigDecimal(input);
    }
    
    /**
     * <处理单行信息>
     * @param line
     * @return
     */
    private static BigDecimal[] parseLine(String line) {
        String[] strs = line.split(";");
        if( strs.length != 4){
            return null;
        }
        
        BigDecimal[] out = null;
        try{
            BigDecimal income = parse(strs[1]);
            BigDecimal payout = parse(strs[2]);
            BigDecimal balance = parse(strs[3]);
            
            if (income != Flag && income != ZERO && payout == Flag)
                payout = ZERO;
            else if (payout != Flag && payout != ZERO && income == Flag)
                income = ZERO;
            
            out = new BigDecimal[]
            {income, payout, balance};
        }catch(Exception e){
            return null;
        }
        return out;
    }
    
    /**
     * <格式化输出>
     * @param f
     * @return
     */
    public static String show(BigDecimal f) {
        if (f == Flag) {
            return "?";
        }
        else if (f == ZERO) {
            return "0.00";
        }
        else {
            return f.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        }
    }
    
    /**
     * <处理当前行及上一行余额已知,且当前行中存在2个未知数情形>
     * @param datas
     * @param currentLineBalanceIndex
     */
    private static void doCaseOne(BigDecimal[] datas, int currentLineBalanceIndex) {
        BigDecimal diff = datas[currentLineBalanceIndex].subtract(datas[currentLineBalanceIndex - 3]);
        if (diff.signum() == -1) {
            datas[currentLineBalanceIndex - 1] = diff.negate();
            datas[currentLineBalanceIndex - 2] = ZERO;
        }
        else {
            datas[currentLineBalanceIndex - 2] = diff;
            datas[currentLineBalanceIndex - 1] = ZERO;
        }
    }
    
    public static void main(String[] args) throws IOException {
        Scanner cin = new Scanner(System.in);
        
        String lineStr = null;
        BigDecimal[] datas = new BigDecimal[MaxLine * 3 + 1];//存放收入,支出,余额数据,从下标为1开始存
        String[] idStrs = new String[MaxLine + 1];//存放每行编号信息,从下标为1开始存
        int[] lineMisCount = new int[MaxLine + 1];//存放每行未知数总数,从下标为1开始存,可为0-3之间的值
        int lineCount = 1;//已读取行数统计
        int dataCount = 1;//已读取数据统计
        int misCount = 0;//未知数统计
        String firstLineStr = null;
        
        while (cin.hasNext() && lineCount < MaxLine + 1) {
            if (firstLineStr == null) {//表头
                firstLineStr = cin.nextLine();
                continue;
            }
            lineStr = cin.nextLine();
            BigDecimal[] d = parseLine(lineStr);
            if(d == null){
                continue; 
            }
            idStrs[lineCount] = lineStr.substring(0, lineStr.indexOf(";"));
            
            int lineMis = 0;
            for (BigDecimal t : d) {
                if (t == Flag) {
                    misCount++;
                    lineMis++;
                }
            }
            lineMisCount[lineCount] = lineMis;
            datas[dataCount++] = d[0];
            datas[dataCount++] = d[1];
            datas[dataCount++] = d[2];
            
            if (lineCount >= 2 && misCount > 0) {//从第二行起,每读一行,循环去倒推当前行及上一行中的未知数
                for (int i = lineCount; i > 1 && misCount > 0; i--) {
                    
                    //==========断层情况开始============
                    if (lineMisCount[i] == 3) {//当前行中三个数未知,将无法倒推出前面所有行中的数据,直接跳出循环,断层原理
                        break;
                    }
                    int index = i * 3;//当前行对应的余额下标
                    if (lineMisCount[i - 1] == 0) {//上一行数据全部已知,则最多只能推出本行的未知数据,断层原理
                        if (lineMisCount[i] == 1) {
                            if (datas[index] == Flag) {//形如 100.00  0.00 ? 形式
                                datas[index] = datas[index - 3].add(datas[index - 2].subtract(datas[index - 1]));
                            }
                            else {//形如  ? 0.00 100.00 或 0.00 ? 100.00形式
                                BigDecimal diff = datas[index].subtract(datas[index - 3]);
                                if (diff.signum() == -1)
                                    datas[index - 1] = diff.negate();
                                else
                                    datas[index - 2] = diff;
                            }
                            lineMisCount[i]--;
                            misCount--;
                        }
                        else if (lineMisCount[i] == 2) {
                            if (datas[index] != Flag) {//形如 ? ? 100.00形式
                                doCaseOne(datas, index);
                                lineMisCount[i] = 0;
                                misCount -= 2;
                            }
                        }//其它 80.00 0.00 100.00 及 ? ? ? 这两种情况不考虑,前一种没有未知数据,后一种情况,根据之前的判断,不可能出现
                        break;
                    }
                    //==========断层情况结束============
                    
                    if (lineMisCount[i] == 0) {//当前行数据全部已知
                        if (datas[index - 3] == Flag) {//推出上一行中的余额
                            datas[index - 3] = datas[index].add(datas[index - 1]).subtract(datas[index - 2]);
                            lineMisCount[i - 1]--;
                            misCount--;
                        }
                        continue;
                    }
                    if (lineMisCount[i] == 2) {//当前行两个未知数
                        if (datas[index] != Flag && datas[index - 3] != Flag) {//形如 ? ? 100.00形式 及上一行的  x x 100.00形式
                            doCaseOne(datas, index);
                            lineMisCount[i] = 0;
                            misCount -= 2;
                        }//其它情况既无法推出本行未知数,也无法推出上一行的未知数
                        continue;
                    }
                    
                    if (lineMisCount[i] == 1) {//当前行一个未知数
                        if (datas[index - 3] != Flag) {//只有上一行余额已知时才能推导出本行未知数
                            if (datas[index - 1] == Flag) {
                                datas[index - 1] = datas[index - 3].subtract(datas[index]);
                            }
                            else if (datas[index - 2] == Flag) {
                                datas[index - 2] = datas[index].subtract(datas[index - 3]);
                            }
                            else {
                                datas[index] = datas[index - 3].add(datas[index - 2]).subtract(datas[index - 1]);
                            }
                            lineMisCount[i] = 0;
                            misCount--;
                        }
                    }
                    
                }
            }
            lineCount++;
        }
        lineCount--;
        
        int size = lineCount * 3;
        if (firstLineStr != null) {
            System.out.println(firstLineStr);//输出表头
        }
        for (int i = 1; i <= size; i += 3) {
            int lineNum = i / 3 + 1;
            System.out.println(idStrs[lineNum] + ";" + show(datas[i]) + ";" + show(datas[i + 1]) + ";"
                + show(datas[i + 2]));
        }
        cin.close();
    }
}

上面用的是BigDecimal来存放数据,个人觉得用double存也是可以的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

分享到:
评论

相关推荐

    平安科技java笔试题

    Java笔试题是评估应聘者Java编程能力的一种常见方式,尤其在技术驱动的公司如平安科技中,这样的测试显得尤为重要。平安科技作为一家领先的金融科技企业,对Java开发人员的专业技能有着高标准的要求。以下是一些可能...

    7 智能金融平安银行零售科技CTO:AI研发之路的「二三五」原则.docx

    平安银行零售科技的首席技术官(CTO)储量,在AI研发的实践中提出了“二三五”原则,这一原则不仅成为平安银行在智能金融领域发展的战略指导,也为整个金融行业提供了一个如何有效融合AI技术与业务需求的实践案例。...

    平安科技开发试题汇总

    【标题】"平安科技开发试题汇总"所涉及的知识点涵盖了Java开发的核心技术和面试常见问题,主要针对的是在平安科技公司进行Java开发岗位面试的求职者。以下是对这些知识点的详细阐述: 1. **Java基础**:Java语言是...

    平安科技技术岗位需求.pdf

    #### 一、平安科技技术岗位薪酬体系与福利待遇 根据平安科技的需求JD文档,平安科技对于不同层级的技术人员设置了明确的薪酬范围,并提供了丰厚的福利待遇。 1. **薪酬标准**: - 对标P6/P6+层级的岗位,月薪范围...

    CCTC 2016 平安科技夏磊豪:两朵云与金融“阿法狗”

    平安科技所提出的“平安深度学习云”和“平安异构计算云”正是基于这样的设计理念,依托于分布式异构计算平台,利用强大的云计算能力,加速深度学习的计算过程,确保深度学习服务的高效与可靠。 在演讲中,夏磊豪还...

    中国平安励志计划创业大赛.doc

    自2011年起,中国青少年发展基金会与平安保险集团联合推出的【中国平安励志计划创业大赛】,已成为中国大学生展现创业才能的重要平台。大赛以“大梦想、微创业”为主题,充分体现了主办方对于激发年轻一代创新精神与...

    平安科技AIOPS建设实践分享.zip

    《平安科技AIOPS建设实践分享》 在当今的数字化时代,运维自动化与智能化的重要性日益凸显。AIOPS(Artificial Intelligence for IT Operations)作为这一领域的前沿技术,正逐步改变着传统IT运维模式。平安科技...

    平安科技Java一百道面试题

    ### 平安科技Java一百道面试题解析 #### 基础知识问题解析 ##### 1. JSP九个内置对象及其作用 JSP(JavaServer Pages)是一种用于创建动态网页的技术,它允许开发者在HTML代码中嵌入Java代码。JSP提供了九个内置...

    java平安科技宝典

    Java 平安科技宝典包含了多个关于 Java 编程、数据库操作、ORM 框架以及软件设计原则的问题。以下是对这些知识点的详细说明: 1. **类的加载与继承**: - 在题目1中,`A` 和 `B` 类的静态块先于实例化执行,因此...

    20200618-平安银行-银行业:平安私人银行2020年第三季度投资策略报告.rar

    平安私人银行在2020年6月发布了其第三季度投资策略报告,这份报告不仅反映了当时经济与投资环境的严峻态势,而且为高净值客户提供了定制化的财富管理方案,帮助他们在充满不确定性的市场中寻找投资机会和规避风险。...

    平安科技精益看板研发实践.pptx

    平安科技在精益看板的研发实践中,逐步推动了价值的拉动和持续改进。这个过程始于2011年,当时平安科技作为国际领先的“互联网+综合金融”高科技提供商,拥有28年的科技、互联网和金融经验,专注于大数据、云平台和...

    IDC&平安银行:中国开放银行白皮书2022(1).pdf

    根据提供的文件信息,我们可以推断出这份文档主要讨论的是关于中国开放银行的发展情况与趋势分析。下面将基于标题、描述以及部分展示的内容来提炼出关键的知识点。 ### 知识点一:开放银行的基本概念 开放银行...

    20201218-平安银行-银行业:平安私人银行2021年第一季度投资策略报告.pdf

    20201218-平安银行-银行业:平安私人银行2021年第一季度投资策略报告.pdf

    (2021-2022)年专题资料平安银行杯模拟炒股大赛.doc

    【文档描述】:“这是一份教育精品资料,详细介绍了2010年广州中医药大学金融理财协会举办的第三届模拟炒股大赛,旨在为大学生提供股票市场的实践平台。” 【文档标签】:“教育精品资料” 【文档部分内容】:文档...

    平安证券计算机行业周报:合肥就促进低空经济产业高质量发展征求意见,国产3A游戏《黑神话:悟空》正式上线.pdf

    【平安证券】计算机行业周报:合肥就促进低空经济产业高质量发展征求意见,国产3A游戏《黑神话:悟空》正式上线.pdf【平安证券】计算机行业周报:合肥就促进低空经济产业高质量发展征求意见,国产3A游戏《黑神话:...

    非银金融行业金融的尽头是科技(一):乘科技之风,破金融创新之浪-20200725-东吴证券-40页.pdf

    蚂蚁集团(原蚂蚁金服)利用金融科技推动普惠金融,而中国平安则通过“金融+科技”策略打造生态圈,其保险科技业务对外销售,实现双重效益。腾讯控股则在金融领域逐步发力,支付业务带动其全牌照布局。 尽管如此,...

    平安银行杯模拟炒股大赛.docx

    为此,广州中医药大学金融理财协会联合广东药学院职业生涯规划与发展协会,共同举办“平安银行杯模拟炒股大赛”,旨在为学生们提供一个接触股票市场的平台。 - **举办目的**: - 活跃校园氛围,丰富校园文化生活; ...

    平安科技AIOPS建设实践分享.pdf

    平安科技AIOPS建设实践分享.pdf

    Java并发编程规则:不可变对象永远是线程安全的.docx

    Java并发编程规则:不可变对象永远是线程安全的 在Java并发编程中,了解不可变对象的概念对于编写线程安全的代码至关重要。不可变对象是指创建后状态不能被修改的对象,这类对象天生就是线程安全的。它们的常量...

    20200923-平安银行-银行业:平安私人银行2020年第四季度投资策略报告.pdf

    20200923-平安银行-银行业:平安私人银行2020年第四季度投资策略报告.pdf

Global site tag (gtag.js) - Google Analytics