回答編集履歴

5

修正

2021/01/30 11:37

投稿

kairi003
kairi003

スコア1332

test CHANGED
@@ -9,3 +9,33 @@
9
9
  また、1~10ということがわかっているなら、ビット演算を用いることでもっと楽にできます。
10
10
 
11
11
  0に対して元の配列から1<<(数値)との論理和を取っていけば、たとえば{1,2,3,5,5,5,8,8,9,9}なら2進数で1100101110になるので、2つの配列をこのようにint型の数値に変換してからビット論理和、論理積をそれぞれとって配列にもどせば終わりです。
12
+
13
+
14
+
15
+ ---
16
+
17
+ 追記
18
+
19
+ 回答修正が迷走してしまってすみません。
20
+
21
+ 「重複を消す」の例はこんな感じですね
22
+
23
+ ```c
24
+
25
+ int main(void) {
26
+
27
+ int ab[20] = {1,1,2,3,3,4,5,6,7,7,7,7,7,8,8,9,9,9,9,10}; // aとbを連結してソートした配列
28
+
29
+ int or[10];
30
+
31
+ or[0] = ab[0];
32
+
33
+ for (int i=0,j=0;i<20;i++) {
34
+
35
+ if (ab[i] > or[j]) or[++j] = ab[i];
36
+
37
+ }
38
+
39
+ }
40
+
41
+ ```

4

削除

2021/01/30 11:37

投稿

kairi003
kairi003

スコア1332

test CHANGED
@@ -1,6 +1,6 @@
1
1
  複数回あるのを除くには、ソートしてから新しい配列を用意して、元の配列の小さい方から順に、数値が大きくなったときだけ、新しい配列に数値を入れていけばいいです。
2
2
 
3
- ~~「2つの配列を1つにまとめる→ソート→重複を除く」で和集合はできます。~~
3
+ 「2つの配列を1つにまとめる→ソート→重複を除く」で和集合はできます。
4
4
 
5
5
  積集合は「2つの配列をそれぞれソート→小さい方から比べつつ共通の数値があったら新しい配列に入れる」というような動作になります。添字の進め方に工夫が必要なので考えてみてください。
6
6
 
@@ -9,79 +9,3 @@
9
9
  また、1~10ということがわかっているなら、ビット演算を用いることでもっと楽にできます。
10
10
 
11
11
  0に対して元の配列から1<<(数値)との論理和を取っていけば、たとえば{1,2,3,5,5,5,8,8,9,9}なら2進数で1100101110になるので、2つの配列をこのようにint型の数値に変換してからビット論理和、論理積をそれぞれとって配列にもどせば終わりです。
12
-
13
-
14
-
15
- ---
16
-
17
- 追記
18
-
19
-
20
-
21
- やっぱり和集合も積集合と同じように「2つの配列をそれぞれソート→小さい方から順に比べ、初出の数値があれば新しい配列に追加する」という方が合わせてイメージしやすいかもしれません。
22
-
23
- その場合「重複を削除」はあまり意識しなくていいです。
24
-
25
-
26
-
27
- ```c
28
-
29
- int a[10] = {...}; // ソートされた配列a
30
-
31
- int b[10] = {...}; // ソートされた配列b
32
-
33
- int or[10] = {0}; // 和集合が入る配列or
34
-
35
-
36
-
37
- int i = 0; // aの添字
38
-
39
- int j = 0; // bの添字
40
-
41
- int k = 0; // orの添字
42
-
43
- int max = 0; // orの現在の最大値(比較用)
44
-
45
-
46
-
47
- while (i < 10 || j < 10) {
48
-
49
- if (a[i] > max) {
50
-
51
- // a[i]がmaxより大きければ、orに入れる→max更新→kを+1
52
-
53
- max = a[i];
54
-
55
- or[k] = a[i];
56
-
57
- k++;
58
-
59
- } else {
60
-
61
- //max以下ならiを+1
62
-
63
- i++;
64
-
65
- };
66
-
67
- if (b[j] > max) {
68
-
69
- max = b[j];
70
-
71
- or[k] = b[j];
72
-
73
- k++;
74
-
75
- } else {
76
-
77
- j++;
78
-
79
-
80
-
81
- };
82
-
83
- ```
84
-
85
-
86
-
87
- 試してないのでちゃんと動くかは分かりませんかイメージとしては↑です。

3

修正

2021/01/30 11:14

投稿

