web-dev-qa-db-fra.com

java codility Frog-River-One

J'ai essayé de résoudre un exercice Java sur une page Web Codility.

Vous trouverez ci-dessous le lien vers l’exercice mentionné et ma solution.

https://codility.com/demo/results/demoH5GMV3-PV8

Quelqu'un peut-il dire ce que je peux corriger dans mon code afin d'améliorer le score?

Juste au cas où voici la description de la tâche:

Une petite grenouille veut aller de l'autre côté d'une rivière. La grenouille se trouve actuellement à la position 0 et souhaite se rendre à la position X. Les feuilles tombent d'un arbre sur la surface de la rivière.

Vous recevez un tableau non vide à index A non constitué de N entiers représentant les feuilles mortes. A [K] représente la position où une feuille tombe à l'instant K, mesurée en minutes.

Le but est de trouver le moment le plus précoce où la grenouille peut sauter de l’autre côté de la rivière. La grenouille ne peut traverser que lorsque les feuilles apparaissent à chaque endroit de la rivière, de 1 à X.

Par exemple, on vous donne le nombre entier X = 5 et le tableau A tel que:

  A[0] = 1
  A[1] = 3
  A[2] = 1
  A[3] = 4
  A[4] = 2
  A[5] = 3
  A[6] = 5
  A[7] = 4

À la minute 6, une feuille tombe en position 5. Il s'agit du moment le plus précoce où les feuilles apparaissent à chaque position de l'autre côté de la rivière.

Ecrire une fonction:

class Solution { public int solution(int X, int[] A); } 

que, étant donné un tableau A non indexé non vide A composé de N entiers et d'un entier X, renvoie le plus ancien moment où la grenouille peut sauter de l'autre côté de la rivière.

Si la grenouille n'est jamais capable de sauter de l'autre côté de la rivière, la fonction devrait retourner -1.

Par exemple, étant donné X = 5 et le tableau A tel que:

  A[0] = 1
  A[1] = 3
  A[2] = 1
  A[3] = 4
  A[4] = 2
  A[5] = 3
  A[6] = 5
  A[7] = 4

la fonction doit renvoyer 6, comme expliqué ci-dessus. Suppose que:

N and X are integers within the range [1..100,000];
each element of array A is an integer within the range [1..X].

Complexité:

expected worst-case time complexity is O(N);
expected worst-case space complexity is O(X), beyond input storage (not counting the storage required for input arguments).

Les éléments des tableaux d'entrée peuvent être modifiés.

Et voici ma solution:

import Java.util.ArrayList;
import Java.util.List;

class Solution {

    public int solution(int X, int[] A) {
        int list[] = A;
        int sum = 0;
        int searchedValue = X;

        List<Integer> arrayList = new ArrayList<Integer>();

        for (int iii = 0; iii < list.length; iii++) {

            if (list[iii] <= searchedValue && !arrayList.contains(list[iii])) {
                sum += list[iii];
                arrayList.add(list[iii]);
            }
            if (list[iii] == searchedValue) {
                if (sum == searchedValue * (searchedValue + 1) / 2) {
                    return iii;
                }
            }
        }
        return -1;
    }
}
11
pshemek

Vous utilisez arrayList.contains dans une boucle, qui parcourt inutilement toute la liste.

Voici ma solution (je l'ai écrite il y a quelque temps, mais je crois qu'elle a obtenu 100/100):

    public int frog(int X, int[] A) {
        int steps = X;
        boolean[] bitmap = new boolean[steps+1];
        for(int i = 0; i < A.length; i++){
            if(!bitmap[A[i]]){
                bitmap[A[i]] = true;
                steps--;
            }
            if(steps == 0) return i;
        }
        return -1;
    }
32
rafalio

Voici ma solution. Il m'a eu 100/100:

public int solution(int X, int[] A)
{
     int[] B = A.Distinct().ToArray();
     return (B.Length != X) ? -1 : Array.IndexOf<int>(A, B[B.Length - 1]);
}
11
Kamlesh Shewani

Une solution Java utilisant Sets (Collections Framework) 100%

