【leetcode】两数相加(算法)

两数之和

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

看到题目我首先想到的是将目标值(target)拆分,将目标值变成0+target,1+(target-1),...,(target/2)+(target-target/2).

由于第一次做算法题,我这种思想在我刚准备打代码时就直接被我抛之脑后,因为这种思路其实很'暴力',数组可能根本没有这么多数,如果给定的target很大,那我势必会在拆分上花费很大的开销。

那么现在,我们可以改进,得到的是,直接用target减去数组里的数,用得到的数去从数组里找,这样的话我们就节省很多。这是又有一个小问题,如果你从数组里找,你每减一个数,你势必需要遍历一遍数组。而我是将target减过的数放进List里面,从后面找前面已有的数。

代码如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
         List list =new ArrayList<Integer>();
         int result[] = new int[2];
        for (int i = 0 ;i<nums.length;i ++){
            if (list.contains(target-nums[i]))
            {
                result[0]=list.indexOf(target-nums[i]);
                result[1]=i;
                break;
            }else {
                list.add(nums[i]);
            }
        }
        return result;
    }

}

时间复杂度为O(n),运行的时间大概为几十ms,下面则是几ms的代码;

class Solution {
    public int[] twoSum(int[] nums, int target) {
		// 先复制一份数组
		int[] newNums = Arrays.copyOf(nums, nums.length);
		// 排序复制的数组
        Arrays.sort(newNums);
        // 结果集
        int[] res = new int[2]; 
        // 循环遍历每一个
        for (int i=0; i<newNums.length - 1; i++) {
        	// 如果剩余的数只有一个,那么判断这一个,并退出循环
        	if (newNums.length-i-1 == 1) {
            	if (newNums[i]+newNums[i+1] == target) {
            		res = new int[]{i,i+1};
            	} else {
            		res = null;
            	}
            	break;
            }
        	
        	// 如果剩余的不只一个,则用二分法
        	int num = newNums[i];
        	int rest = target-num;
        	
        	int start = i+1;
        	int end = newNums.length-1;
        	int mid; // = (start+end) / 2;
        	int src = -1;
        	while(start < end) {
        		mid = (start+end+1) / 2;
        		if (rest < newNums[mid]) {
        			end = mid-1;
        		} else if (rest > newNums[mid]) {
        			start = mid+1;
        		} else {
        			src = mid;
        			break;
        		}
        	}
        	if (start == end && newNums[start] == rest) {
        		src = start;
        	}
        	// 如果二分法找到,则退出循环
        	if (src != -1) {
        		res[0] = i;
        		res[1] = src;
        		break;
        	}
        }
        
        boolean flag1=false;
        boolean flag2=false;
        
        // 在原数组中查找位置
        for(int i=0; i<nums.length; i++) {
        	if (flag1 && flag2) break;
        	if (!flag1 && nums[i] == newNums[res[0]]) {
        		res[0] = i;
        		flag1 = true;
        		continue;
        	}
        	if (!flag2 && nums[i] == newNums[res[1]]) {
        		res[1] = i;
        		flag2 = true;
        	}
        }
		return res;
    }
}

猜你喜欢

转载自blog.csdn.net/PI_PIBOY/article/details/80789386
今日推荐