日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构作业1 讲解和拓展

發(fā)布時(shí)間:2023/12/13 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构作业1 讲解和拓展 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原題來自雪梨教育

http://www.edu2act.net/task/list/checked/

題后給出講解和擴(kuò)展

任務(wù)1_1 比較下列算法的時(shí)間復(fù)雜度

任務(wù)描述:

? ? 下面給出4個(gè)算法,請(qǐng)分析下列各算法的時(shí)間復(fù)雜度,請(qǐng)寫清楚題號(hào),并將每個(gè)小題的分析過程寫出來,并給出分析結(jié)果。

(1)

for(i = 1; i <= n; i++)scanf("%d", &num[i]); ans = num[1]; for(i = 1; i <= n; i++) {for(j = i; j <= n; j++) {s = 0;for(k = i; k <= j; k++)s += num[k];if(s > ans)ans = s;} }

(2)

for(i = 1; i <= n; i++)scanf("%d", &num[i]); sum[0] = 0; for(i = 1; i <= n; i++) {sum[i] = num[i] + sum[i - 1]; }ans = num[1]; for(i = 1; i <= n; i++) {for(j = i; j <= n; j++) {s = sum[j] - sum[i - 1];if(s > ans) ans = s;} }

(3)

int solve(int left, int right) {if(left == right)return num[left];mid = (left + right) / 2;lans = solve(left, mid);rans = solve(mid + 1, right);sum = 0, lmax = num[mid], rmax = num[mid + 1];for(i = mid; i >= left; i--) {sum += num[i];if(sum > lmax) lmax = sum;}sum = 0;for(i = mid + 1; i <= right; i++) {sum += num[i];if(sum > rmax) rmax = sum;}ans = lmax + rmax;if(lans > ans) ans = lans;if(rans > ans) ans = rans;return ans; }int main(void) {scanf("%d", &n);for(i = 1; i <= n; i++)scanf("%d", &num[i]);printf("%d\n", solve(1, n));return 0; }

(4)

for(i = 1; i <= n; i++)scanf("%d", &num[i]);num[0] = 0; ans = num[1]; for(i = 1; i <= n; i++) {if(num[i - 1] > 0) num[i] += num[i - 1];elsenum[i] += 0;if(num[i] > ans) ans = num[i]; }

任務(wù)1_2 數(shù)字反轉(zhuǎn)的時(shí)空復(fù)雜度

任務(wù)描述:

下面兩個(gè)函數(shù)fun1和fun2都是實(shí)現(xiàn)對(duì)整數(shù)的逆序輸出功能,請(qǐng)根據(jù)下面題目要求,給出答案。

(1) 請(qǐng)分析函數(shù)fun1的時(shí)間復(fù)雜度和空間復(fù)雜度;

(2) 請(qǐng)分析函數(shù)fun2的時(shí)間復(fù)雜度和空間復(fù)雜度。

代碼如下:

?

int fun1(int n) {int rev = 0;while (n != 0) {int pop = n % 10;n /= 10;rev = rev * 10 + pop;}return rev; }void fun2(int n) {printf("%d", n % 10);if(n / 10 != 0)fun2(n / 10); }int main(void) {printf("%d\n", fun1(10203)); fun2(10203);return 0; }

?

講解:

說頻度,或者求和公式往上堆出來的解釋,?都是耍流氓

沒有專業(yè)名詞的講解才是講解

?

直接粘貼我交的作業(yè)

?

先用數(shù)學(xué)說明,后解釋題意并分析。

分別為O(N^3),O(N^2),O(N*logN),O(N).

數(shù)學(xué):

1)第一個(gè)循環(huán)O(N)

對(duì)于每一個(gè)i來說,j執(zhí)行n-i+1次,對(duì)于每個(gè)j來說,k執(zhí)行j-i+1次,我們把常數(shù)去掉,

