C++经典面试算法题

#include <assert.h>
#include <string.h>
#include <stack>

//  
// C++ 经典面试算法题  [7/28/2016 FreeAngel]  

//1.实现strcpy.  
char* MyStrCpy( char *pDest, const char *pSrc )  
{  
	if( nullptr == pDest || nullptr == pSrc )  
	{  
		return nullptr;  
	}  
	if( pDest == pSrc )  
	{  
		return pDest;  
	}  
	char *pIter = pDest;  
	while( ( *pIter++=*pSrc++ ) !='\0' );  
	return pDest;  
}  

//2.实现strcat.  
char* MyStrCat( char *pDest, const char *pSrc )  
{  
	if( nullptr == pDest || nullptr == pSrc )  
	{  
		return nullptr;  
	}  

	char *pIter = pDest + strlen( pDest );  
	while( ( *pIter++=*pSrc++ ) != '\0' );  
	return pDest;  
}  

//3.实现CString字符串类缺省四个方法  
class MyCString  
{  
public:  

	MyCString( char *pData = nullptr )  
	{  
		if( nullptr == pData )  
		{  
			mpData = new char[ 1 ];  
			assert( nullptr != mpData );  
			*mpData = '\0';  
		}  
		else  
		{  
			mpData = new char[ strlen( pData ) + 1 ];  
			assert( nullptr != mpData );  
			strcpy( mpData, pData );  
		}  
	}  

	MyCString( const MyCString &Other )  
	{  
		mpData = new char[ strlen( Other.mpData ) + 1 ];  
		assert( nullptr != mpData );  
		strcpy( mpData, Other.mpData );  
	}  

	~MyCString()  
	{  
		if( nullptr != mpData )  
		{  
			delete [] mpData;  
			mpData = nullptr;  
		}  
	}  

	const MyCString& operator =( const MyCString &Other )  
	{  
		if( this == &Other )  
		{  
			return *this;  
		}  
		delete [] mpData;  
		mpData = new char[ strlen( Other.mpData ) + 1 ];  
		assert( nullptr != mpData );  
		strcpy( mpData, Other.mpData );  
		return *this;  
	}  

private:  

	char *mpData;  
};  

//4.不使用第三个变量交换两个数的值  
void SwapA( int &A, int &B )  
{  
	if( A == B )  
	{  
		return;  
	}  
	A = A + B;  
	B = A - B;  
	A = A - B;  
}  
void SwapB( unsigned int &A, unsigned int &B )  
{  
	if( A == B )  
	{  
		return;  
	}
	A = A ^ B;  
	B = A ^ B;  
	A = A ^ B;  
}  

//5.C语言中字符串转数字的方法是什么( atoi ),请实现它  
int Myatoi( const char *pString )  
{  
	assert( nullptr != pString );  
	const int Len = strlen( pString );  
	int Value = 0;  
	int Times = 1;  
	for( int i = Len -1; i >= 0; --i, Times *= 10 )  
	{  
		Value += ( pString[ i ] - '0' ) * Times;  
	}  
	return Value;  
}  

//6.实现一个将字符串逆序的方法  
char* MyInverted( char *pDest )  
{  
	assert( nullptr != pDest );  
	const int Len = strlen( pDest );  
	char T = 0;  
	for( int i = 0; i < Len / 2; ++i )  
	{  
		T = pDest[ i ];  
		pDest[ i ] = pDest[ Len - i - 1 ];  
		pDest[ Len - i -1 ] = T;  
	}  
	return pDest;  
}  

//7.实现一个将字符串中所有字母转换为大写的方法  
char* MyUpper( char *pDest )  
{  
	assert( nullptr != pDest );  
	for( char *i = pDest; *i != '\0'; ++i )  
	{  
		if( *i < 'a' || *i > 'z' )  
		{  
			continue;  
		}  
		*i -= 'a' - 'A';  
	}  
	return pDest;  
}  

