给定两个数组arrx和arry,长度都为N。代表二维平面上有N个点,第i个点的x 坐标和y坐标分别为arrx[i]和arry[i],返回求一条直线最多能穿过多少个点?

问题描述:

        给定两个数组arrx和arry,长度都为N。代表二维平面上有N个点,第i个点的x 坐标和y坐标分别为arrx[i]和arry[i],返回求一条直线最多能穿过多少个点?

思想

        坐标系中两个点的位置关系可以分为以下几种情况:共点、共X轴、共Y轴、两点连线有些率。我们根据上面情况,依次遍历每一个数组位置上点与数组后面位置上点之间的关系(这是因为我们在每一次遍历代表的含义是:如果通过这个点,最多直线可以通过几个点。所以遍历到数组i位置时,表示通过前面的点的直线穿过的点不是最多,所以可以不进行遍历)。

代码

准备代码

    public static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

在统计斜率时,K代表斜率(x_y)V代表点的个数。

    public static int maxPoints1(int[] arrx, int[] arry) {
        if (arrx == null || arrx.length == 0 || arry == null || arry.length == 0) {
            return 0;
        }
        if (arrx.length <= 2) {
            return arrx.length;
        }

        //斜率
        //k:x_y   v:int
        HashMap<String, Integer> map = new HashMap<>();
        //结果
        int res = 0;

        for (int i = 0; i < arrx.length; i++) {
            map.clear();
            map.put("_", 0);
            String key = "_";
            //共点
            int point = 1;
            //共x
            int xNum = 0;
            //共y
            int yNum = 0;
            int maxKey = 0;

            for (int j = i + 1; j < arrx.length; j++) {
                int x = arrx[i];
                int y = arry[i];
                if (x == arrx[j] && y == arry[j]) {
                    //共点
                    point++;
                } else if (y == arry[j]) {
                    xNum++;
                } else if (x == arrx[j]) {
                    yNum++;
                } else {
                    //存在斜率
                    int tempX = arrx[j] - x;
                    int tempY = arry[j] - y;
                    int gcd = gcd(tempX, tempY);
                    int kX = tempX / gcd;
                    int kY = tempY / gcd;
                    key = kX + "_" + kY;
                    if (!map.containsKey(key)) {
                        map.put(key, 1);
                    } else {
                        map.put(key, map.get(key) + 1);
                    }
                    maxKey = Math.max(maxKey, map.get(key));
                }

            }
            res = Math.max(res,
                    Math.max(xNum, Math.max(yNum, maxKey)) + point
            );
        }
        return res;
    }

在统计斜率时,使用两个map嵌套,外面的map K表示x V值嵌套一个map K为y V为点的个数。

    public static class Point {
        public int x;
        public int y;

        Point() {
            x = 0;
            y = 0;
        }

        Point(int a, int b) {
            x = a;
            y = b;
        }
    }


    public static int maxPoints2(Point[] points) {
        if (points == null) {
            return 0;
        }
        if (points.length <= 2) {
            return points.length;
        }
        Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
        int result = 0;
        for (int i = 0; i < points.length; i++) {
            map.clear();
            int samePosition = 1;
            int sameX = 0;
            int sameY = 0;
            int line = 0;
            for (int j = i + 1; j < points.length; j++) {
                int x = points[j].x - points[i].x;
                int y = points[j].y - points[i].y;
                if (x == 0 && y == 0) {
                    samePosition++;
                } else if (x == 0) {
                    sameX++;
                } else if (y == 0) {
                    sameY++;
                } else {
                    int gcd = gcd(x, y);
                    x /= gcd;
                    y /= gcd;
                    if (!map.containsKey(x)) {
                        map.put(x, new HashMap<Integer, Integer>());
                    }
                    if (!map.get(x).containsKey(y)) {
                        map.get(x).put(y, 0);
                    }
                    map.get(x).put(y, map.get(x).get(y) + 1);
                    line = Math.max(line, map.get(x).get(y));
                }
            }
            result = Math.max(result, Math.max(Math.max(sameX, sameY), line) + samePosition);
        }
        return result;
    }

