3sum-closest

https://leetcode.com/problems/3sum-closest/

// At first, my DP solution exceeds time limitation
// Then with the hint fo the discussion board,
// I have the final solution of impl2,
// which is very smart!

 

class Solution {
    map<pair<int, pair<int, int>>, int> mp;
    int diff(int a, int b) {
        return a>=b ? a-b : b-a;
    }
    
    bool close(int a, int b) {
        if (b == 0) {
            // for init condition
            return true;
        }
        
        if (a < 0) {
            a *= -1;
        }
        if (b < 0) {
            b *= -1;
        }
        return a < b;
    }
    
    vector<int> nums;
    
public:
    int threeSumClosest(vector<int>& n, int target) {
        nums = n;
        
        int vlen = nums.size();
        if (vlen < 3) {
            return 0;
        }
        
        //return impl(target, vlen, 3);
        return impl2(target, vlen);
    }
    
    int impl2(const int &target, const int &end) {
        sort(nums.begin(), nums.end());
        // can be 0, as if 0 returns asap
        int df = 0;

        int n;        
        int p;
        int q;
        int ndf;
        for (int i = 0; i < end-2; i++) {
            n = nums[i];
            p = i + 1;
            q = end - 1;
            while (p < q) {
                ndf = n + nums[p] + nums[q];
                if (ndf == target) {
                    return target;
                }
                else if (ndf > target) {
                    q--;
                }
                else {
                    p++;
                }
                if (close(ndf - target, df)) {
                    df = ndf - target;
                }
            }
        }
        return target + df;
    }
    
    // below solution exceed time limit
    int impl(const int &target, const int &end, const int &sz) {
        if (sz == 0 || end == 0) {
            return 0;
        }
        
        pair<int, pair<int, int>> pr = make_pair(target, make_pair(end, sz));
        if (mp.find(pr) != mp.end()) {
            return mp[pr];
        }
        
        int ret;
        int df;
        
        if (sz == 1) {
            
            ret = nums[0];
            df = diff(ret, target);
            
            for (int i=1; i<end; i++) {
                if (diff(nums[i], target) < df) {
                    ret = nums[i];
                    df = diff(ret, target);
                }
            }
            // return
        }
        else {
            if (end < sz) {
                return 0;
            }
            else if (end == sz) {
                ret = 0;
                for (int i=0; i<sz; i++) {
                    ret += nums[i];
                }
                // return
            }
            else {
                
                ret = impl(target-nums[end-1], end-1, sz-1) + nums[end-1];
                df = diff(ret, target);
                
                int a = impl(target, end-1, sz);
                if (diff(a, target) < df) {
                    ret = a;
                }
                //return
            }
        }
        
        mp[pr] = ret;
        return ret;
        
    }
    
};

// Below may be duplicate

class Solution {
    map<pair<int, pair<int, int>>, int> mp;
    int diff(int a, int b) {
        return a>=b ? a-b : b-a;
    }
    
    bool close(int a, int b) {
        if (b == 0) {
            // for init condition
            return true;
        }
        
        if (a < 0) {
            a *= -1;
        }
        if (b < 0) {
            b *= -1;
        }
        return a < b;
    }
    
    vector<int> nums;
    
public:
    int threeSumClosest(vector<int>& n, int target) {
        nums = n;
        
        int vlen = nums.size();
        if (vlen < 3) {
            return 0;
        }
        
        //return impl(target, vlen, 3);
        return impl2(target, vlen);
    }
    
    int impl2(const int &target, const int &end) {
        sort(nums.begin(), nums.end());
        // can be 0, as if 0 returns asap
        int df = 0;

        int n;        
        int p;
        int q;
        int ndf;
        for (int i = 0; i < end-2; i++) {
            n = nums[i];
            p = i + 1;
            q = end - 1;
            while (p < q) {
                ndf = n + nums[p] + nums[q];
                if (ndf == target) {
                    return target;
                }
                else if (ndf > target) {
                    q--;
                }
                else {
                    p++;
                }
                if (close(ndf - target, df)) {
                    df = ndf - target;
                }
            }
        }
        return target + df;
    }
    
    // below solution exceed time limit
    int impl(const int &target, const int &end, const int &sz) {
        if (sz == 0 || end == 0) {
            return 0;
        }
        
        pair<int, pair<int, int>> pr = make_pair(target, make_pair(end, sz));
        if (mp.find(pr) != mp.end()) {
            return mp[pr];
        }
        
        int ret;
        int df;
        
        if (sz == 1) {
            
            ret = nums[0];
            df = diff(ret, target);
            
            for (int i=1; i<end; i++) {
                if (diff(nums[i], target) < df) {
                    ret = nums[i];
                    df = diff(ret, target);
                }
            }
            // return
        }
        else {
            if (end < sz) {
                return 0;
            }
            else if (end == sz) {
                ret = 0;
                for (int i=0; i<sz; i++) {
                    ret += nums[i];
                }
                // return
            }
            else {
                
                ret = impl(target-nums[end-1], end-1, sz-1) + nums[end-1];
                df = diff(ret, target);
                
                int a = impl(target, end-1, sz);
                if (diff(a, target) < df) {
                    ret = a;
                }
                //return
            }
        }
        
        mp[pr] = ret;
        return ret;
        
    }
    
};


// below is my original code some months ago, maybe wrong

    int sumClosest(vector<int>& nums, int target, int len) {
        if (len == 0) {
            return 0;
        }
        
        int vlen = nums.size();
        if (vlen < len) {
            return 0;
        }
        
        int i= 0;
        int result = 0;
        
        if (vlen == len) {
            for (i=0; i<vlen; i++) {
                result += nums[i];
            }
            return result;
        }
        
        int tail = nums[vlen-1];
        
        if (vlen-1 == len) {
            for (i=0; i<vlen-1; i++) {
                result += nums[i];
            }
        }
        else if (vlen-1 > len) {
            nums.pop_back();
            result = sumClosest(nums, target, len);
            nums.push_back(tail);
        }
        
        nums.pop_back();
        int ret = sumClosest(nums, target-tail, len-1) + tail;
        nums.push_back(tail);
        
        int diff1 = target - result;
        diff1 = (diff1>0)?diff1:diff1*-1;
        int diff2 = target - ret;
        diff2 = (diff2>0)?diff2:diff2*-1;
        if(diff1 < diff2) {
            return result;
        }
        return ret;
    }

 

posted @ 2016-04-19 15:31  blcblc  阅读(231)  评论(0编辑  收藏  举报