自从我参加编码课以来已经有20年了。我不时地再次拿起它以获得乐趣,但我的代码很笨重而且低效的。
我有一个只有400多个元素的数组。我目前在该数组上运行了嵌套的foreach循环。
import acm.program.ConsoleProgram;
import java.awt.Color;
import acm.io.IODialog;
import java.text.*;
import static java.lang.Math.*;
import java.util.*;
/** Tests to see if user color matches sample colors */
public class test extends ConsoleProgram
{
//defining sample colors
Color[] dmc =
{
new Color(255,255,255),
new Color(148,91,128),
new Color(206,148,186),
new Color(236,207,225),
new Color(243,218,228),
};
public void run()
{
average();
}
//averages three colors, then tests for match to given color
public void average()
{
//asks for user color
IODialog dialog = new IODialog();
int stitchRed= dialog.readInt("Enter red value: ");
int stitchGreen= dialog.readInt("Enter green value: ");
int stitchBlue= dialog.readInt("Enter blue value: ");
Color stitchColor= new Color(stitchRed,stitchGreen,stitchBlue);
//gets averages for dmc colors
for (Color i:dmc)
{
for (Color j:dmc)
{
for (Color k:dmc)
{
int indexI = Arrays.asList(dmc).indexOf(i);
int indexJ = Arrays.asList(dmc).indexOf(j);
int indexK = Arrays.asList(dmc).indexOf(k);
if(indexI <= indexJ && indexJ <= indexK)
{
int iRed = i.getRed();
int jRed = j.getRed();
int kRed = k.getRed();
int iGreen = i.getGreen();
int jGreen = j.getGreen();
int kGreen = k.getGreen();
int iBlue = i.getBlue();
int jBlue = j.getBlue();
int kBlue = k.getBlue();
int redAverage = (iRed+jRed+kRed)/3;
int greenAverage = (iGreen+jGreen+kGreen)/3;
int blueAverage = (iBlue+jBlue+kBlue)/3;
Color colorAverage = new Color(redAverage,greenAverage,blueAverage);
//tests to see if any thread average equals user color
if (colorAverage.equals(stitchColor))
{
println("The color match is: " + i + ", " + j + ", " + k);
}
}
}
}
}
println("no more matches");
}
}
这编译得很好,但运行速度很慢。
有没有更有效的方法呢?
可能是一种绕过筑巢的方法 - 具有以下效果:
for(Color i,j,k:dmc)
答案 0 :(得分:1)
(我无法测试和调试代码,因为它不是SSCCE,因此我对任何错误都有所了解)
请考虑以下内容,详见评论:
Color[ ] dmc = {element1, element2, ...};
for( int i =0; i < dmc.length ; i++ )
{
//iterate only on values >= i
for( int j = i; j< dmc.length; j++ )
{
//loop only on values >= j
for( int k = j; k < dmc.length ; k++ )
{
//not needed, you already have i, j, k
//int indexI = Arrays.asList(dmc).indexOf(i);
//int indexJ = Arrays.asList(dmc).indexOf(j);
//int indexK = Arrays.asList(dmc).indexOf(k);
//condition is not needed. Allways true.
//if( indexI <= indexJ && indexJ <= indexK ) { }
//bunch of code...
编辑:一个简短的演示,只打印出想要的事件:
public static void main(String[] args) {
Color[ ] dmc = {Color.AQUA, Color.AZURE, Color.BEIGE, Color.BLACK, Color.BLUE,
Color.BROWN, Color.CHOCOLATE, Color.CYAN, Color.CRIMSON, Color.FUCHSIA};
for( int i =0; i < dmc.length ; i++ )
{
System.out.printf("\n >>>>>> i= %s", i);
//iterate only on values >= i
for( int j = i; j< dmc.length; j++ )
{
System.out.printf("\n j= %s",j);
//loop only on values >= j
for( int k = j; k < dmc.length ; k++ )
{
System.out.printf("\n k= %s",k);
}
}
}
}
编辑II:在MCVE发布后,我通过添加fastEverage()
方法对其进行了修改,该方法应与everage()
进行相同的计算,迭代次数较少。
在我检查的单一颜色上,两种方法都有相同的输出:
import java.awt.Color;
import java.util.Arrays;
/** Tests to see if user color matches sample colors */
public class Test
{
//defining sample colors
Color[] dmc =
{
new Color(255,255,255),
new Color(148,91,128),
new Color(206,148,186),
new Color(236,207,225),
new Color(243,218,228),
};
//averages three colors, then tests for match to given color
public void average()
{
//asks for user color
int stitchRed = 203;
int stitchGreen= 164;
int stitchBlue= 189;
Color stitchColor= new Color(stitchRed,stitchGreen,stitchBlue);
//gets averages for dmc colors
for (Color i:dmc)
{
for (Color j:dmc)
{
for (Color k:dmc)
{
int indexI = Arrays.asList(dmc).indexOf(i);
int indexJ = Arrays.asList(dmc).indexOf(j);
int indexK = Arrays.asList(dmc).indexOf(k);
if((indexI <= indexJ) && (indexJ <= indexK))
{
int iRed = i.getRed();
int jRed = j.getRed();
int kRed = k.getRed();
int iGreen = i.getGreen();
int kGreen = k.getGreen();
int jGreen = j.getGreen();
int iBlue = i.getBlue();
int jBlue = j.getBlue();
int kBlue = k.getBlue();
int redAverage = (iRed+jRed+kRed)/3;
int greenAverage = (iGreen+ jGreen + kGreen)/3;
int blueAverage = (iBlue+jBlue+kBlue)/3;
Color colorAverage = new Color(redAverage,greenAverage,blueAverage);
//tests to see if any thread average equals user color
if (colorAverage.equals(stitchColor))
{
System.out.println("The color match is: " + i + ", " + j + ", " + k);
}
}
}
}
}
System.out.println("no more matches");
}
//averages three colors, then tests for match to given color
public void fastEverage()
{
//asks for user color
int stitchRed = 203;
int stitchGreen= 164;
int stitchBlue= 189;
Color stitchColor= new Color(stitchRed,stitchGreen,stitchBlue);
Color colorI, colorJ, colorK;
for( int i =0; i < dmc.length ; i++ )
{
colorI = dmc[i];
//iterate only on values >= i
for( int j = i; j< dmc.length; j++ )
{
colorJ = dmc[j];
//loop only on values >= j
for( int k = j; k < dmc.length ; k++ )
{
colorK = dmc[k];
int iRed = colorI.getRed();
int jRed = colorJ.getRed();
int kRed = colorK.getRed();
int iGreen = colorI.getGreen();
int kGreen = colorK.getGreen();
int jGreen = colorJ.getGreen();
int iBlue = colorI.getBlue();
int jBlue = colorJ.getBlue();
int kBlue = colorK.getBlue();
int redAverage = (iRed+jRed+kRed)/3;
int greenAverage = (iGreen+ jGreen + kGreen)/3;
int blueAverage = (iBlue+jBlue+kBlue)/3;
Color colorAverage = new Color(redAverage,greenAverage,blueAverage);
//tests to see if any thread average equals user color
if (colorAverage.equals(stitchColor))
{
System.out.println("The color match is: " + colorI + ", " + colorJ + ", " + colorK);
}
}
}
}
System.out.println("no more matches");
}
public static void main(String[] args)
{
new Test().average();
new Test().fastEverage();
}
}
在这个测试用例中,两种方法之间的运行时差异很大:
以毫秒为单位运行everage()的时间84752814
以纳秒为单位运行fastEverage()的时间76497255
答案 1 :(得分:1)
它等于@C0der的答案,只是对问题的变量使用相同的名称。
for (int indexI = 0; indexI < dmc.length; indexI++) {
Color i = dmc[indexI];
for (int indexJ = indexI; indexJ< dmc.length; indexJ++) {
Color j = dmc[indexJ];
for (int indexK = indexJ; indexK< dmc.length; indexK++) {
Color k = dmc[indexK];
//....
}
}
}
编辑:
public void average() {
//asks for user color
IODialog dialog = new IODialog();
int stitchRed = dialog.readInt("Enter red value: ");
int stitchGreen = dialog.readInt("Enter green value: ");
int stitchBlue = dialog.readInt("Enter blue value: ");
Color stitchColor = new Color(stitchRed, stitchGreen, stitchBlue);
for (int indexI = 0; indexI < dmc.length; indexI++) {
Color i = dmc[indexI];
for (int indexJ = indexI; indexJ < dmc.length; indexJ++) {
Color j = dmc[indexJ];
for (int indexK = indexJ; indexK < dmc.length; indexK++) {
Color k = dmc[indexK];
int iRed = i.getRed();
int jRed = j.getRed();
int kRed = k.getRed();
int iGreen = i.getGreen();
int jGreen = j.getGreen();
int kGreen = k.getGreen();
int iBlue = i.getBlue();
int jBlue = j.getBlue();
int kBlue = k.getBlue();
int redAverage = (iRed + jRed + kRed) / 3;
int greenAverage = (iGreen + jGreen + kGreen) / 3;
int blueAverage = (iBlue + jBlue + kBlue) / 3;
Color colorAverage = new Color(redAverage, greenAverage, blueAverage);
//tests to see if any thread average equals user color
if (colorAverage.equals(stitchColor)) {
System.out.println("The color match is: " + i + ", " + j + ", " + k);
}
}
}
}
System.out.println("no more matches");
}
答案 2 :(得分:0)
考虑到你在if语句中过滤掉了许多组合,一个优化就是使用for循环,只迭代你实际想要处理的元素而不是for-each-loops。例如。 i&lt; = j表示你可以在i开始迭代。
根据评论中所述的意图,可能会有进一步的改进。
答案 3 :(得分:0)
您可以尝试类似
的内容for( x=1;x<401;x++ )
{
Color j= dmc[x];
Color k= dmc[x+1];
int indexI = Arrays.asList(dmc).indexOf(i);
int indexJ = Arrays.asList(dmc).indexOf(j);
int indexK = Arrays.asList(dmc).indexOf(k);
if( indexI <= indexJ && indexJ <= indexK )
{
//bunch of code...
或者,您可以尝试在java.lang.Object中定义的equals方法。希望这会有所帮助。
答案 4 :(得分:0)
只是一个想法。您可以拆分搜索。有可能在第一次搜索中找到匹配项。如果是这样,那么你不需要搜索其余的匹配。如果没有,你可以继续搜索匹配。
int i,j,k;
for(i=0;i<100;i++){
for(j=i;j<100;j++){
for(k=j;k<100;k++){
//..do stuffs.....//
}
}
}
if(matchnotfound){
for(i=100;i<200;i++){
for(j=i;j<200;j++){
for(k=j;k<200;k++){
//..do stuffs.....//
}
}
}
}
if(matchnotfound){
for(i=200;i<300;i++){
for(j=i;j<300;j++){
for(k=j;k<300;k++){
//..do stuffs.....//
}
}
}
}
if(matchnotfound){
for(i=300;i<400;i++){
for(j=i;j<400;j++){
for(k=j;k<400;k++){
//..do stuffs.....//
}
}
}
}