teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

7

追記3

2021/08/11 11:30

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -93,4 +93,31 @@
93
93
  }
94
94
  ```
95
95
 
96
- gen の呼び出し回数も減ります。
96
+ gen の呼び出し回数も減ります。
97
+
98
+ **追記3**
99
+ xebme さんのコードに刺激されて、for文を再帰呼出しに変えてみました。
100
+ ```Java
101
+ import java.util.Arrays;
102
+
103
+ class Main {
104
+ public static void main(String []args){
105
+ int n = 6;
106
+ gen(new int[n], 0, n, n);
107
+ }
108
+
109
+ static void gen(int[] a, int i, int j, int r) {
110
+ if (r == 0) // 和ができたので表示
111
+ System.out.println(Arrays.toString(Arrays.copyOf(a, i)));
112
+ else { // まだ和に達していない
113
+ a[i] = j = Math.min(j, r);
114
+ gen(a, i + 1, j, r - j);
115
+ if (--j > 0) gen(a, i, j, r);
116
+ }
117
+ }
118
+ }
119
+ ```
120
+
121
+ 和の n は、ハードコーディングしました。
122
+ Scanner による標準入力や、args によるコマンドライン引数に
123
+ 変えるのは簡単でしょう。

6

追記2

2021/08/11 11:30

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -78,4 +78,19 @@
78
78
  [2, 2]
79
79
  [2, 1, 1]
80
80
  [1, 1, 1, 1]
81
- ```
81
+ ```
82
+ **追記2**
83
+ `Math.min` を使うと、`else if (r > 0)` が `else` で済みますね。
84
+ ```Java
85
+ static void gen(int[] a, int i, int j, int r) {
86
+ if (r == 0) // 和ができたので表示
87
+ System.out.println(Arrays.toString(Arrays.copyOf(a, i)));
88
+ else // まだ和に達していない
89
+ for (j = Math.min(j, r); j > 0; j--) {
90
+ a[i] = j;
91
+ gen(a, i + 1, j, r - j); // 再帰呼出し
92
+ }
93
+ }
94
+ ```
95
+
96
+ gen の呼び出し回数も減ります。

5

copyOfRange を copyOf に変更

2021/08/11 05:39

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -57,7 +57,7 @@
57
57
 
58
58
  static void gen(int[] a, int i, int j, int r) {
59
59
  if (r == 0) // 和ができたので表示
60
- System.out.println(Arrays.toString(Arrays.copyOfRange(a, 0, i)));
60
+ System.out.println(Arrays.toString(Arrays.copyOf(a, i)));
61
61
  else if (r > 0) // まだ和に達していない
62
62
  for (; j > 0; j--) {
63
63
  a[i] = j;

4

追記のコードの表示を Arrays を使うものに変更

2021/08/10 21:34

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -44,21 +44,20 @@
44
44
  gen を static にして、Sumクラスを使わずに、
45
45
  さらに、和を引数で与えるようにしてみました。
46
46
  ```Java
47
+ import java.util.Arrays;
48
+
47
49
  class Main {
48
50
  public static void main(String []args){
49
- for (String s : args) {
51
+ for (int i = 0; i < args.length; i++) {
50
- int n = Integer.parseInt(s);
52
+ int n = Integer.parseInt(args[i]);
51
- System.out.println(n);
53
+ if (i > 0) System.out.println();
52
54
  gen(new int[n], 0, n, n);
53
55
  }
54
56
  }
55
57
 
56
58
  static void gen(int[] a, int i, int j, int r) {
57
- if (r == 0) { // 和ができたので表示
59
+ if (r == 0) // 和ができたので表示
58
- String s = "";
59
- for (j = 0; j < i; j++) s += " " + a[j];
60
- System.out.println(s);
60
+ System.out.println(Arrays.toString(Arrays.copyOfRange(a, 0, i)));
61
- }
62
61
  else if (r > 0) // まだ和に達していない
63
62
  for (; j > 0; j--) {
64
63
  a[i] = j;
@@ -70,14 +69,13 @@
70
69
  実行例
71
70
  ```text
72
71
  $ java Main 3 4
73
- 3
72
+ [3]
74
- 3
75
- 2 1
73
+ [2, 1]
76
- 1 1 1
74
+ [1, 1, 1]
75
+
77
- 4
76
+ [4]
78
- 4
79
- 3 1
77
+ [3, 1]
80
- 2 2
78
+ [2, 2]
81
- 2 1 1
79
+ [2, 1, 1]
82
- 1 1 1 1
80
+ [1, 1, 1, 1]
83
81
  ```

3

追記

2021/08/10 21:18

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -39,4 +39,45 @@
39
39
  }
40
40
  }
41
41
  }
42
+ ```
43
+ **追記**
44
+ gen を static にして、Sumクラスを使わずに、
45
+ さらに、和を引数で与えるようにしてみました。
46
+ ```Java
47
+ class Main {
48
+ public static void main(String []args){
49
+ for (String s : args) {
50
+ int n = Integer.parseInt(s);
51
+ System.out.println(n);
52
+ gen(new int[n], 0, n, n);
53
+ }
54
+ }
55
+
56
+ static void gen(int[] a, int i, int j, int r) {
57
+ if (r == 0) { // 和ができたので表示
58
+ String s = "";
59
+ for (j = 0; j < i; j++) s += " " + a[j];
60
+ System.out.println(s);
61
+ }
62
+ else if (r > 0) // まだ和に達していない
63
+ for (; j > 0; j--) {
64
+ a[i] = j;
65
+ gen(a, i + 1, j, r - j); // 再帰呼出し
66
+ }
67
+ }
68
+ }
69
+ ```
70
+ 実行例
71
+ ```text
72
+ $ java Main 3 4
73
+ 3
74
+ 3
75
+ 2 1
76
+ 1 1 1
77
+ 4
78
+ 4
79
+ 3 1
80
+ 2 2
81
+ 2 1 1
82
+ 1 1 1 1
42
83
  ```

2

説明の修正 (0 -> 1)

2021/08/10 20:36

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -1,6 +1,6 @@
1
1
  要素の和を n とすると、全部 1 が一番長い部分集合になるので、
2
2
  大きさ n の配列を用意して、大きい数から詰め込んで行くことにします。
3
- まだ和に達していなければ、左側以下の値を大きいものから順に 0 になるまで
3
+ まだ和に達していなければ、左側以下の値を大きいものから順に 1 になるまで
4
4
  詰め込んで、次に行くというのを繰り返せばよいでしょう。
5
5
 
6
6
  ヒントとして書くのが難しいので、コードで書きます。

1

コードの修正

2021/08/10 14:47

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -20,10 +20,9 @@
20
20
  }
21
21
 
22
22
  class Sum {
23
- int n, a[];
23
+ int a[];
24
24
 
25
25
  Sum(int n) {
26
- this.n = n;
27
26
  a = new int[n];
28
27
  }
29
28
 
@@ -33,8 +32,8 @@
33
32
  System.out.print(" " + a[j]);
34
33
  System.out.println();
35
34
  }
36
- else if (r > 0 && i < n) // まだ和に達していない
35
+ else if (r > 0) // まだ和に達していない
37
- for (int j = k; j >= 0; j--) {
36
+ for (int j = k; j > 0; j--) {
38
37
  a[i] = j;
39
38
  gen(i+1, j, r - j); // 再帰呼出し
40
39
  }