Peak和Flag Codility最新挑战

时间:2013-10-19 12:38:53

标签: javascript algorithm

我正在尝试解决最新的codility.com问题(仅用于提高我的技能)。我试过分配,但没有超过30分,所以现在好奇我在解决方案中究竟缺少什么。

问题是

给出了由N个整数组成的非空零索引数组A.峰值是一个比其邻居更大的数组元素。更确切地说,它是指数P,使得

0 < P < N − 1 and A[P − 1] < A[P] > A[P + 1]

例如,以下数组A:

A[0] = 1 
A[1] = 5 
A[2] = 3 
A[3] = 4 
A[4] = 3 
A[5] = 4 
A[6] = 1 
A[7] = 2 
A[8] = 3 
A[9] = 4 
A[10] = 6 
A[11] = 2

恰好有四个峰:元素1,3,5和10.

您将前往一系列山脉,其相对高度由数组A表示。您必须选择应该携带多少个标志。目标是根据某些规则设置峰值上的最大标志数。

标志只能在峰值上设置。更重要的是,如果你拿K标志,那么任何两个标志之间的距离应该大于或等于K.指数P和Q之间的距离是绝对值| P - Q |。

例如,给定由上面的数组A表示的山脉,N = 12,如果你采取:

> two flags, you can set them on peaks 1 and 5; 

> three flags, you can set them on peaks 1, 5 and 10; 

> four flags, you can set only three flags, on peaks 1, 5 and 10.

因此,在这种情况下,您最多可以设置三个标志。

编写一个函数,给定N个整数的非空零索引数组A,返回可以在数组峰值上设置的最大标志数。 例如,给定上面的数组

该函数应返回3,如上所述。

假设:

N是[1..100,000]范围内的整数;

数组A的每个元素都是[0..1,000,000,000]范围内的整数。

复杂度:

预期的最坏情况时间复杂度为O(N); 预期的最坏情况空间复杂度是O(N),超出输入存储(不计算 输入参数所需的存储空间。)

所以我根据我对问题的理解

尝试了这段代码
var A = [1,5,3,4,3,4,1,2,3,4,6,2];

function solution(A) {
 array = new Array();  
   for (i = 1; i < A.length - 1; i++) {  
    if (A[i - 1] < A[i] && A[i + 1] < A[i]) {  
     array.push(i);  
    }  
   }  

  //console.log(A);
  //console.log(array);
  var position = array[0];
  var counter = 1;
  var len = array.length;
  for (var i = 0; i < len; i++) {
    if (Math.abs(array[i+1] - position) >= len) {
        position = array[i+1];
        counter ++;
        }
    }

  console.log("total:",counter);
  return counter;

}

以上代码适用于示例数组元素:[1,5,3,4,3,4,1,2,3,4,6,2] 在索引处获取峰值:[1, 3, 5, 10]并在1, 5, and 10 (total 3)

处设置标记

但codility.com表示它在阵列[7, 10, 4, 5, 7, 4, 6, 1, 4, 3, 3, 7]上失败 我的代码在索引处获得峰值:[1, 4, 6, 8]并将标志设置为1和6(总计2) 但是coditity.com说它应该是3面旗帜。 (不明白为什么) 我想念 - 理解这个问题吗?

请我只是寻找提示/算法。我知道这个问题已被某人提出并在私人聊天室中解决但在该页面上我试图获得该人的帮助,但成员却将我的帖子标记为不恰当的答案,所以我再次在这里提问。

P.S:您可以点击挑战自己在www.codility.com上试用您的代码!

21 个答案:

答案 0 :(得分:4)

import java.util.Arrays;
import java.lang.Integer;
import java.util.ArrayList;
import java.util.List;
public int solution(int[] A) 
{
    ArrayList<Integer> array = new ArrayList<Integer>();  
        for (int i = 1; i < A.length - 1; i++) 
        {  
            if (A[i - 1] < A[i] && A[i + 1] < A[i]) 
            {  
                array.add(i);  
            }  
        }  
   if (array.size() == 1 || array.size() == 0) 
   {  
        return array.size();  
   }  
    int sf = 1;  
    int ef = array.size();  
    int result = 1;  
    while (sf <= ef) 
    {  
        int flag = (sf + ef) / 2;  
        boolean suc = false;  
        int used = 0;  
        int mark = array.get(0);  
        for (int i = 0; i < array.size(); i++) 
        {  
            if (array.get(i) >= mark) 
            {  
                used++;  
                mark = array.get(i) + flag;  
                    if (used == flag) 
                    {                       
                        suc = true;  
                        break;  
                    }  
            }  
        }  
        if (suc) 
        {  
            result = flag;  
            sf = flag + 1;  
        } 
        else 
        {  
            ef = flag - 1;  
        }  
    }  
   return result;  
 }

