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

歪着看世界 2014-10-02 09:34:08
加精
不说了,有机会在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 < N, is called a slice of array A. The sum of a slice (P, Q) is the total of A[P] + A[P + 1] + ... + A[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 < N, and exchanges the values of A[I] and A[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分。大神们,你们能得到多少分?
...全文
8230 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuefei_wen 2015-10-05
  • 打赏
  • 举报
回复
我一看到O(NlogN)第一反应就是排序 我觉得这道题可以用复制数组然后进行排序 比较排序后的数组和排序前的 如果只有两个位置的数不一样,或者全都一样且数组中有重复元素,就返回true,否则返回false
lhw7791086 2014-10-10
  • 打赏
  • 举报
回复
xx87343133 2014-10-08
  • 打赏
  • 举报
回复
试试[6,3,4,2,7],这是可以的,交换6,2,但程序结果是false
引用 15 楼 u011552243 的回复:
毫无疑问,xuzuning 版主是我心目中努力的一个目标,程序算法犀利无比,再一次感受到啊。 啥也别说,肯定100分啊。 对了,我查了一些资料,在引用codility题目时一般都隐去题目,因为涉及到版权问题。所以,xuzuning版主,是不是把题目具体文字隐去?或者其他方式处理? 只是建议啊。 [quote=引用 14 楼 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;
}
[/quote]
nettman 2014-10-05
  • 打赏
  • 举报
回复
xuzuning 2014-10-03
  • 打赏
  • 举报
回复
再看第一题 同样计算的结果并没有错误,只是算法没有符合:时间复杂度为 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;
}
xuzuning 2014-10-03
  • 打赏
  • 举报
回复
先看第二题 原代码计算结果是正确的,而#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)

歪着看世界 2014-10-03
  • 打赏
  • 举报
回复
毫无疑问,xuzuning 版主是我心目中努力的一个目标,程序算法犀利无比,再一次感受到啊。 啥也别说,肯定100分啊。 对了,我查了一些资料,在引用codility题目时一般都隐去题目,因为涉及到版权问题。所以,xuzuning版主,是不是把题目具体文字隐去?或者其他方式处理? 只是建议啊。
引用 14 楼 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;
}
xuzuning 2014-10-03
  • 打赏
  • 举报
回复
修改后如下
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 2014-10-03
  • 打赏
  • 举报
回复
if($i > 0 && $A[$i-1] <= $A[$i]) $check++; //交换成功,记录 else return false; //交换失败,返回。 原先漏掉了 if($A[$i] < $A[$j+1]) { $flag = 1; break; } 的意思是找到第一个大于 $A[$i] 的位置 要不要等号无所谓
歪着看世界 2014-10-03
  • 打赏
  • 举报
回复
仔细测试了一下你的代码。短时间还没有办法理解版主的思路,不过我多测试了几个例子,大部分正确,但依然有问题。 比如这个例子,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呢?
引用 9 楼 xuzuning 的回复:
对于第二题,我只是根据题目的示例而为之,的确没有考虑的 交换的位置不相邻的情况 所以也在纳闷为何是 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)

xuzuning 2014-10-03
  • 打赏
  • 举报
回复
时间复杂度的简单判断 for() { code } ==> O(N) for() { code for() { code } } ==> O(N*log(N)) for() { for() { code } } ==> O(N*N)
xuzuning 2014-10-03
  • 打赏
  • 举报
回复
对于第二题,我只是根据题目的示例而为之,的确没有考虑的 交换的位置不相邻的情况 所以也在纳闷为何是 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)

歪着看世界 2014-10-03
  • 打赏
  • 举报
回复
就没有大神能来解决么? 尤其第二道题,还是蛮有难度的。
歪着看世界 2014-10-03
  • 打赏
  • 举报
回复
版主第一题的解法,我验证过,确实正确,感觉用这个巧妙的函数去掉一次循环。 我查了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;
引用 6 楼 xuzuning 的回复:
再看第一题 同样计算的结果并没有错误,只是算法没有符合:时间复杂度为 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;
}
歪着看世界 2014-10-03
  • 打赏
  • 举报
回复
感谢版主大驾光临啊。 不过对于第二题,我有不同看法: 1.你的思路是:检查相邻两个大小,若右边的小于左边的数值,则调换;且这种调换满足i左边的大小关系,则check++. 事实上,我在做题时考虑过这个思路,不过考虑这个例子:1,6,3,4,3,7.只要把6和第二个3调换一下,则可以满足非降数列,最后应该是true。但是,按照你的算法,这个题目返回false。 关键点是:数字的调换可以是很巧妙的一次调换。 2.第二题中,$arr = $A;应该放在第二个for后面,我又验证了一遍,不会出现未定义对象等错误。结果是正确的。 我的思路是每次把$A赋值给$arr,并且采用穷举法把任意两个不同数字调换一次,判断调换后的结果是不是非降数列。是的话,返回true,否的话,不改变check的false值。只要穷举法中,任意一次可以做到,check的值就变为true. 这个思路是正确的,但就是时间复杂度不满足,扣分了。 版主,你看呢?
引用 5 楼 xuzuning 的回复:
先看第二题 原代码计算结果是正确的,而#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)

天涯过客009 2014-10-02
  • 打赏
  • 举报
回复
第天回贴即可获得10分可用分
sdgdh43 2014-10-02
  • 打赏
  • 举报
回复
不识英语。。 0分
歪着看世界 2014-10-02
  • 打赏
  • 举报
回复
尼玛,仔细一看,第二题我的程序就有个明显错误,$arr = $A;应该放在第二个 for 的后面。 晕死。

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