算法刷题训练营(三)
题目一:
上面这种利用lambad表达式进行sort自定义的方法要掌握,面试的时候可没有时间让你自己试。。。。。
如果想从小到大排,就顺序<,从大到小排就顺序>。可以把两个参数的位置看成定死的。
sort(job.begin(), job.end(), [](const Job& job1,const Job& job2)
{
return job1.hard != job2.hard ? job1.hard < job2.hard : job1.money>job2.money;
});
return job;
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#include<numeric>
using namespace std;
class Job
{
public:
int hard;
int money;
Job(int h,int m):hard(h),money(m){}
friend ostream& operator<<(ostream& os, const Job& job1)
{
os << "(" << job1.hard << "," << job1.money << ")" << endl;
return os;
}
};
vector<int> getMoney(vector<Job>& job, vector<int>& ability)
{
//难度是从小到达,同级别内报酬是从大到小的。
sort(job.begin(), job.end(), [](const Job& job1,const Job& job2)
{
return job1.hard != job2.hard ? job1.hard < job2.hard : job1.money>job2.money;
});
for (auto o : job)
{
cout << o << endl;
}
//难度为key的工作,最优钱数是多少,有序表。
map<int, int> a;
//a.insert(pair<int,int>(job[0].hard, job[0].money));
a[job[0].hard] = job[0].money;
Job pre = job[0];
int n = job.size();
for (int i = 1; i < n; i++)
{
if (job[i].hard != pre.hard && job[i].money > pre.money)
{
pre = job[i];
a.insert(pair<int,int>(pre.hard, pre.money));
}
}
vector<int> ans;
for (uint32_t i = 0; i < ability.size(); i++)
{
/*
if (a.count(ability[i]) > 0)
{
ans[i] = a[ability[i]];
}
else
{
ans[i] = 0;
}
*/
int maxa = 0;
for (auto it = a.begin(); it != a.end(); it++)
{
if (ability[i] >= (*it).first)
{
maxa = max(maxa, (*it).second);
}
}
ans.push_back(maxa);
}
return ans;
}
int main()
{
vector<Job> job = { Job(1,2),Job(1,1),Job(2,6),Job(1,5),Job(3,2),Job(4,8),Job(3,7),Job(4,6) };
vector<int> ability = {0,1,2,3,4,5,6,7};
vector<int> aa = getMoney(job, ability);
for (auto a : aa)
{
cout <<a<< endl;
}
system("pause");
return 0;
}
题目二
#include<iostream>
#include<vector>
using namespace std;
// 从左往右的经典模型
// 还剩的容量是rest,arr[index...]自由选择,
// 返回选择方案
// index : 0~N
// rest : 0~w
int process(vector<int>& arr, int index, int rest)
{
if (rest < 0)
{
//没有容量了
//-1 无方案的意思
return -1;
}
//rest>=0;
if (index == arr.size())
{
//无零食可选
return 1;
}
// rest >=0
// 有零食index
// index号零食,要 or 不要
// index, rest
// (index+1, rest)
// (index+1, rest-arr[i])
int next1 = process(arr, index + 1, rest);//不选择当前位置;
int next2 = process(arr, index + 1, rest - arr[index]);//要
return next1 + (next2 == -1 ? 0 : next2);
}
int way(vector<int>& arr, int w)
{
process(arr, 0, w);
}
int way1(vector<int>& arr, int w)
{
int n = arr.size();
vector<vector<int>> dp(n + 1, vector<int>(w + 1));
for (int j = 0; j <= w; j++)
{
dp[n][j] = 1;
}
for (int i = n - 1; i >= 0; i--)
{
for (int j = 0; j <= w; j++)
{
dp[i][j] = dp[i + 1][j] + ((j - arr[i] >= 0) ? dp[i + 1][j - arr[i]] : 0);
}
}
return dp[0][w];
}
int ways3(vector<int>& arr, int w)
{
int n = arr.size();
vector<vector<int>> dp(n, vector<int>(w + 1));
for (int i = 0; i < n; i++)
{
dp[i][0] = 1;
}
if (arr[0] <= w)
{
dp[0][arr[0]] = 1;
}
for (int i = 1; i < n; i++)
{
for (int j = 1; j <= w; j++)
{
dp[i][j] = dp[i - 1][j] + ((j - arr[i]) >= 0 ? dp[i - 1][j - arr[i]] : 0);
}
}
int ans = 0;
for (int j = 0; j <= w; j++)
{
ans += dp[n - 1][j];
}
return ans;
}
题目三
#include<iostream>
#include<vector>
using namespace std;
int minPathSum(vector<vector<int>>& matrix)
{
int m = matrix.size();
int n = matrix[0].size();
if (m == 0 || n == 0)return 0;
vector<vector<int>> dp(m, vector<int>(n));
dp[0][0] = matrix[0][0];
for (int i = 1; i < m; i++)
{
dp[i][0] = dp[i - 1][0] + matrix[i][0];
}
for (int j = 1; j < n; j++)
{
dp[0][j] = dp[0][j - 1] + matrix[0][j];
}
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j];
}
}
return dp[m - 1][n - 1];
}
int minPathSum2(vector<vector<int>>& matrix)
{
int m = matrix.size();
int n = matrix[0].size();
int more = max(m, n);
int less = min(m, n);
bool rowmore = more == m;
vector<int> arr(less);
arr[0] = matrix[0][0];
for (int i = 1; i < less; i++) {
arr[i] = arr[i - 1] + (rowmore ? matrix[0][i] : matrix[i][0]);
}
for (int i = 1; i < more; i++) {
arr[0] = arr[0] + (rowmore ? matrix[i][0] : matrix[0][i]);
for (int j = 1; j < less; j++) {
arr[j] = min(arr[j - 1], arr[j])
+ (rowmore ? matrix[i][j] : matrix[j][i]);
}
}
return arr[less - 1];
}
题目四
#include<iostream>
#include<vector>
using namespace std;
// str1[0....i1] 与 str2[0......i2]的最长公共子序列长度是多少?
int process(string str1, int i1, string str2, int i2)
{
if (i1 == 0 && i2 == 0)
{
return str1[i1] == str2[i2] ? 1 : 0;
}
//i1和i2不同时为0
if (i1 == 0)
{
return ((str1[i1] == str2[i2]) || process(str1, i1, str2, i2 - 1) == 1) ? 1 : 0;
}
if (i2 == 0)
{
return ((str1[i1] == str2[i2]) || process(str1, i1 - 1, str2, i2) == 1) ? 1 : 0;
}
//i1和i2都不是0;
//最长公共子序列结尾好,不是以str1[i1]与str2[i2]结尾的。
int p1 = process(str1, i1 - 1, str2, i2 - 1);
int p2 = process(str1, i1, str2, i2 - 1);
int p3 = process(str1, i1 - 1, str2, i2);
int p4 = 0;
if (str1[i1] == str2[i2])
{
p4 = p1 + 1;
}
return max(max(p1, p2), max(p3, p4));
}
int lcs(string s1, string s2)
{
int m = s1.size();
int n = s2.size();
return process(s1, m - 1, s2, n - 1);
}
上面的递归改动态规划
//上面的递归改动态规划
int dp(string s1, string s2)
{
int m = s1.size();
int n = s2.size();
vector<vector<int>> dp(m, vector<int>(n));
dp[0][0] = s1[0] == s2[0] ? 1 : 0;
for (int i = 1; i < m; i++)
{
dp[i][0] = s1[i] == s2[0] ? 1 : dp[i - 1][0];//dp表第一列的元素
}
for (int j = 1; j < n; j++)
{
dp[0][j] = s1[0] == s2[j] ? 1 : dp[0][j - 1];//dp表第一行的元素
}
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if (s1[i] == s2[j])
{
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
}
}
}
return dp[m - 1][n - 1];
}
题目五
#include<iostream>
#include<vector>
using namespace std;
//dp表的含义是s1以i位置结尾,s2以j位置结尾,最长公共子串的长度。
vector<vector<int>> getdp(string s1, string s2)
{
int m = s1.size();
int n = s2.size();
vector<vector<int>> dp(m, vector<int>(n));
for (int i = 0; i < m; i++)
{
if (s1[i] == s2[0])
{
dp[i][0] = 1;
}
}
for (int j = 1; j < n; j++)
{
if (s1[0] == s2[j])
{
dp[0][j] = 1;
}
}
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
if (s1[i] == s2[j])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
}
}
return dp;
}
string lcst1(string s1, string s2)
{
int m = s1.size();
int n = s2.size();
if (m == 0 || n == 0)return "";
vector<vector<int>> dp = getdp(s1, s2);
int end = 0;
int maxa = 0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (dp[i][j] > maxa)
{
end = i;
maxa = dp[i][j];
}
}
}
return s1.substr(end - maxa + 1, maxa);
}
string lcst2(string s1, string s2)
{
int m = s1.size();
int n = s2.size();
if (m == 0 || n == 0)return "";
int row = 0; // 出发点的行号
int col = n - 1; // 出发点的列号
int max = 0;
int end = 0;
while (row < m) {
int i = row;
int j = col;
int len = 0;
// 向右下方移动的这一轮
while (i < m && j < n) {
if (s1[i] != s2[j]) {
len = 0;
}
else {
len++;
}
// len
if (len > max) {
end = i;
max = len;
}
i++;
j++;
}
if (col > 0) {
col--;
}
else {
row++;
}
}
return s1.substr(end - max + 1, max);
}
题目六
// version 1: map+sort
class Node {
public:
int time;
string word;
Node(int _time, string _word) {
time = _time, word = _word;
};
bool operator < (const Node& obj) const {
return time > obj.time || time == obj.time && word < obj.word;
}
};
class Solution {
public:
/**
* @param words an array of string
* @param k an integer
* @return an array of string
*/
vector<string> topKFrequentWords(vector<string>& words, int k) {
int n = words.size();
map<string, int> mp1;
map<string, int>::iterator it1;
for (int i = 0; i < n; ++i) {
if (mp1.find(words[i]) == mp1.end())
mp1[words[i]] = 1;
else
mp1[words[i]] += 1;
}
vector<Node> p;
for (it1 = mp1.begin(); it1 != mp1.end(); it1++)
p.push_back(Node(it1->second, it1->first));
sort(p.begin(), p.end());
vector<string> result;
for (int i = 0; i < k; ++i)
result.push_back(p[i].word);
return result;
}
};
可以使用哈希表加堆来进行操作
// version 2: map+heap
class Node1 {
public:
string s;
int cnt;
Node1(const string s, int cnt)
: s(s)
, cnt(cnt)
{}
bool operator < (const Node1& rhs) const {
return cnt < rhs.cnt ||
(cnt == rhs.cnt && s > rhs.s);
}
};
class Solution {
public:
/**
* @param words: an array of string
* @param k: An integer
* @return: an array of string
*/
vector<string> topKFrequentWords(vector<string>& words, int k) {
map<string, int> m;
for (const string& i : words) {
if (m.find(i) == m.end())
m[i] = 1;
else
m[i]++;
}
priority_queue<Node1> heap;
for (auto i = m.begin(); i != m.end(); i++)
heap.push(Node1(i->first, i->second));
vector<string> result;
for (int i = 0; i < k; i++) {
result.push_back(heap.top().s);
heap.pop();
}
return result;
}
};
题目七:
#include<iostream>
#include<set>
#include<map>
#include<vector>
using namespace std;
map<string, int> words;
class cmp {
public:
bool operator () (const string& a, const string& b) {
int a_count = words[a];
int b_count = words[b];
if (a_count != b_count)
return a_count > b_count;
return a < b;
}
};
class TopK {
private:
set<string, cmp> q;
int k;
public:
TopK(int k) {
// initialize your data structure here
this->k = k;
}
void add(string& word) {
// Write your code here
if (words.find(word) == words.end()) {
words[word] = 1;
}
else {
if (q.find(word) != q.end())
q.erase(q.find(word));
words[word] += 1;
}
q.insert(word);
if (q.size() > k)
q.erase(--q.end());
}
vector<string> topk() {
// Write your code here
vector<string> topk;
set<string, cmp>::iterator it = q.begin();
int i = 0;
for (int i = 0; i < k && it != q.end(); ++i, ++it) {
topk.push_back(*it);
}
return topk;
}
};