zoukankan      html  css  js  c++  java
  • Java-排序-leetcode刷题

      最近在刷LeetCode的算法题,今天学习了排序的高效方法:最小堆和桶排序法。

      题目描述:给定一个非空的整数数组,返回其中出现频率前 高的元素。 

    示例 1:

    输入: nums = [1,1,1,2,2,3], k = 2
    输出: [1,2]
    1.最小堆法
    思路:①借助哈希表来建立数字及其出现频次的映射
    ②维护一个元素数目为k的最小堆
    ③每次都将新元素与堆顶元素(堆中频率最小的元素)比较
    ④若新的元素比堆顶端的元素大,则弹出堆顶元素,将新元素添加进去
    ⑤最终,堆中k个元素即为前k个高频元素
    class Solution{
    	public List<Integer> topKFrequent(int[] nums,int k){
    		//使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
    		HashMap<Integer,Integer> map=new HashMap();
    		for(int num:nums){
    			if(map.containsKey(num)){
    				//若已存在,值加一
    				map.put(num,map.get(num)+1);
    			}else{
    				//若不存在,创建新的键值对
    				map.put(num,1);
    			}
    		}
    	}
    	//遍历map,用优先队列最小堆保存频率最大的k个元素
    	//建立小顶堆,若想建立大顶堆,则return map.get(b)-map.get(a)
    	/*继承Comparator接口,必须重写compare 方法*/
    	PriorityQueue<Integer> pq=new PriorityQueue<>(new Comparator<Integer>(){
    		@Override
    		public int compare(Integer a,Integer b){
    			return map.get(a)-map.get(b);
    		}
    	)};
    	//保存频率最大的k个元素,peek()方法:查看堆顶元素值
    	for(Integer key:map.keySet()){
    		if(pq.size()<k){
    			pq.add(key);
    		}else if(map.get(key)>map.get(pq.peek())){
    			pq.remove();
    			pq.add(key);
    		}
    	}
    	//取出最小堆的元素
    	List<Integer> res=new ArrayList<>();
    	while(!pq.isEmpty()){
    		res.add(pq.remove);
    	}
    	return res;
    }
    

      tips:

    PriorityQueue(优先级队列):按关键词有序排列,插入新数据会自动插入合适位置。默认小顶堆。重写可以改变其排列方式。
    方法1:
    	PriorityQueue<Integer> pq=new PriorityQueue<>(new Comparator<Integer>(){
    		@Override
    		public int compare(Integer a,Integer b){
    			return map.get(b)-map.get(a);
    		}
    	)};
    

      方法2:调用Comparator,reverseOrder()方法

    PriorityQueue<Integer> pq=new PriorityQueue<>(Comparator.reverseOrder());
    

      方法3:Lambda表达式:允许把函数作为一个方法的参数传递进方法。

    PriorityQueue<Integer> pq=new PriorityQueue<>((a,b)->b-a);
    

      时间复杂度:O(nlogk),n表示数组的长度,遍历一遍复杂度为o(n);接着,遍历用于存储元素频率的map,若元素频率大于最小堆中顶部的元素,则将顶部的元素删除并将该元素 加入堆中,这里维护堆的数目为k,因此时间复杂度为O(nlogk)。

    2.桶排序法

    //基于桶排序求解「前 K 个高频元素」
    class Solution {
        public List<Integer> topKFrequent(int[] nums, int k) {
            List<Integer> res = new ArrayList();
            // 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
            HashMap<Integer,Integer> map = new HashMap();
            for(int num : nums){
                if (map.containsKey(num)) {
                   map.put(num, map.get(num) + 1);
                 } else {
                    map.put(num, 1);
                 }
            }
            
            //桶排序
            //将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标
            List<Integer>[] list = new List[nums.length+1];
            for(int key : map.keySet()){
                // 获取出现的次数作为下标
                int i = map.get(key);
                if(list[i] == null){
                   list[i] = new ArrayList();
                } 
                list[i].add(key);
            }
            
            // 倒序遍历数组获取出现顺序从大到小的排列
            for(int i = list.length - 1;i >= 0 && res.size() < k;i--){
                if(list[i] == null) continue;
                res.addAll(list[i]);
            }
            return res;
        }
    }
    

      

     LeetCode-75按颜色排序

    题目:

    给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

    此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

    学习来的思路:1.设置两个指针r1,r2,分别代表当前r1记录左边小于1的当前位置,r2记录左边小于2 的当前位置。

    2.如果左边比2小,那么就r2++,且交换数组的顺序(r2和i),若仍然小于1,r1++,继续交换(r2,r1)

    (这个思路太大神了orz)

    class Solution {
        public void sortColors(int[] nums) {
            int r1=-1,r2=-1;
            for(int i=0;i<nums.length;i++){
                if(nums[i]<2){
                    r2++;
                    swap(nums,i,r2);
                    if(nums[r2]<1){
                        r1++;
                        swap(nums,r1,r2);
                    }
                }
            }
        }
        void swap(int[] nums,int i,int j){
            int temp=nums[i];
            nums[i]=nums[j];
            nums[j]=temp;
        }
    }
    

      

  • 相关阅读:
    windows命令提示符常用命令
    JAVA中定义不同进制整数
    进制转换
    win10配置jdk环境变量
    AI Gossip
    搜狗大数据总监、Polarr 联合创始人关于深度学习的分享交流 | 架构师小组交流会
    后端渲染实践——看掘金社区是如何实践的
    谢孟军:The State of Go | ECUG Con 精粹系列
    让你的 CDN 费用省 50% 以上!图片瘦身的正确姿势
    七牛云大数据平台建设实践
  • 原文地址:https://www.cnblogs.com/zyycumt/p/13557951.html
Copyright © 2011-2022 走看看