简体   繁体   English

修改数组的最大元素而不更改其位置?

[英]Modifying the greatest elements of an array without changing their position?

I'm trying to figure out how to modify the n greatest elements of an array without modifying their position. 我试图弄清楚如何修改数组的n个最大元素而不修改它们的位置。 For example, suppose I have an array of ints {5, 2, 3, 4, 8, 9, 1, 3}; 例如,假设我有一个整数数组{5, 2, 3, 4, 8, 9, 1, 3}; 5,2,3,4,8,8,9,1,3 {5, 2, 3, 4, 8, 9, 1, 3}; I want to add 1 to the two greatest elements, making the array {5, 2, 3, 4, 9, 10, 1, 3} . 我想在两个最大的元素上加1,使数组{5, 2, 3, 4, 9, 10, 1, 3}

All of the methods I can think of to go about doing this end up feeling clunky and unintuitive when I try to implement them, signaling to me that I'm not thinking about it correctly. 当我尝试实现它们时,我想到的所有方法最终都会变得笨拙且不直观,向我发出信号,表示我没有正确考虑它。 For example, I could use a TreeMap with the values of the array as keys and their indices as values to find the greatest values, modify them, and then throw them back into the array, but then I would have have to implement my own Comparator to sort the TreeMap in reverse order(unless there's an easier way I'm not aware of?). 例如,我可以使用TreeMap,将数组的值作为键,并将它们的索引作为值,以找到最大的值,对其进行修改,然后将它们放回数组中,但随后必须实现自己的Comparator以相反的顺序对TreeMap排序(除非有一种我不知道的简便方法?)。 I was also considering copying the contents of the array into a list, iterating through n times, each time finding the greatest element and its index, putting the modified greatest element back into the array at that index, removing the element from the list, and repeat, but that feels sloppy and inefficient to me. 我也在考虑将数组的内容复制到列表中,迭代n次,每次找到最大元素及其索引,将修改后的最大元素放回该索引处的数组,从列表中删除该元素,然后重复一遍,但是对我来说这是草率和低效的

Any suggestions as to how to approach this type of problem? 关于如何解决此类问题有什么建议吗?

The simplest thing would be to scan your array, and store the indices of the n highest values. 最简单的方法是扫描您的数组,并存储n个最大值的索引。 Increment the values of those elements. 递增那些元素的值。

This is going to be O(n) performance, and I don't think any fancier methods can beat that. 这将是O(n)的性能,我认为没有任何更出色的方法可以胜过这一点。

edit to add: you can sort the array in place in O(n) at best, in which case you can get the n highest values very quickly, but the requirement is to not change position of the elements, so you'd have to start with a copy of the array if you wanted to do that (or preserve ordering information so you could put everything back afterward). 编辑添加:您最多可以在O(n)中对数组进行排序,在这种情况下,您可以非常快地获得n个最大值,但是要求是不更改元素的位置,因此您必须如果需要这样做,请从阵列的副本开始(或保留订购信息,以便以后可以放回所有内容)。

You might be over engineering the solution to this problem: scan the array, from beginning to end, and mark the two largest elements. 您可能过度设计了此问题的解决方案:从头到尾扫描阵列,并标记两个最大的元素。 Return to the two greatest elements and add 1 to it. 返回两个最重要的元素,并将其加1。 The solution shouldn't be longer than 10 lines. 解决方案不能超过10行。

  1. Loop over the array and keep track of the indices and values of the two largest items 遍历数组,并跟踪两个最大项目的索引和值

    a. 一种。 Initialize the tracker with -1 for an index and MIN_INT for a value or the first two values of the array 初始化-1的索引器和MIN_INT的值或数组的前两个值来初始化跟踪器

    b. At each step of the loop compare the current value against the two tracker values and update if necessary 在循环的每个步骤中,将当前值与两个跟踪器值进行比较,并在必要时进行更新

  2. Increment the two items 增加两个项目

Any algorithm you choose should be O(n) for this. 为此,您选择的任何算法都应为O(n)。 Sorting and n passes are way overkill. 排序和n次传递是过大的方法。

使用此处此处的技术(可以在线性时间内完成)找到第n个最大元素(称为K),然后遍历数组修改所有> = K的元素。

i would do something like this 我会做这样的事情

int[] indices = new int[2];
int[] maximas = new int[] { 0, 0 };
int[] data = new int[] { 3, 4, 5, 1, 9 };
for (int i = 0; i < 5; ++i)
{
    if (data[i] > maximas[1])
    {
            maximas[0] = maximas[1];
            maximas[1] = data[i];
            indices[0] = indices[1];
            indices[1] = i;
    } 
    else if (data[i] > maximas[0])
    {
            maximas[0] = data[i];
            indices[0] = i;
    }
} 

didn't test it, but I think it should work :) 没有测试它,但我认为它应该工作:)

I have tought a bit about this but I cannot achieve more than worstcase: 关于这一点,我有一点点强硬,但除了最坏的情况,我无法取得更多成就:

O( n + (mn) * n ) : (m > n) O(n +(mn)* n):(m> n)

best case: 最好的情况:

O(m) : (m <= n) O(m):(m <= n)

where m = number of values, n = number of greatest value to search 其中m =值的数量,n =要搜索的最大值的数量

This is the implementation in C#, but you can easily adapt to java: 这是C#中的实现,但是您可以轻松地适应Java:

        int n = 3;
        List<int> values = new List<int> {1,1,1,8,7,6,5};
        List<int> greatestIndexes = new List<int>();

        for (int i = 0; i < values.Count; i++) {
            if (greatestIndexes.Count < n)
            {
                greatestIndexes.Add(i);
            }
            else {
                int minIndex = -1, minValue = int.MaxValue;
                for (int j = 0; j < n; j++)
                {
                    if (values[greatestIndexes[j]] < values[i]) {

                        if (minValue > values[greatestIndexes[j]])
                        {
                            minValue = values[greatestIndexes[j]];
                            minIndex = j;
                        }
                    }
                }
                if (minIndex != -1)
                {
                    greatestIndexes.RemoveAt(minIndex);
                    greatestIndexes.Add(i);
                }
            }
        }

        foreach (var i in greatestIndexes) {
            Console.WriteLine(values[i]);
        }

Output: 输出:

8
7
6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM