LC 3. 无重复字符的最长子串

Posted 菜菜想当诗人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LC 3. 无重复字符的最长子串相关的知识,希望对你有一定的参考价值。

> 原题链接: 3. 无重复字符的最长子串 - 力扣(LeetCode)

 

class Solution 
    public int lengthOfLongestSubstring(String s) 
        /*
        * 思路:
        *        单调栈
        *       构建一个用一个队列存放已经遍历过的元素, 如果当前元素在队列中已经存在, 那么不停出队到队列里
        *    和当前元素相同的元素的下一个位置, 把当前元素放进去, 每次元素入队, 都更新一次最大值, 这样遍历
        *    一遍数组, 就能得到整个字符串的最大不同子串
        * */
        Deque<Character> queue = new LinkedList<>();    // 队列
        int index = 0;                                  // 下标位置
        char[] chs = s.toCharArray();                   // 字符串转化为字符数组方便操作
        int N = chs.length;
        int ans = 0;                                    // 返回的答案, 存放最长的子串长度
        while (index < N) 
            while (index < N && (queue.isEmpty() || !queue.contains(chs[index]))) 
                queue.add(chs[index++]);            // 队列为空或者当前元素不在队列里存在, 入队
                ans = Math.max(ans, queue.size());  // 更新最大值
            
            while (index < N && !queue.isEmpty() && queue.contains(chs[index])) va
                queue.pollFirst();                  // 当前元素在队列里存在, 队头元素不停出队, 
                                               // 直到与当前元素相同的元素出队后位置
            if (index < N) 
                queue.add(chs[index++]);
                ans = Math.max(ans, queue.size());
            
        
        return ans;
    

// 单调栈写法优化
class Solution 
    public int lengthOfLongestSubstring(String s) 
        Deque<Character> que = new LinkedList<>();
        int ans = 0;
        for (int i = 0; i < s.length(); i++) 
            while (!que.isEmpty() && que.contains(s.charAt(i)))
                que.pollFirst();
            que.add(s.charAt(i));
            ans = Math.max(ans, que.size());
        
        return ans;
    

 

class Solution 
    /**
    思路: dp + map 
        用一张 map 表存储每个字符上一次出现的位置
    当前位置向前推的距离 和 上一次位置能向前推出的距离 + 1, 
    小的那个就是当前位置的最长无重复字符串
    
     */
    public int lengthOfLongestSubstring(String s) 
        if (s == null || s.length() == 0)
            return 0;
        char[] str = s.toCharArray();
        // map 表记录 (char)i 字符上一次出现的位置
        int[] map = new int[128];
        // -1 表示都没出现过
        for (int i = 0; i < 128; i++)
            map[i] = -1;
        // dp[i] 表示以 i 位置字符结尾的最长无重复子串
        int[] dp = new int[str.length];
        // 初始化操作
        int ans = 1;
        map[str[0]] = 0;
        dp[0] = 1;
        // 从 1 位置开始
        for (int i = 1; i < str.length; i++) 
            // 当前位置和上一个相同字符的距离
            int cur = i - map[str[i]];
            // i-1 位置字符结尾能推出的最长无重复子串是 dp[i-1],
            dp[i] = Math.min(dp[i - 1] + 1, cur);
            ans = Math.max(ans, dp[i]);
            map[str[i]] = i;
        
        return ans;
    

 

// 空间压缩版本
class Solution 
    /**
    思路: dp + map 
        用一张 map 表存储每个字符上一次出现的位置
    当前位置向前推的距离 和 上一次位置能向前推出的距离 + 1, 
    小的那个就是当前位置的最长无重复字符串
    
     */
    public int lengthOfLongestSubstring(String s) 
        if (s == null || s.length() == 0)
            return 0;
        char[] str = s.toCharArray();
        // map 表记录 (char)i 字符上一次出现的位置
        int[] map = new int[128];
        // -1 表示都没出现过
        for (int i = 0; i < 128; i++)
            map[i] = -1;
        // 初始化操作
        int ans = 1;
        map[str[0]] = 0;
        int pre = 1;
        // 从 1 位置开始
        for (int i = 1; i < str.length; i++) 
            // 当前位置和上一个相同字符的距离
            int cur = i - map[str[i]];
            // i-1 位置字符结尾能推出的最长无重复子串是 dp[i-1],
            pre = cur = Math.min(pre + 1, cur);
            ans = Math.max(ans, cur);
            map[str[i]] = i;
        
        return ans;
    

 

最长不重复子串

问题描述

给定一个字符串,找到最长的子串,要求该子串中没有重复的字符。
例如:
字符串abcabcbb的不含重复字符的最长子串为abc,长度为3。
bbbbbb的不含重复字符的最长子串为b,长度为1。

输入格式

输入包含多行,每一行对应一个长度不超过100 的输出,直到遇到结束符为止。每行依次输入字符串s

输出格式

输出不含重复字符的最长子串的长度。

代码

package javaexam;

import java.util.HashMap;
import java.util.Scanner;

/**
 * @author houhaibushihai
 * The longest non repeating substring
 *
 */
public class LongestNRS
{
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        
        while(input.hasNext())
        {
            int max = 0;
            int start = 0;
            HashMap<Character, Integer> map = new HashMap<Character, Integer>();
            String str = input.nextLine();
            
            for(int i = 0; i < str.length(); ++i)
            {
                if(map.containsKey(str.charAt(i)))
                    start = Math.max(start, map.get(str.charAt(i)) + 1);
                
                map.put(str.charAt(i), i);
                max = Math.max(max, i - start + 1);
            }
            System.out.println(max);
        }
    }
}

样例测试

hchzvfrkmlnozjk
11

以上是关于LC 3. 无重复字符的最长子串的主要内容,如果未能解决你的问题,请参考以下文章

No.3. 无重复字符的最长子串

3. 无重复字符的最长子串

3. 无重复字符的最长子串

3. 无重复字符的最长子串

3. 无重复字符的最长子串

3. 无重复字符的最长子串