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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

数组精选题目三连(5)

發(fā)布時(shí)間:2023/12/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数组精选题目三连(5) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

子數(shù)組的最大累加和問(wèn)題

輸入一個(gè)整形數(shù)組,求數(shù)組中連續(xù)的子數(shù)組使其和最大。比如,數(shù)組x

應(yīng)該返回 x[2..6]的和187.

?

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

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;} }

分別枚舉每一個(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),乘起來(lái)O(N^3).(注意可能產(chǎn)生時(shí)間更大的錯(cuò)覺(jué))。找出所有子數(shù)組中最大的即可。

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;} }

預(yù)處理出每一個(gè)以第一個(gè)元素開(kāi)始,第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)

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; }

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

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

沒(méi)有枚舉,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í)間省在哪里了?我們省掉了許多沒(méi)必要的計(jì)算,計(jì)算i時(shí),之前的數(shù)組和已經(jīng)都計(jì)算過(guò),樸素算法并沒(méi)有記錄下來(lái),而是重復(fù)計(jì)算,造成時(shí)間浪費(fèi)。算法優(yōu)化的過(guò)程就是去掉重復(fù)計(jì)算的過(guò)程。
?

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èn)題

給一個(gè)矩陣,請(qǐng)找出一個(gè)矩陣中,和最大的子矩陣。

?

?

?

如果大家看懂了之前的講解,我給個(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行

然后壓縮成一維來(lái)做

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

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

然后按一維dp來(lái)做就好
?

public class SubMatrixMaxSum {public static int maxSum(int[][] m) {if (m == null || m.length == 0 || m[0].length == 0) {return 0;}int max = Integer.MIN_VALUE;int cur = 0;int[] s = null; // 累加數(shù)組for (int i = 0; i != m.length; i++) {s = new int[m[0].length];for (int j = i; j != m.length; j++) {cur = 0;for (int k = 0; k != s.length; k++) {s[k] += m[j][k];cur += s[k];max = Math.max(max, cur);cur = cur < 0 ? 0 : cur;}}}return max;}public static void main(String[] args) {int[][] matrix = { { -90, 48, 78 }, { 64, -40, 64 }, { -81, -7, 66 } };System.out.println(maxSum(matrix));}}

子數(shù)組的最大累乘積

題目:

給定一個(gè)double類(lèi)型的數(shù)組arr,其中的元素可正、可負(fù)、可為0。返回子數(shù)組累乘的最大乘積。

思路:

假設(shè)以arr[i-1]結(jié)尾的數(shù)組最小累乘積為min,最大累乘積為max,那么以arr[i]結(jié)尾的數(shù)組的最大累乘積可能有三種情況。

  • max*arr[i]//本身乘之前的最大累乘
  • min*arr[i]//可能是負(fù)負(fù)得正變成最大的
  • arr[i]//可能就是它本身,比如之前的max小于1
public class SubArrayMaxProduct {public static double maxProduct(double[] arr) {if (arr == null || arr.length == 0) {return 0;}double max = arr[0];double min = arr[0];double res = arr[0];double maxEnd = 0;double minEnd = 0;for (int i = 1; i < arr.length; ++i) {maxEnd = max * arr[i];minEnd = min * arr[i];max = Math.max(Math.max(maxEnd, minEnd), arr[i]);min = Math.min(Math.min(maxEnd, minEnd), arr[i]);res = Math.max(res, max);}return res;}public static void main(String[] args) {double[] arr = { -2.5, 4, 0, 3, 0.5, 8, -1 };System.out.println(maxProduct(arr));}}

?

總結(jié)

以上是生活随笔為你收集整理的数组精选题目三连(5)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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