问题:
leetcode(3);
思考过程:
1.暴力搜索方法
step1:循环每个下标作为开始,标记为i;
step2:内循环每个下标作为结束,标记为j;
step3:检测以i开头,以j结尾的子串是否重复
关于检测重复:最纯的就是检测每个字符跟后面的字符有没有重复。
以上的时间复杂度为O(n^3);
2.优化检测重复的方法并剪枝;
step1:循环每个下标作为开始,标记为i;
step2:内循环每个下标作为结束,标记为j;
step3:在j向右的过程中,每得到一个新的字符就检测这个字符之前是否出现过,查重可以优化为使用map或者set方法。
step4:如果有重复,那么记录最长的距离,然后break,换到下一个i。
3.考虑类比找最长回文子串长度的方法
step1:新建动态规划二维表
step2:记长度为1的子串为不重复的。
step3:循环步长从2到n;
step4:判断新值时,如果dp中左边或者下边为重复,则该位置为重复,如果s[i-1]和s[j+1]相等,则该位置代表的字符串也重复。
评价,该方法似乎优化了判断重复的标准,但因为不能剪枝,所以速度并不如第二种
4.通过记录观察第二种方法的结果发现,如果在某个区间上判断出了重复,那么下一次i时,很有可能和上次的i停留在相同的位置,因为其内某一元素和当前的j重复。所以又可以优化。
step1:初始定位ij在0处,j先出发,当出现重复时,记录此时的最长,然后移动i到合适位置(不重复)
step2:循环step1,j继续往后走,直到结束。
评价:这样复杂度竟然降到了O(n),采用的方法是双指针法,其中判断重复时可以使用map或者hash.
博客总结:
1.同时向右走的双指针法,或者叫滑动窗口方法是数据结构与算法书中不介绍的,但是很常用,场景就是要寻找一段有特殊性质的连续区间,并且能够方便的定位到合适的尾随的指针的位置。这样想来,就知道了为什么找不重复子串可以用这种办法,而寻找最长回文的时候就必须用dp了,后者没有办法快速定位到尾随指针,这样的话dp中优化的判断方法就很有效了。
2.双指针法在此题中是同时向右走的,还有一种题是分别在头尾放置指针,一起往中间走。
3.又让我想到了典型的寻找区间最大和的题目,从暴力的O(n^3)到使用前缀的O(n^2),到双指针的O(n)。也是经过了整个的优化流程。
完。