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

    题目描述

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

    方法1:基于partition函数的算法  

    public class Test {
        
        public static void main(String[] args) {
            int[] a = {1,1,1,3,4};
            System.out.println(moreThanHalfNum(a));
        }
    
        /**
         * 1、对数组进行快速排序,那么位于数组中间的数字一定是那个出现次数超过数组长度一半的数字。
         * @param array
         * @return
         */
        private static int moreThanHalfNum(int[] array) {
            if(array == null || array.length <= 0) 
                return 0;
            int low = 0;
            int high = array.length - 1;
            int mid = array.length >> 1; 
            int index = partition(array, low, high);
            
            while(index != mid) {
                if(index < mid) {
                    index = partition(array, index+1, high);
                } else {
                    index = partition(array, low, index - 1);
                }
            }
            int result = array[mid];
            
            if(!checkMoreThanHalfNum(array, result)) {
                return 0;
            }
            return result;
        }
        
        private static boolean checkMoreThanHalfNum(int[] array, int result) {
            int times = 0;
            for(int i=0; i<array.length; i++) {
                if(array[i] == result) {
                    times ++;
                }
            }
            
            if(times * 2 <= array.length)
                return false;
            return true;
        }
    
        private static int partition(int[] a, int low, int high) {
            int key = a[low];                 // 第一个数作为key,将数组划为两部分
            while(low < high) {                // 左右未相遇
                while(low < high && a[high] >= key)      // 先从数组右边往前寻找第小于key的数(必须从右开始),交换
                    high --;                                
                a[low] = a[high];
                while(low < high && a[low] <= key)     // 再从左往右找大于key的数,交换
                    low ++;
                a[high] = a[low];              
            }
            a[low] = key;   // key放在合适的位置,其左边都小于key,右边都大于key
            return low;
        }
    }

    方法2:

    数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值: 一个是数组中的一个数字, 一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加 l :如果下一个数字和我们之前保存的数字不同,则次数减 1 。如果次数为0,我们需要保存下一个数字,并把次数设为 1 。由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为 1 时对应的数字。

    public class Test {
        
        public static void main(String[] args) {
            int[] a = {1,2,3};
            System.out.println(majorityElement(a));
        }
        
        public static int majorityElement(int[] a) {
            if(a == null || a.length <= 0)
                return 0;
            
            int candidate = a[0];  // 用于记录出现次数大于数组长度一半的值
            int nTimes = 1;  // 次数
            for (int i = 1; i < a.length; i++)
            {
                if (nTimes == 0)
                {
                    candidate = a[i];
                    nTimes = 1;
                }
                else
                {
                    if (candidate == a[i])
                        nTimes++;
                    else
                        nTimes--;
                }
            }
            
            if(!checkMoreThanHalfNum(a, candidate))
                return 0;
            return candidate;
        }
        private static boolean checkMoreThanHalfNum(int[] array, int result) {
            int times = 0;
            for(int i=0; i<array.length; i++) {
                if(array[i] == result) {
                    times ++;
                }
            }
            
            if(times * 2 <= array.length)
                return false;
            return true;
        }
    }
  • 相关阅读:
    jmeter 工具学习 未完待续
    测试学习
    JavaScript
    新概念第1册
    day08
    LeetCode OJ:Invert Binary Tree(反转二叉树)
    LeetCode OJ:Lowest Common Ancestor of a Binary Search Tree(最浅的公共祖先)
    LeetCode OJ:Maximum Depth of Binary Tree(二叉树最大深度)
    LeetCode OJ:Path Sum(路径之和)
    LeetCode OJ:Symmetric Tree(对称的树)
  • 原文地址:https://www.cnblogs.com/zywu/p/5782013.html
Copyright © 2011-2022 走看看