我正在尝试进行凸壳方法,小问题是我需要获得所有三个连续顶点的集合,如下所示:
private void isConvexHull(Ponto[] points) {
Arrays.sort(points);
for (int i = 0; i <points.length; i++) {
isClockWise(points[i],points[i+1],points[i+2]);
}
//...
}
我总是做一些我不认为干净代码的事情。请帮助我找到一种或多种方法吗?我希望它是循环的,即,如果我的fisrt点是数组中的最后一个元素,第二个元素将是列表中的第3个元素,该集合中的第3个元素将是列表中的第2个元素, 等等。他们必须连续,这就是全部。
答案 0 :(得分:5)
您可以使用%
“技巧”(%
是余数运算符JLS 15.17.3)进行循环索引。在这里,我将使用String
来说明一般概念。
String s = "ABCDE";
final int L = s.length();
for (int i = 0; i < L; i++) {
System.out.format("%c%c%c ",
s.charAt(i),
s.charAt((i + 1) % L),
s.charAt((i + 2) % L)
);
} // prints "ABC BCD CDE DEA EAB "
Iterator
方法如果你经常进行这种三重态处理,那么拥有Iterator<PointTriplet>
或类似的东西将是一个更好的整体设计。
这是一个原型来说明这个想法:
import java.util.*;
public class CircSubArray {
static <T> Iterator<T[]> circularIterator(final T[] arr, final int K) {
return new Iterator<T[]>() {
int index = 0;
final int L = arr.length;
T[] sub = Arrays.copyOf(arr, K); // let it do the dirty work!
@Override public boolean hasNext() {
return index < L;
}
@Override public T[] next() {
for (int i = 0; i < K; i++) {
sub[i] = arr[(index + i) % L];
}
index++;
return sub; // we always overwrite; no need to .clone()
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
String[] arr = { "s1", "s2", "s3", "s4", "s5", "s6" };
Iterator<String[]> iter = circularIterator(arr, 4);
while (iter.hasNext()) {
System.out.println(Arrays.toString(iter.next()));
}
}
}
打印:
[s1, s2, s3, s4]
[s2, s3, s4, s5]
[s3, s4, s5, s6]
[s4, s5, s6, s1]
[s5, s6, s1, s2]
[s6, s1, s2, s3]
List
的解决方案正如 Effective Java 2nd Edition 所述,第25项:首选列表到数组。这是一个在K-1
末尾冗余存储第一个List
元素的解决方案,然后一次只使用subList
来获取K
个元素。
String[] arr = { "s1", "s2", "s3", "s4", "s5", "s6" };
final int L = arr.length;
final int K = 3;
List<String> list = new ArrayList<String>(Arrays.asList(arr));
list.addAll(list.subList(0, K-1));
for (int i = 0; i < L; i++) {
System.out.println(list.subList(i, i + K));
}
打印:
[s1, s2, s3]
[s2, s3, s4]
[s3, s4, s5]
[s4, s5, s6]
[s5, s6, s1]
[s6, s1, s2]
由于subList
是一个视图,因此不必执行基于阵列的解决方案所做的O(K)
转换。这也显示了List
对数组的表达能力。
答案 1 :(得分:2)
简单地记住前两个点,从结束开始,并在每次迭代时移动它们。
private static boolean isConvexHull(Ponto[] points)
{
final int len = points.length;
if (len < 3) return false;
Arrays.sort(points);
Ponto p1 = points[len - 2];
Ponto p2 = points[len - 1];
for (Ponto p3 : points)
{
if (!isClockWise(p1, p2, p3)) return false;
p1 = p2;
p2 = p3;
}
return true;
}
顺便问一下,你究竟如何对数组进行排序?什么是排序标准?