寻找数组中的最小峰值元素

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

Find minimum peak elements in an array

问题

public int[] findMinimumPeaks(int[] arr){
    List<Integer> list1 = new ArrayList<Integer>(arr.length);
    int[] output = new int[arr.length];
    for(int i: arr)
        list1.add(i);

    for(int i =0; i<arr.length; i++){
        int minIndex = minimumPeakElement(list1);
        output[i] = list1.get(minIndex);
        list1.remove(minIndex);
    }
    return output;
}

public int minimumPeakElement(List<Integer> list1){
    int minIndex = 0, peakStart = Integer.MAX_VALUE, peakEnd = Integer.MAX_VALUE;
    int peak = Integer.MAX_VALUE, minPeak = Integer.MAX_VALUE;

    if(list1.size() >= 2){
        if(list1.get(0) > list1.get(1)) peakStart = list1.get(0);
        if(list1.get(list1.size() - 1) > list1.get(list1.size() - 2)) peakEnd = list1.get(list1.size() - 1);
        if(peakStart < peakEnd){
            minPeak = peakStart;
            minIndex = 0;
        }
        else if(peakEnd < peakStart){
            minPeak = peakEnd;
            minIndex = list1.size() - 1;
        }
    }

    for(int i=1; i<list1.size() - 1; i++){
        if(list1.get(i) > list1.get(i + 1) && list1.get(i) > list1.get(i-1)) peak = list1.get(i);
        if(peak < minPeak){
            minPeak = peak;
            minIndex = i;
        } 
    }
    return minIndex;
}

Note: The code provided is the same as the original code you posted. I've only removed the HTML escape codes (e.g., &lt; and &gt;) for better readability. If you're looking for an optimized solution, I would recommend analyzing the algorithm and data structures used to see if there are any improvements that can be made.

英文:

Question: Given an array numbers = {2, 7, 8, 5, 1, 6, 3, 9, 4}. Check the below conditions, both the conditions should be satisfied.

  1. a[i] &gt; a[i-1] or if first element a[i] &gt; a[i+1]
  2. a[i] &gt; a[i+1] or if last element a[lastelement] &gt; a[lastelement - 1]

Therefore:

  • 1st Iteration - 8, 6, 9 are peak values. Remove the smallest ele. Remove 6. New arr {2, 7, 8, 5, 1, 3, 9, 4}. Output Arr - {6}

  • 2nd Iteration - 8, 9 are peak values. Remove the smallest ele. Remove 8. New arr {2, 7, 5, 1, 3, 9, 4}. Output Arr - {6, 8}

  • 3rd Iteration - 7, 9 are peak values. Remove the smallest ele. Remove 7. New arr {2, 5, 1, 3, 9, 4}. Output Arr - {6, 7, 8}

  • 4th Iteration - 5, 9 are peak values. Remove the smallest ele. Remove 5. New arr {2, 1, 3, 9, 4}. Output Arr - {6, 7, 8, 5}

  • 5th Iteration - 2, 9 are peak values. Remove the smallest ele. Remove 2. New arr {1, 3, 9, 4}. Output Arr - {6, 7, 8, 5, 2}

  • 6th Iteration - 9 are peak values. Remove the smallest ele. Remove 9. New arr {1, 3, 4}. Output Arr - {6, 7, 8, 5, 2, 9}

  • 7th Iteration - 4 are peak values. Remove the smallest ele. Remove 4. New arr {1, 3}. Output Arr - {6, 7, 8, 5, 2, 9, 4}

  • 8th Iteration - 3 are peak values. Remove the smallest ele. Remove 3. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3}

  • 9th Iteration - 1 are peak values. Remove the smallest ele. Remove 1. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3, 1}

Output: {6, 8, 7, 5, 2, 9, 4, 3, 1}

My solution is working but I am looking for optimized solution. Please let me know.

Here is my code:

