题目链接
LeetCode 周赛 111场B题
https://leetcode-cn.com/problems/di-string-match/
题意
是有点难懂了,给出一个字符串S,S全部由‘D’和‘I’组成,然后现在需要解出一个数组,而这个数组需要和S相匹配。假设S的长度为N,那么这个数组的长度是N+1,并且值是集合{0...N}的任意排列。给出一个例子,假设有字符串S1 = "DIDID",那么S1的长度为5,那么答案就必须是集合{0,1,2,3,4,5}的一个排序,可能是{5,4,3,2,1,0},也可能是{0,1,3,5,2,4}等等。
而这个排序必须是与字符串S相匹配的。这里上题目的example:
“IDID”
[0,4,1,3,2]
题目的意思是,将字符串与数组一一对应,因为数组多一位,不考虑这一位。剩下的位置,如果字符串写的是‘I’,那么该位置上的数应该比右边所有的数都小。而如果是‘D’,则是比右边的都大。现在需要找到其中任意一组。
题解
其实这个题是一个贪心,并且有点dp的感觉。感觉这个题解不唯一,其实还是比较简单能够证明反例。评论有人提出了解法证明,可以看一下:
只需要证明,对于任何 > 或者 < , 算法的规则都能满足。
△N = max-min; 由于每次遇到一个符号,△N-1。
当符号为“ < < <”: max--可以保证符号的正确性。
当符号为“ > > >”: min++可以保住符号的正确性。
当符号为“ ……< > < ": 任意时刻max和min开始比较,是否满足 min < max?
答案是:YES! 由于符号的数量为N,最开始△N = N。由于至少出现一对大于号和小于号 , min(△N)= 1,仍然满足min < max;
综上,得证。
因为每一位对应的数字只有两种情况:比右边所有数都大,或者都小。那么我们可以设定两个值,初始的话:low = 0,high = N。这样,从左开始遍历字符串,碰见一个字符,如果是‘I’,那么就直接赋值low,同时low++。这样,‘I’右边所有的数,一定是都比这个位置大的。因为此时low>a[i],同时high > low。
反而言之,碰见‘D’,直接赋值hight,同时high--。这样所有的数就一定比这个小了。大概就是这样,在O(n)的时间复杂度下就能构造出答案数组。
Java 代码
class Solution {
public int[] diStringMatch(String S) {
int max = S.length();
int len = S.length();
int min = 0;
int[] ans = new int[max+1];
for(int i = 0;i < len;i++){
char c = S.charAt(i);
if(c == 'D'){
ans[i] = max--;
}else{
ans[i] = min++;
}
}
ans[len] = min;
return ans;
}
}