堆【Lecode_HOT100】

文章目录

1.数组中的第K个最大元素No.215
  • 方法一:NlogN不能满足时间复杂度的要求
java 复制代码
 public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length-k];
    }
  • 方法二:快速排序 NlogN 不能满足时间复杂度的要求
java 复制代码
public int findKthLargest(int[] nums, int k) {
        quick_sort(nums,0,nums.length-1);
        return nums[nums.length-k];
    }
    public void quick_sort(int[] nums,int l,int r){
        if(l>=r) return;
        int i = l-1;
        int j = r+1;
        int x = nums[l];
        while(i<j){
            do{
                i++;
            }while(nums[i]<x);
            do{
                j--;
            }while(nums[j]>x);

            if(i<j){
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
        quick_sort(nums,l,j);
        quick_sort(nums,j+1,r);
        
    }
  • 方法三:
java 复制代码
class Solution {
    // 主函数,用于找到数组中第k大的元素
    public int findKthLargest(int[] nums, int k) {
        int n = nums.length;  // 获取数组长度
        return quick(nums, 0, n - 1, n - k);  // 调用快速选择算法,寻找第(n-k+1)小的元素,即第k大的元素
    }

    // 快速选择算法实现
    int quick(int[] a, int left, int right, int index) {
        int p = partition(a, left, right);  // 对数组进行划分,并返回枢轴位置
        if (p == index) {  // 如果枢轴位置正好是目标索引
            return a[p];  // 返回该位置的元素值
        }
        if (p < index) {  // 如果目标索引在枢轴右侧
            return quick(a, p + 1, right, index);  // 在右子区间继续查找
        } else {  // 如果目标索引在枢轴左侧
            return quick(a, left, p - 1, index);  // 在左子区间继续查找
        }
    }

    // 划分函数,使用随机选择的枢轴进行划分
    int partition(int[] a, int left, int right) {
        int idx = ThreadLocalRandom.current().nextInt(right - left + 1) + left;  // 随机选择一个枢轴位置
        swap(a, left, idx);  // 将枢轴放到最左边
        int pv = a[left];  // 取出枢轴值
        int i = left + 1;  // 初始化左侧指针
        int j = right;  // 初始化右侧指针
        while (i <= j) {  // 当左右指针未交错时
            while (i <= j && a[i] < pv) {  // 左侧找比枢轴大的
                i++;
            }
            while (i <= j && a[j] > pv) {  // 右侧找比枢轴小的
                j--;
            }
            if (i <= j) {  // 如果找到了一对可以交换的元素
                swap(a, i, j);  // 交换这对元素
                i++;  // 移动左侧指针
                j--;  // 移动右侧指针
            }
        }
        swap(a, j, left);  // 将枢轴放回正确的位置
        return j;  // 返回枢轴的新位置
    }

    // 交换数组中的两个元素
    void swap(int[] a, int i, int j) {
        int t = a[i];  // 暂存一个元素
        a[i] = a[j];  // 交换操作
        a[j] = t;
    }
}
  • I like
java 复制代码
import java.util.Random;

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int n = nums.length;
        int target = n - k;  // 因为要找第 k 大元素,等价于找第 n-k 小元素
        int l = 0, r = n - 1;
        
        while (l <= r) {
            int pIndex = partition(nums, l, r);  // 划分后的枢轴位置
            if (pIndex == target) {
                return nums[pIndex];  // 找到目标元素
            } else if (pIndex < target) {
                l = pIndex + 1;  // 目标元素在右半部分
            } else {
                r = pIndex - 1;  // 目标元素在左半部分
            }
        }
        return -1;  // 理论上应该不会到这里,保证数组一定有效
    }

    public int partition(int[] nums, int l, int r) {
        Random random = new Random();
        int idx = random.nextInt(r - l + 1) + l;  // 随机选择枢轴
        swap(nums, l, idx);  // 将枢轴放到数组的最左边
        int x = nums[l];  // 取出枢轴值
        
        int i = l + 1;  // 左侧指针
        int j = r;      // 右侧指针
        while (i <= j) {
            while (i <= j && nums[i] < x) {  // 左侧找比枢轴大的
                i++;
            }
            while (i <= j && nums[j] > x) {  // 右侧找比枢轴小的
                j--;
            }
            if (i <= j) {
                swap(nums, i, j);  // 交换不符合条件的元素
                i++;
                j--;
            }
        }
        swap(nums, l, j);  // 将枢轴放到正确位置
        return j;  // 返回枢轴的位置
    }

    // 交换数组中的两个元素
    public void swap(int[] nums, int x, int y) {
        int temp = nums[x];
        nums[x] = nums[y];
        nums[y] = temp;
    }
}
2.前K个高频元素347
  • 桶排序
java 复制代码
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        // 创建一个hashmap,并统计每个元素的频率
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        // 创建桶数组,桶的索引表示元素的频率,桶中的元素是具有相同频率的数字
        List<Integer>[] bucket = new List[nums.length + 1];
        for (int i = 0; i < bucket.length; i++) {
            bucket[i] = new ArrayList<>();
        }

        // 将频率存入桶中
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            bucket[entry.getValue()].add(entry.getKey());
        }

        // 从桶中提取前 k 个频率最高的元素
        int[] res = new int[k];
        int index = 0;
        for (int i = bucket.length - 1; i >= 0 && index < k; i--) {
            for (int num : bucket[i]) {
                res[index++] = num;
                if (index == k) {
                    break; // 找到 k 个元素后退出
                }
            }
        }
        return res;
    }
}
相关推荐
.格子衫.3 小时前
Spring Boot 原理篇
java·spring boot·后端
多云几多4 小时前
Yudao单体项目 springboot Admin安全验证开启
java·spring boot·spring·springbootadmin
Swift社区5 小时前
LeetCode 394. 字符串解码(Decode String)
算法·leetcode·职场和发展
tt5555555555555 小时前
LeetCode进阶算法题解详解
算法·leetcode·职场和发展
让我们一起加油好吗5 小时前
【基础算法】DFS中的剪枝与优化
算法·深度优先·剪枝
Jabes.yang6 小时前
Java求职面试实战:从Spring Boot到微服务架构的技术探讨
java·数据库·spring boot·微服务·面试·消息队列·互联网大厂
聪明的笨猪猪6 小时前
Java Redis “高可用 — 主从复制”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
Q741_1476 小时前
C++ 模拟题 力扣495. 提莫攻击 题解 每日一题
c++·算法·leetcode·模拟
兮动人6 小时前
Spring Bean耗时分析工具
java·后端·spring·bean耗时分析工具
MESSIR226 小时前
Spring IOC(控制反转)中常用注解
java·spring