牛客在线编程题目-华为机试-中等
题号 | 题目 | 知识点 | 难度 | 通过率 | |
---|---|---|---|---|---|
HJ16 | 购物单 | 动态规划 | 中等 | 21.21% | |
HJ17 | 坐标移动 | 字符串 | 中等 | 24.79% | |
HJ20 | 密码验证合格程序 | 数组 字符串 模拟 | 中等 | 28.91% | |
HJ24 | 合唱队 | 队列 动态规划 | 中等 | 26.04% | |
HJ26 | 字符串排序 | 字符串 排序 | 中等 | 36.80% | |
HJ27 | 查找兄弟单词 | 中等 | 21.10% | ||
HJ29 | 字符串加解密 | 字符串 模拟 | 中等 | 27.18% | |
HJ32 | 密码截取 | 字符串 动态规划 | 中等 | 29.40% | |
HJ33 | 整数与IP地址间的转换 | 字符串 模拟 | 中等 | 31.95% | |
HJ36 | 字符串加密 | 字符串 | 中等 | 40.82% | |
HJ38 | 求小球落地5次后所经历的路程和第5次反弹的高度 | 模拟 | 中等 | 39.23% | |
HJ41 | 称砝码 | 字符串 哈希 | 中等 | 40.68% | |
HJ43 | 迷宫问题 | 广度优先搜索(BFS) dfs | 中等 | 35.60% | |
HJ45 | 名字的漂亮度 | 字符串 贪心 | 中等 | 39.11% | |
HJ48 | 从单向链表中删除指定值的节点 | 链表 | 中等 | 40.08% | |
HJ50 | 四则运算 | 字符串 栈 基础数学 | 中等 | 57.25% | |
HJ52 | 计算字符串的编辑距离 | 字符串 动态规划 | 中等 | 39.79% | |
HJ55 | 挑7 | 穷举 基础数学 | 中等 | 44.49% | |
HJ57 | 高精度整数加法 | 字符串 | 中等 | 38.26% | |
HJ59 | 找出字符串中第一个只出现一次的字符 | 字符串 | 中等 | 33.40% | |
HJ63 | DNA序列 | 字符串 | 中等 | 42.09% | |
HJ64 | MP3光标位置 | 数组 | 中等 | 30.71% | |
HJ65 | 查找两个字符串a,b中的最长公共子串 | 字符串 | 中等 | 36.03% | |
HJ66 | 配置文件恢复 | 字符串 | 中等 | 42.47% | |
HJ67 | 24点游戏算法 | dfs | 中等 | 36.81% | |
HJ69 | 矩阵乘法 | 数组 | 中等 | 45.17% | |
HJ70 | 矩阵乘法计算量估算 | 字符串 栈 | 中等 | 42.50% | |
HJ71 | 字符串通配符 | 字符串 | 中等 | 29.45% | |
HJ74 | 参数解析 | 字符串 模拟 | 中等 | 35.33% | |
HJ75 | 公共子串计算 | 字符串 动态规划 | 中等 | 40.68% | |
HJ77 | 火车进站 | 栈 | 中等 | 46.09% | |
HJ82 | 将真分数分解为埃及分数 | 基础数学 | 中等 | 42.94% | |
HJ90 | 合法IP | 字符串 链表 栈 队列 | 中等 | 31.01% | |
HJ92 | 在字符串中找出连续最长的数字串 | 字符串 模拟 | 中等 | 31.23% | |
HJ103 | Redraiment的走法 | 排序 | 中等 | 28.84% | |
HJ107 | 求解立方根 | 基础数学 二分 | 中等 | 28.44% |
1.购物单
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
int money = sc.nextInt();
int m = sc.nextInt();
sc.nextLine();
money /= 10;
int[][] prices = new int[m+1][3];
int[][] weights = new int[m+1][3];
for(int i=1; i<= m; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
a /= 10; // price ?
b = b * a;
if (c == 0) {
// 主件
prices[i][0] = a;
weights[i][0] = b;
} else if (prices[c][1] == 0) {
// 附件1
prices[c][1] = a;
weights[c][1] = b;
} else {
// 附件2
prices[c][2] = a;
weights[c][2] = b;
}
sc.nextLine();
}
int[][] dp = new int[m+1][money+1];
for(int i=1; i<=m; i++) {
for(int j=1; j<=money; j++) {
int a = prices[i][0];
int b = weights[i][0];
int c = prices[i][1];
int d = weights[i][1];
int e = prices[i][2];
int f = weights[i][2];
dp[i][j] = j - a >= 0 ? Math.max(dp[i-1][j], dp[i-1][j-a] + b) : dp[i-1][j];
dp[i][j] = j-a-c >= 0 ? Math.max(dp[i][j], dp[i-1][j-a-c] + b + d):dp[i][j];
dp[i][j] = j-a-e >= 0 ? Math.max(dp[i][j], dp[i-1][j-a-e] + b + f):dp[i][j];
dp[i][j] = j-a-c-e >= 0 ? Math.max(dp[i][j], dp[i-1][j-a-c-e] + b +d + f):dp[i][j];
}
}
System.out.println(dp[m][money] * 10);
}
}
}
2.坐标移动
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(";");
int x = 0, y = 0;
for(String s : str) {
// 不满足题目给定坐标规则
if(!s.matches("[WASD][0-9]{1,2}")){
continue;
}
int val = Integer.valueOf(s.substring(1));
switch (s.charAt(0)) {
case 'W':
y += val;
break;
case 'S':
y -= val;
break;
case 'A':
x -= val;
break;
case 'D':
x += val;
break;
}
}
System.out.println(x+","+y);
}
}
3.密码验证合格程序
public class Main{
public static void main(String[] arg){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
String str = sc.next();
if (str.length() <= 8) {
System.out.println("NG");
continue;
}
if (getMatch(str)) {
System.out.println("NG");
continue;
}
if (hasSubStr(str, 0, 3)) {
System.out.println("NG");
continue;
}
System.out.println("OK");
}
}
private static boolean hasSubStr(String str, int l, int r) {
if (r >= str.length()) {
return false;
}
if (str.substring(r).contains(str.substring(l, r))) {
return true;
} else {
return hasSubStr(str, l+1, r+1);
}
}
// 检查是否满足正则
private static boolean getMatch(String str){
int count = 0;
Pattern p1 = Pattern.compile("[A-Z]");
if(p1.matcher(str).find()){
count++;
}
Pattern p2 = Pattern.compile("[a-z]");
if(p2.matcher(str).find()){
count++;
}
Pattern p3 = Pattern.compile("[0-9]");
if(p3.matcher(str).find()){
count++;
}
Pattern p4 = Pattern.compile("[^a-zA-Z0-9]");
if(p4.matcher(str).find()){
count++;
}
if(count >= 3){
return false;
}else{
return true;
}
}
}
4.合唱队
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] arr = new int[n];
for(int i=0; i<n; i++) {
arr[i] = sc.nextInt();
}
int[] left = new int[n]; //存储每个数左边小于其的数的个数
int[] right = new int[n];//存储每个数右边小于其的数的个数
left[0] = arr[0];
right[n - 1] = arr[n-1];
int num[] =new int [n];//记录以i为终点的从左向右和从右向走的子序列元素个数
int index = 1;//记录当前子序列的长度
for(int i=1; i<n; i++) {
if (arr[i] > left[index - 1]) {
//直接放在尾部
num[i] = index;
left[index++] = arr[i];
} else {
int low = 0, high = index - 1;
while(low < high) {
int mid = (low + high) / 2;
if (left[mid] < arr[i]) {
low = mid+1;
} else {
high = mid;
}
}
//将所属位置替换为当前元素
left[low] = arr[i];
//当前位置i的左侧元素个数
num[i] = low;
}
}
index = 1;
for(int i=n-2; i>=0; i--) {
if(arr[i] > right[index - 1]) {
num[i] += index;
right[index++] = arr[i];
} else {
int low = 0, high = index - 1;
while(low < high) {
int mid = (high + low) / 2;
if (right[mid] < arr[i]) {
low = mid + 1;
} else {
high = mid;
}
}
right[low] = arr[i];
num[i] += low;
}
}
int max = 1;
for(int number : num) {
max = Math.max(max,number);
}
System.out.println(n - max);
}
}
}
5.字符串排序
public class Main {
public static String sort(String str) {
// 先将英文字母收集起来
List<Character> letters = new ArrayList<>();
for (char ch : str.toCharArray()) {
if (Character.isLetter(ch)) {
letters.add(ch);
}
}
// 将英文字母先排序好
letters.sort(new Comparator<Character>() {
public int compare(Character a, Character b) {
return Character.toLowerCase(a) - Character.toLowerCase(b);
}
});
// 若是非英文字母则直接添加
StringBuilder sb = new StringBuilder();
for(int i=0, j=0; i < str.length(); i++) {
if (Character.isLetter(str.charAt(i))) {
sb.append(letters.get(j++));
} else {
sb.append(str.charAt(i));
}
}
return sb.toString();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextLine()) {
String str = in.nextLine();
String res = sort(str);
System.out.println(res);
}
}
}
6.查找兄弟单词
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String[] ss = scanner.nextLine().split(" ");
Integer a = Integer.parseInt(ss[0]);
String x = ss[ss.length - 2];
Integer k = Integer.parseInt(ss[ss.length - 1]);
List<String> list = new ArrayList<>();
for (int i = 1; i <= a ; i++) {
if (isBrother(x, ss[i])) {
list.add(ss[i]);
}
}
int size = list.size();
System.out.println(size);
if (size >= k) {
Collections.sort(list);
System.out.println(list.get(k - 1));
}
}
}
public static boolean isBrother(String x, String y) {
if (x.length() != y.length() || y.equals(x)) {
return false;
}
char[] s = x.toCharArray();
char[] j = y.toCharArray();
Arrays.sort(s);
Arrays.sort(j);
return new String(s).equals(new String(j));
}
}
7.字符串加解密
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while(in.hasNext()){
System.out.println(encode(in.nextLine()));
System.out.println(decode(in.nextLine()));
}
}
//加密函数
private static String encode(String code){
char[] t = code.toCharArray(); //将String对象转换为字符数组
for(int i=0; i < t.length; i++){
if(t[i]>='a' && t[i]<'z')
t[i] = (char)(t[i] - 'a' + 'A' + 1);
else if(t[i] == 'z')
t[i] = 'A';
else if(t[i]>='A' && t[i]<'Z')
t[i] = (char)(t[i] - 'A' + 'a' + 1);
else if(t[i] == 'Z')
t[i] = 'a';
else if(t[i]>='0' && t[i]<'9')
t[i] = (char)(t[i]+1);
else if(t[i] == '9')
t[i] = '0';
}
return String.valueOf(t);
}
//解密函数
private static String decode(String password){
char[] t = password.toCharArray();
for(int i=0; i < t.length; i++){
if(t[i]>'a' && t[i]<='z')
t[i] = (char)(t[i] - 'a' + 'A' - 1);
else if(t[i] == 'a')
t[i] = 'Z';
else if(t[i]>'A' && t[i]<='Z')
t[i] = (char)(t[i] - 'A' + 'a' - 1);
else if(t[i] == 'A')
t[i] = 'z';
else if(t[i]>'0' && t[i]<='9')
t[i] = (char)(t[i]-1);
else if(t[i] == '0')
t[i] = '9';
}
return String.valueOf(t);
}
}
8.密码截取
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
System.out.println(solution(s));
}
private static int solution(String s) {
int res = 0;
for(int i = 0; i < s.length(); i++) {
// ABA型
int len1 = longest(s, i, i);
// ABBA型
int len2 = longest(s, i, i + 1);
res = Math.max(res, len1 > len2 ? len1 : len2);
}
return res;
}
private static int longest(String s, int l, int r) {
while(l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
l--;
r++;
}
return r - l - 1;
}
}
9.整数与IP地址间的转换
public class Main {
public static String convert(String str) {
// ipv4 -> int
if (str.contains(".")) {
String[] fields = str.split("\\.");
long result = 0;
for (int i = 0; i < 4; i++) {
result = result * 256 + Integer.parseInt(fields[i]);
}
return "" + result;
}
// int -> ipv4
long ipv4 = Long.parseLong(str);
String result = "";
for (int i = 0; i < 4; i++) {
result = ipv4 % 256 + "." + result;
ipv4 /= 256;
}
return result.substring(0, result.length() - 1);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String str = in.next();
String res = convert(str);
System.out.println(res);
}
}
}
10.字符串加密
public class Main{
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s1 = sc.nextLine().toUpperCase();
String s2 = sc.nextLine();
char[] chars1 = s1.toCharArray();
char[] chars2 = s2.toCharArray();
LinkedHashSet<Character> set = new LinkedHashSet();
for (int i = 0; i < chars1.length; i++) {
set.add(chars1[i]);
}
int k = 0;
while (set.size() < 26) {
char a = (char) ('A' + k);
set.add(a);
k++;
}
ArrayList<Character> list = new ArrayList<>(set);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < chars2.length; i++) {
if (chars2[i] == ' ') {
sb.append(chars2[i]);
} else if (chars2[i] < 'a') {
int n = (int) (chars2[i] - 'A');
char c = list.get(n);
sb.append(c);
} else {
int n = (int) (chars2[i] - 'a');
char c = (char)(list.get(n)+'a'-'A');
sb.append(c);
}
}
System.out.println(sb.toString());
}
}
}
11.求小球落地5次后所经历的路程和第5次反弹的高度
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
double h = Double.parseDouble(sc.nextLine());
double tmp = h / 2;
for(int i=1; i<5; i++) {
h += tmp * 2;
tmp /= 2;
}
System.out.println(h);
System.out.println(tmp);
}
}
}
12.称砝码
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) { // 注意 while 处理多个 case
HashSet<Integer> set = new HashSet<>();//存放所有可能的结果,不用担心重复问题
set.add(0);//初始化为0
int n = in.nextInt();//个数
int[] w = new int[n];
int[] nums = new int[n];
for(int i=0;i<n;i++){
w[i] = in.nextInt();//砝码的重量
}
for(int i=0;i<n;i++){
nums[i] = in.nextInt();//砝码个数
}
for(int i=0;i<n;i++){//遍历砝码
ArrayList<Integer> list = new ArrayList<>(set);//取当前所有的结果
for(int j=1;j<=nums[i];j++){//遍历个数
for(int k=0;k<list.size();k++){
set.add(list.get(k) + w[i] * j);
}
}
}
System.out.println(set.size());
}
}
}
13.迷宫问题
// 题目已经提示了【迷宫只有一条通道】,则直接使用 DFS 找路径就行了,如果有多条路径找最短考虑使用 BFS
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt();
int m = in.nextInt();
// 构造迷宫
int[][] map = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = in.nextInt();
}
}
// 路径存储的数组
List<Pos> path = new ArrayList<>();
// DFS 搜索路径
dfs(map, 0, 0, path);
// 输出
for (Pos p : path) {
System.out.println("(" + p.x + "," + p.y + ")");
}
}
}
// 返回值 标记是否找到可通行的路劲
public static boolean dfs(int[][] map, int x, int y, List<Pos> path) {
// 添加路径并标记已走
path.add(new Pos(x, y));
map[x][y] = 1;
// 结束标志
if (x == map.length - 1 && y == map[0].length - 1) {
return true;
}
// 向下能走时
if (x + 1 < map.length && map[x + 1][y] == 0) {
if (dfs(map, x + 1, y, path)) {
return true;
}
}
// 向右能走时
if (y + 1 < map[0].length && map[x][y + 1] == 0) {
if (dfs(map, x, y + 1, path)) {
return true;
}
}
// 向上能走时
if (x - 1 > -1 && map[x - 1][y] == 0) {
if (dfs(map, x - 1, y, path)) {
return true;
}
}
// 向左能走时
if (y - 1 > -1 && map[x][y - 1] == 0) {
if (dfs(map, x, y - 1, path)) {
return true;
}
}
// 回溯
path.remove(path.size() - 1);
map[x][y] = 0;
return false;
}
// 简单的位置类
public static class Pos {
int x;
int y;
public Pos(int x, int y) {
this.x = x;
this.y = y;
}
}
}
14.名字的漂亮度
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int n = in.nextInt();
for (int i = 0; i < n; i++) {
// 读取到空白符就结束
String str = in.next();
int s[] = new int[128];
for (int j = 0; j < str.length(); j++) {
s[str.charAt(j)]++;
}
Arrays.sort(s);
int mul = 26, sum = 0;
for (int j = s.length - 1; j >= 0 && s[j] > 0; j--) {
sum += s[j] * mul;
mul--;
}
System.out.println(sum);
}
}
}
}
15.从单向链表中删除指定值的节点
public class Main {
static class ListNode {
int val;
ListNode next;
static ListNode head;
ListNode(int val) {
this.val = val;
this.next = null;
head = this;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
public ListNode getNode(int val) {
ListNode p = head;
while (p.val != val) {
p = p.next;
}
return p;
}
public void insert(int data) {
this.next = new ListNode(data, this.next);
}
public void delete(int node) {
ListNode dummy = new ListNode(0, head);
ListNode p = dummy;
while (p.next != null && p.next.val != node) {
p = p.next;
}
if (p.next != null) {
p.next = p.next.next;
}
head = dummy.next;
}
public void print() {
ListNode p = head;
while (p != null) {
System.out.print(p.val + " ");
p = p.next;
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int n = Integer.parseInt(in.next());
int val = Integer.parseInt(in.next());
ListNode listHead = new ListNode(val);
for (int i = 1; i < n; i++) {
val = Integer.parseInt(in.next());
int existNodeVal = Integer.parseInt(in.next());
ListNode p = listHead.getNode(existNodeVal);
p.insert(val);
}
val = Integer.parseInt(in.next());
listHead.delete(val);
listHead.print();
}
}
}
16.四则运算
解法1:利用栈
用o1和o2来储存当前符号,具体定义为:
+号时o1=1; -号时o1=-1
*号时o2=1, /号时o2=-1
通过表达式res=num1+o1×num2来保存当前算式,其中num1为已经计算部分的值,而num2是正在计算部分的值,num1和num2中间由±隔开,其中num2正在通过×/计算出结果
当遇到数字时,我们直接获取数字,并且计算o2,获得num2
当遇到±时,代表前面的公式已经计算完毕,计算num1,并更新o1,o2,num2
当遇到×/时,需要对num2进行更新
当遇到左括号时,我们要把现在所有结果入栈,并且重置参数
当遇到右括号时,我们要获得当前数字来更新num2
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
int res = calc(line);
System.out.println(res);
}
private static int calc(String line) {
int len = line.length();
int num1 = 0;
int o1 = 1;
int num2 = 1;
int o2 = 1;
Stack<Integer> stk = new Stack<>();
for (int i = 0; i < len; i++) {
char c = line.charAt(i);
if (Character.isDigit(c)) { //遇到数字则定义num2
int cur = 0;
while (i < len && Character.isDigit(line.charAt(i))) {
cur = cur * 10 + (line.charAt(i) - '0');
i++;
}
i--;
num2 = o2 == 1 ? num2 * cur : num2 / cur;
} else if (c == '*' || c == '/') { //遇到×÷定义o2
o2 = c == '*' ? 1 : -1;
} else if (c == '(' || c == '{' || c == '[') { //遇到括号则保存当前结果,并初始化
stk.push(num1);
stk.push(o1);
stk.push(num2);
stk.push(o2);
num1 = 0;
o1 = 1;
num2 = 1;
o2 = 1;
} else if (c == '+' || c == '-') { //遇到加减,说明可以开始计算,计算num1并对定义其他几个变量
if (c == '-' && (i == 0 || line.charAt(i - 1) == '(' || line.charAt(i - 1) == '[' || line.charAt(i - 1) == '{')) {
o1 = -1;
continue;
}
num1 = num1 + o1 * num2;
o1 = (c == '+' ? 1 : -1);
num2 = 1;
o2 = 1;
} else { //遇到右括号,则出栈,并计算num2
int cur = num1 + o1 * num2;
o2 = stk.pop();
num2 = stk.pop();
o1 = stk.pop();
num1 = stk.pop();
num2 = o2 == 1 ? num2 * cur : num2 / cur;
}
}
return num1 + o1 * num2;
}
}
解法2: 逆波兰表达式
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
List<String> infix = expressionToList(line); // List
List<String> suffix = infixToSuffix(infix); // 中缀转后缀
Stack<String> stk = new Stack<>(); // 存储中间结果
// 逆波兰计算器
for (int i = 0; i < suffix.size(); i++) {
String curr = suffix.get(i);
if (isOper(curr)) {
String num2 = stk.pop();
String num1 = stk.pop();
String reuslt = cal(num1, curr, num2);
stk.push(reuslt);
} else { // 数字直接入栈
stk.push(curr);
}
}
System.out.println(stk.pop());
}
public static String cal(String num1, String oper, String num2) {
Long result = 0l;
Long a = Long.parseLong(num1);
Long b = Long.parseLong(num2);
switch (oper) {
case "+":
result = a + b;
break;
case "-":
result = a - b;
break;
case "*":
result = a * b;
break;
case "/":
result = a / b;
break;
}
return String.valueOf(result);
}
public static List<String> infixToSuffix(List<String> infix) {
List<String> suffix = new ArrayList<>();
Stack<String> stack1 = new Stack<>(); // 只用于保存操作符
Stack<String> stack2 = new Stack<>(); // 用于保存中间结果
for (int i = 0; i < infix.size(); i++) {
String tmp = infix.get(i);
if (isOper(tmp)) { // 操作符要根据情况来入栈 1
if (stack1.isEmpty() || "(".equals(tmp) || "[".equals(tmp) || "{".equals(tmp)) {
// 如果 stack1 是空的,或者 tmp 是左括号,直接入栈
stack1.push(tmp);
} else { // stack1 不是空的,且 tmp 不是左括号
if (")".equals(tmp) || "]".equals(tmp) || "}".equals(tmp)) {
// tmp 是右括号,则把 stack1 遇到左括号之前,全部倒入 stack2
while (!("(".equals(stack1.peek()) || "[".equals(stack1.peek()) || "{".equals(stack1.peek()))) {
stack2.push(stack1.pop());
}
stack1.pop(); // 丢掉左括号
} else {
// tmp 是 +-*/ 其中之一
while (!stack1.isEmpty() && priority(stack1.peek()) >= priority(tmp)) {
// 在 tmp 能够碾压 stack1 的栈顶操作符之前,把 stack1 的栈顶操作符倒入 stack 2 中
stack2.push(stack1.pop());
}
// 离开 while 时,要么 stack1 已经倒空了,要么就是现在 tmp 可以压住 stack.peek() 了
stack1.push(tmp);
}
}
} else { // 操作数直接入栈 2
stack2.push(tmp);
}
}
// stack1 剩余操作符全部倒入 stack2
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
// stack2 的逆序才是结果,所以要再倒一次
while (!stack2.isEmpty()) {
stack1.push(stack2.pop());
}
// 现在 stack1 的元素倒出来的顺序就是后缀表达式
while (!stack1.isEmpty()) {
suffix.add(stack1.pop());
}
return suffix;
}
public static List<String> expressionToList(String expression) {
List<String> list = new ArrayList<>();
int len = expression.length();
String keepNum = "";
for (int i = 0; i < len; i++) {
char c = expression.charAt(i);
if (Character.isDigit(c)) {
if (i != len - 1 && Character.isDigit(expression.charAt(i + 1))) {
// 如果下一个字符也是数字
keepNum += c;
} else {
// 当前是最后一个字符,或者下一个开始不是数字
keepNum += c;
list.add(keepNum);
keepNum = "";
}
}else if(c == '-'){
if(i==0 || expression.charAt(i-1)=='(' || expression.charAt(i-1)=='[' || expression.charAt(i-1)=='{'){
keepNum += c;
}else{
list.add(c + "");
}
}else{
list.add(c + "");
}
}
return list;
}
public static boolean isOper(String str) {
return "+".equals(str) || "-".equals(str) || "*".equals(str) || "/".equals(str) ||
"(".equals(str) || ")".equals(str) || "[".equals(str) || "]".equals(str) ||
"{".equals(str) || "}".equals(str);
}
public static int priority(String oper) {
if ("+".equals(oper) || "-".equals(oper)) {
return 0;
} else if ("*".equals(oper) || "/".equals(oper)) {
return 1;
} else {
return -1;
}
}
}
17.计算字符串的编辑距离
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str1 = sc.nextLine();
String str2 = sc.nextLine();
System.out.println(stringDistance(str1.toCharArray(),str2.toCharArray()));
}
}
private static int stringDistance(char[] a, char[] b) {
int[][] len = new int[a.length + 1][b.length + 1];
for (int i = 0; i < len.length; i++) {
len[i][0] = i;
}
for (int j = 0; j < len[0].length; j++) {
len[0][j] = j;
}
for (int i = 1; i < len.length; i++) {
for (int j = 1; j < len[0].length; j++) {
if (a[i - 1] == b[j - 1]) {
len[i][j] = len[i - 1][j - 1];
} else {
len[i][j] = Math.min(Math.min(len[i - 1][j], len[i - 1][j - 1]), len[i][j - 1]) + 1;
}
}
}
return len[len.length - 1][len[0].length - 1];
}
}
18.挑7
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int sum = 0;
for (int i = 1; i <= n; i++) {
if (i % 7 == 0) {
sum++;
} else {
String s = String.valueOf(i);
if (s.contains("7")) {
sum++;
}
}
}
System.out.println(sum);
}
}
}
19.高精度整数加法
解法1:用BigInteger
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
String s1 = scan.next();
String s2 = scan.next(); //输入两个数
BigInteger a = new BigInteger(s1); //将字符串转成大整数
BigInteger b = new BigInteger(s2);
System.out.println(a.add(b)); //大整数相加
}
}
}
解法2:遍历字符相加
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
String s1 = scan.next();
String s2 = scan.next(); //输入两个数
String res = add(s1, s2); //输出
System.out.println(res);
}
}
private static String add(String s1, String s2) { //两个字符串整数相加
StringBuilder res = new StringBuilder();
int n = s1.length() - 1;
int m = s2.length() - 1;
int carry = 0; //进位
while (n >= 0 || m >= 0) { //从两个人字符串最后一位开始相加
char c1 = n >= 0 ? s1.charAt(n--) : '0'; //没有了就用0代替
char c2 = m >= 0 ? s2.charAt(m--) : '0';
int sum = (c1 - '0') + (c2 - '0') + carry; //两个数子与进位相加
res.append(sum % 10); //余数添加进结果
carry = sum / 10; //进位
}
if (carry == 1) { //最后的进位
res.append(carry);
}
return res.reverse().toString(); //反转后转成字符串
}
20.找出字符串中第一个只出现一次的字符
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()){
//设置信号量
boolean flag = false;
String str = sc.nextLine();
for(int i = 0; i < str.length(); i++){
//判断每个字符是否出现第二次,如果存在,设置信号量signal为1;
if(str.indexOf(str.charAt(i)) == str.lastIndexOf(str.charAt(i))){
System.out.print(str.charAt(i));
flag = true;
break;
}
}
//判断信号,证明不存在重复字符
if(!flag){
System.out.println(-1);
}
System.out.println();
}
}
}
21.DNA序列
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String in = "";
while ((in = br.readLine()) != null) {
int window = Integer.parseInt(br.readLine());
int num = 0;
int max = num;
int left = 0;
for(int i = 1; i <= in.length() - window; i++) {
char pre = in.charAt(i - 1);
char nex = in.charAt(i + window - 1);
if(pre == 'G' || pre == 'C') num--;
if(nex == 'G' || nex == 'C') num++;
if(num > max) {
max = num;
left = i;
}
}
System.out.println(in.substring(left, left + window));
}
}
}
22.MP3光标位置
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
String cmd = sc.next();
parseCmd(cmd, n);
}
}
public static void parseCmd(String commands, int n) {
// 页面的起始位置
int start = 1;
// 页面的末位置
int end = Math.min(n, 4);
// 光标的位置, 三个位置都是从1开始
int index = 1;
for(int i = 0; i < commands.length(); i++) {
// 根据向上移动和向下移动的公式,光标位置的变化
if(commands.charAt(i) == 'U') {
index = (index-1-1+n) % n + 1;
} else if(commands.charAt(i) == 'D') {
index = index % n + 1;
}
// 判断滑动窗口的位置是否需要改变
if(index < start) {
// 光标在窗口之上
start = index;
end = start + 3;
} else if(index > end){
// 光标在窗口之下
end = index;
start = end - 3;
}
}
// 输出窗口内容
for(int i = start; i <= end; i++) {
System.out.print(i + " ");
}
System.out.println();
// 打印当前光标
System.out.println(index);
}
}
23.最长公共子串
public static String commonStr(String shortStr, String longStr){
//计算最长子串
String result;
if(longStr.contains(shortStr)) {
return result = shortStr;
}
int len = shortStr.length() -1; //从短字符串的 length-1开始遍历
for(int i =0; i<shortStr.length(); i++) {
if(i+ len <= shortStr.length()) { //子串末尾不能超出short长度
result = shortStr.substring(i, i+len);
if(longStr.contains(result))
return result;
} else {
len--;
i = -1;
}
}
//所有长度遍历
return null;
}
24.配置文件恢复
import java.util.*;
import java.io.*;
public class Main {
private static HashMap <String, String> map = new HashMap<>();
static {
map.put("reset", "reset what");
map.put("reset board", "board fault");
map.put("board add", "where to add");
map.put("board delete", "no board at all");
map.put("reboot backplane", "impossible");
map.put("backplane abort", "install first");
}
private static ArrayList <String> list = null;//存放每行命令最终匹配的可能性 结果
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = "";
while ((input = br.readLine() ) != null) {
System.out.println(solve(input));
}
}
//判断 map里的每一条指令 是否匹配input
private static String solve(String input) {
list = new ArrayList<>();//每行重置 一次 list
int count = 0;
//遍历 map
for(String key : map.keySet()) {
if (compare(input, key)) {
count++;
}
}
//如果有 多个匹配结果 返回 失败
if (count > 1 || count == 0) {
return "unknown command";
} else {
return list.get(0);//只有一个结果 返回这个命令的唯一 执行结果
}
}
//对一行命令 进行处理
private static boolean compare(String input, String command) {
String[] inputArray = input.split(" "); //举例 res bo
String[] commandAarray = command.split(" ");//举例 reset board
if (inputArray.length != commandAarray.length) {
return false; //命令的 输入 参数数量 不一致 这个命令一定不匹配
}
//比较一位
//以 输入的命令 为主 进行遍历 输入逐位匹配成功即成功
for (int i = 0; i < inputArray.length; i++) {
if (!comparePlus(inputArray[i], commandAarray[i])) {
return false;
}
}
list.add(map.get(command));//将成功的 执行结果 加入 list
return true;
}
//一行命令里 的一位里的 逐位比较
private static boolean comparePlus(String input, String command) {
//以 输入的命令 为主 进行遍历 输入逐位匹配成功即成功
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) != command.charAt(i)) {
return false;
}
}
return true;
}
}
25.24点游戏算法
public class Main{
static int[] nums = new int[4];
static boolean[] visit = new boolean[4];
static int flag = 0;
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String[] a = in.nextLine().split(" ");
for(int i = 0; i < 4; i ++)
nums[i] = Integer.parseInt(a[i]);
dfs(0, 0);
System.out.println( flag == 1 );
}
}
// tmp是前面n个数字运算结果,u表示已经使用了多少个数字
static boolean dfs(int u,float target){
// 递归终止条件:已经使用了数组四个元素,同时结果为24,满足题意
if(target == 24 && u == 4){
flag = 1;
return true;
}
for(int i = 0; i < 4; i ++){
if(visit[i] == false){
visit[i] = true;
// 加减乘除当前数字num[i]
if( dfs(u + 1, target + nums[i]) ||
dfs(u + 1, target - nums[i]) ||
dfs(u + 1,target * nums[i]) ||
dfs(u + 1, target / nums[i])){
return true;
}
// 相当于回溯
visit[i] = false;
}
}
return false;
}
}
26.矩阵乘法
public class Main {
public static int[][] mul(int[][] mat1, int [][]mat2) {
int x = mat1.length, y = mat2.length, z = mat2[0].length;
int[][] res = new int[x][z];
for (int i = 0; i < x; i++) {
for (int j = 0; j < z; j++) {
for (int k = 0; k < y; k++) {
res[i][j] += mat1[i][k] * mat2[k][j];
}
}
}
return res;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int x = in.nextInt(), y = in.nextInt(), z = in.nextInt();
int[][] mat1 = new int[x][y];
int[][] mat2 = new int[y][z];
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
mat1[i][j] = in.nextInt();
}
}
for (int i = 0; i < y; i++) {
for (int j = 0; j < z; j++) {
mat2[i][j] = in.nextInt();
}
}
int[][] res = mul(mat1, mat2);
for (int i = 0; i < x; i++) {
for (int j = 0; j < z; j++) {
System.out.print(res[i][j] + " ");
}
System.out.println();
}
}
}
}
27.矩阵乘法计算量估算
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int n = in.nextInt();
int a[][] = new int[n][2];
for (int i = 0; i < n; i++) {
a[i][0] = in.nextInt();
a[i][1] = in.nextInt();
}
String s = in.next();
Stack<Integer> stack = new Stack(); // 存放矩阵行数和列数
int sum = 0;
for (int i = s.length() - 1, j = n - 1; i >= 0; i--) {
if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z') { // 属于字母则把相应的矩阵列数和行数入栈
stack.push(a[j][1]);
stack.push(a[j][0]);
j--;
} else if (s.charAt(i) == '(') { // 括号:推出计算
int x0 = stack.pop(), y0 = stack.pop(); // 矩阵尺寸x0*y0
int x1 = stack.pop(), y1 = stack.pop(); // 矩阵尺寸x1*y1
sum += x0 * y0 * y1; // 两个矩阵的乘法次数为x0*y0*y1或x0*x1*y1(其中y0==x1)
stack.push(y1); // 把相乘后得到的矩阵列数入栈
stack.push(x0); // 把相乘后得到的矩阵行数入栈
}
}
System.out.println(sum);
}
}
}
28.字符串通配符
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String str = "";
while ((str = bf.readLine()) != null) {
str = str.toLowerCase();
String s = bf.readLine().toLowerCase();
boolean [][] flag = new boolean[str.length() + 1][s.length() + 1];
flag[0][0] = true;
if (str.charAt(0) == '*') {
flag[1][0] = true;
}
for (int i = 1; i <= str.length(); i++) {
char ch = str.charAt(i - 1);
for (int j = 1; j <= s.length(); j++) {
char c = s.charAt(j - 1);
if (ch == '?') {
if (check(c)) {
flag[i][j] = flag[i - 1][j - 1];
} else {
flag[i][j] = false;
}
} else if (ch == '*') {
if (check(c)) {
flag[i][j] = flag[i - 1][j - 1] || flag[i][j - 1] || flag[i - 1][j];
} else {
flag[i][j] = false;
}
} else if (ch == c) {
flag[i][j] = flag[i - 1][j - 1];
} else {
flag[i][j] = false;
}
}
}
System.out.println(flag[str.length()][s.length()]);
}
}
public static boolean check(char ch) {
if (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9') {
return true;
}
return false;
}
}
正则表达式解法2:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String regx = sc.nextLine().toLowerCase();
String string = sc.nextLine().toLowerCase();
//做相应的替换
regx = regx.replaceAll("\\*{1,}", "[0-9A-Za-z]*");
regx = regx.replaceAll("\\?", "[0-9A-Za-z]{1}");
boolean result = string.matches(regx);
System.out.println(result);
}
sc.close();
}
29.参数解析
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
StringBuilder sb = new StringBuilder();
List<String> list = new ArrayList();
boolean flag = false;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (String.valueOf(c).equals("\"")) {
flag = flag ? false : true;
continue;
}
if (String.valueOf(c).equals(" ") && !flag) {
list.add(sb.toString());
sb = new StringBuilder();
} else {
sb.append(c);
}
}
list.add(sb.toString());
System.out.println(list.size());
for (String s : list) {
System.out.println(s);
}
}
}
30.公共子串计算
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String ss1 = in.nextLine();
String ss2 = in.nextLine();
String s1 = ss1.length() < ss2.length() ? ss1 : ss2; // 短的字符串
String s2 = ss1.length() < ss2.length() ? ss2 : ss1; // 长的字符串
int n = 0;
for (int i = 0; i < s1.length(); i++) { // 头指针从第一位开始递增
for (int j = s1.length(); j > i; j--) { // 尾指针从最后一位开始缩减
if (s2.contains(s1.substring(i, j))) { // 第一次发现合集的长度一定是最大的
n = j - i > n ? j - i : n; // 取每一次比较的最大值
continue; // 已经是最大的,无需再进行后续的操作
}
}
}
System.out.println(n);
}
}
31.火车进站
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
Set<String> set = new TreeSet<>();
solve(arr, 0, "", new ArrayList<>(), set);
for (String s : set)
System.out.println(s.trim());
}
sc.close();
}
private static void solve(int[] arr, int index, String res, List<Integer> list, Set<String> set) {
if (index == arr.length) {
for (int i = list.size() - 1; i >= 0; i--) {
res = res + " " + list.get(i);
}
set.add(res);
return ;
}
while (true) {
List<Integer> tmp = new ArrayList<>(list);
tmp.add(arr[index]);
solve(arr, index + 1, res, tmp, set);
if (list.size() == 0)
break;
res = res + " " + list.remove(list.size() - 1);
}
}
}
32.将真分数分解为埃及分数
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
while ((str = br.readLine()) != null) {
String[] ss = str.split("/");
long a = Integer.parseInt(ss[0]);
long b = Integer.parseInt(ss[1]);
long t;
StringBuilder sb = new StringBuilder();
while (a != 0) {
t = b / a + (b % a == 0 ? 0 : 1);
if (b % t == 0 && a >= t) {
a -= b / t;
sb.append('1').append('/').append(t).append('+');
} else {
a = a * t - b;
b = b * t; // 这里可能溢出,所以都用long
if (a != 0)sb.append('1').append('/').append(t).append('+');
else sb.append('1').append('/').append(t);
}
if (a == 1) {
sb.append('1').append('/').append(b);
break;
}
}
System.out.println(sb);
}
}
}
解法2:
数学家斐波那契提出的一种求解真分数的贪心算法,准确的算法表述应该是这样的:
设某个真分数的分子为a,分母为b;
把c=(b/a+1)
作为分解式中第一个真分数的分母;
将a-b%a
作为新的a;
将b*c
作为新的b;
如果a等于1,则最后一个真分数为1/b
,算法结束;
如果a大于1但是a能整除b,则最后一个真分数为1/(b/a)
,算法结束;
否则重复上面的步骤。
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String res = "";
String[] arr = in.nextLine().split("/");
String pre = "";
int a = Integer.valueOf(arr[0]);
int b = Integer.valueOf(arr[1]);
while (true){
int c = b/a+1;
res += "1/";
res += c;
a = a - b % a;
b = b * c;
res += "+";
if (a == 1){
res += "1/";
res += b;
break;
}else if (a > 1 && b % a == 0){
res += "1/";
res += b/a;
break;
}
}
System.out.println(res);
}
}
}
递归解法3:
/**
* 先将 a/b 转换成 1/x+y/z 的形式
* y/z 使用递归继续分解,直到分子为1
*
* b除以a,得商x,得余数y b=a*x+y
* a/b = 1/(x+1) + (a-y)/b(x+1)
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String[] str = sc.next().split("/");
// 分子
int a = Integer.parseInt(str[0]);
// 分母
int b = Integer.parseInt(str[1]);
StringBuffer result = new StringBuffer();
process(a, b, result);
System.out.println(result);
}
}
private static void process(int a, int b, StringBuffer result) {
if (result.length() != 0) {
result.append("+");
}
int x = b / a;
if (a == 1 || b % a == 0) {
result.append("1/").append(x);
} else {
int y = b % a;
result.append("1/").append(x + 1);
process(a - y, b * (x + 1), result);
}
}
}
33.合法IP
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String str = in.next();
String[] nums = str.split("\\.", -1);
String result = "YES";
if (nums.length == 4) {
for (String element : nums) { //遍历每个元素,合不合法
if (element.length() == 0 || element.length() > 3) { //每段长度等于0,或者长度大于4,都不合法
result = "NO";
break;
}
for (Character ch : element.toCharArray()) { //每段的字符必须是数字
if (!Character.isDigit(ch)) {
result = "NO";
break;
}
}
if (element.charAt(0) == '0' && element.length() != 1) { //除0以外,所有0开头的字符串都是非法的
result = "NO";
break;
}
if (Integer.parseInt(element) > 255) { //每段对应的数大于255,也是非法的
result = "NO";
break;
}
}
} else {
result = "NO";
}
System.out.println(result);
}
}
}
34.在字符串中找出连续最长的数字串
public class Main{
public static void main(String[] args) throws Exception{
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()){
String line = sc.nextLine();
String[] ss = line.split("[^0-9]+");
int max = 0;
ArrayList<String> list = new ArrayList<>();
for(String s : ss){
if(s.length() > max){
max = s.length();
list.clear();
list.add(s);
}else if(s.length() == max){
max = s.length();
list.add(s);
}
}
StringBuilder sb = new StringBuilder();
for(String item : list){
sb.append(item);
}
sb.append(",").append(max);
System.out.println(sb.toString());
}
}
}
35.Redraiment的走法
public class Main{
public static void main(String[] arg) {
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
scan.nextLine();
String[] input1 = scan.nextLine().split(" ");
int[] intArr = Arrays.stream(input1).mapToInt(Integer::parseInt).toArray();
int[] k=new int[intArr.length];
for(int j=1;j<intArr.length;j++){
for(int i=0;i<j;i++){
if(intArr[i]<intArr[j]){
k[j]=Math.max(k[j],k[i]+1);
}
}
}
Arrays.sort(k);
System.out.println(k[k.length-1]+1);
}
}
}
解法2:动态规划+二分
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String str;
while ((str = bf.readLine()) != null) {
int len = Integer.parseInt(str);
int[] nums = new int[len];
String[] split = bf.readLine().split(" ");
for (int i = 0; i < len; ++i) {
nums[i] = Integer.parseInt(split[i]);
}
System.out.println(LIS(nums));
}
}
public static int LIS (int[] arr) {
int n = arr.length;
// 列表的最大子序列 下标从1开始
int[] end = new int[n + 1];
// 存储每个元素的最大子序列个数
int[] dp = new int[n];
int len = 1;
//子序列的第一个元素默认为数组第一个元素
end[1] = arr[0];
//第一个元素的最大子序列个数肯定是1
dp[0] = 1;
for (int i = 1; i < n; i++) {
if (end[len] < arr[i]) {
//当arr[i] > end[len] 时 arr[i]添加到 end后面
end[++len] = arr[i];
dp[i] = len;
} else {
// 当前元素小于end中的最后一个元素 利用二分法寻找第一个大于arr[i]的元素
// end[l] 替换为当前元素 dp[]
int l = 0;
int r = len;
while (l <= r) {
int mid = (l + r) >> 1;
if (end[mid] >= arr[i]) {
r = mid - 1;
} else {
l = mid + 1;
}
}
end[l] = arr[i];
dp[i] = l;
}
}
int[] res = new int[len];
for (int i = n - 1; i >= 0; i--) {
if (dp[i] == len) {
res[--len] = arr[i];
}
}
return res.length;
}
}
36.求解立方根
牛顿迭代法:
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (input.hasNextDouble()) {
double num = input.nextDouble();
double x = 1.0;
for ( ; Math.abs(Math.pow(x, 3) - num) > 1e-3 ;
x = x - ((Math.pow(x, 3) - num) / (3 * Math.pow(x, 2))) );
System.out.println(String.format("%.1f", x));
}
}
}