L1-017 到底有多二 (15分)
一个整数“犯二的程度”定义为该数字中包含2的个数与其位数的比值。如果这个数是负数,则程度增加0.5倍;如果还是个偶数,则再增加1倍。例如数字-13142223336是个11位数,其中有3个2,并且是负数,也是偶数,则它的犯二程度计算为:3/11×1.5×2×100%,约为81.82%。本题就请你计算一个给定整数到底有多二。
输入格式:
输入第一行给出一个不超过50位的整数N。
输出格式:
在一行中输出N犯二的程度,保留小数点后两位。
输入样例:
-13142223336
输出样例:
81.82%
实现代码
package com.misakora.home.hooo.l1_0017;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
try {
String string = bf.readLine();
char[] chs = string.toCharArray(),
pattern = {
'2'}; // kmp算法的模式串
int count = KMPIndex(chs,pattern); // 返回 2 的个数
double len = string.length()
,isOdd = 1 //奇1 偶2
,minus = 1; //负1.5 正1
if (string.charAt(0) == '-'){
minus += 0.5;
len -= 1;
}
if (Integer.parseInt(string.charAt(string.length()-1)+"") % 2 == 0){
//判断最后一位是偶数和奇数
isOdd = 2;
}
double d = (count/len) * minus * isOdd * 100; //公式计算
//格式化 d保留两位小数
System.out.println(String.format("%.2f",d).toString() + "%");
} catch (IOException e) {
e.printStackTrace();
}
}
//求kmp算法模式串的next数组
private static int[] computedArray(char[] pattern){
int[] next = new int[pattern.length];
int j = 0;
next[j] = 0;
for (int i = 1; i < pattern.length; i++) {
if (pattern[j] == pattern[i]){
next[i] = j+1;
i++;
j++;
}else {
if (j == 0){
next[i] = 0;
i++;
}else {
j = next[j-1];
}
}
}
return next;
}
//KMP算法本体
public static int KMPIndex(char[] text,char[] pattern){
List<Integer> indexs = new ArrayList<>();
int[] next = computedArray(pattern);
int i = 0, j = 0, count = 0;
while (i< text.length && j< pattern.length){
if (text[i] == pattern[j]){
i++;
j++;
}else {
if (j==0){
i++;
}else {
j = next[j-1];
}
}
if (j == pattern.length){
count++;
j = 0;
if (text[i] != pattern[j])
i++;
}
}
return count;
}
}