如何从数组中删除所有最小值的实例?

huangapple go评论63阅读模式
英文:

How can I remove all instances of minimum values from array?

问题

我正在尝试通过在Codeforces上做一些练习问题来准备USACO Bronze,并且我已经在这个问题上挣扎了两个星期。

这是问题的要求。

起初,我正在迭代数组,删除最小元素,将长度存储在一个变量中,然后重复,直到没有值剩余。

然而,这非常低效,效果不好,所以我决定改为计算每个元素的实例数,然后从中减去。

我预期的值是8。然而,我收到的值是1,这使我认为变量值一直被重置,只打印出最后/最大实例出现的次数。

我应该如何修改我的代码,以便能够成功地从数组长度中删除最小元素的实例数,将新长度存储在变量中,并在此过程中不会重置任何值?

请原谅我如果这是一个非常愚蠢的问题,因为我刚刚开始USACO,而且我还不习惯竞技编程。

public class sort {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // System.out.println("PLEASE INSERT AN ELEMENT");
        int x = sc.nextInt();
        int memory[];
        memory = new int[x];
        for (int i = 0; i < x; i++) {
            memory[i] = sc.nextInt();
        }

        Arrays.sort(memory);
        int k = memory.length;
        int mem2[] = new int[x];
        int min = memory[0];
        int array[];
        for (int i = 0; i < k; i++) {
            countFreq(memory, k);
            array = removeElements(memory, min);
            k = k + array.length;
            System.out.println(k);
        }
        System.out.println(k);
        sc.close();
    }

    public static void countFreq(int arr[], int n) {
        boolean visited[] = new boolean[n];

        Arrays.fill(visited, false);
        for (int i = 0; i < n; i++) {
            if (visited[i] == true)
                continue;
            int count = 1;
            for (int j = i + 1; j < n; j++) {
                if (arr[i] == arr[j]) {
                    visited[j] = true;
                    count++;
                }
            }
        }
    }

    public static int[] removeElements(int[] arr, int key) {
        int index = 0;
        for (int i = 0; i < arr.length; i++)
            if (arr[i] != key)
                arr[index++] = arr[i];
        return Arrays.copyOf(arr, index);
    }

    public static int[] addX(int n, int arr[], int x) {
        int j;
        int newarr[] = new int[n + 1];
        for (j = 0; j < n; j++)
            newarr[j] = arr[j];

        newarr[n] = x;

        return newarr;
    }
}
英文:

I'm trying to prepare for USACO Bronze by doing some practice problems on Codeforces, and I've been struggling on this one for a good two weeks.

Here's the prompt.

At first, I was iterating through the array, removing the minimum element, storing the length in a variable, and repeating until there weren't any values left.

However, that was very inefficient and was not working well, so I decided to instead count the number of instances of each element, subtract those from.

The value I expected was 8. However, the value I received was one, leading me to think the variable value keeps getting reset and it only print out the number of times the last/greatest instance occurs.

How do I modify my code so that I'm able to successfully remove the number of instances of the minimum element from the array length, store the new length in a variable and repeat this without any of my values getting reset in the process?

Please excuse me if this is a really dumb question since I'm just starting USACO, and I'm not used to competitive programming yet.

public class sort {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // System.out.println(&quot;PLEASE INSERT AN ELEMENT&quot;);
        int x = sc.nextInt();
        int memory[];
        memory = new int[x];
        for (int i = 0; i &lt; x; i++) {
            memory[i] = sc.nextInt();
        }

        Arrays.sort(memory);
        int k = memory.length;
        int mem2[] = new int[x];
        int min = memory[0];
        int array[];
        for (int i = 0; i &lt; k; i++) {
            countFreq(memory, k);
            array = removeElements(memory, min);
            k = k + array.length;
            System.out.println(k);
        }
        System.out.println(k);
        sc.close();
    }

    public static void countFreq(int arr[], int n) {
        boolean visited[] = new boolean[n];

        Arrays.fill(visited, false);
        for (int i = 0; i &lt; n; i++) {
            if (visited[i] == true)
                continue;
            int count = 1;
            for (int j = i + 1; j &lt; n; j++) {
                if (arr[i] == arr[j]) {
                    visited[j] = true;
                    count++;
                }
            }
        }
    }

    public static int[] removeElements(int[] arr, int key) {
        int index = 0;
        for (int i = 0; i &lt; arr.length; i++)
            if (arr[i] != key)
                arr[index++] = arr[i];
        return Arrays.copyOf(arr, index);
    }

    public static int[] addX(int n, int arr[], int x) {
        int j;
        int newarr[] = new int[n + 1];
        for (j = 0; j &lt; n; j++)
            newarr[j] = arr[j];

        newarr[n] = x;

        return newarr;
    }
}

