元音包含偶数次的最长字符字串(java)

问题描述:

给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 ‘a’,‘e’,‘i’,‘o’,‘u’ ,在子字符串中都恰好出现了偶数次。

样例:

在这里插入图片描述
思路分析:
(1)刚开始没啥思路最直接的方法就是暴力破解法,直接二层循环解决。但是不出意外的超时了。
(2)看了官方解答后,它是利用前缀和、二进制、异或解决的。利用前缀和解决元素个数,利用二进制表示状态,利用异或解决元音字母偶数。

具体见代码注释:

package Leetcode;
import java.util.Arrays;
import java.util.Scanner;
public class Yyzczic {
    //元音包含偶数次的最长字符字串

    public static boolean check(String s)//判断字串是否符合情况
    {
        int value=0;
        for (int j = 0; j <s.length() ; j++) {
            if (s.charAt(j)=='a')
            {
                value++;
            }
        }
        if (value%2!=0)
            return false;
        for (int j = 0; j <s.length() ; j++) {
            if (s.charAt(j)=='e')
            {
                value++;
            }
        }
        if (value%2!=0)
            return false;
        for (int j = 0; j <s.length() ; j++) {
            if (s.charAt(j)=='i')
            {
                value++;
            }
        }
        if (value%2!=0)
            return false;
        for (int j = 0; j <s.length() ; j++) {
            if (s.charAt(j)=='o')
            {
                value++;
            }
        }
        if (value%2!=0)
            return false;
        for (int j = 0; j <s.length() ; j++) {
            if (s.charAt(j)=='u')
            {
                value++;
            }
        }
        if (value%2!=0)
            return false;
        return true;
    }
    public static int findTheLongestSubstring(String s) {//暴力破解法
        int max=0;
        int len=s.length();
        for (int i = 0; i <len ; i++) {
            for (int j =i+1; j <=len ; j++) {
                String temp=s.substring(i,j);
                if (check(temp))
                {
                    int templen=j-i;
                    if (templen>max)
                        max=templen;
                }
            }
        }
        return max;
    }
    public static int findTheLongestSubstring1(String s) {//前缀法
      int[] statusMinPos = new int[1 << 5];
        //初始化为非法下标
        Arrays.fill(statusMinPos, -1);
        //状态00000对应的最小位置显然是0
        statusMinPos[0] = 0;
        int ans = 0;
        int curStatus = 0;
        for (int i = 0; i < s.length(); i++) {
            switch (s.charAt(i)) {
                case 'a': {
                    curStatus ^=(1<<1);
                }
                break;
                case 'e': {
                    curStatus ^= (1<<2);
                }
                break;
                case 'i': {
                    curStatus ^= (1<<3);
                }
                break;
                case 'o': {
                    curStatus ^= (1<<4);
                }
                break;
                case 'u': {
                    curStatus ^= (1<<5);
                }
                break;
            }
            if (statusMinPos[curStatus] != -1) {
                //该状态之前出现过,计算当前与之前出现的最小下标的距离
                ans = Math.max(ans, i + 1 - statusMinPos[curStatus]);
            } else {
                //该状态未出现过,记录下一个位置。
                statusMinPos[curStatus] = i + 1;
            }
        }
        return ans;
    }


    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        String s=scanner.nextLine();
        System.out.println(findTheLongestSubstring1(s));
        System.out.println(findTheLongestSubstring(s));
    }
}

暴力破解会在如下出现超时:

在这里插入图片描述执行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lianggege88

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值