• 刷题笔记-排序


    归并排序 -模板题

    思路:

    1.确定分界点 mid = l + r >> 2
    2.递归排序Left、Right部分
    3.使用双指针算法归并排序Left、Right部分

    代码:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int N = 100010;
    int a[N],tmp[N];
    
    void merge_sort(int *a , int l, int r)
    {
        //如果子序列小于等于1,则返回
        if(l >= r)  return;
        int mid = l + r >> 1;
        //递归排序
        merge_sort(a, l, mid),  merge_sort(a, mid+1 , r);
        //归并合二为一
        int i = l, j = mid + 1, k = 0;
        while(i <= mid && j <= r)
            if(a[i] <= a[j])   tmp[k++] = a[i++];
            else tmp[k++] = a[j++];
        while(i <= mid)   tmp[k++] = a[i++];
        while(j <= r)     tmp[k++] = a[j++];
        //在放回原数组
        for(i = l, j = 0; i <= r; i++, j++)
            a[i] = tmp[j];
    }
    
    int main(void)
    {
        int n;
        cin >> n;
        for(int i = 0; i < n; i++)    cin >> a[i];
       
        merge_sort(a,0,n-1);
        
        for(int i = 0; i < n; i++)   cout << a[i] << ' ';
        
        return 0;
    }
    

    逆序对的数量

    思路:

    1.总的数量等于 Left边中逆序对的数量、Right边中逆序对的数量、Left、Right两边的元素共同组成的逆序对的数量
    2.如何求算Left、Right两边的元素共同组成的逆序对的数量?

    • 考虑Right中元素被放入tmp数组中,即表示此元素小于Left边中任意元素,所以有 ans += mid - i + 1;

    代码:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    typedef long long int LL;
    
    const int N = 100010;
    int a[N],tmp[N];
    
    LL merge_sort(int *a , int l, int r)
    {
        //如果子序列小于等于1,则返回
        if(l >= r)  return 0;
        int mid = l + r >> 1;
        //递归排序
        LL res = merge_sort(a, l, mid) + merge_sort(a, mid+1 , r);
        //归并合二为一
        int i = l, j = mid + 1, k = 0;
        while(i <= mid && j <= r)
            if(a[i] <= a[j])   
            {
                tmp[k++] = a[i++];
            }
            else 
            {   
                res += (LL)mid - i + 1;
                tmp[k++] = a[j++];
            }
            
        while(i <= mid)   tmp[k++] = a[i++];
        while(j <= r)     tmp[k++] = a[j++];
        //在放回原数组
        for(i = l, j = 0; i <= r; i++, j++)
            a[i] = tmp[j];
        
        return res;
    }
    
    int main(void)
    {
        int n;
        cin >> n;
        for(int i = 0; i < n; i++)    cin >> a[i];
       
        LL ans = merge_sort(a,0,n-1);
        
        cout << ans << endl;
        
        return 0;
    }
    
  • 相关阅读:
    冲印数码照片的奥秘
    买手机(一)
    情人节的考验
    一日三茶
    追寻童年的乐趣在PSP上玩童年玩过的街机游戏
    转贴:常用的美国俚语
    用左手画CAD
    桃花朵朵开春游南汇桃花节
    不用GPRS照样用手机上网以后手机费不能报销的朋友们也能用手机上网啦!
    双休日去爬山
  • 原文地址:https://www.cnblogs.com/zy200128/p/12673543.html
Copyright © 2020-2023  润新知