https://leetcode-cn.com/problems/longest-arithmetic-sequence/
我们使用两重循环(i,j)去查找A[i], A[j]开头的等差数列,但是一旦发现k是后面一个元素的话,那么可以将(j,k)标记已经访问,因为(i,j)开头产生的等差数列长度更长。这种经常下面经常会有三重循环的错觉。
然后得到i,j之后,查找下一个k有两种方法,我记得这个两种方法之前也写过,具体我忘记了是哪题里面提到的。
- 将值为A[k]的所有k位置记录下来,然后使用二分搜索查找第一个>j的位置
- 将(A[k], k)存入TreeSet, 然后使用 `ceiling(A[k], j+1)` 去查找(但是python没有对应实现)
这种情况下面使用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;
}
}