7.优化算法之分治-快排归并

0.分治

分而治之

1.颜色分类

75. 颜色分类 - 力扣(LeetCode)

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

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

必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]

class Solution {
    public void sortColors(int[] nums) {
        int n=nums.length;
        int left=-1,right=n,i=0;
        while(i<right){//i要扫描完
            if(nums[i]==0){
                swap(nums,++left,i++);
            }else if(nums[i]==2){
                swap(nums,--right,i);
            }else{
                i++;
            }
        }
    }
    public void swap(int[] nums,int x,int y){
        int tmp=nums[x];
        nums[x]=nums[y];
        nums[y]=tmp;
    }
}

2.快速排序

排序数组

给你一个整数数组 nums,请你将该数组升序排列。

class Solution {
    public int[] sortArray(int[] nums) {
        qsort(nums,0,nums.length-1);
        return nums;
    }

    public void qsort(int[] nums,int l,int r){
        if(l>=r){
            return;
        }
        //数组分为三块
        //1.随机在区间内选值
        int key=nums[new Random().nextInt(r-l+1)+l];
        int left=l-1,right=r+1,i=l;
        while(i<right){
            if(nums[i]<key){
                swap(nums,++left,i++);
            }else if(nums[i]==key){
                i++;
            }else{
                swap(nums,--right,i);
            }
        }
        //[l,left],[left+1,right-1],[right,r]
        qsort(nums,l,left);
        qsort(nums,right,r);
    }
    public void swap(int[] nums,int x,int y){
        int tmp=nums[x];
        nums[x]=nums[y];
        nums[y]=tmp;
    }
}

3.数组中的第k个最大元素

215. 数组中的第K个最大元素 - 力扣(LeetCode)

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入: [3,2,1,5,6,4], k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return qsortchoice(nums, 0, nums.length - 1, k);
    }

    public int qsortchoice(int[] nums, int l, int r, int k) {
        while (l == r) {
            return nums[l];
        }
        // 随机在范围内选择对应的数字
        // 随机选择一个基准元素
        int key = nums[new Random().nextInt(r - l + 1) + l];
        // 根据基准元素,使得数组分为三部分
        int left = l - 1, right = r + 1, i = l;
        while (i < right) {
            if (nums[i] < key) {
                swap(nums, ++left, i++);
            } else if (nums[i] == key) {
                i++;
            } else {
                swap(nums, --right, i);
            }
        }
        // 快速选择的算法,分情况讨论
        int b = right - left - 1, c = r - right + 1;
        if (c >= k) {
            return qsortchoice(nums, right, r, k);
        } else if (b + c >= k) {
            return key;
        } else {
            return qsortchoice(nums, l, left, k - b - c);
        }
    }

    public void swap(int[] nums, int x, int y) {
        int tmp = nums[x];
        nums[x] = nums[y];
        nums[y] = tmp;
    }
}

4.最小的K个数

class Solution {
    public int[] inventoryManagement(int[] nums, int k) {
        qsortchoice(nums, 0, nums.length - 1, k);
        int[] ret=new int[k];
        for(int i=0;i<k;i++){
            ret[i]=nums[i];
        }
        return ret;
    }

    public void qsortchoice(int[] nums, int l, int r, int k) {
        while (l == r) {
            return;
        }
        // 随机在范围内选择对应的数字
        // 随机选择一个基准元素
        int key = nums[new Random().nextInt(r - l + 1) + l];
        // 根据基准元素,使得数组分为三部分
        int left = l - 1, right = r + 1, i = l;
        while (i < right) {
            if (nums[i] < key) {
                swap(nums, ++left, i++);
            } else if (nums[i] == key) {
                i++;
            } else {
                swap(nums, --right, i);
            }
        }
        // 快速选择的算法,分情况讨论
        int a=left-l+1,b=right-1-left-1+1;
        if (a>k) {
            qsortchoice(nums, l, left, k);
        } else if (a + b >= k) {
            return;
        } else {
            qsortchoice(nums, right,r, k - a-b);
        }
    }

    public void swap(int[] nums, int x, int y) {
        int tmp = nums[x];
        nums[x] = nums[y];
        nums[y] = tmp;
    }
}

5.归并排序

912. 排序数组 - 力扣(LeetCode)

在递归的时候如果总是需要new一个变量,这是我们可以把这个变量作为全局变量。

class Solution {
    int[] tmp;//定义全局变量,就不用反复new了
    public int[] sortArray(int[] nums) {
        tmp=new int[nums.length];
        mergeSort(nums,0,nums.length-1);
        return nums;
    }

