Софтуерно Инженерство
Loading...
+ Нов въпрос
BorisYordanov avatar BorisYordanov 1 Точки

Решение на задача от Глава 7 - Масиви във "Въведение в програмирането със C#"

Линк към главата

Имам въпрос за решението задача №4, с условие:

"4.      Напишете програма, която намира максимална редица от последова­телни еднакви елементи в масив. Пример: {2, 1, 1, 2, 3, 3, 2, 2, 2, 1} à {2, 2, 2}."

По-долу съм сложил и решение, което свалих от сайта.

Имам проблем със следната част от кода:

 for (int count = 0; count < arrayLength; count++)
            {
                int currentCount = 0;
                for (int minCount = count; minCount < arrayLength; minCount++)
                {
                    if (arrayOfNumbers[count] == arrayOfNumbers[minCount])

Очевидно е, че count и minCount винаги ще имат една и съща стойност, но идеята на задачата е програмата ни да сравнява един член от масива със следващия, т.е. да сравним елемент 0 с елемент 1, а след това елемент 1 с елемент 2. А в момента (доколкото разбирам сравняваме един и същ, понеже

arrayOfNumbers[0] == arrayOfNumbers[0])  

arrayOfNumbers[1] == arrayOfNumbers[1]) 

и т.н.

Но решението работи както трябва и е ясно, че аз нещо ме съм разбрал. Може ли някой да ми изясни как точно работи това решение?

using System;

class FindsTheMaximalSequence
{
    static void Main(string[] args)
    {
        string enterLength = Console.ReadLine();
        int arrayLength = int.Parse(enterLength);
        int[] arrayOfNumbers = new int[arrayLength];
        string enterString;
        for (int count = 0; count < arrayLength; count++)
        {
            enterString = Console.ReadLine();
            arrayOfNumbers[count] = int.Parse(enterString);
        }
        int maxCount = 0;
        int value = 0;
        for (int count = 0; count < arrayLength; count++)
        {
            int currentCount = 0;
            for (int minCount = count; minCount < arrayLength; minCount++)
            {
                if (arrayOfNumbers[count] == arrayOfNumbers[minCount])
                {
                    currentCount++;
                    if (maxCount < currentCount)
                    {
                        maxCount = currentCount;
                        value = arrayOfNumbers[count];
                    }
                }
                else
                {
                    break;
                }
            }
        }            
        Console.WriteLine("Max length = {0} and value is {1}", maxCount, value);                        
    }
}

 

Тагове:
sider.topalov avatar sider.topalov 38 Точки
Best Answer

Здравей, ще се опитам да ти го обясня максимално упростено.

Така преди 2-та "for" цикъла имаме 2 променливи с цел в "maxCount" да записваме най-дългата редица,а в "value" да запишем кой индекс от масива отговаря на тая дължина примерно ще ползвам твоя масив по горе и индекса ни е "2". 

Така след като влезнем в първия цикъл, отново имаш променлива "currentCount" value = "0" вътре след първия "for" тя ще ни служи за текущата дължина на дадена поредица и искаме тази променлива всеки път да започва от "0" за да може да броим следващата дълцина на текущата поредица от масива. След това влизаме във втория "for" и казваме "minCount = count" с цел да се подсигурим, че нашия втори цикъл винаги ще започва от индекса на първия тоест ако "count = 4"  в даден момент то ние искаме нашия "minCount" също да има тая стойност "4" защото ние вече сме обходили предните индекси "3,2,1 и 0".

И след това влизаме в тялото на втория "for" и там имаме която проверява "arrayOfNumbers[count] == arrayOfNumbers[minCount]"

нека кажем, че "count = 1" и "minCount = 1"  тогава нашия "arrayOfNumbers[count] и arrayOfNumbers[minCount]" => "1 == 1" тогава "if" връща "true" и влиза вътре и увеличава "currentCount"  с "1"  и там има още един "if" който проверява дали "maxCount" не е по малка от текущата дължина "currentCount"  и ако е то тогава присвояваме на "maxCount = currentCount" и на "value = arrayOfNumbers[count]" все едно "value = 1" и завъртаме втория "for" и правим същите стъпки наново  "arrayOfNumbers[count] == arrayOfNumbers[minCount]" тоест => index(1) със стойност (1) от масива дали е равна(=) на index(2) със стойност(пак 1) от масива връща true и продължава по същия начин по горе. Но в момента в който нашия вътрешен "for" стигне да речем index(3) със стойност(2) в масива и тръгне да проверява "arrayOfNumbers[count] == arrayOfNumbers[minCount]" тоест => index(1) със стойност (1) от масива дали е равна(=) на index(3) със стойност(2) от масива и върне "false" бреаква нашия вътрешен цикъл връща се на първия "for" увеличава индекса и така продължава докато не стигне до края на масива след което ти вече имаш "maxCount = 3" и "value = 2" и като имаш тези две неща с един for цикъл от 0 до maxCount  да принтираш value.

Е това е от мен надявам се съм ти го обяснил до толкова че да ме разбереш от това по просто обяснение честно казано не мисля че мога да дам и все пак ако нещо не ти е станало ясно питай смело. Успех! :)

