[英]How can I solve this problem, and what kind of algorithm is the appropriate on if any to solve it
有一個包含非負整數的數組。 我需要找到一個包含總和等於給定數字(目標)的數字的子數組(如果有的話)。 我編寫了這個有效的代碼,但我嘗試以更有效的方式編寫它(O(n))。
public static void solvedNotSoEnhanced(int[] arr, int target) {
for (int i = 0; i <= arr.length-1;i++) {
int cur_sum = 0;
for (int j = i ; j <= arr.length-1; j++) {
cur_sum += arr[j];
if (cur_sum > target) {
break;
} else if (cur_sum == target) {
System.out.println("start: " + i + " end: " + j);
}
}
}
}
訣竅在於限制:
有一個包含非負整數的數組。
這意味着當您從前到后遍歷輸入時,您假定子數組的“開始”位於索引 0,然后您開始按順序添加每個數字。 由於該限制,只有 3 個選項:
因此:
static void solvedNotSoEnhanced(int[] arr, int target) {
if (target < 1) {
// Always mind your corner cases!
System.out.println("(0, 0)");
return;
}
int start = 0;
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
while (sum > target) {
// Target exceeded; move up our startpoint.
sum -= arr[start];
start++;
}
// If we get here, we found our subsequence!
if (sum == target) {
System.out.println("[" + start + ", " + i + "]");
return;
}
}
return "No subsequence";
}
這里我使用了滑動 window 的方法。 主要是我在遍歷數組時存儲數組元素的總和。 然后我只存儲 2 個指針 i 和 j,它們存儲正在考慮的當前子數組的 position。
public static void solvedNotSoEnhanced(int[] arr, int target)
{
for(int i = 1;i>arr.length;i++)
{
arr[i] += arr[i-1];
}
int i=0,j=1;
while(i<arr.length &&j<arr.Length)
{
int sum = arr[j] - arr[i];
if(sum == target) System.out.println("start: " + (i + 1) + " end: " + j);
else if(sum > target) i++;
else j++;
}
}
它可以在O(nlogn + m)
中完成,其中n
是數組大小, m
是匹配限制的子數組的數量。
首先,創建一個輔助數組sum
,它是當前所有元素的總和:
sum[i] = arr[0] + arr[1] + ... + arr[i]
Or (equivalent definition)
sum[0] = arr[0]
sum[i] = sum[i-1] + arr[i]
現在,請注意sum
是排序(遞增)數組(因為所有元素都不是負數)。
因此,在生成數組之后,您可以迭代sum
,並且對於sum
中的每個i
,使用二進制搜索查找k-sum[i]
,如果元素存在,它將為您提供索引j
,並且 (i,j) 是這樣的子數組。
也可以改為使用 hash 表來存儲總和,以進一步將復雜度降低到平均情況下的O(n)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.