24 фСвраля 2022

🧊 Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ структуры Π΄Π°Π½Π½Ρ‹Ρ…: массивы ΠΈ связанныС списки с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Π½Π° Python

Kaggle expertβš›οΈ ΠŸΠΈΡˆΡƒ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠ°Ρ… ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ°Ρ… Π² сфСрС Machine Learning.
Π’ этой части ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π° ΠΌΡ‹ рассмотрим массивы ΠΈ связанныС списки, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ‚Π΅ΠΎΡ€ΠΈΡŽ, которая стоит Π·Π° Π½ΠΈΠΌΠΈ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΠΌ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ этих структур Π½Π° языкС Python.
🧊 Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ структуры Π΄Π°Π½Π½Ρ‹Ρ…: массивы ΠΈ связанныС списки с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Π½Π° Python

ΠœΠ°ΡΡΠΈΠ²Ρ‹

ΠœΠ°ΡΡΠΈΠ²Ρ‹ – ΠΎΠ΄Π½Π° ΠΈΠ· самых Ρ„ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Ρ… структур Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΠΊΠ΅. Они встроСны Π²ΠΎ всС языки программирования, Π΄Π°ΠΆΠ΅ Ρ‚Π°ΠΊΠΈΠ΅ Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹Π΅, ΠΊΠ°ΠΊ C ΠΈΠ»ΠΈ Assembler. ΠœΠ°ΡΡΠΈΠ²Ρ‹ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ собой Π³Ρ€ΡƒΠΏΠΏΡƒ элСмСнтов ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ располоТСны Π½Π° Π½Π΅ΠΏΡ€Π΅Ρ€Ρ‹Π²Π½ΠΎΠΌ участкС памяти ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π°. НапримСр, [5, 8, -1] ΠΈΠ»ΠΈ ['a', 'b', 'c'].

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ элСмСнты массива стоят рядом Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ Π»ΡŽΠ±ΠΎΠΌΡƒ ΠΈΡ… индСксу. НапримСр, ΠΊ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ, Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΌΡƒ ΠΈΠ»ΠΈ послСднСму элСмСнту Π·Π° врСмя O(1).

🧊 Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ структуры Π΄Π°Π½Π½Ρ‹Ρ…: массивы ΠΈ связанныС списки с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Π½Π° Python

Π’ Ρ‚Π°ΠΊΠΈΡ… языках, ΠΊΠ°ΠΊ C ΠΈ Java, трСбуСтся Π·Π°Ρ€Π°Π½Π΅Π΅ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π°Π·ΠΌΠ΅Ρ€ массива ΠΈ Ρ‚ΠΈΠΏ Π΄Π°Π½Π½Ρ‹Ρ…. Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° списка Π² Python позволяСт ΠΎΠ±ΠΎΠΉΡ‚ΠΈ эти трСбования, сохраняя Π΄Π°Π½Π½Ρ‹Π΅ Π² Π²ΠΈΠ΄Π΅ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ Π½Π° мСстополоТСниС элСмСнтов Π² памяти, автоматичСски измСняя Ρ€Π°Π·ΠΌΠ΅Ρ€ массива, ΠΊΠΎΠ³Π΄Π° мСсто заканчиваСтся. Π­Π»Π΅ΠΌΠ΅Π½Ρ‚Π°ΠΌ памяти Π½Π΅ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ рядом Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ.

РСализация

ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ ограничСния, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ ΠΌΡ‹ сталкиваСмся ΠΏΡ€ΠΈ создании массивов Π½Π° языкС Python:

  1. ПослС выдСлСния мСста для массива ΠΌΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ большС, Π½Π΅ создав Π½ΠΎΠ²Ρ‹ΠΉ массив.
  2. ВсС значСния Π² массивС Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°.

ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Python ΠΎΡ‡Π΅Π½ΡŒ простой класс Array, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΠΌΠΈΡ‚ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ массивов Π² языках Π±ΠΎΠ»Π΅Π΅ Π½ΠΈΠ·ΠΊΠΎΠ³ΠΎ уровня.

        from typing import Any