import Java.util.Set;
import Java.util.TreeSet;
public class Froggy {
    public static int solution(int X, int[] A){
    int steps=-1;
    Set<Integer> values = new TreeSet<Integer>();
    for(int i=0; i<A.length;i++){
        if(A[i]<=X){
            values.add(A[i]);
        }
        if(values.size()==X){
            steps=i;
            break;
        }
    }
        return steps;
    }
6
CraUmm

100/100

public static int solution (int X, int[] A){

    int[]counter = new int[X+1];
    int ans = -1;
    int x = 0;

    for (int i=0; i<A.length; i++){
        if (counter[A[i]] == 0){
            counter[A[i]] = A[i];
            x += 1;
            if (x == X){
                return i;
            }
        } 
    }

    return ans;
}
5
Andrzej Krzyszycha

Une meilleure approche consisterait à utiliser Set, car cela n’ajoute que des valeurs uniques à la liste. Ajoutez simplement des valeurs à la variable Set et décrivez X chaque fois qu'une nouvelle valeur est ajoutée, (Set#add() renvoie true si une valeur est ajoutée, false sinon);

public static int solution(int X, int[] A) {
    Set<Integer> values = new HashSet<Integer>();
    for (int i = 0; i < A.length; i++) {
        if (values.add(A[i])) X--; 
        if (X == 0) return i;
    }
    return -1;
}

ne pas oublier d'importer,

import Java.util.HashSet;
import Java.util.Set;
4
Sufiyan Ghori

Solution simple 100%

public int solution(final int X, final int[] A) {

Set<Integer> emptyPosition = new HashSet<Integer>();

for (int i = 1; i <= X; i++) {
  emptyPosition.add(i);
}
// Once all the numbers are covered for position, that would be the
// moment when the frog will jump
for (int i = 0; i < A.length; i++) {
  emptyPosition.remove(A[i]);
  if (emptyPosition.size() == 0) {
    return i;
  }
}
return -1;
}
3
Anand

Voici ma solution, marqué 100/100:

import Java.util.HashSet;

class Solution {
    public int solution(int X, int[] A) {
        HashSet<Integer> hset = new HashSet<Integer>();

        for (int i = 0 ; i < A.length; i++) {
            if (A[i] <= X)
               hset.add(A[i]);   
            if (hset.size() == X)
               return i;
        }

        return -1;
    }
}
2
joaoprudencio

Voici ma solution avec 100/100.

public int solution(int X, int[] A) {
    int len = A.length;
    if (X > len) {
        return -1;
    }
    int[] isFilled = new int[X];
    int jumped = 0;
    Arrays.fill(isFilled, 0);
    for (int i = 0; i < len; i++) {
        int x = A[i];
        if (x <= X) {
            if (isFilled[x - 1] == 0) {
                isFilled[x - 1] = 1;
                jumped += 1;
                if (jumped == X) {
                    return i;
                }
            }
        }
    }

    return -1;
}
2
Shwetha Shenoy

Voici ma solution… .. Ce n'est pas parfait, mais c'est assez bon pour marquer 100/100… .. (je pense qu'il n'aurait pas dû passer un test avec un gros A et un petit X)

Quoi qu'il en soit, il remplit un nouveau tableau counter avec chaque feuille qui tombe

counter a la taille de X parce que je me fiche des feuilles qui tombent plus loin que X, donc du bloc try-catch.

APRES X leafs sont tombés (parce que c'est le nombre minimum de leafs), je commence à vérifier si j'ai un chemin complet - je vérifie que chaque entier compte est supérieur à 0 . et essayez à nouveau.

public static int solution(int X, int[] A){
    int[] count = new int[X];
    for (int i = 0; i < A.length; i++){
        try{
            count[A[i]-1]++;
        } catch (ArrayIndexOutOfBoundsException e){ }
        if (i >= X - 1){
            for (int j = 0; j< count.length; j++){
                if (count[j] == 0){
                    break;
                }
                if (j == count.length - 1){
                    return i;
                }
            }
        }
    }
    return -1;
}
2
Ariel Voskov

Juste essayé ce problème aussi et voici ma solution. Fondamentalement, je viens de déclarer un tableau dont la taille est égale à la position X. Ensuite, j'ai déclaré un compteur pour surveiller si les feuilles nécessaires sont tombées aux endroits particuliers. La boucle se termine lorsque ces feuilles sont remplies et sinon, renvoie -1 comme indiqué.

class Solution {
    public int solution(int X, int[] A) {
        int size = A.length;
        int[] check = new int[X];
        int cmp = 0;
        int time = -1;

        for (int x = 0; x < size; x++) {
            int temp = A[x];
            if (temp <= X) {
                if (check[temp-1] > 0) {
                    continue;
                }
                check[temp - 1]++;
                cmp++;
            }

            if ( cmp == X) {
                time = x;
                break;
            }
        }

        return time;
    }
}

Il a obtenu 100/100 lors de l'évaluation mais je ne suis pas trop sûr de ses performances. Je suis toujours un débutant en matière de programmation, donc si quelqu'un peut critiquer le code, je vous en serais reconnaissant. 

1
makki

Voici ce que j'ai en C #. Il peut probablement encore être refactorisé…. Nous jetons les nombres supérieurs à X, qui est l'endroit où nous voulons nous arrêter, puis nous ajoutons des nombres à un tableau s'ils n'ont pas déjà été ajoutés. la liste a atteint le nombre attendu, X, puis renvoie le résultat. 100%

        var tempArray = new int[X+1];
        var totalNumbers = 0;
        for (int i = 0; i < A.Length; i++)
        {
            if (A[i] > X || tempArray.ElementAt(A[i]) != 0)
                continue;
            tempArray[A[i]] = A[i];
            totalNumbers++;

            if (totalNumbers == X)
                return i;
        }

        return -1;
1
Bikey

Peut-être que ce n'est pas parfait, mais c'est simple. Vient de faire un compteur Array pour suivre les "feuilles" nécessaires et vérifié à chaque itération si le chemin était complet. M'a eu 100/100 et O (N).

    public static int frogRiver(int X, int[] A)
    {
        int leaves = A.Length;
        int[] counter = new int[X + 1];
        int stepsAvailForTravel = 0;

        for(int i = 0; i < leaves; i++)
        {
            //we won't get to that leaf anyway so we shouldnt count it,
            if (A[i] > X)
            {
                continue;
            } 
            else
            {
                //first hit!, keep a count of the available leaves to jump
                if (counter[A[i]] == 0)
                    stepsAvailForTravel++;

                counter[A[i]]++;

            }
            //We did it!!
            if (stepsAvailForTravel == X)
            {
                return i;
            }
        }

        return -1;

    }
1
Cesar Alvarado

Ceci est ma solution, il m'a obtenu 100/100 et O (N).

public int solution(int X, int[] A) {
    Map<Integer, Integer> leaves = new HashMap<>();

    for (int i = A.length - 1; i >= 0 ; i--)
    {
        leaves.put(A[i] - 1, i);
    }

    return leaves.size() != X ? -1 : Collections.max(leaves.values());
}
1
Bartzilla

Cette solution que j'ai publiée aujourd'hui donnait 100% de codilité, mais la réponse de @rafalio est respectueuse, mais elle nécessite K fois moins de mémoire.

public class Solution {

    private static final int ARRAY_SIZE_LOWER = 1;
    private static final int ARRAY_SIZE_UPPER = 100000;
    private static final int NUMBER_LOWER = ARRAY_SIZE_LOWER;
    private static final int NUMBER_UPPER = ARRAY_SIZE_UPPER;

    public static class Set {

        final long[] buckets;

        public Set(int size) {
            this.buckets = new long[(size % 64 == 0 ? (size/64) : (size/64) + 1)];
        }

        /**
         * number should be greater than zero
         * @param number
         */
        public void put(int number) {
            buckets[getBucketindex(number)] |= getFlag(number); 
        }

        public boolean contains(int number) {
            long flag = getFlag(number);
            // check if flag is stored
            return (buckets[getBucketindex(number)] & flag) == flag;
        }

        private int getBucketindex(int number) {
            if (number <= 64) {
                return 0;
            } else if (number <= 128) {
                return 1;
            } else if (number <= 192) {
                return 2;
            } else if (number <= 256) {
                return 3;
            } else if (number <= 320) {
                return 4;
            } else if (number <= 384) {
                return 5;
            } else 
                return (number % 64 == 0 ? (number/64) : (number/64) + 1) - 1;
        }

        private long getFlag(int number) {
            if (number <= 64) {
                return 1L << number;
            } else
                return 1L << (number % 64);
        }
    }

    public static final int solution(final int X, final int[] A) {
        if (A.length < ARRAY_SIZE_LOWER || A.length > ARRAY_SIZE_UPPER) {
            throw new RuntimeException("Array size out of bounds");
        }
        Set set = new Set(X);
        int ai;
        int counter = X;
        final int NUMBER_REAL_UPPER = min(NUMBER_UPPER, X);
        for (int i = 0 ; i < A.length; i++) {
            if ((ai = A[i]) < NUMBER_LOWER || ai > NUMBER_REAL_UPPER) {
                throw new RuntimeException("Number out of bounds");
            } else if (ai <= X && !set.contains(ai)) {
                counter--;
                if (counter == 0) {
                    return i;
                }
                set.put(ai);
            }
        }
        return -1;
    }

    private static int min(int x, int y) {
        return (x < y ? x : y);
    }
}
1
Egor

Votre algorithme est parfait, à l'exception du code ci-dessous Votre code renvoie une valeur uniquement si la liste [iii] correspond à searchValue.

L'algorithme doit être corrigé de telle sorte qu'il renvoie la valeur si somme == n * (n + 1)/2. 

import Java.util.ArrayList;
import Java.util.List;
class Solution {
    public int solution(int X, int[] A) {
        int list[] = A;
        int sum = 0;
        int searchedValue = X;
        int sumV = searchedValue * (searchedValue + 1) / 2;   
        List<Integer> arrayList = new ArrayList<Integer>();
        for (int iii = 0; iii < list.length; iii++) {
            if (list[iii] <= searchedValue && !arrayList.contains(list[iii])) {
                sum += list[iii];
                if (sum == sumV) {
                    return iii;
                }
                arrayList.add(list[iii]);
            }
        }
        return -1;
    }
}

Je pense que vous devez également vérifier les performances. Je viens d'assurer la sortie seulement

1
ani

En fait, j'ai réécrit cet exercice sans voir ma dernière réponse et j'ai trouvé une autre solution 100/100 et O (N).

public int solution(int X, int[] A) {
    Set<Integer> leaves = new HashSet<>();

    for(int i=0; i < A.length; i++) {
        leaves.add(A[i]);

        if (leaves.contains(X) && leaves.size() == X)  return i; 
    }

    return -1;
}

J'aime mieux celui-ci parce que c'est encore plus simple.

1
Bartzilla

Ceci est ma solution. Je pense que c'est très simple. Il obtient 100/100 sur la codibilité . Set.contains () me laisse éliminer la position en double de la table. Le résultat de la première boucle nous obtient la somme attendue. Dans la seconde boucle, nous obtenons la somme des valeurs d'entrée.

class Solution {
    public int solution(int X, int[] A) {

        Set<Integer> set = new HashSet<Integer>();
        int sum1 = 0, sum2 = 0;

        for (int i = 0; i <= X; i++){
            sum1 += i;       
        }

        for (int i = 0; i < A.length; i++){
            if (set.contains(A[i])) continue;
            set.add(A[i]);
            sum2 += A[i];
            if (sum1 == sum2) return i;
        }        
        return -1;
    }
}
1
Koin Arab

C'est ma solution

public func FrogRiverOne(_ X : Int, _ A : inout [Int]) -> Int {

    var B = [Int](repeating: 0, count: X+1)

    for i in 0..<A.count {
        if B[A[i]] == 0 {
            B[A[i]] = i+1
        }
    }

    var time = 0

    for i in 1...X {
        if( B[i] == 0 ) {
            return -1
        } else {
            time = max(time, B[i])
        }
    }

    return time-1
}

A = [1,2,1,4,2,3,5,4]
print("FrogRiverOne: ", FrogRiverOne(5, &A))
1
Michał Ziobro

ci-dessous est ma solution. J'ai essentiellement créé un ensemble qui n'autorise que les uniques, puis parcourt le tableau et ajoute chaque élément à définir et conserve un compteur pour obtenir la somme de l'ensemble, puis à l'aide de la formule de somme des nombres consécutifs, j'ai obtenu 100%. Remarque: si vous additionnez l'ensemble à l'aide de Java 8 stream, la solution devient quadratique et vous obtenez 56%.

public static int solution2(int X, int[] A) {

    long sum = X * (X + 1) / 2;
    Set<Integer> set = new HashSet<Integer>();
    int setSum = 0;

    for (int i = 0; i < A.length; i++) {
        if (set.add(A[i]))
            setSum += A[i];

        if (setSum == sum) {
            return i;
        }

    }

    return -1;
}

Code C++ court et agréable. Obtient 100% parfait ... Rouleau de tambour ...  enter image description here

#include <set>
int solution(int X, vector<int> &A) {
    set<int> final;
    for(unsigned int i =0; i< A.size(); i++){
        final.insert(A[i]);
        if(final.size() == X) return i;
    }
    return -1;
}
0
sapy

Ceci est ma solution. Il utilise 3 boucles mais est à temps constant et obtient 100/100 sur la codibilité.

class FrogLeap
{
    internal int solution(int X, int[] A)
    {
        int result = -1;
        long max = -1;
        var B = new int[X + 1];

        //initialize all entries in B array with -1
        for (int i = 0; i <= X; i++)
        {
            B[i] = -1;
        }

        //Go through A and update B with the location where that value appeared
        for (int i = 0; i < A.Length; i++)
        {
           if( B[A[i]] ==-1)//only update if still -1
            B[A[i]] = i;
        }

        //start from 1 because 0 is not valid
        for (int i = 1; i <= X; i++)
        {
            if (B[i] == -1)
                return -1;
            //The maxValue here is the earliest time we can jump over
            if (max < B[i])
                max = B[i];
        }

        result = (int)max;
        return result;
    }
}
0
Gali
import Java.util.Set;
import Java.util.HashSet;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");

class Solution {
    public int solution(int X, int[] A) {
     Set<Integer> positionsCovered = new HashSet<Integer>(); 
//Set covering the leaves fallen to keep track of the distance to destination   

        if(X == 1)
             return 0 ;
       int position = 0;     
       for(int i = 0; i < A.length -1 ;i++ ) {       
           if(A[i] <= X && A[i] > 1 && positionsCovered.size() < (X-1)) { 
      //X-1 as we start from 1
               positionsCovered.add(A[i]);
           }
           if(positionsCovered.size()== (X-1)) {
               position = i ;
            break;
           }
       }         
        return position != 0 ? position : -1;
    }
}
0
faizal khan