结束了春招面试以后, 发现自己笔试能力太弱.
毕竟连阿里的面试官都说: 你项目经历倒是很丰富, 但是基础能力太弱.
自己开始在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 <= costs.length <= 100
costs.length
为偶数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();
}
};
别人的程序写的还是很优美的. 继续加油学习