数组问题分类之六

文章目录

  • 边界都是1的最大正方形大小
    • 题目
    • 代码
  • 不包含本位置值的累乘数组
    • 题目
    • 代码
  • 数组的partition调整
    • 题目
    • 代码
  • 最短通路值
    • 题目
    • 代码
  • 数组中未出现的最小正整数
    • 题目
    • 代码
  • 数组排序之后相邻数的最大差值
    • 题目
    • 代码

边界都是1的最大正方形大小

题目

给定一个N×N的矩阵matrix,在这个矩阵中,只有0和1两种值,返回最大正方形的边长长度。
如:
0 1 1 1 1
0 1 0 0 1
0 1 0 0 1
0 1 1 1 1
0 1 0 1 1
其中边框全是1的最大正方形大小为4×4,返回4

代码

逐个位置判断复杂度可以达到O(N4),经过更改后的复杂度可以达到O(N3)

#include
#include
#include
using namespace std;

void setBorderMap(vector<vector<int>> &m, vector<vector<int>> &right, vector<vector<int>> &down)
{
	int row = m.size();
	int col = m[0].size();
	if (m[row - 1][col - 1] == 1)
	{
		right[row - 1][col - 1] = 1;
		down[row - 1][col - 1] = 1;
	}
	for (int i = row - 2; i >= 0; i--)
	{
		if (m[i][col - 1] == 1)
		{
			right[i][col - 1] = 1;
			down[i][col - 1] = down[i + 1][col - 1] + 1;
		}
	}
	for (int i = col - 2; i >= 0; i--)
	{
		if (m[row - 1][i] == 1)
		{
			right[row - 1][i] = right[row - 1][i + 1] + 1;
			down[row - 1][i] = 1;
		}
	}
	for (int i = row - 2; i >= 0; i--)
	{
		for (int j = col - 2; j >= 0; j--)
		{
			if (m[i][j] == 1)
			{
				right[i][j] = right[i][j + 1] + 1;
				down[i][j] = down[i + 1][j] + 1;
			}
		}
	}
}

bool hasSizeofBorder(int size, vector<vector<int>> right, vector<vector<int>> down)
{
	for (int i = 0; i < right.size() - size + 1; i++)
	{
		for (int j = 0; j < right[0].size() - size + 1; j++)
		{
			if (right[i][j] >= size && down[i][j] >= size && right[i + size - 1][j] >= size && down[i][j + size - 1] >= size)
				return true;
		}
	}
	return false;
}

int getMaxSize(vector<vector<int>> m)
{
	int row = m.size();
	int col = m[0].size();
	vector<vector<int>>right(row, vector<int>(col, 0));
	vector<vector<int>>down(row, vector<int>(col, 0));
	setBorderMap(m, right, down);
	for (int size = min(row, col); size > 0; size--)
	{
		if (hasSizeofBorder(size, right, down))
			return size;
	}
	return 0;
}

int main()
{
	int row, col;
	cin >> row >> col;
	vector<vector<int>>in(row, vector<int>(col, 0));
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
			cin >> in[i][j];
	}
	int res = getMaxSize(in);
	cout << res << endl;
	getchar();
	return 0;
}

不包含本位置值的累乘数组

题目

给定一个整形数组arr,返回不包含本位置值得雷乘数组
如:arr=[2, 3, 1, 4],返回[12, 8, 24, 6],即除自己外,其他所有位置上的乘积。
要求时间复杂度O(N);额外空间复杂度为O(1);

代码

两种方法,一种是得到全部乘积后进行除法,不允许除法的情况下,可以参考第二种方法。

#include
#include
using namespace std;

int* multi1(int* arr, int len)
{
	if (arr == NULL || len < 2)
		return NULL;
	int cnt = 0;
	int all = 1;
	for (int i = 0; i < len; i++)
	{
		if (arr[i] != 0)
			all *= arr[i];
		else
			cnt++;
	}
	int* res = new int[len];
	for (int i = 0; i < len; i++)
		res[i] = 0;
	if (cnt == 0)
	{
		for (int i = 0; i < len; i++)
			res[i] = all / arr[i];
	}
	if (cnt == 1)
	{
		for (int i = 0; i < len; i++)
		{
			if (arr[i] == 0)
				res[i] = all;
		}
	}
	return res;
}

int* multi2(int* arr, int len)
{
	if (arr == NULL || len < 2)
		return NULL;
	int* res = new int[len];
	for (int i = 0; i < len; i++)
		res[i] = 0;
	res[0] = 1;
	for (int i = 1; i < len; i++)
		res[i] = res[i - 1] * arr[i - 1];
	int tmp = 1;
	for (int j = len - 2; j >= 0; j--)
	{
		tmp *= arr[j + 1];
		res[j] *= tmp;
	}
	return res;
}

void print(int* arr, int len)
{
	for (int i = 0; i < len; i++)
		cout << arr[i] << " ";
	cout << endl;
}

int main()
{
	int len;
	cin >> len;
	int* input = new int[len];
	for (int i = 0; i < len; i++)
		cin >> input[i];
	int* res1 = new int[len];
	int* res2 = new int[len];
	res1 = multi1(input, len);
	res2 = multi2(input, len);
	print(res1, len);
	print(res2, len);
	getchar();
	return 0;
}

数组的partition调整

题目

给定要给有序数组,调整arr使得这个数组的左半部分没有重复元素且升序,不用保证右半部份是否有序。
补充题目:给定一个数组arr,其中只可能含有0, 1, 2三个值,请实现arr的排序。
要求:时间复杂度O(N),额外空间复杂度为O(1);

