1. 只出现一次的数字
只出现一次的数字OJ链接
分析:
//最佳的解决方式是对所有元素进行异或
//异或的结果就是只出现一次的数据
//在这个地方的目的是为了练习Map和Set
//直接将nums中的元素往HashSet中插入
//插入时,如果该元素已经存在,则删除
class Solution {
public int singleNumber(int[] nums) {
Set<Integer> s=new HashSet<>();
for(int i=0; i<nums.length; i++){
if(!s.add(nums[i])){
s.remove(nums[i]);
}
}
Iterator<Integer> iterator=s.iterator();
return iterator.next();
}
}
2. 复制带随机指针的链表
复制带随机指针的链表OJ链接
分析:
方式一(链表方式)
1.给原链表中每个结点之后插入一个值相等的结点
2.给新插入结点的随机域引用赋值
3.将原链表中新插入的结点拆下来
class Solution {
public Node copyRandomList(Node head) {
if(null==head){
return head;
}
//1.原链表每个结点之后插入一个值相等的新结点
Node cur=head;
while(cur!=null){
Node newNode=new Node(cur.val);
newNode.next=cur.next;
cur.next=newNode;
cur=newNode.next;
}
//2.给新插入的结点的随机引用赋值
cur=head;
while(cur!=null){
Node newNode=cur.next;
if(cur.random!=null){
newNode.random=cur.random.next;
}
cur=newNode.next;
}
//3.将新插入的结点插下来
Node newHead=head.next;
cur=head;
while(cur.next!=null){
Node curnext= cur.next;
cur.next=curnext.next;
cur=curnext;
}
return newHead;
}
}
方式二(Hash)
HashMap:
K-----旧结点
V-----新结点
1.将原链表遍历一遍,遇到每个结点cur就创建一个新结点newNode ,然后往hashmap中插入
2.链接新链表并且给随机域赋值
class Solution {
public Node copyRandomList(Node head) {
if(null==head){
return head;
}
Map<Node,Node> m=new HashMap<>();
Node cur=head;
while(cur!=null){
m.put(cur,new Node(cur.val));
cur=cur.next;
}
cur=head;
while(cur!=null){
//1.将新插入的结点链接起来
m.get(cur).next=m.get(cur.next);
//2.给新插入的结点的随机指针域赋值
m.get(cur).random=m.get(cur.random);
cur=cur.next;
}
return m.get(head);
}
}
3. 宝石与石头
class Solution {
public int numJewelsInStones(String jewels, String stones) {
Map<Character,Integer> m=new HashMap<>();
//1.统计每个石头出现的次数
for(int i=0;i<stones.length();++i){
Character ch=stones.charAt(i);
m.put(ch,m.getOrDefault(ch,0)+1);
}
//2.统计宝石的个数
int count=0;
for(int i=0;i<jewels.length();++i){
Character ch=jewels.charAt(i);
count+=m.getOrDefault(ch,0);
}
return count;
}
}
4. 旧键盘
分析:
1.接收用户的输入String-----将其转换为大写
接收输出的String--------将其转换为大写
2.应该将out的结果放在一个set中-----HashSet
3.从in中依次获取每个字符,往set中插入
如果插入成功,则该键一定是坏键---输出
如果插入失败,要么是已经存在,要么是坏键(坏键已经输出了)
import java.util.*;
public class Main{
public static void main(String[] args){
//1.接收用户输入的 转换为大写
//接收输出的 转换为大写
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
String in=sc.nextLine().toUpperCase();
String out=sc.nextLine().toUpperCase();
//2.将out的结果放到set中
Set<Character> s=new HashSet<>();
for(int i=0; i<out.length();i++){
s.add(out.charAt(i));
}
//3.将in中的结果插入到Set中
//如果插入成功则 是坏的键 将其输出
for(int i=0;i<in.length();++i){
if(s.add(in.charAt(i))){
System.out.print(in.charAt(i));
}
}
System.out.println();
}
}
}
5. 前K个高频单词
前K个高频单词
分析:
1.统计次数---HashMap
<String,Integer>单词,次数
2.topk
优先级队列默认情况下是小堆
用前k个键值对 创建优先级队列之前需要先构造一个比较器(o1-o2)
用剩余的n-k个元素依次与堆顶元素比较,如果大于堆顶元素出现的次数则替换。
class Less implements Comparator<Map.Entry<String,Integer>>{
public int compare(Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2){
if(o1.getValue()>o2.getValue()){
return 1;
}
if(o1.getValue() == o2.getValue()&& o2.getKey().compareTo(o1.getKey())>0){
return 1;
}
if(o1.getValue() == o2.getValue()&& o2.getKey().compareTo(o1.getKey())==0){
return 0;
}
return -1;
}
}
class Solution {
public List<String> topKFrequent(String[] words, int k) {
//1.统计每个单词出现的次数
Map<String,Integer> m=new HashMap<>();
for(int i=0;i<words.length;++i){
m.put(words[i],m.getOrDefault(words[i],0)+1);
}
//2.找Top-k 出现次数最多的前k个单词
//用前k个键值对 建堆
Less cmp =new Less();
PriorityQueue<Map.Entry<String,Integer>> p=new PriorityQueue<>(cmp);
Set< Map.Entry<String,Integer>>s=m.entrySet();
int i=0;
for(Map.Entry<String,Integer>kv:s){
if(i<k){
p.offer(kv);
i++;
}else{
if(cmp.compare(kv,p.peek()) >= 0){
p.poll();
p.offer(kv);
}
}
}
LinkedList<String> list=new LinkedList<>();
for( i=0;i<k;++i){
list.addFirst(p.poll().getKey());
}
return list;
}
}
6. 二叉搜索树与双向链表
public class Solution {
TreeNode prev=null;
public void ConvertTree(TreeNode root){
if(null==root){
return ;
}
ConvertTree(root.left);
root.left=prev;
if(prev!=null){
prev.right=root;
}
prev=root;
ConvertTree(root.right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree== null){
return null;
}
//1. 找转换之后链表的第一个结点---最左侧结点
TreeNode head=pRootOfTree;
while(head.left!=null){
head=head.left;
}
//2.按照中序遍历的方式修改每个结点的left和right
prev=null;
ConvertTree(pRootOfTree);
return head;
}
}