Leetcode 第133场周赛 1029 两地调度

结束了春招面试以后, 发现自己笔试能力太弱.

毕竟连阿里的面试官都说: 你项目经历倒是很丰富, 但是基础能力太弱.

自己开始在Leetcode上刷题, 不过最近一直都在做链表的题目... 

也是心血来潮报名了Leetcode的第133场周赛.

截止到目前我只看了第一题和最后一题.考试期间一道题都没做出来.

还要加油!!!!! 

 

原题:

公司计划面试 2N 人。第 i 人飞往 A 市的费用为 costs[i][0],飞往 B 市的费用为 costs[i][1]

返回将每个人都飞到某座城市的最低费用,要求每个城市都有 N 人抵达

示例:

输入:[[10,20],[30,200],[400,50],[30,20]]
输出:110
解释:
第一个人去 A 市,费用为 10。
第二个人去 A 市,费用为 30。
第三个人去 B 市,费用为 50。
第四个人去 B 市,费用为 20。

最低总费用为 10 + 30 + 50 + 20 = 110,每个城市都有一半的人在面试。

 

 

第一题我过的代码:

#include<algorithm>
class Solution {
public:
    
    static bool cmp(vector<int> a, vector<int> b)
    {
	    return a[0] > b[0];
    }
    int twoCitySchedCost(vector<vector<int>>& costs) {
        //vector<vector<int>> temp = costs;
        vector< vector<int> > abc(costs.size(), vector<int>(2) );
        int i=0;
        for(auto j:costs){
            abc[i][0]=abs(j[0]-j[1]);
            abc[i][1]=i;
            ++i;
        }
        //for(auto j:abc)
        //   cout<<j[0]<<" "<<j[1]<<endl;
        //sort(abc.begin(),abc.end(),[](const vector<int> &a, const vector<int> &b) { return a[0] > b[0]; });
        sort(abc.begin(), abc.end(),cmp);
        //cout<<i<<endl;
        //for(auto j:abc)
        //    cout<<j[0]<<" "<<j[1]<<endl;
        int a=i/2,b=i/2;
        int sum=0;
        for(auto j:abc){
        if(i!=0){
            //cout<<costs[j[1]][0]<< "  "<<costs[j[1]][1]<<endl;
            if(costs[j[1]][0]<costs[j[1]][1]){
                if(a>0){a--; sum+=costs[j[1]][0]; 
                        //cout<<"go a"<<sum <<"+="<<costs[j[1]][0]<<endl;
                       }
                else{b--; sum+=costs[j[1]][1]; 
                     //cout<<"a overflow"<<sum <<"+="<<costs[j[1]][1]<<endl;
                    }
            }
            else{
                if(b>0){b--;sum+=costs[j[1]][1]; 
                        //cout<<"go b"<<sum <<"+="<<costs[j[1]][1]<<endl;
                       }
                else{a--; sum+=costs[j[1]][0]; 
                     //cout<<"b overflow"<<sum <<"+="<<costs[j[1]][0]<<endl;
                    }
            }
            i--;
        }
        } 
    return sum;
    }
};

    

总结, 这个题目用了贪心算法. 其实也是不会的, 看了别人的思路, 自己写出来的.

这些cout都是当时的调试信息. 说一下有一个样例我一直没过, 原因是第11行我原来写的是:

vector< vector<int> > abc(100, vector<int>(2) );

这是因为题目里给了个条件:

  1. 1 <= costs.length <= 100
  2. costs.length 为偶数
  3. 1 <= costs[i][0], costs[i][1] <= 1000

导致的结果就是, 当我sort排序时, 打印出来的只有23项(原始数据24项), 结果我打印排序前的数据是24项,

丢的那一项是第八个人, 他去两地的差值为0   [ 0, 8 ] 排序的时候排到了后面, 因为vector初始化默认是0

而网站上的输出又没有那么长, 会显示 ... more xxx lines

然后我就想, 排序的时候能不能只对vector的一部分排序呢? 我搜索了半天没有找到. 

