目錄
回复讨论(解决方案)
首頁 後端開發 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脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++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的最小公倍數。要求解最小

用C語言程式實現最大公約數求解 用C語言程式實現最大公約數求解 Feb 21, 2024 pm 07:30 PM

標題:以C語言程式實現最大公約數求解最大公約數(GreatestCommonDivisor,簡稱GCD)是指能夠同時整除兩個或多個整數的最大正整數。求解最大公約數對於一些演算法和問題解決非常有幫助。在本文中,將透過C語言程式設計來實現求解最大公約數的功能,並提供具體的程式碼範例。在C語言中,可以使用歐幾裡得演算法(EuclideanAlgorithm)來求解最大

快速計算矩陣逆的方法 - Numpy實現 快速計算矩陣逆的方法 - Numpy實現 Jan 24, 2024 am 08:47 AM

Numpy是Python中著名的科學計算庫,為處理大型多維數組和矩陣提供了豐富的功能和高效的計算方法。在資料科學和機器學習領域,矩陣的逆運算是一項常見的任務。在本文中,我將介紹使用Numpy函式庫快速求解矩陣逆的方法,並提供具體的程式碼範例。首先,讓我們透過安裝Numpy庫引入它到我們的Python環境中。可以使用以下命令在終端機中安裝Numpy:pipinsta

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語言來求解最大公約數,並給出具體的程式碼範例。求解最大公約數的方法有很多種,例如歐

在C/C++中寫出求解模方程式的程式? 在C/C++中寫出求解模方程式的程式? Sep 12, 2023 pm 02:21 PM

在這裡,我們將看到一個與模方程式相關的有趣問題。假設我們有兩個值A和B。我們必須找到變數X可以取的可能值的數量,使得(AmodX)=B成立。假設A為26,B為2。所以X的首選值會是{3,4,6,8,12,24},因此計數為6。這就是答案。讓我們看一下演算法以更好地理解。演算法possibleWayCount(a,b)−begin  ifa=b,thenthereareinfinitesolutions  ifa

See all articles