2021-04-28

1839. 所有元音按顺序排布的最长子字符串

当一个字符串满足如下条件时,我们称它是 美丽的 :

  • 所有 5 个英文元音字母('a' ,'e' ,'i' ,'o' ,'u')都必须 至少 出现一次。
  • 这些元音字母的顺序都必须按照 字典序 升序排布(也就是说所有的 'a' 都在 'e' 前面,所有的 'e' 都在 'i' 前面,以此类推)

比方说,字符串 "aeiou" 和 "aaaaaaeiiiioou" 都是 美丽的 ,但是 "uaeio" ,"aeoiu" 和 "aaaeeeooo" 不是美丽的 。

给你一个只包含英文元音字母的字符串 word ,请你返回 word 中 最长美丽子字符串的长度 。如果不存在这样的子字符串,请返回 0 。

子字符串 是字符串中一个连续的字符序列。

 

示例 1:

输入:word = "aeiaaioaaaaeiiiiouuuooaauuaeiu"
输出:13
解释:最长子字符串是 "aaaaeiiiiouuu" ,长度为 13 。

示例 2:

输入:word = "aeeeiiiioooauuuaeiou"
输出:5
解释:最长子字符串是 "aeiou" ,长度为 5 。

示例 3:

输入:word = "a"
输出:0
解释:没有美丽子字符串,所以返回 0 。

1.首先如果数组长度小于5的话,不可能满足美丽的定义,将这种情况提前排除
2.遍历时分了几种情况判断:
- 如果当前字符比上一个不小(顺序意义),那么当前子串长度+1
- 如果当前字符比上一个大,那么子串中元音字母种类+1
- 如果当前字符比上一个小,那么肯定当前字串不美丽,以当前字符为首继续进行遍历
3.如果当前子字符串没有以a开头的话,那么在进行下一个子字符串开始遍历之前,元音种类一定不会达到5,所以只要判断种类即可
4.当元音种类为5的时候,持续维护更新最终结果,取出最大值即可

class Solution {
    public int longestBeautifulSubstring(String word) {

		if (word.length()<5)return 0;
        char[] arr = word.toCharArray();
		int res=0;
		int rlen=1;
		int vowel=1;
		for(int i=1;i<word.length();i++){
            if(arr[i]>=arr[i-1]) rlen++;
			if(arr[i]>arr[i-1]) vowel++;
			if(arr[i]<arr[i-1]) {rlen=1;vowel=1;}
			if(vowel==5) {res=rlen>res?rlen:res;}
		}
		return res;
    }
}

 

第二种方法滑动窗口

java 中的Set中的数组不能重复 所以用set数组存放5个元音字母

这种求满足某种条件的子字符串问题,是典型的滑动窗口套路题了。

这种题的思路一般是设置一个滑动窗口,每次试探地将元素从右侧加入窗口,如果满足条件则顺利加入;如果遇到的元素加入后使得条件变得不满足,那么试图从左侧移除元素,直到条件满足。
在窗口滑动的过程中,右指针和左指针的移动分别有如下规律:

右指针
right++ 即只向右移动一个位置,每次试探一个新元素。
左指针
left++ 向右移动一个位置
left=right 即清空窗口中所有元素
left移到窗口中某个合适位置(比如刚好使得窗口中没有重复元素-lC003题)
本题中窗口要满足的条件即元素按字典序排列和5个元音字母必须全部出现,对于第一个条件只需要比较新元素和窗口中元素的字典序即可,对于第二个条件我们使用一个hash set来统计窗口中字符的种类。

class Solution {
    public int longestBeautifulSubstring(String word) {
    	List<Character> window=new ArrayList<Character>();
    	Set<Character> set = new HashSet<Character>();
    	int left=0;
    	int res = 0;
    	int right=0;
    	while(right<word.length()) {
    		if (window.isEmpty() || word.charAt(right)>=window.get(window.size()-1)) {
    			window.add(word.charAt(right));
    			set.add(word.charAt(right));
    			if (set.size()==5) {
    				res=Math.max(res, window.size());
    			}
    		}else {
    			window.clear();
    			set.clear();
    			left=right;
    			window.add(word.charAt(left));
    			set.add(word.charAt(left));
    		}
    		right++;
    	}
		return res;
    }
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值