答案 1 :(得分:3)

缺少100%PHP解决方案:)

function solution($A)
{
    $p = array(); // peaks
    for ($i=1; $i<count($A)-1; $i++)
        if ($A[$i] > $A[$i-1] && $A[$i] > $A[$i+1])
            $p[] = $i;

    $n = count($p);
    if ($n <= 2)
        return $n;

    $maxFlags = min(intval(ceil(sqrt(count($A)))), $n); // max number of flags
    $distance = $maxFlags; // required distance between flags
    // try to set max number of flags, then 1 less, etc... (2 flags are already set)
    for ($k = $maxFlags-2; $k > 0; $k--)
    {
        $left = $p[0];
        $right = $p[$n-1];
        $need = $k; // how many more flags we need to set

        for ($i = 1; $i<=$n-2; $i++)
        {
            // found one more flag for $distance
            if ($p[$i]-$left >= $distance && $right-$p[$i] >= $distance)
            {
                if ($need == 1)
                    return $k+2;
                $need--;
                $left = $p[$i];
            }

            if ($right - $p[$i] <= $need * ($distance+1))
                break; // impossible to set $need more flags for $distance
        }

        if ($need == 0)
            return $k+2;

        $distance--;
    }
    return 2;
}

答案 2 :(得分:3)

这是一个具有更好的上层复杂性界限的解决方案:

  • 时间复杂度:O(sqrt(N) * log(N))
  • 空间复杂度:O(1)(超过原始输入存储空间)

Python实现

from math import sqrt

def transform(A):
    peak_pos = len(A)
    last_height = A[-1]
    for p in range(len(A) - 1, 0, -1):
        if (A[p - 1] < A[p] > last_height):
            peak_pos = p
        last_height = A[p]
        A[p] = peak_pos
    A[0] = peak_pos

def can_fit_flags(A, k):
    flag = 1 - k
    for i in range(k):
        # plant the next flag at A[flag + k]
        if flag + k > len(A) - 1:
            return False
        flag = A[flag + k]
    return flag < len(A)  # last flag planted successfully

def solution(A):
    transform(A)
    lower = 0
    upper = int(sqrt(len(A))) + 2
    assert not can_fit_flags(A, k=upper)
    while lower < upper - 1:
        next = (lower + upper) // 2
        if can_fit_flags(A, k=next):
            lower = next
        else:
            upper = next
    return lower

描述

O(N)预处理(就地完成):

A[i] := next peak or end position after or at position i
        (i for a peak itself, len(A) after last peak)

如果我们可以种植k标志,那么我们当然也可以种植k' < k标志。 如果我们不能种植k标志,那么我们当然也不能种植k' > k标志。 我们总是可以设置0个标志。 我们假设我们不能设置X标志。 现在我们可以使用二进制搜索来确切地确定可以种植多少个标志。

Steps:
  1. X/2
  2. X/2 +- X/4
  3. X/2 +- X/4 +- X/8
  ...
  log2(X) steps in total

通过之前的预处理,可以在k操作中执行测试是否可以种植O(k)标记的每个步骤:

  • flag(0)= next(0)
  • flag(1)= next(flag(1)+ k) ...
  • flag(k-1)= next(flag(k-2)+ k)

总费用 - 最糟糕的情况 - 可以种植X - 1个标志:

  

== X *(1/2 + 3/4 + ... +(2 ^ k - 1)/(2 ^ k))
   == X *(log2(X)-1 +(&lt; 1))
   &lt; = X * log(X)

使用X == N会起作用,并且很可能也是次线性的,但不足以用于证明此算法的总上限在O(N)之下。

现在一切都取决于找到一个好的X,并且因为k标志需要大约k^2个位置,所以标志数量似乎应该是一个很好的上限发现在sqrt(N)附近。

如果X == sqrt(N)或其附近有效,那么我们得到O(sqrt(N) * log(sqrt(N)))的上限,这肯定是次线性的,因为log(sqrt(N)) == 1/2 * log(N)上限等于O(sqrt(N) * log(N))

