public class RemoveLeftmostSubstring {
public static String removeLeftmostSubstring(String input, String target) {
while (true) {
int index = input.indexOf(target);
if (index == -1) {
break;
}
input = input.substring(0, index) + input.substring(index + target.length());
}
return input;
}
}
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Comprehensive tests for removeLeftmostSubstring.
* The method removes the leftmost occurrence of target repeatedly
* until no occurrence remains.
*/
public class RemoveLeftmostSubstringTest {
// 被测方法(使用 String 的方法实现)
private static String removeLeftmostSubstring(String input, String target) {
if (input == null) return null;
if (target == null || target.length() == 0) return input; // 约定:空目标不修改字符串
String s = input;
while (true) {
int idx = s.indexOf(target);
if (idx == -1) break;
s = s.substring(0, idx) + s.substring(idx + target.length());
}
return s;
}
// 0 次移除(目标子字符串不存在)
@Test
public void testZeroRemovals() {
String input = "hello world";
String target = "xyz";
String expectedOutput = "hello world";
assertEquals("Should return the original string when no match is found",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 1 次移除(目标子字符串只出现一次)
@Test
public void testOneRemoval() {
String input = "hello world";
String target = "hello";
String expectedOutput = " world";
assertEquals("Should remove the target substring when it appears once",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 2 次移除(目标子字符串出现两次 -> 两次都被移除)
@Test
public void testTwoRemovals() {
String input = "hello world hello";
String target = "hello";
String expectedOutput = " world "; // 两次移除后中间与尾部空格都会保留
assertEquals("Should remove all leftmost occurrences until none remain",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 多次移除(目标子字符串出现多次)
@Test
public void testMultipleRemovals() {
String input = "abcabcabc";
String target = "abc";
String expectedOutput = "";
assertEquals("Should remove all occurrences until no match is found",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 移除后引入新的目标子字符串(移除可能拼接出新的目标)
@Test
public void testRemovalIntroducesTarget() {
String input = "xxxxyxxxxyxxx";
String target = "xyx";
// 逐步移除后最终结果为 7 个 'x'
String expectedOutput = "xxxxxxx";
assertEquals("Should handle cases where removal introduces the target substring",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 空输入字符串
@Test
public void testEmptyInputString() {
String input = "";
String target = "abc";
String expectedOutput = "";
assertEquals("Should return an empty string when the input is empty",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 空目标子字符串(约定:不做任何移除)
@Test
public void testEmptyTargetString() {
String input = "hello world";
String target = "";
String expectedOutput = "hello world";
assertEquals("Should return the original string when the target is an empty string",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 目标子字符串比输入字符串长
@Test
public void testTargetLongerThanInput() {
String input = "abc";
String target = "abcd";
String expectedOutput = "abc";
assertEquals("Should return the original string when the target is longer than the input",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 输入字符串包含特殊字符
@Test
public void testInputWithSpecialCharacters() {
String input = "hello @world! #test";
String target = "@world!";
String expectedOutput = "hello #test";
assertEquals("Should handle input strings with special characters",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 目标子字符串包含特殊字符并出现多次
@Test
public void testTargetWithSpecialCharacters() {
String input = "hello @world! #test @world!";
String target = "@world!";
String expectedOutput = "hello #test ";
assertEquals("Should handle target substrings with special characters",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 目标子字符串是输入字符串的前缀(并可能被多次移除)
@Test
public void testTargetAsPrefix() {
String input = "hellohello world";
String target = "hello";
String expectedOutput = " world";
assertEquals("Should remove the target repeatedly when it appears as prefix(s)",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 目标子字符串是输入字符串的后缀(并可能被多次移除)
@Test
public void testTargetAsSuffix() {
String input = "hello worldhello";
String target = "hello";
String expectedOutput = " world";
assertEquals("Should remove the target repeatedly when it appears as suffix(s)",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 目标子字符串重复多次且密集(重叠/接近的情况)
@Test
public void testDenseRepeatedTargets() {
String input = "abababab";
String target = "aba";
// 解释:第一次移除 "aba" -> "babab"; 再次移除最左侧 "aba"(现在从 index1)-> "bb"
String expectedOutput = "bb";
assertEquals("Should handle densely repeated or overlapping targets",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 输入字符串与目标子字符串相同
@Test
public void testInputEqualsTarget() {
String input = "hello";
String target = "hello";
String expectedOutput = "";
assertEquals("Should remove the entire string when input equals target",
expectedOutput, removeLeftmostSubstring(input, target));
}
// 额外:null 输入的行为(合理性测试)
@Test
public void testNullInput() {
String input = null;
String target = "a";
assertNull("If input is null, should return null", removeLeftmostSubstring(input, target));
}
}