给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。
你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//优先队列默认是最大堆 维护一个k大根堆 找到第k个最小数组和
class Solution {
public:
vector<vector<int>>temp;
int m, n;
int kthSmallest(vector<vector<int>>& mat, int k) {
temp = mat;
m = mat.size(), n = mat[0].size();
int left = 0, right = 0;
for (int i = 0; i < m; i++) left += mat[i][0], right += mat[i].back();
int init = left;
while (left < right) {
int mid = (left + right) >> 1;
int num = 1;
dfs(mid, 0, init, num, k);
if (num >= k) right = mid;
else left = mid + 1;
}
return left;
}
void dfs(int mid, int index, int sum, int& num, int k) {
if (sum > mid || index == m || num > k) return;
dfs(mid, index + 1, sum, num, k);
for (int i = 1; i < n; i++) {
if (sum + temp[index][i] - temp[index][0] <= mid) {
num++;
dfs(mid, index + 1, sum + temp[index][i] - temp[index][0], num, k);
}
else {
break;
}
}
}
};
int main() {
int m, n, data, k;
vector<vector<int> > mat;//二维数组
cin >> m >> n;
for (int i = 0; i < m; i++)
{
vector<int> row;
for (int j = 0; j < n; j++)
{
cin >> data;
row.push_back(data);
}
mat.push_back(row);
}
cin >> k;
int res = Solution().kthSmallest(mat, k);
cout << res << endl;
return 0;
}
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
#include
#include
#include
using namespace std;
/*
* 数组的第 i 个元素是一支给定股票第 i 天的价格。
你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)
*/
class Solution {
public:
int maxProfit(vector<int>& prices) {
//计算最大利润
//贪心思想:在价格最低的时候买入 在价格最高的时候卖出
//遍历数组,找到最低价格,找到最高价格
//可以完成多笔交易但不可以同时交易
int mprofit = 0;
for (int i = 1; i < prices.size(); i++) {
int temp = prices[i] - prices[i - 1];
if (temp > 0) mprofit += temp;
}
return mprofit;
}
};
int main()
{
int n, data;
vector<int> prices;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> data;
prices.push_back(data);
}
int res = Solution().maxProfit(prices);
cout << res;
return 0;
}
第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。
每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。
返回载到每一个人所需的最小船数。(保证每个人都能被船载)。
#include
#include
#include
using namespace std;
int main() {
//第i个人的体重为people[i] 每艘船可以承载的最大重量为limit
//每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。
//返回载到每一个人所需的最小船数。(保证每个人都能被船载)。
vector<int> people;
int limit=0;
int n=0;
cin >> n;
for (int i = 0; i < n; i++) {
int temp;
cin >> temp;
people.push_back(temp);
}
cin >> limit;//3
sort(people.begin(), people.end());//1 2 2 3 i:0 j:3 ,i:1 j:2
int count = 0;//统计船的个数
int num=people.size();//记录还有几个人
int i = 0;
int j = people.size() - 1;
while (1) {
if (num == 0||num==1) {
break;
}
if (people[i] + people[j] <= limit) {
i++;
j--;
num-=2;
}
else if (people[i] + people[j] > limit) {
j--; //让重量大的单独坐船走
num--;
}
count++;
}
if (num == 0) {
cout << count;
}else if (num == 1) {
cout << count + 1;
}
return 0;
}
给你一个仅包含小写字母的字符串,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
#include
#include
#include
using namespace std;
//给你一个仅包含小写字母的字符串,请你去除字符串中重复的字母,使得每个字母只出现一次。
//需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
int main() {
string s = "";
cin >> s;
string stk;
size_t i = 0;
for (size_t i = 0; i < s.size(); ++i)
{
if (stk.find(s[i]) != string::npos) continue;
while (!stk.empty() && stk.back() > s[i] &&
s.find(stk.back(), i) != string::npos)
stk.pop_back();
stk.push_back(s[i]);
}
cout<<stk;
return 0;
}
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
#include
#include
#include
using namespace std;
//给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
//可以认为区间的终点总是大于它的起点。
//区间[1, 2] 和[2, 3] 的边界相互“接触”,但没有相互重叠。
bool compare(vector<int>& a, vector<int>& b) {
return a[1] < b[1]; // 按照区间结束时间从小到大排序
}
int main() {
int n;
;
cin>>n;
vector<vector<int>> intervals(n, vector<int>(2, 0));
for (int i = 0; i < n; ++i) {
cin>>intervals[i][0]>>intervals[i][1];
}
if (intervals.empty()) {
cout << 0;
return 0;
}
sort(intervals.begin(), intervals.end(), compare);//按照区间结束时间从小到大排序
int count = 1; // 计数器,初始化为1,表示至少需要保留一个区间
int end = intervals[0][1]; // 当前保留第一个区间的结束时间
//从第二个区间开始比较
for (int i = 1; i < intervals.size(); ++i) {
if (intervals[i][0] >= end) {
// 当前区间的起始时间大于等于前一个区间的结束时间,不重叠
count++;
end = intervals[i][1];
}
// 如果重叠,不做任何操作
}
cout<<intervals.size() - count; // 需要移除的区间数量
return 0;
}
给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个子序列,其中每个子序列都由连续整数组成且长度至少为 3 。
一个子序列是从原始数组挑选一部分(也可以全部)元素而不改变相对位置形成的新数组
如果可以完成上述分割,则返回 true ;否则,返回 false 。
#include
using namespace std;
int n;
class Solution {
public:
bool isPossible(vector<int>& nums) {
map<int, int> numCounts, seqCounts; // numCounts用于记录数字的出现次数,seqCounts用于记录当前序列中的数字计数
for (auto num : nums) numCounts[num]++; // 记录所有数字的出现次数
for (auto num : nums) {
if (!numCounts[num]) continue; // 如果这个数已经用完了,就跳过本轮循环
if (seqCounts[num - 1]) { // 如果以num-1结尾的序列存在,就把num加到该序列的末尾
seqCounts[num]++;
seqCounts[num - 1]--;
numCounts[num]--;
} else if (numCounts[num + 1] && numCounts[num + 2]) { // 若num-1的序列不存在,尝试创建以num开头,num+2结尾的新序列
seqCounts[num + 2]++; // 创建一个新序列
numCounts[num]--, numCounts[num + 1]--, numCounts[num + 2]--;
} else {
return false; // 无法形成连续序列
}
}
return true;
}
};
int main() {
cin >> n;
vector<int> numbers; // 将v更改为numbers,以提高变量名的描述性
int value;
for (int i = 0; i < n; i++) {
cin >> value;
numbers.push_back(value);
}
if (Solution().isPossible(numbers)) puts("true");
else puts("false");
return 0;
}
有一个二维矩阵 A ,其中每个元素的值为 0 或 1 。
翻转是指选择任一行或列,并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0。
在做出任意次数的翻转后,将该矩阵的每一行都按照二进制数来解释,矩阵的得分就是这些数字的总和。
返回尽可能高的分数。
#include
#include
#include
#include
#include
using namespace std;
/*有一个二维矩阵 A ,其中每个元素的值为 0 或 1 。
翻转是指选择任一行或列,
并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0。
在做出任意次数的翻转后,将该矩阵的每一行都按照二进制数来解释,矩阵的得分就是这些数字的总和。
返回尽可能高的分数。*/
int main() {
int m, n;
;
cin >> m >> n;
vector<vector<int>> A(m, vector<int>(n));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
cin >> A[i][j];
}
}
if (A.empty())
return 0;
int res = 0;
int row = A.size(), col = A[0].size();
// 逐行判断,将首位为0的行进行翻转操作
for (int i = 0; i < row; ++i) {
if (A[i][0] == 0) {
for (int j = 0; j < col; ++j) {
// 进行翻转操作
A[i][j] = (1 - A[i][j]);
}
}
}
// 从第二列开始逐列判断是否需进行翻转操作,在判断是否
// 需要进行行翻转操作时,保证了第一列必全为1
for (int j = 1; j < col; ++j) {
// 设置变量统计该行0的个数
int cnt = 0;
for (int i = 0; i < row; ++i) {
if (A[i][j] == 0) {
++cnt;
}
}
// 若该列中0个数多余1个数,做列翻转操作
if (cnt > (row - cnt)) {
for (int i = 0; i < row; ++i) {
A[i][j] = (1 - A[i][j]);
}
}
}
// 得最后二进制结果
for (int i = 0; i < row; ++i) {
for (int j = col - 1; j >= 0; --j) {
res += A[i][j] * int(pow(2, col - 1 - j));
}
}
cout<< res;
return 0;
}
给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。
求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。
说明: 请尽可能地优化你算法的时间和空间复杂度。
#include
#include
#include
#include
#include
using namespace std;
class Solution {
public:
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int n1 = nums1.size();
int n2 = nums2.size();
vector<int> res;
for (int i = max(0, k - n2); i <= min(k, n1); i++) {
res = max(res, mergeVector(maxVector(nums1, i), maxVector(nums2, k - i)));
}
return res;
}
private:
vector<int> maxVector(vector<int> nums, int k) {
int drop = (int)nums.size() - k;
vector<int> monDecStk;
for (int num : nums) {
while (drop > 0 && !monDecStk.empty() && num > monDecStk.back()) {
monDecStk.pop_back();
drop--;
}
monDecStk.push_back(num);
}
monDecStk.resize(k);
return monDecStk;
}
vector<int> mergeVector(vector<int> nums1, vector<int> nums2) {
vector<int> res;
while (!nums1.empty() || !nums2.empty()) {
auto& bigger = (nums1 > nums2) ? nums1 : nums2;
res.push_back(bigger[0]);
bigger.erase(bigger.begin());
}
return res;
}
};
/*给定长度分别为 m 和 n 的两个数组,
其元素由 0-9 构成,表示两个自然数各位上的数字。
现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,
要求从同一个数组中取出的数字保持其在原数组中的相对顺序。
求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。
说明: 请尽可能地优化你算法的时间和空间复杂度。*/
int main() {
int m, n, k, data;
vector<int> nums1, nums2;
cin >> m;
for (int i = 0; i < m; i++)
{
cin >> data;
nums1.push_back(data);
}
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> data;
nums2.push_back(data);
}
cin >> k;
vector<int> res = Solution().maxNumber(nums1, nums2, k);
for (int i = 0; i < res.size(); i++)
cout << res[i];
return 0;
}
给定一个已排序的正整数数组 nums,和一个正整数 n 。从 [1, n] 区间内选取任意个数字补充到 nums 中,使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的和来表示。请输出满足上述要求的最少需要补充的数字个数。
#include
#include
#include
#include
#include
using namespace std;
/*给定一个已排序的正整数数组 nums ,和一个正整数 n 。
从 [1, n] 区间内选取任意个数字补充到 nums 中,
使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的和来表示。
请返回 满足上述要求的最少需要补充的数字个数 。*/
int main() {
int m;
cin >> m;
//输入m个整数
vector<int> nums(m);
for (int i = 0; i < m; i++) {
cin >> nums[i];
}
int n;
cin >> n;
// 初始区间为空,表示已经覆盖
long long x = 1;
int index = 0;
int times = 0;
while (x <= n) {
if (index < nums.size() && nums[index] < x) {
x += nums[index++];
}
else if (index < nums.size() && nums[index] == x) {
x += nums[index++];
}
else {
x <<= 1;
times++;
}
}
cout<< times;
return 0;
}
一个整数区间 [a, b] ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b。
给你一组整数区间intervals,请找到一个最小的集合 S,使得 S 里的元素与区间intervals中的每一个整数区间都至少有2个元素相交。
输出这个最小集合S的大小。
#include
#include
#include
#include
#include
using namespace std;
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
// 排序
sort(intervals.begin(), intervals.end(), [](const auto& a, const auto& b) {
return a[1] == b[1] ? (a[0] > b[0]) : (a[1] < b[1]);
});
int e = -1, s = -1, res = 0;
for (auto& interval : intervals) {
if (interval[0] > e) {
e = interval[1];
s = e - 1;
res += 2;
}
else if (interval[0] > s) {
s = e;
e = interval[1];
++res;
}
}
return res;
}
};
int main() {
int m, n, data;
vector<vector<int> > intervals;
cin >> m;
for (int j = 0; j < m; j++)
{
vector<int> aRow;
for (int i = 0; i < 2; i++)
{
cin >> data;
aRow.push_back(data);
}
intervals.push_back(aRow);
}
int res = Solution().intersectionSizeTwo(intervals);
cout << res;
return 0;
}