答案1

得分: 1

代码中的方法没有正确遵循问题描述,排序和计数操作的逻辑也不正确。

一些问题包括:

  • countFreq() 方法没有正确使用。它的目的是计算数组中元素的频率,但在排序过程中没有被利用
  • removeElements() 方法用于从内存数组中删除最小元素的出现次数,但这种方法没有正确模拟所描述的“传送”过程
  • 实现的循环与问题不匹配
  • 您可以使用Java集合而不是原始数组。

我基于提示中传递给您的方式来完成这个问题:

Main - 只是输入

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    int[] redPandas = new int[n];
    for (int i = 0; i &lt; n; i++) {
        redPandas[i] = scanner.nextInt();
    }
    scanner.close();

    int seconds = sortingOperationSeconds(redPandas);
    System.out.println(seconds);
}

sortingOperationSeconds - 实际实现

public static int sortingOperationSeconds(int[] redPandas) {
    Queue&lt;Integer&gt; firstLine = new PriorityQueue&lt;&gt;();
    Queue&lt;Integer&gt; secondLine = new LinkedList&lt;&gt;();

    for (int panda : redPandas) {
        firstLine.offer(panda);
    }

    int seconds = 0;
    while (!firstLine.isEmpty()) {
        int flSize = firstLine.size();
        int flSmallestId = firstLine.peek();
        seconds += flSize;
        for (int i = 0; i &lt; flSize; i++) {
            int currentPanda = firstLine.poll();
            if (currentPanda == flSmallestId) {
                secondLine.offer(currentPanda);
            } else {
                firstLine.offer(currentPanda);
            }
        }
    }

    return seconds;
}

让我们逐步来看:

  1. 小熊猫队列:

    Queue&lt;Integer&gt; firstLine = new PriorityQueue&lt;&gt;();
    Queue&lt;Integer&gt; secondLine = new LinkedList&lt;&gt;();
    

    创建两个队列来表示两行红色熊猫,firstLine 是一个PriorityQueue,其中最小的ID始终位于队列的前端,secondLine 是一个LinkedList,红色熊猫在从firstLine中删除后移动到该队列中。

  2. 将红熊猫添加到firstLine:

    for (int panda : redPandas) {
        firstLine.offer(panda);
    }
    

    redPandas数组中的所有红熊猫提供给firstLine队列。

  3. 排序操作:

    int seconds = 0;
    while (!firstLine.isEmpty()) {
        int flSize = firstLine.size();
        int flSmallestId = firstLine.peek();
        seconds += flSize;
        for (int i = 0; i &lt; flSize; i++) {
            int currentPanda = firstLine.poll();
            if (currentPanda == flSmallestId) {
                secondLine.offer(currentPanda);
            } else {
                firstLine.offer(currentPanda);
            }
        }
    }
    

    只要firstLine不为空,循环就会运行。它计算firstLine中的红熊猫数(flSize)和firstLine中的最小ID(flSmallestId)。然后,它将flSize秒添加到seconds计数器中。

    内部循环逐个从firstLine删除红熊猫。如果当前红熊猫的ID等于最小IDflSmallestId),则将该红熊猫移动到secondLine中。否则,将其返回到firstLine中。

    这个过程持续进行,直到所有红熊猫都被移动到secondLine中。

英文:

The approach used in the code does not follow the problem description correctly, and the logic for sorting and counting the operations is not correct.

Some problems are:

  • The countFreq() method is not used correctly. It's meant to count the frequency of elements in an array, but it's not utilized in the sorting process.
  • The removeElements() method is used to remove occurrences of the minimum element from the memory array, but this approach does not simulate the described teleportation process correctly.
  • The implemented loop does not match the question.
  • You can use Java Collections instead of primitive arrays.

I was based on the prompt you passed, and I did it this way:

Main - Just inputs

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    int[] redPandas = new int[n];
    for (int i = 0; i &lt; n; i++) {
        redPandas[i] = scanner.nextInt();
    }
    scanner.close();

    int seconds = sortingOperationSeconds(redPandas);
    System.out.println(seconds);
}

sortingOperationSeconds - Implementation itself

public static int sortingOperationSeconds(int[] redPandas) {
    Queue&lt;Integer&gt; firstLine = new PriorityQueue&lt;&gt;();
    Queue&lt;Integer&gt; secondLine = new LinkedList&lt;&gt;();

    for (int panda : redPandas) {
        firstLine.offer(panda);
    }

    int seconds = 0;
    while (!firstLine.isEmpty()) {
        int flSize = firstLine.size();
        int flSmallestId = firstLine.peek();
        seconds += flSize;
        for (int i = 0; i &lt; flSize; i++) {
            int currentPanda = firstLine.poll();
            if (currentPanda == flSmallestId) {
                secondLine.offer(currentPanda);
            } else {
                firstLine.offer(currentPanda);
            }
        }
    }

    return seconds;
}

