序文:欲張りアルゴリズムの学習は、主に経験と経験を増やすことです。つまり、経験を蓄積するためにより多くのことを行うために、以下では、いくつかのトピックを通じて欲張りアルゴリズムの楽しさを紹介します。
記事ディレクトリ
-
- 1.欲張りアルゴリズムの基本的な紹介
- 2.トピック
-
- 質問1:文字列で構成される配列strsを指定すると、すべての文字列を連結する必要があり、すべての可能な連結結果の中で辞書式順序が最小の結果が返されます。
- 質問2:一部のプロジェクトは、プレゼンテーションのために会議室を占有する必要があり、会議室は2つのプロジェクトのプレゼンテーションを同時に収容することはできません。各プロジェクトの開始時間と終了時間を指定して、プレゼンテーションのスケジュールを調整できます。会議室には、最も多くのプレゼンテーションを行う必要があります。ほとんどのプレゼンテーションを返します
- 質問3:半分にカットされた金の棒は長さと同じ量の銅板を要します。たとえば、長さが20の金の棒は、どのように切断されても20枚の銅板が必要になります。人々のグループは、金の棒全体を分割したいのですが、最も銅のプレートを分割する方法は?配列を入力し、分割の最小コストを返します
- 質問4:入力:正の数の配列のコスト、正の数の配列の利益、正の数のK、正の数のM。cost [i]はアイテムiのコストを表し、profits [i]はコストを差し引いた後にアイテムiが獲得できるお金を表し、Kは最大でK個のアイテムを連続して実行できることを表し、Mは初期資金を表します。説明:プロジェクトを完了していない場合、すぐに得られる収入は、次のプロジェクトを実行するためにあなたをサポートすることができます。プロジェクトを並行して行うことはできません。出力:最後に獲得した最大金額
- 質問5:文字列strを指定すると、「X」文字と「。」文字のみで構成されます。「X」は壁を意味し、ライトを配置することはできず、点灯する必要はありません。「。」は、ライトを配置でき、点灯する必要がある住宅地を意味します。ランプをiの位置にすると、i-1、i、i+1の3つの位置を点灯させることができます。点灯する必要のあるstr内のすべての位置が点灯している場合、少なくとも必要なライトの数を返します
1.欲張りアルゴリズムの基本的な紹介
- これは地域で最も実用的な基準であり、現在の見解では常に最良の選択をしています。
- 困難は、ローカルで最も実用的な基準がグローバルな最適なソリューションにつながる可能性があることを証明することにあります
- 一般的に貪欲選別とヒープ関連している
- 欲張りアルゴリズムの難しさは、標準が実行可能であることを証明する方法ですが、証明はしばしば困難であり、対数を使用して、最終的な方法が実行可能かどうかを検証できます。
2.トピック
質問1:文字列で構成される配列strsを指定すると、すべての文字列を連結する必要があり、すべての可能な連結結果の中で辞書式順序が最小の結果が返されます。
メソッドテンプレート:辞書式順序が最小の結果を取得するために、並べ替えられた配列によって連結された文字列の辞書式順序が最小になるように配列を並べ替えることができます。照合は、文字列aと文字列a + b
bb + a
を連結して、2つの辞書式サイズを比較した後のものです。がa + b
小さい、文字列aは文字列bの前に並べ替えられます。
public static class MyComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return (o1 + o2).compareTo(o2 + o1);
}
}
public static String lowestString(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
Arrays.sort(strs, new MyComparator());
String ans = "";
for (int i = 0; i < strs.length; i++) {
ans += strs[i];
}
return ans;
}
サンプルコード:
public static void main(String[] args) {
String[] strs = {
"ba", "b", "cda"};
System.out.println(lowestString(strs));
}
// 结果为:babcda
質問2:一部のプロジェクトは、プレゼンテーションのために会議室を占有する必要があり、会議室は2つのプロジェクトのプレゼンテーションを同時に収容することはできません。各プロジェクトの開始時間と終了時間を指定して、プレゼンテーションのスケジュールを調整できます。会議室には、最も多くのプレゼンテーションを行う必要があります。ほとんどのプレゼンテーションを返します
最早終了時間
メソッドテンプレート:この問題について考えるとき、検証に最も早い開始時間または最短の説教時間を使用することを考えるかもしれませんが、この種の貪欲な考え方は間違っています。正しい方法は、最も早い終了時間で問題を考えることです。 。終了時刻が最も早い最初の会議を検索し、開始時刻が最も早い終了時刻よりも早い残りの会議を削除してから、終了時刻が最も早い2番目の会議を検索します...
public static class Program {
public int begin;
public int end;
public Program(int begin, int end) {
this.begin = begin;
this.end = end;
}
}
public static int bestArrange(Program[] programs) {
Arrays.sort(programs, new MyComparator());
int timeLine = 0;
int count = 0;
for (int i = 0; i < programs.length; i++) {
if (programs[i].begin >= timeLine) {
count++;
timeLine = programs[i].end;
}
}
return count;
}
public static class MyComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.end - o2.end;
}
}
サンプルコード:
public static void main(String[] args) {
Program[] programs = {
new Program(1, 2), new Program(1, 5), new Program(3, 4), new Program(5, 6) };
System.out.println(bestArrange(programs));
}
// 结果为:3
質問3:半分にカットされた金の棒は長さと同じ量の銅板を要します。たとえば、長さが20の金の棒は、どのように切断されても20枚の銅板が必要になります。人々のグループは、金の棒全体を分割したいのですが、最も銅のプレートを分割する方法は?配列を入力し、分割の最小コストを返します
例:
たとえば、合計3人を表す配列{10、20、30}の場合、金の棒全体の長さは60であり、金の棒を10、20、30の3つの部分に分割する必要があります。 。
最初に長さ60の金の棒を10と50に分割すると、60の費用がかかります。次に、長さ50の金の棒を20と30に分割すると、50の費用がかかり、合計で110の銅板が必要になります。
最初に長さ60の金の棒を30と30に分割すると、60の費用がかかり、次に長さ30の金の棒を30と10に分割すると、30の費用がかかり、合計で90の銅板が必要になります。
メソッドテンプレート:この質問について考えるとき、金の棒の最大の部分の長さで切断することを考えるかもしれませんが、貪欲な考えは間違っています(97、98、99、の長さの部分に分割したい場合100の場合、最初に金の棒を97+98と99+ 100の部分に分割する必要があります)。ここでは、小さなルートヒープを作成し、ヒープの上部をポップアップして2つの要素を追加できます。追加の結果は、2つの金のバーを分割するコストであり、その結果がヒープに追加されます。上記の手順は、ヒープに1つだけ残るまで続けられます。数値
public static int lessMoney(int[] arr) {
Queue<Integer> queue = new PriorityQueue<>();
for(int num : arr) {
queue.add(num);
}
int money = 0;
int cur = 0;
while(queue.size() > 1) {
cur = queue.poll() + queue.poll();
money += cur;
queue.add(cur);
}
return money;
}
サンプルコード:
public static void main(String[] args) {
int[] arr = {
10, 20, 30};
System.out.println(lessMoney(arr));
}
// 结果为:90
質問4:入力:正の数の配列のコスト、正の数の配列の利益、正の数のK、正の数のM。cost [i]はアイテムiのコストを表し、profits [i]はコストを差し引いた後にアイテムiが獲得できるお金を表し、Kは最大でK個のアイテムを連続して実行できることを表し、Mは初期資金を表します。説明:プロジェクトを完了していない場合、すぐに得られる収入は、次のプロジェクトを実行するためにあなたをサポートすることができます。プロジェクトを並行して行うことはできません。出力:最後に獲得した最大金額
メソッドテンプレート:プロジェクトコストが低いものから高いものへと小さなルートヒープを構築し、すべてのアイテムをヒープに入れてから、プロジェクト利益が高いものから低いものへと大きなルートヒープを構築し、小さなルートヒープでの消費量を現在のもの。資金のあるプロジェクトがポップアップされて大きなルートパイルに追加され、最も収益性の高いプロジェクトが購入のために選択され、次に上記の手順が順番に実行されます。
public static class Program {
public int cost;
public int profit;
public Program(int cost, int profit) {
this.cost = cost;
this.profit = profit;
}
}
public static class MinCostComparator implements Comparator<Program>{
@Override
public int compare(Program o1, Program o2) {
return o1.cost - o2.cost;
}
}
public static class MaxProfitComparator implements Comparator<Program>{
@Override
public int compare(Program o1, Program o2) {
return o2.profit - o1.profit;
}
}
public static int findMaximizedCapital(int K, int W, int[] profits, int[] capital) {
Queue<Program> minCostQ = new PriorityQueue<>(new MinCostComparator());
Queue<Program> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
for(int i = 0; i < capital.length; i++) {
Program program = new Program(capital[i], profits[i]);
minCostQ.add(program);
}
while(K > 0) {
while(minCostQ.size() > 0 && minCostQ.peek().cost <= W) {
maxProfitQ.add(minCostQ.poll());
}
if(maxProfitQ.isEmpty()) {
break;
}
W += maxProfitQ.poll().profit;
K--;
}
return W;
}
サンプルコード:
public static void main(String[] args) {
int[] capital = {
2,1,6,4};
int[] profits = {
2,3,1,4};
int K = 3;
int W = 1;
System.out.println(findMaximizedCapital(K,W,profits,capital));
}
// 结果为:10
質問5:文字列strを指定すると、「X」文字と「。」文字のみで構成されます。「X」は壁を意味し、ライトを配置することはできず、点灯する必要はありません。「。」は、ライトを配置でき、点灯する必要がある住宅地を意味します。ランプをiの位置にすると、i-1、i、i+1の3つの位置を点灯させることができます。点灯する必要のあるstr内のすべての位置が点灯している場合、少なくとも必要なライトの数を返します
メソッドテンプレート:インデックス位置が壁であると仮定すると、インデックス=インデックス+ 1;インデックス位置が集落であり、インデックス+1位置が壁である場合、ランプが必要であり、インデックス=インデックス+2;場合インデックスの位置は住宅用サイト、インデックス+1の位置は住宅用サイトです。インデックス+2の位置が住宅用サイトであるか壁であるかに関係なく、ランプが必要であり、インデックス=インデックス+3です。
public static int minLight(String road) {
char[] str = road.toCharArray();
int index = 0;
int light = 0;
while(index<str.length) {
if(str[index] == 'X') {
index++;
}else {
light++;
if(index+1==str.length) {
break;
}else {
if(str[index+1]=='X') {
index=index+2;
}else {
index=index+3;
}
}
}
}
return light;
}
サンプルコード:
public static void main(String[] args) {
String road = "X.XX..X...X....X";
System.out.println(minLight(road));
}
// 结果为:5