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

题目描述

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

示例:

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

思路一:暴力解决法
最暴力的解决方法是这样的,遍历该字符串的所有子字符串,并去除掉所有包含重复字符的子字符串。这样的话找出的最长子串就是我们需要的答案。其中去除含有重复字符的子字符串的方法是利用hashSet逐步添加子字符串字符,若已存在则重复。
代码:

  1. public int lengthOfLongestSubstring(String s) {
  2. int n = s.length();
  3. int length = 0;
  4. for (int i = 0; i < n; i++)
  5. for (int j = i + 1; j <= n; j++)
  6. if (allUnique(s, i, j)) length = Math.max(ans, j - i);
  7. return length;
  8. }
  9. public boolean allUnique(String s, int start, int end) {
  10. Set<Character> set = new HashSet<>();
  11. for (int i = start; i < end; i++) {
  12. Character ch = s.charAt(i);
  13. if (set.contains(ch)) return false;
  14. set.add(ch);
  15. }
  16. return true;

很明显该方法时间复杂度为O(n^3),是肯定不能通过的。
思路二:hashset滑动窗口解法
思路是这样的,使用hashSet表示了一个[i j)左闭右开的滑动窗口,该滑窗表示当前子字符串。当该窗口j向右滑动时,先判断s.charAt(j)是否在HashSet中,若不在,将其放入滑窗里。如果在的话,需要将滑动窗口以存在的字符删除,并将新的字符放入。
注意,删除已存在字符的时候,该字符前面如果有字符的话也要删除。 例如hashSet中此时是{a,b,c}此时j向右滑动一位,s.charAt(j)为c,那么a会先被删除,接着是b,最后删除和s.charAt(j)相同的c,此时hashSet为空了。删除完成后,下一步就是将新的c放入hashSet。

  1. int n = s.length();
  2. Set<Character> set = new HashSet<>();
  3. int length = 0, i = 0, j = 0;
  4. while (i < n && j < n) {
  5. if (!set.contains(s.charAt(j))){
  6. set.add(s.charAt(j++));
  7. length = Math.max(ans, j - i);
  8. }
  9. else {
  10. set.remove(s.charAt(i++));
  11. }
  12. }
  13. return length;

该方法的时间复杂度为O(2n)=O(n)。

思路三:HashMap优化滑动窗口
我们很容易发现,我们可以进一步优化hashSet滑动窗口的代码,如果我们将判断重复字符的方法从遍历HashSet集合,改为使用HashMap映射的话,我们找到重复的字符时,也不用像上面一个一个的删除,直接可以跳过这些字符。我们的O(2n)步骤就变为了O(n)。

  1. int n = s.length();
  2. int length= 0;
  3. Map<Character, Integer> map = new HashMap<>();
  4. for (int j = 0, i = 0; j < n; j++) {
  5. if (map.containsKey(s.charAt(j))) {
  6. i = Math.max(map.get(s.charAt(j)), i);
  7. }
  8. length = Math.max(length, j - i + 1);
  9. map.put(s.charAt(j), j + 1);
  10. }
  11. return length;

思路四:字符数组索引
既然我们可以想到使用HashMap映射来存放子字符串,那么在字符串问题中,字符索引数组就很容易想到了。

  1. int n = s.length(), length = 0;
  2. int[] index = new int[26];
  3. for (int j = 0, i = 0; j < n; j++) {
  4. i = Math.max(index[s.charAt(j) - 'a'], i);
  5. length = Math.max(length, j - i + 1);
  6. index[s.charAt(j) - 'a'] = j + 1;
  7. }
  8. return length;

以上就是这个问题的一些解法了,答案参考了Leetcode的官方解答,有兴趣的可以自己看下
点击这里查看

Leetcode(三)无重复字符的最长子串的更多相关文章

  1. 【LeetCode】无重复字符的最长子串【滑动窗口法】

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc&quo ...

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

    难度: 中等 题目 Given a string, find the length of the longest substring without repeating characters. 给定一 ...

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

    题目链接:(https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/) 题目描述: 给定一个字符 ...

  4. 【leetcode 3. 无重复字符的最长子串】解题报告

    思路:滑动窗口的思想 方法一:滑动窗口 int lengthOfLongestSubstring(string s) { /* 控制一个滑动窗口,窗口内的字符都是不重复的,通过set可以做到判断字符是 ...

  5. LeetCode 3: 无重复字符的最长子串 Longest Substring Without Repeating Characters

    题目: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. Given a string, find the length of the longest substring withou ...

  6. 力扣Leetcode 3. 无重复字符的最长子串

    无重复字符的最长子串 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串 ...

  7. [LeetCode]3. 无重复字符的最长子串(滑动窗口)

    题目 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc ...

  8. [LeetCode]3.无重复字符的最长子串(Java)

    原题地址: longest-substring-without-repeating-characters/submissions 题目描述: 示例 1: 输入: s = "pwwkew&qu ...

  9. LeetCode OJ -- 无重复字符的最长子串

    给定一个字符串,找出不含有重复字符的 最长子串 的长度. 示例: 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3. 给定  ...

随机推荐

  1. os库新建文件夹

    file.write()可以自动生成文件但不能生成文件夹. os库生成文件夹 # 判断文件夹是否存在(./xxx/xxx) if not isExists: os.makedirs(path) pri ...

  2. 重写COMBOXEDIT

    一.需求 C#种的下拉框ComboBox不支持下拉复选框列表与下拉树形列表等,系统中需要用到的地方使用了第三方组件,现在需要将第三方组件替换掉. 二.设计 基本思路:重写ComboBox,将原生的下拉 ...

  3. jackson 字符串转对象

    ObjectMapper mapper = new ObjectMapper(); Map<String, Object> map = mapper.readValue(str, Map. ...

  4. 5. Go函数

    [定义函数] 直接上一个栗子,Go语言定义函数: func add(a int, b int) int { return a + b } 一目了然,还不太习惯Go语言的命名方式, 类型为什么要写到后面 ...

  5. [leetcode]61. Rotate List旋转链表

    Given a linked list, rotate the list to the right by k places, where k is non-negative. Example 1: I ...

  6. 【转】重写Equals为什么要同时重写GetHashCode

    .NET程序员都知道,如果我们重写一个类的Equals方法而没有重写GetHashCode,则VS会提示警告 :“***”重写 Object.Equals(object o)但不重写 Object.G ...

  7. 关于Android UI 优化

    之前项目为了同时兼容tv和手机端的UI,使用了百分比布局来动态计算控件的宽高,这种适配方案只关心屏幕的宽高(分辨率),与屏幕的像素密度无关. 在新的项目里也使用了这种方案.但是由于项目的运行硬件计算能 ...

  8. JS整理--闭包

    1.闭包可以访问当前函数以外的变量 function a(){ var date="1"; function b(str){ console.log(str+date) } ret ...

  9. MySQL加入log_bin报错

    MySQL中二进制日志功能默认是关闭的,查看各种开启方式后,确定在配置文件中加入如下配置来开启该功能: [root@bogon /]# more /etc/my.cnf [mysqld] datadi ...

  10. Python实现对CSV文件的读写功能

    我们要处理csv文件,首先要的导入csv模块 import csv #读取csv文件def readCsv(path): #传入变量csv文件的路径 list=[] #定义一个空列表 with ope ...