• 算法复习——分治算法


    侧重于分解:快速排序、次序选择

    侧重于合并:归并排序、逆序计数、最大子数组

    最大子数组问题

    GetAcross(A, left, mid, right)
    {
        // mid左边
        s_left = -INF, sum = 0;
        for(i=mid to left) {
            sum += A[i];
            if (sum > s_left) {
                s_left = sum;
            }
        }
        // mid右边
        s_right = -INF, sum =0;
        for (i=mid+1 to right) {
        	sum += A[i];
            if (sum > s_right) {
                s_right = sum;
            }
        }
        return (s_left + s_right);
    }
    
    MNC(A, left, right)
    {
        if (left >= right) return A[left];
        else {
            mid = (left + right)/2;
            s1 = MNC(A, left, mid);
            s2 = MNC(A, mid+1, right);
            s3 = GetAcross(A, left, mid, right);
            return max(s1, s2, s3);
        }
    }
    

    归并排序问题

    Merge(A, left, mid, right)
    {
        B[left..right] = A[left..right];
        k = 0;
        i = left, j = mid+1;
        while(i<=mid and j<=right) {
            if(B[i] <= B[j]) {
                A[k] = B[i];
                k++, i++;
            }
            else {
                A[k] = B[j];
                k++, j++;
            }
        }
        
        while (i <= mid) {
            A[k..right] = B[i..mid];
        }
        
        while (j <= right) {
            A[k..right] = B[j..right];
        }
        return A[left..right];
    }
    
    MergeSort(A, left, right)
    {
        if(left >= right) return A[left]
    	else {
            mid = (left + right)/2;
            MergeSort(A, left, mid);       // T(n/2)
            MergeSort(A, mid+1, right);	   // T(n/2)
            Merge(A, left, mid, right);    // O(n)
            return A[left..right];
        }
    }
    
    

    逆序计数问题

    Merge(A, left, mid, right)
    {
        B[left..right] = A[left..right];
        k = 0;
        i = left, j = mid+1;
        s3 = 0;
        while(i<=mid and j<=right) {
            if(B[i] <= B[j]) {
                A[k] = B[i];
                k++, i++;
            }
            else {
                A[k] = B[j];
                k++, j++;
                s3 += mid-i+1; // 如果B[i] > B[j], 那么B[i..mid] > B[j]
            }
        }
        
        while (i <= mid) {
            A[k..right] = B[i..mid];
        }
        
        while (j <= right) {
            A[k..right] = B[j..right];
        }
        return A[left..right];
    }
    
    MergeCount(A, left, right)
    {
        if(left >= right) return 0,A[left]
    	else {
           mid = (left + right)/2;
           s1 = MergeCount(A, left, mid);       	// T(n/2)
           s2 = MergeCount(A, mid+1, right);	   // T(n/2)
           s3 = Merge(A, left, mid, right);    		// O(n)
           return (s1+s2+s3), A[left..right];
        }
    }
    
    

    快速排序算法

    Partation(A, p, r)
    {
        x = A[r]; // 选取固定主元
        i = p - 1; 
        for (j=p to r-1) {
            if (A[j] <= x) {
               exchange(A[i+1], A[j]);
               i = i+1;
            }
        }
        exchange(A[r], A[i+1]); // 把主元放到中间
        return i+1;
    }
    
    QuickSort(A, p, r)
    {
        if (p < r) {
        	q = Partation(A, p, r);
            QuickSort(A, p, q);
            QuickSort(A, q+1, r);
        }
        
    }
    

    时间复杂度为(O(n^2))

    随机化选取主元

    Randomized-Partation(A, p, r)
    {
        k = random(p,r)
        x = A[k]; 
        exchange(A[k], A[r]);
        //
        i = p - 1; 
        for (j=p to r-1) {
            if (A[j] <= x) {
               exchange(A[i+1], A[j]);
               i = i+1;
            }
        }
        exchange(A[r], A[i+1]); // 把主元放到中间
        return i+1;
    }
    
    
    
    Randomized-QuickSort(A, p, r) {
        if (p < r) {
        	q = Randomized-Partation(A, p, r);
            Randomized-QuickSort(A, p, q);
            Randomized-QuickSort(A, q+1, r);
        }
    }
    

    时间复杂度为(O(nlogn))

    次序选择

    找一个数组中第k小的元素

    思路一:将整个数组排序((O(nlogn))), 然后直接选取下标为left+k-1的元素即可

    思路二:根据快速排序数组划分的思想,每次选取一个主元,然后把数组划分成左右两边,判断k 和 q-p+1的大小关系

    SelectionProblem(A, left, right)
    {
        q = Randomized-Partation(A, left, right);  //主要是使用了随机化快速排序,降低了时间复杂度
        if (k == q-p+1){
            return A[q];
        }
        else if (k < q-p+1) {
            return SelectionProblem(A, left, q-1);
        }
        else {
            return SelectionProblem(A, q+1, right);
        }
    }
    

    时间复杂度是(O(n))

    基于比较的排序算法时间复杂度的下限是(O(nlogn))

  • 相关阅读:
    03 Python之变量以及常量介绍
    看女程序员是如何处理男友出轨,网友回复更精彩
    四面美团,收割 offer
    MySQL 优化实战记录
    龙岗一个月350的出租房,我搬出来了
    程序员工作 996 生病 ICU ?
    真的有人在偷听我们讲话么?
    一次非常有趣的 SQL 优化经历
    如何阅读Java源码?
    从 0 开始手写一个 Mybatis 框架,三步搞定!
  • 原文地址:https://www.cnblogs.com/VanHa0101/p/14191488.html
Copyright © 2020-2023  润新知