面试题:寻找字符串中由2种字符组成的最长连续子串
这是前段时间遇到的一道面试题,寻找字符串中由任意2种字符组成的最长连续子串,例如输入为“abababccef”,输出为6,要找的子串为“ababab"。暴力的一点的解法是从每个字符串开始向前遍历,找到符合条件的最小下标值,再计算长度。
public static int findSubString(String str) { if (str.length() <= 2) return str.length(); int max = 0; for (int i = 0; i < str.length(); i++) { char cur_char = str.charAt(i); char new_char = cur_char; int j = i; while (j >= 0 && str.charAt(j) == cur_char) j--; if (j >= 0) { new_char = str.charAt(j); j--; for (; j >= 0; j--) { if (str.charAt(j) != cur_char && str.charAt(j) != new_char) break; } } int tmp = i - j; if (tmp > max) max = tmp; } return max; }
这种方法的时间复杂度是O(n^2),面试官后来说暴搜其实是不得分的。另一种更快的解决方法是记录前一个字符能够向前找到的最小下标位置,计算长度就可以在常数时间完成,时间复杂度为O(n)。
public static int fastFindSubString(String str) { if (str.length() <= 2) return str.length(); int max = 0; char cur_char = str.charAt(0); char lst_char = cur_char; char lst_char2 = cur_char; int lst_pos = 0; int i=0; int start =0; while(i<str.length() && str.charAt(i)==cur_char) i++; for ( ; i < str.length(); i++) { cur_char = str.charAt(i); if(lst_char != cur_char && lst_char2 != cur_char){ int tmp = i-start; if(max<tmp) max=tmp; start = lst_pos; lst_char2 = lst_char; lst_char = cur_char; lst_pos = i; }else{ if(lst_char2 == cur_char){ char t = lst_char; lst_char = lst_char2; lst_char2 = t; lst_pos = i; } } } int tmp=i-start; if(max<tmp) max=tmp; return max; }
估计如果我当时能做到这一步的话,问题会变成3种字符,或者n种字符,维护一个大小为n的有序列表,能得到前一个字符的最前下标就行了。
面试时写的代码丑陋的没法看,而且随便就能找出bug,虽然挂了,但还是获得了一些技术面经验:
- 要习惯在纸上写代码,脱离ide的各种懒人功能。
- 要习惯用纸笔去调试代码。
- 先写测试用例
- 简单题一定要bug free