Wednesday, May 22, 2013

Day 28, 12, 15,16, Integer to Roman, 3Sum, 3Sum Closest

Integer to Roman
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
--------------------------------------------------
set up an dictionary and an array of values in order
pay attention to "4", "9", "19", "989", etc
先检查 == 4,再检查 == 9
COME_BACK
class Solution {
public:
    string intToRoman(int num) {
        unordered_map k;
        k[1] = 'I';
        k[5] = 'V';
        k[10] = 'X';
        k[50] = 'L';
        k[100] = 'C';
        k[500] = 'D';
        k[1000] = 'M';
        string s = "";
        vector order = {1000,500,100,50,10,5,1};
        
        for (int i = 0; i < 7; i++) {
            if (num / order[i] < 0) continue;
            if (num / order[i] == 4) {
                s = s + k[order[i]] + k[order[i - 1]];
                num %= order[i];
            }else if (i + 1 < 7 && num / order[i + 1] == 9) {
                s = s + k[order[i + 1]] + k[order[i - 1]];
                num %= order[i + 1]; 
            }else if (num / order[i] < 4){
                for (int j = 0; j < num / order[i]; j++) {
                    s = s + k[order[i]];
                }
                num %= order[i];
            }
        }
        
        return s;
    }
};

另一种简单方法
class Solution {
public:
    string intToRoman(int num) {
        vector<string> roman = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        vector<int> numbers = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
        string rt = "";
        for (int i = 0; i < 13; i++) {
            while (num >= numbers[i]) {
                rt += roman[i];
                num -= numbers[i];
            }
        }
        return rt;
    }
};

3 Sum
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ? b ? c)
  • The solution set must not contain duplicate triplets.
    For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)
----------------------------------------------------------
Solution #1, O(n^2) time, O(n) space.  
Hash first, then find out all possible pairs, then check for existence of the remaining value
Time Limit Exceeded in large test cases, possibly 'cause of sort() and find() functions.
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > result;
        if (num.size() < 3) {
          return result;
        }
        
        unordered_map<int,int> mapping;
        for (int i=0;i<num.size();i++) {
            if (mapping[num[i]] == NULL) {
                mapping[num[i]] = 1;
            }else {
                mapping[num[i]] = mapping[num[i]] + 1;
            }
        }
        
        for (int i=0;i<num.size()-2;i++) {
            for (int j=i+1;j<num.size()-1;j++) {
                int target = -(num[i] + num[j]);
                // check if target exists
                if (mapping[target] != NULL) {
                    // check duplication
                    if ((num[i] == target && mapping[num[i]] == 1)
                      || (num[j] == target && mapping[num[j]] == 1)) {
                          continue;
                    }
                    // check tri-plication  
                    if (num[i] == num[j] && num[i] == target && mapping[num[i]] < 3) {  
                        continue;
                    }
                    vector<int> t = {num[i],num[j],target};
                    sort(t.begin(),t.end());
                    if (find(result.begin(), result.end(), t) == result.end()) {
                        result.push_back(t);
                    }
                }
            }
        }
        return result;
    }
};
Solution #2, O(n^2) time based on 2sum's algorithm
sort first
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int> > result;
        if (num.size() < 3) {
            return result;
        }
        
        sort(num.begin(),num.end());
        for (int i=0;i<num.size()-2;i++) {
            int a = num[i];
            int left = i+1;
            int right = num.size() - 1;
            // 2 sum
            while (left < right) {
                int b = num[left];
                int c = num[right];
                int sum = a + b + c;
                if (sum == 0) {
                    vector<int> t = {a,b,c};
                    if (find(result.begin(), result.end(), t) == result.end()) {
                        result.push_back(t);
                    }
                    right--;
                    left++;
                }else if (sum < 0) {
                    left++;
                }else {
                    right--;
                }
            }
        }
        return result;
    }
};
Update on Sep-10-2014
Solution #3, O(n^2), no need to check for duplicates of vectors
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        vector<vector<int> > rt;
        if (num.size() < 3) return rt;
        sort(num.begin(),num.end());
        
        for (int i = 0; i < num.size() - 2; i++) {
            int end = num.size() - 1;
            int start = i + 1;
            if (i > 0 && num[i] == num[i -1]) {
                continue;
            }
            
            while (start < end) {
                int sum = num[i] + num[start] + num[end];
                if (sum == 0) {
                    vector<int> v;
                    v.push_back(num[i]);
                    v.push_back(num[start]);
                    v.push_back(num[end]);
                    rt.push_back(v);
                    while (num[start] == num[start + 1]) {
                        start++;
                    }
                    while (num[end] == num[end - 1]) {
                        end--;
                    }
                }
                
                if (sum < 0) {
                    start++;
                }else {
                    end--;
                }
            }
        }
        
        return rt;
    }
};

Java
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        
        Arrays.sort(nums);
        List<List<Integer>> rt = new ArrayList<>();
        
        for (int i = 0; i < nums.length - 2; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                if (left > i + 1 && nums[left] == nums[left - 1]) {
                    left++;
                    continue;
                }
                if (right < nums.length - 1 && nums[right] == nums[right + 1]) {
                    right--;
                    continue;
                }
                
                int sum = nums[left] + nums[right] + nums[i];
                if (sum == 0) {
                    List<Integer> r = new ArrayList<>();
                    rt.add(r);
                    r.add(nums[i]);
                    r.add(nums[left]);
                    r.add(nums[right]);
                    left++;
                    right--;
                }else if (sum < 0) {
                    left++;
                }else {
                    right--;
                }
            }
        }
        
        return rt;
    }
}
3Sum Closest
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).

----------------------------------------------------
class Solution {
public:
    int threeSumClosest(vector<int> &num, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int min = INT_MAX;
        int retSum = 0;
        sort(num.begin(),num.end());
        for (int i=0;i<num.size()-2;i++) {
            int a = num[i];
            int left = i+1;
            int right = num.size() - 1;
            // 2 sum
            while (left < right) {
                int b = num[left];
                int c = num[right];
                int sum = a + b + c;
                int dif = abs(sum - target);
                if (dif < min) {
                    min = dif; 
                    retSum = sum;
                }
                if (sum > target) {
                    right--;
                }else {
                    left++;
                }
            }
        }
        return retSum;
    }
};

No comments:

Post a Comment