    public void mergeSort(int[] nums,int left,int right){
        if(left>=right){
            return;
        }
        //1.根据中间点划分区间
        int mid=(left+right)/2;
        //[left,mid][mid+1,right]
        //2.先把左右区间排个序 
        mergeSort(nums,left,mid);
        mergeSort(nums,mid+1,right);

        //3.合并两个有序数组
        int cur1=left,cur2=mid+1,i=0;
        while(cur1<=mid&&cur2<=right){
            tmp[i++]=nums[cur1]<=nums[cur2]?nums[cur1++]:nums[cur2++];
        }
        //处理没有遍历完的数组
        while(cur1<=mid){
            tmp[i++]=nums[cur1++];
        }
        while(cur2<=right){
            tmp[i++]=nums[cur2++];
        }
        //还原到nums数组上
        for(int j=left;j<=right;j++){
            nums[j]=tmp[j-left];
        }
    }
}

6.数组中的逆序对

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

class Solution {
    int[] tmp;
    public int reversePairs(int[] record) {
        int n=record.length;
        tmp=new int[n];
        return mergeSort(record,0,n-1);
    }
    public int mergeSort(int[] nums,int left,int right){
        while(left>=right){
            return 0;
        }
        int ret=0;
        //选择一个中间点,将数组进行划分
        int mid=(left+right)/2;
        //[left,mid][mid+1,right]
        //2.左半部分的个数+右半部分的个数+排序
        ret=ret+mergeSort(nums,left,mid);
        ret=ret+mergeSort(nums,mid+1,right);
        //3.一左一右的个数
        int cur1=left,cur2=mid+1,i=0;
        while(cur1<=mid&&cur2<=right){
            if(nums[cur1]<=nums[cur2]){
                tmp[i++]=nums[cur1++];
            }else{
                ret=ret+mid-cur1+1;
                tmp[i++]=nums[cur2++];
            }
        }
        //4.处理一下后面的排序
        while(cur1<=mid){
            tmp[i++]=nums[cur1++];
        }
        while(cur2<=right){
            tmp[i++]=nums[cur2++];
        }
        for(int j=left;j<=right;j++){
            nums[j]=tmp[j-left];
        }
        return ret;

    }
}

 7.计算右侧⼩于当前元素的个数(难点)

315. 计算右侧小于当前元素的个数 - 力扣(LeetCode)

class Solution {
    int[] ret;
    int[] index; // 标记 nums 中当前元素的原始下标
    int[] tmpIndex;
    int[] tmpNums;

    public List<Integer> countSmaller(int[] nums) {
        int n = nums.length;
        ret = new int[n];
        index = new int[n];
        tmpIndex = new int[n];
        tmpNums = new int[n];
        // 初始化 index 数组
        for (int i = 0; i < n; i++) {
            index[i] = i;
        }
        mergeSort(nums, 0, n - 1);
        List<Integer> l = new ArrayList<Integer>();
        for (int x : ret) {
            l.add(x);
        }
        return l;
    }

    public void mergeSort(int[] nums, int left, int right) {
        if (left >= right) {
            return;
        }
        // 1. 根据中间元素划分区间
        int mid = (left + right) / 2;
        // [left, mid] [mid + 1, right]
        // 2. 处理左右两个区间
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);
        // 3. 处理⼀左⼀右的情况
        int cur1 = left, cur2 = mid + 1, i = 0;
        while (cur1 <= mid && cur2 <= right) { // 降序排序
            if (nums[cur1] <= nums[cur2]) {
                tmpNums[i] = nums[cur2];
                tmpIndex[i++] = index[cur2++];
            } else {
                ret[index[cur1]] += right - cur2 + 1; // 重点
                tmpNums[i] = nums[cur1];
                tmpIndex[i++] = index[cur1++];
            }
        }
        // 4. 处理剩余的排序⼯作
        while (cur1 <= mid) {
            tmpNums[i] = nums[cur1];
            tmpIndex[i++] = index[cur1++];
        }
        while (cur2 <= right) {
            tmpNums[i] = nums[cur2];
            tmpIndex[i++] = index[cur2++];
        }
        for (int j = left; j <= right; j++) {
            nums[j] = tmpNums[j - left];
            index[j] = tmpIndex[j - left];
        }
    }
}

 8.翻转对

给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对

你需要返回给定数组中的重要翻转对的数量。

示例 1:

输入: [1,3,2,3,1]
输出: 2

示例 2:

