不包含重复字符的最长子串的长度

100 阅读10分钟

不包含重复字符的最长子串的长度

给定一个字符串str,求最长不包含重复字符的子串的长度。

例子:

示例1: 输入:“ABCDEFGABEF”
输出:7
解释:最长的没有重复字符的子串是“ABCDEFG”、“BCDEFGA”和“CDEFGAB”,长度为7

示例2: 输入:“GEEKSFORGEEKS”
输出:7
解释:最长的无重复字符的子串是“EKSFORG”和“KSFORGE”,长度为7


使用滑动窗口在 O(n^3) 时间内求出最长的无重复字符子串的长度:(暴力解法)

逐一考虑所有子字符串,并检查每个子字符串是否包含所有唯一字符。将有 n*(n-1)/2 个子串。通过从左到右扫描子字符串并保留访问过的字符的映射,可以在线性时间内检查子字符串是否包含所有唯一字符。

下面是上述方法的实现:

C++

// C++ program to find the length of the longest substring
// without repeating characters
#include <bits/stdc++.h>
using namespace std;
 
// This function returns true if all characters in str[i..j]
// are distinct, otherwise returns false
bool areDistinct(string str, int i, int j)
{
 
    // Note : Default values in visited are false
    vector<bool> visited(256);
 
    for (int k = i; k <= j; k++) {
        if (visited[str[k]] == true)
            return false;
        visited[str[k]] = true;
    }
    return true;
}
 
// Returns length of the longest substring
// with all distinct characters.
int longestUniqueSubsttr(string str)
{
    int n = str.size();
    int res = 0; // result
    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++)
            if (areDistinct(str, i, j))
                res = max(res, j - i + 1);
    return res;
}
 
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}

C

// C program to find the length of the longest substring
// without repeating characters
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
 
// Find maximum between two numbers.
int max(int num1, int num2)
{
    return (num1 > num2) ? num1 : num2;
}
 
// This function returns true if all characters in str[i..j]
// are distinct, otherwise returns false
bool areDistinct(char str[], int i, int j)
{
 
    // Note : Default values in visited are false
    bool visited[256];
    for (int i = 0; i < 256; i++)
        visited[i] = 0;
 
    for (int k = i; k <= j; k++) {
        if (visited[str[k]] == true)
            return false;
        visited[str[k]] = true;
    }
    return true;
}
 
// Returns length of the longest substring
// with all distinct characters.
int longestUniqueSubsttr(char str[])
{
    int n = strlen(str);
    int res = 0; // result
    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++)
            if (areDistinct(str, i, j))
                res = max(res, j - i + 1);
    return res;
}
 
// Driver code
int main()
{
    char str[] = "geeksforgeeks";
    printf("The input string is %s \n", str);
    int len = longestUniqueSubsttr(str);
    printf("The length of the longest non-repeating "
           "character substring is %d",
           len);
    return 0;
}

Java

// Java program to find the length of the
// longest substring without repeating
// characters
import java.io.*;
import java.util.*;
 
class GFG {
 
    // This function returns true if all characters in
    // str[i..j] are distinct, otherwise returns false
    public static Boolean areDistinct(String str, int i,
                                      int j)
    {
 
        // Note : Default values in visited are false
        boolean[] visited = new boolean[256];
 
        for (int k = i; k <= j; k++) {
            if (visited[str.charAt(k)] == true)
                return false;
 
            visited[str.charAt(k)] = true;
        }
        return true;
    }
 
    // Returns length of the longest substring
    // with all distinct characters.
    public static int longestUniqueSubsttr(String str)
    {
        int n = str.length();
 
        // Result
        int res = 0;
 
        for (int i = 0; i < n; i++)
            for (int j = i; j < n; j++)
                if (areDistinct(str, i, j))
                    res = Math.max(res, j - i + 1);
 
        return res;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String str = "geeksforgeeks";
        System.out.println("The input string is " + str);
 
        int len = longestUniqueSubsttr(str);
 
        System.out.println("The length of the longest "
                           + "non-repeating character "
                           + "substring is " + len);
    }
}
 

