国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【初階算法4】——歸并排序的詳解,及其歸并排序的擴展

這篇具有很好參考價值的文章主要介紹了【初階算法4】——歸并排序的詳解,及其歸并排序的擴展。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

前言

學習目標:

學習內(nèi)容:

一、介紹歸并排序

1.1 歸并排序的思路

1.2 歸并排序的代碼

1.2.1 mergesort函數(shù)部分?

1.2.2 process函數(shù)部分?

1.2.3 merge函數(shù)部分?

二、AC兩道經(jīng)典的OJ題目

題目一:逆序?qū)栴}

題目二:小和問題?

三、練習一道LeetCode的題目

四、總結(jié)在什么情況下使用歸并排序的算法

學習產(chǎn)出:


前言

??作者簡介: 加油,旭杏,目前大二,正在學習C++,數(shù)據(jù)結(jié)構(gòu)等??
??作者主頁:加油,旭杏的主頁??

?本文收錄在:再識C進階的專欄??

??代碼倉庫:旭日東升 1??

??歡迎大家點贊 ?? 收藏 ? 加關注哦!????

學習目標:

???????在這一篇博客中,我們要學習排序算法中比較重要的三個排序中的其中一個,就是歸并排序,并學會使用代碼進行編寫歸并排序,之后能夠AC兩道經(jīng)典的OJ題目,最后是刷幾道LeetCode的題目,這就是本博客的學習目標!


學習內(nèi)容:

通過上面的學習目標,我們可以列出要學習的內(nèi)容:

  1. 學習歸并排序的思想
  2. 使用代碼進行編寫歸并排序
  3. AC兩道經(jīng)典的OJ題目
  4. 練習幾道LeetCode的題目
  5. 總結(jié)在什么情況下使用歸并排序的算法

一、介紹歸并排序

???????在之前的學習中,我們可能或多或少的接觸過排序算法,也知道一些排序算法:冒泡排序選擇排序、插入排序。不過這些排序有共同點——時間復雜度為O(N * N),時間上不是那么有效,我們需要進行進一步的優(yōu)化,從而就有了我們這一篇博客講述的歸并排序,其時間復雜度為:O(N * logN),空間復雜度為:O(N)

1.1 歸并排序的思路

???????歸并排序,顧名思義,“歸并”的含義是將兩個兩個以上的有序表合并一個新的有序表。假設待排序數(shù)表有N個記錄,則可將其視為N個有序的子表,每一個子表的長度是1,然后兩兩歸并,得到[ N / 2 ]個長度為2或1的有序表;繼續(xù)兩兩歸并……如此重復,直到合并成一個長度為N有序表為止。下面小編將畫圖帶大家理解:

【初階算法4】——歸并排序的詳解,及其歸并排序的擴展,初階算法,算法,歸并排序,歸并排序的代碼,小和問題,逆序?qū)栴}

???????而這個排序剛開始有點像這個相反的做法,其思路是:先將這一大長串數(shù)組分割,因為其是一個遞歸的過程,就是將數(shù)組一直分割,直到每一個數(shù)組長度為1,此時每一個數(shù)組都是有序的;之后要開始合并數(shù)組,合并數(shù)組時將進行比較,看需要來判斷是升序或降序,合并的時候就如同上方的合并一樣,最后能夠得出一個有序的數(shù)組。

【初階算法4】——歸并排序的詳解,及其歸并排序的擴展,初階算法,算法,歸并排序,歸并排序的代碼,小和問題,逆序?qū)栴}

1.2 歸并排序的代碼

這個算法有三個部分組成,請看下面我一一為大家進行講解:

1.2.1 mergesort函數(shù)部分?

void mergesort(int arr[], int left, int right)
{
    int sz = right - left + 1; //計算數(shù)組的長度
    if(arr == NULL || sz < 2)  //如果數(shù)組的首元素不存在,則不用排序;
        return ;               //如果數(shù)組的長度只有一個,則也不用排序
    process(arr, left, right); //進入process函數(shù)部分
}

