【问题标题】:Sort a sequence (a sub-array in a array) in decreasing order by their elements (elements in the sub-array of an array)按元素(数组的子数组中的元素)按降序对序列(数组中的子数组)进行排序
【发布时间】:2021-03-14 19:23:15
【问题描述】:

我几天来一直在尝试使用 c# 找到解决此问题的方法。我能够按长度对它们进行排序,但我无法找出从最左边到最右边对数组进行排序的解决方案。

他们给出的提示是定义一个类 Sequence 来保存一系列元素。我们将实现IComparable<Sequence> 以按降序按长度比较序列(当长度相同时按降序按元素)。稍后我们将使用我们的 TreeMultiSet 类。在内部,我们将保留 S 的前 10 个子序列,即 P 的幸运子序列的多组,按长度降序保持(当长度相同时,它们的内容按降序排列)。当我们在多集中有 10 个子序列并且我们添加第 11 个序列时,由于定义了 IComparable<Sequence>,它将在顺序中占据正确的位置。之后我们可以删除第 11 个子序列,因为它不在前 10 个中

问题来了:

给定一个序列 P,其中包含 L 个整数 L (1

示例:给定 N = 5,序列 P = {1, 1, 2, 1, -1, 2, 3, -1, 1, 2, 3, 5, 1, -1, 2, 3}。序列S由P的以下13个子序列组成:

[1, -1, 2, 3, -1, 1] 
[1, 2, 1, -1, 2]
[3, -1, 1, 2]
[2, 3, -1, 1]
[1, 1, 2, 1]
[1, -1, 2, 3]
[1, -1, 2, 3]
[-1, 1, 2, 3]
[5, 1, -1]
[2, 3]
[2, 3] 
[2, 3]
[5]

我的解决方案:

实际上,在阅读提示时,我无法理解这个想法,所以我想出了另一种方法。

class Find
    {
        //Function to manually create an array with N elements
        public static int[] ArrCreate(int n, int[] Arr)
        {
            for (int i = 0; i < n; i++)
            {
                Arr[i] = Convert.ToInt32(Console.ReadLine());
            }
            return Arr;
        }
        //Create a Dictionary class type to hold sub-array with sum of sub-array equal to given number k
        public static Dictionary<int, ArrayList> SubSeqEqual2N()
        {
            Console.WriteLine("Input k: ");
            int k = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Input n element to create an Array: ");
            int n = Convert.ToInt32(Console.ReadLine());
            int[] Arr = new int[n];
            int[] newArr = ArrCreate(n, Arr);
            int keyIndex = 0;
            //ArrayList arlist = new ArrayList();
            Dictionary<int, ArrayList> SeqofLuckyArr = new Dictionary<int, ArrayList> { };
            //Create a loop to find sub-array with the sum equal to given number K.
            for (int i = 0; i < newArr.Length; i++)
            {
                int sum = 0;
                for (int j = i; j < newArr.Length; j++)
                {
                    sum = sum + newArr[j];
                    if (sum == k)
                    { 
                        //When sub-array with the sum equal to given number K is found then add them into a temp Arraylist, also increment the keyIndex.
                        keyIndex++;
                        ArrayList temp = new ArrayList();
                        for (int ko = i; ko <= j; ko++)
                        {
                            temp.Add(newArr[ko]);
                        }
                        //DEBUG PURPOSE
                        /*Console.Write("{");
                        foreach (var hehe in temp)
                        {
                            
                            Console.Write("{0}", string.Join(", ", hehe));
                            
                        }
                        Console.Write("}");
                        Console.WriteLine("");
                        arlist.AddRange(temp);*/
                        //Then add that temp array as value into a Dictionary <key,value>type with that KeyIndex.
                        SeqofLuckyArr.Add(keyIndex,temp);
                    }
                }
            }
            //DEBUG PURPOSE
            //My method to sort the sub-array in the Dictionary by sub-array length and by key index.
            foreach(KeyValuePair<int,ArrayList> kvp in SeqofLuckyArr.OrderByDescending(x => x.Value.Count).ThenBy(y => y.Key))
            {
                Console.Write("Key={0} ",kvp.Key);
                Console.Write(",");
                Console.Write("Value={ ");
                foreach (var hoho in kvp.Value)
                {
                    Console.Write("{0} ", string.Join(", ", hoho));
                }
                Console.WriteLine("}");
                Console.WriteLine("");
                arlist.AddRange(kvp.Value);
            }
            //DEBUG PURPOSE
            return SeqofLuckyArr;
        }
    }

我首先尝试找到总和等于给定数字 K 的子数组,然后将它们作为值添加到字典中,并将其键作为索引。然后使用 OrderByDecreasing 方法按长度对 -sub-array 进行排序。

结果:

Key=4 ,Value={ 1 -1 2 3 -1 1 }

Key=2 ,Value={ 1 2 1 -1 2 }

Key=1 ,Value={ 1 1 2 1 }

Key=3 ,Value={ 1 -1 2 3 }

Key=6 ,Value={ 2 3 -1 1 }

Key=7 ,Value={ 3 -1 1 2 }

Key=8 ,Value={ -1 1 2 3 }

Key=12 ,Value={ 1 -1 2 3 }

Key=11 ,Value={ 5 1 -1 }

Key=5 ,Value={ 2 3 }

Key=9 ,Value={ 2 3 }

Key=13 ,Value={ 2 3 }

Key=10 ,Value={ 5 }

但是结果和例子不一样。我的问题是我被困在“当长度相同时,序列按其元素降序排列:从最左边到最右边”。正如我认为的从左到右是从低到高的子数组的键索引。

谁能帮我找到按元素降序排列子数组的适当方法?如果我的版本也不适合在 SO 上提问,我将删除我的问题。

谢谢!

【问题讨论】:

  • 欢迎来到 SO。在要求我们做你的功课之前,非常感谢你看看你到目前为止所做的事情以及你已经得到的提示。从那里我们可以帮助您指出缺少的内容。
  • 您能告诉我们到目前为止您已经尝试过什么,以及您遇到的问题吗?您的问题提到使用TreeMultiSet,但您没有与我们分享,甚至没有解释它是什么。询问家庭作业很好,但正如stackoverflow.com/help/on-topic 中所解释的,...您必须真诚地尝试自己解决它。问题必须包括您迄今为止为解决该问题所做的工作的总结,以及您在解决该问题时遇到的困难的描述。 谢谢!
  • 感谢您的反馈,我会在问题中更新我迄今为止的工作。

标签: c# icomparable


【解决方案1】:

看来问题仅在于您的订购。序列的内容与示例相同。

首先,您订购的行不完全符合指定的规则:

foreach(KeyValuePair<int,ArrayList> kvp in SeqofLuckyArr
                                           .OrderByDescending(x => x.Value.Count)
                                           .ThenBy(y => y.Key))

[...] 按长度按降序排列。当长度相同时,序列按元素降序排列:[...]

按照序列长度的降序排列,第一个排序似乎是正确的 (OrderByDescending(x =&gt; x.Value.Count))。第二个排序当前按序列的“键索引”升序排序。根据“幸运子序列”的内容,这应该是降序/降序 (ThenByDescending)。

解决所有这些问题的一种方法是引入与给出的提示有点相似的IComparer 实现。下面的IComparer 能够将两个序列(int[])作为输入,并告诉两个序列中的哪一个应该在另一个之前(参见the documentation 以了解IComparer.Compare 的返回值的含义):

public class IntArrayComparer : IComparer<int[]>
{
    public int Compare(int[] x, int[] y)
    {
        // Ensure we don't get a null-ref exception further down
        if (x == null || y == null)
            // x should come before (-1) or after (1) y (default ascending order)
            return y == null ? -1 : 1;
        
        // If the lengths are different, the length is the first ordering priority
        if (x.Length != y.Length)
            // Use the built-in 'CompareTo' method for the 'int' type
            return x.Length.CompareTo(y.Length);
        
        // Lengths are the same, so we compare the contents
        for (var i = 0; i < x.Length; i++)
        {
            var comparison = x[i].CompareTo(y[i]);
            // If the elements in the two seq. are different, we return the ordering
            if (comparison != 0)
                return comparison;
        }
        return 0;
    }
}

现在前面提到的你的订单行变得更简单了(主观意见:)):

