今天浏览文章"一次谷歌面试趣事"时,看到作者分享的一道字符串题目. 具体内容如下
问题描述
假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字母数相对少一些。从算法是讲,什么方法能最快的查出所有小字符串里的字母在大字符串里都有?
比如,如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOM
答案是true,所有在string2里的字母string1也都有。如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOZ
答案是false,因为第二个字符串里的Z字母不在第一个字符串里。
解题思路:
方案一:采用HashMap
采用HashMap存储较长字符串中字符与次数对应关系.其中只要HashMap包含字符,则继续遍历,无需给次数加1. 因为题目中字符串都是由字母组成,所以当HashMap的长度等于26时,就可以停止遍历较长字符串的字符.接着遍历较短字符串的字符,如果字符都包含于HashMap,返回true;否则,返回false;
方案二:采用位运算
首先可以判断最长字符串长度,如果特别长,可以考虑分段来处理.刚试着写了一下代码,字符串没有进行分段处理.
public class IsAllInLongString {
public static boolean isAllInLongString(String longStr, String shortStr) {
/**
* 考虑输入中有一个或两个参数为null的情况
*/
if (longStr == null && shortStr == null || longStr == null
&& shortStr != null || longStr != null && shortStr == null) {
return true;
}
if (longStr.length() < shortStr.length()) {
String tempString = longStr;
longStr = shortStr;
shortStr = tempString;
}
/**
* 最短字符串为0,直接返回true;
*/
if (shortStr.length() == 0) {
return true;
}
int longBit = 0;
int shortBit = 0;
for (int i = 0; i < longStr.length(); i++) {
longBit |= 1 << (longStr.charAt(i) - 'a');
}
for (int i = 0; i < shortStr.length(); i++) {
shortBit |= 1 << (shortStr.charAt(i) - 'a');
}
int temp = longBit & shortBit;
/**
* 统计temp和shortBit中二进制一的个数
* 如果相等,返回true 否则,返回false
*/
if (getNumsOfOneInBinary(temp) == getNumsOfOneInBinary(shortBit)) {
return true;
}
return false;
}
/**
* 统计正整数二进制出现一的个数
*
* @param num
* @return
*/
public static int getNumsOfOneInBinary(int num) {
if (num < 0) {
throw new IllegalArgumentException("argument < 0");
}
int count = 0;
while (num != 0) {
count++;
num &= (num - 1);
}
return count;
}
public static void main(String[] args) {
System.out.println(isAllInLongString("hello", "hello world"));
}
}
写在最后
想法写出来才能知道对不对,有考虑不足的地方,谢谢大家的指点