leetcode题解日练--2016.7.25

日练三题,冰冻三尺非一日之寒。

今日题目:

1、组合加法IV; | tag:DP

2、最接近的三数字和; |tag:数组、两指针

3、查找目标范围。 |tag:数组|二分查找

今日摘录:

一个人爱什么,就死在什么上。
——老舍

377. Combination Sum IV | Difficulty: Medium

Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example:

nums = [1, 2, 3]
target = 4

The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)

Note that different sequences are counted as different combinations.

Therefore the output is 7.
Follow up:
What if negative numbers are allowed in the given array?
How does it change the problem?
What limitation we need to add to the question to allow negative numbers?

tag:DP
题意:找到数组元素中部分和等于目标值的组合数
思路:
1、思路很好理清,以nums = [1,2,3] target = 4为例。如果我们需要找到和为1的组合可能数,怎么去做?用res[i]表示和为i的可能性,res[0] = 1,需要找和为1的可能性,只可能是nums中有1 这一种情况,这个时候res[1] = 1,然后再去求res[2],2无非就是两种情况,第一种情况res[1]+1,也就是在res[1]的基础上再碰到一个1,因为res[1]只有一种情况,随意再碰到一个1还是只有一种情况,第二种情况是res[0]+2,也就是res[0]的情况可能性加上碰到一个2,也是一种情况,合起来res[2]就是2种可能性,继续往下去计算,res[3] = (res[2]+1存在)+(res[1]+2存在)+(res[0]+3存在)=4,res[4]=7.

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        vector<int>res(target+1,0);
        res[0] = 1;
        for(int i=1;i<=target;i++)
        {
            for(int num:nums)
            {
                if(i>=num)  res[i]+=res[i-num];
            }
        }
        return res[target];
    }
};

结果:4ms

16. 3Sum Closest | Difficulty: Medium

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

tag: 数组|两指针
题意:给定一个n个整数的数组,找到S中的三个整数使得和最接近给定数值。
思路:
1、首先对数组进行排序,然后运用三个指针,第一个指针确定第一个元素,第二个指针和第三个指针在剩余元素的两头,如果大了就移动后面的指针,小了就移动前面的指针,这样不断更新最小的误差,就能得到最终结果,复杂度O(N^2)

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        vector<int> v(nums.begin(),nums.end());
        int n = nums.size();
        sort(v.begin(),v.end());
        if(nums.size()<=3)  return accumulate(v.begin(), v.end(), 0);   
        int res = v[0]+v[1]+v[2];
        for(int i=0;i<n-2;i++)
        {
            int j = i+1;
            int k = n-1;
            while(j<k)
            {
             int sum = v[i]+v[j]+v[k];
             if(abs(sum-target)<abs(res-target))
             {
                 res = sum;
             }
             if(abs(sum-target)==0) return sum;
             (sum>target)? k--:j++;
            }
        }
        return res;
    }
};

结果:16ms

34. Search for a Range | Difficulty: Medium

Given a sorted array of integers, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

tag:数组|二分查找
题意:给定一个整型数组,找到目标值的起始和终止位置。
思路:
1、二分查找的思想,首先找左边界的时候,应该是mid位置值小了就将left=mid+1,mid值大了就right=mid-1,否则就是相等,这个时候左边界可能在mid的左边,也可能就是mid,不过无论如何将right设置成mid就可以保证不出错。照此找出左边界之后,以左边界为左分界线,最右为又分界线开始二分查找,这时候mid只有两种情况,等于target和大于target,等于的时候就将left = mid,大于就将right = mid-1.这里为了防止最后剩下2个元素并且相等的时候形成死循环,可以设置元素在二分的时候向右边倾斜一点,即原本偶数个数取偏左,现在改成偏右。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int>res(2,-1);
        int left = 0,right = nums.size()-1;
        while(left<right)
        {
            int mid = left+(right-left)/2;
            if(nums[mid]<target)    left = mid+1;
            else if(nums[mid]>target)    right = mid-1;
            else    right = mid;
        }
        if(nums[left]!=target)  return res;
        else    res[0] = left;
        right = nums.size()-1;
        while(left<right)
        {
            int mid = left+(right-left)/2+1;
            if(nums[mid]>target)    right = mid-1;
            else    left = mid;
        }
        res[1] = right;
        return res;
    }
};

结果:12ms
第二次刷代码

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> res(2,-1);
        int n =nums.size();
        if(n==0 || target<nums[0] || target>nums[n-1])  return res;
        int l = 0,r = n-1;
        while(l<r)
        {
            int mid = l+(r-l)/2;
            if(nums[mid]<target)    l = mid+1;
            else    r = mid;
        }
        if(nums[l]==target)  res[0] = l;
        else    return res;
        l=0,r=n-1;
        while(l<r)
        {
            int mid = l+(r-l+1)/2;
            if(nums[mid]>target)    r=mid-1;
            else    l=mid;
        }
        if(nums[l]==target) res[1] = l;
        return res;
    }
};

结果:12ms

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值