算法练习-排序(一)

news2024/12/25 13:01:57

算法练习-排序(一)

文章目录

  • 算法练习-排序(一)
    • 1 排序算法
      • 1.1 冒泡排序
        • 1.1.1代码
      • 1.2插入排序
        • 1.2.1代码
      • 1.3 选择排序
        • 1.3.1代码
      • 1.4归并排序
        • 1.4.1代码
      • 1.5 快速排序
        • 1.5.1 思路
        • 1.5.2 代码
    • 2 题目
      • 2.1 特殊排序
        • 2.1.1 题目
        • 2.1.2 题解
      • 2.2 数组中的第k个最大元素
        • 2.2.1 题目
        • 2.2.2 题解
      • 2.3 对链表进行插入排序
        • 2.3.1 题目
        • 2.3.2 题解
      • 2.4 排序预处理
        • 2.4.1 题目

1 排序算法

1.1 冒泡排序

1.1.1代码

void bubbleSort(int[] a, int n) {
    if (n <= 1) return;
    for (int i = 0; i < n; i++) { // 第几趟冒泡
        boolean flag = false;
        for (int j = 0; j < n - i - 1; j++) {
            if (a[j] > a[j + 1]) {
                int tmp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = tmp;
                flag = true; // 表示有数据交换
            }
        }
        if (!flag) break;
    }
}

1.2插入排序

1.2.1代码

public static void InsertSort(int[] a, int n) {
	if (n <= 1) return;
    for (int i = 1; i < n; i++) {
		int value = a[i];
         for (int j = i - 1; j >= 0; --j) {
             if (a[j] > value) {
				a[j + 1] = a[j];
             } else {
                 break;
             }
         }
        a[j + 1] = value;
    }
}
	

1.3 选择排序

1.3.1代码

public void selectionSort(int[] a, int n) {
    if (n <= 1) return;
    for (int i = 0; i < n - 1; i++) {
        int minPos = i;
        for (int j = i; j < n; j++) {
            if (a[j] < a[minPos]) {
                minPos = j;
            }
        }
        
        int tmp = a[i];
        a[i] = a[minPos];
        a[minPos] = tmp;
    }
}

1.4归并排序

1.4.1代码

public void mergeSort(int[] a, int n) {
    mergeSort_r(a, 0, n - 1);
}

private void mergeSort_r(int[] a, int p, int r) {
    if (p >= r) return;
    
    int q = p + (r - q) / 2;
    mergeSort_r(a, p, q);
    mergeSort_r(a, q + 1, r);
    
    merge(a, p, q, r);
}

private void merge(int[] a, int p, int q, int r) {
    int i = p;
    int j = q + 1;
    int k = 0;
    int[] tmp = new int[r - q + 1];
    while (i <= q && j <= r) {
        if (a[i] <= a[j]) {
            tmp[k++] = a[i++];
        } else {
			tmp[k++] = a[j++];
        }
    }
    
    while (i <= q) {
        tmp[k++] = a[i++];
    }
    
    while (j <= r) {
        tmp[k++] = a[j++];
    }
    
    for (int i = 0; i < r - p; i++) {
        a[p + i] = tmp[i];
    }
}

1.5 快速排序

1.5.1 思路

先把数组中的一个数当作基准数,一般把数组最左面的数当作基准数,然后从两边进行检索。

先从右边检索比基准数小的,再从左边检索比基准数大的。

如果检索到了,就停下,交换这两个元素,然后继续检索

两个指针一旦相遇就停止检索,将基准数和相遇位置进行交换

1.5.2 代码

public static void quickSort(int[] a, int n) {
    quickSort_r(a, 0, n - 1);
}

private void swap(int[] nums, int i ,int j) {
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}


public static void quickSort_r(int[] arr, int left, int right) {
    if (left >= right) return;
    
    // 定义变量保存基准数
    int base = arr[left];
    // 定义变量i,指向最左边
    int i = left;
    // 定义变量j,指向最右边
    int j = right;
    
    //  当i和j不相遇时,在循环中进行检索
    while (i != j) {
        // 现由j从右往左检索
        while (arr[j] >= base && i < j) j--;
        while (arr[i] <= base && i < j) i++;
        
        // i 和 j都停下了,交换 i 和 j 位置的元素
        swap(arr, i, j);
    }
    swap(arr, left, i);
    
    quickSort_r(arr, left, i - 1);
    quickSort_r(arr, j + 1, right);
    
}
public static void quickSort(int[] a, int n) {
    quickSort_r(a, 0, n - 1);
}

