第1章数组和字符串—6~8题【倒计时23天】

病了一场,家庭琐事太多,耽搁了好些日子。看来后面得抓紧时间了!

6. 一幅图像由N X N矩阵的像素点组成,每个像素点4个字节的信息量,将图像顺时针(逆时针)旋转90度。如何做到?

思路:剥洋葱法,由外而内分层进行,以4x4大小的像素点矩阵为例,先从最外圈(黄色)开始调整,然后是内圈(绿色)。


编程实现:

/*
@ clockwise rotate a matrix N x N
*/
void rotateMatrix(int** matrix, int n)
{
	if(matrix == NULL || n < 2) return;
	
	//rotate by layer from outer to inner
	for(int layer=0; layer<n/2; layer++){
		int first = layer;
		int last = n - 1 - layer;
		for(int i=first; i<last; i++){
			int offset = i - first;
			int top = matrix[layer][i];
			//left -> top
			matrix[layer][i] = matrix[last-offset][layer];
			//bottom -> left
			matrix[last-offset][layer] = matrix[last][last-offset];
			//right -> bottom
			matrix[last][last-offset] = matrix[i][last];
			// top -> right
			matrix[i][last] = top;		
		}
	}
}
部分测试代码:

	const int N = 10;
	int **pMatrix = new int*[N];
	for(int i=0; i<N; i++)
		pMatrix[i] = new int[N];
	cout << "before rotation, matrix is " << endl;
	for(int i=0; i<N; i++){
		for(int j=0; j<N; j++){
			pMatrix[i][j] = i*N + j;
			cout << pMatrix[i][j] << " ";
		}
		cout << endl;
	}

	rotateMatrix(pMatrix, N);
	cout << "after rotation, matrix is " << endl;
	for(int i=0; i<N; i++){
		for(int j=0; j<N; j++)
			cout << pMatrix[i][j] << " ";
		cout << endl;
	}
	delete []pMatrix;

7.M X N大小矩阵中某个元素为0, 则将该元素所在的行和列均置为0

思路:这道题看似简单,其实暗藏机关。如果遍历矩阵,遇到0元素,则将所在行和列均置为0,最后得到0矩阵。为什么呢?不明白的时候可以找个简单的例子推理。一种可行的方法是第一次遍历时候记录下0元素所在的行和列,然后在第二次遍历时将所在行或者列为0的元素置为0即可。

编程实现:

/*
@ if an element in a MxN matrix is 0, its entire row and column is set to 0.
*/
void setZeros(int** matrix, int m, int n)
{
	if(matrix==NULL || m<1 || n<1) return;
	bool *zerosColumn = new bool[m];
	bool *zerosRow = new bool[n];
	//initialize zerosColumn and zerosRow
	for(int i=0; i<m; i++)
		zerosColumn[i] = false;
	for(int i=0; i<n; i++)
		zerosRow[i] = false;
	//count '0' in matrix
	for(int i=0; i<m; i++)
		for(int j=0; j<n; j++)
			if(matrix[i][j] == 0){
				zerosColumn[i] = true;
				zerosRow[j] = true;		
			}

	for(int i=0; i<m; i++)
		for(int j=0; j<n; j++)
		{
			if(zerosColumn[i]||zerosRow[j])
				matrix[i][j] = 0;
		}
	delete zerosColumn;
	delete zerosRow;
}
部分测试代码:

	//test setZeros
	const int M = 5;const int N = 6;
	//int matrix[N][N] = {1,2,3,4};
	int **pMatrix = new int*[M];
	for(int i=0; i<M; i++)
		pMatrix[i] = new int[N];
	cout << "before rotation, matrix is " << endl;
	for(int i=0; i<M; i++){
		for(int j=0; j<N; j++){
			pMatrix[i][j] = i*N + j;
			if(i==M/2 && j==N/2)
				pMatrix[i][j] = 0;
			cout << setw(5) << pMatrix[i][j];
		}
		cout << endl;
	}
	
	setZeros(pMatrix,M,N);
	cout << "after Zero setting, matrix is " << endl;
	for(int i=0; i<M; i++){
		for(int j=0; j<N; j++)
			cout << setw(5) << pMatrix[i][j];
		cout << endl;
	}
	delete []pMatrix;

8. 假设已有isSubstring方法去判断一个字符串是否为另一个的子字符串;现有S1和S2两个字符串,调用一次isSubstring方法判断两者是否互为旋转式?如“waterbottle”和“bottlewater”互为旋转式。

思路:简单清晰,方法如下:1) 先检查S1和S2的长度是否相等,不等显然不能满足互为旋转式;2)将S1首尾链接组成一个新的字符串S11,然后调用isSubstring判断S2是否为S1的一个字符串。

编程实现:

/*
@ judge s is Substring of t or not.
*/
bool isSubstring(const string& s, const string& t)
{
	if(s.length()<1 || t.length()<1)
		return false;//NULL is NOT Substring of NULL string.
	int n = 0; //index of t
	for(int i=0; i<t.length(); i++){
		if(t[i] == s[n])
			++n;
		else if(t[i]==s[0])
			n = 1;
		else
			n=0;
		if(n==s.length())
			return true;
	}
	return false;
}
bool isRotateString(const string& str1, const string& str2)
{
	if(str1.length() > 0 && str1.length()==str2.length()){
		string s1 = string(str1);
		s1 += str1;
		return isSubstring(str2, s1);	
	}
	return false;
}
部分测试代码如下:

	//test isSubstring
	string str1 = "world";
	string str2 = "Hello wor2ldworworld";
	if(isSubstring(str1, str2))
		cout << str1 << " is Substring of " << str2 << endl;
	else
		cout << str1 << " is NOT Substring of " << str2 << endl;
	string str3 = "ldwor";
	if(isRotateString(str1,str3))
		cout << str1 << " is rotated by " << str3 << endl;
	else
		cout << str1 << " is NOT rotated by " << str3 << endl;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值