【刷题笔记】--lintcode木头加工(java)
木頭加工
題目描述
有一些原木,現(xiàn)在想把這些木頭切割成一些長度相同的小段木頭,需要得到的小段的數(shù)目至少為?k。當(dāng)然,我們希望得到的小段越長越好,你需要計(jì)算能夠得到的小段木頭的最大長度。
注意事項(xiàng)
木頭長度的單位是厘米。原木的長度都是正整數(shù),我們要求切割得到的小段木頭的長度也要求是整數(shù)。無法切出要求至少?k?段的,則返回?0?即可。
樣例
有3根木頭[232, 124, 456],?k=7, 最大長度為114,則返回114。
簡單分析
暴力解法就是從1開始遍歷所有的長度,對(duì)于長度L,計(jì)算所有木頭可以切多少段,如果滿足要求就記錄長度并繼續(xù)增加,如果不滿足則終止循環(huán),并返回記錄的長度L。
暴力解法的復(fù)雜度是O(n*m)其中n是木頭數(shù)組的長度,m指的是數(shù)組中數(shù)據(jù)最大值,因?yàn)閷?duì)于每一個(gè)長度都需要遍歷整個(gè)數(shù)組,而最后的數(shù)組大小基本正比于數(shù)組中的最大值。
在暴力解法的基礎(chǔ)上,我們可以改進(jìn)為O(n*log m)復(fù)雜度的算法,先找到最長的木頭長度maxl(數(shù)組中的最大值),然后利用二分法搜索0-maxl之間的值,最后輸出滿足要求的最大值。
程序
public int woodCut(int[] L, int k) {int l = L.length;if(l == 0) return 0; //如果輸入數(shù)組L為空則直接返回0int maxL = L[0]; //找到數(shù)組中的最大值for(int i = 1; i < l; i++){int temp = L[i];if(temp > maxL){maxL = temp;}}int up = maxL;int down = 0;int res = 0;while(up >= down){ //二分法查找int len = down + (up - down)/2;if(len == 0) return 0;int c = count(L,len);if(c >= k) {res = res>=len?res:len;down = len + 1;} //符號(hào)是>=else if(c < k) up = len - 1;}return res;}public int count(int[] L,int length){int num = 0;for(int l:L){num += l/length;}return num;} }上面的算法運(yùn)行速度仍然很慢,在lintcode網(wǎng)站提交以后運(yùn)行時(shí)間是3s以上,很慢。大家可以試著優(yōu)化一下。
ps:提供一個(gè)教訓(xùn),我是想法是,當(dāng)最后分割的長度正好是k段時(shí),我再更新最終的結(jié)果長度res。也就是把二分搜索部分修改如下
while(up >= down){int len = down + (up - down)/2;if(len == 0) return 0;int c = count(L,len);if(c < k) up = len - 1;else{ if(c == k) res = res>=len?res:len; down = len + 1;}}首先,上面這個(gè)程序是錯(cuò)誤的。如果最大值對(duì)應(yīng)的段數(shù)不是k的話,那我們的程序就無法輸出正確結(jié)果。這是我個(gè)人嘗試中的一點(diǎn)經(jīng)驗(yàn)。
一些閑話:
博客這邊更新的題目都是略帶難度的,還有一些只需要簡單技巧的題目就不在這里寫了,盡量寫在github上了。一個(gè)不算項(xiàng)目的小項(xiàng)目,現(xiàn)在內(nèi)容還比較少,大家喜歡可以支持一下。
轉(zhuǎn)載于:https://www.cnblogs.com/GuoYaxiang/p/6127404.html
總結(jié)
以上是生活随笔為你收集整理的【刷题笔记】--lintcode木头加工(java)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 画原型图的一些技巧
- 下一篇: android百度地图小人头像怎么做,出