• 2016腾讯编程题:微信红包


    题目描述

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

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

    测试样例:
    [1,2,3,2,2],5
    返回:2

    解题

    题目要求一定存在大于数量一半的数,测试用例出现不到一半的情况。

    当一定存在大于一半的数时候,直接求中位数就好了,快排求中位数,在找到中位数,在统计中位数出现的次数,大于一半就是答案否则返回0 

    import java.util.*;
    
    public class Gift {
        public int getValue(int[] gifts, int n) {
            // write code here
            //if(n == 134)
           //     return 0;
            quickSort(gifts,0,n-1);
            int count = 0;
            for(int i = 0;i< n;i++){
                if(gifts[i] == gifts[n / 2])
                    count++;
            }
            return count>n/2?gifts[n/2]:0;
        }
        // 快速排序取中位数
        public void quickSort(int[] A,int low,int high){
            if(low >= high)
                return;
            int mid = partition(A,low,high);
            quickSort(A,low,mid - 1);
            quickSort(A,mid+1,high);
        }
        public int partition(int [] A,int low ,int high){
            int x = A[high];
            int i = low - 1;
            for( int j = low;j<= high - 1;j++){
                if( A[j] <= x){
                    i = i + 1;
                    int temp = A[i];
                    A[i] = A[j];
                    A[j] = temp;
                }
            }
            int temp = A[i+1];
            A[i+1] = A[high];
            A[high] = temp;
            return i + 1;
        }
    }

    参考剑指Offer

    在遍历数组的时候保存两个数:一个是数组中的一个数,一个是次数。当我们遍历到下一个数字的时候,如果下一个数和我们之前保存的数字相同,则次数加一;如果下一个数字和我们之前保存的数组不同,则次数减一。如果次数为0,我们需要更新保存的下一个数字,并把次数记作为1

    import java.util.*;
    
    public class Gift {
        public int getValue(int[] A, int n) {
            
            int count = 0;
            int mid = -1;
            for(int i = 0;i< n;i++){
                if(A[i] == mid){
                    count++;
                }else {
                    if(count!=0){
                        count--;
                    }else{
                        mid = A[i];
                        count = 1;
                    }
                }
            }
            count = 0;
            for(int i = 0;i< n;i++){
                if(A[i] == mid)
                    count++;
            }
            return count>n/2?mid:0;
        }
       
    }

    剑指offer上第一种方法不需要严格的排序,利用的快排的partition的思想,找到使得某一侧的划分在n/2附近这里就是中位数的位置。

    import java.util.*;
    
    public class Gift {
        public int getValue(int[] A, int n) {
            
            int count = 0;
            
            int midId = partition(A,0,n-1);
            while(midId != n/2){
                if(midId > n/2){
                    midId = partition(A,0,midId-1);
                }else{
                    midId = partition(A,midId+1,n-1);
                }
            }
            int mid = A[midId];
            for(int i = 0;i< n;i++){
                if(A[i] == mid)
                    count++;
            }
            return count>n/2?mid:0;
        }
        public int partition(int[] A,int low ,int high){
            int x = A[high];
            int i = low - 1;
            for(int j = low;j< high ;j++){
                if(A[j] <= x){
                    i = i + 1;
                    int tmp = A[i];
                    A[i] = A[j];
                    A[j] = tmp;
                }
            }
            int tmp = A[i + 1];
            A[i + 1] = A[high];
            A[high] = tmp;
            return i + 1;
        }
       
    }
  • 相关阅读:
    rqnoj PID95:多多看DVD(加强版)
    洛谷1309:瑞士轮
    codevs 1052:地鼠游戏
    noi openjudge7627:鸡蛋的硬度
    codevs 1039:数的划分
    lesson 20 pioneer pilots
    TPO-10 C2 Return a literature book
    lesson 19 A very dear cat
    word record 01
    lesson 18 Electric currents in modern art
  • 原文地址:https://www.cnblogs.com/bbbblog/p/5387308.html
Copyright © 2020-2023  润新知