public int[] findMinimumPeaks(int[] arr){
List&lt;Integer&gt; list1 = new ArrayList&lt;Integer&gt;(arr.length);
int[] output = new int[arr.length];
for(int i: arr)
list1.add(i);
for(int i =0; i&lt;arr.length; i++){
int minIndex = minimumPeakElement(list1);
output[i] = list1.get(minIndex);
list1.remove(minIndex);
}
return output;
}
public int minimumPeakElement(List&lt;Integer&gt; list1){
int minIndex = 0, peakStart = Integer.MAX_VALUE, peakEnd = Integer.MAX_VALUE;
int peak = Integer.MAX_VALUE, minPeak = Integer.MAX_VALUE;
if(list1.size() &gt;= 2){
if(list1.get(0) &gt; list1.get(1)) peakStart = list1.get(0);
if(list1.get(list1.size() - 1) &gt; list1.get(list1.size() - 2)) peakEnd = list1.get(list1.size() - 1);
if(peakStart &lt; peakEnd){
minPeak = peakStart;
minIndex = 0;
}
else if(peakEnd &lt; peakStart){
minPeak = peakEnd;
minIndex = list1.size() - 1;
}
}
for(int i=1; i&lt;list1.size() - 1; i++){
if(list1.get(i) &gt; list1.get(i + 1) &amp;&amp; list1.get(i) &gt; list1.get(i-1)) peak = list1.get(i);
if(peak &lt; minPeak){
minPeak = peak;
minIndex = i;
} 
}
return minIndex;
}

答案1

得分: 1

以下是如何优化渐近复杂性的想法。

使用一次对初始数组的元素进行遍历,将其分割成“上升-下降”、“斜坡”或“山坡”,即升序排列的元素子序列,后跟降序排列的子序列。
寻找数组中的最小峰值元素

将这些斜坡存储在以下数据结构中:

val slopes = MinPriorityQueue<Slope>()

class Slope(
 var first: Int, // 斜坡的第一个元素
 var last: Int,   // 斜坡的最后一个元素
 var peak: Int,   // 最大或峰值元素
 var els: MaxPriorityQueue<Int>(),  // 斜坡的所有元素
 var prev: Slope?,    // 列表中前一个斜坡的链接,如果是第一个则为null
 var next: Slope?     // 列表中下一个斜坡的链接,如果是最后一个则为null
)

斜坡应该按照它们的peak值进行比较。

现在,有了这个数据结构,您可以在O(log(N))时间内poll具有最小峰值的斜坡。在弹出斜坡后,您应该通过移除其峰值元素(即弹出els,然后更新firstlastpeak)来更新斜坡,另外,斜坡可能有资格与前一个或下一个斜坡合并:

寻找数组中的最小峰值元素

诚然,这个解决方案并不简单,需要维护很多内容和大量的边缘情况。然而,从渐近复杂性的角度来看,它要好得多。

  • 初始数据结构构建:O(n log(n))
  • 在维护斜坡的同时进行元素轮询:O(n log(n))
  • 总体复杂性:O(n log(n))

注:

  1. 其中一个边缘情况是,如果数组可以包含重复元素,那么内部优先级队列(els)将变为MaxPriorityQueue<Pair<Int, Int>>,即您需要同时存储潜在的重复元素数量和元素值。

  2. MinPriorityQueueMaxPriorityQueue是一个基于堆的抽象数据结构,其中分别在头部具有最小和最大元素。可以在Java中使用PriorityQueue来实现。

英文:

Here is an idea how to optimize asymptotic complexity.

Use single pass over elements of your initial array to split it into "up-down" "slopes" or "hills", i.e. subsequence of elements in ascending order, followed by subsequence in descending order.
寻找数组中的最小峰值元素

Store these slopes in the following datastructure:

val slopes = MinPriorityQueue&lt;Slope&gt;()
class Slope(
var first: Int, // first element of the slope
var last: Int,   // last element of the slope
var peak: Int,   // max or peak element
var els: MaxPriorityQueue&lt;Int&gt;(),  // all elements of the slope
var prev: Slope?,    // link to the previous slope in the list or null if first
var next: Slope?     // link to the next slope in the list or null if last
)

Slopes should be comparable by their peak value.

Now, having this data structure, you can poll the slope that has minimal peak value in O(log(N)). After you polled the slope, you should update the slope by removing it's peak element (i.e. poll els, then update first, last, peak), also, slope might become eligible to be merged with the previous or next slope:

寻找数组中的最小峰值元素

Admittedly, this solution is not an easy one, having a lot of things to maintain and large number of corner cases. However, it's much better in terms of asymptotic complexity.

  • Initial data structure build: O(n log(n))
  • Polling elements while maintaining slopes: O(n log (n))
  • Overall complexity: O(n log(n))

Notes:

  1. One of the corner cases, if array can have duplicate elements, then inner priority queue (els) becomes MaxPriorityQueue&lt;Pair&lt;Int,Int&gt;&gt;, i.e. you need to store the number of potentially duplicate elements along with the element value.

  2. MinPriorityQueue and MaxPriorityQueue is an abstract heap-based data structure with min and max element at the head respectively. Can be implemented with PriorityQueue in java

huangapple
  • 本文由 发表于 2020年8月28日 00:24:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63620300.html
匿名

发表评论

匿名网友

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

确定