組み合わせアルゴリズム——華為面接の問題
3151 ワード
1、abc、2が入力されるとab、ac、bcが出力される
2、abcd、3を入力とabc、abd、acd、bcdが出力される
実装コードは次のとおりです.
テーマ分析:
str:既存文字列 Cut:切り取った文字列の長さ result:切り取った文字列 length:現在切り取られているのはlength文字目です
2つの条件から、これは1つの文字列の切り取りの問題であり、与えられた整数に基づいて既存の文字列(str)の中で対応する長さ(cut)の文字列を切り取り、出力された文字列の中の文字のソート順は元の文字列の中の文字の配列順、すなわちabの中のaの下に0、bの下に1、a
abc、2を例にとると、まずabcの最初の文字からresultの最初の文字を取り、最初の文字をaと取ります.では、最初の文字はどれまで取ることができますか.全部でcut(2)文字を切り取る必要があります.現在切り取っているのは第length(1)文字です.strの中で私はcut-length文字を予約しなければなりません.つまり、第1文字は最大1と下付き文字を取ります.下付き文字は0から始まるので、第1文字の下付き文字はstr.length()-(cut-length)より小さくなければなりません.現在取得されているlength番目の文字にかかわらず、strにcut-length番目の文字を残しておく必要があります.そうしないと、最後に切り取った文字の長さはcutの長さに達しません.最初の文字を取ると、最初の下に0と表示されます.そのため、次のようになります.
1文字目を取った後、2文字目を取りに行くには、下の文字が1のところからしか検索できないはずですが、1文字目を取る原理と同じであることがわかります.2文字目がstrで切り取った文字の下の文字がstr.length()-cut+lengthを超えないことを保証すれば、lengthが2になると同時に、2文字目を取る場合、strでの開始検索の下付き文字が最初の文字であるべきときstrでの下付き文字+1、すなわち最初の文字がstrでの下付き文字が0、2番目の文字が1から検索を開始する場合、再帰ループを使用することができる:
再帰サイクルに入った以上、終了条件が必要であることを意味し、そうでないと無限のデッドサイクルに陥るので、いつ終了するのか、lengthは現在取るべき第length文字を表し、最終長さはcutであるべきであるため、length=cutの場合、combSelectに入るのではなく、今回取るべき出力結果を表し、length
出力後、abc、2のように、最初の文字aを取り、再帰し、2番目の文字bを取り、このときプログラムは2番目の文字のサイクルの中で、条件はi=1である.i<3-2+2;i++すなわちi<3;bを取ったとき、i=1で、2番目の文字には他の選択肢があることを説明します.bだけではありません.では、iを2にしてacに重ねます.しかし、resultはabになりました.どうやってaにしますか.そのため、ループが始まる前に、forループに入っていないときのresult値を保存する文字列を定義します.
これにより,ループ毎にresultをsに変更すると,再びループを重ねることができる.
問題が解決する.over-(以上はいずれも個人の粗浅な理解と解釈であり、異なる解法と観点があれば指摘を歓迎する)
2、abcd、3を入力とabc、abd、acd、bcdが出力される
実装コードは次のとおりです.
package com.funny.algorithm;
/**
* 1、 abc 2, ab、ac、bc
* 2、 abcd 3, abc、abd、acd、bcd
*/
import java.util.Scanner;
public class Exercise1 {
public static void main(String[] args) {
combSelect(0, 1, "abc", 2, "");
}
/**
*
* @param head
*
* @param length
* result length
* @param str
*
* @param cut
*
* @param result
*
*/
private static void combSelect(int head, int length, String str, int cut, String result) {
// s result
String s = result;
for (int i = head; i < str.length() - (cut - length); i++) {
// length cut ,
if (length < cut) {
result += str.substring(i, i + 1);
combSelect(i + 1, length + 1, str, cut, result);
}
// cut ,
else if (length == cut) {
result += str.substring(i, i + 1);
System.out.println(result);
}
// result , : ab , , , a c
result = s;
}
}
}
テーマ分析:
str:既存文字列 Cut:切り取った文字列の長さ result:切り取った文字列 length:現在切り取られているのはlength文字目です
2つの条件から、これは1つの文字列の切り取りの問題であり、与えられた整数に基づいて既存の文字列(str)の中で対応する長さ(cut)の文字列を切り取り、出力された文字列の中の文字のソート順は元の文字列の中の文字の配列順、すなわちabの中のaの下に0、bの下に1、a
abc、2を例にとると、まずabcの最初の文字からresultの最初の文字を取り、最初の文字をaと取ります.では、最初の文字はどれまで取ることができますか.全部でcut(2)文字を切り取る必要があります.現在切り取っているのは第length(1)文字です.strの中で私はcut-length文字を予約しなければなりません.つまり、第1文字は最大1と下付き文字を取ります.下付き文字は0から始まるので、第1文字の下付き文字はstr.length()-(cut-length)より小さくなければなりません.現在取得されているlength番目の文字にかかわらず、strにcut-length番目の文字を残しておく必要があります.そうしないと、最後に切り取った文字の長さはcutの長さに達しません.最初の文字を取ると、最初の下に0と表示されます.そのため、次のようになります.
for(int i=0;i
1文字目を取った後、2文字目を取りに行くには、下の文字が1のところからしか検索できないはずですが、1文字目を取る原理と同じであることがわかります.2文字目がstrで切り取った文字の下の文字がstr.length()-cut+lengthを超えないことを保証すれば、lengthが2になると同時に、2文字目を取る場合、strでの開始検索の下付き文字が最初の文字であるべきときstrでの下付き文字+1、すなわち最初の文字がstrでの下付き文字が0、2番目の文字が1から検索を開始する場合、再帰ループを使用することができる:
combSelect(i+1,length+1,str,cut,result);
再帰サイクルに入った以上、終了条件が必要であることを意味し、そうでないと無限のデッドサイクルに陥るので、いつ終了するのか、lengthは現在取るべき第length文字を表し、最終長さはcutであるべきであるため、length=cutの場合、combSelectに入るのではなく、今回取るべき出力結果を表し、length
// length cut ,
if (length < cut) {
result += str.substring(i, i + 1);
combSelect(i + 1, length + 1, str, cut, result);
}
// cut ,
else if (length == cut) {
result += str.substring(i, i + 1);
System.out.println(result);
}
出力後、abc、2のように、最初の文字aを取り、再帰し、2番目の文字bを取り、このときプログラムは2番目の文字のサイクルの中で、条件はi=1である.i<3-2+2;i++すなわちi<3;bを取ったとき、i=1で、2番目の文字には他の選択肢があることを説明します.bだけではありません.では、iを2にしてacに重ねます.しかし、resultはabになりました.どうやってaにしますか.そのため、ループが始まる前に、forループに入っていないときのresult値を保存する文字列を定義します.
String s = result;
これにより,ループ毎にresultをsに変更すると,再びループを重ねることができる.
問題が解決する.over-(以上はいずれも個人の粗浅な理解と解釈であり、異なる解法と観点があれば指摘を歓迎する)