leetcode:Contains Duplicate

217. Contains Duplicate

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

1 先排序再比较

Time complexity: O(N lg N), memory: O(1) - not counting the memory used by sort

public class Solution {
    public boolean containsDuplicate(int[] nums) {
        Arrays.sort(nums);
        for(int i = 0; i < nums.length-1; i++) {
            if(nums[i] == nums[i+1]) {
                return true;
            }
        }
        return false;
    }
}
2 利用hash值

public class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set = new HashSet<Integer>();
        for(int c: nums) {
            if(set.contains(c)) {            //先比较是否相等,在进行添加
                return true;
            }
            set.add(c);
        }
        return false;
        
    }
}
关于HashSet的发现:
1:HashSet是一个Set,也就是所谓的集合。集合的概念是元素在集合中无序、唯一。无序对于计算机来说没有什么意义,因为计算机总要按照一定的顺序存储对象。唯一是怎么实现的呢?名字上说的已经很清楚了。HashSet,就是通过其中的元素(对象)的hashconde来区分对象是否唯一的。所以,HashSet的对象中着一个集合中对象的hashcode的list,每次执行set.add(obj)的时候,都会取出obj的hashcode与其内部的list进行比较,如果没有与之相等的,就加进set里去,同时把那个obj的hashcode加到list里面去;如果有相等的,就再调用obj的equals方法与各个对象进行比较,如果没有相等的,就加入到set里面去,如果还有相等的,就不执行加入操作。
1) 对象相等则hashCode一定相等;
2) hashCode相等对象未必相等。
public Set add(Object obj){
  int code = obj.hashCode();
  if(code not in this.hashcodeList){//如果没有于之相等的hashcode。就将obj加入
   this.valueList.add(obj);
   this.hashcodeList.add(code);
   return true;
  }else{//否则看看是否有与之equals相等的。
   if(code in this.valueList){//有,add失败
    return false;
   }else{//没有,add成功
    this.valueList.add(obj);
    return true;
   }
  }
 }
其实相当于执行了一次contains方法,根据contains方法的返回值决定是否真的add。
 
 
 
也就是说HashSet在确定已经包含某个对象相等的标准是:它们的hashcode相等或者它们的equals方法返回true。
 
郁闷了半天,怎么先比较hashcode呢?
 
总算知道了为什么覆盖了toString()后不覆盖hashcode(),Eclipse会给出警告。原来这两个都和对象的相等比较有关系啊。Object的hashcode就是根据对象的内存地址计算出了,保证不重复。而String的hashcode就不一样了,只要字符串的内容相等(equals返回true),它们的hashcode就是相等的。
 
特别需要注意的是HashSet是有缓存的,第一次contains执行完后会缓存所有的hashcode,以后再调用contains比较的时候使用缓存的hashcode(就是那个list),所以说HashSet最好只用来存储不可变对象,否则contains方法的返回值是不准确的。
 
一下原则要记住:
1:对于不可变类(String、Integer、以及自己定义的不可变类等),要保证equals返回true的时候,它们的hashcode的值相等。
2:对于不可变类,也要尽量满足1。以避免出现上面说的Set比较时出现的问题。
3:覆盖一个类的equals方法的时候,要注意可交换性,要保证a.equals(b)的值一定等于b.equals(a)的数值。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值