官方题解的另一种思路
题目
给定只含 “I”(增大)或 “D”(减小)的字符串 S ,令 N = S.length。
返回 [0, 1, …, N] 的任意排列 A 使得对于所有 i = 0, …, N-1,都有:
如果 S[i] == “I”,那么 A[i] < A[i+1]
如果 S[i] == “D”,那么 A[i] > A[i+1]
来源:https://leetcode-cn.com/problems/di-string-match
解题思路
官方提供的题解,维护可用的最大和最小 high,low 两个变量,每次需要递增时放入high,并使 high–;需要递减时放入low,并使low–;当S遍历结束后,追加最后剩下数。代码如下:
|
|
而下面要介绍的,和这个思路类似,但不同于维护相互靠近的两个变量,它维护的是向外远离的两个变量,即比当前数组内元素 刚好大/小一点 的 nextSmaller 和 nextBiger 变量。
另外,因为数组首元素放入0,数组可能放入负数,因此最后需要额外将所有元素向(0,N)范围偏移。代码如下:
tip: 因为放入数的取值范围依赖 S 的长度 N,因此无论官方题解的内缩还是第二种思路的外延,差值都是1,所以数组的所有元素差值正好为 N,不需要考虑重复数或超出(0,N)范围的情况
代码
|
|
分析
时间复杂度:O(N),其中 N 是字符串 S 的长度。
空间复杂度:O(N)。
虽然算法复杂度和官方题解同样是O(n), 但是第二种思路多了两个遍历(min函数 与for循环)算法复杂度为 3n(感谢 @瞌睡 指出), 但是第二种思路多了次遍历(for循环偏移)算法复杂度为 2n,而且代码也不够简洁优雅。 这种写法不值得提倡,但提供了另外一种思考角度,拓展下思维还是不错的。