- Translate each rule into one explicit state update.
- Maintain the invariant after every processed item.
- Return the accumulated state once all relevant input has been handled.
Code notes
- 108 lines of Java from the credited upstream file 1924.java.
- The implementation visibly relies on sequence storage.
- 1 loop block detected.
Complexity
Count the number and nesting of passes over the input, then include the maintained containers in the memory estimate.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Point {2 public double x;3 public double y;4 public Point(double x, double y) {5 this.x = x;6 this.y = y;7 }8}9 10class Disk {11 public Point center;12 public double radius;13 public Disk(Point center, double radius) {14 this.center = center;15 this.radius = radius;16 }17}18 19class Solution {20 public double[] outerTrees(int[][] trees) {21 Point[] points = new Point[trees.length];22 for (int i = 0; i < trees.length; ++i)23 points[i] = new Point(trees[i][0], trees[i][1]);24 Disk disk = welzl(points, 0, new ArrayList<>());25 return new double[] {disk.center.x, disk.center.y, disk.radius};26 }27 28 29 30 31 private Disk welzl(Point[] points, int i, List<Point> planePoints) {32 if (i == points.length || planePoints.size() == 3)33 return trivial(planePoints);34 Disk disk = welzl(points, i + 1, planePoints);35 if (inside(disk, points[i]))36 return disk;37 return welzl(points, i + 1, addPlanePoints(planePoints, points[i]));38 }39 40 private List<Point> addPlanePoints(List<Point> planePoints, Point point) {41 List<Point> newPlanePoints = new ArrayList<>(planePoints);42 newPlanePoints.add(point);43 return newPlanePoints;44 }45 46 47 private Disk trivial(List<Point> planePoints) {48 if (planePoints.isEmpty())49 return null;50 if (planePoints.size() == 1)51 return new Disk(new Point(planePoints.get(0).x, planePoints.get(0).y), 0);52 if (planePoints.size() == 2)53 return getDisk(planePoints.get(0), planePoints.get(1));54 55 Disk disk01 = getDisk(planePoints.get(0), planePoints.get(1));56 if (inside(disk01, planePoints.get(2)))57 return disk01;58 59 Disk disk02 = getDisk(planePoints.get(0), planePoints.get(2));60 if (inside(disk02, planePoints.get(1)))61 return disk02;62 63 Disk disk12 = getDisk(planePoints.get(1), planePoints.get(2));64 if (inside(disk12, planePoints.get(0)))65 return disk12;66 67 return getDisk(planePoints.get(0), planePoints.get(1), planePoints.get(2));68 }69 70 71 private Disk getDisk(Point A, Point B) {72 final double x = (A.x + B.x) / 2;73 final double y = (A.y + B.y) / 2;74 return new Disk(new Point(x, y), distance(A, B) / 2);75 }76 77 78 private Disk getDisk(Point A, Point B, Point C) {79 80 Point mAB = new Point((A.x + B.x) / 2, (A.y + B.y) / 2);81 Point mBC = new Point((B.x + C.x) / 2, (B.y + C.y) / 2);82 83 84 final double slopeAB = (B.y - A.y) / (B.x - A.x);85 final double slopeBC = (C.y - B.y) / (C.x - B.x);86 final double perpSlopeAB = -1 / slopeAB;87 final double perpSlopeBC = -1 / slopeBC;88 89 90 final double x =91 (perpSlopeBC * mBC.x - perpSlopeAB * mAB.x + mAB.y - mBC.y) / (perpSlopeBC - perpSlopeAB);92 final double y = perpSlopeAB * (x - mAB.x) + mAB.y;93 Point center = new Point(x, y);94 return new Disk(center, distance(center, A));95 }96 97 98 private boolean inside(Disk disk, Point point) {99 return disk != null && distance(disk.center, point) <= disk.radius;100 }101 102 private double distance(Point A, Point B) {103 final double dx = A.x - B.x;104 final double dy = A.y - B.y;105 return Math.sqrt(dx * dx + dy * dy);106 }107}108