// C#: arrays have fixed size
int[] arr = new int[5]; // [0, 0, 0, 0, 0]
arr[0] = 10;
// Cannot grow beyond initial size — List<T> is the dynamic equivalent
# Python has no fixed-size array in the core language;
# array.array is the closest typed buffer with a size set at creation
from array import array
arr = array("i", [0] * 5) # [0, 0, 0, 0, 0]
arr[0] = 10
# It can still grow via append — list is the idiomatic dynamic array
### Динамический массив
Автоматически увеличивается при добавлении элементов.
// By value
foreach ($arr as $x) {
echo $x . "\n";
}
// By index and value
foreach ($arr as $i => $x) {
echo "arr[$i] = $x\n";
}
// In reverse order
for ($i = count($arr) - 1; $i >= 0; $i--) {
echo $arr[$i] . "\n";
}
// By value
for _, x := range arr {
fmt.Println(x)
}
// By index and value
for i, x := range arr {
fmt.Printf("arr[%d] = %d\n", i, x)
}
// In reverse order
for i := len(arr) - 1; i >= 0; i-- {
fmt.Println(arr[i])
}
// By value
foreach (int x in arr)
{
Console.WriteLine(x);
}
// By index and value
foreach ((int x, int i) in arr.Select((x, i) => (x, i)))
{
Console.WriteLine($"arr[{i}] = {x}");
}
// In reverse order
for (int i = arr.Length - 1; i >= 0; i--)
{
Console.WriteLine(arr[i]);
}
# By value
for x in arr:
print(x)
# By index and value
for i, x in enumerate(arr):
print(f"arr[{i}] = {x}")
# In reverse order
for x in reversed(arr):
print(x)
### Срезы (slicing)
$arr = [10, 20, 30, 40, 50];
array_slice($arr, 1, 2); // [20, 30] — from index 1, take 2
array_slice($arr, 0, 3); // [10, 20, 30] — first 3
array_slice($arr, 2); // [30, 40, 50] — from index 2 to end
array_slice($arr, -2); // [40, 50] — last 2
array_reverse($arr); // [50, 40, 30, 20, 10] — reverse
arr := []int{10, 20, 30, 40, 50}
_ = arr[1:3] // [20, 30] — from index 1 to 3 (exclusive)
_ = arr[:3] // [10, 20, 30] — first 3
_ = arr[2:] // [30, 40, 50] — from index 2 to end
_ = arr[len(arr)-2:] // [40, 50] — last 2
// Reverse: use slices.Reverse(arr) from "slices" package (Go 1.21+)
int[] arr = [10, 20, 30, 40, 50];
_ = arr[1..3]; // [20, 30] — range operator, end exclusive
_ = arr[..3]; // [10, 20, 30] — first 3
_ = arr[2..]; // [30, 40, 50] — from index 2 to end
_ = arr[^2..]; // [40, 50] — last 2 via index-from-end
_ = arr.Reverse().ToArray(); // [50, 40, 30, 20, 10]
// Ranges on arrays copy; use arr.AsSpan()[1..3] for a zero-copy view
arr = [10, 20, 30, 40, 50]
arr[1:3] # [20, 30] — from index 1 to 3 (exclusive)
arr[:3] # [10, 20, 30] — first 3
arr[2:] # [30, 40, 50] — from index 2 to end
arr[-2:] # [40, 50] — last 2
arr[::-1] # [50, 40, 30, 20, 10] — reverse
# Slicing a list always copies; use memoryview for zero-copy over buffers
> **Запомни:** В PHP `array_slice()` создаёт **копию** — это O(k) по памяти, где k — размер среза.
Строки как массивы
Строки — это по сути массивы символов (с некоторыми отличиями).
// PHP: strings are mutable, accessible by index
$s = 'hello';
echo $s[0]; // 'h'
$s[0] = 'H'; // 'Hello' — strings ARE mutable in PHP
// Useful string functions
strpos($s, 'll'); // 2 (index of substring)
substr_count($s, 'l'); // 2
explode(',', 'a,b,c'); // split by delimiter -> ['a', 'b', 'c']
// For multibyte (Unicode) strings use mb_* functions
$s = 'привет';
mb_strlen($s); // 6
mb_substr($s, 0, 1); // 'п'
// Go: strings are IMMUTABLE, accessible by index (bytes)
s := "hello"
fmt.Println(s[0]) // 104 (byte value of 'h')
fmt.Println(string(s[0])) // "h"
// s[0] = 'H' — compile error! Strings are immutable in Go
// Useful string functions
strings.Index(s, "ll") // 2 (index of substring)
strings.Count(s, "l") // 2
strings.Split("a,b,c", ",") // split by delimiter -> ["a", "b", "c"]
// For Unicode strings use []rune
s2 := "привет"
fmt.Println(len([]rune(s2))) // 6
fmt.Println(string([]rune(s2)[:1])) // "п"
// C#: strings are IMMUTABLE, indexable by UTF-16 char
string s = "hello";
Console.WriteLine(s[0]); // 'h'
// s[0] = 'H'; — compile error! Strings are immutable in C#
// Useful string methods
s.IndexOf("ll"); // 2 (index of substring, -1 if missing)
s.Count(c => c == 'l'); // 2
"a,b,c".Split(','); // split by delimiter -> ["a", "b", "c"]
// To "mutate", build a new string
var sb = new StringBuilder(s);
sb[0] = 'H';
string capitalized = sb.ToString(); // "Hello"
// A char is a UTF-16 unit; for grapheme-safe work use StringInfo
string s2 = "привет";
Console.WriteLine(s2.Length); // 6 (Cyrillic fits into one UTF-16 unit)
Console.WriteLine(s2[..1]); // "п"
# Python: strings are IMMUTABLE, indexed by Unicode code point
s = "hello"
print(s[0]) # 'h'
# s[0] = "H" — TypeError! Build a new string instead
s = "H" + s[1:] # "Hello"
# Useful string methods
s.find("ll") # 2 (index of substring, -1 if missing)
s.count("l") # 2
"a,b,c".split(",") # split by delimiter -> ['a', 'b', 'c']
# Unicode works out of the box — no mb_* functions or []rune needed
s2 = "привет"
len(s2) # 6
s2[0] # 'п'
// O(n) time, O(1) memory
func reverseArray(arr []int) {
left, right := 0, len(arr)-1
for left < right {
arr[left], arr[right] = arr[right], arr[left]
left++
right--
}
}
// O(n) time, O(1) memory
public static void ReverseArray(int[] arr)
{
int left = 0;
int right = arr.Length - 1;
while (left < right)
{
(arr[left], arr[right]) = (arr[right], arr[left]); // Tuple deconstruction swap
left++;
right--;
}
}
# O(n) time, O(1) memory
def reverse_array(arr: list[int]) -> None:
left, right = 0, len(arr) - 1
while left < right:
arr[left], arr[right] = arr[right], arr[left]
left += 1
right -= 1
### Удаление дубликатов из отсортированного массива
// In-place, O(1) extra memory
function removeDuplicates(array &$arr): int
{
if (empty($arr)) {
return 0;
}
$write = 1;
for ($read = 1; $read < count($arr); $read++) {
if ($arr[$read] !== $arr[$read - 1]) {
$arr[$write] = $arr[$read];
$write++;
}
}
return $write; // Length of unique part
}
// Example: [1,1,2,2,3] -> [1,2,3,...] returns 3
// In-place, O(1) extra memory
func removeDuplicates(arr []int) int {
if len(arr) == 0 {
return 0
}
write := 1
for read := 1; read < len(arr); read++ {
if arr[read] != arr[read-1] {
arr[write] = arr[read]
write++
}
}
return write // Length of unique part
}
// Example: [1,1,2,2,3] -> [1,2,3,...] returns 3
// In-place, O(1) extra memory
public static int RemoveDuplicates(int[] arr)
{
if (arr.Length == 0)
{
return 0;
}
int write = 1;
for (int read = 1; read < arr.Length; read++)
{
if (arr[read] != arr[read - 1])
{
arr[write] = arr[read];
write++;
}
}
return write; // Length of unique part
}
// Example: [1,1,2,2,3] -> [1,2,3,...] returns 3
# In-place, O(1) extra memory
def remove_duplicates(arr: list[int]) -> int:
if not arr:
return 0
write = 1
for read in range(1, len(arr)):
if arr[read] != arr[read - 1]:
arr[write] = arr[read]
write += 1
return write # Length of unique part
# Example: [1,1,2,2,3] -> [1,2,3,...] returns 3
### Поворот массива
// Rotate array to the right by k positions
// [1,2,3,4,5], k=2 -> [4,5,1,2,3]
function rotate(array &$arr, int $k): void
{
$n = count($arr);
$k = $k % $n; // In case k > n
$reverse = function (int $start, int $end) use (&$arr): void {
while ($start < $end) {
[$arr[$start], $arr[$end]] = [$arr[$end], $arr[$start]];
$start++;
$end--;
}
};
$reverse(0, $n - 1); // [5,4,3,2,1]
$reverse(0, $k - 1); // [4,5,3,2,1]
$reverse($k, $n - 1); // [4,5,1,2,3]
}
// Rotate slice to the right by k positions
// [1,2,3,4,5], k=2 -> [4,5,1,2,3]
func rotate(arr []int, k int) {
n := len(arr)
k = k % n // In case k > n
reverse := func(start, end int) {
for start < end {
arr[start], arr[end] = arr[end], arr[start]
start++
end--
}
}
reverse(0, n-1) // [5,4,3,2,1]
reverse(0, k-1) // [4,5,3,2,1]
reverse(k, n-1) // [4,5,1,2,3]
}
// Rotate array to the right by k positions
// [1,2,3,4,5], k=2 -> [4,5,1,2,3]
public static void Rotate(int[] arr, int k)
{
int n = arr.Length;
k %= n; // In case k > n
void Reverse(int start, int end)
{
while (start < end)
{
(arr[start], arr[end]) = (arr[end], arr[start]);
start++;
end--;
}
}
Reverse(0, n - 1); // [5,4,3,2,1]
Reverse(0, k - 1); // [4,5,3,2,1]
Reverse(k, n - 1); // [4,5,1,2,3]
}
# Rotate list to the right by k positions
# [1,2,3,4,5], k=2 -> [4,5,1,2,3]
def rotate(arr: list[int], k: int) -> None:
n = len(arr)
k %= n # In case k > n
def reverse(start: int, end: int) -> None:
while start < end:
arr[start], arr[end] = arr[end], arr[start]
start += 1
end -= 1
reverse(0, n - 1) # [5,4,3,2,1]
reverse(0, k - 1) # [4,5,3,2,1]
reverse(k, n - 1) # [4,5,1,2,3]
// Create 3x4 matrix
rows, cols := 3, 4
matrix := make([][]int, rows)
for i := 0; i < rows; i++ {
matrix[i] = make([]int, cols)
}
// Traverse matrix
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
fmt.Printf("%d ", matrix[i][j])
}
fmt.Println()
}
// Create 3x4 matrix
int rows = 3, cols = 4;
int[,] matrix = new int[rows, cols]; // Rectangular array — one contiguous block
// Traverse matrix
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
Console.Write($"{matrix[i, j]} ");
}
Console.WriteLine();
}
# Create 3x4 matrix
rows, cols = 3, 4
matrix = [[0] * cols for _ in range(rows)] # Each row is a separate list
# Traverse matrix
for row in matrix:
print(" ".join(str(value) for value in row))
```
Матрица 3x4:
col 0 col 1 col 2 col 3
row 0: [ 1, 2, 3, 4 ]
row 1: [ 5, 6, 7, 8 ]
row 2: [ 9, 10, 11, 12 ]
matrix[1][2] = 7 (строка 1, столбец 2)
> **Запомни:** Массив — это основа всего. Знание сложности операций критически важно: доступ по индексу O(1), поиск O(n), вставка/удаление в начале O(n). Для интервью — освой паттерны Two Pointers, Sliding Window и Prefix Sum (следующие главы).
## Итоги
1. Массив = непрерывная память, доступ по индексу O(1)
2. Динамические массивы растут автоматически, append амортизированно O(1)
3. Вставка/удаление не с конца — O(n) из-за сдвига элементов
4. Строки в PHP — изменяемые (mutable), но для Unicode используй mb_* функции
5. `array_slice()` в PHP создаёт копии
6. Для интервью: знай как делать reverse, remove duplicates, rotate in-place
Проверь себя
Какова сложность вставки элемента в начало массива (array_unshift) из n элементов?
Что произойдёт при доступе к символу Unicode-строки по индексу?
```php
$s = 'привет';
echo $s[0];
```
Как работает алгоритм поворота массива через три разворота?
```php
// [1,2,3,4,5], k=2
$reverse(0, $n-1); // Шаг 1
$reverse(0, $k-1); // Шаг 2
$reverse($k, $n-1); // Шаг 3
```
Что вернёт функция removeDuplicates для отсортированного массива [1, 1, 2, 2, 3, 3, 3]?