Given a string S
that only contains "I" (increase) or "D" (decrease), let N = S.length
.
Return any permutation A
of [0, 1, ..., N]
such that for all i = 0, ..., N-1
:
- If
S[i] == "I"
, thenA[i] < A[i+1]
- If
S[i] == "D"
, thenA[i] > A[i+1]
Example 1:
Input: "IDID"
Output: [0,4,1,3,2]
Example 2:
Input: "III"
Output: [0,1,2,3]
Example 3:
Input: "DDI"
Output: [3,2,0,1]
Note:
1 <= S.length <= 10000
S
only contains characters"I"
or"D"
.
题解:可以负责任的告诉大家,这道题虽然列为简单题,但是绝不简单。
下面介绍第一种解法:
class Solution {
public int[] diStringMatch(String S) {
int Slength = S.length();
int decr = Slength;
int incr = 0;
int[] a = new int[Slength+1];
for(int i=0;i<Slength;i++){
if(S.charAt(i)=='I')
a[i] = incr++;
else
a[i] = decr--;
}
a[Slength] = incr;
return a;
}
}
证明:
只需要证明,对于任何 > 或者 < , 算法的规则都能满足。
incr = 0; decr = S.length;
△N = decr-incr; 由于每次遇到一个符号,△N-1。
当符号为“ < < < < < ”: decr--可以保证符号的正确性。
当符号为“ > > > > >”: incr++可以保住符号的正确性。
当符号为“ ……< > < > <……": 任意时刻decr和incr开始比较,那么任意时刻是否满足 incr < decr ?
答案是:YES! 由于符号的数量为N,最开始△N = N。由于至少出现一对 < >, min(△N)= 1,仍然满足incr < decr;
综上,得证。
其他可能解法:
第一种解法的前提是:小于号左边的数字 全部都小于小于号右边的数字。根据之前的分析这样可以求出一个解。
"IDIDIDDDIIIID"
Output
[0,13,1,12,2,11,10,9,3,4,5,6,8,7]
Expected
[0,13,1,12,2,11,10,9,3,4,5,6,8,7]
小于号左边【0,1,2,3,4,5,6】 大于号右边【7,8,9 ,10,11,12,13】
0< 13 > 1 < 12 > 2 < 11 > 10 > 9 > 3 < 4 < 5 < 6 < 8 > 7
0< 13 > 9 < 12 > 2 < 11 > 10 > 3 > 1 < 4 < 5 < 6 < 8 > 7
我们将小于号和大于号的集合里面的数字进行交换,并做适当调整,发现可以满足要求。
那么,问题来了,第一种解法的前提可以保证得出一个解,但是不是必要条件!那么求解这个问题的必要条件是什么?
换句话说,如何求出满足条件的所有解?个人认为是一件非常困难的事情。