zoukankan      html  css  js  c++  java
  • 找出数组中出现次数超过一半的元素

    参考地址:http://www.cnblogs.com/DayByDay/p/3871834.html?utm_source=tuicool&utm_medium=referral

    题目:找出数组中出现次数超过一半的元素(前提是该元素一定存在)

    解法1:每次删除数组中两个不同的元素,删除后,要查找的那个元素的个数仍然超过删除后的元素总数的一半

    解法2:如果数据量小,可以对数组进行排序,那么数组中间的数就是出现次数超过一半的数

     1 #include <stdio.h>
     2 
     3 int half_number(int a[], int n)
     4 {
     5     if( a == NULL || n <= 0 )
     6         return -1;
     7 
     8     int i, candidate;
     9     int times = 0;
    10     for( i=0; i<n; i++ )
    11     {
    12         if( times == 0 )
    13         {
    14             candidate = a[i];
    15             times = 1;
    16         }
    17         else if( a[i] == candidate )
    18             ++times;
    19         else
    20             --times;
    21     }
    22     return candidate;
    23 }
    24 
    25 int main(void)
    26 {
    27     int a[] = {1,2,3,2,2,2,5,4,2};
    28 
    29     int result = half_number(a, 9);
    30     if( result != -1 )
    31         printf("%d
    ", result);
    32     else
    33         printf("Error.
    ");
    34 
    35     return 0;
    36 }

    坑!坑!坑!(腾讯挖的):

    春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。

    给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。

    本题的测试案例上包括0的情况,即红包中没有出现相同金额次数超过红包一半的,那此种情况应该返回0

     1 class Gift {
     2 public:
     3     int getValue(vector<int> gifts, int n) {
     4         // write code here
     5         // write code here
     6         int nRet;
     7         int nCnt = 0;
     8         for(int i = 0; i < n; ++i){
     9             if(nCnt == 0){
    10                 nRet = gifts[i];
    11                 nCnt = 1;   
    12             }
    13             else if(nRet == gifts[i]){
    14                 ++nCnt;
    15             }
    16             else{
    17                 --nCnt;
    18             }
    19         }
          //最后要做个验证
    20 nCnt = 0; 21 int nLeft = n; 22 for(int i = 0; i < n; ++i){ 23 if(gifts[i] == nRet) 24 ++nCnt; 25 if(nCnt + nLeft < n/2) 26 return 0; 27 if(nCnt > n/2) 28 return nRet; 29 30 --nLeft; 31 } 32 return 0; 33 } 34 };

    该题的扩展:数组中有3个元素出现的次数都超过数组元素总数N的1/4, 找出这三个元素

    解法:同上,但是每次删除4个互不相同的元素,处理上比上面的稍微麻烦

     1 #include <stdio.h>
     2 
     3 void find(int a[], int n)
     4 {
     5     if( a==NULL || n<=3 )
     6     {
     7         printf("Error.
    ");
     8         return ;
     9     }
    10 
    11     int i,j;
    12     int times[3] = {0,0,0}; // 3个candidate的计数
    13     int candidate[3] = {-1,-1,-1}; // 假设元素不可能是-1
    14 
    15     for( i=0; i<n; i++ )
    16     {
    17         if( times[0] == 0 && a[i] != candidate[1] && a[i] != candidate[2] ) // 第1个candidate目前空缺, 且当前元素a[i]不等于其他两个candidate时, 将该元                                                素作为新的candidate
    18         {
    19             candidate[0] = a[i];
    20             times[0] = 1;
    21         }
    22         if( times[1] == 0 && a[i] != candidate[0] && a[i] != candidate[2] )
    23         {
    24             candidate[1] = a[i];
    25             times[1] = 1;
    26         }
    27         if( times[2] == 0 && a[i] != candidate[1] && a[i] != candidate[0] )
    28         {
    29             candidate[2] = a[i];
    30             times[2] = 1;
    31         }
    32         else if( a[i] == candidate[0] )
    33         {
    34             ++times[0];
    35         }
    36         else if( a[i] == candidate[1] )
    37         {
    38             ++times[1];
    39         }
    40         else if( a[i] == candidate[2] )
    41         {
    42             ++times[2];
    43         }
    44         else // 删除4个各不相同的数组元素, 删除后
    45         {
    46             --times[0];
    47             --times[1];
    48             --times[2];
    49         }
    50     }
    51     printf("%d %d %d
    ",candidate[0],candidate[1],candidate[2]);
    52 }
    53 
    54 int main(void)
    55 {
    56     int a[] = {5,1,1,3,8,1,3,1,4,1,7,1,2,9,2,3,2,3,2,3,2,3,2};
    57     find(a, 23);
    58     return 0;
    59 }
  • 相关阅读:
    hdu1003 Max Sum【最大连续子序列之和】
    HDU 2639 骨头收集者 II【01背包 】+【第K优决策】
    poj2184 Cow Exhibition【01背包】+【负数处理】+(求两个变量的和最大)
    HDU 2955_Robberies 小偷抢银行【01背包】
    UVa 562
    HDU 1159 Common Subsequence 【最长公共子序列】模板题
    hdu 5748 Bellovin【最长上升子序列】
    POJ 3903 Stock Exchange 【最长上升子序列】模板题
    UVA 624 CD[【01背包】(输出路径)
    hdu 2546 饭卡【01背包】
  • 原文地址:https://www.cnblogs.com/dongsheng/p/5067238.html
Copyright © 2011-2022 走看看