Loading...
imollov avatar imollov 1 Точки

Въпрос относно последователност от числа в масив

Здравейте,

Решавайки една от задачите в глава 7. Масиви от "Въведение в програмирането със С#" се сблъсках трудност относно разбирането на логикатата й и не успях да я реша. Става въпрос за задача 9. Напишете програма, която намира последователност от числа, чиито сума е максимална. 
Пример: {2, 3, -6, -1, 2, -1, 6, 4, -8, 8} = 11.

След като намерих едно от възможните й решения, се помъчих да открия логиката как точно се достига до крайния верен резултат, но без успех. Блъсках си главата, но нищо не мога да разбера, а изглежда доста кратък и лесен код.

Да поясня, всички въпроси и коментари, които имам към кода, са с примерните числа от масива в задачата.

int sum = 0, tempSum;
            
            Console.Write("Enter array length: ");
            int length = Int32.Parse(Console.ReadLine());

            int[] arr = new int[length];

            for (int i = 0; i < length; i++)
            {
                Console.Write("Enter {0} element: ", i);
                arr[i] = Int32.Parse(Console.ReadLine());
            }

            for (int i = 0; i < length - 1; i++) // ако вземем числата в условието, то в началото i = 2.
            {
                tempSum = arr[i]; // следователно тук tempSum = 2.

                for (int j = i + 1; j < length; j++) // ако вземем числата в условието, то в началото j = 3.

                {
                    tempSum += arr[j];  // тук tempSum = 2 + 3 = 5.
                    if (tempSum > sum) //тук tempSum е 5, а не 2, ако правилно разсъждавам. 5 > 0, тъй като sum = 0. 
                     {
                     sum = tempSum;     // от тук следва, че sum = 5. 
                     }
                }
            }

            Console.WriteLine("Result is {0}. ", sum);

Ако коментарите са ми верни. То при следващата итерация на вътрешния for loop:

j = -6, tempSum = 2 + (-6) = -4, ако взема стойността на sum от предната итерация то би трябвало да е равен на 5 и няма да се изпълни if-a. 

При следващо завъртане на вътрешния цикъл:

j = -1, tempSum = 2 + (-1) = 1, тук sum коя стойност взема, тази от предната итерация ли, т.е. няма как да го вземе тъй като не се е изпълнил if-a, значи взима от първата и е равен на 5, и пак няма да се изпълни if-a, защото 1 < 5?

Така продължавам до края на вътрешния цикъл, после външния се завърта и вече i = 3,  tempSum = 3. А j = -6, tempSum = 3 + (-6) = -3  и вече не знам sum на какво е равно.

Просто много се обърках. Явно не мисля в правилната посока.

Ако някой може да ми обясни логиката на двата цикъла и как точно се извършват итерациите във вътрешния цикъл, външния и съответно какви са стойностите които приемат tempSum при i, tempSum при j и sum. 

Благодаря предварително.

Тагове:
0
Programming Basics
Gesh4o avatar Gesh4o Trainer 305 Точки

Здравей,

Ако трябва да се опише идеята на решението, тя е нещо такова:

1. Минаваме през всеки един елемент от масива.

2. За всеки един елемент събираме последователно числата, намиращи се след него.

3. На всяко едно събиране правим проверка дали текущия сбор е по-голям от вече получения и ако е така - заместваме старата максимална стойност с новата.

Ето пример:

Имаме поредицата 1, 2, 3. Минаваме през първия и елемент(Стъпка №1) и за него последователно събираме всички следващи елементи(Стъпка №2) :

1 = 1 - тук обаче не събираме нищо, тъй като самата стойност може да е максималният сбор.

(Какво става при поредица: -1, -1, 5, -2 ?)

Тук максималния сбор е: 1 (защото е начален - преди него няма други суми). 

1 + 2 = 3

Тук максималния сбор е: 3 (3 >1).

1 + 2 + 3 = 6

Тук максималния сбор е: 6 (6 >3).

На всяка една стъпка правим проверка с текущата максимална сума и ако сегашния сбор е по-голям - той става максималния сбор за момента(Стъпка №3). Съответно за втория елемент имаме:

2 = 2

Тук максималния сбор е: 6 (6 >2)  и т.н.

2 + 3 = 5

И за третия(тук той е последен елемент и затова няма допълнително суми):

3 = 3 

Съгласен съм с предложения от @puffed отговор, като също така мисля, че ако минеш с дебъгера през тази задача ще можеш да разбереш какво се случва и то по-подробно.

Ако има още нещо за доизясняване, пиши. 

Поздрави! :)

1
imollov avatar imollov 1 Точки

Здравей,

След като видях това, което сте ми писали ти и @puffed, и след като дебъгнах кода, нещата малко по малко се подредиха.

Мерси за помощта. yes

0
02/09/2016 21:51:14
kaloyannikov avatar kaloyannikov 531 Точки

Междудругото, ако ти е интересно има доста ефективен алгоритъм(Kadane Algorithm) точно за тоя проблем . Не е може би за основи на програмирането , но всъщност не е толкова труден и като код е доста кратко. А е по-бърз тъй като му отнема N стъпки за да се изпълни, а не N^2.

При редица : -2 , 3 , 2 , -1 

  0 1 2 3
  -2 3 2 -1
currentSum -2 3 5 4
maxSum -2 3 5 5

На всяка стъпка за всеки индекс се записва най-голямата стойност между стойноста на елемента или стойноста на елемента + текущата сума. Другото от алгоритъма е да направиш проверка текущата сума дали е > maxSum и ако е да присвоиш на maxSum стойноста на currentSum.

Като почнем от 1 до дължината  ( отначало слагаме max и current да са array[0] т.е. - 2)  

1ва итерация - currentSum  =  Math.Max(3 , 3 + (-2)) , записва се 3 , maxSum става 3

2ра итерация - currentSum = Math.Max(2 , 3 +2 ) , записва се 5 , maxSum става 5

3та итерация  - currentSum = Math.Max(-1, 5 + (-1)) записва се 4 , maxSum си остава 5 защото 5 > 4 

като цял код - http://pastebin.com/8hHVZ1Sk

3
03/09/2016 12:16:12
Innos avatar Innos 419 Точки

Много съм приятно изненадан от наличието на този отговор тук, ако можех и повече плюсове щях да дам.
Като занимавка за любопитният читател, предлагам да се пробва да модифицира алгоритъмът да връща и началният и крайният индекс на максималната редица.

1
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.