【LeetCode】算法系列(Algorithms)(一)——2sum,3sum,3sum Closeset

本系列记录了博主在刷LeetCode过程中的笔记。更新于2019.5.13。

ps:今天是母亲节,祝所有的母亲们节日快乐,健康幸福!

1. 2Sum

题目难度: easy

题目

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
给定一个由整数组成的array,返回和等于某个特定目标数的两个数的indices。

You may assume that each input would have exactly one solution, and you may not use the same element twice.
可以假设每个输入只有一个特定的解,且一个元素只能用一次。

Example:
例:

Given nums = [2, 7, 11, 15], target = 9,
给定整数[2,7,11,15],目标数9。

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
因为nums[0]+nums[1]=2+7=9,所以返回[0,1]。

答案

方法1:暴力搜索
这个方案相信很多人都可以想到,即查询整个array,对每个元素 x x x都查找一下有没有元素等于 t a r g e t − x target-x targetx

Java答案:

public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}

方法2: Two-pass Hash Table
为了节省运算时间,需要有一个更有效的方法检查元素是否存在于array中。如果存在,需要找到该元素的index。那么什么是管理array内的每个元素到其index映射的最好方法呢?那就是hash table(哈希表)

由此,我们以存储空间为代价,将查找时间从 O ( n ) O(n) O(n)下降到了 O ( 1 ) O(1) O(1)。具体实现方法是,首先建一个哈希表,随后查表。

Java答案:

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement) && map.get(complement) != i) {
            return new int[] { i, map.get(complement) };
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}

在这里插入图片描述
方法3:其他方法

Python答案:

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        
        for i in range(len(nums)):
            search_num = target-nums[i]
            if search_num in nums:
                index_b = nums.index(search_num)
                if index_b != i:
                    index_a = i
                    return index_a,index_b

在这里插入图片描述

C++答案:

#include <unordered_map>
#include <vector>
using namespace std;

class Solution
{
public:
    vector<int> twoSum(vector<int>& nums, int target)
    {
        unordered_map<int, size_t> N;
        vector<int> res;
        for(size_t i = 0; i < nums.size(); ++i) {
            int num = nums[i];
            if(N.count(target - num)) {
                res.push_back(i);
                res.push_back(N[target - num]);
            } else {
                N.insert({ num, i });
            }
        }
        return res;
    }
};

在这里插入图片描述

15. 3sum

题目难度:Medium

题目

Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
给定一个由n个整数组成的array,找到是否存在三个元素a,b,c之和等于0。
如果存在,找到所有不重复的组合。

Note:
注意:

The solution set must not contain duplicate triplets.
答案中的所有组合不能重复。

Example:
例:

Given array nums = [-1, 0, 1, 2, -1, -4],
给定矩阵nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
一个解是:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

答案

没有官方答案,博主写的python代码,虽然不是暴力搜索但是仍然超出时间限制:

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        results = [];
        final_results = [];
        
        for i in range(len(nums)):
            for j in range(len(nums)):
                if i != j:
                    num_search = -nums[i]-nums[j]
                    if num_search in nums:
                        index_n = nums.index(num_search)
                        if index_n != i:
                            if index_n != j:
                                l = [nums[i],nums[j],num_search]
                                l.sort()
                                results.append(l)
        
        for i in range(len(results)):
            tmp = results[i]
            results[i] = ['a','a','a']
            if tmp in results:
                continue
            else:
                final_results.append(tmp)
                
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        results = [];
        
        if len(nums) < 3:
            return results
            
        for i in range(len(nums)):
            for j in range(len(nums[i+1:])):
                search_nums = -nums[i]-nums[i+j+1]
                if search_nums in nums[i+1:]:
                    search_nums_index = nums[i+1:].index(search_nums)
                    if j != search_nums_index:
                        l = [nums[i],nums[i+j+1],search_nums]
                        l.sort()
                        if l in results:
                            continue
                        else:
                            results.append(l)
        return results

C++答案:
代码来自于这里

