leetcode记录-排序-215、347、451、75

215.数组中第K大元素

在这里插入图片描述

思路

【最终位置】求数组中第K大元素,与排序相关,快排每次都能找到一个元素在排序好的数组中的最终位置(且左边的都比该数小,右边的都比该数大),借鉴快排思想,利用下标优化查找过程。每次找一个元素最终位置,如果等于K-1,将该元素返回;否则,若该元素位置小于K,在其右边子数组快排,否则在左边快排。

代码

public int findKthLargest0(int[] nums, int k){
        int left=0,right=nums.length-1;
        while(left<right){
            int mid=findIndex(nums,left,right); //调用此方法已经将一个元素排序了(mid处
            if (mid==nums.length-k) return nums[mid]; //当mid为所指下标
            else if (mid>nums.length-k) //mid靠右了,去左边找
                right=mid-1;
           else
               left=mid+1;
        }
        return nums[left];
    }
    public int findIndex(int[] nums,int begin,int end){ //指定区间内将begin下标元素最终位置找到
        int value=nums[begin];
        int left=begin;
        int right=end;
        while(left<right){
            while (left<right&&nums[right]>value)
                right--;
            while(left<right&&nums[left]<=value)
                left++;
            int temp=nums[left];
            nums[left]=nums[right];
            nums[right]=temp;
        }
        nums[begin]=nums[left];
        nums[left]=value;
        return left;
    }

347.前K个高频元素

在这里插入图片描述

思路

【元素频率顺序】因为不同元素个数统计排序,借鉴桶排序,先统计元素个数(HashMap),再将个数相同的元素放到一个桶里(二维List),元素从多到少输出。
在这里插入图片描述

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //统计元素个数相关或者元素某个属性——用HashMap键值对
        //整数不好作为下标,就用次数作为下标

        //初始化HashMap
        Map<Integer,Integer> map=new HashMap<>();//键代表数,值代表该数出现次数
        for (int key:nums){
            //是否包含该键,没有的话初始化值1
            if (map.containsKey(key))
                map.put(key,map.get(key)+1);
            else
                map.put(key,1);
        }
        //将相同次数的放在一个List里
        List<Integer>[] list=new ArrayList[nums.length+1];//以防都是相同元素,这时候就要放在下标为nums.length处
        for (int key:map.keySet()){ //对于每个键——map.keySet()获取键集合
            int value=map.get(key); //获取该键的值,表示键数字出现次数
            if(list[value] == null){
                list[value] = new ArrayList();
            }

            list[value].add(key); //加到对应次数下标里
        }
        //倒序遍历List输出——因为每个子list下不知道有几个,用int[]得遍历,所以还是用list的addAll
        List<Integer> output=new ArrayList<>();
        for (int i = nums.length; i >0 && output.size()<k; i--) {
            if (list[i]==null) continue;;
            output.addAll(list[i]);
        }
        return output.stream().mapToInt(Integer::valueOf).toArray();
    }
}

451.根据字符出现频率排序

在这里插入图片描述

思路

【元素频率顺序】依旧是元素频率/个数相关的题目,而且范围未知,不是下面的三个元素的问题,借鉴桶排序。统计每个字符出现次数,然后按个数装桶,最后倒序取。

代码

  1. 与347相似版
class Solution {
    public String frequencySort(String s) {
        Map<Character,Integer> map=new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.get(s.charAt(i))==null) map.put(s.charAt(i),1);
            else map.put(s.charAt(i),map.get(s.charAt(i))+1);
        }
        List<Character>[] list=new ArrayList[s.length()+1]; //注意
        for (Character key:map.keySet()){
            int value=map.get(key);
            if (list[value]==null) list[value]=new ArrayList<>();
            list[value].add(key);
        }
        List<Character> listOut=new ArrayList<>();
        for (int i = list.length-1; i >0 ; i--) {
            if (list[i]==null) continue; //注意
            for (int j = 0; j < list[i].size(); j++) {
                for (int k = 0; k < i; k++) {
                    listOut.add(list[i].get(j));
                }
            }
        }
        StringBuilder str = new StringBuilder();
        for (Character character : listOut) {// 对ArrayList进行遍历,将字符放入StringBuilder中
            str.append(character);
        }
        return str.toString();
    }
}
  1. List存字符,按照每种字符出现次数从小到大排列,最后倒序输出(因为List存的去重后的,所以要取map里的value,输出value个字符)
