zoukankan      html  css  js  c++  java
  • TwoSum:两数相加得0

    在一个不重复的数组中,统计有多少组两个元素相加得0。

    这里使用三种方式实现,并统计他们各自花费的时间:

    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Random;
    
    public class TwoSum {
    	private static int N = 100000;
    	private static int[] a = new int[N];
    	private static Random random = new Random();
    	private static HashMap<Integer, Boolean> m = new HashMap<Integer, Boolean>();
    	
    	private int binarySearch(int[] a, int num) {
    		int low = 0, mid = 0, high = a.length - 1;
    		while (low <= high) {
    			mid = low + (high - low) / 2;
    			if (a[mid] > num) {
    				high = mid - 1;
    			} else if (a[mid] < num) {
    				low = mid + 1;
    			} else {
    				return mid;
    			}
    		}
    		
    		return -1;
    	}
    	
    	public int solution1() {
    		int count = 0;
    		for (int i = 0; i < N; i++) {
    			for (int j = i + 1; j < N; j++) {
    				if (a[i] + a[j] == 0) {
    					count++;
    				}
    			}
    		}
    		return count;
    	}
    	
    	public int solution2() {
    		int count = 0;
    		Arrays.sort(a);
    		for (int i = 0; i < N; i++) {
    			if (binarySearch(a, -a[i]) > i) {
    				count++;
    			}
    		}
    		return count;
    	}
    	
    	public int solution3() {
    		int count = 0;
    		for (int i = 0; i < N; i++) {
    			if (m.containsKey(-a[i])) {
    				count++;
    			}
    		}
    		return count / 2;
    	}
    	
    	public static int uniform(int N) {
            if (N <= 0) throw new IllegalArgumentException("Parameter N must be positive");
            return random.nextInt(N);
        }
    	
    	public int uniform(int a, int b) {
            if (b <= a) throw new IllegalArgumentException("Invalid range");
            if ((long) b - a >= Integer.MAX_VALUE) throw new IllegalArgumentException("Invalid range");
            return a + uniform(b - a);
        }
    	
    	public static void main(String[] args) {
    		TwoSum ts = new TwoSum();
    		int count = 0;
    		int rand = 0;
    		int i = 0;
    		boolean flag = true;
    		
    		while (i < a.length) {
    			rand = ts.uniform(-10000000, 10000000);
    			flag = true;
    			for (int j = 0; j < a.length; j++) {
    				if (a[j] == rand) {
    					flag = false;
    					break;
    				}
    			}
    			if (flag) {
    				a[i] = rand;			
    				i++;
    				//System.out.println(rand + " " + flag);
    			}
    		}
    		
    		for (int j = 0; j < N; j++) {
    			m.put(a[j], true);
    		}
    		
    		Stopwatch timer1 = new Stopwatch();
    		count = ts.solution1();
    		double time = timer1.elapsedTime();
    		System.out.println("count1: " + count + " cost1: " + time);
    		
    		count = 0;
    		time = 0;
    		Stopwatch timer2 = new Stopwatch();
    		count = ts.solution2();
    		time = timer2.elapsedTime();
    		System.out.println("count2: " + count + " cost2: " + time);
    		
    		count = 0;
    		time = 0;
    		Stopwatch timer3 = new Stopwatch();
    		count = ts.solution3();
    		time = timer3.elapsedTime();
    		System.out.println("count3: " + count + " cost3: " + time);
    	}
    }
    

    solution1:直接使用一个两层for循环,所以最终的时间复杂度为O(N^2);

    solution2:先将数组排序,然后通过二分查找来搜索数组中每个元素的相反数,此时的时间复杂度为O(N*log(N));

    solution3:和方法一类似,只不过是通过哈希表中查找元素的复杂度为O(1)来优化搜索时间,此时时间复杂度为O(N);

    当N=1000时
    
    count1: 0 cost1: 0.004
    count2: 0 cost2: 0.002
    count3: 0 cost3: 0.001
    
    当N=10000时
    
    count1: 5 cost1: 0.026
    count2: 5 cost2: 0.009
    count3: 5 cost3: 0.005
    
    当N=100000时
    
    count1: 238 cost1: 2.296
    count2: 238 cost2: 0.077
    count3: 238 cost3: 0.012

    这里因为产生不重复的随机数使用的是最简单的两层循环,所以当数组的length太大时,比如1000000时,在产生随机数的过程中会消耗很长时间,这一部分可以使用其他更优的方法实现。

    ------------------------------- 问道,修仙 -------------------------------
  • 相关阅读:
    Linux新手入门:通过chmod改变文件权限--转
    一个非常好的性格切割问题
    Weka算法Classifier-tree-J48源代码分析(一个)基本数据结构和算法
    百度地图3.1课程—检索演示
    JAVA在IO流量汇总
    crm2011i创建nt类型字段
    学习vi和vim编辑(3):一个简单的文本编辑器(2)
    禹洲:我们这一代人的困惑
    D其他项目打电话AL工程EF Model
    HDU 2289 Cup(可以二分法,但是除了它的一半?)
  • 原文地址:https://www.cnblogs.com/elvalad/p/4060991.html
Copyright © 2011-2022 走看看