1. two sum حل المسئلة مع الشرح

يمكنك زيارة المسئلة في الموقع الرسمي leetcode من هنا

basmala qur an allah madhhab mosaic بسم الله الرحمن الرحيم a462a02761ac8f0dbeb078e54568370a

نص السؤال

إذا كانت المعطيات كالتالي:

  • مصفوفة ==> nums
  • رقم صحيح ==> target

المطلوب هو

  • اوجد ال index الخاص بالرقمين في المصفوفة اللذان مجموعهما = target.

ملحوظات

  • يوجد رقمين فقط مجموعهما ال target في المصفوفة
  • لا يمكنك استخدام نفس العنصر مرتين
  • لا يشترط الترتيب في الإجابة

مثال 1

  • المعطيات: nums = [2,7,11,15] ، target = 9 .
  • النتيجة: [0,1] .
  • لماذا: لأن nums[0] + nums[1] = 9

مثال 2

  • المعطيات: nums = [3,2,4] ، target = 6 .
  • النتيجة: [1,2] .

مثال 3

  • المعطيات: nums = [3,3] ، target = 6 .
  • النتيجة: [0,1] .

شرح الحل

image

إذا أردت أن تحل هذه المسئلة وأردت إيجاد رقمين في المصفوفة يكون مجموعهما 9 فإنك ستقوم بتجربة كل رقمين مع بعضهما حتى تصل إلى رقمين في المصفوفة يكون ناتج جمعهم = 9 .

أي بصورة أخرى ستقوم بإستخدام متغيرين سيكونون لنا بمثابة ال pointers ولنفترض أنهما left , right.

وليبدأ left من اليسار أى left = 0 .

ويبدأ right بعده مباشرة أى right = 1 .

image

والفكرة هنا أننا سنقوم أول شئ بالتحقق هل مجموع العنصرين في left وفي right يساوي ال target لاحظ أن ال left و ال right هما ال indexes للعناصر في المصفوفة أى أنك ستتحقق من المعادلة nums[left] + nums[right] == target أم لا فإذا كانا متساويين فإننا سنقوم بعمل return للمصفوفة الجديدة [left,right] وإلا فإننا سنقوم بزيادة المتغير right بمقدار 1 ونتحقق مجدداً حتى يصل right إلى نهاية المصفوفة.

image

عندما يصل right إلى نهاية المصفوفة سنقوم بتزويده بمقدار 1 وسيصبح right متساوياً مع عدد عناصر المصفوفة أى أن right = 4 فإننا هنا يجب أن نتحقق إذا كان right يساوي عدد عناصر المصفوفة يجب أن نبدأ في الدورة التالية وهي أن نقوم بتزويد المؤشر left بمدار 1 وجعل المؤشر right بعده مباشرة.

image

لاحظ هنا أننا لا نحتاج أن نقارن ال 11 مع ال 15 لأننا قمنا بعمل هذه المقارنة في الدورة السابقة. إذاً هنا نحن نلاحظ أن كل العناصر قبل ال left قد تم التحقق منها واستبعادها وبالتالي لا يوجد داعي للتحقق منها مجدداً.

ستظل هذه العملية جارية حتى نجد أن العنصر left أصبح بينه وبين اخر عنصر خطوة واحدة

image

إذا قمنا بتزويد المؤشر left فسيصبح ال left = 3 ولكن المؤشر right ستكون قيمته 4 وهذا خارج الحدود الخاصة بالمصفوفة . وقد قمنا مسبقاً بفحص العنصر الأخير مع العنصر قبل الأخير حيث كانت ال left = 2 وال right = 3 . ونفهم من ذلك أننا سنتوقف حينما تصل left إلى العنصر الأخير والعنصر الأخير يكون ال index الخاص به هو عدد عناصر المصفوفة ناقص 1 (nums.length – 1) فيجب أن تكون ال left أصغر من هذه القيمة لاحظ في الكود.

function twoSum(nums: number[], target: number): number[] {
    let left = 0;
    let right = 1;
    while(left < nums.length - 1){
        if(nums[left] + nums[right] === target){
            return [left,right]
        }
        right++
        if(right == nums.length){
            left++
            right = left + 1
        }
    }
    return [-1,-1]
};

وأخيراً إذا لم تستطع الدالة أن تجد الحل ستعود ب [-1,-1] ولكن في هذه المسئلة دائماً يوجد جل.

Time Complexity

O(n2)O(n^2)

حل آخر

في الحل السابق كانت ال time complexity ليست أفضل شئ هنالك حل أفضل من حيث الوقت ولكن على حساب المساحة.

في هذه الطريقة نقوم باستخدام hash-map لتخزين العناصر وال index الخاص بها كالتالي.

سيكون ال key هو الرقم في المصفوفة وال value هو ال index الخاص به.

سنقوم بعمل loop واحدة في كل دورة يجب أن نخزن كل عنصر في ال map .

image

ثم نبحث في كل دورة في الmap عن عنصر إذا جمعناه مع العنصر الحالي يكون الناتج هو ال target وبالتالي تكون النتيجة [i , index of found number].

ملحوظة يجب أن نتحقق أولاً من وجود العنصر قبل إضافة العنصر الجديد لل map حتى لا نقوم بمقارنة العنصر مع نفسه.

ولكن كيف نتحقق فكر هنا معي على سبيل المثال نأخذ الأرقام في المثال السابق ونتتبع المسئلة:

لقد أضفت الرقم 11 إلى ال map وعلى وشك أن أضيف الرقم التالي وهو 15 فإنني قبل إضافته أتحقق هل 15 + رقم موجود مسبقاً يعطيني 9 (ال target): لا ، إذاً نقوم بإضافة ال 15 إلى ال map .

image

ثم في الدورة التالي نحن على وشك إضافة الرقم 2 فنتحقق هل يوجد رقم نضيفه ل 2 ليصبح الناتج 9 والإجابة هي الرقم 7 فنتحقق هل الرقم 7 موجود مسبقاً في ال map إذا مع كل رقم نحن نتحقق من وجود target – num[i] أو باختصار نتحقق من وجود الهدف – الرقم وإذا كان هذا الرقم موجود فقد وجدنا الحل وفي هذه المسئلة فإنها يوجد حل دائماً . نُكمل بإضافة الرقم 2 .

image

ثم نحن على وشك إضافة الرقم التالي وهو الرقم 7 فنتحقق هل يوجد الرقم (9 – 7) أى 2 في ال map مسبقاً والإجابة هي نعم يوجد فيكون الحل هو ال index الحالي وهو 3 وقيمة الرقم 2 في ال map وهو 2

أو بتعبير آخر [ i , map[ target – map[ i ] ] ]

function twoSum(nums: number[], target: number): number[] {
    let map: Record<number, number> = {};
    for (let i = 0; i < nums.length; i++) {
        if (map.hasOwnProperty(target - nums[i])) {
            return [i, map[target - nums[i]]]
        }
        map[nums[i]] = i;
    }

    return [-1, -1]
};

Time Complexity

O(n)O(n)

Space Complexity

O(n)O(n)
picmix.com 3618251

اترك ردّاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *