• [剑指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)。
    • 思路二:
      思路:利用快排的partion函数。
      算法描述:记数组长度为n,数组第n/2大的数即中位数即是要找的数。利用快排思想,每一轮partition后,定位一个数(位置也表示第几小),将该数的位置与中位比较,若该数的位置大于中位,则应partion该数左侧的这些比该数小的数。反之partion右侧。直到partion的这个数位置是中位。
      时间复杂度O(n),但会改变输入
    • 思路三:
      思路:由题,所求数比其他所有数出现次数还要多。
      算法描述:遍历数组,记两个变量,一个是临时元素变量,一个是次数,当便利到的的元素与临时元素变量相同则次数++,相异则次数--;若次数已为0,则临时元素变量换为下一个元素,次数设为1;这样最终的临时元素所存元素即为所求值。
      时间复杂度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;
    		}
    	}
    };
    

    思路三代码

    class Solution {
    public:
    	int MoreThanHalfNum_Solution(vector<int> numbers) {
    		if (numbers.empty()) {
    			return 0;
    		}
    		int num;
    		int numCnt = 0;
    		for (int i = 0;i < numbers.size();++i) {
    			if (numCnt == 0) {
    				num = numbers[i];
    				++numCnt;
    			}
    			else {
    				if (numbers[i] == num) {
    					++numCnt;
    				}
    				else {
    					--numCnt;
    				}
    			}
    		}
    		if (!moreThanHalfCheck(numbers,num)) {
    			return 0;
    		}
    		else {
    			return num;
    		}
    	}
    private:
    	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;
    		}
    	}
    };
    
  • 相关阅读:
    一个比较日期大小的javascript函数
    导出Excel(利用xml标记)
    Oracle 数据库的备份与恢复
    总是浮在页面底部的广告DIV
    实用批处理文件 (IP设置.bat, 清理系统垃圾.bat, atc.)
    【转:来源不详】几家IT公司面试全揭秘
    二级联动(javascript Array)
    JS实现定时循环上翻
    ORACLE函数大全 [转]
    C#中Timer类与线程
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/10478288.html
Copyright © 2020-2023  润新知