How to find the largest element in a list of integers recursively?

前端 未结 16 1605
不知归路
不知归路 2021-01-31 19:49

I\'m trying to write a function which will recursively find the largest element in a list of integers. I know how to do this in Java, but can\'t understand how to do this at Sca

相关标签:
16条回答
  • 2021-01-31 20:20

    Here is my code (I am a newbie in functional programming) and I'm assuming whoever lands up under this question will be folks like me. The top answer, while great, is bit too much for newbies to take! So, here is my simple answer. Note that I was asked (as part of a Course) to do this using only head and tail.

    /**
       * This method returns the largest element in a list of integers. If the
       * list `xs` is empty it throws a `java.util.NoSuchElementException`.
       *
       * @param xs A list of natural numbers
       * @return The largest element in `xs`
       * @throws java.util.NoSuchElementException if `xs` is an empty list
       */
        @throws(classOf[java.util.NoSuchElementException])
        def max(xs: List[Int]): Int = find_max(xs.head, xs.tail)
    
        def find_max(max: Int, xs: List[Int]): Int = if (xs.isEmpty) max else if (max >= xs.head) find_max(max, xs.tail) else find_max(xs.head, xs.tail)
    

    Some tests:

    test("max of a few numbers") {
        assert(max(List(3, 7, 2)) === 7)
        intercept[NoSuchElementException] {
          max(List())
        }
        assert(max(List(31,2,3,-31,1,2,-1,0,24,1,21,22)) === 31)
        assert(max(List(2,31,3,-31,1,2,-1,0,24,1,21,22)) === 31)
        assert(max(List(2,3,-31,1,2,-1,0,24,1,21,22,31)) === 31)
        assert(max(List(Int.MaxValue,2,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,22)) === Int.MaxValue)
      }
    
    0 讨论(0)
  • 2021-01-31 20:21

    With pattern matching to find max and return zero in case empty

      def findMax(list: List[Int]) = {
        def max(list: List[Int], n: Int) : Int = list match {
          case h :: t => max(t, if(h > n) h else n)
          case _ => n
        }
        max(list,0)
      }
    
    0 讨论(0)
  • 2021-01-31 20:22

    I used just head() and tail()

    def max(xs: List[Int]): Int = {
        if (xs.isEmpty) throw new NoSuchElementException
        else maxRecursive(xs.tail, xs.head) 
      }
      
      def maxRecursive(xs: List[Int], largest: Int): Int = {
        if (!xs.isEmpty) {
          if (xs.head > largest) maxRecursive(xs.tail, xs.head)
          else maxRecursive(xs.tail, largest)
        } else {
          largest
        }
      }
    

    Here is tests for this logic:

    test("max of a few numbers") {
        assert(max(List(3, 7, 2, 1, 10)) === 10)
        assert(max(List(3, -7, 2, -1, -10)) === 3)
        assert(max(List(-3, -7, -2, -5, -10)) === -2)
      }
    
    0 讨论(0)
  • 2021-01-31 20:24
    def max(xs: List[Int]): Int = {
      def _max(xs: List[Int], maxAcc:Int): Int = {
        if ( xs.isEmpty ) 
          maxAcc 
        else 
          _max( xs.tail, Math.max( maxAcc, xs.head ) ) // tail call recursive
      }
    
      if ( xs.isEmpty ) 
        throw new NoSuchElementException() 
      else 
        _max( xs, Int.MinValue );
    }
    
    0 讨论(0)
  • 2021-01-31 20:26

    The easiest approach would be to use max function of TraversableOnce trait, as follows,

    val list = (1 to 10).toList
    list.max
    

    to guard against the emptiness you can do something like this,

    if(list.empty) None else Some(list.max)
    

    Above will give you an Option[Int]

    My second approach would be using foldLeft

    (list foldLeft None)((o, i) => o.fold(Some(i))(j => Some(Math.max(i, j))))
    

    or if you know a default value to be returned in case of empty list, this will become more simpler.

    val default = 0
    (list foldLeft default)(Math.max)
    

    Anyway since your requirement is to do it in recursive manner, I propose following,

    def recur(list:List[Int], i:Option[Int] = None):Option[Int] = list match {
      case Nil => i
      case x :: xs => recur(xs, i.fold(Some(x))(j => Some(Math.max(j, x))))
    }
    

    or as default case,

    val default = 0
    def recur(list:List[Int], i:Int = default):Int = list match {
      case Nil => i
      case x :: xs => recur(xs, i.fold(x)(j => Math.max(j, x)))
    }
    

    Note that, this is tail recursive. Therefore stack is also saved.

    0 讨论(0)
  • 2021-01-31 20:28

    Scala is a functional language whereby one is encourage to think recursively. My solution as below. I recur it base on your given method.

      def max(xs: List[Int]): Int = {
        if(xs.isEmpty == true) 0
        else{
          val maxVal= max(xs.tail)
          if(maxVal >= xs.head) maxVal 
          else                  xs.head     
        }
      }
    

    Updated my solution to tail recursive thanks to suggestions.

      def max(xs: List[Int]): Int = {    
        def _max(xs: List[Int], maxNum: Int): Int = {   
          if (xs.isEmpty) maxNum
          else {
            val max = {
              if (maxNum >= xs.head) maxNum
              else xs.head
            }
            _max(xs.tail, max)
          }
        }
        _max(xs.tail, xs.head)
      }
    
    0 讨论(0)
提交回复
热议问题