数组和矩阵之五

打印矩阵

题目

转圈打印矩阵(螺旋打印);
旋转矩阵,将矩阵调整成顺时针转动90度之后的形式;
之字形打印矩阵;给定一个矩阵,按照“之”字形的方式打印这个矩阵。

代码

按照书中的方式分别实现了三种打印的方式,书中给出的方法与剑指offer的方法基本一致,稍微仔细看下就可以理解,但是写的话如果大意还是会有问题(对于我来说的)

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

void printEdge(vector<vector<int>> m, int tR, int tC, int dR, int dC)
{
	if (tR == dR)
	{
		for (int i = tC; i <= dC; i++)
			cout << m[tR][i] << " ";
	}
	else if (tC == dC)
	{
		for (int i = tR; i <= dR; i++)
		{
			cout << m[i][tC] << " ";
		}
	}
	else
	{
		int curC = tC;
		int curR = tR;
		while (curC != dC)
		{
			cout << m[tR][curC] << " ";
			curC++;
		}
		while (curR != dR)
		{
			cout << m[curR][dC] << " ";
			curR++;
		}
		while (curC != tC)
		{
			cout << m[dR][curC] << " ";
			curC--;
		}
		while (curR != tR)
		{
			cout << m[curR][tC] << " ";
			curR--;
		}
	}
}
void circlePrint1(vector<vector<int>> matrix)
{
	int tR = 0;
	int tC = 0;
	int dR = matrix.size() - 1;
	int dC = matrix[0].size() - 1;
	while (tR <= dR && tC <= dC)
	{
		printEdge(matrix, tR, tC, dR, dC);
		tR++;
		tC++;
		dR--;
		dC--;
	}
	cout << endl;
}

/*旋转矩阵*/
void rotateEdge(vector<vector<int>> &m, int tR, int tC, int dR, int dC)
{
	int times = dC - tC;
	int tmp = 0;
	for (int i = 0; i != times; i++)
	{
		tmp = m[tR][tC + i];
		m[tR][tC + i] = m[dR - i][tC];
		m[dR - i][tC] = m[dR][dC - i];
		m[dR][dC - i] = m[tR + i][dC];
		m[tR + i][dC] = tmp;
	}
}

void rotate(vector<vector<int>> matrix)
{
	int tR = 0;
	int tC = 0;
	int dR = matrix.size() - 1;
	int dC = matrix[0].size() - 1;
	while (tR < dR)
	{
		rotateEdge(matrix, tR, tC, dR, dC);
		tR++;
		tC++;
		dR--;
		dC--;
	}
	for (int i = 0; i <= 3; i++)
	{
		for (int j = 0; j <= 3; j++)
			cout << matrix[i][j] << " ";
		cout << endl;
	}
	cout << endl;
}

//"之"字形打印矩阵
void printLevel(vector<vector<int>> m, int tR, int tC, int dR, int dC, bool f)
{
	if (f)
	{
		while (tR != dR + 1)
			cout << m[tR++][tC--] << " ";
	}
	else
	{
		while (dR != tR - 1)
			cout << m[dR--][dC++] << " ";
	}
}

void printMatrixZigZag(vector<vector<int>> matrix)
{
	int tR = 0;
	int tC = 0;
	int dR = 0;
	int dC = 0;
	int endR = matrix.size() - 1;
	int endC = matrix[0].size() - 1;
	bool fromUp = false;
	while (tR != endR + 1)
	{
		printLevel(matrix, tR, tC, dR, dC, fromUp);
		tR = tC == endC ? tR + 1 : tR;
		tC = tC == endC ? tC : tC + 1;
		dC = dR == endR ? dC + 1 : dC;
		dR = dR == endR ? dR : dR + 1;
		fromUp = !fromUp;
	}
	cout << endl;
}

int main()
{
	int len;
	cin >> len;
	vector<vector<int>> m(len, vector<int>(len, 0));
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len; j++)
			cin >> m[i][j];
	}
	cout << "Circle print of matrix!" << endl;
	circlePrint1(m);
	cout << "Zigzag print of matrix!" << endl;
	printMatrixZigZag(m);
	cout << "Rotate of matrix!" << endl;
	rotate(m);
	getchar();
	return 0;
}

