1.只出现一次的数字
public int singleNumber(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
for (int x:nums) {
Integer count = map.get(x);
if (count == null) {
map.put(x,1);
}else {
map.put(x,count+1);
}
}
//System.out.println(map);
for (Map.Entry<Integer,Integer> entry:map.entrySet()) {
if (entry.getValue().equals(1)) {
return entry.getKey();
}
}
return 0;
}
我们可以利用键值对来进行解决,Key为数组中的每个元素,value为每个数字出现的次数,我们创建一个Map,遍历数组,如果通过key不能找到,则把(key,1)加入到map里,表示key这个关键字出现一次,如果找到了,就把(x,count+1)存到里面,因为当key重复时,会自动把以前的value修改为当前要插入的value,当整个数组遍历完后,我们的Map也就完成了,通过遍历Map来找出value为1的关键字,就是我们要找的出现一次的数。
但是这个问题还可以用另一种方法来解决:
public int singleNumber2(int[] nums) {
int ret = 0;
for (int x:nums) {
ret^=x; //a^b^b=a
}
return ret;
}
简单的几行代码就可以,但其中的内涵并不是那么简单。这个是通过一个数异或两个相同的数,最终结果还是他本身这个特性来解决的,这个思路值得我们去学习。
2.复制带随机指针的链表
节点结构如下:
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
题中要求的是深拷贝,就需要我们去拷贝链表中的每一个节点,每个节点之间的关系也要和原来一样。
public Node copyRandomList(Node head) {
Map<Node,Node> map = new HashMap<>();
for (Node cur = head;cur!=null;cur=cur.next) {
map.put(cur,new Node(cur.val));
}
for (Node cur = head;cur!=null;cur=cur.next) {
Node newNode = map.get(cur);
newNode.next = map.get(cur.next);
newNode.random = map.get(cur.random);
}
return map.get(head);
}
我们依然可以用Map来解决,通过遍历旧的链表,把旧的链表中的节点当为key,然后通过旧链表的val值新建的节点作为value,形成通过旧节点可以找到新节点的关系。
然后再次去遍历链表,通过旧的节点,找到新的节点,新节点的next和random也就可以通过旧节点的next和random来找到,最后通过旧链表的头节点找到新链表的头节点并返回,这个问题就解决了。
3.宝石与石头
public int numJeweIsInStones(String J,String S) {
int count = 0;
Set<Character> set = new HashSet<>();
for (int i = 0;i<J.length();i++) {
set.add(J.charAt(i));
}
for (int i = 0;i<S.length();i++) {
if (set.contains(S.charAt(i))) {
count++;
}
}
return count;
}
判断是否存在问题,我们想到可以用set,判断s中有多少是宝石,我们可以将J存到set里面,然后遍历S中的每一个,看set里面是否存在,若存在,则count加一,遍历结束后返回最终的count,就是宝石的数目。
4.前K个高频单词
public List<String> topKFrequent(String[] words,int k) {
Map<String,Integer> map = new HashMap<>();
for (String x:words) {
Integer value = map.get(x);
if (value == null) {
map.put(x,1);
}else {
map.put(x,value+1);
}
List<String> result = new ArrayList<>(map.keySet());
Collections.sort(result, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//在这个匿名内部类里面可以访问到上面的map变量
int count1 = map.get(o1);
int count2 = map.get(o2);
if (count1 == count2) {
return o1.compareTo(o2);//默认字典序
}
return count2-count1;
}
});
//取前K个
return result.subList(0,k);
}
}
首先创建一个Map,key为字符串数组中的元素,value为每个元素出现的次数,由于函数的返回值类型是List,所以我们创建一个List把Map里面的key传到链表里面,有个keySet()操作,然后利用标准库中的排序对类进行排序,这里需要重写比较器,通过Key获取到每个数出现的次数,如果两个数相同,就按系统默认的字典序进行排序,否则就按从大到小进行排序,排好之后,直接利用链表的subList截取操作截取前K个元素返回,问题就完成了。