kairi003
kairi003

スコア1332

test CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
  int k = 0; // orの添字
42
42
 
43
- int max = -1; // orの現在の最大値(比較用)
43
+ int max = 0; // orの現在の最大値(比較用)
44
44
 
45
45
 
46
46
 
@@ -48,11 +48,19 @@
48
48
 
49
49
  if (a[i] > max) {
50
50
 
51
- // a[i]がmax以上なら、orに入れる→max更新→kとiを+1
51
+ // a[i]がmaxより大きければ、orに入れる→max更新→kを+1
52
52
 
53
53
  max = a[i];
54
54
 
55
- or[k++] = a[i++];
55
+ or[k] = a[i];
56
+
57
+ k++;
58
+
59
+ } else {
60
+
61
+ //max以下ならiを+1
62
+
63
+ i++;
56
64
 
57
65
  };
58
66
 
@@ -60,9 +68,15 @@
60
68
 
61
69
  max = b[j];
62
70
 
63
- or[k++] = b[j++];
71
+ or[k] = b[j];
64
72
 
65
- };
73
+ k++;
74
+
75
+ } else {
76
+
77
+ j++;
78
+
79
+
66
80
 
67
81
  };
68
82
 

2

修正

2021/01/30 10:57

投稿

kairi003
kairi003

スコア1332

test CHANGED
@@ -44,7 +44,7 @@
44
44
 
45
45
 
46
46
 
47
- while (i < 10 || < || 10) {
47
+ while (i < 10 || j < 10) {
48
48
 
49
49
  if (a[i] > max) {
50
50
 

1

追記

2021/01/30 10:51

投稿

kairi003
kairi003

スコア1332

test CHANGED
@@ -1,6 +1,6 @@
1
1
  複数回あるのを除くには、ソートしてから新しい配列を用意して、元の配列の小さい方から順に、数値が大きくなったときだけ、新しい配列に数値を入れていけばいいです。
2
2
 
3
- 「2つの配列を1つにまとめる→ソート→重複を除く」で和集合はできます。
3
+ ~~「2つの配列を1つにまとめる→ソート→重複を除く」で和集合はできます。~~
4
4
 
5
5
  積集合は「2つの配列をそれぞれソート→小さい方から比べつつ共通の数値があったら新しい配列に入れる」というような動作になります。添字の進め方に工夫が必要なので考えてみてください。
6
6
 
@@ -9,3 +9,65 @@
9
9
  また、1~10ということがわかっているなら、ビット演算を用いることでもっと楽にできます。
10
10
 
11
11
  0に対して元の配列から1<<(数値)との論理和を取っていけば、たとえば{1,2,3,5,5,5,8,8,9,9}なら2進数で1100101110になるので、2つの配列をこのようにint型の数値に変換してからビット論理和、論理積をそれぞれとって配列にもどせば終わりです。
12
+
13
+
14
+
15
+ ---
16
+
17
+ 追記
18
+
19
+
20
+
21
+ やっぱり和集合も積集合と同じように「2つの配列をそれぞれソート→小さい方から順に比べ、初出の数値があれば新しい配列に追加する」という方が合わせてイメージしやすいかもしれません。
22
+
23
+ その場合「重複を削除」はあまり意識しなくていいです。
24
+
25
+
26
+
27
+ ```c
28
+
29
+ int a[10] = {...}; // ソートされた配列a
30
+
31
+ int b[10] = {...}; // ソートされた配列b
32
+
33
+ int or[10] = {0}; // 和集合が入る配列or
34
+
35
+
36
+
37
+ int i = 0; // aの添字
38
+
39
+ int j = 0; // bの添字
40
+
41
+ int k = 0; // orの添字
42
+
43
+ int max = -1; // orの現在の最大値(比較用)
44
+
45
+
46
+
47
+ while (i < 10 || < || 10) {
48
+
49
+ if (a[i] > max) {
50
+
51
+ // a[i]がmax以上なら、orに入れる→max更新→kとiを+1
52
+
53
+ max = a[i];
54
+
55
+ or[k++] = a[i++];
56
+
57
+ };
58
+
59
+ if (b[j] > max) {
60
+
61
+ max = b[j];
62
+
63
+ or[k++] = b[j++];
64
+
65
+ };
66
+
67
+ };
68
+
69
+ ```
70
+
71
+
72
+
73
+ 試してないのでちゃんと動くかは分かりませんかイメージとしては↑です。