LeetCode 之双指针 two pointers

1. 3Sum

Given an array S of n integers, are there elements abc 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)
two pointer scan

遍历数组,双指针维护一个区间进行加和比较。

vector<vector<int> > threeSum(vector<int> &num) {
    vector<vector<int>> result;
    sort(num.begin(),num.end());
    for(int i=0; i<num.size(); i++){
        int target = 0-num[i];
        int start = i+1;
        int end = num.size()-1;
        while(start<end){
            if(num[start]+ num[end] == target){
                vector<int> solution;
                solution.push_back(num[i]);
                solution.push_back(num[start]);
                solution.push_back(num[end]);
                result.push_back(solution);
                start++, end--;
                while(start<end && num[start] == num[start-1]) start++;
                while(start<end && num[end] == num[end+1]) end--;
            }
            else if(num[start] + num[end] >target)
                end--;
            else
                start++;
        }
        while(i<num.size() && num[i] == num[i+1]) i++;
    }
    return result;
}
其中18,19行 去除前后的重复 比如[-2,-2,-2,0,2,3,4,4,4]

26行去除遍历时的重复 比如[2,2,3,3,5]

2. 3Sum Closet

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).

与3Sum 类似,需要加一个记录最小距离的变量

int threeSumClosest(vector<int> &num, int target) {
    int result;
    vector<int> solution;
    sort(num.begin(), num.end());
    int minD = INT_MAX;
    for(int i=0; i<num.size()-2;i++){
        int start = i+1;
        int end = num.size()-1;
        while(start < end){
            int sum = num[i]+num[start]+num[end];
            if(sum == target){
                minD = 0;
                result = sum;
                return result;
            }
            else if(sum<target){
                if(target-sum < minD){
                    minD = target-sum;
                    result = sum;
                }
                start++;
            }
            else{
                if(sum-target < minD){
                    minD = sum-target;
                    result = sum;
                }
                end--;
            }
        }
        while(i<num.size() && num[i] == num[i+1]) i++;
    }
    return result;
}

3. 4Sum

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.

    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)

上述问题其实可以归纳为K sum问题,解题思路都比较相似。

都是要求, N个数字中,找出k个数字之和 == target (去重复)

解法:

排序,头尾两指针扫描找到相应的求和

3sum 可以化成 2sum, 4sum 可以化成3sum

比如:

排好序后数字为a b c d e f g h

先枚举a, 然后再b--h中查询

再枚举b 在c-h中查询

以此类推

这里有一篇博文总结的很好,来自烟客旅人

http://tech-wonderland.net/blog/summary-of-ksum-problems.html


vector<vector<int> > fourSum(vector<int> &num, int target) {
    vector<vector<int>> result;
    sort(num.begin(), num.end());
    for(int i=0; i<num.size();i++){
        int target1 = target- num[i];
        for(int j=i+1; j<num.size();j++){
            int target2 = target1-num[j];
            int start = j+1;
            int end = num.size()-1;
            while(start<end){
                if(num[start]+num[end]==target2){
                    vector<int> solution;
                    solution.push_back(num[i]);
                    solution.push_back(num[j]);
                    solution.push_back(num[start]);
                    solution.push_back(num[end]);
                    result.push_back(solution);
                    start++, end--;
                    while(start<end && num[start] == num[start-1]) start++;
                    while(start<end && num[end] == num[end+1]) end--;
                }
                else if(num[start] + num[end] >target2)
                    end--;
                else
                    start++;
            }
            while(j<num.size() && num[j] == num[j+1]) j++;
        }
        while(i<num.size() && num[i] == num[i+1]) i++;
    }
    return result;
}

4.Add Binary

Given two binary strings, return their sum (also a binary string).

For example,
a = "11"
b = "1"
Return "100".

实现题, 双指针操作,

string addBinary(string a, string b) {
    string result;
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    int maxL = a.size()>b.size() ? a.size() : b.size();
    int carry = 0;
    for(int i=0; i<maxL; i++){
        int la = i<a.size()? a[i]-'0':0;
        int lb = i<b.size()? b[i]-'0':0;
        int sum = (la+lb+carry)%2;
        carry = (la+lb+carry)/2;
        result.insert(result.begin(),sum+'0');
    }
    if(carry == 1)
        result.insert(result.begin(),'1');
    return result;
}

5. Add two numbers

You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8


和 add binary 类似,指针操作不同

v1

ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
    int carry = 0;
    ListNode *result = new ListNode(-1);
    ListNode *head = result;
    ListNode *p1 = l1;
    ListNode *p2 = l2;
    while(p1!=NULL && p2!=NULL){

        int sum = (p1->val+p2->val+carry)%10;
        carry = (p1->val+p2->val+carry)/10;
        ListNode *didgt = new ListNode(sum);
        head->next = didgt;
        head = head->next;
        p1 = p1->next, p2 = p2->next;
    }
    while(p1!=NULL){
        int sum = (p1->val+carry)%10;
        carry = (p1->val+carry)/10;
        ListNode *didgt = new ListNode(sum);
        head->next = didgt;
        head = head->next;
        p1 = p1->next;
    }
    while(p2!=NULL){
        int sum = (p2->val+carry)%10;
        carry = (p2->val+carry)/10;
        ListNode *didgt = new ListNode(sum);
        head->next = didgt;
        head = head->next;
        p2 = p2->next;
    }
    if(carry!=0){
        ListNode *didgt = new ListNode(carry);
        head->next = didgt;
    }
    return result->next;
}


v2

ListNode *addTwoNumbersS2(ListNode *l1, ListNode *l2) {
    int carry = 0;
    ListNode *result = new ListNode(-1);
    ListNode *head = result;
    ListNode *p1 = l1;
    ListNode *p2 = l2;
    while(p1!=NULL || p2!=NULL){
        int av = p1 !=NULL? p1->val :0;
        int bv = p2 !=NULL? p2->val :0;
        int sum = (av+bv+carry)%10;
        carry = (av+bv+carry)/10;
        ListNode *didgt = new ListNode(sum);
        head->next = didgt;
        head = head->next;
        p1 = p1 !=NULL? p1->next:NULL;
        p2 = p2 !=NULL? p2->next:NULL;
    }
    if(carry!=0){
        ListNode *didgt = new ListNode(carry);
        head->next = didgt;
    }
    head = result->next;
    delete result;
    return head;
}

6.Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

int removeElement(int A[], int n, int elem) {
    int cur =0;
    for(int i=0;i<n;i++){
        if(A[i]==elem)
            continue;
        A[cur] = A[i];
        cur++;
    }
    return cur;
}



未完待续

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值