问题一:给出一连串姓名,按照如下规则排序,在整个名单中姓氏出现频次较多的在前面,对于相同姓氏的,在原名单中靠前的排在前面。
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]));
}
}
本文介绍了一种姓名排序算法,依据姓氏频率进行排序,并讨论了一个键盘输入优化问题,利用动态规划解决不同输入状态下最小操作数的问题。
1618

被折叠的 条评论
为什么被折叠?



