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

    题目描述

    数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
     
    三种解法:
     
    1. 用map将number和出现次数存起来。
    时间复杂度O(n), 空间复杂度O(n)
    import java.util.HashMap;
    
    public class Solution {
        public int MoreThanHalfNum_Solution(int [] array) {
            HashMap<Integer, Integer> map = new HashMap<>();
            if (array.length == 1) return array[0];
            for (int i = 0; i < array.length; i++) {
                if (map.containsKey(array[i])) {
                    int count = map.get(array[i]);
                    if (count >= array.length / 2)
                        return array[i];
                    map.put(array[i], count + 1);
                }
                else {
                    map.put(array[i], 1);
                }
            }
            return 0;
        }
    }
    2. 出现超过一半的数字一定是中位数,但中位数不一定是超过一半的数字(可能不存在这样的数字),先利用position算法得到中位数,再验证是否为出现超过一半的数字。
    时间复杂度O(n),空间复杂度O(1)
    public class Solution {
        public int MoreThanHalfNum_Solution(int [] array) {
            if (array.length == 0) return 0;
            if (array.length == 1) return array[0];
            int left = 0;
            int right = array.length - 1;
            
            while (left < right) {
                int index = position(array, left, right);
                if (index == array.length / 2) {
                    if (checkMoreThanHalf(array, array[index]))
                        return array[index];
                    else 
                        return 0;
                }
                    
                else if (index < array.length / 2)
                    left = index + 1;
                else 
                    right = index - 1;
            }
            
            return 0;
        }
        
        private int position(int[] array, int start, int end) {
            int index = start + (int)Math.random() * (end - start);
            swap(array, index, end);
            
            int small = start - 1;
            for (int i = start; i < end; i++) {
                if (array[i] <= array[end] && ++small != i) {
                    swap(array, small, i);
                } 
            }
            
            swap(array, ++small, end);
            return small;
        }
        
        private void swap(int[] array, int a, int b) {
            int temp = array[a];
            array[a] = array[b];
            array[b] = temp;
        } 
        
      //验证数组是否合理
    private boolean checkMoreThanHalf (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; else return true; } }
     
    3. 出现超过一半的数字出现的次数一定比其他数字出现的次数之和要大,因此设置两个变量,一个是数组中的数字,另一个是出现次数。遍历数组,当出现相同的数字是,出现次数加1,否则减1,当次数变为0时,记录新的数字。最后一个次数>=1的数字可能为所求的数字。但也需要验证数组是否合理。
    时间复杂度O(n),空间复杂度O(1)
    public class Solution {
        public int MoreThanHalfNum_Solution(int [] array) {
            int len = array.length;
            if (len == 0) return 0;
            if (len == 1) return array[0];
            
            int result = array[0];
            int times = 1;
            
            for (int i = 1; i < len; i++) {
                if (times == 0) {
                    result = array[i];
                    times = 1;
                }
                else if (array[i] == result) {
                    times++;
                }
                else {
                    times--;
                }
            }
            
            if (times >= 1 && checkMoreThanHalf(array, result)) 
                return result;
            else 
                return 0;
        }
        
        
        private boolean checkMoreThanHalf (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;
            else 
                return true;
        }
    }
     
  • 相关阅读:
    想要快速上手 Spring Boot?看这些教程就足够了!| 码云周刊第 81 期
    Eclipse Java注释模板设置详解以及版权声明
    java跨域解决
    微信公众号创建
    Java与JS生成二维码与条形码
    Java基础break、continue语句的用法
    分布式文件系统介绍
    Hadoop的RPC机制及简单实现
    RPC简介与hdfs读过程与写过程简介
    JVM的Client模式与Server模式
  • 原文地址:https://www.cnblogs.com/weiququ/p/12387259.html
Copyright © 2011-2022 走看看