题目如下:
Given two arrays, write a function to compute their intersection.
Example:
Given nums1 = [1, 2, 2, 1]
, nums2 = [2, 2]
, return [2]
.
Note:
- Each element in the result must be unique.
- The result can be in any order.
<span style="font-size:14px;"> public int[] intersection(int[] nums1, int[] nums2) {
HashSet intersectSet = new HashSet();
for(int i=0;i<nums1.length;i++){
Integer temp = Integer.valueOf(nums1[i]);
if(!intersectSet.contains(temp)){
intersectSet.add(temp);
}
}
ArrayList<Integer> result = new ArrayList<Integer>();
for(int j=0;j<nums2.length;j++){
Integer temp2 = Integer.valueOf(nums2[j]);
if(intersectSet.contains(temp2)){
result.add(temp2);
intersectSet.remove(temp2);
}
}
int[] finalResult = new int[result.size()];
for (int k=0;k<result.size();k++){
finalResult[k] = result.get(k).intValue();
}
return finalResult;
}</span>
首先声明一个HashSet类型的对象intersectSet,然后先把数组nums1转化为集合intersectSet。根据intersectSet中已有的元素,判断nums2中有哪些元素是nums1的交集,并将这些元素add进一个ArrayList类型的对象中,然后将intersectSet中的该元素删除(防止以后的循环中出现相同元素然后重复add到ArrayList这种情况)。最后就是将ArrayList转化为int型数组返回即可。真的是炒鸡容易想到的思路呢。
然后是LeetCode讨论区大神的各种套路,第一种和我的方法思路一样,写法也差不多,这里就不再多进行解释了,代码如下:
</pre><pre style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 9.5px; margin-top: 0px; margin-bottom: 10px; line-height: 1.42857; word-break: break-all; word-wrap: break-word; color: rgb(51, 51, 51); border: 1px solid rgb(204, 204, 204); border-radius: 0px; max-height: 600px; background-color: rgb(245, 245, 245);"><code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 0px; color: inherit; border-radius: 0px; word-wrap: normal; min-width: 100%; background-color: transparent;"><span style="font-size:14px;">public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet<>();
Set<Integer> intersect = new HashSet<>();
for (int i = 0; i < nums1.length; i++) {
set.add(nums1[i]);
}
for (int i = 0; i < nums2.length; i++) {
if (set.contains(nums2[i])) {
intersect.add(nums2[i]);
}
}
int[] result = new int[intersect.size()];
int i = 0;
for (Integer num : intersect) {
result[i++] = num;
}
return result;
}</span></code>
第二种是通过先将两个数组进行排序,然后通过比较元素大小的方法确定该元素是不是交集的一部分,如果是的话就添加到一个HashSet的对象中(这里就算相同元素多次add到HashSet中也没关系,HashSet满足集合的基本性质,add多少次相同元素,HashSet中也只会保留一个的)。最后,将HashSet转化为int类型数组即可,代码如下:
<span style="font-size:14px;">public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet<>();
Arrays.sort(nums1);
Arrays.sort(nums2);
int i = 0;
int j = 0;
while (i < nums1.length && j < nums2.length) {
if (nums1[i] < nums2[j]) {
i++;
} else if (nums1[i] > nums2[j]) {
j++;
} else {
set.add(nums1[i]);
i++;
j++;
}
}
int[] result = new int[set.size()];
int k = 0;
for (Integer num : set) {
result[k++] = num;
}
return result;
}</span>
第三种是使用二分查找的方法,先讲给定数组其中之一进行排序(这里以nums2为例),然后查找nums1中的每一个元素是否在nums2中,由于nums2是已经排好顺序的,所以我们可以使用“二分法”来提高查找的效率,代码如下:
<span style="font-size:14px;"> public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet<>();
Arrays.sort(nums2);
for (Integer num : nums1) {
if (binarySearch(nums2, num)) {
set.add(num);
}
}
int i = 0;
int[] result = new int[set.size()];
for (Integer num : set) {
result[i++] = num;
}
return result;
}
public boolean binarySearch(int[] nums, int target) {
int low = 0;
int high = nums.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (nums[mid] == target) {
return true;
}
if (nums[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return false;
}</span>
总结一下,遇到这类“查找数据中相同部分”的问题,使用各种Hash类型的对象往往是最便捷的方式,时间复杂度更小。上述三种讨论区方法时间复杂度分别为O(n),O(nlogn),O(nlogn)。为什么后两种是时间复杂度都是O(nlogn)呢,因为它们都用到了排序算法,即Arrays.sort()方法,而又由于Arrays.sort()是使用归并排序实现的,所以时间复杂度是O(nlogn)。归并排序详情:https://zh.wikipedia.org/wiki/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F