zoukankan      html  css  js  c++  java
  • [LeetCode] Contains Duplicate II

    Given an array of integers and an integer k, find out whether there there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between iand j is at most k.

    思路:这里需要注意两个地方,一是at most k  而是时间复杂度是O(n^2)时会TLE

    代码:自己首先想到的是双重循环,时间复杂度O(n^2),结果肯定就是TLE

        public boolean containsNearbyDuplicate(int[] nums, int k) {
            int i=0,j=1;
            while(i<nums.length)
            {
                j=1;
                while(i+j<nums.length && j<=k && nums[i]!=nums[i+j])
                {
                    j++;
                }
                if(i+j<nums.length && nums[i]==nums[i+j])
                    return true;
                i++;
            }
            return false;
        }

    明显,题目要求时间复杂度更低的算法,比如O(n)

    像这样的在临近找数值的题目,一般采用哈希表或者哈希集合去实现一个窗口。

    在本题中采用哈希集合去实现一个长度为K的窗口,end不断向前走,当碰到end-start>k时,就remove掉nums[start],并且移动start。在K步中碰到相同的数,就返回true

    实质就是,将前面的至多K个数存在哈希set里面,然后去找是否存在。时间复杂度O(n)

        public boolean containsNearbyDuplicate(int[] nums, int k) {
            Set<Integer> set=new HashSet<Integer>();
            int start=0,end =0;
            for(int i=0;i<nums.length;i++)
            {
                if(!set.contains(nums[i]))
                {
                    set.add(nums[i]);
                    end++;
                }
                else return true;
                if(end-start>k)
                {
                    set.remove(nums[start]);
                    start++;
                }
            }
            return false;
        }

    优化:

    扩展:

    1、Given an array of integers and an integer k, return true if and only if there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and j is at most k.

    上面那个题是存在,这个题是存在且只存在一组

     这里采用的是哈希图,因为假如使用hashset的话,可能出现这样的情况,{1,2,1,1}  2,由于hashset不存储重复的值,当start=0,end=3时,需要删除1,在进行判断的时候start=1,end=3,而set里面的1已经被删除,会出现错误判断,采用哈希图,保证窗口中有K个值,不管是否重复。定义变量d记录重复出现的次数,这里需要注意的是不管是否存在end始终要往前加。

        public boolean containsNearbyDuplicate(int[] nums, int k) {
            Map<Integer,Integer> map=new HashMap<Integer,Integer>();
            int start=0,end =0;
            int d=0;
            for(int i=0;i<nums.length;i++)
            {
                if(map.containsValue(nums[i]))
                {
                    d++;
                }
                map.put(i,nums[i]);
                end++;
                if(end-start>k)
                {
                    map.remove(start);
                    start++;
                }
            }
            return d==1;
        }

    2、Given an array of integers, find out whether there are two distinct indices i and j in the array such that the difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.

    思路:采用两重遍历,TLE

        public boolean containsNearbyDuplicate(int[] nums, int k,int t) {
            if(nums.length==0)return false;
            Set<Integer> set=new HashSet<Integer>();
            int start=0,end =0;  //横向窗口
            for(int i=0;i<nums.length;i++)
            {
                Iterator<Integer> iterator=set.iterator();
                while(iterator.hasNext())
                {
                    int x=iterator.next();
                    if(x>=nums[i]-t && x<=nums[i]+t)
                    {
                        return true;
                    }
                }
                set.add(nums[i]);
                end++;
                if(end-start>k)
                {
                    set.remove(nums[start]);
                    start++;
                }
            }
            return false;
        }

    采用treeset

    import java.util.SortedSet;
    import java.util.TreeSet;
    
    public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            if(k<1 || t<0 || nums==null || nums.length<2) return false;
            SortedSet<Long> set = new TreeSet<Long>();  
              
            for(int j=0; j<nums.length; j++) {  
                SortedSet<Long> subSet =  set.subSet((long)nums[j]-t, (long)nums[j]+t+1);  
                if(!subSet.isEmpty()) return true;  
                  
                if(j>=k) {  
                    set.remove((long)nums[j-k]);  
                }  
                set.add((long)nums[j]);  
            }  
            return false; 
        }
    }

    采用sub的时候,起始点是包含在内的,而终点是不包含在内的,所以这里会产生超过Integer.maxValue的情况(见红色字体),所以需要使用Long

  • 相关阅读:
    CodePlus#4 最短路
    最大子矩阵问题———悬线法
    Luogu P3393 逃离僵尸岛
    SCOI2011 糖果
    关于页面的跳转添加参数(比如id啥的)
    npm 常用命令
    移动开发中的一些基本的思想,和需要注意的细节技巧之处
    Mock模拟后台数据接口--再也不用等后端的API啦
    普及知识
    移动端JD首页H5页面
  • 原文地址:https://www.cnblogs.com/maydow/p/4642140.html
Copyright © 2011-2022 走看看