Removing Points from an Array and returning a new Array - Java [closed]

可紊 提交于 2019-12-24 19:19:37

问题


Write a method named removeSomePoints. This method takes an array of Points, and returns a new array of points that is the same as the original array, except that it removes all points that have x- and y-coordinates that differ by less than 20. In other words, the returned array will probably have a smaller size than the original array. This method should leave the original array untouched. To clarify: If any of the following points were in the original array, they would not be in the array that is returned.

100 90 (x and y differ by 10)

90 100 (x and y differ by 10)

3 22 (x and y differ by 19)

On the other hand, any of the following points would be in the array that is returned:

100 80 (x and y differ by 20)

80 100 (x and y differ by 20)

2 25 (x and y differ by 23)

My code:

   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;
    }

Can't seem to figure out what is going wrong. It is returning an array but it doesn't change anything.


回答1:


Ok, so your program is currently not working because you determine the number of matching items (lets say N), in your input array of length M. Now given that N is guaranteed to be less than M, notice that you are then iterating over a subset of your input array (of length N) and copying any matches in that subset into your output array. This is simply incorrect.

I take it this is a learning project - and its obvious the key point of the lesson is in picking appropriate data structures for your code. Arrays are great when dealing with fixed size sets, but not so appropriate for variable sized sets. For variable data, lists are definitely the way to go.

So let's take a look at some pseudocode:

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
}

Thats your algorithm, in a nutshell. Converting that into real code:

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());
 }

Don't forget to go over the documentation for List and ArrayList, in order to better understand how they work.




回答2:


Your second loop should be:

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];
   }
}



回答3:


The key flaw in the logic is that the shorter array index is being used in the raw array.

This means that the array [[90,100],[75,100],[85,100],[80,100]] would first count 2 valid entries, create a new array of size 2, and then copy the first two entries from the raw array to create [[90,100],[75,100]] rather than the desired [[75,100],[80,100]].

One approach is to add a "resizeArray()" function (example here: http://www.source-code.biz/snippets/java/3.htm), populate your new array during the initial loop using a separate index (eg "count") which is only incremented upon adding to the new array, then resize the new array down to the target size.

Like so:

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);
}



回答4:


As others have mentioned, the problem is due to the logic flaw in the second loop. You should iterate over the original array instead of the one to be returned.

The answers that make use of ArrayList and resizeArray are both good. In @Perception's answer, ArrayList is used as an intermediate data structure while in @DreadPirateShawn's answer, Array is used as an intermediate data structure. In the end both of them will be resized to the result array to be returned. Since random access to the intermediate data structure is not required, I would prefer using LinkedList instead. Using a linked list does not require any resizing, thus potentially saving some time and space.

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()]);
}


来源:https://stackoverflow.com/questions/14408134/removing-points-from-an-array-and-returning-a-new-array-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!