c/c++笔试中编程题总结

1.请实现字符串右循环移位函数,比如:“abcdefghi”循环右移2位就是“hiabcdefg”.
函数原型:void RightLoopMove(char *pStr, unsigned short steps)
函数参数说明: pStr: Point to a ‘\0’ terminated string  steps: The rotate shift numbers*/

解法一:常规解法(万不得已时候考虑使用),直接采用指针移动

void _fun(char *pStr, unsigned short steps)
{
	assert(pStr != NULL && steps > 0);
	int n = strlen(pStr);//abcdefghi
	char * p = pStr;     //p指向 abcdefghi
	char *back = (p + n - steps);//back 指向 ghi
	char *temp = (char*)malloc(sizeof(char)*steps + 1);//开辟temp 存取要移动到前面的字符
	strcpy(temp, back);   //先把后面要移动的字符拷贝到temp
	while (p != back)
	{
		for (int i = 0; i < n; ++i)
		{
			*(pStr + steps + i) = *(p + i);
		}
		p++;
	}
	strcpy(pStr, temp);
	free(temp);
}
int main()
{
	char *a = (char *)malloc(sizeof(char) * 20);
	strcpy(a, "abcdefghi");
	char * p = a;
	while (*p != '\0') { cout << *p; p++; }
	cout << endl;
	_fun(a, 2);
	p = a;
	while (*p != '\0') { cout << *p; p++; }
	cout << endl;
	free(a);
	return 0;
}

解法二:采用临时空间来存放一个值,先把最后一个值存放其中,然后整体右移动  时间复杂度为O(n+m)

 

void RightLoopMove(char *pStr, unsigned short steps)
{
	assert(pStr != NULL && steps > 0);
	int str_len = strlen(pStr);
	steps %= str_len;
	char tmp;
	while (steps > 0)
	{
		tmp = *(pStr + str_len - 1);
		for (int i = str_len - 1; i > 0; --i)
		{
			*(pStr + i) = *(pStr + i - 1);
		}
		pStr[0] = tmp;
		steps--;
	}
}

2..功能:实现对一个8 bit数据(unsigned char类型)的指定位(例如第n位)的置0或者置1操作,并保持其他位不变。
函数原型:
 void bit_set(unsigned char *p_data, unsigned char position, bool flag)
 函数参数说明: P_data 是指定的源数据,position是指定位(取值范围1~8);flag表示是置0还是置1操作,true: 置1  flase:置0*/

思路:通过移动1,或等和与等取反(移动后的1)来实现位操作

void bit_set(unsigned char *p_data, unsigned char position, bool flag)
{
	assert(p_data != NULL, position >= 1 && position <= 8);
	//边界值的问题
	/*if (p_data == NULL){}
	if (position < 1 || position >8){}*/
	if (flag)//1
	{
		*p_data |= ((0x01) << (position - 1));
	}
	else //0
	{
		*p_data &= ~((0x01) << (position - 1));

	}
}

3.有一个16位的整数,每4位为一个数,写函数求他们的和。
例如:整数1101010110110111,和 1101+0101+1011+0111 = 13+5+11+7=36*/

方法一:

int fun(unsigned short a)
{
	assert(a <= 65535);
	int x[4] = { 0 };
	int y[4] = { 0 };
	int result = 0;
	x[0] = 15; x[1] = 240; x[2] = 3840; x[3] = 61440;
	for (int i = 0; i < 4; i++)
		y[i] = x[i] & a;
	y[1] >>= 4; y[2] >>= 8; y[3] >>= 12;
	for (int i = 0; i < 4; i++)
		result += y[i];
	return result;
}
int main()
{
	unsigned short a = 54711;
	int b = sum(a);
	cout << b << endl;
	return 0;
}

方法二:

int sum(unsigned short value)
{
	int sum = 0;
	for (int i = 0; i < 4; ++i)
	{
		sum += ((value&(0x0f << i * 4)) >> (i * 4));
	}
	return sum;
}

