[LeetCode] 001. Two Sum (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql)
Github: https://github.com/illuz/leetcode


001.Two_Sum (Medium)

链接

题目:https://oj.leetcode.com/problems/two-sum/
代码(github):https://github.com/illuz/leetcode

题意

一个数组中两个位置上的数的和恰为 target,求这两个位置。

分析

暴力找过去复杂度是 O(n^2),会 TLE。

  1. 可以先排序再用双指针向中间夹逼,复杂度 O(nlogn)。
  2. 可以用 Map 记录出现的数,只要判断有没有和当前的数凑成 target 的数,再找出来就行,复杂度 O(nlogn) 而不是 O(n) ,因为 Map 也要复杂度的。
  3. 在 2 中的 Map 复杂度可以用数组来弥补,时间复杂度是 O(n) ,不过空间复杂度是 O(MAXN)。

代码

方法一:双指针

class Solution {
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            int sz = numbers.size();
            int left = 0, right = sz - 1, sum = 0;

            vector<int> sorted (numbers);
            std::sort(sorted.begin(), sorted.end());

            vector<int> index;
            while (left < right) {
                sum = sorted[left] + sorted[right];
                if (sum == target) {
                    // find the answer
                    for (int i = 0; i < sz; i++) {
                        if (numbers[i] == sorted[left])
                            index.push_back(i + 1);
                        else if (numbers[i] == sorted[right])
                            index.push_back(i + 1);
                        if (index.size() == 2)
                            return index;
                    }
                } else if (sum > target) {
                    right--;
                } else {
                    left++;
                }
            }
            // Program never go here, because
            // "each input would have exactly one solution"
        }
};

Java:

public class Solution {

    static class Pair implements Comparable<Pair> {
        int value, index;
        public Pair(int v, int id) {
            value = v;
            index = id;
        }

        @Override
        public int compareTo(Pair b) {
            return this.value - b.value;
        }
    }

    public static int[] twoSum(int[] numbers, int target) {
        int[] res = new int[2];
        Pair[] pairs = new Pair[numbers.length];

        // get pairs and sort
        for (int i = 0; i < numbers.length; ++i) {
            pairs[i] = new Pair(numbers[i], i + 1);
        }
        Arrays.sort(pairs);

        // two points
        int left = 0, right = numbers.length - 1, sum = 0;
        while (left < right) {
            sum = pairs[left].value + pairs[right].value;
            if (sum == target) {
                res[0] = pairs[left].index;
                res[1] = pairs[right].index;
                if (res[0] > res[1]) {
                    // swap them
                    res[0] ^= res[1];
                    res[1] ^= res[0];
                    res[0] ^= res[1];
                }
                break;
            } else if (sum > target) {
                --right;
            } else {
                ++left;
            }
        }

        return res;
    }
}

Python:

class Solution:
    # @return a tuple, (index1, index2)
    def twoSum(self, num, target):
        # sort
        sorted_num = sorted(num)

        # two points
        left = 0
        right = len(num) - 1
        res = []
        while (left < right):
            sum = sorted_num[left] + sorted_num[right]
            if sum == target:
                # find out index
                break;
            elif sum > target:
                right -= 1
            else:
                left += 1

        if left == right:
            return -1, -1
        else:
            pos1 = num.index(sorted_num[left]) + 1
            pos2 = num.index(sorted_num[right]) + 1
            if pos1 == pos2:    # find again
                pos2 = num[pos1:].index(sorted_num[right]) + pos1 + 1

            return min(pos1, pos2), max(pos1, pos2)

方法二: Map

C++ :

const int N = 200002;
const int OFFSET = 100000;

class Solution {
    private:
        int idOfNum[N];
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            vector<int> index;
            memset(idOfNum, 0, sizeof(idOfNum));

            int sz = numbers.size();
            for (int i = 0; i < sz; i++) {
                int rest = target - numbers[i];
                if (idOfNum[rest + OFFSET]) {
                    index.push_back(idOfNum[rest + OFFSET]);
                    index.push_back(i + 1);
                    return index;
                }
                idOfNum[numbers[i] + OFFSET] = i + 1;
            }
            // Program never go here, because
            // "each input would have exactly one solution"
        }
};

Java:

public class Solution {
    public static int[] twoSum(int[] numbers, int target) {
        int[] res = new int[2];
        HashMap<Integer, Integer> nums = new HashMap<Integer, Integer>();

        for (int i = 0; i < numbers.length; ++i) {
            // add i-th number
            Integer a = nums.get(numbers[i]);
            if (a == null)
                nums.put(numbers[i], i);

            // find (target - numbers[i])
            a = nums.get(target - numbers[i]);
            if (a != null && a < i) {
                res[0] = a + 1;
                res[1] = i + 1;
                break;
            }
        }
        return res;
    }
}

Python:

class Solution:
    # @return a tuple, (index1, index2)
    def twoSum(self, num, target):
        dictMap = {}
        for index, value in enumerate(num):
            if target - value in dictMap:
                return dictMap[target - value] + 1, index + 1
            dictMap[value] = index

方法三:数组

C++: (与方法二的对比)

const int N = 200002;
const int OFFSET = 100000;

class Solution {
    private:
        int idOfNum[N];
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            vector<int> index;
            memset(idOfNum, 0, sizeof(idOfNum));

            int sz = numbers.size();
            for (int i = 0; i < sz; i++) {
                int rest = target - numbers[i];
                if (idOfNum[rest + OFFSET]) {
                    index.push_back(idOfNum[rest + OFFSET]);
                    index.push_back(i + 1);
                    return index;
                }
                idOfNum[numbers[i] + OFFSET] = i + 1;
            }
            // Program never go here, because
            // "each input would have exactly one solution"
        }
};
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值