数组中子数组和为固定值的题目汇总
2018-02-03 20:31
204 查看
开头附件一部分数组去重的知识
其中,最关键的是:并不是删除并不是把重复的元素删除,而是全部放倒数组的后面。
因为,unique只是去除(相邻)的重复元素,因此,为了去除重复的元素,应该,首先对数组/Vector进行排序,这样保证重复元素在相邻的位置。
unique函数,返回的是去重后的尾地址。
因此对于一个内容为{2, 2, 5, 5, 6}的vector,执行unique函数以后,vector大小并没有改变,只不过顺序变成了{2, 5, 6, 2, 5},并且函数的返回值为:3。
此时需要删除重复元素,只需要将后面的数据全部删除即可。
排序函数(sort)和去重函数都在<algorithm>头文件中。
de53
span class="cnblogs_code_copy">
unique()函数将重复的元素放到vector的尾部然后返回指向第一个重复元素的迭代器再用erase函数擦除从这个元素到最后元素的所有的元素
自己写的去重函数!
int QuChong(int *nums, int len)
{
sort(nums, nums + len);
int i = 0, j = 0;
for ( i = 0; i < len-1; i++)
{
while (nums[i] == nums[i + 1])
{
i++;
}
nums[j++] = nums[i];
}
return j;
}
int main()
{
int nums[10] = { 1, 1,8,2, 3, 4, 5, 6, 7, 8 };
cout << QuChong(nums,10) << endl;
cout << unique(nums, nums + 10)-nums << endl;;
system("pause");
return 0;
}
题目表1)输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出任意一对既可。2)排序不重复的数组求所有对数和为固定值sum的所有对数!3)排序不重复的数组求所有对数差值为固定值的所有对数!4)输入一个非递增非排序的数组(可能有重复数字)和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出所有可能对数,不能重复。5)输入一个正数S,打印出所有和为S的连续正数序列,至少包含两个数;例如输入15,应该输出(1,2,3,4,5)(4,5,6)(7,8)。6)回溯法求数组中和为定值的子数组的组合!7)求连续子数组的最大和问题!
文章正式开始!!
1)输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出任意一对既可。
bool FindTwoNumsWithSum(int *nums, int sum, int len, vector<int> &res)
{
bool found = false;
if (len < 1 || nums == NULL)
return found;
int begin = 0, end = len - 1;
while (begin < end)
{
long long cursum = nums[begin] + nums[end];
if (cursum == sum)
{
res.push_back(nums[begin]);
res.push_back(nums[end]);
found = true;
break;
}
if (cursum>sum)
{
end--;
}
else
begin++;
}
return found;
}
int main()
{
int nums[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int len = 8;
int sum = 9;
vector<int> res;
FindTwoNumsWithSum(nums, sum, len, res);
cout << res[0] << res[1] << endl;
// MainFun(nums, len, sum);
system("pause");
return 0;
}
2)排序不重复的数组求所有对数和为固定值sum的所有对数!
void dualSum(int arr[], int len, int sum)
{
int low = 0;
int high = len - 1;
while (low<high)
{
while (arr[high] >= sum)
{
high--;
}
if (arr[low] + arr[high]>sum)
high--;
else if (arr[low] + arr[high]<sum)
low++;
else
{
cout << arr[low] << " + " << arr[high] << " = " << sum << endl;
high--; low++;//仅仅是如果题目要求数组没有重复元素的时候才会成立!
}
}
}
int main()
{
int arr2[] = { 1,2,3,4,5,6 };
int len = 6;
int sum = 7;
dualSum(arr2, len, sum);
system("pause");
return 0;
}
3)排序不重复的数组求所有对数差值为固定值的所有对数!
void dualSum(int arr[], int len, int k)
{
int low = 0;
int high = 0;
while (low<len)
{
if (arr[high] -arr[low]>k)
low++;
else if (arr[high] - arr[low]<k)
high++;
else
{
cout << arr[low] << " chavalue" << arr[high] << " = " << k << endl;
high++;//仅仅是如果题目要求数组没有重复元素的时候才会成立!
}
}
}
int main()
{
int arr[] = { 1, 3, 5, 7, 9, 10 };
int len = 6;
int k = 2;
dualSum(arr, len, k);
system("pause");
return 0;
}
4)输入一个非递增非排序的数组(可能有重复数字)和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出所有可能对数,不能重复。
方法一思路: 用N减去每个元素得到另一个数组b,嵌套循环找到a与b中值相同而位置不同的元素对;空间复杂度2N,时间复杂度O(N^2)。(时间复杂度较高,相当于暴力解法)
void CalcTwoSum(int *nums, int len, int sum, vector<vector<int>> &vec)
{
int *numsB= new int[len];
for (int i = 0; i < len; i++)
{
numsB[i] = sum - nums[i];
}
int index = 0;
for (int i = 0; i < len; i++)
{
int find = numsB[i];
for (int j = i + 1; j < len; j++)
{
if (nums[j] == find)
{
cout << numsB[i] << " + " << nums[i] << endl;
vector<int> tmp;
tmp.push_back(numsB[i]);
tmp.push_back(nums[i]);
vec.push_back(tmp);//注意vector<vector<int>>的赋值方法,不能像二维数组那样单独赋值,需要建一个临时vector<int>tmp来赋值处理!!
}
}
}
}
int QuChong(int *nums, int len)
{
sort(nums, nums + len);
int i = 0, j = 0;
for ( i = 0; i < len-1; i++)
{
while (nums[i] == nums[i + 1])
{
i++;
}
nums[j++] = nums[i];
}
return j;
}
int main()
{
int nums[10] = { 1, 1,8,2, 3, 4, 5, 6, 7, 8 };
int len = QuChong(nums, 10);
int sum = 9;
vector<vector<int>> vec;
CalcTwoSum(nums, len, sum,vec);
system("pause");
return 0;
}
5)输入一个正数S,打印出所有和为S的连续正数序列,至少包含两个数;例如输入15,应该输出(1,2,3,4,5)(4,5,6)(7,8)。
我的做法,好理解一些
void PrintContinuousSequence(int small, int big);
void FindContinuousSequence(int sum)
{
if (sum < 3)
return;
int small = 1;
int big = 2;
int middle = (1 + sum) / 2;
int curSum = small + big;
while (small < middle)
{
if (curSum == sum)
{
PrintContinuousSequence(small, big);
big++;
curSum += big;//这个千万不要漏掉,因为要求满足和为sum的所有组合,否则就停掉了!
}
else if (curSum > sum)
{
curSum -= small;
small++;
}
else
{
big++;
curSum += big;
}
}
}
void PrintContinuousSequence(int small, int big)
{
for (int i = small; i <= big; ++i)
printf("%d ", i);
printf("\n");
}
int main()
{
FindContinuousSequence(15);
system("pause");
return 0;
}
剑指offer做法
void PrintContinuousSequence(int small, int big);
void FindContinuousSequence(int sum)
{
if(sum < 3)
return;
int small = 1;
int big = 2;
int middle = (1 + sum) / 2;
int curSum = small + big;
while(small < middle)
{
if(curSum == sum)
PrintContinuousSequence(small, big);
while(curSum > sum && small < middle)
{
curSum -= small;
small ++;
if(curSum == sum)
PrintContinuousSequence(small, big);
}
big ++;
curSum += big;
}
}
void PrintContinuousSequence(int small, int big)
{
for(int i = small; i <= big; ++ i)
printf("%d ", i);
printf("\n");
}
6)回溯法求数组中和为定值的子数组的组合(方法2 感觉好理解一些)
方法1
void sumn(vector<int> &A, int start, int end, int sum, vector<int> &tmp, vector<vector<int>> &res);
void MainFun(int *nums, int len, int sum)
{
vector<int> A;
int start = 0,end=len-1;
for (int i = 0; i < len; i++)
A.push_back(nums[i]);
vector<int> tmp;
vector<vector<int>> res;
sumn(A, start, end, sum, tmp, res);
for (int i = 0; i < res.size(); i++)
{
for (unsigned int j = 0; j < res[i].size(); j++)
{
cout << res[i][j] << " ";
}
cout << endl;
}
}
void sumn(vector<int> &A, int start, int end, int sum, vector<int> &tmp, vector<vector<int>> &res){
if (start == end && sum == 0)
{
res.push_back(tmp);
}
else if (start == end)
return;
else
{
if (sum >= A[start])
{
tmp.push_back(A[start]);
sumn(A, start + 1, end, sum - A[start], tmp, res);//求start后面和为sum - A[start]的组合
tmp.pop_back();//需要将tmp临时数组恢复原样
}
sumn(A, start + 1, end, sum, tmp, res);//依次递增start求数组后面除了含有start前面数字的子数组组合。
}
}
int main()
{
int nums[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int len = 8;
int sum = 15;
MainFun(nums, len, sum);
system("pause");
return 0;
}
方法2
void Combination_helper(vector<int> array, int begin, int ¤t, int target, vector<int>&path)
{
if (begin >= array.size())
return;
current += array[begin];
path.push_back(array[begin]);
if (current == target)
{
for (int i = 0; i < path.size(); i++)
cout << path[i] << ' ';
cout << endl;
}
Combination_helper(array, begin + 1, current, target, path);
path.pop_back();
current -= array[begin];
/*
int j;
for (j = begin + 1; j < array.size();)
{
if (array[j] == array[begin])
j++;
else
break;
}
*///这个是去掉重复值的作用,看看要求里面有没有去重的题目要求
Combination_helper(array, begin+1, current, target, path);
}
int main()
{
vector<int>array({ 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7 });
//vector<int>array({ 1, 2, 3});
vector<int>path;
int current = 0;
Combination_helper(array, 0, current, 10, path);
system("pause");
return 0;
}
7)求连续子数组的最大和问题(剑指offer T31)并且输出这个最大的子数组ResMaxInt
int maxSubInt(int arr[], int length, vector<int> &ResMaxInt)
{
if (NULL == arr || length <= 0)
return 0;
int TmpSum = 0;
vector<int> TmpMaxInt;
int ResSum = 0;
for (int i = 0; i < length; i++)
{
if (TmpSum <= 0)
{
TmpSum = arr[i];
vector<int> TmporaryMaxInt;
TmporaryMaxInt.push_back(arr[i]);
TmpMaxInt = TmporaryMaxInt;
}
else
{
TmpSum += arr[i];
TmpMaxInt.push_back(arr[i]);
}
if (TmpSum>ResSum)
{
ResSum = TmpSum;
ResMaxInt = TmpMaxInt;
}
}
return ResSum;
}
int main() {
int arr[] = { 1, -2, 3, 10, -4, 7, 2, -5 };
int length = sizeof(arr) / sizeof(arr[0]);
vector<int> ResMaxInt;
cout << maxSubInt(arr, length, ResMaxInt) << endl;
system("pause");
return 0;
}
C++中数组/Vector中去除重复元素
unique函数是一个去重函数,去除相邻中的重复元素(只留一个)。其中,最关键的是:并不是删除并不是把重复的元素删除,而是全部放倒数组的后面。
因为,unique只是去除(相邻)的重复元素,因此,为了去除重复的元素,应该,首先对数组/Vector进行排序,这样保证重复元素在相邻的位置。
unique函数,返回的是去重后的尾地址。
因此对于一个内容为{2, 2, 5, 5, 6}的vector,执行unique函数以后,vector大小并没有改变,只不过顺序变成了{2, 5, 6, 2, 5},并且函数的返回值为:3。
此时需要删除重复元素,只需要将后面的数据全部删除即可。
排序函数(sort)和去重函数都在<algorithm>头文件中。
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 6 7 int main() { 8 vector<int> v; 9 cout << "Number of vector's element : " << endl; 10 int number; 11 cin >> number; 12 for (int i = 0; i < number; i++) { 13 int temp; 14 cin >> temp; 15 v.push_back(temp); 16 } 17 sort(v.begin(),v.end()); 18 v.erase(unique(v.begin(), v.end()), v.end()); 19 for (int i = 0; i < v.size(); i++) { 20 cout << v[i] << " "; 21 } 22 cout << endl; 23 return 0; 24 }<
de53
span class="cnblogs_code_copy">
unique()函数将重复的元素放到vector的尾部然后返回指向第一个重复元素的迭代器再用erase函数擦除从这个元素到最后元素的所有的元素
自己写的去重函数!
int QuChong(int *nums, int len)
{
sort(nums, nums + len);
int i = 0, j = 0;
for ( i = 0; i < len-1; i++)
{
while (nums[i] == nums[i + 1])
{
i++;
}
nums[j++] = nums[i];
}
return j;
}
int main()
{
int nums[10] = { 1, 1,8,2, 3, 4, 5, 6, 7, 8 };
cout << QuChong(nums,10) << endl;
cout << unique(nums, nums + 10)-nums << endl;;
system("pause");
return 0;
}
题目表1)输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出任意一对既可。2)排序不重复的数组求所有对数和为固定值sum的所有对数!3)排序不重复的数组求所有对数差值为固定值的所有对数!4)输入一个非递增非排序的数组(可能有重复数字)和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出所有可能对数,不能重复。5)输入一个正数S,打印出所有和为S的连续正数序列,至少包含两个数;例如输入15,应该输出(1,2,3,4,5)(4,5,6)(7,8)。6)回溯法求数组中和为定值的子数组的组合!7)求连续子数组的最大和问题!
文章正式开始!!
1)输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出任意一对既可。bool FindTwoNumsWithSum(int *nums, int sum, int len, vector<int> &res)
{
bool found = false;
if (len < 1 || nums == NULL)
return found;
int begin = 0, end = len - 1;
while (begin < end)
{
long long cursum = nums[begin] + nums[end];
if (cursum == sum)
{
res.push_back(nums[begin]);
res.push_back(nums[end]);
found = true;
break;
}
if (cursum>sum)
{
end--;
}
else
begin++;
}
return found;
}
int main()
{
int nums[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int len = 8;
int sum = 9;
vector<int> res;
FindTwoNumsWithSum(nums, sum, len, res);
cout << res[0] << res[1] << endl;
// MainFun(nums, len, sum);
system("pause");
return 0;
}
2)排序不重复的数组求所有对数和为固定值sum的所有对数!
void dualSum(int arr[], int len, int sum)
{
int low = 0;
int high = len - 1;
while (low<high)
{
while (arr[high] >= sum)
{
high--;
}
if (arr[low] + arr[high]>sum)
high--;
else if (arr[low] + arr[high]<sum)
low++;
else
{
cout << arr[low] << " + " << arr[high] << " = " << sum << endl;
high--; low++;//仅仅是如果题目要求数组没有重复元素的时候才会成立!
}
}
}
int main()
{
int arr2[] = { 1,2,3,4,5,6 };
int len = 6;
int sum = 7;
dualSum(arr2, len, sum);
system("pause");
return 0;
}
3)排序不重复的数组求所有对数差值为固定值的所有对数!
void dualSum(int arr[], int len, int k)
{
int low = 0;
int high = 0;
while (low<len)
{
if (arr[high] -arr[low]>k)
low++;
else if (arr[high] - arr[low]<k)
high++;
else
{
cout << arr[low] << " chavalue" << arr[high] << " = " << k << endl;
high++;//仅仅是如果题目要求数组没有重复元素的时候才会成立!
}
}
}
int main()
{
int arr[] = { 1, 3, 5, 7, 9, 10 };
int len = 6;
int k = 2;
dualSum(arr, len, k);
system("pause");
return 0;
}
4)输入一个非递增非排序的数组(可能有重复数字)和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对,输出所有可能对数,不能重复。
方法一思路: 用N减去每个元素得到另一个数组b,嵌套循环找到a与b中值相同而位置不同的元素对;空间复杂度2N,时间复杂度O(N^2)。(时间复杂度较高,相当于暴力解法)
void CalcTwoSum(int *nums, int len, int sum, vector<vector<int>> &vec)
{
int *numsB= new int[len];
for (int i = 0; i < len; i++)
{
numsB[i] = sum - nums[i];
}
int index = 0;
for (int i = 0; i < len; i++)
{
int find = numsB[i];
for (int j = i + 1; j < len; j++)
{
if (nums[j] == find)
{
cout << numsB[i] << " + " << nums[i] << endl;
vector<int> tmp;
tmp.push_back(numsB[i]);
tmp.push_back(nums[i]);
vec.push_back(tmp);//注意vector<vector<int>>的赋值方法,不能像二维数组那样单独赋值,需要建一个临时vector<int>tmp来赋值处理!!
}
}
}
}
int QuChong(int *nums, int len)
{
sort(nums, nums + len);
int i = 0, j = 0;
for ( i = 0; i < len-1; i++)
{
while (nums[i] == nums[i + 1])
{
i++;
}
nums[j++] = nums[i];
}
return j;
}
int main()
{
int nums[10] = { 1, 1,8,2, 3, 4, 5, 6, 7, 8 };
int len = QuChong(nums, 10);
int sum = 9;
vector<vector<int>> vec;
CalcTwoSum(nums, len, sum,vec);
system("pause");
return 0;
}
5)输入一个正数S,打印出所有和为S的连续正数序列,至少包含两个数;例如输入15,应该输出(1,2,3,4,5)(4,5,6)(7,8)。
我的做法,好理解一些
void PrintContinuousSequence(int small, int big);
void FindContinuousSequence(int sum)
{
if (sum < 3)
return;
int small = 1;
int big = 2;
int middle = (1 + sum) / 2;
int curSum = small + big;
while (small < middle)
{
if (curSum == sum)
{
PrintContinuousSequence(small, big);
big++;
curSum += big;//这个千万不要漏掉,因为要求满足和为sum的所有组合,否则就停掉了!
}
else if (curSum > sum)
{
curSum -= small;
small++;
}
else
{
big++;
curSum += big;
}
}
}
void PrintContinuousSequence(int small, int big)
{
for (int i = small; i <= big; ++i)
printf("%d ", i);
printf("\n");
}
int main()
{
FindContinuousSequence(15);
system("pause");
return 0;
}
剑指offer做法
void PrintContinuousSequence(int small, int big);
void FindContinuousSequence(int sum)
{
if(sum < 3)
return;
int small = 1;
int big = 2;
int middle = (1 + sum) / 2;
int curSum = small + big;
while(small < middle)
{
if(curSum == sum)
PrintContinuousSequence(small, big);
while(curSum > sum && small < middle)
{
curSum -= small;
small ++;
if(curSum == sum)
PrintContinuousSequence(small, big);
}
big ++;
curSum += big;
}
}
void PrintContinuousSequence(int small, int big)
{
for(int i = small; i <= big; ++ i)
printf("%d ", i);
printf("\n");
}
6)回溯法求数组中和为定值的子数组的组合(方法2 感觉好理解一些)
方法1
void sumn(vector<int> &A, int start, int end, int sum, vector<int> &tmp, vector<vector<int>> &res);
void MainFun(int *nums, int len, int sum)
{
vector<int> A;
int start = 0,end=len-1;
for (int i = 0; i < len; i++)
A.push_back(nums[i]);
vector<int> tmp;
vector<vector<int>> res;
sumn(A, start, end, sum, tmp, res);
for (int i = 0; i < res.size(); i++)
{
for (unsigned int j = 0; j < res[i].size(); j++)
{
cout << res[i][j] << " ";
}
cout << endl;
}
}
void sumn(vector<int> &A, int start, int end, int sum, vector<int> &tmp, vector<vector<int>> &res){
if (start == end && sum == 0)
{
res.push_back(tmp);
}
else if (start == end)
return;
else
{
if (sum >= A[start])
{
tmp.push_back(A[start]);
sumn(A, start + 1, end, sum - A[start], tmp, res);//求start后面和为sum - A[start]的组合
tmp.pop_back();//需要将tmp临时数组恢复原样
}
sumn(A, start + 1, end, sum, tmp, res);//依次递增start求数组后面除了含有start前面数字的子数组组合。
}
}
int main()
{
int nums[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int len = 8;
int sum = 15;
MainFun(nums, len, sum);
system("pause");
return 0;
}
方法2
void Combination_helper(vector<int> array, int begin, int ¤t, int target, vector<int>&path)
{
if (begin >= array.size())
return;
current += array[begin];
path.push_back(array[begin]);
if (current == target)
{
for (int i = 0; i < path.size(); i++)
cout << path[i] << ' ';
cout << endl;
}
Combination_helper(array, begin + 1, current, target, path);
path.pop_back();
current -= array[begin];
/*
int j;
for (j = begin + 1; j < array.size();)
{
if (array[j] == array[begin])
j++;
else
break;
}
*///这个是去掉重复值的作用,看看要求里面有没有去重的题目要求
Combination_helper(array, begin+1, current, target, path);
}
int main()
{
vector<int>array({ 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7 });
//vector<int>array({ 1, 2, 3});
vector<int>path;
int current = 0;
Combination_helper(array, 0, current, 10, path);
system("pause");
return 0;
}
7)求连续子数组的最大和问题(剑指offer T31)并且输出这个最大的子数组ResMaxInt
int maxSubInt(int arr[], int length, vector<int> &ResMaxInt)
{
if (NULL == arr || length <= 0)
return 0;
int TmpSum = 0;
vector<int> TmpMaxInt;
int ResSum = 0;
for (int i = 0; i < length; i++)
{
if (TmpSum <= 0)
{
TmpSum = arr[i];
vector<int> TmporaryMaxInt;
TmporaryMaxInt.push_back(arr[i]);
TmpMaxInt = TmporaryMaxInt;
}
else
{
TmpSum += arr[i];
TmpMaxInt.push_back(arr[i]);
}
if (TmpSum>ResSum)
{
ResSum = TmpSum;
ResMaxInt = TmpMaxInt;
}
}
return ResSum;
}
int main() {
int arr[] = { 1, -2, 3, 10, -4, 7, 2, -5 };
int length = sizeof(arr) / sizeof(arr[0]);
vector<int> ResMaxInt;
cout << maxSubInt(arr, length, ResMaxInt) << endl;
system("pause");
return 0;
}
相关文章推荐
- 树状数组 OJ题目大汇总----czyuan原创
- 数组相关题目汇总
- 数组值和下标是同一值域的题目汇总
- java将固定长度的byte数组转成String,并去掉后面多余的0
- 题目:返回一个一维循环数组中最大子数组的和
- 其他题目---在有序旋转数组中找到一个数
- iOS数组方法汇总
- 九度oj 题目1055:数组逆置
- 剑指offer面试题目:数字在排序数组中出现的次数
- 固定数组NSArray 和 可变NSMutableArray
- 面试10大算法汇总+常见题目解答
- 从列表中或数组中随机抽取固定数量的元素组成新的数组或列表
- 剑指offer面试题java实现之题4之相关题目:两个排序数组合并
- 专题待刷题目汇总
- 解法汇总:找数组中前K大(小)个数
- 固定分隔符字符串与数组互转及ArrayList与数组(Array)互转
- 数组循环:循环多个li 每个li 固定N条数据
- 【华为】题目:有两个数组a,b,大小都为n,数组元素的值任意,无序; 要求: 通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小。
- Web/JAVA 简单题目汇总