查看: 472|回复: 12
|
Google面试题目
[复制链接]
|
|
Given a String pattern as "ABCDFGHK" write a function if input strings like XYZCDFGABHKERYT or LOPIKHFGDCBAYRT should return the starting index of the pattern and if the intput strings are XYZCDFGABBHKERYT or LOPIKHFDBAYRGCT it should return -1.
Do not use any data structures like dict or set to store all the possible combinations of the pattern string.
The interviewer said no to regular expressions too.
有谁会解答? |
|
|
|
|
|
|
|
发表于 27-3-2019 01:59 AM
|
显示全部楼层
本帖最后由 SotongJiang 于 27-3-2019 02:01 AM 编辑
去面试看到这题的话,肯定超时出局。当作编程练习还是能挤一挤脑汁。
按题意是coding不能用library的data structure或RE,越原始越好。
我的C/C++差不多还给老师了,唯有偷鸡用python如下,欢迎指教。
- def match_pattern(inStr, pattern, p_len):
- summation = 0
- for c in pattern:
- c_cnt = inStr.count(c)
- if c_cnt==1:
- summation += c_cnt
- else:
- break
- if summation==p_len:
- return True
- return False
- def find_pattern(inStr, pattern):
- p_len = len(pattern)
- s_len = len(inStr)
- i=0
- print '%s has pattern %s in it?' % (inStr, pattern)
- while (i < s_len):
- if pattern.count(inStr[i])>0:
- if s_len-i >= p_len:
- if match_pattern(inStr[i:i+p_len], pattern, p_len):
-
- print 'Found it at index ',i
- return i
- else:
- print 'Not found '
- return -1
- else:
- #pattern string not found throughout the inStr
- return -1
- i += 1
- find_pattern('XYZCDFGABHKERYT','ABCDFGHK')
- find_pattern('LOPIKHFGDCBAYRT','ABCDFGHK')
- find_pattern('XYZCDFGABBHKERYT','ABCDFGHK')
- find_pattern('LOPIKHFDBAYRGCT','ABCDFGHK')
-
-
复制代码 |
评分
-
查看全部评分
|
|
|
|
|
|
|
楼主 |
发表于 27-3-2019 06:03 PM
|
显示全部楼层
坦白说,我对Python不熟,但是在Visual Studio试了你的Code,结果是正确的:
从我在leetcode.com转载过来的那里,有关匿名人士没有给出答案,有些人就建议使用Permutation of Strings 或Anagram in Strings的方式,也有人提议用Hash 及 Sliding Window的方式。不过我请教了这里一位资深程序员,他说基本上在本地IT公司你的答案是过关的,只不过真正来说Google会不会接受则不得而知了。据我所了解,你用了str.Count这个功能。
谢谢你的参与,非常高兴看到本地也有人答题。
|
|
|
|
|
|
|
|
发表于 27-3-2019 08:09 PM
|
显示全部楼层
褐眼睛 发表于 27-3-2019 06:03 PM
坦白说,我对Python不熟,但是在Visual Studio试了你的Code,结果是正确的:
从我在leetcode.com转载过来的那里,有关匿名人士没有给出答案,有些人就建议使用Permutation of Strings 或Anagram in Strings的方式 ...
嘿嘿,没错用了python string里的count(), 所以我说偷鸡啊。
当然另写一个count()也ok,那就完全符合“越原始越好”的题目本意。
你看那论坛的建议,都违背了题意, hash是data structure的一种(类似dict), permutation的话也会用到library(除非大神级的自己重写)。
程序员用惯了library,突然要求不能用了就很痛苦。
上回你po的图片压缩比赛,我就无能为力了。
|
|
|
|
|
|
|
|
发表于 27-3-2019 10:35 PM
|
显示全部楼层
我的方法不过string要ABC-Z 而已
public class Test {
public static void main(String[] args) {
System.out.println(checkPattern("XYZCDFGABHKERYT", "ABCDFGHK"));
System.out.println(checkPattern("LOPIKHFGDCBAYRT", "ABCDFGHK"));
System.out.println(checkPattern("XYZCDFGABBHKERYT", "ABCDFGHK"));
System.out.println(checkPattern("LOPIKHFDBAYRGCT", "ABCDFGHK"));
}
public static int checkPattern(String input, String pattern) {
int len = pattern.length();
int[] patternLocation = new int[26];
for (int i = 0; i < 26; i++) {
patternLocation = 0;
}
for (int i = 0; i < len; i++) {
char ch = pattern.charAt(i);
patternLocation[ch - 'A'] = 1;
}
int count = 0;
int index = -1;
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (patternLocation[ch - 'A'] == 1) {
patternLocation[ch - 'A']= 0;
count=count+1;
index = i;
} else {
count = 0;
index = -1;
}
if (count == len) {
return index+1-len;
}
}
return -1;
}
}
|
评分
-
查看全部评分
|
|
|
|
|
|
|
楼主 |
发表于 28-3-2019 12:53 AM
|
显示全部楼层
我用C#(改了一下,如charAt 改成ElementAt),你的答案是正确的。
我发现你的方法很新颖,是Toggle Bit的方式来完成,不过有一个缺点,虽然和题目无关:无法使用相同字母作为String Pattern喔。
十分感谢你花时间来解决这道题!
|
|
|
|
|
|
|
|
发表于 28-3-2019 02:46 AM
|
显示全部楼层
本帖最后由 martinng 于 28-3-2019 05:24 AM 编辑
- C#:
- static void Main(string[] args)
- {
- string pattern = "ABCDFGHK";
- string inputString = "XYZCDFGABHKERYT";
- Console.WriteLine("Pattern = {0}", pattern);
- Console.WriteLine("Input string = {0}, index = {1}", inputString, findPattern(inputString, pattern)); //3
- inputString = "LOPIKHFGDCBAYRT";
- Console.WriteLine("Input string = {0}, index = {1}", inputString, findPattern(inputString, pattern)); //4
- inputString = "XYZCDFGABBHKERYT";
- Console.WriteLine("Input string = {0}, index = {1}", inputString, findPattern(inputString, pattern)); //-1
- inputString = "LOPIKHFDBAYRGCT";
- Console.WriteLine("Input string = {0}, index = {1}", inputString, findPattern(inputString, pattern)); //-1
- Console.WriteLine();
- pattern = "ABBBBACDXZMARTIN";
- inputString = "XYZCDFGABDZMARBBINTBAXCHKERYT";
- Console.WriteLine("Input string = {0}, index = {1}", inputString, findPattern(inputString, pattern)); //7
- inputString = "XYZCDFGABDZMARBBINTBAABXCHKERYT";
- Console.WriteLine("Input string = {0}, index = {1}", inputString, findPattern(inputString, pattern)); //9
- inputString = "XYZCDFGABDZMARBHBINTBAABXCHKERYT";
- Console.WriteLine("Input string = {0}, index = {1}", inputString, findPattern(inputString, pattern)); //-1
- Console.ReadKey();
- }
- static int findPattern(string inputString, string pattern)
- {
- int index = -1;
- int patternLength = pattern.Length;
- int inputStringLength = inputString.Length;
- long patternValue = 0;
- long inputStringValue = 0;
- int bFirst = 1;
- if (inputStringLength < patternLength) return index;
- for (int i = 0; i < inputStringLength; i++)
- {
- inputStringValue = 0;
- for (int j = i; j < (i + patternLength); j ++)
- {
- if (bFirst == 1) patternValue += (long)1 << ((byte)(pattern[j - i]) - 65);
- inputStringValue += (long)1 << ((byte)(inputString[j]) - 65);
- }
- bFirst = 0;
- if (patternValue == inputStringValue)
- {
- index = i;
- break;
- }
- if ((i + patternLength) >= inputStringLength) break;
- }
- return index;
- }
复制代码
第五给example,其实pattern 已经改变了,变成"ABBBBACDXZMARTIN"了。
PS: 这个写得不够优化,不是O(N) running time,因为每次都重复计算inputStringValue。变成O(N^2)了。下面是更优化的版本。
|
-
|
|
|
|
|
|
|
发表于 28-3-2019 05:27 AM
|
显示全部楼层
本帖最后由 martinng 于 28-3-2019 11:38 AM 编辑
- static int findPattern(string inputString, string pattern)
- {
- int index = -1;
- int patternLength = pattern.Length;
- int inputStringLength = inputString.Length;
- long patternValue = 0;
- long inputStringValue = 0;
- long firstCharValue = 0;
- int bFirst = 1;
- if (inputStringLength < patternLength) return index;
- for (int i = 0; i < inputStringLength; i++)
- {
- if (bFirst == 1)
- {
- for (int j = i; j < (i + patternLength); j++)
- {
- patternValue += (long)1 << ((byte)(pattern[j - i]) - 65);
- inputStringValue += (long)1 << ((byte)(inputString[j]) - 65);
- if (i == j) firstCharValue = (long)1 << ((byte)(inputString[j]) - 65);
- }
- bFirst = 0;
- }
- else
- {
- //Sliding window algorithm, 每次前进一个字母,都是减去上次的第一个字母和加上这个新字母。
- inputStringValue = inputStringValue - firstCharValue + ((long)1 << ((byte)(inputString[i + patternLength - 1]) - 65));
- firstCharValue = (long)1 << ((byte)(inputString[i]) - 65);
- }
- if (patternValue == inputStringValue)
- {
- index = i;
- break;
- }
- if ((i + patternLength) >= inputStringLength) break;
- }
- return index;
- }
复制代码
这个才是真正O(N) running time,就是只要loop inputstring 字母数目,就能找到答案。
P/S:程式写得很不精简,有时间再refactor吧。
|
|
|
|
|
|
|
|
发表于 28-3-2019 05:58 AM
|
显示全部楼层
你误解了hash的真正定义了。dict 内部可能是用hash,但hash不一定就是dict,所以hash 不是一个data structure,而是algorithm。
其实leetcode 有个鬼佬(就是那个说用sliding window + hash)已经把正确解答方式说出来了。他的所谓Hash,是为Pattern取Hash值。只是他没有讲出来到底如何取Hash值,这个才是这个题目的重点。第二个重点就是:在比较pattern hash和 input string时,必须是最多loop N次,N就是input string的长度。如果call instr,substring,indexOf等等built in function,可能会在内部执行更多次数的loop,所以不鼓励用。
|
|
|
|
|
|
|
|
发表于 29-3-2019 01:09 AM
|
显示全部楼层
- static int findPattern(string inputString, string pattern)
- {
- if (inputString.Length < pattern.Length) return -1;
- long patternValue = 0, inputStringValue = 0;
- bool bPatternHashed = false;
- for (int i = 0; (i + pattern.Length) <= inputString.Length; i++)
- {
- if (!bPatternHashed)
- {
- for (int j = i; j < (i + pattern.Length); j++)
- {
- patternValue += (long)1 << ((byte)(pattern[j]) - 65);
- inputStringValue += (long)1 << ((byte)(inputString[j]) - 65);
- }
- bPatternHashed = true;
- }
- else inputStringValue -= ((long)1 << ((byte)(inputString[i - 1]) - 65)) - ((long)1 << ((byte)(inputString[i + pattern.Length - 1]) - 65));
- if (patternValue == inputStringValue) return i;
- }
- return -1;
- }
复制代码
刚刚refactor了。 |
|
|
|
|
|
|
|
发表于 30-3-2019 02:29 PM
|
显示全部楼层
本帖最后由 martinng 于 30-3-2019 02:33 PM 编辑
我们全都理解错这个问题啦。其实这个问题是考对Rabin Karp rolling hash 的理解和应用能力。这个问题的正确要求:
1)pattern 的字元顺序必须一致。ABC不等于CBA。
2)是要所有occurrence,并不是first occurrence而已。 ABC,“AZX【ABC】XXTML【ABC】D”
关于2),有一个疑惑:就是如果pattern是“AA”,string 是 “AAAA”,所有occurrence到底是 0,1,2(有重叠)还是0和2而已(不重叠)
|
|
|
|
|
|
|
|
发表于 31-3-2019 11:56 AM
|
显示全部楼层
褐眼睛 发表于 28-3-2019 12:53 AM
我用C#(改了一下,如charAt 改成ElementAt),你的答案是正确的。
我发现你的方法很新颖,是Toggle Bit的方式来完成,不过有一个缺点,虽然和题目无关:无法使用相同字母作为String Pattern喔。
十分感谢你花 ...
改用incremental or decremental因该就可以了
|
|
|
|
|
|
|
| |
本周最热论坛帖子
|