对数组进行k次操作,以便每次将最大值除以2并四舍五入。 经过这k次操作后,我需要找到它的最小值。 k和数组num> 1中的所有数字。 minSum方法接收一个名为num和整数k的数组。 适用于我的具有很差的时间复杂性的原始Python代码是:
String[] categories = listCategories.toArray(new String[listCategories.size()]);
Double[] values = listValues.toArray(new Double[listValues.size()]);
final int numOfPoints = categories.length;
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange);
final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange);
XDDFPieChartData.Series firstSeries = (XDDFPieChartData.Series) pie.getSeries().get(0);
firstSeries.replaceData(categoriesData, valuesData);
firstSeries.setTitle(chartTitle, chart.setSheetTitle(chartTitle, 0));
firstSeries.setExplosion(25);
chart.plot(pie);
我也尝试过首先对数组进行排序,但是随后我尝试的每个算法都失败了。 您能想到一种具有良好时间复杂度的好的算法吗?最好不使用特殊进口。
答案 0 :(得分:3)
标准库(即无特殊导入)带有heapq
模块,该模块使算法O(3n + k *(2 lg n))=> O(lg n):
import math
import heapq
def minSum(num, k):
heap = [-n for n in num] # negate values for max-heap
heapq.heapify(heap)
for i in range(k):
# Find max value
max_value = heapq.heappop(heap)
# Change max value to rounded half
# use floor since we've negated the values
heapq.heappush(heap, math.floor(max_value/2))
# Calculate minimum sum
return -sum(heap) # reverse polarity again
更新1:(来自@ raury-daulton的评论)结合了pop / push,O(3n + k *(lg n))=> O(lg n):
def minSum(num, k):
heap = [-n for n in num] # negate values for max-heap
heapq.heapify(heap)
for i in range(k):
max_value = heap[0]
heapq.heapreplace(heap, math.floor(max_value/2))
# Calculate minimum sum
return -sum(heap) # reverse polarity again
更新2:直接使用最大堆O(2n + k *(lg n))=> O(lg n)
def heapreplace_max(heap, item):
"We need to implement this ourselves from primitives."
returnitem = heap[0]
heap[0] = item
heapq._siftup_max(heap, 0)
return returnitem
def minSum(num, k):
heap = num # alias for consistency with other samples
heapq._heapify_max(heap) # make it a max heap (no negation hack)
for i in range(k):
max_value = heap[0]
heapreplace_max(heap, math.ceil(max_value/2))
return sum(heap)
更新3:的最终优化(这要求输入数组必须是int
的数组)。
def minSum(num, k):
heap = num # alias for consistency with other samples
heapq._heapify_max(heap)
for i in range(k):
max_value = heap[0]
if max_value == 1: # exit early if there is no more work
break
new_val = (max_value >> 1) + (max_value & 1) # same as, but much faster than math.ceil(max_value/2)
heapreplace_max(heap, new_val)
return sum(heap)
k的上限是sum(math.floor(math.log(v, 2)+1) for v in num)
(即表示所有输入数字所需的总位数)。预计算循环变量可能比在循环中包含if max_value == 1:
更快,即:
for i in range(min(k, int(sum(floor(log(v, 2)+1) for v in num)))):
max_value = heap[0]
new_val = ...
但是我还没有实际测量。
答案 1 :(得分:0)
您的代码的每个循环都会遍历整个数组两次,因此您的算法的执行顺序为kn
,其中n
是数组的长度。您可以通过在每次操作后不取总和来加快速度,因为您的操作“除以2并四舍五入”不能减少总和。 (这取决于没有一个数组值可以为负的事实。)仅在应用所有k
操作之后取总和。这将使您的执行量减少大约一半。
另一个更重要的优化是避免在数组中搜索最大值。我建议您使用heapq(优先级队列)结构。您存储数组值的负数,因此heapq的最小值是数组最大值的负数。然后,找到最大数组值是一个顺序1
操作,而更改它是一个顺序log(n)
操作。使用heapreplace
方法进行替换,以获取最大速度。使用heapify
将数组放入堆是唯一的命令n
操作,但这仅发生一次。
如果有时间,我将在今天晚些时候添加代码。该算法确实需要一次导入,即heapq
,但是它在标准库中,因此实际上不算作“特殊导入”。
答案 2 :(得分:0)
O(n + 10000)= O(n)的解决方案是可能的,每次为了使最终答案最小化,您应该选择最大x值,您可以使用说堆来解决问题,但是由于数字数量少的想法可以在更短的时间内解决问题。
<button
type="submit"
disabled={!fistname && !lastname}
/>
答案 3 :(得分:0)
这个在js中?
s= [89,62,3,4,55,6]
console.log(s.length)
n=3
for(k=0; k < n; k++){
max = s[0]
j=0
for(i=0; i < s.length; i++){
if(max < s[i]) {
max = s[i]
j=i
}
if(i === s.length-1){
s[j]= s[j]/2
}
}
}
console.log(s)
答案 4 :(得分:-1)
Java : Minimum sum K operations
public static int minimumSum(int[] A, int k) {
int sum = 0;
Arrays.sort(A);
for (int i = 0; i < k; i++) {
int len = A.length;
if (A[len - 1] % 2 == 0) {
A[len - 1] = A[len - 1] / 2;
} else {
A[len - 1] = (int) Math.ceil((double) A[len - 1] / 2);
}
Arrays.sort(A);
}
for (int i = 0; i < A.length; i++) {
sum += A[i];
}
return sum;
}