private static void quickSort_r(int[] a, int p, int r) {
    if (p >= r) return;
    int q = partition(a, p, r);
    quickSort_r(a, p, q - 1);
    quickSort_r(a, q + 1, r);
}

private static int partition(int[] a, int p, int r) {
    int i = p - 1; // [p, i]表示小于pivot值的元素
    for (int j = p; j < r; j++) {
		if (a[j] < a[r]) {
            swap(a, i + 1, j);
            i++;
        }
    }
    swap(a, i + 1, r);
    return i + 1;
}

private void swap(int[] nums, int i, int j) {
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

2 题目

2.1 特殊排序

2.1.1 题目

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分

2.1.2 题解

class Solution {
    public int[] exchange(int[] nums) {
        int i = 0;
        int j = nums.length - 1;
        while (i < j) {
            if (nums[i] % 2 == 1) {
                i++;
                continue;
            }
            if (nums[j] % 2 == 0) {
				j--;
                continue;
            }
            int tmp = nums[j];
            nums[i] = nums[j];
            nums[j] = tmp;
            i++;
            j--;
        }
        return nums;
    }
}

2.2 数组中的第k个最大元素

链接:https://leetcode.cn/problems/kth-largest-element-in-an-array

2.2.1 题目

给定整数数组 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

2.2.2 题解

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

    private int quickSort(int[] nums, int p, int r, int k) {
        if (p > r) return -1;
        int q = partition(nums, p ,r);
        if (q - p + 1 == k) {
            return nums[q];
        } else if (q - p + 1 < k) {
            return quickSort(nums, q + 1, r, k - (q - p + 1));
        } else {
            return quickSort(nums, p, q - 1, k);
        }
    }

    private int partition(int[] nums, int p, int r) {
        int i = p;
        int j = r - 1;
        while (i < j) {
            while (i < j && nums[i] > nums[r]) {
                i++;
            }
            while (i < j && nums[j] <= nums[r]) {
                j--;
            }
            if (i < j) {
                swap(nums, i, j);
                i++;
                j--;
            }
        }
        if (j >= p && nums[j] < nums[r]) {
            swap(nums, j , r);
            return j;
        } else {
            swap(nums, j + 1, r);
            return j + 1;
        }
    }

    private void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}
class Solution {
    public int findKthLargest(int[] nums, int k) {
        if (nums.length < k) return -1;
        return quickSort(nums, 0, nums.length - 1, k);
    }

    private int quickSort(int[] nums, int p, int r, int k) {
        if (p > r) return -1;
        int q = partition(nums, p ,r);
        if (q - p + 1 == k) {
            return nums[q];
        } else if (q - p + 1 < k) {
            return quickSort(nums, q + 1, r, k - (q - p + 1));
        } else {
            return quickSort(nums, p, q - 1, k);
        }
    }

    private int partition(int[] nums, int p, int r) {
        int i = p - 1; // [p, i]表示小于pivot值的元素
    for (int j = p; j < r; j++) {
		if (nums[j] > nums[r]) {
            swap(nums, i + 1, j);
            i++;
        }
    }
    swap(nums, i + 1, r);
    return i + 1;
    }

    private void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

2.3 对链表进行插入排序

链接:https://leetcode.cn/problems/insertion-sort-list

2.3.1 题目

给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。

插入排序 算法的步骤:

插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。
下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。

对链表进行插入排序。

示例 1:

请添加图片描述

输入: head = [4,2,1,3]
输出: [1,2,3,4]
示例 2:

请添加图片描述

输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]

2.3.2 题解

class Solution {
    public ListNode insertionSortList(ListNode head) {
		if (head == null) return null;
        
        // 存储已经排序好的节点
        ListNode newHead = new ListNode(Integer.MIN_VALUE, null);
        
        // 遍历节点
       	ListNode p = head;
        while (p != null) {
            ListNode tmp = p.next;
            
            // 寻找p节点插入的位置,插入到哪个节点后面
            ListNode q = newHead;
            while (q.next != null && q.next.val <= p.val) {
                q = q.next;
            }
            
            p.next = q.next;
            q.next = p;
            
            p = tmp;
        }
        return newHead.next;
    }
}