class Solution {
public:
    vector< vector<int> > threeSum(vector<int>& nums) {
        int n = nums.size();
        vector< vector<int> > res;
        if (n < 3)
            return res;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < n - 2; i++)
        {
            if(i == 0 ||  (i > 0 && nums[i] != nums[i - 1]))
            {
                int left = i + 1, right = n - 1;
                int sum = 0 - nums[i];
                while(left < right)
                {
                    if(nums[left] + nums[right] == sum)
                    {
                        vector<int> vi;
                        vi.push_back(nums[i]);
                        vi.push_back(nums[left]);
                        vi.push_back(nums[right]);
                        res.push_back(vi);
                        while(left < right && nums[left] == nums[left + 1])
                            left++;
                        while(left < right && nums[right] == nums[right - 1])
                            right--;
                        left++;
                        right--;
                    }
                    else if(nums[left] + nums[right] < sum)
                        left++;
                    else
                        right--;
                }
            }
        }
        return res;
    }
};

在这里插入图片描述
但是博主尝试用相同的逻辑撰写Python代码,仍然超出时间限制:

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        results = []
        n = len(nums)
        
        nums.sort()
        for i in range(n):
            left = i+1
            right = n-1
            rest_num = -nums[i]
            while left < right:
                if nums[left]+nums[right]==rest_num:
                    l = [nums[i],nums[left],nums[right]]
                    if l in results:
                        left=left+1
                        right=right-1
                        continue
                    else:
                        results.append(l)
                        left=left+1
                        right=right-1
                elif nums[left]+nums[right]<rest_num:
                    left = left+1
                else:
                    right=right-1
        return results

正确Python代码,相同思路:

class Solution:
    # @return a list of lists of length 3, [[val1,val2,val3]]
    def threeSum(self, num):
        num.sort()
        res = []
        for i in range(len(num)-2):
            if i == 0 or num[i] > num[i-1]:
                left = i + 1; right = len(num) - 1
                while left < right:
                    if num[left] + num[right] == -num[i]:
                        res.append([num[i], num[left], num[right]])
                        left += 1; right -= 1
                        while left < right and num[left] == num[left-1]: left +=1
                        while left < right and num[right] == num[right+1]: right -= 1
                    elif num[left] + num[right] < -num[i]:
                        while left < right:
                            left += 1
                            if num[left] > num[left-1]: break
                    else:
                        while left < right:
                            right -= 1
                            if num[right] < num[right+1]: break
        return res

在这里插入图片描述

16. 3Sum Closest

题目难度:Medium

题目

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
给定一个由整数组成的array nums和一个目标整数target,找到nums中的三个整数,使得其和最接近target。
返回这三个整数的和。可以假设只存在一个解。

Example:
例:

Given array nums = [-1, 2, 1, -4], and target = 1.
给定array nums = [-1, 2, 1, -4]和目标target = 1

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
最接近目标的和应该是2:(-1 + 2 + 1 = 2)。

答案

Python答案:
以下为博主自己写的Python版本答案

class Solution(object):
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        
        nums.sort()
        tmp_left = []
        tmp_right = []
        
        for i in range(len(nums)-2):
            obj = target-nums[i]
            left = i+1; right = len(nums)-1
            
            while left<right:
                tmp = nums[left]+nums[right]
                if tmp == obj:
                    return tmp+nums[i]
                elif tmp < obj:
                    tmp_left.append(tmp + nums[i])
                    left = left+1
                else:
                    tmp_right.append(tmp + nums[i])
                    right = right-1
                
        try:
            left_max = max(tmp_left)
            res_left = abs(left_max-target)
            left_exist = True
        except:
            left_exist = False
            
        try:
            right_min = min(tmp_right)
            res_right = abs(right_min-target)
            right_exist = True
        except:
            right_exist = False
                
        if left_exist and not right_exist:
            return left_max
        elif not left_exist and right_exist:
            return right_min
        elif left_exist and right_exist and res_left < res_right:
            return left_max
        elif left_exist and right_exist and res_left > res_right:
            return right_min
        else:
            print('Answer not found!')

更多内容,欢迎加入星球讨论。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019070914030826.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1NodXFpYW9T,size_16,color_FFFFFF,t_70)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值