مهمة اختبار ياندكس

مهمة


اكتب دالة من صفيف إدخال تعسفي ستحدد جميع مجموعات الأرقام التي يبلغ مجموعها 10.

للوهلة الأولى ، المهمة بسيطة ، كل ما عليك فعله هو كتابة تكرارات وتصنيف جميع القيم.

أو يمكنك استخدام زيادة ثنائية ، ولكن من أجل التكرار على كل القيم لمتجه بأعداد الطول N ، يستغرق تكرارًا 2 ^ n.

أولاً ، نختار حالة خاصة ، لنفترض أن الصفيف يتكون من أرقام> 0. لاحقًا ، بناءً على هذا المثال ، سننفذ جميع الحالات.

الخطوة 1


أ) النظر في واحدة من الحالات الخاصة - مجموع جميع عناصر الصفيف <10.
المنطق بسيط ، sum (V) <10 ، ثم sum (V) -V [i] <sum ، وهذا هو ، إذا كان مجموع المجموعات سيكون دائمًا أقل من 10.

ب) إذا كان مجموع (V) = 10 ، ثم مجموع المبلغ (V) -V [i] <sum. ستكون النتيجة واحدة فقط.

الخطوة 2


نزيل كل ما لا لزوم له من ناقل

على سبيل المثال ، خذ الصفيف [13 ، 10 ، 20 ، 13 ، 13 ، 18 ، 2 ، 9 ، 5 ، 8 ، 8 ، 9 ، 2 ، 1 ، 8 ، 16 ، 4 ، 15 ، 2 ، 2 ، 2 ، 1 ، 5 ، 5 ، 5].

يظهر على الفور أنه لا معنى للبحث عن المجموعات إذا كانت القيمة> 10 ، ولكن كل شيء سوف يصبح واضحًا على الفور. إذا قمنا بفرزها:

[1 ، 1 ، 2 ، 2 ، 2 ، 2 ، 2 ، 4 ، 5 ، 5 ، 5 ، 5 ، 8 ، 8 ، 8 ، 9 ، 9 ، 10 ، 13 ، 13 ، 13 ، 15 ، 16 ، 18 ، 20 ]

في هذه المرحلة ، يمكننا بالفعل أن نعرف بالتأكيد أننا بحاجة إلى حذف جميع العناصر أكبر من 10
ت => [1 ، 1 ، 2 ، 2 ، 2 ، 2 ، 2 ، 4 ، 5 ، 5 ، 5 ، 5 ، 5 ، 8 ، 8 ، 8 ، 9 ، 9 ، 10]

ولكن في الواقع ، كل شيء أكثر إثارة للاهتمام قليلا. نحن بحاجة إلى قصر المتجه على القيمة بحيث V [0] + V [i] <= 10 ؛ حيث أميل إلى N ؛ لكن إذا كانت V [i] = 10 ، فإننا نضيف 10 إلى النتيجة
ت => [1 ، 1 ، 2 ، 2 ، 2 ، 2 ، 2 ، 4 ، 5 ، 5 ، 5 ، 5 ، 5 ، 8 ، 8 ، 8 ، 9 ، 9]

الخطوة 3


هناك عناصر مكررة في صفيف تمت تصفيته بالفعل. إذا قمنا بتحليل المتجه إلى متجهات فرعية ، وحساب مجموعته ، فسنحصل على شيء من هذا القبيل
[1،1] => 2
[2 ، 2 ، 2 ، 2 ، 2] => 10
[4] => 4
[5 ، 5 ، 5 ، 5] => 20
[8 ، 8 ، 8] => 24
[9.9] => 18

يكمن جوهر أفكاري في أنه من غير المنطقي التفكير في مجموعات من الأرقام المكررة إذا كان عددها * القيمة> 10. وهذا يعني أننا نقطع المتجهات حتى يقل مجموعها عن 10 ، ونضيف تلك التي تكون 10 في النتيجة:
[1،1] => [1،1]
[2 ، 2 ، 2 ، 2 ، 2] => [2 ، 2 ، 2 ، 2]
[4] => [4]
[5 ، 5 ، 5 ، 5] => [5]
[8 ، 8 ، 8] => [8]
[9.9] => [9]

نتيجة للخطوة الثالثة ، سيكون متجهنا على النحو التالي
[1 ، 1 ، 2 ، 2 ، 2 ، 4 ، 5 ، 8 ، 9]

كما ترون ، انخفض حجم المتجه من 25 إلى 9 ، وهو أصغر كثيرًا (تذكر عدد التكرارات) ؛

مع الأرقام السالبة


هذا هو أكثر تعقيدا قليلا. سنفترض أننا قمنا بتنفيذ وظيفة العثور على مجموعات لمتجه فرز إيجابي بناءً على القيود السابقة.
مشط (arr ، مبلغ) ، حيث المبلغ هو المبلغ المطلوب ، arr هو ناقل مصنفة من أرقام موجبة

على سبيل المثال ، خذ المتجه:
[19 ، 15 ، -9 ، 3 ، -13 ، -8 ، -12 ، 11 ، -2 ، -10 ، 0 ، 7 ، 17 ، -17 ، -14 ، -15 ، -11 ، -6 ، -12 و -10 ، 9]

