[C++]LeetCode: 15 3Sum Closest (plus JAVA Code)

题目:

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).
思路: 寻找数组中三个数的和,满足最接近target

     先对数组进行排序,然后i,j,k三个点。i是最小值,k是最大值,j是中间某值。三个数的和如果大于target,需要左移k,如果小于target,需要右移j。遍历i从最小到最大。
        //此题隐含的意思是可以选择相同的三个整数。所以设计算法时,不需要考虑三个不同整数的约束。

参考:stackoverflow

Attention: 

1. 使用STL里的方法时,必须给出作用域。如 Arrays.sort(num);

2. 对于返回和ans的初始化很重要,不能忘记。还有不能随意初始化,都会影响后面的比较。

3. 遍历i时,只需要到num.length  - 2, 后面是重复的同i,j, k。

4. 注意题目的输入类型java版是数组,C++版是vector.

C++ AC Code:

class Solution {
public:
    int threeSumClosest(vector<int> &num, int target) {
        //寻找数组中三个数的和,满足最接近target
        //思路:先对数组进行排序,然后i,j,k三个点。i是最小值,k是最大值,j是中间某值。三个数的和如果大于target,需要左移k,如果小于target,需要右移j。遍历i从最小到最大。
        //此题隐含的意思是可以选择相同的三个整数。所以设计算法时,不需要考虑三个不同整数的约束。
        
        vector<int> ivec(num.begin(), num.end());
        int ans = 0;
        int sum;
        
        //template <class RandomAccessIterator>
        // void sort (RandomAccessIterator first, RandomAccessIterator last);
        sort(ivec.begin(), ivec.end());
        
        //template <class InputIterator, class T>
        //T accumulate (InputIterator first, InputIterator last, T init); 第三个参数是初值。
        //如果个数小于3个,返回和
        if(ivec.size() < 3)
            return accumulate(ivec.begin(), ivec.end(), 0);
        
        ans = ivec[0] + ivec[1] + ivec[2];  
        
        /* v[0] v[1] v[2] ... v[i] .... v[j] ... v[k] ... v[n-2] v[n-1]
     *                    v[i]  <=  v[j]  <= v[k] always, because we sorted our array. 
     * Now, for each number, v[i] : we look for pairs v[j] & v[k] such that 
     * absolute value of (target - (v[i] + v[j] + v[k]) is minimised.
     * if the sum of the triplet is greater then the target it implies
     * we need to reduce our sum, so we do K = K - 1, that is we reduce
     * our sum by taking a smaller number.
     * Simillarly if sum of the triplet is less then the target then we
     * increase out sum by taking a larger number, i.e. J = J + 1.
     */
     
        //只需要遍历到倒数第三个,倒数一和倒数二是反向重复的。
        for(int i = 0; i < ivec.size() - 2; i++)
        {
            int j = i + 1;
            int k = ivec.size() - 1;
            while(j < k)
            {
                sum = ivec[i] + ivec[j] + ivec[k];
                if(abs(target - ans) > abs(target - sum))
                {
                    ans = sum;
                    if(ans == target)
                        return ans;
                }
                //条件运算符把冒号两边之一作为返回值,所以必须是值,不能是语句
                //(sum > target) ? k-- : j++;   ERROR!!
                //(sum > target) ? k -= 1 : j += 1;
                if(sum > target)
                  k--;
                else
                  j++; 
            }
        }
        
        return ans;
        
    }
};


JAVA AC Code:

public class Solution {
    public int threeSumClosest(int[] num, int target) {
        //先排序,再遍历。
       int ans =0;
       int sum;
       int ArrySize = num.length;
       //需要加上作用域Array才能调用其内的方法
       Arrays.sort(num);
       
       //ans初始化很重要 影响后面比较
       ans = num[0] + num[1] + num[2];
       
       //遍历
       for(int i = 0; i < ArrySize - 2; i++)
       {
           int j = i + 1;
           int k = ArrySize - 1;
           
           while(j < k)
           {
               sum = num[i] + num[j] + num[k];
               
               if( Math.abs(target - ans) > Math.abs(target - sum))
               {
                   ans = sum;
                   //如果距离为0  直接返回ans
                   if(ans == target)
                        return ans;
               }
               //条件运算符把冒号两边之一作为返回值,所以必须是值,不能是语句
               //(sum > target) ? k-- : j++; (sum > target) ? (k -= 1) : (j += 1);  ERROR!!
              // (sum > target) ? (k -= 1) : (j += 1);
               if(sum > target)
                  k--;
               else
                  j++; 
           }
       }
       
       //遍历后计算出距离最近的ans
       return ans;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值