准备od机考中, c++答案和java都有
标括号(博客)代表是题目链接里给的答案, 大部分是自己写的, 比较喜欢打上注释, 帮助理解
我觉得c++还是简洁点, 不过有的题目就是为了考java的集合用法, 就用java更好
题目链接
华为OD机试真题2023(JAVA&JS)_华为机试真题_若博豆的博客-CSDN博客
1 猜字谜
c++代码(我写的)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20010;
string aa[N], bb[N];
int main()
{
string a;//谜面
string b;//谜底 在谜底中找谜面里的错误词
getline(cin, a);
getline(cin, b);
string res;//每个单词
int count = 0;
for(int i = 0; i < a.length(); i ++ )
{
if(a[i] == ',')
{
aa[count ++ ] = res;
res = "";
}
else res += a[i];
}
aa[count] = res;//最后一个res也存进去 count不用加了
int len_aa = count + 1;
res = "";
count = 0;
for(int i = 0; i < b.length(); i ++ )
{
if(b[i] == ',')
{
bb[count ++ ] = res;
res = "";
}
else res += b[i];
}
bb[count] = res;//最后一个res也存进去 count不用加了
int len_bb = count + 1;
bool flag = false;//是否找到
bool comma = false;//是否有逗号
//然后两个字符串数组就是 aa 和 bb, 长度分别是len_aa, len_bb
for(int i = 0; i < len_aa; i ++ ) {//循环aa字符串数组,
string str = aa[i];
sort(str.begin(), str.end());
str.erase(unique(str.begin(), str.end()), str.end()); //去掉重复元素
for(int j = 0; j < len_bb; j ++ ) {
string str2 = bb[j];
sort(str2.begin(), str2.end());
str2.erase(unique(str2.begin(), str2.end()), str2.end());
if(str2 == str) {
if(comma) cout << ',';
cout << bb[j];
flag = true;
comma = true;
break;
}
}
if(flag == false) cout << "not found" << endl;
flag = false;
}
return 0;
}
java代码(博客里的):
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] question=in.nextLine().split(",");
String[] answer=in.nextLine().split(",");
List<String> resList=new ArrayList<>();
for(int i=0;i<question.length;i++){
String q=question[i];
boolean isFound=false;
for(int j=0;j<answer.length;j++){
String a=answer[j];
if(change(q,a)){
resList.add(a);
isFound=true;
}else if(dist(q,a)){
resList.add(a);
isFound=true;
}
}
if(!isFound){
resList.add("not found");
}
}
String res= "";
for(int i=0;i<resList.size();i++){
res+=resList.get(i)+",";
}
System.out.println(res.substring(0,res.length()-1));
}
public static boolean dist(String question,String answer){
List<Character> qList=new ArrayList<>();
for(int i=0;i<question.length();i++){
char c=question.charAt(i);
if(!qList.contains(c)){
qList.add(c);
}
}
List<Character> aList=new ArrayList<>();
for(int i=0;i<answer.length();i++){
char c=answer.charAt(i);
if(!aList.contains(c)){
aList.add(c);
}
}
if(qList.equals(aList)){
return true;
}
return false;
}
public static boolean change(String question,String answer){
String[] qStr=question.split("");
Arrays.sort(qStr);
String[] aStr=answer.split("");
Arrays.sort(aStr);
if(Arrays.equals(qStr,aStr)){
return true;
}
return false;
}
}
2 木板
题目链接:
【满分】【华为OD机试真题2023 JAVA&JS】木板_若博豆的博客-CSDN博客
java代码(博客里的):
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] nums = new int[n];
for(int i=0; i<n; i++){
nums[i] = sc.nextInt();
}
Arrays.sort(nums);
while (m>0){
m--; //木材一段一段的截
for(int i=1; i<n; i++){
if(nums[i] > nums[i-1]){
nums[i-1] ++; //碰到比后面的短的就加一截
break;
}
if(i == n-1){
nums[i] ++; //所有木材一样长则在最后一根加一截
}
}
}
System.out.println(nums[0]);
}
}
c++代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n, m;
int a[N];
int main()
{
scanf("%d%d", &n, &m);
int min = 0;
for(int i = 0; i < n; i ++ )
scanf("%d", &a[i]);
sort(a , a + n);//从小到大排序
while(m -- ) {
for(int i = 1; i < n; i ++ ) {
if(a[i] > a[i - 1])//如果比前一个长, 前一个+1
{
a[i - 1] ++ ;//
break;
}//否则 不加
if(i == n - 1)//遍历到尾巴了, 就最后一节+1
{
a[i] ++ ;
}
}
}
cout << a[0] << endl;
return 0;
}
3 查找重复代码
题目链接:
java(博客里的)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
String str2 = sc.nextLine();
String result = "";
int start = 0;
int end = 1;
while(end <= str2.length()){
String subStr = str2.substring(start,end);
if (str1.contains(subStr)){
result = subStr;
}else {
start++;
}
end++;
}
System.out.println(result);
}
}
c++代码:
#include <iostream>
using namespace std;
int main()
{
string a;//0-200 暴力枚举
string b;
getline(cin, a);
getline(cin, b);
int len1 = a.length();
int len2 = b.length();
if(len1 > len2) swap(a, b);//让a是短的
string res = "";
//双指针 [i,j] 判断 n * n = 10000
for(int j = len1 - 1; j > 0; j -- )
{
for(int i = 0; i < j; i ++ )
{
string temp = a.substr(i, j - i + 1);
if(b.find(temp) != -1) {
if(temp.length() > res.length())
res = temp;
}
}
}
cout << res << endl;
return 0;
}
5 单词倒序
java代码(博客里的)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
String result = "";
int start = 0;
for (int i = 0; i< str.length(); i++) {
char a = str.charAt(i);
if (a==' ' || a=='?' || a=='.' || a==',') {
if (i > start) {
StringBuilder word = new StringBuilder(str.substring(start, i));
result = result + word.reverse() + a;
} else {
result = result + a;
}
start = i + 1;
} else if (i == str.length() -1) {
StringBuilder word = new StringBuilder(str.substring(start, i + 1));
result = result + word.reverse();
}
}
System.out.println(result);
}
}
c++代码:
#include <iostream>
using namespace std;
int main()
{
string a[100];
int i = 0;
while(cin >> a[i]) i ++;
for(int j = 0; j < i; j ++ )
{
//取出字符串数组中的每个字符串a[i]
string str = a[j];
char temp = '\0';
for(int k = str.length() - 1; k >= 0; k -- )
{
//反转后将字符串中的每个字符输出
//如果是标点, 先不输出
if(str[k] == ',' || str[k] == '.' || str[k] == '!') {
temp = str[k];
}
else cout << str[k];
}
if(temp != '\0') cout << temp;
cout << ' ';
temp = '\0';
}
cout << endl;
return 0;
}
6 打印文件
java代码(博客里的)
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
List<List<File>> m = new ArrayList<>();
for (int i = 0; i < 5; i++) {
m.add(new ArrayList<>());
}
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int flag = 0;
for (int i = 0; i <= n; i++) {
String s = in.nextLine();
String[] s1 = s.split(" ");
String type = s1[0];
if ("IN".equals(type)) {
int p = Integer.parseInt(s1[1]);
int num = Integer.parseInt(s1[2]);
flag++;
File file = new File(flag, num);
List<File> files = m.get(p - 1);
files.add(file);
} else if ("OUT".equals(type)) {
int p = Integer.parseInt(s1[1]);
List<File> files = m.get(p - 1);
if (files != null && files.size() > 0) {
files.sort((a, b) -> {
return b.getWeight() - a.getWeight();
});
File file = files.get(0);
System.out.println(file.getIndex());
files.remove(0);
} else {
System.out.println("NULL");
}
}
}
}
}
class File {
private int index;
private int weight;
public File(int index, int weight) {
this.index = index;
this.weight = weight;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
c++代码:
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
const int N = 1010;
typedef pair<int, pair<int, int>> PII;
int m;
vector<PII> alls;
int main()
{
scanf("%d", &m);
int count = 1;//文件的编号
while(m -- ) {
string op;
cin >> op;
int p, n;
bool flag = false;
if(op == "IN")
{
scanf("%d%d", &p, &n);//打印机编号p, 优先级n
alls.push_back({n, {count, p}});
count ++ ;
//sort(alls.rbegin(), alls.rend());//按照n排序
sort(alls.rbegin(), alls.rend(), [](const PII &a, const PII &b){
return a.x < b.x; // 先按照优先级n降序, 再按照插入顺序count升序
});
// for(auto e : alls)
// {
// cout << e.x << ' '<< e.y.x << ' ' << e.y.y << endl;
// } cout << endl;
}
else if(op == "OUT")
{
scanf("%d", &p);
int len = alls.size();
//遍历输出结果
for(int i = 0; i < len; i ++ )
{
//如果有结果 输出结果, 在数组中删除该数 flag=true, 退出循环
if(alls[i].y.y == p)
{
cout << alls[i].y.x << endl;
auto iter = alls.erase(alls.begin() + i);//删除元素
flag = true;
break;
}
}
//如果遍历完都没有结果, flag还是false 输出NULL
if(flag == false) cout << "NULL" << endl;
flag = false;
}
}
return 0;
}
7 对称字符串
c++代码, 不过这个回溯会爆内存 报memory limit exceeded 或者 time limit exceeded
#include <iostream>
using namespace std;
const int N = 100010;
int t, n, k;
string solve(int x) {//每次就是把前一个的字符串取反 + 原字符串
if(x == 1) return "R";//1输出R
string str = solve(x - 1);
string res = "";
for(int i = 0; i < str.length(); i ++ ) {
if(str[i] == 'R') res += 'B';
else if(str[i] == 'B') res += 'R';
}
return res + str; //翻转结果 + 原字符串
}
int main()
{
scanf("%d", &t);
while(t -- ) {
scanf("%d%d", &n, &k);
string ans = solve(n);//只能在25以内, 否则memory limit exceeded
if(ans[k] == 'R') cout << "red" << endl;
else cout << "blue" << endl;
}
return 0;
}
c++ 找规律写法: 这个是扒的博客java解法
#include <iostream>
#include <cmath>
#include <algorithm>
typedef long long ll;
using namespace std;
int t, n, k;//n是第几个字符串, k是字符的位置
int solve(ll len, ll k, int rev) //len是字符串的长度, k是位置, rev是翻转次数
{
if(len == 1) return rev;//回溯到最底层 就返回现在的rev就是翻转的次数
ll half = len / 2;//长度的一半
if(k < half) { //k在前半部分, 是反转后的部分
rev ++ ;//翻转次数++
return solve(half, k, rev);
} else {//后半部分
return solve(half, k - half, rev);
}
}
int main()
{
scanf("%d", &t);
while(t -- ) {
scanf("%d%d", &n, &k);
//长度
ll len = (ll)pow(2, n - 1);
//cout << len << endl;
int ans = solve(len, k, 0);//传入长度, 位置, 求该位置的翻转次数
//原字符是R 翻转偶数次就是R 翻转奇数次就是B
if(ans % 2) cout << "blue" << endl;//奇数次
else cout << "red" << endl;//偶数次
}
return 0;
}
java代码(博客)
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for(int i=0; i<T; i++){
int n = sc.nextInt();
long k = sc.nextLong();
long charNum = (long) Math.pow(2, n - 1); //第n行的总字符个数
int re = doProcess(charNum, k, 0);
if (re % 2 == 0) {
System.out.println("red"); //翻转次数为2的倍数
} else {
System.out.println("blue");
}
}
}
/**
* 翻转次数
* @param count 总字符的个数
* @param cur 字符的索引
* @param reverse 翻转次数
* @return
*/
public static int doProcess(long count, long cur, int reverse){
if (count == 1) {
return reverse;
}
long half = count / 2;
if (cur < half) { //小于半数说明是经过翻转的部分
reverse ++;
return doProcess(half, cur, reverse);
} else {
return doProcess(half, cur - half, reverse);
}
}
}
8 分界线
爷的c++代码, 纯打暴力
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
string aa[N], bb[N];
int main()
{
string a;//报纸内容
string b;//是否可以拼成的 匿名信
getline(cin, a);
getline(cin, b);
string res = "";
int j = 0;
for(int i = 0; i < a.length(); i ++ ) //100 * 104 = 100400
{
if(a[i] == ' ') {
aa[j ++ ] = res;
res = "";
} else res += a[i];
} aa[j ++ ] = res;
//存进去了aa[N] 报文的字符串数组
int len_a = j;
res = "";
j = 0;
for(int i = 0; i < b.length(); i ++ ) //100400
{
if(b[i] == ' ') {
bb[j ++ ] = res;
res = "";
} else res += b[i];
} bb[j ++ ] = res;
//存进去了bb[N] 报文的字符串数组
int len_b = j;
int count = 0;
for(int i = 0; i < len_b; i ++ ) {//枚举每个匿名信单词
string ano = bb[i];
sort(ano.begin(), ano.end());
for(int j = 0; j < len_a; j ++ ) {//枚举原报文遍历单词
string news = aa[j];
sort(news.begin(), news.end());
if(ano == news) {
count ++ ;
break;//结束报文的遍历
}
}
}
if(count == len_b) cout << "true" << endl;
else cout << "false" << endl;
return 0;
}
java(博客里的)
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String newsapper = sc.nextLine();
String anonymousLetter = sc.nextLine();
String[] newsapperArr = newsapper.split(" ");
String[] anonymousLetterArr = anonymousLetter.split(" ");
for (int i = 0; i < anonymousLetterArr.length; i++) {
String ii = anonymousLetterArr[i];
char[] ic = ii.toCharArray();
Arrays.sort(ic);
boolean flag = false;
for (int j = 0; j < newsapperArr.length; j++) {
String jj = newsapperArr[j];
char[] jc = jj.toCharArray();
Arrays.sort(jc);
if (Arrays.equals(ic, jc)){
flag = true;
break;
}
}
if (!flag){
System.out.println(false);
System.exit(0);
}
}
System.out.println(true);
}
}
9 关联端口组合并
string数组转成int数组的方法:
String数组转int数组_躺平的菜鸟啊的博客-CSDN博客
不需要像c++那样遍历了哈哈哈, java也不错嘛
java代码(博客里的思路) 我打了备注, 改动了一点:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner myScanner = new Scanner(System.in);
//二维数组, 外层用list保存, 内层用set集合保存, set集合有去重和排序的功能,
//每输入一个组合, 对list进行遍历, 找出其中有两个并集的集合进行合并
int m = myScanner.nextInt();
if(m > 10) System.out.println("[[]]");
else {
List<Set<Integer>> list = new ArrayList<>();
//myScanner.nextLine();//读取行
//循环
for(int i = 0; i < m; i ++ ) {
String[] strings = myScanner.nextLine().split(",");//读取行 分成zi字符串数组strings
int[] nums = Arrays.stream(strings).mapToInt(Integer::parseInt).toArray();//转换成字符串数组nums
Set<Integer> set = new TreeSet<>();
if(nums.length == 1 ) {//只有一个元素, 直接添加
set.add(nums[0]);
list.add(set);//加入list
} else {
for(int num : nums) {
set.add(num);//数字加到set集合中
}
list.add(set);//这个新的set加到list, 默认加到最后
merge(set, list, list.size() - 1 );//看是否需要合并set和list内的set
}
}
System.out.println(list);//输出结果
}
}
public static void merge(Set<Integer> set, List<Set<Integer>> list, int index) {
for(int i = 0; i < list.size(); i ++ ) {//遍历list中的每个set
if(i == index) continue;//如果是相同 就不继续了
Set<Integer> setIdx = list.get(i);//当前索引的set集合
Set<Integer> setTemp = new TreeSet<>();
setTemp.addAll(set);//临时集合 保存交集
setTemp.retainAll(setIdx);//待判断的set和当前的setIdx的交集, 返回交集
if(setTemp.size() >= 2) {//当交集>=2 则需要合并
set.addAll(setIdx); //把新传入的set与setIdx合并
list.remove(i);//两个都移除后
list.remove(index);
int st = i < index ? i : index;//存靠前的下标
list.add(st, set);//加上并集set 在st位置
merge(set, list, st);//新建的组合再进行判断合并, 因为合并之后
}
}
}
}
10 货币单位换算
c++代码, 按照博客思路写的
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int n;
double solve(string str, char c) {
double res;
for(int i = 0; i < str.length(); i ++ ) {
res *= 10;
res += str[i] - '0';
}
if(c == 'C') res *= 100;
else if(c == 'J') res *= (double) 10000 / 1825;
else if(c == 'H') res *= (double) 10000 / 123;
else if(c == 'E') res *= (double) 10000 / 14;
else if(c == 'G') res *= (double) 10000 / 12;
else if(c == 'f') res *= 1;
else if(c == 's') res *= (double) 100 / 1825;
else if(c == 'c') res *= (double) 100 / 123;
else if(c == 'e') res *= (double) 100 / 14;
else if(c == 'p') res *= (double) 100 / 12;
return res;
}
int main(){
scanf("%d", &n);
double res = 0;
while(n -- ) {
string str;
cin >> str;
string tmp;
for(int i = 0; i < str.length(); i ++ ) {
char c = str[i];
if(c >= '0' && c <= '9') tmp += str[i];
else {
res += solve(tmp, c);
i += 2;
if(c == 'c') i += 2;
else if(c == 'e') i += 8;
else if(c == 'p') i += 2;
tmp = "";//重来
}
}
}
cout << floor(res) << endl;
return 0;
}
java代码(博客中的)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double money = 0.0;
int count = Integer.parseInt(sc.nextLine());
for (int i = 0; i < count; i++) {
String line = sc.nextLine();
String[] split = line.split("\\d");
for (String type : split) {
if(!type.isEmpty()){
String num = line.substring(0, line.indexOf(type));
money += getCny(type, Double.parseDouble(num));
line = line.substring(line.indexOf(type) + type.length());
}
}
}
System.out.println(Math.round(Math.floor(money)));
}
private static double getCny(String type, double num) {
switch (type) {
case "CNY":
return num * 100;
case "fen":
return num;
case "JPY":
return num / 1825 * 10000;
case "sen":
return num / 1825 * 100;
case "HKD":
return num / 123 * 10000;
case "cents":
return num / 123 * 100;
case "EUR":
return num / 14 * 10000;
case "eurocents":
return num / 14 * 100;
case "GBP":
return num / 12 * 10000;
case "pence":
return num / 12 * 100;
}
return 0;
}
}
11 获得完美走位
java代码(博客中的, 我打了备注)
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
int strLen = str.length();
int count = strLen / 4;
Map<Character, Integer> map = new HashMap<>();
//把字符串中所有的字符存到map中, k-v表示字符-个数
for(int i = 0; i < strLen; i++)
{
char c = str.charAt(i);
if(map.containsKey(c)) map.put( c, map.get(c) + 1);//保存k-v 字符-个数+1
else map.put( c, 1 - count);//字符-需要的个数(用负数表示, 最后才能归0)
}//比如AASW 就是 [A,1] [S,0] [W,0]
int min = str.length();
for (int i = 0; i < strLen; i++) {
HashMap<Character, Integer> copy = new HashMap<>(map);
int res = 0;
if (copy.get(str.charAt(i)) > 0) //如果某个方向多走了
{
for (int j = i; j < str.length(); j++) //往后遍历其他的
{
char c = str.charAt(j);
copy.put(c, copy.get(c) - 1);//把他变换一下
res ++ ;//答案++
if (isZero(copy)) break;//判断是否都是0
}
}
if (isZero(copy)) res = Math.min(min, res);
}
System.out.println(res);
}
private static boolean isZero(HashMap<Character, Integer> copy) {
Collection<Integer> values = copy.values();
for (Integer value : values) {
if (value > 0) return false;
}
return true;
}
}
12 简单的自动曝光
忽然发现我自己做的题, 不一定会满分哈哈 因为都只测了一两个用例
c++代码: 这个很简单
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 110;
int a[N];
int main(){
int sum = 0;
int i = 0;
while(cin >> a[i]) {
sum += a[i];
i ++ ;
}
double res = (double)(512 - sum) / 4;
cout << floor(res) << endl;//向下取整 1 2
return 0;
}
参考一下java的满分答案, 博客里面的:
import java.util.*;
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Stream;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] strings = in.nextLine().split(" ");
int[] nums = Arrays.stream(strings).mapToInt(Integer::parseInt).toArray();
solution(nums);
}
public static void solution(int[] list) {
int ans = 0;
int t = Integer.MAX_VALUE;
for (int i = -127; i < 255; ++i) {
int sum = 0;
for (int j = 0; j < list.length; ++j) {
int tmp = i + list[j];
if (tmp < 0) {
tmp = 0;
} else if (tmp > 255) {
tmp = 255;
}
sum += tmp;
}
if (t > Math.abs(128 * list.length - sum)) {
ans = i;
t = Math.abs(128 * list.length - sum);
}
}
System.out.println(ans);
}
}
13 日志采集系统
c++ 代码, 我觉得我写的很牛哈哈哈
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1010;//最多1000个 每个里面100条
int a[N], s[N], m[N];//
int main(){
int i = 1;
while(cin >> a[i]) {
s[i] = s[i - 1] + a[i];//前缀和
m[i] = s[i - 1] + s[i];//要减去的
//cout << s[i] << ' ' <<m[i] << endl;
i ++ ;
}
int n = i;//总采集次数
int res = 0;
int score = 0;
for(int i = 1; i <= n; i ++ )
{
score = min(100, s[i]) - m[i - 1];
res = max(res, score);
if(s[i] >= 100) break;
}
cout << res <<endl;
return 0;
}
java代码:
就不放了 没我写得好
14 数组的中心位置
c++ 简洁优雅, 不过可能会爆int 需要优化一下
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1034;//最多1024个
int a[N], s[N];
int main(){
int i = 1;
s[0] = 1;
while(cin >> a[i]) {
s[i] = s[i - 1] * a[i];
i ++ ;
}
int n = i - 1;
for(int j = 1; j <= n; j ++ ) {
if(s[j] * s[j + 1] == s[n]) {
cout << j << endl;
return 0;
}
}
cout << "-1" << endl;
return 0;
}
优化:
看一下java解法 博客写的, 没动过:
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
int len = strings.length;
int[] nums = Arrays.stream(strings).mapToInt(Integer::parseInt).toArray();
//题目说:数组第一个元素的左侧积为1,最后一个元素的右侧积为1
int left=1, right=1;
for(int num : nums){
right = right * num; //数组的总乘积
}
boolean flag =false;
for(int i=0; i<len; i++){
if(i!=0){
left = left * nums[i-1]; //左侧积做乘法
}
right = right / nums[i]; //右侧积做除法
if(left == right){
System.out.print(i);
flag = true;
break;
}
}
if(!flag){
System.out.println(-1);
}
}
}
15 通信误码
java代码: 按照博客思路打的
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
for(int i = 0; i < n; i ++ ) {
nums[i] = sc.nextInt();
}
Map<Integer, Integer> map = new HashMap<>();//存k-v 误码-误码频率
int max = 0;//数字出现的最大次数
for(int i = 0; i < n; i ++ ) {
int count = map.getOrDefault(nums[i], 0) + 1;//当前数字出现次数再加上1次
max = Math.max(max, count);//取最大值
map.put(nums[i], count);//存进map
}
Set<Integer> set = new HashSet<>();//存最高误码的集合
for(Map.Entry<Integer, Integer> entry : map.entrySet()) {
if(entry.getValue() == max) {
set.add(entry.getKey());//加入频率最高的数字
}
}
int res = n;
for(Integer integer : set) {//双指针 取出某个max值,
int l = 0, r = n - 1;
while(nums[l] != integer) l ++ ;//当两个指针都是max值的时候才停下
while(nums[r] != integer) r -- ;
if(l <= r) res = Math.min(res, r - l + 1);//max取结果
}
System.out.println(res);
}
}
getOrDefault方法:
格式:
Map.getOrDefault(key,默认值);
Map中会存储一一对应的key和value。
如果 在Map中存在key,则返回key所对应的的value。
如果 在Map中不存在key,则返回默认值。
entrySet()
Java中Map的 entrySet() 详解以及用法(四种遍历map的方式)-CSDN博客
Map中采用Entry内部类来表示一个映射项,映射项包含Key和Value (我们总说键值对键值对, 每一个键值对也就是一个Entry)
Map.Entry里面包含getKey()和getValue()方法
entrySet是java中 键-值对的集合,Set里面的类型是Map.Entry,一般可以通过map.entrySet()得到。
- entrySet实现了Set接口,里面存放的是键值对。一个K对应一个V。
即通过getKey()得到K,getValue得到V。
这种遍历方法比较快:
Map.Entry<Integer, Integer> entry : map.entrySet()
16 网上商城优惠
【华为OD机试真题2023 JAVA】网上商城优惠活动(一)_接口测试主要测哪些方面_若博豆的博客-CSDN博客z
这题绕糊涂了 , 没写对, 有空重新弄一下
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int mj;
int dz;
int wmk;
int n;
double manjian(int money) {
int a = money / 100;//可以使用的张数
int count = a > mj ? mj : a;
double res = (double) (money - count * 10) ;
return res;
}
double wumenk(int money) {
int a = money / 5;//可以使用的张数
int count = a > wmk ? wmk : a;
double res = (double) (money - count * 5) ;
return res;
}
int main()
{
scanf("%d%d%d", &mj, &dz, &wmk);
scanf("%d", &n);
int res;
while(n -- ) {
int money;
scanf("%d", &money);//账单金额 操作前
int res = 2e9;
int tmp = 2e9;
//C32 6中情况 打折只能用一次, 其他的无使用限制
//先满减后打折
if(mj > 0 && dz > 0) {
tmp = manjian(money);
tmp = floor((double)tmp * 0.92);
}
res = min(res, tmp);
//先满减后无门槛
if(mj > 0 && wmk > 0) {
tmp = manjian(money);
tmp = wumenk(tmp);
}
res = min(res, tmp);
//先打折后满减
if(dz > 0 && mj > 0) {
tmp = floor(money * 0.92);
tmp = manjian(tmp);
}
res = min(res, tmp);
//先打折后无门槛
if(dz > 0 && wmk > 0) {
tmp = floor((double)tmp * 0.92);
tmp = wumenk(tmp);
}
res = min(res, tmp);
//先无门槛后满减
if(mj > 0 && wmk > 0) {
tmp = wumenk(tmp);
tmp = manjian(money);
}
res = min(res, tmp);
//先无门槛后打折
if(dz > 0 && wmk > 0) {
tmp = wumenk(tmp);
tmp = floor((double)tmp * 0.92);
}
res = min(res, tmp);
cout << res << endl;
}
return 0;
}
java博客代码
import java.util.Scanner;
public class Main{
public static int manjian;
public static int dazhe;
public static int wumenkan;
//券的最小使用量
public static int mincountQuan;
//最少价格
public static int minCount;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
manjian = sc.nextInt();
dazhe = sc.nextInt();
wumenkan = sc.nextInt();
int n = sc.nextInt();
for(int i=0; i<n; i++){
double money = sc.nextInt();
//首先使用满减的张数
int quanMJ = money/100 > manjian ? manjian : (int) (money / 100);
//使用无门槛的券的张数
int quanWMK;
//券的最小使用量
mincountQuan = Integer.MAX_VALUE;
//最少价格
minCount = Integer.MAX_VALUE;
if(dazhe > 0){ //有打折券的情况
//先满减后打折
int MJafterDZ = (int) Math.floor(Manjian(money) * 0.92);
flush( MJafterDZ, quanMJ + 1);
//先打折后满减
int DZafterMJ = (int) Math.floor(Manjian(money * 0.92));
//先打折后满减的满减券
int quanDZafterMJ = (int) (money * 0.92 / 100 > manjian ? manjian : money * 0.92 / 100);
flush( DZafterMJ, quanDZafterMJ + 1);
//先打折后无门槛
double dazhe = money * 0.92;
//无门槛需要的张数
quanWMK = wumenkan(dazhe);
int dazheWMK;
if(dazhe <= quanWMK * 5){
//打折后的价格小于等于无门槛的全部价格(可以0元购)
dazheWMK = 0;
}else {
dazheWMK = (int) Math.floor(dazhe - quanWMK * 5);
}
flush( dazheWMK, quanWMK + 1);
//先无门槛后打折
int wmkDZ;
//无门槛需要的张数
quanWMK = wumenkan(money);
if(money <= quanWMK * 5 ){
//价格小于等于无门槛的全部价格(可以0元购)
flush( 0, quanWMK);
}else {
wmkDZ = (int) Math.floor((money - quanWMK * 5) * 0.92);
flush( wmkDZ, quanWMK + 1);
}
}
//先满减后无门槛
int mjWMK;
double manjian= Manjian(money);
//无门槛需要的张数
quanWMK = wumenkan(manjian);
if(manjian <= quanWMK * 5){
//满减后的价格小于等于无门槛的全部价格(可以0元购)
mjWMK = 0;
}else {
mjWMK = (int) Math.floor(manjian - quanWMK * 5);
}
flush( mjWMK, quanWMK + quanMJ);
System.out.println(minCount + " " + mincountQuan);
}
}
/**
* 刷新最少价格和最少使用券
* @param count
* @param quanCount
*/
public static void flush(int count, int quanCount){
if(count < minCount){
minCount = count;
mincountQuan = quanCount;
}else if(count == minCount){
mincountQuan = Math.min( quanCount, mincountQuan);
}
}
/**
* 求出需要无门槛优惠券的张数
* @param money
* @return
*/
public static int wumenkan(double money){
for(int i=1; i<=wumenkan; i++){
if(money <= 5 * i) {
return i;
}
}
return wumenkan;
}
/**
* 满减后的价格
* @param money
* @return
*/
public static double Manjian(double money){
if(money/100 >= manjian){
return money - manjian*10;
}else {
return money - ((int) money/100)*10;
}
}
}
17 开心消消乐
java代码
感觉这个没有回溯啊 就是找到第一个点来计算的.. 有空看吧 先记住了
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int row = scanner.nextInt();
int column = scanner.nextInt();
int[][] numbers = new int[row][column];
scanner.nextLine();
for (int i = 0; i < row; i++) {//每行
for (int j = 0; j < column; j++) {
numbers[i][j] = scanner.nextInt();
}
}
int count = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (numbers[i][j] == 1) {//如果该点值为1 点击一下, 再继续循环其他的点
turnZero(numbers, row, column, i, j);
count++;
}
}
}
System.out.println(count);
}
private static void turnZero(int[][] numbers, int row, int col, int x, int y) {
numbers[x][y] = 0;//点击为0
for (int i = x - 1; i <= x + 1; i ++ ) {
for (int j = y - 1; j <= y + 1; j ++ ) {//遍历相邻的8个点
if (i >= 0 && i < row && j >= 0 && j < col && numbers[i][j] == 1) {//如果是1
turnZero(numbers, row, col, i, j);//就自动变为0
}
}
}
}
}
18 获取最大软件版本号
compareTo 复习一下
java中compareTo方法的使用_compareto在java中的用法_高某123的博客-CSDN博客
java代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String a = scanner.nextLine();
String b = scanner.nextLine();
String[] strs1 = a.split("\\.");//1.5.1-A 分成 1 5 1-A
String[] strs2 = b.split("\\.");
//比较主次版本 1.3.11-S2 1.05.1 中的 1 3 和 1 05 挨个遍历这两个字符
for(int i = 0; i < 2; i ++ ) {
int va = Integer.valueOf(strs1[i]);
int vb = Integer.valueOf(strs2[i]);
if(va != vb) {//继续遍历
System.out.println(va > vb ? a : b);
return;
}
}
//增量版本可能不存在 如 直接是 1.5
//比较增量版本 和里程碑版本
if(strs1.length > 2 && strs2.length > 2 ) {//两个版本长度都 > 2
//有增量版本 就在strs[2]位置
String[] s1 = strs1[2].split("-"); //分成 1 A
String[] s2 = strs2[2].split("-");
int va = Integer.valueOf(s1[0]);
int vb = Integer.valueOf(s2[0]);
if(va != vb) {
System.out.println(va > vb ? va : vb);
return;
}
//增量版本也相同 如果都有里程碑版本
if(s1.length == 2 && s2.length == 2) {
//字典序排序 compareTo
System.out.println(s1[1].compareTo(s2[1]) >= 0 ? a : b);
} else {
System.out.println(s2.length >= s2.length ? a : b);
}
} else {
System.out.println(strs1.length >= strs2.length ? a : b);
}
}
}
19 寻找链表的中间节点
输入:
00100 4
00000 4 -1
00100 1 12309
33218 3 00000
12309 2 33218
输出: 3
输入:
10000 3
76892 7 12309
12309 5 -1
10000 1 76892
输出: 7
java代码: 博客里的 我打了备注
import java.util.*;
public class Main {
public static class Node{
String data;
String next;
public Node(String data, String next) {
this.data = data;
this.next = next;
}
}
public static void main(String[] args) {
//保存 地址 - 节点
Map<String, Node> map = new HashMap<>();
Scanner sc = new Scanner(System.in);
//初始化元信息
String[] mate = sc.nextLine().split(" "); //mate[0] 是 地址 mate[1] 是个数
for(int i = 0; i < Integer.parseInt(mate[1]); i ++ ) {
String[] info = sc.nextLine().split(" ");//每一行的地址 value next
map.put(info[0], new Node(info[1], info[2]));
}
//通过list保存有效数据和记录数据链长度
List<String> res = new LinkedList<>();//保存结果 list是有序的
String address = mate[0];//起始地址是第一个
while(true) {
if(map.containsKey(address) == false) break;
//不包含起始地址, 链表为空; 或者找不到下一个地址, 链表结束
Node node = map.get(address);//get(Key) 得到的v就是 Node
res.add(node.data);//链表保存数据
address = node.next;//address记录下一个node
}
//返回中间位置的值
int idx = res.size() / 2;
System.out.println(res.get(idx));
}
}
20 最小的调整次数
输入:
3
head add 1
remove
tail add 2
head add 3
remove
remove
输出: 1
java代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());//读取数据范围
int cnt = 0;//变幻的次数
int left = 0;//剩下待移除的数字
boolean flag = false;//是否需要逆转
//2n 行
for(int i = 0; i < 2 * n; i ++ ) {
//读取一行 head add 1 或者 remove
String[] str = sc.nextLine().split(" ");
if(str.length == 3 ) {//add操作
if(left != 0) {//有数字的情况下
//如果是head, 就要调整一次顺序
if(str[0].equals("head") && !flag ) { //不需要调整
flag = true;//标记需要调整
}
//如果是tail, 不用管, 直接添加
}
//如果left==0, 不管头和尾都直接添加
left ++ ;//数字添加
}
if(str.length == 1) {//移除操作
left -- ;//数字减少
cnt += flag ? 1 : 0;//是不是需要调整, 需要的话结果+1
flag = false;//调整完结束
}
}
System.out.println(cnt);
}
}
这个题目的意思是 一次调整可以调整所有的数, 所以一直等待一个head插入就可以计数了
21 字符串解密
java代码 自己打了备注
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
String s2 = sc.nextLine();
//处理字符串2
HashSet<String> set = new HashSet<>();
for(char c : s2.toCharArray()) {//把字符串2变成字符数组 遍历每个字符
set.add(c + "");//把每个字符都存到set中 set是自动去重的
}
//处理字符串1
String sub = "123456789abcdef";
//去掉0-9 a-f
int index = 0;//起始点
ArrayList<String> list = new ArrayList<>();//保存删除0-9 a-f后的 字符串数组
//保存筛选后的字符串
for(int i = 0; i < s1.length(); i ++ ) {
if(sub.contains(s1.charAt(i) + "")) {//遍历到0-9 a-f时, 保存当前字符串
list.add(s1.substring(index, i));//substring(1,1)是空, 所以不保存
index = i + 1;
} else {
if(i == s1.length() - 1) { //遍历到结尾的时候
list.add(s1.substring(index));
}
}
}
String res = "";
for(int i = 0; i < list.size(); i ++) {//枚举i 获得每个子字符串
String cs = list.get(i);//list里面每个子字符串
if(cs.length > 0) {
//hashset会自动去重, 获得的长度就是去重后的
HashSet<String> cset = new HashSet<>();
for(int j = 0; j < cs.length(); j++ ) {
cset.add(cs.charAt(j) + "" );
}
int len = cset.size();//去重后 每个子串的长度
//如果这个子串满足题目要求的条件: < 字符串2的长度
if (len <= set.size()) {
//就把结果字符串去重
HashSet<String> sset = new HashSet<>();
for (int j = 0; j < res.length(); j++) {
sset.add(res.charAt(j) + "");
}
int slen = sset.size();
//如果子串长度 > 结果串长度, 更新结果
if (len > slen) {
res = cs;
} else if (len == slen && cs.compareTo(res) > 0) {//字典序
res = cs;//如果子串长度相同, 字典序更大 也更新结果
}
}
}
}
if (res.length() > 0) {
System.out.println(res);
} else {
System.out.println("Not Found");
}
}
}
22 投篮大赛
java代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String[] nums = s.split(" ");
List<Integer> list = new ArrayList<>();
int res = 0;
for(int i = 0; i < nums.length; i ++ ) {//遍历每个串
if(nums[i].equals("+")) {
int j = list.size();
if(list.size() < 2) {//需要集合 >= 2 才能+
System.out.println("-1");
return;
}
int grade = list.get(j - 1) + list.get(j - 2);//倒数第一个和倒数第二个
list.add(grade);
} else if (nums[i].equals("D")) {
int j = list.size();
if(list.size() < 1) {//需要集合 >= 1 需要前面有一个数字
System.out.println("-1");
return;
}
int grade = list.get(j - 1) * 2;
list.add(grade);
} else if(nums[i].equals("C") ) {
if(list.size() < 1 ) {//需要集合 >= 1 前面有1个数据
System.out.println("-1");
return;
}
list.remove(list.size() - 1);//去掉最后一个数字
} else {//直接添加
list.add(new Integer(nums[i]));
}
}
for(int i = 0; i < list.size(); i ++ ) {
res += list.get(i);
}
System.out.println(res);
}
}
23 任务总执行时长
java
咱们就是说, 我只会写这种
// 本题为考试单行多行输入输出规范示例,无需提交,不计分。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] input = in.nextLine().split(",");
int taskA = Integer.valueOf(input[0]);
int taskB = Integer.valueOf(input[1]);
int nums = Integer.valueOf(input[2]);
HashSet<Integer> set = new HashSet<>();
if(nums != 0){
int countA = nums;
while(countA >= 0){
int countB = nums - countA;
set.add(countA * taskA + countB * taskB);
countA -- ;
}
}
List<Integer> ans = new ArrayList<>(set);
Collections.sort(ans);
System.out.println(ans);
}
}
24 找数字
java
这个可以看下原链接 满分解法 好像写的更好, 没来得及看
import java.util.*;
//找数字
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int row = sc.nextInt();
int col = sc.nextInt();
int[][] nums = new int[row][col];
for(int i = 0; i < row; i ++ ) {
for(int j = 0; j < col; j ++ ) {
nums[i][j] = sc.nextInt();
}
}
HashMap<Integer, List<int[]>> map = new HashMap<>();//存<数字, {
{坐标}, {坐标} ..}>
for(int i = 0; i < row; i ++ ) {
for(int j = 0; j < col; j ++ ) {
List<int[]> list;
if(map.containsKey(nums[i][j])) {
list = map.get(nums[i][j]);
} else {
list = new ArrayList<>();
}
list.add(new int[]{i, j});
map.put(nums[i][j], list);
}
}
ArrayList<List<Integer>> resList = new ArrayList<>();
for(int i = 0; i < row; i ++ ) {
ArrayList<Integer> row_list = new ArrayList<>();//一行的结果
for(int j = 0; j < col; j ++ ) {//该行每个数字
int key = nums[i][j];
List<int[]> sites = map.get(key);//每个数字的坐标集合
if(sites.size() == 1) {
row_list.add(-1);
continue;//遍历下一个数字
}
int res = Integer.MAX_VALUE;
//当坐标集合>1时 遍历每个集合
for(int k = 0; k < sites.size(); k ++ ) {
int[] ints = sites.get(k);
int x = ints[0];
int y = ints[1];
//距离
int distance = Math.abs(x - i) + Math.abs(y - j);
if(distance == 0) continue;//否则把自己比较进去了 0 也会影响结果
res = Math.min(distance, res);//每个结果都更新
}
row_list.add(res);
}
resList.add(row_list);
}
System.out.println(resList);
}
}
26 箱子之形摆放
java
map存<位置, 结果字符串>
import java.util.*;
//26 箱子的摆放
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
String str = strings[0];
int n = Integer.parseInt(strings[1]);
char[] chars = str.toCharArray();
//用map存每一行
//k-v是 <Integer. String>
// key是行数, values每一行的内容 把该位置的字符拼到values
HashMap<Integer, String> res = new HashMap<>();//<0,A> <1,B> <2,C>
for(int i = 0 ; i < str.length(); i += n ) {
if(i / n % 2 == 0) {//偶数列 正序
for(int j = 0; j < n; j ++ ) {
if(i + j < str.length()) {
if(res.containsKey(j)) {
String value = res.get(j);//必须要判断 否则会把null加进去
value += str.charAt(j + i);
res.put(j, value);
} else {
res.put(j, String.valueOf(str.charAt(j + i)));
}
}
}
} else {//奇数 倒序
for(int j = 0; j < n; j ++ ) {
if(res.containsKey(j)) {
String value = res.get(n - 1 - j);
value += str.charAt(j + i);
res.put(n - 1 - j, value);
} else {
res.put(n - 1 - j, String.valueOf(str.charAt(j + i)));
}
}
}
}
for(String sb: res.values()) {
System.out.println(sb);
}
// for(Map.Entry<Integer, String> map : res.entrySet()) {
// System.out.println(map.getValue());
// }
}
}
27 异常的打卡记录
java
import java.util.*;
//找数字
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();//打卡记录数
sc.nextLine();
HashMap<Integer, List<int[]>> map = new HashMap<>();
//遍历每个打卡记录
ArrayList<String> alls = new ArrayList<>();
for(int i = 0; i < n; i ++ ) {
String str = sc.nextLine();
//System.out.println(str);
String[] strings = str.split(",");
alls.add(str);
int id = Integer.parseInt(strings[0]);
int time = Integer.parseInt(strings[1]);
int distance = Integer.parseInt(strings[2]);
if(map.containsKey(id)) {
List<int[]> list = map.get(id);
list.add(new int[]{time, distance});
map.put(id, list);
} else {
ArrayList<int[]> list = new ArrayList<>();
list.add(new int[]{time, distance});
map.put(id, list);
}
}
ArrayList<Integer> res = new ArrayList<>();
//遍历每个map 找重复打卡的人是不是有异常
for(Map.Entry<Integer, List<int[]>> entry : map.entrySet()) {
Integer id = entry.getKey();
List<int[]> list = entry.getValue();//{时间, 地点} {} {} ..
// if(list.size() == 1) {
// //打卡记录一次, 不存在两次打卡距离的问题
// //判断内部是否需要检查
// }
if(list.size() != 1) {//比较 任意两个数组
for(int i = 0; i < list.size() - 1; i ++ ) {
int[] ints = list.get(i);
int time1 = ints[0];
int distance1 = ints[1];
for(int j = i + 1; i < list.size(); i ++ ) {
int[] ints2 = list.get(i);
int time2 = ints2[0];
int distance2 = ints2[1];
if(Math.abs(time1 - time2) < 60
&& Math.abs(distance1 - distance2) > 5) {
res.add(id);
}
}
}
}
}
//遍历每个打卡记录 集合alls里面的
boolean flag = true;
StringBuilder ans = new StringBuilder();
for(int i = 0; i < n; i ++ ) {
String str = alls.get(i);
String[] strings = str.split(",");
int id = Integer.parseInt(strings[0]);
String log = strings[3];
String register = strings[4];
if(res.contains(id)) {
//System.out.println(str);
ans.append(str);
ans.append(" ");
flag = false;
} else if(!log.equals(register)) {
//System.out.println(str);
ans.append(str);
ans.append(" ");
flag = false;
}
}
if(flag) System.out.println("null");
else System.out.println(ans.toString().trim().replace(" ", ";"));
}
}
28 最左侧冗余覆盖子串
import java.util.*;
//28 最左侧冗余覆盖子串
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
String s2 = sc.nextLine();
int k = sc.nextInt();
int n1 = s1.length();
int n2 = s2.length();
int len = n1 + k;
for(int i = 0; i < n2 - len + 1; i ++ ) {//枚举子串开始的下标
String tmp = "";
for(int j = 0; j < len; j ++ ) {//子串长度
tmp += s2.charAt(j + i);
}
if(tmp.contains(s1)) {
System.out.println(i);
return;
}
}
System.out.println("-1");
}
}
或者substring
for(int i = 0; i < n2 - len + 1; i ++ ) {//枚举子串开始的下标
String tmp = s2.substring(i, i + len);
if(tmp.contains(s1)) {
System.out.println(i);
return;
}
}
29 最多提取子串数目
import java.util.*;
//29 最多提取子串数目
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String stra = sc.nextLine();//父字符串
String strb = sc.nextLine();
//char[] charsa = stra.toCharArray();//父字符串的字符数组
int len = stra.length();
int[] a = new int[len];//数组 保存是否已经被取过 0/1 没取过 是 0
int i = 0, j = 0;
int cnt = 0;
while (i < stra.length()) {
if (stra.charAt(i) == strb.charAt(j) && a[i] == 0) {//匹配上了
a[i] = 1;
//匹配上了 需要判断: 如果匹配完子串, 父串从0开始, 否则父串i++往后移动
j ++ ;//子串往后移动
}
if (j == strb.length()) {//子串遍历到尾巴了 说明都匹配上了
cnt ++ ;
j = 0;
i = 0;
} else {
i ++ ;//父串继续往后遍历
}
}
System.out.println(cnt);
}
}
30 找出通过车辆最多颜色
java:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
int n = sc.nextInt();//n秒时间
int res = 0;
for(int i = 0; i < strings.length - n + 1; i ++ ) {
//类似滑动窗口, 遍历每个窗口
int[] ints = new int[3];//3中颜色
for(int j = i; j < n; j ++ ) {
int num = Integer.parseInt(strings[j]);
ints[num] ++ ;
}//遍历完得到这个窗口的每个颜色个数
int max = Arrays.stream(ints).max().getAsInt();
//Arrays.stream(intArr); 转成int流, 可以求sum max min average()
res = Math.max(res, max);
}
System.out.println(res);
}
}
31 优秀学员统计
java
import java.util.*;
//26 箱子的摆放
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();//员工数量
//sc.nextLine();
int[] nums = new int[30];//30天 每天打卡人数
for (int i = 0; i < 30; i++) {
nums[i] = sc.nextInt();//第i的打卡人数
}
//int[] cnts = new int[n];//下标是id, 大小是打卡次数
//换成用map存 <Integer, int[]> <id, {最早打卡时间, 打卡天数}>
//用map存, <integer, int[2]> 员工工号 - (第一次打卡时间, 打卡数)
HashMap<Integer, int[]> res = new HashMap<>();
for (int i = 0; i < 30; i++) {//循环30天
for(int j = 0; j < nums[i]; j ++ ) {
int id = sc.nextInt();
if(res.containsKey(id)) {//包含这个员工
int[] tmp = res.get(id);
tmp[1] ++;
res.put(id, tmp);
} else {
int[] tmp = new int[2];
tmp[0] = i;
tmp[1] = 1;
res.put(id, tmp);
}
}
}
List<Map.Entry<Integer, int[]>> resList = new ArrayList<>(res.entrySet());
resList.sort(new Comparator<Map.Entry<Integer, int[]>>() {
@Override
public int compare(Map.Entry<Integer, int[]> o1, Map.Entry<Integer, int[]> o2) {
if(o1.getValue()[1] == o2.getValue()[1]) {
return o1.getValue()[0] - o2.getValue()[0];//按照打卡时间 从小到大
} else {
return o2.getValue()[1] - o1.getValue()[1];//按照打卡天数 从大到小
}
}
});
StringBuilder ans = new StringBuilder();
for(int i = 0; i < (Math.min(resList.size(), 5)); i ++ ) {//前五 员工 的 id
ans.append(resList.get(i).getKey()).append(" ");
}
System.out.println(ans.substring(0, ans.length() - 1));
}
}
考的时候写的 救命 紧张了 写的比原来复杂, 不过也是满分
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
/*
11
4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2
0 1 7 10
0 1 6 10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
6 10
7 10
*/
//员工情况 int[]
int n = sc.nextInt();//新员工数量
int[] empls = new int[30];//每天打卡的员工数量
for(int i = 0; i < 30; i ++ ) {
empls[i] = sc.nextInt();
}
int[] cnts = new int[n];//保存员工打卡的数量
int[] first = new int[n];
for(int i = 0; i < 30; i ++ ) {//天数
for(int j = 0; j < empls[i]; j ++ ){
int id = sc.nextInt();//员工编号
if(cnts[id] == 0) first[id] = i;
cnts[id] ++ ;
}
}
//map <员工id, 员工打卡情况int[]{最早打卡时间, 打卡总数}>
HashMap<Integer, int[]> map = new HashMap<>();
for(int i = 0; i < n; i ++ ) {
int days = cnts[i];//每个员工打卡次数
int date = first[i];//最早打卡日期
//i是员工id
int[] ints = new int[2];
ints[0] = date;
ints[1] = days;
map.put(i, ints);
}
ArrayList<Map.Entry<Integer, int[]>> list = new ArrayList<>(map.entrySet());
list.sort(new Comparator<Map.Entry<Integer, int[]>>() {
@Override
public int compare(Map.Entry<Integer, int[]> o1, Map.Entry<Integer, int[]> o2) {
if(o1.getValue()[1] == o2.getValue()[1]) {//打卡次数相同时候
if(o1.getValue()[0] == o2.getValue()[0]) {//打卡时间相同
return o1.getKey() - o2.getKey();//打卡id较小的员工
}
return o1.getValue()[0] - o2.getValue()[0];//较早打卡的员工排在前
}
return o2.getValue()[1] - o1.getValue()[1];//打卡次数
}
});
String res = "";
int len = Math.min(5, list.size());
for(int i = 0; i < len; i ++ ) {
res += list.get(i).getKey();
if(i != len - 1) res += " ";
}
System.out.println(res);
}
}
32 租车骑绿道
java 我写的
import java.util.*;
//32 租车骑绿道
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();//限重m
int n = sc.nextInt();//人数n
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();//每个人的体重
}
Arrays.sort(a);//从小到大排序
int cnt = 0;
int[] flag = new int[n]; //0
//双指针遍历 一个从小到大, 一个从大到小
int i = 0, j = n - 1;
while (i < j) {
//如果和超过限制了
if (a[i] + a[j] > m) {
cnt ++ ;//给最后一个++一辆车
flag[j] = 1;
j--;
}
if (a[i] + a[j] <= m) {
cnt++;//给i和 j 分配 一辆车
flag[i] = 1;
flag[j] = 1;
i++;
j--;
}
}
if(flag[i] == 0) cnt ++;//以防最中间剩下一个 没加上//比如 1 1 2 2 3 4 4 4 5 5, 剩下2
System.out.println(cnt);
}
}
33 相同数字的积木游戏
我写的:
import java.util.*;
import java.util.stream.Stream;
//33 相同数字的积木游戏
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
for(int i = 0; i < n; i ++ ) {
int num = sc.nextInt();
a[i] = num;//存进数组
}
//双指针 一个从前往后遍历 一个从后往前遍历
//结果保存到res
int res = -1;
for(int i = 0; i < n; i ++ ) {
int tmp = a[i];
for(int j = n - 1; j > i; j -- ) {
if(tmp == a[j]) {
res = Math.max(res, j - i);
break;
}
}
}
System.out.println(res);
}
}
考试时候写的 , 救命 一紧张又写复杂了
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
HashMap<Integer, List<Integer>> map = new HashMap<>();//存<数字, 位置int>
for(int i = 0 ; i < n; i ++ ) {
int tmp = sc.nextInt();
if(map.containsKey(tmp)) {
List<Integer> list = map.get(tmp);
list.add(i);
map.put(tmp, list);
} else {
ArrayList<Integer> list = new ArrayList<>();
list.add(i);
map.put(tmp, list);
}
}
boolean flag = true;
int ans = -1;
for(Map.Entry<Integer, List<Integer>> entry : map.entrySet()) {
List<Integer> list = entry.getValue();
if(list.size() > 1) {
flag = false;
int res = 0;
int len = list.size();
for(int i = 0; i < len - 1; i ++ ) {
for(int j = i + 1; j < len; j ++ ) {
//遍历 得到一个数字的最大距离
res = Math.max(res, list.get(j) - list.get(i));
}
}
//每个数字的最大距离都更新
ans = Math.max(res, ans);
}
}
System.out.println(ans);
}
}
java满分答案:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = in.nextInt();
int[] arr = new int[num];
for(int i=0;i<num;i++){
arr[i] = in.nextInt();
}
int max=-1;
for(int i=0;i<num;i++){
for(int j=i+1;j<num;j++){
if(arr[i]==arr[j]){
max = Math.max(max,j-i);
}
}
}
System.out.println(max);
}
}
34工作安排
01背包问题
f[i][j]表示只考虑前i个物品, 总体不超过j的情况下, 总价值最大是多少
状态转移 f[i][j]
1.不选第i个物品: f[i][j] = f[i - 1][j]
2.选第i个物品: f[i][j] = f[i - 1][j - v[i]] + w[i]
装不下的时候 f[i][j] = f[i - 1][j] (这个情况是一定存在的
能装下的时候, 可以选或者不选, f[i][j] = max(第一种情况, 第二种情况) (这个情况不一定存在 要判断)
f[0][0] = 0 默认0 初始化不需要写了
c++ 代码
#include <iostream>
#include <algorithm>
using namespace std;
//01背包 二维数组做法
const int N = 1010;
int n, m; // 物品数量, 背包容量
int v[N], w[N]; // 体积 价值
int f[N][N]; // f[i][j], 前 i 个物品中体积不超过 j 的最大价值
int main()
{
cin >> m >> n;// 输入物品数量n, 背包容量m
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i] ;//输入背包内所有东西的体积和价值
for (int i = 1; i <= n; i++) // 物品数量<n
for (int j = 0; j <= m; j++) // 背包
{
// 当前背包容量装不下第 i 个物品, 则价值等于前 i-1 个物品
f[i][j] = f[i - 1][j];
// 当前背包容量能装下第 i 个物品, 选择是否装第 i 个物品, 取较大的那个结果
if (j >= v[i]) f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
}
cout << f[n][m] << endl;
return 0;
}
c++ 一维数组做法:
#include <iostream>
#include <algorithm>
using namespace std;
//01背包 一维数组做法
const int N = 1010;
int n, m; // 物品数量, 背包容量
int v[N], w[N]; // 体积 价值
int f[N]; // 最大价值
int main()
{
cin >> m >> n;// 输入物品数量, 背包容量
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];//输入背包内所有东西的体积和价值
for (int i = 1; i <= n; i++) // 物品数量<n
for (int j = m; j >= v[i]; j--) // 背包
f[j] = max(f[j], f[j - v[i]] + w[i]);//max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
cout << f[m] << endl;
return 0;
}
35 预定酒店
java
import java.util.*;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strs = sc.nextLine().split(" ");
int n = Integer.parseInt(strs[0]);
int k = Integer.parseInt(strs[1]);
int x = Integer.parseInt(strs[2]);
Integer[] integers =
Arrays.stream(sc.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);
ArrayList<int[]> list = new ArrayList<>();
for(int i = 0; i < n; i ++ ) {
Integer price = integers[i];
int[] ints = new int[2];
ints[0] = price;
ints[1] = Math.abs(x - price);//距离价格的绝对值
list.add(ints);
}
//排序 按照绝对值 和 价格大小
list.sort(((o1, o2) -> {
if (o1[1] == o2[1]) {//比较二者
return o1[0] - o2[0];//如果绝对值相同 比比较数字大小 取较小的
} else {
return o1[1] - o2[1];//如果绝对值不同, 先按绝对值比较, 取绝对值小的
}
}));
//把前k个结果保存到结果数组
ArrayList<Integer> res = new ArrayList<>();
//输出前k个
for(int i = 0; i < k; i ++ ) {
int i1 = list.get(i)[0];
res.add(i1);
}
//按照值排序
Collections.sort(res);
for(int i = 0; i < k; i ++ ) {
System.out.print(res.get(i));
if(i != k - 1) System.out.print(" ");
}
// 参考答案中去除最后一个空格的方法:
// StringBuilder sb = new StringBuilder();
// for (int i = 0; i < res.size(); i++) {
// sb.append(res.get(i)).append(" ");
// }
//
// System.out.println(sb.deleteCharAt(sb.length()-1));
}
}
36 学校的位置
给学生家排序, 如果个数是奇数, 就在中间位置的学生家
如果是偶数, 就在中间两个位置的学生家之间, 题意要求输出较小的位置, 就是中间两个位置中靠左的那一个
这个用c++写更简单, java的话位移要加括号, 否则会报错
import java.util.*;
//学校的位置
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] sites = new int[n];
for(int i = 0; i < n; i ++ ) {
sites[i] = sc.nextInt();//存储家庭的位置
}
//排序
Arrays.sort(sites);
int res;
if(n % 2 == 0) {
res = sites[(n >> 1) - 1];
} else {
res = sites[(n - 1) >> 1];
}
System.out.println(res);
}
}
37 寻找密码
import java.util.*;
//37 寻找密码
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
HashSet<String> set = new HashSet<>();
set.addAll(Arrays.asList(strings));
String str = "";//结果字符串
for (String string : strings) {
if (check(set, string)) {
if (string.length() > str.length()) {
str = string;
}
if (string.length() == str.length() && string.compareTo(str) > 0) {
str = string;
}
}
}
System.out.println(str);
}
public static boolean check(Set<String> set, String str) {
String tmp = str;
boolean flag = true;
//最大的密码就是 str str缩短 查询set的子集就好了
for(int i = str.length() - 1; i > 0; i -- ) {
tmp = str.substring(0, i);
if(!set.contains(tmp)) flag = false;
}
return flag;
}
}
38 寻找关键钥匙
import java.util.*;
//38 寻找关键钥匙
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String key = sc.nextLine();
String[] boxes = sc.nextLine().split(" ");
for(int i = 0; i < boxes.length; i ++ ) {
String str = "";//保存待比较的字符串
for(int j = 0; j < boxes[i].length(); j ++ ) {
char c = boxes[i].charAt(j);
c = Character.toLowerCase(c);
if(c >= 'a' && c <= 'z') str += c;
}
//str = str.toLowerCase();//或者这么写 字符串转换
char[] chars = str.toCharArray();//每个box转成 char数组
Arrays.sort(chars);
if(String.valueOf(chars).equals(key)) {
System.out.println(i + 1);
return;
}
}
System.out.println("-1");
}
}
39 查找充电设备组合 TODO
java
import java.util.*;
//39 查找充电设备组合
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
ArrayList<Integer> list = new ArrayList<>();//存储充电设备的集合
for(int i = 0; i < n; i ++ ) {
list.add(sc.nextInt());
}
int p_max = sc.nextInt();//最大功率
int max = 0;//结果数组里的最大功率
HashSet<Integer> res = new HashSet<>();
res.add(0);//存一个0
for(Integer num : list){
HashSet<Integer> tmps = new HashSet<>();//每一次遍历的临时数组
for(Integer power : res) {//循环一遍每个结果
int new_p = power + num;
if(new_p <= p_max) {
tmps.add(new_p);//做临时数组来存, 否则会改变遍历的情况
max = Math.max(new_p, max);
}
}
res.addAll(tmps);
}
System.out.println(max);
}
}
40 知识图谱新词挖掘
import java.util.*;
//39 查找充电设备组合
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String content = sc.nextLine();
String word = sc.nextLine();
int len_c = content.length();
int len_w = word.length();
char[] words = word.toCharArray();
Arrays.sort(words);//排序后
int count = 0;
for(int i = 0; i < len_c - len_w + 1; i ++ ) {
String new_word = content.substring(i, len_w + i);
char[] new_words = new_word.toCharArray();
Arrays.sort(new_words);
if(String.valueOf(new_words).equals(String.valueOf(words))) {
count ++;
}
}
System.out.println(count);
}
}
41 静态代码扫描服务
java
记得换行的时候要 sc.NextLine(); !!!!!
import java.util.*;
//39 查找充电设备组合
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();//缓存一个报告的金币数m
sc.nextLine();//换行了!!!!!
String[] nums = sc.nextLine().split(" ");//标识序列
String[] sizes = sc.nextLine().split(" ");//每个文件的大小
HashMap<Integer, Integer> numsMap = new HashMap<>();//存储 标识 - 个数
HashMap<Integer, Integer> sizeMap = new HashMap<>();//存储 标识 - 大小
//把两个map存好
for(int i = 0; i < nums.length; i ++ ) {
int num = Integer.parseInt(nums[i]);
int size = Integer.parseInt(sizes[i]);
if(numsMap.containsKey(num)) {
numsMap.put(num, numsMap.get(num) + 1);
} else {
numsMap.put(num, 1);
sizeMap.put(num, size);
}
}
int res = 0;
for(Map.Entry<Integer, Integer> map : numsMap.entrySet()) {
Integer key = map.getKey();//标识
Integer value = map.getValue();//文件个数
Integer size = sizeMap.get(key);//文件大小(扫描一次的成本价格)
int save = 0;
int noSave = 0;//每个标识文件 的 存和不存的需要金币数
save = m + size;//缓存一个报告的金币数m + 扫描的成本(文件大小)
noSave = value * size;//不缓存, 每次都扫描, 大小 * 个数
res += Math.min(save, noSave);
}
System.out.println(res);
}
}
42 不爱施肥的小布
java:
这个向上取整没整明白 ceil为啥没取到呢, 换了朴素写法
import java.util.*;
//42
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();//m个果林
int n = sc.nextInt();//n天
int[] fields = new int[m];
for(int i = 0; i < m; i ++ ) {
fields[i] = sc.nextInt();
}
Arrays.sort(fields);
int k = 0;
int cnt = 0;
int res = 0;
for(int i = 0; i < m; i ++ ) {
k = fields[i];
cnt += i + 1;//前i个都可以1天完成
for(int j = i + 1; j < m; j ++ ) {
int days = fields[j] / k;
if(fields[j] % k != 0) {
days ++ ;
}
// int days = (int) Math.ceil(fields[j] / k);//向上取整
cnt += days;
}
if(cnt <= n) {
System.out.println(k);
return;
}
cnt = 0;
}
System.out.println("-1");
}
}
44 新员工座位安排系统
我写的
import java.util.*;
//44 新员工座位安排
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
int n = strings.length;
int[] a = new int[n];
boolean flag = false;
ArrayList<Integer> indexes = new ArrayList<>();
for(int i = 0; i < n; i ++ ) {
a[i] = Integer.parseInt(strings[i]);
if(a[i] == 0) {
flag = true;//只要有0 就改为true
indexes.add(i);//存入0点的下标
}
}
if(!flag) {
System.out.println(0);
return;
}
int res = 0;
int tmp = 0;//当前的友好值
//0点所在的下标
for (Integer index : indexes) {//枚举每个0点
if (index != 0) {
int l = index - 1;
while (a[l] == 1) {
tmp++;
if (l == 0) break;
l--;
}
}
if (index != n - 1) {
int r = index + 1;
while (a[r] == 1) {
tmp++;
if (r == n - 1) break;
r++;
}
}
res = Math.max(res, tmp);
tmp = 0;
}
System.out.println(res);
}
}
45 光伏场地建设规划
java
import java.util.Scanner;
//45 光伏场地建设规划
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
int row = Integer.parseInt(strings[0]);
int col = Integer.parseInt(strings[1]);
int n = Integer.parseInt(strings[2]);
int min = Integer.parseInt(strings[3]);//最低发电量
int[][] a = new int[row][col];
for(int i = 0; i < row; i ++ ) {
for(int j = 0; j < col; j ++ ) {
a[i][j] = sc.nextInt();
}
}
if(col < n || row < n) {
System.out.println("0");
return;
}
int[][] area = new int[n][n];
int sum = 0;
int res = 0;
for(int k = 0; k < row - n + 1; k ++ ) {
for(int p = 0; p < col - n + 1; p ++ ) {//遍历所有起始点的位置
for (int i = 0; i < n; i++) {//正方形内的值
for (int j = 0; j < n; j++) {
area[i][j] = a[i + k][j + p];//相对地址 +k +p
sum += area[i][j];
}
}
if(sum >= min) res ++;
sum = 0;
}
}
System.out.println(res);
}
}
java
import java.util.Scanner;
//45 光伏场地建设规划
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
int row = Integer.parseInt(strings[0]);
int col = Integer.parseInt(strings[1]);
int n = Integer.parseInt(strings[2]);
int min = Integer.parseInt(strings[3]);//最低发电量
int[][] a = new int[row][col];
for(int i = 0; i < row; i ++ ) {
for(int j = 0; j < col; j ++ ) {
a[i][j] = sc.nextInt();
}
}
if(col < n || row < n) {
System.out.println("0");
return;
}
int count = (col - n + 1) * (row - n + 1);//总数是这些
int[][] area = new int[n][n];
int sum = 0;
for(int k = 0; k < row - n + 1; k ++ ) {
for(int p = 0; p < col - n + 1; p ++ ) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
area[i][j] = a[i + k][j + p];
sum += area[i][j];
}
}
if(sum < min) count --;//不满足的减掉
sum = 0;
}
}
System.out.println(count);
}
}
46 微服务的集成测试 dfs
java
import java.util.*;
//微服务的集成测试
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] useTime = new int[n][n];
for(int i = 0; i < n; i ++ ) {
for(int j = 0; j < n; j ++ ) {
useTime[i][j] = sc.nextInt();
}
}
int k = sc.nextInt();//待计算 的 服务 k
int cnt = 0;
cnt = dfs(useTime, k - 1);
System.out.println(cnt);
}
public static int dfs(int[][] useTime, int k) {
int max = 0;
// 计算启动服务k的时间
//遍历k的一行数据, 得到它依赖的服务器, 获得启动时间
for(int j = 0; j < useTime.length; j ++ ) {
int tmp = useTime[k][j];
if(tmp != 0 && j != k ) {
max = Math.max(max, dfs(useTime, j));
}
}
return max + useTime[k][k];//依赖的加载时间 max + 自身的加载时间
}
}
47 字符串重新排序
java
import java.util.*;
//微服务的集成测试
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] strings = sc.nextLine().split(" ");
HashMap<String, Integer> map = new HashMap<>();
for(int i = 0; i < strings.length; i ++ ) {
String key = arrange(strings[i]);//单词字典序
map.put(key, map.getOrDefault(key, 0) + 1);//map存储 单词和出现次数
}
ArrayList<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
list.sort(new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
if(o2.getValue() == o1.getValue()) {//出现次数相同的情况下, 按照单词(key)的长度排序
if(o1.getKey().length() == o2.getKey().length()) {
return o1.getKey().compareTo(o2.getKey());//单词长度相同, 按照字典序升序
}
return o1.getKey().length() - o2.getKey().length();//按照单词长度升序排
}
return o2.getValue() - o1.getValue();//按照出现次数降序排
}
});
for(int i = 0; i < list.size(); i ++ ) {
for(int j = 0; j < list.get(i).getValue(); j ++ ) {
System.out.print(list.get(i).getKey());
if (i != list.size() - 1) System.out.print(" ");
}
}
}
public static String arrange(String str) {//单词内部的字典序
//list可以排字典序
ArrayList<Character> list = new ArrayList<>();
for(int i = 0; i < str.length(); i ++ ) {
list.add(str.charAt(i));
}
list.sort(new Comparator<Character>() {
@Override
public int compare(Character o1, Character o2) {
return o1.compareTo(o2);
}
});
StringBuilder res = new StringBuilder();
for(char c : list) {
res.append(c);
}
return res.toString();
}
}
48 MVP争夺战 TODO 要背
这个有点难, dfs
java
import java.util.*;
//48 MVP争夺战
public class Main {
static int max = -1;
static int min = 51;
static int[] cnt = new int[51];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();//有得分的分钟数 [1,50]
int[] scores = new int[t];
int sum = 0;
for(int i = 0; i < t; i ++ ) {
scores[i] = sc.nextInt();
sum += scores[i];
cnt[scores[i]] ++ ;//得分i 出现几次cnt[i]
}
Arrays.sort(scores);
max = scores[t - 1];//最末尾就是最大值
min = scores[0];//最开头就是最大值
//mvp得分即是 = 总分 / 人数 = 平均分
//最小平均分 数组的最大值
//最大平均分 总分, 即所有都是一个人投中的
// [数组里的最大值, sum / 1]
//按照题意 找最小平均分, 从最小平均分开始遍历, 满足条件则结束
for(int i = max; i <= sum; i ++ ) {
if(sum % i == 0) {//mvp平均分 能被 总分 整除 = mvp人数, 才有意义
dfs(sum / i, 0, i, max);//dfs(总人数, 当前的分数和0, 目标平均分. 枚举位置?)
}
}
System.out.println(sum);
}
public static void dfs(int res, int sum, int target, int p) {
//人数是0了 说明所有人都被遍历过了, 输出结果
if(res == 0) {//表示一种情况结束了
System.out.println(target);
System.exit(0);
}
//当 一个获得的分数sum == 目标平均分target, 遍历其余人
if(sum == target) {
dfs(res - 1, 0, target, max);//下一个
// dfs(人-1, 该人的分0, 目标分target, 继续从最大开始枚举)
return;
}
//i从 最大得分 遍历到 最小得分, 枚举每个数字 选择是否用
for(int i = p; i >= min; -- i) {
//如果这个分数是在原数组中存在的 cnt>0 且加上之后 <= 目标分, 就把该数字用掉
if(cnt[i] > 0 && (i + sum) <= target) {
cnt[i] --;//用到该数字 i
dfs(res, sum + i, target, i);//dfs(还是当前人, 当前人的分数, 目标分, 继续从i枚举);
cnt[i] ++ ;//放回该数字
if(sum == 0 || (sum + i) == target) {
break;
}
}
}
}
}
49 贪心的商人
java
import java.util.*;
//49 贪心的商人
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();//商品种类
int days = sc.nextInt();//天数
int[] v = new int[number];
for(int i = 0; i < number; i ++ ) {
v[i] = sc.nextInt();//商品i的最大持有量 v[i]
}
int[][] w = new int[number][days];//第i个商品 的 第j天的价格
for(int i = 0; i < number; i ++ ) {
for(int j = 0; j < days; j ++ ) {
w[i][j] = sc.nextInt();//
}
}
int tmp = 0;
int res = 0;
for(int i = 0; i < number; i ++ ) {
for(int j = 0; j < days - 1; j ++ ) {
for(int k = j; k < days; k ++ ) {
int sell = w[i][k];
int buy = w[i][j];
tmp = Math.max((sell - buy) * v[i], tmp);//每个商品的最大利润
}
}
res += tmp;
tmp = 0;//换商品的时候置0
}
System.out.println(res);
}
}
50 核酸检测人员安排
java
这也用不到dp 数学退一下就行了
import java.util.*;
//50 核酸检测人员安排
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int c_num = sc.nextInt();//采样员
int z_num = sc.nextInt();//志愿者
int[] k = new int[c_num];
int sum = 0;
for(int i = 0; i < c_num; i ++ ) {
k[i] = sc.nextInt();//每个员工的效率
sum += k[i];
}
Arrays.sort(k);//从小到大 按照效率排序
int res = 0;
//每个都要保证 1个
if(z_num <= c_num) {//志愿者不足 1倍的采样员
//从尾到头遍历 基准效率 60-600 m= 6-60
// 所以分配给个人更好 不需要判断 M > k[i]的情况
for(int i = c_num - 1; i > c_num - z_num - 1; i -- ) {
res += k[i];
}
} //每个保证1个
else if(z_num < c_num * 3) {//志愿者1-3倍 采样员
int left = z_num - c_num;
res = sum;
for(int i = c_num - 1; i > 0; i -- ) {
int m = (int) (k[i] * 0.1);
if(left >= 3) {
res += 3 * m;
left -= 3;
} else {
res += left * m;
left = 0;
}
}
} else { //志愿者>= 3倍采样员的时候
res = (int) (sum * 1.3);
}
System.out.println(res);
}
}