1. كسر ناقلات
أ = القيم الإيجابية فقط
ب = القيم السلبية فقط
وانظر أيضًا إذا كانت لدينا قيم = 0

2. فرز
فرز المتجهات (تصاعدي موجب ، تنازلي سلبي)

تحقق من الحالة الخاصة لمعرفة الأرقام الإيجابية (الخطوة 1)

3. التحقق من الإيجابية
تحقق من وجود قيم إيجابية
مشط (ب ، 10)

3. تحقق من وجود سلبي
إنشاء مجموعات من جميع الأرقام السالبة ، ولكن مع التقييد:

(مجموع عناصر modulo) <(مجموع كل الموجب) + 10
نجد مجموعات للمبالغ المرجعية الجديدة (مجموع عناصر المعامل + 10)

4. المساواة 0
إذا كان المتجه المصدر له قيمة 0 ، فإننا نضيف جميع المجموعات + 0 إلى النتيجة ؛

نتيجة لهذه القيود ، في المتوسط ​​، عند اختبار القيم بمجموعة مكونة من 28 و 1000 اختبار ، يكون كسب الوقت 42٪ تقريبًا

كن حذرا حتى لا تبدو عصبية. المؤلف ليست مسؤولة عن المعاناة الأخلاقية.
function combine(arr, etalon = 10) { //--------------------------------------------// //------------- helpers --------------------// //    // Create binnary array function createBin(length) { let bin = []; for (let i = 0; i < length; i++) { bin[i] = false; } return bin; } //   1 //Binnary add 1 bit function binAddBit(bin, i = 0) { if (i >= bin.length) { return null; } if (bin[i] == false) { bin[i] = true; return bin; } else { bin[i] = false; i++; return binAddBit(bin, i); } } function iniq(arr) { let result = []; let object = {}; arr.forEach(vector => { value = vector.sort(function(a, b) { return a - b }); key = value.join(','); object[key] = value; }); for (var key in object) { result.push(object[key]); } return result; } //   // : //       //       //       function _combine(arr, sum = 10) { let result = []; //   if (arr[0] > sum) return []; if (arr[0] == sum) return [ [sum] ]; //1.   let $aKey = {}; let $a = []; let $sum = 0; //    $aKey[arr[0]] = arr[0]; $a.push(arr[0]); $sum += arr[0]; let $eqSum = false; for (let i = 1; i < arr.length; i++) { if ((arr[i] + arr[0]) <= sum) { //-----------------------------// // count*element < sum $aKey[arr[i]] = $aKey[arr[i]] != undefined ? $aKey[arr[i]] += arr[i] : arr[i]; if ($aKey[arr[i]] < sum) { $a.push(arr[i]); $sum += arr[i]; } //-----------------------------// //-----------------------------// // count*element = sum if ($aKey[arr[i]] === sum) { let $res = []; for (let j = 0; j < (sum / arr[i]); j++) { $res.push(arr[i]); } result.push($res); } //-----------------------------// } if (arr[i] == sum) { $eqSum = true; } } if ($eqSum) { result.push([sum]); } if ($sum < sum) return result; if ($sum == sum) { result.push($a); return result; } //   let bin = createBin($a.length); while (change = binAddBit(bin)) { let $sum = 0; let $comb = []; for (let i = 0; i < change.length; i++) { if (change[i] == false) continue; $sum += $a[i]; if ($sum > sum) break; // exit in accumulate $comb.push($a[i]); if ($sum == sum) { result.push($comb); } } } return result; } //------------- helpers --------------------// //--------------------------------------------// let result = []; //         //   -   let zero = false; //       let posetive = []; let negative = []; let sumPosetive = 0; arr.forEach(element => { if (element === 0) { zero = true; } if (element < 0) { negative.push(element); } if (element > 0) { posetive.push(element); sumPosetive += element; } }); //   ( ) posetive.sort(function(a, b) { return a - b }); negative.sort(function(a, b) { return b - a }); //       ,  //       if (sumPosetive < etalon) return []; //       if (sumPosetive == etalon) { result.push(posetive); if (zero) { let _clone = posetive.slice(); _clone.push(0); result.push(_clone); } return result; } //      ; result = result.concat(_combine(posetive, etalon)); // SUPPLE -          combinPosetiveLim negative = negative.filter(function(value) { return -value <= (sumPosetive + etalon); }); //    (  ) let bin = createBin(negative.length); //   while (changeBin = binAddBit(bin)) { let sum = etalon; let vector = []; //      for (let i = 0; i < changeBin.length; i++) { if (changeBin[i] == false) continue; sum -= negative[i]; vector.push(negative[i]); } if (sum > (sumPosetive + etalon)) continue; let lines = _combine(posetive, sum); lines.forEach(value => { result.push(vector.concat(value)); }); } //    0 if (zero) { result.forEach(item => { let _clone = item.slice(); _clone.push(0); result.push(_clone); }); } result = iniq(result); return result; } 

Source: https://habr.com/ru/post/ar460923/


All Articles