javascript Peak and Flag Codility 最新款
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19466115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Peak and Flag Codility latest chellange
提问by Usman Wali
I'm trying to solve the latest codility.com question (just for enhance my skills). I tried allot but not getting more than 30 marks there so now curious what exactly I am missing in my solution.
我正在尝试解决最新的 codility.com 问题(只是为了提高我的技能)。我试过 allot 但没有得到超过 30 分,所以现在很好奇我的解决方案中到底缺少什么。
The question says
问题说
A non-empty zero-indexed array A consisting of N integers is given. A peak is an array element which is larger than its neighbours. More precisely, it is an index P such that
给出了一个由 N 个整数组成的非空零索引数组 A。峰值是一个数组元素,它比它的邻居大。更准确地说,它是一个索引 P 使得
0 < P < N ? 1 and A[P ? 1] < A[P] > A[P + 1]
For example, the following array A:
例如下面的数组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
has exactly four peaks: elements 1, 3, 5 and 10.
正好有四个峰:元素 1、3、5 和 10。
You are going on a trip to a range of mountains whose relative heights are represented by array A. You have to choose how many flags you should take with you. The goal is to set the maximum number of flags on the peaks, according to certain rules.
您要去一系列山脉,这些山脉的相对高度由数组 A 表示。您必须选择应携带多少面旗帜。目标是根据某些规则在峰上设置最大数量的标志。
Flags can only be set on peaks. What's more, if you take K flags, then the distance between any two flags should be greater than or equal to K. The distance between indices P and Q is the absolute value |P ? Q|.
标志只能在峰值上设置。更何况,如果取K个flag,那么任意两个flag之间的距离都应该大于等于K。索引P和Q之间的距离就是绝对值|P?问|。
For example, given the mountain range represented by array A, above, with N = 12, if you take:
例如,给定由数组 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.
You can therefore set a maximum of three flags in this case.
因此,在这种情况下,您最多可以设置三个标志。
Write a function that, given a non-empty zero-indexed array A of N integers, returns the maximum number of flags that can be set on the peaks of the array. For example, given the array above
编写一个函数,给定一个 N 整数的非空零索引数组 A,返回可以在数组的峰值上设置的最大标志数。例如,给定上面的数组
the function should return 3, as explained above.
如上所述,该函数应返回 3。
Assume that:
假使,假设:
N is an integer within the range [1..100,000];
N 是 [1..100,000] 范围内的整数;
each element of array A is an integer within the range [0..1,000,000,000].
数组 A 的每个元素都是 [0..1,000,000,000] 范围内的整数。
Complexity:
复杂:
expected worst-case time complexity is O(N); expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
预期的最坏情况时间复杂度为 O(N);预期的最坏情况空间复杂度为 O(N),超出输入存储(不包括输入参数所需的存储)。
So I tried this code according to my understanding of question
所以我根据我对问题的理解尝试了这段代码
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;
}
The above code works for sample array elements: [1,5,3,4,3,4,1,2,3,4,6,2]
Get peaks at indices: [1, 3, 5, 10]
and set flags at 1, 5, and 10 (total 3)
上面的代码适用于示例数组元素:[1,5,3,4,3,4,1,2,3,4,6,2]
在索引处获取峰值:[1, 3, 5, 10]
并在1, 5, and 10 (total 3)
But codility.com says it fails on array [7, 10, 4, 5, 7, 4, 6, 1, 4, 3, 3, 7]
My code get peaks at indices: [1, 4, 6, 8]
and set flags at 1 and 6 (total 2)
but coditity.com says it should be 3 flags. (no idea why)
Am I miss-understanding the question ?
但是 codility.com 说它在数组上失败了[7, 10, 4, 5, 7, 4, 6, 1, 4, 3, 3, 7]
我的代码在索引处达到峰值:[1, 4, 6, 8]
并将标志设置为 1 和 6(总共 2 个)但 coditity.com 说它应该是 3 个标志。(不知道为什么)我是不是没有理解这个问题?
Please I am only looking for the hint/algo. I know this question is already asked by someone and solved on private chatroom but on that page I tried to get the help with that person but members rather flagging my posts as inappropriate answer so I am asking the question here again.
请我只是在寻找提示/算法。我知道这个问题已经有人问过并在私人聊天室中解决了,但在那个页面上,我试图向那个人寻求帮助,但成员们宁愿将我的帖子标记为不恰当的答案,所以我再次在这里问这个问题。
P.S: You can try coding the challenge yourself here!
PS:您可以在这里尝试自己编写挑战代码!
采纳答案by andy_s
Missing 100% PHP solution :)
缺少 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;
}
回答by francesco Malagrino
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;
}
回答by Jurko Gospodneti?
This is a solution with better upper complexity bounds:
这是一个具有更好的复杂度上限的解决方案:
- time complexity:
O(sqrt(N) * log(N))
- space complexity:
O(1)
(over the original input storage)
- 时间复杂度:
O(sqrt(N) * log(N))
- 空间复杂度:(
O(1)
超过原始输入存储)
Python implementation
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
Description
描述
O(N)
preprocessing (done inplace):
O(N)
预处理(就地完成):
A[i] := next peak or end position after or at position i
(i for a peak itself, len(A) after last peak)
If we can plant k
flags then we can certainly plant k' < k
flags as well.
If we can not plant k
flags then we certainly can not plant k' > k
flags either.
We can always set 0 flags.
Let us assume we can not set X
flags.
Now we can use binary search to find out exactly how many flags can be planted.
如果我们可以插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
With the preprocessing done before, each step testing whether k
flags can be planted can be performed in O(k)
operations:
通过之前的预处理,k
可以在O(k)
操作中进行每一步测试是否可以植入标志:
- flag(0) = next(0)
- flag(1) = next(flag(1) + k) ...
- flag(k-1) = next(flag(k-2) + k)
- 标志(0)=下一个(0)
- 标志(1) = 下一个(标志(1) + k) ...
- 标志(k-1)=下一个(标志(k-2)+k)
total cost - worst case - when X - 1
flags can be planted:
总成本 - 最坏的情况 - 何时X - 1
可以插旗:
== X * (1/2 + 3/4 + ... + (2^k - 1)/(2^k))
== X * (log2(X) - 1 + (<1))
<= X * log(X)
== X * (1/2 + 3/4 + ... + (2^k - 1)/(2^k))
== X * (log2(X) - 1 + (<1))
<= X *日志(X)
Using X == N
would work, and would most likely also be sublinear, but is not good enough to use in a proof that the total upper bound for this algorithm is under O(N)
.
使用X == N
会起作用,并且很可能也是次线性的,但不足以用于证明该算法的总上限低于O(N)
。
Now everything depends on finding a good X
, and it since k
flags take about k^2
positions to fit, it seems like a good upper limit on the number of flags should be found somewhere around sqrt(N)
.
现在一切都取决于找到一个好的X
,并且由于k
标志需要大约k^2
位置来适应,因此似乎应该在 附近的某个地方找到标志数量的一个很好的上限sqrt(N)
。
If X == sqrt(N)
or something close to it works, then we get an upper bound of O(sqrt(N) * log(sqrt(N)))
which is definitely sublinear and since log(sqrt(N)) == 1/2 * log(N)
that upper bound is equivalent to O(sqrt(N) * log(N))
.
如果X == sqrt(N)
或接近它的东西有效,那么我们得到一个O(sqrt(N) * log(sqrt(N)))
绝对是次线性的log(sqrt(N)) == 1/2 * log(N)
上限,因为该上限等于O(sqrt(N) * log(N))
。
Let's look for a more exact upper bound on the number of required flags around sqrt(N)
:
让我们寻找一个更精确的所需标志数量的上限sqrt(N)
:
- we know
k
flags requiresNk := k^2 - k + 3
flags - by solving the equation
k^2 - k + 3 - N = 0
overk
we find that ifk >= 3
, then any number of flags <= the resultingk
can fit in some sequence of length N and a larger one can not; solution to that equation is1/2 * (1 + sqrt(4N - 11))
- for
N >= 9
we know we can fit 3 flags ==> forN >= 9
,k = floor(1/2 * (1 + sqrt(4N - 11))) + 1
is a strict upper bound on the number of flags we can fit inN
- for
N < 9
we know 3 is a strict upper bound but those cases do not concern us for finding the big-O algorithm complexity
- 我们知道
k
标志需要Nk := k^2 - k + 3
标志 - 通过对方程求解
k^2 - k + 3 - N = 0
,k
我们发现如果k >= 3
,那么任意数量的标志 <= 结果k
可以适合某些长度为 N 的序列,而更大的则不能;该方程的解是1/2 * (1 + sqrt(4N - 11))
- 因为
N >= 9
我们知道我们可以容纳 3 个标志 ==> forN >= 9
,k = floor(1/2 * (1 + sqrt(4N - 11))) + 1
是我们可以容纳的标志数量的严格上限N
- 因为
N < 9
我们知道 3 是一个严格的上限,但这些情况与我们寻找大 O 算法复杂度无关
floor(1/2 * (1 + sqrt(4N - 11))) + 1
== floor(1/2 + sqrt(N - 11/4)) + 1
<= floor(sqrt(N - 11/4)) + 2
<= floor(sqrt(N)) + 2
floor(1/2 * (1 + sqrt(4N - 11))) + 1
== floor(1/2 + sqrt(N - 11/4)) + 1
<= floor(sqrt(N - 11/4) ) + 2
<= 楼层(sqrt(N)) + 2
==> floor(sqrt(N)) + 2
is also a good strict upper bound for a number of flags that can fit in N
elements + this one holds even for N < 9
so it can be used as a generic strict upper bound in our implementation as well
==>floor(sqrt(N)) + 2
也是一个不错的严格的上限为一些能够适应的标志N
元素+这其中甚至对N < 9
因此它可以作为一种通用的严格在我们执行上限以及
If we choose X = floor(sqrt(N)) + 2
we get the following total algorithm upper bound:
如果我们选择,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
回答by Alexander Ivanenko
C++ solution, O(N) detected
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;
}
回答by Guillermo
Here is a C++ Solution with 100% score
这是一个得分为 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;
}
回答by Chizbox
I know that the answer had been provided by francesco Malagrino, but i have written my own code. for the arrays {1,5,3,4,3,4,1,2,3,4,6,2} and { 7, 10, 4, 5, 7, 4, 6, 1, 4, 3, 3, 7 } my code is working just fine. and when I took my code on the codility exams i had failed on {9, 9, 4, 3, 5, 4, 5, 2, 8, 9, 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 } 我的代码运行良好。当我在 codility 考试中使用我的代码时,我在 {9, 9, 4, 3, 5, 4, 5, 2, 8, 9, 3, 1} 上失败了
my answer resulted to 3 maximum flags. the way I understand it it supposed to be 3 but instead the correct answer is 2, and also with also in respect to francesco Malagrino's solution.
我的回答导致最多 3 个标志。我理解它的方式应该是 3,但正确答案是 2,而且也与 francesco Malagrino 的解决方案有关。
what seems to be wrong in my code and how come the answer should only be 2 the fact that distances between peaks 4, 6, 9 followed the rule.
我的代码中似乎有什么问题,为什么答案应该只是 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;
}
回答by Farid A
I cam up with an algorithm for this problem that is both of O(N) and passed all of the codility tests. The main idea is that the number of flags can not be more than the square root of N. So to keep the total order linear, each iteration should be less than the square root of N too, which is the number of flags itself.
我想出了一个解决这个问题的算法,它是 O(N) 并通过了所有的编码测试。主要思想是flags的个数不能超过N的平方根。所以为了保持全阶线性,每次迭代也应该小于N的平方根,也就是flags的个数本身。
So first, I built an array nextPeak that for each index of A provides the closest flag after the index. Then, in the second part, I iterate f over all possible number of flags from root of N back to 0 to find the maximum number of flags that can be applied on the array. In each iteration, I try to apply the flags and use the nextPeak array to find the next peak in constant time.
所以首先,我构建了一个数组 nextPeak ,它为 A 的每个索引提供索引后最接近的标志。然后,在第二部分,我将 f 遍历所有可能数量的标志,从 N 的根返回到 0,以找到可以应用于数组的最大标志数量。在每次迭代中,我尝试应用标志并使用 nextPeak 数组在恒定时间内找到下一个峰值。
The code looks like this:
代码如下所示:
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;
}
回答by user2310334
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;
}
回答by yfeng
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
I used DP to solve this problem. Here is the python code: The max num of flags can be set for array ending at i is the max num of flags can be set on j if min(min_diff(0 .. j), j to i) is no less than max_len(0 .. j)+1 Please correct me if I'm wrong or there is a O(N) solution
我用DP来解决这个问题。这是python代码:如果min(min_diff(0 .. j), j to i)不小于max_len,则可以为以i结尾的数组设置最大标志数是可以在j上设置的最大标志数(0 .. j)+1 如果我错了或有 O(N) 解决方案,请纠正我
回答by snowolf
C# Solution with 100% points.
C# 解决方案,100% 分。
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;
}
}
}