目录
回复讨论(解决方案)
首页 后端开发 php教程 诚征大神求解codility上两个测试题,智力和能力大考验!(我是被打击惨了,看看大神们如何吧)

诚征大神求解codility上两个测试题,智力和能力大考验!(我是被打击惨了,看看大神们如何吧)

Jun 23, 2016 pm 01:48 PM
大神 求解

不说了,有机会在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;}
登录后复制
登录后复制

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何用Python编写求解最小公倍数的算法? 如何用Python编写求解最小公倍数的算法? Sep 19, 2023 am 11:25 AM

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

快速计算矩阵逆的方法 - Numpy实现 快速计算矩阵逆的方法 - Numpy实现 Jan 24, 2024 am 08:47 AM

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

用C语言编程实现最大公约数求解 用C语言编程实现最大公约数求解 Feb 21, 2024 pm 07:30 PM

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

win7和8.1哪个好?大神告诉你 win7和8.1哪个好?大神告诉你 Jul 19, 2023 pm 12:21 PM

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

如何使用Python实现求解阶乘的算法? 如何使用Python实现求解阶乘的算法? Sep 19, 2023 am 10:30 AM

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

从小白到大神:Go语言项目开发心得分享 从小白到大神:Go语言项目开发心得分享 Nov 02, 2023 pm 03:15 PM

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

学习C语言如何求解最大公约数 学习C语言如何求解最大公约数 Feb 21, 2024 pm 11:18 PM

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

求第n个斐波那契数的C/C++程序? 求第n个斐波那契数的C/C++程序? Sep 12, 2023 pm 06:01 PM

斐波那契数列是一个数列,其中下一项是前两项之和。斐波那契数列的前两项是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

See all articles