找到无序数组中最小的k个数

题目

给定一个无序整型数组arr,找到其中最小的k个数。
要求:排序之后可以得到最小的前k个数,时间复杂度为O(NlogN),要求实现*O(Nlogk)O(N)*的方法。

代码

按照书中所题,根据最大堆的方式实现了O(Nlogk) 的方法,*O(N)*方法略复杂,未做实现。

#include<iostream>
#include<algorithm>
#define lChild(i) 2 * (i) + 1;
#define rChild(i) 2 * (i) + 2;
using namespace std;

void swap(int* &arr, int a, int b)
{
	int tmp = arr[a];
	arr[a] = arr[b];
	arr[b] = tmp;
}

void heapify(int* in, int len, int i)
{
	int left = lChild(i);
	int right = rChild(i);
	int largest = i;
	while (left < len)
	{
		if (in[left] > in[i])
			largest = left;
		if (right < len && in[right] > in[largest])
			largest = right;
		if (largest != i)
			swap(in, largest, i);
		else
			break;
		i = largest;
		left = lChild(i);
		right = rChild(i);
	}
}

void heapInsert(int* in, int i, int value)
{
	in[i] = value;
	while (i != 0)
	{
		int parent = (i - 1) / 2;
		if (in[parent] < in[i])
		{
			swap(in, parent, i);
			i = parent;
		}
		else
			break;
	}
}

int* getMinKNum(int* in, int k, int len)
{
	if (k < 1 || k > len)
		return in;
	int* kHeap = new int[k];
	for (int i = 0; i < k; i++)
		heapInsert(kHeap, i, in[i]);
	for (int i = k; i < len; i++)
	{
		if (in[i] < kHeap[0])
		{
			kHeap[0] = in[i];
			heapify(kHeap, k, 0);
		}
	}
	return kHeap;
}

int main()
{
	int len, k;
	cin >> len >> k;
	int* in = new int[len];
	for (int i = 0; i < len; i++)
		cin >> in[i];
	int* numK = new int[k];
	numK = getMinKNum(in, k, len);
	for (int i = 0; i < k; i++)
		cout << numK[i] << " ";
	cout << endl;
	getchar();
	return 0;
}

需要排序的最短子数组长度

题目

给定一个无序数组arr,求出需要排序的最短子数组长度
例如:arr = [1, 5, 3, 4, 2, 6, 7]返回4,因为只有[5, 4, 3, 2]需要排序。

代码

#include<iostream>
#include<algorithm>
using namespace std;

int getMinLen(int* arr, int len)
{
	if (arr == NULL || len < 1)
		return 0;
	int Min = arr[len - 1];
	int noMinIndex = -1;
	for (int i = len - 2; i >= 0; i--)
	{
		if (arr[i] > Min)
			noMinIndex = i;
		else
			Min = min(Min, arr[i]);
	}
	if (noMinIndex == -1)
		return 0;
	int Max = arr[0];
	int noMaxIndex = -1;
	for (int i = 1; i < len; i++)
	{
		if (arr[i] < Max)
			noMaxIndex = i;
		else
			Max = max(Max, arr[i]);
	}
	return noMaxIndex - noMinIndex + 1;
}

int main()
{
	int len;
	cin >> len;
	int* in = new int[len];
	for (int i = 0; i < len; i++)
		cin >> in[i];
	int res = getMinLen(in, len);
	cout << res << endl;
	getchar();
	return 0;
}

在数组中找到出现次数大于N/K的数

题目

给定一个整型数组arr,打印其中出现次数大于一半的数,如果没有这样的数,打印提示信息
进阶:给定一个整型数组arr,再给定一个整数K,打印所有出现次数大于N/K的数,如果没有这样的数,打印提示信息。
要求:原问题时间复杂度为O(N),额外空间复杂度为O(1)。进阶问题时间复杂度要求为O(N×K),额外空间复杂度为O(K)

代码

根据书中java代码实现了原问题和进阶问题。

