1、在行列都排好序的矩阵中找指定的数
思路:从右上角或者左下角开始比较,或者用二分查找
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, k;
cin >> n >> m >> k;
vector<int> ans(m);
vector<vector<int>> tmp(n,ans);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> tmp[i][j];
/*if (tmp[i][j] == k) {
cout << "Yes" << endl;
return 0;
}*/
}
}
// cout << "No" << endl;
int i = 0;
int j = m - 1;
while (i < n && j >= 0) {
if (tmp[i][j] == k) {
cout << "Yes" << endl;
return 0;
}
k > tmp[i][j] ? ++i: --j;
}
cout << "No" << endl;
}
二分查找
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, k;
cin >> n >> m >> k;
vector<int> ans(m);
vector<vector<int>> tmp(n,ans);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> tmp[i][j];
/*if (tmp[i][j] == k) {
cout << "Yes" << endl;
return 0;
}*/
}
}
//cout << "No" << endl;
for (int i = 0; i < n; ++i) {
if (binary_search(tmp[i].begin(), tmp[i].end(), k)) {
cout << "Yes" << endl;
return 0;
}
}
cout << "No" << endl;
}
2、最长的可整合子数组的长度
思路:先排序,再动态规划
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> tmp(n);
for (int i = 0; i < n; ++i) {
cin >> tmp[i];
}
sort(tmp.begin(), tmp.end());
vector<int> res(n);
res[0] = 1;
int max = res[0];
for (int i = 1; i < n; ++i) {
if (tmp[i] - tmp[i - 1] == 1) {
res[i] = res[i - 1] + 1;
max = max > res[i] ? max : res[i];
}
else if (tmp[i] - tmp[i - 1] > 1) {
res[i] = 1;
}
}
cout << max << endl;
}
3、不重复打印排序数组中相加和为给定值的所有二元组
思路: 双指针分别指向左右
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> tmp(n);
for (int i = 0; i < n; ++i) {
cin >> tmp[i];
}
int i = 0, j = n - 1;
while (i < j) {
if (tmp[i] + tmp[j] < k)
++i;
else if(tmp[i] + tmp[j] > k)
--j;
else
{
if (i == 0 || tmp[i] != tmp[i-1])
cout << tmp[i] << " " << tmp[j] << endl;
i++;
j--;
}
}
return 0;
}
4、不重复打印排序数组中相加和为给定值的所有三元组
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> tmp(n);
for (int i = 0; i < n; ++i) {
cin >> tmp[i];
}
for (int i = 0; i < n - 2; ++i) {
if (i == 0 || tmp[i] != tmp[i - 1]) {
int j = i + 1;
int t = n - 1;
while (j < t) {
if (tmp[j] + tmp[t] < k - tmp[i])
++j;
else if (tmp[j] + tmp[t] > k - tmp[i])
--t;
else
{
if (tmp[j] != tmp[j - 1])
cout << tmp[i] << " " << tmp[j] << " " << tmp[t] << endl;
j++;
t--;
}
}
}
}
return 0;
}
5、设计getMin功能的栈
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
stack<int> stk;
stack<int> minStk;
for (int i = 0; i < n; ++i) {
string str;
cin >> str;
if (str == "push") {
int tmp;
cin >> tmp;
stk.push(tmp);
if (minStk.size() == 0 || tmp < minStk.top()) {
minStk.push(tmp);
}
else
{
minStk.push(minStk.top());
}
}
else if (str == "pop") {
stk.pop();
minStk.pop();
}
else if (str == "getMin") {
cout << minStk.top() << endl;
}
}
return 0;
}
6、由两个栈组成的队列
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
stack<int> stk1; // 数据栈
stack<int> stk2; // 辅助栈
for (int i = 0; i < n; ++i) {
string str;
cin >> str;
if (str == "add") {
int tmp;
cin >> tmp;
while (!stk2.empty())
{
stk1.push(stk2.top());
stk2.pop();
}
stk1.push(tmp);
}
else if (str == "poll") {
while (!stk1.empty()) {
stk2.push(stk1.top());
stk1.pop();
}
stk2.pop();
}
else if (str == "peek") {
while (!stk1.empty()) {
stk2.push(stk1.top());
stk1.pop();
}
cout << stk2.top() << endl;
}
}
return 0;
}
7、用递归函数和栈逆序一个栈
#include <bits/stdc++.h>
using namespace std;
void dfs(stack<int> &stk1) {
if (stk1.empty()) return;
cout << stk1.top() << " ";
stk1.pop();
dfs(stk1);
}
int main() {
int n;
cin >> n;
stack<int> stk1; // 数据栈
for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp;
stk1.push(tmp);
}
dfs(stk1);
return 0;
}
8、未排序正数数组中累加和为给定值的最长子数组的长度
思路:考虑k = 0, k > 0, k < 0 这三种情况,count = r-l+1;
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> res(n);
for (int i = 0; i < n; ++i) {
cin >> res[i];
}
int count = 0;
int l = 0, r = 0;
while (r < n) {
k -= res[r];
if (k == 0) {
count = count > r - l + 1 ? count : r - l + 1;
k += res[l];
++l;
++r;
}
else if (k > 0) {
++r;
}
else if (k < 0) {
k += res[l] + res[r];
++l;
}
}
cout << count << endl;
return 0;
}
9、未排序数组中累加和为给定值的最长子数组长度
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> res(n);
for (int i = 0; i < n; ++i) {
cin >> res[i];
}
map<int, int> hash;
hash[0] = -1;
int sum = 0;
int max = 0;
for (int i = 0; i < n; ++i) {
sum += res[i];
if (hash.find(sum - k) != hash.end()) {
max = max > i - hash[sum - k] ? max : i - hash[sum - k];
}
if (hash.find(sum) == hash.end()) hash[sum] = i;
}
cout << max << endl;
return 0;
}
10、未排序数组中累加和为给定值的最长子数组系列问题补1
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> res(n);
map<int, int> hash;
int max = 0, count = 0;
hash[0] = -1;
for (int i = 0; i < n; ++i) {
cin >> res[i];
if (res[i] > 0) {
++count;
}
else if (res[i] < 0) {
--count;
}
if (hash.find(count) != hash.end())
max = max > i - hash[count] ? max : i - hash[count];
else
hash[count] = i;
}
cout << max << endl;
return 0;
}
11、未排序数组中累加和为给定值的最长子数组系列问题补2
跟上一题没区别,换了个判断条件
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> res(n);
map<int, int> hash;
int max = 0, count = 0;
hash[0] = -1;
for (int i = 0; i < n; ++i) {
cin >> res[i];
if (res[i] == 1) {
++count;
}
else if (res[i] == 0) {
--count;
}
if (hash.find(count) != hash.end())
max = max > i - hash[count] ? max : i - hash[count];
else
hash[count] = i;
}
cout << max << endl;
return 0;
}
12、换钱的最少货币数
#include <bits/stdc++.h>
using namespace std;
int main() {
//freopen("in", "r", stdin);
int n,V;
cin>>n>>V;
vector<long long> dp(V+1, INT_MAX);
dp[0] = 0;
for(int i = 1;i<=n;i++) {
long long cost;
cin>>cost;
for(int v = cost; v<=V;v++){
dp[v] = min(dp[v - cost] + 1, dp[v]);
}
}
if(dp[V]==INT_MAX) cout<< -1 <<endl;
else cout<<dp[V]<<endl;
return 0;
}
13、用一个栈实现另一个栈的排序
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, x, t;
cin >> n;
stack<int> stk1;
for (int i = 0; i < n; ++i) {
cin >> x;
stk1.push(x);
}
stack<int> stk2;
while (!stk1.empty()) {
x = stk1.top();
stk1.pop();
if (stk2.empty())
stk2.push(x);
else {
t = stk2.top();
while (!stk2.empty() && t > x) {
stk2.pop();
stk1.push(t);
t = stk2.top();
}
stk2.push(x);
}
}
while (!stk2.empty()) {
cout << stk2.top() << " ";
stk2.pop();
}
return 0;
}
14、未排序数组中累加和小于或等于给定值的最长子数组长度
#include <bits/stdc++.h>
using namespace std;
int F(int *a, int n, int x){
int l=0, r=n-1, m, p=-1;
while(l<=r){
m = (l+r)>>1;
if(a[m]>=x){
p = m;
r = m-1;
}else
l = m+1;
}
return p;
}
int main(){
int n, k;
cin>>n>>k;
int a[n];
for(int i=0;i<n;i++)
cin>>a[i];
int b[n+1];
memset(b, 0, sizeof(b));
int s=0, Max=0, t=0, l=0;
b[0] = s;
for(int i=0;i<n;i++){
s += a[i];
b[i+1] = max(b[i], s);
}
s = 0;
for(int i=0;i<n;i++){
s += a[i];
t = F(b, n+1, s-k);
l = (t==-1?0:i-t+1);
Max = max(Max, l);
}
cout<<Max<<endl;
return 0;
}
15、生成窗口最大值数组
// 回头仔细看看
原题链接
思路:使用deque维护最大值,看代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, w;
cin >> n >> w;
vector<int> tmp(n);
for (int i = 0; i < n; ++i) {
cin >> tmp[i];
}
deque<int> dque;
for (int i = 0; i < n; i++) {
while (!dque.empty() && tmp[dque.back()] <= tmp[i])
dque.pop_back();
dque.push_back(i);
if (dque.front() == i - w)
dque.pop_front();
if (i >= w - 1)
cout << tmp[dque.front()] << ' ';
}
return 0;
}
16、求最大子矩阵的大小
思路:依次以矩阵每一行j为底,往j-1结算每一列有多少个连续的1,将结果存在一个数组height[j]。例如以矩阵第三行[1,1,1,1,1]往1,2行结算,可得height[j]={3,1,3,2,2}。对于每次结算得到height[j]数组,们依次求出可以这个height[j]数组中最大矩形的大小maxArea是多少,依次更新这个maxArea,就可以得到结果。
求数组最大矩形大小,我们是利用一个单调栈来实现的。单调栈顾名思义就是栈的元素从栈底到栈顶依次是递增或递减的。利用单调递增栈我们可以求出数组中每一个元素左边离它最近比它小的位置和右边离它最近比它小的位置在哪里。例如对于数组{3,1,3,2,2}对于第一个元素左边离它最近比它小的位置为空,右边离它最近比它小的位置在哪里为1。如何利用单调递增栈实现上述过程呢?在将数组元素压入栈时需要遵循下面的规则:
- 如果当前栈stack为空或者当前数组的元素
height[j]>=height[stack.top()]
(栈顶元素),那么直接把当前元素的位置j压入stack。- 如果当前栈不为空且当前数组元素
height[j]<=height[stack.top()]
(栈顶元素),那么依次从stack弹出元素,并结算栈顶元素为根基,向左和向右分别可以拓展到哪里,则可以得出当前最大子矩阵的大小为多少。结算最大矩阵大小思想如下:
如果当前遍历的元素的元素为i,当前栈顶元素元素为j,弹出栈顶元素后,新的栈顶元素为k。那么现在考虑以元素为j为根基,其向左最左能达到k+1,因为j最左最近小于j的元素应该为k,那么向右最远应该能到i-1,因为j之所以被弹出,就是因为遇到了第一个比位置j值小的位置。所以其最大子矩阵大小结算为
(i-k-1)*height[j].
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> res(m);
vector<vector<int>> tmp(n, res);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> tmp[i][j];
}
}
if (tmp.empty() || tmp[0].empty()) {
cout << 0 << endl;
return 0;
}
vector<int> ans(m, 0); // weishen_=+1
int maxArea = -1;
for (int i = 0; i < n; ++i) {
stack<int> stk;
for (int j = 0; j < m; ++j) {
ans[j] = tmp[i][j] == 0 ? 0 : ans[j] + 1;
// int indexcur = j;
while (stk.size() != 0 && ans[j] <= ans[stk.top()]) {
int indexcur = stk.top();
stk.pop();
int preIndex = stk.empty() ? -1 : stk.top();
int curArea = ans[indexcur] * (j -1- preIndex);
maxArea = maxArea > curArea ? maxArea : curArea;
}
stk.push(j);
}
while (!stk.empty()) {
int indexcur = stk.top();
stk.pop();
int preIndex = stk.empty() ? -1 : stk.top();
int curArea = ans[indexcur] * (m - 1 - preIndex);
maxArea = maxArea > curArea ? maxArea : curArea;
}
}
cout << maxArea << endl;
return 0;
}
17、机器人达到指定位置方法数
思路1: 暴力穷举
#include<bits/stdc++.h>
using namespace std;
int walk(int N, int cur, int rest, int P) {
if (rest == 0) {
return cur == P ? 1 : 0;
}
if (cur == 1) {
return walk(N, 2, rest - 1, P);
}
if (cur == N) {
return walk(N, N - 1, rest - 1, P);
}
// 如果当前位置在中间,可以向左,也可以向右走,总的方法数都要计算
return walk(N, cur - 1, rest - 1, P) + walk(N, cur + 1, rest - 1, P);
}
int ways1(int N, int M, int K, int P) {
if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {
return 0;
}
return walk(N, M, K, P);
}
int main() {
int n, m, k, p;
cin >> n >> m >> k >> p;
if (n < 2 || m < 1 || m > n || k < 1 || p < 1 || p > n) {
cout << 0 << endl;
return 0;
}
int res = ways1(n, m, k, p);
cout << res << endl;
return 0;
}
18、最大值减去最小值小于或等于num的子数组数量
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, num;
cin >> n >>num;
vector<int> res(n);
for (int i = 0; i < n; ++i) {
cin >> res[i];
}
int count = 0;
for (int i = 0; i < n - 1; ++i) {
int min = res[i];
int max = res[i];
for (int j = i + 1; j < n; ++j) {
min = res[j] < min ? res[j] : min;
max = res[j] > max ? res[j] : max;
if (max - min <= num)
++count;
else
break;
}
}
count += n;
cout << count << endl;
return 0;
}
19、换钱的方法数
链接:https://www.nowcoder.com/questionTerminal/39cb6c6e2b844a8cba382c8e26951e0a?f=discussion
来源:牛客网
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9+7;
int main(){
int n, m;
cin>>n>>m;
long a[n], dp[m+1];
memset(dp, 0, sizeof(dp));
for(int i=0;i<n;i++)
cin>>a[i];
dp[0] = 1;
for(int i=0;i<n;i++)
for(int j=a[i];j<=m;j++)
dp[j] = (dp[j]+dp[j-a[i]])%MOD;
cout<<dp[m]%MOD<<endl;
return 0;
}
20、打气球的最大分数
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> a(n+2);
vector<vector<long long>> dp(n+2,vector<long long>(n+2));
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
a[0] = 1;
a[n+1] = 1;
for (int i = 1; i <= n; i++) {
dp[i][i] = a[i-1]*a[i]*a[i+1];
}
for(int i=1;i<n;i++){
for(int j=1;j<=n-i;j++){
for(int k=j;k<=j+i;k++){
dp[j][j+i] = max(dp[j][j+i],a[k]*a[j-1]*a[j+i+1]+dp[j][k-1]+dp[k+1][j+i]);
}
}
}
cout << dp[1][n] << endl;
return 0;
}
21、计算数组的小和
思路:按题意,ac50%,超时
#include<bits/stdc++.h>
#include <time.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> tmp(n);
for (int i = 0; i < n; ++i) {
cin >> tmp[i];
}
vector<int> ans(n);
int sum = 0;
for (int i = 0; i < n; ++i) {
int cnt = 0;
for (int j = 0; j < i; ++j) {
if (tmp[j] <= tmp[i]) cnt += tmp[j];
}
sum += cnt;
}
cout << sum << endl;
return 0;
}
思路:使用归并排序
#include<iostream>
#include<vector>
using namespace std;
long merge(vector<int>& arr, int left, int mid, int right)
{
vector<int> help(right-left+1, 0);
int i = 0;
int p1 = left;
int p2 = mid + 1;
long res = 0;
while (p1 <= mid && p2 <= right)
{
res += arr[p1] <= arr[p2] ? arr[p1]*(right-p2+1) : 0;
help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= mid) help[i++] = arr[p1++];
while (p2 <= right) help[i++] = arr[p2++];
for (int num : help) arr[left++] = num;
return res;
}
long mergeSort(vector<int>& arr, int left, int right)
{
if (left >= right) return 0;
int mid = left + ((right - left) >> 1);
return mergeSort(arr, left, mid) +
mergeSort(arr, mid+1, right) +
merge(arr, left, mid, right);
}
int main()
{
int n;
cin >> n;
vector<int> arr(n, 0);
for (int i=0; i<n; i++) cin >> arr[i];
cout << mergeSort(arr, 0, arr.size()-1);
return 0;
}
22、用栈来求解汉诺塔问题
23、自然数数组的排序
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, x;
cin>>n;
int a[n+1];
for(int i=0;i<n;i++){
cin>>x;
a[x] = x;
}
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
return 0;
}
24、奇数下标都是奇数或者偶数下标都是偶数
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, l=0, r=1;
cin>>n;
int a[n];
for(int i=0;i<n;i++)
cin>>a[i];
while(l<n && r<n){
while(!(a[l]&1))
l+=2;
while(a[r]&1)
r+=2;
if(l<n && r<n)
swap(a[l], a[r]);
}
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
25、最长递增子序列
26、子数组的最大累加和问题
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, x, Max=0;
cin>>n;
for(int i=0,s=0;i<n;i++){
cin>>x;
s += x;
if(s<0)
s = 0;
else
Max = max(Max, s);
}
cout<<Max<<endl;
return 0;
}
27、子矩阵的最大累加和问题
#include <bits/stdc++.h>
using namespace std;
int main(){
int m,n;
cin>>m>>n;
int a[m][n], b[n], s=INT_MIN;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
for(int i=0;i<m;i++){
memset(b, 0, sizeof(b));
for(int j=i;j<m;j++){
for(int k=0;k<n;k++)
b[k] += a[j][k];
for(int k=0,t=0;k<n;k++){
if(k==0 || t<0)
t = b[k];
else
t += b[k];
s = max(s, t);
}
}
}
cout<< s << endl;
return 0;
}