大家好,今后我会在博客分享自己一些算法解题思路和一些有趣的推理题,欢迎有兴趣的朋友们一起来学习呀
双指针是一种思想或一种技巧并不是特别具体的算法。
具体就是用两个变量动态存储两个结点,来方便我们进行一些操作。通常用在线性的数据结构中。
解决双指针问题四种常用思想:
1、普通双指针(two sum),一般两个for循环,外层i和内层j可以认为是普通的双指针;
2、左右指针(二分搜索):需要两个指针,一个指向开头,一个指向末尾,然后向中间遍历,直到满足条件或者两个指针相遇;
3、快慢指针:需要两个指针,开始都指向开头,根据条件不同,快指针走得快,慢指针走的慢,直到满足条件或者快指针走到结尾;
4、滑动窗口。
今日的题目是力扣中的第三题:无重复字符的最长子串
题目:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
看到这道题,脑海里第一反应是暴力解法,遍历所有可能嘛;
但是,咱们是谁?咱们是优雅的工程师,怎么能局限于这么粗鄙的解决方法,所以这里博主使用第二反应的方法:双指针
为了方便各位更好的理解,这里将示例1以图示的形式画出来:
其中Left和Right分别为左指针和右指针,我们现在开始分析:
首先,我们直接判断字符串长度是否大于1,如果不大于直接return,进入下一步,此时长度一定大于一,所以直接把第一个元素存入HashSet;
之后就是通过判断右指针指向的值和HashSet中存储的值进行对比,如果已经存储了,便将left开始右移,并在left右移的时候将left指向的值从HashSet中移除,直到HashSet中不包含right指向的值为止;如果不好含,则right继续右移,并将值存入HashSet,while循环中记住要注意边界值条件,以防数组越界;
至于这里为什么要用HashSet呢,这个就留待各位思考咯
最终完整代码如下:
public int LengthOfLongestSubstring(string s)
{
if(s.Length == 0||s.Length==1)
{
return s.Length;
}
else
{
char[] chars = s.ToCharArray();
HashSet<char> set = new HashSet<char>();
int left = 0;
int right = 1;
int maxLength = 0;
set.Add(chars[left]);
while (left <= right && right < chars.Length)
{
if (!set.Contains(chars[right]))
{
set.Add(chars[right]);
right++;
maxLength = Math.Max(maxLength, right - left);
}
else
{
set.Remove(chars[left]);
left++;
}
}
return maxLength;
}
}
这就是一道经典的双指针问题,现在是不是感觉So easy;
其实很多时候只要愿意去花时间分析问题,就会发现问题其实很简单。
欢迎各位留言,有技术想法或者有疑问的都欢迎来讨论