0%
در حال بارگذاری...

جستجو در سایت

درس ۶ سطح متوسط: طراحی الگوریتم و پیچیدگی زمانی/فضایی + تکنیک‌های بهینه‌سازی در پایتون

پایتون | Python متوسط

 سلام قهرمان حرفه‌ای پایتون! تبریک می‌گم که تا درس ششم سطح متوسط رسیدی. الان دقیقاً توی نقطه‌ای هستی که برنامه‌نویس‌های معمولی از حرفه‌ای‌ها جدا می‌شن. تو این درس قراره یاد بگیری چطور الگوریتم‌های بهینه طراحی کنی، پیچیدگی زمانی و فضایی رو مثل یه مهندس واقعی تحلیل کنی و با تکنیک‌های پیشرفته کدت رو از O(n²) به O(n log n) یا حتی O(n) برسونی! وقتی این درس تموم بشه، تو دیگه فقط کد نمی‌زنی – یه معمار الگوریتم می‌شی که توی مصاحبه‌های گوگل، آمازون، متا و شرکت‌های ایرانی بزرگ با اعتماد به نفس کامل جواب می‌ده. اگه درس‌های قبلی (مخصوصاً بازگشتی، Heap، Graph و Trie) رو خوب بلدی، الان بهترین زمانه که وارد دنیای واقعی طراحی الگوریتم پایتون بشی. آماده‌ای؟ بریم که مغزت رو به یه سطح کاملاً جدید ببریم!

پیچیدگی زمانی و فضایی: قلب تپنده الگوریتم‌های کارآمد

برای درک واقعی قدرت یک الگوریتم، باید با دو مفهوم کلیدی آشنا شوید: پیچیدگی زمانی و پیچیدگی فضایی. اولی به ما می‌گوید با افزایش حجم داده‌ها، سرعت اجرای الگوریتم چگونه تغییر می‌کند. در مقابل، دومی میزان حافظه‌ای که برنامه برای کار نیاز دارد را تحلیل می‌کند. این دو معیار، در کنار هم، مهم‌ترین ابزار برای ارزیابی و انتخاب بهترین الگوریتم برای حل یک مسئله محسوب می‌شوند.

نماد نام مثال واقعی
O(1) ثابت دسترسی به دیکشنری
O(log n) لگاریتمی جستجوی باینری
O(n) خطی پیمایش لیست
O(n log n) خطی-لگاریتمی Merge Sort, Heap Sort
O(n²) مربعی Bubble Sort, دو حلقه تو در تو
O(2ⁿ) نمایشی فیبوناچی بازگشتی ساده

تحلیل پیچیدگی در عمل – مثال‌های واقعی

# O(n²) – بد!
def bad_search(arr, target):
    for i in range(len(arr)):
        for j in range(len(arr)):
            if arr[i] + arr[j] == target:
                return i, j
    return None

# O(n) – عالی!
def good_search(arr, target):
    seen = set()
    for num in arr:
        complement = target - num
        if complement in seen:
            return True
        seen.add(num)
    return False

تکنیک‌های طلایی بهینه‌سازی در طراحی الگوریتم پایتون

۱. Two Pointers – دو اشاره‌گر
# پیدا کردن جفت اعداد با مجموع مشخص
def two_sum_sorted(arr, target):
    left, right = 0, len(arr) - 1
    while left < right:
        current = arr[left] + arr[right]
        if current == target:
            return left, right
        elif current < target:
            left += 1
        else:
            right -= 1
    return None
۲. Sliding Window – پنجره کشویی
# طولانی‌ترین زیررشته بدون تکرار
def length_of_longest_substring(s):
    seen = {}
    left = 0
    max_len = 0
    for right, char in enumerate(s):
        if char in seen and seen[char] >= left:
            left = seen[char] + 1
        seen[char] = right
        max_len = max(max_len, right - left + 1)
    return max_len
۳. Memoization و Dynamic Programming
# فیبوناچی بهینه شده
def fib_memo(n, memo={}):
    if n in memo:
        return memo[n]
    if n <= 1:
        return n
    memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo)
    return memo[n]