//8.已知一个数组已经降序排序请用二分查字法找到其中的某个元素找到返回索引否则返回-1  
int BinarySearch( int *pArray, int Count, int Value )  
{  
	assert( nullptr != pArray );  
	int Left = 0;  
	int Right = Count -1;  
	int Mid = 0;  
	while( Left <= Right )  
	{  
		Mid = ( Left + Right ) / 2;  
		if( Value < pArray[ Mid ] )  
		{  
			Right = Mid - 1;  
		}  
		else if( Value > pArray[ Mid ] )  
		{  
			Left = Mid + 1;  
		}  
		else  
		{  
			return Mid;  
		}  
	}  
	return -1;  
}  

struct Node  
{  
	Node *mpNext;  
	int mData;  
};
//9.删除链表中值为Value的所有元素( [Head]->[node1]->[node2]->...[noden] )
void DeleteFromList( Node *pHead, int Value )
{
	Node *pPrev = pHead;
	Node *pNext = pHead->mpNext;
	while( nullptr != pNext )
	{
		if( pNext->mData != Value )
		{
			pPrev = pNext;
			pNext = pNext->mpNext;
		}
		else
		{
			pPrev->mpNext = pNext->mpNext;
			delete pNext;
			pNext = pPrev->mpNext;
		}
	}
}  

//10.在链表Index位置插入新的值为Value的元素  
void InsertFromList( Node *pHead, int Index, int Value )  
{
	Node *pIter = pHead;
	for( int i = 0; i < Index && nullptr != pIter; ++i, pIter = pIter->mpNext );
	assert( nullptr != pIter );
	Node *pNew = new Node;
	pNew->mData = Value;
	pNew->mpNext = pIter->mpNext;
	pIter->mpNext = pNew;
}  

//11.将链表逆序  
Node* InvertedFromList( Node *pHead )  
{  
	//A->B->C
	Node *pPrev = pHead;            //A
	Node *pNext = pHead->mpNext;        //B
	Node *pNextNext = nullptr;        //C
	while( nullptr != pNext )  
	{
		pNextNext = pNext->mpNext;    //C = B->C
		pNext->mpNext = pPrev;        //B->A

		pPrev = pNext;                //A = B
		pNext = pNextNext;            //B = C
	}
	pHead->mpNext = nullptr;//C->B->A->null
	return pPrev;            //return C( new head )
}  

//12.判断X年X月X日是这年的第几天  
int GetDay( int Year, int Month, int Day )
{  
	int MonthDays[ 13 ] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  

	if( ( Year % 4 == 0 && Year % 100 != 0 ) || ( Year % 400 == 0 ) )  
	{  
		++MonthDays[ 2 ];  
	}  

	int Days = 0;  
	for( int i = 1; i < Month; ++i )  
	{  
		Days += MonthDays[ i ];  
	}  
	Days += Day;  

	return Days;  
}
//13.求斐波拉契数列第N项
int GetFibonacci1( int N )
{
	if( 1 == N || 2 == N )
	{
		return 1;
	}
	if( 3 == N )
	{
		return 2;
	}
	int A = 2;
	int B = 3;
	int C = 5;
	for( int i = 0; i < N - 4; ++i )
	{
		C = A + B;
		A = B;
		B = C;
	}
	return C;
}

//14.递归求斐波拉契数列数列第N项
int GetFibonacci2( int N )
{
	if( 1 == N || 2 == N )
	{
		return 1;
	}
	return GetFibonacci2( N - 1 ) + GetFibonacci2( N - 2 );
}
//15.实现一个产生[N-M]区间数字的随机方法
int GetRandomRange( int N, int M )
{
	if( N == M )
	{
		return N;
	}
	if( N > M )
	{
		N = N + M;
		M = N - M;
		N = N - M;
	}
	return N + ( rand() % ( M - N + 1 ) );
}

