Algoritma Challanges | #1

kondanta

Katılımcı Üye
29 Tem 2017
910
0
CNCF

Merhabalar, şu aralar leetcode, hackerrank gibi sitelerdeki challengeları çözmeye adadım kendimi. Daha sonrasında, bunu neden forumda bir chain haline getirmeyeyim ki diye. Öncelikli olarak not düşeyim; Problemlerde aksi iddia edilmediği sürece time complexity üzerine odaklı çözüm yapmaya çalışacağım.

Gelelim problemimize. Çözmeye çalıştığım problem diyor ki: "Elimizde bir array olduğunu varsayalım. İçerisinde random rakamlar bulunmakta. Bu array ile birlikte size bir de hedef rakam vereceğiz. Amacınız, arraydaki elemanları kullanarak toplamları verilen hedef sonuca ulaşan 2 değeri return etmek. Kısıtılama olarak, her rakam sadece bir kez kullanılacaktır ve sadece 2 indis return edeceksiniz diye iki ibare mevcut. İndisden kasıt ise, rakamın array içerisinde bulunduğu yer. Soru ne kadar kolay görünse de en sondaki ulaştığım sonuca kadar toplam 37 dakika 44 saniye harcamışım.

Çözüm
Çözüm için ilk yaklaşımım tabii ki de brute force oldu. Yani ilk önce çalışan bir algoritma oluşturmam gerekliydi. Dil olarak C++ kullandım, bilginize.
Not: Tavsiyem, önce kendiniz uğraşın birazcık. Daha sonrasında buradan çözüme bakarsınız.
İlk aklıma gelen çözüm yöntemleri tabii ki başarısızlık ile sonuçlandı. Akabinde ise aklıma gelen ve ilk çalışan algoritmam şu şekildeydi:
Kod:
vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> res;
        for(int i = 0; i < nums.size(); i++){
            for(int j = i+1; j < nums.size(); j++){
                if(nums[j] == target - nums[i]){
                    res.push_back(i);
                    res.push_back(j);
                    return res;
                }
                    
            }
        }
        return nums;
    }
Burada ne yaptığımdan kısaca bahsedecek olursam, array içerisindeki ilk indis için i değişkenini, bir sonraki indis için ise j değişkenini kullandım. Bu şekilde "target" değere ulaşana kadar arrayin içerisindeki tüm elemanları bir kez ziyaret etmiş oldum. Bu da bana run time olarak O(N^2)'e patlıyor. Bilmiyor iseniz, Big O notasyonu nedir diye araştırınız.

NbA7JQ.png

Şimdi gelelim çözümün geri kalan optimizasyon kısmınaa. Evet elimizde bir çözüm var, lakin pek de optimal değil yukarıdaki resimde gördüğünüz gibi. Şimdi burada ki asıl trick ise, böyle bir algoritmayı nasıl optimize edebiliriz sorusu. Şöyle biraz düşündükten sonra aklıma hashmap geldi. Tabii ki veri yapılarına ne kadar aşina iseniz o kadar kardasınız burada. Şuraya şöyle de küçük bir bilgi düşeyim.

Kod:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::unordered_map<int, int> m;
        vector<int> res;
        for(int i = 0; i < nums.size(); i++){
            int result = target - nums[i];
            if(m.count(result)) {
                res.push_back(m[result]);
                res.push_back(i);
                return res;
            }
            m.insert (std::pair<int, int>(nums[i], i));
        }
        return nums;
    }


yc299z.png

Yeni çözümümüz ise O(1) de çalışmakta yani performans bazında çok yüksek bir artış söz konusu. Lakin bu artış tabii ki bedavaya gelmiş bir şey değil, memoryde kullandığımız alan da bir artış söz konusu. Buradaki olay ise, elimizdeki hashmap'i doldururken her seferinde toplamı bize verecek olan rakamın hashmap girdisi olup olmadığını kontrol etmek. Ve yukarıdaki diagramında gösterdiği gibi, unordered_list üzerinde yaptığımız arama işlemleri constant, yani sabit zaman almakta.


xMBNb8.png

Performans ölçütü olarak, şu resmi gösterebilirim. Elimizdeki arraylerin içerisinde maximum 10-15 eleman olduğunu varsayarak düşünebilirsiniz. Bu eleman sayısının milyonlarca olduğunu hayal ettiğinizde aradaki farkı hayal bile etmek istemezsiniz diye düşünüyorum.

52TTcL.png

Umarım bir şekilde faydalı olmuştur, forumda bu tarz paylaşımları arttırmayı hedefliyorum. Bir sonraki problem ve çözümüyle görüşmek dileğiyle :)

 

LEOHUNTERA

Üye
31 Ara 2018
79
3
Öncelikle elinize sağlık, Hashmap kullandığınız algoritmanın O(1) seviyesinde çalıştığını söylemişsiniz ama O(n) seviyesinde çalışmıyor mu?
 

LEOHUNTERA

Üye
31 Ara 2018
79
3
Hashmap in neden O(1) de çalıştığını biliyorum ama sonuçta hashmap li çözüm içinde her bir elemanın gezilmesi gerekiyor mu, yani tasarladığınız algoritma genel olarak O(n) mertebesinde mi çalışıyor (Sadece hashmap kısmını söylemiyorum, genel olarak algoritmanın çalışma zamanını soruyorum)
 

kondanta

Katılımcı Üye
29 Tem 2017
910
0
CNCF
Hashmap in neden O(1) de çalıştığını biliyorum ama sonuçta hashmap li çözüm içinde her bir elemanın gezilmesi gerekiyor mu, yani tasarladığınız algoritma genel olarak O(n) mertebesinde mi çalışıyor (Sadece hashmap kısmını söylemiyorum, genel olarak algoritmanın çalışma zamanını soruyorum)

Worst case senaryoda evet N elemani gezmek zorunda. Ama secilen hash fonskiyonuna gore Average case de near constant calismakta. Yani burada mevzu senaryonun ne oldugu biraz da.
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.