編程作業(1)修正

因爲作業代碼涉及隱私,所以文章只提供解題思路和有關拓展,若實在需要源碼可以私信

作業:

習題課作業:
	用更快更好的算法算上課第一個演示程序(找前個數位之和等於後幾個數位之和的數的個數。如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, 函數作爲參數傳到另一個函數時,使用函數指針, 該函數的參數只需要寫出數據類型就好    
	eg: func2(int (*func)(int, int) )
8,通過更縝密的數學推理,可以獲得更優美的代碼

有關拓展

|| 爲了求數組中每一個數的平方和,寫了個使用指針的遞歸函數 稍微複習

//明確函數功能:求出放入的數組的平方
//定好尾頭:尾:數組中無值  頭:第一個數求好平方後加第二個數的平方 
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,利用數組求平方和即爲結果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章