2.4 排序预处理

2.4.1 题目

有一组无序数据,找到出现次数最多的数据

public int maxCount(int[] data) {
    Arrays.sort(data);
    int n = data.length;
    int pre = -1;
    int count = 0;
    int max = -1;
    for (int i = 0; i < n; ++i) {
        if (data[i] == pre) {
            count++;
            if (max < count) max = count;
        } else {
            count = 1;
            pre = data[i];
            if (max < count) max = count;
        }
    }
    return max;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux学习】基础IO——系统调用 | 文件描述符fd | 重定向

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 基础IO&#x1f34e;文件操作&#x1f349;使用C接口进行文件操作&#x1f349;文件操作的系统调…

Ingress

Ingres 目录 文章目录Ingres目录本节实战1、Ingress是什么2、定义1.rules2.Resource3.pathType4.IngressClass5.TLS3、Ingress-controller1.什么是Ingress-controller2.其他ingress-controller控制器FAQ零碎ingress就是借用service实现服务发现机制关于我最后本节实战 无 1、…

MySQL基础(一)SQL分类、导入、SELECT语句,运算符

目录 MySQL安装以及相关工具 SQL分类 导入数据 最基本的SELECT语句 SELECT FROM 列的别名 去除重复行 着重号 查询常数 描述表结构 过滤数据&#xff08;重要&#xff09; 运算符 算数运算符 比较运算符 符号运算符 非符号运算符 逻辑运算符 位运算符 MySQL安…

【C++】继承与多态

目录前言1. 继承1.1 继承的概念1.2 继承的定义1.3 切片赋值1.4 继承中的作用域1.5 派生类的默认成员函数1.6 继承与友元、静态成员1.7 多继承、菱形继承、菱形虚拟继承1.7.1 区分单继承与多继承1.7.2 菱形继承1.7.3 菱形虚拟继承1.7.4 菱形虚拟继承的原理2. 多态2.1 概念2.2 多…

Elasticsearch实战之(商品搜索API实现)

Elasticsearch实战之&#xff08;商品搜索API实现&#xff09; 1、案例介绍 某医药电商H5商城基于Elasticsearch实现商品搜索 2、案例分析 2.1、数据来源 商品库 - 平台运营维护商品库 - 供应商维护 2.2、数据同步 2.2.1、同步双写 写入 MySQL&#xff0c;直接也同步往…

如何使用C2concealer生成随机化的C2 Malleable配置文件

关于C2concealer C2concealer是一款功能强大的命令行工具&#xff0c;在该工具的帮助下&#xff0c;广大研究人员可以轻松生成随机化的C2 Malleable配置文件&#xff0c;以便在Cobalt Strike中使用。 工具运行机制 开发人员对Cobalt Strike文档进行了详细的研究&#xff0c;…

【转载】2020融云:基于WebRTC的低延迟视频直播

原文直接访问本文是读书笔记。基于WebRTC的低延迟视频直播 需要学习rtp包的缓存设计,于是找到了这一篇文章rtp包缓存 如何适应直播需求?直播与实时通信的区别 流量更少: RTMP或者HLS主要基于TCP传输,WebRTC是基于UDP的传输, **UDP协议的头小。**TCP为了保证传输质量,因…

Zotero设置毕业论文/中文期刊参考文献格式

大家在使用zotero时很容易遇到的问题&#xff1a; 英文参考文献中有多个作者时出现“等”&#xff0c;而不是用"et al"引文最后面有不需要的DOI号&#xff0c;或者论文链接对于一些期刊分类上会出现OL字样&#xff0c;即[J/OL]作者名为全大写 本文主要解决以上几个…

string函数以及string常用接口

本文介绍的是C关键字string中一些重要用法&#xff0c;以及各种字符串序列的处理操作 ——飘飘何所似&#xff0c;天地一沙鸥 文章目录前言一、string&#xff08;字符串类&#xff09;二、string类对象的容量操作2.1 size/length2.2 capacity2.3 empty/clear2.4 resize/reser…

教你如何搭建设备-保养管理系统,demo可分享

1、简介1.1、案例简介本文将介绍&#xff0c;如何搭建设备-保养管理。1.2、应用场景设备管理员进行制定设备保养计划、记录设备保养信息、可以查看设备保养日历。2、设置方法2.1、表单搭建1&#xff09;新建表单【设备档案-履历表】&#xff0c;字段设置如下&#xff1a;名称类…

SSM SpringBoot vue 在线教学质量评价系统

SSM SpringBoot vue 在线教学质量评价系统 SSM 在线教学质量评价系统 功能介绍 首页 图片轮播展示 登录 学生注册 教师注册 督导注册 教师展示 教师详情 学生评价 课程信息 课程详情 提交选修该课 学生选课 学生留言 个人中心 后台管理 管理员或学生或教师或督导登录 个人中…

项目经理处理团队冲突 5大注意事项

1、在时间、场景、体验矩阵中的5种处理方式 第一种方式&#xff1a;强迫命令&#xff0c;即职位高的一方在不考虑对方感受的情况下&#xff0c;强迫职位低的一方接受自己的意见。这种处理方式的适用场景为重要且紧急&#xff0c;这种方式团队成员的体验感低。 第二种方式&#…

Linux 学习笔记(一):终端 和 Shell 的区别和联系

一、Linux 介绍 1、什么是 Linux Linux 就是一个操作系统&#xff0c;全称 GNU/Linux&#xff0c;是一种类 Unix 操作系统Linux 一开始是没有图形界面的&#xff0c;所有操作都靠 命令 完成。如 磁盘操作、文件存取、目录操作、进程管理、文件权限 等等&#xff0c;可以说 Li…

Android Handler机制(二) Handler 实现原理

一. 前言 接上一篇文章为什么设计Handler , 我们来继续讲解一下Handler的实现原理, 俗话说一个好汉三个帮, 接下来一步一步引入各个主角,并说明它们在Handler机制中扮演的角色和作用. 二. Handler实现原理 首先我们先确定一个结论: 使用 Handler 是希望它被实例化在哪个线程&a…

不同序列模型的输入和输出总结

不同序列模型的输入和输出总结 文章目录不同序列模型的输入和输出总结RNNLSTMGRURNN RNN 是迭代输出&#xff1a; 输入第一个 -> 输出第二个&#xff0c; 输入第二个 -> 输出第三个&#xff0c; 输出倒数第二个 -> 输出最后一个。 LSTM LSTM 也是迭代输出&#xff…

Ep_操作系统面试题-什么是协程

协程 是一种 比线程更加轻量级的存 在&#xff0c;一个线程可以拥有多个协程。是一个特殊的 函数 &#xff0c;这个函数可以在某个地方挂起&#xff0c;并且可以重新在挂起处外继续运行。协程 不是被操作系统内核所管理 &#xff0c; 而完全是由程序所控制&#xff08;也就是在…

冯诺依曼体系结构与操作系统的理解

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;操作系统 &#x1f4ac;<3>前言&#xff1a;今天来介绍一下冯诺依曼体系结构&#xff0c;和操作系统的理解。 目录 1.冯诺依曼体系结构 冯诺依曼体系的工作原理&#xff1a; 为…

注意力机制详解系列(四):混合注意力机制

👨‍💻作者简介: 大数据专业硕士在读,CSDN人工智能领域博客专家,阿里云专家博主,专注大数据与人工智能知识分享。 🎉专栏推荐: 目前在写CV方向专栏,更新不限于目标检测、OCR、图像分类、图像分割等方向,目前活动仅19.9,虽然付费但会长期更新,感兴趣的小伙伴可以…

超详细Eclipse配置JDK

在此附上Eclipse安装教程 超详细Eclipse安装教程 在此附上JDK1.8安装配置教程 超详细JDK1.8安装与配置 ①打开Eclipse–>点击Window–>点击Preferences ②找到Java–>找到Installed JREs–>点击Add… ③选中Standard VM–>之后点击Next ④点击Directory找…

Substrate 基础教程(Tutorials) -- 模拟网络 添加可信节点

三、模拟网络 本教程基本介绍了如何使用一个私有验证器&#xff08;validators&#xff09;的授权集合来启动私有区块链网络。 Substrate节点模板使用授权共识模型(authority consensus model)&#xff0c;该模型将块生产限制为授权帐户的旋转列表(rotating list)。授权帐户(…