算法----两数之和

算法是一个很有意思的事情,尤其是,当你看到比你想法更好的算法的时候,真的是,有些人思维独特,很聪明。把复杂的问题,用很简单的代码写出来。

反正,算法是思想的交流。思想的交流,一般都会碰撞出火花。

总结:

1.我喜欢先写思路,再写代码。思路很重要,实现很简单。
有时候,你的思路的优化,决定了你的算法的效率。所以,一定要多斟酌几次。可以找到自己思路里面,可以优化的点。
2.自己写出来,要和别人比一下效率。不要闭门造车。
3.我学到了通过双层索引 解决问题的思路。

算法题目:

两数之和 II - 输入有序数组
     给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

     函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

     说明:

     返回的下标值(index1 和 index2)不是从零开始的。
     你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
     示例:

     输入: numbers = [2, 7, 11, 15], target = 9
     输出: [1,2]
     解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

我的解决办法:

    public static int[] twoSum(int[] numbers, int target) {
        int[]result = {0,0};
        int length = numbers.length;
        if (length <2) {
            return result;
        }
        int endIndex = length -1;
        int startIndex = 0;
        //找到比target 小的第一个数  需要考虑有负数的情况
//        while (endIndex >=0 && numbers[endIndex] >= target){
//            endIndex--;
//        }
//        // 该数组没有满足条件的
//        if (endIndex == 0) {
//            return result;
//        }

        //从最小的那个数 往前遍历循环  如果当前的这个数 和前面的数都不符合  该数pass
        //遍历的时候,当前的数和在遍历的数 如果比要找的数大 后面直接不用遍历
        //直接遍历下一个数

        //优化点:  1. 一层for 循环就可以  不要想的太复杂  2.遍历的时候,当前的数和在遍历的数 如果比要找的数小 前面的直接不用遍历
        out:for (; endIndex > 0; endIndex--) {
            for (; startIndex <endIndex; startIndex++) {
                int sum = numbers[endIndex] + numbers[startIndex];
                if (sum == target) {
                    break out;
                }else if (sum > target){
                    //结束层循环
//                    i = endIndex;
                    break;
                }

            }
        }
        //最后返回两个索引
        result[0] = ++startIndex;
        result[1] = ++endIndex;
        return result;
        }

网上写的比我优秀的代码,我用了两个for循环,但是别人用一个循环,两个index 搞定:

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int left = 0;
        int right = numbers.length - 1;
        while (left < right) {
            if (numbers[left] + numbers[right] > target) {
                right--;
            } else if (numbers[left] + numbers[right] == target){
                return new int[] {left + 1, right + 1};
            } else {
                left++;
            }
        }
        
        return null;
    }
}

网上最快的方法:

    网上最快的 通过2分查找   确实 两个数只和  要么是两个一样的中间数  要么是一个比他大的数  一个比他小的数加起来的
   因为二分法查找的两个数的合  所以二分法查找的一定在第一个数的右边  所以下面numbers[load - 1] 里面的load - 1 不可能是-1
class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] ans = new int[2];
			int half = target / 2;
			int load = Arrays.binarySearch(numbers, half) >= 0 ? Arrays.binarySearch(numbers, half)
					: Arrays.binarySearch(numbers, half) * -1 - 1;
			if (numbers[load - 1] + numbers[load] == target) {
				ans[0] = load;
				ans[1] = load + 1;
				return ans;
			}
			if (numbers[load] + numbers[load + 1] == target) {
				ans[0] = load + 1;
				ans[1] = load + 2;
				return ans;
			}
			int start = load - 1;
			int end = load;
			while (start >= 0 && end < numbers.length) {
				if (numbers[start] + numbers[end] > target) {
					start--;
				} else if (numbers[start] + numbers[end] < target) {
					end++;
				} else {
					ans[0] = start + 1;
					ans[1] = end + 1;
					return ans;
				}
			}
			return null;
    }
}

加油吧,少年

posted @ 2019-01-14 16:32  有点理想的码农  阅读(348)  评论(0编辑  收藏  举报