codility абсолютное отличное количество от массива - PullRequest
11 голосов
/ 20 апреля 2011

поэтому я вчера прошел тест на собеседование и был проинформирован сегодня о том, что потерпел неудачу, к сожалению, ни администрация, ни работодатель не дали никакой другой информации о том, где я облажался, так что я был бы признателен за помощь в том, чтобы узнать, где я ошибся,я знаю, что codility уделяет большое внимание тому, как быстро работает программа и как она ведет себя в больших количествах.теперь я не копировал и вставлял вопросы, так что это приблизительно то, что я помню

  1. подсчитывает количество элементов в массиве, которые абсолютно различны, что это означает, если массив имел -3 и 3в нем эти числа не различны, потому что | -3 | = | 3 |.я думаю, что пример прояснит это лучше

a = {- 5, -3,0,1, -3} результат будет 4, потому что в этом массиве есть 4 абсолютно разных элемента.

В вопросе также указывалось, что a.length будет <= 10000, и, что наиболее важно, указывалось, что предполагается, что массив <strong>отсортирован в порядке возрастания , но я действительно не понимал, зачем нам нужноэто будет отсортировано

ЕСЛИ ВЫ ДУМАЕТЕ, ЧТО-ТО ЧТО-ТО ЗАПРОСИЛ, И Я ПОПРОБУЮ УДАЛИТЬ ВОПРОС ДАЛЬШЕ.

здесьмой код

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;


public class test2 {

    int test(int[] a){
        Set<Integer> s=new HashSet<Integer>();

        for(int i=0;i<a.length;i++){
            s.add(Math.abs(a[i]));

        }
        return s.size();

    }

    public static void main(String[] args) {
        test2 t=new test2();
        int[] a={1,1,1,2,-1};
        System.out.println(t.test(a));

    }

}

Ответы [ 31 ]

0 голосов
/ 21 апреля 2011

Решение состоит в том, чтобы использовать тот факт, что массив отсортирован. То, что вы можете сделать, это иметь два указателя, указывающих на начало и конец массива соответственно. Затем, основываясь на значении abs, уменьшите / увеличьте указатель конца / указатель начала. В то же время вы должны будете отслеживать повторяющиеся элементы в последовательности, например {3,3,3,4} (3 следует считать один раз).

В целом это не было бы слишком сложно, я думаю, с 20-25 loc в C.

0 голосов
/ 14 мая 2014

Вот код C ++ для обеих реализаций с кодом, который генерирует случайный отсортированный целочисленный вектор:

#include <vector>
#include <set>
#include <iostream>
#include <random>
#include <cstdlib>
using namespace std;
int main(int argc, char** argv) {

    // generate a vector with random negative and positive integers, then sort it
    // vector<int> vQ2{ -5, -4, -4, -2, 0, 3, 4, 5, 5, 7, 12, 14};
    vector<int> vQ2;
    std::default_random_engine e;
    std::uniform_int_distribution<> d(-10, 10);
    std::function<int()> rnd = std::bind(d, e);
    for(int n=0; n<10; ++n)
        vQ2.push_back(rnd());
    sort(vQ2.begin(),vQ2.end());

    // set (hashfunction) solution (hash)
    set<int> sQ2;
    for_each(vQ2.cbegin(),vQ2.cend(),[&sQ2](const int input) -> void { sQ2.insert( std::abs(input) ); } );
    cout << sQ2.size() << endl;

    // pointers-meeting-in-the-middle solution        
    int absUniqueCount = 0;
    vector<int>::iterator it1 = vQ2.begin();
    vector<int>::iterator it2 = prev(vQ2.end());
    int valueIt1Prev = *it1;
    int valueIt2Prev = *it2;
    while(valueIt1Prev <= valueIt2Prev)
    {
        ++absUniqueCount;
        while(valueIt1Prev == *it1 && abs(valueIt1Prev) >= abs(valueIt2Prev))
        {   advance(it1,1); } // using advance in case of non contiguous memory container (e.g. list)
        while(valueIt2Prev == *it2 && abs(valueIt2Prev) >= abs(valueIt1Prev))
        {   advance(it2,-1); } 
        valueIt1Prev = *it1;
        valueIt2Prev = *it2;
    }
    copy(vQ2.cbegin(),vQ2.cend(),ostream_iterator<int>(cout,",")); cout << endl;
    cout << absUniqueCount << endl;

    return 0;
}

, который дает:

6
-9,-8,-8,-8,-5,0,4,4,6,6,
6
0 голосов
/ 26 сентября 2013

