题目1:输入一串字符串,其中有普通的字符与括号组成(包括‘(’、‘)’、‘[’,']'), 要求验证括号是否匹配,如果匹配则输出 0、否则输出 1.
输入示例:
dfa(sdf)df[dfds(dfd)]
输出示例:
0
int match(){
stack<char> s;
char p;
scanf("%c",&p);
while(p!='\n'){
if(p=='('||p=='[')
s.push(p);
else if(p==')'){
if(!s.empty()&&s.top()=='(')
s.pop();
else
return 1;
}
else if(p==']'){
if(!s.empty()&&s.top()=='[')
s.pop();
else
return 1;
}
scanf("%c",&p);
}
if(s.empty())
return 0;
else
return 1;
}
题目2:如果一个字符串可以由某个长度为 k 的字符串重复多次得到,我们说该串以 k 为周期。
例如,abcabcabcabc 以 3 为周期(注意,它也可以 6 和 12 为周期,结果取最小周期 3)。字符串的长度小于等于 100,由调用者保证。
说明: 原型:int GetMinPeriod(char *inputstring); 输入参数:char * inputstring:字符串 返回值:int 字符串最小周期
int GetMinPeriod(char *inputstring){
if(inputstring == NULL)
{
return -1;
}
int size = strlen(inputstring);
int maxPeriod = size / 2;
bool isSucess = true;
for(int i = 1;i <= maxPeriod;++i)
{
isSucess = true;
for(int j = 0;j < i;++j)
{
for(int k = i+j;k < size;k+=i)
{
if(inputstring[j] != inputstring[k])
{
isSucess = false;
break;
}//if
}//for
if(isSucess == false)
{
break;
}
}//for
if(isSucess)
{
return i;
}
}//for
return size;
}
题目3:判断是否为回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1: 输入:121 输出:true 示例 2: 输入:-121 输出:false 解释:从左向右读,为 -121 。从右向左读,为 121- 。因此它不是一个回文数。 示例 3: 输入:10 输出:false 解释:从右向左读,为 01 。因此它不是一个回文数。方法一:可以将该整数转换成字符串,根据字符串的长度奇偶性来确定中间位置,然后首尾进行对比是否是回文数字。此时需要额外空间来存储字符串,然后进行判断 方法二:可以将整数的最后一半数字进行整数反转,然后将反转的部分与数字的前部分进行比较,判断是否是回文数。也可以将整个整数进行反转然后进行比较,但是会发生溢出情况,所以可以选择只反转数字的后半部分,若与前半部分相同则为回文数。 我选择的方案是只对后半部分的数字进行反转,但是反转的停止点是反转的数字是否反转了一半的判断。 根据题目中的描述,若该整数是一个负数那么肯定不是回文数,或者该整数的最后一位为 0 而第一位不为 0 也不可能是回文数,所以可以直接将这两种情况判断返回 false。 此时剩下的普通情况的话,此处分为两种情况,若假设该数字是一个回文数,若是回文数的话,长度又分为奇数和偶数。若该整数长度为奇数的话那么反转一半的标志就是反转的数字与目前剩下的前面的那部分数字相同了,此时应停止反转;若该回文整数长度为偶数的话,我们将中间的那个元素归在反转数字中(例如:12321 我们一直将从 1 一直反转到 3 才停止)此时的话反转后的数字 123 大于了目前剩下的 12 的时候停止反转。 若假设该数字不是一个回文数字,其中若整数长度无论是偶数还是奇数,进行反转的时候,反转的数字和目前前半部分剩下的数字永远不可能相等的,所以停止反转的标志就是当反转的数字大于目前前半部的数字的时候,停止反转。停止反转后,我们只需要将反转的结果和目前剩下的前半部分进行对比就行。在此处,若该数字是回文数的话,长度并且为奇数的时候(之前回文数长度为奇数的时候,我们反转的时候是将中间的那个数字算了进去),所以在最后进行对比的时候,要将反转的数字/10,再与前半部分的数字进行对比才可以,若该回文数长度是偶数的话,只需要将反转数和前半部数字直接对比就可以。而若该数字不是回文数的话,无论是奇数还是偶数长度,它都是不可能满足以上两种可能的,所以若都不满足以上的两种情况的话就说明该数字不是回文数。 下面列出方法二的代码:
class Solution {
public:
bool isPalindrome(int x) {
int sum=0;
if(x<0 || (x/10!=0 && x%10==0))
{
return false;
}
else{
while(x>sum)
{
sum = sum * 10 + x%10;
x = x/10;
}
}
/*若整数为偶数*/
if(sum == x)
{
return true;
}
/*若整数位数为奇数*/
if(sum/10 == x)
{
return true;
}
return false;
}
};
题目4:给定一个包含 n 整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c,使得 a+b+c=0?找出所以满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组,
例如,给定数组 nums = [-1,0,1,2,-1,-4],
满足要求的三元组集合为:
[
[-1,0,1],
[-1,-1,2]
]
题目要求三数之和为零,即:a+b+c=0; 那么若满足 b+c = -a 的话就满足题目的第一个要求啦。假设 - a = tem 那么 b+c=tem 就说明满足条件。这样的话三数之和变成了两数之和,再两个数字和的基础上,只需要找到一个 tem 为定点以后,然后再判断数组中剩下的数字两两相加是否等于 tem 即可。若用暴力求解的话会超出时间限制。此时,假设该数组是一个有序数组(升序)的话,那么我们可以知道,从左到右数字时依次增加的。此时设置索引 left,mid,right,然后以最左边的点为定点(tem),只需要看 nums [mid]+nums [right]+nums [left]?=0 即:nums [mid]+nums [right]=-nums [left] ---> nums [mid]+nums [right]=tem。
而且题目中要求不能重复,那么当 nums [left] 判断后,需要判断之前的 nums [left-1] 和现在的 nums [left] 是否是相同的数字,若是的话,left 继续往后移动,直到移动到不同的数字为止。同理,mid right 也是这样操作。
根据以上两个思路之后,我们知道这个思路是建立在有序数组上的。所以我们首先要将数组进行升序使得为有序数组后再进行之后的操作。
![7f50b072492e0da54653b8bb4199b2e9.png](https://i-blog.csdnimg.cn/blog_migrate/a8273896843a4bd0cae5530aef86b0d3.png)
- 其中,我们知道 a+b+c=0 的话,a+b 要与 c 互为相反数,所以定点 left 只需要在小于等于 0 之前进行循环就可以。
- 其中,right 往小的方向移动,mid 往大的方向移动。所以根据 num [right]+nums [mid] 与 tem 的对比,来移动它们。
- 若 num [right]+nums [mid]
- 若 num [right]+nums [mid]>tem 那么说明等于 tem 的数值范围靠近左边,此时要减小两数之和,right 往左移动。
- 为了减少时间复杂度,可以选择相应的排序算法去实现。
class Solution {
public:
void sort(vector<int>& nums)
{
int temp = 0;
int len = nums.size();
for(int i=0; i
{
for(int j=i+1; j
{
if(nums[i] > nums[j])
{
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
}
vector<vector<int> > threeSum(vector<int>& nums)
{
int len = nums.size()/3 ;
vector <int> vi(3);
vector <vector<int> > arry;
sort(nums);
int right;
int mid;
for(int left=0; (left0); left++)
{
mid = left+1;
right = nums.size()-1;
int tem = 0 - nums[left];
if(left > 0 && nums[left]==nums[left-1])
{
continue;
}
while(mid < right)
{
if(nums[mid] + nums[right] == tem)
{
int m = nums[mid];
int r = nums[right];
vi[0] = nums[left];
vi[1] = nums[mid];
vi[2] = nums[right];
arry.push_back(vi);
while((mid < right) && (nums[++mid]==m))
{
continue;
}
while((mid < right) && (nums[--right]==r))
{
continue;
}
}
else if(nums[mid] + nums[right] > tem)
{
right--;
}
else{
mid++;
}
}
}
return arry;
}
};
题目5:翻译英文数字
例如:
输入:OneTwoThree
输出:123
输入:OneTwoDoubleTwo
输出:1222
输入:1Two2
输出:ERROR
输入:DoubleDoubleTwo
输出:ERROR
有空格,非法字符,两个 Double 相连,Double 位于最后一个单词 都错误。
const string process(const string& s){
const char* num[]={"zero","one","two","three","four","five","six","seven","eight","nine"};
if(s.empty())
return "error";
int i=0;
bool flagDouble=false;
bool flagNumber;
string result;
while(i
flagNumber=false;
if(isalpha(s[i])){//先判断是否是字母
for(int j=0;j<10;j++){//判断数字
if((i+strlen(num[j])-1)strcmp(s.substr(i,strlen(num[j])).c_str(),num[j])){
result+=(char)(j+'0');
i+=strlen(num[j]);
if(flagDouble){//该数字是否需要重复
result+=(char)(j+'0');
flagDouble=false;
}
flagNumber=true;//数字判断成功
break;
}
}
if(!flagNumber&&(i+5)strcmp(s.substr(i,6).c_str(),"double")){//判断double
if(!flagDouble){
flagDouble=true;
i+=6;
}
else//double之前已经出现过
return "error";
}
if(!flagNumber&&!flagDouble)//double和数字都未判读成功
return "error";
}
else
return "error";//非字母
}
if(flagDouble)//防止,double与数字没有匹配,即单个double出现
return "error";
else
return result;
}
int main(int argc, char *argv[])
{
string s;
getline(cin,s);
cout<endl;
}
题目6:背包容量为V,商品数目为N,第i个商品的价值为v[i],第i个商品的体积为v[i],每件商品最多放入一次,,问背包价值最大为多少?
每件商品最多放入一次,因此每件商品都有两种可能,一种是放入,另一种是不放入。
OK, 假设此时我们正要放入第 i 件商品,那么此时背包的价值为多少呢?
细想一下,会发现此时背包的价值完全取决于放不放第 i 件商品,
为了方便,设 dp [i][j] 表示放入第 i 件商品进入背包容量为 j 的价值为 dp [i][j]
1、不放入第 i 件商品。
此时 dp [i][j]=dp [i-1][j];
意思是:在不放入第 i 件商品进入容量为 j 的背包中时,此时背包的价值 dp [i][j] 应该继承放入第 i-1 件商品到容量为 j 的背包时的价值 dp [i-1][j];
2、放入第 i 件商品。
此时 dp [i][j]=dp [i-1][j-w [i]]+value [i];
意思是:当前价值 (f [i][j]) 不是前 i-1 个物品的价值 f [i-1][j],因为你放进去了第 i 件商品,所以这个时候包内的空间就不是 j 了,而应该是 j-c [i],所以说,现在需要继承前 i-1 个物品占用体积为 v-w [i] 时的价值,还需要加上当前物品价值 wi, 所以 f [i][j]=f [i-1][j-c [i]]+value [i]
那么在碰见选择时,我们选择一种可以得到最大背包价值的做法,即放与不放。
此时,dp [i][j]=Max {dp [i-1][j],dp [i-1][j-w [i]]+value [i]}
以上便是动态规划方程的推导过程。
public class Version1 {
public static void main(String[] args) {
int v = 10;
int n = 3;
int[] w = { 3, 4, 5 };
int[] value = { 4, 5, 6 };
System.out.println(getMaxweight(w, value, v, n));//11
}
public static int getMaxweight(int[] w, int[] value, int v, int n) {
int[][] dp = new int[n + 1][v + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= v; j++) {
// 当物品为i件重量为j时,如果第i件的重量(w[i-1])小于重量j时,dp[i][j]为下列两种情况之一:
// (1)物品i不放入背包中,所以dp[i][j]为dp[i-1][j]的值
// (2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以dp[i][j]为dp[i-1][j-w[i-1]]的值加上当前物品i的价值
if (w[i - 1] <= j) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + value[i - 1]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=v;j++){
System.out.print(dp[i][j]+" ");
}
System.out.println();
}
return dp[n][v];
}
}
题目7:在n种物品中选取若干件(同一种物品可多次选取)放在空间为v的背包里,每种物品的体积为w1,w2,…,wn, 与之相对应的价值为v1,v2,…,vn.求解怎么装物品可使背包里物品总价值最大?
首先明白完全背包与 0-1 背包问题的区别 ——–> 完全背包问
题中,每件商品可以放 0 次,1 次,多次。
依然设 dp [i][j] 代表放入第 i 件商品进入容量为 j 的背包时所能得到的背包价值。
那么在放第 i 件商品时:
1、不放。
dp[i][j]=dp[i-1][j];
意思是:在不放入第 i 件商品进入容量为 j 的背包中时,此时背包的价值 dp [i][j] 应该继承放入第 i-1 件商品到容量为 j 的背包时的价值 dp [i-1][j]; 此时,与 0-1 背包一样。
2、放。
dp[i][j]=dp[i][j-w[i]]+value[i];
这是什么意思呢?
如果用的是 dp [i-1][j-w [i]],它的意思是说,只有一件当前商品 i,所以在放入商品 i 的时候需要考虑到第 i-1 个商品在容量为 j-c [i] 时的价值 (f [i-1][j-c [i]]);但是现在有无限件当前商品 i,那么就不用再考虑第 i-1 个物品了,所要考虑的是在当前容量 j 下是否再装入一个商品 i,而 [j-w [i]] 的意思是指要确保 dp [i][j] 至少有一件第 i 件商品,所以要预留 w [i] 的空间来存放一件第 i 种物品。
综上可得到动态规划方程:
dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+value[i]) for(int i = 0 ; i < n ; i ++) { for(int j = 1 ; j <= v ; j++) { if(w[i]<=j) dp[i][j] = max(dp[i-1][j],dp[i][j-w[i]]+value[i]); else dp[i][j]=dp[i-1][j]; } }
0-1 背包:在放入第 i 件商品时,只有放与不放两种选择,此时需考虑放入第 i-1 件商品时的背包价值。
完全背包:在放入第 i 件商品时,因为可以放入多次,此时不用考虑放入第 i-1 商品时的背包价值,应考虑是否可以放入再放入一件商品 i。
题目8:有数量不限的硬币,币值为25分、10分、5分和1分,请编写代码计算n分有几种表示法。
给定一个int n,请返回n分有几种表示法。保证n小于等于100000,为了防止溢出,请将答案Mod 1000000007。
测试样例:
6
返回:
2
这一题和完全背包几乎一模一样,每种硬币都是数量不限的,设 dp [i][j] 为使用第 i 种硬币来表示 j 分时表示法有 dp [i][j] 种,A [i] 是第 i 种硬币的价值。
在使用第 i 种硬币表示 j 分时有两种情况:
1、 A [I]<=j,此时 dp [i][j]=dp [i-1][j]+dp [i][j-A [i]];
意思是:在第 i 种硬币的价值小于 j 分,此时可以选择使用或者不用第 i 种硬币,如果不使用则为 dp [i-1][j], 使用了则是 dp [i][j-A [i]],因此应该为两种情况之和。
2、A [i]>j, 此时 dp [i][j]=dp [i-1][j];
public class YingBiBiaoShi {
public static void main(String[] args) {
System.out.println(countWays(6));
}
public static int countWays(int n) {
int A[] = { 1, 5, 10, 25 }, dp[][] = new int[A.length][n + 1];
for (int j = 0; j <= n; j++) {
dp[0][j] = 1;//初始化
}
for (int i = 1; i < A.length; i++) {
for (int j = 0; j <= n; j++) {
if (A[i] <= j) {
dp[i][j] = (dp[i - 1][j] + dp[i][j-A[i]]) % 1000000007;
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[A.length - 1][n];
}
}
题目9:给定两个非常大的正整数 A 和 B,位数在 50 至 100 之间。求 C=A+B。
输入:
因为 A 和 B 很大,从高位到低位,以字符串的形式输入两行数字 A 和 B。A 和 B 的位数在 50 至 100 之间。
输出:
以字符串形式,输出一行,表示 A 和 B 的和。
样例输入:
11111111111111111111111111111111111111111111111111
22222222222222222222222222222222222222222222222222
样例输出:
33333333333333333333333333333333333333333333333333
#include
#include
using namespace std;
string Add(string a,string b){
int size1 = a.size();
if(size1 == 0){
return b;
}//if
int size2 = b.size();
if(size2 == 0){
return a;
}//if
// 进位
int c = 0,num1,num2,sum;
string result = "";
for(int i = size1 - 1,j = size2 - 1;i >= 0 || j >= 0 || c > 0;--i,--j){
num1 = i >= 0 ? a[i] - '0' : 0;
num2 = j >= 0 ? b[j] - '0' : 0;
sum = num1 + num2 + c;
c = sum / 10;
result.insert(result.begin(),sum % 10 + '0');
}//for
return result;
}
int main(){
string a;
string b;
while(cin>>a>>b){
cout<endl;
}//while
return 0;
}
题目10:按要求分解字符串,输入两个数 M,N;M 代表输入的 M 串字符串,N 代表输出的每串字符串的位数,不够补 0。
例如:输入 2,8, “abc” ,“123456789”,则输出为 “abc00000”,“12345678“,”90000000”
#include
#include
using namespace std;
vector<string> ResolveString(vector<string> vec,int n){
int size = vec.size();
vector<string> result;
if(size == 0 || n <= 0){
return result;
}//if
string str;
int len;
for(int i = 0;i < size;++i){
str = vec[i];
len = str.size();
// 补齐0
for(int j = 0;j < (n - len % n);++j){
str += "0";
}//for
// 分解
int index = 0;
while(index < len){
result.push_back(str.substr(index,n));
index += n;
}//while
}//for
return result;
}
int main(){
int m = 2,n = 8;
vector<string> vec = {"abc","123456789"};
vector<string> result = ResolveString(vec,n);
for(int i = 0;i < result.size();++i){
cout<endl;
}//for
return 0;
}
![99cf8321909122f5686276cb74819a85.png](https://i-blog.csdnimg.cn/blog_migrate/be0369c4d5ac38c8d1809b99dd8db41c.png)
计算机视觉常见面试题型介绍及解答
第一期 | 第二期 | 第三期 | 第四期 | 第五期 |
第六期 | 第七期 | 第八期 | 第九期 | 第十期 | 第11期
腾讯算法工程师笔试真题介绍及解析汇总合集
第一期 | 第二期 | 第三期 | 第四期 | 第五期
阿里算法岗位最新编程题介绍及解析
第一期 | 第二期 | 第三期 | 第四期 | 第五期 | 第六期 | 第七期
华为研发工程师编程题型介绍及解析
第一期 | 第二期 | 第三期
![987997bb9bf8d24fe395ef49b29f5d21.png](https://i-blog.csdnimg.cn/blog_migrate/593dd5c8132bfc877ef4135b05f87591.png)
![66dcfed129420845cb8e0b808515a4c0.png](https://i-blog.csdnimg.cn/blog_migrate/12dbff3474be18a0bb4a7649ba0f8d8c.png)