class Solution {
    public String frequencySort(String s) {
        Map<Character,Integer> map=new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.get(s.charAt(i))==null) map.put(s.charAt(i),1);
            else map.put(s.charAt(i),map.get(s.charAt(i))+1);
        }
        List<Character> listOut = new ArrayList<Character>(map.keySet());
        Collections.sort(listOut, (a, b) -> map.get(b) - map.get(a));
        StringBuilder str = new StringBuilder();
        int size = listOut.size();
        for (int i = 0; i < size; i++) {
            char c = listOut.get(i);
            int frequency = map.get(c);
            for (int j = 0; j < frequency; j++) {
                str.append(c);
            }
        }
        return str.toString();
    }
}

75.颜色分类

在这里插入图片描述

思路

【3个元素整体排序】若使用上面多个元素出现频率的方法,会比较麻烦。三个元素则可以遇到0挪前面,遇到2挪后面,遇到1不变。使用双指针法(一个left指向排序好的0下一位,一个right指向排序好的2上一位),同时再多一个指针i依次遍历元素,满足条件与相应指针元素交换,然后再进行不同的步进。特别的,如果right处交换完,i处不知道交换的是啥元素,不能直接步进,需要再次处理i,而right正常–。

代码

class Solution {
    public void sortColors(int[] nums){
        //左右指针指向待放0的位置和待放2的位置;i步进处理元素,看是否交换——思想是0放前面,2放后面
        int left=0,right=nums.length-1,i=0;
        while(i<=right){ //注意right后面都是2,不用处理,right处可能为任意值,需要处理,如果为0,就需要换到前面去
            if (nums[i]==0)
                swap(nums,i++,left++);
            else if (nums[i]==2)
                swap(nums,i,right--); //换后面去的是2,换前面来的可能0/1/2,需要再次处理
            else
                i++;
        }
    }
    public void swap(int[] nums,int index1,int index2){
        int temp=nums[index1];
        nums[index1]=nums[index2];
        nums[index2]=temp;
    }
}

技巧总结

排序相关思路

① 某个元素的位置/分水岭——参考快排(快排每次把一个元素放到最终位置,且左边都小,右边都大)
② 多个元素个数相关——参考桶排序(按照出现个数元素放到相应桶里)
③ 三种元素排序——一种放前,一种放后,一种不处理

元素出现个数统计HashMap

Map<Character,Integer> map=new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if (map.get(s.charAt(i))==null) map.put(s.charAt(i),1);
            else map.put(s.charAt(i),map.get(s.charAt(i))+1);
        }

List相关(二维List,Integer的List转数组)

① 当List指定长度,且每个元素存的也是List(二维List):

List<Integer>[] list=new ArrayList[nums.length+1];//以防都是相同元素,这时候就要放在下标为nums.length处
        for (int key:map.keySet()){ //对于每个键——map.keySet()获取键集合
            int value=map.get(key); //获取该键的值,表示键数字出现次数
            if(list[value] == null){
                list[value] = new ArrayList();
            }

            list[value].add(key); //加到对应次数下标里
        }

② 二维List中的每个List第一次用都要声明:if (list[value]==null) list[value]=new ArrayList<>();
③ List中加许多键值对addAll:output.addAll(list[i]); list[i]为一个List。
④ Integer类型的List转数组:return output.stream().mapToInt(Integer::valueOf).toArray();

map操作(键集合、按键排序、某键值+1)

① 获取键集合:map.keySet(),一般用于遍历每个key:for (int key:map.keySet()){},也可以直接创建含有每个键的List:List<Character> listOut = new ArrayList<Character>(map.keySet());
② 某键的值+:map.put(s.charAt(i),map.get(s.charAt(i))+1);
③ 按照map里的value排序键(存在了List里):Collections.sort(listOut, (a, b) -> map.get(b) - map.get(a));

字符List转String(Character数组同理)

StringBuilder str = new StringBuilder();
for (Character character : listOut) {// 对ArrayList进行遍历,将字符放入StringBuilder中
    str.append(character);
}
return str.toString();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值