貪欲な問題解決法(1)

目次

K 個の要素の最大合計

一連の考え

コード

 配列内の最大のペアの合計の最小値

説明

コード

K 個の要素の最大合計

0からインデックスが付けられた 整数の配列 nums と integer が与えられます k 。 スコアを最大化するには、次の回数を 正確に実行する必要があります。 k

  1. そこから nums 要素を選択します m 。
  2. 選択した要素を m 配列から削除します。
  3. 新しい要素を m + 1 配列に追加します。
  4. スコアが上がります m 。

k 上記の操作を正確に回数実行した後、最大スコアを返してください 。

例 1:

入力: nums = [1,2,3,4,5]、k = 3
出力: 18
説明: nums から正確に 3 つの要素を選択し、スコアを最大化する必要があります。
初めての場合は5を選択します。合計は 5、nums = [1,2,3,4,6] です。
もう一度 6 を選択します。合計は 6、nums = [1,2,3,4,7] です。
3 回目は 7 を選択します。合計は 5 + 6 + 7 = 18、数値 = [1,2,3,4,8] となります。
したがって、18 を返します。
18 は、取得できる最大の答えです。

例 2:

入力: nums = [5,5,5]、k = 2
出力: 11
説明: nums から正確に 2 つの要素を選択し、スコアを最大化する必要があります。
初めての場合は5を選択します。合計は 5、nums = [5,5,6] です。
もう一度 6 を選択します。合計は 6、nums = [5,5,7] です。
したがって、11 を返します。
得られる最大の答えは 11 です。

ヒント:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100
  • 1 <= k <= 100

一連の考え

難解すぎる気がします。

実際、それは非常に単純です。配列を与えると、ソートされない可能性があります。

それから、並べ替えなければなりませんが、もちろん並べ替える必要はありません、結局のところ、これは単なる質問です。


状況 1: 単一層の for ループを直接並べず、最大のものを見つけます。配列は必要ありません。直接累積し、max を合計に加算するたびに max に 1 を加算し、そのような操作を何度も実行しますk は であるため、最後に sum を返します。ケース 1 の時間計算量は O(n) です。

事例2:
並べ替えたら一番大きいのではないか?次に、ソートされた配列の最大値 (合計) を指定し、それを削除するかどうかは無視して、元の最大値に 1 を加算するだけで、最大値のままになります。kが何であっても、何度でも受け取って、1を足して返すことができます。ケース 2 の時間計算量は O(nlogn) です。

コード

import java.util.Arrays;

public class k个元素的最大和 {
    public static void main(String[] args) {
        int k=3;
        int nums[]={1,2,3,4,5};
        k个元素的最大和 kg = new k个元素的最大和();
        System.out.println(kg.maximizeSum(nums,k));
    }
    public int maximizeSum(int nums[],int k){
        int sum=0;
        //排序版:
//        Arrays.sort(nums);
//        for (int i = 0; i < k; i++) {
//            sum+=nums[nums.length-1];
//            nums[nums.length-1]+=1;
//        }
        //未排序版:
        int max=Returnmax(nums);
        for (int i = 0; i < k; i++) {
            sum+=max;
            max+=1;
        }
        return sum;
    }
    //找最大
    public int Returnmax(int nums[]){
        int max=nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (max<nums[i]){
                max=nums[i];
            }
        }
        return max;
    }
}

 配列内の最大のペアの合計の最小値

ペア のペア(a,b) の 合計 は に等しい a + b 。最大のペアの合計は、ペアの配列内の 最大のペアの 合計です 。

  • たとえば、 と のペアがある場合  最大 (1,5) のペアの合計 は です  。(2,3)(4,4)max(1+5, 2+3, 4+4) = max(6, 5, 8) = 8

偶数 nの長さ の配列 を指定した場合 nums 、  次のようにnums 要素をペアに分割して ください。n / 2

  • nums の各要素は 正確に1 つのペア になっており  、
  • 最大のペアの合計が最小の 値 になります 。

最適な数値ペア除算スキームに基づいて、 最小および最大の数値ペアの合計を返してください 。

例 1:

入力: nums = [3,5,2,3]
出力: 7
説明:配列内の要素は、ペア (3,3) と (5,2) に分割できます。
ペアの最大合計は max(3+3, 5+2) = max(6, 7) = 7 です。

例 2:

入力: nums = [3,5,4,2,4,6]
出力: 8
説明:配列内の要素は、ペア (3,5)、(4,4)、および (6,2) に分割できます。
ペアの最大合計は、 max(3+5, 4+4, 6+2) = max(8, 8, 8) = 8 です。

ヒント:

  • n == nums.length
  • 2 <= n <= 105
  • nは偶数 です  。
  • 1 <= nums[i] <= 105

説明

この問題の難易度は中程度ですが、私はそうは思わないので、欲が比較的簡単なのかもしれません。

まず第一に、nums[] 配列の長さは偶数であることがわかっているため、判断を省くことができます。

次に、例から、ペアの一致は相互に相対的であるという規則があることがわかります。なぜそう言えるのでしょうか? この例の配列を並べ替えると、グループの数が取得されるたびに、最大のグループと最小のグループ、2 番目に大きいグループと 2 番目に小さいグループの順になることがわかります。

そこで、ダブルポインタを使用し、それぞれ最初と最後から開始し、判断する必要がなく、2つのポインタが1ステップ進むたびのforの時間計算量はO(n/2)だけです。

しかし、私のアルゴリズムの全体的な時間計算量は O(nlogn) であり、2 つのクイック ソートは大きいです。実際、最大数値ペアの合計を格納する 2 番目の配列はすぐにソートする必要はなく、単一サイクルの比率を直接書き込んで、最後に max に戻すだけで十分です。

コード

import java.util.Arrays;

public class 数组中最大数对和的最小值 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
//        int nums[] = {3,5,2,3};
        int nums[] = {3,5,4,2,4,6};
        数组中最大数对和的最小值 s = new 数组中最大数对和的最小值();
        System.out.println(s.minPairSum(nums));
//        System.out.println(nums.length);
    }

    public int minPairSum(int[] nums) {
        int max = 0, j = nums.length - 1;
        Arrays.sort(nums);
        int temp[] = new int[nums.length / 2];
        for (int i = 0; i < nums.length / 2; i++) {
            temp[i] = nums[i] + nums[j--];
//            j++;
        }
        Arrays.sort(temp);
        max = temp[temp.length - 1];
        return max;
    }
}

おすすめ

転載: blog.csdn.net/m0_64206989/article/details/131314986