剑指offer-数组中出现次数超过一半的数字

 考完试,做完课设后继续来做题。

题目:数组中出现次数超过一半的数字

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

 

思路分析:剑指offer 上的题感觉都不难,我其实很想做那种能思考良久,最终想到答案,答案又是很巧妙的那种题。而这样的题无非是对语言特性或是一点点数据结构的考察,对这个题而言有多种方法。

 

方法一:利用数组结合题目要求进行分析,实际上这个题就是给你一个数组,看是否存在这样一个数,它的个数大于数组中所有元素数的一半,有的话就输出这个数,没有的话就输出0。如果存在这个数,那么它出现的次数比其他所有数字出现的次数和还要多。由于数组本身是无序的,先对数组进行遍历,在遍历数组时保存两个值:一是数组中一个数字,一是次数。遍历下一个数字时,若它与之前保存的数字相同,则次数加1,否则次数减1;若次数为0,则保存下一个数字,并将次数置为1。遍历结束后,所保存的数字即为所求。然后再判断它是否符合条件即可。由于只进行了数组的遍历,所以时间复杂度就是O(n)

代码如下:

 1 public class Solution {
 2     public int MoreThanHalfNum_Solution(int [] array) {
 3         if(array.length==0)return 0;
 4         int count=1,num=array[0];
 5         for(int i=1;i<array.length;i++){
 6             if(array[i]==num)count++;
 7             else count--;
 8             if(count==0){
 9                 num=array[i]; 
10                 count=1;
11             }          
12         }
13         count=0;
14         for(int i=0;i<array.length;i++){
15             if(array[i]==num)count++;
16         }
17         if(count*2>array.length){
18             return num;
19         }
20         else return 0;
21     }
22 } 

方法二:由于数组本身是无序的,那我当然也可以通过排序来得到我想要的结果,java自带的sort方法即可对数组进行排序,其使用的是快排的思想,所以时间复杂度为O(nlogn)

如果存在这样一个数,那么,在我排序后,在数组的中间位置必定有它,那么我便已经知道了这个数,只需再求其出现的次数进行验证即可

代码如下:

 1 import java.util.Arrays;
 2  
 3 public class Solution {
 4     public int MoreThanHalfNum_Solution(int [] array) {
 5         Arrays.sort(array);
 6         int count=0;
 7          
 8         for(int i=0;i<array.length;i++){
 9             if(array[i]==array[array.length/2]){
10                 count++;
11             }
12         }
13         if(count>array.length/2){
14             return array[array.length/2];
15         }else{
16             return 0;
17         }
18          
19     }
20 }

方法三:使用hashmap

hashmap方法简单明了,直接把每个数和它对应的次数存下来,然后对整个hashmap进行遍历,找出次数超过数组的长度一半的那个键

 1 public class Solution {
 2     public int MoreThanHalfNum_Solution(int [] array) {
 3         HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
 4          
 5         for(int i=0;i<array.length;i++){
 6              
 7             if(!map.containsKey(array[i])){
 8                map.put(array[i],1);
 9             }else{
10                 int count = map.get(array[i]);
11                 map.put(array[i],++count);
12             }
13         }
14         Iterator iter = map.entrySet().iterator();
15         while(iter.hasNext()){
16             Map.Entry entry = (Map.Entry)iter.next();
17             Integer key =(Integer)entry.getKey();
18             Integer val = (Integer)entry.getValue();
19             if(val>array.length/2){
20                 return key;
21             }
22         }
23         return 0;
24 }

感觉这种方法考察的主要是对hashmap的遍历

简要回顾一下hashmap的遍历方法:

法1:利用foreach 取出map.entrySet()并获取key和value

1  Map<String, String> map = new HashMap<String, String>();
2  for (Entry<String, String> entry : map.entrySet()) {
3      entry.getKey();
4      entry.getValue();
5  }

法2:调用map.entrySet()的集合迭代器,通过hasNext()方法判断是否有元素可迭代

1 Map<String, String> map = new HashMap<String, String>();
2 Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
3  while (iterator.hasNext()) {
4      Map.Entry<String, String> entry = iterator.next();
5      entry.getKey();
6      entry.getValue();
7  }

法3:通过HashMap中的keySet()方法获取key集合,通过循环获取value

1 Map<String, String> map = new HashMap<String, String>();
2 for (String key : map.keySet()) {
3     map.get(key);
4 }

法4:通过临时变量保存map.entrySet(),遍历输出

1 Map<String, String> map = new HashMap<String, String>();
2 Set<Entry<String, String>> entrySet = map.entrySet();
3 for (Entry<String, String> entry : entrySet) {
4     entry.getKey();
5     entry.getValue();
6 }

参考:hashmap的遍历方法总结

posted @ 2018-07-10 16:55  pathjh  阅读(177)  评论(0编辑  收藏  举报