7. 尋找和為定值的任意多個數(shù)

一、尋找和為定值的兩個數(shù)

算法思想:

  1. 排序,然后兩端掃描。時間復雜度O(nlogn+n) 空間復雜度O(1)
  2. 散列映射,先確定其中一個數(shù),再判斷另一個是否存在。時間復雜度O(1),空間復雜度O(n)

算法實現(xiàn)

#include <iostream>
#include <algorithm>
#include <fstream>

using namespace std;

int main()
{
    ifstream cin("in.txt");

    int n, a[100], ans;

    while(cin >> n)
    {
        for(int i = 0; i < n; ++i)
            cin >> a[i];

        cin >> ans;

        sort(a, a+n);

        int i = 0, j = n-1;

        while(i < j)
        {
            if(a[i] + a[j] < ans)
                ++i;
            else if(a[i] + a[j] > ans)
                --j;
            else
            {
                cout << a[i] << " " << a[j] << endl;
                break;
            }
        } 
    }
}
二、擴展:尋找和為定值的任意多個數(shù)
1. 遞歸法

算法思想:考慮是否取第n個數(shù),問題可以轉(zhuǎn)化為前n-1個數(shù)和為sum-a[n-1]的問題,也可以轉(zhuǎn)化為后n-1個數(shù)的求和問題。使用遞歸思想解決。

  • 如果取第n個數(shù),即求得前n-1個數(shù)滿足和為sum-a[n-1]的問題
  • 如果不取第n個數(shù),即求得前n-1個數(shù)滿足和為sum的問題
#include <iostream>
#include <fstream>

using namespace std;

int res[100], k = 0;

void sumOfKNumber(int * a, int n, int sum)
{
    if(n <= 0 || sum <= 0)
        return;

    if(k > 0)
    {
        if(sum == a[n-1])
        {
            for(int i = k-1; i >= 0; --i)
                cout << res[i] << "+";

            cout << a[n-1] << endl; //特別注意,輸出時,該元素還未加入數(shù)組
        }
    }

    //考慮是否取第n個數(shù)
    res[k++] = a[n-1];
    sumOfKNumber(a, n-1, sum-a[n-1]);
    k--;

    sumOfKNumber(a, n-1, sum);
}

int main()
{
    ifstream cin("in.txt");

    int n, a[100], ans;

    while(cin >> n)
    {
        for(int i = 0; i < n; ++i)
            cin >> a[i];
        cin >> ans;

        sumOfKNumber(a, n, ans);
    }

    return 0;
}
三、k個和為定值的個數(shù)

題目:給出[1,2,3,4],k=2, target=5,[1,4] and [2,3]是2個符合要求的方案
地址:http://www.lintcode.com/zh-cn/problem/k-sum/
解析:dp[i][j][p] 表示從i個數(shù)中挑j個數(shù)和為p時的次數(shù)。
dp[0][0][0]表示在一個空集中找出0個數(shù),target為0,則有1個解,就是什么也不挑嘛!
其實應該這樣寫,也就是說,找0個數(shù),目標為0,則一定是有1個解:
if (j == 0 && p == 0) {
  // select 0 number from i to the target: 0
  D[i][j][p] = 1;
}

  1. 狀態(tài)表達式:
D[i][j][p] = D[i - 1][j][p];  //不包含第i個元素
if (p - A[i - 1] >= 0) { //可以包含第i個元素
D[i][j][p] += D[i - 1][j - 1][t - A[i - 1]];
}

意思就是:

(1)我們可以把當前A[i - 1]這個值包括進來,所以需要加上D[i - 1][j - 1][t - A[i - 1]](前提是t - A[i - 1]要大于0)

(2)我們可以不選擇A[i - 1]這個值,這種情況就是D[i - 1][j][t],也就是說直接在前i-1個值里選擇一些值加到target.

public class Solution {
    /**
     * @param A: an integer array.
     * @param k: a positive integer (k <= length(A))
     * @param target: a integer
     * @return an integer
     */
    public int kSum(int A[], int k, int target) {
        // write your code here
        
        int len = A.length;
        int [][][] dp = new int[len+1][k+1][target+1];
        
        if(target < 0)
            return 0;
            
        for(int i = 0; i <= len; ++i)
            for(int j = 0; j <= k; ++j)
                for(int p = 0; p <= target; ++p)
                {
                    if(j == 0 && p == 0)
                        dp[i][j][p] = 1;
                    else if(i != 0 && j != 0 && p!= 0)
                    {
                        dp[i][j][p] = dp[i-1][j][p];
                        if(p >= A[i-1])
                            dp[i][j][p] += dp[i-1][j-1][p-A[i-1]];
                    }
                    
                }
                
        return dp[len][k][target];
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容