输入: [2,4,3,5,1]
输出: 3

注意:

  1. 给定数组的长度不会超过50000
  2. 输入数组中的所有数字都在32位整数的表示范围内。

 

class Solution {
    int[] tmp;

    public int reversePairs(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        return mergeSort(nums, 0, n - 1);
    }

    public int mergeSort(int[] nums, int left, int right) {
        if (left >= right)
            return 0;
        int ret = 0;
        // 1. 根据中间元素,将区间分成两部分
        int mid = (left + right) / 2;
        // [left, mid] [mid + 1, right]
        // 2. 求出左右两个区间的翻转对
        ret += mergeSort(nums, left, mid);
        ret += mergeSort(nums, mid + 1, right);
        // 3. 处理⼀左⼀右 - 先计算翻转对
        int cur1 = left, cur2 = mid + 1, i = left;
        // 降序版本
        while (cur1 <= mid) {
            while (cur2 <= right && nums[cur2] >= nums[cur1] / 2.0)
                cur2++;
            if (cur2 > right)
                break;
            ret += right - cur2 + 1;
            cur1++;
        }
        // 4. 合并两个有序数组
        cur1 = left;
        cur2 = mid + 1;
        while (cur1 <= mid && cur2 <= right)
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur2++] : nums[cur1++];
        while (cur1 <= mid)
            tmp[i++] = nums[cur1++];
        while (cur2 <= right)
            tmp[i++] = nums[cur2++];
        for (int j = left; j <= right; j++)
            nums[j] = tmp[j];