//16.实现一个产生[0~1]之间的随机浮点数
double GetRandomRange()
{
	return rand() / static_cast< double >( RAND_MAX );
}
//17.实现一个打印出1-1000之间的所有素数的方法
void PrintfPrime()
{
	//1不是素数
	//2是最小非奇数素数
	//直接从3开始
	printf( "2\n" );
	bool b = false;
	for( int i = 3; i <= 1000; ++i )
	{
		b = true;
		for( int j = 2; j <= i / 2; ++j )
		{
			if( i % j == 0 )
			{
				b = false;
				break;
			}
		}
		if( b )
		{
			printf( "%d\n", i );
		}
	}
}

//18.已知Z = X + Y 其中 Z, X, Y 均为无符号int型 定义一个宏判断Z是否已经越界
#define IS_OVER_FLOW( Z, X, Y ) ( Z < ( ( X ) < ( Y ) ? ( Y ) : ( X ) ) )

//19.请用栈实现队列
int QueuePop( std::stack< int > &StackA )
{
	std::stack< int > StackB;
	while( false == StackA.empty() )
	{
		StackB.push( StackA.top() );
		StackA.pop();
	}

	const int top = StackB.top();
	StackB.pop();

	while( false == StackB.empty() )
	{
		StackA.push( StackB.top() );
		StackB.pop();
	}
	return top;
}

//20.已知X班X成绩0-100分编写一个方法实现0-59打印不合格,60-69打印合格,70-79打印良好,80-100打印优秀
//不能使用if,:?,switch
void PrintScore( int Score )
{
	assert( Score >= 0 && Score <= 100 );
	const char *pString[] =
	{ 
		"不合格",
		"不合格",
		"不合格",
		"不合格",
		"不合格",
		"不合格",
		"合格",
		"良好",
		"优秀",
		"优秀",
		"优秀",
	};
	printf( "%s\n", pString[ Score / 10 ] );
}
//21.实现strncpy
char *Mystrncpy( char *pDest, const char *pSrc, int Count )
{
	assert( NULL != pDest && NULL != pSrc );
	if( pDest == pSrc )
	{
		return pDest;
	}
	if( Count <= 0 )
	{
		return pDest;
	}
	char *pStart = pDest;
	while( ( Count-- ) > 0 && ( *pStart++=*pSrc++ ) );
	*pStart = '\0';
	return pDest;
} 
//22.C语言中数字转字符串的方法是什么?(itoa)请实现他
char* Myitoa( char *pDest, int val, int radix )
{
	assert( NULL != pDest );
	assert( radix > 1 );
	const bool IsMinu = val < 0;
	char buffer[ 16 ] = {};
	int count = 0;

	do
	{
		buffer[ count++ ] = abs(val) % radix;
		val /= radix;
	}
	while( val );


	if( IsMinu )
	{
		pDest[ 0 ] = '-';
		for( int i = 0; i < count; ++i )
		{
			pDest[ i + 1 ] = '0' + buffer[ count - i - 1 ];
		}
		pDest[ count + 1 ] = '\0';
	}
	else
	{
		for( int i = 0; i < count; ++i )
		{
			pDest[ i ] = '0' + buffer[ count - i - 1 ];
		}
		pDest[ count ] = '\0';
	}
	return pDest;
}
//23.如何判断链表是否有环
bool IsLoop( Node *pHead )
{
	//[H->A->B->C->A]
	assert( NULL != pHead );
	Node *pNext = pHead->mpNext;
	Node *pNextNext = pHead->mpNext;
	while( NULL != pNext && NULL != pNextNext->mpNext )
	{
		pNext = pNext->mpNext;//[ B、C、A ]
		pNextNext = pNextNext->mpNext->mpNext;//[C、B、A]
		if( pNext == pNextNext )
		{
			return true;
		}
	}
	return false;
}
//24.统计出一个字符串每种字母出现的次数要求时间复杂度为O(n)
void CountLetter( const char *pSrc )
{
	int count[ 256 ] = {};
	for( ; *pSrc !='\0'; ++pSrc )
	{
		const char &c = *pSrc;
		if( ( c < 'A' || c > 'z') && ( c < 'a' || c > 'z' ) )
		{
			continue;
		}
		++count[ c ];
	}
} 
//25.选择排序的思想是什么?( 每次找到最大或最小的值放在数组的低位上 )请实现它
void SelectSort( int *pArray, int count )
{
	for( int i = 0; i < count; ++i )
	{
		//默认低位元素最小
		int MinValue = pArray[ i ];
		//默认保存低位元素的索引
		int MinIndex = i;
		//除开第一个元素找是否还有比它还小的元素( 升序 )
		for( int j = i + 1; j < count; ++j )
		{
			//发现找到比它还小的元素重新赋值和保存索引
			if( pArray[ j ] < MinValue )
			{
				MinValue = pArray[ j ];
				MinIndex = j;
			}
		}
		//将找到最小元素放在数组低位上面
		const int Temp = pArray[ i ];
		pArray[ i ] = MinValue;
		pArray[ MinIndex ] = Temp;
	}
}