1.2.2 process函數(shù)部分?

void process(int arr[], int left, int right)
{
    int sz = right - left + 1;   //與mergesort函數(shù)的部分作用是一樣的
    if(arr == NULL || sz < 2)
        return ;
//分割數(shù)組
    int mid = left + ((right - left) >> 1);  //計算出這段數(shù)組中正中心的位置坐標
    process(arr, left, mid);     //遞歸過程中,將數(shù)組分為左右部分,這是左部分
    process(arr, mid + 1, right);//這是右部分
    merge(arr, left, mid, right);
}

1.2.3 merge函數(shù)部分?

void merge(int arr[], int left, int mid, int right)
{
    int sz = right - left + 1;
    int* help = (int*)malloc(sizeof(int) * sz); //構(gòu)造輔助數(shù)組
    int i = 0;
    int p1 = left;  //建立指針
    int p2 = mid + 1;
    while(p1 <= mid && p2 <= right) //如果左指針與右指針都不越界,則進入循環(huán)
    {
        help[i++] = arr[p1] > arr[p2] ? arr[p1++] : arr[p2++]; //進行比較,交換數(shù)據(jù)
    }
    while(p1 <= mid) //將左邊剩余的數(shù)據(jù)拷貝到輔助數(shù)組中
    {
        help[i++] = arr[p1++];
    }
    while(p2 <= right) //將右邊剩余的數(shù)據(jù)拷貝到輔助數(shù)組中
    {
        help[i++] = arr[p2++];
    }
    for(int i = 0; i < sz; i++) //最后將輔助數(shù)組中的數(shù)據(jù)轉(zhuǎn)移到原數(shù)組中
    {
        arr[left + i] = help[i];
    }
}

二、AC兩道經(jīng)典的OJ題目

題目一:逆序?qū)栴}

題目:

???????在數(shù)組中的兩個數(shù)字,如果前面一個數(shù)字大于后面的數(shù)字,則這兩個數(shù)字組成一個逆序?qū)?。輸入一個數(shù)組,求出這個數(shù)組中的逆序?qū)Φ目倲?shù)。

思路:

???????在這道題中,我們要注意題目中標紅的描述,這個逆序?qū)τ肋h都是前一個數(shù)字的坐標位置永遠小于后一個數(shù)字的坐標位置。這一點就和歸并排序不謀而合,歸并排序算法總是將左邊的數(shù)字與右邊的數(shù)字進行比較,然后進行排序。而這道題要求的是逆序?qū)Φ膫€數(shù),我們可以在進行比較的時候進行計數(shù),這就是大致思路。

???????將這個數(shù)組進行降序排序還是逆序排序呢?如果是降序排序時,我們將左邊有右邊進行比較,如果左邊大于右邊,則大于右邊所有的數(shù)字,進行計數(shù)即可;如果是升序排序可能會出現(xiàn)漏項的情況,自然排除升序,采用降序。

代碼:

int merge(int arr[], int left, int mid, int right)
{
    int sz = right - left + 1;
    int* help = (int*)malloc(sizeof(int) * sz);
    int p1 = left;
    int p2 = mid + 1;
    int i = 0;
    int ret = 0;
    while(p1 <= mid && p2 <= right)
    {
        ret += arr[p1]>arr[p2]?(right - p2 + 1):0; //如果左邊的數(shù)字大于右邊的數(shù)字,則計算右邊
//一共有多少數(shù)字
        help[i++] = arr[p1] > arr[p2]?arr[p1++]:arr[p2++];
    }
    while(p1 <= mid)
    {
        help[i++] = arr[p1++];
    }
    while(p2 <= right)
    {
        help[i++] = arr[p2++];
    }
    for(int i = 0; i < sz; i++)
    {
        arr[left + i] = help[i];
    }
    return ret;
}