class Array:
    def __init__(self, n: int, dtype: Any):
        self.vals = [None] * n
        self.dtype = dtype

    def get(self, i: int) -> Any:
        """
        Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠ°ΠΊ индСкс i
        """
        return self.vals[i]

    def put(self, i: int, val: Any) -> None:
        """
        ОбновляСм массив ΠΊΠ°ΠΊ индСкс i с val. Val Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° с self.dtype
        """
        if not isinstance(val, self.dtype):
            raise ValueError(f"val явл {type(val)}; Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ {self.dtype}")

        self.vals[i] = val
    

Π”Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим, ΠΊΠ°ΠΊΠΈΠ΅ способы Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ класса Array ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ. Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ экзСмпляр. ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€Π΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ индСкс пустой. Π—Π°ΠΏΠΎΠ»Π½ΠΈΠΌ слот символом char, Π° Π·Π°Ρ‚Π΅ΠΌ Π²Π΅Ρ€Π½Π΅ΠΌ Π΅Π³ΠΎ. Наши ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠ΅ дСйствия ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€Π΄ΠΈΠ»ΠΈ, Ρ‡Ρ‚ΠΎ массив ΠΎΡ‚Π²Π΅Ρ€Π³Π°Π΅Ρ‚ non-char (Π½Π΅ΡΠΈΠΌΠ²ΠΎΠ»ΡŒΠ½Ρ‹Π΅) значСния. Код Π½Π΅ самый Π»ΡƒΡ‡ΡˆΠΈΠΉ, Π½ΠΎ Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ:

        arr = Array(10, str)

arr.get(0)       # None
arr.put(0, 'a')  # None
arr.get(0)       # 'a'

arr.put(1, 5)    
# ValueError: val is <class 'int'>; must be <class 'str'>
    

ΠŸΡ€ΠΈΠΌΠ΅Ρ€

Π’ процСссС Ρ€Π°Π±ΠΎΡ‚Ρ‹ с массивами Π²Ρ‹, скорСС всСго, Π·Π°Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ встроСнный список Python, ΠΈΠ»ΠΈ массив NumPy, Π° Π½Π΅ созданный Π½Π°ΠΌΠΈ класс Array. Однако, Π² цСлях использования массива, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π΅ мСняСт Ρ€Π°Π·ΠΌΠ΅Ρ€, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ с Leetcode LC 1089: Duplicate Zeros (Π”ΡƒΠ±Π»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½ΡƒΠ»Π΅ΠΉ). ЦСль Π΄Π°Π½Π½Ρ‹Ρ… дСйствий – ΠΏΡ€ΠΎΠ΄ΡƒΠ±Π»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ всС Π½ΡƒΠ»ΠΈ Π² массивС, измСняя Π΅Π³ΠΎ Π½Π° мСстС Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ элСмСнты двигались Π²Π½ΠΈΠ· ΠΈ исчСзали, Π° Π½Π΅ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π»ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€ массива ΠΈΠ»ΠΈ создавали Π½ΠΎΠ²Ρ‹ΠΉ.

        def duplicate_zeros(arr: list) -> None:
    """
    Π”ΡƒΠ±Π»ΠΈΡ€ΡƒΠ΅ΠΌ всС Π½ΡƒΠ»ΠΈ Π² массивС, оставляя Π΅Π³ΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΡƒΡŽ     Π΄Π»ΠΈΠ½Ρƒ. НапримСр, [1, 0, 2, 3] -> [1, 0, 0, 2]
    """
    i = 0

    while i < len(arr):
        if arr[i] == 0:
            arr.insert(i, 0)   # ВставляСм 0 ΠΊΠ°ΠΊ индСкс i
            arr.pop()          # Π£Π±ΠΈΡ€Π°Π΅ΠΌ послСдний элСмСнт
            i += 1
        i += 1
    

Π’ ΠΈΡ‚ΠΎΠ³Π΅ ΠΌΡ‹ ΠΈΡ‚Π΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎ пСрСмСщаСмся ΠΏΠΎ списку, ΠΏΠΎΠΊΠ° Π½Π΅ Π½Π°ΠΉΠ΄Π΅ΠΌ ноль. Π—Π°Ρ‚Π΅ΠΌ вставляСм Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ноль ΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ послСдний элСмСнт для сохранСния Ρ€Π°Π·ΠΌΠ΅Ρ€Π° массива.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: Π² Π΄Π°Π½Π½ΠΎΠΌ случаС Π²Π°ΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ†ΠΈΠΊΠ»Π° while, Π° Π½Π΅ for, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΌΡ‹ измСняСм массив ΠΏΠΎ ΠΌΠ΅Ρ€Π΅ Π΅Π³ΠΎ прохоТдСния. Π’Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Π½Π°Π΄ индСксом i позволяСт Π½Π°ΠΌ ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ вставлСнный ноль, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π΄Π²ΠΎΠΉΠ½ΠΎΠ³ΠΎ счСта.

Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° питониста»

