LeetCode.No3——无重复字符的最长子串

题目

  • 给定一个字符串,找出其中不含有重复字符的最长子串的长度
  • 例:
  • 输入:“abcabcbb”
  • 输出:3

解法一:暴力

一开始看到这道题目的时候,很容易地想到了暴力解法,即从头开始进行扫描。
算法步骤:

    1. 从头到尾扫描一次s,用一个数组记录其中不同字符的总数量,存储总不同的字符数。
    1. 从第 i (i从0开始)个字符开始扫描
    1. 不存在重复时,则子串长度加一,j (子字符串的扫描指针)指针右移;扫描到重复时,则开始判断此时的子串长度是否比当前记录的子串长度长,以及为依据判断是否记录当前子串长度,然后母串的指针从 i + 1的位置开始重新扫描。
    1. 重复 2、3步骤,直到 i == s.length 或 当前子串的长度等于给定字符串中的不同字符数,则结束。
      这算法相当于每次判断到重复字符时,都需要进行回溯,时间复杂度较大。
  • 算法复杂度:O(n)~O(n^2),我觉得是O(n ^2),但是跑起来不慢。
package com.company;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // write your code here
        int length;
        String s;
        Scanner in = new Scanner(System.in);
        System.out.println("Please input the String");
        s = in.nextLine();
        length = lengthOfLongestSubstring(s);
        System.out.println(length);
    }

    public static int lengthOfLongestSubstring(String s) {
        char[] array = new char[100];
        char[] s_change = s.toCharArray();
        int k = 0;
        int biggest_count = 0;
        int length_of_substring = 0;
        int length_temp = 0;
        int i = 0;
        boolean similar = false;

        //计算有可能的最大子串数
        for (i = 0; i < s_change.length; i++) {
            for (int j = 0; j < biggest_count; j++) {
                if (array[j] == s_change[i]) {
                    similar = true;
                }
            }
            if (similar == false) {
                array[biggest_count] = s_change[i];
                biggest_count++;
            } else {
                similar = false;
            }
        }

        //寻找最大子串数,当目前扫描的子串数等于最大的可能子串数或扫描完成时,退出。
        while (k < s_change.length && length_of_substring < biggest_count) {
            for (i = k; i < s_change.length; i++) {
                //跟子串进行对比
                for (int j = 0; j < length_temp; j++) {
                    if (array[j] == s_change[i]) {
                        similar = true;
                        break;
                    }
                }
                //不存在重复时进行加一
                if (similar == false) {
                    array[length_temp] = s_change[i];
                    length_temp++;
                } else//存在重复时的操作
                {
                    similar = false;
                    break;
                }
            }
            if (i == s_change.length) {
                k = i - 1;
            }
            //选出最长的子串
            if (length_temp > length_of_substring) {
                length_of_substring = length_temp;
            }
            length_temp = 0;
            k++;
        }
        return length_of_substring;
    }
}

解法二:简单类型的滑窗算法

此算法为后续学习来的,故记录
算法

  • 定义的关键数据意义:1.此算法需要两个 int 型变量作为指针,分别作为“窗户”的左右,故定义了 left 和 right。2.其次需要额外开一个数组count [ ] ,大小大于ASCII码表的数,因为后续需要用到count [ ] 数组来记录字符在s中出现的次数,其中,以字符本身的ACSII码作为下标。
    1. 右指针 right 从 s[0] 开始,向右扫描,每扫描到字符时,将字符的ACSII码在count中对应的位置 + 1;
    1. 此时判断该字符的ASCII码在count中记录的数量是否 == 2(等于 2 则说明扫描到了重复的字符):若为2,此时记录该字符的ACSII码(后面判断需要),得到子串长度,判断是否为目前最长;若不为2,则重复 1 步骤,直到扫描完毕。
    1. 将左指针对饮的字符的ACSII码在count中 - 1,左指针右移,直到上面记录的count[ position ] 不为2时,则重复1步骤。
  • 算法复杂度:O(n)
package com.company;

import java.util.Scanner;

public class Main
{
    public static void main(String[] args)
    {
        // write your code here
        int length;
        String s;
        Scanner in = new Scanner(System.in);
        System.out.println("Please input the String");
        s = in.nextLine();
        length = lengthOfLongestSubstring(s);
        System.out.println(length);
    }
    //滑窗法寻找最长不重复字符串
    public static int lengthOfLongestSubstring(String s)
    {
        int left = 0,right = 0;
        int max_substring_length = 0;
        int temp_substring_length = 0;
        int []count = new int[150];//用于记录字符出现的次数
        char []s_change = s.toCharArray();
        int position = 0;
        //开始进行扫描
        while (right < s_change.length)
        {
            //以字符的ACSII码作为下标
            count[s_change[right]] ++;
            //右指针右移
            if(count[s_change[right]] == 2)//当出现重复字母时
            {
                position = s_change[right];
                temp_substring_length = right - left;
                if(temp_substring_length > max_substring_length)//判断子串长度
                {
                    max_substring_length = temp_substring_length;
                }
            }
            right ++;
            //当出现重复的字符时,左指针右移,直到将重复的字符不包括在区间
            while (count[position] == 2 )
            {
                count[s_change[left]] --;
                left ++;
            }
        }
        if(right == s_change.length)
        {
            temp_substring_length = right -left;
            if(temp_substring_length > max_substring_length)
            {
                max_substring_length = temp_substring_length;
            }
        }
        return max_substring_length;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值