天真地,我们想做这样的事情:
for(int i = 0, j = 0; i <= n || j <= m; i = Math.min(n, i+1), j = Math.min(m, j+1))
...但这不会终止,因为i
is的最大值和isn
的最大值,其中之一将始终为真。j
m
如果你愿意让 (for n < m
)i
结束n+1
,问题就简单多了,我们可以这样写:
for(int i = 0, j = 0; i <= n || j <= m; i = Math.min(n+1, i+1), j = Math.min(m+1, j+1))
仅当您想在完成递增时保留 (for n < m
)i = n
时,这才是复杂的。j
复杂性被隔离到让循环在正确的时间终止,同时仍然允许j
完成递增。
为了使循环终止,我们希望将较大的数字增加超过其最大值的一步,以便我们达到终止条件。由于我们至少知道其中一个i <= n
并且j <= m
将永远为真,让我们专注于使两者始终为真,并将我们的终止标准更改为
i <= n && j <= m
在这种情况下n < m
,i
将在之前完成递增j
,因此我们需要让j
递增超过其有效最大值才能违反i <= n && j <= m
。类似的条件适用于n > m
,但相反,我们需要增加i
一个过去n
。
但是请注意,如果n == m
,我们可以安全地将两者都增加超过各自的限制,并且终止条件将同时达到。下面的循环处理任何正输入n
或m
在给定条件的情况下正确终止,同时允许较小的n
或m
成为相应迭代器的最大值。
for(int i = 0, j = 0, nadj = n + (n >= m ? 1 : 0), madj = m + (m >= n ? 1 : 0)
i <= n && j <= m;
i = Math.min(nadj, i+1), j = Math.min(madj, j+1))
值得注意的是,我们在第一部分计算nadj
和madj
以避免在每次迭代期间重新计算它们。