《程序员代码面试指南》刷题集合

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值