C#

// C# program to find the length of the
// longest substring without repeating
// characters
using System;
 
class GFG {
 
    // This function returns true if all characters in
    // str[i..j] are distinct, otherwise returns false
    public static bool areDistinct(string str, int i, int j)
    {
 
        // Note : Default values in visited are false
        bool[] visited = new bool[256];
 
        for (int k = i; k <= j; k++) {
            if (visited[str[k]] == true)
                return false;
 
            visited[str[k]] = true;
        }
        return true;
    }
 
    // Returns length of the longest substring
    // with all distinct characters.
    public static int longestUniqueSubsttr(string str)
    {
        int n = str.Length;
 
        // Result
        int res = 0;
 
        for (int i = 0; i < n; i++)
            for (int j = i; j < n; j++)
                if (areDistinct(str, i, j))
                    res = Math.Max(res, j - i + 1);
 
        return res;
    }
 
    // Driver code
    public static void Main()
    {
        string str = "geeksforgeeks";
        Console.WriteLine("The input string is " + str);
 
        int len = longestUniqueSubsttr(str);
 
        Console.WriteLine("The length of the longest "
                          + "non-repeating character "
                          + "substring is " + len);
    }
}
 

Javascript

// JavaScript program to find the length of the
// longest substring without repeating
// characters
// This function returns true if all characters in
// str[i..j] are distinct, otherwise returns false
function areDistinct(str, i, j)
{
     
    // Note : Default values in visited are false
    var visited = new Array(256);
 
    for(var k = i; k <= j; k++)
    {
        if (visited[str.charAt(k) ] == true)
            return false;
             
        visited[str.charAt(k)] = true;
    }
    return true;
}
 
// Returns length of the longest substring
// with all distinct characters.
function longestUniqueSubsttr(str)
{
    var n = str.length;
     
    // Result
    var res = 0; 
     
    for(var i = 0; i < n; i++)
        for(var j = i; j < n; j++)
            if (areDistinct(str, i, j))
                res = Math.max(res, j - i + 1);
                 
    return res;
}
 
// Driver code
    var str = "geeksforgeeks";
    console.log("The input string is " + str);
 
    var len = longestUniqueSubsttr(str);
     
    console.log("The length of the longest " +
                       "non-repeating character " + 
                       "substring is " + len);
 

Python

# Python3 program to find the length
# of the longest substring without
# repeating characters
 
# This function returns true if all
# characters in str[i..j] are
# distinct, otherwise returns false
 
 
def areDistinct(str, i, j):
 
    # Note : Default values in visited are false
    visited = [0] * (256)
 
    for k in range(i, j + 1):
        if (visited[ord(str[k])] == True):
            return False
 
        visited[ord(str[k])] = True
 
    return True
 
# Returns length of the longest substring
# with all distinct characters.
 
 
def longestUniqueSubsttr(str):
 
    n = len(str)
 
    # Result
    res = 0
 
    for i in range(n):
        for j in range(i, n):
            if (areDistinct(str, i, j)):
                res = max(res, j - i + 1)
 
    return res
 
 
# Driver code
if __name__ == '__main__':
 
    str = "geeksforgeeks"
    print("The input is ", str)
 
    len = longestUniqueSubsttr(str)
    print("The length of the longest "
          "non-repeating character substring is ", len)
 

输出

The input string is geeksforgeeks
The length of the longest non-repeating character substring is 7

时间复杂度:O(n^3),因为我们正在处理最大长度为 n 的 n*(n-1)/2 个子字符串。
辅助空间:O(1)

使用滑动窗口在 O(n^2) 时间内求出最长的无重复字符子串的长度:

对于每个索引 i,找到从索引 i 开始的、不存在重复字符的最长子串的长度。这可以通过从索引 i 开始,迭代直到字符串末尾来完成,如果在字符串末尾之前找到重复字符,我们将中断,否则如果当前子字符串较大,则更新答案。

