• 面试题:求给定字符串中最长无重复子字符串的长度。


    题干:

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

    Examples:

    Given "abcabcbb", the answer is "abc", which the length is 3.

    Given "bbbbb", the answer is "b", with the length of 1.

    Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.


    解法一:

    列出所有字符串,并判断是否有重复字符。(最直观的方法,但是运算量极大,不要用)

    public class Solution {
        public int lengthOfLongestSubstring(String s) {
            int n = s.length();
            int ans = 0;
            for (int i = 0; i < n; i++)
                for (int j = i + 1; j <= n; j++)
                    if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
            return ans;
        }
    
        public boolean allUnique(String s, int start, int end) {
            Set<Character> set = new HashSet<>();
            for (int i = start; i < end; i++) {
                Character ch = s.charAt(i);
                if (set.contains(ch)) return false;
                set.add(ch);
            }
            return true;
        }
    }
    

    解法二:

    利用HashSet做划窗来判断字符唯一性。(用这个)

    public class LengthOfLongestSubstring3 {
    	/*
    	 * 思路:
    	 * 	用Set做一个范围为 [i,j)的划窗(利用Set检查char的唯一性)。
    	 * 	在确定s[i,j-1]没有重复字符的情况下,只需检查s[j]是否存在于s[i,j-1]中就可以了。
    	 * 	如果s[j]存在于s[i,j-1]中,那么划窗变为 [i+1,j),继续检查。
    	 * 
    	 **/
    	public int lengthOfLongestSubstring(String s) {
    		int n = s.length();
    		Set<Character> set = new HashSet<>();
    		int ans = 0, i = 0, j = 0;
    		while (i < n && j < n) {
    			// try to extend the range [i, j]
    			if (!set.contains(s.charAt(j))) {
    				// 此处是根据角标j来遍历,一个一个的往里存
    				set.add(s.charAt(j++));
    				ans = Math.max(ans, j - i);//注意这里为什么是j-1而不是j-i+1呢?因为j已经++了
    			} else {
    				set.remove(s.charAt(i++));
    			}
    		}
    		return ans;
    	}
    }
    

    思考:整个流程中,角标是如何变化的?以及while(i<n & j<n)配合i++和j++这种代码结构。


    解法三:

    利用HashMap建立{字符-索引}的映射,降低找重复时的时间复杂度(优解但是不太好想)

    public class Solution {
    	/*
    	 * 思路: 使用HashMap存放{字符-索引}的映射,当我们发现重复的字符时,直接跳过这些字符。
    	 * 通过遍历j来循环。如果遍历到j时,s[i,j)中有重复元素s[j],我们不再一点一点移动i的位置了,
    	 * 若重复元素角标为j',直接跳过[i,j′]这个区间即可,直接将i赋值为j'+1。
    	 * 
    	 */
    	public int lengthOfLongestSubstring(String s) {
    		int n = s.length(), ans = 0;
    		// Hashmap中存放的是 字符-索引
    		Map<Character, Integer> map = new HashMap<>();
    		// try to extend the range [i, j]
    		for (int j = 0, i = 0; j < n; j++) {
    			if (map.containsKey(s.charAt(j))) {
    				// 如果map里已经有这个index[j]处的char,将i赋成j+1。
    				i = Math.max(map.get(s.charAt(j)) + 1, i);
    			}
    			// 注意这里的max,适用于“abba”这种情况,“a”虽然存在于map中了,但i也不移动
    			ans = Math.max(ans, j - i + 1);
    			// 将char加入哈希表中,value为索引值j。
    			map.put(s.charAt(j), j);
    		}
    		return ans;
    	}
    }

      思考:怎么用一次循环完成整个算法的?想清楚整个流程中两个索引i,j是怎么变化的。

          *注意max*

  • 相关阅读:
    Centos7配置编译Tenflow1.15 GPU版本笔记
    今年有哪些便宜的国外域名注册商?
    VPS,域名,主机,建站主题,2020黑色星期五优惠大放送
    这些个挂机项目,赚点小钱玩玩
    WPF管理系统开发框架搭建指南,2020从入门到放弃
    智和信通助力荆门电教馆及六所市直学校实现网络智能化运维管理
    智和网管平台政企信创网管监控运维可视化方案
    智和网管平台与统信操作系统完成认证 强力支撑信创国产替代进程
    GIT基础操作与理解
    高数复习一(数列极限)
  • 原文地址:https://www.cnblogs.com/kkkky/p/7687083.html
Copyright © 2020-2023  润新知