引言
- 今天用牛客的平台做了作业帮的笔试,发现没有leetcode那么顺利,在acm模式下,没有自动给你导包,我还有点整的难受,然后写的效率很低!
- 今天就是要重新把那三道题过一遍,把我不会的知识点再补充上去,以便于我明天的面试!
正文
牛客输入和输出练习
- 练习链接
- 这里花了差不多五十分钟,完成了牛客输入输出练习,直到怎处理输入输出了。主要集中在以下几个操作点
- 使用分割符号,useDelimiter(“,”),然后在调用时使用trim
- Scanner可以嵌套,参数为一个string
- 对于同一个Scanner,尽量不要交叉使用hasNext和hasNextLine,容易出错
第一题奇数和偶数的绝对值
- 一个数字最大是 1 0 14 10^{14} 1014,然后遍历其中每一位,分别提出其中的奇数和偶数,然后重新组成两个数字,然后求这两个数的绝对值。
- 这道题还是很简单的,但是我对于Java中的字符串操作还有字符串和整数转换不熟悉,所以做的比较慢!这里补充一下
import java.util.*;
import java.util.concurrent.*;
class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String str = in.next();
StringBuilder oddStr = new StringBuilder();
StringBuilder evenStr = new StringBuilder();
for(int i = 0;i < str.length();i ++){
if((str.charAt(i) - '0') % 2 == 0) {
evenStr.append(str.charAt(i));
}else{
oddStr.append(str.charAt(i));
}
}
// cconvert string to number
long odd =(!oddStr.isEmpty() ? Long.parseLong(oddStr.toString()):0);
long even =(!evenStr.isEmpty() ? Long.parseLong(evenStr.toString()):0);
System.out.println(Math.abs(odd - even));
in.close();
}
}
这个只能通过百分之四十的样例,不知道哪里有问题。
补充知识
- 将String转成对应的数字型的数据的方法,使用Long.parseLong() || Integer.parseInt() || Double.parseDouble()
- 将上述数字转成对应的数字,使用String.valueOf || Long.toString(longNum) || Integer.toString(IntNum)
第二题最大的好数字
- 小红把所有小于105的非负整数放在一起,位数不足5位的补前导零补至5位:00000,00001,00002,99999。一共有105个数。其中,小红定义“好数”为:五个数位上的数都不相同。例如,03265、54321为好数,而66015,00983则不是好数。小红想知道,第k大的好数是多少?
个人实现
- 这题我是按照数位不同的区间进行划分的,最大的六个数字,前四位是确定的,能够变得也只有后六位,然后最大的第7位数字,7 / 6 = 1,说明第四位比最大值小一,然后最后一位是7%6 = 1,说明比最大值小一。
import java.util.*;
import java.util.concurrent.*;
class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int k = in.nextInt();
// define the num,divNum
// int[] num = {9,8,7,6,5,4,3,2,1,0};
List<Integer> list = new LinkedList<>(Arrays.asList(9,8,7,6,5,4,3,2,1,0));
int[] divNum = {1,6,6*7,6*7*8,6*7*8*9,6*7*8*9};
// define the result
StringBuilder res = new StringBuilder("");
int travIdx = 5;
while (travIdx > 0){
int curNum = 0;
if(travIdx != 1) curNum = k / divNum[travIdx - 1];
else curNum = k / divNum[travIdx - 1] - 1;
res.append(list.get(curNum));
list.remove(curNum);
k = k % divNum[travIdx - 1];
travIdx--;
}
System.out.println(res.toString());
}
}
不知道逻辑写的对不对,没时间弄了,就写成了这样
GPT参考实现
- 计算只有10的5次方,完全不用担心计算超时或者超过内存,使用这种方式可以直接实现,先计算出所有好数字,然后在进行排序即可!
import java.util.*;
import java.util.concurrent.*;
class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int k = in.nextInt();
// define the list to sort the legally num
List<String> list = new ArrayList<>();
// generate the num list
for(int i = 1;i < 99999;i ++){
String str = String.format("%05d",i);
if(judgeNum(str)){
list.add(str);
}
}
// sort the list
Collections.sort(list,Collections.reverseOrder());
if(k < 1 || k > list.size()){
System.out.println(-1);
return;
}
System.out.println(list.get(k - 1));
in.close();
}
static boolean judgeNum(String str){
Set<Character> set = new HashSet<>();
for(int i = 0;i < str.length();i ++){
if(set.contains(str.charAt(i))){
return false;
}
set.add(str.charAt(i));
}
return true;
}
}
知识补充
- String.format 的使用
- %05d:0填充字符,5表示填充宽度,d表示十进制整数
- Collections.sort(list,Collections.reverseOrder());
- PriorityQueue pq = new PriorityQueue<>(Comparator.reverseOrder());
总结
- 其实当初也是想这么写的,但是不知道保证定长的字符串,如果自己写的话,还不如自己的重新写一种方法!
- 还是不熟悉Java,还是不熟悉常规的编程方法!
- 真的,太有挫败感了,这两道题那么简单,做的一点都不好!
第三题
- 小红定义一个字符串是好串,当且仅当每个字母出现的次数均为偶数。小红拿到了一个字符串,她想知道该字符串有多少子序列是好串?
- 子序列的定义:字符串中按原串顺序取一些字母组成的字符串(在原串中可以不连续)。例如,“arcaea"的子序列有"aaa”、"ace"等等。
- 输出的结果会比较大,对 1 0 7 + 7 10^{7} + 7 107+7取余数之后,在进行计算
个人实现
- 感觉这个题目不像是会让你逐个进行遍历的,应该是直接计算的,想想看怎么直接计算!
- 不不,还是得让我逐个计算,但是不可能是完全遍历,应该是想着怎么使用动态规划的方式进行计算!
- 每一个字符串只有放或者不放两种情况,然后计算方式如下
- 当前字母放?会有状态转变之说,如果原来的字母某一个情况下是奇数的情况下,再放一个,就有可能是满足要求的好子串,也有可能更加不满足了!
- 使用贪婪的方式解决?目标函数就是尽可能多的成双的字符串?
- 还是使用动态规划去做,最后一个字母放或者不放
- 最后一个字母放入其中
- 上一个状态中,已经满足要求,不需要增加,再增加就是不满足要求,不需要表达式
- 上一个状态,就缺这个字母,然后放进去了,就一下子成了
- 上一个状态,却很多字母,放进去没有意义,不需要表达式
- 最后一个字母放入其中
这道题完全不会
参考实现
- 这个就是使用组合数实现的,直接计算公式,具体实现如下!
import java.util.*;
import java.math.BigInteger;
public class Main {
// Method to calculate n choose m
public static BigInteger C(int n, int m) {
if (m > n) return BigInteger.ZERO;
BigInteger numerator = factorial(n);
BigInteger denominator = factorial(m).multiply(factorial(n - m));
return numerator.divide(denominator);
}
// Method to calculate factorial
public static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 1; i <= n; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
scanner.close();
// Count the frequency of each character
Map<Character, Integer> countMap = new HashMap<>();
for (char c : s.toCharArray()) {
countMap.put(c, countMap.getOrDefault(c, 0) + 1);
}
long mod = 1000000007;
boolean allUnique = countMap.values().stream().allMatch(v -> v == 1);
if (allUnique) {
System.out.println(0);
return;
}
BigInteger ans = BigInteger.ONE;
for (int v : countMap.values()) {
BigInteger cnt = BigInteger.ZERO;
for (int j = 0; j <= v; j += 2) {
cnt = cnt.add(C(v, j));
}
ans = ans.multiply(cnt).mod(BigInteger.valueOf(mod));
}
// Adjust result
ans = ans.subtract(BigInteger.ONE).add(BigInteger.valueOf(mod)).mod(BigInteger.valueOf(mod));
System.out.println(ans);
}
}
- 这里明显是我不会的,暂时没时间弄这个,先搁这吧,这题就是不会!
总结
- 今天的题目主要是以算法为主,确实不会,排列组合忘记的有点多!
- 明天下午的笔试加油!不过也不是重点!还是得赶项目!