//26.冒泡排序的思想是什么?(升序排序中越小的数往低位走,越大的数往高位走,每次与相邻元素比较导致的特点)请实现它
void BubbleSort( int *pArray, int count )
{
	//eg.[6][8][8][0][9][1]
	//i = 0,j < 5    [6][8][0][8][1][9]
	//i = 1,j < 4    [6][0][8][1][8][9]
	//i = 2,j < 3    [0][6][1][8][8][9]
	//i = 3,j < 2    [0][1][6][8][8][9]

	//到此为止已经排序OK了
	//i = 4,j < 1    [0][1][6][8][8][9]
	//i = 5,j < 0    [0][1][6][8][8][9]
	for( int i = 0; i < count; ++i )
	{
		for( int j = 0; j < count - i - 1; ++j )
		{
			if( pArray[ j ] > pArray[ j + 1 ] )
			{
				const int Temp = pArray[ j ];
				pArray[ j ] = pArray[ j + 1 ];
				pArray[ j + 1 ] = Temp;
			}
		}
	}
}

//27.已知两个数组有序实现一个方法将他们合并后任然有序
void MergeSort( int *pMerge, int *p1, int p1len, int *p2, int p2len )
{
	assert( nullptr != pMerge && nullptr != p1 && nullptr != p2 );
	int i = 0;
	int j = 0;
	int k = 0;
	while( i < p1len && j < p2len )
	{
		if( p1[ i ] < p2[ j ] )
		{
			pMerge[ k ] = p1[ i ];
			++k;
			++i;
		}
		else
		{
			pMerge[ k ] = p2[ j ];
			++k;
			++j;
		}
	}
	while( i < p1len )
	{
		pMerge[ k ] = p1[ i ];
		++k;
		++i;
	}
	while( j < p2len )
	{
		pMerge[ k ] = p2[ j ];
		++k;
		++j;
	}
}

