1. 程式人生 > >c/c++筆試中程式設計題總結

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<stack>
void stringZip(const char *pInputStr, long lInputLen, char *pOutputStr)
{
	assert(pInputStr != NULL);
	stack<int> 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<char, int> 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;
}