文章目录
最长的可整合子数组的长度
题目
可整合数组的定义:如果一个数组在排序之后,每相邻两个数差的绝对值都为1,则该数组为可整合数组。如[5, 3, 4, 6, 2]排序之后为[2, 3, 4, 5, 6]。符合每相邻两个数差的绝对值为1.所以这个数组为可整合数组。
给定一个整型数组arr,返回其中最大可整合子数组的长度。
代码
逐个子数组排序后进行判断的话复杂度比较高,达到O(N^3logN)。可以用max-min == j - i这种方式来判断。这样可以将排序的O(NlogN)降到O(1)
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
bool isIntegrated(vector<int> arr, int left, int right)
{
int subLen = right - left + 1;
vector<int> newArr(subLen, 0);
for (int i = 0; i < subLen; i++)
newArr[i] = arr[i + left];
sort(newArr.begin(), newArr.end());
for (int i = 1; i < subLen; i++)
{
if (newArr[i - 1] != newArr[i] - 1)
return false;
}
return true;
}
int getLIL1(vector<int> arr)
{
if (arr.size() < 1)
return 0;
int size = arr.size();
int len = 0;
for (int i = 0; i < size; i++)
{
for (int j = i; j < size; j++)
{
if (isIntegrated(arr, i, j))
len = max(len, j - i + 1);
}
}
return len;
}
int getLIL2(vector<int> arr)
{
if (arr.size() < 1)
return 0;
int size = arr.size();
int len = 0;
int Max = 0;
int Min = 0;
set<int> s;
for (int i = 0; i < size; i++)
{
Max = INT_MIN;
Min = INT_MAX;
for (int j = i; j < size; j++)
{
if (s.find(arr[j]) != s.end())
break;
s.emplace(arr[j]);
Max = max(Max, arr[j]);
Min = min(Min, arr[j]);
if (Max - Min == j - i)
len = max(len, j - i + 1);
}
s.clear();
}
return len;
}
int main()
{
int len;
cin >> len;
vector<int> in(len, 0);
for (int i = 0; i < len; i++)
cin >> in[i];
int res1 = getLIL1(in);
int res2 = getLIL2(in);
cout << res1 << " " << res2 << endl;
getchar();
return 0;
}
未完待续…(11.30)
不重复打印排序数组中相加和为给定值的所有二元组和三元组
题目
给定排序数组arr和整数k,不重复打印arr中所有相加和为k的不降序二元组。
补充题目:给定排序数组arr和整数k,不重复打印arr中所有相加和为k的不降序三元组。
代码
左右两个指针一次寻找合适的元组打印,不重复打印的话因为是已排序数组,只需加上一个判断即可。三元组的打印与二元组比较类似,将sum变为sum-arr[i]即可,详细参考书
#include<iostream>
#include<algorithm>
using namespace std;
void printUniquePair(int* arr, int k, int len)
{
if (arr == NULL || len < 2)
return;
int left = 0;
int right = len - 1;
while (left < right)
{
if (arr[left] + arr[right] < k)
left++;
else if (arr[left] + arr[right] > k)
right--;
else
{
if (left == 0 || arr[left - 1] != arr[left])
cout << arr[left] << "," << arr[right] << endl;
left++;
right--;
}
}
}
void printRest(int* arr, int f, int l, int r, int k)
{
while (l < r)
{
if (arr[l] + arr[r] < k)
l++;
else if (arr[l] + arr[r] > k)
r--;
else
{
if (l == f + 1 || arr[l - 1] != arr[l])
cout << arr[f] << "," << arr[l] << "," << arr[r] << endl;
l++;
r--;
}
}
}
void printUniqueTri(int* arr, int len, int k)
{
if (arr == NULL || len < 3)
return;
for (int i = 0; i < len - 2; i++)
{
if (i == 0 || arr[i] != arr[i - 1])
printRest(arr, i, i + 1, len - 1, k - arr[i]);
}
}
int main()
{
int k, len;
cin >> k >> len;
int* arr = new int[len];
for (int i = 0; i < len; i++)
cin >> arr[i];
printUniquePair(arr, k, len);
printUniqueTri(arr, len, k);
getchar();
return 0;
}
未排序正数数组中累加和为给定值的最长子数组长度
题目
给定数组arr,该数组无序,每个值均为正数,在给定一个整数k,求arr的所有子数组中所有元素相加和为k的最长子数组长度。
如:arr=[1, 2, 1, 1, 1],k=3;累加和为3的最长子数组为【1,1,1】,所以返回结果为3.
代码
#include<iostream>
#include<algorithm>
using namespace std;
int getMaxLen(int* arr, int len, int k)
{
if (arr == NULL || len == 0 || k <= 0)
return 0;
int left = 0;
int right = 0;
int sum = arr[0];
int maxSize = 0;
while (right < len)
{
if (sum == k)
{
maxSize = max(maxSize, right - left + 1);
sum -= arr[left++];
}
else if (sum < k)
{
right++;
if (right == len)
break;
sum += arr[right];
}
else
sum -= arr[left++];
}
return maxSize;
}
int main()
{
int len, k;
cin >> len >> k;
int* in = new int[len];
for (int i = 0; i < len; i++)
cin >> in[i];
int res = getMaxLen(in, len, k);
cout << res << endl;
getchar();
return 0;
}
未排序数组中累加和为给定值的最长子数组系列问题
题目
给定一个无序数组arr,其中元素可正,可负,可0.给定一个整数k,求arr所有子数组中累加和为k的最长字数组长度
补充题目1:给定无序数组arr,其中元素可正,可负,可0.求arr所有子数组中正数与负数个数相等的最长子数组长度
补充题目2:给定一个无序数组arr,其中元素只是1或0.求arr中所有子数组0和1个数相等的最长子数组长度。
代码
两个补充题目可以根据原问题的原理将正数或负数做替换,进一步得到对应解。
原问题解如下:
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int maxLen(int* arr, int len, int k)
{
if (arr == NULL || len == 0)
return 0;
map<int, int> re;
re[0] = -1;
int maxSize = 0;
int sum = 0;
for (int i = 0; i < len; i++)
{
sum += arr[i];
if (re.find(sum - k) != re.end())
maxSize = max(maxSize, i - re[sum - k]);
if (re.find(sum) == re.end())
re[sum] = i;
}
return maxSize;
}
int main()
{
int len, k;
cin >> len >> k;
int* arr = new int[len];
for (int i = 0; i < len; i++)
cin >> arr[i];
int res = maxLen(arr, len, k);
cout << res << endl;
getchar();
return 0;
}
未排序数组中累加和小于或等于给定值的最长子数组长度
题目
给定一个无序数组arr,其中元素可正,可负,可0.给定一个整数k,求arr所有的子数组中累加和小于或等于k的最长子数组长度。
如:arr=【3,-2,-4,0,6】,k=-2;相加和小于或等于-2的最长子数组为【-3,-2,-4,0】,长度为4.
代码
#include<iostream>
#include<algorithm>
using namespace std;
int getLessIndex(int* arr, int num, int len)
{
int low = 0;
int high = len - 1;
int mid = 0;
int res = -1;
while (low <= high)
{
mid = (low + high) / 2;
if (arr[mid] >= num)
{
res = mid;
high = mid - 1;
}
else
{
low = mid + 1;
}
}
return res;
}
int maxLength(int* arr, int k, int len)
{
int* h = new int[len + 1];
int sum = 0;
h[0] = sum;
for (int i = 0; i < len; i++)
{
sum += arr[i];
h[i + 1] = max(sum, h[i]);
}
sum = 0;
int res = 0;
int pre = 0;
int maxLen = 0;
for (int i = 0; i < len; i++)
{
sum += arr[i];
pre = getLessIndex(h, sum - k, len + 1);
maxLen = pre == -1 ? 0 : i - pre + 1;
res = max(res, maxLen);
}
return res;
}
int main()
{
int len, k;
cin >> len >> k;
int* arr = new int[len];
for (int i = 0; i < len; i++)
cin >> arr[i];
int res = maxLength(arr, k, len);
cout << res << endl;
getchar();
return 0;
}
大失误,周末比较放松,学习不能!学校网速让我望课兴叹!