Let’s step by step:

  1. Red Panda Queues:

    Queue&lt;Integer&gt; firstLine = new PriorityQueue&lt;&gt;();
    Queue&lt;Integer&gt; secondLine = new LinkedList&lt;&gt;();
    

    Two Queues are created to represent the two lines of red pandas, the firstLine is a PriorityQueue, where the smallest ID always stays at the front of the queue and the secondLine is a LinkedList, where red pandas are moved after being removed from firstLine.

  2. Adding Red Pandas to firstLine:

    for (int panda : redPandas) {
        firstLine.offer(panda);
    }
    

    Offers all red pandas from the redPandas array to the firstLine queue.

  3. Sorting Operation:

    int seconds = 0;
    while (!firstLine.isEmpty()) {
        int flSize = firstLine.size();
        int flSmallestId = firstLine.peek();
        seconds += flSize;
        for (int i = 0; i &lt; flSize; i++) {
            int currentPanda = firstLine.poll();
            if (currentPanda == flSmallestId) {
                secondLine.offer(currentPanda);
            } else {
                firstLine.offer(currentPanda);
            }
        }
    }
    

    While firstLine is not empty, the loop runs. It calculates the number of red pandas in firstLine (flSize) and the smallest ID in firstLine (flSmallestId). Then, it adds flSize seconds to the seconds counter.

    The inner loop removes red pandas from firstLine one by one. If the ID of the current red panda is equal to the smallest ID (flSmallestId), that red panda is moved to secondLine. Otherwise, it is returned to firstLine.

    This process continues until all red pandas have been moved to secondLine.

答案2

得分: -1

你当前方法的主要问题是在尝试计数和删除元素时修改了原始数组memory,这会导致意外行为和不正确的结果。

不要修改原始数组,可以使用一个单独的数据结构来跟踪每个元素的出现次数,并在不改变数组的情况下移除最小元素。

import java.util.Scanner;
import java.util.Arrays;

public class Sort {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();
        int memory[] = new int[x];

        for (int i = 0; i < x; i++) {
            memory[i] = sc.nextInt();
        }

        int min = Arrays.stream(memory).min().getAsInt();
        int minCount = (int) Arrays.stream(memory).filter(num -> num == min).count();
        int k = x - minCount;

        while (minCount > 0) {
            memory = removeElements(memory, min);
            minCount = (int) Arrays.stream(memory).filter(num -> num == min).count();
            k -= minCount;
        }

        System.out.println(k);
        sc.close();
    }

    public static int[] removeElements(int[] arr, int key) {
        return Arrays.stream(arr).filter(num -> num != key).toArray();
    }
}

我们做了以下修改:

  1. 不使用额外的数组mem2,而是直接使用原始数组memory

  2. 找到数组中的最小元素并计算其出现次数。

  3. 在循环中移除数组中的最小元素,直到最小元素不再出现。在每次迭代中,更新k的值,并重新计算要移除的最小元素的计数。

通过这样做,您可以避免修改原始数组并计算正确的k值,而无需重置任何值。

英文:

The main problem with your current approach is that you are modifying the original array memory while trying to count the occurrences and remove elements. This leads to unexpected behavior and incorrect results.

Instead of modifying the original array, you can use a separate data structure to keep track of the occurrences of each element and remove the minimum element without altering the array.

import java.util.Scanner;
import java.util.Arrays;
public class Sort {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int memory[] = new int[x];
for (int i = 0; i &lt; x; i++) {
memory[i] = sc.nextInt();
}
int min = Arrays.stream(memory).min().getAsInt();
int minCount = (int) Arrays.stream(memory).filter(num -&gt; num == min).count();
int k = x - minCount;
while (minCount &gt; 0) {
memory = removeElements(memory, min);
minCount = (int) Arrays.stream(memory).filter(num -&gt; num == min).count();
k -= minCount;
}
System.out.println(k);
sc.close();
}
public static int[] removeElements(int[] arr, int key) {
return Arrays.stream(arr).filter(num -&gt; num != key).toArray();
}
}

Here's what we did:

1.Instead of using an additional array mem2, we directly use the original array memory.

2.We find the minimum element in the array and count its occurrences.

3.We remove the minimum element from the array in a loop until there are no more occurrences of the minimum element. In each iteration, we update the count of k and recalculate the count of the minimum element to be removed.

By doing this, you can avoid modifying the original array and calculate the correct value of k without resetting any values.

huangapple
  • 本文由 发表于 2023年7月27日 21:11:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76780103.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定