0

编写一个名为 removeSomePoints 的方法。此方法接受一个点数组,并返回一个与原始数组相同的新点数组,只是它删除了所有 x 和 y 坐标相差小于 20 的点。换句话说,返回的数组可能比原始数组的大小更小。此方法应保持原始数组不变。澄清:如果以下任何点在原始数组中,它们将不在返回的数组中。

100 90(x 和 y 相差 10)

90 100(x 和 y 相差 10)

3 22(x 和 y 相差 19)

另一方面,以下任何点都将在返回的数组中:

100 80(x 和 y 相差 20)

80 100(x 和 y 相差 20)

2 25(x 和 y 相差 23)

我的代码:

   public static Point[] removeSomePoints(Point[] arr) 
   {

    int count = 0;      
    for (int i = 0; i < arr.length; i++) {
         if (Math.abs(arr[i].getX() - arr[i].getY()) > 19) {
            count++;
          }
         }

        Point[] finalArr = new Point[count];

        for (int i = 0; i < finalArr.length; i++) {
          if (Math.abs(arr[i].getX() - arr[i].getY()) > 19) {
               finalArr[i] = arr[i];
          }

     }

       return finalArr;
    }

似乎无法弄清楚出了什么问题。它正在返回一个数组,但它不会改变任何东西。

4

4 回答 4

1

好的,因此您的程序当前无法运行,因为您确定了N长度为输入数组中匹配项的数量(比如说 )M。现在鉴于N保证小于M,请注意您正在迭代输入数组的子集(长度为N)并将该子集中的任何匹配项复制到输出数组中。这是完全不正确的。

我认为这是一个学习项目——很明显,本课的重点是为您的代码选择合适的数据结构。数组在处理固定大小的集合时很棒,但不适合可变大小的集合。对于可变数据,列表绝对是要走的路。

那么让我们来看看一些伪代码:

public static Point[] removeSomePoints(Point[] arr) {
    // If 'arr' is null, return null
    // If 'arr' is empty, return empty

    // Initialize a variable list structure, of at least arr.length in size
    // For each element in arr
    //     if element matches condition, add to variable list
    // End for
    // 
    // Convert variable list into array and return
}

简而言之,这就是你的算法。将其转换为真实代码:

public static Point[] removeSomePoints(Point[] arr) {
    if(arr == null) return null;
    if(arr.length == 0) return new Point[0];

    List<Point> outputList = new ArrayList<Point>(arr.length);
    for(Point p : arr) {
        if (Math.abs(p.getX() - p.getY()) > 19) outputList.add(p);
    }

    return outputList.toArray(new Point[outputList.size());
 }

不要忘记查看ListArrayList的文档,以便更好地了解它们的工作原理。

于 2013-01-18T22:28:34.017 回答
0

逻辑中的关键缺陷是在原始数组中使用了较短的数组索引。

这意味着数组 [[90,100],[75,100],[85,100],[80,100]] 将首先计算 2 个有效条目,创建一个大小为 2 的新数组,然后从原始数组中复制前两个条目以创建[[90,100],[75,100]] 而不是所需的 [[75,100],[80,100]]。

一种方法是添加“resizeArray()”函数(此处示例:http: //www.source-code.biz/snippets/java/3.htm),在初始循环期间使用单独的索引填充新数组(例如“count”),它仅在添加到新数组时递增,然后将新数组的大小调整为目标大小。

像这样:

public static Point[] removeSomePoints(Point[] arr)
{
    int count = 0;

    Point[] finalArr = new Point[arr.length];

    for (int i = 0; i < arr.length; i++)
    {
        if (Math.abs(arr[i].getX() - arr[i].getY()) > 19)
        {
            finalArr[count] = arr[i];
            count++;
        }
    }

    return (Point[])resizeArray(finalArr, count);
}
于 2013-01-18T21:51:41.997 回答
0

你的第二个循环应该是:

int j = 0;
for (int i = 0; i < arr.length; ++i) {
   if ((Math.abs(arr[i].getX() - arr[i].getY()) > 19) {
            finalArr[j++] = arr[i];
   }
}
于 2013-01-18T21:51:56.707 回答
0

正如其他人所提到的,问题是由于第二个循环中的逻辑缺陷造成的。您应该遍历原始数组而不是要返回的数组。

利用ArrayList和的答案resizeArray都很好。在@Perception 的回答中,用作ArrayList中间数据结构,而在@DreadPirateShawn 的回答中,Array用作中间数据结构。最后,它们都将被调整为要返回的结果数组。由于不需要随机访问中间数据结构,因此我更喜欢使用LinkedList。使用链表不需要任何调整大小,因此可能会节省一些时间和空间。

public static Point[] removeSomePoints(Point[] arr) {
    if(arr == null) return null;
    if(arr.length == 0) return new Point[0];

    List<Point> outputList = new LinkedList<Point>();
    for(Point p : arr) {
        if (Math.abs(p.getX() - p.getY()) > 19) outputList.add(p);
    }

    return outputList.toArray(new Point[outputList.size()]);
}
于 2013-01-18T23:43:34.460 回答