diff --git a/src/algorithm_practice/Dynamic_Programming/maximumSubarray/README.md b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/README.md new file mode 100644 index 00000000..e8ae1448 --- /dev/null +++ b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/README.md @@ -0,0 +1,70 @@ +# Maximum (Sum) Subarray + +## Naïve solution + +This is quite an interesting problem, and lends itself to a rather straightforward +naive solution. Basically if we were to try and find the subarray with the largest sum +(the maximum sum subarray), we could do so pretty easily by just seeing what the maximum +possible subarray starting at a given element would be, and just do that for each element, +keeping track of the max. Consider the following array: + +[1, 2, -4, 5, -2, 9] + +All of the subarrays starting with `1` are: + +| Subarray | Sum | +|---------------|-----| +| [1] | 1 | +| [1, 2] | 3 | +| [1, 2, -4] | -1 | +| [1, 2, -4, 5] | 4 | +| [...so on] | x | + +The max of which is finally 11. We can keep track of this max, and compare it against the max of +all of the other `n - 1` tables. We can see that the number of subarrays at a given index is bounded +by `n`, thus making this trivial solution quite slow. Ultimately in this example, we'll see that the +max of the max subarrays has a sum of 12, and is the array [5, -2, 9]. + +### Complexity analysis: + + - Time complexity: O(n2) + - Space complexity: O(1) + +## Optimal Solution (dynamic programming) + +In the above example, we're doing a ton of work. It'd be nice to make the realization that the reason +[5, -2, 9] is the maximum subarray, as opposed to [1, 2, -4, 5, -2, 9], is because the subarray +[1, 2, -4] has a negative sum, so any subarray concatenated onto it is damaged by having it as a prefix. +In other words, when we get to the point where we are to see what the result of adding `5` to [1, 2, -4] +will be, we can optimize our approach by saying "Wait, that's less than just starting over at `5`. No need +to tack `5` onto the negative prefix if I'd be in a better place just starting over at `5`". + +It feels like we just skipped over all subarrays that could start with `2` here, or for that matter, +any value in between the original start, and the new start that we jumped to right? We did! And the reason +that's ok is because by the time we got to those values, it was still beneficial to have the prefix subarray +we started before getting there. There's no reason to drop the `1`, from [1, 2, ...], because it'll just lead +to a lower value. Any subarray starting with `2` can _only be enhanced_ by adding `1` to the beginning. In other +words, by the time we got to `2`, we didn't have a reason to drop the prefix, because it was helping. Finally, when +we dipped into the negatives, we realized it'd make more sense to just start over. This solution is nice, and is +basically a sliding window kinda solution rooted in dynamic programming principles. + +This is exactly the logic we use in the approach based off of Kadane's maximum sum subarray algorithm. It +is a dynamic programming solution, where we essentially keep track of what the maximum sum subarray could be +if it were to _end_ at any given element. If the sum is ever negative, we know that we can be in a better place +by starting over at the next not-so-bad solo value. To read more about Kadane's algorithm approach, check out my +[blog post](https://blog.domfarolino.com/Maximum-Subarray-Study/) on this topic, which goes into much more detail. + +### Complexity analysis: + + - Time complexity: O(n) + - Space complexity: O(1) + +## Performance analysis + +Of course the difference between O(n2) and O(n) is probably obvious to most of the +readers here, but since it's fun creating and analyzing data, here's a nifty chart I made with gnuplot: + +![alt text](plot.png) + +For more reading, check out my [blog post](https://blog.domfarolino.com/Maximum-Subarray-Study/) post which +goes into a little more detail. diff --git a/src/algorithm_practice/Dynamic_Programming/maximumSubarray/data.csv b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/data.csv new file mode 100644 index 00000000..395128b4 --- /dev/null +++ b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/data.csv @@ -0,0 +1,1001 @@ +# Size Naive Linear +2 0.003 0.001 +4 0.001 0 +6 0.001 0.001 +8 0.002 0.002 +10 0.001 0 +12 0.002 0.002 +14 0.001 0 +16 0.003 0.001 +18 0.002 0.002 +20 0.002 0.001 +22 0.003 0.002 +24 0.002 0.001 +26 0.003 0.001 +28 0.003 0.002 +30 0.003 0.001 +32 0.005 0.002 +34 0.004 0.001 +36 0.005 0.001 +38 0.004 0.002 +40 0.005 0.001 +42 0.005 0.003 +44 0.005 0.001 +46 0.007 0.003 +48 0.006 0.002 +50 0.007 0.002 +52 0.008 0.002 +54 0.008 0.003 +56 0.008 0.001 +58 0.01 0.003 +60 0.01 0.002 +62 0.01 0.003 +64 0.011 0.002 +66 0.012 0.002 +68 0.012 0.002 +70 0.013 0.003 +72 0.012 0.001 +74 0.015 0.002 +76 0.014 0.002 +78 0.014 0.001 +80 0.016 0.003 +82 0.016 0.001 +84 0.018 0.003 +86 0.018 0.002 +88 0.019 0.002 +90 0.019 0.003 +92 0.02 0.002 +94 0.021 0.003 +96 0.021 0.002 +98 0.023 0.002 +100 0.023 0.002 +102 0.025 0.003 +104 0.025 0.002 +106 0.029 0.002 +108 0.031 0.004 +110 0.027 0.002 +112 0.034 0.002 +114 0.029 0.002 +116 0.03 0.003 +118 0.031 0.002 +120 0.032 0.003 +122 0.033 0.002 +124 0.034 0.004 +126 0.036 0.002 +128 0.038 0.003 +130 0.039 0.004 +132 0.039 0.003 +134 0.04 0.002 +136 0.042 0.003 +138 0.042 0.002 +140 0.044 0.002 +142 0.044 0.002 +144 0.047 0.003 +146 0.047 0.003 +148 0.048 0.003 +150 0.05 0.003 +152 0.051 0.003 +154 0.053 0.003 +156 0.053 0.002 +158 0.056 0.004 +160 0.056 0.002 +162 0.062 0.004 +164 0.061 0.004 +166 0.065 0.003 +168 0.062 0.003 +170 0.064 0.003 +172 0.064 0.003 +174 0.067 0.004 +176 0.067 0.003 +178 0.07 0.004 +180 0.07 0.003 +182 0.073 0.003 +184 0.073 0.003 +186 0.075 0.004 +188 0.076 0.003 +190 0.079 0.004 +192 0.079 0.003 +194 0.082 0.004 +196 0.104 0.003 +198 0.089 0.003 +200 0.085 0.003 +202 0.088 0.004 +204 0.089 0.003 +206 0.092 0.004 +208 0.093 0.004 +210 0.097 0.004 +212 0.096 0.003 +214 0.098 0.003 +216 0.1 0.004 +218 0.102 0.003 +220 0.115 0.004 +222 0.111 0.012 +224 0.138 0.004 +226 0.106 0.005 +228 0.106 0.004 +230 0.11 0.005 +232 0.11 0.004 +234 0.112 0.004 +236 0.115 0.004 +238 0.117 0.004 +240 0.12 0.004 +242 0.12 0.004 +244 0.122 0.003 +246 0.137 0.004 +248 0.127 0.004 +250 0.129 0.004 +252 0.129 0.004 +254 0.136 0.005 +256 0.134 0.004 +258 0.136 0.004 +260 0.138 0.004 +262 0.14 0.005 +264 0.147 0.006 +266 0.196 0.005 +268 0.146 0.003 +270 0.149 0.004 +272 0.151 0.005 +274 0.152 0.004 +276 0.155 0.005 +278 0.158 0.004 +280 0.16 0.004 +282 0.171 0.007 +284 0.167 0.004 +286 0.167 0.004 +288 0.168 0.006 +290 0.172 0.004 +292 0.173 0.005 +294 0.176 0.005 +296 0.178 0.004 +298 0.187 0.004 +300 0.2 0.004 +302 0.186 0.004 +304 0.187 0.004 +306 0.191 0.005 +308 0.192 0.004 +310 0.22 0.006 +312 0.202 0.004 +314 0.2 0.006 +316 0.202 0.005 +318 0.206 0.005 +320 0.283 0.005 +322 0.252 0.005 +324 0.214 0.004 +326 0.215 0.005 +328 0.219 0.006 +330 0.22 0.006 +332 0.273 0.005 +334 0.225 0.022 +336 0.299 0.006 +338 0.25 0.006 +340 0.251 0.006 +342 0.254 0.005 +344 0.257 0.006 +346 0.26 0.006 +348 0.263 0.006 +350 0.265 0.005 +352 0.269 0.005 +354 0.272 0.005 +356 0.275 0.006 +358 0.278 0.005 +360 0.289 0.006 +362 0.339 0.006 +364 0.287 0.006 +366 0.291 0.005 +368 0.293 0.005 +370 0.348 0.007 +372 0.304 0.005 +374 0.292 0.006 +376 0.295 0.006 +378 0.299 0.007 +380 0.32 0.007 +382 0.305 0.006 +384 0.307 0.005 +386 0.321 0.007 +388 0.315 0.006 +390 0.318 0.006 +392 0.362 0.006 +394 0.329 0.006 +396 0.327 0.006 +398 0.364 0.006 +400 0.335 0.005 +402 0.337 0.005 +404 0.339 0.006 +406 0.365 0.005 +408 0.346 0.005 +410 0.366 0.006 +412 0.365 0.006 +414 0.362 0.007 +416 0.369 0.007 +418 0.37 0.007 +420 0.371 0.006 +422 0.387 0.006 +424 0.509 0.007 +426 0.398 0.008 +428 0.401 0.006 +430 0.55 0.007 +432 0.442 0.006 +434 0.427 0.006 +436 0.458 0.023 +438 0.455 0.007 +440 0.502 0.006 +442 0.451 0.006 +444 0.435 0.006 +446 0.484 0.007 +448 0.455 0.006 +450 0.508 0.007 +452 0.487 0.007 +454 0.445 0.007 +456 0.433 0.006 +458 0.484 0.008 +460 0.438 0.006 +462 0.446 0.007 +464 0.477 0.007 +466 0.465 0.006 +468 0.459 0.007 +470 0.479 0.007 +472 0.463 0.008 +474 0.47 0.007 +476 0.47 0.008 +478 0.49 0.008 +480 0.48 0.008 +482 0.481 0.007 +484 0.512 0.007 +486 0.491 0.006 +488 0.499 0.008 +490 0.499 0.007 +492 0.503 0.007 +494 0.538 0.008 +496 0.569 0.006 +498 0.596 0.007 +500 0.629 0.008 +502 0.622 0.008 +504 0.637 0.007 +506 0.633 0.008 +508 0.632 0.007 +510 0.617 0.007 +512 0.609 0.007 +514 0.612 0.008 +516 0.533 0.008 +518 0.539 0.008 +520 0.541 0.008 +522 0.546 0.007 +524 0.606 0.007 +526 0.571 0.006 +528 0.56 0.006 +530 0.561 0.007 +532 0.566 0.007 +534 0.55 0.006 +536 0.554 0.008 +538 0.558 0.007 +540 0.563 0.007 +542 0.568 0.007 +544 0.57 0.006 +546 0.596 0.008 +548 0.561 0.006 +550 0.581 0.007 +552 0.567 0.007 +554 0.572 0.006 +556 0.577 0.008 +558 0.579 0.007 +560 0.587 0.006 +562 0.57 0.007 +564 0.576 0.006 +566 0.578 0.007 +568 0.586 0.007 +570 0.606 0.006 +572 0.59 0.006 +574 0.606 0.008 +576 0.608 0.008 +578 0.589 0.007 +580 0.588 0.007 +582 0.596 0.008 +584 0.599 0.008 +586 0.599 0.007 +588 0.612 0.007 +590 0.698 0.008 +592 0.622 0.006 +594 0.581 0.007 +596 0.584 0.008 +598 0.593 0.007 +600 0.593 0.006 +602 0.616 0.006 +604 0.673 0.008 +606 0.615 0.007 +608 0.63 0.007 +610 0.61 0.006 +612 0.636 0.008 +614 0.631 0.007 +616 0.63 0.007 +618 0.627 0.007 +620 0.633 0.006 +622 0.635 0.006 +624 0.642 0.008 +626 0.646 0.007 +628 0.683 0.008 +630 0.651 0.007 +632 0.692 0.007 +634 0.659 0.006 +636 0.683 0.008 +638 0.697 0.01 +640 0.703 0.007 +642 0.678 0.007 +644 0.709 0.007 +646 0.697 0.007 +648 0.754 0.007 +650 0.713 0.008 +652 0.696 0.006 +654 0.73 0.007 +656 0.837 0.008 +658 0.708 0.007 +660 0.726 0.007 +662 0.718 0.008 +664 0.721 0.006 +666 0.754 0.008 +668 0.754 0.008 +670 0.744 0.007 +672 0.742 0.008 +674 0.768 0.008 +676 0.809 0.008 +678 0.768 0.008 +680 0.756 0.006 +682 0.784 0.007 +684 0.791 0.007 +686 0.779 0.007 +688 0.78 0.008 +690 0.784 0.009 +692 0.827 0.008 +694 0.847 0.008 +696 0.814 0.007 +698 0.798 0.008 +700 0.817 0.007 +702 0.814 0.007 +704 0.826 0.008 +706 0.821 0.008 +708 0.844 0.008 +710 0.828 0.008 +712 0.841 0.007 +714 0.875 0.009 +716 0.844 0.008 +718 0.842 0.008 +720 0.858 0.009 +722 0.853 0.007 +724 0.859 0.008 +726 0.862 0.007 +728 0.867 0.007 +730 0.873 0.008 +732 0.875 0.008 +734 0.881 0.008 +736 0.885 0.009 +738 0.891 0.009 +740 0.895 0.007 +742 0.902 0.008 +744 0.905 0.007 +746 0.911 0.007 +748 0.914 0.008 +750 0.93 0.008 +752 0.929 0.009 +754 0.932 0.008 +756 0.943 0.007 +758 0.946 0.008 +760 0.959 0.007 +762 0.993 0.008 +764 0.968 0.008 +766 0.969 0.009 +768 0.99 0.008 +770 0.97 0.008 +772 0.988 0.008 +774 0.99 0.009 +776 0.984 0.008 +778 0.997 0.009 +780 1.216 0.015 +782 1.377 0.008 +784 1.003 0.007 +786 1.183 0.009 +788 1.192 0.009 +790 1.304 0.012 +792 1.453 0.013 +794 1.456 0.009 +796 1.213 0.011 +798 1.218 0.01 +800 1.235 0.02 +802 1.068 0.008 +804 1.066 0.008 +806 1.069 0.01 +808 1.085 0.009 +810 1.096 0.008 +812 1.095 0.009 +814 1.082 0.009 +816 1.088 0.01 +818 1.094 0.008 +820 1.097 0.009 +822 1.106 0.008 +824 1.11 0.009 +826 1.125 0.008 +828 1.129 0.01 +830 1.134 0.008 +832 1.13 0.008 +834 1.141 0.008 +836 1.251 0.011 +838 1.344 0.01 +840 1.367 0.01 +842 1.261 0.009 +844 1.169 0.009 +846 1.172 0.008 +848 1.176 0.009 +850 1.212 0.009 +852 1.187 0.01 +854 1.232 0.01 +856 1.204 0.01 +858 1.202 0.008 +860 1.378 0.011 +862 1.213 0.008 +864 1.218 0.009 +866 1.225 0.008 +868 1.231 0.01 +870 1.235 0.009 +872 1.241 0.009 +874 1.245 0.009 +876 1.289 0.009 +878 1.319 0.009 +880 1.278 0.009 +882 1.29 0.009 +884 1.283 0.01 +886 1.28 0.009 +888 1.289 0.009 +890 1.302 0.009 +892 1.842 0.018 +894 1.62 0.01 +896 1.57 0.011 +898 1.684 0.011 +900 1.574 0.013 +902 1.561 0.009 +904 1.334 0.01 +906 1.341 0.009 +908 1.37 0.011 +910 1.388 0.009 +912 1.385 0.009 +914 1.365 0.009 +916 1.372 0.011 +918 1.382 0.011 +920 1.493 0.013 +922 1.465 0.009 +924 1.407 0.009 +926 1.396 0.011 +928 1.407 0.01 +930 1.409 0.009 +932 1.43 0.01 +934 1.436 0.013 +936 1.447 0.009 +938 2.241 0.009 +940 1.462 0.01 +942 1.463 0.01 +944 1.456 0.011 +946 1.463 0.01 +948 1.48 0.009 +950 1.519 0.01 +952 1.524 0.01 +954 1.506 0.01 +956 1.501 0.011 +958 1.535 0.01 +960 1.518 0.01 +962 1.52 0.011 +964 1.628 0.01 +966 1.526 0.01 +968 1.596 0.012 +970 1.55 0.011 +972 1.559 0.01 +974 1.57 0.011 +976 1.563 0.011 +978 1.594 0.011 +980 1.581 0.01 +982 1.593 0.01 +984 1.618 0.01 +986 1.67 0.01 +988 1.607 0.011 +990 1.596 0.011 +992 1.602 0.01 +994 1.641 0.01 +996 1.69 0.011 +998 1.648 0.011 +1000 1.642 0.009 +1002 1.677 0.01 +1004 1.662 0.01 +1006 1.661 0.011 +1008 1.689 0.012 +1010 1.669 0.011 +1012 1.675 0.01 +1014 1.691 0.011 +1016 1.701 0.011 +1018 1.724 0.011 +1020 1.711 0.011 +1022 1.731 0.013 +1024 1.789 0.011 +1026 1.719 0.011 +1028 1.753 0.012 +1030 1.865 0.02 +1032 2.028 0.01 +1034 1.771 0.011 +1036 1.75 0.011 +1038 1.768 0.011 +1040 1.769 0.011 +1042 1.766 0.01 +1044 1.784 0.01 +1046 1.786 0.011 +1048 1.829 0.012 +1050 1.802 0.012 +1052 1.803 0.011 +1054 1.831 0.011 +1056 1.822 0.017 +1058 1.835 0.011 +1060 1.83 0.01 +1062 1.959 0.012 +1064 1.867 0.011 +1066 1.867 0.012 +1068 1.883 0.011 +1070 1.872 0.011 +1072 1.924 0.011 +1074 1.907 0.011 +1076 1.89 0.011 +1078 1.929 0.012 +1080 1.931 0.011 +1082 1.928 0.011 +1084 1.922 0.011 +1086 1.933 0.011 +1088 1.952 0.012 +1090 1.952 0.012 +1092 1.955 0.017 +1094 1.996 0.012 +1096 2.125 0.012 +1098 2.046 0.012 +1100 1.974 0.012 +1102 2.005 0.012 +1104 2.051 0.011 +1106 2.002 0.012 +1108 2.178 0.012 +1110 2.013 0.011 +1112 2.04 0.011 +1114 2.044 0.012 +1116 2.046 0.012 +1118 2.044 0.011 +1120 2.045 0.011 +1122 2.108 0.012 +1124 2.083 0.012 +1126 2.084 0.011 +1128 2.132 0.011 +1130 2.089 0.013 +1132 2.093 0.011 +1134 2.113 0.013 +1136 2.133 0.011 +1138 2.247 0.013 +1140 2.174 0.013 +1142 2.143 0.013 +1144 2.165 0.012 +1146 2.158 0.011 +1148 2.162 0.012 +1150 2.154 0.012 +1152 2.156 0.011 +1154 2.211 0.012 +1156 2.261 0.012 +1158 2.197 0.012 +1160 2.191 0.012 +1162 2.208 0.014 +1164 2.217 0.012 +1166 2.211 0.012 +1168 2.684 0.013 +1170 2.619 0.015 +1172 2.685 0.014 +1174 2.651 0.012 +1176 2.325 0.012 +1178 2.309 0.011 +1180 2.263 0.011 +1182 2.277 0.013 +1184 2.277 0.011 +1186 2.285 0.011 +1188 2.292 0.011 +1190 2.302 0.011 +1192 2.318 0.014 +1194 2.403 0.013 +1196 2.496 0.013 +1198 2.427 0.012 +1200 2.488 0.014 +1202 2.399 0.012 +1204 2.362 0.012 +1206 2.383 0.013 +1208 2.421 0.013 +1210 2.384 0.011 +1212 2.43 0.013 +1214 2.411 0.012 +1216 2.448 0.012 +1218 2.411 0.012 +1220 2.431 0.013 +1222 2.435 0.014 +1224 2.508 0.012 +1226 2.458 0.013 +1228 2.449 0.012 +1230 2.46 0.012 +1232 2.626 0.012 +1234 2.609 0.012 +1236 2.487 0.012 +1238 2.676 0.013 +1240 2.503 0.012 +1242 2.523 0.012 +1244 2.531 0.013 +1246 2.533 0.013 +1248 2.607 0.015 +1250 2.621 0.012 +1252 2.685 0.013 +1254 2.585 0.012 +1256 2.607 0.014 +1258 2.579 0.013 +1260 2.6 0.014 +1262 2.603 0.013 +1264 2.66 0.012 +1266 2.618 0.014 +1268 2.614 0.014 +1270 2.725 0.013 +1272 2.663 0.012 +1274 2.679 0.012 +1276 2.656 0.012 +1278 2.674 0.012 +1280 2.702 0.014 +1282 2.858 0.014 +1284 2.677 0.013 +1286 2.797 0.014 +1288 2.707 0.018 +1290 2.753 0.014 +1292 2.771 0.013 +1294 2.748 0.013 +1296 2.732 0.013 +1298 2.825 0.014 +1300 2.791 0.013 +1302 2.805 0.014 +1304 2.801 0.013 +1306 2.792 0.013 +1308 2.789 0.014 +1310 2.803 0.014 +1312 2.808 0.013 +1314 2.853 0.014 +1316 2.826 0.013 +1318 2.876 0.013 +1320 2.876 0.013 +1322 3.026 0.017 +1324 2.975 0.013 +1326 2.914 0.013 +1328 2.885 0.013 +1330 2.913 0.013 +1332 2.879 0.014 +1334 2.998 0.013 +1336 2.923 0.014 +1338 2.946 0.015 +1340 2.949 0.019 +1342 2.93 0.014 +1344 2.934 0.013 +1346 3.032 0.013 +1348 3.247 0.013 +1350 2.974 0.014 +1352 3.005 0.013 +1354 3.029 0.013 +1356 3.058 0.013 +1358 3.033 0.013 +1360 3.011 0.013 +1362 3.204 0.019 +1364 3.135 0.016 +1366 3.085 0.014 +1368 3.051 0.014 +1370 3.08 0.014 +1372 3.136 0.014 +1374 3.104 0.021 +1376 3.116 0.015 +1378 3.214 0.014 +1380 3.121 0.014 +1382 3.132 0.015 +1384 3.147 0.015 +1386 3.187 0.016 +1388 3.135 0.014 +1390 3.143 0.015 +1392 3.232 0.014 +1394 3.183 0.014 +1396 3.179 0.013 +1398 3.184 0.015 +1400 3.244 0.015 +1402 3.232 0.014 +1404 3.727 0.016 +1406 3.246 0.015 +1408 3.402 0.014 +1410 3.289 0.014 +1412 3.246 0.014 +1414 3.297 0.014 +1416 3.311 0.014 +1418 3.909 0.015 +1420 3.293 0.014 +1422 3.391 0.018 +1424 3.405 0.015 +1426 3.342 0.014 +1428 3.4 0.015 +1430 3.334 0.014 +1432 3.511 0.014 +1434 3.384 0.014 +1436 3.443 0.014 +1438 3.409 0.014 +1440 3.409 0.015 +1442 3.428 0.014 +1444 3.411 0.015 +1446 3.543 0.015 +1448 3.447 0.018 +1450 3.497 0.015 +1452 3.512 0.015 +1454 3.492 0.016 +1456 3.465 0.015 +1458 3.712 0.018 +1460 3.539 0.014 +1462 3.508 0.014 +1464 3.593 0.016 +1466 3.539 0.015 +1468 3.593 0.014 +1470 3.516 0.015 +1472 3.569 0.015 +1474 3.544 0.017 +1476 3.572 0.015 +1478 3.549 0.015 +1480 3.573 0.014 +1482 3.586 0.014 +1484 3.597 0.015 +1486 3.698 0.015 +1488 3.61 0.015 +1490 3.617 0.016 +1492 3.634 0.015 +1494 3.644 0.015 +1496 3.649 0.016 +1498 3.75 0.014 +1500 3.736 0.016 +1502 3.669 0.015 +1504 3.7 0.014 +1506 3.716 0.016 +1508 3.723 0.015 +1510 4.286 0.017 +1512 4.617 0.017 +1514 4.222 0.017 +1516 3.743 0.015 +1518 3.797 0.014 +1520 3.857 0.016 +1522 3.775 0.017 +1524 3.86 0.018 +1526 4.028 0.016 +1528 4.417 0.016 +1530 3.825 0.016 +1532 3.907 0.015 +1534 3.864 0.017 +1536 3.862 0.016 +1538 3.881 0.015 +1540 3.851 0.015 +1542 4.304 0.02 +1544 3.885 0.016 +1546 3.975 0.016 +1548 3.91 0.015 +1550 3.958 0.016 +1552 4.123 0.016 +1554 4.061 0.015 +1556 3.991 0.017 +1558 3.947 0.015 +1560 4.031 0.015 +1562 3.994 0.016 +1564 4.15 0.016 +1566 3.98 0.016 +1568 4.236 0.018 +1570 4.004 0.019 +1572 4.108 0.017 +1574 4.556 0.018 +1576 4.972 0.019 +1578 4.222 0.016 +1580 4.112 0.016 +1582 4.103 0.015 +1584 4.075 0.016 +1586 4.113 0.016 +1588 4.322 0.016 +1590 4.361 0.015 +1592 4.342 0.019 +1594 4.209 0.016 +1596 4.194 0.016 +1598 4.493 0.024 +1600 4.505 0.017 +1602 4.168 0.017 +1604 4.443 0.016 +1606 4.362 0.015 +1608 4.32 0.017 +1610 4.238 0.019 +1612 4.284 0.016 +1614 4.264 0.016 +1616 4.577 0.015 +1618 5.1 0.019 +1620 4.404 0.016 +1622 4.387 0.015 +1624 4.332 0.016 +1626 4.366 0.016 +1628 4.405 0.02 +1630 4.383 0.015 +1632 4.33 0.016 +1634 4.387 0.016 +1636 4.422 0.017 +1638 4.463 0.017 +1640 4.48 0.017 +1642 4.399 0.016 +1644 4.484 0.016 +1646 4.512 0.017 +1648 4.543 0.016 +1650 4.473 0.016 +1652 4.506 0.018 +1654 4.529 0.016 +1656 4.519 0.016 +1658 4.497 0.017 +1660 4.483 0.018 +1662 4.872 0.023 +1664 5.107 0.016 +1666 4.547 0.017 +1668 4.646 0.017 +1670 4.555 0.017 +1672 4.575 0.016 +1674 4.707 0.016 +1676 4.856 0.016 +1678 4.628 0.017 +1680 4.602 0.016 +1682 4.629 0.019 +1684 5.117 0.02 +1686 4.774 0.017 +1688 4.67 0.017 +1690 4.681 0.016 +1692 5.428 0.017 +1694 4.9 0.016 +1696 4.667 0.018 +1698 4.94 0.02 +1700 4.98 0.016 +1702 4.724 0.017 +1704 5.199 0.017 +1706 4.941 0.018 +1708 4.735 0.017 +1710 4.744 0.017 +1712 4.805 0.016 +1714 4.794 0.02 +1716 4.934 0.018 +1718 4.792 0.017 +1720 4.801 0.018 +1722 4.808 0.016 +1724 4.818 0.017 +1726 4.87 0.018 +1728 4.938 0.017 +1730 4.854 0.016 +1732 5.007 0.018 +1734 5.018 0.018 +1736 5.274 0.018 +1738 4.913 0.017 +1740 5.361 0.025 +1742 5.274 0.021 +1744 5.115 0.017 +1746 4.971 0.017 +1748 5.686 0.019 +1750 6.273 0.021 +1752 5.192 0.017 +1754 5.016 0.018 +1756 6.154 0.02 +1758 6.17 0.026 +1760 5.268 0.018 +1762 5.036 0.017 +1764 5.044 0.018 +1766 5.058 0.018 +1768 5.103 0.018 +1770 5.203 0.017 +1772 5.17 0.018 +1774 5.152 0.018 +1776 5.224 0.017 +1778 5.166 0.019 +1780 5.173 0.018 +1782 5.181 0.018 +1784 5.208 0.017 +1786 5.352 0.028 +1788 5.31 0.026 +1790 5.66 0.018 +1792 5.447 0.02 +1794 5.434 0.018 +1796 5.405 0.018 +1798 5.305 0.018 +1800 5.365 0.018 +1802 5.742 0.018 +1804 5.32 0.017 +1806 5.322 0.018 +1808 5.357 0.02 +1810 5.35 0.02 +1812 5.362 0.018 +1814 5.49 0.019 +1816 5.347 0.019 +1818 6.98 0.025 +1820 5.664 0.019 +1822 5.471 0.019 +1824 5.446 0.018 +1826 5.463 0.02 +1828 5.548 0.02 +1830 5.489 0.017 +1832 6.675 0.02 +1834 6.441 0.023 +1836 5.537 0.019 +1838 5.488 0.018 +1840 5.492 0.02 +1842 5.519 0.019 +1844 5.531 0.017 +1846 5.53 0.019 +1848 5.823 0.019 +1850 5.645 0.018 +1852 5.576 0.025 +1854 5.699 0.019 +1856 6.2 0.019 +1858 5.788 0.021 +1860 5.692 0.02 +1862 5.685 0.019 +1864 5.825 0.018 +1866 6.755 0.024 +1868 7.145 0.025 +1870 7.318 0.024 +1872 7.331 0.022 +1874 7.459 0.024 +1876 7.406 0.023 +1878 7.381 0.024 +1880 7.439 0.024 +1882 7.269 0.025 +1884 7.68 0.035 +1886 7.24 0.024 +1888 6.819 0.021 +1890 6.444 0.021 +1892 6.26 0.019 +1894 5.906 0.019 +1896 5.855 0.02 +1898 5.887 0.02 +1900 5.871 0.019 +1902 6.028 0.023 +1904 5.998 0.019 +1906 5.959 0.019 +1908 5.996 0.034 +1910 6.633 0.02 +1912 5.929 0.02 +1914 6.094 0.02 +1916 6.386 0.018 +1918 6.523 0.02 +1920 6.161 0.019 +1922 6.025 0.021 +1924 6.44 0.019 +1926 6.118 0.019 +1928 6.083 0.02 +1930 6.3 0.019 +1932 6.046 0.019 +1934 6.799 0.02 +1936 6.389 0.019 +1938 6.12 0.019 +1940 6.334 0.019 +1942 6.141 0.02 +1944 6.237 0.018 +1946 7.067 0.022 +1948 6.738 0.02 +1950 6.253 0.019 +1952 6.195 0.019 +1954 7.063 0.02 +1956 6.24 0.019 +1958 6.245 0.02 +1960 6.947 0.024 +1962 6.669 0.019 +1964 6.499 0.019 +1966 6.345 0.019 +1968 6.377 0.023 +1970 6.345 0.021 +1972 6.445 0.02 +1974 6.387 0.019 +1976 6.35 0.02 +1978 6.46 0.025 +1980 6.639 0.021 +1982 6.455 0.019 +1984 7.227 0.021 +1986 6.449 0.02 +1988 6.413 0.019 +1990 8.02 0.028 +1992 7.195 0.02 +1994 6.539 0.021 +1996 6.668 0.02 +1998 6.598 0.02 +2000 6.49 0.019 diff --git a/src/algorithm_practice/Dynamic_Programming/maximumSubarray/max.cpp b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/max.cpp new file mode 100644 index 00000000..8f1d6e27 --- /dev/null +++ b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/max.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include + +// Source: CLRS Chatper 4 Section 1 +// Source: https://leetcode.com/problems/maximum-subarray/description/ +// Source: https://blog.domfarolino.com/Maximum-Subarray-Study/ + +/** + * Maximum Subarray + * This is a really interesting and important problem. For a complete + * problem description, see the Leetcode link above. For a complete solution + * read the README in this directory explaining Kadane's algorithm, and see the + * link to my blog post above. + */ + +/** + * Naive maximum subarray algorithm + * Theta(n^2) by looking at every contiguous + * subarray in the entire array A[low, ..., high] + */ +std::tuple maximumSubarrayNaive(const std::vector &nums) { + int sum = INT_MIN, currentSum, subArrayStart, subArrayEnd; + + for (int i = 0; i < nums.size(); ++i) { + currentSum = 0; + for (int j = i; j < nums.size(); ++j) { + currentSum += nums[j]; + if (currentSum > sum) { + sum = currentSum; + subArrayStart = i; + subArrayEnd = j; + } + } + + } + + return std::make_tuple(subArrayStart, subArrayEnd, sum); +} + +/** + * Dynamic programming. + * This algorithm embodies + * the technique of keeping track + * of the maxSubarray we have come + * accross thus far. This gives us a + * one-pass O(n) solution, and is essentially + * Kadane's max sum subarray algorithm. + */ +std::tuple maximumSubarrayLinear(const std::vector &nums) { + if (!nums.size()) return std::make_tuple(0, 0, 0); + int currStartIndex, currEndIndex, startIndex, endIndex; + int maxSum = INT_MIN, currSum = 0; + + for (int i = 0; i < nums.size(); i++) { + if (currSum + nums[i] < nums[i]) { + // Here, having currSum be the subarray that may end with nums[i] is + // actually less beneficial than just starting over with a new subarray @ i. + currStartIndex = i; + currSum = nums[i]; + } else { + // Update the existing subarray we're trying out to now include nums[i] + currSum += nums[i]; + } + + endIndex = i; + if (currSum > maxSum) { + maxSum = currSum; + startIndex = currStartIndex; + endIndex = currEndIndex; + } + } + + return std::make_tuple(startIndex, endIndex, maxSum); +} + +// TODO(domfarolino): Consider adding the divide and conquer solution from CLRS. +int main() { + srand(0); + std::vector a; + std::vector b; + + int s = 2000; + std::cout << "# Size" << '\t' << "Naive" << '\t' << /*"Divide and Conquer" <<*/ "Linear" << std::endl; + int push; + for (int i = 2; i <= s; i+=2) { + for (int j = 0; j < i; ++j) { + push = rand() % 20000; + if (rand() % 3) push *= -1; + a.push_back(push); + } + clock_t clock_a_start = clock(); + maximumSubarrayNaive(a); + clock_t clock_a_stop = clock(); + + /* + clock_t clock_b_start = clock(); + maximumSubarrayDivideAndConquer(a, 0, a.size()-1); + clock_t clock_b_stop = clock(); + */ + + clock_t clock_c_start = clock(); + maximumSubarrayLinear(a); + clock_t clock_c_stop = clock(); + + std::cout << i << '\t'; + std::cout << (float)(clock_a_stop - clock_a_start)/(CLOCKS_PER_SEC/1000) << '\t'; + //cout << (float)(clock_b_stop - clock_b_start)/(CLOCKS_PER_SEC/1000) << '\t'; + std::cout << (float)(clock_c_stop - clock_c_start)/(CLOCKS_PER_SEC/1000) << std::endl; + + a.clear(); + } + + return 0; +} diff --git a/src/algorithm_practice/Dynamic_Programming/maximumSubarray/ojAns.cpp b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/ojAns.cpp new file mode 100644 index 00000000..6fe4dfc6 --- /dev/null +++ b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/ojAns.cpp @@ -0,0 +1,21 @@ +// Source: https://leetcode.com/problems/maximum-subarray/description/ + +class Solution { +public: +int maxSubArray(const std::vector &nums) { + if (!nums.size()) return 0; + int maxSum = INT_MIN, currSum = 0; + + for (int i = 0; i < nums.size(); i++) { + if (currSum + nums[i] < nums[i]) + currSum = nums[i]; + else + currSum += nums[i]; + + maxSum = max(maxSum, currSum); + } + + return maxSum; +} + +}; diff --git a/src/algorithm_practice/Dynamic_Programming/maximumSubarray/plot.png b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/plot.png new file mode 100644 index 00000000..214477ad Binary files /dev/null and b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/plot.png differ diff --git a/src/algorithm_practice/Dynamic_Programming/maximumSubarray/plot.txt b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/plot.txt new file mode 100644 index 00000000..b4e217e4 --- /dev/null +++ b/src/algorithm_practice/Dynamic_Programming/maximumSubarray/plot.txt @@ -0,0 +1,5 @@ +set title "Maximum Subarray Solution Analysis" +set xlabel "Array Size" +set ylabel "Time (ms)" +set output "plot.svg" +plot "data.txt" using 1:2 title 'Naive' smooth unique, "data.txt" using 1:3 title "Linear" with linespoints