华为OD刷题C卷 – 每日刷题 6 (求字符串中所有整数的最小和、求满足条件的最长子串的长度)
两段代码分别解决了两个字符串处理的问题,下面是对它们的概述:
1、(求字符串中所有整数的最小和):
这段代码是解决“求字符串中所有整数的最小和”的问题。它提供了一个Java类Main
,其中包含一个方法getMinSum
,该方法接收一个字符串str
,并返回字符串中包含的所有整数的最小和。
代码首先将字符串转换成字符数组,然后使用一个Stack
来存储遇到的数字。由于题目要求处理的整数没有长度限制,因此使用BigInteger
来处理大数。
在遍历字符串的过程中,代码会根据字符是数字还是符号(+
或-
)来更新当前数字或将其压入栈中。如果遇到负号,则将当前数字乘以-1
后压入栈中。如果遇到非数字字符(除了数字和加减号之外的字符),则将当前符号设置为+
,并将数字重置为0
。
最后,使用stream().reduce()
方法对栈中的所有数字进行求和操作,并返回结果。
2、(求满足条件的最长子串的长度):
这段代码是解决“求满足条件的最长子串的长度”的问题。它提供了一个Java类Main
,其中包含一个方法getResult
,该方法接收一个字符串s
,并返回满足条件的最长子串的长度。
满足条件的子串要求只包含一个字母(a~z, A~Z
),其余部分必须是数字。字母可以在子串中的任意位置。
代码使用双指针left
和right
来遍历字符串。同时使用一个LinkedList
来记录字母的索引。当遇到字母时,将其索引压入栈中,并更新字母的计数。如果字母计数超过1,则将左指针移动到上一个字母的下一个位置,并将左指针之前的字母索引从栈中移除。
在遍历过程中,代码会更新满足条件的最长子串长度maxLen
。最后,如果整个字符串中没有字母,则返回-1
;否则返回计算得到的最长子串长度。
package OD149;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;
/**
* @description 求字符串中所有整数的最小和
* @level 7
* @score 100
*/
/**
* 题目描述
* 输入字符串s,输出s中包含所有整数的最小和。
*
* 说明:
*
* 字符串s,只包含 a-z A-Z ±
*
* 合法的整数包括
*
* 1)正整数:一个或者多个0-9组成,如 0 2 3 002 102
*
* 2)负整数:负号 – 开头,数字部分由一个或者多个0-9组成,如 -0 -012 -23 -00023
*
* 输入描述
* 包含数字的字符串
*
* 输出描述
* 所有整数的最小和
*/
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//读取
String str = sc.nextLine();
System.out.println(getMinSum(str));
}
//读取字符串中的最小整数和 数字没有限制长度,要用大数处理
public static BigInteger getMinSum(String str) {
//字符串str,只包含 a-z A-Z ±
char[] chars = str.toCharArray();
int n = chars.length;
//初始化数字
BigInteger number = new BigInteger("0");
//初始化符号
char sign = '+';
//存放操作数,正数单个加,负数整体加
Stack<BigInteger> stack = new Stack<>();
for (int i = 0; i < n; i++) {
//因为要找最小和,遇到正号直接加,遇到负号把后面数字拼起来加
char c = chars[i];
//遇到数字,判断正数直接入栈、负数整体入栈
if (Character.isDigit(c)) {
if (sign == '+') {
stack.push(new BigInteger(String.valueOf(c)));
} else {
//拼数字
number = number.multiply(new BigInteger("10")).add(new BigInteger(String.valueOf(c)));
}
}
//不是数字,则判断是符号 输入控制只有a-z A-Z ±
if (!Character.isDigit(c) || i == n - 1) {
//如果符号为-,把前面整体入栈
if (sign == '-') {
//把前面整体入栈
stack.push(number.multiply(new BigInteger("-1")));
}
//刷新符号 遇到字母的话刷新为+号
sign = c == '-' ? '-' : '+';
//刷新数字
number = new BigInteger("0");
}
}
//返回stack求和
return stack.stream().reduce(BigInteger::add).orElse(new BigInteger("0"));
}
}
package OD153;
import java.util.LinkedList;
import java.util.Scanner;
/**
* @description 求满足条件的最长子串的长度
* @level 6
* @score 100
*/
/**
* 题目描述
* 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度,字符串本身是其最长的子串,子串要求:
*
* 1、 只包含1个字母(a~z, A~Z),其余必须是数字;
*
* 2、 字母可以在子串中的任意位置;
*
* 如果找不到满足要求的子串,如全是字母或全是数字,则返回-1。
*
* 输入描述
* 字符串(只包含字母和数字)
*
* 输出描述
* 子串的长度
*/
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//读取输入字符串
String str = sc.nextLine();
System.out.println(getResult(str));
}
//寻找只包含一个数字的最长子串长度,没有则返回-1
public static int getResult(String s) {
int n = s.length();
//存放数字的索引
//双指针:从0开始,右指针往右移动,遇到字母就+1,并记录下标,左指针移动到上一个字母下标+1处
int left = 0;
int right = 0;
int maxLen = -1;
LinkedList<Integer> lastLetter = new LinkedList<>();
int countLetter = 0;
while (right < n) {
char c = s.charAt(right);
//如果是字母,则记录下标
if (Character.isLetter(c)) {
countLetter++;
lastLetter.add(right);
//如果超过1个字母,则左指针移动
if (countLetter > 1) {
left = lastLetter.removeFirst() + 1;
countLetter--;
}
if (left == right) {
right++;
continue;
}
}
//此时left到right之间一定最多一个字母
maxLen = Math.max(maxLen, right - left + 1);
right++;
}
//如果没有字母,则返回-1
if (countLetter == 0) {
return -1;
}
//否则返回maxLen
return maxLen;
}
}