//28.实现一个算法找到数组中第二大的数
int FindSec( int *p, int len )
{
    assert( nullptr != p );
    int maxv = p[ 0 ];
    int secv = p[ 0 ];
    for( int i = 1; i < len; ++i )
    {
        if( maxv < p[ i ] )
        {
            secv = maxv;
            maxv = p[ i ];
        }
    }
    return secv;
}


  • 5
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: C算法实战面试可以是各种类型和难度的问,从简单的数组操作到复杂的图算法。下面是一个可能的目: 假设有一个数组num,其中包含了一些整数。请编写一个算法,找到数组中两个元素的和等于给定的目标数的索引,并返回这两个元素的索引。 解思路如下: 1. 创建一个空的字典,用来存储已经遍历过的元素的值和对应的索引。 2. 遍历整个数组num,对于每个元素num[i],检查目标数与当前元素之差是否已经存在于字典中。 3. 如果存在,说明之前已经遍历过一个元素num[j],使得num[i] + num[j] = 目标数。返回j和i作为结果。 4. 如果不存在,说明之前没有找到与当前元素相加等于目标数的元素,将当前元素的值和索引添加到字典中,继续遍历数组。 5. 如果遍历结束后没有找到满足条件的元素,返回一个空的结果。 这个算法的时间复杂度是O(n),其中n是数组num的长度。因为只需要遍历一次数组,并且利用字典的查找操作是常数时间的。 在实际的面试中,可以进一步要求优化算法,例如考虑数组中可能存在重复元素的情况,或者要求返回所有的满足条件的索引对等。根据具体情况,可以对算法进行细化和改进。 ### 回答2: c 算法实战面试是指在面试过程中,针对 C 语言编程能力要求的一系列算法目。这类目旨在考察面试者对基本算法和数据结构的理解和掌握程度,以及解决实际问的能力和思维方式。 常见的 C 算法实战面试包括排序算法(如冒泡排序、插入排序、快速排序等)、查找算法(如二分查找、哈希查找等)、字符串处理问(如字符串反转、字符串匹配等)、链表相关问(如链表反转、链表中的环检测等)、递归和迭代等等。 在面试中回答此类问,需要从具体算法和解思路两个方面进行回答。 对于具体算法,需要清晰地解释算法原理和实现步骤,算法的时间和空间复杂度等。例如,对于快速排序算法,可以解释其基本思想是通过选择一个基准元素,并将待排序数组分为两部分,一部分小于等于基准元素,一部分大于基准元素,然后递归地对两部分进行排序,最终达到整个数组有序的目的。 对于解思路,可以从多个角度进行分析和讨论。例如,在链表环检测问中,除了传统的使用哈希表或快慢指针的方法之外,还可以考虑使用递归和迭代的思路来解决。并且需要考虑解决问时可能存在的边界情况和异常情况。 总之,回答 C 算法实战面试需要充分理解算法原理,并能运用一定的思维方式和解技巧,同时也需要注重代码实现的效率和边界情况的处理,以展现自己扎实的编程能力和解决问的能力。 ### 回答3: c算法实战面试是一种在面试中常见的型,需要候选人用C语言编写代码解决给定的问。以下是一个简单的示例目和解答: 目:给定一个整数数组nums和一个目标值target,请找出数组中两个数的和等于目标值,并返回它们的索引。 示例输入:nums = [2, 7, 11, 15], target = 9 示例输出:[0, 1] 解答: ``` #include <stdio.h> int* twoSum(int* nums, int numsSize, int target, int* returnSize) { int i, j; int* result = (int*)malloc(2 * sizeof(int)); for (i = 0; i < numsSize - 1; i++) { for (j = i + 1; j < numsSize; j++) { if (nums[i] + nums[j] == target) { result[0] = i; result[1] = j; *returnSize = 2; return result; } } } *returnSize = 0; return NULL; } int main() { int nums[] = {2, 7, 11, 15}; int target = 9; int returnSize; int* result = twoSum(nums, sizeof(nums) / sizeof(nums[0]), target, &returnSize); if (returnSize == 2) { printf("[%d, %d]\n", result[0], result[1]); } else { printf("No result found.\n"); } free(result); return 0; } ``` 这个示例目要求在给定的数组中找到和为目标值的两个数,并返回它们的索引。在解法中,我们使用了简单的双重循环来遍历数组,找到符合条件的两个数后,保存它们的索引并返回。如果遍历完整个数组没有找到符合条件的数对,则返回NULL。 以上是一个简单的C语言面试示例,实际的目可能会更复杂,但解思路一般都是类似的,即使用适当的算法和数据结构来解决问。在面试中,除了正确的解答,面试官还会关注代码的可读性、性能等方面。因此,在写出代码解答之前,应该先仔细阅读目要求,并在思考清楚解思路后再动手编写代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值