静的配列 (Static Arrays)
2025-08-17
静的配列の学習ノート
JavaやC++を勉強してて初めて知った「静的配列」。最初はPythonに慣れてたから「なんで最初にサイズ決めなきゃいけないの?」って思った。
静的配列とは
静的型付け言語(Java、C++、C#など)では、配列を作る時にサイズと型を決める必要がある。一度決めたら変更できない。
# Pythonで静的配列をシミュレート
class StaticArray:
def __init__(self, capacity):
self.data = [0] * capacity # 固定サイズ
self.capacity = capacity
self.length = 0 # 実際に使ってる要素数
基本操作と時間計算量
1. 読み込み(アクセス) - O(1)
def get(self, index):
if 0 <= index < self.length:
return self.data[index]
raise IndexError("インデックスが範囲外")
# 使用例
myArray = StaticArray(5)
myArray.data = [1, 3, 5, 0, 0] # 最初の3つだけ使用
myArray.length = 3
print(myArray.get(1)) # 3を返す(一瞬でアクセス!)
なぜO(1)なのか理解した瞬間:
- メモリアドレスが
先頭 + (index × 要素サイズ)
で計算できる - 配列のサイズが100でも100万でも、アクセス時間は同じ!
2. 配列の走査 - O(n)
def traverse(self):
for i in range(self.length):
print(self.data[i])
# または
i = 0
while i < self.length:
print(self.data[i])
i += 1
重要な発見:配列の最後の要素は常に n-1
番目(nは配列サイズ)
3. 末尾から削除 - O(1)
def remove_end(self):
if self.length > 0:
# ソフトデリート:値を0にして長さを減らすだけ
self.data[self.length - 1] = 0
self.length -= 1
return True
return False
# 例:[4, 5, 6] → [4, 5, 0](lengthは2になる)
4. 任意の位置から削除 - O(n)
これが最初めっちゃ苦労した操作:
def remove_middle(self, index):
if index < 0 or index >= self.length:
return False
# index+1から最後まで、全部1つ左にシフト
for i in range(index + 1, self.length):
self.data[i - 1] = self.data[i]
# 最後の要素をクリア
self.data[self.length - 1] = 0
self.length -= 1
return True
# 例:[1, 2, 3, 4] でindex=1を削除
# → [1, 3, 4, 0](2が消えて、後ろが詰まる)
最悪のケース:最初の要素を削除 → 全要素をシフトする必要がある
5. 末尾に挿入 - O(1)
def insert_end(self, value):
if self.length < self.capacity:
self.data[self.length] = value
self.length += 1
return True
return False # 配列が満杯
# 例:[1, 2, 0, 0] に3を追加 → [1, 2, 3, 0]
6. 任意の位置に挿入 - O(n)
これも結構複雑だった:
def insert_middle(self, index, value):
if index < 0 or index > self.length:
return False
if self.length >= self.capacity:
return False # 配列が満杯
# 後ろから順番に右にシフト(重要:後ろから!)
for i in range(self.length - 1, index - 1, -1):
self.data[i + 1] = self.data[i]
# indexの位置に挿入
self.data[index] = value
self.length += 1
return True
# 例:[4, 5, 6, 0] のindex=1に8を挿入
# → [4, 8, 5, 6]
完全な静的配列クラス(練習用)
class StaticArray:
def __init__(self, capacity):
self.data = [0] * capacity
self.capacity = capacity
self.length = 0
def get(self, index):
if 0 <= index < self.length:
return self.data[index]
raise IndexError(f"Index {index} out of bounds")
def set(self, index, value):
if 0 <= index < self.length:
self.data[index] = value
return True
return False
def insert_end(self, value):
if self.length < self.capacity:
self.data[self.length] = value
self.length += 1
return True
return False
def remove_end(self):
if self.length > 0:
self.data[self.length - 1] = 0
self.length -= 1
return True
return False
def insert_middle(self, index, value):
if index < 0 or index > self.length or self.length >= self.capacity:
return False
for i in range(self.length - 1, index - 1, -1):
self.data[i + 1] = self.data[i]
self.data[index] = value
self.length += 1
return True
def remove_middle(self, index):
if index < 0 or index >= self.length:
return False
for i in range(index + 1, self.length):
self.data[i - 1] = self.data[i]
self.data[self.length - 1] = 0
self.length -= 1
return True
def print_array(self):
print(f"配列: {self.data[:self.length]}")
print(f"全体: {self.data}")
print(f"長さ: {self.length}/{self.capacity}")
時間計算量まとめ
操作 | 時間計算量 | 備考 |
---|---|---|
読み込み | O(1) | インデックスアクセス最強 |
挿入(末尾) | O(1) | 空きがあれば一瞬 |
挿入(中間) | O(n) | シフトが必要 |
削除(末尾) | O(1) | 簡単 |
削除(中間) | O(n) | シフトが必要 |
学んだこと・ハマったポイント
lengthとcapacityの違いを最初理解してなかった
- capacity: 配列の最大サイズ
- length: 実際に使ってる要素数
シフト操作の向きでよく間違えた
- 挿入時:後ろから前にシフト
- 削除時:前から後ろにシフト
境界チェックを忘れがち
- 必ずindexの範囲チェックをする
- 配列が満杯かチェックする
なぜ静的配列を使うのか
- メモリ使用量が予測可能
- 動的配列より若干高速(リサイズがない)
- 組み込みシステムでは必須
実際の面接問題での使い方
# Two Sum問題で静的配列を使う
def two_sum(nums, target):
# ハッシュテーブルの代わりに配列を使う(値の範囲が限定的な場合)
seen = [False] * 10001 # 値の範囲が0-10000と仮定
for num in nums:
complement = target - num
if 0 <= complement <= 10000 and seen[complement]:
return True
if 0 <= num <= 10000:
seen[num] = True
return False
まとめ
- 静的配列はサイズ固定だけど、それが逆に利点になることもある
- **中間への挿入・削除がO(n)**なのが弱点
- でも**インデックスアクセスがO(1)**なのは最強
- 動的配列の基礎になってるから、これを理解すると動的配列もわかりやすい
次は動的配列がどうやってサイズを変えるか見ていく
Tags:
配列
静的配列