LeetCode पर Swift: कहां से शुरू करें और कैसे न छोड़ें
\n\nहर iOS डेवलपर को देर-सबेर एक दीवार का सामना करना पड़ता है: आप प्रोजेक्ट बनाते हैं, AppStore पर ऐप्स भेजते हैं, लेकिन साक्षात्कार में बाइनरी ट्री के बारे में एक समस्या दी जाती है, और आप अटक जाते हैं। परिचित लगता है? LeetCode वह ट्रेनर है जो "मैं सिर्फ UI लिखता हूं" को "मैं एल्गोरिदम से सोचता हूं" में बदल देता है। लेकिन एक बात है: इंटरनेट पर अधिकांश समाधान Python या Java में लिखे गए हैं, जबकि Swift अपने दर्शन वाली भाषा है। इस लेख में, हम चर्चा करेंगे कि Swift पर LeetCode की समस्याओं को प्रभावी ढंग से कैसे हल किया जाए, कौन सी डेटा संरचनाओं का उपयोग करें और समय बर्बाद न करने के लिए किन बातों पर ध्यान दें।
\n\nयह लेख उन लोगों के लिए है जो पहले से ही Swift की मूल बातें जानते हैं, लेकिन एल्गोरिदमिक सोच में सुधार करना चाहते हैं। हम सिंटैक्स नहीं सिखाएंगे - हम सोचना सीखेंगे।
\n\nSwift LeetCode के लिए एक बेहतरीन विकल्प क्यों है
\n\nबहुत से लोग सोचते हैं कि Swift केवल UIKit और SwiftUI है, लेकिन वास्तव में भाषा में एल्गोरिदमिक समस्याओं के लिए शक्तिशाली क्षमताएं हैं:
\n\n- \n
- वैकल्पिक प्रकार (Optionals) — अप्रत्याशित क्रैश के बिना nil के साथ सुरक्षित कार्य। \n
- मूल्य प्रकार (Value types) (स्ट्रक्चर) — पूर्वानुमानित कॉपी, संदर्भों से कोई आश्चर्य नहीं। \n
- आलसी गणना (Lazy evaluation) और कार्यात्मक दृष्टिकोण (Functional approaches) — map, filter, reduce कोड को बहुत सरल बनाते हैं। \n
- गति (Speed) — Swift नेटिव कोड में कंपाइल होता है, अक्सर Python से 2-3 गुना तेज। \n
हालांकि, कुछ नुकसान भी हैं: उदाहरण के लिए, Swift में ऐरे स्ट्रक्चर हैं, और एक बड़े ऐरे की कॉपी महंगी हो सकती है। लेकिन इस पर हम अलग से चर्चा करेंगे।
\n\nडेटा संरचनाएं: LeetCode पर Swift के लिए क्या जानना आवश्यक है
\n\nसमस्याओं को हल करने में कूदने से पहले, सुनिश्चित करें कि आप बुनियादी संरचनाओं के साथ आत्मविश्वास से काम करते हैं। Swift के लिए must-know की सूची यहां दी गई है:
\n\nऐरे और स्लाइस (Array, ArraySlice)
\nSwift में ऐरे केवल सूचियां नहीं हैं, बल्कि इंडेक्स द्वारा O(1) एक्सेस के साथ शक्तिशाली संरचनाएं हैं। लेकिन सावधान रहें: शुरुआत में इन्सर्ट/डिलीट O(n) है। उप-ऐरे के साथ काम करते समय डेटा कॉपी न करने के लिए ArraySlice का उपयोग करें।
let numbers = [1, 2, 3, 4, 5]\nlet slice = numbers[1..<4] // ArraySlice, बिना कॉपी किए\nprint(slice) // [2, 3, 4]\n\nशब्दकोश और सेट (Dictionary, Set)
\nआवृत्ति गणना, डुप्लिकेट खोजने या दो-पास एल्गोरिदम के लिए - ये आपके सबसे अच्छे दोस्त हैं। याद रखें: Dictionary एक हैश टेबल है, औसतन O(1), लेकिन खराब हैश फ़ंक्शन के साथ O(n) तक गिर सकता है।
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {\n var dict = [Int: Int]()\n for (i, num) in nums.enumerated() {\n if let j = dict[target - num] {\n return [j, i]\n }\n dict[num] = i\n }\n return []\n}\n\nस्टैक और क्यू (Stack, Queue)
\nSwift में स्टैक और क्यू की अंतर्निहित संरचनाएं नहीं हैं, लेकिन उन्हें ऐरे के साथ आसानी से अनुकरण किया जा सकता है। स्टैक के लिए — append और popLast। क्यू के लिए, dequeue पर O(n) से बचने के लिए ArraySlice या डबल-लिंक्ड लिस्ट का उपयोग करें।
struct Stack<T> {\n private var array = [T]()\n mutating func push(_ element: T) { array.append(element) }\n mutating func pop() -> T? { array.popLast() }\n var isEmpty: Bool { array.isEmpty }\n}\n\nलिंक्ड लिस्ट (Linked List)
\nLeetCode को सिंगल-लिंक्ड लिस्ट पर समस्याएं पसंद हैं। Swift में कोई अंतर्निहित कार्यान्वयन नहीं है, लेकिन आप एक क्लास परिभाषित कर सकते हैं:
\n\nclass ListNode {\n var val: Int\n var next: ListNode?\n init(_ val: Int) { self.val = val; self.next = nil }\n}\n\nयह लिस्ट को रिवर्स करने, चक्र का पता लगाने या नोड को हटाने की समस्याओं के लिए क्लासिक है।
\n\nSwift समस्याओं के लिए एल्गोरिदमिक पैटर्न
\n\nहर बार पहिया का पुन: आविष्कार न करने के लिए, कुछ पैटर्न याद रखें जो LeetCode की 80% समस्याओं को कवर करते हैं।
\n\nदो पॉइंटर्स (Two Pointers)
\nइ