当时尝试多次第二种想法是: 动态的去建立vector<vector<int>>不就可以了吗? 于是便有了上面的答案.

直到事后根据http://www.cplusplus.com/reference/algorithm/sort/

template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

我找到了答案, 当时我一直想初始化一个Iterator, 就用 abc[i] 来初始化, 没有成功, 根据上面网站.

其实也可以这样改: sort( abc.begin(), abc.begin()+i, cmp )

这就是对vector 进行局部排序的方法!!!!! 

 

其实我以前做项目的时候也真的是很少用到STL库, 毕竟以前做单片机什么的很多, 有限的单片机资源, 也不允许去调用STL

感觉自己还是没能从传统C语言的编程思想中走出来, STL又不熟悉. 倒是for(auto i:XXX) 用的很熟, 颇有python的感觉(以前做项目也总是现学现用)

总之自己的程序又臭又长, 贴上几个别人的程序:

这种解法经过大佬讲解, 是垃圾dp, 时间复杂度说是n^2.....

const int INF = 1000000000;
int F[110][110];

class Solution {
public:
    int twoCitySchedCost(vector<vector<int>>& a) {
        int n = a.size();
        for (int i = 0; i <= n; ++ i)
            for (int j = 0; j <= n; ++ j)
                F[i][j] = INF;            //初始化INF, 每一项都是最大值
        F[0][0] = 0;                      //把F[0][0]置为0
        for (int i = 0; i < n; ++ i)      //下面看不懂, 有看懂的大佬, 评论讲解一下呗?
            for (int j = 0; j <= i; ++ j)
            {
                F[i+1][j] = min(F[i+1][j], F[i][j]+a[i][0]);
                F[i+1][j+1] = min(F[i+1][j+1], F[i][j]+a[i][1]);
            }
        return F[n][n/2];
    }
};

大佬说了, 这是最优解法, 时间复杂度nlogn

另外一个:

class Solution {
public:
    int twoCitySchedCost(vector<vector<int>>& costs) {
        sort(costs.begin(),costs.end(),[](vector<int>& a,vector<int>& b){
            return a[0]-a[1]<b[0]-b[1];
        });        
        int N=costs.size()/2;
        int r=0;
        for(int i=0;i<N;i++) r+=costs[i][0];
        for(int j=N;j<2*N;j++) r+=costs[j][1];
        return r;
    }
};
/*
对每一个人 A-B地的费用排序, 负值说明这个人去B地更便宜, 正值说明这个人去A地更便宜
然后再排序a[0]-a[1]<b[0]-b[1]就得到了 从A到B的优先度的排序.
前一半去A, 后一半去B

这种思想通过做差值, 量化了去A或者去B(相对于不去)(正负号代表方向, 值代表代价)所要付出的代价
通过贪心, 减小代价, 达到目的

而我的算法虽然也过了, 但是我量化的是去A(相对于去B)和去B(相对于去A)所要付出的代价
而通过后面的去比较谁大谁小, 不过就是在讨论方向的问题.

*/

再来一个:

大佬说了, 这个也是垃圾算法, n^2

#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define sz(x) ((int)(x).size())
#define all(x) begin(x),end(x)
#define rep(i,l,r) for(int i=(l);i<(r);++i)
#define per(i,l,r) for(int i=(r)-1;i>=(l);--i)
#define dd(x) cout << #x << "=" << x << ", "
#define de(x) cout << #x << "=" << x << endl
//-------


class Solution {
public:
    int twoCitySchedCost(vector<vector<int>>& costs) {
    	int n = sz(costs);
    	vector<int> f(n / 2 + 1, INT_MAX / 2);
    	f[0] = 0;
    	rep(i, 0, n) {
    		int a = costs[i][0], b = costs[i][1];
    		per(j, 0, sz(f)) {
    			f[j] = f[j] + b;
    			if (j) f[j] = min(f[j], f[j - 1] + a);
    		}
    	}
    	return f.back();
    }
};

别人的程序写的还是很优美的. 继续加油学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值