算法练习:
题目1:模拟一个trim方法,去除字符串两端的空格。
public String myTrim(String str) {
if (str != null) {
int start = 0;// 用于记录从前往后首次索引位置不是空格的位置的索引
int end = str.length() - 1;// 用于记录从后往前首次索引位置不是空格的位置的索引while (start < end && str.charAt(start) == ' ') {
start++;
}while (start < end && str.charAt(end) == ' ') {
end--;
}
if (str.charAt(start) == ' ') {
return "";
}return str.substring(start, end + 1);
}
return null;
}@Test
public void testMyTrim() {
String str = " a ";
// str = " ";
String newStr = myTrim(str);
System.out.println("---" + newStr + "---");
}
题目2:将一个字符串进行反转。将字符串中指定部分进行反转。
比如"abcdefg"反转为"abfedcg"
package chapter11_api.src.com.atguigu01.string.exer2; import org.junit.Test; /** * ClassName: StringTest2 * Package: chapter11_api.src.com.atguigu01.string.exer2 * Description: * *题目2:将一个字符串进行反转。将字符串中指定部分进行反转。 * 比如"abcdefg"反转为"abfedcg" * * * * @Author 小白 * @Create 2024/4/9 13:47 * @Version 1.0 */ public class StringTest2 { @Test public void test(){ String s = "abcdefg"; // String s1 = reverse(s, 2, 5); String s2 = reverse(s, 2, 5); // System.out.println(s1); System.out.println(s2); } //reverse:反转 //reverse()方法也是自己写的 String里面没有这个方法 //String str,int fromIndex,int toIndex 这几个形参是根据题目要求自己写的 不是哪个方法的构造器 /* * 方式1:将String转为char[],针对char[]数组进行相应位置的反转,反转以后将char[]转为String * */ public String reverse(String str,int fromIndex,int toIndex){ //将String转为char[] char[] toCharArray(): 将此字符串转换为一个新的字符数组返回 // String s = "abcdef"; // arr 数组的内容为 ['a', 'b', 'c', 'd', 'e', 'f'],即字符串中每个字符对应的元素。 char[] arr = str.toCharArray(); for(int i = fromIndex,j = toIndex;i < j;i++,j--){ char temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } //通过使用 String类的构造函数 String(char[] value)来实现,该构造函数会根据给定的字符数组创建一个新的字符串对象。 //public String(char[] value):通过当前参数中的字符数组来构造新的String。 //将char[]转为String return new String(arr); } /* * 第2种方式 * */ public String reverse1(String str,int fromIndex ,int toIndex){ //String substring(int beginIndex, int endIndex) : // 返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。 // 创建一个空字符串用于存放反转后的结果 String finalStr = ""; //获取str的第1部分 finalStr = str.substring(0,fromIndex); //ab abcdefg---->0123456 ab----.01 //fromIndex的位置是2 //返回一个新字符串,它是此字符串从0开始截取到fromIndex(2)(不包含)的一个子字符串。 //char charAt(index):返回[index]位置的字符 比如i=5 那我们就返回索引上的字符f //拼接上第2部分 /* * */ for(int i = toIndex;i >= fromIndex;i--){ finalStr += str.charAt(i); }//abfedc //拼接上第3部分 //String substring(int beginIndex) : //返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。 //因为 substring() 方法是左闭右开区间,即 beginIndex 是包含在内的,但 endIndex 是不包含在内的。 //所以,当我们想要从 toIndex + 1 开始截取字符串时,我们需要传入的参数是 toIndex + 1 //一定要加1 finalStr += str.substring(toIndex +1 ); return finalStr; } }
解释代码:
/* * 方式1:将String转为char[],针对char[]数组进行相应位置的反转,反转以后将char[]转为String * */
for(int i = fromIndex,j = toIndex;i < j;i++,j--){
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
解释:
/*当遍历字符数组时,我们需要交换指定范围内的字符,即从索引 `fromIndex` 到索引 `toIndex` 的字符。在这个例子中,指定的范围是从索引 `2` 到索引 `5`。让我们详细说明如何遍历并交换字符数组中的元素:
1. 首先,我们需要定义两个指针或索引变量,一个从头开始,一个从尾部开始。在这个例子中,`fromIndex` 的值为 `2`,`toIndex` 的值为 `5`。
2. 然后,我们使用一个 `for` 循环来遍历字符数组。在循环中,第一个指针从 `fromIndex` 开始递增,第二个指针从 `toIndex` 开始递减。在每次迭代中,我们交换这两个指针位置上的字符。
3. 在第一次迭代中,我们交换索引为 `2` 和 `5` 的元素;在第二次迭代中,交换索引为 `3` 和 `4` 的元素;然后依次类推,直到两个指针相遇为止。
让我们根据例子 `"abcdef"` 来详细说明: - 我们有一个字符数组 `arr`,其中包含了字符 `'a'`、`'b'`、`'c'`、`'d'`、`'e'` 和 `'f'`,索引从 `0` 到 `5`。
- 现在,我们有两个指针,一个从索引 `2` 开始,一个从索引 `5` 开始。
- 在第一次迭代中,我们交换索引为 `2` 和 `5` 的元素,即 `'c'` 和 `'f'`。此时,字符数组变为 `['a', 'b', 'f', 'd', 'e', 'c']`。
- 在第二次迭代中,我们交换索引为 `3` 和 `4` 的元素,即 `'d'` 和 `'e'`。此时,字符数组变为 `['a', 'b', 'f', 'e', 'd', 'c']`。
- 在第三次迭代中,由于指针相遇,循环结束。 通过以上步骤,我们完成了指定范围内字符的交换,即完成了字符数组的反转操作。最后,我们将反转后的字符数组转换为字符串,并返回结果。
/* * 第2种方式 * */
解释以下代码:
for(int i = toIndex;i >= fromIndex;i--){
finalStr += str.charAt(i);
}//abfedc
解释:
1. 当 `toIndex` 为 5 时,意味着我们应该包括索引 5 的字符,即字符 "f"。而 `fromIndex` 为 2,意味着我们应该包括索引 2 的字符,即字符 "c"。这段代码旨在将从 "c" 到 "f" 的部分进行反转。
2. 我们进入 `for` 循环,`i` 从 5 开始递减,直到 2。
3. 在循环的每一步中,我们从原始字符串的索引位置 `i`(初始为 5)提取字符,并将其添加到 `finalStr` 中。
4. 循环的第一步,我们添加 "f" 到 `finalStr`,因为原始字符串中索引为 5 的位置是 "f"。
5. 循环的第二步,我们添加 "e" 到 `finalStr`,因为原始字符串中索引为 4 的位置是 "e"。
6. 循环的第三步,我们添加 "d" 到 `finalStr`,因为原始字符串中索引为 3 的位置是 "d"。
7. 循环的第四步,我们添加 "c" 到 `finalStr`,因为原始字符串中索引为 2 的位置是 "c"。
8. 当 `i` 等于 `fromIndex`,即 2 时,我们完成了需要反转的部分,因此停止循环。
9. 最终,`finalStr` 变成了 "fedc",这是 "abcdef" 中索引为 2 到 5 的部分反转后的结果。
题目3:获取一个字符串在另一个字符串中出现的次数。
比如:获取"ab"在 "abkkcadkabkebfkabkskab" 中出现的次数
package chapter11_api.src.com.atguigu01.string.exer2; import org.junit.Test; /** * ClassName: StringTest3 * Package: chapter11_api.src.com.atguigu01.string.exer2 * Description: * * 题目3:获取一个字符串在另一个字符串中出现的次数。 * 比如:获取"ab"在 "abkkcadkabkebfkabkskab" 中出现的次数 * * @Author 小白 * @Create 2024/4/9 13:48 * @Version 1.0 */ public class StringTest3 { @Test public void test(){ String subStr = "ab"; String str = "abkkcadkabkebfkabkskab"; int count = getSubStringCount(str,subStr); System.out.println(count); } ///获取子字符串的次数 /** * 判断subStr在str中出现的次数 * @param str * @param subStr * @return 返回次数 */ /*让我们逐步解释 `"ab"` 在原始字符串 `"abkkcadkabkebfkabkskab"` 中的出现次数: 1. 首先,我们定义了原始字符串 `str = "abkkcadkabkebfkabkskab"` 和子字符串 `subStr = "ab"`。 2. 我们开始搜索子字符串 `"ab"` 在原始字符串中的出现位置。 3. 首先,我们使用 `indexOf()` 方法找到第一次出现 `"ab"` 的位置。在整个字符串中,第一次出现 `"ab"` 的位置是索引 0。 4. 然后,我们将计数器 `count` 加一,并更新查找索引,使其指向下一个潜在的出现位置。由于我们已经在索引 0 处找到了一个子字符串,因此我们将索引更新为 `0 + 2 = 2`(即当前索引加上子字符串的长度),从这个位置继续搜索下一个可能的出现位置。 5. 在索引 2 处,我们找到了第二个子字符串 `"ab"`。我们再次将计数器 `count` 加一,并更新查找索引为 `2 + 2 = 4`。 6. 在索引 4 处,我们找到了第三个子字符串 `"ab"`。我们再次将计数器 `count` 加一,并更新查找索引为 `4 + 2 = 6`。 7. 在索引 6 处,我们找到了第四个子字符串 `"ab"`。我们再次将计数器 `count` 加一,并更新查找索引为 `6 + 2 = 8`。 8. 在索引 8 处,我们没有找到子字符串 `"ab"`,因此 `indexOf()` 方法返回 -1。 9. 循环结束,我们得到了子字符串 `"ab"` 在原始字符串中出现的总次数,即 4。 所以,根据上述步骤,程序会打印出子字符串 `"ab"` 在原始字符串 `"abkkcadkabkebfkabkskab"` 中出现的次数,即 4。*/ public int getSubStringCount(String str,String subStr){ int count = 0;//记录出现的次数 if(str.length() >= subStr.length()){ //int indexOf(xx):从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1 int index = str.indexOf(subStr); while(index >= 0){ count++; //int indexOf(String str, int fromIndex): // 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始 /*当我们使用 `indexOf()` 方法来查找子字符串在原始字符串中的出现位置时,我们传递了两个参数: 1. 第一个参数是要查找的子字符串 `subStr`。 2. 第二个参数是开始查找的位置,我们希望从当前位置的下一个位置开始查找。 在这种情况下,`index + subStr.length()` 计算出的是下一个潜在的出现位置。因为我们已经找到了一个子字符串的位置,所以我们希望从当前位置的下一个位置继续搜索,而不是重叠查找之前找到的子字符串。 例如,如果我们在索引 0 找到了子字符串 `"ab"`,则下一个潜在的出现位置应该从索引 `0 + 2 = 2` 开始查找,以避免重复计数。 因此,`index = str.indexOf(subStr, index + subStr.length())` 这行代码的作用是更新 `index` 的值,使其指向下一个潜在的出现位置。*/ index = str.indexOf(subStr,index + subStr.length()); } } return count; } }
题目4:获取两个字符串中最大相同子串。比如:
str1 = "abcwerthelloyuiodef";
str2 = "cvhellobnm"
提示:将短的那个串进行长度依次递减的子串与较长的串比较。
// 第4题
// 如果只存在一个最大长度的相同子串
public String getMaxSameSubString(String str1, String str2) {
if (str1 != null && str2 != null) {
String maxStr = (str1.length() > str2.length()) ? str1 : str2;
String minStr = (str1.length() > str2.length()) ? str2 : str1;int len = minStr.length();
for (int i = 0; i < len; i++) {// 0 1 2 3 4 此层循环决定要去几个字符
for (int x = 0, y = len - i; y <= len; x++, y++) {
if (maxStr.contains(minStr.substring(x, y))) {
return minStr.substring(x, y);
}}
}
}
return null;
}// 如果存在多个长度相同的最大相同子串
// 此时先返回String[],后面可以用集合中的ArrayList替换,较方便
public String[] getMaxSameSubString1(String str1, String str2) {
if (str1 != null && str2 != null) {
StringBuffer sBuffer = new StringBuffer();
String maxString = (str1.length() > str2.length()) ? str1 : str2;
String minString = (str1.length() > str2.length()) ? str2 : str1;int len = minString.length();
for (int i = 0; i < len; i++) {
for (int x = 0, y = len - i; y <= len; x++, y++) {
String subString = minString.substring(x, y);
if (maxString.contains(subString)) {
sBuffer.append(subString + ",");
}
}
System.out.println(sBuffer);
if (sBuffer.length() != 0) {
break;
}
}
String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,");
return split;
}return null;
}
// 如果存在多个长度相同的最大相同子串:使用ArrayList
// public List<String> getMaxSameSubString1(String str1, String str2) {
// if (str1 != null && str2 != null) {
// List<String> list = new ArrayList<String>();
// String maxString = (str1.length() > str2.length()) ? str1 : str2;
// String minString = (str1.length() > str2.length()) ? str2 : str1;
//
// int len = minString.length();
// for (int i = 0; i < len; i++) {
// for (int x = 0, y = len - i; y <= len; x++, y++) {
// String subString = minString.substring(x, y);
// if (maxString.contains(subString)) {
// list.add(subString);
// }
// }
// if (list.size() != 0) {
// break;
// }
// }
// return list;
// }
//
// return null;
// }@Test
public void testGetMaxSameSubString() {
String str1 = "abcwerthelloyuiodef";
String str2 = "cvhellobnmiodef";
String[] strs = getMaxSameSubString1(str1, str2);
System.out.println(Arrays.toString(strs));
}
题目5:对字符串中字符进行自然顺序排序。
提示:
1)字符串变成字符数组。
2)对数组排序,选择,冒泡,Arrays.sort();
3)将排序后的数组变成字符串。
// 第5题
@Test
public void testSort() {
String str = "abcwerthelloyuiodef";
char[] arr = str.toCharArray();
Arrays.sort(arr);String newStr = new String(arr);
System.out.println(newStr);
}