БвязанныС списки

БвязанныС списки – Π΅Ρ‰Π΅ ΠΎΠ΄Π½Π° ΠΊΠ»ΡŽΡ‡Π΅Π²Π°Ρ структура Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΠΊΠ΅. Как ΠΈ массивы, связный список – это Π³Ρ€ΡƒΠΏΠΏΠ° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ. Однако, Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ массивов, значСния Π² связанном спискС Π½Π΅ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, ΠΈ Π½Π°ΠΌ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π·Π°Ρ€Π°Π½Π΅Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ Ρ€Π°Π·ΠΌΠ΅Ρ€ списка.

ΠžΡΠ½ΠΎΠ²Π½Ρ‹ΠΌ элСмСнтом связанного списка являСтся ΡƒΠ·Π΅Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТит Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° любоС мСсто Π² памяти.

НиТС прСдставлСн связанный список со значСниями [1, 'a', 0.3]. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ€Π°Π·Π»ΠΈΡ‡ΠΈΠ΅ Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠ² элСмСнтов. ΠœΡ‹ Π²ΠΈΠ΄ΠΈΠΌ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ Π±Π°ΠΉΡ‚Π° для Ρ†Π΅Π»Ρ‹Ρ… ΠΈ ΠΏΠ»Π°Π²Π°ΡŽΡ‰ΠΈΡ… чисСл, ΠΎΠ΄ΠΈΠ½ Π±Π°ΠΉΡ‚ для символов. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ·Π΅Π» ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅Ρ…Π±Π°ΠΉΡ‚ΠΎΠ²Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, расстояниС ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΎ, послСдний ΠΈΠ· Π½ΠΈΡ… содСрТит Π½ΡƒΠ»Π΅Π²ΠΎΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π² пространство.

🧊 Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ структуры Π΄Π°Π½Π½Ρ‹Ρ…: массивы ΠΈ связанныС списки с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Π½Π° Python

ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΠΈΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ Π½Π° Ρ‚ΠΈΠΏΡ‹ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Π΄Π»ΠΈΠ½Ρƒ Π΄Π΅Π»Π°Π΅Ρ‚ связанныС списки ΠΏΡ€ΠΈΠ²Π»Π΅ΠΊΠ°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ. Однако эта Π³ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒ создаСт Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ доступСн Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π΅Ρ€Ρ… списка, Π° это Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ для поиска любого Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ ΡƒΠ·Π»Π° Π½Π°ΠΌ придСтся ΠΏΡ€ΠΎΠΉΡ‚ΠΈ вСсь список. Π”Ρ€ΡƒΠ³ΠΈΠΌΠΈ словами, ΠΌΡ‹ лишаСмся O(1) поиска для любого элСмСнта, ΠΊΡ€ΠΎΠΌΠ΅ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΡƒΠ·Π»Π°. Если Π²Ρ‹ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚Π΅ 100-ΠΉ элСмСнт, Ρ‚ΠΎ для Π΅Π³ΠΎ получСния потрСбуСтся 100 шагов: схСма O(n).

МоТно ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ связанныС списки Π±ΠΎΠ»Π΅Π΅ ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ. Для этого Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ Π½Π° ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠ΅ ΡƒΠ·Π»Ρ‹ ΠΈ Ρ€Π°ΡΠΊΡ€Ρ‹Ρ‚ΡŒ ΠΊΠΎΠ½Π΅Ρ† списка, ΠΈΠ»ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π΅Π³ΠΎ ΠΊΠΎΠ»ΡŒΡ†Π΅Π²Ρ‹ΠΌ. Π’ Ρ†Π΅Π»ΠΎΠΌ, Π²Ρ‹Π±ΠΎΡ€ связанных списков вмСсто массивов являСтся ΠΏΠ»Π°Ρ‚ΠΎΠΉ Π·Π° удобство.