代码

#include
using namespace std;

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

void leftUnique(int* arr, int len)
{
	if (arr == NULL || len < 2)
		return;
	int u = 0;
	int i = 1;
	while (i != len)
	{
		if (arr[i++] != arr[u])
			swap(arr, ++u, i - 1);
	}
}

void sort(int* &arr, int len)
{
	if (arr == NULL || len < 2)
		return;
	int left = -1;
	int index = 0;
	int right = len;
	while (index < right)
	{
		if (arr[index] == 0)
			swap(arr, ++left, index++);
		else if (arr[index] == 2)
			swap(arr, index, --right);
		else
			index++;
	}
}

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

最短通路值

题目

给定一个整型矩阵matrix表示一个网络,1表示有路,0表示无路,每个位置只要不越界,都有上下左右四个方向,求从左上角到右下角最短通路值。如matrix为:
1 0 1 1 1
1 0 1 0 1
1 1 1 0 1
0 0 0 0 1
通路由12个1构成,返回12.

代码

#include
#include
#include
using namespace std;

void walkTo(int pre, int toR, int toC, vector<vector<int>> &m, vector<vector<int>>&mp, queue<int> &rQ, queue<int>&cQ)
{
	if (toR < 0 || toR >= m.size() || toC < 0 || toC >= m[0].size() || m[toR][toC] != 1 || mp[toR][toC] != 0)
		return;
	mp[toR][toC] = pre + 1;
	rQ.push(toR);
	cQ.push(toC);
}

int minPath(vector<vector<int>> m)
{
	if (m.size() < 1 || m[0].size() < 1 || m[0][0] != 1 || m[m.size() - 1][m[0].size() - 1] != 1)
		return 0;
	int res = 0;
	int row = m.size();
	int col = m[0].size();
	vector<vector<int>> mp(row, vector<int>(col, 0));
	mp[0][0] = 1;
	queue<int> rQ, cQ;
	int r = 0;
	int c = 0;
	rQ.push(r);
	cQ.push(c);
	while (!rQ.empty())
	{
		r = rQ.front();
		c = cQ.front();
		rQ.pop();
		cQ.pop();
		if (r == row - 1 && c == col - 1)
			return mp[r][c];
		walkTo(mp[r][c], r - 1, c, m, mp, rQ, cQ);
		walkTo(mp[r][c], r + 1, c, m, mp, rQ, cQ);
		walkTo(mp[r][c], r, c + 1, m, mp, rQ, cQ);
		walkTo(mp[r][c], r, c - 1, m, mp, rQ, cQ);
	}
	return res;
}

int main()
{
	int row, col;
	cin >> row >> col;
	vector<vector<int>>in(row, vector<int>(col, 0));
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
			cin >> in[i][j];
	}
	int res = minPath(in);
	cout << res << endl;
	getchar();
	return 0;
}

数组中未出现的最小正整数

题目

给定一个无序整形数组arr,找到数组中未出现的最小正整数。
如:arr=[-1,2,3,4]。返回1;arr=[1,2,3,4],返回5;

代码

#include
using namespace std;

void swap1(int* &arr, int index1, int index2)
{
	int tmp = arr[index1];
	arr[index1] = arr[index2];
	arr[index2] = tmp;
}

int minNum(int* arr, int len)
{
	int l = 0;
	int r = len;
	while (l < r)
	{
		if (arr[l] == l + 1)
			l++;
		else if (arr[l] <= l || arr[l] > r || arr[arr[l] - 1] == arr[l])
			arr[l] = arr[--r];
		else
			swap1(arr, l, arr[l] - 1);
	}
	return l + 1;
}

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

数组排序之后相邻数的最大差值

题目

给定一个整型数组arr,返回排序后的相邻两数的最大差值。
arr=[9,3,1,10],排序之后为[1,3,9,10],相邻两个数之间最大插值为6,返回6即可。
如果arr长度为N,要求时间复杂度为O(N).
类似桶排序思想

代码

#include
#include
using namespace std;
int bucket(long num, long len, long Min, long Max)
{
	return (int)((num - Min) * len / (Max - Min));
}

int maxGap(int* arr, int len)
{
	if (arr == NULL || len < 2)
		return 0;
	int Min = INT_MAX;
	int Max = INT_MIN;
	for (int i = 0; i < len; i++)
	{
		Min = min(Min, arr[i]);
		Max = max(Max, arr[i]);
	}
	if (Min == Max)
		return 0;
	bool* hasNum = new bool[len + 1];
	int* maxs = new int[len + 1];
	int* mins = new int[len + 1];
	for (int i = 0; i <= len; i++)
	{
		hasNum[i] = false;
		maxs[i] = 0;
		mins[i] = 0;
	}

	int bid = 0;
	for (int i = 0; i < len; i++)
	{
		bid = bucket(arr[i], len, Min, Max);
		mins[bid] = hasNum[bid] ? min(mins[bid], arr[i]) : arr[i];
		maxs[bid] = hasNum[bid] ? max(maxs[bid], arr[i]) : arr[i];
		hasNum[bid] = true;
	}
	int res = 0;
	int lastMax = 0;
	int i = 0;
	while (i <= len)
	{
		if (hasNum[i++])
		{
			lastMax = maxs[i - 1];
			break;
		}
	}
	for (; i <= len; i++)
	{
		if (hasNum[i])
		{
			res = max(res, mins[i] - lastMax);
			lastMax = maxs[i];
		}
	}
	return res;
}

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

你可能感兴趣的:(数组问题分类之六)