zoukankan      html  css  js  c++  java
  • 3 sum

    3 Sum – leetcode
    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: 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]
    ]
    思路:
    数组三个数相加为0 可以首先枚举第一个数,然后就剩下两个数的和
    (1)首先对数组进行排序(从小到大)
    (2)依次取出第 i 个数(i从0开始),并且不重复的选取(跳过重复的数)
    (3)这样问题就转换为 2 个数求和的问题(可以用双指针解决方法)
    转换为 2 数求和问题
    (1)对数组进行排序(由小到大)O(logn)
    (2)定义两个指针:左指针(left) 和 右指针(right)
    (3)找出固定 left, 此时left所指的位置为数组中最小数,再找到两个数和 不大于 target 的最大 right 的位置
    (4)调整 left 的位置(后移),求解和是否为 target O(n)
    (5)时间复杂度:O(nlogn) + O(n)
    代码如下:

    class Solution {
    public:
        vector<vector<int>> threeSum(vector<int>& nums) {
            //将数组排序,方便计算(从小到大排序)
            sort(nums.begin(), nums.end());
            //数组nums的长度
            int len =nums.size();
            //存储结果集合
            vector<vector<int>> resultVec;
            //找加和为0的值
            for (int i = 0; i < len; ++i){
                if (i == 0 || nums[i] != nums[i-1]){//去除重复
                    // 按照 2 sum的双指针方法来进行计算
                    int left = i + 1;//左指针
                    int right = len - 1;//右指针
                    while (left < right){
                        // 右边界左移(找到和不大于0最大的right)
                        while (left < right && nums[i] + nums[left] + nums[right] > 0) right--;
                        // 添加一组答案
                        if (left < right && nums[i] + nums[left] + nums[right] == 0){
                            vector<int> temp(3);
                            temp[0] = nums[i];
                            temp[1] = nums[left];
                            temp[2] = nums[right];
                            resultVec.push_back(temp);
                //找到一组解后,后移左指针
                            while(left < right && nums[left] == temp[1]) left++;//去重
                        } else {// nums[i] + nums[left] + nums[right] < 0的情况,右移left 增大 nums[left]
                            // 左边界右移
                            left++;
                        }
                    }
                }
            }
            return resultVec;
        }
    };

    拓展 2 数求和代码(返回的是数组中的数值):

    /**
     * (1)对数组进行排序(由小到大)O(nlogn)
     * (2)定义两个指针:左指针(left) 和 右指针(right)
     * (3)找出固定 left, 此时left所指的位置为数组中最小数,再找到两个数和 不大于 target 的最大 right 的位置
     * (4)调整 left 的位置(后移),求解和是否为 target O(n)
     * (5)时间复杂度:O(nlogn) + O(n)
    */
    class Solution {
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            // 排序
            sort(nums.begin(), nums.end());
            //存放结果
            vector<int> vec;
            //定义左右指针
            int left = 0, right = nums.size() - 1;
            //固定left,找到最大right的位置
            while (left < right){
                // 左移right 减小nums[right]的值
                while (left < right && nums[left] + nums[right] > target) right--; 
                if (left < right && nums[left] + nums[right] == target){
                    //将对应的位置保存到结果中
                    vec.push_back(nums[left]);
                    vec.push_back(nums[right]);
                    //只用求出一组解,所以直接退出循环
                    break;
                    /**如果多组解,右移left
                    while(left < right && nums[left] == vec[0]) left++;//防止重复
                    */
                } else {// nums[left] + nums[right] < target的情况下,右移left 增大nums[left] 的值
                    //右移left
                    left++;
                }
            }
            return vec;
        }
    };
    
    不积跬步,无以至千里;不积小流,无以成江海。
  • 相关阅读:
    Java 进制转换
    k-近邻算法实例
    Java JTS & 空间数据模型
    Java中 &&与&,||与|的区别
    http https 区别
    四种DCOM错误的区别,0x80080005 0x800706be 0x80010105 0x
    OPC测试常用的OPCClient和OPCServer软件推荐
    关于TFS2010 远程无法创建团队项目的若干问题总结
    我对NHibernate的感受(4):令人欣喜的Interceptor机制
    我对NHibernate的感受(3):有些尴尬的集合支持
  • 原文地址:https://www.cnblogs.com/xiaocai-ios/p/7779787.html
Copyright © 2011-2022 走看看