例题一:是否包含相同的数
class Solution {
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int each : nums){
if(set.contains(each))
return true;
set.add(each);
}
return false;
}
}
例题二:Single Number
class Solution {
public int singleNumber(int[] nums) {
int i = 0;
for(int each : nums)
i = i ^ each;
return i;
}
}
a ^ b ^ a = a ^ a ^ b = 0 ^ b = b
例题三:数组的交集
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
for(int each : nums1)
set1.add(each);
for(int each : nums2){
set2.add(each);
}
Set<Integer> small, big;
if(set1.size() > set2.size()){
small = set2;
big = set1;
}else{
small = set1;
big = set2;
}
int index = 0;
int[] res = new int[small.size()];
for(Integer each : small){
if(big.contains(each))
res[index++] = each;
}
return Arrays.copyOf(res, index);
}
}
Set有一个内建的方法:set1.retainAll(set2),直接返回一个set1和set2的交集。
例题四:Happy Number
方法一:Hash Set
如图所示,不论从什么树开始,经过几次计算,结果都会变成三位数且小于243。因为最大的三位数999计算后结果为243。也就是说,如果不是happy number,其计算结果就会一直在243内,因此必定会出现循环。所以问题的本质就是检测出这个循环。
class Solution {
public int getSum(int n){
int sum = 0;
int mod;
while(n != 0){
mod = n % 10;
sum += mod * mod;
n = n / 10;
}
return sum;
}
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
set.add(n);
while(true){
n = getSum(n);
if(set.contains(n))
break;
set.add(n);
}
return n == 1;
}
}
时间复杂度为O(logn),主要取决与getSum()这个方法的时间复杂度。空间复杂度也为O(logn)。
方法二:双指针
类似于在链表中检测循环,用一个快指针和一个慢指针,指针重合则说明有循环。
class Solution {
public int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}
public boolean isHappy(int n) {
int slowRunner = n;
int fastRunner = getNext(n);
while (fastRunner != 1 && slowRunner != fastRunner) {
slowRunner = getNext(slowRunner);
fastRunner = getNext(getNext(fastRunner));
}
return fastRunner == 1;
}
}
时间复杂度依然取决于getSum()这个方法的时间复杂度,为O(logn)。空间复杂度为O(1)。
方法三:数学推导
根据数学推算,其实只存在一个循环,如下:
4→16→37→58→89→145→42→20→4.
因此只要判断数字有没有落在这个循环中即可。
public boolean isHappy(int n) {
private static Set<Integer> cycleMembers =
new HashSet<>(Arrays.asList(4, 16, 37, 58, 89, 145, 42, 20));
while (n != 1 && !cycleMembers.contains(n)) {
n = getNext(n);
}
return n == 1;
}
或者下面这种也行,时间复杂度上多了一个常量,但是空间复杂度上少了一个常量。
public boolean isHappy(int n) {
while (n != 1 && n != 4) {
n = getNext(n);
}
return n == 1;
}