18年拼多多学霸批算法笔试

1. 数组的山谷是指数组A里面的一个连续子数组B满足:

1) B.length>=3

2) 存在i,有B[i]左边的值比它小,右边的值比它大

现给出一个数组A,找出其中的最长山谷,有就输出其长度,没有就输出为0;

输入为一个数组A; 输出为山谷的长度。

分析:

这个题只需要从左往右查找,注意边界处理即可

#include<iostream>
#include <string>
#include <vector>
using namespace std;

int main()
{
	int m;
	vector<int> vi;
	while (cin >> m)
	{
		vi.push_back(m);
	}
	int len = vi.size();
	int  idown=1;
	int  iup=1;
	int maxlen = 0, re = 0;
	for (int i = 1; i < len; i++)
	{
		if (iup == 1)
		{
			if (vi[i] < vi[i - 1])
			{
				idown++;
			}
			else if (vi[i]==vi[i-1])
			{
				iup = 1;
				idown = 1;
				maxlen = 0;
			}
			else
			{
				maxlen += idown;
				iup++;;
			}
		}
		else
		{
			if (vi[i] > vi[i- 1])
			{
				iup++;;
			}
			else if (vi[i] == vi[i- 1])
			{
				maxlen += (iup-1);
				if (re < maxlen)
					re = maxlen;
				iup = 1;
				idown = 1;
				maxlen = 0;
			}
			else
			{
				maxlen += (iup - 1);
				if (re < maxlen)
					re = maxlen;
				iup = 1;
				idown =2;
				maxlen = 0;
			}
		}
			
	}
	cout << re << endl;
	system("pause");
	return 0;
}

 

2、给定一个字符串S,求出通过循环构造出S的最短字符串P;

输入:输入只包含一个用例,字符串S:abcabc

输出:最短字符串P :abc

分析:

这个题开始看到后想用最长重复子串来做,后来感觉实在不太好做,后来想想还是平移字符串的方式强行解,也即是若是循环平移k个单位,前后字符串相同,这是平移的是最短字符串。

#include<iostream>
#include <string>
#include <vector>
using namespace std;

int main()
{
	string str;
	cin >> str;
	string s1(str);
	int i = 0;
	for (i = 0; i < str.size(); i++)
	{
		s1 += str[i];
		s1.erase(s1.begin());
		if (s1 == str) break;
	}
  if(i==str.size())
  {
		i = 0;
  }
	cout << ++i << endl;
	system("pause");
	return 0;
}

3、这个题是lintcode原题,题号797,到达一个数字,这里就不赘述了。

4、靓号问题

描述:手机号码0-9,一个手机号码至少有K位数相同则为靓号,若修改号码中的一个数字需要的金额为新数字与旧数字的差值(绝对值),问给出一个号码,改成靓号需要多少钱。

分析:

      这个题想来想去还是只能暴力解:

1)求出替换成0-9个数为k时需要的花费,在附近像两边逐渐扩散找,比如3,可以先找4和2,找完了找3和5。

2)找出花费最小的并且替换成号码

代码如下:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{

	int  m = 0, K = 0;
	cin >> m >> K;
	vector<int> vi;
	vector<int> vnum(10, 0);

	string s;
	getline(cin, s);
	s.clear();
	cin >> s;
	for (int i = 0; i < m; i++)
	{
		int si = int(s[i] - '0');
		vi.push_back(si);
		vnum[si]++;
	}
	vector<vector<int>> cl(10, vector<int>(10, 0));
	vector<int> mCost(10, 0);
	for (int i = 0; i < 10; i++)
	{
		int num = K - vnum[i];
		if (num <= 0) {
			cl[i][i] = 0; break;
		}
		int flag = -1;
		while (num > 0)
		{
			if (i + flag >= 0)
			{
				num = num - vnum[i + flag];
				if (num <= 0) {
					mCost[i] += abs(flag)*(num + vnum[i + flag]);
					cl[i][i + flag] = num + vnum[i + flag]; break;
				}
				mCost[i] += abs(flag)*vnum[i + flag];
				cl[i][i + flag] = vnum[i + flag];
			}
			flag = -flag;
			if (i + flag < 10)
			{
				num = num - vnum[i + flag];
				if (num <= 0) {
					mCost[i] += abs(flag)*(num + vnum[i + flag]);
					cl[i][i + flag] = num + vnum[i + flag]; break;
				}
				mCost[i] += abs(flag)*vnum[i + flag];
				cl[i][i + flag] = vnum[i + flag];
			}
			flag = -(flag + 1);
		}
	}

	int minCost = mCost[0], mini = 0;
	for (int i = 1; i < 10; i++)
	{
		if (minCost > mCost[i])
		{
			minCost = mCost[i];
			mini = i;
		}
	}
	for (int i = 0; i < vi.size(); i++)
	{
		if (cl[mini][vi[i]] != 0)
		{
			cl[mini][vi[i]]--;
			s[i] = mini + '0';
		}
	}
	cout << minCost << endl;
	cout << s << endl;
	vi.clear();
	vnum.clear();
	mCost.clear();
	cl.clear();
	system("pause");
	return 0;
}

这个主要还是自己记录,没有测试用例来测,只是提供一种方法,若有漏洞或好的算法欢迎大神指点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值