int process(int arr[], int left, int right)
{
    int sz = right - left + 1;
    if(arr == NULL || sz < 2)
        return 0;
    int mid = left + ((right - left) >> 1);
    return process(arr, left, mid) + process(arr, mid + 1, right) + merge(arr, left, mid, right);
}

int revOrder(int arr[], int left, int right)
{
    int sz = right - left + 1;
    if(arr == NULL || sz < 2)
        return 0;
    return process(arr, left, right);
}

int reversePairs(int* nums, int numsSize){
    int left = 0;
    int right = numsSize - 1;
    int ans = revOrder(nums, left, right);
    return ans;
}

題目二:小和問題?

題目:

???????在一個數(shù)組中,每一個數(shù)左邊比當前的數(shù)小進行累加起來,叫做這個數(shù)組的小和,求一個數(shù)組的小和。

思路:

???????同理,看題目中被標紅的描述,進行降序排序,如果左邊的數(shù)字小于右邊的數(shù)字,則將左邊的數(shù)字乘右邊有多少個大于他的個數(shù),進行累加即可。

代碼:

int merge(int arr[], int left, int mid, int right)
{
	int sz = right - left + 1;
	int* help = (int*)malloc(sizeof(int) * sz);
	int i = 0;
	int p1 = left;
	int p2 = mid + 1;
	int count = 0;
	while (p1 <= mid && p2 <= right)
	{
		count += arr[p1] < arr[p2] ? (right - p2 + 1)*arr[p1] : 0;
		help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
	}
	while (p1 <= mid)
	{
		help[i++] = arr[p1++];
	}
	while (p2 <= right)
	{
		help[i++] = arr[p2++];
	}
	for (int i = 0; i < sz; i++)
	{
		arr[left + i] = help[i];
	}
	return count;
}

int process(int arr[], int left, int right)
{
	int sz = right - left + 1;
	if (arr == NULL || sz < 2)
		return 0;
	int mid = left + ((right - left) >> 1);
	return process(arr, left, mid) + process(arr, mid + 1, right) + merge(arr, left, mid, right);
}
int reverseOrder(int arr[], int left, int right)
{
	int sz = right - left + 1;
	if (arr == NULL || sz < 2)
		return 0;
	return process(arr, left, right);
}