测试代码

    public static Point[] ToShift(int[] arrx, int[] arry) {
        if (arrx == null || arrx.length == 0 || arry == null || arry.length == 0) {
            return null;
        }
        Point[] res = new Point[arrx.length];
        for (int i = 0; i < arrx.length; i++) {
            Point temp = new Point(arrx[i], arry[i]);
            res[i] = temp;
        }
        return res;
    }

    public static int[] generateRandomArray(int maxSize, int maxValue) {
        int[] arr = new int[maxSize];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) ((maxValue + 1) * Math.random());
        }
        return arr;
    }

    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    public static void printArray(int[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int maxSize = 20;
        int maxValue = 200;
        int testTime = 500000;
        System.out.println("test begin!");
        for (int i = 0; i < testTime; i++) {
            int[] arrX1 = generateRandomArray(maxSize, maxValue);
            int[] arrY1 = generateRandomArray(maxSize, maxValue);
            int[] arrX2 = copyArray(arrX1);
            int[] arrY2 = copyArray(arrY1);
            int res1 = maxPoints1(arrX1, arrY1);
            Point[] points = ToShift(arrX2, arrY2);
            int res2 = maxPoints2(points);

            if (res1 != res2) {
                System.out.println("Oops!");
                printArray(arrX1);
                printArray(arrY1);
                System.out.println(res1);
                System.out.println(res2);
                break;
            }
        }
        System.out.println("test end!");
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用 vtkContextInteractorStyle 类来处理 vtkContextView 中的交互操作,并在事件回调函数中实现拾取点的功能。以下是一个简单的示例代码,演示了如何在 vtkContextView 中通过 vtkCommand 回调实现点的拾取: ```c++ // 创建一个 vtkChartXY 对象 vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New(); // 创建一些测试数据 vtkNew<vtkTable> table; vtkNew<vtkFloatArray> arrX; arrX->SetName("X Axis"); table->AddColumn(arrX); vtkNew<vtkFloatArray> arrC; arrC->SetName("Cosine"); table->AddColumn(arrC); vtkNew<vtkFloatArray> arrS; arrS->SetName("Sine"); table->AddColumn(arrS); const int numPoints = 40; float inc = 7.5 / (numPoints - 1); table->SetNumberOfRows(numPoints); for (int i = 0; i < numPoints; ++i) { table->SetValue(i, 0, i * inc); table->SetValue(i, 1, cos(i * inc)); table->SetValue(i, 2, sin(i * inc)); } // 将数据添加到图表中 vtkPlot *line = chart->AddPlot(vtkChart::LINE); line->SetInputData(table, 0, 1); line = chart->AddPlot(vtkChart::LINE); line->SetInputData(table, 0, 2); // 创建一个 vtkContextView 对象,并将图表添加到其中 vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New(); view->GetScene()->AddItem(chart); // 设置交互样式 vtkSmartPointer<vtkContextInteractorStyle> interactorStyle = vtkSmartPointer<vtkContextInteractorStyle>::New(); view->GetInteractor()->SetInteractorStyle(interactorStyle); // 定义事件回调函数 class PickCallback : public vtkCommand { public: static PickCallback *New() { return new PickCallback; } virtual void Execute(vtkObject *caller, unsigned long eventId, void *callData) { if (vtkCommand::MouseMoveEvent == eventId) { // 获取交互器 vtkContextInteractorStyle *style = vtkContextInteractorStyle::SafeDownCast(caller); if (!style) { return; } // 获取拾取点 int x = style->GetInteractor()->GetEventPosition()[0]; int y = style->GetInteractor()->GetEventPosition()[1]; vtkPlot *plot = style->GetScene()->PickProp(x, y); if (!plot) { return; } // 获取拾取点的坐标 vtkIdType index = plot->GetNearestPoint(x, y); double *point = plot->GetData()->GetPoint(index); std::cout << "Picked point: (" << point[0] << ", " << point[1] << ")" << std::endl; } } }; // 创建回调对象并将其添加到交互器中 vtkSmartPointer<PickCallback> pickCallback = vtkSmartPointer<PickCallback>::New(); interactorStyle->AddObserver(vtkCommand::MouseMoveEvent, pickCallback); // 启动交互器 view->GetInteractor()->Initialize(); view->GetInteractor()->Start(); ``` 在此示例中,我们创建了一个 vtkChartXY 对象并将一些测试数据添加到其中。然后,我们创建了一个 vtkContextView 对象,并将图表添加到其中。接下来,我们创建了一个 vtkContextInteractorStyle 对象,并将其设置为交互器的样式。然后,我们定义了一个 PickCallback 类来处理事件回调函数,其中我们使用 GetScene()->PickProp(x, y) 方法获取拾取的 plot 对象,然后使用 GetNearestPoint(x, y) 方法获取拾取点的索引,最后使用 GetData()->GetPoint(index) 方法获取拾取点的坐标。最后,我们创建了回调对象并将其添加到交互器中,然后启动交互器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值