下面是上述方法的实现:

C++

// C++ program to find the length of the longest substring
// without repeating characters
#include <bits/stdc++.h>
using namespace std;
 
int longestUniqueSubsttr(string str)
{
    int n = str.size();
    int res = 0; // result
 
    for (int i = 0; i < n; i++) {
 
        // Note : Default values in visited are false
        vector<bool> visited(256);
 
        for (int j = i; j < n; j++) {
 
            // If current character is visited
            // Break the loop
            if (visited[str[j]] == true)
                break;
 
            // Else update the result if
            // this window is larger, and mark
            // current character as visited.
            else {
                res = max(res, j - i + 1);
                visited[str[j]] = true;
            }
        }
 
        // Remove the first character of previous
        // window
        visited[str[i]] = false;
    }
    return res;
}
 
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}

Java

// Java program to find the length of the
// longest substring without repeating
// characters
import java.io.*;
import java.util.*;
 
class GFG {
 
    public static int longestUniqueSubsttr(String str)
    {
        int n = str.length();
 
        // Result
        int res = 0;
 
        for (int i = 0; i < n; i++) {
 
            // Note : Default values in visited are false
            boolean[] visited = new boolean[256];
 
            for (int j = i; j < n; j++) {
 
                // If current character is visited
                // Break the loop
                if (visited[str.charAt(j)] == true)
                    break;
 
                // Else update the result if
                // this window is larger, and mark
                // current character as visited.
                else {
                    res = Math.max(res, j - i + 1);
                    visited[str.charAt(j)] = true;
                }
            }
 
            // Remove the first character of previous
            // window
            visited[str.charAt(i)] = false;
        }
        return res;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String str = "geeksforgeeks";
        System.out.println("The input string is " + str);
 
        int len = longestUniqueSubsttr(str);
        System.out.println("The length of the longest "
                           + "non-repeating character "
                           + "substring is " + len);
    }
}
 

C#

// C# program to find the length of the
// longest substring without repeating
// characters
using System;
 
class GFG {
 
    static int longestUniqueSubsttr(string str)
    {
        int n = str.Length;
 
        // Result
        int res = 0;
 
        for (int i = 0; i < n; i++) {
 
            // Note : Default values in visited are false
            bool[] visited = new bool[256];
 
            // visited = visited.Select(i =>
            // false).ToArray();
            for (int j = i; j < n; j++) {
 
                // If current character is visited
                // Break the loop
                if (visited[str[j]] == true)
                    break;
 
                // Else update the result if
                // this window is larger, and mark
                // current character as visited.
                else {
                    res = Math.Max(res, j - i + 1);
                    visited[str[j]] = true;
                }
            }
 
            // Remove the first character of previous
            // window
            visited[str[i]] = false;
        }
        return res;
    }
 
    // Driver code
    static void Main()
    {
        string str = "geeksforgeeks";
        Console.WriteLine("The input string is " + str);
 
        int len = longestUniqueSubsttr(str);
        Console.WriteLine("The length of the longest "
                          + "non-repeating character "
                          + "substring is " + len);
    }
}
 

Javascript

// JavaScript program to find the length of the 
// longest substring without repeating
// characters
 
function longestUniqueSubsttr(str)
{
    var n = str.length;
     
    // Result
    var res = 0;
     
    for(var i = 0; i < n; i++)
    {
         
        // Note : Default values in visited are false
        var visited = new Array(256);
         
        for(var j = i; j < n; j++)
        {
             
            // If current character is visited
            // Break the loop
            if (visited[str.charCodeAt(j)] == true)
                break;
 
            // Else update the result if
            // this window is larger, and mark
            // current character as visited.
            else
            {
                res = Math.max(res, j - i + 1);
                visited[str.charCodeAt(j)] = true;
            }
        }
    }
    return res;
}
 
