LeetCode 15 - 17

Problem 15 3Sum

在给定的数组中找出三个数,使得其和为0,并且输出所有不重复的组合。
这道题复杂度基本上就是 O(n2) 了,不知道有没有什么好的改进方法。
基本思路就是,先对所有数从小到大排序,选择一个数 ai ,然后在排在它后面的数从头( ajj=i+1 )从尾( akk=size1 )向当中遍历。并且遵守以下规则:
若三数之和等于0,去掉所有重复的;
若三数之和小于0,j++;
若三数之和大于0,k–;

vector<vector<int>> threeSum(vector<int>& nums) {
    vector<vector<int>> result;
    int size = nums.size();
    if (size < 3)
        return result;
    if (size == 3) {
        if (nums[0] + nums[1] + nums[2] == 0)
            result.push_back(nums);
        return result;
    }
    sort(nums.begin(), nums.end());
    for (int i = 0; i < size; i++) {
        int j = i + 1, k = size - 1;
        while (j < k) {
            if (nums[j] + nums[k] == -nums[i]) {
                vector<int> temp = { nums[i],nums[j],nums[k] };
                result.push_back(temp);
                // 去除重复
                while (j < k && nums[j] == nums[j + 1])j++;
                while (j < k && nums[k] == nums[k - 1])k--;
                j++;
                k--;
            }
            else if (nums[j] + nums[k] > -nums[i])
                k--;
            else
                j++;
        }
        while (i < size && nums[i] == nums[i + 1])i++;
    }
    return result;
}

Problem 15 3Sum Closest

这题是上一题的进阶版,这次要求找到与目标数 target 距离最小的三数之和,并且返回三数之和。
基本思路依然先对所有数从小到大排序,选择一个数 ai ,然后在排在它后面的数从头( ajj=i+1 )从尾( akk=size1 )向当中遍历。
若三数之和 == target,直接返回;
若三数之和在 (target - best_diff, target + best_diff) 这个开区间之内,修改best_diff;
若三数之和小于 target,j++;
若三数之和大于 target,k–;

int threeSumClosest(vector<int>& nums, int target) {
    int size = nums.size();
    sort(nums.begin(), nums.end());
    int best_sum = nums[0] + nums[1] + nums[size - 1];
    int best_diff = abs(best_sum - target);
    for (int i = 0; i < size; i++) {
        int left = i + 1, right = size - 1;
        while (left < right) {
            int sum = nums[i] + nums[left] + nums[right];
            if (sum == target)
                return sum;
            if (sum > target - best_diff && sum < target + best_diff) {
                if (sum < target) {
                    best_diff = target - (best_sum = sum);
                }
                else {
                    best_diff = (best_sum = sum) - target;
                }
            }
            if (sum < target) {
                while (left < right && nums[left] == nums[left + 1])
                    left++;
                left++;
            }
            else {
                while (left < right && nums[right] == nums[right - 1])
                    right--;
                right--;
            }
        }
    }
    return best_sum;
}

Problem 17 Letter Combinations of a Phone Number

题目的背景是手机上的九宫格键盘,输入是数字,输出这两个数字可能代表的所有结果。

Input: Digit string “23”
Output: [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]

实际上这道题就是一个排列组合,基本想法就是利用递归来遍历所有可能性。
用 result 来存储所有的结果,用 last_string 来表示上一层递归得到的字符串,用digits 表示当前得到的数字组成的字符串。
首先是递归结束点。当 digits 的长度为 0 的时候,说明没有新的字母能被加进去,那么将 last_string 放入 result 中,退出函数。
其次,考虑每个函数需要完成的工作。获得当前 digits 中第一位字符,遍历它所表达的所有字母,并且每次将这个新的字母放入 last_string,再次调用函数。

vector<vector<char>> digits_num = { {'a','b','c'},{'d','e','f'},{'g','h','i'},{'j','k','l'},{'m','n','o'},{'p','q','r','s'},{'t','u','v'},{ 'w','x','y','z'} };

void recursive_letter(string digits, vector<string>& result, string last_string) {
    int size = digits.size();
    if (size == 0) {
        result.push_back(last_string);
        return;
    }
    vector<char> now = digits_num[digits[0] - '0' - 2];
    size = now.size();
    string last_;
    for (int i = 0; i < size; i++) {
        last_ = last_string;
        last_ += now[i];
        recursive_letter(digits.substr(1), result, last_);
    }
    return;
}
vector<string> letterCombinations(string digits) {
    vector<string> result;
    recursive_letter(digits, result, "");
    if (result[0] == "")
        result.erase(result.begin());
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值