Copyright © 2015 Powered by MWeb, Theme used GitHub CSS.
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入: nums1 = \([1,2,2,1]\), nums2 = \([2,2]\)
输出: \([2,2]\)
示例 2:
输入: nums1 = \([4,9,5]\), nums2 = \([9,4,9,8,4]\)
输出: [4,9]
说明:
进阶:
问题比较简单。可以遍历两个数组,获得数字出现的频次,然后对比两个频次即可。或者可以直接排序两个数组,然后使用两个指针分别遍历数组即可。
频次法
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
if(nums1.length > nums2.length) {
return intersect(nums2, nums1);
}
//这里使用hashmap,因为数字是不定长的。
Map<Integer, Integer> map1 = new HashMap<>(nums1.length);
for (Integer i: nums1) {
Integer count = map1.get(i);
if (count == null) {
map1.put(i, 1);
} else {
map1.put(i, count+1);
}
}
Map<Integer, Integer> map2 = new HashMap<>(nums2.length);
for (Integer i: nums2) {
Integer count = map2.get(i);
if (count == null) {
map2.put(i, 1);
} else {
map2.put(i, count+1);
}
}
Iterator iter = map1.entrySet().iterator();
List<Integer> result = new LinkedList();
//遍历两个频次map即可,这里使用小的那个map遍历。可以减少查询次数
while(iter.hasNext()) {
Map.Entry<Integer, Integer> entry = (Map.Entry) iter.next();
Integer key = entry.getKey();
Integer val1 = entry.getValue();
Integer val2 = map2.get(key);
if(val2 != null) {
int count = Math.min(val1, val2);
while (count-- > 0) {
result.add(key);
}
}
}
//最终生成结果,因为没有用从List到int[]的方便转换方法。
int[] res = new int[result.size()];
for(int m=0;m<res.length;m++)
{
res[m]=result.get(m);
}
return res;
}
}
排序遍历法
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
if(nums1.length > nums2.length) {
return intersect(nums2, nums1);
}
List<Integer> result = new LinkedList();
//排序两个数组
Arrays.sort(nums1);
Arrays.sort(nums2);
//遍历两个数组
for (int i = 0,j=0; i<nums1.length && j<nums2.length;) {
//相等则加入result
if (nums1[i] == nums2[j]) {
result.add(nums1[i]);
i++;
j++;
} else if (nums1[i] < nums2[j]){
// 这里注意只有其中一个往前推进。
i++;
} else {
j++;
}
}
int[] res = new int[result.size()];
for(int m=0;m<res.length;m++)
{
res[m]=result.get(m);
}
return res;
}
}
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点\(c1\)开始相交。
示例 1:
输入: intersectVal = 8, listA = \([4,1,8,4,5]\), listB = \([5,0,1,8,4,5]\), skipA = 2, skipB = 3
**输出:**Reference of the node with value = 8
**输入解释:**相交节点的值为 \(8 \)(注意,如果两个列表相交则不能为 \(0\))。从各自的表头开始算起,链表 A 为 \([4,1,8,4,5]\),链表 B 为 \([5,0,1,8,4,5]\)。在 A 中,相交节点前有\(2\)个节点;在 B 中,相交节点前有\(3\)个节点。
示例 2:
**输入:**intersectVal = 2, listA = \([0,9,1,2,4]\), listB = \([3,2,4]\), skipA = 3, skipB = 1
**输出:**Reference of the node with value = 2
**输入解释:**相交节点的值为 \(2\) (注意,如果两个列表相交则不能为 \(0\))。从各自的表头开始算起,链表 A 为 \([0,9,1,2,4]\),链表 B 为 \([3,2,4]\)。在 A 中,相交节点前有 \(3\) 个节点;在 B 中,相交节点前有 \(1\) 个节点。
示例 3:
**输入:**intersectVal = 0, listA = \([2,6,4]\), listB = \([1,5]\), skipA = 3, skipB = 2
**输出:**null
**输入解释:**从各自的表头开始算起,链表 A 为 \([2,6,4]\),链表 B 为 \([1,5]\)。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
**解释:**这两个链表不相交,因此返回 null。
注意:
注意到这样一个事实,如果两个链表相交,那么在相交节点前面的两个分叉上,正好相差这两个链表长度之差的元素个数。因此,首先遍历两个链表,得到链表长度,然后长度更长的链表先往前走长度之差的步数,然后后面两个链表向前推进到相等即为结果。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
//首先遍历两个链表查询长度
int l1 = 0;
ListNode h1 = headA;
while (h1 != null) {
h1 = h1.next;
l1++;
}
int l2 = 0;
ListNode h2 = headB;
while (h2 != null) {
h2 = h2.next;
l2++;
}
//长度更长的那个需要先走几步,直到两个长度相等时才同时前进。
h1 = headA;
h2 = headB;
int dif = l1-l2;
if (dif > 0) {
while(dif-- >0) {
h1 = h1.next;
}
} else if (dif < 0) {
while(dif++ < 0) {
h2 = h2.next;
}
}
int len = Math.min(l1, l2);
while (h1 != h2){
h1 = h1.next;
h2 = h2.next;
}
return h1;
}
}
Copyright © 2015 Powered by MWeb, Theme used GitHub CSS.