在列表中查找连续增加的数字

时间:2018-03-20 03:54:53

标签: algorithm list recursion

处理更大的问题,其中一部分需要使用递归在给定列表中查找连续的数字

[1,2,3,8,6,7]

需要输出

[[1,2,3],8,[6,7]]

我已经处理过了 空列表案例 列表只有一个值的情况, 但我很困惑如何通过递归来完成上述情况。

6 个答案:

答案 0 :(得分:0)

您是否有理由以递归方式执行此操作?只是线性地做它可能更容易。

这样的事可能吗?

Function increasing(originalArray) {
     Let groupedArray = [ ]
     Let subArray = [ ]
     For(let i = 0; i < originalArray.length; i++){
         If(subArray.length === 0){
             subArray = subArray.concat(originalArray[i])
          } else if(originalArray[i] - subArray[subArray.length - 1] === 1){
              subArray = subArray.concat(originalArray[i])
          } else {
             groupedArray = groupedArray.concat(subArray)
             subArray = [originalArray[i]]
          }
      }
     Return groupedArray
}

答案 1 :(得分:0)

常见的算法技术称为divide and conquer。我喜欢把它想象成问这些问题:

  1. 如果这个问题的范围非常小,可以轻松解决吗?

  2. 如果我对这个问题的子集有多个解决方案,我可以轻松地将它们组合起来解决更大的问题吗?

  3. 现在让我们将它应用到您的问题中。为了简单起见,我将把它们称为长度为1的数组,而不是像你那样的单独的数字和数组。如果你必须使用1号数组进行此操作,那将很容易。答案总是与你放在另一个数组中的数组相同。如果你有两个已经完成的数组,你可以将它们组合起来。如果第一个数组的最后一个值小于第二个数据的第一个值,则将前半部分的最后一个子数组和后半部分的第一个子数组合并为一个连续数字数组,否则只需将两个求解合并数组通常。

    这是在python中实现的解决方案,对不起,不是最好的,但它完成了工作:

    def myFunc(arr):
      # If there is only 1 element wrap in an array
      if (len(arr) == 1):
        return [arr]
      else:
        # apply the func to first and second array halves
        arrOne = myFunc(arr[:len(arr) / 2])
        arrTwo = myFunc(arr[len(arr) / 2:])
    
        # last array of the first
        arrOneEnd = arrOne[len(arrOne) - 1]
        # first array of the last
        arrTwoStart = arrTwo[0]
    
        # if the last element of the last array is 
        # 1 less than the first element of the first array
        if (arrOneEnd[len(arrOneEnd) - 1] - arrTwoStart[0] == -1):
          # Append them combining the first and last
          return arrOne[:len(arrOne) - 1] + [arrOneEnd + arrTwoStart] + arrTwo[1:]
        else:
          # Otherwise just append
          return arrOne + arrTwo
    

    然后,您可以将长度为1的所有数组映射到它们的唯一元素:

    def myFinalFunc(arr):
      return map(lambda subArr: if(len(subArr) == 1) subArr[0] else subArr, arr)
    

答案 2 :(得分:0)

我不确定你在这里指的是什么数据结构:[[1,2,3],8,[6,7]]所有输出结果(包括单项内容)都包含在子列表中

def SuccRec(lst, start, idx):
    if (idx >= len(lst)):
        print(lst[start:idx])
    else:
        if (lst[idx] != lst[idx-1] + 1):
             print(lst[start:idx])
             SuccRec(lst, idx, idx + 1)
        else:
             SuccRec(lst, start, idx + 1)


SuccRec([1,2,3,8,6,7], 0, 1)

output:
[1, 2, 3]
[8]
[6, 7]

答案 3 :(得分:0)

让我们概括一下。

如果item 为空chunk符合chunk项目,请继续将condition添加到当前last chunkitem。否则,请启动 new chunk。在你的情况下,条件是

 item - last == 1

我们可以看到,我们有一个直接(不是 recoursive )算法。 C#实现:

public static IEnumerable<T[]> Successive<T>(IEnumerable<T> source, 
                                             Func<T, T, bool> condition) {
  if (null == source)
    throw new ArgumentNullException("source");
  else if (null == condition)
    throw new ArgumentNullException("condition");

  List<T> chunk = new List<T>();

  foreach (var item in source) {
    if (!chunk.Any() || condition(chunk.Last(), item))
      chunk.Add(item);              // keep on adding into current chunk
    else {
      yield return chunk.ToArray(); // return current chunk

      chunk.Clear();                // start a new one
      chunk.Add(item);
    }
  }

  if (chunk.Any())
    yield return chunk.ToArray();
}

测试:

  int[] data = new int[] { 1, 2, 3, 8, 6, 7 };

  // In our case the condition (successive items) is "current - last == 1"
  var result = Successive(data, (last, current) => current - last == 1)
    .Select(chunk => chunk.Length == 1     // ? : - to provide required output format
       ? chunk[0].ToString()
       : $"[{string.Join(",", chunk)}]");

  string report = $"[{string.Join(",", result)}]";

  Console.Write(report); 

结果:

 [[1,2,3],8,[6,7]]

答案 4 :(得分:0)

这是我的建议,有很多关于可读性的评论:

myList = [1,2,3,8,6,7]
newList = []

def treatItem(i=0, startOfRange=myList[0]):
    """
        Treat each item of the list recursively
        @param i : index of an element in myList
        @param startOfRange: start of the range the element belongs to
    """
    if (i+1 == len(myList)):
        # Here: we treat the last value of the list (so this is the end of a last range)
        # Store this range in newList
        lastRange = list(range(startOfRange,myList[i]+1))
        newList.append(lastRange)
        return
    elif (myList[i] + 1 != myList[i+1]):
        # Here: this is the end of a range
        # Store this range in newList
        newRange = list(range(startOfRange,myList[i]+1))
        newList.append(newRange)
        # Treat the next item, starting a new range
        treatItem(i+1, startOfRange=myList[i+1])
    else:
        # Here: this is not the end of a range
        # Treat the next item, without starting a new range
        treatItem(i+1, startOfRange=startOfRange)

treatItem()

print(newList) # [[1, 2, 3], [8], [6, 7]]

答案 5 :(得分:0)

Haskel尝试:)

f [] = []
f [x] = [[x]]
f (x:xs)
  | z == succ x = (x:z:zs):zzs
  | otherwise   = [x]:rest
    where rest@((z:zs):zzs) = f xs

main = print(f [1,2,3,8,6,7])