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;
        }
    }
     
  • 相关阅读:
    Python实现日志分析并转成excel
    dockerfile案例 springboot项目部署
    1、springboot启动加载不到src/main/resources下的配置文件application.yml
    [Dockerfile构建镜像]
    dockerfile案例 centos
    dockerfile语法
    dockerfile 笔记202110622
    docker 数据卷 挂载共享
    docker 国内镜像加速aliyun
    微信公众号 几种移动端UI框架介绍
  • 原文地址:https://www.cnblogs.com/weiququ/p/12387259.html
Copyright © 2011-2022 走看看