Help with the solution of the problem.

In the array, find a subset of consecutive numbers (elements cannot be rearranged) composed of K not necessarily adjacent elements of the array (there may be several such subsets). Type array elements.

It is necessary to modify this code.

#include "stdafx.h" #include <stdio.h> #include <conio.h> #include "testing.h" int main() { int length_subset = 0; //Π΄Π»ΠΈΠ½Π° искомого подмноТСства int max_length_subset = 0; //Π΄Π»ΠΈΠ½Π° максимального подмноТСства int start_subset = 0; //Π½Π°Ρ‡Π°Π»ΠΎ искомого мноТСства Π² исходном массивС(пСрСмСнная содСрТит адрСс элСмСнта массива,с ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ начинаСтся искомоС мноТСство) int original_subset[20]; //исходный массив чисСл int result_subset[20]; //массив, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π±ΡƒΠ΄ΡƒΡ‚ хранится значСния искомой ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ int k = 0, j = 0, count_subset = 0; //счСтчики int end_subset; //ΠΊΠΎΠ½Π΅Ρ† искомого подмноТСства Π² исходном массивС(пСрСмСнная содСрТит адрСс элСмСнта массива,Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ заканчиваСтся искомоС мноТСство) int quantity_elements; // количСство элСмСнтов подмноТСства int m = 0; //Π΄Π»ΠΈΠ½Π° массива //ВвСсти Π΄Π»ΠΈΠ½Ρƒ массива //ВывСсти Π½Π° экран сообщСниС "Enter lenght of array: " input_printf("Enter lenght of array: "); scanf_s("%d", &m); //ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π΅Π΅ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ if (m < 2 || m > 20) { //ВывСсти Π½Π° экран сообщСниС "No solution" printf("Invalid input data"); WAIT_ANY_KEY return 0; } //ВвСсти элСмСнты массива for (int i = 0; i < m; i++) { //ВывСсти Π½Π° экран сообщСниС "Enter element of array: " input_printf("Enter element of array: "); scanf_s("%d", &original_subset[i]); //ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ ΠΈΡ… ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ if (original_subset[i] > 1000 || original_subset[i] < -1000) { //ВывСсти Π½Π° экран сообщСниС "No solution" error_printf("Invalid input data"); WAIT_ANY_KEY return 0; } } //Найти ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ подмноТСства ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… чисСл Π² Π΄Π°Π½Π½ΠΎΠΌ массивС //Для всСх элСмСнтов массива for (int i = 0; i < m; i++) { j = i; length_subset = 0; start_subset = 0; //Пока Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ элСмСнт массива + 1 = ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌΡƒ элСмСнту массива while ((original_subset[j] + 1) == (original_subset[j + 1])) { ++length_subset; //ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ Π΄Π»ΠΈΠ½Ρƒ искомого подмноТСства Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ j++; if (start_subset == 0) //условиС для Ρ‚ΠΎΠ³ΠΎ,Ρ‡Ρ‚ΠΎΠ±Ρ‹ пСрСмСнная ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π»Π°ΡΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· { start_subset = i; } } ++length_subset; //ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ Π΄Π»ΠΈΠ½Ρƒ, Ρ‚.ΠΊ. для послСднСго Ρ‡Π»Π΅Π½Π° условиС while Π½Π΅ выполняСтся //ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Π΅Ρ† удаляСмой ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ end_subset = start_subset + length_subset; //ΠΊΠΎΠ½Π΅Ρ† удаляСмой ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ //Если Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ количСство = ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠΌΡƒ количСству if (max_length_subset == length_subset && max_length_subset > 1) //искомыС мноТСства Ρ€Π°Π²Π½Ρ‹, Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π΅ { //Π—Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ значСния элСмСнтов Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ массив for (start_subset; start_subset < end_subset; start_subset++) { result_subset[k] = original_subset[start_subset]; k++; //k здСсь Π½Π΅ мСняСтся ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ, Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Π½Π°Ρ‡Π½Π΅Ρ‚ с Ρ‚ΠΎΠ³ΠΎ мСста, Π³Π΄Π΅ Π±Ρ‹Π»ΠΎ записано послСднСС } quantity_elements += length_subset; //ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ количСство элСмСнтов, Ρ‚.ΠΊ. Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ мноТСство } //Если Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ количСство > максимального количСства else if (max_length_subset < length_subset && length_subset > 1) { max_length_subset = length_subset; //ΠΏΡ€ΠΈΡΠ²ΠΎΠΈΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠΌΡƒ k = 0; //k здСсь обнуляСтся, Ρ‚.ΠΊ. Π½Π°ΠΉΠ΄Π΅Π½ΠΎ большСС мноТСство ΠΈ Π½ΡƒΠΆΠ½ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΅Π³ΠΎ ΠΈ сначала //Π—Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ значСния элСмСнтов Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ массив for (start_subset; start_subset < end_subset; start_subset++) { result_subset[k] = original_subset[start_subset]; k++; } quantity_elements = length_subset; //ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ количСство элСмСнтов } } //Если Π² массивС Π½Π΅Ρ‚ подмноТСств //Если число ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… элСмСнтов Π² подмноТСствС Ρ€Π°Π²Π½ΠΎ 0 if (max_length_subset == 0) { //ВывСсти Π½Π° экран сообщСниС "No solution" printf("no solution"); WAIT_ANY_KEY return 0; } //ВывСсти Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ подмноТСства else { printf("\n\n\n"); //ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π½Π° 3 строки Π²Π½ΠΈΠ· //ВывСсти всС элСмСнты подмноТСств for (k = 0; k < quantity_elements; k++) { //ВывСсти Π½Π° экран Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ элСмСнт массива printf("%d ", result_subset[k]); count_subset++; //Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ пСрСнос строки Ρ‡Π΅Ρ€Π΅Π· максимальноС количСство элСмСнтов Π² подмноТСствС if (count_subset == max_length_subset) { printf("\n"); count_subset = 0; } } WAIT_ANY_KEY return 0; } } 
  • For example, the test: -7; 1; 3; 4; -2; 2; 5; 6. Result: 1.2, 3.4, 4.5, 5.6 - user241815
  • What is the problem with the code? What did you expect to receive? What happens instead? Do not put the necessary information for the answer in the comments, edit your question instead. Click the edit button. - jfs
  • Should the @ourcode sequence be incrementing? nowhere said, but judging by the comments it is - Schullz
  • @Schullz Yes, ascending. - user241815
  • @jfs I see a problem that I don’t understand how to implement it, because in my code the subsets are sequentially behind them, and here they may not be in the neighborhood. - user241815