让我们查找sqrt(N)周围所需标志数量的更精确上限:

  • 我们知道k标志需要Nk := k^2 - k + 3标志
  • 通过求解k^2 - k + 3 - N = 0上的等式k,我们发现如果k >= 3,那么任意数量的标志&lt; =生成的k都可以适合某个长度序列N和更大的不能;该等式的解决方案是1/2 * (1 + sqrt(4N - 11))
  • 对于N >= 9我们知道我们可以装3个旗帜 ==&GT;对于N >= 9k = floor(1/2 * (1 + sqrt(4N - 11))) + 1N
  • 中可以容纳的标志数量的严格上限
  • 对于N < 9我们知道3是一个严格的上界但这些情况并不关心我们找到big-O算法的复杂性
  

楼层(1/2 *(1 + sqrt(4N - 11)))+ 1
    ==楼层(1/2 + sqrt(N - 11/4))+ 1
    &lt; = floor(sqrt(N - 11/4))+ 2
    &lt; = floor(sqrt(N))+ 2

==&GT; floor(sqrt(N)) + 2对于许多适合N元素的标志也是一个很好的严格上限+这个标准甚至适用于N < 9,所以它可以用作通用的严格上限我们的实施也是如此

如果我们选择X = floor(sqrt(N)) + 2,我们得到以下总算法上限:

O((floor(sqrt(N)) + 2) * log(floor(sqrt(N)) + 2))
   {floor(...) <= ...}
O((sqrt(N) + 2) * log(sqrt(N) + 2))
   {for large enough N >= 4: sqrt(N) + 2 <= 2 * sqrt(N)}
O(2 * sqrt(N) * log(2 * sqrt(N)))
   {lose the leading constant}
