leetcode3 无重复字符的最长子串

先说结论:自己没做出来,抄的别人的。

https://www.cnblogs.com/ariel-dreamland/p/8668286.html

给定一个字符串,找出不含有重复字符的最长子串的长度。

示例:

给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3。

给定 "bbbbb" ,最长的子串就是 "b" ,长度是1。

给定 "pwwkew" ,最长子串是 "wke" ,长度是3。请注意答案必须是一个子串"pwke" 是 子序列  而不是子串。

JAVA 滑动窗口

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // 哈希集合,记录每个字符是否出现过
        Set<Character> occ = new HashSet<Character>();
        int n = s.length();
        // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        int rk = -1, ans = 0;
        for (int i = 0; i < n; ++i) {
            if (i != 0) {
                // 左指针向右移动一格,移除一个字符
                occ.remove(s.charAt(i - 1));
            }
            while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
                // 不断地移动右指针
                occ.add(s.charAt(rk + 1));
                ++rk;
            }
            // 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = Math.max(ans, rk - i + 1);
        }
        return ans;
    }
}
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int length = s.length();
        int left = 0, right = 0;
        int result = 0;
        Set<Character> set = new HashSet<>();
        for (; left < length; left++) {
            while (right < length && !set.contains(s.charAt(right))) {
                set.add(s.charAt(right));
                right++;
            }
            result = Math.max(result, right - left);
            set.remove(s.charAt(left));
        }
        return result;
    }
}

7-24更新,自己在剑指offer上又看到这个题目了,重新做了一下:

思路:

动态规划,

建立一个数组当哈希表用。本来用pos[26],结果测试用例中有很多非英语字符,所以用pos[256]

分两种情况

  • 没有见过这个字母,那么就对dp[i]=dp[i-1]+1;
  • 之前遇到过这个字母,又分两种情况:
  • (1)距离上一个字母的距离大于dp[i-1]。比如arabcacfr----检测到r,发现其实不影响状态方程:dp[i]=dp[i-1]+1
  • (2)距离上一个字母的距离小于等于dp[i-1]。比如arabcacfr----检测到a,考虑等于的情况,必须把dp[3]设置为距离2,不能再用状态方程了。

坑:

字符串为0,以后这个要最先考虑。

有其他的字符,pos数组必须256大小。

数组必须初始化为-1,因为0是存在的。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size()==0)
            return 0;
        int dp[50000]={0};
        int pos[256]={0};
        for(int i=1;i<256;i++)
            pos[i]=-1;
        pos[s[0]]=0;
        dp[0]=1;
        int maxlen=1;

        for (int i=1;i<s.size();i++)
        {
            if (pos[s[i]]==-1||i-pos[s[i]]>dp[i-1])
            {
                dp[i]=dp[i-1]+1;
                maxlen=max(dp[i],maxlen);
            }else {
                dp[i]=i-pos[s[i]];
                maxlen=max(dp[i],maxlen);
            }
            pos[s[i]]=i;
        }

        return maxlen;
    }
};

调试代码:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int lengthOfLongestSubstring(string s) {
	if(s.size()==0)
		return 0;
	int dp[50000]={0};
	int pos[256]={0};
	for(int i=1;i<256;i++)
		pos[i]=-1;
	pos[s[0]]=0;
	dp[0]=1;
	int maxlen=1;

	for (int i=1;i<s.size();i++)
	{
		if (pos[s[i]]==-1||i-pos[s[i]]>dp[i-1])
		{
			dp[i]=dp[i-1]+1;
			maxlen=max(dp[i],maxlen);
		}else {
			dp[i]=i-pos[s[i]];
			maxlen=max(dp[i],maxlen);
		}
		pos[s[i]]=i;
	}

	return maxlen;
}

int main()
{
	string str("abcabcbb");
	int res=lengthOfLongestSubstring(str);
	cout<<res<<endl;
	return 0;
}

思路:

循环字符串,找下一个相同的字符,计算间隔。写了半天发现是错的。。。凉凉因为aab都过不了。。。

暴力搜索:

循环所有字符串,两个循环,然后还要再判断这个里面重复不。用set来做。最后超时了。凉凉。。。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        set<char> myset;
        int res=0;
        for(int i=0;i<s.size()-1;i++)
            for(int j=0;j<s.size();j++){
                string s1(s,i,j-i);
                for(int k=0;k<s1.size();k++){
                    if(!myset.insert(s1[k]).second)
                        break;
                }
                if(res<myset.size())
                    res=myset.size();
                myset.clear();
                s1.clear();
            }
        return res;
    }
};

优化了一下,让i从0到n-1;j从n开始往前走j--,如果发现不重复的子串,就没有必要再往前走了。但是还是超时了。。。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        set<char> myset;
        int res=0;
        int flag=0;
        int success=0;
        for(int i=0;i<s.size()-1;i++){
            success=0;
            for(int j=s.size();j>i;j--){
                string s1(s,i,j-i);
                for(int k=0;k<s1.size();k++){
                    if(!myset.insert(s1[k]).second)
                    {
                        flag=1;//insert fail -- substring has same character
                        break;
                    }
                }
                if(!flag){//insert success for substring whose characters are all different 
                    if(res<myset.size())
                        res=myset.size();
                    success=1;//no need to decrease j
                    flag=0;
                    myset.clear();
                    s1.clear();
                    break;
                }
                flag=success=0;
                myset.clear();
                s1.clear();
            }
        }
        return res;
    }
};

又不甘心,再优化,感觉myset插入的时候太耗时间,改为手动排序子字符串,结果还是超时啊。。。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
       // set<char> myset;
        int res=0;
        int flag=0;
        int success=0;
        for(int i=0;i<s.size()-1;i++){
            success=0;
            for(int j=s.size();j>i;j--){
                string s1(s,i,j-i);
                sort(s1.begin(),s1.end());
                for(int k=0;k<s1.size()-1;k++){
                    if(s1[k]==s1[k+1])
                        flag=1;
                }
                if(!flag){//insert success for substring whose characters are all different 
                    if(res<s1.size())
                        res=s1.size();
                    success=1;//no need to decrease j
                    flag=0;
                   // myset.clear();
                    s1.clear();
                    break;
                }
                flag=success=0;
                //myset.clear();
                s1.clear();
            }
        }
        return res;
    }
};

心态崩了。。。去看看人家的吧。

这个博客讲的太好:

LeetCode(3):无重复字符的最长子串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,有三种方法可以解决LeetCode上的最长回文子串问题。 方法一是使用扩展中心法优化,即从左向右遍历字符串,找到连续相同字符组成的子串作为扩展中心,然后从该中心向左右扩展,找到最长的回文子串。这个方法的时间复杂度为O(n²)。\[1\] 方法二是直接循环字符串,判断子串是否是回文子串,然后得到最长回文子串。这个方法的时间复杂度为O(n³),效率较低。\[2\] 方法三是双层for循环遍历所有子串可能,然后再对比是否反向和正向是一样的。这个方法的时间复杂度也为O(n³),效率较低。\[3\] 综上所述,方法一是解决LeetCode最长回文子串问题的最优解法。 #### 引用[.reference_title] - *1* [LeetCode_5_最长回文子串](https://blog.csdn.net/qq_38975553/article/details/109222153)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode-最长回文子串](https://blog.csdn.net/duffon_ze/article/details/86691293)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [LeetCode 第5题:最长回文子串(Python3解法)](https://blog.csdn.net/weixin_43490422/article/details/126479629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值