诚征大神求解codility上两个测试题,智力和能力大考验!(我是被打击惨了,看看大神们如何吧)
不说了,有机会在codility上做了两个测试题,用php解。我写了两个程序,当时感觉还行,但出来结果一看,200分就得了50分。诚征大神指出我的程序中的错误,以及大神们的solution.
啥都不说了,先上题目:
1. You are given a non-empty zero-indexed array A consisting of N integers. Each element of array A can be ?1, 0 or 1.
A pair of integers (P, Q), such that 0 ≤ P ≤ Q
You are given integer S. The goal is to find the largest slice whose sum equals S.
For example, consider integer S = 2 and array A such that:
A[0] = 1
A[1] = 0
A[2] = -1
A[3] = 1
A[4] = 1
A[5] = -1
A[6] = -1
There are exactly two slices (0, 4) and (3, 4) whose sum equals 2. The largest such slice is (0, 4) and its length equals 5.
Write a function:
function solution($A, $S);
that, given a non-empty zero-indexed array A consisting of N integers and an integer S, returns the length of the largest slice whose sum equals S.
The function should return ?1 if there is no such slice.
For example, given S = 2 and:
A[0] = 1
A[1] = 0
A[2] = -1
A[3] = 1
A[4] = 1
A[5] = -1
A[6] = -1
the function should return 5, as explained above.
Assume that:
N and S are integers within the range [1..100,000];
each element of array A is an integer within the range [?1..1].
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).
Elements of input arrays can be modified.
2.A non-empty zero-indexed array A consisting of N integers is given.
You can perform a single swap operation in array A. This operation takes two indices I and J, such that 0 ≤ I ≤ J
The goal is to check whether array A can be sorted into non-decreasing order by performing only one swap operation.
For example, consider array A such that:
A[0] = 1
A[1] = 3
A[2] = 5
A[3] = 3
A[4] = 7
After exchanging the values A[2] and A[3] we obtain an array [1, 3, 3, 5, 7], which is sorted in non-decreasing order.
Write a function:
function solution($A);
that, given a non-empty zero-indexed array A consisting of N integers, returns true if the array can be sorted into non-decreasing order by one swap operation or false otherwise.
For example, given:
A[0] = 1
A[1] = 3
A[2] = 5
A[3] = 3
A[4] = 7
the function should return true, as explained above.
On the other hand, for the following array:
A[0] = 1
A[1] = 3
A[2] = 5
A[3] = 3
A[4] = 4
the function should return false, as there is no single swap operation that sorts the array.
Assume that:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [1..1,000,000,000].
Complexity:
expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
我的程序:
针对第一题:
function solution($A, $S) { // write your code in PHP5.3 $len = count($A); $slice = -1; for ($begin=0; $begin<$len;$begin++) { $total = 0; for ($end = $begin; $end < $len; $end ++) { $total = $total + $A[$end]; if ($total == $S) { $temp = $end - $begin +1; if ($temp > $slice) { $slice = $temp; } } } } return $slice;}
针对第二题:
function solution($A) { // write your code in PHP5.3 $arr = array(); $len = count($A); $check = false; for ($i=0;$i<$len-1;$i++) { $arr = $A; for ($j=$i+1;$j<$len;$j++) { $temp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $temp; $no_decrease = true; for ($k=1;$k< $len;$k++) { if ($arr[$k]<$arr[$k-1]) { $no_decrease = false; } } if ($no_decrease == true) { $check = true; } } } return $check; }
我是被打击惨了,最后200分中只得了50分。大神们,你们能得到多少分?
回复讨论(解决方案)
尼玛,仔细一看,第二题我的程序就有个明显错误,$arr = $A;应该放在第二个 for 的后面。
晕死。
不识英语。。 0分
第天回贴即可获得10分可用分
就没有大神能来解决么? 尤其第二道题,还是蛮有难度的。
先看第二题
原代码计算结果是正确的,而#1的补充是错误的!
如果将 $arr = $A; 放在第二个 for 的后面那么将出现一系列的使用未定义变量的警告
解答被扣分的原因在于你的答案不符合:时间复杂度为 O(N*log(N)) 的要求
可以写作这样
var_dump(solution([1,3,5,3,7]));var_dump(solution([1,3,5,3,4]));function solution($A) { $arr = array(); $len = count($A); $check = 0; for($i=0;$i<$len-1;$i++) { if($A[$i+1] < $A[$i]) { $temp = $A[$i+1]; $A[$i+1] = $A[$i]; $A[$i] = $temp; if($i > 0 && $A[$i-1] <= $A[$i]) $check++; } } return $check == 1;}
bool(true)bool(false)
再看第一题
同样计算的结果并没有错误,只是算法没有符合:时间复杂度为 O(N) 的要求
你使用了双重循环,所以时间复杂度为 O(N*N)
可以用闭包来去掉一重循环
var_dump(solution([1,0,-1,1,1,-1,-1], 2));function solution($A, $S) { $len = count($A); $slice = -1; for ($begin=0; $begin<$len; $begin++) { $total = 0; array_walk($A, function($v, $end, $S) use ($begin, &$slice, &$total) { if($end < $begin) return; $total += $v; if($total == $S) { $temp = $end - $begin + 1; if ($temp > $slice) $slice = $temp; } }, $S); } return $slice;}
感谢版主大驾光临啊。
不过对于第二题,我有不同看法:
1.你的思路是:检查相邻两个大小,若右边的小于左边的数值,则调换;且这种调换满足i左边的大小关系,则check++.
事实上,我在做题时考虑过这个思路,不过考虑这个例子:1,6,3,4,3,7.只要把6和第二个3调换一下,则可以满足非降数列,最后应该是true。但是,按照你的算法,这个题目返回false。
关键点是:数字的调换可以是很巧妙的一次调换。
2.第二题中,$arr = $A;应该放在第二个for后面,我又验证了一遍,不会出现未定义对象等错误。结果是正确的。
我的思路是每次把$A赋值给$arr,并且采用穷举法把任意两个不同数字调换一次,判断调换后的结果是不是非降数列。是的话,返回true,否的话,不改变check的false值。只要穷举法中,任意一次可以做到,check的值就变为true.
这个思路是正确的,但就是时间复杂度不满足,扣分了。
版主,你看呢?
先看第二题
原代码计算结果是正确的,而#1的补充是错误的!
如果将 $arr = $A; 放在第二个 for 的后面那么将出现一系列的使用未定义变量的警告
解答被扣分的原因在于你的答案不符合:时间复杂度为 O(N*log(N)) 的要求
可以写作这样
var_dump(solution([1,3,5,3,7]));var_dump(solution([1,3,5,3,4]));function solution($A) { $arr = array(); $len = count($A); $check = 0; for($i=0;$i<$len-1;$i++) { if($A[$i+1] < $A[$i]) { $temp = $A[$i+1]; $A[$i+1] = $A[$i]; $A[$i] = $temp; if($i > 0 && $A[$i-1] <= $A[$i]) $check++; } } return $check == 1;}
bool(true)bool(false)
版主第一题的解法,我验证过,确实正确,感觉用这个巧妙的函数去掉一次循环。
我查了array_walk的介绍,还不能理解版主精妙的思路。版主能否提点两句?
还有,第二个题目,调整后的代码如下,供版主以及其他大神测试用
$arr = array();$len = count($A);$check = false; for ($i=0;$i<$len-1;$i++){ for ($j=$i+1;$j<$len;$j++) { $arr = $A; $temp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $temp; $no_decrease = true; for ($k=1;$k< $len;$k++) { if ($arr[$k]<$arr[$k-1]) { $no_decrease = false; } } if ($no_decrease == true) { $check = true; } }}return $check;
再看第一题
同样计算的结果并没有错误,只是算法没有符合:时间复杂度为 O(N) 的要求
你使用了双重循环,所以时间复杂度为 O(N*N)
可以用闭包来去掉一重循环
var_dump(solution([1,0,-1,1,1,-1,-1], 2));function solution($A, $S) { $len = count($A); $slice = -1; for ($begin=0; $begin<$len; $begin++) { $total = 0; array_walk($A, function($v, $end, $S) use ($begin, &$slice, &$total) { if($end < $begin) return; $total += $v; if($total == $S) { $temp = $end - $begin + 1; if ($temp > $slice) $slice = $temp; } }, $S); } return $slice;}
对于第二题,我只是根据题目的示例而为之,的确没有考虑的 交换的位置不相邻的情况
所以也在纳闷为何是 O(N*log(N)) 呢?O(N)) 不就可以了吗
改写一下
var_dump(solution([1,3,5,3,7]));var_dump(solution([1,3,5,3,4]));var_dump(solution([1,6,3,4,3,7])); function solution($A) { $arr = array(); $len = count($A); $check = 0; for($i=0;$i<$len-1;$i++) { if($A[$i+1] < $A[$i]) { $flag = 0; for($j=$i+1; $j<$len-1; $j++) { if($A[$i] < $A[$j+1]) { $flag = 1; break; } } $temp = $A[$j]; $A[$j] = $A[$i]; $A[$i] = $temp; if($i > 0 && $A[$i-1] <= $A[$i]) $check++; if(! $flag) $i--; } } return $check == 1;}
bool(true)bool(false)bool(true)
时间复杂度的简单判断
for() {
code
}
==> O(N)
for() {
code
for() {
code
}
}
==> O(N*log(N))
for() {
for() {
code
}
}
==> O(N*N)
仔细测试了一下你的代码。短时间还没有办法理解版主的思路,不过我多测试了几个例子,大部分正确,但依然有问题。
比如这个例子,var_dump(solution([1,6,5,3,3,4,7]));
目测应该无法一次调换成功,但程序返回是正确的。
因为暂时还没有理解版主大神的思路,所以还不好评论,但我一直担心non-decreasing 非降,其中包括等号=的情况,比如下面
if($A[$i] < $A[$j+1]) {
$flag = 1;
break;
}
其中,$A[$i] < $A[$j+1]是否需要等号呢?
我提供的测试例子是不是应该返回false呢?
对于第二题,我只是根据题目的示例而为之,的确没有考虑的 交换的位置不相邻的情况
所以也在纳闷为何是 O(N*log(N)) 呢?O(N)) 不就可以了吗
改写一下
var_dump(solution([1,3,5,3,7]));var_dump(solution([1,3,5,3,4]));var_dump(solution([1,6,3,4,3,7])); function solution($A) { $arr = array(); $len = count($A); $check = 0; for($i=0;$i<$len-1;$i++) { if($A[$i+1] < $A[$i]) { $flag = 0; for($j=$i+1; $j<$len-1; $j++) { if($A[$i] < $A[$j+1]) { $flag = 1; break; } } $temp = $A[$j]; $A[$j] = $A[$i]; $A[$i] = $temp; if($i > 0 && $A[$i-1] <= $A[$i]) $check++; if(! $flag) $i--; } } return $check == 1;}
bool(true)bool(false)bool(true)
if($i > 0 && $A[$i-1] <= $A[$i]) $check++; //交换成功,记录
else return false; //交换失败,返回。 原先漏掉了
if($A[$i] < $A[$j+1]) {
$flag = 1;
break;
}
的意思是找到第一个大于 $A[$i] 的位置
要不要等号无所谓
修改后如下
var_dump(solution([1,3,5,3,7]));var_dump(solution([1,3,5,3,4]));var_dump(solution([1,6,3,4,3,7]));var_dump(solution([1,6,5,3,3,4,7])); function solution($A) { $arr = array(); $len = count($A); $check = 0; for($i=0;$i<$len-1;$i++) { if($A[$i+1] < $A[$i]) { //如果降序 $flag = 0; for($j=$i+1; $j<$len-1; $j++) { //向后找到符合升序的位置 if($A[$i] < $A[$j+1]) { $flag = 1; break; } } $temp = $A[$j]; //交换 $A[$j] = $A[$i]; $A[$i] = $temp; if($i > 0 && $A[$i-1] <= $A[$i]) $check++; //交换成功 else return false; //交换失败 if(! $flag) $i--; // $flag = 0 表示前面的查找是自然结束的,有待商榷 } } return $check == 1;}
毫无疑问,xuzuning 版主是我心目中努力的一个目标,程序算法犀利无比,再一次感受到啊。
啥也别说,肯定100分啊。
对了,我查了一些资料,在引用codility题目时一般都隐去题目,因为涉及到版权问题。所以,xuzuning版主,是不是把题目具体文字隐去?或者其他方式处理? 只是建议啊。
修改后如下
var_dump(solution([1,3,5,3,7]));var_dump(solution([1,3,5,3,4]));var_dump(solution([1,6,3,4,3,7]));var_dump(solution([1,6,5,3,3,4,7])); function solution($A) { $arr = array(); $len = count($A); $check = 0; for($i=0;$i<$len-1;$i++) { if($A[$i+1] < $A[$i]) { //如果降序 $flag = 0; for($j=$i+1; $j<$len-1; $j++) { //向后找到符合升序的位置 if($A[$i] < $A[$j+1]) { $flag = 1; break; } } $temp = $A[$j]; //交换 $A[$j] = $A[$i]; $A[$i] = $temp; if($i > 0 && $A[$i-1] <= $A[$i]) $check++; //交换成功 else return false; //交换失败 if(! $flag) $i--; // $flag = 0 表示前面的查找是自然结束的,有待商榷 } } return $check == 1;}

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

如何用Python编写求解最小公倍数的算法?最小公倍数是指两个数中能够整除这两个数的最小整数。在数学中,求解最小公倍数是一项基本的数学任务,而在计算机编程中,我们可以使用Python来编写一个求解最小公倍数的算法。下面将介绍基本的最小公倍数算法,并给出具体的代码示例。最小公倍数的数学定义是:如果a能被n整除且b能被n整除,则n是a和b的最小公倍数。要求解最小

Numpy是Python中著名的科学计算库,为处理大型多维数组和矩阵提供了丰富的功能和高效的计算方法。在数据科学和机器学习领域,矩阵的逆运算是一项常见的任务。在本文中,我将介绍使用Numpy库快速求解矩阵逆的方法,并提供具体的代码示例。首先,让我们通过安装Numpy库引入它到我们的Python环境中。可以使用以下命令在终端中安装Numpy:pipinsta

标题:用C语言编程实现最大公约数求解最大公约数(GreatestCommonDivisor,简称GCD)是指能够同时整除两个或多个整数的最大正整数。求解最大公约数对于一些算法和问题解决非常有帮助。在本文中,将通过C语言编程来实现求解最大公约数的功能,并提供具体的代码示例。在C语言中,可以使用欧几里得算法(EuclideanAlgorithm)来求解最大

说起windows系统,相信很多人都不陌生,我们现在很多在用的也是windows系统,而windows包含多个系统版本,其中就有win7和win8.1。有网友不知道该选择win7还是8.1系统,win7和8.1哪个好?大神告诉你win7和win8.1的区别和选择。 Windows8.1,有着华丽的界面。不过改进更大,缺点也更多。比较显着的有游戏字体模糊,还有内存不足的bug。无论内存有多大,在运行一些游戏的时候会提示内存不足,并且需要关闭。实际在检查中,内存正常。一说是内存管理机制存在问题,另一种

如何使用Python实现求解阶乘的算法?阶乘是数学中的重要概念,指的是一个数乘上其自身减一,再乘上自身减一减一,以此类推,直到乘到1为止。阶乘通常用符号"!"来表示,例如5的阶乘表示为5!,计算公式为:5!=5×4×3×2×1=120。在Python中,我们可以使用循环来实现一个简单的阶乘算法。下面给出一个示例代码:deffacto

从小白到大神:Go语言项目开发心得分享近年来,Go语言因其简洁高效的特性越来越受到开发者的喜爱。作为一门开源的编程语言,Go具有并发能力强、静态类型检查、内存管理自动化等优点,受到了众多大型互联网公司的青睐。作为一名从零开始学习Go的小白开发者,我在项目开发的过程中,不断摸索和学习,逐渐成长为一个能够独立开发Go项目的大神,积累了一些经验和心得,今天我将与大

学习C语言如何求解最大公约数,需要具体代码示例最大公约数(GreatestCommonDivisor,简称GCD)是指两个或多个整数中能够整除它们的最大正整数。在计算机编程中经常会用到最大公约数,特别是在处理分数、化简分数以及求解最简整数比例等问题时。本篇文章将介绍如何使用C语言来求解最大公约数,并给出具体的代码示例。求解最大公约数的方法有很多种,例如欧

斐波那契数列是一个数列,其中下一项是前两项之和。斐波那契数列的前两项是0后跟1。在这个问题中,我们会发现斐波那契数列中的第n个数字。为此,我们将计算所有数字并打印n项。Input:8Output:011235813说明0+1=11+1=21+2=32+3=5使用For循环将前两项求和作为下一项示例#include<iostream>usingnamespacestd;intmain(){ intt1=0,t2=1,n,i,nextTerm;&am