O(sqrt(N) * (log(2) + loq(sqrt(N)))
O(sqrt(N) * log(2) + sqrt(N) * log(sqrt(N)))
   {lose the lower order bound}
O(sqrt(N) * log(sqrt(N)))
   {as noted before, log(sqrt(N)) == 1/2 * log(N)}
O(sqrt(N) * log(N))
                                  QED

答案 3 :(得分:1)

我知道答案是由francesco Malagrino提供的,但我已经编写了自己的代码。对于阵列{1,5,3,4,3,4,1,2,3,4,6,2}和{7,10,4,5,7,4,6​​,1,4,3, 3,7}我的代码工作正常。当我在代码考试中接受我的代码时,我在{9,9,4,3,5,4,5,2,8,9,3,1}上失败了

我的回答是3个最大标志。我理解它的方式应该是3但是相反 正确的答案是2,还有francesco Malagrino的解决方案。

我的代码中似乎有什么问题,为什么答案应该只是2 峰值4,6,9之间的距离遵循规则。

private static int getpeak(int[] a) {
    List<Integer> peak = new ArrayList<Integer>();
    int temp1 = 0;
    int temp2 = 0;
    int temp3 = 0;

    for (int i = 1; i <= (a.length - 2); i++) {
        temp1 = a[i - 1];
        temp2 = a[i];
        temp3 = a[i + 1];
        if (temp2 > temp1 && temp2 > temp3) {
            peak.add(i);
        }
    }

    Integer[] peakArray = peak.toArray(new Integer[0]);
    int max = 1;
    int lastFlag = 0;

    for (int i = 1; i <= peakArray.length - 1; i++) {
        int gap = peakArray[i] - peakArray[lastFlag];
        gap = Math.abs(gap);
        if (gap >= i+1) {
            lastFlag = i;
            max = max + 1;
        }
    }
    return max;
}

答案 4 :(得分:1)

这是一个100%得分的C ++解决方案

int test(vector<int> &peaks,int i,int n)
{
int j,k,sum,fin,pos;

fin =  n/i;
for (k=0; k< i; k++) 
{
     sum=0;
     for (j=0; j< fin; j++) 
     {   pos = j + k * fin;
         sum=sum + peaks[ pos  ];        
     }
     if (0==sum) return 0;
}   
return 1;   
}

int solution(vector<int> &A) {
// write your code in C++98 
int i,n,max,r,j,salir;
n = A.size();  
vector<int> peaks(n,0);

if (0==n) return 0;
if (1==n) return 0;

for (i=1; i< (n-1) ; i++)
{     
    if (  (A[i-1] < A[i]) && (A[i+1] < A[i]) ) peaks[i]=1;   
}
i=1;
max=0;
salir =0;
while ( ( i*i < n) && (0==salir) )
{
    if ( 0== n % i)
    {
        r=test(peaks,i,n);
        if (( 1==r ) && (i>max)) max=i; 

        j = n/i;
        r=test(peaks,j,n);
        if (( 1==r ) && (j>max)) max=j; 
        if ( max > n/2) salir =1;
    }
    i++;
}

if (0==salir)
{
    if (i*i == n) 
    {

        if ( 1==test(peaks,i,n) ) max=i;

    } 
}



return max;

}

答案 5 :(得分:1)

C ++解决方案,检测到O(N)

#include <algorithm>

int solution(vector<int> &a) {

    if(a.size() < 3) return 0;

    std::vector<int> peaks(a.size());

    int last_peak = -1;

    peaks.back() = last_peak;

    for(auto i = ++a.rbegin();i != --a.rend();i++)
    {

        int index = a.size() - (i - a.rbegin()) - 1;
        if(*i > *(i - 1) && *i > *(i + 1))
            last_peak = index;
        peaks[index] = last_peak;
    }

    peaks.front() = last_peak;

    int max_flags = 0;

    for(int i = 1;i*i <= a.size() + i;i++)
    {
        int next_peak = peaks[0];
        int flags = 0;
        for(int j = 0;j < i && next_peak != -1;j++, flags++)
        {               
            if(next_peak + i >= a.size())
                next_peak = -1;
            else
                next_peak = peaks[next_peak + i];            
        }
        max_flags = std::max(max_flags, flags);
    }

    return max_flags;

}

答案 6 :(得分:0)

这是一个100%的Java解决方案

class Solution {
    public int solution(int[] A) {

        int[] nextPeaks = nextPeaks(A);

        int flagNumebr = 1;
        int result = 0;

        while ((flagNumebr-1)*flagNumebr <= A.length) {

            int flagPos = 0;
            int flagsTaken = 0;

            while (flagPos < A.length && flagsTaken < flagNumebr) {
                flagPos = nextPeaks[flagPos];

                if (flagPos == -1) {
                    // we arrived at the end of the peaks;
                    break;
                }

                flagsTaken++;
                flagPos += flagNumebr;
            }
            result = Math.max(result, flagsTaken);
            flagNumebr++;

        }

        return  result;



    }

    private boolean[] createPeaks(int[] A) {
        boolean[] peaks = new boolean[A.length];
        for (int i = 1; i < A.length-1; i++) {
            if (A[i - 1] < A[i] && A[i] > A[i + 1]) {
                peaks[i] = true;
            }
        }

        return  peaks;
    }

    private int[] nextPeaks (int[] A) {
        boolean[] peaks = createPeaks(A);
        int[] nextPeaks = new int[A.length];
        // the last position is always -1
        nextPeaks[A.length-1] = -1;

        for (int i = A.length-2; i >= 0 ; i--) {
            nextPeaks[i] = peaks[i] ? i : nextPeaks[i+1];
        }

        return  nextPeaks;
    }
}

答案 7 :(得分:0)

我 100% 使用 Java 中的这个解决方案。我为第一个循环做了一件事来找到峰值,即在找到峰值后我跳过下一个元素,因为它小于峰值。 我知道这个解决方案可以由小组成员进一步优化,但这是我目前能做的最好的,所以请告诉我如何进一步优化它。

检测时间复杂度:O(N) https://app.codility.com/demo/results/trainingG35UCA-7B4/

public static int solution(int[] A) {
        int N = A.length;
        if (N < 3)
            return 0;
        
        ArrayList<Integer> peaks = new ArrayList<Integer>();
 
        for (int i = 1; i < N - 1; i++) {
 
            if (A[i] > A[i - 1]) {
                if (A[i] > A[i + 1]) {
                    peaks.add(i);
                    i++;// skip for next as A[i + 1] <  A[i] so no need to check again
 
                }
            }
        }
 
        
        int size = peaks.size();
        if (size < 2)
            return size;
 
        int k = (int) Math.sqrt(peaks.get(size - 1) - peaks.get(0))+1; // added 1 to round off
        int flagsLeft = k - 1; // one flag is used for first element
        int maxFlag = 0;
        int prevEle = peaks.get(0);
 
        while (k > 0) { // will iterate in descending order
            flagsLeft = k - 1; // reset first peak flag 
            prevEle = peaks.get(0);  // reset the flag to first element
 
            for (int i = 1; i < size && flagsLeft > 0; i++) {
 
                if (peaks.get(i) - prevEle >= k) {
                    flagsLeft--;
                    prevEle = peaks.get(i);
                }
 
                if ((size - 1 - i) < flagsLeft) { // as no. of peaks < flagsLeft
                    break;
                    
                }
            }
 
            
            if (flagsLeft == 0 && maxFlag < k) {
                maxFlag = k;
                break; // will break at first highest flag as iterating in desc order
            }
 
            k--;
        }
 
        return maxFlag;
    }

答案 8 :(得分:0)

def solution(A):
    peak=[x for x in range(1,len(A))if A[x-1]<A[x]>A[x+1]]
    max_flag=len(peak)
    for x in range(1,max_flag+1):
        for y in range(x-1):
            if abs(peak[y]-peak[y+1])>=max_flag:
                max_flag=max_flag-1
    print(max_flag)**strong text**

答案 9 :(得分:0)

我的 C++ 解决方案,100% 结果

def check(reaction, user):
        return user == ctx.author and str(reaction.emoji) in ["◀️", "▶️"]
        # This makes sure nobody except the command sender can interact with the "menu"

答案 10 :(得分:0)

100%python解决方案,比@JurkoGospodnetić上面发布的解决方案简单得多

https://github.com/niall-oc/things/blob/master/codility/flags.py

https://app.codility.com/demo/results/training2Y78NP-VHU/

您无需对此问题进行二进制搜索。 MAX标志是((在第一个和最后一个标志之间分布的)平方根)+1。索引9的第一个峰值和索引58的最后一个峰值意味着扩展为sqrt(49),即(7)+1。因此,尝试8个标志,然后尝试7个然后是6个,依此类推。解决方案达到顶峰后,您应该休息一下!无需鞭打一匹死马!

答案 11 :(得分:0)

具有O(N)复杂度的100%Java解决方案。

https://app.codility.com/demo/results/trainingPNYEZY-G6Q/

class Solution {
    public int solution(int[] A) {
        // write your code in Java SE 8
        int[] peaks = new int[A.length];
        int peakStart = 0;
        int peakEnd = 0;
        
        //Find the peaks.
        //We don't want to traverse the array where peaks hasn't started, yet, 
        //or where peaks doesn't occur any more.
        //Therefore, find start and end points of the peak as well.
        for(int i = 1; i < A.length-1; i++) {
            if(A[i-1] < A[i] && A[i+1] < A[i]) {
                peaks[i] = 1;
                peakEnd = i + 1;
            }
            if(peakStart == 0) {
                peakStart = i;
            }
        }
        
        int x = 1;
        //The maximum number of flags can be √N
        int limit = (int)Math.ceil(Math.sqrt(A.length));
        int prevPeak = 0;
        int counter = 0;
        int max = Integer.MIN_VALUE;
        
        while(x <= limit) {
            counter = 0;
            prevPeak = 0;
            for(int y = peakStart; y < peakEnd; y++) {
                //Find the peak points when we have x number of flags.
                if(peaks[y] == 1 && (prevPeak == 0 || x <= (y - prevPeak))) {
                    counter++;
                    prevPeak = y;
                }
                //If we don't have any more flags stop.
                if(counter == x ) {
                    break;
                }
            }
            //if the number of flags set on the peaks starts to reduce stop searching.
            if(counter <= max) {
                return max;
            }
            //Keep the maximum number of flags we set on.
            max = counter;
            x++;
        }
        return max;
    }
}
  • 我们可以带走的标志数量与 我们可以设置的标志数。我们不能设置超过√N个 因为N /√N=√N如果设置大于√N,则最终 峰上设置的标志数量减少。

  • 当我们增加带走旗帜的数量时, 我们可以设置的标志增加到一个点。在那之后的数字 我们可以设置的标志数量将减少。因此,当数量 我们可以设置的标志开始减少一次,我们不必检查 其余可能的解决方案。

  • 我们在代码的开头标记峰值,并且 标记第一个和最后一个峰值点。这减少了不必要的 检查峰从大块的最后一个元素开始的位置 数组或最后一个峰出现在大分子的最开始的元素上 数组。

答案 12 :(得分:0)

第一个想法是我们不能设置超过sqrt(N)个标志。假设我们已经使用了N个标志,在这种情况下,我们应该至少有N * N个项目来设置所有标志,因为N是标志之间的最小距离。因此,如果我们有N个项目,则不可能设置超过sqrt(N)个标志。

function solution(A) {
    const peaks = searchPeaks(A);
    const maxFlagCount = Math.floor(Math.sqrt(A.length)) + 1;

    let result = 0;
    for (let i = 1; i <= maxFlagCount; ++i) {
        const flagsSet = setFlags(peaks, i);
        result = Math.max(result, flagsSet);
    }

    return result;
}

function searchPeaks(A) {
    const peaks = [];

    for (let i = 1; i < A.length - 1; ++i) {
        if (A[i] > A[i - 1] && A[i] > A[i + 1]) {
            peaks.push(i);
        }
    }

    return peaks;
}

function setFlags(peaks, flagsTotal) {
    let flagsSet = 0;
    let lastFlagIndex = -flagsTotal;

    for (const peakIndex of peaks) {
        if (peakIndex >= lastFlagIndex + flagsTotal) {
            flagsSet += 1;
            lastFlagIndex = peakIndex;

            if (flagsSet === flagsTotal) {
                return flagsSet;
            }
        }
    }

    return flagsSet;
}

这种解决方案具有O(N)的复杂性。我们应该遍历A以找到峰值,并从1迭代到sqrt(N)标志计数,以尝试设置所有标志。因此,我们有O(N + 1 + 2 + 3 ... sqrt(N)) = O(N + sqrt(N*N)) = O(N)的复杂性。

上述解决方案非常快,并且可以得到100%的结果,但可以进行更优化。想法是二进制搜索标志计数。让我们使用F标志并尝试全部设置它们。如果留下多余的标志,则答案将不再是tan F。但是,如果所有标志都已设置并且有更多标志的空间,则答案大于F

function solution(A) {
    const peaks = searchPeaks(A);
    const maxFlagCount = Math.floor(Math.sqrt(A.length)) + 1;
    return bSearchFlagCount(A, peaks, 1, maxFlagCount);
}

function searchPeaks(A) {
    const peaks = [];

    for (let i = 1; i < A.length - 1; ++i) {
        if (A[i] > A[i - 1] && A[i] > A[i + 1]) {
            peaks.push(i);
        }
    }

    return peaks;
}

function bSearchFlagCount(A, peaks, start, end) {
    const mid = Math.floor((start + end) / 2);
    const flagsSet = setFlags(peaks, mid);

    if (flagsSet == mid) {
        return mid;
    } else if (flagsSet < mid) {
        return end > start ? bSearchFlagCount(A, peaks, start, mid) : mid - 1;
    } else {
        return bSearchFlagCount(A, peaks, mid + 1, end);
    }
}

function setFlags(peaks, flagsTotal) {
    let flagsSet = 0;
    let lastFlagIndex = -flagsTotal;

    for (const peakIndex of peaks) {
        if (peakIndex >= lastFlagIndex + flagsTotal) {
            flagsSet += 1;
            lastFlagIndex = peakIndex;

            // It only matters that we can set more flags then were taken.
            // It doesn't matter how many extra flags can be set.
            if (flagsSet > flagsTotal) {
                return flagsSet;
            }
        }
    }

    return flagsSet;
}

Here is该任务的官方Codility解决方案。

答案 13 :(得分:0)

检测到100%python O(N)。

import math
def solution(A):
 N=len(A)
#Trivial cases
 if N<3:
    return 0
 Flags_Idx=[]

 for p in range(1,N-1):
     if A[p-1]<A[p] and A[p]>A[p+1] :
         Flags_Idx.append(p)

 if len(Flags_Idx)==0:
    return 0
 if len(Flags_Idx)<=2:
     return len(Flags_Idx)
 Start_End_Flags=Flags_Idx[len(Flags_Idx)-1]-Flags_Idx[0]  
#Maximum number of flags N is such that Start_End_Flags/(N-1)>=N
#After solving a second degree equation we obtain the maximal value of N
 num_max_flags=math.floor(1.0+math.sqrt(4*Start_End_Flags+1.0))/2.0

#Set the current number of flags to its total number      
 len_flags=len(Flags_Idx)
 min_peaks=len(Flags_Idx)
 p=0

#Compute the minimal number of flags by checking each indexes
#and comparing to the maximal theorique value num_max_flags
 while p<len_flags-1:
    add = 1
#Move to the next flag until the condition Flags_Idx[p+add]-Flags_Idx[p]>=min(num_max_flags,num_flags) 
    while Flags_Idx[p+add]-Flags_Idx[p]<min(num_max_flags,min_peaks):
         min_peaks-=1
         if p+add<len_flags-1:
          add+=1
         else:
             p=len_flags
             break
    p+=add

 if num_max_flags==min_peaks:
  return min_peaks
#Bisect the remaining flags : check the condition
#for flags in [min_peaks,num_max_flags]
 num_peaks=min_peaks
 for nf in range (min_peaks,int(num_max_flags)+1):
  cnt=1
  p=0
  while p<len_flags-1:
    add = 1
    while Flags_Idx[p+add]-Flags_Idx[p]<nf:
         if p+add<len_flags-1:
          add+=1
         else:
             cnt-=1
             p=len_flags
             break
    p+=add
    cnt+=1
  num_peaks=max(min(cnt,nf),num_peaks)  
 return num_peaks

我首先计算出最大数量的标志以验证情况 Interval /(N-1)> = N,其中Interval是第一个和最后一个标志之间的索引差。然后浏览所有标志,并与该值的最小值和当前标志数进行比较。如果条件未经验证,则减去。 获得最小数量的标志并将其用作检查条件的起点 其余的(间隔[min_flag,max_flag])。

答案 14 :(得分:0)

100%有效的JS解决方案:

function solution(A) {
    let peaks = [];

    for (let i = 1; i < A.length - 1; i++) {
        if (A[i] > A[i - 1] && A[i] > A[i + 1]) {
            peaks.push(i);  
        }
    }

    let n = peaks.length;
    if (n <= 2) {
        return n;
    }

    let maxFlags = Math.min(n, Math.ceil(Math.sqrt(A.length)));
    let distance = maxFlags;
    let rightPeak = peaks[n - 1];

    for (let k = maxFlags - 2; k > 0; k--) {
        let flags = k;
        let leftPeak = peaks[0];

        for (let i = 1; i <= n - 2; i++) {
            if (peaks[i] - leftPeak >= distance && rightPeak - peaks[i] >= distance) {
                if (flags === 1) {
                    return k + 2;    
                }

                flags--;
                leftPeak = peaks[i];
            }

            if (rightPeak - peaks[i] <= flags * (distance + 1)) {
                break;
            }
        }

        if (flags === 0) {
            return k + 2;
        }

        distance--;
    }

    return 2;
}

答案 15 :(得分:0)

具有100%积分的C#解决方案。

using System;
using System.Collections.Generic;



class Solution {
    public int solution(int[] A) {
    // write your code in C# 6.0 with .NET 4.5 (Mono)
    List<int> peaks = new List<int>();
        for (int i = 1; i < A.Length - 1; i++)
        {
            if (A[i - 1] < A[i] && A[i + 1] < A[i])
            {
                peaks.Add(i);
            }
        }
        if (peaks.Count == 1 || peaks.Count == 0)
        {
            return peaks.Count;
        }
        int leastFlags = 1;
        int mostFlags = peaks.Count;
        int result = 1;
        while (leastFlags <= mostFlags)
        {
            int flags = (leastFlags + mostFlags) / 2;
            bool suc = false;
            int used = 0;
            int mark = peaks[0];
            for (int i = 0; i < peaks.Count; i++)
            {
                if (peaks[i] >= mark)
                {
                    used++;
                    mark = peaks[i] + flags;
                    if (used == flags)
                    {
                        suc = true;
                        break;
                    }
                }
            }
            if (suc)
            {
                result = flags;
                leastFlags = flags + 1;
            }
            else
            {
                mostFlags = flags - 1;
            }
        }
        return result;
}

}

答案 16 :(得分:0)

我为这个问题提出了一个算法,它既是O(N)又是通过了所有的密码测试。主要思想是标志的数量不能超过N的平方根。因此,为了使总顺序保持线性,每次迭代应该小于N的平方根,这也就是标志本身的数量。 / p>

首先,我构建了一个数组nextPeak,它为A的每个索引提供索引后最接近的标志。 然后,在第二部分中,我将来自N的根的所有可能数量的标志的f迭代回0,以找到可以在阵列上应用的最大标志数。在每次迭代中,我尝试应用标志并使用nextPeak数组在恒定时间内找到下一个峰值。

代码如下所示:

public int solution(int[] A){
    if( A==null || A.length<3){
        return 0;
    }

    int[] next = new int[A.length];
    int nextPeak=-1;
    for(int i =1; i<A.length; i++){
        if(nextPeak<i){
            for(nextPeak=i; nextPeak<A.length-1; nextPeak++){
                if(A[nextPeak-1]<A[nextPeak] && A[nextPeak]>A[nextPeak+1]){
                    break;
                }
            }
        }

        next[i] = nextPeak;
    }

    next[0] = next[1];

    int max = new Double(Math.sqrt(A.length)).intValue();

    boolean failed = true ;
    int f=max;
    while(f>0 && failed){
        int v=0;
        for(int p=0; p<A.length-1 && next[p]<A.length-1 && v<f; v++, p+=max){
            p = next[p];
        }

        if(v<f){
            f--;
        } else {
            failed = false;
        }

    }

    return f;
}

答案 17 :(得分:0)

import sys

def get_max_num_peaks(arr):
    peaks = [i for i in range(1, len(arr)-1, 1) if arr[i]>arr[i-1] and arr[i]>arr[i+1]]
    max_len = [1 for i in peaks]
    smallest_diff = [0 for i in peaks]
    smallest_diff[0] = sys.maxint
    for i in range(1, len(peaks), 1):
        result = 1
        for j in range(0, i, 1):
            m = min(smallest_diff[j], peaks[i]-peaks[j])
            if smallest_diff[j]>0 and m>=max_len[j]+1:
                max_len[i] = max_len[j]+1
                smallest_diff[i] = m 
                result = max(result, max_len[i])
    return result

if __name__ == "__main__":
    result = get_max_num_peaks([7, 10, 4, 5, 7, 4, 6, 1, 4, 3, 3, 7])
    print result

我用DP来解决这个问题。这是python代码: 可以为结束于i的数组设置最大标志数,如果min(min_diff(0 ... j),j到i)不小于max_len(0 .. j),则可以在j上设置最大标志数。 +1 如果我错了或有O(N)解决方案,请纠正我

答案 18 :(得分:0)

public int solution(int[] A) {
     int p = 0;
     int q = 0;
     int k = 0;

        for (int i = 0; i < A.length; i++) {

        if (i > 0 && i < A.length && (i + 1) < A.length - 1) {
            if (A[i] > A[i - 1] && A[i] > A[i + 1]) {
                p = i;

                if (i < A.length / 2)
                    k++;

            }

            if (i > 0 && i < A.length && (A.length - i + 1) < A.length) {
                if (A[A.length - i] > A[A.length - i - 1]
                        && A[A.length - i] > A[A.length - i + 1] ) {
                    q = A.length - i;

                    if (i < A.length / 2)
                        k++;
                    else {
                        if (Math.abs(p - q) < k && p != q)
                            k--;
                    }

                }
            }

        }

    }
    return k;
}

答案 19 :(得分:-1)

解决这个问题:

  1. 你必须找到高峰
  2. 计算每2个峰值之间的距离(指数差异)
  3. 最初标志的数量与峰值的数量相同
  4. 将每2个峰之间的距离与最初指定的标志数([P - Q] >= K
  5. 进行比较
  6. 比较后你会发现你必须避免一些高峰
  7. 最大标志的最终数量与剩余峰值的数量相同
  8. **我仍在寻找如何为此问题编写最佳优化代码

答案 20 :(得分:-1)

int solution(int A[], int N) {
    int i,j,k;
    int count=0;
    int countval=0;
    int count1=0;
    int flag;
    for(i=1;i<N-1;i++)
    {`enter code here`
        if((A[i-1]<A[i]) && (A[i]>A[i+1]))
        {



            printf("%d %d\n",A[i],i);
             A[count++]=i;
            i++;

        }
    }  

    j=A[0];
    k=0;
    if (count==1 || count==0)
    return count;
    if (count==2)
    {
        if((A[1]-A[0])>=count)
        return 2;
        else 
        return 1;
    }


    flag=0;
    // contval=count;
    count1=1;
    countval=count;
    while(1)
    {
    for(i=1;i<count;i++)
    {
           printf("%d %d\n",A[i],j);
           if((A[i]-j)>=countval)
            {
                printf("Added %d %d\n",A[i],j);
                count1++;
                j=A[i];

            }
           /* if(i==count-1 && count1<count)
            {
                j=A[0];
                i=0;
                count1=1;
            }*/

    }
printf("count %d count1 %d \n",countval,count1);
if (count1<countval)
            {
               count1=1;
               countval--;
               j=A[0];
              }
            else
            {
              break;            }


}
    return countval;
   }