`

一道阿里电话面试中的算法题

阅读更多

 

电话面试算法题一道:找出数组中重复次数最多的元素并打印

 

问题不难,看你能给出更优的方案

 

 

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import commons.algorithm.sort.QuickSort;

/**
 * 找出数组中重复次数最多的元素并打印
 *
 */
public class Problem_3 {
	
	//先快速排序后循环查找    O( n*log2(n) + n )
	public static void find1(int[] arr){
		
		QuickSort.sort(arr);
		
		
		int max = arr[0];
		int pre=1;
		int now=1;
		
		for(int i=0;i<(arr.length-1);i++){
			
			if(arr[i]==arr[i+1])
				now++;
			else {
				if(now>=pre){
					pre=now;
					now=1;
					max=arr[i];
				}	
			}
		}
		
		
		
	}
	
	//嵌套循环查找   O(n*n)
	public static void find2(int[] arr){
		

		int pre=0;
		int max=arr[0];
		
		for(int i=0;i<arr.length;i++){
			int now=0;
			for(int j=0;j<arr.length;j++){
				
				if(arr[i]==arr[j]) {
					now++;	
				}				
			}
			
			if(now>=pre){			
				max=arr[i];
				pre=now;			
			}
			
					
		}
		
	
		
	}
	
	//通过 Hash 方式
	public static void find3(int[] arr){
		HashMap<Integer,Integer> hm=new HashMap<Integer, Integer>();
		for(int i=0;i<arr.length;i++){
			if(hm.containsKey(arr[i])) {
				int count=hm.get(arr[i]);
				hm.put(arr[i], ++count);
			 
			}else{
				hm.put(arr[i],1);
			}
		}
		
		Iterator<Entry<Integer, Integer>> it=hm.entrySet().iterator();
		int pre=0;
		int max=arr[0];
		while(it.hasNext()) {
			Entry<Integer, Integer> en=it.next();
			int key=en.getKey();
			int val=en.getValue();
			if(val>pre){	
				pre=val;
				max=key;
			}
			
		}
		
	
		
	}
	public static  void main(String args[]){

		//数据量800 重复元素多,查找时候分别是:  46  3680  195
		int arr2[]={0,1,2,        .....       
				,0,1,2,3,6,7,8,9};
		
		//数据量800 重复元素少,查找时间分别是     82  3727  360
		int arr[]={0,0,0,11,12,13,14,5,6    ......     
		                ,51,52,53,,728,29,730,731,3,794,95,796,797,798,799};
		

		
		long start,end;
			
		start=System.currentTimeMillis();
		for(int i=0;i<1000;i++) find1(arr);
		end=System.currentTimeMillis();
		System.out.println(end-start);
		
		start=System.currentTimeMillis();
		for(int i=0;i<1000;i++) find2(arr);
		end=System.currentTimeMillis();
		System.out.println(end-start);
		
		
		start=System.currentTimeMillis();
		for(int i=0;i<1000;i++) find3(arr);
		end=System.currentTimeMillis();
		System.out.println(end-start);
		
	}
}
 
分享到:
评论
70 楼 yiyidog125 2010-10-20  
O(n)是最优解 不可能O(lgn) 你至少要遍历数组一遍才知道哪个值出现得最多...
69 楼 sdh5724 2010-10-20  
我也不会解啊, 这么有才的题目。
如果是有限内存, 海量数据的话, 谁能给一个接近O(N)的算法呢。
68 楼 fengjia10 2010-10-20  
<div class="quote_title">lewisw 写道</div>
<div class="quote_div">
<div class="quote_title">leves 写道</div>
<div class="quote_div">
<p> </p>
<pre name="code" class="java">public static void find3(int[] arr){
HashMap&lt;Integer,Integer&gt; hm=new HashMap&lt;Integer, Integer&gt;();
for(int i=0;i&lt;arr.length;i++){
if(hm.containsKey(arr[i])) {
int count=hm.get(arr[i]);
hm.put(arr[i], ++count);

}else{
hm.put(arr[i],1);
}
}

Iterator&lt;Entry&lt;Integer, Integer&gt;&gt; it=hm.entrySet().iterator();
int pre=0;
int max=arr[0];
while(it.hasNext()) {
Entry&lt;Integer, Integer&gt; en=it.next();
int key=en.getKey();
int val=en.getValue();
if(val&gt;pre){
pre=val;
max=key;
}

}

//System.out.println(max);

}</pre>
<p> </p>
<p>用Hash的方式写的,为什么测试的时候速度上反而是最慢的</p>
</div>
<p> </p>
<p>这个map创建的时候一定要考虑他的两个构造参数(int initialCapacity, float loadFactor),非常重要, 尤其数据量大的时候, 不然老是在哪里构造新的大的数组然后拷贝,越大越慢, 最后慢死你。</p>
<p>HashMap的内部使用数组+链表保存数据, 默认的initialCapacity=16, loadFactor = 0.75, 具体的自己参考文档。</p>
<p> </p>
<p>你可以这样<span>HashMap&lt;Integer,Integer&gt; hm=<span class="keyword" style="color: #7f0055; font-weight: bold;">new</span><span style="color: black;"> HashMap&lt;Integer, Integer&gt;(arr.length);</span></span></p>
<p>当然一定要确认这个arr.length是不是太大了,内存溢出,数组的length在java里是int的,就是说最大值是4g, 你的内存大大,虚拟机能分配那么多也行,呵呵</p>
</div>
<p>补充一点,初始容量和装载因子是影响hash函数性能的重要因子,也就是影响你地址是否冲突的重要因素,当地址冲突时,选择合适的再散列函数,对相应元素进行地址分配,以便无冲突装载该元素,这个也是很重要的,</p>
67 楼 chen592969029 2010-10-13  
<p>看了楼主的代码,想自己试试,结果发现你那第一种方法很明显是有错误的,更正后的代码如下:</p>
<p> </p>
<p>
</p>
<pre name="code" class="java"> ArrayUtil.quickSort(arr, 0, arr.length - 1);

int now = 1;
int pre = 1;
for(int i = 0; i &lt; arr.length - 1; i ++) {
if(arr[i] == arr[i + 1]) {
now ++;
} else {
if(now &gt;= pre) {
pre = now;
}
//now = 1;应该放在if语句的外面
now = 1;
}
}
//缺少这一句
if(now &gt;= pre) {
pre = now;
}</pre>
 
66 楼 hoorace 2010-10-10  
《编程珠玑》第二章有讲到相关内容
在线性时间排序算法(Linear-Time Sorting)中到计数排序(Counting Sorting)或许是解决这个问题的。具体java实现:

public class CountingSort {
	private static final int N= 10000;
	private static final int K= 1000;
	/**
	 * 得到计数数组
	 * @param num
	 * @return
	 */
	public static int[] computeCountingNum(int[] num){
		int maxAppearNum = 0;
		int count = 0;
		int[] countingNum = new int[K];
		int value,countTmpValue;
		for(int i=0;i<N;i++){
			value = num[i];
			countTmpValue = countingNum[value];
			//查找出现次数最多的数字
			if(countTmpValue > count){
				count = countTmpValue;
				maxAppearNum = value;
			}                 
			countingNum[value] = countingNum[value] + 1; 
		}
		//打印出满足阿里面试要求到数据
		System.out.println("\n"+maxAppearNum);
		System.out.println(count);
		return countingNum;
	}
	/**
	 * 遍历计数数组,得到排序结果
	 * @param num
	 * @return
	 */
	public static int[] sortedNum(int[] num){
		int[] countingNum = computeCountingNum(num);
		int[] sortedNum = new int[N];
		int value;
		int j = 0;
		for(int i=0;i<K;i++){
			value = countingNum[i];
			if(value > 0){
				while(value > 0){
					sortedNum[j] = i;
					--value;
					++j;
				}
			}
		}
		return sortedNum;
	}
	/**
	 * 产生随机数
	 * @return
	 */
	public static int[] randomNumber(){
		int[] num = new int[N];
		Random random = new Random();
		for(int i=0;i<N;i++){
			int m = random.nextInt(K);
			num[i] = m;
		}
		return num;
	}
	
	public static void main(String[] args) {
		int[] num = CountingSort.randomNumber();
		//计数排序耗时
		long t1 = System.currentTimeMillis();
		CountingSort.sortedNum(num);
		long t2 = System.currentTimeMillis();
		System.out.print(t2-t1);
		System.out.println();
		//快速排序耗时
		long t3 = System.currentTimeMillis();
		Arrays.sort(num);
		long t4 = System.currentTimeMillis();
		System.out.print(t4-t3);
	}
}

具体讨论的博文:http://www.longtask.com/blog/?p=616
65 楼 sunhj000java 2010-10-09  
Crusader 写道
hikaru1012 写道
sunhj000java 写道
我认为这道题的关键是如何遍历这个数据集合,如果能不用遍历集合而找出出现最多的次数的数字是这道题的关键。
我们可以用hashmap保存数据出现的个数,并且用两个变量保存出现最多的次数(max1)和次多的次数(max2),当剩下的数据个数小于max1-max2,那么我们就找出了这个数字了。
最优为n/2  最差为n


如何维护记录出现次数最多和次多的变量要比实现问题本身困难得多吧?


+1
无论在时间和空间上都会耗费很多额外的消耗来维护“最多”与“次多”,我认为大多数情况可能都会得不偿失。。

这个应该不会消耗太多资源吧,在开始比较的时候就确定最多和次多两个变量,在每次改动对应数字的次数时和次多比较一下就可以了,如果大于次多就替换次多并和最多比较,如果也大于最多也替换,否则不做任何操作。这个动作并不消耗太多资源吧
64 楼 zhzhwe 2010-10-09  
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">    </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">public</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">static</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">void</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> findRepeatMaxValue(</span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">int</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">[] arr) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">long</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> time1 = System.<em>nanoTime</em>();</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">int</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> max = 0;</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #3f7f5f; font-family: "Courier New";' lang="EN-US">// </span><span style="">定义</span><span style='font-size: 10pt; color: #3f7f5f; font-family: "Courier New";' lang="EN-US">MAP KEY</span><span style="">表示存放的数字,</span><span style='font-size: 10pt; color: #3f7f5f; font-family: "Courier New";' lang="EN-US">VALUES</span><span style="">表示出现的次数</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>Map&lt;Integer, Integer&gt; map = </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">new</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> HashMap&lt;Integer, Integer&gt;();</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">for</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> (</span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">int</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> n : arr) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> (map.containsKey(n)) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span>map.put(n, map.get(n) + 1);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span>} </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">else</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span>map.put(n, 1);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><span style='font-size: 10pt; color: #3f7f5f; font-family: "Courier New";' lang="EN-US">// </span><span style="">比较是此数是否为最大次数</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> (map.get(n) &gt; max)</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span>max = map.get(n);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"> </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">for</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> (Map.Entry&lt;Integer, Integer&gt; m : map.entrySet()) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> (m.getValue() == max) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span>System.</span><em><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">out</span></em><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.println(m.getKey() + </span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">" </span><span style="">出现了</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US"> "</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> + m.getValue() + </span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">" </span><span style="">次</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">."</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"> </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"> </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">long</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> time2 = System.<em>nanoTime</em>();</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>System.</span><em><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">out</span></em><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.println(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"findRepeatMaxValue time is "</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span>+ ((time2 - time1) / 1000000.0) + </span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"ms"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"> </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">    </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"> </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">    </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">public</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">static</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">void</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> main(String[] args) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>Random rand = </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">new</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> Random();</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">int</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> arr[] = </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">new</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">int</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">[1000000];</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">for</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> (</span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">int</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> i = 0; i &lt; arr.</span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">length</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">; i++) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span>arr[i] = rand.nextInt(100);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span><em>findRepeatMaxValue</em>(arr);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
63 楼 zhzhwe 2010-10-09  
clufeng 写道
 public static void findRepeatMaxValue(int[] arr) {
		long time1 = System.nanoTime();
		HashMap<Integer, Integer> box = new HashMap<Integer, Integer>();
		int maxValue = 0;
		int maxCount = 0;
		for (int i = 0; i < arr.length; i++) {
			Integer count = box.get(arr[i]);
			box.put(arr[i], count == null ? 1 : ++count);
			int newCount = box.get(arr[i]);
			if(newCount > maxCount) {
				maxCount = newCount;
				maxValue = arr[i];
			}
		}
		long time2 = System.nanoTime();
		System.out.println("findRepeatMaxValue time is "
				+ ((time2 - time1) / 1000000.0) + "ms");
		System.out.println("maxValue : " + maxValue +"  maxCount : " + maxCount);
	}

 public static void main(String[] args) {
		Random rand = new Random();	
		int arr[] = new int[1000000];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = rand.nextInt(100);
		}
		findRepeatMaxValue(arr);
	}


测试结果:
测试数量:1000000
findRepeatMaxValue time is 146.057722ms
maxValue : 50  maxCount : 10261





楼主说是数组中重复次数最多的元素,而且我认为出现最多次数也有可能不同元素出现相同次数且是最多的,而上面的只显示最大了。
62 楼 hibernater 2010-10-09  
lewisw 写道
qvjing520 写道
我测了一下感觉效率换可以,希望大家指教
public class Num2 {
//找出一个数组中重复元素最多的元素并打印出来
    private static int[] num1 = {1, 2, 2 ,3,4,4,4,5,6,6,6,6,7,10,11,11,11,11,11,11,15};
    private static Object[] num =null;
    Map<Integer,Integer> map = new HashMap<Integer,Integer>();
   
    static
    {
    List lst = new ArrayList();
    for(int i=0;i<10000;i++)
    {
    for(Integer temp:num1)
    {
    lst.add(temp);
    }
    }
    num = lst.toArray();
    }
   
    public static void main(String[] args) {
//System.out.println("second");
    new Num2().find(num);
}
   
  
   
    private void find(Object[] data)
    {
    long time = System.currentTimeMillis()/1000;
    for(int i=0;i<data.length;i++)
    {
    if(map.containsKey(data[i]))
    {
    int t=map.get(data[i]);
    map.put((Integer)data[i], ++t);
    }
    else
    {
    map.put((Integer)data[i], 1);
    }
   
    }
        int max = java.util.Collections.max(map.values());
       
    for(Integer key:map.keySet())
    {
    if(map.get(key)==max)
    {
    System.out.println("number:"+key+" value:"+max);
    }
    }
    System.out.println(time-(System.currentTimeMillis()/1000));
   
    }
   
}


这么点数据能说明什么问题啊,起码几十万个数才行啊


测试了一下,900000*21=18900000的数据(约一千九百万),再多就报错了,应该是内存的问题,这个不关心了。

MAX_number:11     MAX_value:5400000

cost:1062ms

qvjing520 的速度比楼上稍好
61 楼 clufeng 2010-10-09  
 public static void findRepeatMaxValue(int[] arr) {
		long time1 = System.nanoTime();
		HashMap<Integer, Integer> box = new HashMap<Integer, Integer>();
		int maxValue = 0;
		int maxCount = 0;
		for (int i = 0; i < arr.length; i++) {
			Integer count = box.get(arr[i]);
			box.put(arr[i], count == null ? 1 : ++count);
			int newCount = box.get(arr[i]);
			if(newCount > maxCount) {
				maxCount = newCount;
				maxValue = arr[i];
			}
		}
		long time2 = System.nanoTime();
		System.out.println("findRepeatMaxValue time is "
				+ ((time2 - time1) / 1000000.0) + "ms");
		System.out.println("maxValue : " + maxValue +"  maxCount : " + maxCount);
	}

 public static void main(String[] args) {
		Random rand = new Random();	
		int arr[] = new int[1000000];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = rand.nextInt(100);
		}
		findRepeatMaxValue(arr);
	}


测试结果:
测试数量:1000000
findRepeatMaxValue time is 146.057722ms
maxValue : 50  maxCount : 10261


60 楼 lewisw 2010-10-09  
qvjing520 写道
我测了一下感觉效率换可以,希望大家指教
public class Num2 {
//找出一个数组中重复元素最多的元素并打印出来
    private static int[] num1 = {1, 2, 2 ,3,4,4,4,5,6,6,6,6,7,10,11,11,11,11,11,11,15};
    private static Object[] num =null;
    Map<Integer,Integer> map = new HashMap<Integer,Integer>();
   
    static
    {
    List lst = new ArrayList();
    for(int i=0;i<10000;i++)
    {
    for(Integer temp:num1)
    {
    lst.add(temp);
    }
    }
    num = lst.toArray();
    }
   
    public static void main(String[] args) {
//System.out.println("second");
    new Num2().find(num);
}
   
  
   
    private void find(Object[] data)
    {
    long time = System.currentTimeMillis()/1000;
    for(int i=0;i<data.length;i++)
    {
    if(map.containsKey(data[i]))
    {
    int t=map.get(data[i]);
    map.put((Integer)data[i], ++t);
    }
    else
    {
    map.put((Integer)data[i], 1);
    }
   
    }
        int max = java.util.Collections.max(map.values());
       
    for(Integer key:map.keySet())
    {
    if(map.get(key)==max)
    {
    System.out.println("number:"+key+" value:"+max);
    }
    }
    System.out.println(time-(System.currentTimeMillis()/1000));
   
    }
   
}


这么点数据能说明什么问题啊,起码几十万个数才行啊
59 楼 lewisw 2010-10-09  
evanz 写道
单编程角度,还是TreeMap吧,自己实现一个Comparator,一个for循环搞定



可能是个最好的解决方法
58 楼 qvjing520 2010-10-09  
我测了一下感觉效率换可以,希望大家指教
public class Num2 {
//找出一个数组中重复元素最多的元素并打印出来
    private static int[] num1 = {1, 2, 2 ,3,4,4,4,5,6,6,6,6,7,10,11,11,11,11,11,11,15};
    private static Object[] num =null;
    Map<Integer,Integer> map = new HashMap<Integer,Integer>();
   
    static
    {
    List lst = new ArrayList();
    for(int i=0;i<10000;i++)
    {
    for(Integer temp:num1)
    {
    lst.add(temp);
    }
    }
    num = lst.toArray();
    }
   
    public static void main(String[] args) {
//System.out.println("second");
    new Num2().find(num);
}
   
  
   
    private void find(Object[] data)
    {
    long time = System.currentTimeMillis()/1000;
    for(int i=0;i<data.length;i++)
    {
    if(map.containsKey(data[i]))
    {
    int t=map.get(data[i]);
    map.put((Integer)data[i], ++t);
    }
    else
    {
    map.put((Integer)data[i], 1);
    }
   
    }
        int max = java.util.Collections.max(map.values());
       
    for(Integer key:map.keySet())
    {
    if(map.get(key)==max)
    {
    System.out.println("number:"+key+" value:"+max);
    }
    }
    System.out.println(time-(System.currentTimeMillis()/1000));
   
    }
   
}
57 楼 lewisw 2010-10-09  
<div class="quote_title">leves 写道</div>
<div class="quote_div">
<p> </p>
<pre name="code" class="java">public static void find3(int[] arr){
HashMap&lt;Integer,Integer&gt; hm=new HashMap&lt;Integer, Integer&gt;();
for(int i=0;i&lt;arr.length;i++){
if(hm.containsKey(arr[i])) {
int count=hm.get(arr[i]);
hm.put(arr[i], ++count);

}else{
hm.put(arr[i],1);
}
}

Iterator&lt;Entry&lt;Integer, Integer&gt;&gt; it=hm.entrySet().iterator();
int pre=0;
int max=arr[0];
while(it.hasNext()) {
Entry&lt;Integer, Integer&gt; en=it.next();
int key=en.getKey();
int val=en.getValue();
if(val&gt;pre){
pre=val;
max=key;
}

}

//System.out.println(max);

}</pre>
<p> </p>
<p>用Hash的方式写的,为什么测试的时候速度上反而是最慢的</p>
</div>
<p> </p>
<p>这个map创建的时候一定要考虑他的两个构造参数(int initialCapacity, float loadFactor),非常重要, 尤其数据量大的时候, 不然老是在哪里构造新的大的数组然后拷贝,越大越慢, 最后慢死你。</p>
<p>HashMap的内部使用数组+链表保存数据, 默认的initialCapacity=16, loadFactor = 0.75, 具体的自己参考文档。</p>
<p> </p>
<p>你可以这样<span style="">HashMap&lt;Integer,Integer&gt; hm=<span class="keyword" style="color: #7f0055; font-weight: bold;">new</span><span style="color: black;"> HashMap&lt;Integer, Integer&gt;(arr.length);</span></span></p>
<p>当然一定要确认这个arr.length是不是太大了,内存溢出,数组的length在java里是int的,就是说最大值是4g, 你的内存大大,虚拟机能分配那么多也行,呵呵</p>
56 楼 Crusader 2010-10-09  
hikaru1012 写道
sunhj000java 写道
我认为这道题的关键是如何遍历这个数据集合,如果能不用遍历集合而找出出现最多的次数的数字是这道题的关键。
我们可以用hashmap保存数据出现的个数,并且用两个变量保存出现最多的次数(max1)和次多的次数(max2),当剩下的数据个数小于max1-max2,那么我们就找出了这个数字了。
最优为n/2  最差为n


如何维护记录出现次数最多和次多的变量要比实现问题本身困难得多吧?


+1
无论在时间和空间上都会耗费很多额外的消耗来维护“最多”与“次多”,我认为大多数情况可能都会得不偿失。。
55 楼 CrystalBear 2010-10-09  
hash就可以了,用考虑这么复杂么
54 楼 chenlixun 2010-10-09  
zhzhwe 写道
public static void main(String[] args) {
int arr[] = { 1, 2, 5, 5, 6, 6, 9, 5, 3, 3, 4, 4, 4, 4, 5, 2, 2, 2, 2,
2, 7, 7, 7, 7, 7, 7 };
//定义MAP KEY表示存放的数字,VALUES表示出现的次数
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int n : arr) {
if (map.containsKey(n)) {
map.put(n, map.get(n) + 1);
} else {
map.put(n, 1);
}
}
//定义最大次数变量
int max = 1;

//遍厉MAP查出最大次数
for (Map.Entry<Integer, Integer> m : map.entrySet()) { 
if(m.getValue() > max)
max = m.getValue();


for (Map.Entry<Integer, Integer> m : map.entrySet()) {
if(m.getValue() == max)
{
System.out.println(m.getKey() + " 出现了 " + m.getValue() + " 次.");
}

}


根据楼上的做了修改如下, 请大家批批.

public static void main(String[] args) {
long startTime = 0;
long endTime = 0;

startTime = System.currentTimeMillis();
int arr[] = { 1, 2, 2, 5, 7, 5, 6, 6, 9, 5, 3, 3, 4, 7, 4, 4, 4, 5, 2,
2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7 };

for(int i = 0; i < 1; i++)
Example.findMaxTime(arr);

endTime = System.currentTimeMillis();
System.out.println("总花费时间:" + (endTime - startTime) + " ms.");
}

private static void findMaxTime(int arr[]) {
// 定义MAP KEY表示存放的数字,VALUES表示出现的次数
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
// 定义最大次数变量
int max = 0;
// 定义出现最多次数的数字
int maxValue = 0;

// 定义临时交换变量
int temp = 0;
for (int n : arr) {
if (map.containsKey(n)) {
map.put(n, map.get(n) + 1);
} else {
map.put(n, 1);
}

temp = map.get(n);
if (temp > max) {
max = temp;
maxValue = n;
}
}

System.out.println("出现最多的数字:" + maxValue + ";出现次数: " + max + " 次。");
}
53 楼 zhzhwe 2010-10-09  
public static void main(String[] args) {
int arr[] = { 1, 2, 5, 5, 6, 6, 9, 5, 3, 3, 4, 4, 4, 4, 5, 2, 2, 2, 2,
2, 7, 7, 7, 7, 7, 7 };
//定义MAP KEY表示存放的数字,VALUES表示出现的次数
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int n : arr) {
if (map.containsKey(n)) {
map.put(n, map.get(n) + 1);
} else {
map.put(n, 1);
}
}
//定义最大次数变量
int max = 1;

//遍厉MAP查出最大次数
for (Map.Entry<Integer, Integer> m : map.entrySet()) { 
if(m.getValue() > max)
max = m.getValue();


for (Map.Entry<Integer, Integer> m : map.entrySet()) {
if(m.getValue() == max)
{
System.out.println(m.getKey() + " 出现了 " + m.getValue() + " 次.");
}

}
52 楼 ihc 2010-10-08  
使用linkedList 也行吧,将数组元素和出现次数封装成一个内部类,把次数最多的放在linkedList的第一个位置, 每次拿循环到的元素的map值跟linkedlist中的第一个元素比较,比它大的话插到第一个位置,最后取出第一个元素就行了吧,因为linkedlist的增删操作比较快捷 应该效率点。
51 楼 xcv4javaeye 2010-10-08  
<div class="quote_title">xcv4javaeye 写道</div>
<div class="quote_div">
<div class="quote_title">iamlotus 写道</div>
<div class="quote_div">用Hash的各位算过Hash的开销没有?不能光考虑时间复杂度,还要考虑空间复杂度。如果没有更多附加空间怎么办?<br>既然是电面,首先问明白限制条件,数据量是多大,K/M/G/T?重复数据占比?有没有附加空间/时间要求?<br>数据量K,随便怎么搞。<br>数据量M,QuickSort<br>数据量G,MergeSort了,因为内存不够要用IO<br>数据量T,MapReduce,否则单机处理不过来<br><br>重复数据非常多,考虑用Hash {data-&gt;repeatCount},以空间换时间<br>重复数据少,还是老老实实排序吧,Hash的空间开销蛮大的,而且resize相当慢。<br><br>复杂度分析来说,每个数据至少访问一遍,不可能有比O(n)更好的,这就是个考实现的题。既然是实现,当然要搞清楚环境,哪有闷着头写程序的道理。</div>
<p><br><br><br>        同意,你考虑了很多实现中的问题。但是还是没有回答为什么lz的代码,hash比qsort慢了一个数量级?理论上hash平均复杂度是O(n),qsort是O(nlogn)<br>        我开始认为是Sun的jdk的hash实现比较复杂,导致线性复杂度的常系数比较大,使得在小数据量的时候O(n)的时间大于O(nlogn),但我跑了一下,没用楼主的qsort,而用的是JDK1.6的Arrays.sort,得出数据如下,可以观察,qsort根本就是线性的....这到底是为什么啊为什么...<br>      我又单独跑了一下Arrays.sort,发现还是线性的...<br><br>代码如下:</p>
<pre name="code" class="java">import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

/**
* 找出数组中重复次数最多的元素并打印
*
*/
public class Problem_3 {

    // 先快速排序后循环查找 O( n*log2(n) + n )
    public static void find1(int[] arr) {

        Arrays.sort(arr);

        int max = arr[0];
        int pre = 1;
        int now = 1;

        for (int i = 0; i &lt; (arr.length - 1); i++) {

            if (arr[i] == arr[i + 1])
                now++;
            else {
                if (now &gt;= pre) {
                    pre = now;
                    now = 1;
                    max = arr[i];
                }
            }
        }

    }

    // 嵌套循环查找 O(n*n)
    public static void find2(int[] arr) {

        int pre = 0;
        int max = arr[0];

        for (int i = 0; i &lt; arr.length; i++) {
            int now = 0;
            for (int j = 0; j &lt; arr.length; j++) {

                if (arr[i] == arr[j]) {
                    now++;
                }
            }

            if (now &gt;= pre) {
                max = arr[i];
                pre = now;
            }

        }

    }

    // 通过 Hash 方式
    public static void find3(int[] arr) {
        HashMap&lt;Integer, Integer&gt; hm = new HashMap&lt;Integer, Integer&gt;(10000);
        for (int i = 0; i &lt; arr.length; i++) {
            if (hm.containsKey(arr[i])) {
                int count = hm.get(arr[i]);
                hm.put(arr[i], ++count);

            } else {
                hm.put(arr[i], 1);
            }
        }

        Iterator&lt;Entry&lt;Integer, Integer&gt;&gt; it = hm.entrySet().iterator();
        int pre = 0;
        int max = arr[0];
        while (it.hasNext()) {
            Entry&lt;Integer, Integer&gt; en = it.next();
            int key = en.getKey();
            int val = en.getValue();
            if (val &gt; pre) {
                pre = val;
                max = key;
            }

        }

    }

    public static void main(String args[]) {
        for (int n = 100000; n &lt; 100000000; n += 100000) {
            invoke(n);
        }

    }

    private static void invoke(int n) {
        // // 数据量800 重复元素多,查找时候分别是: 46 3680 195
        // int arr2[] = new int[800];
        // for (int i = 0; i &lt; 800; i++) {
        // arr2[i] = (int) (Math.random() * 800);
        // }
        // 数据量800 重复元素少,查找时间分别是 82 3727 360
        System.out.print("n=" + n+"\t\t");
        int arr[][] = new int[100][n];
        for (int j = 0; j &lt; arr.length; j++) {
            for (int i = 0; i &lt; n; i++) {
                arr[j][i] = (int) (Math.random() * n);
            }
        }

        long start, end;

        // start = System.currentTimeMillis();
        // for (int i = 0; i &lt; 1000; i++)
        // find2(arr);
        // end = System.currentTimeMillis();
        // System.out.println(end - start);

        start = System.currentTimeMillis();
        for (int i = 0; i &lt; 100; i++)
            find3(arr[i]);
        end = System.currentTimeMillis();
        System.out.print("hash:" + (end - start)+ "\t\t");

        start = System.currentTimeMillis();
        for (int i = 0; i &lt; 100; i++)
            find1(arr[i]);
        end = System.currentTimeMillis();
        System.out.println("sort:" + (end - start));
    }
}</pre>
<p> </p>
<p> </p>
</div>
<p>有人研究了这个问题吗?为啥么快排比hashmap快这么多?我自己试了一下JDK的Arrays.sort,接近线性的时间性能,参见文章:http://xcv4javaeye.iteye.com/blog/779032 。为啥么啊为什么?</p>

相关推荐

Global site tag (gtag.js) - Google Analytics