РСализация

Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ связанный список Π² Python, Π½Π°Ρ‡Π½Π΅ΠΌ с опрСдСлСния ΡƒΠ·Π»Π°. НСобходимы Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄Π²Π΅ части: Π΄Π°Π½Π½Ρ‹Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ…Ρ€Π°Π½ΠΈΡ‚ ΡƒΠ·Π΅Π» ΠΈ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΡƒΠ·Π΅Π» Π² спискС. Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΠΌΠ΅Ρ‚ΠΎΠ΄ __repr__ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Ρ‹Π»ΠΎ Π»Π΅Π³Ρ‡Π΅ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ содСрТаниС ΡƒΠ·Π»Π°.

        class ListNode:
    def __init__(self, val=None, next=None):
        self.val = val
        self.next = next

    def __repr__(self):
        return f"ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ {self.val}"
    

Π”Π°Π»Π΅Π΅ ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ класс ListNode. Π’Π°ΠΆΠ½ΠΎ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π²Π΅Ρ€ΡˆΠΈΠ½Π° списка – это наша пСрСмСнная head. НСобходимо ΠΈΡ‚Π΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ .next для доступа ΠΊ Π±ΠΎΠ»Π΅Π΅ Π³Π»ΡƒΠ±ΠΎΠΊΠΈΠΌ ΡƒΠ·Π»Π°ΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ввСсти индСкс Ρ‚ΠΈΠΏΠ° [1] ΠΈΠ»ΠΈ [2], Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ Π΄ΠΎ Π½ΠΈΡ….

        head = ListNode(5)
head.next = ListNode('abc')
head.next.next = ListNode(4.815162342)

print(head)            # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 5
print(head.next)       # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ abc
print(head.next.next)  # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 4.815162342
    

Для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Ρ‹Π»ΠΎ Π»Π΅Π³Ρ‡Π΅ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΡƒΠ·Π΅Π» ΠΊΠ°ΠΊ Π² ΠΊΠΎΠ½Π΅Ρ†, Ρ‚Π°ΠΊ ΠΈ Π² Π½Π°Ρ‡Π°Π»ΠΎ списка, напишСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

        def add_to_end(head: ListNode, val: Any) -> None:
    ptr = head
    while ptr.next:
        ptr = ptr.next
    ptr.next = ListNode(val)

def add_to_front(head: ListNode, val: Any) -> ListNode:
    node = ListNode(val)
    node.next = head
    return node
    

Π’ add_to_end создаСм ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ptr (ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ). Она начинаСтся с head ΠΈ ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΡ‚ список, ΠΏΠΎΠΊΠ° Π½Π΅ достигнСт послСднСго ΡƒΠ·Π»Π°, Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠΌ .next ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ являСтся Π½ΡƒΠ»Π΅Π²ΠΎΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ. Π”Π°Π»Π΅Π΅, устанавливаСм Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ .next этого ΡƒΠ·Π»Π° Π² Π½ΠΎΠ²Ρ‹ΠΉ ListNode. Π’Π½ΡƒΡ‚Ρ€ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π½ΠΈΡ‡Π΅Π³ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ вступило Π² силу.

Π’ add_to_front ΠΌΡ‹ создаСм Π½ΠΎΠ²Ρ‹ΠΉ head, устанавливаСм ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ .next Π² Π²Π΅Ρ€ΡˆΠΈΠ½Ρƒ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ связанного списка. Π’Ρ€ΡƒΡ‡Π½ΡƒΡŽ обновляСм head Π²Π½Π΅ Π΄Π°Π½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΡƒΠ·Π»Π°. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС, head ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Π½Π° старый head.

        # Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΈ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ список
head = ListNode(5)
add_to_end(head, 'abc')
add_to_end(head, 4.815162342)

# Π’Ρ‹Π²ΠΎΠ΄
print(head)            # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 5
print(head.next)       # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ abc
print(head.next.next)  # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 4.815162342

# ΠŸΡ‹Ρ‚Π°Π΅ΠΌΡΡ ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ head
add_to_front(head, 0)  
print(head)            # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 5

# ΠšΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ head
head = add_to_front(head, 0)
print(head)            # ListNode со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 0
    

