剑指offer-数组中出现次数超过一半的数字(数组)

题目描述

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

看到这个就想到了c++中的map,C++中map提供的是一种键值对容器,里面的数据都是成对出现的。每对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值(values)。

因为只可能有一个数出现的次数count是大于长度的一半的。因此通过count>len/2,可以找到唯一对应的numbers[i]。

先对numbers进行排序,这样相同的数字就排列在一起。如果前后两数相等count的值就加1,把count作为键值,numbers[i]为values。

c++实现:

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if(numbers.size()==0)
            return 0;
        int len = numbers.size();
        sort(numbers.begin(),numbers.end());
        int count=1;
        map<int,int> n;
        for(int i=0;i<len;i++)
        {
            if(numbers[i]==numbers[i+1])
                count++;
            if(numbers[i]!=numbers[i+1])
            {
                n.insert(pair<int,int>(count,numbers[i]));
                count=1;
            }
            if(count>len/2)
                return numbers[i];
            }
        return 0;
    }
};

因为用到了sort函数,时间复杂度为O(n*logn)。考虑有没有更优化的情况。而且这里存在问题,虽然count>len/2的值是唯一的,但是对于其他的数字选择了忽略次数对应关系,即有可能有其他的两个数count都为2。

方法二:

不使用sort函数,在map中,对不存在的键值自动分配空间,对应values值为0

用numbers[i]的值作为键值,这样键值对应count就是这个数的次数,也就是数-次数这个组合。numbers[i]出现,count就自增1,也就是相同数字出现时,count的值加一。注意++在左,先自增再赋值。

这个方法的时间复杂度为O(n),也比上面的方法更直观一些

推荐算法(c++)

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if(numbers.size()==0)
            return 0;
        int len = numbers.size();
        sort(numbers.begin(),numbers.end());
        int count=1;
        map<int,int> n;
        for(int i=0;i<len;i++)
        {
            count=++n[numbers[i]];  //n[numbers[i]]的初始值是0,因此要先++
            if(count>len/2)
                return numbers[i];
        }
        return 0;
    }
};

方法三:

还在讨论区中看到一个很巧妙的方法,这里也放出来。

如果存在这个数,那么这个数的count一定比其他数加起来的count还多,所以如果num是这个数,那么他的count永远不会被减至零。举几个例子就能很清楚的理解这个方法的思路了。

比如1,1,2,3,1。1,2,1,3,1,2,1

想象一下1,1,2,3,1.这样就算前面count减至零了后面num还是等于1

        int n = numbers.size();
        if (n == 0) return 0;
         
        int num = numbers[0], count = 1;
        for (int i = 1; i < n; i++) {
            if (numbers[i] == num) count++;
            else count--;
            if (count == 0) {
                num = numbers[i];
                count = 1;
            }
        }
        // Verifying
        count = 0;
        for (int i = 0; i < n; i++) {
            if (numbers[i] == num) count++;
        }
        if (count * 2 > n) return num;
        return 0;

python实现:

python用到的是字典,也是一个key值对应一个values值

这里用numbers[i]的值作为key值,count作为values值,得到每个数字出现的次数的一个字典

# -*- coding:utf-8 -*-
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        dic={}
        n=len(numbers)
        for i in range(n):
            if numbers[i] in dic:
                dic[numbers[i]]+=1
            else:
               
                dic[numbers[i]]=1
            if dic[numbers[i]]>n/2:
                return numbers[i]
        return 0

猜你喜欢

转载自blog.csdn.net/Mr_xuexi/article/details/84555464
今日推荐