Вот мой тест ruby ​​версии 100/100 на codility, основанный на тестовых случаях codility, массив с одинаковыми абсолютными значениями [3, -3] или [3,3] должен вернуть 1, вот список примеров1001 * ссылка

def absolute(a)
    b = Hash.new(0)
    a.each do |x|
        x = x.abs
        b[x] += 1
    end 
    return b.size
end 
0 голосов
/ 25 июня 2012
class Program
{
    static int CountArray(int[] MyIntArray)
    {
        int countNum = 0;
        int[] TempIntArray = new int[MyIntArray.Length];
        for (int i = 0; i < MyIntArray.Length; i++)
        {
            TempIntArray[i] = Math.Abs(MyIntArray[i]);
        }
        var queryResults = from n in TempIntArray 
                           select n;
        countNum = queryResults.Distinct().ToArray().Length;
        return countNum;
    }

    static void Main(string[] args)
    {
        Console.WriteLine("demoX6FVFB-KX8");
        Random randomNumber = new Random();
        int[] TheArray = new int[100];
        for (int j = 0; j < TheArray.Length; j++)
        {
            TheArray[j] = randomNumber.Next(-50, 50);
        }
        int counta = Program.CountArray(TheArray);
        Console.WriteLine(counta);
    }
}
0 голосов
/ 10 мая 2012

Это моя версия.Что ты думаешь?

int count(vector<int> testVector){

  for(unsigned int i = 0; i < testVector.size(); i++){
    // empty array, return 0
    if(testVector.empty()) return 0;

    // one number left, must be unique, return 1;
    if(testVector.size() == 1) return 1;

    // neighbour elements are the same, delete first element
    if(testVector[0] == testVector[1]) {
        testVector.erase(testVector.begin());
        return count(testVector);
    }

    // absolute value of first and last element identical, delete first element
    if(abs(testVector[0]) == abs(testVector[testVector.size() - 1])){
        testVector.erase(testVector.begin());
        return count(testVector);
    }

    // if absolute value of beginning is greater than absolute value of end, delete beginning, otherwise end
    if(abs(testVector[0]) > abs(testVector[testVector.size() - 1])){
        testVector.erase(testVector.begin());
    } else {
        testVector.erase(testVector.end() - 1);
    }       
    // increase counter and recurse
    return 1 + count(testVector);
  }
}
0 голосов
/ 04 ноября 2011

Вот рекурсивный алгоритм, который будет возвращать абсолютные уникальные записи в списке за один проход, то есть за O (n) время.Он основан на том факте, что массив отсортирован и не использует java.util.Set.

Рассмотрим этот пример массива {-5, -5, -3,0,1,3}

  • Поскольку массив отсортирован, один из двух элементов на каждом конце массива будет иметь абсолютное наибольшее значение: -5
  • Опять же, поскольку массив отсортирован, если этот элементесли будет совпадение, он будет его соседом или соседями для нескольких совпадений.
  • Так что для -5 мы делаем одну проверку с его соседом: они равны.-5 является дубликатом, поэтому удалите его, не увеличивайте наш текущий итог и повторяйте.

{- 5, -3,0,1,3} Теперь мы выбираем -5, его уникальныйпоэтому увеличьте промежуточный итог до 1, а затем удалите его.

{- 3,0,1,3} Если два конца имеют одинаковые абсолютные значения, просто удалите один, это не имеет значения, который, так же как еготолько один.Скажи первый.Мы не увеличиваем нашу промежуточную сумму, потому что значение, которое мы удалили, было дубликатом.

{0,1,3} Теперь мы выбираем 3, его уникальная промежуточная сумма равна 2.

{0,1} Выберите 1, его уникальный промежуточный итог 3.

{0} Размер равен 1, значение уникально, увеличьте промежуточный итог и верните его.4 Правильно!

package com.codility.tests;

import java.util.ArrayList; 
import java.util.Arrays;
import java.util.List;