1
23/05/2016 14:08:34
DStefanow avatar DStefanow 112 Точки

Според мене това решение е бая сложно (като се има предвид двата вложени цикъла), аз лично го правя с едно обхождане, като count = 1, и карам от нулевия елемент на масива от array.Length - 1, и на всяка итерация от цикъла сравнявам дали съм намерил по- голяма подредица от предходната и от там нататък става лесно, ако искам най- лявата подредица в if-a сравнявам с ' > ', ако целта ми е най- дясната ' >= '.

0
Nikola_Andreev avatar Nikola_Andreev 671 Точки

Ами това е вложен цикъл, незнам дали ти е ясно как работят, ще се опитам да ти обясня накратко.

Първият цикъл започва от 0. Влизаме в него и започва вторият цикъл и той също е от 0. Този втория обаче ще се извърти от 0 до дължината на масива (10 примерно), а първия си стой на 0. Първият масив ще стане 1 чак когато се извърти втория. И общо взето получаваме 10 пъти въртене от 1 до 10 (ако масива е от 10 елемента). Едва ли ще ти стане ясно веднага, но най-просто казано първо се извърта вътрешния цикъл и чак тогава продължава въртенето на външния. Пусни си го през дебъгера, ако можеш да дебъгваш и изгледай някое видео където се обясняват вложени цикли и ще ти стане по ясно.

Поздрави.

0
BorisYordanov avatar BorisYordanov 1 Точки

Знам какво е вложен цикъл, но не бях разбрал, че така работят (първо се извърта втория, а после първия). Благодаря за информацията!

0
KrasimirPetkov avatar KrasimirPetkov 331 Точки

Задачата може да се реши с един for-цикъл, който да обходи масива.

Необходимата информация, за извеждане на резултат е:

1. Най-големият брой еднакви елементи.

2. Началната им позиция в масива.

Това означава, че имаме нужда от две променливи: maxCount и maxStart.

За целта може да сравним последователно всеки елемент от масива с предходния, като началният индекс се съхранява в променлива currentStart, а броя на еднаквите елементи в currentCount. При всяка промяна на currentCount, сравняваме currentCount с maxCount и ако е по-голям, присвояваме стойностите към maxCount и maxStart. Ако елементът е различен от предходните, currentCount се връща в изходна позиция, а currentStart става еквивалентен на настоящия индекс.

int maxCount = 0;
int maxStart = 0;
int currentCount = 1;
int currentStart = 0;
for (int i = 1; i < array.Length; i++)
{
    if (array[i]==array[i-1])
    {
        currentCount++;
        if (currentCount > maxCount) { maxCount = currentCount; maxStart = currentStart; }
    }
    else
    {
        currentCount = 1;
        currentStart = i;
    }
}

Ето и линк към решението (масивът се въвежда на един ред, разделен с интервали):

http://pastebin.com/wPqkkyMw

PS: Използвал съм малко Linq, което не се учи в Programming Basics, но това е само с цел по-лесно въвеждане на изходните данни и извеждане на резултата. Можеш да го замениш с каквото намериш за удачно :)

1
23/05/2016 16:47:21
BorisYordanov avatar BorisYordanov 1 Точки

Твоето решение наистина е доста по-опростено. Благодаря

1