LeetCode - Medium - 3. Longest Substring Without Repeating Characters

Topic

  • Hash Table
  • Two Pointers
  • String
  • Sliding Window

Description

https://leetcode.com/problems/longest-substring-without-repeating-characters/

Given a string s, find the length of the longest substring without repeating characters.

Example 1:

Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.

Example 2:

Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.

Example 3:

Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.

Example 4:

Input: s = ""
Output: 0

Constraints:

  • 0 <= s.length <= 5 * 10⁴
  • s consists of English letters, digits, symbols and spaces.

Analysis

基本思想:用缓存以字符串的字符为键,下标为值。用左右指针标记最大子字符串起始与末尾下标。移动右指针扫描字符串的字符,与此同时,更新缓存,更新最长值。当发现重复的字符,查找缓存这字符对应下标,左指针指向这下标+1。

方法一:双指针+哈希表

方法二:比方法一精简些

方法三:移动窗口(队列)

方法四:双指针+哈希集

Submission

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

public class LongestSubstringWithoutRepeatingCharacters {

	//方法一:双指针+哈希表
	public int lengthOfLongestSubstring1(String s) {
		int max = 0, count = 0;
		Map<Character, Integer> cache = new HashMap<>();
		for (int leftIndex = 0, rightIndex = 0; rightIndex < s.length(); rightIndex++) {
			char character = s.charAt(rightIndex);
			Integer existIndex = cache.get(character);

			if (existIndex != null && existIndex >= leftIndex) {
				if (count > max)
					max = count;
				count = rightIndex - existIndex;
				leftIndex = existIndex + 1;
			} else {
				count++;
			}
			cache.put(character, rightIndex);
		}
		return Math.max(max, count);// max()针对字符串完全无重复字符(如:"abc")的情况
	}

	//方法二:比方法一精简些
	public int lengthOfLongestSubstring2(String s) {
		int max = 0, leftIndex = 0, rightIndex = 0;
		Map<Character, Integer> cache = new HashMap<>();
		for (; rightIndex < s.length(); rightIndex++) {
			char character = s.charAt(rightIndex);
			Integer existIndex = cache.get(character);
			if (existIndex != null && existIndex >= leftIndex) {
				max = Math.max(max, rightIndex - leftIndex);
				leftIndex = existIndex + 1;
			}
			cache.put(character, rightIndex);
		}
		return Math.max(max, rightIndex - leftIndex);
	}

	//方法三:移动窗口(队列)
	public int lengthOfLongestSubstring3(String s) {
		Queue<Character> queue = new LinkedList<>();
		int res = 0;
		for (char c : s.toCharArray()) {
			while (queue.contains(c)) {
				queue.poll();
			}
			queue.offer(c);
			res = Math.max(res, queue.size());
		}
		return res;
	}

	//方法四:双指针+哈希集
	public int lengthOfLongestSubstring4(String s) {
		int maxLen = 0;
		Set<Character> window = new HashSet<>();

		int left = 0, right = 0;
		while (right < s.length()) {
			while (window.contains(s.charAt(right)))
				window.remove(s.charAt(left++));
			window.add(s.charAt(right++));
			maxLen = Math.max(maxLen, right - left);
		}
		return maxLen;
	}
}

Test

import static org.junit.Assert.*;
import org.junit.Test;

public class LongestSubstringWithoutRepeatingCharactersTest {

	@Test
	public void test() {
		LongestSubstringWithoutRepeatingCharacters obj = new LongestSubstringWithoutRepeatingCharacters();

		assertEquals(3, obj.lengthOfLongestSubstring1("abcabcbb"));
		assertEquals(1, obj.lengthOfLongestSubstring1("bbbbb"));
		assertEquals(3, obj.lengthOfLongestSubstring1("pwwkew"));
		assertEquals(0, obj.lengthOfLongestSubstring1(""));
		assertEquals(1, obj.lengthOfLongestSubstring1(" "));
		assertEquals(3, obj.lengthOfLongestSubstring1("dvdf"));
		assertEquals(2, obj.lengthOfLongestSubstring1("abba"));
		
		assertEquals(3, obj.lengthOfLongestSubstring2("abcabcbb"));
		assertEquals(1, obj.lengthOfLongestSubstring2("bbbbb"));
		assertEquals(3, obj.lengthOfLongestSubstring2("pwwkew"));
		assertEquals(0, obj.lengthOfLongestSubstring2(""));
		assertEquals(1, obj.lengthOfLongestSubstring2(" "));
		assertEquals(3, obj.lengthOfLongestSubstring2("dvdf"));
		assertEquals(2, obj.lengthOfLongestSubstring2("abba"));
		
		assertEquals(3, obj.lengthOfLongestSubstring3("abcabcbb"));
		assertEquals(1, obj.lengthOfLongestSubstring3("bbbbb"));
		assertEquals(3, obj.lengthOfLongestSubstring3("pwwkew"));
		assertEquals(0, obj.lengthOfLongestSubstring3(""));
		assertEquals(1, obj.lengthOfLongestSubstring3(" "));
		assertEquals(3, obj.lengthOfLongestSubstring3("dvdf"));
		assertEquals(2, obj.lengthOfLongestSubstring3("abba"));
		
		assertEquals(3, obj.lengthOfLongestSubstring4("abcabcbb"));
		assertEquals(1, obj.lengthOfLongestSubstring4("bbbbb"));
		assertEquals(3, obj.lengthOfLongestSubstring4("pwwkew"));
		assertEquals(0, obj.lengthOfLongestSubstring4(""));
		assertEquals(1, obj.lengthOfLongestSubstring4(" "));
		assertEquals(3, obj.lengthOfLongestSubstring4("dvdf"));
		assertEquals(2, obj.lengthOfLongestSubstring4("abba"));
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值