我正在解决Codility的以下问题:
一只小青蛙想要到达河的另一边。青蛙目前位于0号位置,想要到达位置X.树叶从树上落到河面上。 您将获得一个非空的零索引数组A,它由表示落叶的N个整数组成。 A [K]表示一片叶子在时间K下降的位置,以分钟为单位测量。 目标是找到青蛙可以跳到河的另一边的最早时间。只有当叶子出现在从1到X的河对岸的每个位置时,青蛙才能穿过。
我使用了以下解决方案,但只获得了81分:
代码在C#中。
using System;
using System.Collections.Generic;
class Solution {
public int solution(int X, int[] A) {
bool[] tiles = new bool[X];
for (int i = 0; i < A.Length; i++)
{
tiles[A[i] - 1] = true;
bool complete = true;
for (int j = 0; j < tiles.Length; j++)
{
if (!tiles[j])
{
complete = false;
break;
}
}
if (complete)
return i;
}
return -1;
}
}
我的算法运行在O(NX)。什么是更好的算法,只需要O(N)?
答案 0 :(得分:9)
将您的代码更改为以下内容:
public int solution(int X, int[] A)
{
bool[] tiles = new bool[X];
int todo = X;
for (int i = 0; i < A.Length; i++)
{
int internalIndex = A[i] - 1;
if (internalIndex < X && !tiles[internalIndex])
{
todo--;
tiles[internalIndex] = true;
}
if (todo == 0)
return i;
}
return -1;
}
这个算法只需要O(A.length)
时间,因为它总是跟踪我们仍然要用叶子填充多少“洞”。
这是怎么做到的?
todo
是构建树叶“桥梁”所需的树叶数量。每当叶子掉落时,我们首先检查在它落下的位置是否已经 一片叶子。如果没有,我们递减todo
,填补空洞并继续。
只要todo
到达0
,就会覆盖整条河流;)
答案 1 :(得分:1)
虽然我同意你得到100分但不满足所有测试用例
对于1,3,1,4,2,3,5,4的样本数据
如果您尝试找到3它应该返回5但是给出的答案会抛出异常
修正后的版本是,因为在第4分钟之后履行了在第2位失败的叶子
public int solution(int X, int[] A)
{
int steps = -1;
bool[] tiles = new bool[X];
int todo = X;
for (int i = 0; i < A.Length; i++)
{
steps += 1;
int internalIndex = A[i] - 1;
if (internalIndex < tiles.Length)
{
if (!tiles[internalIndex])
{
todo--;
tiles[internalIndex] = true;
}
}
if (todo == 0)
return steps;
}
return -1;
}
答案 2 :(得分:1)
这让我100/100
public int solution(int X, int[] A)
{
int z = -1;
long combA = ((long) X)*(((long) X) + 1)/2;
long sumA = 0;
int[] countA = new int[X];
for (int i = 0; i < A.Length; i++)
{
countA[A[i] - 1] += 1;
if (countA[A[i] - 1] > 1)
{
countA[A[i] - 1] = 1;
}
else
{
sumA += A[i];
}
if (sumA == combA)
{
z = i;
break;
}
}
return z;
}
答案 3 :(得分:1)
这是一个简单的C ++解决方案:
int solution(int X, vector<int> &A)
{
vector<bool> removed( X );
for( size_t i = 0; i < A.size(); i++ )
{
if( removed[ A[i] - 1 ] == false )
{
removed[ A[i] - 1 ] = true;
X--;
if(X == 0)
{
return i;
}
}
}
return -1;
}
答案 4 :(得分:1)
100%得分:FrogRiverOne的PHP代码:Ajeet Singh
function solution($X, $A) {
for ($i = 0; $i < count($A); $i++){
if (!isset($position_achieved[$A[$i]])){
$X--; // reduce X by one position is achieved
$position_achieved[$A[$i]] = true;
}
if (!$X){
return $i;
}
}
return -1;
}
答案 5 :(得分:1)
这是我基于HashSet的变体。 结果是here
public int solution(int X, int[] A)
{
HashSet<int> hash = new HashSet<int>();
for(int i=0;i<A.Length;i++)
{
if(A[i]<=X)
{
hash.Add(A[i]);
if(hash.Count == X)
return i;
}
}
return -1;
}
答案 6 :(得分:0)
这是我提出的Python解决方案(Codility上的100/100):
def solution(X, A):
N = len(A)
count = [0] * (X+1)
steps = 0
for k in xrange(N):
if not count[A[k]]:
count[A[k]] = 1
steps += 1
if steps == X:
return k
return -1
答案 7 :(得分:0)
Ruby解决方案(Codility上的100/100):
def solution(x, a)
check_array = (0..a.length).to_a
check_array.each { |i| check_array[i]=0 }
a.each_with_index do |element, i|
if (check_array[element]==0)
check_array[element]=1
x -= 1
end
return i if (x==0)
end
return -1
end
答案 8 :(得分:0)
我发生这项运动有点晚了。除了C90
之外,我看到了很多语言。像许多人一样,我通过创建二级数组找到了解决方案。我使用了典型的calloc
,然后是free
。我的第一个解决方案与发布的其他解决方案类似:
int solution(int X, int A[], int N)
{
int *n = calloc(X, sizeof(*A));
int index;
for (index = 0; index < N; index++) {
if (n[A[index] - 1] == 0) {
n[A[index] - 1] = 1;
if (--X == 0) {
free(n);
return index;
}
}
}
free(n);
return -1;
}
我意识到,由于我们处理的是有符号整数,我可以完全离开而没有第二个数组,codility
网站也说 Elements of input arrays can be modified
。它还说 each element of array A is an integer within the range [1..X]
。由于原始输入数组A
将始终具有正数,因此我可以将其用于我的优势。我可以使用数组int
中int A[]
s的符号位来表示我是否已经看过特定的叶位置(或不是)。新版本的代码使用函数abs
来处理每个数组元素中的绝对值,以便进行索引。我将符号位设置为表示我已经访问了特定的叶位置,并使用abs
检查索引的实际值,而不是,以了解我是否已经访问过该位置。我的最终解决方案看起来像:
int solution(int X, int A[], int N)
{
int index;
int leaftimeidx;
for (index = 0; index < N; index++) {
leaftimeidx = abs(A[index]) - 1;
if (A[leaftimeidx] > 0) {
A[leaftimeidx] *= -1;
if (--X == 0)
return index;
}
}
return -1;
}
我的解决方案的两个变体都通过了所有测试。
答案 9 :(得分:0)
这是我在C99的解决方案,可能不是最优雅的。但我希望这是可读和可理解的。这是我测试的链接。 https://codility.com/demo/results/demoNGRG5B-GMR/
int solution(int X, int A[], int N) {
if (X <= 1) return 0; //if we only need to go 1 step we are already there
if (N == 0) return -1;//if we don't have timing we can't predict
int B[X+1];
for (int i=0; i <= X; i++) {
B[i] = -1; //i set default value to -1 so i can see later if we missed a step.
}
for (int i=0; i < N; i++) {
if (A[i] <= X && (B[A[i]] == -1 || B[A[i]] > i)) B[A[i]] = i; //prepare my second array here with timing data
}
int max_min = 0; //store the highest timing later on.
for (int i=1; i <= X; i++) {
if (B[i] == -1) return -1; //if we have any elements with -1 then we didn't cross the river
if (max_min < B[i]) max_min = B[i]; //keep setting the highest timing seen the steps.
}
return max_min;
}
答案 10 :(得分:0)
100%使用C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
public int solution(int X, int[] A)
{
// write your code in C# 5.0 with .NET 4.5 (Mono)
int N = A.Length;
int step = 0;
List<int> k = new List<int>();
for (int i = 0; i < X; i++)
{
k.Add(0);
}
//Inserts an element into the ArrayList at the specified index.
for (int i = 0; i < N; i++)
{
int diff = A[i] - 1;
k[diff] = A[i];
if (i >= X-1 && (k.Contains(0) == false))
{
return i;
}
}
return -1;
}
答案 11 :(得分:0)
以下是另一种使用Dictionary的方法:
public int solution(int X, int[] A) {
int result = -1;
Dictionary<int, int> jumps = new Dictionary<int, int>();
int res = (X*(X+1))/2;
int sum = 0;
for (int i = 0; i < A.Length; i++)
{
if (!jumps.ContainsKey(A[i]))
{
sum = sum + A[i];
jumps.Add(A[i],i);
if (sum == res)
{
result = i;
break;
}
}
}
return result;
}
&#13;
上面的代码创建了直到X的整数之和,即如果X = 5,那么我们使用高斯公式(X *(X + 1))/ 2计算(1 + 2 + 3 + 4 + 5),这将允许我们稍后知道是否添加或发生了总跳数。此值将与添加到字典中的不同步骤的总和进行比较。 根据描述&#34;只有当叶子出现在从1到X的河对岸的每个位置时,青蛙才能穿过。&#34; 我尝试使用列表而不是dic但是它在某些性能测试中失败了,当我们通过key进行查找时,会出现Dictionay对象的强大功能。
答案 12 :(得分:0)
这以O(N)运行并返回100%:
public int solution(int X, int[] A) {
Hashtable spaces = new Hashtable();
int counter = 0;
foreach(int i in A)
{
//Don't insert duplicate keys OR
//keys greater than requested path length
if (!spaces.ContainsKey(i) && i <= X)
spaces.Add(i, i);
//If Hashtable contents count = requested number of leaves,
//then we're done
if (spaces.Count == X)
return (counter);
counter++;
}
return -1;
}
答案 13 :(得分:0)
这是我的100%解决方案,时间复杂度为O(N)。请记住,您可以在这些作业中使用泛型和Linq。
public int solution(int X, int[] A)
{
SortedSet<int> leaves = new SortedSet<int>();
for (int i = 0; i < A.Length; i++)
{
leaves.Add(A[i]);
if (leaves.Count() == X) return i;
}
return -1;
}