简体   繁体   English

如何在时间复杂度方面改进算法?

[英]How to improve algorithm with respect of time complexity?

I'm trying to measure time complexity of my algorithm: 我正在尝试测量算法的时间复杂度:

public boolean rotateAndCompare(int[] fst, int[] snd) {
    int len = fst.length;
    for (int k = 0; k < len; k++) {
        for (int j = 0; j < len; j++) {
            if (fst[(k + j) % len] != snd[j]) {
                break;
            }
            if (j == len - 1) {
                return true;
            }
        }
    }
    return false;
}

My assumption that it has O(n*n) complexity because we iterate through an array and then through another one array. 我假设它具有O(n*n)复杂度,因为我们先迭代一个数组,然后再迭代另一个数组。 Am I right? 我对吗? And If so then how can I improve it? 如果是这样,那我该如何改善呢?

If I understand it correctly, your algorithm decides if the first fst.length integers of snd are equal to fst , possibly rotated. 如果我理解正确的话,你的算法决定,如果第一fst.length的整数snd等于fst ,可能旋转。 It assumes that snd.length >= fst.length . 假设snd.length >= fst.length If that isn't what you meant, please specify in the question. 如果这不是您的意思,请在问题中指定。

But assuming that's what you really meant, you can solve this problem in O(n) using a string matching algorithm like KMP . 但是假设这就是您的真正意思,则可以使用诸如KMP的字符串匹配算法在O(n)中解决此问题。 You need, in other words, see if you can find snd as a subarray of fst + fst , and that's a classic problem. 换句话说,您需要查看是否可以将snd找到为fst + fst的子fst + fst ,这是一个经典问题。

Here's an example implementation in Java: 这是Java的示例实现:

import java.util.Arrays;

public class Main {
    public static class KMP {
        private final int F[];
        private final int[] needle;

        public KMP(int[] needle) {
            this.needle = needle;
            this.F = new int[needle.length + 1];

            F[0] = 0;
            F[1] = 0;
            int i = 1, j = 0;
            while (i < needle.length) {
                if (needle[i] == needle[j])
                    F[++i] = ++j;
                else if (j == 0)
                    F[++i] = 0;
                else
                    j = F[j];
            }
        }

        public int find(int[] haystack) {
            int i = 0, j = 0;
            int n = haystack.length, m = needle.length;

            while (i - j <= n - m) {
                while (j < m) {
                    if (needle[j] == haystack[i]) {
                        i++;
                        j++;
                    } else break;
                }
                if (j == m) return i;
                else if (j == 0) i++;
                j = F[j];
            }
            return -1;
        }
    }

    public static boolean rotateAndCompare(int[] fst, int[] snd) {
        int[] fst2 = new int[fst.length * 2];
        System.arraycopy(fst, 0, fst2, 0, fst.length);
        System.arraycopy(fst, 0, fst2, fst.length, fst.length);

        int[] snd2 = Arrays.copyOf(snd, fst.length);
        return new KMP(snd2).find(fst2) >= 0;
    }

    public static void main(String[] args) {
        System.out.println(rotateAndCompare(new int[]{1, 2, 3}, new int[]{3, 1, 2, 4}));
        System.out.println(rotateAndCompare(new int[]{1, 2, 2}, new int[]{3, 1, 2, 4}));
    }
}

O(n*n) is usually expressed as "order n-squared", O(n^2), which your algorithm is. O(n * n)通常表示为“阶n平方”,即O(n ^ 2),即您的算法。 However, since you do absolutely no length checking it could break altogether, which is more serious than algorithmic complexity. 但是,由于您绝对不进行长度检查,因此它可能会完全中断,这比算法复杂性更为严重。 'snd' (what does that stand for? Why so terse?) might not even have 'len' elements. “ snd”(这代表什么?为什么这么简洁?)甚至可能没有“ len”元素。 Also, you can get a little improvement by making your terminal condition part of the loop control instead of checking it twice. 另外,通过将终端条件作为循环控件的一部分,而不是对其进行两次检查,可以得到一些改进。

The risk of a crash is far more serious than algorithmic complexity. 崩溃的风险远比算法复杂性严重得多。 Once you solve that, you might be able to refactor the indexes to make it more linear, but I suspect that's not possible. 一旦解决了这一问题,您便可以重构索引以使其更加线性,但是我怀疑那是不可能的。 If there are symmetries in your problem you might be able to exploit them. 如果您的问题中存在对称性,您也许可以利用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM