首页 > 其他分享 >力扣148排序链表--复习归并和快速排序

力扣148排序链表--复习归并和快速排序

时间:2024-03-12 22:14:25浏览次数:37  
标签:head ListNode cur -- nullptr next 链表 int 排序

递归的归并排序

归并排序主要流程是拆分 -- 排序 -- 合并 -- 排序 -- 合并

//拆分
void mergeSort(vector<int>& nums,int start, int end)
{
	if(start>=end) return ;
	int mid = start+(end-start)/2;
	mergeSort(nums,start,mid);
	mergeSort(nums,mid+1,end);
	//最后一层排序
	merge(nums,start,mid,end);
}
//排序
void merge(vector<int>& nums,int start, int mid, int end)
{
	vector<int> temp(end-start+1);
	int p1 = start;
	int p2 = mid+!;
	int p = 0;
	while(p1<=mid && p2<=end)
	{
		if(nums[p1] < nums[p2])
		{
			temp[p++] = nums[p1++];
		}
		else
		{
			temp[p++] = nums[p2++];
		}
	}
	while(p1<=mid)
	{
		temp[p++] = nums[p1++]; 
	}
	while(p2<=end)
	{
		temp[p++] = nums[p2++];
	}
	for(int i = 0;i<temp.size();i++)
	{
		nums[i] = temp[i];
	}
}
//实际调用
void sort(vector<int>& nums)
{
	mergeSort(nums,0,nums.size()-1);
}

对于链表的递归归并排序

最主要的就是如何找到中间节点,可以利用快慢指针来寻找中间节点,然后在mergeSort函数中记录中间节点的下一个节点,然后断开mid->next = nullptr;

class Solution {
public:
    //寻找中点
    ListNode* FindMid(ListNode* head)
    {
        if(head == nullptr) return nullptr;
        //快慢指针
        ListNode* fast = head->next;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }
    //合并
    ListNode* merge(ListNode* left,ListNode* right)
    {
        ListNode* dummy = new ListNode(-1,left);
        ListNode* cur = dummy;
        while(left && right)
        {
            if(left->val < right->val)
            {
                cur->next = left;
                left = left->next;
            }
            else
            {
                cur->next = right;
                right = right->next;
            }
            cur = cur->next;
        }
        while(left)
        {
            cur->next = left;
            left = left->next;
            cur = cur->next;
        }
        while(right)
        {
            cur->next = right;
            right = right->next;
            cur = cur->next;
        }
        return dummy->next;
    }
    //归并排序
    ListNode* mergeSort(ListNode* head)
    {
        //当为空或者只有一个节点时直接返回
        if(head == nullptr || head->next == nullptr)
        {
            return head;
        }
        //寻找中间节点
        ListNode* mid = FindMid(head);
        ListNode* next = mid->next;
        //断开分段
        mid->next = nullptr;
        //划分
        ListNode* left = mergeSort(head);
        ListNode* right = mergeSort(next);

        //合并
        return merge(left,right);
    }
public:
    ListNode* sortList(ListNode* head) {
        return mergeSort(head);
    }
};

快速排序

冒泡排序基础上使用了递归分治法,快速排序在每一轮挑选一个基准元素,并让其他比它大的元素移到数列一边,比他小的移动到另一边,进行拆解。

int partition(vector<int>& nums,int start, int end)
{
	//假设以最后一个值为基准
	int resval = nums[end];
	int res = start-1;
	for(int i = start;i<end;i++)
	{
		if(nums[i] <= resval)
		{
			swap(nums[i],nums[++res]);
		}
	}
	//将基准点交换到分割点的右侧
	swap(nums[res+1],nums[end]);
	return res+1;
}


void quickSort(vector<int>& nums,int start, int end)
{
	if(start >= end)
	{
		return ;
	}
	//获取基准的准确位置
	int mid = partition(nums,start,end);
	quickSort(nums,start,mid-1);
	quickSort(nums,mid+1,end);
}

快速排序链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* FindMid(ListNode* head)
    {
        //if(head == nullptr || head->next == nullptr) return head;
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            fast= fast->next->next;
            slow = slow->next;
        }
        return slow;
    }
    ListNode* quickSort(ListNode* head)
    {
        if(head == nullptr || head->next == nullptr) return head;
        //3组指针:小于 等于 大于 基准值的边界节点
        ListNode* leftmin = new ListNode(-1);
        ListNode* rightmin = leftmin;
        ListNode* lefteq = new ListNode(-1);
        ListNode* righteq = lefteq;
        ListNode* leftmax = new ListNode(-1);
        ListNode* rightmax = leftmax;

        ListNode* cur = head;
        //选择中间节点为基准
        int pivot = FindMid(head)->val;

        while(cur)
        {
            //记录当前分段头节点的下一个节点
            ListNode* next = cur->next;

            //当当前分段的第一个值小于当前分段的基准,截断
            //更新小于的区间
            if(cur->val < pivot)
            {
                cur->next = nullptr;
                rightmin->next = cur;
                rightmin = rightmin->next;
            }
            else if(cur->val > pivot)
            {
                cur->next = nullptr;
                rightmax->next = cur;
                rightmax = rightmax->next;
            }
            else
            {
                cur->next = nullptr;
                righteq->next = cur;
                righteq = righteq->next;
            }
            //对下一个节点开始判断
            cur = next;
        }
        //对小于和大于的链表快排
        leftmin = quickSort(leftmin->next);
        leftmax = quickSort(leftmax->next);

        //leftmin 可能为空
        lefteq = lefteq->next;
        righteq->next = leftmax;
        if(leftmin == nullptr) return lefteq;
        else
        {
            rightmin = leftmin;
            while(rightmin->next)
            {
                rightmin = rightmin->next;
            }
            rightmin->next = lefteq;
            return leftmin;
        }
    }
public:
    ListNode* sortList(ListNode* head) {
        return quickSort(head);
    }
};

标签:head,ListNode,cur,--,nullptr,next,链表,int,排序
From: https://www.cnblogs.com/XTG111/p/18069251

相关文章

  • NVM安装和使用(无法下载npm)
    1.卸载已经安装的node版本2.下载nvm_setup.exe2.1github官网上下载2.2我给你免费发3.安装nvm4.在cmd中输入nvminstall15.14.0node会被正常安装下来,但是npm不会被安装下来但是地址栏会给你npm下载地址和下载后要存放的位置5.下载后解压复制该文件6.打开要存放的位......
  • 小白Windows下通过Ollama部署使用本地模型
    安装环境运行环境为windowsR9000P2021拯救者笔记本AMDR7-5800H32G内存NVIDIARTX3070LaptopGPU安装主程序Ollama下载exe,直接下一步下一步没有设置可以更改windows默认安装路径:C:\Users\wbigo\AppData\Local\Programs\Ollama\安装后会自动将该路径加入环境变量双......
  • YC256B [ 20240312 CQYC省选模拟赛 T2 ] count
    题意对于一个长度为\(n\)的排列\(P\)。你需要求出所有满足条件的长度为\(k\)的数列\(A\)的个数。\(A\)单调不减且\(1\leA_i\len\)\(\min_{j=1}^{A_1}P_j=\min_{j-1}^{A_i}P_j\)求出对于\(P_1=x\)的所有排列的满足条件的\(A\)的个数。Sol......
  • android使用okhttp3连接springboot
    首先在build.gradle.kts中导入依赖在dependencies{}中添加以下代码implementation("com.squareup.okhttp3:okhttp:4.9.1")之后在MainActivity中加入以下代码privateOkHttpClientclient=newOkHttpClient();privatevoidsendPostRequest(Useruser){//......
  • 第七天
    c++打卡一、哈希表理论哈希表用途:快速判断一个元素是否在集合里定义:哈希表是根据关键码的值而直接进行访问的数据结构好处:枚举的时间复杂度为O(n),而使用哈希表,时间复杂度为O(1)三种哈希结构:数组、集合set、映射map使用场景:集合:unordered_set查询、增删快,且不重复,set有......
  • macOS下安装telegraf记录
    一、通过homebrew安装influxdb官网上说通过homebrew安装,命令如下:brewupdate&&brewinstalltelegraf我执行后,发现报错:dialtcp142.251.42.241:443:i/otimeo 网上说,解决办法:换一个国内能访问的代理地址goproxy.cngoenv-wGOPROXY=https://goproxy.cn对我没用......
  • 中考英语首字母快速突破004-2021上海虹口英语二模-Exploring Fun Career Options for
    PDF格式公众号回复关键字:ZKSZM004原文​Withequalopportunities,womenareabletochoosetheirownidealjobs.Ifa9to5officejobisn'tyourstyle,considerthefollowingf(71)funjobsavailable.​Wedding(婚礼)planner​Whilesom......
  • SciTech-Mathmatics-RealAnalysis: Cantor-Schröder-Bernstein Theorem
    Cornell:https://www.cs.cornell.edu/courses/cs2800/2017fa/lectures/lec14-cantor.htmlUCLA:https://web.cs.ucla.edu/~palsberg/course/cs232/papers/bernstein.pdfhttps://artofproblemsolving.com/wiki/index.php/Schroeder-Bernstein_Theoremhttps://www.whitman.e......
  • 从键盘输入两个数,求它们的和并输出 &&从键盘输入三个数到a,b,c中,按公式值输出
    别急别急,先看完(从初学者出发,大佬勿喷,Iam小小蒟蒻)从键盘输入两个数,求它们的和并输出作者 陈春晖单位 浙江大学本题目要求读入2个整数A和B,然后输出它们的和。输入格式:在一行中给出一个被加数在另一行中给出一个加数输出格式:在一行中输出和值。输入样例:在这里......
  • ruoyi框架学习笔记(二)
    三、通知公告发布流程搭建3.1功能策划在第一篇学习笔记中已经将“通知公告”拆分为两个部分,分别为全部公告:主要是实现查看所有用户已经走完发布流程且是发布状态的公告;我的公告:实现当前用户新建公告、发起审批流程并发布公告的编辑位置;在笔记一中已经实现上述两个部分的前......