int main()
{
	int arr[] = { 1,3,4,2,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = sz - 1;
	int ans = reverseOrder(arr, left, right);
	printf("%d\n", ans);
	return 0;
}

三、練習一道LeetCode的題目

題目:

???????給定一個數(shù)組?nums?,如果?i < j?且?nums[i] > 2*nums[j]?我們就將?(i, j)?稱作一個重要翻轉(zhuǎn)對。你需要返回給定數(shù)組中的重要翻轉(zhuǎn)對的數(shù)量。

思路:

???????前面的操作基本一樣,只需將merge函數(shù)部分進行修改即可,將左邊的指針不動,一一右邊的數(shù)字進行比較,如果條件成立,就將指針向右移動一位,如果不成立跳出,結(jié)果加上右指針減去初始位置的個數(shù)。

代碼:

int process(int arr[], int left, int right)
{
    int sz = right - left + 1;
    if(arr == NULL || sz < 2)
        return 0;
    int mid = left + ((right - left) >> 1);
    int n1 = process(arr, left, mid);
    int n2 = process(arr, mid + 1, right);
    int ret = n1 + n2;
    int p1 = left;
    int p2 = mid + 1;
    int i = 0;
    while(p1 <= mid)
    {
        while(p2 <= right && (long long)arr[p1]>2*(long long)arr[p2])
        p2++;
        ret += (p2 - mid - 1);
        p1++;
    }
    p1 = left;
    p2 = mid + 1;
    int* help = (int*)malloc(sizeof(int) * sz);
    while(p1 <= mid && p2 <= right)
    {
        help[i++] = arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
    }
    while(p1 <= mid)
    {
        help[i++] = arr[p1++];
    }
    while(p2 <= right)
    {
        help[i++] = arr[p2++];
    }
    for(int i = 0; i < sz; ++i)
    {
        arr[left + i] = help[i];
    }
    return ret;
}

int mergeSort(int arr[], int left, int right)
{
    int sz = right - left + 1;
    if(arr == NULL || sz < 2)
        return 0;
    return process(arr, left, right);
}

int reversePairs(int* nums, int numsSize){
    int left = 0;
    int right = numsSize - 1;
    return mergeSort(nums, left, right);
}

四、總結(jié)在什么情況下使用歸并排序的算法

???????小編覺得在數(shù)組對問題可能使用歸并排序,尤其是一個數(shù)組對中滿足一定條件,左邊的左邊小于右邊的坐標時,可以考慮考慮歸并排序算法的思想。文章來源地址http://www.zghlxwxcb.cn/news/detail-712983.html


學習產(chǎn)出:

  1. 學習歸并排序的思想
  2. 使用代碼進行編寫歸并排序
  3. AC兩道經(jīng)典的OJ題目
  4. 練習幾道LeetCode的題目
  5. 總結(jié)在什么情況下使用歸并排序的算法

到了這里,關于【初階算法4】——歸并排序的詳解,及其歸并排序的擴展的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【排序算法】 歸并排序詳解!深入理解!思想+實現(xiàn)!

    【排序算法】 歸并排序詳解!深入理解!思想+實現(xiàn)!

    ?? 嶼小夏 : 個人主頁 ??個人專欄 : 算法—排序篇 ?? 莫道桑榆晚,為霞尚滿天! ? 什么是歸并?通過歸并排序就能讓數(shù)據(jù)有序?分治法是怎么在歸并排序上應用的?本文將對歸并排序進行細致入微的講解,庖丁解牛般讓你徹底明白歸并排序! 歸并排序(MERGE-SORT)是建

    2024年02月08日
    瀏覽(24)
  • 【算法】歸并排序 詳解

    【算法】歸并排序 詳解

    排序: 排序,就是使一串記錄,按照其中的某個或某些的大小,遞增或遞減的排列起來的操作。 穩(wěn)定性: 假定在待排序的記錄序列中,存在多個具有相同的的記錄,若經(jīng)過排序,這些記錄的相對次序保持不變,即在原序列中, r[i] = r[j], 且 r[i] 在 r[j] 之前,而

    2024年02月09日
    瀏覽(16)
  • 排序算法-歸并排序(含C語言代碼示例)

    ????????歸并排序是一種基于分治思想的經(jīng)典排序算法,其主要思想是將待排序的數(shù)組分割成兩個子數(shù)組,分別對這兩個子數(shù)組進行遞歸排序,然后將排好序的子數(shù)組合并起來得到最終有序數(shù)組。整個歸并排序的過程可以分為三個步驟:分割、排序和合并。 ????????首

    2024年01月16日
    瀏覽(19)
  • 【排序算法】 歸并排序詳解!深入理解!思想+源碼實現(xiàn)!

    【排序算法】 歸并排序詳解!深入理解!思想+源碼實現(xiàn)!

    ?? 嶼小夏 : 個人主頁 ??個人專欄 : 算法—排序篇 ?? 莫道桑榆晚,為霞尚滿天! ? 什么是歸并?通過歸并排序就能讓數(shù)據(jù)有序?分治法是怎么在歸并排序上應用的?本文將對歸并排序進行細致入微的講解,庖丁解牛般讓你徹底明白歸并排序! 歸并排序(MERGE-SORT)是建

    2024年02月06日
    瀏覽(24)
  • ①歸并排序、快速排序 、堆排序、計數(shù)排序[算法、代碼模板、面試題]

    ①歸并排序、快速排序 、堆排序、計數(shù)排序[算法、代碼模板、面試題]

    個人簡介:Java領域新星創(chuàng)作者;阿里云技術博主、星級博主、專家博主;正在Java學習的路上摸爬滾打,記錄學習的過程~ 個人主頁:.29.的博客 學習社區(qū):進去逛一逛~ ?步驟 歸并排序 : 歸并排序是一種分治法(Divide and Conquer)的經(jīng)典排序算法,它的基本思想是將原始數(shù)組

    2024年02月04日
    瀏覽(21)
  • [排序算法]:歸并排序(Merge Sort)(遞歸與非遞歸實現(xiàn)詳解)

    [排序算法]:歸并排序(Merge Sort)(遞歸與非遞歸實現(xiàn)詳解)

    ????????歸并排序,是創(chuàng)建在歸并操作上的一種有效的排序算法。算法是采用分治法(Divide and Conquer)的一個非常典型的應用,且各層分治遞歸可以同時進行。歸并排序思路簡單,速度僅次于快速排序,為穩(wěn)定排序算法,一般用于對總體無序,但是各子項相對有序的數(shù)列。

    2024年01月20日
    瀏覽(37)
  • 七大排序算法——歸并排序,通俗易懂的思路講解與圖解(完整Java代碼)

    七大排序算法——歸并排序,通俗易懂的思路講解與圖解(完整Java代碼)

    排序:所謂排序,就是使一串記錄,按照其中的某個或某些的大小,遞增或遞減的排列起來的操作。 上述待排序的數(shù)中,有兩個5。 將 前面 的5標記一個a, 將 后面 的5標記一個b。 通過算法進行排序后,這一組數(shù)就有序了, 但是要看兩個相同的5的位置是否有改變。

    2024年02月15日
    瀏覽(25)
  • 【數(shù)據(jù)結(jié)構(gòu)初階】八大排序(三)——歸并排序&&計數(shù)排序

    【數(shù)據(jù)結(jié)構(gòu)初階】八大排序(三)——歸并排序&&計數(shù)排序

    大家好我是沐曦希?? 往期博客:【數(shù)據(jù)結(jié)構(gòu)初階】八大排序(一)——希爾排序堆排序直接插入排序直接選擇排序 【數(shù)據(jù)結(jié)構(gòu)初階】八大排序(二)——快速排序冒泡排序 歸并排序(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一

    2024年02月03日
    瀏覽(89)
  • 詳解八大排序算法-附動圖和源碼(插入,希爾,選擇,堆排序,冒泡,快速,歸并,計數(shù))

    詳解八大排序算法-附動圖和源碼(插入,希爾,選擇,堆排序,冒泡,快速,歸并,計數(shù))

    目錄 ??一.排序的概念及應用?? ?1.排序的概念 ?2.排序的應用 ?3.常用的排序算法 ??二.排序算法的實現(xiàn)?? 1.插入排序 1.1直接插入排序 1.2希爾排序(縮小增量排序) 2.選擇排序 2.1直接選擇排序 2.2堆排序 3.比較排序 3.1冒泡排序 3.2快速排序? 遞歸版本 快速排序遞歸優(yōu)化 快速

    2024年02月01日
    瀏覽(17)
  • 【算法與數(shù)據(jù)結(jié)構(gòu)】歸并排序的代碼實現(xiàn)(詳細圖解)以及master公式的講解

    【算法與數(shù)據(jù)結(jié)構(gòu)】歸并排序的代碼實現(xiàn)(詳細圖解)以及master公式的講解

    目錄 1、歸并排序 ?1.1、算法描述 ?1.2、圖解說明 2、代碼實現(xiàn)? 3、master公式 3.1、公式以及結(jié)論 3.2、適用于某些特殊的遞歸 3.3、計算歸并排序的時間復雜度 歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用 遞歸 或者說是 分治法 (Divide and Conquer)的一個非

    2024年02月08日
    瀏覽(36)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包