京东秋招数据分析算法题解(20190824)

本文介绍了一种姓名排序算法,依据姓氏频率进行排序,并讨论了一个键盘输入优化问题,利用动态规划解决不同输入状态下最小操作数的问题。

问题一:给出一连串姓名,按照如下规则排序,在整个名单中姓氏出现频次较多的在前面,对于相同姓氏的,在原名单中靠前的排在前面。

package Jingdong;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Scanner;
public class test1 {

    static class MyName implements Comparable<MyName>{

        int idx;
        int count;

        public MyName(int idx,int count){

            this.idx=idx;   //姓名录入的编号
            this.count=count;   //姓名出现的频次
        }

        @Override
        public int compareTo(MyName o) {   //重写compareTo方法用于排序
            int t=o.count-this.count;
            return t==0?this.idx-o.idx:t;
        }

        public String toString(){
            String ans="idx:"+this.idx+" count: "+this.count;
            return ans;
        }
    }

    public static String getSurname(String s){    //从姓名字符串中得到姓氏
        //get surname from string of name
        int i=0;
        while (i<s.length() && s.charAt(i)!=' ')
            i++;
        return s.substring(0,i);
    }


    public static void main(String[] args){

        Scanner cin=new Scanner(System.in);
        String s;
        HashMap<String,Integer> map=new HashMap<>();
        ArrayList<String> arr=new ArrayList<>();
        ArrayList<MyName> names=new ArrayList<>();
        while (cin.hasNextLine()){
            s=cin.nextLine();
            String surname=getSurname(s);
            arr.add(s);
            map.put(surname,map.getOrDefault(surname,0)+1);
        }
        for(int i=0;i<arr.size();i++){
            names.add(new MyName(i,map.get(getSurname(arr.get(i)))));
            System.out.println(names.get(names.size()-1).toString());
        }
        Collections.sort(names);
        for(int i=0;i< names.size();i++){
            System.out.println(arr.get(names.get(i).idx));
        }

    }
}

这个算法只能通过91%,不知道为什么,分析了时间复杂度并没有超时。
问题二:
在这里插入图片描述
dp[i][j]表示第i个字母在当前输入法状态为j时输入的最小方案数,输入法状态只有两种,大写模式和小写模式
这个问题第一反应就是动态规划,关键是状态设计和状态转移方程
1.当输入为大写字母时:
1.1 当前为小写状态的最小方案数=min(上一次输入是小写状态的最小方案数+2,上一次是大写状态的最小方案数+2)
1.2 当前是大写状态的最小方案数=min(上一次输入是小写状态的最小方案数+2,上一次是大写状态的最小方案数+1)
2.当输入为小写字母时:
2.1 当前为小写状态的最小方案数=min(上一次输入是小写状态的最小方案数+1,上一次是大写状态的最小方案数+2)
2.2 当前是大写状态的最小方案数=min(上一次输入是小写状态的最小方案数+2,上一次是大写状态的最小方案数+2)

package Jingdong;

import java.util.Scanner;
public class test2 {
    public static void main(String[] args) {
    
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        String s = cin.next();
        int len = s.length();
        int[][] dp = new int[len][2];
        if (s.charAt(0) >= 'A' && s.charAt(0) <= 'Z') 
        {
            dp[0][0] = 2;      //当前状态为小写状态写入第一个(大写)字符需要两步shift+key
            dp[0][1] = 2;      //当前状态为大写状态写入第一个(大写)字符需要两步caps+key
        } 
        else
         {
            dp[0][0] = 1;   //当前状态为小写状态写入第一个(小写)字符需要1步,key
            dp[0][1] = 2;   //当前状态为大写状态写入第一个(小写)字符需要两步,shift+key
        }
        for (int i = 1; i < len; i++) 
        {
            if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z') 
            {
                dp[i][0] = Math.min(dp[i - 1][0] + 2, dp[i - 1][1] + 2);
                dp[i][1] = Math.min(dp[i - 1][0] + 2, dp[i - 1][1] + 1);
            }
             else
              {
                dp[i][0] = Math.min(dp[i - 1][0] + 1, dp[i - 1][1] + 2);
                dp[i][1] = Math.min(dp[i - 1][0] + 2, dp[i - 1][1] + 2);
            }
        }
        System.out.println(Math.min(dp[len - 1][0], dp[len - 1][1]));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值