4.给出unsigned char value, 判断value中的二进制1的个数,要求算法效率尽可能高

方法一:

int main()
{
	unsigned char value = 'A';
	int a[30], i = 0, x = (int)value, y, n = 0;
	while (x != 0)
	{
		y = x % 2;
		a[i] = y;
		i++;
		x = x / 2;
	}
	i--;//按照循环i多加一次,所以要减去一
	for (; i >= 0; --i)
	{
		printf("%d", a[i]);
	}
	cout << endl;
	for (int i = 0; i < 30; ++i)
		if (a[i] == 1)
			n++;
	cout << "value中的二进制1的个数 = " << n << endl;
}

方法二:

int main()
{
	unsigned char v = '15';
	int count = 0;
	while (v)
	{
		count += v & 0x1;
		v >>= 1;
	}
	cout << count << endl;
	return 0;
}

方法三:

int fun(int v)
{
	int count = 0;
	while (v)
	{
		v &= (v - 1);
		count++;
	}
	return count;
}
int main()
{
	int i = fun(100);
	cout << i << endl;
	return 0;
}

5、通过键盘输入一串小写字母(a~z)组成的字符串。请编写一个字符串压缩程序,将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串。
压缩规则:
    1、仅压缩连续重复出现的字符。比如字符串"abcbc"由于无连续重复字符,压缩后的字符串还是"abcbc"。
    2、压缩字段的格式为"字符重复的次数+字符"。例如:字符串"xxxyyyyyyz"压缩后就成为"3x6yz"。
要求实现函数:
     void stringZip(const char *pInputStr, long lInputLen, char *pOutputStr);
    输入pInputStr:  输入字符串lInputLen:  输入字符串长度
    输出 pOutputStr: 输出字符串,空间已经开辟好,与输入字符串等长;
注意:只需要完成该函数功能算法,中间不需要有任何IO的输入输出
示例
    输入:“cccddecc”   输出:“3c2de2c”
    输入:“adef”     输出:“adef”
    输入:“pppppppp” 输出:“8p”

#include
void stringZip(const char *pInputStr, long lInputLen, char *pOutputStr)
{
	assert(pInputStr != NULL);
	stack st;
	long n = strlen(pInputStr);
	const char *p = pInputStr;
	char *out = pOutputStr;
	int count = 1;
	while (*p != '\0')
	{
		if (*p == *(p + 1))
		{
			count++;
		}
		else
		{
			if (count != 1)
			{
				while (count)
				{
					st.push(count % 10);
					count /= 10;
				}
				while (!st.empty())
				{
					*pOutputStr++ = st.top() + '0';
					st.pop();
				}
				
			}
			count = 1;
			*pOutputStr++ = *p;	//cout << *p;//
		}
		*pOutputStr = '\0';
		p++;
	}
}
int main()
{
	const char *str = "cccddecc";
	long n = strlen(str);
	char output[30] = { 0 };
	stringZip(str, n, output);
	/*char *p = output;
	while (p != NULL)
	{
		cout << *p;
		p++;
	}*/
	for (int i = 0; i < 10; i++)
		cout << output[i];
	cout << endl;
	return 0;
}

6、如果一个字符串str, 把字符串str前面任意的部分挪到后面形成的字符串叫做str的旋转词,比如str=”12345”,
str的旋转词有”12345”, ”23451”, “34512”, “45123”, “51234”, 给定两个字符串a和b,请判断a和b是否为旋转词。

int main()
{
	char str[] = "12345";
	char RotatetWord[] = "45123";
	int  count = 0, n = strlen(str) + 1;
	char *temp;
	temp = (char*)malloc(sizeof(char) * 2 * n - 1);
	strcpy(temp, str);
	strcat(temp, str); //tmp 1234512345

	char *T = temp, *R = RotatetWord;
	while (*R != '\0')
	{
		while (*T != '\0')
		{
			if (*R == *T)
			{
				count++;
				R++;
			}
			T++;
		}
	}
	if (count == (n - 1))
	{
		cout << "a是b的旋转词。" << endl;
	}
	else
	{
		cout << "a不是b的旋转词。" << endl;
	}
	return 0;
}