// Driver code
    var str = "geeksforgeeks";
    console.log("The input string is " + str);
 
    var len = longestUniqueSubsttr(str);
    console.log("The length of the longest " +
                       "non-repeating character " +
                       "substring is " + len);
  

Python

# Python3 program to find the
# length of the longest substring
# without repeating characters
 
 
def longestUniqueSubsttr(str):
 
    n = len(str)
 
    # Result
    res = 0
 
    for i in range(n):
 
        # Note : Default values in
        # visited are false
        visited = [0] * 256
 
        for j in range(i, n):
 
            # If current character is visited
            # Break the loop
            if (visited[ord(str[j])] == True):
                break
 
            # Else update the result if
            # this window is larger, and mark
            # current character as visited.
            else:
                res = max(res, j - i + 1)
                visited[ord(str[j])] = True
 
        # Remove the first character of previous
        # window
        visited[ord(str[i])] = False
 
    return res
 
 
# Driver code
str = "geeksforgeeks"
print("The input is ", str)
 
len = longestUniqueSubsttr(str)
print("The length of the longest "
      "non-repeating character substring is ", len)
 

输出

The input string is geeksforgeeks
The length of the longest non-repeating character substring is 7

时间复杂度:O(n^2) 辅助空间:O(1)

使用滑动窗口计算无重复字符的最长子串的长度:

使用此解决方案,可以在线性时间内解决问题。

请按照以下步骤解决问题:

  • 用0初始化左右两个指针,定义当前正在考虑的窗口。
  • 右指针从左向右移动,扩展当前窗口, 直至出现重复字符。
  • 左指针向右移动,直到重复字符不再是当前窗口的一部分。
  • 计算当前窗口的长度(右 - 左 + 1)并相应更新答案。

下面是上述方法的实现:

C++

#include <iostream>
#include <string>
using namespace std;
 
int longestUniqueSubsttr(string str)
{
    // if string length is 0
    if (str.length() == 0)
        return 0;
 
    // if string length 1
    if (str.length() == 1)
        return 1;
 
    // if string length is more than 2
    int maxLength = 0;
    bool visited[256] = { false };
 
    // left and right pointer of sliding window
    int left = 0, right = 0;
    while (right < str.length()) {
 
        // if character is visited
        if (visited[str[right]] == true) {
 
            // The left pointer moves to the right while
            // marking visited characters as false until the
            // repeating character is no longer part of the
            // current window.
            while (visited[str[right]] == true) {
 
                visited[str[left]] = false;
                left++;
            }
        }
 
        visited[str[right]] = true;
 
        // The length of the current window (right - left +
        // 1) is calculated and answer is updated
        // accordingly.
        maxLength = max(maxLength, (right - left + 1));
        right++;
    }
    return maxLength;
}
 
// Driver code
int main()
{
    string str = "geeksforgeeks";
    cout << "The input string is " << str << endl;
    int len = longestUniqueSubsttr(str);
    cout << "The length of the longest non-repeating "
            "character substring is "
         << len;
    return 0;
}

Java

import java.io.*;
 
class GFG {
    public static int longestUniqueSubsttr(String str)
    {
        // if string length is 0
        if (str.length() == 0)
            return 0;
 
        // if string length 1
        if (str.length() == 1)
            return 1;
 
        // if string length is more than 2
        int maxLength = 0;
        boolean[] visited = new boolean[256];
 
        // left and right pointer of sliding window
        int left = 0, right = 0;
        while (right < str.length()) {
 
            // if character is visited
            if (visited[str.charAt(right)]) {
 
                // The left pointer moves to the right while
                // marking visited characters as false until
                // the repeating character is no longer part
                // of the current window.
                while (visited[str.charAt(right)]) {
 
                    visited[str.charAt(left)] = false;
                    left++;
                }
            }
 
            visited[str.charAt(right)] = true;
 
            // The length of the current window (right -
            // left + 1) is calculated and answer is updated
            // accordingly.
            maxLength
                = Math.max(maxLength, (right - left + 1));
            right++;
        }
        return maxLength;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String str = "geeksforgeeks";
        System.out.println("The input string is " + str);
 
        int len = longestUniqueSubsttr(str);
        System.out.println("The length of the longest "
                           + "non-repeating character "
                           + "substring is " + len);
    }
}

