1 编码
假定一种编码的编码范围是a ~ y的25个字母,从1位到4位的编码,如果我们把该编码按字典序排序,形成一个数组如下: a, aa, aaa, aaaa, aaab, aaac, … …, b, ba, baa, baaa, baab, baac … …, yyyw, yyyx, yyyy 其中a的Index为0,aa的Index为1,aaa的Index为2,以此类推。 编写一个函数,输入是任意一个编码,输出这个编码对应的Index.
输入描述:
输入一个待编码的字符串,字符串长度小于等于100.
输出描述:
输出这个编码的index
输入例子1:
baca
输出例子1:
16331
思路:
题目还是有依据的:
五笔的编码范围是a到y的25个字母,从1位到4位的编码,
如果将五笔的编码按字典序排序,形成数组如下:a, aa, aaa, aaaa, aaab, aaac, …, b, ba, baa, baaa, baab…yyyx, yyyy
不过还是有些难懂,这个字典序
首先可以分成25个大块,每块是以字母a-y开头(不是x是叉,代表空,不满四个字符)
第一大块包含多少个呢?如果长度是4,说明都不包含空(x)第一位已经确定,就是a还有三位可选(选25个字母之一),就是252525,长度是3说明有一个空,25*25,长度为2,两个空只剩一个位置可以是25个字母中任意一个,25,长度是1,那就只有a自己了。所以一共是 253+252+25+1
例:bcd
第一位是b所以处在第二大块,result += 1 * (253+252+25+1)
第二位是c, result += 2 (25^2+25+1)+1
第三位是d, result += 3 (25+1)+1 (加一是因为最前面有个空)
第四位是空,不管,因为空就是第一个
result = 17658
例:defc
第一位是d所以处在第四大块,result += 3 * (253+252+25+1)
第二位是e, result += 4 (25^2+25+1)+1
第三位是 f, result += 5 (25+1)+1
第四位是c, result += 2* (1)+1
result = 51567
public class BianMa {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str=sc.next();
int res=0;
if(str.length()>0){
res+=(str.charAt(0)-'a')*(25*25*25+25*25+25+1);
}
if(str.length()>1){
res+=(str.charAt(1)-'a')*(25*25+25+1)+1;
}
if(str.length()>2){
res+=(str.charAt(2)-'a')*(25+1)+1;
}
if(str.length()>3){
res+=(str.charAt(3)-'a')*(1)+1;
}
System.out.println(res);
}
}
2 构造回文
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入例子1:
abcda
google
输出例子1:
2
2
思路:
找到str的reverse:str2,求出str和str2的公共最长串的长度,放在int[][] dp中,用动态规划的思路做。
public class HuiWen {
//构造回文 动态规划
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String str=sc.next();
String str2=new StringBuilder(str).reverse().toString();
int[][] dp=new int[str.length()+1][str2.length()+1];
for(int i=1;i<dp.length;i++){
for(int j=1;j<dp[0].length;j++){
dp[i][j]=str.charAt(i-1)==str2.charAt(j-1)?dp[i-1][j-1]+1:Math.max(dp[i-1][j],dp[i][j-1]);
}
}
System.out.println(str.length()-dp[str.length()][str2.length()]);
}
}
}
3 字符移位
小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
你能帮帮小Q吗?
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出移位后的字符串。
输入例子1:
AkleBiCeilD
输出例子1:
kleieilABCD
public class CharMove {
//字符移位
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next(); ;
System.out.println(str.replaceAll("[A-Z]","")+str.replaceAll("[a-z]",""));
}
}
4 有趣的数字
小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,相差最小的有多少对呢?相差最大呢?
输入描述:
输入包含多组测试数据。
对于每组测试数据:
N - 本组测试数据有n个数
a1,a2…an - 需要计算的数据
保证:
1<=N<=100000,0<=ai<=INT_MAX.
输出描述:
对于每组数据,输出两个数,第一个数表示差最小的对数,第二个数表示差最大的对数。
输入例子1:
6
45 12 45 32 5 6
输出例子1:
1 2
public class FindMinMaxCount {
public static void main(String[] args) {
//有趣的数字
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
Arrays.sort(arr);
//如果数组中的值全相同,直接两两组合
if(arr[0]==arr[n-1]){
int cur=n*(n-1)/2;
System.out.println(cur+" "+cur);
continue;
}
//treemap中存的是num,和num出现的次数
TreeMap<Integer,Integer> treeMap=new TreeMap<>();
for(int i=0;i<n;i++){
if(treeMap.containsKey(arr[i])){
treeMap.put(arr[i],treeMap.get(arr[i])+1);
}else{
treeMap.put(arr[i],1);
}
}
//求差值最小的对数
int minCount=0;
//没有重复的数字,求差值最小的组合的对数
if(treeMap.size()==n){
int min=Math.abs(arr[1]-arr[0]);
for(int i=2;i<n;i++){
int cur=Math.abs(arr[i]-arr[i-1]);
if(cur==min){
minCount++;
}else if(min>cur){
min=cur;
minCount=1;
}
}
}else{//有重复数字的话,求差值最小的组合的对数
for(int key:treeMap.keySet()){
int val=treeMap.get(key);
if(val>1){
minCount+=val*(val-1)/2;
}
}
}
//求差值最大的对数
List<Integer> list=new ArrayList<>(treeMap.keySet());
int maxCount=treeMap.get(list.get(0))*treeMap.get(list.get(list.size()-1));
System.out.println(minCount+" "+maxCount);
}
}
}