7、给定一个字符类型的数组chas, 请在单词间做逆序调整, 只要做到单词顺序逆序即可,对空格的位置没有特别要求。
  例如:如果把chas看作字符串为“dog  loves  pig”, 调整为 “pig  loves  dog”
        如果把chas看作字符串为 “  I’ m  a  student .  ”  调整为 “student.  a  I’m ” 

void reverse(char *str, int start, int end)
{
	while (start <= end)
	{
		char tmp = str[start];
		str[start] = str[end];
		str[end] = tmp;
		start++;
		end--;
	}
}
void RotateWord(char*str)
{
	if (str == NULL || *str == '\0')
		return;
	int len = strlen(str);
	reverse(str, 0, len - 1);/*先把整个字符串倒过来*/
	/
	int left = 0, right = 0;
	for (int i = 0; i <= len; ++i)
	{
		if (str[i] == ' '|| str[i] == '\0')
		{
			right = i - 1;
			reverse(str, left, right);
			left = i + 1;
		}
	}
}
int main()
{
	char str[] = "dog loves pig";
	RotateWord(str);
	cout << str << endl;
	return 0;
}

8.给定一个字符数组,判断字符数组中是否所有的字符都只出现过一次
根据两个要求,分别实现两个函数。在保证额外空间复杂度为O(1)的前提下,实现时间复杂顿尽量低的方法。

bool oneCharacter(char* str) //char a[] = "awwbc";
{
	int n = strlen(str),i = 0,j=i+1;
	while (*str != '\0')
	{
		while(*(str+j) !='\0')
		{
			if (*(str) == *(str + j))
			{
				return false;
			}
			++j;
		}
		j = i+1;
		++i; 
		++str;
	}
	return true;
}
int main()
{
	char a[] = "awwbc";
	bool result = oneCharacter(a);
	cout << result << endl;
	return 0;
}

9.给定一个字符串str, 返回str的最长无重复字符子串的长度;
例如:str=”abcd” ,返回 4  str=”aabcb”, 最长无重复字符子串为“abc”, 返回3

int lengthOfLongestSubstring(string s) {
	// write your code here  
	int ret = 0;
	map m;
	int start = 1;
	for (int i = 1; i <= s.length(); i++)
	{
		char c = s[i - 1];
		if (m[c] >= start)
		{
			start = m[c] + 1;
			m[c] = i;

		}
		else
		{
			m[c] = i;
			ret = max(ret, i - start + 1);
		}

	}
	return ret;
}

int main()
{
	char str[] = "aabcb";
	int i = lengthOfLongestSubstring(str);
	cout << i << endl;
	return 0;
}

10.请编写函数实现,找出一个字符数组中第一个只出现一次的字符。

void Judge(char *str)
{
	assert(str != NULL);
	int i;
	int pindu = 256;
	int Index = 23;
	int cnt = 0;
	int Count[256] = { 0 };
	int sequence[256] = { 0 };
	for (i = 0; str[i] != '\0'; i++)
	{
		Count[(int)(*(str + i))] ++;
		sequence[(int)(*(str + i))] = cnt++;
	}
	for (i = 0; i < 256; i++)
	{
		if (Count[i] == 1)
		{
			if (sequence[i] < pindu)
			{
				pindu = sequence[i];
				Index = i;
			}
		}
	}
	cout << "数组下标为:" << pindu << endl;
	cout << "第一次只出现一次的字符为: " << str[pindu] << endl;
}
int main()
{
	char str[] = "aaaaaassssssbsssddggaafewfasfwefewwffadaccbeez"; //qwertyuiqwer
	Judge(str);
	return 0;
}

 

你可能感兴趣的:(c/c++笔试中编程题总结)