對(duì)于每一個(gè)i,執(zhí)行的常數(shù)操作為1+2+3+...+(n-i+1),等差數(shù)列[1+(n-i+1)](n-i+1)/2約等于(n-i)^2而i=1,2,....n,分別執(zhí)行常熟操作次數(shù)為(n-1)^2,(n-2)^2......1^2,0^2.,可以看出是平方函數(shù)求和,而對(duì)x^2求和n項(xiàng)的公式為(n^3)/3+(n^2)/2+n/6,我們只看最大,去掉常數(shù),也就是O(N^3).

O(N^3)+O(N)當(dāng)然還是O(N^3)

2)前兩個(gè)循環(huán)都是O(N),下面兩重循環(huán),對(duì)于每個(gè)i,j執(zhí)行n-i次,當(dāng)i=1,2....n,j執(zhí)行次數(shù)為n-1,n-2....1,0,可以看出是等差數(shù)列求和,最高項(xiàng)是(n^2)/2,去掉系數(shù),時(shí)間復(fù)雜度為O(N^2).

加起來:O(N^2)+O(N)+O(N)=O(N^2)

3)分析solve函數(shù):采用二分,將序列分成兩份,直到不可再分,執(zhí)行的兩個(gè)循環(huán)加起來就是遍歷一遍左右端點(diǎn)之間數(shù)的復(fù)雜度。我們看所有從長(zhǎng)度為1的子數(shù)組,數(shù)量為n,合并后,所有長(zhǎng)度為2的子數(shù)組,數(shù)量為n/2,再合并,長(zhǎng)度為4的子數(shù)組,數(shù)量為n/4,我們會(huì)發(fā)現(xiàn)對(duì)于每個(gè)長(zhǎng)度1,2^2,2^4,2^3,的子數(shù)組,遍歷一遍所有長(zhǎng)度一樣的子數(shù)組的復(fù)雜度都是O(N),設(shè)一共有x種長(zhǎng)度,2^x=n,很明顯x=log(2,n)。

每次O(N),次數(shù)o(log(2,n)),乘起來O(n*logn)

看main函數(shù),接收數(shù)據(jù)是O(N),加solve,等于O(n*logn)

4)接收數(shù)據(jù)O(N),一個(gè)循環(huán)O(N),加起來O(N)。

?

下面我根據(jù)完成的功能和思路分析一下:(思路簡(jiǎn)單,文字略長(zhǎng),不太會(huì)敘述)

這四個(gè)代碼完成的功能都是求最大子數(shù)組(注意用詞準(zhǔn)確,子數(shù)組連續(xù),子序列可以不連續(xù))。

1)分別枚舉每一個(gè)子數(shù)組的起點(diǎn)和終點(diǎn),也就是i和j,對(duì)于每一個(gè)起點(diǎn)和終點(diǎn),對(duì)中間部分求和,也就是k循環(huán)。顯然有n個(gè)起點(diǎn)n個(gè)終點(diǎn)(去重減半,不影響復(fù)雜度),所以子數(shù)組數(shù)量為O(N^2),對(duì)于每個(gè)子數(shù)組,我們要遍歷一下求和,子數(shù)組長(zhǎng)度1-n不等,遍歷一遍平均O(N),乘起來O(N^3).(注意可能產(chǎn)生時(shí)間更大的錯(cuò)覺)。找出所有子數(shù)組中最大的即可。

2)預(yù)處理出每一個(gè)以第一個(gè)元素開始,第i個(gè)元素結(jié)尾的子數(shù)組和,還是枚舉每個(gè)起點(diǎn)終點(diǎn),但是我們求和時(shí)直接減就可以了,不用遍歷。對(duì)于每個(gè)子數(shù)組,操作為O(1),子數(shù)組數(shù)量O(N^2),所以總時(shí)間O(N^2).

3)二分,求左右兩邊最大子數(shù)組,取最大。但是還有一種情況:包含斷點(diǎn)的那些子數(shù)組也要考慮,請(qǐng)思考那兩個(gè)那兩個(gè)循環(huán)為什么那么寫?最后邏輯為何正確?

