判断一个字符串是否含有相同字符

本文介绍两种判断字符串中是否存在重复字符的方法,并对这两种方法的时间复杂度进行了对比分析。

一、题目

        判断一个字符串str是否含有相同的字符,假设字符为ASCII码表上的字符(前127位,不包括扩展字符)。

二、分析

       大家很容易想到的一个方法是,依次取一个字符x,然后遍历整个字符串,如果x==str[i],则返回true。当所有的字符都取出完毕都还没有发现相等,则返回false。该方法原理很简单,代码也很容易写出来,如下:

#include<stdio.h><pre name="code" class="cpp">#include<stdlib.h>
#include<string.h>
void main(int argc, char* argv[]){char* str = "abcdefg12345ah";int i, j;int ret=-1;for (i = 0; i<strlen(str);i++){for (j = i + 1; j < strlen(str);j++){if (str[i]==str[j]){ret = true;} }}ret > 0 ? (printf("含有相同字符\n")) : (printf("没有相同字符\n"));return;}

         另外一种方法,我们设置一个数组,标志该字符是否被访问过,然后遍历这个字符串,如果访问到了该字符则设置该标志为true。如果再次访问到了,则立即返回true。如果遍历完成,都没有重复访问,则返回false;代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main(int argc, char* argv[])
{
	char* str = "5bcdefg12345ah";
	int visited[127];//用数组标志该字符是否被访问过
	int i;
	int index;//数组下标
	int ret=-1;//结果
	for (i = 0; i<strlen(str);i++)
	{
		index = (int)str[i];//取ASCII码值作为下标
		if (visited[index]<=0)
		{
			visited[index] = 1;
		} 
		else
		{
			ret = 1;
		}
	}
	ret > 0 ? (printf("含有相同字符\n")) : (printf("没有相同字符\n"));
	return 0;
}


我们来做时间复杂度的分析:

第一个算法用了两层循环,运算次数为(n-1)*n/2,所以时间复杂度为o(n2);

第二个算法仅用了一层循环,时间复杂度为o(n);

所以从时间复杂度来看,明显第二个算法优于第一个。

<think>我们讨论的是判断一个字符串(target)是否包含列表(list)中任意一个字符串(即列表中是否字符串是target的子串)。 根据引用[1][3][4],我们可以使用indexOf方法来判断一个字符串是否包含另一个字符串(即子串)。但这里的需求是:判断target字符串是否包含列表中的任意一个字符串(即列表中是否字符串是target的子串)。 因此,我们需要遍历列表中的每个字符串,检查target是否包含当前列表项(子串)。如果有一个满足,则返回true。 方法: 1. 使用循环遍历列表,对每个列表项,使用target.indexOf(item) >= 0 或者 target.contains(item) 来判断。 2. 使用Java 8的Stream API,用anyMatch方法。 注意:contains方法内部也是调用indexOf,所以本质一样。 步骤: 1. 遍历字符串列表。 2. 对于每个列表中的字符串item,检查target是否包含它(即target.indexOf(item) != -1 或者 target.contains(item))。 3. 如果有一个满足,则整个方法返回true;如果遍历完都没有,则返回false。 示例代码: 方法一:循环遍历 ```java public static boolean containsAny(String target, List<String> list) { for (String item : list) { if (target.contains(item)) { // 或者使用 target.indexOf(item) != -1 return true; } } return false; } ``` 方法二:使用Stream API ```java public static boolean containsAny(String target, List<String> list) { return list.stream().anyMatch(target::contains); } ``` 注意:这里的需求是判断target字符串是否包含列表中的任意一个字符串(即列表中的字符串是target的子串)。与之前的问题(判断字符串是否在列表中)不同,之前是判断字符串是否等于列表中的某个元素。 举例: target = "Hello world" list = ["Hello", "abc"] -> 返回true,因为target包含"Hello" list = ["abc", "def"] -> 返回false 另外,引用[2]中提到了Python的列表推导,在Java中我们可以用类似循环或Stream的方式实现。 如果我们需要获取所有包含在target中的列表项,可以这样: ```java List<String> containedItems = list.stream() .filter(target::contains) .collect(Collectors.toList()); ``` 但问题只是判断是否存在,所以用anyMatch即可。 下面是一个完整的示例: </think> # 判断字符串是否包含列表中任意字符串的方法详解 在Java中判断一个字符串是否包含列表中的任意字符串,主要有以下几种高效方法: ## 1. 循环遍历 + `contains()` 方法(推荐) 这是最直接的方法,时间复杂度为 $O(n \times m)$,其中 $n$ 是列表长度,$m$ 是平均字符串长度。 ```java import java.util.Arrays; import java.util.List; public class StringContainsExample { public static void main(String[] args) { String target = "编程学习Java和Python"; List<String> keywords = Arrays.asList("Java", "C++", "Python"); // 检查target是否包含列表中的任意字符串 if (containsAny(target, keywords)) { System.out.println("目标字符串包含列表中的关键词"); } else { System.out.println("目标字符串不包含列表中的关键词"); } } public static boolean containsAny(String target, List<String> list) { for (String item : list) { if (target.contains(item)) { return true; // 找到匹配立即返回 } } return false; } } ``` ## 2. 使用 Java 8 Stream API(函数式风格) 对于更简洁的代码实现: ```java public static boolean containsAnyStream(String target, List<String> list) { return list.stream().anyMatch(target::contains); } ``` ## 3. 使用 `indexOf()` 方法(替代`contains()`) `contains()` 方法内部实际上是调用 `indexOf()`,两者性能相同: ```java public static boolean containsAnyIndex(String target, List<String> list) { for (String item : list) { if (target.indexOf(item) != -1) { return true; } } return false; } ``` ## 4. 需要忽略大小写的情况 使用 `toLowerCase()` 统一大小写: ```java public static boolean containsAnyIgnoreCase(String target, List<String> list) { String targetLower = target.toLowerCase(); for (String item : list) { if (targetLower.contains(item.toLowerCase())) { return true; } } return false; } ``` ## 性能优化技巧 - **预处理字符串**:对于多次查询,可以预处理目标字符串(如小写化) - **使用正则表达式**:当需要更复杂的匹配逻辑时 - **并行流处理**:对于大型列表,可使用并行流加速 ```java // 使用并行流处理大型列表 public static boolean containsAnyParallel(String target, List<String> list) { return list.parallelStream().anyMatch(target::contains); } ``` ## 完整示例代码 ```java import java.util.Arrays; import java.util.List; public class StringContainsDemo { public static void main(String[] args) { String target = "Java编程学习:掌握Java核心和Python基础"; List<String> languages = Arrays.asList("C#", "Python", "JavaScript"); System.out.println("循环遍历: " + containsAny(target, languages)); System.out.println("Stream API: " + containsAnyStream(target, languages)); System.out.println("忽略大小写: " + containsAnyIgnoreCase("java programming", languages)); } // 方法实现同上... } ``` **输出**: ``` 循环遍历: true Stream API: true 忽略大小写: false ``` ## 关键注意事项 1. **大小写敏感**:默认情况下`contains()`是大小写敏感的 2. **空值处理**:列表中的`null`元素会导致`NullPointerException` 3. **性能考虑**: - 小列表(<100元素):直接循环即可 - 大列表(>1000元素):考虑并行处理 - 超长字符串:注意子串匹配算法的效率 > 在Java中,`String.contains()`方法实际上是调用`indexOf()`实现的[^1][^3][^4],两者性能相同,可互换使用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值