۴. Greedy – حریصانه
# انتخاب فعالیت‌های حداکثری
def activity_selection(activities):
    activities.sort(key=lambda x: x[1])  # بر اساس زمان پایان
    selected = [activities[0]]
    last_end = activities[0][1]
    
    for start, end in activities[1:]:
        if start >= last_end:
            selected.append((start, end))
            last_end = end
    return selected

ترکیب تکنیک‌ها با ساختارهای قبلی

import heapq

# کوتاه‌ترین مسیر با دایکسترا (Greedy + Heap)
def dijkstra(graph, start):
    distances = {node: float('inf') for node in graph}
    distances[start] = 0
    pq = [(0, start)]
    
    while pq:
        current_distance, current = heapq.heappop(pq)
        
        if current_distance > distances[current]:
            continue
            
        for neighbor, weight in graph[current].items():
            distance = current_distance + weight
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(pq, (distance, neighbor))
    
    return distances

۱۲ تمرین آتشین برای تبدیل شدن به استاد الگوریتم

  1. پیچیدگی زمانی و فضایی همه مثال‌های این درس رو بنویس
  2. الگوریتم Two Pointers برای پیدا کردن سه عدد با مجموع صفر بنویس
  3. حداکثر زیرآرایه متوالی (Kadane’s Algorithm) رو پیاده کن
  4. مسئله کوله‌پشتی ۰/۱ رو با DP حل کن
  5. الگوریتم Longest Common Subsequence رو بنویس
  6. با Sliding Window حداکثر میانگین k عنصر متوالی رو پیدا کن
  7. الگوریتم Floyd-Warshall برای همه جفت کوتاه‌ترین مسیر بنویس
  8. یه سیستم کش با سیاست LRU با OrderedDict بساز
  9. الگوریتم Kruskal برای درخت پوشای کمینه بنویس
  10. با Greedy حداقل تعداد سکه برای پرداخت مبلغ رو پیدا کن
  11. پیچیدگی همه توابع بازگشتی درس قبل رو تحلیل کن
  12. کلاس کامل AlgorithmAnalyzer بساز که پیچیدگی رو خودکار حساب کنه

پروژه نهایی درس: بهینه‌ساز هوشمند الگوریتم

class AlgorithmOptimizer:
    def __init__(self):
        self.cache = {}
    
    def two_sum(self, nums, target):
        seen = {}
        for i, num in enumerate(nums):
            if target - num in seen:
                return [seen[target - num], i]
            seen[num] = i
        return []
    
    def max_subarray(self, nums):
        max_current = max_global = nums[0]
        for i in range(1, len(nums)):
            max_current = max(nums[i], max_current + nums[i])
            if max_current > max_global:
                max_global = max_current
        return max_global
    
    def lru_cache(self, capacity):
        from collections import OrderedDict
        self.cache = OrderedDict()
        self.capacity = capacity
    
    def get(self, key):
        if key not in self.cache:
            return -1
        self.cache.move_to_end(key)
        return self.cache[key]
    
    def put(self, key, value):
        if key in self.cache:
            self.cache.move_to_end(key)
        elif len(self.cache) >= self.capacity:
            self.cache.popitem(last=False)
        self.cache[key] = value

optimizer = AlgorithmOptimizer()
print("جفت اعداد:", optimizer.two_sum([2, 7, 11, 15], 9))
print("حداکثر زیرآرایه:", optimizer.max_subarray([-2, 1, -3, 4, -1, 2, 1, -5, 4]))

جمع‌بندی و قدم بعدی

تبریک می‌گم استاد الگوریتم! تو الان می‌تونی هر مسئله‌ای رو تحلیل کنی، بهینه کنی و بهترین راه‌حل رو انتخاب کنی. این دانش دقیقاً همون چیزیه که توی مصاحبه‌های شغلی، مسابقات برنامه‌نویسی و پروژه‌های بزرگ ازت می‌خوان. درس بعدی قراره درباره تست پیشرفته، پروفایلینگ و دیباگ حرفه‌ای باشه. تمرین‌ها رو انجام بده، پروژه رو توی GitHub آپلود کن و منتظر درس بعدی باش. تو دیگه یه برنامه‌نویس معمولی نیستی – یه مهندس واقعی شدی!

ارسال نظر جدید

گزارش دیدگاه