        return ret;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/758628.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

推动多模态智能模型发展:大型视觉语言模型综合多模态评测基准

随着人工智能技术的飞速发展&#xff0c;大型视觉语言模型&#xff08;LVLMs&#xff09;在多模态应用领域取得了显著进展。然而&#xff0c;现有的多模态评估基准测试在跟踪LVLMs发展方面存在不足。为了填补这一空白&#xff0c;本文介绍了MMT-Bench&#xff0c;这是一个全面的…

Django 模版继承

1&#xff0c;设计母版页 Test/templates/6/base.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><!-- 修正了模板标签的全角字符问题 -->{% block title %}<title>这个是母版页</title>{…

leetCode.93. 复原 IP 地址

leetCode.93. 复原 IP 地址 题目思路&#xff1a; 代码 // 前导零的判断方法&#xff1a;如果第一个数是0&#xff0c;且第二个数还有数据&#xff0c;那就是前导0&#xff0c;要排除的 // 注意跟单个 0 区分开 class Solution { public:vector<string> res;vector<…

Opencv+python模板匹配

我们经常玩匹配图像或者找相似&#xff0c;opencv可以很好实现这个简单的小功能。 模板是被查找目标的图像&#xff0c;查找模板在原始图像中的哪个位置的过程就叫模板匹配。OpenCV提供的matchTemplate()方法就是模板匹配方法&#xff0c;其语法如下&#xff1a; result cv2.…

【活动感想】筑梦之旅·AI共创工坊 workshop 会议回顾

目录 &#x1f30a;1. 会议详情 &#x1f30a;2. 会议回顾 &#x1f30d;2.1 主持人开场 &#x1f30d;2.2 元甲-小当家 AI 驱动的创意儿童营养早餐料理机&今天吃什么App &#x1f30d;2.3 Steven- A l 心理疗愈认知 &#x1f30d;2.4 伯棠-诸子百家(xExperts)-多智能…

私有部署Twikoo评论系统

原文&#xff1a;https://blog.c12th.cn/archives/12.html 前言 以前用 MongoDB Vercel 搭建 Twikoo 老是有点小问题&#xff0c;所以就放弃了。无意中看到可以用 docker 来搭建&#xff0c;正好有台服务器可以尝试下。 私有部署 Twikoo 版本要求 1.6.0 或以上 &#xff0c; …

AMD Anti-Lag 2抗延迟技术落地 CS2首发、延迟缩短95%

AMD发布了全新重磅驱动程序Adrenalin 24.6.1版本&#xff0c;包括首发落地Anti-Lag 2抗延迟技术、优化支持新游戏、升级支持HYPR-Tune、支持新操作系统、优化AI加速与开发、扩展支持Agility SDK、修复已知Bug&#xff0c;等等。 一、Anti-Lag 2 今年5月份刚宣布&#xff0c;重…

【计算机毕业设计】基于Springboot的智能物流管理系统【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

信号与系统-实验6-离散时间系统的 Z 域分析

一、实验目的 1、掌握 z 变换及其性质&#xff1b;了解常用序列的 z 变换、逆 z 变换&#xff1b; 2、掌握利用 MATLAB 的符号运算实现 z 变换&#xff1b; 3、掌握利用 MATLAB 绘制离散系统零、极点图的方法&#xff1b; 4、掌握利用 MATLAB 分析离散系统零、极点的方法&a…

kicad第三方插件安装问题

在使用KICAD时想安装扩展内容&#xff0c;但是遇到下载失败&#xff0c;因为SSL connect error。 因为是公司网络&#xff0c;我也不是很懂&#xff0c;只能另寻他法。找到如下方法可以曲线救国。 第三方插件包目录 打开存放第三方插件存放目录&#xff0c;用于存放下载插件包…

vue3+vite+nodejs,通过接口的形式请求后端打包(可打包全部或指定打包组件)

项目地址https://gitee.com/sybb011016/test_build 打包通过按钮的形式请求接口&#xff0c;让后端进行打包&#xff0c;后端使用express-generator搭建模版。前端项目就在npm init vuelatest基础上添加了路由 如果只想打包AboutView组件&#xff0c;首先修改后端接口。 //打…

Linux如何安装openjdk1.8

文章目录 Centosyum安装jdk和JRE配置全局环境变量验证ubuntu使用APT(适用于Ubuntu 16.04及以上版本)使用PPA(可选,适用于需要特定版本或旧版Ubuntu)Centos yum安装jdk和JRE yum install java-1.8.0-openjdk-devel.x86_64 安装后的目录 配置全局环境变量 vim /etc/pr…

运营商、银行、国企等单位开发岗24届Offer薪资与福利汇总

本文介绍24届校园招聘中&#xff0c;地理信息科学&#xff08;GIS&#xff09;专业硕士研究生所得Offer的整体薪资情况、福利待遇等。 在2024届秋招与春招中&#xff0c;我累计投递了170余个单位&#xff0c;获得17个Offer&#xff1b;平均每投递10个简历才能获得1个Offer。说句…

2024年6月29日 每周新增游戏

图吧工具箱: 全名图拉丁吧硬件检测工具箱,是开源、免费、绿色、纯净的硬件检测工具合集,专为图钉及所有DIY爱好者制作,包含常用硬件测试和检测工具,月工JS必备! iGuzheng爱古筝iguzheng古筝是一款可以在线模拟古筝练习的软件&#xff0c;用户可以直接在手机上练习古筝&#xff…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 6月30日,星期日

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年6月30日 星期日 农历五月廿五 1、 气象台继续发布暴雨红色预警&#xff1a;30日&#xff0c;安徽、湖南等地局地有特大暴雨。 2、 稀土管理条例公布&#xff1a;任何组织和个人不得侵占或者破坏稀土资源。 3、 暑期全国将…

ubuntu丢失网络/网卡的一种原因解决方案

现象 开机进入ubuntu后发现没有网络&#xff0c;无论是在桌面顶部状态栏的快捷键 还是 系统设置中&#xff0c;都没有”有线网“和”无线网“的选项&#xff0c;”代理“的选项是有的使用数据线连接电脑和手机&#xff0c;手机开启”通过usb共享网络“&#xff0c;还是没有任何…

Parzen 窗估计法

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在AI学习笔记&#…

一文弄懂逻辑回归算法

1. 引言 今天我们将深入探讨另一种基本的机器学习算法&#xff1a;逻辑回归。在前两篇文章中&#xff0c;我们使用线性回归和梯度下降法帮助我们的朋友马克确定了他 2400 平方英尺房子的理想售价。 最近马克再次向我们求助。他住在一个高档社区&#xff0c;他认为低于一定面积…

docker pull 镜像的时候遇到Pulling fs layer问题

最近遇到一个很奇怪的问题,docker pull 镜像的时候,总是出现Pulling fs layer问题,导致镜像拉取不成功,以前是安装好docker,正常拉取镜像都是没什么问题的,在这里记录一下这个问题的解决方法,当然,可能并不通用。 1、进入阿里云容器服务 地址:https://cr.console.aliy…

宝藏网站推荐,这些网站不可不知

在如今网络信息爆炸的时代&#xff0c;想要在众多网站中查找筛选一些好用的宝藏网站不是一件容易的事情。下面小编就来和大家分享几个值得推荐的宝藏网站&#xff0c;可以极大的提高大家上网效率&#xff0c;涵盖办公&#xff0c;学习&#xff0c;生活各个方面。 一、b站 b站…