在Java算法专栏,博主会分 1. 解题思路 2. 代码实现及解析 3. 总结 三部分整理算法解析,作为我们笔试手撕算法的资本,博主会慢慢整理出更多的不同的算法篇章,敬请期待!进去狠狠刷题~~
预祝大家笔试、面试轻松过,拿下满意offer~
文章目录
一、随机链表的复制
题目简单说就是复刻一个和原随机链表结构、指向完全一样的新链表,新链表所有节点都是全新的,指针绝对不能指向原链表的任何节点。
核心要求就2点:
-
新节点的 val 、 next 指向、 random 指向,和原链表对应节点完全一致;
-
新链表的所有指针,只能指向新链表自己的节点,不能碰原链表。
解题思路
哈希表映射法:用map存<原节点,新节点>,一次遍历建节点,二次遍历补next/random。
代码实现及解析
java
import java.util.HashMap;
import java.util.Map;
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
class Solution {
public Node copyRandomList(Node head) {
Map<Node,Node> map=new HashMap<>();//map来存放"旧-新"节点对
Node cur=head;
//遍历原链表,对于每一个节点,构造出一个新的节点(val值复制),并将这样的新旧两个节点作为一个键值对存入map中
while(cur!=null){
Node node=new Node(cur.val);
map.put(cur,node);
cur=cur.next;
}
//再遍历一遍旧链表,这一遍有了map的作用,我们再遍历旧链表的同时就可以对新链表节点之间的一一对应关系搭建好
cur=head;
while(cur!=null){
map.get(cur).next=map.get(cur.next);//根据旧链表遍历结果将新链表的节点链接
map.get(cur).random=map.get(cur.random);//根据旧链表的random值,新链表也具有一样的对应关系,将其填入
cur=cur.next;
}
return map.get(head);
}
}
总结
充分利用了map能储存key与val的对应关系的特点
二、前K个高频单词
给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序排序。
解题思路
- 先利用Map统计好各单词出现的次数
- 再使用经典的topK问题的解题法解题
代码实现
java
import java.util.*;
//构造一个比较器,作为PriorityQueue的参数
class myComparator implements Comparator<Map.Entry<String,Integer>> {
public int compare(Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2){
if(o1.getValue().equals(o2.getValue())){//如果出现次数一样,则按照字典序排序
return o2.getKey().compareTo(o1.getKey());
}else{//谁的val(出现次数)小,谁就排在前面
return o1.getValue().compareTo(o2.getValue());
}
}
}
class Solution {
public List<String> topKFrequent(String[] words, int k) {
//1.先将各单词出现的次数统计出来
Map<String,Integer> map=new HashMap<>();
for(String str:words){
if(!map.containsKey(str)){
map.put(str,1);
}else{
int val=map.get(str);
map.put(str,val+1);
}
}
//2.再来使用topK问题的解法
//建立小根堆
PriorityQueue<Map.Entry<String,Integer>> minHeap=new PriorityQueue<>(new myComparator());
//遍历map
for(Map.Entry<String,Integer> entry:map.entrySet()){
if(minHeap.size()<k){//先用前k个map节点建个小根堆
minHeap.offer(entry);
}else{//后面的节点再依据数据值按不同逻辑处理
Map.Entry<String,Integer> top=minHeap.peek();//堆顶元素
if(entry.getValue().compareTo(top.getValue())>0){//若该节点的val值大于top的val值,则弹出top,插入该节点
minHeap.poll();
minHeap.offer(entry);
}else if(entry.getValue().compareTo(top.getValue())==0){//若该节点的val值等于top的val值,则按照字典序排序
if(entry.getKey().compareTo(top.getKey())<0){
minHeap.poll();
minHeap.offer(entry);
}
}
}
}
//将minHeap中每个节点的key值,也就是单词一一取出(此时还是升序)
List<String> list=new ArrayList<>();
while(!minHeap.isEmpty()){
String str=minHeap.poll().getKey();
list.add(str);
}
//将list反转
Collections.reverse(list);
return list;
}
}
觉得文章对你有帮助的话就点个赞,收藏起来这份免费的资料吧!也欢迎大家在评论区讨论技术、经验