Leetcode题库-存在重复元素3(java语言版)

题目描述:

给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ

示例 1:

输入: nums = [1,2,3,1], k = 3, t = 0
输出: true

示例 2:

输入: nums = [1,0,1,1], k = 1, t = 2
输出: true

示例 3:

输入: nums = [1,5,9,1,5,9], k = 2, t = 3
输出: false

     这道题和上一道题特别相似,只是将两个元素相同变成了两个元素差的绝对值小于的与一个数(范围就变成了num[i]-t---num[i]+t)。这样的话就有问题,就要考虑不能int越界,所以进行操作时转化为long就可以。(因为abs函数在int越界时会失去作用)

     具体思路还是滑动窗口和查找表。滑动窗口的长度是查找表的长度,不能大于k,大于k就将查找表最左边的元素删去,然后在进行比较。比较两个数的绝对值的时,滑动窗口中额所有元素与当前的元素进行计算比较,然后得出结果。

    这道题也可以用暴力for,不过还是不推荐,虽然简单,但是时间复杂度高,很容易超时。

    代码如下:

 int a [] = new int[]{-1,2147483647};
        int k =1;
        int t =2147483647;


//        第一种方法,暴力for(考点就是Integer.MAX_VALUE 和Integer.MIN_VALUE 的临界点,所以用abs取绝对值的时候,-2147483648的绝对值还是-2147483648)
//        for (int i=0;i<a.length;i++){
//           for (int j = i+1;j<a.length;j++){
//               if (Math.abs ( (long) a[i]-(long) a[j] )<=t &&Math.abs ( (long) i-(long) j )<=k){
//                   System.out.println(i+" "+j);
//                   System.out.println("true");
//               }
//           }
//        }
//        System.out.println("false");
//        第二种方法:滑动窗口加查找:维持滑动窗的大小最大为 k,遍历每一个元素 nums[i],在活动窗口中寻找 |one-nums[i]| <= t,即窗口中的元素范围为:[one-t … one+t] 之间。
//        map和set都可以,本题推荐用set,因为要求不是两个元素相等。
//        Set<Integer> set = new HashSet (  );
//        for (int i =0;i<a.length;i++){
//           if ((long)t==0){
////               判断是否存在重复的元素,存在时并且set长度未大于k返回true。
//               if (set.contains (  a[i] )){
//                   System.out.println("true");
//               }
//           }else {
//               for (int num:set){
////                  判断是否小于等于t。
//                   if (Math.abs ((long)num-(long)a[i])<=t){
//                       System.out.println("true");
//                   }
//               }
//           }
//           set.add ( a[i] );
//           if (set.size ()>k){
//               set.remove ( a[i-k] );//删除滑动窗口最左端的元素
//           }
//        }
//        System.out.println("false");.

        Map<Integer,Integer> map = new HashMap (  );
        for (int i=0;i<a.length;i++){
//            当t=0时,证明两个元素相等,集合中存在这个元素,且未超过k,则证明存在
            if ((long)t==0){
                if (map.containsKey ( a[i] )){
                    System.out.println("true");
                }
            }else {
                //判断滑动窗口内的元素减去数组元素是否小于等于t,(遍历hash判断绝对值是否小于t)
                for (int key:map.keySet ()) {
                    if (Math.abs ( (long) key - (long) a[i] ) <= t) {
                        System.out.println ( "true" );
                    }
                }
            }
//            添加元素
            map.put ( a[i],i );
            if (map.size ()>k){//滑动窗口的大小不小于k,若大于k是,就将最左边的元素删除。
                map.remove ( a[i-k] );
            }
        }
       System.out.println("false");

查找表用set,用map都是可以的。我两种都写了,可以参考一下。

执行结果:

执行用时:

     总结:这道题和上一道题都用到了查找表的相关技术,还有滑动窗口的知识,选择合适的查找表和滑动窗口技巧,可以让我们事半功倍。这三道题特别值得细细品味。

   2019-3-28


发布了43 篇原创文章 · 获赞 6 · 访问量 6656

猜你喜欢

转载自blog.csdn.net/weixin_37850160/article/details/88859055