ΠŸΡ€ΠΈΠΌΠ΅Ρ€

Один ΠΈΠ· частых вопросов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Π²ΠΎ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ со связными списками – Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ срСднСго ΡƒΠ·Π»Π°. Π’Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ сущСствуСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π°Ρ‡Π°Π»ΠΎ списка, Π½Π΅Ρ‚ возмоТности Π·Π°Ρ€Π°Π½Π΅Π΅ ΡƒΠ·Π½Π°Ρ‚ΡŒ Π΅Π³ΠΎ Π΄Π»ΠΈΠ½Ρƒ. Π˜ΡΡ…ΠΎΠ΄Ρ ΠΈΠ· этого, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ придСтся ΠΎΠ±ΠΎΠΉΡ‚ΠΈ список Π΄Π²Π°ΠΆΠ΄Ρ‹: ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ·Π½Π°Ρ‚ΡŒ Π΅Π³ΠΎ Π΄Π»ΠΈΠ½Ρƒ, Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠΉΡ‚ΠΈ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Ρƒ ΠΏΡƒΡ‚ΠΈ.

Π Π°Π½Π΅Π΅ ΠΌΡ‹ использовали ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±ΠΎΠΉΡ‚ΠΈ список ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ ΡƒΠ·Π»Ρƒ Π·Π° Ρ€Π°Π·, ΠΏΠΎΠΊΠ° Π½Π΅ Π΄ΠΎΠΉΠ΄Π΅ΠΌ ΠΊΠΎΠ½Ρ†Π°.

На самом Π΄Π΅Π»Π΅ сущСствуСт способ Π½Π°ΠΉΡ‚ΠΈ сСрСдину списка Π·Π° ΠΎΠ΄ΠΈΠ½ ΠΏΡ€ΠΎΡ…ΠΎΠ΄.

Π§Ρ‚ΠΎ Ссли Ρƒ нас Π±ΡƒΠ΄Π΅Ρ‚ Π΄Π²Π° указатСля? ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈΠ· Π½ΠΈΡ… Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒΡΡ ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ ΡƒΠ·Π»Ρƒ Π·Π° ΠΏΠΎΠ΄Ρ…ΠΎΠ΄, Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ – ΠΏΠΎ Π΄Π²Π°. Π’ Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° быстрый ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ достигнСт ΠΊΠΎΠ½Ρ†Π° списка, наш ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ окаТСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² сСрСдинС.

Π˜ΡΡ…ΠΎΠ΄Ρ ΠΈΠ· написанного Π²Ρ‹ΡˆΠ΅, ΠΌΡ‹ ΠΎΡ‚Π²Π΅Ρ‚ΠΈΠΌ Π½Π° LC 876: Π‘Π΅Ρ€Π΅Π΄ΠΈΠ½Π° связанного списка (Middle of the Linked List) ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

        def find_middle(head: ListNode) -> ListNode:
    """
    Return middle node of linked list. If even number of nodes,
    returns the second middle node.
    """
    # Π‘ΠΌΠΎΡ‚Ρ€ΠΈΠΌ Π½Π° ΠΌΠ΅Π΄Π»Π΅Π½Π½ΡƒΡŽ ΠΈ Π±Ρ‹ΡΡ‚Ρ€ΡƒΡŽ Ρ‚ΠΎΡ‡ΠΊΠΈ
    slow = head
    fast = head.next

    # ΠŸΡ€ΠΎΠ³ΠΎΠ½ΡΠ΅ΠΌ список Ρ‡Π΅Ρ€Π΅Π· Ρ†ΠΈΠΊΠ»
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

    return slow 

    

Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с Leetcode, ΠΌΡ‹ убСТдаСмся, Ρ‡Ρ‚ΠΎ head.next – ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚.

        # Бписок: A -> B -> C -> D -> E
# Π‘Π΅Ρ€Π΅Π΄ΠΈΠ½Π°: C

# Начало с head: Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ
# Slow: A -> B -> C -> D  ==> Π‘Π΅Ρ€Π΅Π΄ΠΈΠ½Π°: D
# Fast: A -> C -> E -> null

# Начало с head.next: ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ
# Slow: A -> B -> C       ==> Π‘Π΅Ρ€Π΅Π΄ΠΈΠ½Π°: C
# Fast: B -> D -> null
    