1 answer 1

Two algorithms: one rectilinear quadratic O(n**2) , and the other optimal single pass O(n) .

O (n ** 2) in time, O (k) in memory algorithm

Algorithm: for each element in the array X , we build subsequences starting with this element and consisting of consecutive numbers (but the indices may not be consecutive) until the length of the subsequence is equal to the desired one (they did not find a solution).

The current subsequence is represented by an array of indices M such that

 X[M[i]] + 1 == X[M[i+1]] 

for all possible i (expresses the condition of a sequence of numbers):

 #include <stdbool.h> #include <stdlib.h> /** Fill *M* such that: all(X[M[i]] == X[M[i+1]] - 1 for i in range(k-1)). * * Return whether found the natural subsequence (managed to fill *M*). */ bool find_natural_subsequence(int *X, size_t n, int* M, size_t k) { if (k == 0) return true; /* empty result (M), do nothing */ else if (k == 1) { if (n > 0) { M[0] = 0; /* [X[0]]: any subsequence with one item will do */ return true; } } else { /* k > 1 */ for (size_t i = 0; i < n; ++i) { size_t last = 0; /* index of the last filled M value */ M[last] = i; /* check the subsequence starting here */ for (size_t j = i + 1; j < n; ++j) { if (X[M[last]] == X[j] - 1) { /* found the next item */ M[++last] = j; if (last == k-1) return true; /* found the subsequence */ } } } } return false; /* not found */ } 

This is a quadratic algorithm ( O(n**2) time, O(k) memory for the result). Example:

 #include <stdio.h> int main(void) { int k = 4; int X[] = {-7, 1, 3, 4, -2, 2, 5, 6}; int M[k]; if(find_natural_subsequence(X, sizeof(X)/sizeof(*X), M, k)) { for (int i = 0; i < k; ++i) printf("%d ", X[M[i]]); putchar('\n'); return 0; } fputs("not found\n", stderr); exit(EXIT_FAILURE); } 

Result:

 $ cc *.c && ./a.out 3 4 5 6 

O (n) time and memory algorithm

You can improve the algorithm and make it O(n) (linear one-pass) using O(n) memory (the stack here is like a stack of cards, in which we see the value of only the most recent (top) card):

  1. If the input size is zero, then we return an empty list.
  2. For each item in the collection, we take out the stack where the item is one more than the top of the stack in order to get consecutive numbers in each stack. If you have not found a suitable stack, then create a new empty stack.
  3. Add an item to the stack (up, last)
  4. If the stack size is equal to the required one, then we return it.
  5. We add a stack back, indexing on a new last element. If the seat is already taken, then we leave a higher (long) stack.

On Python, this can be expressed as:

 def find_natural_subsequence(iterable, size): if size == 0: return [] # 1. empty pile piles = {} # mapping: <top of the pile> -> pile for x in iterable: # 2. extract the pile where we can put `x`: <top of the pile> + 1 == x pile = piles.pop(x-1, []) # O(1) # 3. add x to the pile (push on top) pile.append(x) # O(1) # 4. found the subsequence if len(pile) == size: return pile # 5. put it back piles[x] = max(pile, piles.pop(x, ()), key=len) # O(1) raise ValueError((iterable, size)) 

Example:

 >>> find_natural_subsequence([-7, 1, 3, 4, -2, 2, 5, 6], 4) [3, 4, 5, 6] 

Here is a visualization that shows how the stacks (stacks) represented by the piles in the code grow .

For C ++ implementation, you can use std::unordered_map to represent piles and std::vector for each stack.