Given a list of integers, write a Python program to find groups of strictly increasing numbers.
Examples:
Input : [1, 2, 3, 5, 6] Output : [[1, 2, 3], [5, 6]] Input : [8, 9, 10, 7, 8, 1, 2, 3] Output : [[8, 9, 10], [7, 8], [1, 2, 3]]
Approach #1 : Pythonic naive This is a naive approach which uses an extra input list space. It makes use of a for loop and in every iteration, it checks if the next element increments from previous by 1. If yes, append it to the current sublist, otherwise, create another sublist.
# Python3 program to Find groups # of strictly increasing numbers within def groupSequence(lst):
res = [[lst[ 0 ]]]
for i in range ( 1 , len (lst)):
if lst[i - 1 ] + 1 = = lst[i]:
res[ - 1 ].append(lst[i])
else :
res.append([lst[i]])
return res
# Driver program l = [ 8 , 9 , 10 , 7 , 8 , 1 , 2 , 3 ]
print (groupSequence(l))
|
[[8, 9, 10], [7, 8], [1, 2, 3]]
Time complexity: O(n), where n is the length of the input list.
Auxiliary space: O(n).
Approach #2 : Alternate naive This is an alternative to the above mentioned naive approach. This method is quite simple and straight. It constructs a start_bound list and an end_bound list, which contains the position of starting and ending sequence of increasing integers. Thus simply return the bounds using for loops.
# Python3 program to Find groups # of strictly increasing numbers within def groupSequence(l):
start_bound = [i for i in range ( len (l) - 1 )
if (l = = 0 or l[i] ! = l[i - 1 ] + 1 )
and l[i + 1 ] = = l[i] + 1 ]
end_bound = [i for i in range ( 1 , len (l))
if l[i] = = l[i - 1 ] + 1 and
(i = = len (l) - 1 or l[i + 1 ] ! = l[i] + 1 )]
return [l[start_bound[i]:end_bound[i] + 1 ]
for i in range ( len (start_bound))]
# Driver program l = [ 8 , 9 , 10 , 7 , 8 , 1 , 2 , 3 ]
print ( list (groupSequence(l)))
|
[[8, 9, 10], [7, 8], [1, 2, 3]]
Time complexity: O(n), where n is the length of the input list.
Auxiliary space: O(n), as two additional lists are created with a maximum size of n.
Approach #3 : Using iterable and yield This approach uses another list ‘res’ and an iterable ‘it’. A variable ‘prev’ is used for keeping the record of previous integer and start is used for getting the starting position of the increasing sequence. Using a loop, in every iteration, we check if start element is a successor of prev or not. If yes, we append it to res, otherwise, we simply yield the res + [prev] as list element.
# Python3 program to Find groups # of strictly increasing numbers within def groupSequence(x):
it = iter (x)
prev, res = next (it), []
while prev is not None :
start = next (it, None )
if prev + 1 = = start:
res.append(prev)
elif res:
yield list (res + [prev])
res = []
prev = start
# Driver program l = [ 8 , 9 , 10 , 7 , 8 , 1 , 2 , 3 ]
print ( list (groupSequence(l)))
|
[[8, 9, 10], [7, 8], [1, 2, 3]]
Time complexity: O(n), where n is the length of the input list.
Auxiliary space: O(n), as two additional lists are created with a maximum size of n.
Approach #4 : Using itertools Python itertools provides operations like cycle and groupby which are used in this method. First we form another list ‘temp_list‘ using cycle. Cycle generates an infinitely repeating series of values. Then we group the temp_list accordingly using groupby operation and finally yield the desired output.
# Python3 program to Find groups # of strictly increasing numbers within from itertools import groupby, cycle
def groupSequence(l):
temp_list = cycle(l)
next (temp_list)
groups = groupby(l, key = lambda j: j + 1 = = next (temp_list))
for k, v in groups:
if k:
yield tuple (v) + ( next (( next (groups)[ 1 ])), )
# Driver program l = [ 8 , 9 , 10 , 7 , 8 , 1 , 2 , 3 ]
print ( list (groupSequence(l)))
|
[(8, 9, 10), (7, 8), (1, 2, 3)]
Approach #5: Using recursion
This approach uses recursion to find groups of strictly increasing numbers. The function find_groups takes two arguments – the input list and the index of the current element being processed. Initially, the index is set to 0. The function returns a list of lists, where each inner list represents a group of strictly increasing numbers.
Algorithm:
- If the index is equal to the length of the input list, return an empty list.
- Initialize the current element to the value at the current index.
- Find the groups of strictly increasing numbers starting from the next index recursively.
- If the next group starts with the current element + 1, add the current element to the start of the next group.
- If the next group is empty or does not start with the current element + 1, create a new group starting with the current element.
- Return the list of groups.
def find_groups(l, index = 0 ):
if index = = len (l):
return []
current_element = l[index]
groups = find_groups(l, index + 1 )
if len (groups) > 0 and groups[ 0 ][ 0 ] = = current_element + 1 :
groups[ 0 ].insert( 0 , current_element)
else :
groups.insert( 0 , [current_element])
return groups
# Driver program l = [ 8 , 9 , 10 , 7 , 8 , 1 , 2 , 3 ]
print (find_groups(l))
|
[[8, 9, 10], [7, 8], [1, 2, 3]]
Time complexity: O(n^2), where n is the length of the input list. This is because in the worst case, we may have to check each element against every other element.
Auxiliary space: O(n), where n is the length of the input list. This is because we are creating a list of lists to store the groups.