回答編集履歴

6

テキスト修正

2019/05/30 11:21

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -402,7 +402,7 @@
402
402
 
403
403
 
404
404
 
405
- - [https://repl.it/@jun68ykt/Q284975](https://repl.it/@jun68ykt/Q284975)
405
+ - [https://repl.it/@jun68ykt/Q192033](https://repl.it/@jun68ykt/Q192033)
406
406
 
407
407
 
408
408
 

5

テキスト修正

2019/05/30 11:21

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -337,3 +337,81 @@
337
337
 
338
338
 
339
339
  上記は二重のループがないので、 `O(n)` で済んでいます。
340
+
341
+
342
+
343
+ ### 追記2
344
+
345
+
346
+
347
+ 上記のコードが正解ではないことを、コメントからご指摘、ありがとうございます。
348
+
349
+ 自分でやろうと思ったのですが、たぶんどこかに良質な回答のコードがあるだろうと思って調べましたところ、以下を見つけました。
350
+
351
+
352
+
353
+ - Stackoverflow: [Maximum sum sublist? の回答](https://stackoverflow.com/a/15063394)
354
+
355
+
356
+
357
+
358
+
359
+ > If you want the start and end slice indices, too, you need to track a few more bits of information (note this is still O(1) space and O(n) time, it's just a bit hairier):
360
+
361
+
362
+
363
+ ```python
364
+
365
+ def mssl(l):
366
+
367
+ best = cur = 0
368
+
369
+ curi = starti = besti = 0
370
+
371
+ for ind, i in enumerate(l):
372
+
373
+ if cur+i > 0:
374
+
375
+ cur += i
376
+
377
+ else: # reset start position
378
+
379
+ cur, curi = 0, ind+1
380
+
381
+
382
+
383
+ if cur > best:
384
+
385
+ starti, besti, best = curi, ind+1, cur
386
+
387
+ return starti, besti, best
388
+
389
+ ```
390
+
391
+
392
+
393
+ 上記に対して、
394
+
395
+
396
+
397
+ `A = [-1, 5, -10, 9, -4, 18, -10, 30, 23, -26, 37, 48, -19, -13, 31]`
398
+
399
+
400
+
401
+ を与えたサンプルを以下に作成しました。
402
+
403
+
404
+
405
+ - [https://repl.it/@jun68ykt/Q284975](https://repl.it/@jun68ykt/Q284975)
406
+
407
+
408
+
409
+ 上記を実行すると
410
+
411
+
412
+
413
+ > (3, 12, 125)
414
+
415
+
416
+
417
+ と表示されます。このコードの場合、 `(開始, 終端, 合計)` を返しており、`終端` は含まない形式で返してくれます。

4

テキスト修正

2019/05/30 04:59

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -258,7 +258,7 @@
258
258
 
259
259
 
260
260
 
261
- 55 個のすべての部分リストを調べなくても、以下で大丈夫かなと思います。
261
+ すべての部分リストを調べなくても、以下で大丈夫かなと思います。
262
262
 
263
263
 
264
264
 
@@ -336,4 +336,4 @@
336
336
 
337
337
 
338
338
 
339
- 上記は `O(n)` になってるかと思います。
339
+ 上記は二重のループがないので、 `O(n)` で済んでいます。

3

テキスト修正

2019/05/29 14:24

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -249,3 +249,91 @@
249
249
 
250
250
 
251
251
  以上、参考になれば幸いです。
252
+
253
+
254
+
255
+
256
+
257
+ ### 追記
258
+
259
+
260
+
261
+ 55 個のすべての部分リストを調べなくても、以下で大丈夫かなと思います。
262
+
263
+
264
+
265
+ ```python3
266
+
267
+ def solution(A):
268
+
269
+ start = None
270
+
271
+ end = None
272
+
273
+
274
+
275
+ if len(A) == 0:
276
+
277
+ return 0, start, end
278
+
279
+
280
+
281
+ # 開始インデクスを求める
282
+
283
+ start = 0
284
+
285
+ tmp = 0
286
+
287
+ for i in range(len(A)):
288
+
289
+ tmp += A[i]
290
+
291
+ if tmp <= 0 and i+1 < len(A):
292
+
293
+ start = i+1
294
+
295
+
296
+
297
+ # 終端インデクスを求める
298
+
299
+ tmp = 0
300
+
301
+ max_total = None
302
+
303
+
304
+
305
+ for j in range(start, len(A)):
306
+
307
+ tmp += A[j]
308
+
309
+ if max_total is None or tmp > max_total:
310
+
311
+ end = j
312
+
313
+ max_total = tmp
314
+
315
+
316
+
317
+ return max_total, start, end
318
+
319
+
320
+
321
+
322
+
323
+ if __name__ == '__main__':
324
+
325
+ A = [-1, 5, -10, 9, -4, 18, -10, 30, 23, -26, 37, 48, -19, -13, 31]
326
+
327
+ ans = solution(A)
328
+
329
+ print(ans)
330
+
331
+ ```
332
+
333
+
334
+
335
+ > (120, 5, 11)
336
+
337
+
338
+
339
+ 上記は `O(n)` になっているかと思います。

2

テキスト修正

2019/05/29 13:33

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
 
42
42
 
43
- ご質問に上げられているコードでは何が拙いかというと、合計の比較の際に、以下のようにしている箇所です。
43
+ まず、ご質問に上げられているコードでは何が拙いかというと、合計の比較の際に、以下のようにしている箇所です。
44
44
 
45
45
 
46
46
 
@@ -82,17 +82,13 @@
82
82
 
83
83
 
84
84
 
85
- あるはずです。
86
-
87
-
88
-
89
- ずこれを抑えたうえで、二重のループによって、合計を算出すべき部分リストが 55 種類出現しているかという観点で、見直されるとよいかと思います。
85
+ あるはです。これを抑えたうえで、二重のループによって、合計を算出すべき部分リストが 55 種類出現しているかという観点で、見直されるとよいかと思います。
90
-
91
-
92
-
93
-
94
-
86
+
87
+
88
+
89
+
90
+
95
- 具体的な修正ですが、ご質問にあるコードをなるべく活かすとすると、たとえば以下のようになるかと思います。
91
+ 次に、具体的な修正ですが、ご質問にあるコードをなるべく活かすとすると、たとえば以下のようになるかと思います。
96
92
 
97
93
 
98
94
 
@@ -172,9 +168,7 @@
172
168
 
173
169
 
174
170
 
175
- もうひとつ別解を以下にげます。
171
+ もうひとつ別解を以下にげます。
176
-
177
-
178
172
 
179
173
  ```python3
180
174
 
@@ -224,7 +218,23 @@
224
218
 
225
219
 
226
220
 
227
- 上記で、 `sorted` の第1引数になる、内包表記によるリストは、以下のようなタプル
221
+ 上記で、 `sorted` の第1引数になる、内包表記によるリスト
222
+
223
+ ```pyhon3
224
+
225
+ [(sum(A[i:j+1]), i, j)
226
+
227
+ for i in range(len(A))
228
+
229
+ for j in range(len(A))
230
+
231
+ if i <= j
232
+
233
+ ]
234
+
235
+ ```
236
+
237
+ は、以下のようなタプル
228
238
 
229
239
 
230
240
 

1

テキスト修正

2019/05/29 12:25

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -30,11 +30,11 @@
30
30
 
31
31
 
32
32
 
33
- `(合計値の最大値, 合計が最大になる部分配列の開始インデクス, 合計が最大になる部分配列の終端インデクス)`
33
+ `(合計値の最大値, 合計が最大になる部分リストの開始インデクス, 合計が最大になる部分配列の終端インデクス)`
34
-
35
-
36
-
34
+
35
+
36
+
37
- という要素が3つのタプルで、`合計が最大になる部分配列の終端インデクス` も、合計の対象に**含まれる** と解釈しました。以下、これを前提とした回答になります。
37
+ という要素が3つのタプルで、`合計が最大になる部分リストの終端インデクス` も、合計の対象に**含まれる** と解釈しました。以下、これを前提とした回答になります。
38
38
 
39
39
 
40
40
 
@@ -74,7 +74,7 @@
74
74
 
75
75
 
76
76
 
77
- 開始インデクスを `i` ( 0<=i<len(A) )とすると 終端インデクスの取り得る場合の数は `len(A)-i` 個 で 、いま `len(A) は` 10 なので、比較対象となる合計値は、**重複を考慮しなければ(すなわち、異なる部分配列の要素の合計が一致してもそれらは個別に数えるとして、)**
77
+ 開始インデクスを `i` ( 0<=i<len(A) )とすると 終端インデクスの取り得る場合の数は `len(A)-i` 個 で 、いま `len(A) は` 10 なので、比較対象となる合計値は、**重複を考慮しなければ(すなわち、異なる部分リストの要素の合計が(たまたま)一致してもそれらは個別に数えるとして、)**
78
78
 
79
79
 
80
80
 
@@ -154,7 +154,7 @@
154
154
 
155
155
 
156
156
 
157
- と表示されます。開始インデクス `0` 、終端インデクス `6`(※これも含む) であるAの部分配列
157
+ と表示されます。開始インデクス `0` 、終端インデクス `6`(※これも含む) であるAの部分リスト
158
158
 
159
159
  ```
160
160
 
@@ -228,11 +228,11 @@
228
228
 
229
229
 
230
230
 
231
- `(部分配列の要素の合計値, 部分配列の開始インデクス, 部分配列の終端インデクス)`
231
+ `(部分リストの要素の合計値, 部分リストの開始インデクス, 部分リストの終端インデクス)`
232
-
233
-
234
-
232
+
233
+
234
+
235
- を、`A` の部分配列のすべてについて含み、このリストの長さは先に求めた、場合の数の **55** になります。
235
+ を、`A` の部分リストのすべてについて含み、このリストの長さは先に求めた、場合の数の **55** になります。
236
236
 
237
237
 
238
238