组队
作为篮球队教练,你需要从以下名单中选出 1 号位至 5 号位各一名球员, 组成球队的首发阵容。
每位球员担任 1 号位至 5 号位时的评分如下表所示。请你计算首发阵容 1 号位至 5 号位的评分之和最大可能是多少?
这题手算即可,但是还是给出代码运算也行
两种解决方法
1.暴力破解法,直接嵌套5层for循环
2.贪心算法,每次选择当前位最高的人,保存总和,三次for循环,以不同位置起手结果不同,所以首层遍历5次位置,二层选出其他号位号位的最高成绩,3层选出本号位最高的选手.
不同的子串
一个字符串的非空子串是指字符串中长度至少为 1 的连续的一段字符组成 的串。例如,字符串aaab 有非空子串a, b, aa, ab, aaa, aab, aaab,一共 7 个。 注意在计算时,只算本质不同的串的个数。 请问,字符串0100110001010001 有多少个不同的非空子串?
- 本题按位分解即可,使用set去重
数列求值
给定数列1, 1, 1, 3, 5, 9, 17, …,从第4 项开始,每项都是前3 项的和。求
第20190324 项的最后4 位数字
一开始使用暴力结果很大,存不下.
题目说也就是说4位之外的数字我们都不管,就直接舍弃
public static void main(String[] args) {
int a = 1, b = 1, c = 1;
for (int i = 3; i < 20190324; i++) {
//也就是说4位之外的数字我们都不管,就直接舍弃,
int index = (a + b + c) % 10000;
a = b;
b = c;
c = index;
}
System.out.println(c);
}
数的分解
把2019 分解成3 个各不相同的正整数之和,并且要求每个正整数都不包
含数字2 和4,一共有多少种不同的分解方法?
注意交换3 个整数的顺序被视为同一种方法,例如1000+1001+18 和
1001+1000+18 被视为同一种。
一开始想的是暴力破解,从1到2019建立3个循环,但是衍生出重复的情况,一开始设想建立比较器进行判断,但是3的n次方量太大.后来想到,如果一开始建立序列即可,根据范围求解
i: 可以为任何数
b:范围则 i+1~(2019-i+1) ,加一是因为数组for循环从0开始,加一弥补实例上的b能到达循环2018的情况,
c: **范围则为2019-i-b **,其实使用for循环也行,但是会浪费太多时间
分成3个范围,此时就不会出现重复的情况
加上题目给的条件即可
//判断题目的条件
public static boolean textNum(int i){
//处理 2,20 200 2000
if (i/100==2||i/10==2||i/1000==2||i%1000==2
||i%100==2||i%10==2||i==2)return false;
//处理 1200,1120
int n=i%1000;//比如 293
if(n<300&&n>199) return false;
if(n<500&&n>399) return false;
n=i%100;
if(n<30&&n>19) return false;
if(n<50&&n>39) return false;
if (i/100==4||i/10==4||i%1000==4
||i%100==4||i%10==4||i==4)return false;
return true;
}
//主方法
public static void ada(int nums){
//按照范围即可
int count=0;
for (int i=1;i<nums;i++){
if (!textNum(i)) continue;
for (int b=i+1;b<(nums-i+1)/2;b++){
if(textNum(b)){
int c=nums-i-b;
// if (textNum(c)&&i!=b&&i!=c&&b!=c){\
if (textNum(c)&&c!=i&&c!=b){
//去除重复
count++;
}
}
}
}
System.out.println(count);
}
5.迷宫:
题目不在赘述,一开始的想法便是 要么动态规划,回溯,要么就是广度优先算法, 一步一步试探进行,然后不行再回溯.
6 特别数的和
小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。
请问,在 1 到 n 中,所有这样的数的和是多少?
public static void sadaad(int n){
//
int count=0;
for (int i=1;i<=n;i++){
String s=i+"";
if (s.contains("2")||s.contains("1")||
s.contains("9")||s.contains("0")) count+=i;
}
System.out.println(count);
}
7.外卖店优先级
饱了么”外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。 每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。 如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。 给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优先缓存中。
给出的信息
第一行包含 3 个整数 N、M 和 T。 以下 M 行每行包含两个整数 ts 和 id,表示 ts 时刻编号 id 的外卖店收到 一个订单。
【输出格式】
输出一个整数代表答案。
【样例输入】
2 6 6
1 1
5 2
3 1
6 2
2 1
6 2
【样例输出】
1
【样例解释】
6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6, 加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。
解题思路,看着题目长长的,实际不难解决
1.第一步是先存放好店铺的id,拿到M行下的数组里的店铺id,先暂存到一个Set集合中,防止店铺重复
//按照题目生成的方法
public static int elm(int n,int m,int t,int [][] oreder){
Set<Integer> ids = new HashSet<Integer>();
for(int i = 0; i < m;i++) {
ids.add(oreder[i][1]);
}
- 根据店铺的id开始遍历表中的数据,我们对于每个店铺都是单独进行处理.根据比对店铺id与订单表中的id进行比对,将相关的时间ts单独存放再一个ArrayList中, 先大小排序,防止时间短的再后面
for (int userid:ids){
//当前店铺的订单
List<Integer> temp=new ArrayList<>();
// int[] aa=new int[m];
for(int i = 0; i < m; i++) {
if(oreder[i][1] == userid) {
// aa[i]=oreder[i][0];//保存订单的时间
temp.add(oreder[i][0]); //保存订单的时间
}
}
//开始计算店铺优先级
int nowLeven=0;
//比较订单大小,有小到大排序
// Arrays.sort(aa);
Collections.sort(temp);//使用比较器进行排序
// ====for (int userid:ids)未结束====
}
- 开始计算优先级,然而题目中存在两个同样的订单,所以对于多个一样的订单,我先遍历看看有没有一样的订单再进行其余的计算.
for(int ts = 1; ts <= t; ts++) {
//时间开始计算
if (temp.contains(ts)) {
//当前时间有订单
for (int w = 0; w < temp.size(); w++) {
//判断是否包含多个订单,如果含有多个则快速进行排序
if (temp.get(w) == ts) {
nowLeven += 2;
} else if (temp.get(w) > ts) {
break;//推出循环
} else {
continue;
}
}
//for循环------未结束
- 接下来计算优先级就行,初始化为0, int nowLeven=0;,当大于5是进入缓存中,小与3则移除,我用一个set进行存储就行优先缓存就行,然后继续进行时间片的计算
- 最后输出优先缓存的大小即可
public static int elm(int n,int m,int t,int [][] oreder){
//id集合,用来存放商家的id号
Set<Integer> dianCaChe = new HashSet<Integer>();
Set<Integer> ids = new HashSet<Integer>();
for(int i = 0; i < m;i++) {
ids.add(oreder[i][1]);
}
//遍历订单,给每位店铺计算一次时间
for (int userid:ids){
//当前店铺的订单
List<Integer> temp=new ArrayList<>();
// int[] aa=new int[m];
for(int i = 0; i < m; i++) {
if(oreder[i][1] == userid) {
// aa[i]=oreder[i][0];//保存订单的时间
temp.add(oreder[i][0]); //保存订单的时间
}
}
//开始计算店铺优先级
int nowLeven=0;
//比较订单大小,有小到大排序
// Arrays.sort(aa);
Collections.sort(temp);//使用比较器进行排序
for(int ts = 1; ts <= t; ts++) {
//时间开始计算
if (temp.contains(ts)) {
//当前时间有订单
for (int w = 0; w < temp.size(); w++) {
//判断是否包含多个订单,如果含有多个则快速进行排序
if (temp.get(w) == ts) {
nowLeven += 2;
} else if (temp.get(w) > ts) {
break;//推出循环
} else {
continue;
}
}
//判断是否可以加入缓存
if (nowLeven > 5) {
dianCaChe.add(userid);
System.out.println("====添加id为" + userid + "的店铺");
}
} else {//当前没有订单
if (nowLeven>=1)
{nowLeven--;}
else {
nowLeven=0;
}
if(nowLeven<=3){
dianCaChe.remove(userid);
System.out.println("清除id为"+userid+"的店铺");
}
}
}
}
//结束根据id存储用户的比较
System.out.println("最终剩余的店铺数量为:"+dianCaChe.size());
return dianCaChe.size();
}
代码很长,但是不难理解.
剩下的有空再写
【问题描述】
小明正在分析一本小说中的人物相关性。他想知道在小说中 Alice 和 Bob 有多少次同时出现。 更准确的说,小明定义 Alice 和 Bob“同时出现”的意思是:在小说文本 中 Alice 和 Bob 之间不超过 K 个字符。 例如以下文本: ThisisastoryaboutAliceandBob.AlicewantstosendaprivatemessagetoBob.
假设 K = 20,则 Alice 和 Bob 同时出现了 2 次,分别是”Alice and Bob” 和”Bob. Alice”。前者 Alice 和 Bob 之间有 5 个字符,后者有 2 个字符。
注意:
1.Alice 和 Bob 是大小写敏感的,alice 或 bob 等并不计算在内。
2.Alice 和 Bob 应为单独的单词,前后可以有标点符号和空格,但是不能有字母。例如 Bobbi 并不算出现了 Bob。
判断是否包含完事了
public static int getFunction(String people,int maxCode){
//拿到了语句
//根据空格切割语句
String[] allWord=people.split("\\s+|\\.");
//此时按照空格和多个标点符号切割了字符串
int[] wordLength=new int[allWord.length];
for (int i = 0; i < allWord.length; i++) {
wordLength[ i]=allWord[i].length();
}
//遍历拿到每个字符串的长度
int count=0;//记录人数
//开始比对情况,
for (int k = 0; k < allWord.length; k++) {
if(allWord[k].equals("Alice")){
for (int w=k+1;w< allWord.length;w++){
int strSum=1;//Alice之后的空格数为1
if(allWord[w].equals("Bob")){
//找到当前的W,到w即for循环停止
for (int q = k + 1;q <w; q++) {
// 每个单词的长度加空格占据的长度
strSum += wordLength[q] + 1;
}
if(strSum<=maxCode) count++;
}
}
}
}
//重复一次
for (int k = 0; k < allWord.length; k++) {
if(allWord[k].equals("Bob")){
for (int w=k+1;w< allWord.length;w++){
int strSum=1;//Alice之后的空格数为1
if(allWord[w].equals("Alice")){
//找到当前的W,到w即for循环停止
for (int q = k + 1; q <w; w++) {
// 每个单词的长度加空格占据的长度,所以加一
strSum += wordLength[q] + 1;
}
if(strSum<=maxCode) count++;
}
}
}
}
System.out.println(count);
return count;
}
9.后缀表达式
【问题描述】
给定 N 个加号、M 个减号以及 N + M + 1 个整数 A1,A2,··· ,AN+M+1,小 明想知道在所有由这 N 个加号、M 个减号以及 N + M +1 个整数凑出的合法的 后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。 例如使用1 2 3 + -,则 “2 3 + 1 -” 这个后缀表达式结果是 4,是最大的。
【输入格式】
第一行包含两个整数 N 和 M。 第二行包含 N + M + 1 个整数 A1,A2,··· ,AN+M+1。
【输出格式】
输出一个整数,代表答案。
【样例输入】
1 1
1 2 3
【样例输出】
4
这里一题使出全部情况即可,但是我写的繁杂
列出3种情况
-
当减号小与0 的时候,将数组就相加就行
-
当加号少于0的时候,出现两种细微的情况
2.1 出现全部正数:
例如:[1,2,3,4,5,6] 加号:0,减去:5
6-(1-2-3-4-5)=19 最大的减去-(最小的数-第二小的数…)
利用正负转换的,拿到最大数
2.2 出现负数
含有负数: [-3,1,2,3,4] 加号:0,减号:4
4-3-2-1+3=1 ,显然不是最大的,
4-(-3-1-2-3)=4+9=13 -
出现减号和加号
3.1 减号>=负数的个数
例如 [-2, -1, 1, 2, 3],两个减号两个加号
运算过程为 3 - (-1) - (-2) + 1 + 2,
即每个减号匹配一个负数将其变正,然后从大到小累加这些数,再减去和剩下的减号数量相等的数
3.2 减<负数的个数:
例如 [-2,-1,1],一个加号一个减号,运算过程为 1 - (-2 + -3)
即把负数相加来消除负数,这时候有两种情况3.2.2 全是负数,如 [-1, -2, -3, -4, -5],一个加号三个减号 运算过程为 -1 - ( -4 + -5 ) - (-3) - (-2) 即首先排序选择其中的最大值,加上其他数字的绝对值就行。 3.2.2 有正数,有负数,如 [-4,-3,-2,-1,1],两个加号两个减号 运算过程为 1 - ( -4 + -3 + -2 + -1 ) - -1 即首先排序选择其中的最大值,加上其他数字的绝对值就行。
按照以上情形解决就行
public static int getMaxNum(int add ,int reduce ,int[] number ){
int num = add + reduce + 1;//数
int sum = 0;
if (reduce == 0) {//1
for (int i = 0; i < num; i++) {
sum += number[i];
}
}
if (add == 0) {//2
Arrays.sort(number);
if (number[0] < 0) {//2.1
for (int i = 0; i <= reduce; i++) {
if (number[i] > 0)
sum += number[i];
else
sum -= number[i];
}
} else {//2.2
for (int i = 1; i <= reduce; i++) {
sum += number[i];
}
sum -= number[0];
}
}
//3. 第三的情况
if (add != 0 && reduce != 0) {//3
int negativeNumber = 0;//负数
for (int i = 0; i < num; i++) {
if (number[i] < 0) {
negativeNumber++;
}
}
Arrays.sort(number);
if (reduce >= negativeNumber) {//3.1
int temp = reduce;
for (int i = 0; i < negativeNumber; i++) {
number[i] = -number[i];
temp--;
}
Arrays.sort(number);
for (int i = num - 1; i >= temp; i--) {
sum += number[i];
}
for (int i = temp - 1; i >= 0; i--) {
sum -= number[i];
}
} else {//3.2
sum += number[num - 1];
for (int i = 0; i < num - 1; i++) {
if (number[i] > 0)
sum += number[i];
else
sum -= number[i];
}
}
}
System.out.println(sum);
sc.close();
}
}