赞
踩
滑动窗口也叫尺取法,是一种在字符串或数组中查找满足条件的算法。
例如可以在字符串中查找满足条件的子串。
在这里,规定窗口大小为3,每次向右滑动一位。
当然,窗口的大小可以随意调整,调整至满足条件即可。
规定开始窗口大小为0,利用左右指针指向子串的开始和结束。截取左右指针中的子串,每次移动右边指针将元素加入子串并判断在子串中是否有相同元素,如果有则移动左指针。一直重复上述操作,直到右指针指向字符串尾。记录出现的最长子串。
代码:
// 判断右指针元素是否在前方出现,没有出现则扩大窗口大小,元素出现则改变左指针位置 // 此方法利用滑动窗口将窗口的字符串截取出来存到子串中,判断子串中是否包含即将加入的字符串, int lengthOfLongestSubstring(string s) { if (s.length() <= 1) { return s.length(); } int left = 0, right = 0; int maxlen = 0; while (right <= s.length()) { // 截取子串 string sub = s.substr(left, right - left); maxlen = maxlen > right - left ? maxlen : right - left; // 判断子串中是否含有新加入的字符,如果含有新加入的字符,改变窗口大小 while ( left < right && sub.find(s[right]) != string::npos) { left++; // 窗口大小发生改变 截取新串 sub = s.substr(left, right - left); } right++; } return maxlen; }
原理与上述相同,但不用截取子串,效率更高。
int lengthOfLongestSubstring(string s) { if (s.length() <= 1) { return s.length(); } int left = 0, right = 1, max = 1; while (right < len) { // 在子串中进行查找该字符第一次出现的位置,如果第一次出现的位置与右值相同,则代表没有出现过该字符 while (right < len && s.find(s[right], left) == right) { right++; } max = right - left > max ? right - left : max; left++; } return max; }
与上述思路完全不同,不再利用滑动窗口。出现一个字符记录一个字符,并且累加器累加,如果遇到已经出现过的字符,则根据这个重复字符出现在字符串中的位置,决定累加器的值。重复上述操作,记录最大累加器的值。
int lengthOfLongestSubstring(string s) { if (s.length() <= 1) { return s.length(); } int acsii[256] = { 0 }; // 记录字符串出现的次数 int count = 0; int maxcount = 1; for (int i = 0; i < s.length(); i++) { // 如果字符已经出现 if (acsii[s[i]] == 1) { // 判断前后时候是一样的字符串,如果重复,则当前字符为新子串,则让计数器重新计数 if (s[i] == s[i - 1]) { //如果计数器大于字符串一半长度则说明不会出现更长子串, 所以清零也就没有必要了 if (count > s.length() / 2) { break; } count = 0; } else { // 如果该串与周边字符串没有关系,则对长度-1,再开始计数, count--; } } // 如果没有字符出现则累加器++,如果有字符出现过则对长度改变后再++ count++; acsii[s[i]] = 1; maxcount = maxcount > count ? maxcount : count; } return maxcount; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。