C#

// Include namespace system
using System;
 
public class GFG {
 
    public static int LongestUniqueSubsttr(string str)
    {
 
        // if string length is 0
        if (str.Length == 0)
            return 0;
 
        // if string length 1
        if (str.Length == 1)
            return 1;
 
        // if string length is more than 2
        int maxLength = 0;
        bool[] visited = new bool[256];
 
        // left and right pointer of sliding window
        int left = 0, right = 0;
        while (right < str.Length) {
 
            // if character is visited
            if (visited[str[right]]) {
 
                // The left pointer moves to the right
                // while marking visited characters as
                // false until the repeating character
                // is no longer part of the current
                // window.
                while (visited[str[right]]) {
 
                    visited[str[left]] = false;
                    left++;
                }
            }
 
            visited[str[right]] = true;
 
            // The length of the current window (right -
            // left + 1) is calculated and the answer is
            // updated accordingly.
            maxLength
                = Math.Max(maxLength, right - left + 1);
            right++;
        }
 
        return maxLength;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        var str = "geeksforgeeks";
        Console.WriteLine("The input string is " + str);
        var len = GFG.LongestUniqueSubsttr(str);
        Console.WriteLine("The length of the longest "
                          + "non-repeating character "
                          + "substring is "
                          + len.ToString());
    }
}

Javascript

function longestUniqueSubsttr(str) {
    // if string length is 0
    if (str.length === 0)
        return 0;
 
    // if string length 1
    if (str.length === 1)
        return 1;
 
    // if string length is more than 2
    let maxLength = 0;
    let visited = new Array(256).fill(false);
 
    // left and right pointer of sliding window
    let left = 0, right = 0;
    while (right < str.length) {
 
        // if character is visited
        if (visited[str.charCodeAt(right)]) {
 
            // The left pointer moves to the right while
            // marking visited characters as false until the
            // repeating character is no longer part of the
            // current window.
            while (visited[str.charCodeAt(right)]) {
                visited[str.charCodeAt(left)] = false;
                left++;
            }
        }
 
        visited[str.charCodeAt(right)] = true;
 
        // The length of the current window (right - left + 1)
        // is calculated and the answer is updated accordingly.
        maxLength = Math.max(maxLength, right - left + 1);
        right++;
    }
 
    return maxLength;
}
 
 
    let s = "geeksforgeeks";
    console.log("The input string is " + s);
    console.log("The length of the longest non-repeating "+
            "character substring is "+ longestUniqueSubsttr(s));   
      

Python

import math
 
 
def longestUniqueSubsttr(s):
    # if string length is 0
    if len(s) == 0:
        return 0
 
    # if string length 1
    if len(s) == 1:
        return 1
 
    # if string length is more than 2
    maxLength = 0
    visited = [False] * 256
 
    # left and right pointer of sliding window
    left, right = 0, 0
    while right < len(s):
 
        # if character is visited
        if visited[ord(s[right])]:
 
            # The left pointer moves to the right while
            # marking visited characters as false until the
            # repeating character is no longer part of the
            # current window.
            while visited[ord(s[right])]:
 
                visited[ord(s[left])] = False
                left += 1
 
        visited[ord(s[right])] = True
 
        # The length of the current window (right - left + 1)
        # is calculated and the answer is updated accordingly.
        maxLength = max(maxLength, right - left + 1)
        right += 1
 
    return maxLength
 
 
# Driver Code
string = "geeksforgeeks"
print("The input string is", string)
length = longestUniqueSubsttr(string)
print("The length of the longest non-repeating character substring is", length)

输出

The input string is geeksforgeeks
The length of the longest non-repeating character substring is 7

时间复杂度:O(n)
辅助空间:O(1)