• 《剑指offer》第四十八题:最长不含重复字符的子字符串


    // 面试题48:最长不含重复字符的子字符串
    // 题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子
    // 字符串的长度。假设字符串中只包含从'a'到'z'的字符。
    
    #include <string>
    #include <iostream>
    
    // 方法一:蛮力法
    bool hasDuplication(const std::string& str, int position[]);
    
    int longestSubstringWithoutDuplication_1(const std::string& str)
    {
        int length = str.length();
        int longest = 0;
        int* position = new int[26];  //26个字母
    
        for (int start = 0; start < length; ++start)
        {
            for (int end = start; end < length; ++end)
            {
                int count = end - start + 1;
                const std::string& substring = str.substr(start, count); //裁剪出子字符串
                if (!hasDuplication(substring, position))
                {
                    if (count > longest)
                        longest = count;
                }
                else
                    break;
            }
        }
        delete[] position;
    
        return longest;
    }
    
    bool hasDuplication(const std::string& str, int position[])
    {
        for (int i = 0; i < 26; ++i)
            position[i] = -1;
    
        for (int i = 0; i < str.length(); ++i)
        {
            int indexInPosition = str[i] - 'a';
            if (position[indexInPosition] >= 0)  //字符串出现过2次以上
                return true;
    
            position[indexInPosition] = indexInPosition;
        }
    
        return false;
    }
    
    // 方法二:动态规划
    int longestSubstringWithoutDuplication_2(const std::string& str)
    {
        int maxLength = 0;
        int curLength = 0;
    
        //每个字母上一次出现的位置
        int* position = new int[26];
        for (int i = 0; i < 26; ++i)
            position[i] = -1;
    
        for (int i = 0; i < str.length(); ++i)
        {
            int indexPrev = position[str[i] - 'a'];  //该字母上次出现的位置
            if (indexPrev < 0 || i - indexPrev > curLength)  //当前字母未出现过, 或上次出现在当前序列外
                ++curLength;
            else
            {
                if (curLength > maxLength)
                    maxLength = curLength;
    
                curLength = i - indexPrev; //否则以当前字母上次出现的位置后到当前字母位置作为当前长度
            }
            position[str[i] - 'a'] = i;  //更新位置索引
        }
        
        if (curLength > maxLength)
            maxLength = curLength;
    
        delete[] position;
    
        return maxLength;
    }
    // ====================测试代码====================
    void testSolution1(const std::string& input, int expected)
    {
        int output = longestSubstringWithoutDuplication_1(input);
        if (output == expected)
            std::cout << "Solution 1 passed, with input: " << input << std::endl;
        else
            std::cout << "Solution 1 FAILED, with input: " << input << std::endl;
    }
    
    void testSolution2(const std::string& input, int expected)
    {
        int output = longestSubstringWithoutDuplication_2(input);
        if (output == expected)
            std::cout << "Solution 2 passed, with input: " << input << std::endl;
        else
            std::cout << "Solution 2 FAILED, with input: " << input << std::endl;
    }
    
    void test(const std::string& input, int expected)
    {
        testSolution1(input, expected);
        testSolution2(input, expected);
    }
    
    void test1()
    {
        const std::string input = "abcacfrar";
        int expected = 4;
        test(input, expected);
    }
    
    void test2()
    {
        const std::string input = "acfrarabc";
        int expected = 4;
        test(input, expected);
    }
    
    void test3()
    {
        const std::string input = "arabcacfr";
        int expected = 4;
        test(input, expected);
    }
    
    void test4()
    {
        const std::string input = "aaaa";
        int expected = 1;
        test(input, expected);
    }
    
    void test5()
    {
        const std::string input = "abcdefg";
        int expected = 7;
        test(input, expected);
    }
    
    void test6()
    {
        const std::string input = "aaabbbccc";
        int expected = 2;
        test(input, expected);
    }
    
    void test7()
    {
        const std::string input = "abcdcba";
        int expected = 4;
        test(input, expected);
    }
    
    void test8()
    {
        const std::string input = "abcdaef";
        int expected = 6;
        test(input, expected);
    }
    
    void test9()
    {
        const std::string input = "a";
        int expected = 1;
        test(input, expected);
    }
    
    void test10()
    {
        const std::string input = "";
        int expected = 0;
        test(input, expected);
    }
    
    int main(int argc, char* argv[])
    {
        test1();
        test2();
        test3();
        test4();
        test5();
        test6();
        test7();
        test8();
        test9();
        test10();
    
        return 0;
    }
    测试代码

    分析:动态规划,递归。

  • 相关阅读:
    Java的值传递机制
    面向对象
    java中static关键字的作用
    方法的重载和重写
    this和super的用法
    Java中关于return的理解
    java经典的内存图 (数据结构)
    java IO最让初学者误解的取名方式
    UDP 与 TCP简单入门理解示例
    Shiro简单入门
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12636233.html
Copyright © 2020-2023  润新知