【问题标题】:Finding the third largest element of an array by sorting it through TreeSet in a decreasing order通过 TreeSet 以降序对数组进行排序,找到数组的第三大元素
【发布时间】:2020-04-24 10:52:52
【问题描述】:

我试图通过树集按降序对数组进行排序来找到数组的第三大元素,但是某些测试用例对于某些输入值失败,而大多数测试用例对于某些输入值通过。

我的代码:

// { Driver Code Starts
import java.util.Scanner;
import java.util.*;
import java.io.*;

class ThirdLargestElement
{
    public static void main(String args[])
    {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while(t>0)
        {
            long n =sc.nextLong();
            Long arr[] = new Long[(int)n];
            for(long i=0;i<n;i++)
                arr[(int)i] = sc.nextLong();
            GfG g = new GfG();
            System.out.println(g.thirdLargest(arr));
        t--;
        }
    }
}// } Driver Code Ends
class GfG
{
    long thirdLargest(Long a[])
    {
    // Your code here
        if(a.length<3)
            return -1;
        else{
            TreeSet<Long> ts=new TreeSet<Long>(new myComparator());
            for(long i:a)
                ts.add(i);
            ArrayList<Long> al=new ArrayList<Long>(ts);
            return al.get(2);
        }
    }
}
class myComparator implements Comparator{
    public int compare(Object obj1,Object obj2){
        Long a=(Long) obj1;
        Long b=(Long) obj2;
        if(a<b)
            return 1;
        else if(a>b)
            return -1;
        else 
            return 0;
    }
}

失败的测试用例:

Link to the question where you can run the code

请解释为什么这段代码未能通过给定的测试用例。

【问题讨论】:

  • Scanner 获取数字时,只需将数字直接添加到TreeSet。然后使用方法descendingIterator()

标签: java arraylist comparator testcase treeset


【解决方案1】:

试试这个

class GfG {
    long thirdLargest(Long a[]) {
        Arrays.sort(a);
        List<Long> numbers = Arrays.asList(a);
        Collections.reverse(numbers);
        return numbers.size() >= 3 ? numbers.get(2) : -1;
    }
}

【讨论】:

  • 在执行此操作时for(long i:a) ts.add(i); Tress set 删除重复的元素。我们不能在Set 或它的实现类中插入重复值。这就是你的测试用例失败的原因
【解决方案2】:

您可以直接向TreeSet添加元素并使用流获得第三大数字,

while(t>0)
{
    long n =sc.nextLong();
    TreeSet<Long> ts=new TreeSet<>(Comparator.comparingLong(Long::longValue).reversed());
    for(long i=0;i<n;i++)
        ts.add(sc.nextLong());
    long thirdLast = ts.stream()
            .limit(3)
            .skip(2)
            .mapToLong(e->e)
            .findAny().orElse(0l);

    System.out.println(thirdLast);
    t--;
}

【讨论】:

  • 但是你能告诉我为什么我的测试用例没有通过,如给定的图片所示?对我来说,我没有看到我的代码有缺陷。
  • 在您的代码 Treeset 中删除重复值,这就是您的测试用例失败并且在获取元素时顺序不同的原因。在我的第一次尝试中,我得到了同样的结果,
【解决方案3】:

question 声明:

函数thirdLargest ... 有两个参数。第一个参数是数组 a[],第二个参数是数组的大小 (n)。

虽然问题表明数组是...

不同元素的数组

测试用例表明我们正在处理一个整数数组。

就个人而言,我认为不需要第二个方法参数,因为在 java 中,数组是一个对象,并且有一个 length 成员。所以我下面的实现只需要一个参数,即int的数组。可能 geeksforgeeks.org 的人只是将原本针对 C 语言的问题转换为 java,因为在 C 中,很难确定任何数组的大小。

TreeSet 中的每个元素都必须是一个对象,因此我们需要将int 数组中的元素转换为Integer 对象。 Autoboxing 将自动执行此操作,但我下面的代码包含显式转换。所以在方法中我创建了一个TreeSet。由于类Integer 实现了接口Comparable,因此默认的TreeSet 构造函数就足够了。我将int数组的所有元素添加到TreeSet中,然后得到一个降序迭代器,然后迭代到迭代器返回的第三个元素,也就是方法需要返回的值。

    int thirdLargest(int[] arr) {
        int third = -1;
        if (arr != null  &&  arr.length > 2) {
            TreeSet<Integer> set = new TreeSet<Integer>();
            for (int elem : arr) {
                set.add(Integer.valueOf(elem));
            }
            Iterator<Integer> iter = set.descendingIterator();
            if (iter.hasNext()) {
                iter.next();
                if (iter.hasNext()) {
                    iter.next();
                    if (iter.hasNext()) {
                        third = iter.next().intValue();
                    }
                }
            }
        }
        return third;
    }

当然,如果你想忽略原始问题强加的条件,你可以使用stream API获得第三大元素

IntStream.of(2, 4, 1, 3, 5)
         .boxed()
         .sorted(Collections.reverseOrder())
         .collect(Collectors.toList()).get(2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 2014-02-16
    • 1970-01-01
    相关资源
    最近更新 更多