[剑指Offer]39-数组中出现次数超过一半的数字(快排延申,找第k大数同理)(思路三待补)

题目链接

https://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163?tpId=13&tqId=11181&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解题思路

思路一:排序再计数,时间复杂度O(nlogn)。
思路二:记数组长度为n,数组第n/2大的数即中位数即是要找的数。利用快排思想,每一轮partition后,定位一个数(位置也表示第几小),将该数的位置与中位比较,若该数的位置大于中位,则应partion该数左侧的这些比该数小的数。反之partion右侧。直到partion的这个数位置是中位。时间复杂度O(n)。
思路三:

关于特例:若输入数组中没有出现次数超过一半的数,则返回0.对于思路二的解法,这个要在找到第n/2大数后判断一下。

相关知识

我认为,关于快排,精髓在于partion函数:即每次定位一个数,即是最终排序的位置,且该数左侧的数都比它小,右侧的数都比它大。

思路二代码 O(n)

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if (numbers.empty()) {
            return 0;
        }
        int index = partition(numbers, 0, numbers.size() - 1);
        int mid = numbers.size() >> 1;
        while (index != mid) {
            if (index > mid) {
                index = partition(numbers, 0, index - 1);
            }
            else if (index < mid) {
                index = partition(numbers, index + 1, numbers.size());
            }
        }

        if (!moreThanHalfCheck(numbers, numbers[index])) {
            return 0;
        }
        else {
            return numbers[index];
        }
        
    }
private:
    int partition(vector<int>& num, int start, int end) {
        if (num.empty() || start > end || start < 0) {
            throw "invaild!";
        }
        int index = randomInRange(start, end);
        swap(num[start], num[index]);

        int l = start;
        int r = end;
        int tempElm = num[l];
        while (l<r)
        {
            while (num[r] >= tempElm && l < r) {
                --r;
            }
            if (l != r) {
                num[l] = num[r];
                ++l;
            }
            while (num[l] <= tempElm && l < r) {
                ++l;
            }
            if (l != r) {
                num[r] = num[l];
                --r;
            }
        }
        num[l] = tempElm;
        return l;
    }

    int randomInRange(int start, int end) {
        if (start > end) {
            throw"invaild!";
        }
        srand((unsigned)time(0));
        int index = start + rand() % (end - start + 1);
        return index;
    }

    void swap(int& a, int& b) {
        int temp = a;
        a = b;
        b = temp;
    }

    bool moreThanHalfCheck(vector<int> numbers, int number) {
        int numberCnt = 0;
        for (int i = 0;i < numbers.size();++i) {
            if (numbers[i] == number) {
                ++numberCnt;
            }
        }
        if (numberCnt > numbers.size() / 2) {
            return true;
        }
        else {
            return false;
        }
    }
};

猜你喜欢

转载自www.cnblogs.com/coding-gaga/p/10478288.html