public class AbsDistinct {

/**
 * Count the number of absolute distinct elements in an array.
 * The array is sorted in ascending order.
 */
private static int countAbsDistinct(List<Integer> list, int count) {
    int lastIndex = list.size() - 1;
    if (lastIndex == -1) { // zero size list, terminate
        return 0;
    }
    if (lastIndex == 0) { // one element list, terminate
        return ++count;
    }
    if (Math.abs(list.get(0)) == Math.abs(list.get(lastIndex))) {
        // doesn't matter which end is removed, but to remove _only_ 1
        list.remove(0);
    } else if (Math.abs(list.get(0)) > Math.abs(list.get(lastIndex))) {
        // if different to its nighbour, its unique hence count it
        if (list.get(0) != list.get(1)) {
            count++;
        }
        // now that its been accounted for, remove it
        list.remove(0);
    } else {
        // same logic but for the other end of the list
        if (list.get(lastIndex) != list.get(lastIndex - 1)) {
            count++;
        }
        list.remove(lastIndex);
    }
    return countAbsDistinct(list, count);
}

public static void main(String[] args) {
    if (args.length == 0) { // just run the tests
        List<Integer> testList = new ArrayList<Integer>(Arrays.asList(-9, -6, -5, -5, -5, -5, -3, -3, 0, 0, 1, 5, 6, 7, 7, 8));
        List<Integer> empty = new ArrayList<Integer>();
        List<Integer> singleElement = new ArrayList<Integer>(Arrays.asList(1));
        List<Integer> sameElement = new ArrayList<Integer>(Arrays.asList(1, 1, 1, 1, 1, 1));
        System.out.println("test array: " + countAbsDistinct(testList, 0));
        System.out.println("empty array: " + countAbsDistinct(empty, 0));
        System.out.println("single element array: " + countAbsDistinct(singleElement, 0));
        System.out.println("same element array: " + countAbsDistinct(sameElement, 0));
    } else {
        List<String> argStringList = new ArrayList<String>(Arrays.asList(args));
        List<Integer> argList = new ArrayList<Integer>();
        for (String s : argStringList) {
            argList.add(Integer.parseInt(s));
        }
        System.out.println("argument array: " + countAbsDistinct(argList, 0));
    }
}
}
0 голосов
/ 26 октября 2011

Ниже приведена реализация, которая даже намного быстрее, чем у Питера.

if (A == null || A.length == 0) {
  return 0;
} else if (A.length == 1 || A[0] == A[A.length - 1]) {
  return 1;
}

int absDistinct = 0;
int leftCurrent;
int leftNext;
int rightCurrent;
int rightPrevious;

for (int i = 0, j = A.length; i < j; ) {

  leftCurrent = A[i];
  rightCurrent = A[j];
  leftNext = A[i + 1];
  rightPrevious = A[j - 1];

  if (leftCurrent + rightCurrent == 0) {
    while (A[i] - A[i + 1] == 0) {
      i++;
    }
    while (A[j] - A[j - 1] == 0) {
      j--;
    }
    i++;
    j--;
    absDistinct++;
  } else {
    if (leftCurrent + rightCurrent < 0) {
      if (leftCurrent - leftNext != 0) {
        absDistinct++;
      }
      i++;
    } else {
      if (rightCurrent - rightPrevious != 0) {
        absDistinct++;
      }
      j--;
    }
  }
}

return absDistinct;

Важно распределение чисел.Но если будет много серий с одинаковыми номерами, этот алгоритм будет работать лучше.Это показывает, что сложность алгоритмов - не единственный барьер для преодоления.Когда у вас есть алгоритм со сложностью propper, это может быть только один из вариантов.Линейная коррекция алгоритма все еще возможна.Характер ввода иногда также важен.

0 голосов
/ 28 июня 2013
int[] arr= new int[]{-5,-5,-6,-6,-6};
Set<Integer> newSet = new HashSet<Integer>();
for(int i=0;i<arr.length;i++)
  newSet.add(Math.abs(arr[i]));    

System.out.println(newSet.size());
0 голосов
/ 06 августа 2015

100/100 Java O (N)

public class Distinct {

    public static int solution(int[] A) {

        Set<Integer> set = new HashSet<>();
        for (int i : A) {
            set.add(i);
        }
        return set.size();
    }
}
0 голосов
/ 25 июля 2013

Довольно быстрое решение на основе бинарного поиска

import java.util.Arrays;

public class AbsoluteDistinct {

    private int absoluteDistinct(int[] a) {
        if (a.length == 0 || a.length == 1) return a.length;

        Arrays.sort(a);

        int dist = 1;
        int N = a.length;
        for (int i = 0; i < N; i++) {
            if (i + 1 == N) break;
            int temp = Math.abs(a[i]);
            if (temp == Math.abs(a[i+1])) continue;
            if (Arrays.binarySearch(a, (i + 1), N, temp) < 0) dist++;
        }

        return dist;
    }


    public static void main(String[] args) {
        //generate array of 1 Million random values
        int LIMIT = 1000000;
        int[] a = new int[LIMIT];
        for (int i = 0; i < LIMIT; i++) {
            int r = (int) (Math.random() * (LIMIT + LIMIT + 1)) - LIMIT;
            a[i] = r;
        }
        //print absolute distinct numbers 
        System.out.println(new AbsoluteDistinct().absoluteDistinct(a));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...