ამოცანები რომლებიც იხსნება
ჰეშ ცხრილების (Hash Table)
საშუალებით.
მარიამ გობრონიძე
• Contains Duplicate,
• Majority Element,
• Two Sum,
• LRU Cache
განრიგი
Contains Duplicate
პრობლემა :
მოცემულია სია nums, უნდა დავადგინოთ, შეიცავს თუ არა ის “დუბლიკატ” ელემენტს. თუ სია
შეიცავს ერთსა და იმავე მნიშვნელობას მინიმუმ ორჯერ, უნდა დავაბრუნოთ True, წინააღმდეგ
შემთხვევაში False.
გამოყენების შემთხვევები :
● მონაცემთა დამუშავება, სადაც უნიკალურობა მნიშვნელოვანია.
● სიის ელემენტების სისწორის შემოწმება.
● მონაცემთა დუბლიკაციის თავიდან არიდება
იდეა
● შევქმნათ ცარიელი ჰეშსეტი (set).
● თითოეული ელემენტი დავამატოთ ჰეშსეტში და შევამოწმოთ, უკვე არის თუ არა ის მასში.
● თუ რომელიმე ელემენტი უკვე არის ჰეშსეტში , მაშინ სიაში დუბლიკატი არსებობს და
ვაბრუნებთ True-ს.
● თუ ყველა ელემენტი უნიკალურია, ვაბრუნებთ False-ს.
სირთულის შეფასება
დროითი სირთულე (Time Complexity):
● O(n), სადაც n არის სიის სიგრძე.
● უარეს შემთხვევაში, შეიძლება დაგვჭირდეს მთელი სიის გავლა.
მეხსიერებითი სირთულე (Space Complexity):
● O(n), რადგან შესაძლოა, ყველა ელემენტი უნიკალური იყოს და დაგვჭირდეს მათი
შენახვა ჰეშსეტში
ჰეშსეტის გამოყენებით ეფექტურად ვპოულობთ განმეორებით მნიშვნელობებს .
ალტერნატიული მეთოდები :
1. Sorting + O(n log n) Complexity – სიის დალაგება და ელემენტების
თანმიმდევრული შედარება.
2. Brute Force O(n^2) Complexity – ყველა ელემენტის შედარება ერთმანეთთან
(არაეფექტური).
ჰეშსეტის გამოყენება საუკეთესო გამოსავალია O(n) სირთულით !
ამოცანა
მოცემულია სია arr. უნდა ვიპოვოთ სიაში არსებული “Majority element”. თუ ასეთი არ
არსებობს, უნდა დავაბრუნოთ -1. “Majority element” არის ის ელემენტი, რომელიც
სიაში გვხვდება arr.size() / 2-ზე მეტჯერ.
Majority Element,
მაგალითი
1. arr[] = {1, 1, 2, 1, 3, 5, 1}
ამ სიისთვის majority element არის 1( ოთხჯერ გვხვდება, რაც მეტია 7 / 2-ზე).
2. arr[] = {3, 3, 4, 2, 4, 4, 2, 4}
დაიბეჭდება — -1
არ არსებობს ელემენტი, რომელიც სიაში n/2-ზე მეტჯერ გვხვდება.
იდეა
იდეა მდგომარეობს იმაში, რომ ჰეშ ცხრილის გამოყენებით დავითვალოთ თითოეული
ელემენტის რაოდენობა.
1. გავიაროთ სია და თითოეული ელემენტის რაოდენობა დავამატოთ ჰეშ ცხრილში.
2. განახლების შემდეგ შევამოწმოთ, აჭარბებს თუ არა რომელიმე ელემენტის რაოდენობა
n / 2-ს.
3. თუ ასეთი ელემენტი ვიპოვეთ, დაუყოვნებლივ დავაბრუნოთ ის.
4. თუ არცერთი ელემენტი არ აკმაყოფილებს ამ პირობას, დავაბრუნოთ -1.
დროითი სირთულე (Time Complexity): O(n)
მეხსიერებითი სირთულე (Space Complexity): O(n)
სირთულის შეფასება
● ნაივური მიდგომა : მარტივია, მაგრამ არაეფექტური (O(n²)).
● დალაგების მეთოდი : შედარებით უკეთესია (O(n log n)).
● ჰეშინგი : ეფექტურია (O(n)), მაგრამ იყენებს დამატებით მეხსიერებას.
● Moore’s Voting Algorithm: ყველაზე ოპტიმალურია (O(n) დრო და O(1)
მეხსიერება).
ალტერნატიული ამოხსნები
Two Sum
მოცემულია მთელი რიცხვების სია nums და სამიზნე რიცხვი target. უნდა
ვიპოვოთ ორი ისეთი ინდექსი i და j, სადაც nums[i] + nums[j] == target.
შეზღუდვები
● თითოეულ შეყვანილ მონაცემში მხოლოდ ერთი სწორი წყვილი
არსებობს.
● ერთსა და იმავე ელემენტს ორჯერ ვერ გამოვიყენებთ.
მაგალითი
— nums = [2, 7, 11, 15], target = 9
— [0, 1] ( რადგან nums[0] + nums[1] = 2 + 7 = 9)
დროითი სირთულე (Time Complexity): O(n)
მეხსიერებითი სირთულე (Space Complexity): O(n)
სირთულის შეფასება
ალტერნატიული ამოხსნები
● ნაივური მიდგომა (O(n²)) მარტივია, მაგრამ არაეფექტური დიდ მონაცემებზე.
● დალაგება და ორი მაჩვენებლის მეთოდი (O(n log n)) უფრო ოპტიმალურია, მაგრამ
საჭიროებს დალაგებას.
● ჰეშ ცხრილი (O(n)) ყველაზე ეფექტურია და ოპტიმალური მეხსიერების გამოყენებას
უზრუნველყოფს.
LRU Cache
● Cache ჩანაცვლების ალგორითმები გამოიყენება მეხსიერების
ოპტიმიზაციისთვის.
● LRU (Least Recently Used) არჩევს და შლის იმ მონაცემს, რომელიც
ყველაზე ნაკლებად გამოიყენებოდა.
● პრიორიტეტი იცვლება: ხშირად გამოყენებული მონაცემი მაღალი
პრიორიტეტისაა.
LRU Cache-ის ოპერაციები
LRUCache: ქმნის LRU cache-ს მოცემული ტევადობით.
get(key): აბრუნებს შესაბამის მნიშვნელობას ან -1-ს, თუ არ მოიძებნა.
put(key, value): ამატებს ახალ მონაცემს და საჭიროების შემთხვევაში შლის ყველაზე
ნაკლებად გამოყენებულს.
მუშაობის მექანიზმი
მაგალითი (ტევადობა = 3):
1. put(1, A), put(2, B), put(3, C) – მონაცემთა დამატება.
2. get(2) – პრიორიტეტი იცვლება, ახლა {2:B} უმაღლესია.
3. get(4) – მონაცემი არ არსებობს (აბრუნებს -1-ს).
4. put(4, D) – წაიშლება {1:A}, რადგან ის ყველაზე ნაკლებად იქნა
გამოყენებული.
5. put(3, E) – {3:C} განახლდება {3:E}-ით.
6. put(1, A) – წაიშლება {2:B}, რადგან ის ყველაზე ნაკლებად გამოყენებულია
ტრადიციული მიდგომა (Array, Hashing, Heap)
● Array: ძებნა O(n) დროში, ოპერაციები ნელია.
● Hashing: ელემენტებზე წვდომა O(1) დროში, მაგრამ პრიორიტეტის ცვლილება
რთულია.
● Heap + Hashing: მინიმალურის პოვნა O(log n)-ში.
LRU Cache-ის რეალიზაცია
ეფექტური გადაწყვეტა – Doubly Linked List
+ Hash Map
Hash Map: სწრაფი წვდომა გასაღებებით.
Doubly Linked List: მონაცემთა მოძრაობა O(1) დროში.
პრინციპი :
● ახალი მონაცემი ემატება თავში .
● არსებული მონაცემის განახლება – მისი წაშლა და თავიდან დამატება.
● LRU წაშლა – ბოლო ელემენტის წაშლა.
LRU Cache-ის უპირატესობები და
ნაკლოვანებები
უპირატესობები
✅ მონაცემთა სწრაფი წვდომა (O(1))
✅ ეფექტური ჩანაცვლების მექანიზმი
✅ ოპერაციული სისტემებში გვერდების მენეჯმენტისთვის იდეალურია
ნაკლოვანებები
❌ საჭიროებს მეტ მეხსიერებას
❌ რთული დასაყენებელია
რეალური გამოყენება
● ოპერაციული სისტემები – გვერდების ოპტიმალური ჩატვირთვა.
● მონაცემთა ბაზები – სწრაფი მოთხოვნების შესრულება.
● ქსელური მოწყობილობები – მარშრუტიზატორებში კავშირის ოპტიმიზაცია.
● ტექსტური რედაქტორები – ხშირად გამოყენებული ფაილების შენახვა.
● ტექსტის პროგნოზირება – ავტოკომპლიტისა და AI-ს სისტემებში.
პრაქტიკული განხორციელება
სია წარმოადგენს ორმხრივ ბმულ სიას.
გმადლობთ ყურადღებისთვის!
