美团笔试
第一题
给出A,B两国想要的土地,输出只有A国想要的土地数,只有B国想要的土地数,两个国家都想要的土地数。
思路:简单的求交集大小,甚至不用给出交集,先遍历A,用set存下来,再遍历B,遇到set中有的就cnt++,最后输出A-cnt, B-cnt, cnt。
作者:js8544
链接:https://www.nowcoder.com/discuss/500649
来源:牛客网
int n, p, q;
set<int> a;
void solve() {
cin >> n >> p >> q;
for (int i = 0; i < p; i++) {
int x;
cin >> x;
a.insert(x);
}
int cnt = 0;
for (int i = 0; i < q; i++) {
int x;
cin >> x;
if (a.count(x)) cnt++;
}
cout<<p - cnt<<" "<<q - cnt<<" "<<cnt<<endl;
}
第二题,
给一串偶数个字符,只有大小写字母,求修改多少个字母可以让大小写数量相同。
思路:求出大小写个数,相减除以二即可。用islower判断大小写。
int n;
void solve() {
char c;
int l = 0, u = 0;
while (cin >> c) {
if (islower(c)) {
l++;
} else {
u++;
}
}
cout<<abs(l - u) / 2<<endl;
}
第三题
思路:观察到异或的两个性质:1. 可交换 2. 任何数异或自身为零。观察到mod的一个性质:循环。因此我们可以竖着求,而不是横着求。也就是我们遍历j去求,而不是i。
int n;
int pre[100001];
void solve() {
cin >> n;
pre[0] = 0;
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] ^ i;
}
int ans = 0;
for (int i = 1; i <= n; i++) {
ans ^= pre[n % i];
if ((n / i) % 2) {
ans ^= pre[i - 1];
}
}
for (int i = 0; i < n; i++) {
int x;
cin >> x;
ans ^= x;
}
cout << ans << endl;
}
第四题
方法一:
作者:阿康201903182006590
链接:https://www.nowcoder.com/discuss/500551?type=6&channel=666&source_id=discuss_center_discuss_hot
来源:牛客网
import java.util.Scanner;
public class Main4 {
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
while(in.hasNext()){
int n=in.nextInt();
boolean flag=false;
int[] arr=new int[n];
for(int i=0;i<n;i++){
arr[i]=in.nextInt();
}
int empcnt=0;
for(int a:arr){
if(n==2&&a==2){
flag=false;
}
if(a==1){
empcnt++;
}else{
if(a==empcnt+1&&a>2&&a==n){
flag=true;
}
}
}
if(flag==true){
System.out.println("YES");
}else {
System.out.println("NO");
}
}
}
}
方法二:
int n;
int arr[25];
int child[25];
bool dfs(int x, set<int>& can) {
if (x == n) {
for (int i = 0; i < n; i++) {
if (arr[i] != 1 || child[i] == 1) return false;
}
return true;
}
set<int> new_can = can;
if (arr[x] != 1) new_can.insert(x);
for (int i : can) {
if (arr[i] > arr[x]) {
if (arr[i] == arr[x] + 1 && child[i] == 0) continue;
arr[i] -= arr[x];
child[i]++;
if (arr[i] == 1) new_can.erase(i);
if (dfs(x + 1, new_can)) return true;
if (arr[i] == 1) new_can.insert(i);
arr[i] += arr[x];
child[i]--;
}
}
return false;
}
void solve() {
bool flag = true;
REP(i, n) {
cin >> arr[i];
if (arr[i] == 2) {
flag = false;
}
}
if (!flag) {
cout << "NO" << endl;
return;
}
sort(arr, arr + n, greater<int>());
if (arr[0] != n) {
cout << "NO" << endl;
return;
}
set<int> can;
can.insert(0);
memset(child, 0, sizeof(child));
if (dfs(1, can)) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
字节
第一题
- 动态规划。分别计算最后跳1步和跳2步的状态
作者:yuzining
链接:https://www.nowcoder.com/discuss/500713?type=2
来源:牛客网
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
vector<vector<int64_t>> dp(105, vector<int64_t>(2, 0));
dp[0][0] = 1;
for (int i = 1; i < 105; i++) {
dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
if (i >= 2) {
dp[i][1] = dp[i - 2][0];
}
}
int n; cin >> n;
if (n == 0) {
cout << 0 << '\n';
return 0;
}
cout << (dp[n][0] + dp[n][1]) << '\n';
}
- 两次单调栈。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n; cin >> n;
int64_t ans = 0;
vector<int> a(n), l(n, 0);
stack<int> stk;
for (int i = 0; i < n; i++) {
cin >> a[i];
while (!stk.empty() && a[stk.top()] <= a[i]) {
stk.pop();
}
if (!stk.empty()) {
l[i] = stk.top() + 1;
}
stk.push(i);
}
while (!stk.empty()) {
stk.pop();
}
for (int i = n - 1; i >= 0; i--) {
while (!stk.empty() && a[stk.top()] <= a[i]) {
stk.pop();
}
if (!stk.empty()) {
ans = max(ans, (int64_t)(1ll * l[i] * (stk.top() + 1)));
}
stk.push(i);
}
cout << ans << '\n';
}
- 最大子段和。M=1,2直接做;当M>2时,先做两段,如果整段之和大于0,最优解要再加上中间(m-2)段的和
java实现:
作者:OFFER—PLSxD
链接:https://www.nowcoder.com/discuss/500713?type=2
来源:牛客网
import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
int [] arr = new int [n];
int [] L = new int [n]; // L[i] = first j satisfy arr[ j -1 ] > arr[i]
for(int i=0 ; i< n ; i++ ){
arr[i] = sc.nextInt();
}
Deque<Integer> s1 = new LinkedList<>(); // montonic decreasing stack
for(int i = n - 1 ; i >= 0 ; i-- ){
while(!s1.isEmpty() && arr[s1.peek()] < arr[i]){
L[s1.pop()] = i + 1 ; // idx start from 1
}
s1.push(i);
}
long max = 0L;
s1 = new LinkedList<>(); // montonic decreasing stack
for(int i = 0 ; i < n ; i++ ){
while(!s1.isEmpty() && arr[s1.peek()] < arr[i]){
int RR = (i + 1);// idx start from 1
int LL = L[s1.pop()];
max = Math.max ( max , 1L *LL * RR ) ;
}
s1.push(i);
}
System.out.println(max);
}
}
C++实现:
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m; cin >> n >> m;
vector<int> a(n * 2);
int64_t ans = LLONG_MIN, dp = 0, sum = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (dp <= 0) {
dp = a[i];
} else {
dp += a[i];
}
ans = max(ans, dp);
sum += a[i];
}
if (m == 1) {
cout << ans << '\n';
return 0;
}
int64_t link = LLONG_MIN;
for (int i = n; i < 2 * n; i++) {
a[i] = a[i - n];
if (dp <= 0) {
dp = a[i];
} else {
dp += a[i];
}
link = max(link, dp);
}
if (sum > 0) {
link += 1ll * sum * (m - 2);
}
cout << max(link, ans) << '\n';
}
- 差分数组,记录到当前位置上有多少个-1,分别讨论当前位置差分结果为-1,0,1的情况,递推更新答案。要用long long存。
#include <bits/stdc++.h>
using namespace std;
int a[100005], b[100005];
const int64_t MOD = 1e9 + 7;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, w; cin >> n >> w;
bool ok = true;
for (int i = 1; i <= n; i++) {
cin >> a[i];
a[i] = w - a[i];
b[i] = a[i] - a[i - 1];
if (a[i] < 0 || b[i] < -1 || b[i] > 1) {
ok = false;
}
}
b[n + 1] = -a[n];
if (b[n + 1] < -1 || b[n + 1] > 1) {
ok = false;
}
if (!ok) {
cout << "0\n";
return 0;
}
int64_t ans = 1;
for (int i = 1; i <= n + 1; i++) {
if (b[i] == 0 || b[i] == -1) {
ans = (ans * (a[i] + 1)) % MOD;
}
}
cout << ans << '\n';
}