这道题,要求cut ribbons,怎么cut都行,只要能cut出k条丝带就行,不是每条丝带都需要被cut,cut完没用的可以丢弃,求能cut出k条丝带的情况下,丝带的最大长度。你可以想象这样的场景,客户给你一堆丝带,让你帮忙cut出几条丝带,希望丝带越长越好,剩下的丝带就不要了。
暴力求解方法很简单,就是从数组里的最大数开始,每次减1,挨个试,作为被除数去除每个数,如果得到的商的总数等于k了,把数值返回即可, 如果都试到1了,还达不到k,就返回0.
我的暴力算法,时间复杂度O(n*m), n是数组里的最大数的数值,m是数组长度,会TLE:
public int maxLength(int[] ribbons, int k) { Arrays.sort(ribbons); int max = ribbons[ribbons.length-1]; for(int i=max;i>=1;i--){ if(cutRibben(ribbons, i, k)) return i; } return 0; } public boolean cutRibben(int[] ribbons, int length, int k) { int count = 0; for (int ribbon: ribbons) { count += (ribbon / length); if(count>=k) return true; } return false; }
既然时间超时了,咱就得想想有没有时间复杂度好一点的算法,那么自然就想到了binary search, 时间复杂度是O(logn*m), n是数组里的最大数的数值, m是数组长度:
public int maxLength(int[] ribbons, int k) { Arrays.sort(ribbons); int max = ribbons[ribbons.length-1]; int low = 1, high = max, mid = low, res = 0; while(low <= high){ mid = (low+high)/2; if(cutRibben(ribbons, mid, k)){ low = mid+1; res = mid; } else high = mid-1; } return res; } public boolean cutRibben(int[] ribbons, int length, int k) { int count = 0; for (int ribbon: ribbons) { count += (ribbon / length); if(count>=k) return true; } return false; }
利用万能模版:
class Solution { public int maxLength(int[] ribbons, int k) { int r=0; for(int i=0;i<ribbons.length;i++){ r = Math.max(r, ribbons[i]); } int l=1; while(l+1<r){ int mid = (l+r)/2; int count = getRibbons(ribbons, mid); if(count>=k){ l=mid; }else{ r=mid; } } int right = getRibbons(ribbons, r); if(right>=k) return r; int left = getRibbons(ribbons,l); if(left>=k) return l; else return 0; } private int getRibbons(int[] ribbons, int n){ int res = 0; for(int i=0;i<ribbons.length;i++){ res+=ribbons[i]/n; } return res; } }