给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱).

问题:给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4.

分析:这里给出一种近乎求 所有的子单调序列的做法

这里的序列其实可以表示为一颗树来存储 如下图给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱).给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱).

 

 

 

故设计如下数据结构

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    public class Leaf
    {
        public int key = 0;
        public List<Leaf> leafs = new List<Leaf>();
        public Stack<int> stack = new Stack<int>();
        private void OutTree(Leaf leaf)
        {
            if (leaf.leafs.Count <= 0)
            {
                Stack<int> sk = new Stack<int>();
                foreach (var item in stack)
                {
                    sk.Push(item);
                }
                foreach (var item in sk)
                {
                    Console.Write(item + " ");
                }
                Console.WriteLine();
                
            }
            foreach (Leaf item in leaf.leafs)
            {
                stack.Push(item.key);
                OutTree(item);
                stack.Pop();
            }
        }
        public void OutTree()
        {
            OutTree(this);
        }
        public void OutTree(List<Leaf> list)
        {
            foreach (var item in list)
            {
                OutTree(item);
            }
        }
    }

}


 

这里有个输出树的算法 使用的是dfs回溯法,使用一个栈来保存父节点序列以方便输出

具体算法如下。 获取每个序列的开头 这些序列都是以逆序形式存在的发现了这个特点 可以求出每个的开头然后递归求出每个子序列的子序列的开头。。。构造树

代码如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace ConsoleApplication1
{
    class Program
    {
        //森林
        static Dictionary<int, List<int>> dicNums = new Dictionary<int, List<int>>();
        static void Main(string[] args)
        {

            List<int> nums = new List<int>() { 4,7,5,2,3,4,1,5,100,99,2,5,6,7,9,13,17};
            Leaf tree = GetTree(nums);
            for (int i = 0; i < tree.leafs.Count; i++)
            {
                dicNums.Add(tree.leafs[i].key, new List<int>());
            }
            tree.OutTree();
            Console.Read();

        }
        static void OutPutTree(Leaf tree)
        {
            for (int i = 0; i < tree.leafs.Count; i++)
            {
                Console.Write(tree.leafs[i].key + " ");
                OutPutTree(tree.leafs[i]);
            }
        }
        //去掉最少的为单增就是单增
        static Leaf GetTree(List<int> nums)
        {
            Leaf tree = new Leaf();
            CreateTree(nums, tree);
            return tree;

        }
        static void CreateTree(List<int> nums, Leaf tree)
        {
            //leaf的简单集
            Dictionary<int, List<int>> dic = new Dictionary<int, List<int>>();
            for (int i = 0; i < nums.Count; i++)
            {
                Leaf leaf = CreateLeaf(nums, tree, dic, i);
                if (leaf != null)
                {
                    tree.leafs.Add(leaf);
                }
            }
            if (tree.leafs.Count <= 0)
            {
                return;
            }
            foreach (var item in tree.leafs)
            {

                CreateTree(dic[item.key], item);
            }


        }

        private static Leaf CreateLeaf(List<int> nums, Leaf tree, Dictionary<int, List<int>> dic, int i)
        {
            bool flag = false;
            //key代表第一个数字
            foreach (Leaf item in tree.leafs)
            {
                if (nums[i] > item.key)
                {
                    dic[item.key].Add(nums[i]);
                    //不存在新节点
                    flag = true;
                }
            }
            if (flag)
            {
                return null;
            }
            if (!dic.ContainsKey(nums[i]))
            {

                //不存在num
                Leaf leaf = new Leaf();
                leaf.key = nums[i];
                dic.Add(nums[i], new List<int>());
                return leaf;
            }
            return null;
            
        }


    }
}

输出结果:

给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱).

 

 

给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱).

上一篇:Illustrator制作超强蓝色3D立体AI艺术字效果


下一篇:ubuntu 下make menuconfig的支持