【问题标题】:How to reduce the number of for loops如何减少for循环的数量
【发布时间】:2019-09-01 10:44:47
【问题描述】:

如何改进此代码,我得到了准确的输出,但它似乎有点长且不必要的操作。任何建议。

public class Test {

    public static void main(String[] args) {
        List<Integer> a = new ArrayList<Integer>();
        a.add(1);
        a.add(2);

        List<Integer> b = new ArrayList<Integer>();
        b.add(3);
        b.add(5);
        System.out.println(test(5, a, b));
    }

    public static long test(int n, List<Integer> a, List<Integer> b) {
        // Write your code here
        long retCnt = 0;
        List<String> enemy = new ArrayList<String>();
        for (int i = 0; i < a.size(); i++) {
            enemy.add(a.get(i) + "" + b.get(i));
        }



        String tempstr = "";
        int tempj = 1;
        for (int m = 1; m <= n; m++) {
            int temp = 1;
            for (int i = 1; i <= n; i++) {
                tempstr = "";
                for (int j = tempj; j <= temp; j++) {
                    tempstr += j;
                }
                temp++;
                if (!"".equalsIgnoreCase(tempstr)) {
                    if (isValidGroup(enemy, tempstr)) {
                        retCnt++;
                    } else {
                        break;
                    }
                }
            }
            tempj++;
        }

        return retCnt;
    }

    public static boolean isValidGroup(List<String> enemy, String group) {
        for (int i = 0; i < enemy.size(); i++) {
            if (group.trim().toUpperCase().contains(String.valueOf(enemy.get(i).charAt(0)).toUpperCase())&& group.trim().contains(String.valueOf(enemy.get(i).charAt(1)).toUpperCase())) {
                return false;
            }
        }
        return true;
    }
}

问题陈述的简短描述。

我有一个敌人列表,即分别包含输入数组列表和 b 中的 13 和 25 对。 我有一个数字 n 调用 5 ,我必须生成可能的排列,这些排列不应该是敌人列表的一部分。

如果需要进一步说明,请发表评论。

【问题讨论】:

    标签: java arraylist data-structures


    【解决方案1】:

    您的代码很慢。如果 n 为 100,您的代码将需要超过 1 亿次计算才能执行。

    但是,如果您直接跳到无效数字所在的索引之上,则可以使用一些二项式数学在 O(N) 中执行整个测试函数。也可以使用下面非常简单的算法在 O(N^2) 内完成。

    为了节省内存和代码,我要做的第一件事是删除变量 tempj 和 temp,因为您可以使用变量 m 和 i 来完成相同的工作,并且它们始终具有相同的关联值,并且无论如何都必须创建它们进行适当数量的迭代。

    另一个需要注意的有用的事情是 tempj 有时(更准确地说,在大约一半的迭代中)会大于 temp。在所有这些情况下,您将找不到任何有效的排列,因为 j 仅以 increasing 顺序从 temp 迭代到 tempj。换句话说,一半的计算是无用的。

    Tempstr 可以预先计算。

    假设 tempj 为 1,temp 为 3。然后 J 将从 1 到 2 和从 2 到 3 进行 2 次迭代。J 已达到 temp,因此您将 temp 加一。 Temp 现在是 4,而 Tempj 仍然是 1。

    现在 J 必须执行前 2 个步骤才能从 1 到 3,然后再执行一个步骤才能到达 temp 所在的 4。您可以跳过前两个步骤,因为您已经知道 tempstr 在它们之后会是什么样子。不要重置 j,而是随着温度的升高继续增加它。

    这是 O(N^2) 的 sn-p (不考虑 isValidGroup() 的复杂性,可以使用布尔数组轻松优化,您可以在其中标记 N^2 中的无效位置)

    String tempstr = "";
    for(int start = 1; start <= n; start++) {
        tempstr = "";
        for(int end = start; end <= n; end++) {
            tempstr += end;
            if(isValidGroup(enemy, tempstr)) {
                retCnt++;
            } else {
                break;
            }
        }
    }
    

    【讨论】:

    • 感谢您提供很好的解释,但恐怕我仍然有一些测试用例的时间。
    猜你喜欢
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 2011-12-22
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多