[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"
        }
};
时间: 2024-10-22 08:57:32

[LeetCode] 001. Two Sum (Medium) (C++/Java/Python)的相关文章

[LeetCode] 016. 3Sum Closest (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 016.3Sum_Closest (Medium) 链接: 题目:https://oj.leetcode.com/problems/3sum-closest/ 代码(github):https://github.com/illuz/leetcode 题意: 在给定数列中找出三个数,使和最接近 target. 分析:

[LeetCode] 039. Combination Sum (Medium) (C++)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 039. Combination Sum (Medium) 链接: 题目:https://leetcode.com/problems/combination-sum/ 代码(github):https://github.com/illuz/leetcode 题意: 给出一些正整数集合,以及一个目标数,从集合中选择一

[array] leetcode - 39. Combination Sum - Medium

leetcode - 39. Combination Sum - Medium descrition Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The same repeated number may be chosen from

[LeetCode] 018. 4Sum (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 018.4Sum (Medium) 链接: 题目:https://oj.leetcode.com/problems/4sum/ 代码(github):https://github.com/illuz/leetcode 题意: 给一个数列 S ,找出四个数 a,b,c,d 使得a + b + c + d = targ

[LeetCode] 002. Add Two Numbers (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 002.Add_Two_Numbers (Medium) 链接: 题目:https://oj.leetcode.com/problems/add-two-numbers/ 代码(github):https://github.com/illuz/leetcode 题意: 求两个 List 相加产生的新的一个 List

[LeetCode] 011. Container With Most Water (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 011.Container_With_Most_Water (Medium) 链接: 题目:https://oj.leetcode.com/problems/container-with-most-water/ 代码(github):https://github.com/illuz/leetcode 题意: 给一些

[LeetCode] 012. Integer to Roman (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 012.Integer_to_Roman (Medium) 链接: 题目:https://oj.leetcode.com/problems/integer-to-roman/ 代码(github):https://github.com/illuz/leetcode 题意: 把十进制转为罗马数. 分析: 模拟即可.

[LeetCode] 005. Longest Palindromic Substring (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 005.Longest_Palindromic_Substring (Medium) 链接: 题目:https://oj.leetcode.com/problems/Longest-Palindromic-Substring/ 代码(github):https://github.com/illuz/leetcode

[LeetCode] 015. 3Sum (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 015.3Sum (Medium) 链接: 题目:https://oj.leetcode.com/problems/3sum/ 代码(github):https://github.com/illuz/leetcode 题意: 在给定数列中找出三个数,使和为 0. 分析: 先排序,再左右夹逼,复杂度 O(n*n).