因为作业代码涉及隐私,所以文章只提供解题思路和有关拓展,若实在需要源码可以私信
作业:
习题课作业:
用更快更好的算法算上课第一个演示程序(找前个数位之和等于后几个数位之和的数的个数。如abcdef,
需a+b+c=d+e+f)。并且能够在程序中比较方法之间的优劣:内存占用,运行时间等参数。
全部跳过直接看解题算法点这里:↓↓↓↓↓↓
写在前面
1, 如何在递归中使用指针来表示数组结尾(传入一个一直指向指针头部的参数, 并利用它表示出数组的范围)
2,指针参数的自增需要注意是先增还是后增,尾递归add(arr++, p)和add(++arr, p)是不同的结果
3,多维数组的声明需要将双箭头用空格隔开 std::vector<std::vector<float> > //right!
4,for循环的终止条件和变化方式是不一定必须写在开头括号里的,也可以写在循环体内部以便灵活使用
5,vector的push_back,只可以push进其“规定类型”的“一个”元素。
eg:三维数组可push进一个二维数组,一维int数组push进入一个int
6,在多层循环中可以将一些语句尽量放在外层循环中,时间复杂度不变,但是可以减少运算量
7,通过更缜密的数学推理,可以获得更优美的代码
有关拓展
|| 为了求数组中每一个数的平方和,写了个使用指针的递归函数 稍微复习
//明确函数功能:求出放入的数组的平方
//定好尾头:尾:数组中无值 头:第一个数求好平方后加第二个数的平方
int add(int* arr, int *p) {
if(arr > p+(sizeof(p)/sizeof(*p)) )
return 0;
return *arr * (*arr) + add(++arr,p);
}
|| 可以用c++自制一个python中的map高级函数,用于返回数组的个元素平方和
int myMap(int (*func)(int), vector<int> arr) {
int res = 0;
for (vector<int>::iterator it = arr.begin(); it != arr.end(); it++) {
res += (*func)(*it);
}
return res;
}
int sqrt(int x) {return x * x;}
-> vector<int> arr = { 1,2,3,4,5 };
-> int res = myMap(sqrt, arr);
|| 回忆类似写法的leetcode题,使用双指针使得数组返回三数之和的
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解题思路:最重要的是去重操作(即跳步操作)
#include<iostream>
using namespace std;
#include <vector>
#include <algorithm>
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if (nums.size() < 3) return res;
sort(nums.begin(), nums.end());
for (vector<int>::iterator it = nums.begin(); it != nums.end() - 2;) {
int tmp = *it;
if (tmp > 0) break;
int target = 0 - tmp;
vector<int>::iterator left = it + 1;
vector<int>::iterator right = nums.end() - 1;
while (left < right) {
if (*right < 0) break;
if (*left + *right < target) {
int v = *left;
while (left != right && *left == v) left++; //跳过相等的元素
}
else if (*left + *right > target) {
int v = *right;
while (left != right && *right == v) right--;//跳过相等的元素
}
else {
vector<int> tmp_res{ tmp,*left,*right };
res.push_back(tmp_res);
int v = *left;
while (left != right && *left == v) left++;//跳过相等的元素
v = *right;
while (left != right && *right == v) right--;//跳过相等的元素
}
}
while (it != nums.end() - 2 && *it == tmp) it++;//跳过相等的元素
}
}
};
解题思路:
解优化题:正常的思路
正常的思路是使用多层循环,在多层循环中可以将一些语句尽量放在外层循环中,时间复杂度不变,
但是可以减少运算量 eg: 将a+b在外层提前运算后,再将其和放进内层中运算
#include<iostream>
using namespace std;
#include <time.h>
int main(int argc, char** argv) {
int num = 0;
int res = 0;
int ab, abc, de;
for (int a = 0; a < 6; a++)
for (int b = 0; b < 6; b++) {
ab = a + b;
for (int c = 0; c < 6; c++)
{
abc = ab + c;
for (int d = 0; d < 6; d++)
for (int e = 0; e < 6; e++){
de = d + e;
for (int f = 0; f < 6; f++) {
if (abc == de + f)
res++;
}
}
}
}
cout<< "////////////" << endl;
cout << "result:\t " << res << endl;
cout << "///////////" << endl;
return 0;
}
更高效的算法
通过位数最高值为 0~6 的 6位数 寻找规律,可以获得下图规律
6位数 需要 分成两个3位数,若该6位数满足条件则其两个3位数之和相等,求出三位数每种和可能出
现的种类,其该和的三位数种类^2 (排列组合) 即成功搭配出所有满足条件的6位数。
eg: 和为2的三位数 110 /101/011 /020/200/002 它们进行搭配可得出满足条件的6位数
因此我们将目光放在3位数上
1,先获得三位数为 00n ,0nn,和nnn的情况,即三位数的位数之和为1-18的所有情况,我们使用矩阵
注意:(x,y)中,x是可能的位数和,通过y可以将每个x值对应的y值求和得到∑y,
2,如图:黄色部分每个位上可能出现的数字,黄色部分下方/右方的数字是其对应黄色数字已有的搭配
图一表示两位数与两位数,其每个和(即x)的搭配结果(即∑y)称为图二对应的左列!
注意:两位数之间的搭配结果刚好是个d=1递增的数列 【1,2,3,4,5,6,5,4,3,2,1】
重复以上步骤,可求出结果,修改相关数据可求出0~x 任意位数的符合条件解
以下 关于0~6 的 6位数 的运算代码,根据规律改动相关数据即可称为 0~x 任意位数 的代码
#include<iostream>
using namespace std;
#include<vector>
int*** spisok() {
int*** arr_np3D = arr_np3D = (int***)new int** [11];
for (int x = 0; x < 11; x++)
{
arr_np3D[x] = (int**)new int* [6];
}
for (int x = 0; x < 11; x++)
{
int arr[] = { 1,2,3,4,5,6,5,4,3,2,1 };
for (int y = 0; y < 6; y++)
{
arr_np3D[x][y] = new int[2];
arr_np3D[x][y][0] = x + y + 3;
arr_np3D[x][y][1] = arr[x];
}
}
return arr_np3D;
}
int getRes(){
int*** arr_np3D = spisok();
int arr[16] = {0};
int res = 0;
for (int x = 0; x < 11; x++)
{
for (int y = 0; y < 6; y++)
{
arr[arr_np3D[x][y][0] - 3] += arr_np3D[x][y][1];
}
}
for (int i = 0; i < 16; i++)
{
res += arr[i]*arr[i];
}
return res;
}
需要编写下列函数:
1,求2位数间搭配数,参数为每一个 位数上的最大数,返回值为其各种和搭配数的数组
2,求3位数间的搭配数,参数为1中的数组,创建三维数组 表示3位数间的搭配数情况,返回值为其各种和搭配数的数组
3,利用数组求平方和即为结果