2

假设你想循环from i=0 to i=n and j=0 to j=m并且那个m!=n. 是否可以将以下两个循环缩短为一个?

for(int i=0; i<=n; i++){}
for(int j=0; j<=m; j++){}

沿着某事

for(int i=0,j=0; i<=n, j<=m; i++, j++){}

本质上,我希望循环说“将 i 和 j 都加一,如果 i=n 则停止增加 i,但如果 m>n 则继续增加 j”或相反的方式 if n>m

可能看起来微不足道或愚蠢,但我很好奇。

4

4 回答 4

4

天真地,我们想做这样的事情:

for(int i = 0, j = 0; i <= n || j <= m; i = Math.min(n, i+1), j = Math.min(m, j+1))

...但这不会终止,因为iis的最大值和isn的最大值,其中之一将始终为真。jm

如果你愿意让 (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 < mi将在之前完成递增j,因此我们需要让j递增超过其有效最大值才能违反i <= n && j <= m。类似的条件适用于n > m,但相反,我们需要增加i一个过去n

但是请注意,如果n == m,我们可以安全地将两者都增加超过各自的限制,并且终止条件将同时达到。下面的循环处理任何正输入nm在给定条件的情况下正确终止,同时允许较小的nm成为相应迭代器的最大值。

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))

值得注意的是,我们在第一部分计算nadjmadj以避免在每次迭代期间重新计算它们。

于 2013-09-21T22:04:19.423 回答
2

编辑

for(int i=0,j=0; i+1<=n || j+1<=m; ){
    if(i<n) i++;
    if(j<m) j++;
    // do stuff here
    // keep in mind that i and j starts from 1
}

小提琴:http: //jsfiddle.net/nilgundag/4frCG/

老答案:

for(int i=0,j=0; i<=n || j<=m; ){
    if(i<=n) i++;
    if(j<=m) j++;
    // do stuff here
    // keep in mind that i and j starts from 1
}
于 2013-09-21T22:09:22.617 回答
1

您只能使用一个迭代器 i 因为您每次都将 i 和 j 增加 1。

for(int i=0; i<=n || i<=m;i++ ){
    if(i<=n) //{do first loop job}
    if(i<=m) //{do second loop job}
}
于 2013-09-21T23:20:59.513 回答
0

C++:

for (int i=0, j=0; j<=m || i<=n; i+=i<=n, j+=j<=m ){}

爪哇:

for (int i=0, j=0; j<=m || i<=n; i+=(i<=n)?1:0, j+=(j<=m)?1:0 ){}
于 2013-09-21T22:48:29.477 回答