zoukankan      html  css  js  c++  java
  • <剑指offer39>数组中出现次数超过一半的数字

    题目:数组中出现次数超过一半的数字

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

    解题思路:根据数组特点找出时间复杂度为O(n)的算法。因为该数字出现次数比其他所有数字出现的次数之和还要多,所有要找的数字肯定是最后一次把次数设为1时对应的数字。

    /*******************************************************************
    Copyright(c) 2016, Harry He
    All rights reserved.
    
    Distributed under the BSD license.
    (See accompanying file LICENSE.txt at
    https://github.com/zhedahht/CodingInterviewChinese2/blob/master/LICENSE.txt)
    *******************************************************************/
    
    //==================================================================
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 作者:何海涛
    //==================================================================
    
    // 面试题39:数组中出现次数超过一半的数字
    // 题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例
    // 如输入一个长度为9的数组{1, 2, 3, 2, 2, 2, 5, 4, 2}。由于数字2在数组中
    // 出现了5次,超过数组长度的一半,因此输出2。
    
    #include <cstdio>
    #include "..UtilitiesArray.h"
    
    bool g_bInputInvalid = false;
    
    bool CheckInvalidArray(int* numbers, int length)
    {
        g_bInputInvalid = false;
        if(numbers == nullptr && length <= 0)
            g_bInputInvalid = true;
    
        return g_bInputInvalid;
    }
    
    bool CheckMoreThanHalf(int* numbers, int length, int number)
    {
        int times = 0;
        for(int i = 0; i < length; ++i)
        {
            if(numbers[i] == number)
                times++;
        }
     
        bool isMoreThanHalf = true;
        if(times * 2 <= length)
        {
            g_bInputInvalid = true;
            isMoreThanHalf = false;
        }
    
        return isMoreThanHalf;
    }
    
    // ====================方法1====================
    int MoreThanHalfNum_Solution1(int* numbers, int length)
    {
        if(CheckInvalidArray(numbers, length))
            return 0;
     
        int middle = length >> 1;
        int start = 0;
        int end = length - 1;
        int index = Partition(numbers, length, start, end);
        while(index != middle)
        {
            if(index > middle)
            {
                end = index - 1;
                index = Partition(numbers, length, start, end);
            }
            else
            {
                start = index + 1;
                index = Partition(numbers, length, start, end);
            }
        }
     
        int result = numbers[middle];
        if(!CheckMoreThanHalf(numbers, length, result))
            result = 0;
    
        return result;
    }
    
    // ====================方法2====================
    int MoreThanHalfNum_Solution2(int* numbers, int length)
    {
        if(CheckInvalidArray(numbers, length))
            return 0;
     
        int result = numbers[0];
        int times = 1;
        for(int i = 1; i < length; ++i)
        {
            if(times == 0)
            {
                result = numbers[i];
                times = 1;
            }
            else if(numbers[i] == result)
                times++;
            else
                times--;
        }
     
        if(!CheckMoreThanHalf(numbers, length, result))
            result = 0;
     
        return result;
    }
    
    // ====================测试代码====================
    void Test(char* testName, int* numbers, int length, int expectedValue, bool expectedFlag)
    {
        if(testName != nullptr)
            printf("%s begins: 
    ", testName);
    
        int* copy = new int[length];
        for(int i = 0; i < length; ++i)
            copy[i] = numbers[i];
    
        printf("Test for solution1: ");
        int result = MoreThanHalfNum_Solution1(numbers, length);
        if(result == expectedValue && g_bInputInvalid == expectedFlag)
            printf("Passed.
    ");
        else
            printf("Failed.
    ");
    
        printf("Test for solution2: ");
        result = MoreThanHalfNum_Solution2(copy, length);
        if(result == expectedValue && g_bInputInvalid == expectedFlag)
            printf("Passed.
    ");
        else
            printf("Failed.
    ");
    
        delete[] copy;
    }
    
    // 存在出现次数超过数组长度一半的数字
    void Test1()
    {
        int numbers[] = {1, 2, 3, 2, 2, 2, 5, 4, 2};
        Test("Test1", numbers, sizeof(numbers) / sizeof(int), 2, false);
    }
    
    // 不存在出现次数超过数组长度一半的数字
    void Test2()
    {
        int numbers[] = {1, 2, 3, 2, 4, 2, 5, 2, 3};
        Test("Test2", numbers, sizeof(numbers) / sizeof(int), 0, true);
    }
    
    // 出现次数超过数组长度一半的数字都出现在数组的前半部分
    void Test3()
    {
        int numbers[] = {2, 2, 2, 2, 2, 1, 3, 4, 5};
        Test("Test3", numbers, sizeof(numbers) / sizeof(int), 2, false);
    }
    
    // 出现次数超过数组长度一半的数字都出现在数组的后半部分
    void Test4()
    {
        int numbers[] = {1, 3, 4, 5, 2, 2, 2, 2, 2};
        Test("Test4", numbers, sizeof(numbers) / sizeof(int), 2, false);
    }
    
    // 输入空指针
    void Test5()
    {
       int numbers[] = {1};
       Test("Test5", numbers, 1, 1, false);
    }
    
    // 输入空指针
    void Test6()
    {
        Test("Test6", nullptr, 0, 0, true);
    }
    
    int main(int argc, char* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
    
        return 0;
    }
  • 相关阅读:
    Scrum为什么不喜欢“来自客户的频繁变更”?
    [转]SQL Server计算列
    宽容,是创新的土壤
    【转载】《2010年年度总结》
    远程维护需要“千里眼”
    TOP语句放到表值函数外,效率异常低下
    “设计应对变化”实例讲解一个数据同步系统
    “批量少次”还是“少量多次”邮件通信系统效率浅谈
    NYOJ117 求逆序数
    NYOJ92 图像有用区域
  • 原文地址:https://www.cnblogs.com/focus-z/p/13251909.html
Copyright © 2011-2022 走看看