package leetcode.wyj;

/**
 * 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
 * <p>
 * 示例1:
 * <p>
 * 输入: "abcabcbb"
 * 输出: 3
 * 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
 * 示例 2:
 * <p>
 * 输入: "bbbbb"
 * 输出: 1
 * 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
 * 示例 3:
 * <p>
 * 输入: "pwwkew"
 * 输出: 3
 * 解释: 因为无重复字符的最长子串是"wke",所以其长度为 3。
 *     请注意,你的答案必须是 子串 的长度,"pwke"是一个子序列,不是子串。
 * <p>
 * 来源:力扣(LeetCode)
 * 链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
 * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
 */

import java.util.*;

public class leetCode3 {

    /**
     * 两个指针 i和j  分别为最长不重复字符串的头和尾
     * 当j指的字符 与前面有重复 则 i 向后移动
     */
    public int lengthOfLongestSubstring(String s) {
        int i = 0;
        int j = 0;
        int maxLength = 0;
        Set<Character> set = new HashSet<>();
        while (i < s.length() - maxLength && j < s.length()) {
            if (!set.contains(s.charAt(j))) {
                set.add(s.charAt(j++));
                maxLength = Math.max(maxLength, j - i);
            } else {
                set.remove(s.charAt(i++));
            }
        }
        return maxLength;
    }

    /**
     * 两个指针 i和j  分别为最长不重复字符串的头和尾
     * 当j指的字符 与前面有重复 则 i 直接向后移动到重复字符的后一个字符的位置
     * LeetCode执行貌似没快多少
     */
    public int lengthOfLongestSubstring2(String s) {
        int i = 0;
        int j = 0;
        int maxLength = 0;
        Set<Character> set = new HashSet<>();
        while (i < s.length() - maxLength && j < s.length()) {
            if (!set.contains(s.charAt(j))) {
                set.add(s.charAt(j++));
                maxLength = Math.max(maxLength, j - i);
            } else {
                char c = s.charAt(j);

                while (true) {
                    if (c == s.charAt(i)) {
                        set.remove(s.charAt(i++));
                        break;
                    }
                    set.remove(s.charAt(i++));
                }

            }
        }
        return maxLength;
    }


    /**
     * 使用map优化第二个算法,没什么乱用,不快
     */
    public int lengthOfLongestSubstring3(String s) {
        int i = 0;
        int j = 0;
        int maxLength = 0;
        Map<Character, Integer> map = new HashMap();
        while (i < s.length() - maxLength && j < s.length()) {
            char c = s.charAt(j);
            if (map.containsKey(c)) {
                int v = map.get(c) + 1;
                while (i < v) {
                    map.remove(s.charAt(i++));
                }

                map.put(c, j);
                j++;
            } else {
                map.put(s.charAt(j), j);
                j++;
                maxLength = Math.max(j - i, maxLength);
            }
        }
        return maxLength;
    }

    public static void main(String[] args) {
        lengthOfLongestSubstring4("pwwkew");
    }
    /**
     * 用队列
     */
    public static int lengthOfLongestSubstring4(String s) {
        int maxLength = 0;
        Queue<Character> queue = new ArrayDeque();
        Set<Character> set = new HashSet<>();
        int i = 0;
        while (i < s.length()) {
            char c = s.charAt(i);
            if (set.contains(c)) {
                queue.add(c);
                while (true) {
                    set.remove(queue.peek());
                    if(c == queue.poll()){
                        break;
                    }
                }
                set.add(c);

            } else {
                queue.add(c);
                set.add(c);
                maxLength = Math.max(queue.size(), maxLength);
            }
            i++;
        }
        return maxLength;
    }
}