假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字母数相对少一些。从算法上讲,什么方法能最快的查出所有小字符串里的字母在大字符串里都有?
比如,如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOM
答案是true,所有在string2里的字母string1也都有。如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOZ
答案是false,因为第二个字符串里的Z字母不在第一个字符串里。
方法一[时间复杂度O(m*n)]: 对于这种操作一种幼稚的做法是轮询第二个字符串里的每个字母,看它是否同在第一个字符串里。从算法上讲,这需要O(n*m)次操作,其中n是string1的长度,m是string2的长度。就拿上面的例子来说,最坏的情况下将会有16*8 = 128次操作。
方法二:一个稍微好一点的方案是先对这两个字符串的字母进行排序,然后同时对两个字串依次轮询。两个字串的排序需要(常规情况)O(m log m)+ O(n log n)次操作,之后的线性扫描需要O(m+n)次操作。同样拿上面的字串做例子,将会需要16*4 + 8*3 = 88加上对两个字串线性扫描的16 + 8 = 24的操作。(随着字串长度的增长,你会发现这个算法的效果会越来越好)
方法三[时间复杂度O(n+m)]: 对第一个字串进行轮询,把其中的每个字母都放入一个Hashtable里(成本是O(n)或16次操作)。然后轮询第二个字串,在Hashtable里查询每个字母,看能否找到。如果找不到,说明没有匹配成功。这将消耗掉8次操作——这样两项操作加起来一共只有24次。
方法四: 假设我们有一个一定个数的字母组成字串——我给每个字母分配一个素数,从2开始,往后类推。这样A将会是2,B将会是3,C将会是5,等等。现在我遍历第一个字串,把每个字母代表的素数相乘,你最终会得到一个很大的整数。然后——轮询第二个字符串,用每个字母除它。如果除的结果有余数,这说明有不匹配的字母。如果整个过程中没有余数,你应该知道它是第一个字串恰好的子集了。
方案4:实现
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
public class StringTest {
static HashMap<String,Integer> hashMap = new HashMap();
static{
hashMap.put("A",2);
hashMap.put("B",3);
hashMap.put("C",5);
hashMap.put("D",7);
hashMap.put("E",11);
hashMap.put("F",13);
hashMap.put("G",17);
hashMap.put("H",19);
hashMap.put("I",23);
hashMap.put("J",29);
hashMap.put("K",31);
hashMap.put("L",37);
hashMap.put("M",41);
hashMap.put("N",43);
hashMap.put("O",47);
hashMap.put("P",53);
hashMap.put("Q",59);
hashMap.put("R",61);
hashMap.put("S",67);
hashMap.put("T",71);
hashMap.put("U",73);
hashMap.put("V",79);
hashMap.put("W",83);
hashMap.put("X",89);
hashMap.put("Y",97);
hashMap.put("Z",101);
}
public static void setSuShu(){
int cout = 0;
//随便定义300个数 里面肯定有26个素数
for (int i = 2; i < 300; i++) {
if(cout<26) {
boolean flag = true;
for (int j = 2; j < i; j++) {
if (i % j == 0) {
flag = false;
}
}
if (flag == true) {
System.out.println(i);
cout++;
}
}
}
}
/**
* 比如,如果是下面两个字符串:
* String 1: ABCDEFGHLMNOPQRS
* String 2: DCGSRQPOM
* 答案是true,所有在string2里的字母string1也都有。如果是下面两个字符串:
* String 1: ABCDEFGHLMNOPQRS
* String 2: DCGSRQPOZ
* 答案是false,因为第二个字符串里的Z字母不在第一个字符串里。
*
* 方法三[时间复杂度O(n+m)]: 对第一个字串进行轮询,把其中的每个字母都放入一个Hashtable里(成本是O(n)
* 或16次操作)。然后轮询第二个字串,在Hashtable里查询每个字母,看能否找到。如果找不到,
* 说明没有匹配成功。这将消耗掉8次操作——这样两项操作加起来一共只有24次。
*
* 方法四: 假设我们有一个一定个数的字母组成字串——我给每个字母分配一个素数,从2开始,往后类推。
* 这样A将会是2,B将会是3,C将会是5,等等。现在我遍历第一个字串,把每个字母代表的素数相乘,
* 你最终会得到一个很大的整数。然后——轮询第二个字符串,用每个字母除它。如果除的结果有余数,
* 这说明有不匹配的字母。如果整个过程中没有余数,你应该知道它是第一个字串恰好的子集了。
*
* @param args
*/
public static void main(String[] args) {
//先求出26个素数 然后赋值给hashmap的26个字母
String a = "ABCDEFGHLMNOPQRS";
String b = "DCGSRQPOM";
BigInteger totalA = BigInteger.ONE;
String[] a1 = new String[a.length()];
for(int i=0;i<a.length();i++){
a1[i] = a.substring(i,i+1);
totalA = totalA.multiply(BigInteger.valueOf(hashMap.get(a1[i])));
}
boolean flg = isInStringA(b,totalA);
System.out.println(flg);
// System.out.println(Arrays.toString(a1));
// System.out.println(Arrays.toString(b1));
}
public static boolean isInStringA(String b,BigInteger totalA){
String[] b1 = new String[b.length()];
for(int i=0;i<b.length();i++){
b1[i] = b.substring(i,i+1);
if(!totalA.mod(BigInteger.valueOf(hashMap.get(b1[i]))).equals(BigInteger.ZERO)){
return false;
}
}
return true;
}
}

2118

被折叠的 条评论
为什么被折叠?