🧊 Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ структуры Π΄Π°Π½Π½Ρ‹Ρ…: массивы ΠΈ связанныС списки с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Π½Π° Python

LC 141. Linked List Cycle: Π¦ΠΈΠΊΠ» связанного списка – ΠΏΡ€ΠΈΠΌΠ΅Ρ€ использования ΠΌΠ΅Π΄Π»Π΅Π½Π½Ρ‹Ρ… ΠΈ быстрых ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ. Наша Ρ†Π΅Π»ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, Π΅ΡΡ‚ΡŒ Π»ΠΈ Π² спискС Ρ†ΠΈΠΊΠ», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚, ΠΊΠΎΠ³Π΄Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ ΡƒΠ·Π»Π° ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° Π±ΠΎΠ»Π΅Π΅ Ρ€Π°Π½Π½ΠΈΠΉ ΡƒΠ·Π΅Π» Π² спискС.

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΡ…ΠΎΠ΄ списка Ρ‡Π΅Ρ€Π΅Π· Ρ†ΠΈΠΊΠ» Π±ΡƒΠ΄Π΅Ρ‚ бСсконСчным.

Один ΠΈΠ· Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ выполнСния ΠΎΠ±Ρ…ΠΎΠ΄Π°, ΠΈΠ»ΠΈ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΡŽΡ‰ΠΈΡ…ΡΡ ΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½ΠΎΠ² Π·Π° Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.

Π‘ΠΎΠ»Π΅Π΅ простой ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² использовании Π΄Π²ΡƒΡ… ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ.

Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ использованиС while fast ΠΈ fast.next, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ эти ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈΠΌΠ΅ΡŽΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ False Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ достиТСнии ΠΊΠΎΠ½Ρ†Π° списка. ВмСсто этого, подставим slow ΠΈ fast Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΡƒΠ·Π»Ρ‹. Π‘ΡƒΠ΄Π΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ ΠΈΡ… ΠΏΠΎ списку с Ρ€Π°Π·Π½ΠΎΠΉ ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒΡŽ, ΠΏΠΎΠΊΠ° ΠΎΠ½ΠΈ Π½Π΅ совпадут. Π’ ΠΊΠΎΠ½Ρ†Π΅ списка Π²Π΅Ρ€Π½Π΅ΠΌ False. Если Π΄Π²Π° указатСля Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Π½Π° ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΡƒΠ·Π΅Π», Π²Π΅Ρ€Π½Π΅ΠΌ True.

        def has_cycle(head: ListNode) -> bool:
    """
    ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅ΠΌ Π³Π΄Π΅ связанный список ΠΈΠΌΠ΅Π΅Ρ‚ Ρ†ΠΈΠΊΠ»
    """
    slow = head
    fast = head.next

    while slow != fast:

        # Находим ΠΊΠΎΠ½Π΅Ρ† списка
        if not (fast or fast.next):
            return False

        slow = slow.next
        fast = fast.next.next

    return True
    
***

ΠœΡ‹ ΡƒΠ·Π½Π°Π»ΠΈ, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ массивы ΠΈ связанныС списки. Π­Ρ‚ΠΎ ваТная ΡΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰Π°Ρ структур Π΄Π°Π½Π½Ρ‹Ρ…, которая ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²ΠΎ всСх языках программирования.

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ части ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Π° приступим ΠΊ ΠΈΠ·ΡƒΡ‡Π΅Π½ΠΈΡŽ Π΄Π΅Ρ€Π΅Π²ΡŒΠ΅Π² ΠΈ Π³Ρ€Π°Ρ„ΠΎΠ².

ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ ΠΏΠΎ Ρ‚Π΅ΠΌΠ΅

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊΠΈ

ΠœΠ•Π ΠžΠŸΠ Π˜Π―Π’Π˜Π―

ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

Π’ΠΠšΠΠΠ‘Π˜Π˜

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ вакансию
Senior Java Developer
Москва, ΠΏΠΎ ΠΈΡ‚ΠΎΠ³Π°ΠΌ собСсСдования
Java Team Lead
Москва, ΠΏΠΎ ΠΈΡ‚ΠΎΠ³Π°ΠΌ собСсСдования

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•