第一题[编程题25分]: 闹钟叫醒去上课
题目描述:小明总是睡过头,所以他定了很多闹钟,只有在闹钟响的时候他才会醒过来并且决定起不起来。
从他起床算起他需要X分钟到达教室,上课时间为当天的A时B分,请问他最晚可以什么时候起床。
输入描述:每个输入包含一个测试用例
每个测试用例的第一行包含一个整数,表示闹钟的数量N(N <= 100)
接下来的N行每行包含两个整数,表示这个闹钟响起的时间为Hi(0 <= A < 24)时Mi(0 <= B < 60)分
接下来的一行包含一个整数,表示从他起床算起他需要X(0 <= X <= 100)分钟到达教室
接下来的一行包含两个整数,表示上课时间为A(0 <= A < 24)时B(0 <= B < 60)分
数据保证至少有一个闹钟可以让小明及时到达教室
输出描述:描述两个整合素表示小明起床时间
示例1:(输入输出示例仅供调试,后台判题数据一般不包含示例)
输入:
输出:
思路一:创建一个时间对象,包含Hi和Mi,然后将闹钟时间封装成这个时间对象,然后将这些对象排序)(快排时间复杂度为O(nlog2n)),然后从结尾遍历,找到第一个满足条件的就输出(条件:闹钟时间 + X <=上课时间),然后终止。
import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport;
import org.omg.CORBA.PUBLIC_MEMBER;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class NaoZhong {
public static void main(String[] args) {
run();
}
public static void run(){
//获取输入
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();//闹钟数量
//该list存储每一个闹钟的时间点,time对象的第一个元素为小时,第二个元素为分钟
ArrayList<Time> list = new ArrayList<Time>();
for (int i = 0; i < N; i++) {
//将小时和分钟封装成Time对象
list.add(new Time(scanner.nextInt(), scanner.nextInt()));
}
//将list按照时间进行升序排序
list.sort(new Comparator<Time>() {
@Override
public int compare(Time o1, Time o2) {
return o1.hi - o2.hi == 0 ? o1.mi - o2.mi : o1.hi - o2.hi;
}
});
int X = scanner.nextInt(), A = scanner.nextInt(), B = scanner.nextInt();
Time AB = new Time(A, B);//上课时间
AB.jian(X);
int l = 0, r = list.size() - 1;
while(l <= r){
//二分搜索
/*
<< : 左移运算符,num << 1,相当于num乘以2
>> : 右移运算符,num >> 1,相当于num除以2
>>> : 无符号右移,忽略符号位,空位都以0补齐*/
int m = (l + r) / 2;
if (AB.compareTo(list.get(m)) >= 0){ //此时可以多睡一会
l = m + 1;
}
else { //起晚了
r = m - 1;
}
}
if (r < 0){
//r可能小于0,由于题目说了保证有解,那么输出第一个闹钟就可以了
System.out.println(list.get(0));
}
else
System.out.println(list.get(r));
scanner.close();
}
/**
* Time对象,实现Comparable接口,方便比较
*/
static class Time implements Comparable<Time>{
int hi;
int mi;
public Time(int hi, int mi){
this.hi = hi;
this.mi = mi;
}
public Time jian(int X){ //时间的减法,6时30分-10分 = 6时20分
int T = hi * 60 + mi;//将闹钟时间转发为分钟
int cha = T - X;
hi = cha / 60;
mi = cha % 60;
return this;
}
/**
* 按照小时升序,当小时相同时,按照分钟升序
* @param o
* @return 若返回值小于0说明闹钟订晚了,若大于零,则说明此时起床来的及
*/
@Override
public int compareTo(Time o){
return hi - o.hi == 0 ? mi - o.mi : hi - o.hi;
}
@Override
public String toString(){
return hi + " " + mi;
}
}
}
思路二:由于上面创建了很多闹钟对象,比较费空间,所以我们可以将输入的时间全部转换成分钟,比如6时10分=6*60+10=370分,然后将输入的时间排序(快排时间复杂度为O(nlog2n)),然后二分,思路和上面一样。
import sun.security.krb5.SCDynamicStoreConfig;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class NaoZhong2 {
public static void main(String[] args) {
run();
}
public static void run(){
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < N; i++){
list.add(scanner.nextInt() * 60 + scanner.nextInt());
}
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
int X = scanner.nextInt();
int A = scanner.nextInt();
int B = scanner.nextInt();
int AB = A * 60 + B - X;
int lo = 0;
int hi = list.size() - 1;
while (lo <= hi){
int mid = (lo + hi) / 2;
if (AB >= list.get(mid)){
lo = mid + 1;
}
else hi = mid - 1;
}
if (hi < 0){
System.out.println(list.get(0) / 60 + " " + list.get(0) % 60);
}
else
System.out.println(list.get(hi) / 60 + " " + list.get(hi) % 60);
scanner.close();
}
}
第二题[编程题25分]: 秘密通信
小明和安琪是好朋友。最近,他们的谈话被一家侦探机构监控,所以他们想将他们的谈话内容进行加密处理。
于是,他们发明了一种新的加密方式。每条信息都被编译成二进制数B(明文),其长度为N。
然后该信息被写下K次,每次向右移动0,1,…,K-1位。
例如:B = 1001010,K=4
1001010
1001010
1001010
1001010
然后对每一列进行异或操作,并且把最终所得的结果记录下来,我们将该数称为S(密文)。
例如上述例子的结果为:1110100110。
最后,将编码的信息S和K发送给安琪。
小明已经实现了这种编码的加密过程,但他要求安琪写一个程序去实现这种编码的解密过程,你能帮助安琪实现解密过程吗?
package com.company;
import java.util.Scanner;
public class mimitongxin {
public static void main(String[] args) {
run();
}
private static void run() {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int K = scanner.nextInt();
scanner.nextLine();
String S = scanner.nextLine();
int[] S_int = new int[N + K - 1]; // 将输入的01字符串转化为01整数数组,方便下面进行异或操作
int[] res = new int[N]; // 输出的结果
for (int i = 0; i < N + K - 1; ++i) { // 将输入的01字符串转化为01整数数组,方便下面进行异或操作
S_int[i] = S.charAt(i) - '0';
}
res[0] = S_int[0]; // 第一段
for (int i = 1; i < K; ++i) { // 第二段
res[i] = S_int[i - 1] ^ S_int[i];
}
for (int i = K; i < N; i++) { // 第三段
res[i] = res[i - K] ^ S_int[i - 1] ^ S_int[i];
}
for (int i = 0, len = res.length; i < len; ++i) {
System.out.print(res[i]);
}
System.out.println();
scanner.close();
}
}
第三题[编程题25分]: 万万没想到之抠门的老板
我叫王大锤,是一家互联网公司的老板,快到年底了,要给员工发奖金。
真头疼,大环境这么差,怎么才能尽可能的少发点、同时还能让大家怨气少一点呢?
公司的座位是排成一排的,每个人都最多打听的到和自己相邻左右两个人的奖金数,我决定这样发:
- 每个人都至少发100块。
- 论资排辈:每个人加入公司的年限是公开的,如果一个员工A加入公司的时间比领座的同事B早,那A至少比B多拿100块。这样,他的心理会平衡一些。
我特喵是个天才!将人性理解的如此透彻,做一个小公司的老板真是屈才了。
······
万万没想到,发完奖金,所有员工都离职了,都跳槽去了一家叫字节跳动的公司,他们都说这家公司一不论资排辈,二不吃大锅饭,
奖罚分明,激励到位,老板还特大方,说的我都想去应聘了…
请听题:给定大锤公司员工的座位表,以及每个员工的入职时间,计算大锤最少需要发多少奖金。
方法一:
import org.omg.PortableInterceptor.SUCCESSFUL;
import java.util.Arrays;
import java.util.Map;
import java.util.Scanner;
public class koumen_laoban {
public static void main(String[] args) {
run();
}
private static void run(){
Scanner scanner = new Scanner(System.in);
//获取员工人数
int N = scanner.nextInt();
//存储员工工作年限
int[] people = new int[N];
for (int i = 0; i < N; i++){
people[i] = scanner.nextInt();
}
//存储员工工资
int[] money = new int[N];
//默认将所有员工工资设置为100元
Arrays.fill(money, 100);
for (int i = 0; i < N; i++) {
//从右到左跟后一个人相比
for (int j = i - 1; j >= 0; j--){
if (people[j] < people[j + 1])
break;
money[j] = Math.max(money[j + 1] + 100, money[j]);
}
//从左到右跟前一个人相比
for (int j = i + 1; j < N; j++){
if (people[j] < people[j - 1])
break;
money[j] = Math.max(money[j - 1] + 100, money[j]);
}
}
int sum = 0;
for (int i = 0; i < N; i++) {
sum += money[i];
}
System.out.println(sum);
scanner.close();
}
}
方法二:
import java.util.Arrays;
import java.util.Scanner;
public class koumen_laoban2 {
public static void main(String[] args) {
run();
}
private static void run(){
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int[] left = new int[N];
int[] right = new int[N];
Arrays.fill(left, 100);
Arrays.fill(right, 100);
int[] people = new int[N];
for (int i = 0; i < N; i++) {
people[i] = scanner.nextInt();
}
for (int i = 1; i < N; i++){
if (people[i] > people[i - 1])
left[i] = Math.max(left[i], left[i - 1] + 100);
}
for (int i = N - 2; i >= 0; i--){
if (people[i] > people[i + 1])
right[i] = Math.max(right[i], right[i + 1] + 100);
}
int sum = 0;
for (int i = 0; i < N; i++) {
sum += Math.max(left[i], right[i]);
}
System.out.println(sum);
}
}