4)動(dòng)態(tài)規(guī)劃入門思想

沒有枚舉,num[i]的含義是以下標(biāo)i結(jié)尾的所有子數(shù)組中最大的。

遍歷數(shù)組,對(duì)于第i個(gè)元素,它的所有子數(shù)組下標(biāo)范圍有[1,i],[2,i].....[i-1,i],還有它自己,我們看i-1個(gè)元素,他的子數(shù)組為[1,i-1],[2,i-1].....[i-1]。請(qǐng)想num[i]的含義,我們求i結(jié)尾的,只要把i-1結(jié)尾的最大加上i就好了,當(dāng)然如果i-1結(jié)尾最大子數(shù)組是負(fù)的,i結(jié)尾最大子數(shù)組就是它本身。

為什么O(N)?時(shí)間省在哪里了?我們省掉了許多沒必要的計(jì)算,計(jì)算i時(shí),之前的數(shù)組和已經(jīng)都計(jì)算過,樸素算法并沒有記錄下來,而是重復(fù)計(jì)算,造成時(shí)間浪費(fèi)。算法優(yōu)化的過程就是去掉重復(fù)計(jì)算的過程。

?

1-2

fun1:時(shí)間O(log10,N),空間O(1)

FUN2:時(shí)間O(log10,N),空間O(log10,N)

第一個(gè)函數(shù)只是有限幾個(gè)變量,所以空間O(1),一個(gè)循環(huán)n每次縮小十倍,時(shí)間O(log10,N).

第二個(gè)函數(shù)遞歸調(diào)用,這個(gè)函數(shù)沒執(zhí)行完就跳到另外的函數(shù),會(huì)壓函數(shù)棧,空間O(log(10,n)),

而時(shí)間還是O(log10,N),復(fù)雜度沒變但是時(shí)間稍長(zhǎng)。

?

?

?

作業(yè)完了

?

我們說拓展:如何求二維數(shù)組的最大和子數(shù)組?

如果大家看懂了之前的講解,我給個(gè)提示:利用第二個(gè)代碼和第四個(gè)代碼思想的結(jié)合

?

?

解釋:

1? ?2? 3? ?4

-1 -2? 1? ?2

1? ?3? ?-2? 1

-1? -2? -1? -3

如圖是前三行整體最大

怎么做呢?

先用第二個(gè)代碼的思想,我們進(jìn)行預(yù)處理

每個(gè)數(shù)代表這一列到這個(gè)數(shù)位置截止,累加和。

1? 2? 3? 4

0? 0? 4? 6

1? 3? 2? 7

0? 1? 1? 4

然后,我們枚舉每一列的起點(diǎn)和終點(diǎn)分別為第0,1,2,3行

然后壓縮成一維來做

比如求1-3行的這個(gè)矩形,我們拿0和3行減一下就行了

0-1,1-2,1-3,4-4=-1,-1,-2,0就是1-3行壓縮后的結(jié)果

然后按一維do來做就好

時(shí)間復(fù)雜度:n行m列:

預(yù)處理:每個(gè)元素弄一遍,O(N*M)

枚舉壓縮:起點(diǎn)n個(gè)終點(diǎn)n個(gè),數(shù)量:O(N^2),對(duì)于每個(gè)矩陣,我們壓縮為一維,只要減一下就好,O(M)

dp:每個(gè)一維O(M)

?

求最大子長(zhǎng)方體或者多維也一樣,預(yù)處理,三維壓二維,二維壓一維,按一維dp來做。

?

算法優(yōu)化的過程就是去除重復(fù)計(jì)算過程的過程

想象一下沒有預(yù)處理沒有dp的樸素做法時(shí)間是多少?

算法的魅力

?

以前寫過這個(gè)問題的總結(jié)了,所以這次可能寫的有點(diǎn)簡(jiǎn)單。看不懂再去之前博客找找

總結(jié)

以上是生活随笔為你收集整理的数据结构作业1 讲解和拓展的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。