How to resolve the algorithm Longest increasing subsequence step by step in the C# programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Longest increasing subsequence step by step in the C# programming language

Table of Contents

Problem Statement

Calculate and show here a longest increasing subsequence of the list: And of the list: Note that a list may have more than one subsequence that is of the maximum length.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Longest increasing subsequence step by step in the C# programming language

The provided C# code defines a class named LIS (Longest Increasing Subsequence) that provides two methods to find the longest increasing subsequence of a given sequence of elements.

Method 1: FindRec

  • Input: A list of elements IList<T> values and an optional IComparer<T> comparer to specify how to compare elements.
  • Output: An IEnumerable<T> representing the elements in the longest increasing subsequence, in reverse order.

This method uses a recursive algorithm to find the longest increasing subsequence. It starts by checking if the input list is null. If it is, it throws an ArgumentNullException.

If the list is not null, the method calls the FindRecImpl method to do the actual work of finding the longest increasing subsequence.

The FindRecImpl method takes the following parameters: - IList<T> values: The input list of elements. - Sequence<T> current: The current longest increasing subsequence. - int index: The current index in the input list. - IComparer<T> comparer: The comparer to use when comparing elements.

The FindRecImpl method works as follows: - If index is equal to the length of the input list, it means we have reached the end of the list. In this case, we return the current subsequence, which is the longest increasing subsequence. - If current is not empty and the current element in the input list is not greater than the last element in current, it means we cannot extend the current subsequence. In this case, we skip the current element and move on to the next element in the input list. - Otherwise, we have two options: - We can either skip the current element and move on to the next element in the input list. - We can extend the current subsequence by including the current element.

The FindRecImpl method calls itself recursively to try both options and returns the subsequence with the longest length.

The Max method is a helper method that returns the subsequence with the longest length.

Method 2: Find

  • Input: A list of elements IList<T> values and an optional IComparer<T> comparer to specify how to compare elements.
  • Output: An array of elements T[] representing the elements in the longest increasing subsequence.

This method uses a more efficient iterative algorithm to find the longest increasing subsequence. It starts by checking if the input list is null or empty. If it is, it throws an ArgumentNullException.

If the list is not null or empty, the method creates two arrays: pileTops and pileAssignments.

The pileTops array will store the elements at the top of each pile in the longest increasing subsequence. The pileAssignments array will store the index of the pile that each element in the input list belongs to.

The method then iterates over the input list and does the following for each element:

- It uses the BinarySearch method to find the index of the pile that the element belongs to. - If the element is not greater than the element at the top of the pile, it creates a new pile with the element at the top. - Otherwise, it replaces the element at the top of the pile with the new element. - It stores the index of the pile that the element belongs to in the pileAssignments array.

After iterating over the input list, the method creates a new array result to store the elements in the longest increasing subsequence. It then iterates over the pileAssignments array in reverse order and adds the elements that belong to the longest pile to the result array.

The Find method returns the result array, which contains the elements in the longest increasing subsequence.

Usage

The Main method in the code creates two sample input lists and calls the Find method to find the longest increasing subsequence for each list. The results are then printed to the console.

Output:

2, 3, 4, 5, 6
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

Source code in the csharp programming language

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public static class LIS
{
    public static IEnumerable<T> FindRec<T>(IList<T> values, IComparer<T> comparer = null) =>
        values == null ? throw new ArgumentNullException() :
            FindRecImpl(values, Sequence<T>.Empty, 0, comparer ?? Comparer<T>.Default).Reverse();

    private static Sequence<T> FindRecImpl<T>(IList<T> values, Sequence<T> current, int index, IComparer<T> comparer) {
        if (index == values.Count) return current;
        if (current.Length > 0 && comparer.Compare(values[index], current.Value) <= 0)
            return FindRecImpl(values, current, index + 1, comparer);
        return Max(
            FindRecImpl(values, current, index + 1, comparer),
            FindRecImpl(values, current + values[index], index + 1, comparer)
        );
    }

    private static Sequence<T> Max<T>(Sequence<T> a, Sequence<T> b) => a.Length < b.Length ? b : a;

    class Sequence<T> : IEnumerable<T>
    {
        public static readonly Sequence<T> Empty = new Sequence<T>(default(T), null);

        public Sequence(T value, Sequence<T> tail)
        {
            Value = value;
            Tail = tail;
            Length = tail == null ? 0 : tail.Length + 1;
        }

        public T Value { get; }
        public Sequence<T> Tail { get; }
        public int Length { get; }

        public static Sequence<T> operator +(Sequence<T> s, T value) => new Sequence<T>(value, s);

        public IEnumerator<T> GetEnumerator()
        {
            for (var s = this; s.Length > 0; s = s.Tail) yield return s.Value;
        }

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
}


public static class LIS
{
    public static T[] Find<T>(IList<T> values, IComparer<T> comparer = null) {
        if (values == null) throw new ArgumentNullException();
        if (comparer == null) comparer = Comparer<T>.Default;
        var pileTops = new List<T>();
        var pileAssignments = new int[values.Count];
        for (int i = 0; i < values.Count; i++) {
            T element = values[i];
            int pile = pileTops.BinarySearch(element, comparer);
            if (pile < 0) pile = ~pile;
            if (pile == pileTops.Count) pileTops.Add(element);
            else pileTops[pile] = element;
            pileAssignments[i] = pile;
        }
        T[] result = new T[pileTops.Count];
        for (int i = pileAssignments.Length - 1, p = pileTops.Count - 1; p >= 0; i--) {
            if (pileAssignments[i] == p) result[p--] = values[i];
        }
        return result;
    }

    public static void Main() {
        Console.WriteLine(string.Join(",", LIS.Find(new [] { 3, 2, 6, 4, 5, 1 })));
        Console.WriteLine(string.Join(",", LIS.Find(new [] { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 })));
    }
}


  

You may also check:How to resolve the algorithm Price fraction step by step in the C++ programming language
You may also check:How to resolve the algorithm Reverse a string step by step in the BQN programming language
You may also check:How to resolve the algorithm Soundex step by step in the Common Lisp programming language
You may also check:How to resolve the algorithm Copy a string step by step in the REBOL programming language
You may also check:How to resolve the algorithm Order two numerical lists step by step in the clojure programming language