foreach(KeyValuePair<int,ArrayList> kvp in SeqofLuckyArr
                                           .OrderByDescending(x => x.Value, new IntArrayComparer()))

查看this fiddle 以了解订购部件的试运行。

提示:实际上,您甚至不需要将子序列存储在 Dictionary 中 - List 就足够了。

【讨论】:

  • 感谢您的解决方案。它就像一个魅力。我按照您的提示使用 List + IComparer 并将它们实现到我的代码中,并且输出满足要求。
【解决方案2】:

抱歉,回复晚了。在参考了上面的 Imcomparer 实现之后。我能够获得与示例相同的输出。这是我的代码,适用于与我面临相同问题的任何人。

class Find
    {
        public static int[] ArrCreate(int n, int[] Arr)
        {
            for (int i = 0; i < n; i++)
            {
                Arr[i] = Convert.ToInt32(Console.ReadLine());
            }
            return Arr;
        }
        public static void SubSeqEqual2N()
        {
            Console.WriteLine("Input k: ");
            int k = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Input n element to create an Array: ");
            int n = Convert.ToInt32(Console.ReadLine());
            int[] Arr = new int[n];
            int[] newArr = ArrCreate(n, Arr);
            //int keyIndex = 0;
            //ArrayList arlist = new ArrayList();
            //Dictionary<int, ArrayList> SeqofLuckyArr = new Dictionary<int, ArrayList> { };
            
            //Create a List of int array to store 
            List<int[]> luckyArray = new List<int[]>{ };
            for (int i = 0; i < newArr.Length; i++)
            {
                int sum = 0;
                for (int j = i; j < newArr.Length; j++)
                {
                    sum = sum + newArr[j];
                    if (sum == k)
                    {
                        //keyIndex++;
                        ArrayList temp = new ArrayList();
                        for (int ko = i; ko <= j; ko++)
                        {
                            temp.Add(newArr[ko]);
                        }

                        //Convert ArrayList temp into int array for applying IComparer.Compare<Int[],Int[]>
                        int[] luckySubArray = temp.ToArray(typeof(int)) as int[];
                        luckyArray.Add(luckySubArray);

                        //SeqofLuckyArr.Add(keyIndex,temp);
                    }
                }
            }
            var orderedSeq = luckyArray.OrderByDescending(s => s, new IntArrayComparer());           
            foreach(var seq in orderedSeq)
            {
                Console.Write("[ ");
                foreach (var i in seq)
                {
                    Console.Write("{0} ", string.Join(", ", i));
                }
                Console.Write(" ]");
                Console.WriteLine("");
            }

        }
    }
    public class IntArrayComparer : IComparer<int[]>
    {
        public int Compare(int[] x, int[] y)
        {
            // Ensure we don't get a null-ref exception further down
            if (x == null || y == null)
                // x should come before (-1) or after (1) y (default ascending order)
                return y == null ? -1 : 1;

            // If the lengths are different, the length is the first ordering priority
            if (x.Length != y.Length)
                // Use the built-in 'CompareTo' method for the 'int' type
                return x.Length.CompareTo(y.Length);

            // Lengths are the same, so we compare the contents
            for (var i = 0; i < x.Length; i++)
            {
                var comparison = x[i].CompareTo(y[i]);
                // If the elements in the two seq. are different, we return the ordering
                if (comparison != 0)
                    return comparison;
            }
            return 0;
        }
    }

还有输出:

[ 1 -1 2 3 -1 1  ]
[ 1 2 1 -1 2  ]
[ 3 -1 1 2  ]
[ 2 3 -1 1  ]
[ 1 1 2 1  ]
[ 1 -1 2 3  ]
[ 1 -1 2 3  ]
[ -1 1 2 3  ]
[ 5 1 -1  ]
[ 2 3  ]
[ 2 3  ]
[ 2 3  ]
[ 5  ]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 2015-10-18
    相关资源
    最近更新 更多