原题:牛客10道练习题2_meiribaofu的博客-CSDN博客
1、快递运输
一辆运送快递的货车,运送的快递均放在大小不等的长方体快递盒中,为了能够装载更多的快递,同时不能让货车超载,需要计算最多能装多少个快递。
输入描述:
第一行输入每个快递的重量,用英文逗号分隔,如:5,10,2,11
第二行输入货车的载重量,如:20
不需要考虑异常输入。
输出描述:
输出最多能装多少个快递,如:3
public static int delivery(int[] arr, int weight) {
Arrays.sort(arr);
int sum = Arrays.stream(arr).sum(); //快递总重量
int sums = 0;
//sum - sums[i] = sums //去掉某个快递的剩余重量
for (int i = arr.length - 1; i >= 0; i--) {
if (sum - sums < weight) {
return i + 1;
} else {
sums += arr[i];
}
}
return 0;
}
(没有第二题,因为题目看不懂QAQ)
3、考勤信息
公司用一个字符串来表示员工的出勤信息:
absent:缺勤
late:迟到
leaveearly:早退
present:正常上班
现需根据员工出勤信息,判断本次是否能获得出勤奖,能获得出勤奖的条件如下:
缺勤不超过一次;没有连续的迟到/早退;任意连续7次考勤,缺勤/迟到/早退不超过3次
present
present absent present present leaveearly present absent
输出描述:
根据考勤数据字符串,如果能得到考勤奖,输出"true";否则输出"false",对于输入示例的结果应为:
true false
public static boolean fullAttendance(String str) {
Stack<String> stack = new Stack<>();
Queue<String> queue = new LinkedList<>();
String[] s = str.split(" ");
int absent = 0;
int count = 0;
for (int i = 0; i < s.length; i++) {
String cur = s[i];
if (cur.equals("absent")) {
if (++absent > 1) return false;
}
//用栈判断是否有连续的早退或迟到
if (cur.equals("leaveearly") || cur.equals("late")) {
if (stack.peek().equals("late") || stack.peek().equals("leaveearly")) {
return false;
} else {
count++;
}
}
stack.push(cur);
queue.offer(cur);
//队列7次判断是否三次以上迟到或早退,否则出队一个保证任意7天
if (queue.size() == 7 && count > 3) {
return false;
} else {
String poll = queue.poll();
if (poll.equals("late") || poll.equals("leaveearly")) {
count--;
}
}
}
return true;
}
4、字符串分割
给定一个非空字符串S,其被N个‘-’分隔成N+1的子串,给定正整数K,要求除第一个子串外,其余的子串每K个字符组成新的子串,并用‘-’分隔。对于新组成的每一个子串,如果它含有的小写字母比大写字母多,则将这个子串的所有大写字母转换为小写字母;反之,如果它含有的大写字母比小写字母多,则将这个子串的所有小写字母转换为大写字母;大小写字母的数量相等时,不做转换。
输入描述:
输入为两行,第一行为参数K,第二行为字符串S。
输出描述:
输出转换后的字符串。
示例1
输入
3
12abc-abCABc-4aB@
输出
12abc-abc-ABC-4aB-@
public static String strChange(String str, Integer k) {
String[] arr = str.split("-");
StringBuffer newStr = new StringBuffer();
newStr.append(arr[0]);
StringBuffer childs = new StringBuffer();
for (int i = 1; i < arr.length; i++) {
childs.append(arr[i]);
}
//双指针
int left = 0;
int right = left + k;
while (right < childs.length()) {
String substring = childs.substring(left, right);
String s = countUpCase(substring.toString(), k);
newStr.append("-").append(s);
left += k;
right = left + k;
}
if (left < childs.length()) {
newStr.append("-").append(childs.substring(left));
}
return newStr.toString();
}
public static String countUpCase(String str, int k) {
int letter = 0;
int capital = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) >= 'a' && str.charAt(i) <= 'z') {
letter++;
}
if (str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') {
capital++;
}
}
if (capital == letter) {
return str;
} else if (letter > k / 2) {
return str.toLowerCase();
} else {
return str.toUpperCase();
}
}
5、组成最大数
小组中每位都有一张卡片,卡片上是6位内的正整数,将卡片连起来可以组成多种数字,计算组成的最大数字。
输入描述:
“,”号分割的多个正整数字符串,不需要考虑非数字异常情况,小组最多25个人
输出描述:
最大的数字字符串
输入
4589,101,41425,9999
输出
9999458941425101
public static String maxStr(String str) {
String[] arr = str.split(",");
//使用大顶堆 重写字符串比较方法
PriorityQueue<String> queue = new PriorityQueue<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int len1 = o1.length();
int len2 = o2.length();
int lim = Math.min(len1, len2);
char v1[] = o1.toCharArray();
char v2[] = o2.toCharArray();
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c2 - c1;
}
k++;
}
return len1 - len2;
}
});
for (int i = 0; i < arr.length; i++) {
queue.offer(arr[i]);
}
StringBuffer sb = new StringBuffer();
while (!queue.isEmpty()) {
sb.append(queue.poll());
}
return sb.toString();
}
6、高矮个子排队
现在有一队小朋友,他们高矮不同,我们以正整数数组表示这一队小朋友的身高,如数组{5,3,1,2,3}。
我们现在希望小朋友排队,以“高”“矮”“高”“矮”顺序排列,每一个“高”位置的小朋友要比相邻的位置高或者相等;每一个“矮”位置的小朋友要比相邻的位置矮或者相等;
要求小朋友们移动的距离和最小,第一个从“高”位开始排,输出最小移动距离即可。
例如,在示范小队{5,3,1,2,3}中,{5, 1, 3, 2, 3}是排序结果。{5, 2, 3, 1, 3} 虽然也满足“高”“矮”“高”“矮”顺序排列,但小朋友们的移动距离大,所以不是最优结果。
移动距离的定义如下所示:
第二位小朋友移到第三位小朋友后面,移动距离为1,若移动到第四位小朋友后面,移动距离为2;
public static int[] queueUp(int[] arr) {
// {5,3,1,2,3}
//5,1,3,2,3
//4 1 3 5 2
//4,1,5,3,2
//4,1,5,2,3
//使用双指针,当前指向和下一个进行比较,如果是偶数下标就判断是否大,奇数判断是否小
int cur = 0;
int next = cur+1;
while(next != arr.length){
if(cur % 2 == 0){
if(arr[cur] < arr[next]) swap(arr,cur,next);
}else{
if(arr[cur] > arr[next]) swap(arr,cur,next);
}
cur++;
next++;
}
return arr;
}
public static void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
7、猴子爬山
一天一只顽猴想去从山脚爬到山顶,途中经过一个有个N个台阶的阶梯,但是这猴子有一个习惯: 每一次只能跳1步或跳3步,试问猴子通过这个阶梯有多少种不同的跳跃方式?
//动态规划
public static int monkey(int n){
//dp[n] = dp[n-1]+dp[n-3]
int[] dp = new int[n+1];
//确定边界
dp[0] = 1;dp[1]= 1;
dp[2] = 1;dp[3] = 2;
for(int i = 4 ; i < n+1;i++){
dp[i] = (dp[i-3]+dp[i-1])%1000000007;
}
return dp[n];
}
8、分糖果
小明从糖果盒中随意抓一把糖果,每次小明会取出一半的糖果分给同学们。
当糖果不能平均分配时,小明可以选择从糖果盒中(假设盒中糖果足够)取出一个糖果或放回一个糖果。
小明最少需要多少次(取出、放回和平均分配均记一次),能将手中糖果分至只剩一颗
输入描述:
抓取的糖果数(<10000000000):
15
输出描述:
最少分至一颗糖果的次数:
5
public static int candy(int n){
int count = 0;
//2 count = 1 2/2 = 1 count =2
for(int i = n ; i != 1 ; i /= 2, count++){
if(n == 3){
return count += 2;
}
if(i % 2 != 0){
if ((i + 1) / 2 % 2 == 0) i++;
else i--;
count++;
}
}
return count;
}
9、报数游戏
100个人围成一圈,每个人有一个编码,编号从1开始到100。他们从1开始依次报数,报到为M的人自动退出圈圈,然后下一个人接着从1开始报数,直到剩余的人数小于M。请问最后剩余的人在原先的编号为多少?
//约瑟夫问题,单循环链表(取余完成)
public static void Josef(int m){
List<Integer> list = new LinkedList<>();
int person = 100;
for (int i = 1; i <= person; i++) {
list.add(i);
}
int index = 0;
//3
//index = 2 % 100 = 2
//index = 4 % 99 = 4
while (list.size() >= m) {
index = (index + m - 1) % list.size();
list.remove(index);
}
System.out.println(list);
}
10、消消乐游戏
消消乐游戏
游戏规则:输入一个只包含英文字母的字符串,字符串中的两个字母如果相邻且相同,就可以消除。
在字符串上反复执行消除的动作,直到无法继续消除为止,此时游戏结束。
输出最终得到的字符串长度。
public static int clear(String str){
//stringbuffer做栈
StringBuffer stack = new StringBuffer();
int head = -1;
for(int i = 0 ; i < str.length(); i++){
if(stack.length() > 0){
if (stack.charAt(head) == str.charAt(i)){
stack.deleteCharAt(head);
head--;
continue;
}
}
stack.append(str.charAt(i));
head++;
}
return stack.length();
}