给定一个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;
}
给定要给有序数组,调整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;
}