leetcode NO.888:公平的糖果棒交换

leetcode NO.888

  • 公平的糖果棒交换,题目转自leetcode
    • 使用普通方式寻找合理解
      • 代码解释
        • `vector`是容器,可以理解为一个`数组`。
          • `vector`有一些简单的操作:
        • `unordered_set`
        • 代码中的for语句
        • 主函数
    • 双指针法

公平的糖果棒交换,题目转自leetcode

爱丽丝和鲍勃有不同大小的糖果棒:A[i] 是爱丽丝拥有的第 i 根糖果棒的大小,B[j] 是鲍勃拥有的第 j 根糖果棒的大小。

因为他们是朋友,所以他们想交换一根糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。)

返回一个整数数组 ans,其中 ans[0] 是爱丽丝必须交换的糖果棒的大小,ans[1] 是 Bob 必须交换的糖果棒的大小。

如果有多个答案,你可以返回其中任何一个。保证答案存在。

//来源:力扣(LeetCode)
//链接:https://leetcode-cn.com/problems/fair-candy-swap
//著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

使用普通方式寻找合理解

  1. 记数列A的要交换元素为x,数列B的要交换元素为y
      同时,数列A的和为SumA, 数列B的和为SumB
      则:          SumA-x+y = SumB+x-y
      整理得:(SumB-SumA)/2 = y-x
      (不能调换顺序,不能添加绝对值)

  2. 得出上式后,就可以遍历B数列,找出当y=B[i]时,期待的x。
    如果A中存在x,则直接返回x和y。

代码如下:

#include "iostream"
#include "vector"
#include "unordered_set"
#include "numeric"
using namespace std;

class Solution {
public:
    vector<int> fairCandySwap(vector<int>& A, vector<int>& B) {
        int sumA = accumulate(A.begin(), A.end(), 0);
        int sumB = accumulate(B.begin(), B.end(), 0);
        int delta = (sumA - sumB) / 2;
        unordered_set<int> rec(A.begin(), A.end());     //将A中所有元素浅拷贝入一个新的unsorted_map
        vector<int> ans;                                //不需要静态
        for (auto& y : B) {
            int x = y + delta;
            if (rec.count(x)) {                         //若rec中有x,则返回1
                ans = vector<int>{x, y};
                break;
            }
        }
        return ans;
    }
};

int main(int argc, char const *argv[])
{
    vector<int>a = {1,2};
    vector<int>b = {2,3};
    Solution s;
    vector<vector<int> > c;
    //未结束
    c.push_back(s.fairCandySwap(a,b));
    for (int i = 0; i < c[0].size(); ++i)
    {
        cout<<c[0][i]<<"    ";
    }
    cout<<endl;
    return 0;
}




代码解释

为了让纯新手(完全没有接触过STL的)更快的了解代码中的语句,下面将会结合我自己刚上手的时候的理解来简略地解释代码。高手不喜勿喷。

对于没有学过面向对象的同学,记住先去学面向对象的程序设计。

vector是容器,可以理解为一个数组

vector<int> a;

上面的语句意思是创建了一个int型的vector,对象名为a

vector<vector<int> > a; //注意两个>之间的空格,目的是防止编译器将这个和std的>>搞混
//如果没有空格,就会报错

上述语句的意思是创建了一个二维的int型vector,对象名为a。可以直接看作是二维数组。

vector有一些简单的操作:
  1. 一维vector的push_back()
    下列语句意思是a的尾部加上元素5。也就是使a={}变成a={5}
vector<int> a;
a.push_back(5);
  1. 二维vector的push_back()
    下列语句的意思是把[[2,3],[3,4]]赋值给二维vector a。
vector<vector<int> > a;
vector<int> temp;
temp.push_back(2);
temp.push_back(3);
a.push_back(temp);
temp.push_back(3);
temp.push_back(4);
a.push_back(temp);
  1. accumulate是加和,一般人都能看懂。
    以下语句的意思是从a的开始加到结束,累加初始值为0。
accumulate(a.begin(),a.end(),0);

unordered_set

unordered_set可以直接看成一个无序数组(内含哈希表的迭代器,新手可以完全不用了解这个,因为不了解也可以使用),在代码中,它的目的是查找。比如你想查一个无序数组中有没有值5,则可以使用

set.count(5)

来查找。其中set是一个unsorted_set类型的无序数组,比如{1,6,8,5,3,0,9,3}。这样set.count(5)的意思是:set里有没有5?有的话返回值为1,反之为0。可以作为判断的条件直接使用。

代码中的for语句

如果没有见过这样的语法,你看到以下程序会很困惑

for (auto& y : B){/*语句*/}

这个语法的意思是在B这个数列(vector……)中,从头到尾进行遍历。其中y是B中的元素。
比如:B={1,2,3,4,5}
在第三次循环中,在循环主题中使用到y,y=3。

主函数

新手在看懂leetcode中的解答后,会尝试在自己的IDE中尝试打一遍Solution。但是打完后可能不知道如何测试,因为leetcode并没有给出主函数。再此特地补出主函数。

int main(int argc, char const *argv[])
{
    vector<int>a = {1,2};
    vector<int>b = {2,3};
    Solution s;
    vector<vector<int> > c;
    c.push_back(s.fairCandySwap(a,b));
    for (int i = 0; i < c[0].size(); ++i)
    {
        cout<<c[0][i]<<"    ";
    }
    cout<<endl;
    return 0;
}

主函数中包含了vector的初始化,如何对返回值为vector的函数的处理以及将二维vector的遍历。
s.fairCandySwap(a,b)返回值是一个vector,所以用一个二维的vector将返回值push_back。这样我们就可以把返回值存放在一个有主函数生存期的变量中。



双指针法

在上面的推导中,我们已经得出了以下算式:
(SumB-SumA)/2 = y-x
在普通方法中,是通过遍历y寻找可能的x实现的交换。但是其中包含了查找,时间复杂度会和查找的方式正相关。双指针法给出了另一种从查找方式。
将A和B均从小到大排序。从最小的脚标开始遍历(i=j=0)。
当y-x符合要求,直接输出。
当y-x小于要求,说明y小了(从小到大排序),则j++
当y-x大于要求,说明x小了(从小到大排序),则i++

代码如下:

#include "iostream"
#include "vector"
#include "numeric"
#include "algorithm"
using namespace std;

class Solution {
public:
    vector<int> fairCandySwap(vector<int>& A, vector<int>& B) {
        int sumA = accumulate(A.begin(),A.end(),0);
        int sumB = accumulate(B.begin(),B.end(),0);
        int target = (sumB - sumA)/2;
        sort(A.begin(),A.end());
        sort(B.begin(),B.end());
        vector<int> ans;
        int i = 0;
        int j = 0;
        while(i<A.size()&&j<B.size()){
            int temp = B[j]-A[i];
            if(temp == target){
                ans.push_back(A[i]);
                ans.push_back(B[i]);
                break;
            }
            if(temp < target){
                j++;
            }
            if(temp > target){
                i++;
            }
        }
        return ans;
    }
};


int main(int argc, char const *argv[])
{
    vector<int>a = {1,2};
    vector<int>b = {2,3};
    Solution s;
    vector<vector<int> > c;
    c.push_back(s.fairCandySwap(a,b));
    for (int i = 0; i < c[0].size(); ++i)
    {
        cout<<c[0][i]<<"    ";
    }
    cout<<endl;
    return 0;
}

你可能感兴趣的:(leetcode学习笔记,c++)