Как я мог улучшить скорость / производительность для этой проблемы Java - PullRequest
0 голосов
/ 02 февраля 2019

Я видел этот вызов на https://www.topcoder.com/ для начинающих.И я действительно хотел закончить это.Я так близко после многих неудач.Но я застрял и не знаю, что делать больше нет.Вот что я имею в виду

Вопрос:

Чтение ввода по одной строке за раз и вывод текущей строки, если и только если вы уже прочитали вминимум на 1000 строк больше текущей строки и как минимум на 1000 строк меньше текущей строки.(Опять же, больше и меньше, чем в отношении порядка, определенного String.compareTo ().)

Ссылка на вызов

Мое решение:

public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
    SortedSet<String> linesThatHaveBeenRead = new TreeSet<>();
    int lessThan =0;
    int greaterThan =0;

    Iterator<String> itr;
    for (String currentLine = r.readLine(); currentLine != null; currentLine = r.readLine()){
        itr = linesThatHaveBeenRead.iterator();
        while(itr.hasNext()){
            String theCurrentLineInTheSet = itr.next();
            if(theCurrentLineInTheSet.compareTo(currentLine) == -1)++lessThan;
            else if(theCurrentLineInTheSet.compareTo(currentLine) == 1)++greaterThan;
        }
        if(lessThan >= 1000 && greaterThan >= 1000){
            w.println(currentLine);
            lessThan = 0;
            greaterThan =0;
        }
        linesThatHaveBeenRead.add(currentLine);

    }
}

ПРОБЛЕМА

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

ЦЕЛЬ:

Цель состоит в том, чтобы использовать наиболее эффективные данные-структура для этой проблемы.

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

Позвольте мне представить лишь доступное уточнение того, что делать.

    public static void
    doIt(java.io.BufferedReader r, java.io.PrintWriter w)
        throws java.io.IOException {
        feedNonExtremes(r, (line) -> { w.println(line);}, 1000, 1000);
    }
   /** Read <code>r</code> one line at a time and
    *   output the current line if and only there already were<br/>
    *    at least <code>nHigh</code> lines greater than the current line <br/>
    *    and at least <code>nLow</code> lines less than the current line.<br/>
    * @param r  to read lines from
    * @param sink   to feed lines to
    * @param nLow   number of lines comparing too small to process
    * @param nHigh  number of lines comparing too great to process
    */
    static void feedNonExtremes(java.io.BufferedReader r,
        Consumer<String> sink, int nLow, int nHigh) {
    // collect nLow+nHigh lines into firstLowHigh; instantiate
    // - a PriorityQueue(firstLowHigh) highest
    // - a PriorityQueue(nLow, (a, b) -> String.compareTo(b, a)) lowest
    // remove() nLow elements from highest and insert each into lowest
    // for each remaining line
    //     if greater than the head of highest
    //         add to highest and remove head
    //     else if smaller than the head of lowest
    //         add to lowest and remove head
    //     else feed to sink
    }
0 голосов
/ 03 февраля 2019

Вам необходимо реализовать бинарный поиск, а также обработать дубликаты.Я сделал здесь некоторый пример кода, который делает то, что вы хотите (может содержать ошибки).

public class CheckRead1000 {


    public static void main(String[] args) {

        //generate strings in revert order to get the worse case
        List<String> aaa = new ArrayList<String>();
        for (int i = 50000; i > 0; i--) {
            aaa.add("some string 123456789" + i);
        }

        //fast solution
        ArrayList<String> sortedLines = new ArrayList<>();
        long st1 = System.currentTimeMillis();
        for (String a : aaa) {
            checkIfRead1000MoreAndLess(sortedLines, a);
        }
        System.out.println(System.currentTimeMillis() - st1);

        // doIt solution
        TreeSet<String> linesThatHaveBeenRead = new TreeSet<>();
        long st2 = System.currentTimeMillis();
        for (String a : aaa) {
            doIt(linesThatHaveBeenRead, a);
        }
        System.out.println(System.currentTimeMillis() - st2);
    }


    // solution doIt
    public static void doIt(SortedSet<String> linesThatHaveBeenRead, String currentLine) {

        int lessThan = 0;
        int greaterThan = 0;

        Iterator<String>  itr = linesThatHaveBeenRead.iterator();
        while (itr.hasNext()) {
            String theCurrentLineInTheSet = itr.next();
            if (theCurrentLineInTheSet.compareTo(currentLine) == -1) ++lessThan;
            else if (theCurrentLineInTheSet.compareTo(currentLine) == 1) ++greaterThan;
        }
        if (lessThan >= 1000 && greaterThan >= 1000) {
            // System.out.println(currentLine);
            lessThan = 0;
            greaterThan = 0;
        }
        linesThatHaveBeenRead.add(currentLine);
    }