#include<iostream>
#include<algorithm>
#include<map>
#include<list>
using namespace std;

void printHalfMajor(int* arr, int len)
{
	int cand = 0;
	int times = 0;
	for (int i = 0; i < len; i++)
	{
		if (times == 0)
		{
			cand = arr[i];
			times = 1;
		}
		else if (arr[i] == cand)
			times++;
		else
			times--;
	}
	times = 0;
	for (int i = 0; i < len; i++)
	{
		if (arr[i] == cand)
			times++;
	}
	if (times > len / 2)
		cout << cand << endl;
	else
		cout << "No such Number!" << endl;
}//阵地攻守or删除数组中相同两个数()


map<int, int> getReals(int* arr, int len, map<int, int>cands)
{
	map<int, int> reals;
	for (int i = 0; i < len; i++)
	{
		int curNum = arr[i];
		if (cands.find(curNum) != cands.end())
		{
			if (reals.find(curNum) != reals.end())
				reals[curNum] = reals[curNum] + 1;
			else
				reals[curNum] = 1;
		}
	}
	return reals;
}

void allCandsMinusOne(map<int, int> &m)
{
	list<int> removeList;
	map<int, int>::iterator it;
	list<int>::iterator itList = removeList.begin();
	for (it = m.begin(); it != m.end(); it++)
	{
		int key = it->first;
		int value = it->second;
		if (value == 1)
		{
			removeList.push_back(key);
		}
		m[key] = value - 1;
	}
	list<int>::iterator it1;
	map<int, int>::iterator del1;
	int value = 0;
	for (it1 = removeList.begin(); it1 != removeList.end(); it1++)
	{
		value = *it1;
		del1 = m.find(value);
		m.erase(del1);
	}
}

void printKMajor(int* arr, int k, int len)
{
	if (k < 2)
	{
		cout << "The value of K is invalie." << endl;
		return;
	}
	map<int, int>cands;
	for (int i = 0; i < len; i++)
	{
		if (cands.find(arr[i]) != cands.end())
			cands[arr[i]] = cands[arr[i]] + 1;
		else
		{
			if (cands.size() == k - 1)
				allCandsMinusOne(cands);
			else
				cands[arr[i]] = 1;
		}
	}
	map<int, int> reals = getReals(arr, len, cands);
	bool hasPrint = false;
	map<int, int>::iterator it;
	for (it = cands.begin(); it != cands.end(); it++)
	{
		int key = it->first;
		if (reals[key] > len / k)
		{
			hasPrint = true;
			cout << key << " ";
		}
	}
	cout << (hasPrint ? "" : "No such Number.") << endl;
}

int main()
{
	int len, k; 
	cin >> len >> k;
	int* in = new int[len];
	for (int i = 0; i < len; i++)
		cin >> in[i];
	//printHalfMajor(in, len);
	printKMajor(in, k, len);
	getchar();
	return 0;
}

在行列都排好序的矩阵中找数

题目

给定一个有N×M的整型矩阵matrix和一个整数K,matrix的每一行和每一列都是排好序的。实现一个函数,判断K是否在matrix中。

代码

题目比较简单,见过几次了,从左下角开始搜索即可。可以达到*O(M+N)*时间复杂度

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

bool findNum(vector<vector<int>> in, int k)
{
	int row = in.size();
	int col = in[0].size();
	int i = row - 1;
	int j = 0;
	bool res = false;
	while (i >= 0 && j <= col - 1)
	{
		if (in[i][j] < k)
			j++;
		else if (in[i][j] > k)
			i--;
		else
		{
			res = true;
			break;
		}
	}
	return res;
}

int main()
{
	int m, n, k;
	cin >> m >> n >> k;
	vector<vector<int>> in(m, vector<int>(n, 0));
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
			cin >> in[i][j];
	}
	bool res = findNum(in, k);
	if (res)
		cout << "true" << endl;
	else
		cout << "false" << endl;
	getchar();
	return 0;
}

发现自己思路一点都不活跃,本来就是刷题纯刷来的,可是一道简单题就能别自己好久,一天下来也刷不了几道题,果然还是菜鸡,一点疑问都没有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值