您的位置:首页 > 职场人生

师兄面试总结编程部分解答之一

2014-08-27 16:21 225 查看
首先感谢朱宏师兄给出的总结,是一些典型的内容。

最近将编程部分看了一遍,并给出了解答,整体内容可能会比较长,可能会分为两到三篇文章里介绍。

一、字符串

1、逆序(百度面试题,要求最小的时间复杂度,个人觉得应该是方法1了)

(1) 双指针头尾互换

(2) 递归互换

(3) STL入栈出栈

void reverse(char *str)
{
int len = strlen(str);
//双指针头尾互换
char tmp;
int start = 0;
int end = len - 1;
while(start < end)
{
tmp = *(str + start);
*(str + start) = *(str + end);
*(str + end) = tmp;
start++;
end--;
}
}


2、回文

(1)一个字符串,补充后面的字符组成回文字符串

//对原始字符串继续补充成回文
char *palindromes(char* str)
{
int len = strlen(str);
char* str2 = new char[len*2];//创建新的数组,用来对元素进行存放
for(int i = 0; i < len; i++)
{
*(str2 + i) = *(str + i);
}
for(int i = 0; i < len; i++)
{
*(str2 + len + i) = *(str + (len - 1 - i));
}
*(str2 + 2*len) = '\0';
return str2;
}

(2)在一个字符串中,找出最长的回文字符串

//找出一个字符串中最长的回文串,符合回文特征的字符子串
//aba & abba均为回文串,这个要首先明确的的一点
void findLongest(char* str)
{
//给出的思路1,是在字符之间插入'#'以统一奇数串和偶数串,均为奇数串
//利用现有最长子串为依据,由回文串的对称性,可以减少不必要的计算,
//具体分析,对称点的最长子串已知,则当前最长子串的最小长度也就可以确定,对称性
int len = strlen(str);
const int lenNew = 2 * len + 1;
char* str2 = new char[lenNew];
int* p = new int[lenNew];
int max = 0;
int id = 0;
for(int i = 0; i < len; ++i)
{
*(str2 + 2 * i) = '#';
*(str2 + 2 * i + 1) = *(str + i);
}
*(str2 + 2 * len) = '#';
//完成插入操作

//进行统计过程
//p[i] 存储以i位置为中心的最长回文子串长度
//max存储当前最优结果,id存储单签最优结果对应的下标
for(int i = 1; i < lenNew; ++i)
{
if (max > i)
p[i] = p[2 * id - i] > max - i ? max - i: p[2 * id - i];//由于关于id对称,已判断的回文部分不需要再次判断,
else
p[i] = 1;

for(;str2[i - p[i]] == str2[i + p[i]]; p[i]++)
;
p[i]--;

if(p[i] > max)
{
max = p[i];
id = i;
}
}
printf("the longest one is %d \n",max);
}

(3)一个字符串中,最多有一个字符出现了奇数次,别的字符都出现了偶数次,要求将这个字符串变成回文字符串(要求最少的交换次数,不能开辟新的存储空间)(百度面试题)

//将原有字符串转换成回文串
//给出的测试字符串最多有一个出现奇数次,其他均出现偶数次,在不开辟新的存储空间的前提下,如何实现
//且交换次数尽可能少
void producePralindroms(char* str)
{
//连续交换,从前向后遍历,并与前面的内容进行比较,如果存在相同则交换到与之对称位置处
//交换的前提条件是对应位置的元素不同,否则,保持原位置继续向后遍历,直至结束
//缺陷,不能够将唯一的奇数元素放到中间位置
//改进,依然是从前向后遍历,在遍历位置,向后遍历到对称位置处,期间存在相同元素,则置换到对称位置,同时跳出内层遍历
//不存在相同元素,则将该元素置换到中间位置,并进行下一轮遍历(新一轮遍历起始位置不变)
int len = strlen(str);
for(int i = 0; i < (len / 2); i++)
{
char cur = *(str + i);
bool change = false;
for(int j = i + 1; j < len - i; j++)
{
if(*(str + j) == cur )
{
//交换
if(j != len - i - 1)
{
char tmp = *(str + j);
*(str + j) = *(str + len - i - 1);
*(str + len - i - 1) = tmp;
}
change = true;
break;
}
}
if(!change)//只有在存在奇数个数元素时,才可能出现这个情况
{
*(str + i) = *(str + len / 2);
*(str + len / 2) = cur;
--i;
}

}
printf("%s\n",str);
}


3、左/右移动K位

(有时间复杂度的限制,要用三次交换法(剑指offer 221页)

//向左或向右移动k位
//利用翻手法则,三次变换即可
//对[start,end]区间进行翻转操作
void reverse(char* start, char* end)
{
//最直接的头尾互换即可
while(start < end)
{
char tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
}
void shiftK(char* str,int k)
{
int len = strlen(str);
char* start = str;
char* middle = str + len - k;
char* end = str + len - 1;
reverse(start,middle - 1);
reverse(middle, end);
reverse(start,end);
printf("%s\n",str);
}

4、itoa

atoi

strcpy

strcat等源代码

char* myitoa(int num, char* str,int radix)
{
char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char* ptr = str;
bool isNegative = false;
if (num < 0)
{
num = -1 * num;
isNegative = true;
}
while(num >= radix)
{
*ptr++ = index[num % radix];
num = num / radix;
}
if(num)
{
*ptr++ = index[num];
}
if(isNegative)
{
*ptr++ = '-';
}
*ptr='\0';
ptr--;
//当前ptr指向内容为num的倒序存在,需要将其进行逆序
char* start = str;
char* end = ptr;
while(start < end)
{
char tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
printf("%s\n",str);
return str;
}
//将string转化为整型输出
int myatoi(const char* str)
{
const char* ptr = str;
int num = 0;
bool isNegative = false;
if(*ptr == '-')
{
ptr++;
isNegative = true;
}
while(*ptr != '\0')
{
int tmp = *ptr++ - '0';
num = num * 10 + tmp;

}
if(isNegative)
{
num = num * -1;
}
printf("%d\n",num);
return num;
}
char* myStrcpy(char* dest, char* src)
{
if(NULL == dest || NULL == src)
return NULL;

char* ret = dest;
while((*dest++ = *src++) != '\0')
;
return ret;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: