Map--Set--二叉搜索树OJ练习题

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;

    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值