LC 1027. 最长等差数列

https://leetcode-cn.com/problems/longest-arithmetic-sequence/

我们使用两重循环(i,j)去查找A[i], A[j]开头的等差数列,但是一旦发现k是后面一个元素的话,那么可以将(j,k)标记已经访问,因为(i,j)开头产生的等差数列长度更长。这种经常下面经常会有三重循环的错觉。

然后得到i,j之后,查找下一个k有两种方法,我记得这个两种方法之前也写过,具体我忘记了是哪题里面提到的。

这种情况下面使用Java还是更好懂


class Solution:
    def longestArithSeqLength(self, A: List[int]) -> int:
        from collections import defaultdict
        nums = defaultdict(list)
        n = len(A)

        for i in range(n):
            x = A[i]
            nums[x].append(i)

        def find_next(exp, i):
            xs = nums[exp]
            s, e = 0, len(xs) - 1
            while s <= e:
                m = (s + e) // 2
                if xs[m] > i:
                    e = m - 1
                else:
                    s = m + 1
            # print(exp, xs, i, s)
            if s >= len(xs):
                return None
            return xs[s]

        visited = set()
        ans = 2
        for i in range(n):
            for j in range(i + 1, n):
                d = A[j] - A[i]
                if (i, j) in visited:
                    continue
                visited.add((i, d))
                sz = 2
                exp = A[j] + d
                k = j
                while True:
                    k2 = find_next(exp, k)
                    if k2 is None:
                        break
                    visited.add((k, k2))
                    sz += 1
                    exp += d
                    k = k2
                ans = max(ans, sz)
        return ans

class Item implements Comparable<Item> {
    int value;
    int index;
    public Item(int value, int index) {
        this.value = value;
        this.index = index;
    }
    public int compareTo(Item x) {
        if (value != x.value) {
            return value - x.value;
        }
        return index  - x.index;
    }
    public String toString() {
        return String.format("(value=%d, index=%d)", value, index);
    }
}
class Solution {
    public int longestArithSeqLength(int[] A) {
        TreeSet<Item> ts = new TreeSet<>();
        for (int i = 0; i < A.length; i++ ){
            int x = A[i];
            ts.add(new Item(x,i));
        }
        int[][]visited = new int[A.length][];
        for(int i=0;i<A.length;i++) {
            visited[i] = new int[A.length];
        }
        int ans = 2;
        for(int i=0;i<A.length;i++) {
            for (int j=i+1;j<A.length;j++) {
                if (visited[i][j] == 1) {
                    continue;
                }
                visited[i][j] = 1;
                int d = A[j] - A[i];
                int exp = A[j] + d;
                int sz = 2;
                int k = j;
                while (true) {
                    Item x = ts.ceiling(new Item(exp, k+1));
                    // System.out.printf("search item. exp = %d, k+1 = %d, x = %s\n", exp, k+1, x);
                    if (x != null && x.value == exp) {
                        sz += 1;
                        exp += d;
                        int k2 = x.index;
                        visited[k][k2] = 1;
                        k = k2;
                    } else {
                        break;
                    }
                }
                ans = Math.max(ans, sz);
            }
        }
        return ans;
    }
}