    // will return if we have read more at least 1000 string more and less then our string
    private static boolean checkIfRead1000MoreAndLess(List<String> sortedLines, String newLine) {
        //adding string to list and calculating its index and the last search range
        int indexes[] = addNewString(sortedLines, newLine);
        int index = indexes[0]; // index of element
        int low = indexes[1];
        int high = indexes[2];

        //we need to check if this string already was in list for instance
        // 1,2,3,4,5,5,5,5,5,6,7   for 5  we need to count 'less' as 4 and 'more' is 2
        int highIndex = index;
        for (int i = highIndex + 1; i < high; i++) {
            if (sortedLines.get(i).equals(newLine)) {
                highIndex++;
            } else {
                //no more duplicates
                break;
            }
        }

        int lowIndex = index;
        for (int i = lowIndex - 1; i > low; i--) {
            if (sortedLines.get(i).equals(newLine)) {
                lowIndex--;
            } else {
                //no more duplicates
                break;
            }
        }

        //just calculating how many we did read more and less
        if (sortedLines.size() - highIndex - 1 > 1000 && lowIndex > 1000) {
            return true;
        }
        return false;
    }


    // simple binary search will insert string and return its index and ranges in sorted list
    // first int is index,
    // second int is start of range - will be used to find duplicates,
    // third int  is end of range - will be used to find duplicates,
    private static int[] addNewString(List<String> sortedLines, String newLine) {
        if (sortedLines.isEmpty()) {
            sortedLines.add(newLine);
            return new int[]{0, 0, 0};
        }

        // int index = Integer.MAX_VALUE;
        int low = 0;
        int high = sortedLines.size() - 1;
        int mid = 0;
        while (low <= high) {
            mid = (low + high) / 2;
            if (sortedLines.get(mid).compareTo(newLine) < 0) {
                low = mid + 1;
            } else if (sortedLines.get(mid).compareTo(newLine) > 0) {
                high = mid - 1;
            } else if (sortedLines.get(mid).compareTo(newLine) == 0) {
                // index = mid;
                break;
            }

            if (low > high) {
                mid = low;
            }
        }

        if (mid == sortedLines.size()) {
            sortedLines.add(newLine);
        } else {
            sortedLines.add(mid, newLine);
        }
        return new int[]{mid, low, high};
    }
}
0 голосов
/ 02 февраля 2019

Сделал вам небольшой пример с бинарным поиском, теперь в коде Java.Он будет использовать бинарный поиск только тогда, когда newLine находится в пределах границ сортировки.

public static void main(String[] args) {
        // Create random lines
        ArrayList<String> lines = new ArrayList<String>();

        Random rn = new Random();

        for (int i = 0; i < 50000; i++) {
            int lenght = rn.nextInt(100);
            char[] newString = new char[lenght];
            for (int j = 0; j < lenght; j++) {
                newString[j] = (char) rn.nextInt(255);
            }

            lines.add(new String(newString));
        }

        // Here starts logic
        ArrayList<String> lowerCompared = new ArrayList<String>();
        ArrayList<String> higherCompared = new ArrayList<String>();
        int lowBoundry = 1000, highBoundry = 1000;

        int k = 0;
        int firstLimit = Math.min(lowBoundry, highBoundry);

        // first x lines sorter equal
        for (; k < firstLimit; k++) {
            int index = Collections.binarySearch(lowerCompared, lines.get(k));
            if (index < 0)
                index = ~index;
            lowerCompared.add(index, lines.get(k));
            higherCompared.add(index, lines.get(k));
        }

        for (; k < lines.size(); k++) {
            String newLine = lines.get(k);
            boolean lowBS = newLine.compareTo(lowerCompared.get(lowBoundry - 1)) < 0;
            boolean highBS = newLine.compareTo(higherCompared.get(0)) > 0;
            if (lowerCompared.size() == lowBoundry && higherCompared.size() == highBoundry && !lowBS && !highBS) {
                System.out.println("Time to print: " + newLine);
                continue;
            }
            if (lowBS) {
                int lowerIndex = Collections.binarySearch(lowerCompared, newLine);
                if (lowerIndex < 0)
                    lowerIndex = ~lowerIndex;

                lowerCompared.add(lowerIndex, newLine);
                if (lowerCompared.size() > lowBoundry)
                    lowerCompared.remove(lowBoundry);

            }
            if (highBS) {
                int higherIndex = Collections.binarySearch(higherCompared, newLine);
                if (higherIndex < 0)
                    higherIndex = ~higherIndex;

                higherCompared.add(higherIndex, newLine);
                if (higherCompared.size() > highBoundry)
                    higherCompared.remove(0);

            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...