Cracking Coding Interview, 6-е издание, 8.3 (магический индекс) [дубликат]

Вы можете загружать двоичные данные jpeg в виде файла и самостоятельно разбирать заголовки jpeg. Тот, который вы ищете, это заголовок 0xFFC0 или Start of Frame:

Start of frame marker (FFC0)

* the first two bytes, the length, after the marker indicate the number of bytes, including the two length bytes, that this header contains
* P -- one byte: sample precision in bits (usually 8, for baseline JPEG)
* Y -- two bytes
* X -- two bytes
* Nf -- one byte: the number of components in the image
      o 3 for color baseline JPEG images
      o 1 for grayscale baseline JPEG images

* Nf times:
      o Component ID -- one byte
      o H and V sampling factors -- one byte: H is first four bits and V is second four bits
      o Quantization table number-- one byte

The H and V sampling factors dictate the final size of the component they are associated with. For instance, the color space defaults to YCbCr and the H and V sampling factors for each component, Y, Cb, and Cr, default to 2, 1, and 1, respectively (2 for both H and V of the Y component, etc.) in the Jpeg-6a library by the Independent Jpeg Group. While this does mean that the Y component will be twice the size of the other two components--giving it a higher resolution, the lower resolution components are quartered in size during compression in order to achieve this difference. Thus, the Cb and Cr components must be quadrupled in size during decompression.

Для получения дополнительной информации о заголовках проверьте запись jpeg в wikipedia или я получил здесь информацию здесь .

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

import java.awt.Dimension;
import java.io.*;

public class JPEGDim {

public static Dimension getJPEGDimension(File f) throws IOException {
    FileInputStream fis = new FileInputStream(f);

    // check for SOI marker
    if (fis.read() != 255 || fis.read() != 216)
        throw new RuntimeException("SOI (Start Of Image) marker 0xff 0xd8 missing");

    Dimension d = null;

    while (fis.read() == 255) {
        int marker = fis.read();
        int len = fis.read() << 8 | fis.read();

        if (marker == 192) {
            fis.skip(1);

            int height = fis.read() << 8 | fis.read();
            int width = fis.read() << 8 | fis.read();

            d = new Dimension(width, height);
            break;
        }

        fis.skip(len - 2);
    }

    fis.close();

    return d;
}

public static void main(String[] args) throws IOException {
    System.out.println(getJPEGDimension(new File(args[0])));
}

}

3
задан Johan S 4 December 2015 в 22:13
поделиться

3 ответа

Нет, на мой взгляд, первое решение - это не O (log n), как утверждают другие ответы, это действительно O (n) наихудший случай (в худшем случае ему все равно нужно пройти через все элементы, рассмотрите массив эквивалентности

Причина, по которой это не O (log n), заключается в том, что она должна искать по обе стороны от середины (двоичный поиск проверяет только одну сторону середины поэтому это O (log n)).

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

EDIT: Однако когда я снова подумал о первом решении, он с другой стороны позволяет «пропустить назад», если это возможно, итерационное решение не позволяет - рассмотрим например, массив, например {-10, -9, -8, -7, -6, -5}, итерационное решение должно будет проверять все элементы, поскольку оно начинается с начала, а значения не позволяют пропустить вперед, тогда как при старте с середины, алго может полностью пропустить проверку первой половины, затем первой половины второй половины и т. д.

3
ответ дан axalis 19 August 2018 в 03:43
поделиться
  • 1
    Спасибо за понимание вопроса, однако вы можете получить еще одну сложность времени, например. введение отдельной переменной d или что-то еще? Если никто не ответит на что-то более подробное, я приму ваш ответ. – Johan S 4 December 2015 в 22:14
  • Вы правы, худшей сложностью является O (n). Возможно, вам придется посетить все элементы вашего массива.
  • Есть только одна причина не посещать элементы массива [mid, end], и это когда array[mid] > end (потому что в этом случае магия индекс, конечно, отсутствует в [mid, end] элементах.
  • Точно так же существует только одна причина не посещать элементы массива [start, mid], а это когда array[start] > mid.
  • Итак, есть надежда, что вы можете не посещать все элементы. Поэтому это одна оптимизация, которая может работать.

Таким образом, этот двоично-подобный метод кажется лучше, чем итерация по всему массиву линейно, но в худшем случае вы будете (0).


PS: Я предположил, что массив отсортирован в порядке возрастания.

2
ответ дан displayName 19 August 2018 в 03:43
поделиться
  • 1
    Сейчас я просто позвоню, однако спасибо за то, что вы столкнулись с проблемой. У вас есть преимущество! – Johan S 4 December 2015 в 22:36
  • 2
    @JohanS: Я сломал проблему, чтобы подчеркнуть тот факт, что когда причина не посещать половинки массива не хватает, вы, в конечном итоге, окажетесь во всём массиве. Отв, как вы сказали, люди заканчивают Log (n), когда видят что-то похожее на двоичный поиск. – displayName 4 December 2015 в 22:39

Похоже, вы неправильно поняли временную сложность требуемого решения. Хуже дело не O(n), это O(log(n)). Это потому, что во время каждого прохода вы в следующий раз выполняете только половину массива.

Вот пример C ++ и проверьте, что для всего массива из 11 элементов требуется всего 3 проверка.

0
ответ дан Salvador Dali 19 August 2018 в 03:43
поделиться
  • 1
    Если вы посмотрите на этот пример: [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8], он посетит все элементы, так как мы не ищем критерия, который можно поймать с помощью регулярный двоичный поиск (следовательно, мы не можем разделить на две части). – Johan S 4 December 2015 в 22:10
  • 2
    Кстати, ваш алгоритм для разных значений, не работает с нечеткими значениями, попробуйте следующее: [5, 5, 5, 5, 5, 5, 1337]. – Johan S 4 December 2015 в 22:17
Другие вопросы по тегам:

Похожие вопросы: