diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000000..9397c04a1ad1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# REF: https://spec.editorconfig.org/#supported-pairs + +root = true + +[*] +indent_style = space +indent_size = 4 +# tab_width = 4 +# end_of_line = lf +charset = utf-8 +# spelling_language = en-US +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{md}] +trim_trailing_whitespace = false + +[*.{go}] +indent_style = tab + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.husky/commit-msg b/.husky/commit-msg index 34eed8b2868d..823cbaa47f80 100644 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1 +1,3 @@ -npx --no -- commitlint --edit $1 \ No newline at end of file +#!/bin/sh + +npx --no -- commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit index f031a09bd442..b915ae7603b0 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,3 @@ -npx lint-staged --allow-empty $1 \ No newline at end of file +#!/bin/sh + +npx lint-staged --allow-empty $1 diff --git a/.prettierignore b/.prettierignore index 98948b2cd253..05bf32e47805 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,7 +16,6 @@ node_modules/ /solution/0100-0199/0177.Nth Highest Salary/Solution.sql /solution/0100-0199/0178.Rank Scores/Solution2.sql /solution/0500-0599/0586.Customer Placing the Largest Number of Orders/Solution2.sql -/solution/1400-1499/1454.Active Users/Solution.sql /solution/1600-1699/1635.Hopper Company Queries I/Solution.sql /solution/2100-2199/2118.Build the Equation/Solution.sql /solution/2100-2199/2175.The Change in Global Rankings/Solution.sql @@ -25,4 +24,4 @@ node_modules/ /solution/2200-2299/2252.Dynamic Pivoting of a Table/Solution.sql /solution/2200-2299/2253.Dynamic Unpivoting of a Table/Solution.sql /solution/3100-3199/3150.Invalid Tweets II/Solution.sql -/solution/3100-3199/3198.Find Cities in Each State/Solution.sql \ No newline at end of file +/solution/3100-3199/3198.Find Cities in Each State/Solution.sql diff --git a/images/starcharts.svg b/images/starcharts.svg index 485f9a72848d..cd058586c205 100644 --- a/images/starcharts.svg +++ b/images/starcharts.svg @@ -1,4 +1,4 @@ - + \n2018-09-252019-06-162020-03-072020-11-272021-08-182022-05-102023-01-302023-10-222024-07-12Time2018-09-252019-06-212020-03-162020-12-102021-09-062022-06-022023-02-262023-11-222024-08-17Time038007500113001500018800225002630030000Stargazers039007800117001550019400233002720031000Stargazers \ No newline at end of file +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 882 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 45 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 883 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 44 +L 884 43 +L 884 43 +L 884 43 +L 884 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 885 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 886 43 +L 887 43 +L 887 43 +L 887 43 +L 887 43 +L 887 43 +L 887 43 +L 887 43 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 887 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 888 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 42 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 889 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 890 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 41 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 891 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 892 40 +L 893 40 +L 893 40 +L 893 40 +L 893 40 +L 893 40 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 893 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 894 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 39 +L 895 38 +L 895 38 +L 895 38 +L 895 38 +L 895 38 +L 895 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 896 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 897 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 38 +L 898 37 +L 898 37 +L 898 37 +L 898 37 +L 898 37 +L 898 37 +L 898 37 +L 898 37 +L 898 37 +L 898 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 899 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 900 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 37 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 901 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 902 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 903 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 36 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 904 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 905 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 906 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 35 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 907 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 908 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 909 34 +L 910 34 +L 910 34 +L 910 34 +L 910 34 +L 910 34 +L 910 34 +L 910 34 +L 910 34 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 910 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 911 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 33 +L 912 32 +L 912 32 +L 912 32 +L 912 32 +L 912 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 913 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 914 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 32 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 915 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 916 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 31 +L 917 30 +L 917 30 +L 917 30 +L 917 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 918 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 30 +L 919 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 920 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 921 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 29 +L 922 28 +L 922 28 +L 922 28 +L 922 28 +L 922 28 +L 922 28 +L 922 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 923 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 924 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 28 +L 925 27 +L 925 27 +L 925 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 926 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 927 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 27 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 928 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 929 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 930 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 26 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 931 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 932 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 25 +L 933 24 +L 933 24 +L 933 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 934 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 935 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 24 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 936 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 937 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 938 23 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 939 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 940 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 22 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 941 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 942 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 21 +L 943 20 +L 943 20 +L 943 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 944 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 20 +L 945 19 +L 945 19 +L 945 19 +L 945 19 +L 945 19 +L 945 19 +L 945 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 946 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 19 +L 947 18 +L 947 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 948 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 949 18 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17 +L 950 17" style="stroke-width:2;stroke:rgba(129,199,239,1.0);fill:none"/> \ No newline at end of file diff --git a/lcci/03.01.Three in One/README.md b/lcci/03.01.Three in One/README.md index e9e9bd2ee6f2..3a2604f22caf 100644 --- a/lcci/03.01.Three in One/README.md +++ b/lcci/03.01.Three in One/README.md @@ -47,7 +47,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/03.01.Three%20in%20On ### 方法一:数组模拟 -我们使用一个变量 $cap$ 来表示每个栈的大小,使用一个长度为 $3 \times \text{cap} + 3$ 的数组 $stk$ 来模拟三个栈,数组的前 $3 \times \text{cap}$ 个元素用来存储栈的元素,数组的后三个元素用来存储每个栈的元素个数。 +我们使用一个变量 $cap$ 来表示每个栈的大小,使用一个长度为 $3 \times \textit{cap} + 3$ 的数组 $stk$ 来模拟三个栈,数组的前 $3 \times \textit{cap}$ 个元素用来存储栈的元素,数组的后三个元素用来存储每个栈的元素个数。 对于 `push` 操作,我们首先判断栈是否已满,如果未满,则将元素压入栈中,并更新栈的元素个数。 @@ -55,9 +55,9 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/03.01.Three%20in%20On 对于 `peek` 操作,我们首先判断栈是否为空,如果不为空,则返回栈顶元素。 -对于 `isEmpty` 操作,我们直接判断栈是否为空即可。对于栈 $i$,我们只需要判断 $stk[\text{cap} \times 3 + i]$ 是否为 $0$ 即可。 +对于 `isEmpty` 操作,我们直接判断栈是否为空即可。对于栈 $i$,我们只需要判断 $stk[\textit{cap} \times 3 + i]$ 是否为 $0$ 即可。 -时间复杂度上,每个操作的时间复杂度均为 $O(1)$。空间复杂度为 $O(\text{cap})$,其中 $\text{cap}$ 为栈的大小。 +时间复杂度上,每个操作的时间复杂度均为 $O(1)$。空间复杂度为 $O(\textit{cap})$,其中 $\textit{cap}$ 为栈的大小。 diff --git a/lcci/03.01.Three in One/README_EN.md b/lcci/03.01.Three in One/README_EN.md index 61347236f71d..e3a480115049 100644 --- a/lcci/03.01.Three in One/README_EN.md +++ b/lcci/03.01.Three in One/README_EN.md @@ -62,7 +62,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/03.01.Three%20in%20On ### Solution 1: Array Simulation -We use a variable $cap$ to represent the size of each stack, and use an array $stk$ of length $3 \times \text{cap} + 3$ to simulate three stacks. The first $3 \times \text{cap}$ elements of the array are used to store the elements of the stack, and the last three elements are used to store the number of elements in each stack. +We use a variable $cap$ to represent the size of each stack, and use an array $stk$ of length $3 \times \textit{cap} + 3$ to simulate three stacks. The first $3 \times \textit{cap}$ elements of the array are used to store the elements of the stack, and the last three elements are used to store the number of elements in each stack. For the `push` operation, we first check whether the stack is full. If it is not full, we push the element into the stack and update the number of elements in the stack. @@ -70,9 +70,9 @@ For the `pop` operation, we first check whether the stack is empty. If it is not For the `peek` operation, we first check whether the stack is empty. If it is not empty, we return the top element of the stack. -For the `isEmpty` operation, we directly check whether the stack is empty. For stack $i$, we only need to check whether $stk[\text{cap} \times 3 + i]$ is $0$. +For the `isEmpty` operation, we directly check whether the stack is empty. For stack $i$, we only need to check whether $stk[\textit{cap} \times 3 + i]$ is $0$. -In terms of time complexity, the time complexity of each operation is $O(1)$. The space complexity is $O(\text{cap})$, where $\text{cap}$ is the size of the stack. +In terms of time complexity, the time complexity of each operation is $O(1)$. The space complexity is $O(\textit{cap})$, where $\textit{cap}$ is the size of the stack. diff --git a/lcci/04.02.Minimum Height Tree/README.md b/lcci/04.02.Minimum Height Tree/README.md index dedb278968fc..3fccbc8f9376 100644 --- a/lcci/04.02.Minimum Height Tree/README.md +++ b/lcci/04.02.Minimum Height Tree/README.md @@ -24,12 +24,12 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/04.02.Minimum%20Heigh ### 方法一:递归 -我们设计一个函数 $\text{dfs}(l, r)$,表示构造出从 $l$ 到 $r$ 的子树,那么答案就是 $\text{dfs}(0, \text{len}(nums) - 1)$。 +我们设计一个函数 $\textit{dfs}(l, r)$,表示构造出从 $l$ 到 $r$ 的子树,那么答案就是 $\textit{dfs}(0, \textit{len}(nums) - 1)$。 -函数 $\text{dfs}(l, r)$ 的执行过程如下: +函数 $\textit{dfs}(l, r)$ 的执行过程如下: -1. 如果 $l > r$,返回 $\text{None}$。 -2. 否则,我们计算出中间位置 $mid = \frac{l + r}{2}$,然后构造出根节点,左子树为 $\text{dfs}(l, mid - 1)$,右子树为 $\text{dfs}(mid + 1, r)$。 +1. 如果 $l > r$,返回 $\textit{None}$。 +2. 否则,我们计算出中间位置 $mid = \frac{l + r}{2}$,然后构造出根节点,左子树为 $\textit{dfs}(l, mid - 1)$,右子树为 $\textit{dfs}(mid + 1, r)$。 3. 最后返回根节点。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。 diff --git a/lcci/04.05.Legal Binary Search Tree/README.md b/lcci/04.05.Legal Binary Search Tree/README.md index 8c738774f7d2..290f758b7d25 100644 --- a/lcci/04.05.Legal Binary Search Tree/README.md +++ b/lcci/04.05.Legal Binary Search Tree/README.md @@ -26,7 +26,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/04.05.Legal%20Binary% 我们可以对二叉树进行递归中序遍历,如果遍历到的结果是严格升序的,那么这棵树就是一个二叉搜索树。 -因此,我们使用一个变量 $\textit{prev}$ 来保存上一个遍历到的节点,初始时 $\textit{prev} = -\infty$,然后我们递归遍历左子树,如果左子树不是二叉搜索树,直接返回 $\text{False}$,否则判断当前节点的值是否大于 $\textit{prev}$,如果不是,返回 $\text{False}$,否则更新 $\textit{prev}$ 为当前节点的值,然后递归遍历右子树。 +因此,我们使用一个变量 $\textit{prev}$ 来保存上一个遍历到的节点,初始时 $\textit{prev} = -\infty$,然后我们递归遍历左子树,如果左子树不是二叉搜索树,直接返回 $\textit{False}$,否则判断当前节点的值是否大于 $\textit{prev}$,如果不是,返回 $\textit{False}$,否则更新 $\textit{prev}$ 为当前节点的值,然后递归遍历右子树。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。 diff --git a/lcci/05.02.Binary Number to String/README.md b/lcci/05.02.Binary Number to String/README.md index e65e49dbeebd..2064ff9d442e 100644 --- a/lcci/05.02.Binary Number to String/README.md +++ b/lcci/05.02.Binary Number to String/README.md @@ -42,10 +42,10 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/05.02.Binary%20Number $$ \begin{aligned} -0.8125 \times 2 &= 1.625 \quad \text{取整数部分} \quad 1 \\ -0.625 \times 2 &= 1.25 \quad \text{取整数部分} \quad 1 \\ -0.25 \times 2 &= 0.5 \quad \text{取整数部分} \quad 0 \\ -0.5 \times 2 &= 1 \quad \text{取整数部分} \quad 1 \\ +0.8125 \times 2 &= 1.625 \quad \textit{取整数部分} \quad 1 \\ +0.625 \times 2 &= 1.25 \quad \textit{取整数部分} \quad 1 \\ +0.25 \times 2 &= 0.5 \quad \textit{取整数部分} \quad 0 \\ +0.5 \times 2 &= 1 \quad \textit{取整数部分} \quad 1 \\ \end{aligned} $$ diff --git a/lcci/05.02.Binary Number to String/README_EN.md b/lcci/05.02.Binary Number to String/README_EN.md index c54d0c6cad2b..39edca43b3d3 100644 --- a/lcci/05.02.Binary Number to String/README_EN.md +++ b/lcci/05.02.Binary Number to String/README_EN.md @@ -51,10 +51,10 @@ Let's take an example, suppose we want to convert $0.8125$ to a binary fraction, $$ \begin{aligned} -0.8125 \times 2 &= 1.625 \quad \text{take the integer part} \quad 1 \\ -0.625 \times 2 &= 1.25 \quad \text{take the integer part} \quad 1 \\ -0.25 \times 2 &= 0.5 \quad \text{take the integer part} \quad 0 \\ -0.5 \times 2 &= 1 \quad \text{take the integer part} \quad 1 \\ +0.8125 \times 2 &= 1.625 \quad \textit{take the integer part} \quad 1 \\ +0.625 \times 2 &= 1.25 \quad \textit{take the integer part} \quad 1 \\ +0.25 \times 2 &= 0.5 \quad \textit{take the integer part} \quad 0 \\ +0.5 \times 2 &= 1 \quad \textit{take the integer part} \quad 1 \\ \end{aligned} $$ diff --git a/lcci/05.07.Exchange/README.md b/lcci/05.07.Exchange/README.md index ea45ce6241d4..a6c96240f256 100644 --- a/lcci/05.07.Exchange/README.md +++ b/lcci/05.07.Exchange/README.md @@ -44,7 +44,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/05.07.Exchange/README ### 方法一:位运算 -我们可以将 $\text{num}$ 与 $\text{0x55555555}$ 进行与运算,得到的结果是 $\text{num}$ 的偶数位,然后将其左移一位。再将 $\text{num}$ 与 $\text{0xaaaaaaaa}$ 进行与运算,得到的结果是 $\text{num}$ 的奇数位,然后将其右移一位。最后将两个结果进行或运算,即可得到答案。 +我们可以将 $\textit{num}$ 与 $\textit{0x55555555}$ 进行与运算,得到的结果是 $\textit{num}$ 的偶数位,然后将其左移一位。再将 $\textit{num}$ 与 $\textit{0xaaaaaaaa}$ 进行与运算,得到的结果是 $\textit{num}$ 的奇数位,然后将其右移一位。最后将两个结果进行或运算,即可得到答案。 时间复杂度 $O(1)$,空间复杂度 $O(1)$。 diff --git a/lcci/10.09.Sorted Matrix Search/README.md b/lcci/10.09.Sorted Matrix Search/README.md index f1678a642d65..0cf5d1ed6b3b 100644 --- a/lcci/10.09.Sorted Matrix Search/README.md +++ b/lcci/10.09.Sorted Matrix Search/README.md @@ -249,9 +249,9 @@ class Solution { 这里我们以左下角作为起始搜索点,往右上方向开始搜索,比较当前元素 `matrix[i][j]`与 `target` 的大小关系: -- 若 $\text{matrix}[i][j] = \text{target}$,说明找到了目标值,直接返回 `true`。 -- 若 $\text{matrix}[i][j] > \text{target}$,说明这一列从当前位置开始往上的所有元素均大于 `target`,应该让 $i$ 指针往上移动,即 $i \leftarrow i - 1$。 -- 若 $\text{matrix}[i][j] < \text{target}$,说明这一行从当前位置开始往右的所有元素均小于 `target`,应该让 $j$ 指针往右移动,即 $j \leftarrow j + 1$。 +- 若 $\textit{matrix}[i][j] = \textit{target}$,说明找到了目标值,直接返回 `true`。 +- 若 $\textit{matrix}[i][j] > \textit{target}$,说明这一列从当前位置开始往上的所有元素均大于 `target`,应该让 $i$ 指针往上移动,即 $i \leftarrow i - 1$。 +- 若 $\textit{matrix}[i][j] < \textit{target}$,说明这一行从当前位置开始往右的所有元素均小于 `target`,应该让 $j$ 指针往右移动,即 $j \leftarrow j + 1$。 若搜索结束依然找不到 `target`,返回 `false`。 diff --git a/lcci/10.09.Sorted Matrix Search/README_EN.md b/lcci/10.09.Sorted Matrix Search/README_EN.md index 737900835597..9cf63c625e0c 100644 --- a/lcci/10.09.Sorted Matrix Search/README_EN.md +++ b/lcci/10.09.Sorted Matrix Search/README_EN.md @@ -258,9 +258,9 @@ class Solution { Here, we start searching from the bottom left corner and move towards the top right direction, comparing the current element `matrix[i][j]` with `target`: -- If $\text{matrix}[i][j] = \text{target}$, it means the target value has been found, and we directly return `true`. -- If $\text{matrix}[i][j] > \text{target}$, it means all elements in this column from the current position upwards are greater than `target`, so we should move the $i$ pointer upwards, i.e., $i \leftarrow i - 1$. -- If $\text{matrix}[i][j] < \text{target}$, it means all elements in this row from the current position to the right are less than `target`, so we should move the $j$ pointer to the right, i.e., $j \leftarrow j + 1$. +- If $\textit{matrix}[i][j] = \textit{target}$, it means the target value has been found, and we directly return `true`. +- If $\textit{matrix}[i][j] > \textit{target}$, it means all elements in this column from the current position upwards are greater than `target`, so we should move the $i$ pointer upwards, i.e., $i \leftarrow i - 1$. +- If $\textit{matrix}[i][j] < \textit{target}$, it means all elements in this row from the current position to the right are less than `target`, so we should move the $j$ pointer to the right, i.e., $j \leftarrow j + 1$. If the search ends and the `target` is still not found, return `false`. diff --git a/lcci/16.25.LRU Cache/README_EN.md b/lcci/16.25.LRU Cache/README_EN.md index 615b6cc4fdf0..afedd5b11b2a 100644 --- a/lcci/16.25.LRU Cache/README_EN.md +++ b/lcci/16.25.LRU Cache/README_EN.md @@ -67,7 +67,7 @@ When accessing a node, if the node exists, we delete it from its original positi When inserting a node, if the node exists, we delete it from its original position and reinsert it at the head of the list. If it does not exist, we first check if the cache is full. If it is full, we delete the node at the tail of the list and insert the new node at the head of the list. -The time complexity is $O(1)$, and the space complexity is $O(\text{capacity})$. +The time complexity is $O(1)$, and the space complexity is $O(\textit{capacity})$. diff --git a/lcci/17.20.Continuous Median/README.md b/lcci/17.20.Continuous Median/README.md index dd85a2ce6a2a..10ae1f356a39 100644 --- a/lcci/17.20.Continuous Median/README.md +++ b/lcci/17.20.Continuous Median/README.md @@ -48,11 +48,11 @@ findMedian() -> 2 ### 方法一:大小根堆(优先队列) -我们可以使用两个堆来维护所有的元素,一个小根堆 $\text{minQ}$ 和一个大根堆 $\text{maxQ}$,其中小根堆 $\text{minQ}$ 存储较大的一半,大根堆 $\text{maxQ}$ 存储较小的一半。 +我们可以使用两个堆来维护所有的元素,一个小根堆 $\textit{minQ}$ 和一个大根堆 $\textit{maxQ}$,其中小根堆 $\textit{minQ}$ 存储较大的一半,大根堆 $\textit{maxQ}$ 存储较小的一半。 -调用 `addNum` 方法时,我们首先将元素加入到大根堆 $\text{maxQ}$,然后将 $\text{maxQ}$ 的堆顶元素弹出并加入到小根堆 $\text{minQ}$。如果此时 $\text{minQ}$ 的大小与 $\text{maxQ}$ 的大小差值大于 $1$,我们就将 $\text{minQ}$ 的堆顶元素弹出并加入到 $\text{maxQ}$。时间复杂度为 $O(\log n)$。 +调用 `addNum` 方法时,我们首先将元素加入到大根堆 $\textit{maxQ}$,然后将 $\textit{maxQ}$ 的堆顶元素弹出并加入到小根堆 $\textit{minQ}$。如果此时 $\textit{minQ}$ 的大小与 $\textit{maxQ}$ 的大小差值大于 $1$,我们就将 $\textit{minQ}$ 的堆顶元素弹出并加入到 $\textit{maxQ}$。时间复杂度为 $O(\log n)$。 -调用 `findMedian` 方法时,如果 $\text{minQ}$ 的大小等于 $\text{maxQ}$ 的大小,说明元素的总数为偶数,我们就可以返回 $\text{minQ}$ 的堆顶元素与 $\text{maxQ}$ 的堆顶元素的平均值;否则,我们返回 $\text{minQ}$ 的堆顶元素。时间复杂度为 $O(1)$。 +调用 `findMedian` 方法时,如果 $\textit{minQ}$ 的大小等于 $\textit{maxQ}$ 的大小,说明元素的总数为偶数,我们就可以返回 $\textit{minQ}$ 的堆顶元素与 $\textit{maxQ}$ 的堆顶元素的平均值;否则,我们返回 $\textit{minQ}$ 的堆顶元素。时间复杂度为 $O(1)$。 空间复杂度为 $O(n)$。其中 $n$ 为元素的个数。 diff --git a/lcci/17.20.Continuous Median/README_EN.md b/lcci/17.20.Continuous Median/README_EN.md index 132be30ebad8..6c8ca71a339c 100644 --- a/lcci/17.20.Continuous Median/README_EN.md +++ b/lcci/17.20.Continuous Median/README_EN.md @@ -55,11 +55,11 @@ findMedian() -> 2 ### Solution 1: Min Heap and Max Heap (Priority Queue) -We can use two heaps to maintain all the elements, a min heap $\text{minQ}$ and a max heap $\text{maxQ}$, where the min heap $\text{minQ}$ stores the larger half, and the max heap $\text{maxQ}$ stores the smaller half. +We can use two heaps to maintain all the elements, a min heap $\textit{minQ}$ and a max heap $\textit{maxQ}$, where the min heap $\textit{minQ}$ stores the larger half, and the max heap $\textit{maxQ}$ stores the smaller half. -When calling the `addNum` method, we first add the element to the max heap $\text{maxQ}$, then pop the top element of $\text{maxQ}$ and add it to the min heap $\text{minQ}$. If at this time the size difference between $\text{minQ}$ and $\text{maxQ}$ is greater than $1$, we pop the top element of $\text{minQ}$ and add it to $\text{maxQ}$. The time complexity is $O(\log n)$. +When calling the `addNum` method, we first add the element to the max heap $\textit{maxQ}$, then pop the top element of $\textit{maxQ}$ and add it to the min heap $\textit{minQ}$. If at this time the size difference between $\textit{minQ}$ and $\textit{maxQ}$ is greater than $1$, we pop the top element of $\textit{minQ}$ and add it to $\textit{maxQ}$. The time complexity is $O(\log n)$. -When calling the `findMedian` method, if the size of $\text{minQ}$ is equal to the size of $\text{maxQ}$, it means the total number of elements is even, and we can return the average value of the top elements of $\text{minQ}$ and $\text{maxQ}$; otherwise, we return the top element of $\text{minQ}$. The time complexity is $O(1)$. +When calling the `findMedian` method, if the size of $\textit{minQ}$ is equal to the size of $\textit{maxQ}$, it means the total number of elements is even, and we can return the average value of the top elements of $\textit{minQ}$ and $\textit{maxQ}$; otherwise, we return the top element of $\textit{minQ}$. The time complexity is $O(1)$. The space complexity is $O(n)$, where $n$ is the number of elements. diff --git a/lcci/17.22.Word Transformer/README.md b/lcci/17.22.Word Transformer/README.md index 3955d805a6ae..6d3d28ed495e 100644 --- a/lcci/17.22.Word Transformer/README.md +++ b/lcci/17.22.Word Transformer/README.md @@ -50,15 +50,15 @@ wordList = ["hot","dot","dog","lot",&quo 我们定义一个答案数组 $\textit{ans}$,初始时只包含 $\textit{beginWord}$。然后我们定义一个数组 $\textit{vis}$,用来标记 $\textit{wordList}$ 中的单词是否被访问过。 -接下来,我们设计一个函数 $\text{dfs}(s)$,表示从 $\textit{s}$ 出发,尝试将 $\textit{s}$ 转换为 $\textit{endWord}$,是否能够成功。如果能够成功,返回 $\text{True}$,否则返回 $\text{False}$。 +接下来,我们设计一个函数 $\textit{dfs}(s)$,表示从 $\textit{s}$ 出发,尝试将 $\textit{s}$ 转换为 $\textit{endWord}$,是否能够成功。如果能够成功,返回 $\textit{True}$,否则返回 $\textit{False}$。 -函数 $\text{dfs}(s)$ 的具体实现如下: +函数 $\textit{dfs}(s)$ 的具体实现如下: -1. 如果 $\textit{s}$ 等于 $\textit{endWord}$,说明转换成功,返回 $\text{True}$; -2. 否则,我们遍历 $\textit{wordList}$ 中的每个单词 $\textit{t}$,如果 $\textit{t}$ 没有被访问过且 $\textit{s}$ 和 $\textit{t}$ 之间只有一个字符不同,那么我们将 $\textit{t}$ 标记为已访问,并将 $\textit{t}$ 加入到 $\textit{ans}$ 中,然后递归调用 $\text{dfs}(t)$,如果返回 $\text{True}$,说明转换成功,我们返回 $\text{True}$,否则我们将 $\textit{t}$ 从 $\textit{ans}$ 中移除,继续遍历下一个单词; -3. 如果遍历完 $\textit{wordList}$ 中的所有单词都没有找到可以转换的单词,说明转换失败,我们返回 $\text{False}$。 +1. 如果 $\textit{s}$ 等于 $\textit{endWord}$,说明转换成功,返回 $\textit{True}$; +2. 否则,我们遍历 $\textit{wordList}$ 中的每个单词 $\textit{t}$,如果 $\textit{t}$ 没有被访问过且 $\textit{s}$ 和 $\textit{t}$ 之间只有一个字符不同,那么我们将 $\textit{t}$ 标记为已访问,并将 $\textit{t}$ 加入到 $\textit{ans}$ 中,然后递归调用 $\textit{dfs}(t)$,如果返回 $\textit{True}$,说明转换成功,我们返回 $\textit{True}$,否则我们将 $\textit{t}$ 从 $\textit{ans}$ 中移除,继续遍历下一个单词; +3. 如果遍历完 $\textit{wordList}$ 中的所有单词都没有找到可以转换的单词,说明转换失败,我们返回 $\textit{False}$。 -最后,我们调用 $\text{dfs}(\textit{beginWord})$,如果返回 $\text{True}$,说明转换成功,我们返回 $\textit{ans}$,否则返回空数组。 +最后,我们调用 $\textit{dfs}(\textit{beginWord})$,如果返回 $\textit{True}$,说明转换成功,我们返回 $\textit{ans}$,否则返回空数组。 diff --git a/lcci/17.23.Max Black Square/README.md b/lcci/17.23.Max Black Square/README.md index a109449e1845..be1392c6bbfc 100644 --- a/lcci/17.23.Max Black Square/README.md +++ b/lcci/17.23.Max Black Square/README.md @@ -52,16 +52,16 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcci/17.23.Max%20Black%20S $$ down[i][j] = \begin{cases} -down[i + 1][j] + 1, & matrix[i][j] = 0 \text{ 且 } i + 1 < n \\ -1, & matrix[i][j] = 0 \text{ 且 } i + 1 = n \\ +down[i + 1][j] + 1, & matrix[i][j] = 0 \textit{ 且 } i + 1 < n \\ +1, & matrix[i][j] = 0 \textit{ 且 } i + 1 = n \\ 0, & matrix[i][j] = 1 \end{cases} $$ $$ right[i][j] = \begin{cases} -right[i][j + 1] + 1, & matrix[i][j] = 0 \text{ 且 } j + 1 < n \\ -1, & matrix[i][j] = 0 \text{ 且 } j + 1 = n \\ +right[i][j + 1] + 1, & matrix[i][j] = 0 \textit{ 且 } j + 1 < n \\ +1, & matrix[i][j] = 0 \textit{ 且 } j + 1 = n \\ 0, & matrix[i][j] = 1 \end{cases} $$ diff --git "a/lcof/\351\235\242\350\257\225\351\242\23014- I. \345\211\252\347\273\263\345\255\220/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23014- I. \345\211\252\347\273\263\345\255\220/README.md" index 7bd4e7328cbe..f80ac7c16500 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23014- I. \345\211\252\347\273\263\345\255\220/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23014- I. \345\211\252\347\273\263\345\255\220/README.md" @@ -42,15 +42,22 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9 ### 方法一:动态规划 -我们定义 $f[i]$ 表示正整数 $n$ 能获得的最大乘积,初始化 $f[1] = 1$。答案即为 $f[n]$。 +我们定义 $f[i]$ 表示正整数 $i$ 拆分后能获得的最大乘积,初始时 $f[1] = 1$。答案即为 $f[n]$。 -状态转移方程为: +考虑 $i$ 最后拆分出的数字 $j$,其中 $j \in [1, i)$。对于 $i$ 拆分出的数字 $j$,有两种情况: + +1. 将 $i$ 拆分成 $i - j$ 和 $j$ 的和,不继续拆分,此时乘积为 $(i - j) \times j$; +2. 将 $i$ 拆分成 $i - j$ 和 $j$ 的和,继续拆分,此时乘积为 $f[i - j] \times j$。 + +因此,我们可以得到状态转移方程: $$ f[i] = \max(f[i], f[i - j] \times j, (i - j) \times j) \quad (j \in [0, i)) $$ -时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为正整数 $n$。 +最后返回 $f[n]$ 即可。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为给定的正整数。 @@ -208,7 +215,7 @@ class Solution { ### 方法二:数学 -当 $n \lt 4$,此时 $n$ 不能拆分成至少两个正整数的和,因此 $n - 1$ 是最大乘积。当 $n \ge 4$ 时,我们尽可能多地拆分 $3$,当剩下的最后一段为 $4$ 时,我们将其拆分为 $2 + 2$,这样乘积最大。 +当 $n \lt 4$ 时,由于题目要求至少剪一次,因此 $n - 1$ 是最大乘积。当 $n \ge 4$ 时,我们尽可能多地拆分 $3$,当剩下的最后一段为 $4$ 时,我们将其拆分为 $2 + 2$,这样乘积最大。 时间复杂度 $O(1)$,空间复杂度 $O(1)$。 diff --git "a/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md" index a098001e6570..d82afb7073eb 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23026. \346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/README.md" @@ -54,15 +54,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9 ### 方法一:递归 -我们设计一个函数 $\text{dfs}(A, B)$,用于判断树 A 中以节点 A 为根节点的子树是否包含树 B。 +我们设计一个函数 $\textit{dfs}(A, B)$,用于判断树 A 中以节点 A 为根节点的子树是否包含树 B。 -函数 $\text{dfs}(A, B)$ 的执行步骤如下: +函数 $\textit{dfs}(A, B)$ 的执行步骤如下: 1. 如果树 B 为空,则树 B 是树 A 的子结构,返回 `true`; 2. 如果树 A 为空,或者树 A 的根节点的值不等于树 B 的根节点的值,则树 B 不是树 A 的子结构,返回 `false`; -3. 判断树 A 的左子树是否包含树 B,即调用 $\text{dfs}(A.left, B)$,并且判断树 A 的右子树是否包含树 B,即调用 $\text{dfs}(A.right, B)$。如果其中有一个函数返回 `false`,则树 B 不是树 A 的子结构,返回 `false`;否则,返回 `true`。 +3. 判断树 A 的左子树是否包含树 B,即调用 $\textit{dfs}(A.left, B)$,并且判断树 A 的右子树是否包含树 B,即调用 $\textit{dfs}(A.right, B)$。如果其中有一个函数返回 `false`,则树 B 不是树 A 的子结构,返回 `false`;否则,返回 `true`。 -在函数 `isSubStructure` 中,我们首先判断树 A 和树 B 是否为空,如果其中有一个为空,则树 B 不是树 A 的子结构,返回 `false`。然后,我们调用 $\text{dfs}(A, B)$,判断树 A 是否包含树 B。如果是,则返回 `true`;否则,递归判断树 A 的左子树是否包含树 B,以及树 A 的右子树是否包含树 B。如果其中有一个返回 `true`,则树 B 是树 A 的子结构,返回 `true`;否则,返回 `false`。 +在函数 `isSubStructure` 中,我们首先判断树 A 和树 B 是否为空,如果其中有一个为空,则树 B 不是树 A 的子结构,返回 `false`。然后,我们调用 $\textit{dfs}(A, B)$,判断树 A 是否包含树 B。如果是,则返回 `true`;否则,递归判断树 A 的左子树是否包含树 B,以及树 A 的右子树是否包含树 B。如果其中有一个返回 `true`,则树 B 是树 A 的子结构,返回 `true`;否则,返回 `false`。 时间复杂度 $O(n \times m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是树 A 和树 B 的节点个数。 diff --git "a/lcof/\351\235\242\350\257\225\351\242\23041. \346\225\260\346\215\256\346\265\201\344\270\255\347\232\204\344\270\255\344\275\215\346\225\260/README.md" "b/lcof/\351\235\242\350\257\225\351\242\23041. \346\225\260\346\215\256\346\265\201\344\270\255\347\232\204\344\270\255\344\275\215\346\225\260/README.md" index 6b34dbdd86dc..6e04b4fed401 100644 --- "a/lcof/\351\235\242\350\257\225\351\242\23041. \346\225\260\346\215\256\346\265\201\344\270\255\347\232\204\344\270\255\344\275\215\346\225\260/README.md" +++ "b/lcof/\351\235\242\350\257\225\351\242\23041. \346\225\260\346\215\256\346\265\201\344\270\255\347\232\204\344\270\255\344\275\215\346\225\260/README.md" @@ -60,11 +60,11 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9 ### 方法一:大小根堆(优先队列) -我们可以使用两个堆来维护所有的元素,一个小根堆 $\text{minQ}$ 和一个大根堆 $\text{maxQ}$,其中小根堆 $\text{minQ}$ 存储较大的一半,大根堆 $\text{maxQ}$ 存储较小的一半。 +我们可以使用两个堆来维护所有的元素,一个小根堆 $\textit{minQ}$ 和一个大根堆 $\textit{maxQ}$,其中小根堆 $\textit{minQ}$ 存储较大的一半,大根堆 $\textit{maxQ}$ 存储较小的一半。 -调用 `addNum` 方法时,我们首先将元素加入到大根堆 $\text{maxQ}$,然后将 $\text{maxQ}$ 的堆顶元素弹出并加入到小根堆 $\text{minQ}$。如果此时 $\text{minQ}$ 的大小与 $\text{maxQ}$ 的大小差值大于 $1$,我们就将 $\text{minQ}$ 的堆顶元素弹出并加入到 $\text{maxQ}$。时间复杂度为 $O(\log n)$。 +调用 `addNum` 方法时,我们首先将元素加入到大根堆 $\textit{maxQ}$,然后将 $\textit{maxQ}$ 的堆顶元素弹出并加入到小根堆 $\textit{minQ}$。如果此时 $\textit{minQ}$ 的大小与 $\textit{maxQ}$ 的大小差值大于 $1$,我们就将 $\textit{minQ}$ 的堆顶元素弹出并加入到 $\textit{maxQ}$。时间复杂度为 $O(\log n)$。 -调用 `findMedian` 方法时,如果 $\text{minQ}$ 的大小等于 $\text{maxQ}$ 的大小,说明元素的总数为偶数,我们就可以返回 $\text{minQ}$ 的堆顶元素与 $\text{maxQ}$ 的堆顶元素的平均值;否则,我们返回 $\text{minQ}$ 的堆顶元素。时间复杂度为 $O(1)$。 +调用 `findMedian` 方法时,如果 $\textit{minQ}$ 的大小等于 $\textit{maxQ}$ 的大小,说明元素的总数为偶数,我们就可以返回 $\textit{minQ}$ 的堆顶元素与 $\textit{maxQ}$ 的堆顶元素的平均值;否则,我们返回 $\textit{minQ}$ 的堆顶元素。时间复杂度为 $O(1)$。 空间复杂度为 $O(n)$。其中 $n$ 为元素的个数。 diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 072. \346\261\202\345\271\263\346\226\271\346\240\271/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 072. \346\261\202\345\271\263\346\226\271\346\240\271/README.md" index e5a3f00d1894..c1532de5315a 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 072. \346\261\202\345\271\263\346\226\271\346\240\271/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 072. \346\261\202\345\271\263\346\226\271\346\240\271/README.md" @@ -160,6 +160,29 @@ public class Solution { } ``` +#### Swift + +```swift +class Solution { + func mySqrt(_ x: Int) -> Int { + if x == 0 { + return 0 + } + var left = 0 + var right = x + while left < right { + let mid = (left + right + 1) / 2 + if mid <= x / mid { + left = mid + } else { + right = mid - 1 + } + } + return left + } +} +``` + diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 072. \346\261\202\345\271\263\346\226\271\346\240\271/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 072. \346\261\202\345\271\263\346\226\271\346\240\271/Solution.swift" new file mode 100644 index 000000000000..cbf73f89238e --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 072. \346\261\202\345\271\263\346\226\271\346\240\271/Solution.swift" @@ -0,0 +1,18 @@ +class Solution { + func mySqrt(_ x: Int) -> Int { + if x == 0 { + return 0 + } + var left = 0 + var right = x + while left < right { + let mid = (left + right + 1) / 2 + if mid <= x / mid { + left = mid + } else { + right = mid - 1 + } + } + return left + } +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 073. \347\213\222\347\213\222\345\220\203\351\246\231\350\225\211/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 073. \347\213\222\347\213\222\345\220\203\351\246\231\350\225\211/README.md" index e690c64d1aab..bd642ce6f118 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 073. \347\213\222\347\213\222\345\220\203\351\246\231\350\225\211/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 073. \347\213\222\347\213\222\345\220\203\351\246\231\350\225\211/README.md" @@ -182,6 +182,34 @@ public class Solution { } ``` +#### Swift + +```swift +class Solution { + func minEatingSpeed(_ piles: [Int], _ h: Int) -> Int { + var left = 1 + var right = piles.max() ?? 0 + + while left < right { + let mid = (left + right) / 2 + var hours = 0 + + for pile in piles { + hours += (pile + mid - 1) / mid + } + + if hours <= h { + right = mid + } else { + left = mid + 1 + } + } + + return left + } +} +``` + diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 073. \347\213\222\347\213\222\345\220\203\351\246\231\350\225\211/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 073. \347\213\222\347\213\222\345\220\203\351\246\231\350\225\211/Solution.swift" new file mode 100644 index 000000000000..63a63918a837 --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 073. \347\213\222\347\213\222\345\220\203\351\246\231\350\225\211/Solution.swift" @@ -0,0 +1,23 @@ +class Solution { + func minEatingSpeed(_ piles: [Int], _ h: Int) -> Int { + var left = 1 + var right = piles.max() ?? 0 + + while left < right { + let mid = (left + right) / 2 + var hours = 0 + + for pile in piles { + hours += (pile + mid - 1) / mid + } + + if hours <= h { + right = mid + } else { + left = mid + 1 + } + } + + return left + } +} \ No newline at end of file diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 074. \345\220\210\345\271\266\345\214\272\351\227\264/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 074. \345\220\210\345\271\266\345\214\272\351\227\264/README.md" index 85910bed4d7e..411c4a9817d2 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 074. \345\220\210\345\271\266\345\214\272\351\227\264/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 074. \345\220\210\345\271\266\345\214\272\351\227\264/README.md" @@ -188,6 +188,32 @@ public class Solution { } ``` +#### Swift + +```swift +class Solution { + func merge(_ intervals: [[Int]]) -> [[Int]] { + guard !intervals.isEmpty else { return [] } + + let intervals = intervals.sorted { $0[0] < $1[0] } + var result: [[Int]] = [] + + var currentInterval = intervals[0] + for interval in intervals.dropFirst() { + if currentInterval[1] < interval[0] { + result.append(currentInterval) + currentInterval = interval + } else { + currentInterval[1] = max(currentInterval[1], interval[1]) + } + } + result.append(currentInterval) + + return result + } +} +``` + diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 074. \345\220\210\345\271\266\345\214\272\351\227\264/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 074. \345\220\210\345\271\266\345\214\272\351\227\264/Solution.swift" new file mode 100644 index 000000000000..3962b75d1c53 --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 074. \345\220\210\345\271\266\345\214\272\351\227\264/Solution.swift" @@ -0,0 +1,21 @@ +class Solution { + func merge(_ intervals: [[Int]]) -> [[Int]] { + guard !intervals.isEmpty else { return [] } + + let intervals = intervals.sorted { $0[0] < $1[0] } + var result: [[Int]] = [] + + var currentInterval = intervals[0] + for interval in intervals.dropFirst() { + if currentInterval[1] < interval[0] { + result.append(currentInterval) + currentInterval = interval + } else { + currentInterval[1] = max(currentInterval[1], interval[1]) + } + } + result.append(currentInterval) + + return result + } +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/README.md" index 979fe1952d23..b0debe2acef4 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/README.md" @@ -50,7 +50,11 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%2 -### 方法一 +### 方法一:自定义排序 + +我们先用哈希表 $pos$ 记录数组 $arr2$ 中每个元素的位置。然后,我们将数组 $arr1$ 中的每个元素映射成一个二元组 $(pos.get(x, 1000 + x), x)$,并对二元组进行排序。最后我们取出所有二元组的第二个元素并返回即可。 + +时间复杂度 $O(n \times \log n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是数组 $arr1$ 和 $arr2$ 的长度。 @@ -59,9 +63,8 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%2 ```python class Solution: def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: - mp = {num: i for i, num in enumerate(arr2)} - arr1.sort(key=lambda x: (mp.get(x, 10000), x)) - return arr1 + pos = {x: i for i, x in enumerate(arr2)} + return sorted(arr1, key=lambda x: pos.get(x, 1000 + x)) ``` #### Java @@ -69,20 +72,17 @@ class Solution: ```java class Solution { public int[] relativeSortArray(int[] arr1, int[] arr2) { - int[] mp = new int[1001]; - for (int x : arr1) { - ++mp[x]; + Map pos = new HashMap<>(arr2.length); + for (int i = 0; i < arr2.length; ++i) { + pos.put(arr2[i], i); } - int i = 0; - for (int x : arr2) { - while (mp[x]-- > 0) { - arr1[i++] = x; - } + int[][] arr = new int[arr1.length][0]; + for (int i = 0; i < arr.length; ++i) { + arr[i] = new int[] {arr1[i], pos.getOrDefault(arr1[i], arr2.length + arr1[i])}; } - for (int j = 0; j < mp.length; ++j) { - while (mp[j]-- > 0) { - arr1[i++] = j; - } + Arrays.sort(arr, (a, b) -> a[1] - b[1]); + for (int i = 0; i < arr.length; ++i) { + arr1[i] = arr[i][0]; } return arr1; } @@ -95,14 +95,18 @@ class Solution { class Solution { public: vector relativeSortArray(vector& arr1, vector& arr2) { - vector mp(1001); - for (int x : arr1) ++mp[x]; - int i = 0; - for (int x : arr2) { - while (mp[x]-- > 0) arr1[i++] = x; + unordered_map pos; + for (int i = 0; i < arr2.size(); ++i) { + pos[arr2[i]] = i; } - for (int j = 0; j < mp.size(); ++j) { - while (mp[j]-- > 0) arr1[i++] = j; + vector> arr; + for (int i = 0; i < arr1.size(); ++i) { + int j = pos.count(arr1[i]) ? pos[arr1[i]] : arr2.size(); + arr.emplace_back(j, arr1[i]); + } + sort(arr.begin(), arr.end()); + for (int i = 0; i < arr1.size(); ++i) { + arr1[i] = arr[i].second; } return arr1; } @@ -113,58 +117,250 @@ public: ```go func relativeSortArray(arr1 []int, arr2 []int) []int { - mp := make([]int, 1001) - for _, x := range arr1 { - mp[x]++ + pos := map[int]int{} + for i, x := range arr2 { + pos[x] = i } - i := 0 - for _, x := range arr2 { - for mp[x] > 0 { - arr1[i] = x - mp[x]-- - i++ + arr := make([][2]int, len(arr1)) + for i, x := range arr1 { + if p, ok := pos[x]; ok { + arr[i] = [2]int{p, x} + } else { + arr[i] = [2]int{len(arr2), x} } } - for j, cnt := range mp { - for cnt > 0 { - arr1[i] = j - i++ - cnt-- - } + sort.Slice(arr, func(i, j int) bool { + return arr[i][0] < arr[j][0] || arr[i][0] == arr[j][0] && arr[i][1] < arr[j][1] + }) + for i, x := range arr { + arr1[i] = x[1] } return arr1 } ``` +#### TypeScript + +```ts +function relativeSortArray(arr1: number[], arr2: number[]): number[] { + const pos: Map = new Map(); + for (let i = 0; i < arr2.length; ++i) { + pos.set(arr2[i], i); + } + const arr: number[][] = []; + for (const x of arr1) { + const j = pos.get(x) ?? arr2.length; + arr.push([j, x]); + } + arr.sort((a, b) => a[0] - b[0] || a[1] - b[1]); + return arr.map(a => a[1]); +} +``` + +#### Swift + +```swift +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var pos = [Int: Int]() + for (i, x) in arr2.enumerated() { + pos[x] = i + } + var arr = [(Int, Int)]() + for x in arr1 { + let j = pos[x] ?? arr2.count + arr.append((j, x)) + } + arr.sort { $0.0 < $1.0 || ($0.0 == $1.0 && $0.1 < $1.1) } + return arr.map { $0.1 } + } +} +``` + - + -### 方法二 +### 方法二:计数排序 - +我们可以使用计数排序的思想,首先统计数组 $arr1$ 中每个元素的出现次数,然后按照数组 $arr2$ 中的顺序,将 $arr1$ 中的元素按照出现次数放入答案数组 $ans$ 中。最后,我们遍历 $arr1$ 中的所有元素,将未在 $arr2$ 中出现的元素按照升序放入答案数组 $ans$ 的末尾。 + +时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 $arr1$ 和 $arr2$ 的长度。 + + #### Python3 ```python class Solution: def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: - mp = [0] * 1001 - for x in arr1: - mp[x] += 1 - i = 0 + cnt = Counter(arr1) + ans = [] for x in arr2: - while mp[x] > 0: - arr1[i] = x - mp[x] -= 1 - i += 1 - for x, cnt in enumerate(mp): - for _ in range(cnt): - arr1[i] = x - i += 1 - return arr1 + ans.extend([x] * cnt[x]) + cnt.pop(x) + mi, mx = min(arr1), max(arr1) + for x in range(mi, mx + 1): + ans.extend([x] * cnt[x]) + return ans +``` + +#### Java + +```java +class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + int[] cnt = new int[1001]; + int mi = 1001, mx = 0; + for (int x : arr1) { + ++cnt[x]; + mi = Math.min(mi, x); + mx = Math.max(mx, x); + } + int m = arr1.length; + int[] ans = new int[m]; + int i = 0; + for (int x : arr2) { + while (cnt[x] > 0) { + --cnt[x]; + ans[i++] = x; + } + } + for (int x = mi; x <= mx; ++x) { + while (cnt[x] > 0) { + --cnt[x]; + ans[i++] = x; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector relativeSortArray(vector& arr1, vector& arr2) { + vector cnt(1001); + for (int x : arr1) { + ++cnt[x]; + } + auto [mi, mx] = minmax_element(arr1.begin(), arr1.end()); + vector ans; + for (int x : arr2) { + while (cnt[x]) { + ans.push_back(x); + --cnt[x]; + } + } + for (int x = *mi; x <= *mx; ++x) { + while (cnt[x]) { + ans.push_back(x); + --cnt[x]; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func relativeSortArray(arr1 []int, arr2 []int) []int { + cnt := make([]int, 1001) + mi, mx := 1001, 0 + for _, x := range arr1 { + cnt[x]++ + mi = min(mi, x) + mx = max(mx, x) + } + ans := make([]int, 0, len(arr1)) + for _, x := range arr2 { + for cnt[x] > 0 { + ans = append(ans, x) + cnt[x]-- + } + } + for x := mi; x <= mx; x++ { + for cnt[x] > 0 { + ans = append(ans, x) + cnt[x]-- + } + } + return ans +} +``` + +#### TypeScript + +```ts +function relativeSortArray(arr1: number[], arr2: number[]): number[] { + const cnt = Array(1001).fill(0); + let mi = Number.POSITIVE_INFINITY; + let mx = Number.NEGATIVE_INFINITY; + + for (const x of arr1) { + cnt[x]++; + mi = Math.min(mi, x); + mx = Math.max(mx, x); + } + + const ans: number[] = []; + for (const x of arr2) { + while (cnt[x]) { + cnt[x]--; + ans.push(x); + } + } + + for (let i = mi; i <= mx; i++) { + while (cnt[i]) { + cnt[i]--; + ans.push(i); + } + } + + return ans; +} +``` + +#### Swift + +```swift +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var cnt = [Int](repeating: 0, count: 1001) + for x in arr1 { + cnt[x] += 1 + } + + guard let mi = arr1.min(), let mx = arr1.max() else { + return [] + } + + var ans = [Int]() + for x in arr2 { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + for x in mi...mx { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + return ans + } +} ``` diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.cpp" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.cpp" index 6b3c5fdd5b2c..fcf60d27382a 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.cpp" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.cpp" @@ -1,14 +1,18 @@ class Solution { public: vector relativeSortArray(vector& arr1, vector& arr2) { - vector mp(1001); - for (int x : arr1) ++mp[x]; - int i = 0; - for (int x : arr2) { - while (mp[x]-- > 0) arr1[i++] = x; + unordered_map pos; + for (int i = 0; i < arr2.size(); ++i) { + pos[arr2[i]] = i; } - for (int j = 0; j < mp.size(); ++j) { - while (mp[j]-- > 0) arr1[i++] = j; + vector> arr; + for (int i = 0; i < arr1.size(); ++i) { + int j = pos.count(arr1[i]) ? pos[arr1[i]] : arr2.size(); + arr.emplace_back(j, arr1[i]); + } + sort(arr.begin(), arr.end()); + for (int i = 0; i < arr1.size(); ++i) { + arr1[i] = arr[i].second; } return arr1; } diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.go" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.go" index b20033dee249..9c9cdd1191d9 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.go" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.go" @@ -1,22 +1,21 @@ func relativeSortArray(arr1 []int, arr2 []int) []int { - mp := make([]int, 1001) - for _, x := range arr1 { - mp[x]++ + pos := map[int]int{} + for i, x := range arr2 { + pos[x] = i } - i := 0 - for _, x := range arr2 { - for mp[x] > 0 { - arr1[i] = x - mp[x]-- - i++ + arr := make([][2]int, len(arr1)) + for i, x := range arr1 { + if p, ok := pos[x]; ok { + arr[i] = [2]int{p, x} + } else { + arr[i] = [2]int{len(arr2), x} } } - for j, cnt := range mp { - for cnt > 0 { - arr1[i] = j - i++ - cnt-- - } + sort.Slice(arr, func(i, j int) bool { + return arr[i][0] < arr[j][0] || arr[i][0] == arr[j][0] && arr[i][1] < arr[j][1] + }) + for i, x := range arr { + arr1[i] = x[1] } return arr1 } \ No newline at end of file diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.java" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.java" index 544cc51b9396..23afacc4be6a 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.java" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.java" @@ -1,19 +1,16 @@ class Solution { public int[] relativeSortArray(int[] arr1, int[] arr2) { - int[] mp = new int[1001]; - for (int x : arr1) { - ++mp[x]; + Map pos = new HashMap<>(arr2.length); + for (int i = 0; i < arr2.length; ++i) { + pos.put(arr2[i], i); } - int i = 0; - for (int x : arr2) { - while (mp[x]-- > 0) { - arr1[i++] = x; - } + int[][] arr = new int[arr1.length][0]; + for (int i = 0; i < arr.length; ++i) { + arr[i] = new int[] {arr1[i], pos.getOrDefault(arr1[i], arr2.length + arr1[i])}; } - for (int j = 0; j < mp.length; ++j) { - while (mp[j]-- > 0) { - arr1[i++] = j; - } + Arrays.sort(arr, (a, b) -> a[1] - b[1]); + for (int i = 0; i < arr.length; ++i) { + arr1[i] = arr[i][0]; } return arr1; } diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.py" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.py" index 2d57297cd3d6..67a4ab1154ad 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.py" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.py" @@ -1,5 +1,4 @@ class Solution: def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: - mp = {num: i for i, num in enumerate(arr2)} - arr1.sort(key=lambda x: (mp.get(x, 10000), x)) - return arr1 + pos = {x: i for i, x in enumerate(arr2)} + return sorted(arr1, key=lambda x: pos.get(x, 1000 + x)) diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.swift" new file mode 100644 index 000000000000..af048342c47b --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.swift" @@ -0,0 +1,15 @@ +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var pos = [Int: Int]() + for (i, x) in arr2.enumerated() { + pos[x] = i + } + var arr = [(Int, Int)]() + for x in arr1 { + let j = pos[x] ?? arr2.count + arr.append((j, x)) + } + arr.sort { $0.0 < $1.0 || ($0.0 == $1.0 && $0.1 < $1.1) } + return arr.map { $0.1 } + } +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.ts" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.ts" new file mode 100644 index 000000000000..c31bb8552096 --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution.ts" @@ -0,0 +1,13 @@ +function relativeSortArray(arr1: number[], arr2: number[]): number[] { + const pos: Map = new Map(); + for (let i = 0; i < arr2.length; ++i) { + pos.set(arr2[i], i); + } + const arr: number[][] = []; + for (const x of arr1) { + const j = pos.get(x) ?? arr2.length; + arr.push([j, x]); + } + arr.sort((a, b) => a[0] - b[0] || a[1] - b[1]); + return arr.map(a => a[1]); +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.cpp" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.cpp" new file mode 100644 index 000000000000..8ceeb19fee19 --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.cpp" @@ -0,0 +1,24 @@ +class Solution { +public: + vector relativeSortArray(vector& arr1, vector& arr2) { + vector cnt(1001); + for (int x : arr1) { + ++cnt[x]; + } + auto [mi, mx] = minmax_element(arr1.begin(), arr1.end()); + vector ans; + for (int x : arr2) { + while (cnt[x]) { + ans.push_back(x); + --cnt[x]; + } + } + for (int x = *mi; x <= *mx; ++x) { + while (cnt[x]) { + ans.push_back(x); + --cnt[x]; + } + } + return ans; + } +}; diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.go" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.go" new file mode 100644 index 000000000000..cafbc511113b --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.go" @@ -0,0 +1,23 @@ +func relativeSortArray(arr1 []int, arr2 []int) []int { + cnt := make([]int, 1001) + mi, mx := 1001, 0 + for _, x := range arr1 { + cnt[x]++ + mi = min(mi, x) + mx = max(mx, x) + } + ans := make([]int, 0, len(arr1)) + for _, x := range arr2 { + for cnt[x] > 0 { + ans = append(ans, x) + cnt[x]-- + } + } + for x := mi; x <= mx; x++ { + for cnt[x] > 0 { + ans = append(ans, x) + cnt[x]-- + } + } + return ans +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.java" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.java" new file mode 100644 index 000000000000..b7c284041e15 --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.java" @@ -0,0 +1,27 @@ +class Solution { + public int[] relativeSortArray(int[] arr1, int[] arr2) { + int[] cnt = new int[1001]; + int mi = 1001, mx = 0; + for (int x : arr1) { + ++cnt[x]; + mi = Math.min(mi, x); + mx = Math.max(mx, x); + } + int m = arr1.length; + int[] ans = new int[m]; + int i = 0; + for (int x : arr2) { + while (cnt[x] > 0) { + --cnt[x]; + ans[i++] = x; + } + } + for (int x = mi; x <= mx; ++x) { + while (cnt[x] > 0) { + --cnt[x]; + ans[i++] = x; + } + } + return ans; + } +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.py" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.py" index fc44d1f6ea54..389ef3393ec9 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.py" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.py" @@ -1,16 +1,11 @@ class Solution: def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]: - mp = [0] * 1001 - for x in arr1: - mp[x] += 1 - i = 0 + cnt = Counter(arr1) + ans = [] for x in arr2: - while mp[x] > 0: - arr1[i] = x - mp[x] -= 1 - i += 1 - for x, cnt in enumerate(mp): - for _ in range(cnt): - arr1[i] = x - i += 1 - return arr1 + ans.extend([x] * cnt[x]) + cnt.pop(x) + mi, mx = min(arr1), max(arr1) + for x in range(mi, mx + 1): + ans.extend([x] * cnt[x]) + return ans diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.swift" new file mode 100644 index 000000000000..c737ce8d1f4b --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.swift" @@ -0,0 +1,29 @@ +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var cnt = [Int](repeating: 0, count: 1001) + for x in arr1 { + cnt[x] += 1 + } + + guard let mi = arr1.min(), let mx = arr1.max() else { + return [] + } + + var ans = [Int]() + for x in arr2 { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + for x in mi...mx { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + return ans + } +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.ts" "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.ts" new file mode 100644 index 000000000000..ce90520b6bcf --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 075. \346\225\260\347\273\204\347\233\270\345\257\271\346\216\222\345\272\217/Solution2.ts" @@ -0,0 +1,28 @@ +function relativeSortArray(arr1: number[], arr2: number[]): number[] { + const cnt = Array(1001).fill(0); + let mi = Number.POSITIVE_INFINITY; + let mx = Number.NEGATIVE_INFINITY; + + for (const x of arr1) { + cnt[x]++; + mi = Math.min(mi, x); + mx = Math.max(mx, x); + } + + const ans: number[] = []; + for (const x of arr2) { + while (cnt[x]) { + cnt[x]--; + ans.push(x); + } + } + + for (let i = mi; i <= mx; i++) { + while (cnt[i]) { + cnt[i]--; + ans.push(i); + } + } + + return ans; +} diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 076. \346\225\260\347\273\204\344\270\255\347\232\204\347\254\254 k \345\244\247\347\232\204\346\225\260\345\255\227/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 076. \346\225\260\347\273\204\344\270\255\347\232\204\347\254\254 k \345\244\247\347\232\204\346\225\260\345\255\227/README.md" index 3832f7087e47..7b9be98b5e3d 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 076. \346\225\260\347\273\204\344\270\255\347\232\204\347\254\254 k \345\244\247\347\232\204\346\225\260\345\255\227/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 076. \346\225\260\347\273\204\344\270\255\347\232\204\347\254\254 k \345\244\247\347\232\204\346\225\260\345\255\227/README.md" @@ -180,6 +180,41 @@ func quickSort(nums []int, left, right, k int) int { } ``` +#### Swift + +```swift +class Solution { + func findKthLargest(_ nums: [Int], _ k: Int) -> Int { + var nums = nums + let n = nums.count + return quickSelect(&nums, 0, n - 1, n - k) + } + + private func quickSelect(_ nums: inout [Int], _ left: Int, _ right: Int, _ k: Int) -> Int { + if left == right { + return nums[left] + } + + var i = left - 1 + var j = right + 1 + let pivot = nums[(left + right) / 2] + + while i < j { + repeat { i += 1 } while nums[i] < pivot + repeat { j -= 1 } while nums[j] > pivot + if i < j { + nums.swapAt(i, j) + } + } + + if j < k { + return quickSelect(&nums, j + 1, right, k) + } + return quickSelect(&nums, left, j, k) + } +} +``` + diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 076. \346\225\260\347\273\204\344\270\255\347\232\204\347\254\254 k \345\244\247\347\232\204\346\225\260\345\255\227/Solution.swift" "b/lcof2/\345\211\221\346\214\207 Offer II 076. \346\225\260\347\273\204\344\270\255\347\232\204\347\254\254 k \345\244\247\347\232\204\346\225\260\345\255\227/Solution.swift" new file mode 100644 index 000000000000..357311f343c0 --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 076. \346\225\260\347\273\204\344\270\255\347\232\204\347\254\254 k \345\244\247\347\232\204\346\225\260\345\255\227/Solution.swift" @@ -0,0 +1,30 @@ +class Solution { + func findKthLargest(_ nums: [Int], _ k: Int) -> Int { + var nums = nums + let n = nums.count + return quickSelect(&nums, 0, n - 1, n - k) + } + + private func quickSelect(_ nums: inout [Int], _ left: Int, _ right: Int, _ k: Int) -> Int { + if left == right { + return nums[left] + } + + var i = left - 1 + var j = right + 1 + let pivot = nums[(left + right) / 2] + + while i < j { + repeat { i += 1 } while nums[i] < pivot + repeat { j -= 1 } while nums[j] > pivot + if i < j { + nums.swapAt(i, j) + } + } + + if j < k { + return quickSelect(&nums, j + 1, right, k) + } + return quickSelect(&nums, left, j, k) + } +} \ No newline at end of file diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 094. \346\234\200\345\260\221\345\233\236\346\226\207\345\210\206\345\211\262/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 094. \346\234\200\345\260\221\345\233\236\346\226\207\345\210\206\345\211\262/README.md" index 3147f7ba4e49..bb55fa65ac8e 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 094. \346\234\200\345\260\221\345\233\236\346\226\207\345\210\206\345\211\262/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 094. \346\234\200\345\260\221\345\233\236\346\226\207\345\210\206\345\211\262/README.md" @@ -71,7 +71,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%2 接下来,我们考虑 $f[i]$ 如何进行状态转移。我们可以枚举上一个分割点 $j$,如果子串 $s[j..i]$ 是一个回文串,那么 $f[i]$ 就可以从 $f[j]$ 转移而来。如果 $j=0$,那么说明 $s[0..i]$ 本身就是一个回文串,此时不需要进行分割,即 $f[i]=0$。因此,状态转移方程如下: $$ -f[i]=\min_{0\leq j \leq i}\begin{cases} f[j-1]+1, & \text{if}\ g[j][i]=\text{True} \\ 0, & \text{if}\ g[0][i]=\text{True} \end{cases} +f[i]=\min_{0\leq j \leq i}\begin{cases} f[j-1]+1, & \textit{if}\ g[j][i]=\textit{True} \\ 0, & \textit{if}\ g[0][i]=\textit{True} \end{cases} $$ 答案即为 $f[n]$,其中 $n$ 是字符串 $s$ 的长度。 diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 096. \345\255\227\347\254\246\344\270\262\344\272\244\347\273\207/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 096. \345\255\227\347\254\246\344\270\262\344\272\244\347\273\207/README.md" index 1bdb9ae5b776..7303593e9a38 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 096. \345\255\227\347\254\246\344\270\262\344\272\244\347\273\207/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 096. \345\255\227\347\254\246\344\270\262\344\272\244\347\273\207/README.md" @@ -304,13 +304,13 @@ public class Solution { $$ f[i][j] = \begin{cases} -f[i - 1][j] & \text{if } s_1[i - 1] = s_3[i + j - 1] \\ -\text{or } f[i][j - 1] & \text{if } s_2[j - 1] = s_3[i + j - 1] \\ -\text{false} & \text{otherwise} +f[i - 1][j] & \textit{if } s_1[i - 1] = s_3[i + j - 1] \\ +\textit{or } f[i][j - 1] & \textit{if } s_2[j - 1] = s_3[i + j - 1] \\ +\textit{false} & \textit{otherwise} \end{cases} $$ -其中 $f[0][0] = \text{true}$ 表示空串是两个空串的交错字符串。 +其中 $f[0][0] = \textit{true}$ 表示空串是两个空串的交错字符串。 答案即为 $f[m][n]$。 diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 098. \350\267\257\345\276\204\347\232\204\346\225\260\347\233\256/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 098. \350\267\257\345\276\204\347\232\204\346\225\260\347\233\256/README.md" index 805e968332fc..cb03911942f5 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 098. \350\267\257\345\276\204\347\232\204\346\225\260\347\233\256/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 098. \350\267\257\345\276\204\347\232\204\346\225\260\347\233\256/README.md" @@ -85,7 +85,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%2 $$ f[i][j] = \begin{cases} 1 & i = 0, j = 0 \\ -f[i - 1][j] + f[i][j - 1] & \text{otherwise} +f[i - 1][j] + f[i][j - 1] & \textit{otherwise} \end{cases} $$ diff --git "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/README.md" "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/README.md" index f500b965aeff..4e21105c919d 100644 --- "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/README.md" +++ "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/README.md" @@ -42,13 +42,20 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcp/LCP%2040.%20%E5%BF%83% -### 方法一:排序 + 贪心 +### 方法一:贪心 + 排序 -排序先取最大的 $cnt$ 个数,如果和为偶数则直接返回答案。 +我们注意到,题目选取的是子序列,因此我们可以考虑先对数组进行排序。 -否则,找一个已取的最小奇数换成剩余未取的最大偶数,或者找一个已取的最小偶数换成剩下未取的最大奇数,取两者中较大的。 +接下来,我们先贪心地选取最大的 $\textit{cnt}$ 个数,如果这些数的和为偶数,则直接返回这个和 $ans$。 -时间复杂度 $O(nlogn)$。 +否则,我们有两种贪心策略: + +1. 在最大的 $\textit{cnt}$ 个数中,找到一个最小的偶数 $mi1$,然后在剩下的 $n - \textit{cnt}$ 个数中,找到一个最大的奇数 $mx1$,将 $mi1$ 替换为 $mx1$,如果存在这样的替换,那么替换后的和 $ans - mi1 + mx1$ 一定是偶数; +1. 在最大的 $\textit{cnt}$ 个数中,找到一个最小的奇数 $mi2$,然后在剩下的 $n - \textit{cnt}$ 个数中,找到一个最大的偶数 $mx2$,将 $mi2$ 替换为 $mx2$,如果存在这样的替换,那么替换后的和 $ans - mi2 + mx2$ 一定是偶数。 + +我们取最大的偶数和作为答案。如果不存在偶数和,则返回 $0$。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组长度。 @@ -57,16 +64,25 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcp/LCP%2040.%20%E5%BF%83% ```python class Solution: def maxmiumScore(self, cards: List[int], cnt: int) -> int: - cards.sort(reverse=True) - t = cards[:cnt] - ans = sum(t) + cards.sort() + ans = sum(cards[-cnt:]) if ans % 2 == 0: return ans - a = min([v for v in t if v & 1], default=inf) - b = min([v for v in t if v % 2 == 0], default=inf) - c = max([v for v in cards[cnt:] if v % 2 == 0], default=-inf) - d = max([v for v in cards[cnt:] if v & 1], default=-inf) - return max(ans - a + c, ans - b + d, 0) + n = len(cards) + mx1 = mx2 = -inf + for x in cards[: n - cnt]: + if x & 1: + mx1 = x + else: + mx2 = x + mi1 = mi2 = inf + for x in cards[-cnt:][::-1]: + if x & 1: + mi2 = x + else: + mi1 = x + ans = max(ans - mi1 + mx1, ans - mi2 + mx2, -1) + return 0 if ans < 0 else ans ``` #### Java @@ -83,26 +99,25 @@ class Solution { if (ans % 2 == 0) { return ans; } - int inf = 0x3f3f3f3f; - int a = inf, b = inf; - for (int i = 0; i < cnt; ++i) { - int v = cards[n - i - 1]; - if (v % 2 == 1) { - a = Math.min(a, v); + final int inf = 1 << 29; + int mx1 = -inf, mx2 = -inf; + for (int i = 0; i < n - cnt; ++i) { + if (cards[i] % 2 == 1) { + mx1 = cards[i]; } else { - b = Math.min(b, v); + mx2 = cards[i]; } } - int c = -inf, d = -inf; - for (int i = cnt; i < n; ++i) { - int v = cards[n - i - 1]; - if (v % 2 == 0) { - c = Math.max(c, v); + int mi1 = inf, mi2 = inf; + for (int i = n - 1; i >= n - cnt; --i) { + if (cards[i] % 2 == 1) { + mi2 = cards[i]; } else { - d = Math.max(d, v); + mi1 = cards[i]; } } - return Math.max(0, Math.max(ans - a + c, ans - b + d)); + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? 0 : ans; } } ``` @@ -114,27 +129,33 @@ class Solution { public: int maxmiumScore(vector& cards, int cnt) { sort(cards.begin(), cards.end()); - reverse(cards.begin(), cards.end()); - int ans = 0, n = cards.size(); - for (int i = 0; i < cnt; ++i) ans += cards[i]; - if (ans % 2 == 0) return ans; - int inf = 0x3f3f3f3f; - int a = inf, b = inf, c = -inf, d = -inf; + int ans = 0; + int n = cards.size(); for (int i = 0; i < cnt; ++i) { - int v = cards[i]; - if (v % 2 == 1) - a = min(a, v); - else - b = min(b, v); + ans += cards[n - i - 1]; } - for (int i = cnt; i < n; ++i) { - int v = cards[i]; - if (v % 2 == 0) - c = max(c, v); - else - d = max(d, v); + if (ans % 2 == 0) { + return ans; + } + const int inf = 1 << 29; + int mx1 = -inf, mx2 = -inf; + for (int i = 0; i < n - cnt; ++i) { + if (cards[i] % 2) { + mx1 = cards[i]; + } else { + mx2 = cards[i]; + } } - return max(0, max(ans - a + c, ans - b + d)); + int mi1 = inf, mi2 = inf; + for (int i = n - 1; i >= n - cnt; --i) { + if (cards[i] % 2) { + mi2 = cards[i]; + } else { + mi1 = cards[i]; + } + } + ans = max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? 0 : ans; } }; ``` @@ -143,31 +164,74 @@ public: ```go func maxmiumScore(cards []int, cnt int) int { + sort.Ints(cards) ans := 0 - sort.Slice(cards, func(i, j int) bool { return cards[i] > cards[j] }) - for _, v := range cards[:cnt] { - ans += v + n := len(cards) + for i := 0; i < cnt; i++ { + ans += cards[n-1-i] } if ans%2 == 0 { return ans } - inf := 0x3f3f3f3f - a, b, c, d := inf, inf, -inf, -inf - for _, v := range cards[:cnt] { - if v%2 == 1 { - a = min(a, v) + const inf = 1 << 29 + mx1, mx2 := -inf, -inf + for _, x := range cards[:n-cnt] { + if x%2 == 1 { + mx1 = x } else { - b = min(b, v) + mx2 = x } } - for _, v := range cards[cnt:] { - if v%2 == 0 { - c = max(c, v) + mi1, mi2 := inf, inf + for i := n - 1; i >= n-cnt; i-- { + if cards[i]%2 == 1 { + mi2 = cards[i] } else { - d = max(d, v) + mi1 = cards[i] } } - return max(0, max(ans-a+c, ans-b+d)) + ans = max(-1, max(ans-mi1+mx1, ans-mi2+mx2)) + if ans < 0 { + return 0 + } + return ans +} +``` + +#### TypeScript + +```ts +function maxmiumScore(cards: number[], cnt: number): number { + cards.sort((a, b) => a - b); + let ans = 0; + const n = cards.length; + for (let i = 0; i < cnt; ++i) { + ans += cards[n - i - 1]; + } + if (ans % 2 === 0) { + return ans; + } + const inf = 1 << 29; + let mx1 = -inf, + mx2 = -inf; + for (let i = 0; i < n - cnt; ++i) { + if (cards[i] % 2 === 1) { + mx1 = cards[i]; + } else { + mx2 = cards[i]; + } + } + let mi1 = inf, + mi2 = inf; + for (let i = n - 1; i >= n - cnt; --i) { + if (cards[i] % 2 === 1) { + mi2 = cards[i]; + } else { + mi1 = cards[i]; + } + } + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? 0 : ans; } ``` diff --git "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.cpp" "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.cpp" index 385484dd7f08..c0c34b2c228b 100644 --- "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.cpp" +++ "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.cpp" @@ -2,26 +2,32 @@ class Solution { public: int maxmiumScore(vector& cards, int cnt) { sort(cards.begin(), cards.end()); - reverse(cards.begin(), cards.end()); - int ans = 0, n = cards.size(); - for (int i = 0; i < cnt; ++i) ans += cards[i]; - if (ans % 2 == 0) return ans; - int inf = 0x3f3f3f3f; - int a = inf, b = inf, c = -inf, d = -inf; + int ans = 0; + int n = cards.size(); for (int i = 0; i < cnt; ++i) { - int v = cards[i]; - if (v % 2 == 1) - a = min(a, v); - else - b = min(b, v); + ans += cards[n - i - 1]; } - for (int i = cnt; i < n; ++i) { - int v = cards[i]; - if (v % 2 == 0) - c = max(c, v); - else - d = max(d, v); + if (ans % 2 == 0) { + return ans; } - return max(0, max(ans - a + c, ans - b + d)); + const int inf = 1 << 29; + int mx1 = -inf, mx2 = -inf; + for (int i = 0; i < n - cnt; ++i) { + if (cards[i] % 2) { + mx1 = cards[i]; + } else { + mx2 = cards[i]; + } + } + int mi1 = inf, mi2 = inf; + for (int i = n - 1; i >= n - cnt; --i) { + if (cards[i] % 2) { + mi2 = cards[i]; + } else { + mi1 = cards[i]; + } + } + ans = max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? 0 : ans; } -}; \ No newline at end of file +}; diff --git "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.go" "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.go" index 3379eeaca2a9..9af7695a4ebe 100644 --- "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.go" +++ "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.go" @@ -1,27 +1,33 @@ func maxmiumScore(cards []int, cnt int) int { + sort.Ints(cards) ans := 0 - sort.Slice(cards, func(i, j int) bool { return cards[i] > cards[j] }) - for _, v := range cards[:cnt] { - ans += v + n := len(cards) + for i := 0; i < cnt; i++ { + ans += cards[n-1-i] } if ans%2 == 0 { return ans } - inf := 0x3f3f3f3f - a, b, c, d := inf, inf, -inf, -inf - for _, v := range cards[:cnt] { - if v%2 == 1 { - a = min(a, v) + const inf = 1 << 29 + mx1, mx2 := -inf, -inf + for _, x := range cards[:n-cnt] { + if x%2 == 1 { + mx1 = x } else { - b = min(b, v) + mx2 = x } } - for _, v := range cards[cnt:] { - if v%2 == 0 { - c = max(c, v) + mi1, mi2 := inf, inf + for i := n - 1; i >= n-cnt; i-- { + if cards[i]%2 == 1 { + mi2 = cards[i] } else { - d = max(d, v) + mi1 = cards[i] } } - return max(0, max(ans-a+c, ans-b+d)) -} \ No newline at end of file + ans = max(-1, max(ans-mi1+mx1, ans-mi2+mx2)) + if ans < 0 { + return 0 + } + return ans +} diff --git "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.java" "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.java" index 8372eaaa75bf..1bf357429b13 100644 --- "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.java" +++ "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.java" @@ -9,25 +9,24 @@ public int maxmiumScore(int[] cards, int cnt) { if (ans % 2 == 0) { return ans; } - int inf = 0x3f3f3f3f; - int a = inf, b = inf; - for (int i = 0; i < cnt; ++i) { - int v = cards[n - i - 1]; - if (v % 2 == 1) { - a = Math.min(a, v); + final int inf = 1 << 29; + int mx1 = -inf, mx2 = -inf; + for (int i = 0; i < n - cnt; ++i) { + if (cards[i] % 2 == 1) { + mx1 = cards[i]; } else { - b = Math.min(b, v); + mx2 = cards[i]; } } - int c = -inf, d = -inf; - for (int i = cnt; i < n; ++i) { - int v = cards[n - i - 1]; - if (v % 2 == 0) { - c = Math.max(c, v); + int mi1 = inf, mi2 = inf; + for (int i = n - 1; i >= n - cnt; --i) { + if (cards[i] % 2 == 1) { + mi2 = cards[i]; } else { - d = Math.max(d, v); + mi1 = cards[i]; } } - return Math.max(0, Math.max(ans - a + c, ans - b + d)); + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? 0 : ans; } -} \ No newline at end of file +} diff --git "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.py" "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.py" index 508387b12f15..ea164ef9bfd9 100644 --- "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.py" +++ "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.py" @@ -1,12 +1,21 @@ class Solution: def maxmiumScore(self, cards: List[int], cnt: int) -> int: - cards.sort(reverse=True) - t = cards[:cnt] - ans = sum(t) + cards.sort() + ans = sum(cards[-cnt:]) if ans % 2 == 0: return ans - a = min([v for v in t if v & 1], default=inf) - b = min([v for v in t if v % 2 == 0], default=inf) - c = max([v for v in cards[cnt:] if v % 2 == 0], default=-inf) - d = max([v for v in cards[cnt:] if v & 1], default=-inf) - return max(ans - a + c, ans - b + d, 0) + n = len(cards) + mx1 = mx2 = -inf + for x in cards[: n - cnt]: + if x & 1: + mx1 = x + else: + mx2 = x + mi1 = mi2 = inf + for x in cards[-cnt:][::-1]: + if x & 1: + mi2 = x + else: + mi1 = x + ans = max(ans - mi1 + mx1, ans - mi2 + mx2, -1) + return 0 if ans < 0 else ans diff --git "a/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.ts" "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.ts" new file mode 100644 index 000000000000..4e6114429978 --- /dev/null +++ "b/lcp/LCP 40. \345\277\203\347\256\227\346\214\221\346\210\230/Solution.ts" @@ -0,0 +1,32 @@ +function maxmiumScore(cards: number[], cnt: number): number { + cards.sort((a, b) => a - b); + let ans = 0; + const n = cards.length; + for (let i = 0; i < cnt; ++i) { + ans += cards[n - i - 1]; + } + if (ans % 2 === 0) { + return ans; + } + const inf = 1 << 29; + let mx1 = -inf, + mx2 = -inf; + for (let i = 0; i < n - cnt; ++i) { + if (cards[i] % 2 === 1) { + mx1 = cards[i]; + } else { + mx2 = cards[i]; + } + } + let mi1 = inf, + mi2 = inf; + for (let i = n - 1; i >= n - cnt; --i) { + if (cards[i] % 2 === 1) { + mi2 = cards[i]; + } else { + mi1 = cards[i]; + } + } + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? 0 : ans; +} diff --git a/solution/0000-0099/0001.Two Sum/README.md b/solution/0000-0099/0001.Two Sum/README.md index 41f53671375c..815841ec0b76 100644 --- a/solution/0000-0099/0001.Two Sum/README.md +++ b/solution/0000-0099/0001.Two Sum/README.md @@ -19,7 +19,7 @@ tags:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

-

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

+

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

@@ -70,11 +70,11 @@ tags: ### 方法一:哈希表 -我们可以用哈希表 $m$ 存放数组值以及对应的下标。 +我们可以使用一个哈希表 $\textit{d}$ 来存储每个元素及其对应的索引。 -遍历数组 `nums`,当发现 `target - nums[i]` 在哈希表中,说明找到了目标值,返回 `target - nums[i]` 的下标以及 $i$ 即可。 +遍历数组 $\textit{nums}$,对于当前元素 $\textit{nums}[i]$,我们首先判断 $\textit{target} - \textit{nums}[i]$ 是否在哈希表 $\textit{d}$ 中,如果在 $\textit{d}$ 中,说明 $\textit{target}$ 值已经找到,返回 $\textit{target} - \textit{nums}[i]$ 的索引和 $i$ 即可。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 `nums` 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -83,12 +83,12 @@ tags: ```python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: - m = {} + d = {} for i, x in enumerate(nums): y = target - x - if y in m: - return [m[y], i] - m[x] = i + if y in d: + return [d[y], i] + d[x] = i ``` #### Java @@ -96,14 +96,14 @@ class Solution: ```java class Solution { public int[] twoSum(int[] nums, int target) { - Map m = new HashMap<>(); + Map d = new HashMap<>(); for (int i = 0;; ++i) { int x = nums[i]; int y = target - x; - if (m.containsKey(y)) { - return new int[] {m.get(y), i}; + if (d.containsKey(y)) { + return new int[] {d.get(y), i}; } - m.put(x, i); + d.put(x, i); } } } @@ -115,14 +115,14 @@ class Solution { class Solution { public: vector twoSum(vector& nums, int target) { - unordered_map m; + unordered_map d; for (int i = 0;; ++i) { int x = nums[i]; int y = target - x; - if (m.count(y)) { - return {m[y], i}; + if (d.contains(y)) { + return {d[y], i}; } - m[x] = i; + d[x] = i; } } }; @@ -132,14 +132,14 @@ public: ```go func twoSum(nums []int, target int) []int { - m := map[int]int{} + d := map[int]int{} for i := 0; ; i++ { x := nums[i] y := target - x - if j, ok := m[y]; ok { + if j, ok := d[y]; ok { return []int{j, i} } - m[x] = i + d[x] = i } } ``` @@ -148,17 +148,14 @@ func twoSum(nums []int, target int) []int { ```ts function twoSum(nums: number[], target: number): number[] { - const m: Map = new Map(); - + const d = new Map(); for (let i = 0; ; ++i) { const x = nums[i]; const y = target - x; - - if (m.has(y)) { - return [m.get(y)!, i]; + if (d.has(y)) { + return [d.get(y)!, i]; } - - m.set(x, i); + d.set(x, i); } } ``` @@ -170,15 +167,15 @@ use std::collections::HashMap; impl Solution { pub fn two_sum(nums: Vec, target: i32) -> Vec { - let mut m = HashMap::new(); + let mut d = HashMap::new(); for (i, &x) in nums.iter().enumerate() { let y = target - x; - if let Some(&j) = m.get(&y) { + if let Some(&j) = d.get(&y) { return vec![j as i32, i as i32]; } - m.insert(x, i as i32); + d.insert(x, i); } - unreachable!() + vec![] } } ``` @@ -192,14 +189,14 @@ impl Solution { * @return {number[]} */ var twoSum = function (nums, target) { - const m = new Map(); + const d = new Map(); for (let i = 0; ; ++i) { const x = nums[i]; const y = target - x; - if (m.has(y)) { - return [m.get(y), i]; + if (d.has(y)) { + return [d.get(y), i]; } - m.set(x, i); + d.set(x, i); } }; ``` @@ -209,15 +206,15 @@ var twoSum = function (nums, target) { ```cs public class Solution { public int[] TwoSum(int[] nums, int target) { - var m = new Dictionary(); + var d = new Dictionary(); for (int i = 0, j; ; ++i) { int x = nums[i]; int y = target - x; - if (m.TryGetValue(y, out j)) { + if (d.TryGetValue(y, out j)) { return new [] {j, i}; } - if (!m.ContainsKey(x)) { - m.Add(x, i); + if (!d.ContainsKey(x)) { + d.Add(x, i); } } } @@ -234,13 +231,13 @@ class Solution { * @return Integer[] */ function twoSum($nums, $target) { - $m = []; + $d = []; foreach ($nums as $i => $x) { $y = $target - $x; - if (isset($m[$y])) { - return [$m[$y], $i]; + if (isset($d[$y])) { + return [$d[$y], $i]; } - $m[$x] = $i; + $d[$x] = $i; } } } @@ -252,17 +249,20 @@ class Solution { import scala.collection.mutable object Solution { - def twoSum(nums: Array[Int], target: Int): Array[Int] = { - var map = new mutable.HashMap[Int, Int]() - for (i <- 0 to nums.length) { - if (map.contains(target - nums(i))) { - return Array(map(target - nums(i)), i) - } else { - map += (nums(i) -> i) - } + def twoSum(nums: Array[Int], target: Int): Array[Int] = { + val d = mutable.Map[Int, Int]() + var ans: Array[Int] = Array() + for (i <- nums.indices if ans.isEmpty) { + val x = nums(i) + val y = target - x + if (d.contains(y)) { + ans = Array(d(y), i) + } else { + d(x) = i + } + } + ans } - Array(0, 0) - } } ``` @@ -271,17 +271,15 @@ object Solution { ```swift class Solution { func twoSum(_ nums: [Int], _ target: Int) -> [Int] { - var m = [Int: Int]() - var i = 0 - while true { - let x = nums[i] - let y = target - nums[i] - if let j = m[target - nums[i]] { + var d = [Int: Int]() + for (i, x) in nums.enumerated() { + let y = target - x + if let j = d[y] { return [j, i] } - m[nums[i]] = i - i += 1 + d[x] = i } + return [] } } ``` @@ -293,12 +291,14 @@ class Solution { # @param {Integer} target # @return {Integer[]} def two_sum(nums, target) - nums.each_with_index do |x, idx| - if nums.include? target - x - return [idx, nums.index(target - x)] if nums.index(target - x) != idx + d = {} + nums.each_with_index do |x, i| + y = target - x + if d.key?(y) + return [d[y], i] + end + d[x] = i end - next - end end ``` @@ -306,17 +306,16 @@ end ```nim import std/enumerate +import std/tables proc twoSum(nums: seq[int], target: int): seq[int] = - var - bal: int - tdx: int - for idx, val in enumerate(nums): - bal = target - val - if bal in nums: - tdx = nums.find(bal) - if idx != tdx: - return @[idx, tdx] + var d = initTable[int, int]() + for i, x in nums.pairs(): + let y = target - x + if d.hasKey(y): + return @[d[y], i] + d[x] = i + return @[] ``` diff --git a/solution/0000-0099/0001.Two Sum/README_EN.md b/solution/0000-0099/0001.Two Sum/README_EN.md index 798d0152d3b2..abdb96e24b70 100644 --- a/solution/0000-0099/0001.Two Sum/README_EN.md +++ b/solution/0000-0099/0001.Two Sum/README_EN.md @@ -67,11 +67,11 @@ tags: ### Solution 1: Hash Table -We can use the hash table $m$ to store the array value and the corresponding subscript. +We can use a hash table $\textit{d}$ to store each element and its corresponding index. -Traverse the array `nums`, when you find `target - nums[i]` in the hash table, it means that the target value is found, and the index of `target - nums[i]` and $i$ are returned. +Traverse the array $\textit{nums}$, for the current element $\textit{nums}[i]$, we first check if $\textit{target} - \textit{nums}[i]$ is in the hash table $\textit{d}$. If it is in $\textit{d}$, it means the $\textit{target}$ value has been found, and we return the indices of $\textit{target} - \textit{nums}[i]$ and $i$. -The time complexity is $O(n)$ and the space complexity is $O(n)$. Where $n$ is the length of the array `nums`. +Time complexity is $O(n)$, and space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. @@ -80,12 +80,12 @@ The time complexity is $O(n)$ and the space complexity is $O(n)$. Where $n$ is t ```python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: - m = {} + d = {} for i, x in enumerate(nums): y = target - x - if y in m: - return [m[y], i] - m[x] = i + if y in d: + return [d[y], i] + d[x] = i ``` #### Java @@ -93,14 +93,14 @@ class Solution: ```java class Solution { public int[] twoSum(int[] nums, int target) { - Map m = new HashMap<>(); + Map d = new HashMap<>(); for (int i = 0;; ++i) { int x = nums[i]; int y = target - x; - if (m.containsKey(y)) { - return new int[] {m.get(y), i}; + if (d.containsKey(y)) { + return new int[] {d.get(y), i}; } - m.put(x, i); + d.put(x, i); } } } @@ -112,14 +112,14 @@ class Solution { class Solution { public: vector twoSum(vector& nums, int target) { - unordered_map m; + unordered_map d; for (int i = 0;; ++i) { int x = nums[i]; int y = target - x; - if (m.count(y)) { - return {m[y], i}; + if (d.contains(y)) { + return {d[y], i}; } - m[x] = i; + d[x] = i; } } }; @@ -129,14 +129,14 @@ public: ```go func twoSum(nums []int, target int) []int { - m := map[int]int{} + d := map[int]int{} for i := 0; ; i++ { x := nums[i] y := target - x - if j, ok := m[y]; ok { + if j, ok := d[y]; ok { return []int{j, i} } - m[x] = i + d[x] = i } } ``` @@ -145,17 +145,14 @@ func twoSum(nums []int, target int) []int { ```ts function twoSum(nums: number[], target: number): number[] { - const m: Map = new Map(); - + const d = new Map(); for (let i = 0; ; ++i) { const x = nums[i]; const y = target - x; - - if (m.has(y)) { - return [m.get(y)!, i]; + if (d.has(y)) { + return [d.get(y)!, i]; } - - m.set(x, i); + d.set(x, i); } } ``` @@ -167,15 +164,15 @@ use std::collections::HashMap; impl Solution { pub fn two_sum(nums: Vec, target: i32) -> Vec { - let mut m = HashMap::new(); + let mut d = HashMap::new(); for (i, &x) in nums.iter().enumerate() { let y = target - x; - if let Some(&j) = m.get(&y) { + if let Some(&j) = d.get(&y) { return vec![j as i32, i as i32]; } - m.insert(x, i as i32); + d.insert(x, i); } - unreachable!() + vec![] } } ``` @@ -189,14 +186,14 @@ impl Solution { * @return {number[]} */ var twoSum = function (nums, target) { - const m = new Map(); + const d = new Map(); for (let i = 0; ; ++i) { const x = nums[i]; const y = target - x; - if (m.has(y)) { - return [m.get(y), i]; + if (d.has(y)) { + return [d.get(y), i]; } - m.set(x, i); + d.set(x, i); } }; ``` @@ -206,15 +203,15 @@ var twoSum = function (nums, target) { ```cs public class Solution { public int[] TwoSum(int[] nums, int target) { - var m = new Dictionary(); + var d = new Dictionary(); for (int i = 0, j; ; ++i) { int x = nums[i]; int y = target - x; - if (m.TryGetValue(y, out j)) { + if (d.TryGetValue(y, out j)) { return new [] {j, i}; } - if (!m.ContainsKey(x)) { - m.Add(x, i); + if (!d.ContainsKey(x)) { + d.Add(x, i); } } } @@ -231,13 +228,13 @@ class Solution { * @return Integer[] */ function twoSum($nums, $target) { - $m = []; + $d = []; foreach ($nums as $i => $x) { $y = $target - $x; - if (isset($m[$y])) { - return [$m[$y], $i]; + if (isset($d[$y])) { + return [$d[$y], $i]; } - $m[$x] = $i; + $d[$x] = $i; } } } @@ -249,17 +246,20 @@ class Solution { import scala.collection.mutable object Solution { - def twoSum(nums: Array[Int], target: Int): Array[Int] = { - var map = new mutable.HashMap[Int, Int]() - for (i <- 0 to nums.length) { - if (map.contains(target - nums(i))) { - return Array(map(target - nums(i)), i) - } else { - map += (nums(i) -> i) - } + def twoSum(nums: Array[Int], target: Int): Array[Int] = { + val d = mutable.Map[Int, Int]() + var ans: Array[Int] = Array() + for (i <- nums.indices if ans.isEmpty) { + val x = nums(i) + val y = target - x + if (d.contains(y)) { + ans = Array(d(y), i) + } else { + d(x) = i + } + } + ans } - Array(0, 0) - } } ``` @@ -268,17 +268,15 @@ object Solution { ```swift class Solution { func twoSum(_ nums: [Int], _ target: Int) -> [Int] { - var m = [Int: Int]() - var i = 0 - while true { - let x = nums[i] - let y = target - nums[i] - if let j = m[target - nums[i]] { + var d = [Int: Int]() + for (i, x) in nums.enumerated() { + let y = target - x + if let j = d[y] { return [j, i] } - m[nums[i]] = i - i += 1 + d[x] = i } + return [] } } ``` @@ -290,12 +288,14 @@ class Solution { # @param {Integer} target # @return {Integer[]} def two_sum(nums, target) - nums.each_with_index do |x, idx| - if nums.include? target - x - return [idx, nums.index(target - x)] if nums.index(target - x) != idx + d = {} + nums.each_with_index do |x, i| + y = target - x + if d.key?(y) + return [d[y], i] + end + d[x] = i end - next - end end ``` @@ -303,17 +303,16 @@ end ```nim import std/enumerate +import std/tables proc twoSum(nums: seq[int], target: int): seq[int] = - var - bal: int - tdx: int - for idx, val in enumerate(nums): - bal = target - val - if bal in nums: - tdx = nums.find(bal) - if idx != tdx: - return @[idx, tdx] + var d = initTable[int, int]() + for i, x in nums.pairs(): + let y = target - x + if d.hasKey(y): + return @[d[y], i] + d[x] = i + return @[] ``` diff --git a/solution/0000-0099/0001.Two Sum/Solution.cpp b/solution/0000-0099/0001.Two Sum/Solution.cpp index 8ba078b1bc02..8a7d8354e061 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.cpp +++ b/solution/0000-0099/0001.Two Sum/Solution.cpp @@ -1,14 +1,14 @@ class Solution { public: vector twoSum(vector& nums, int target) { - unordered_map m; + unordered_map d; for (int i = 0;; ++i) { int x = nums[i]; int y = target - x; - if (m.count(y)) { - return {m[y], i}; + if (d.contains(y)) { + return {d[y], i}; } - m[x] = i; + d[x] = i; } } -}; \ No newline at end of file +}; diff --git a/solution/0000-0099/0001.Two Sum/Solution.cs b/solution/0000-0099/0001.Two Sum/Solution.cs index f01832c83837..1a3fd2a6100c 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.cs +++ b/solution/0000-0099/0001.Two Sum/Solution.cs @@ -1,14 +1,14 @@ public class Solution { public int[] TwoSum(int[] nums, int target) { - var m = new Dictionary(); + var d = new Dictionary(); for (int i = 0, j; ; ++i) { int x = nums[i]; int y = target - x; - if (m.TryGetValue(y, out j)) { + if (d.TryGetValue(y, out j)) { return new [] {j, i}; } - if (!m.ContainsKey(x)) { - m.Add(x, i); + if (!d.ContainsKey(x)) { + d.Add(x, i); } } } diff --git a/solution/0000-0099/0001.Two Sum/Solution.go b/solution/0000-0099/0001.Two Sum/Solution.go index 6c5c6ca899ff..9e43d34ab888 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.go +++ b/solution/0000-0099/0001.Two Sum/Solution.go @@ -1,11 +1,11 @@ func twoSum(nums []int, target int) []int { - m := map[int]int{} + d := map[int]int{} for i := 0; ; i++ { x := nums[i] y := target - x - if j, ok := m[y]; ok { + if j, ok := d[y]; ok { return []int{j, i} } - m[x] = i + d[x] = i } -} \ No newline at end of file +} diff --git a/solution/0000-0099/0001.Two Sum/Solution.java b/solution/0000-0099/0001.Two Sum/Solution.java index f0e517db5b9c..8399b8e0af45 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.java +++ b/solution/0000-0099/0001.Two Sum/Solution.java @@ -1,13 +1,13 @@ class Solution { public int[] twoSum(int[] nums, int target) { - Map m = new HashMap<>(); + Map d = new HashMap<>(); for (int i = 0;; ++i) { int x = nums[i]; int y = target - x; - if (m.containsKey(y)) { - return new int[] {m.get(y), i}; + if (d.containsKey(y)) { + return new int[] {d.get(y), i}; } - m.put(x, i); + d.put(x, i); } } -} \ No newline at end of file +} diff --git a/solution/0000-0099/0001.Two Sum/Solution.js b/solution/0000-0099/0001.Two Sum/Solution.js index 1d8802042aba..3181501f6df1 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.js +++ b/solution/0000-0099/0001.Two Sum/Solution.js @@ -4,13 +4,13 @@ * @return {number[]} */ var twoSum = function (nums, target) { - const m = new Map(); + const d = new Map(); for (let i = 0; ; ++i) { const x = nums[i]; const y = target - x; - if (m.has(y)) { - return [m.get(y), i]; + if (d.has(y)) { + return [d.get(y), i]; } - m.set(x, i); + d.set(x, i); } }; diff --git a/solution/0000-0099/0001.Two Sum/Solution.nim b/solution/0000-0099/0001.Two Sum/Solution.nim index 5d5dc18ff9b3..91ad470acaff 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.nim +++ b/solution/0000-0099/0001.Two Sum/Solution.nim @@ -1,12 +1,11 @@ import std/enumerate +import std/tables proc twoSum(nums: seq[int], target: int): seq[int] = - var - bal: int - tdx: int - for idx, val in enumerate(nums): - bal = target - val - if bal in nums: - tdx = nums.find(bal) - if idx != tdx: - return @[idx, tdx] + var d = initTable[int, int]() + for i, x in nums.pairs(): + let y = target - x + if d.hasKey(y): + return @[d[y], i] + d[x] = i + return @[] diff --git a/solution/0000-0099/0001.Two Sum/Solution.php b/solution/0000-0099/0001.Two Sum/Solution.php index e706f0382e53..1b90c6f04a2a 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.php +++ b/solution/0000-0099/0001.Two Sum/Solution.php @@ -5,13 +5,13 @@ class Solution { * @return Integer[] */ function twoSum($nums, $target) { - $m = []; + $d = []; foreach ($nums as $i => $x) { $y = $target - $x; - if (isset($m[$y])) { - return [$m[$y], $i]; + if (isset($d[$y])) { + return [$d[$y], $i]; } - $m[$x] = $i; + $d[$x] = $i; } } -} \ No newline at end of file +} diff --git a/solution/0000-0099/0001.Two Sum/Solution.py b/solution/0000-0099/0001.Two Sum/Solution.py index 07e85af43d32..35a41d01ac45 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.py +++ b/solution/0000-0099/0001.Two Sum/Solution.py @@ -1,8 +1,8 @@ class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: - m = {} + d = {} for i, x in enumerate(nums): y = target - x - if y in m: - return [m[y], i] - m[x] = i + if y in d: + return [d[y], i] + d[x] = i diff --git a/solution/0000-0099/0001.Two Sum/Solution.rb b/solution/0000-0099/0001.Two Sum/Solution.rb index 26235fca40c3..777f10f4bcf3 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.rb +++ b/solution/0000-0099/0001.Two Sum/Solution.rb @@ -2,10 +2,12 @@ # @param {Integer} target # @return {Integer[]} def two_sum(nums, target) - nums.each_with_index do |x, idx| - if nums.include? target - x - return [idx, nums.index(target - x)] if nums.index(target - x) != idx + d = {} + nums.each_with_index do |x, i| + y = target - x + if d.key?(y) + return [d[y], i] + end + d[x] = i end - next - end end diff --git a/solution/0000-0099/0001.Two Sum/Solution.rs b/solution/0000-0099/0001.Two Sum/Solution.rs index 7f3e7361c783..fbd2efd3e4c6 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.rs +++ b/solution/0000-0099/0001.Two Sum/Solution.rs @@ -2,14 +2,14 @@ use std::collections::HashMap; impl Solution { pub fn two_sum(nums: Vec, target: i32) -> Vec { - let mut m = HashMap::new(); + let mut d = HashMap::new(); for (i, &x) in nums.iter().enumerate() { let y = target - x; - if let Some(&j) = m.get(&y) { + if let Some(&j) = d.get(&y) { return vec![j as i32, i as i32]; } - m.insert(x, i as i32); + d.insert(x, i); } - unreachable!() + vec![] } } diff --git a/solution/0000-0099/0001.Two Sum/Solution.scala b/solution/0000-0099/0001.Two Sum/Solution.scala index 15e2a5ccec96..6a28ccb83e82 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.scala +++ b/solution/0000-0099/0001.Two Sum/Solution.scala @@ -1,15 +1,18 @@ import scala.collection.mutable object Solution { - def twoSum(nums: Array[Int], target: Int): Array[Int] = { - var map = new mutable.HashMap[Int, Int]() - for (i <- 0 to nums.length) { - if (map.contains(target - nums(i))) { - return Array(map(target - nums(i)), i) - } else { - map += (nums(i) -> i) - } + def twoSum(nums: Array[Int], target: Int): Array[Int] = { + val d = mutable.Map[Int, Int]() + var ans: Array[Int] = Array() + for (i <- nums.indices if ans.isEmpty) { + val x = nums(i) + val y = target - x + if (d.contains(y)) { + ans = Array(d(y), i) + } else { + d(x) = i + } + } + ans } - Array(0, 0) - } } diff --git a/solution/0000-0099/0001.Two Sum/Solution.swift b/solution/0000-0099/0001.Two Sum/Solution.swift index 6a84df9aaf96..0f53f111fed5 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.swift +++ b/solution/0000-0099/0001.Two Sum/Solution.swift @@ -1,15 +1,13 @@ class Solution { func twoSum(_ nums: [Int], _ target: Int) -> [Int] { - var m = [Int: Int]() - var i = 0 - while true { - let x = nums[i] - let y = target - nums[i] - if let j = m[target - nums[i]] { + var d = [Int: Int]() + for (i, x) in nums.enumerated() { + let y = target - x + if let j = d[y] { return [j, i] } - m[nums[i]] = i - i += 1 + d[x] = i } + return [] } } diff --git a/solution/0000-0099/0001.Two Sum/Solution.ts b/solution/0000-0099/0001.Two Sum/Solution.ts index 624e48d25102..3e425cb5ca1c 100644 --- a/solution/0000-0099/0001.Two Sum/Solution.ts +++ b/solution/0000-0099/0001.Two Sum/Solution.ts @@ -1,14 +1,11 @@ function twoSum(nums: number[], target: number): number[] { - const m: Map = new Map(); - + const d = new Map(); for (let i = 0; ; ++i) { const x = nums[i]; const y = target - x; - - if (m.has(y)) { - return [m.get(y)!, i]; + if (d.has(y)) { + return [d.get(y)!, i]; } - - m.set(x, i); + d.set(x, i); } } diff --git a/solution/0000-0099/0010.Regular Expression Matching/README.md b/solution/0000-0099/0010.Regular Expression Matching/README.md index eb824ee89d24..5eb9ff8be6f3 100644 --- a/solution/0000-0099/0010.Regular Expression Matching/README.md +++ b/solution/0000-0099/0010.Regular Expression Matching/README.md @@ -25,7 +25,7 @@ tags:
  • '*' 匹配零个或多个前面的那一个元素
  • -

    所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

    +

    所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串。

     

    示例 1:

    diff --git a/solution/0000-0099/0013.Roman to Integer/README.md b/solution/0000-0099/0013.Roman to Integer/README.md index ca5d3ca8955b..4d985955579f 100644 --- a/solution/0000-0099/0013.Roman to Integer/README.md +++ b/solution/0000-0099/0013.Roman to Integer/README.md @@ -87,7 +87,7 @@ M 1000
  • 题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999]
  • 题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
  • IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
  • -
  • 关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics
  • +
  • 关于罗马数字的详尽书写规则,可以参考 罗马数字 - 百度百科
  • diff --git a/solution/0000-0099/0015.3Sum/README.md b/solution/0000-0099/0015.3Sum/README.md index 0d60c80a54ff..97e493065a58 100644 --- a/solution/0000-0099/0015.3Sum/README.md +++ b/solution/0000-0099/0015.3Sum/README.md @@ -18,9 +18,7 @@ tags: -

    给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

    - -

    你返回所有和为 0 且不重复的三元组。

    +

    给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

    注意:答案中不可以包含重复的三元组。

    diff --git a/solution/0000-0099/0016.3Sum Closest/README.md b/solution/0000-0099/0016.3Sum Closest/README.md index 36a0f1a68f58..26a419cdec0e 100644 --- a/solution/0000-0099/0016.3Sum Closest/README.md +++ b/solution/0000-0099/0016.3Sum Closest/README.md @@ -31,7 +31,7 @@ tags:
     输入:nums = [-1,2,1,-4], target = 1
     输出:2
    -解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
    +解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2)。
     

    示例 2:

    @@ -39,7 +39,7 @@ tags:
     输入:nums = [0,0,0], target = 1
     输出:0
    -
    +解释:与 target 最接近的和是 0(0 + 0 + 0 = 0)。

     

    diff --git a/solution/0000-0099/0032.Longest Valid Parentheses/README.md b/solution/0000-0099/0032.Longest Valid Parentheses/README.md index 6f29dbc12303..41b8be83eb9e 100644 --- a/solution/0000-0099/0032.Longest Valid Parentheses/README.md +++ b/solution/0000-0099/0032.Longest Valid Parentheses/README.md @@ -77,9 +77,9 @@ tags: $$ \begin{cases} -f[i] = 0, & \text{if } s[i-1] = '(',\\ -f[i] = f[i-2] + 2, & \text{if } s[i-1] = ')' \text{ and } s[i-2] = '(',\\ -f[i] = f[i-1] + 2 + f[i-f[i-1]-2], & \text{if } s[i-1] = ')' \text{ and } s[i-2] = ')' \text{ and } s[i-f[i-1]-2] = '(',\\ +f[i] = 0, & \textit{if } s[i-1] = '(',\\ +f[i] = f[i-2] + 2, & \textit{if } s[i-1] = ')' \textit{ and } s[i-2] = '(',\\ +f[i] = f[i-1] + 2 + f[i-f[i-1]-2], & \textit{if } s[i-1] = ')' \textit{ and } s[i-2] = ')' \textit{ and } s[i-f[i-1]-2] = '(',\\ \end{cases} $$ diff --git a/solution/0000-0099/0032.Longest Valid Parentheses/README_EN.md b/solution/0000-0099/0032.Longest Valid Parentheses/README_EN.md index c6dba25b590c..3b724ae45f68 100644 --- a/solution/0000-0099/0032.Longest Valid Parentheses/README_EN.md +++ b/solution/0000-0099/0032.Longest Valid Parentheses/README_EN.md @@ -75,9 +75,9 @@ Therefore, we can get the state transition equation: $$ \begin{cases} -f[i] = 0, & \text{if } s[i-1] = '(',\\ -f[i] = f[i-2] + 2, & \text{if } s[i-1] = ')' \text{ and } s[i-2] = '(',\\ -f[i] = f[i-1] + 2 + f[i-f[i-1]-2], & \text{if } s[i-1] = ')' \text{ and } s[i-2] = ')' \text{ and } s[i-f[i-1]-2] = '(',\\ +f[i] = 0, & \textit{if } s[i-1] = '(',\\ +f[i] = f[i-2] + 2, & \textit{if } s[i-1] = ')' \textit{ and } s[i-2] = '(',\\ +f[i] = f[i-1] + 2 + f[i-f[i-1]-2], & \textit{if } s[i-1] = ')' \textit{ and } s[i-2] = ')' \textit{ and } s[i-f[i-1]-2] = '(',\\ \end{cases} $$ diff --git a/solution/0000-0099/0044.Wildcard Matching/README.md b/solution/0000-0099/0044.Wildcard Matching/README.md index af58b95316fb..4307c23d0f1b 100644 --- a/solution/0000-0099/0044.Wildcard Matching/README.md +++ b/solution/0000-0099/0044.Wildcard Matching/README.md @@ -79,8 +79,8 @@ tags: 函数 $dfs(i, j)$ 的执行过程如下: -- 如果 $i \geq \text{len}(s)$,那么只有当 $j \geq \text{len}(p)$ 或者 $p[j] = '*'$ 且 $dfs(i, j + 1)$ 为真时,$dfs(i, j)$ 才为真。 -- 如果 $j \geq \text{len}(p)$,那么 $dfs(i, j)$ 为假。 +- 如果 $i \geq \textit{len}(s)$,那么只有当 $j \geq \textit{len}(p)$ 或者 $p[j] = '*'$ 且 $dfs(i, j + 1)$ 为真时,$dfs(i, j)$ 才为真。 +- 如果 $j \geq \textit{len}(p)$,那么 $dfs(i, j)$ 为假。 - 如果 $p[j] = '*'$,那么 $dfs(i, j)$ 为真当且仅当 $dfs(i + 1, j)$ 或 $dfs(i + 1, j + 1)$ 或 $dfs(i, j + 1)$ 中有一个为真。 - 否则 $dfs(i, j)$ 为真当且仅当 $p[j] = '?'$ 或 $s[i] = p[j]$ 且 $dfs(i + 1, j + 1)$ 为真。 @@ -293,7 +293,7 @@ public class Solution { 我们可以将方法一中的记忆化搜索转换为动态规划。 -定义 $f[i][j]$ 表示字符串 $s$ 的前 $i$ 个字符和字符串 $p$ 的前 $j$ 个字符是否匹配。初始时 $f[0][0] = \text{true}$,表示两个空字符串是匹配的。对于 $j \in [1, n]$,如果 $p[j-1] = '*'$,那么 $f[0][j] = f[0][j-1]$。 +定义 $f[i][j]$ 表示字符串 $s$ 的前 $i$ 个字符和字符串 $p$ 的前 $j$ 个字符是否匹配。初始时 $f[0][0] = \textit{true}$,表示两个空字符串是匹配的。对于 $j \in [1, n]$,如果 $p[j-1] = '*'$,那么 $f[0][j] = f[0][j-1]$。 接下来我们考虑 $i \in [1, m]$ 和 $j \in [1, n]$ 的情况: diff --git a/solution/0000-0099/0044.Wildcard Matching/README_EN.md b/solution/0000-0099/0044.Wildcard Matching/README_EN.md index 4bce7a87a592..a18cfe3de356 100644 --- a/solution/0000-0099/0044.Wildcard Matching/README_EN.md +++ b/solution/0000-0099/0044.Wildcard Matching/README_EN.md @@ -74,8 +74,8 @@ We design a function $dfs(i, j)$, which represents whether the string $s$ starti The execution process of the function $dfs(i, j)$ is as follows: -- If $i \geq \text{len}(s)$, then $dfs(i, j)$ is true only when $j \geq \text{len}(p)$ or $p[j] = '*'$ and $dfs(i, j + 1)$ is true. -- If $j \geq \text{len}(p)$, then $dfs(i, j)$ is false. +- If $i \geq \textit{len}(s)$, then $dfs(i, j)$ is true only when $j \geq \textit{len}(p)$ or $p[j] = '*'$ and $dfs(i, j + 1)$ is true. +- If $j \geq \textit{len}(p)$, then $dfs(i, j)$ is false. - If $p[j] = '*'$, then $dfs(i, j)$ is true if and only if $dfs(i + 1, j)$ or $dfs(i + 1, j + 1)$ or $dfs(i, j + 1)$ is true. - Otherwise, $dfs(i, j)$ is true if and only if $p[j] = '?'$ or $s[i] = p[j]$ and $dfs(i + 1, j + 1)$ is true. @@ -288,7 +288,7 @@ public class Solution { We can convert the memoization search in Solution 1 into dynamic programming. -Define $f[i][j]$ to represent whether the first $i$ characters of string $s$ match the first $j$ characters of string $p$. Initially, $f[0][0] = \text{true}$, indicating that two empty strings are matching. For $j \in [1, n]$, if $p[j-1] = '*'$, then $f[0][j] = f[0][j-1]$. +Define $f[i][j]$ to represent whether the first $i$ characters of string $s$ match the first $j$ characters of string $p$. Initially, $f[0][0] = \textit{true}$, indicating that two empty strings are matching. For $j \in [1, n]$, if $p[j-1] = '*'$, then $f[0][j] = f[0][j-1]$. Next, we consider the case of $i \in [1, m]$ and $j \in [1, n]$: diff --git a/solution/0000-0099/0062.Unique Paths/README.md b/solution/0000-0099/0062.Unique Paths/README.md index 5f4413661b48..d8c583dcb020 100644 --- a/solution/0000-0099/0062.Unique Paths/README.md +++ b/solution/0000-0099/0062.Unique Paths/README.md @@ -86,7 +86,7 @@ tags: $$ f[i][j] = \begin{cases} 1 & i = 0, j = 0 \\ -f[i - 1][j] + f[i][j - 1] & \text{otherwise} +f[i - 1][j] + f[i][j - 1] & \textit{otherwise} \end{cases} $$ diff --git a/solution/0000-0099/0062.Unique Paths/README_EN.md b/solution/0000-0099/0062.Unique Paths/README_EN.md index 2c2321c934c2..f276f8bc01d1 100644 --- a/solution/0000-0099/0062.Unique Paths/README_EN.md +++ b/solution/0000-0099/0062.Unique Paths/README_EN.md @@ -70,7 +70,7 @@ Therefore, we have the following state transition equation: $$ f[i][j] = \begin{cases} 1 & i = 0, j = 0 \\ -f[i - 1][j] + f[i][j - 1] & \text{otherwise} +f[i - 1][j] + f[i][j - 1] & \textit{otherwise} \end{cases} $$ diff --git a/solution/0000-0099/0071.Simplify Path/README.md b/solution/0000-0099/0071.Simplify Path/README.md index 4ea9bfda09e2..6551d3fe9d4d 100644 --- a/solution/0000-0099/0071.Simplify Path/README.md +++ b/solution/0000-0099/0071.Simplify Path/README.md @@ -17,9 +17,9 @@ tags: -

    给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/' 开头),请你将其转化为更加简洁的规范路径。

    +

    给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/' 开头),请你将其转化为更加简洁的规范路径。

    -

    在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。

    +

    在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。

    请注意,返回的 规范路径 必须遵循下述格式:

    @@ -32,44 +32,74 @@ tags:

    返回简化后得到的 规范路径

    -

     

    +

     

    -

    示例 1:

    +

    示例 1:

    -
    -输入:path = "/home/"
    -输出:"/home"
    -解释:注意,最后一个目录名后面没有斜杠。 
    +
    +

    输入:path = "/home/"

    -

    示例 2:

    +

    输出:"/home"

    -
    -输入:path = "/../"
    -输出:"/"
    -解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。
    -
    +

    解释:

    -

    示例 3:

    +

    应删除尾部斜杠。

    +
    -
    -输入:path = "/home//foo/"
    -输出:"/home/foo"
    -解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
    -
    +

    示例 2:

    -

    示例 4:

    +
    +

    输入:path = "/home//foo/"

    -
    -输入:path = "/a/./b/../../c/"
    -输出:"/c"
    -
    +

    输出:"/home/foo"

    -

     

    +

    解释:

    + +

    多个连续的斜杠被单个斜杠替换。

    +
    + +

    示例 3:

    + +
    +

    输入:path = "/home/user/Documents/../Pictures"

    + +

    输出:"/home/user/Pictures"

    + +

    解释:

    + +

    两个点 ".." 表示上一级目录。

    +
    + +

    示例 4:

    + +
    +

    输入:path = "/../"

    + +

    输出:"/"

    + +

    解释:

    + +

    不可能从根目录上升级一级。

    +
    + +

    示例 5:

    + +
    +

    输入:path = "/.../a/../b/c/../d/./"

    + +

    输出:"/.../b/d"

    + +

    解释:

    + +

    "..." 是此问题中目录的有效名称。

    +
    + +

     

    提示:

      -
    • 1 <= path.length <= 3000
    • +
    • 1 <= path.length <= 3000
    • path 由英文字母,数字,'.''/''_' 组成。
    • path 是一个有效的 Unix 风格绝对路径。
    diff --git a/solution/0000-0099/0071.Simplify Path/README_EN.md b/solution/0000-0099/0071.Simplify Path/README_EN.md index 9d900204626d..eddbbd32ac0b 100644 --- a/solution/0000-0099/0071.Simplify Path/README_EN.md +++ b/solution/0000-0099/0071.Simplify Path/README_EN.md @@ -45,8 +45,6 @@ tags:

    The trailing slash should be removed.

    -
     
    -

    Example 2:

    @@ -69,6 +67,7 @@ tags:

    Explanation:

    A double period ".." refers to the directory up a level.

    +

    Example 4:

    @@ -81,7 +80,6 @@ tags:

    Going one level up from the root directory is not possible.

    -

    Example 5:

    diff --git a/solution/0000-0099/0072.Edit Distance/README.md b/solution/0000-0099/0072.Edit Distance/README.md index 404004165ea2..757c2199f9a9 100644 --- a/solution/0000-0099/0072.Edit Distance/README.md +++ b/solution/0000-0099/0072.Edit Distance/README.md @@ -81,10 +81,10 @@ exection -> execution (插入 'u') $$ f[i][j] = \begin{cases} -i, & \text{if } j = 0 \\ -j, & \text{if } i = 0 \\ -f[i - 1][j - 1], & \text{if } word1[i - 1] = word2[j - 1] \\ -\min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1, & \text{otherwise} +i, & \textit{if } j = 0 \\ +j, & \textit{if } i = 0 \\ +f[i - 1][j - 1], & \textit{if } word1[i - 1] = word2[j - 1] \\ +\min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1, & \textit{otherwise} \end{cases} $$ diff --git a/solution/0000-0099/0072.Edit Distance/README_EN.md b/solution/0000-0099/0072.Edit Distance/README_EN.md index cbac236faf70..41321ff89386 100644 --- a/solution/0000-0099/0072.Edit Distance/README_EN.md +++ b/solution/0000-0099/0072.Edit Distance/README_EN.md @@ -79,10 +79,10 @@ Finally, we can get the state transition equation: $$ f[i][j] = \begin{cases} -i, & \text{if } j = 0 \\ -j, & \text{if } i = 0 \\ -f[i - 1][j - 1], & \text{if } word1[i - 1] = word2[j - 1] \\ -\min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1, & \text{otherwise} +i, & \textit{if } j = 0 \\ +j, & \textit{if } i = 0 \\ +f[i - 1][j - 1], & \textit{if } word1[i - 1] = word2[j - 1] \\ +\min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1, & \textit{otherwise} \end{cases} $$ diff --git a/solution/0000-0099/0075.Sort Colors/README.md b/solution/0000-0099/0075.Sort Colors/README.md index 3cdb264d2e73..03206a6cb6bc 100644 --- a/solution/0000-0099/0075.Sort Colors/README.md +++ b/solution/0000-0099/0075.Sort Colors/README.md @@ -18,7 +18,7 @@ tags: -

    给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

    +

    给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

    我们使用整数 0、 12 分别表示红色、白色和蓝色。

    diff --git a/solution/0000-0099/0085.Maximal Rectangle/README.md b/solution/0000-0099/0085.Maximal Rectangle/README.md index 8f7d6760b3a3..e549b2983cc9 100644 --- a/solution/0000-0099/0085.Maximal Rectangle/README.md +++ b/solution/0000-0099/0085.Maximal Rectangle/README.md @@ -25,7 +25,7 @@ tags:

     

    示例 1:

    - +
     输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
     输出:6
    diff --git a/solution/0000-0099/0085.Maximal Rectangle/images/1722912576-boIxpm-image.png b/solution/0000-0099/0085.Maximal Rectangle/images/1722912576-boIxpm-image.png
    new file mode 100644
    index 000000000000..bbf815c01d20
    Binary files /dev/null and b/solution/0000-0099/0085.Maximal Rectangle/images/1722912576-boIxpm-image.png differ
    diff --git a/solution/0000-0099/0091.Decode Ways/README.md b/solution/0000-0099/0091.Decode Ways/README.md
    index 4f263c0409f8..9c51a029e9fa 100644
    --- a/solution/0000-0099/0091.Decode Ways/README.md	
    +++ b/solution/0000-0099/0091.Decode Ways/README.md	
    @@ -19,22 +19,25 @@ tags:
     
     

    一条包含字母 A-Z 的消息通过以下映射进行了 编码

    -
    -'A' -> "1"
    -'B' -> "2"
    -...
    -'Z' -> "26"
    +

    "1" -> 'A'
    +"2" -> 'B'
    +...
    +"25" -> 'Y'
    +"26" -> 'Z'

    + +

    然而,在 解码 已编码的消息时,你意识到有许多不同的方式来解码,因为有些编码被包含在其它编码当中("2""5""25")。

    -

    解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

    +

    例如,"11106" 可以映射为:

      -
    • "AAJF" ,将消息分组为 (1 1 10 6)
    • -
    • "KJF" ,将消息分组为 (11 10 6)
    • +
    • "AAJF" ,将消息分组为 (1, 1, 10, 6)
    • +
    • "KJF" ,将消息分组为 (11, 10, 6)
    • +
    • 消息不能分组为  (1, 11, 06) ,因为 "06" 不是一个合法编码(只有 "6" 是合法的)。
    -

    注意,消息不能分组为  (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6""06" 在映射中并不等价。

    +

    注意,可能存在无法解码的字符串。

    -

    给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数

    +

    给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。如果没有合法的方式解码整个字符串,返回 0

    题目数据保证答案肯定是一个 32 位 的整数。

    diff --git a/solution/0000-0099/0091.Decode Ways/README_EN.md b/solution/0000-0099/0091.Decode Ways/README_EN.md index aa4494f02283..670935d80be0 100644 --- a/solution/0000-0099/0091.Decode Ways/README_EN.md +++ b/solution/0000-0099/0091.Decode Ways/README_EN.md @@ -17,52 +17,66 @@ tags: -

    A message containing letters from A-Z can be encoded into numbers using the following mapping:

    +

    You have intercepted a secret message encoded as a string of numbers. The message is decoded via the following mapping:

    -
    -'A' -> "1"
    -'B' -> "2"
    -...
    -'Z' -> "26"
    -
    +

    "1" -> 'A'
    +"2" -> 'B'
    +...
    +"25" -> 'Y'
    +"26" -> 'Z'

    -

    To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, "11106" can be mapped into:

    +

    However, while decoding the message, you realize that there are many different ways you can decode the message because some codes are contained in other codes ("2" and "5" vs "25").

    + +

    For example, "11106" can be decoded into:

      -
    • "AAJF" with the grouping (1 1 10 6)
    • -
    • "KJF" with the grouping (11 10 6)
    • +
    • "AAJF" with the grouping (1, 1, 10, 6)
    • +
    • "KJF" with the grouping (11, 10, 6)
    • +
    • The grouping (1, 11, 06) is invalid because "06" is not a valid code (only "6" is valid).
    -

    Note that the grouping (1 11 06) is invalid because "06" cannot be mapped into 'F' since "6" is different from "06".

    - -

    Given a string s containing only digits, return the number of ways to decode it.

    +

    Note: there may be strings that are impossible to decode.
    +
    +Given a string s containing only digits, return the number of ways to decode it. If the entire string cannot be decoded in any valid way, return 0.

    The test cases are generated so that the answer fits in a 32-bit integer.

     

    Example 1:

    -
    -Input: s = "12"
    -Output: 2
    -Explanation: "12" could be decoded as "AB" (1 2) or "L" (12).
    -
    +
    +

    Input: s = "12"

    + +

    Output: 2

    + +

    Explanation:

    + +

    "12" could be decoded as "AB" (1 2) or "L" (12).

    +

    Example 2:

    -
    -Input: s = "226"
    -Output: 3
    -Explanation: "226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
    -
    +
    +

    Input: s = "226"

    + +

    Output: 3

    + +

    Explanation:

    + +

    "226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).

    +

    Example 3:

    -
    -Input: s = "06"
    -Output: 0
    -Explanation: "06" cannot be mapped to "F" because of the leading zero ("6" is different from "06").
    -
    +
    +

    Input: s = "06"

    + +

    Output: 0

    + +

    Explanation:

    + +

    "06" cannot be mapped to "F" because of the leading zero ("6" is different from "06"). In this case, the string is not a valid encoding, so return 0.

    +

     

    Constraints:

    diff --git a/solution/0000-0099/0097.Interleaving String/README.md b/solution/0000-0099/0097.Interleaving String/README.md index 564d3cc41af1..805e8315d4e0 100644 --- a/solution/0000-0099/0097.Interleaving String/README.md +++ b/solution/0000-0099/0097.Interleaving String/README.md @@ -377,13 +377,13 @@ public class Solution { $$ f[i][j] = \begin{cases} -f[i - 1][j] & \text{if } s_1[i - 1] = s_3[i + j - 1] \\ -\text{or } f[i][j - 1] & \text{if } s_2[j - 1] = s_3[i + j - 1] \\ -\text{false} & \text{otherwise} +f[i - 1][j] & \textit{if } s_1[i - 1] = s_3[i + j - 1] \\ +\textit{or } f[i][j - 1] & \textit{if } s_2[j - 1] = s_3[i + j - 1] \\ +\textit{false} & \textit{otherwise} \end{cases} $$ -其中 $f[0][0] = \text{true}$ 表示空串是两个空串的交错字符串。 +其中 $f[0][0] = \textit{true}$ 表示空串是两个空串的交错字符串。 答案即为 $f[m][n]$。 diff --git a/solution/0000-0099/0097.Interleaving String/README_EN.md b/solution/0000-0099/0097.Interleaving String/README_EN.md index eb48eb39c68a..93801d1703bc 100644 --- a/solution/0000-0099/0097.Interleaving String/README_EN.md +++ b/solution/0000-0099/0097.Interleaving String/README_EN.md @@ -379,13 +379,13 @@ We define $f[i][j]$ to represent whether the first $i$ characters of string $s_1 $$ f[i][j] = \begin{cases} -f[i - 1][j] & \text{if } s_1[i - 1] = s_3[i + j - 1] \\ -\text{or } f[i][j - 1] & \text{if } s_2[j - 1] = s_3[i + j - 1] \\ -\text{false} & \text{otherwise} +f[i - 1][j] & \textit{if } s_1[i - 1] = s_3[i + j - 1] \\ +\textit{or } f[i][j - 1] & \textit{if } s_2[j - 1] = s_3[i + j - 1] \\ +\textit{false} & \textit{otherwise} \end{cases} $$ -where $f[0][0] = \text{true}$ indicates that an empty string is an interleaving string of two empty strings. +where $f[0][0] = \textit{true}$ indicates that an empty string is an interleaving string of two empty strings. The answer is $f[m][n]$. diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/README.md b/solution/0000-0099/0098.Validate Binary Search Tree/README.md index 129b61bafaef..0f2ca49cb604 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/README.md +++ b/solution/0000-0099/0098.Validate Binary Search Tree/README.md @@ -65,7 +65,7 @@ tags: 我们可以对二叉树进行递归中序遍历,如果遍历到的结果是严格升序的,那么这棵树就是一个二叉搜索树。 -因此,我们使用一个变量 $\textit{prev}$ 来保存上一个遍历到的节点,初始时 $\textit{prev} = -\infty$,然后我们递归遍历左子树,如果左子树不是二叉搜索树,直接返回 $\text{False}$,否则判断当前节点的值是否大于 $\textit{prev}$,如果不是,返回 $\text{False}$,否则更新 $\textit{prev}$ 为当前节点的值,然后递归遍历右子树。 +因此,我们使用一个变量 $\textit{prev}$ 来保存上一个遍历到的节点,初始时 $\textit{prev} = -\infty$,然后我们递归遍历左子树,如果左子树不是二叉搜索树,直接返回 $\textit{False}$,否则判断当前节点的值是否大于 $\textit{prev}$,如果不是,返回 $\textit{False}$,否则更新 $\textit{prev}$ 为当前节点的值,然后递归遍历右子树。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。 diff --git a/solution/0100-0199/0132.Palindrome Partitioning II/README.md b/solution/0100-0199/0132.Palindrome Partitioning II/README.md index 90bde0e1186f..6c79e69452a6 100644 --- a/solution/0100-0199/0132.Palindrome Partitioning II/README.md +++ b/solution/0100-0199/0132.Palindrome Partitioning II/README.md @@ -73,7 +73,7 @@ tags: 接下来,我们考虑 $f[i]$ 如何进行状态转移。我们可以枚举上一个分割点 $j$,如果子串 $s[j..i]$ 是一个回文串,那么 $f[i]$ 就可以从 $f[j]$ 转移而来。如果 $j=0$,那么说明 $s[0..i]$ 本身就是一个回文串,此时不需要进行分割,即 $f[i]=0$。因此,状态转移方程如下: $$ -f[i]=\min_{0\leq j \leq i}\begin{cases} f[j-1]+1, & \text{if}\ g[j][i]=\text{True} \\ 0, & \text{if}\ g[0][i]=\text{True} \end{cases} +f[i]=\min_{0\leq j \leq i}\begin{cases} f[j-1]+1, & \textit{if}\ g[j][i]=\textit{True} \\ 0, & \textit{if}\ g[0][i]=\textit{True} \end{cases} $$ 答案即为 $f[n]$,其中 $n$ 是字符串 $s$ 的长度。 diff --git a/solution/0100-0199/0137.Single Number II/README.md b/solution/0100-0199/0137.Single Number II/README.md index 380f5e4329ad..7befb363ad3f 100644 --- a/solution/0100-0199/0137.Single Number II/README.md +++ b/solution/0100-0199/0137.Single Number II/README.md @@ -146,6 +146,19 @@ function singleNumber(nums: number[]): number { } ``` +#### JavaScript + +```js +function singleNumber(nums) { + let ans = 0; + for (let i = 0; i < 32; i++) { + const count = nums.reduce((r, v) => r + ((v >> i) & 1), 0); + ans |= count % 3 << i; + } + return ans; +} +``` + #### Rust ```rust @@ -319,6 +332,22 @@ function singleNumber(nums: number[]): number { } ``` +#### JavaScript + +```js +function singleNumber(nums) { + let a = 0; + let b = 0; + for (const c of nums) { + const aa = (~a & b & c) | (a & ~b & ~c); + const bb = ~a & (b ^ c); + a = aa; + b = bb; + } + return b; +} +``` + #### Rust ```rust @@ -343,4 +372,74 @@ impl Solution { + + +### 方法三:哈希表 + 数学 + + + +#### TypeScript + +```ts +function singleNumber(nums: number[]): number { + const sumOfUnique = [...new Set(nums)].reduce((a, b) => a + b, 0); + const sum = nums.reduce((a, b) => a + b, 0); + return (sumOfUnique * 3 - sum) / 2; +} +``` + +#### JavaScript + +```js +function singleNumber(nums) { + const sumOfUnique = [...new Set(nums)].reduce((a, b) => a + b, 0); + const sum = nums.reduce((a, b) => a + b, 0); + return (sumOfUnique * 3 - sum) / 2; +} +``` + + + + + + + +### 方法四:位运算 + + + +#### TypeScript + +```ts +function singleNumber(nums: number[]): number { + let [ans, acc] = [0, 0]; + + for (const x of nums) { + ans ^= x & ~acc; + acc ^= x & ~ans; + } + + return ans; +} +``` + +#### JavaScript + +```ts +function singleNumber(nums) { + let [ans, acc] = [0, 0]; + + for (const x of nums) { + ans ^= x & ~acc; + acc ^= x & ~ans; + } + + return ans; +} +``` + + + + + diff --git a/solution/0100-0199/0137.Single Number II/README_EN.md b/solution/0100-0199/0137.Single Number II/README_EN.md index 65c7a2543a18..81e2ceb8cb0a 100644 --- a/solution/0100-0199/0137.Single Number II/README_EN.md +++ b/solution/0100-0199/0137.Single Number II/README_EN.md @@ -137,6 +137,19 @@ function singleNumber(nums: number[]): number { } ``` +#### JavaScript + +```js +function singleNumber(nums) { + let ans = 0; + for (let i = 0; i < 32; i++) { + const count = nums.reduce((r, v) => r + ((v >> i) & 1), 0); + ans |= count % 3 << i; + } + return ans; +} +``` + #### Rust ```rust @@ -310,6 +323,22 @@ function singleNumber(nums: number[]): number { } ``` +#### JavaScript + +```js +function singleNumber(nums) { + let a = 0; + let b = 0; + for (const c of nums) { + const aa = (~a & b & c) | (a & ~b & ~c); + const bb = ~a & (b ^ c); + a = aa; + b = bb; + } + return b; +} +``` + #### Rust ```rust @@ -334,4 +363,74 @@ impl Solution { + + +### Solution 3: Set + Math + + + +#### TypeScript + +```ts +function singleNumber(nums: number[]): number { + const sumOfUnique = [...new Set(nums)].reduce((a, b) => a + b, 0); + const sum = nums.reduce((a, b) => a + b, 0); + return (sumOfUnique * 3 - sum) / 2; +} +``` + +#### JavaScript + +```js +function singleNumber(nums) { + const sumOfUnique = [...new Set(nums)].reduce((a, b) => a + b, 0); + const sum = nums.reduce((a, b) => a + b, 0); + return (sumOfUnique * 3 - sum) / 2; +} +``` + + + + + + + +### Solution 4: Bit Manipulation + + + +#### TypeScript + +```ts +function singleNumber(nums: number[]): number { + let [ans, acc] = [0, 0]; + + for (const x of nums) { + ans ^= x & ~acc; + acc ^= x & ~ans; + } + + return ans; +} +``` + +#### JavaScript + +```ts +function singleNumber(nums) { + let [ans, acc] = [0, 0]; + + for (const x of nums) { + ans ^= x & ~acc; + acc ^= x & ~ans; + } + + return ans; +} +``` + + + + + diff --git a/solution/0100-0199/0137.Single Number II/Solution.js b/solution/0100-0199/0137.Single Number II/Solution.js new file mode 100644 index 000000000000..97db05ced723 --- /dev/null +++ b/solution/0100-0199/0137.Single Number II/Solution.js @@ -0,0 +1,8 @@ +function singleNumber(nums) { + let ans = 0; + for (let i = 0; i < 32; i++) { + const count = nums.reduce((r, v) => r + ((v >> i) & 1), 0); + ans |= count % 3 << i; + } + return ans; +} diff --git a/solution/0100-0199/0137.Single Number II/Solution2.js b/solution/0100-0199/0137.Single Number II/Solution2.js new file mode 100644 index 000000000000..b9385331291d --- /dev/null +++ b/solution/0100-0199/0137.Single Number II/Solution2.js @@ -0,0 +1,11 @@ +function singleNumber(nums) { + let a = 0; + let b = 0; + for (const c of nums) { + const aa = (~a & b & c) | (a & ~b & ~c); + const bb = ~a & (b ^ c); + a = aa; + b = bb; + } + return b; +} diff --git a/solution/0100-0199/0137.Single Number II/Solution3.js b/solution/0100-0199/0137.Single Number II/Solution3.js new file mode 100644 index 000000000000..8b8ab60c7e10 --- /dev/null +++ b/solution/0100-0199/0137.Single Number II/Solution3.js @@ -0,0 +1,5 @@ +function singleNumber(nums) { + const sumOfUnique = [...new Set(nums)].reduce((a, b) => a + b, 0); + const sum = nums.reduce((a, b) => a + b, 0); + return (sumOfUnique * 3 - sum) / 2; +} diff --git a/solution/0100-0199/0137.Single Number II/Solution3.ts b/solution/0100-0199/0137.Single Number II/Solution3.ts new file mode 100644 index 000000000000..02674c63ff57 --- /dev/null +++ b/solution/0100-0199/0137.Single Number II/Solution3.ts @@ -0,0 +1,5 @@ +function singleNumber(nums: number[]): number { + const sumOfUnique = [...new Set(nums)].reduce((a, b) => a + b, 0); + const sum = nums.reduce((a, b) => a + b, 0); + return (sumOfUnique * 3 - sum) / 2; +} diff --git a/solution/0100-0199/0137.Single Number II/Solution4.js b/solution/0100-0199/0137.Single Number II/Solution4.js new file mode 100644 index 000000000000..dde5cb51e40c --- /dev/null +++ b/solution/0100-0199/0137.Single Number II/Solution4.js @@ -0,0 +1,10 @@ +function singleNumber(nums) { + let [ans, acc] = [0, 0]; + + for (const x of nums) { + ans ^= x & ~acc; + acc ^= x & ~ans; + } + + return ans; +} diff --git a/solution/0100-0199/0137.Single Number II/Solution4.ts b/solution/0100-0199/0137.Single Number II/Solution4.ts new file mode 100644 index 000000000000..d4d59d1de5af --- /dev/null +++ b/solution/0100-0199/0137.Single Number II/Solution4.ts @@ -0,0 +1,10 @@ +function singleNumber(nums: number[]): number { + let [ans, acc] = [0, 0]; + + for (const x of nums) { + ans ^= x & ~acc; + acc ^= x & ~ans; + } + + return ans; +} diff --git a/solution/0100-0199/0146.LRU Cache/README.md b/solution/0100-0199/0146.LRU Cache/README.md index ce93f6c338ef..7bb35b178741 100644 --- a/solution/0100-0199/0146.LRU Cache/README.md +++ b/solution/0100-0199/0146.LRU Cache/README.md @@ -87,7 +87,7 @@ lRUCache.get(4); // 返回 4 当插入一个节点时,如果节点存在,我们将其从原来的位置删除,并重新插入到链表头部。如果不存在,我们首先检查缓存是否已满,如果已满,则删除链表尾部的节点,将新的节点插入链表头部。 -时间复杂度 $O(1)$,空间复杂度 $O(\text{capacity})$。 +时间复杂度 $O(1)$,空间复杂度 $O(\textit{capacity})$。 diff --git a/solution/0100-0199/0146.LRU Cache/README_EN.md b/solution/0100-0199/0146.LRU Cache/README_EN.md index 719886f5ead4..c3dbdaea5a85 100644 --- a/solution/0100-0199/0146.LRU Cache/README_EN.md +++ b/solution/0100-0199/0146.LRU Cache/README_EN.md @@ -81,7 +81,7 @@ When accessing a node, if the node exists, we delete it from its original positi When inserting a node, if the node exists, we delete it from its original position and reinsert it at the head of the list. If it does not exist, we first check if the cache is full. If it is full, we delete the node at the tail of the list and insert the new node at the head of the list. -The time complexity is $O(1)$, and the space complexity is $O(\text{capacity})$. +The time complexity is $O(1)$, and the space complexity is $O(\textit{capacity})$. diff --git a/solution/0100-0199/0147.Insertion Sort List/README.md b/solution/0100-0199/0147.Insertion Sort List/README.md index f70899b2e4c3..5f9c2b84a6d0 100644 --- a/solution/0100-0199/0147.Insertion Sort List/README.md +++ b/solution/0100-0199/0147.Insertion Sort List/README.md @@ -31,13 +31,13 @@ tags:

    对链表进行插入排序。

    -

    +

     

    示例 1:

    -

    +

     输入: head = [4,2,1,3]
    @@ -45,7 +45,7 @@ tags:
     
     

    示例 2:

    -

    +

     输入: head = [-1,5,3,4,0]
    diff --git a/solution/0100-0199/0147.Insertion Sort List/images/1724130387-qxfMwx-Insertion-sort-example-300px.gif b/solution/0100-0199/0147.Insertion Sort List/images/1724130387-qxfMwx-Insertion-sort-example-300px.gif
    new file mode 100644
    index 000000000000..96c1b12d5cc8
    Binary files /dev/null and b/solution/0100-0199/0147.Insertion Sort List/images/1724130387-qxfMwx-Insertion-sort-example-300px.gif differ
    diff --git a/solution/0100-0199/0147.Insertion Sort List/images/1724130414-QbPAjl-image.png b/solution/0100-0199/0147.Insertion Sort List/images/1724130414-QbPAjl-image.png
    new file mode 100644
    index 000000000000..7b4b401c0539
    Binary files /dev/null and b/solution/0100-0199/0147.Insertion Sort List/images/1724130414-QbPAjl-image.png differ
    diff --git a/solution/0100-0199/0147.Insertion Sort List/images/1724130432-zoOvdI-image.png b/solution/0100-0199/0147.Insertion Sort List/images/1724130432-zoOvdI-image.png
    new file mode 100644
    index 000000000000..af28294b1e9d
    Binary files /dev/null and b/solution/0100-0199/0147.Insertion Sort List/images/1724130432-zoOvdI-image.png differ
    diff --git a/solution/0100-0199/0191.Number of 1 Bits/README_EN.md b/solution/0100-0199/0191.Number of 1 Bits/README_EN.md
    index 72cc09656abc..42fc428aab19 100644
    --- a/solution/0100-0199/0191.Number of 1 Bits/README_EN.md	
    +++ b/solution/0100-0199/0191.Number of 1 Bits/README_EN.md	
    @@ -60,7 +60,7 @@ tags:
     

    Constraints:

      -
    • 1 <= n <= 231 - 1
    • +
    • 1 <= n <= 231 - 1

     

    diff --git a/solution/0100-0199/0192.Word Frequency/README.md b/solution/0100-0199/0192.Word Frequency/README.md index b73e14dcc749..4c783786ef02 100644 --- a/solution/0100-0199/0192.Word Frequency/README.md +++ b/solution/0100-0199/0192.Word Frequency/README.md @@ -1,13 +1,13 @@ - - --- - comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0100-0199/0192.Word%20Frequency/README.md - +tags: + - Shell --- + + # [192. 统计词频](https://leetcode.cn/problems/word-frequency) [English Version](/solution/0100-0199/0192.Word%20Frequency/README_EN.md) diff --git a/solution/0100-0199/0193.Valid Phone Numbers/README.md b/solution/0100-0199/0193.Valid Phone Numbers/README.md index 819f8d240f5e..f9800080c44d 100644 --- a/solution/0100-0199/0193.Valid Phone Numbers/README.md +++ b/solution/0100-0199/0193.Valid Phone Numbers/README.md @@ -1,13 +1,13 @@ - - --- - comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0100-0199/0193.Valid%20Phone%20Numbers/README.md - +tags: + - Shell --- + + # [193. 有效电话号码](https://leetcode.cn/problems/valid-phone-numbers) [English Version](/solution/0100-0199/0193.Valid%20Phone%20Numbers/README_EN.md) diff --git a/solution/0100-0199/0194.Transpose File/README.md b/solution/0100-0199/0194.Transpose File/README.md index 90293ccffbeb..1f9b12cb1ccd 100644 --- a/solution/0100-0199/0194.Transpose File/README.md +++ b/solution/0100-0199/0194.Transpose File/README.md @@ -1,13 +1,13 @@ - - --- - comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0100-0199/0194.Transpose%20File/README.md - +tags: + - Shell --- + + # [194. 转置文件](https://leetcode.cn/problems/transpose-file) [English Version](/solution/0100-0199/0194.Transpose%20File/README_EN.md) diff --git a/solution/0100-0199/0195.Tenth Line/README.md b/solution/0100-0199/0195.Tenth Line/README.md index 54d3accff972..82a57ae3d8d9 100644 --- a/solution/0100-0199/0195.Tenth Line/README.md +++ b/solution/0100-0199/0195.Tenth Line/README.md @@ -1,13 +1,13 @@ - - --- - comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0100-0199/0195.Tenth%20Line/README.md - +tags: + - Shell --- + + # [195. 第十行](https://leetcode.cn/problems/tenth-line) [English Version](/solution/0100-0199/0195.Tenth%20Line/README_EN.md) diff --git a/solution/0200-0299/0208.Implement Trie (Prefix Tree)/README.md b/solution/0200-0299/0208.Implement Trie (Prefix Tree)/README.md index 76481c3da592..76c12ffdbb11 100644 --- a/solution/0200-0299/0208.Implement Trie (Prefix Tree)/README.md +++ b/solution/0200-0299/0208.Implement Trie (Prefix Tree)/README.md @@ -19,7 +19,7 @@ tags: -

    Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

    +

    Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。

    请你实现 Trie 类:

    @@ -27,10 +27,10 @@ tags:
  • Trie() 初始化前缀树对象。
  • void insert(String word) 向前缀树中插入字符串 word
  • boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false
  • -
  • boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false
  • +
  • boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false
  • -

     

    +

     

    示例:

    @@ -51,12 +51,12 @@ trie.insert("app"); trie.search("app"); // 返回 True
    -

     

    +

     

    提示:

      -
    • 1 <= word.length, prefix.length <= 2000
    • +
    • 1 <= word.length, prefix.length <= 2000
    • wordprefix 仅由小写英文字母组成
    • insertsearchstartsWith 调用次数 总计 不超过 3 * 104
    diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md b/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md index 9b23bf83a977..80f8c5d01219 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/README.md @@ -266,13 +266,15 @@ public class Solution { ### 方法二:双指针 -我们可以使用双指针 $j$ 和 $i$ 维护一个窗口,其中窗口中的所有元素之和小于 $target$。初始时 $j = 0$,答案 $ans = n + 1$,其中 $n$ 为数组 $nums$ 的长度。 +我们注意到,数组 $\textit{nums}$ 中的元素均为正整数,我们可以考虑使用双指针来维护一个滑动窗口。 -接下来,指针 $i$ 从 $0$ 开始向右移动,每次移动一步,我们将指针 $i$ 对应的元素加入窗口,同时更新窗口中元素之和。如果窗口中元素之和大于等于 $target$,说明当前子数组满足条件,我们可以更新答案,即 $ans = \min(ans, i - j + 1)$。然后我们不断地从窗口中移除元素 $nums[j]$,直到窗口中元素之和小于 $target$,然后重复上述过程。 +具体地,我们定义两个指针 $\textit{l}$ 和 $\textit{r}$ 分别表示滑动窗口的左边界和右边界,用一个变量 $\textit{s}$ 代表滑动窗口中的元素和。 -最后,如果 $ans \leq n$,则说明存在满足条件的子数组,返回 $ans$,否则返回 $0$。 +在每一步操作中,我们移动右指针 $\textit{r}$,使得滑动窗口中加入一个元素,如果此时 $\textit{s} \ge \textit{target}$,我们就更新最小长度 $\textit{ans} = \min(\textit{ans}, \textit{r} - \textit{l} + 1$,并将左指针 $\textit{l}$ 循环向右移动,直至有 $\textit{s} < \textit{target}$。 + +最后,如果最小长度 $\textit{ans}$ 仍为初始值,我们就返回 $0$,否则返回 $\textit{ans}$。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 @@ -281,16 +283,15 @@ public class Solution { ```python class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: - n = len(nums) - ans = n + 1 - s = j = 0 - for i, x in enumerate(nums): + l = s = 0 + ans = inf + for r, x in enumerate(nums): s += x - while j < n and s >= target: - ans = min(ans, i - j + 1) - s -= nums[j] - j += 1 - return ans if ans <= n else 0 + while s >= target: + ans = min(ans, r - l + 1) + s -= nums[l] + l += 1 + return 0 if ans == inf else ans ``` #### Java @@ -298,17 +299,17 @@ class Solution: ```java class Solution { public int minSubArrayLen(int target, int[] nums) { - int n = nums.length; + int l = 0, n = nums.length; long s = 0; int ans = n + 1; - for (int i = 0, j = 0; i < n; ++i) { - s += nums[i]; - while (j < n && s >= target) { - ans = Math.min(ans, i - j + 1); - s -= nums[j++]; + for (int r = 0; r < n; ++r) { + s += nums[r]; + while (s >= target) { + ans = Math.min(ans, r - l + 1); + s -= nums[l++]; } } - return ans <= n ? ans : 0; + return ans > n ? 0 : ans; } } ``` @@ -319,17 +320,17 @@ class Solution { class Solution { public: int minSubArrayLen(int target, vector& nums) { - int n = nums.size(); + int l = 0, n = nums.size(); long long s = 0; int ans = n + 1; - for (int i = 0, j = 0; i < n; ++i) { - s += nums[i]; - while (j < n && s >= target) { - ans = min(ans, i - j + 1); - s -= nums[j++]; + for (int r = 0; r < n; ++r) { + s += nums[r]; + while (s >= target) { + ans = min(ans, r - l + 1); + s -= nums[l++]; } } - return ans == n + 1 ? 0 : ans; + return ans > n ? 0 : ans; } }; ``` @@ -338,18 +339,17 @@ public: ```go func minSubArrayLen(target int, nums []int) int { - n := len(nums) - s := 0 - ans := n + 1 - for i, j := 0, 0; i < n; i++ { - s += nums[i] + l, n := 0, len(nums) + s, ans := 0, n+1 + for r, x := range nums { + s += x for s >= target { - ans = min(ans, i-j+1) - s -= nums[j] - j++ + ans = min(ans, r-l+1) + s -= nums[l] + l++ } } - if ans == n+1 { + if ans > n { return 0 } return ans @@ -361,16 +361,15 @@ func minSubArrayLen(target int, nums []int) int { ```ts function minSubArrayLen(target: number, nums: number[]): number { const n = nums.length; - let s = 0; - let ans = n + 1; - for (let i = 0, j = 0; i < n; ++i) { - s += nums[i]; + let [s, ans] = [0, n + 1]; + for (let l = 0, r = 0; r < n; ++r) { + s += nums[r]; while (s >= target) { - ans = Math.min(ans, i - j + 1); - s -= nums[j++]; + ans = Math.min(ans, r - l + 1); + s -= nums[l++]; } } - return ans === n + 1 ? 0 : ans; + return ans > n ? 0 : ans; } ``` diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md b/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md index f540fa51066b..404a6cdd43a9 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/README_EN.md @@ -272,16 +272,15 @@ The time complexity is $O(n)$, and the space complexity is $O(1)$. Here, $n$ is ```python class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: - n = len(nums) - ans = n + 1 - s = j = 0 - for i, x in enumerate(nums): + l = s = 0 + ans = inf + for r, x in enumerate(nums): s += x - while j < n and s >= target: - ans = min(ans, i - j + 1) - s -= nums[j] - j += 1 - return ans if ans <= n else 0 + while s >= target: + ans = min(ans, r - l + 1) + s -= nums[l] + l += 1 + return 0 if ans == inf else ans ``` #### Java @@ -289,17 +288,17 @@ class Solution: ```java class Solution { public int minSubArrayLen(int target, int[] nums) { - int n = nums.length; + int l = 0, n = nums.length; long s = 0; int ans = n + 1; - for (int i = 0, j = 0; i < n; ++i) { - s += nums[i]; - while (j < n && s >= target) { - ans = Math.min(ans, i - j + 1); - s -= nums[j++]; + for (int r = 0; r < n; ++r) { + s += nums[r]; + while (s >= target) { + ans = Math.min(ans, r - l + 1); + s -= nums[l++]; } } - return ans <= n ? ans : 0; + return ans > n ? 0 : ans; } } ``` @@ -310,17 +309,17 @@ class Solution { class Solution { public: int minSubArrayLen(int target, vector& nums) { - int n = nums.size(); + int l = 0, n = nums.size(); long long s = 0; int ans = n + 1; - for (int i = 0, j = 0; i < n; ++i) { - s += nums[i]; - while (j < n && s >= target) { - ans = min(ans, i - j + 1); - s -= nums[j++]; + for (int r = 0; r < n; ++r) { + s += nums[r]; + while (s >= target) { + ans = min(ans, r - l + 1); + s -= nums[l++]; } } - return ans == n + 1 ? 0 : ans; + return ans > n ? 0 : ans; } }; ``` @@ -329,18 +328,17 @@ public: ```go func minSubArrayLen(target int, nums []int) int { - n := len(nums) - s := 0 - ans := n + 1 - for i, j := 0, 0; i < n; i++ { - s += nums[i] + l, n := 0, len(nums) + s, ans := 0, n+1 + for r, x := range nums { + s += x for s >= target { - ans = min(ans, i-j+1) - s -= nums[j] - j++ + ans = min(ans, r-l+1) + s -= nums[l] + l++ } } - if ans == n+1 { + if ans > n { return 0 } return ans @@ -352,16 +350,15 @@ func minSubArrayLen(target int, nums []int) int { ```ts function minSubArrayLen(target: number, nums: number[]): number { const n = nums.length; - let s = 0; - let ans = n + 1; - for (let i = 0, j = 0; i < n; ++i) { - s += nums[i]; + let [s, ans] = [0, n + 1]; + for (let l = 0, r = 0; r < n; ++r) { + s += nums[r]; while (s >= target) { - ans = Math.min(ans, i - j + 1); - s -= nums[j++]; + ans = Math.min(ans, r - l + 1); + s -= nums[l++]; } } - return ans === n + 1 ? 0 : ans; + return ans > n ? 0 : ans; } ``` diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.cpp b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.cpp index b6d57f2aaabd..cc31cd24044b 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.cpp +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.cpp @@ -1,16 +1,16 @@ class Solution { public: int minSubArrayLen(int target, vector& nums) { - int n = nums.size(); + int l = 0, n = nums.size(); long long s = 0; int ans = n + 1; - for (int i = 0, j = 0; i < n; ++i) { - s += nums[i]; - while (j < n && s >= target) { - ans = min(ans, i - j + 1); - s -= nums[j++]; + for (int r = 0; r < n; ++r) { + s += nums[r]; + while (s >= target) { + ans = min(ans, r - l + 1); + s -= nums[l++]; } } - return ans == n + 1 ? 0 : ans; + return ans > n ? 0 : ans; } -}; \ No newline at end of file +}; diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.go b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.go index 37a23211e974..e3cecbba9dff 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.go +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.go @@ -1,17 +1,16 @@ func minSubArrayLen(target int, nums []int) int { - n := len(nums) - s := 0 - ans := n + 1 - for i, j := 0, 0; i < n; i++ { - s += nums[i] + l, n := 0, len(nums) + s, ans := 0, n+1 + for r, x := range nums { + s += x for s >= target { - ans = min(ans, i-j+1) - s -= nums[j] - j++ + ans = min(ans, r-l+1) + s -= nums[l] + l++ } } - if ans == n+1 { + if ans > n { return 0 } return ans -} \ No newline at end of file +} diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.java b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.java index 11b6a8155908..d922a1fb4b6c 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.java +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.java @@ -1,15 +1,15 @@ class Solution { public int minSubArrayLen(int target, int[] nums) { - int n = nums.length; + int l = 0, n = nums.length; long s = 0; int ans = n + 1; - for (int i = 0, j = 0; i < n; ++i) { - s += nums[i]; - while (j < n && s >= target) { - ans = Math.min(ans, i - j + 1); - s -= nums[j++]; + for (int r = 0; r < n; ++r) { + s += nums[r]; + while (s >= target) { + ans = Math.min(ans, r - l + 1); + s -= nums[l++]; } } - return ans <= n ? ans : 0; + return ans > n ? 0 : ans; } -} \ No newline at end of file +} diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.py b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.py index 6dcbc2480b59..38e471713800 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.py +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.py @@ -1,12 +1,11 @@ class Solution: def minSubArrayLen(self, target: int, nums: List[int]) -> int: - n = len(nums) - ans = n + 1 - s = j = 0 - for i, x in enumerate(nums): + l = s = 0 + ans = inf + for r, x in enumerate(nums): s += x - while j < n and s >= target: - ans = min(ans, i - j + 1) - s -= nums[j] - j += 1 - return ans if ans <= n else 0 + while s >= target: + ans = min(ans, r - l + 1) + s -= nums[l] + l += 1 + return 0 if ans == inf else ans diff --git a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.ts b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.ts index ef54870682bf..66fd4ae9b601 100644 --- a/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.ts +++ b/solution/0200-0299/0209.Minimum Size Subarray Sum/Solution2.ts @@ -1,13 +1,12 @@ function minSubArrayLen(target: number, nums: number[]): number { const n = nums.length; - let s = 0; - let ans = n + 1; - for (let i = 0, j = 0; i < n; ++i) { - s += nums[i]; + let [s, ans] = [0, n + 1]; + for (let l = 0, r = 0; r < n; ++r) { + s += nums[r]; while (s >= target) { - ans = Math.min(ans, i - j + 1); - s -= nums[j++]; + ans = Math.min(ans, r - l + 1); + s -= nums[l++]; } } - return ans === n + 1 ? 0 : ans; + return ans > n ? 0 : ans; } diff --git a/solution/0200-0299/0214.Shortest Palindrome/README.md b/solution/0200-0299/0214.Shortest Palindrome/README.md index d79f1e47c941..ffd8c38adc83 100644 --- a/solution/0200-0299/0214.Shortest Palindrome/README.md +++ b/solution/0200-0299/0214.Shortest Palindrome/README.md @@ -201,43 +201,193 @@ impl Solution { #### C# ```cs -// https://leetcode.com/problems/shortest-palindrome/ - -using System.Text; - -public partial class Solution -{ - public string ShortestPalindrome(string s) - { - for (var i = s.Length - 1; i >= 0; --i) - { - var k = i; - var j = 0; - while (j < k) - { - if (s[j] == s[k]) - { - ++j; - --k; - } - else - { - break; - } +public class Solution { + public string ShortestPalindrome(string s) { + int baseValue = 131; + int mul = 1; + int mod = (int)1e9 + 7; + int prefix = 0, suffix = 0; + int idx = 0; + int n = s.Length; + + for (int i = 0; i < n; ++i) { + int t = s[i] - 'a' + 1; + prefix = (int)(((long)prefix * baseValue + t) % mod); + suffix = (int)((suffix + (long)t * mul) % mod); + mul = (int)(((long)mul * baseValue) % mod); + if (prefix == suffix) { + idx = i + 1; } - if (j >= k) - { - var sb = new StringBuilder(s.Length * 2 - i - 1); - for (var l = s.Length - 1; l >= i + 1; --l) - { - sb.Append(s[l]); - } - sb.Append(s); - return sb.ToString(); + } + + if (idx == n) { + return s; + } + + return new string(s.Substring(idx).Reverse().ToArray()) + s; + } +} +``` + + + + + + + +### 方法二:KMP 算法 + +根据题目描述,我们需要将字符串 $s$ 反转,得到字符串 $\textit{rev}$,然后求出字符串 $rev$ 的后缀与字符串 $s$ 的前缀的最长公共部分。我们可以使用 KMP 算法,将字符串 $s$ 与字符串 $rev$ 连接起来,求出其最长前缀与最长后缀的最长公共部分。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def shortestPalindrome(self, s: str) -> str: + t = s + "#" + s[::-1] + "$" + n = len(t) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if t[i - 1] == t[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s[::-1][: -next[-1]] + s +``` + +#### Java + +```java +class Solution { + public String shortestPalindrome(String s) { + String rev = new StringBuilder(s).reverse().toString(); + char[] t = (s + "#" + rev + "$").toCharArray(); + int n = t.length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return rev.substring(0, s.length() - next[n - 1]) + s; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string shortestPalindrome(string s) { + string t = s + "#" + string(s.rbegin(), s.rend()) + "$"; + int n = t.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; } } + return string(s.rbegin(), s.rbegin() + s.size() - next[n - 1]) + s; + } +}; +``` + +#### Go - return string.Empty; +```go +func shortestPalindrome(s string) string { + t := s + "#" + reverse(s) + "$" + n := len(t) + next := make([]int, n) + next[0] = -1 + for i, j := 2, 0; i < n; { + if t[i-1] == t[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return reverse(s)[:len(s)-next[n-1]] + s +} + +func reverse(s string) string { + t := []byte(s) + for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 { + t[i], t[j] = t[j], t[i] + } + return string(t) +} +``` + +#### TypeScript + +```ts +function shortestPalindrome(s: string): string { + const rev = s.split('').reverse().join(''); + const t = s + '#' + rev + '$'; + const n = t.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (t[i - 1] === t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return rev.slice(0, -next[n - 1]) + s; +} +``` + +#### C# + +```cs +public class Solution { + public string ShortestPalindrome(string s) { + char[] t = (s + "#" + new string(s.Reverse().ToArray()) + "$").ToCharArray(); + int n = t.Length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return new string(s.Substring(next[n - 1]).Reverse().ToArray()).Substring(0, s.Length - next[n - 1]) + s; } } ``` diff --git a/solution/0200-0299/0214.Shortest Palindrome/README_EN.md b/solution/0200-0299/0214.Shortest Palindrome/README_EN.md index eb80912e1c16..78c948e1285f 100644 --- a/solution/0200-0299/0214.Shortest Palindrome/README_EN.md +++ b/solution/0200-0299/0214.Shortest Palindrome/README_EN.md @@ -182,43 +182,193 @@ impl Solution { #### C# ```cs -// https://leetcode.com/problems/shortest-palindrome/ - -using System.Text; - -public partial class Solution -{ - public string ShortestPalindrome(string s) - { - for (var i = s.Length - 1; i >= 0; --i) - { - var k = i; - var j = 0; - while (j < k) - { - if (s[j] == s[k]) - { - ++j; - --k; - } - else - { - break; - } +public class Solution { + public string ShortestPalindrome(string s) { + int baseValue = 131; + int mul = 1; + int mod = (int)1e9 + 7; + int prefix = 0, suffix = 0; + int idx = 0; + int n = s.Length; + + for (int i = 0; i < n; ++i) { + int t = s[i] - 'a' + 1; + prefix = (int)(((long)prefix * baseValue + t) % mod); + suffix = (int)((suffix + (long)t * mul) % mod); + mul = (int)(((long)mul * baseValue) % mod); + if (prefix == suffix) { + idx = i + 1; } - if (j >= k) - { - var sb = new StringBuilder(s.Length * 2 - i - 1); - for (var l = s.Length - 1; l >= i + 1; --l) - { - sb.Append(s[l]); - } - sb.Append(s); - return sb.ToString(); + } + + if (idx == n) { + return s; + } + + return new string(s.Substring(idx).Reverse().ToArray()) + s; + } +} +``` + + + + + + + +### Solution 2: KMP Algorithm + +According to the problem description, we need to reverse the string $s$ to obtain the string $\textit{rev}$, and then find the longest common part of the suffix of the string $\textit{rev}$ and the prefix of the string $s$. We can use the KMP algorithm to concatenate the string $s$ and the string $\textit{rev}$ and find the longest common part of the longest prefix and the longest suffix. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $s$. + + + +#### Python3 + +```python +class Solution: + def shortestPalindrome(self, s: str) -> str: + t = s + "#" + s[::-1] + "$" + n = len(t) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if t[i - 1] == t[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s[::-1][: -next[-1]] + s +``` + +#### Java + +```java +class Solution { + public String shortestPalindrome(String s) { + String rev = new StringBuilder(s).reverse().toString(); + char[] t = (s + "#" + rev + "$").toCharArray(); + int n = t.length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return rev.substring(0, s.length() - next[n - 1]) + s; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string shortestPalindrome(string s) { + string t = s + "#" + string(s.rbegin(), s.rend()) + "$"; + int n = t.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; } } + return string(s.rbegin(), s.rbegin() + s.size() - next[n - 1]) + s; + } +}; +``` + +#### Go - return string.Empty; +```go +func shortestPalindrome(s string) string { + t := s + "#" + reverse(s) + "$" + n := len(t) + next := make([]int, n) + next[0] = -1 + for i, j := 2, 0; i < n; { + if t[i-1] == t[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return reverse(s)[:len(s)-next[n-1]] + s +} + +func reverse(s string) string { + t := []byte(s) + for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 { + t[i], t[j] = t[j], t[i] + } + return string(t) +} +``` + +#### TypeScript + +```ts +function shortestPalindrome(s: string): string { + const rev = s.split('').reverse().join(''); + const t = s + '#' + rev + '$'; + const n = t.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (t[i - 1] === t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return rev.slice(0, -next[n - 1]) + s; +} +``` + +#### C# + +```cs +public class Solution { + public string ShortestPalindrome(string s) { + char[] t = (s + "#" + new string(s.Reverse().ToArray()) + "$").ToCharArray(); + int n = t.Length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return new string(s.Substring(next[n - 1]).Reverse().ToArray()).Substring(0, s.Length - next[n - 1]) + s; } } ``` diff --git a/solution/0200-0299/0214.Shortest Palindrome/Solution.cs b/solution/0200-0299/0214.Shortest Palindrome/Solution.cs index c33ad4ae5091..d1b54e89b6a8 100644 --- a/solution/0200-0299/0214.Shortest Palindrome/Solution.cs +++ b/solution/0200-0299/0214.Shortest Palindrome/Solution.cs @@ -1,39 +1,26 @@ -// https://leetcode.com/problems/shortest-palindrome/ +public class Solution { + public string ShortestPalindrome(string s) { + int baseValue = 131; + int mul = 1; + int mod = (int)1e9 + 7; + int prefix = 0, suffix = 0; + int idx = 0; + int n = s.Length; -using System.Text; - -public partial class Solution -{ - public string ShortestPalindrome(string s) - { - for (var i = s.Length - 1; i >= 0; --i) - { - var k = i; - var j = 0; - while (j < k) - { - if (s[j] == s[k]) - { - ++j; - --k; - } - else - { - break; - } - } - if (j >= k) - { - var sb = new StringBuilder(s.Length * 2 - i - 1); - for (var l = s.Length - 1; l >= i + 1; --l) - { - sb.Append(s[l]); - } - sb.Append(s); - return sb.ToString(); + for (int i = 0; i < n; ++i) { + int t = s[i] - 'a' + 1; + prefix = (int)(((long)prefix * baseValue + t) % mod); + suffix = (int)((suffix + (long)t * mul) % mod); + mul = (int)(((long)mul * baseValue) % mod); + if (prefix == suffix) { + idx = i + 1; } } - return string.Empty; + if (idx == n) { + return s; + } + + return new string(s.Substring(idx).Reverse().ToArray()) + s; } -} \ No newline at end of file +} diff --git a/solution/0200-0299/0214.Shortest Palindrome/Solution2.cpp b/solution/0200-0299/0214.Shortest Palindrome/Solution2.cpp new file mode 100644 index 000000000000..6956b5693fc4 --- /dev/null +++ b/solution/0200-0299/0214.Shortest Palindrome/Solution2.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + string shortestPalindrome(string s) { + string t = s + "#" + string(s.rbegin(), s.rend()) + "$"; + int n = t.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return string(s.rbegin(), s.rbegin() + s.size() - next[n - 1]) + s; + } +}; diff --git a/solution/0200-0299/0214.Shortest Palindrome/Solution2.cs b/solution/0200-0299/0214.Shortest Palindrome/Solution2.cs new file mode 100644 index 000000000000..067a74e88ad3 --- /dev/null +++ b/solution/0200-0299/0214.Shortest Palindrome/Solution2.cs @@ -0,0 +1,18 @@ +public class Solution { + public string ShortestPalindrome(string s) { + char[] t = (s + "#" + new string(s.Reverse().ToArray()) + "$").ToCharArray(); + int n = t.Length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return new string(s.Substring(next[n - 1]).Reverse().ToArray()).Substring(0, s.Length - next[n - 1]) + s; + } +} diff --git a/solution/0200-0299/0214.Shortest Palindrome/Solution2.go b/solution/0200-0299/0214.Shortest Palindrome/Solution2.go new file mode 100644 index 000000000000..a254925e173c --- /dev/null +++ b/solution/0200-0299/0214.Shortest Palindrome/Solution2.go @@ -0,0 +1,27 @@ +func shortestPalindrome(s string) string { + t := s + "#" + reverse(s) + "$" + n := len(t) + next := make([]int, n) + next[0] = -1 + for i, j := 2, 0; i < n; { + if t[i-1] == t[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return reverse(s)[:len(s)-next[n-1]] + s +} + +func reverse(s string) string { + t := []byte(s) + for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 { + t[i], t[j] = t[j], t[i] + } + return string(t) +} diff --git a/solution/0200-0299/0214.Shortest Palindrome/Solution2.java b/solution/0200-0299/0214.Shortest Palindrome/Solution2.java new file mode 100644 index 000000000000..2e92823c7796 --- /dev/null +++ b/solution/0200-0299/0214.Shortest Palindrome/Solution2.java @@ -0,0 +1,19 @@ +class Solution { + public String shortestPalindrome(String s) { + String rev = new StringBuilder(s).reverse().toString(); + char[] t = (s + "#" + rev + "$").toCharArray(); + int n = t.length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (t[i - 1] == t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return rev.substring(0, s.length() - next[n - 1]) + s; + } +} diff --git a/solution/0200-0299/0214.Shortest Palindrome/Solution2.py b/solution/0200-0299/0214.Shortest Palindrome/Solution2.py new file mode 100644 index 000000000000..7d538100384a --- /dev/null +++ b/solution/0200-0299/0214.Shortest Palindrome/Solution2.py @@ -0,0 +1,18 @@ +class Solution: + def shortestPalindrome(self, s: str) -> str: + t = s + "#" + s[::-1] + "$" + n = len(t) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if t[i - 1] == t[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s[::-1][: -next[-1]] + s diff --git a/solution/0200-0299/0214.Shortest Palindrome/Solution2.ts b/solution/0200-0299/0214.Shortest Palindrome/Solution2.ts new file mode 100644 index 000000000000..ba0dba154f53 --- /dev/null +++ b/solution/0200-0299/0214.Shortest Palindrome/Solution2.ts @@ -0,0 +1,17 @@ +function shortestPalindrome(s: string): string { + const rev = s.split('').reverse().join(''); + const t = s + '#' + rev + '$'; + const n = t.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (t[i - 1] === t[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return rev.slice(0, -next[n - 1]) + s; +} diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md index c38a44c96519..9e8137ed7f22 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md @@ -60,7 +60,7 @@ tags: 快速选择算法是一种在未排序的数组中查找第 `k` 个最大元素或最小元素的算法。它的基本思想是每次选择一个基准元素,将数组分为两部分,一部分的元素都比基准元素小,另一部分的元素都比基准元素大,然后根据基准元素的位置,决定继续在左边还是右边查找,直到找到第 `k` 个最大元素。 -时间复杂度 $O(n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -283,9 +283,9 @@ impl Solution { ### 方法二:优先队列(小根堆) -我们可以维护一个大小为 $k$ 的小根堆 $\text{minQ}$,然后遍历数组 $\text{nums}$,将数组中的元素依次加入到小根堆中,当小根堆的大小超过 $k$ 时,我们将堆顶元素弹出,这样最终小根堆中的 $k$ 个元素就是数组中的 $k$ 个最大元素,堆顶元素就是第 $k$ 个最大元素。 +我们可以维护一个大小为 $k$ 的小根堆 $\textit{minQ}$,然后遍历数组 $\textit{nums}$,将数组中的元素依次加入到小根堆中,当小根堆的大小超过 $k$ 时,我们将堆顶元素弹出,这样最终小根堆中的 $k$ 个元素就是数组中的 $k$ 个最大元素,堆顶元素就是第 $k$ 个最大元素。 -时间复杂度 $O(n\log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n\log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -400,9 +400,9 @@ impl Solution { ### 方法三:计数排序 -我们可以使用计数排序的思想,统计数组 $\text{nums}$ 中每个元素出现的次数,记录在哈希表 $\text{cnt}$ 中,然后从大到小遍历元素 $i$,每次减去出现的次数 $\text{cnt}[i]$,直到 $k$ 小于等于 $0$,此时的元素 $i$ 就是数组中的第 $k$ 个最大元素。 +我们可以使用计数排序的思想,统计数组 $\textit{nums}$ 中每个元素出现的次数,记录在哈希表 $\textit{cnt}$ 中,然后从大到小遍历元素 $i$,每次减去出现的次数 $\textit{cnt}[i]$,直到 $k$ 小于等于 $0$,此时的元素 $i$ 就是数组中的第 $k$ 个最大元素。 -时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{nums}$ 的长度,而 $m$ 为数组 $\text{nums}$ 中元素的最大值。 +时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $m$ 为数组 $\textit{nums}$ 中元素的最大值。 diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md index 9eecbd327736..19297f374806 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md @@ -52,7 +52,7 @@ tags: Quick Select is an algorithm for finding the $k^{th}$ largest or smallest element in an unsorted array. Its basic idea is to select a pivot element each time, dividing the array into two parts: one part contains elements smaller than the pivot, and the other part contains elements larger than the pivot. Then, based on the position of the pivot, it decides whether to continue the search on the left or right side until the $k^{th}$ largest element is found. -The time complexity is $O(n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\text{nums}$. +The time complexity is $O(n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -275,9 +275,9 @@ impl Solution { ### Solution 2: Priority Queue (Min Heap) -We can maintain a min heap $\text{minQ}$ of size $k$, and then iterate through the array $\text{nums}$, adding each element to the min heap. When the size of the min heap exceeds $k$, we pop the top element of the heap. This way, the final $k$ elements in the min heap are the $k$ largest elements in the array, and the top element of the heap is the $k^{th}$ largest element. +We can maintain a min heap $\textit{minQ}$ of size $k$, and then iterate through the array $\textit{nums}$, adding each element to the min heap. When the size of the min heap exceeds $k$, we pop the top element of the heap. This way, the final $k$ elements in the min heap are the $k$ largest elements in the array, and the top element of the heap is the $k^{th}$ largest element. -The time complexity is $O(n\log k)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array $\text{nums}$. +The time complexity is $O(n\log k)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -392,9 +392,9 @@ impl Solution { ### Solution 3: Counting Sort -We can use the idea of counting sort, counting the occurrence of each element in the array $\text{nums}$ and recording it in a hash table $\text{cnt}$. Then, we iterate over the elements $i$ from largest to smallest, subtracting the occurrence count $\text{cnt}[i]$ each time, until $k$ is less than or equal to $0$. At this point, the element $i$ is the $k^{th}$ largest element in the array. +We can use the idea of counting sort, counting the occurrence of each element in the array $\textit{nums}$ and recording it in a hash table $\textit{cnt}$. Then, we iterate over the elements $i$ from largest to smallest, subtracting the occurrence count $\textit{cnt}[i]$ each time, until $k$ is less than or equal to $0$. At this point, the element $i$ is the $k^{th}$ largest element in the array. -The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\text{nums}$, and $m$ is the maximum value among the elements in $\text{nums}$. +The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$, and $m$ is the maximum value among the elements in $\textit{nums}$. diff --git a/solution/0200-0299/0221.Maximal Square/README.md b/solution/0200-0299/0221.Maximal Square/README.md index 908e41eea3d3..808e67027d02 100644 --- a/solution/0200-0299/0221.Maximal Square/README.md +++ b/solution/0200-0299/0221.Maximal Square/README.md @@ -69,8 +69,8 @@ tags: $$ dp[i + 1][j + 1] = \begin{cases} -0 & \text{if } matrix[i][j] = '0' \\ -\min(dp[i][j], dp[i][j + 1], dp[i + 1][j]) + 1 & \text{if } matrix[i][j] = '1' +0 & \textit{if } matrix[i][j] = '0' \\ +\min(dp[i][j], dp[i][j + 1], dp[i + 1][j]) + 1 & \textit{if } matrix[i][j] = '1' \end{cases} $$ diff --git a/solution/0200-0299/0221.Maximal Square/README_EN.md b/solution/0200-0299/0221.Maximal Square/README_EN.md index 0c7a2f3e0133..26665820aa50 100644 --- a/solution/0200-0299/0221.Maximal Square/README_EN.md +++ b/solution/0200-0299/0221.Maximal Square/README_EN.md @@ -67,8 +67,8 @@ The state transition equation is: $$ dp[i + 1][j + 1] = \begin{cases} -0 & \text{if } matrix[i][j] = '0' \\ -\min(dp[i][j], dp[i][j + 1], dp[i + 1][j]) + 1 & \text{if } matrix[i][j] = '1' +0 & \textit{if } matrix[i][j] = '0' \\ +\min(dp[i][j], dp[i][j + 1], dp[i + 1][j]) + 1 & \textit{if } matrix[i][j] = '1' \end{cases} $$ diff --git a/solution/0200-0299/0230.Kth Smallest Element in a BST/README.md b/solution/0200-0299/0230.Kth Smallest Element in a BST/README.md index 6448cfa693a3..dabb554f1e38 100644 --- a/solution/0200-0299/0230.Kth Smallest Element in a BST/README.md +++ b/solution/0200-0299/0230.Kth Smallest Element in a BST/README.md @@ -11,7 +11,7 @@ tags: -# [230. 二叉搜索树中第K小的元素](https://leetcode.cn/problems/kth-smallest-element-in-a-bst) +# [230. 二叉搜索树中第 K 小的元素](https://leetcode.cn/problems/kth-smallest-element-in-a-bst) [English Version](/solution/0200-0299/0230.Kth%20Smallest%20Element%20in%20a%20BST/README_EN.md) diff --git a/solution/0200-0299/0240.Search a 2D Matrix II/README.md b/solution/0200-0299/0240.Search a 2D Matrix II/README.md index 278faf4bff98..70b13fc1bb89 100644 --- a/solution/0200-0299/0240.Search a 2D Matrix II/README.md +++ b/solution/0200-0299/0240.Search a 2D Matrix II/README.md @@ -239,9 +239,9 @@ public class Solution { 这里我们以左下角作为起始搜索点,往右上方向开始搜索,比较当前元素 `matrix[i][j]`与 `target` 的大小关系: -- 若 $\text{matrix}[i][j] = \text{target}$,说明找到了目标值,直接返回 `true`。 -- 若 $\text{matrix}[i][j] > \text{target}$,说明这一列从当前位置开始往上的所有元素均大于 `target`,应该让 $i$ 指针往上移动,即 $i \leftarrow i - 1$。 -- 若 $\text{matrix}[i][j] < \text{target}$,说明这一行从当前位置开始往右的所有元素均小于 `target`,应该让 $j$ 指针往右移动,即 $j \leftarrow j + 1$。 +- 若 $\textit{matrix}[i][j] = \textit{target}$,说明找到了目标值,直接返回 `true`。 +- 若 $\textit{matrix}[i][j] > \textit{target}$,说明这一列从当前位置开始往上的所有元素均大于 `target`,应该让 $i$ 指针往上移动,即 $i \leftarrow i - 1$。 +- 若 $\textit{matrix}[i][j] < \textit{target}$,说明这一行从当前位置开始往右的所有元素均小于 `target`,应该让 $j$ 指针往右移动,即 $j \leftarrow j + 1$。 若搜索结束依然找不到 `target`,返回 `false`。 diff --git a/solution/0200-0299/0240.Search a 2D Matrix II/README_EN.md b/solution/0200-0299/0240.Search a 2D Matrix II/README_EN.md index 1f1f8a46be5e..2c2559f1266e 100644 --- a/solution/0200-0299/0240.Search a 2D Matrix II/README_EN.md +++ b/solution/0200-0299/0240.Search a 2D Matrix II/README_EN.md @@ -237,9 +237,9 @@ public class Solution { Here, we start searching from the bottom left corner and move towards the top right direction, comparing the current element `matrix[i][j]` with `target`: -- If $\text{matrix}[i][j] = \text{target}$, it means the target value has been found, and we directly return `true`. -- If $\text{matrix}[i][j] > \text{target}$, it means all elements in this column from the current position upwards are greater than `target`, so we should move the $i$ pointer upwards, i.e., $i \leftarrow i - 1$. -- If $\text{matrix}[i][j] < \text{target}$, it means all elements in this row from the current position to the right are less than `target`, so we should move the $j$ pointer to the right, i.e., $j \leftarrow j + 1$. +- If $\textit{matrix}[i][j] = \textit{target}$, it means the target value has been found, and we directly return `true`. +- If $\textit{matrix}[i][j] > \textit{target}$, it means all elements in this column from the current position upwards are greater than `target`, so we should move the $i$ pointer upwards, i.e., $i \leftarrow i - 1$. +- If $\textit{matrix}[i][j] < \textit{target}$, it means all elements in this row from the current position to the right are less than `target`, so we should move the $j$ pointer to the right, i.e., $j \leftarrow j + 1$. If the search ends and the `target` is still not found, return `false`. diff --git a/solution/0200-0299/0260.Single Number III/README.md b/solution/0200-0299/0260.Single Number III/README.md index c3a3cff649bd..10d058692990 100644 --- a/solution/0200-0299/0260.Single Number III/README.md +++ b/solution/0200-0299/0260.Single Number III/README.md @@ -238,4 +238,48 @@ public class Solution { + + +### 方法二:哈希表 + + + +#### TypeScript + +```ts +function singleNumber(nums: number[]): number[] { + const set = new Set(); + + for (const x of nums) { + if (set.has(x)) set.delete(x); + else set.add(x); + } + + return [...set]; +} +``` + +#### JavaScript + +```js +/** + * @param {number[]} nums + * @return {number[]} + */ +function singleNumber(nums) { + const set = new Set(); + + for (const x of nums) { + if (set.has(x)) set.delete(x); + else set.add(x); + } + + return [...set]; +} +``` + + + + + diff --git a/solution/0200-0299/0260.Single Number III/README_EN.md b/solution/0200-0299/0260.Single Number III/README_EN.md index a5208fc56eca..89e787d9e26c 100644 --- a/solution/0200-0299/0260.Single Number III/README_EN.md +++ b/solution/0200-0299/0260.Single Number III/README_EN.md @@ -236,4 +236,48 @@ public class Solution { + + +### Solution 2: Hash Table + + + +#### TypeScript + +```ts +function singleNumber(nums: number[]): number[] { + const set = new Set(); + + for (const x of nums) { + if (set.has(x)) set.delete(x); + else set.add(x); + } + + return [...set]; +} +``` + +#### JavaScript + +```js +/** + * @param {number[]} nums + * @return {number[]} + */ +function singleNumber(nums) { + const set = new Set(); + + for (const x of nums) { + if (set.has(x)) set.delete(x); + else set.add(x); + } + + return [...set]; +} +``` + + + + + diff --git a/solution/0200-0299/0260.Single Number III/Solution2.js b/solution/0200-0299/0260.Single Number III/Solution2.js new file mode 100644 index 000000000000..a7207c2194bd --- /dev/null +++ b/solution/0200-0299/0260.Single Number III/Solution2.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +function singleNumber(nums) { + const set = new Set(); + + for (const x of nums) { + if (set.has(x)) set.delete(x); + else set.add(x); + } + + return [...set]; +} diff --git a/solution/0200-0299/0260.Single Number III/Solution2.ts b/solution/0200-0299/0260.Single Number III/Solution2.ts new file mode 100644 index 000000000000..6851e0822813 --- /dev/null +++ b/solution/0200-0299/0260.Single Number III/Solution2.ts @@ -0,0 +1,10 @@ +function singleNumber(nums: number[]): number[] { + const set = new Set(); + + for (const x of nums) { + if (set.has(x)) set.delete(x); + else set.add(x); + } + + return [...set]; +} diff --git a/solution/0200-0299/0266.Palindrome Permutation/README.md b/solution/0200-0299/0266.Palindrome Permutation/README.md index b1181c7a2fe3..222068a8d380 100644 --- a/solution/0200-0299/0266.Palindrome Permutation/README.md +++ b/solution/0200-0299/0266.Palindrome Permutation/README.md @@ -58,9 +58,9 @@ tags: -### 方法一:数组 +### 方法一:计数 -创建一个长度为 $26$ 的数组,统计每个字母出现的频率,至多有一个字符出现奇数次数即可。 +如果一个字符串是回文串,那么至多只有一个字符出现奇数次数,其余字符都出现偶数次数。因此我们只需要统计每个字符出现的次数,然后判断是否满足这个条件即可。 时间复杂度 $O(n)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 是字符串的长度,而 $|\Sigma|$ 是字符集的大小,本题中字符集为小写字母,因此 $|\Sigma|=26$。 @@ -131,7 +131,7 @@ func canPermutePalindrome(s string) bool { ```ts function canPermutePalindrome(s: string): boolean { - const cnt: number[] = new Array(26).fill(0); + const cnt: number[] = Array(26).fill(0); for (const c of s) { ++cnt[c.charCodeAt(0) - 97]; } @@ -147,11 +147,11 @@ function canPermutePalindrome(s: string): boolean { * @return {boolean} */ var canPermutePalindrome = function (s) { - const cnt = new Array(26).fill(0); + const cnt = new Map(); for (const c of s) { - ++cnt[c.charCodeAt() - 'a'.charCodeAt()]; + cnt.set(c, (cnt.get(c) || 0) + 1); } - return cnt.filter(c => c % 2 === 1).length < 2; + return [...cnt.values()].filter(v => v % 2 === 1).length < 2; }; ``` diff --git a/solution/0200-0299/0266.Palindrome Permutation/README_EN.md b/solution/0200-0299/0266.Palindrome Permutation/README_EN.md index 927d690bcf32..593d55562d79 100644 --- a/solution/0200-0299/0266.Palindrome Permutation/README_EN.md +++ b/solution/0200-0299/0266.Palindrome Permutation/README_EN.md @@ -56,7 +56,11 @@ tags: -### Solution 1 +### Solution 1: Counting + +If a string is a palindrome, at most one character can appear an odd number of times, while all other characters must appear an even number of times. Therefore, we only need to count the occurrences of each character and then check if this condition is satisfied. + +Time complexity is $O(n)$, and space complexity is $O(|\Sigma|)$. Here, $n$ is the length of the string, and $|\Sigma|$ is the size of the character set. In this problem, the character set consists of lowercase letters, so $|\Sigma|=26$. @@ -125,7 +129,7 @@ func canPermutePalindrome(s string) bool { ```ts function canPermutePalindrome(s: string): boolean { - const cnt: number[] = new Array(26).fill(0); + const cnt: number[] = Array(26).fill(0); for (const c of s) { ++cnt[c.charCodeAt(0) - 97]; } @@ -141,11 +145,11 @@ function canPermutePalindrome(s: string): boolean { * @return {boolean} */ var canPermutePalindrome = function (s) { - const cnt = new Array(26).fill(0); + const cnt = new Map(); for (const c of s) { - ++cnt[c.charCodeAt() - 'a'.charCodeAt()]; + cnt.set(c, (cnt.get(c) || 0) + 1); } - return cnt.filter(c => c % 2 === 1).length < 2; + return [...cnt.values()].filter(v => v % 2 === 1).length < 2; }; ``` diff --git a/solution/0200-0299/0266.Palindrome Permutation/Solution.js b/solution/0200-0299/0266.Palindrome Permutation/Solution.js index 346a9ee9421a..9d3ff25b7e41 100644 --- a/solution/0200-0299/0266.Palindrome Permutation/Solution.js +++ b/solution/0200-0299/0266.Palindrome Permutation/Solution.js @@ -3,9 +3,9 @@ * @return {boolean} */ var canPermutePalindrome = function (s) { - const cnt = new Array(26).fill(0); + const cnt = new Map(); for (const c of s) { - ++cnt[c.charCodeAt() - 'a'.charCodeAt()]; + cnt.set(c, (cnt.get(c) || 0) + 1); } - return cnt.filter(c => c % 2 === 1).length < 2; + return [...cnt.values()].filter(v => v % 2 === 1).length < 2; }; diff --git a/solution/0200-0299/0266.Palindrome Permutation/Solution.ts b/solution/0200-0299/0266.Palindrome Permutation/Solution.ts index 5edeb264d774..5004ae6504ac 100644 --- a/solution/0200-0299/0266.Palindrome Permutation/Solution.ts +++ b/solution/0200-0299/0266.Palindrome Permutation/Solution.ts @@ -1,5 +1,5 @@ function canPermutePalindrome(s: string): boolean { - const cnt: number[] = new Array(26).fill(0); + const cnt: number[] = Array(26).fill(0); for (const c of s) { ++cnt[c.charCodeAt(0) - 97]; } diff --git a/solution/0200-0299/0270.Closest Binary Search Tree Value/README.md b/solution/0200-0299/0270.Closest Binary Search Tree Value/README.md index 38a99a6093a7..8dc6f44ceb1c 100644 --- a/solution/0200-0299/0270.Closest Binary Search Tree Value/README.md +++ b/solution/0200-0299/0270.Closest Binary Search Tree Value/README.md @@ -56,7 +56,7 @@ tags: ### 方法一:递归 -我们定义一个递归函数 $\text{dfs}(node)$,表示从当前节点 $node$ 开始,寻找最接近目标值 $target$ 的节点。我们可以通过比较当前节点的值与目标值的差的绝对值,来更新答案,如果目标值小于当前节点的值,我们就递归地搜索左子树,否则我们递归地搜索右子树。 +我们定义一个递归函数 $\textit{dfs}(node)$,表示从当前节点 $node$ 开始,寻找最接近目标值 $target$ 的节点。我们可以通过比较当前节点的值与目标值的差的绝对值,来更新答案,如果目标值小于当前节点的值,我们就递归地搜索左子树,否则我们递归地搜索右子树。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉搜索树的节点数。 diff --git a/solution/0200-0299/0273.Integer to English Words/README.md b/solution/0200-0299/0273.Integer to English Words/README.md index 54a28c894882..a7fce1803bf4 100644 --- a/solution/0200-0299/0273.Integer to English Words/README.md +++ b/solution/0200-0299/0273.Integer to English Words/README.md @@ -296,6 +296,58 @@ public class Solution { } ``` +#### TypeScript + +```ts +function numberToWords(num: number): string { + if (num === 0) return 'Zero'; + + // prettier-ignore + const f = (x: number): string => { + const dict1 = ['','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Eleven','Twelve','Thirteen','Fourteen','Fifteen','Sixteen','Seventeen','Eighteen','Nineteen',] + const dict2 = ['','','Twenty','Thirty','Forty','Fifty','Sixty','Seventy','Eighty','Ninety',] + let ans = '' + + if (x <= 19) ans = dict1[x] ?? '' + else if (x < 100) ans = `${dict2[Math.floor(x / 10)]} ${f(x % 10)}` + else if (x < 10 ** 3) ans = `${dict1[Math.floor(x / 100)]} Hundred ${f(x % 100)}` + else if (x < 10 ** 6) ans = `${f(Math.floor(x / 10 ** 3))} Thousand ${f(x % 10 ** 3)}` + else if (x < 10 ** 9) ans = `${f(Math.floor(x / 10 ** 6))} Million ${f(x % 10 ** 6)}` + else ans = `${f(Math.floor(x / 10 ** 9))} Billion ${f(x % 10 ** 9)}` + + return ans.trim() + } + + return f(num); +} +``` + +#### JavaScript + +```js +function numberToWords(num) { + if (num === 0) return 'Zero'; + + // prettier-ignore + const f = (x) => { + const dict1 = ['','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Eleven','Twelve','Thirteen','Fourteen','Fifteen','Sixteen','Seventeen','Eighteen','Nineteen',] + const dict2 = ['','','Twenty','Thirty','Forty','Fifty','Sixty','Seventy','Eighty','Ninety',] + let ans = '' + + if (x <= 19) ans = dict1[x] ?? '' + else if (x < 100) ans = `${dict2[Math.floor(x / 10)]} ${f(x % 10)}` + else if (x < 10 ** 3) ans = `${dict1[Math.floor(x / 100)]} Hundred ${f(x % 100)}` + else if (x < 10 ** 6) ans = `${f(Math.floor(x / 10 ** 3))} Thousand ${f(x % 10 ** 3)}` + else if (x < 10 ** 9) ans = `${f(Math.floor(x / 10 ** 6))} Million ${f(x % 10 ** 6)}` + else ans = `${f(Math.floor(x / 10 ** 9))} Billion ${f(x % 10 ** 9)}` + + return ans.trim() + } + + return f(num); +} +``` + diff --git a/solution/0200-0299/0273.Integer to English Words/README_EN.md b/solution/0200-0299/0273.Integer to English Words/README_EN.md index 51615ba7e4a7..3260ff5261c9 100644 --- a/solution/0200-0299/0273.Integer to English Words/README_EN.md +++ b/solution/0200-0299/0273.Integer to English Words/README_EN.md @@ -294,6 +294,58 @@ public class Solution { } ``` +#### TypeScript + +```ts +function numberToWords(num: number): string { + if (num === 0) return 'Zero'; + + // prettier-ignore + const f = (x: number): string => { + const dict1 = ['','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Eleven','Twelve','Thirteen','Fourteen','Fifteen','Sixteen','Seventeen','Eighteen','Nineteen',] + const dict2 = ['','','Twenty','Thirty','Forty','Fifty','Sixty','Seventy','Eighty','Ninety',] + let ans = '' + + if (x <= 19) ans = dict1[x] ?? '' + else if (x < 100) ans = `${dict2[Math.floor(x / 10)]} ${f(x % 10)}` + else if (x < 10 ** 3) ans = `${dict1[Math.floor(x / 100)]} Hundred ${f(x % 100)}` + else if (x < 10 ** 6) ans = `${f(Math.floor(x / 10 ** 3))} Thousand ${f(x % 10 ** 3)}` + else if (x < 10 ** 9) ans = `${f(Math.floor(x / 10 ** 6))} Million ${f(x % 10 ** 6)}` + else ans = `${f(Math.floor(x / 10 ** 9))} Billion ${f(x % 10 ** 9)}` + + return ans.trim() + } + + return f(num); +} +``` + +#### JavaScript + +```js +function numberToWords(num) { + if (num === 0) return 'Zero'; + + // prettier-ignore + const f = (x) => { + const dict1 = ['','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Eleven','Twelve','Thirteen','Fourteen','Fifteen','Sixteen','Seventeen','Eighteen','Nineteen',] + const dict2 = ['','','Twenty','Thirty','Forty','Fifty','Sixty','Seventy','Eighty','Ninety',] + let ans = '' + + if (x <= 19) ans = dict1[x] ?? '' + else if (x < 100) ans = `${dict2[Math.floor(x / 10)]} ${f(x % 10)}` + else if (x < 10 ** 3) ans = `${dict1[Math.floor(x / 100)]} Hundred ${f(x % 100)}` + else if (x < 10 ** 6) ans = `${f(Math.floor(x / 10 ** 3))} Thousand ${f(x % 10 ** 3)}` + else if (x < 10 ** 9) ans = `${f(Math.floor(x / 10 ** 6))} Million ${f(x % 10 ** 6)}` + else ans = `${f(Math.floor(x / 10 ** 9))} Billion ${f(x % 10 ** 9)}` + + return ans.trim() + } + + return f(num); +} +``` + diff --git a/solution/0200-0299/0273.Integer to English Words/Solution.js b/solution/0200-0299/0273.Integer to English Words/Solution.js new file mode 100644 index 000000000000..4abc586bf2de --- /dev/null +++ b/solution/0200-0299/0273.Integer to English Words/Solution.js @@ -0,0 +1,21 @@ +function numberToWords(num) { + if (num === 0) return 'Zero'; + + // prettier-ignore + const f = (x) => { + const dict1 = ['','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Eleven','Twelve','Thirteen','Fourteen','Fifteen','Sixteen','Seventeen','Eighteen','Nineteen',] + const dict2 = ['','','Twenty','Thirty','Forty','Fifty','Sixty','Seventy','Eighty','Ninety',] + let ans = '' + + if (x <= 19) ans = dict1[x] ?? '' + else if (x < 100) ans = `${dict2[Math.floor(x / 10)]} ${f(x % 10)}` + else if (x < 10 ** 3) ans = `${dict1[Math.floor(x / 100)]} Hundred ${f(x % 100)}` + else if (x < 10 ** 6) ans = `${f(Math.floor(x / 10 ** 3))} Thousand ${f(x % 10 ** 3)}` + else if (x < 10 ** 9) ans = `${f(Math.floor(x / 10 ** 6))} Million ${f(x % 10 ** 6)}` + else ans = `${f(Math.floor(x / 10 ** 9))} Billion ${f(x % 10 ** 9)}` + + return ans.trim() + } + + return f(num); +} diff --git a/solution/0200-0299/0273.Integer to English Words/Solution.ts b/solution/0200-0299/0273.Integer to English Words/Solution.ts new file mode 100644 index 000000000000..32c8e3b3a24a --- /dev/null +++ b/solution/0200-0299/0273.Integer to English Words/Solution.ts @@ -0,0 +1,21 @@ +function numberToWords(num: number): string { + if (num === 0) return 'Zero'; + + // prettier-ignore + const f = (x: number): string => { + const dict1 = ['','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Eleven','Twelve','Thirteen','Fourteen','Fifteen','Sixteen','Seventeen','Eighteen','Nineteen',] + const dict2 = ['','','Twenty','Thirty','Forty','Fifty','Sixty','Seventy','Eighty','Ninety',] + let ans = '' + + if (x <= 19) ans = dict1[x] ?? '' + else if (x < 100) ans = `${dict2[Math.floor(x / 10)]} ${f(x % 10)}` + else if (x < 10 ** 3) ans = `${dict1[Math.floor(x / 100)]} Hundred ${f(x % 100)}` + else if (x < 10 ** 6) ans = `${f(Math.floor(x / 10 ** 3))} Thousand ${f(x % 10 ** 3)}` + else if (x < 10 ** 9) ans = `${f(Math.floor(x / 10 ** 6))} Million ${f(x % 10 ** 6)}` + else ans = `${f(Math.floor(x / 10 ** 9))} Billion ${f(x % 10 ** 9)}` + + return ans.trim() + } + + return f(num); +} diff --git a/solution/0200-0299/0277.Find the Celebrity/README.md b/solution/0200-0299/0277.Find the Celebrity/README.md index 501457473064..8ae7e2cf7015 100644 --- a/solution/0200-0299/0277.Find the Celebrity/README.md +++ b/solution/0200-0299/0277.Find the Celebrity/README.md @@ -18,62 +18,56 @@ tags: -

    假设你是一个专业的狗仔,参加了一个 n 人派对,其中每个人被从 0 到 n - 1 标号。在这个派对人群当中可能存在一位 “名人”。所谓 “名人” 的定义是:其他所有 n - 1 个人都认识他/她,而他/她并不认识其他任何人。

    +

    假设你是一个专业的狗仔,参加了一个 n 人派对,其中每个人被从 0 到 n - 1 标号。在这个派对人群当中可能存在一位 “名人”。所谓 “名人” 的定义是:其他所有 n - 1 个人都认识他/她,而他/她并不认识其他任何人。

    -

    现在你想要确认这个 “名人” 是谁,或者确定这里没有 “名人”。而你唯一能做的就是问诸如 “A 你好呀,请问你认不认识 B呀?” 的问题,以确定 A 是否认识 B。你需要在(渐近意义上)尽可能少的问题内来确定这位 “名人” 是谁(或者确定这里没有 “名人”)。

    +

    现在你想要确认这个 “名人” 是谁,或者确定这里没有 “名人”。而你唯一能做的就是问诸如 “A 你好呀,请问你认不认识 B呀?” 的问题,以确定 A 是否认识 B。你需要在(渐近意义上)尽可能少的问题内来确定这位 “名人” 是谁(或者确定这里没有 “名人”)。

    -

    在本题中,你可以使用辅助函数 bool knows(a, b) 获取到 A 是否认识 B。请你来实现一个函数 int findCelebrity(n)

    +

    在本题中,你可以使用辅助函数 bool knows(a, b) 获取到 A 是否认识 B。请你来实现一个函数 int findCelebrity(n)

    -

    派对最多只会有一个 “名人” 参加。若 “名人” 存在,请返回他/她的编号;若 “名人” 不存在,请返回 -1

    +

    派对最多只会有一个 “名人” 参加。若 “名人” 存在,请返回他/她的编号;若 “名人” 不存在,请返回 -1

    -

     

    - -

    示例 1:

    - -

    +

     

    +

    示例 1:

    +
    -输入: graph = [
    -  [1,1,0],
    -  [0,1,0],
    -  [1,1,1]
    -]
    +输入: graph = [[1,1,0],[0,1,0],[1,1,1]]
     输出: 1
     解释: 有编号分别为 0、1 和 2 的三个人。graph[i][j] = 1 代表编号为 i 的人认识编号为 j 的人,而 graph[i][j] = 0 则代表编号为 i 的人不认识编号为 j 的人。“名人” 是编号 1 的人,因为 0 和 2 均认识他/她,但 1 不认识任何人。
     
    + -

    示例 2:

    - -

    - +

    示例 2:

    +
    -输入: graph = [
    -  [1,0,1],
    -  [1,1,0],
    -  [0,1,1]
    -]
    +输入: graph = [[1,0,1],[1,1,0],[0,1,1]]
     输出: -1
     解释: 没有 “名人”
     
    -

     

    +

     

    + -

    提示:

    +

    提示:

    +
      -
    • n == graph.length
    • -
    • n == graph[i].length
    • -
    • 2 <= n <= 100
    • -
    • graph[i][j]01.
    • +
    • n == graph.length == graph[i].length
    • +
    • 2 <= n <= 100
    • +
    • graph[i][j]01
    • graph[i][i] == 1
    + -

     

    +

     

    + -

    进阶:如果允许调用 API knows 的最大次数为 3 * n ,你可以设计一个不超过最大调用次数的解决方案吗?

    +

    进阶:如果允许调用 API knows 的最大次数为 3 * n ,你可以设计一个不超过最大调用次数的解决方案吗?

    +
    + diff --git a/solution/0200-0299/0277.Find the Celebrity/images/277_example_1_bold.png b/solution/0200-0299/0277.Find the Celebrity/images/277_example_1_bold.png deleted file mode 100644 index f4f70164e618..000000000000 Binary files a/solution/0200-0299/0277.Find the Celebrity/images/277_example_1_bold.png and /dev/null differ diff --git a/solution/0200-0299/0277.Find the Celebrity/images/277_example_2.png b/solution/0200-0299/0277.Find the Celebrity/images/277_example_2.png deleted file mode 100644 index 00ea91bd7a90..000000000000 Binary files a/solution/0200-0299/0277.Find the Celebrity/images/277_example_2.png and /dev/null differ diff --git a/solution/0200-0299/0295.Find Median from Data Stream/README.md b/solution/0200-0299/0295.Find Median from Data Stream/README.md index e2121ad72456..5ac081b9a13b 100644 --- a/solution/0200-0299/0295.Find Median from Data Stream/README.md +++ b/solution/0200-0299/0295.Find Median from Data Stream/README.md @@ -74,11 +74,11 @@ medianFinder.findMedian(); // return 2.0
    ### 方法一:大小根堆(优先队列) -我们可以使用两个堆来维护所有的元素,一个小根堆 $\text{minQ}$ 和一个大根堆 $\text{maxQ}$,其中小根堆 $\text{minQ}$ 存储较大的一半,大根堆 $\text{maxQ}$ 存储较小的一半。 +我们可以使用两个堆来维护所有的元素,一个小根堆 $\textit{minQ}$ 和一个大根堆 $\textit{maxQ}$,其中小根堆 $\textit{minQ}$ 存储较大的一半,大根堆 $\textit{maxQ}$ 存储较小的一半。 -调用 `addNum` 方法时,我们首先将元素加入到大根堆 $\text{maxQ}$,然后将 $\text{maxQ}$ 的堆顶元素弹出并加入到小根堆 $\text{minQ}$。如果此时 $\text{minQ}$ 的大小与 $\text{maxQ}$ 的大小差值大于 $1$,我们就将 $\text{minQ}$ 的堆顶元素弹出并加入到 $\text{maxQ}$。时间复杂度为 $O(\log n)$。 +调用 `addNum` 方法时,我们首先将元素加入到大根堆 $\textit{maxQ}$,然后将 $\textit{maxQ}$ 的堆顶元素弹出并加入到小根堆 $\textit{minQ}$。如果此时 $\textit{minQ}$ 的大小与 $\textit{maxQ}$ 的大小差值大于 $1$,我们就将 $\textit{minQ}$ 的堆顶元素弹出并加入到 $\textit{maxQ}$。时间复杂度为 $O(\log n)$。 -调用 `findMedian` 方法时,如果 $\text{minQ}$ 的大小等于 $\text{maxQ}$ 的大小,说明元素的总数为偶数,我们就可以返回 $\text{minQ}$ 的堆顶元素与 $\text{maxQ}$ 的堆顶元素的平均值;否则,我们返回 $\text{minQ}$ 的堆顶元素。时间复杂度为 $O(1)$。 +调用 `findMedian` 方法时,如果 $\textit{minQ}$ 的大小等于 $\textit{maxQ}$ 的大小,说明元素的总数为偶数,我们就可以返回 $\textit{minQ}$ 的堆顶元素与 $\textit{maxQ}$ 的堆顶元素的平均值;否则,我们返回 $\textit{minQ}$ 的堆顶元素。时间复杂度为 $O(1)$。 空间复杂度为 $O(n)$。其中 $n$ 为元素的个数。 diff --git a/solution/0200-0299/0295.Find Median from Data Stream/README_EN.md b/solution/0200-0299/0295.Find Median from Data Stream/README_EN.md index c2787a62043d..8f0d3a8b7cf0 100644 --- a/solution/0200-0299/0295.Find Median from Data Stream/README_EN.md +++ b/solution/0200-0299/0295.Find Median from Data Stream/README_EN.md @@ -79,11 +79,11 @@ medianFinder.findMedian(); // return 2.0 ### Solution 1: Min Heap and Max Heap (Priority Queue) -We can use two heaps to maintain all the elements, a min heap $\text{minQ}$ and a max heap $\text{maxQ}$, where the min heap $\text{minQ}$ stores the larger half, and the max heap $\text{maxQ}$ stores the smaller half. +We can use two heaps to maintain all the elements, a min heap $\textit{minQ}$ and a max heap $\textit{maxQ}$, where the min heap $\textit{minQ}$ stores the larger half, and the max heap $\textit{maxQ}$ stores the smaller half. -When calling the `addNum` method, we first add the element to the max heap $\text{maxQ}$, then pop the top element of $\text{maxQ}$ and add it to the min heap $\text{minQ}$. If at this time the size difference between $\text{minQ}$ and $\text{maxQ}$ is greater than $1$, we pop the top element of $\text{minQ}$ and add it to $\text{maxQ}$. The time complexity is $O(\log n)$. +When calling the `addNum` method, we first add the element to the max heap $\textit{maxQ}$, then pop the top element of $\textit{maxQ}$ and add it to the min heap $\textit{minQ}$. If at this time the size difference between $\textit{minQ}$ and $\textit{maxQ}$ is greater than $1$, we pop the top element of $\textit{minQ}$ and add it to $\textit{maxQ}$. The time complexity is $O(\log n)$. -When calling the `findMedian` method, if the size of $\text{minQ}$ is equal to the size of $\text{maxQ}$, it means the total number of elements is even, and we can return the average value of the top elements of $\text{minQ}$ and $\text{maxQ}$; otherwise, we return the top element of $\text{minQ}$. The time complexity is $O(1)$. +When calling the `findMedian` method, if the size of $\textit{minQ}$ is equal to the size of $\textit{maxQ}$, it means the total number of elements is even, and we can return the average value of the top elements of $\textit{minQ}$ and $\textit{maxQ}$; otherwise, we return the top element of $\textit{minQ}$. The time complexity is $O(1)$. The space complexity is $O(n)$, where $n$ is the number of elements. diff --git a/solution/0300-0399/0308.Range Sum Query 2D - Mutable/README.md b/solution/0300-0399/0308.Range Sum Query 2D - Mutable/README.md index 54fffba910df..a7b7363fef66 100644 --- a/solution/0300-0399/0308.Range Sum Query 2D - Mutable/README.md +++ b/solution/0300-0399/0308.Range Sum Query 2D - Mutable/README.md @@ -12,7 +12,7 @@ tags: -# [308. 二维区域和检索 - 可变 🔒](https://leetcode.cn/problems/range-sum-query-2d-mutable) +# [308. 二维区域和检索 - 矩阵可修改 🔒](https://leetcode.cn/problems/range-sum-query-2d-mutable) [English Version](/solution/0300-0399/0308.Range%20Sum%20Query%202D%20-%20Mutable/README_EN.md) diff --git a/solution/0300-0399/0332.Reconstruct Itinerary/README.md b/solution/0300-0399/0332.Reconstruct Itinerary/README.md index f14fd8ac83b8..09f9bbbeb93b 100644 --- a/solution/0300-0399/0332.Reconstruct Itinerary/README.md +++ b/solution/0300-0399/0332.Reconstruct Itinerary/README.md @@ -64,7 +64,13 @@ tags: -### 方法一 +### 方法一:欧拉路径 + +题目实际上是给定 $n$ 个点和 $m$ 条边,要求从指定的起点出发,经过所有的边恰好一次,使得路径字典序最小。这是一个典型的欧拉路径问题。 + +由于本题保证了至少存在一种合理的行程,因此,我们直接利用 Hierholzer 算法,输出从起点出发的欧拉路径即可。 + +时间复杂度 $O(m \times \log m)$,空间复杂度 $O(m)$。其中 $m$ 是边的数量。 @@ -73,56 +79,43 @@ tags: ```python class Solution: def findItinerary(self, tickets: List[List[str]]) -> List[str]: - graph = defaultdict(list) - - for src, dst in sorted(tickets, reverse=True): - graph[src].append(dst) - - itinerary = [] - - def dfs(airport): - while graph[airport]: - dfs(graph[airport].pop()) - itinerary.append(airport) - + def dfs(f: str): + while g[f]: + dfs(g[f].pop()) + ans.append(f) + + g = defaultdict(list) + for f, t in sorted(tickets, reverse=True): + g[f].append(t) + ans = [] dfs("JFK") - - return itinerary[::-1] + return ans[::-1] ``` #### Java ```java class Solution { - void dfs(Map> adjLists, List ans, String curr) { - Queue neighbors = adjLists.get(curr); - if (neighbors == null) { - ans.add(curr); - return; - } - while (!neighbors.isEmpty()) { - String neighbor = neighbors.poll(); - dfs(adjLists, ans, neighbor); - } - ans.add(curr); - return; - } + private Map> g = new HashMap<>(); + private List ans = new ArrayList<>(); public List findItinerary(List> tickets) { - Map> adjLists = new HashMap<>(); + Collections.sort(tickets, (a, b) -> b.get(1).compareTo(a.get(1))); for (List ticket : tickets) { - String from = ticket.get(0); - String to = ticket.get(1); - if (!adjLists.containsKey(from)) { - adjLists.put(from, new PriorityQueue<>()); - } - adjLists.get(from).add(to); + g.computeIfAbsent(ticket.get(0), k -> new ArrayList<>()).add(ticket.get(1)); } - List ans = new ArrayList<>(); - dfs(adjLists, ans, "JFK"); + dfs("JFK"); Collections.reverse(ans); return ans; } + + private void dfs(String f) { + while (g.containsKey(f) && !g.get(f).isEmpty()) { + String t = g.get(f).remove(g.get(f).size() - 1); + dfs(t); + } + ans.add(f); + } } ``` @@ -132,36 +125,77 @@ class Solution { class Solution { public: vector findItinerary(vector>& tickets) { - unordered_map, greater>> g; - vector ret; - - // Initialize the graph - for (const auto& t : tickets) { - g[t[0]].push(t[1]); + sort(tickets.rbegin(), tickets.rend()); + unordered_map> g; + for (const auto& ticket : tickets) { + g[ticket[0]].push_back(ticket[1]); } + vector ans; + auto dfs = [&](auto&& dfs, string& f) -> void { + while (!g[f].empty()) { + string t = g[f].back(); + g[f].pop_back(); + dfs(dfs, t); + } + ans.emplace_back(f); + }; + string f = "JFK"; + dfs(dfs, f); + reverse(ans.begin(), ans.end()); + return ans; + } +}; +``` - findItineraryInner(g, ret, "JFK"); +#### Go + +```go +func findItinerary(tickets [][]string) (ans []string) { + sort.Slice(tickets, func(i, j int) bool { + return tickets[i][0] > tickets[j][0] || (tickets[i][0] == tickets[j][0] && tickets[i][1] > tickets[j][1]) + }) + g := make(map[string][]string) + for _, ticket := range tickets { + g[ticket[0]] = append(g[ticket[0]], ticket[1]) + } + var dfs func(f string) + dfs = func(f string) { + for len(g[f]) > 0 { + t := g[f][len(g[f])-1] + g[f] = g[f][:len(g[f])-1] + dfs(t) + } + ans = append(ans, f) + } + dfs("JFK") + for i := 0; i < len(ans)/2; i++ { + ans[i], ans[len(ans)-1-i] = ans[len(ans)-1-i], ans[i] + } + return +} +``` - ret = {ret.rbegin(), ret.rend()}; +#### TypeScript - return ret; +```ts +function findItinerary(tickets: string[][]): string[] { + const g: Record = {}; + tickets.sort((a, b) => b[1].localeCompare(a[1])); + for (const [f, t] of tickets) { + g[f] = g[f] || []; + g[f].push(t); } - - void findItineraryInner(unordered_map, greater>>& g, vector& ret, string cur) { - if (g.count(cur) == 0) { - // This is the end point - ret.push_back(cur); - return; - } else { - while (!g[cur].empty()) { - auto front = g[cur].top(); - g[cur].pop(); - findItineraryInner(g, ret, front); - } - ret.push_back(cur); + const ans: string[] = []; + const dfs = (f: string) => { + while (g[f] && g[f].length) { + const t = g[f].pop()!; + dfs(t); } - } -}; + ans.push(f); + }; + dfs('JFK'); + return ans.reverse(); +} ``` diff --git a/solution/0300-0399/0332.Reconstruct Itinerary/README_EN.md b/solution/0300-0399/0332.Reconstruct Itinerary/README_EN.md index bb688d0f1ada..3fcd849fbd06 100644 --- a/solution/0300-0399/0332.Reconstruct Itinerary/README_EN.md +++ b/solution/0300-0399/0332.Reconstruct Itinerary/README_EN.md @@ -62,7 +62,13 @@ tags: -### Solution 1 +### Solution 1: Eulerian Path + +The problem is essentially about finding a path that starts from a specified starting point, passes through all the edges exactly once, and has the smallest lexicographical order among all such paths, given $n$ vertices and $m$ edges. This is a classic Eulerian path problem. + +Since the problem guarantees that there is at least one feasible itinerary, we can directly use the Hierholzer algorithm to output the Eulerian path starting from the starting point. + +The time complexity is $O(m \times \log m)$, and the space complexity is $O(m)$. Here, $m$ is the number of edges. @@ -71,56 +77,43 @@ tags: ```python class Solution: def findItinerary(self, tickets: List[List[str]]) -> List[str]: - graph = defaultdict(list) - - for src, dst in sorted(tickets, reverse=True): - graph[src].append(dst) - - itinerary = [] - - def dfs(airport): - while graph[airport]: - dfs(graph[airport].pop()) - itinerary.append(airport) - + def dfs(f: str): + while g[f]: + dfs(g[f].pop()) + ans.append(f) + + g = defaultdict(list) + for f, t in sorted(tickets, reverse=True): + g[f].append(t) + ans = [] dfs("JFK") - - return itinerary[::-1] + return ans[::-1] ``` #### Java ```java class Solution { - void dfs(Map> adjLists, List ans, String curr) { - Queue neighbors = adjLists.get(curr); - if (neighbors == null) { - ans.add(curr); - return; - } - while (!neighbors.isEmpty()) { - String neighbor = neighbors.poll(); - dfs(adjLists, ans, neighbor); - } - ans.add(curr); - return; - } + private Map> g = new HashMap<>(); + private List ans = new ArrayList<>(); public List findItinerary(List> tickets) { - Map> adjLists = new HashMap<>(); + Collections.sort(tickets, (a, b) -> b.get(1).compareTo(a.get(1))); for (List ticket : tickets) { - String from = ticket.get(0); - String to = ticket.get(1); - if (!adjLists.containsKey(from)) { - adjLists.put(from, new PriorityQueue<>()); - } - adjLists.get(from).add(to); + g.computeIfAbsent(ticket.get(0), k -> new ArrayList<>()).add(ticket.get(1)); } - List ans = new ArrayList<>(); - dfs(adjLists, ans, "JFK"); + dfs("JFK"); Collections.reverse(ans); return ans; } + + private void dfs(String f) { + while (g.containsKey(f) && !g.get(f).isEmpty()) { + String t = g.get(f).remove(g.get(f).size() - 1); + dfs(t); + } + ans.add(f); + } } ``` @@ -130,36 +123,77 @@ class Solution { class Solution { public: vector findItinerary(vector>& tickets) { - unordered_map, greater>> g; - vector ret; - - // Initialize the graph - for (const auto& t : tickets) { - g[t[0]].push(t[1]); + sort(tickets.rbegin(), tickets.rend()); + unordered_map> g; + for (const auto& ticket : tickets) { + g[ticket[0]].push_back(ticket[1]); } + vector ans; + auto dfs = [&](auto&& dfs, string& f) -> void { + while (!g[f].empty()) { + string t = g[f].back(); + g[f].pop_back(); + dfs(dfs, t); + } + ans.emplace_back(f); + }; + string f = "JFK"; + dfs(dfs, f); + reverse(ans.begin(), ans.end()); + return ans; + } +}; +``` - findItineraryInner(g, ret, "JFK"); +#### Go + +```go +func findItinerary(tickets [][]string) (ans []string) { + sort.Slice(tickets, func(i, j int) bool { + return tickets[i][0] > tickets[j][0] || (tickets[i][0] == tickets[j][0] && tickets[i][1] > tickets[j][1]) + }) + g := make(map[string][]string) + for _, ticket := range tickets { + g[ticket[0]] = append(g[ticket[0]], ticket[1]) + } + var dfs func(f string) + dfs = func(f string) { + for len(g[f]) > 0 { + t := g[f][len(g[f])-1] + g[f] = g[f][:len(g[f])-1] + dfs(t) + } + ans = append(ans, f) + } + dfs("JFK") + for i := 0; i < len(ans)/2; i++ { + ans[i], ans[len(ans)-1-i] = ans[len(ans)-1-i], ans[i] + } + return +} +``` - ret = {ret.rbegin(), ret.rend()}; +#### TypeScript - return ret; +```ts +function findItinerary(tickets: string[][]): string[] { + const g: Record = {}; + tickets.sort((a, b) => b[1].localeCompare(a[1])); + for (const [f, t] of tickets) { + g[f] = g[f] || []; + g[f].push(t); } - - void findItineraryInner(unordered_map, greater>>& g, vector& ret, string cur) { - if (g.count(cur) == 0) { - // This is the end point - ret.push_back(cur); - return; - } else { - while (!g[cur].empty()) { - auto front = g[cur].top(); - g[cur].pop(); - findItineraryInner(g, ret, front); - } - ret.push_back(cur); + const ans: string[] = []; + const dfs = (f: string) => { + while (g[f] && g[f].length) { + const t = g[f].pop()!; + dfs(t); } - } -}; + ans.push(f); + }; + dfs('JFK'); + return ans.reverse(); +} ``` diff --git a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.cpp b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.cpp index c9a7344be9fe..daa0b3bd96ab 100644 --- a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.cpp +++ b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.cpp @@ -1,33 +1,23 @@ class Solution { public: vector findItinerary(vector>& tickets) { - unordered_map, greater>> g; - vector ret; - - // Initialize the graph - for (const auto& t : tickets) { - g[t[0]].push(t[1]); + sort(tickets.rbegin(), tickets.rend()); + unordered_map> g; + for (const auto& ticket : tickets) { + g[ticket[0]].push_back(ticket[1]); } - - findItineraryInner(g, ret, "JFK"); - - ret = {ret.rbegin(), ret.rend()}; - - return ret; - } - - void findItineraryInner(unordered_map, greater>>& g, vector& ret, string cur) { - if (g.count(cur) == 0) { - // This is the end point - ret.push_back(cur); - return; - } else { - while (!g[cur].empty()) { - auto front = g[cur].top(); - g[cur].pop(); - findItineraryInner(g, ret, front); + vector ans; + auto dfs = [&](auto&& dfs, string& f) -> void { + while (!g[f].empty()) { + string t = g[f].back(); + g[f].pop_back(); + dfs(dfs, t); } - ret.push_back(cur); - } + ans.emplace_back(f); + }; + string f = "JFK"; + dfs(dfs, f); + reverse(ans.begin(), ans.end()); + return ans; } }; \ No newline at end of file diff --git a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.go b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.go new file mode 100644 index 000000000000..35ba5bc6ee49 --- /dev/null +++ b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.go @@ -0,0 +1,23 @@ +func findItinerary(tickets [][]string) (ans []string) { + sort.Slice(tickets, func(i, j int) bool { + return tickets[i][0] > tickets[j][0] || (tickets[i][0] == tickets[j][0] && tickets[i][1] > tickets[j][1]) + }) + g := make(map[string][]string) + for _, ticket := range tickets { + g[ticket[0]] = append(g[ticket[0]], ticket[1]) + } + var dfs func(f string) + dfs = func(f string) { + for len(g[f]) > 0 { + t := g[f][len(g[f])-1] + g[f] = g[f][:len(g[f])-1] + dfs(t) + } + ans = append(ans, f) + } + dfs("JFK") + for i := 0; i < len(ans)/2; i++ { + ans[i], ans[len(ans)-1-i] = ans[len(ans)-1-i], ans[i] + } + return +} \ No newline at end of file diff --git a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.java b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.java index 970cd30092f1..ddc8efbf4551 100644 --- a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.java +++ b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.java @@ -1,31 +1,22 @@ class Solution { - void dfs(Map> adjLists, List ans, String curr) { - Queue neighbors = adjLists.get(curr); - if (neighbors == null) { - ans.add(curr); - return; - } - while (!neighbors.isEmpty()) { - String neighbor = neighbors.poll(); - dfs(adjLists, ans, neighbor); - } - ans.add(curr); - return; - } + private Map> g = new HashMap<>(); + private List ans = new ArrayList<>(); public List findItinerary(List> tickets) { - Map> adjLists = new HashMap<>(); + Collections.sort(tickets, (a, b) -> b.get(1).compareTo(a.get(1))); for (List ticket : tickets) { - String from = ticket.get(0); - String to = ticket.get(1); - if (!adjLists.containsKey(from)) { - adjLists.put(from, new PriorityQueue<>()); - } - adjLists.get(from).add(to); + g.computeIfAbsent(ticket.get(0), k -> new ArrayList<>()).add(ticket.get(1)); } - List ans = new ArrayList<>(); - dfs(adjLists, ans, "JFK"); + dfs("JFK"); Collections.reverse(ans); return ans; } + + private void dfs(String f) { + while (g.containsKey(f) && !g.get(f).isEmpty()) { + String t = g.get(f).remove(g.get(f).size() - 1); + dfs(t); + } + ans.add(f); + } } \ No newline at end of file diff --git a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.py b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.py index 8b6c452a44ca..7614c393c9f7 100644 --- a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.py +++ b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.py @@ -1,17 +1,13 @@ class Solution: def findItinerary(self, tickets: List[List[str]]) -> List[str]: - graph = defaultdict(list) - - for src, dst in sorted(tickets, reverse=True): - graph[src].append(dst) - - itinerary = [] - - def dfs(airport): - while graph[airport]: - dfs(graph[airport].pop()) - itinerary.append(airport) - + def dfs(f: str): + while g[f]: + dfs(g[f].pop()) + ans.append(f) + + g = defaultdict(list) + for f, t in sorted(tickets, reverse=True): + g[f].append(t) + ans = [] dfs("JFK") - - return itinerary[::-1] + return ans[::-1] diff --git a/solution/0300-0399/0332.Reconstruct Itinerary/Solution.ts b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.ts new file mode 100644 index 000000000000..d8a61a461a1f --- /dev/null +++ b/solution/0300-0399/0332.Reconstruct Itinerary/Solution.ts @@ -0,0 +1,18 @@ +function findItinerary(tickets: string[][]): string[] { + const g: Record = {}; + tickets.sort((a, b) => b[1].localeCompare(a[1])); + for (const [f, t] of tickets) { + g[f] = g[f] || []; + g[f].push(t); + } + const ans: string[] = []; + const dfs = (f: string) => { + while (g[f] && g[f].length) { + const t = g[f].pop()!; + dfs(t); + } + ans.push(f); + }; + dfs('JFK'); + return ans.reverse(); +} diff --git a/solution/0300-0399/0338.Counting Bits/README.md b/solution/0300-0399/0338.Counting Bits/README.md index 9a81e7663965..7e7fa93ad1cd 100644 --- a/solution/0300-0399/0338.Counting Bits/README.md +++ b/solution/0300-0399/0338.Counting Bits/README.md @@ -161,7 +161,7 @@ function bitCount(n: number): number { 我们定义一个长度为 $n+1$ 的答案数组 $ans$,初始时 $ans[0]=0$。 -对于 $1 \leq i \leq n$,我们有 $ans[i] = ans[i \text{ and } (i-1)] + 1$。其中 $i \text{ and } (i-1)$ 表示将 $i$ 的二进制表示中的最低位 $1$ 变成 $0$ 之后的数,显然 $i \text{ and } (i-1) < i$,且 $ans[i \text{ and } (i-1)]$ 已经被计算出来了,我们就能以 $O(1)$ 的时间得到 $ans[i]$。 +对于 $1 \leq i \leq n$,我们有 $ans[i] = ans[i \textit{ and } (i-1)] + 1$。其中 $i \textit{ and } (i-1)$ 表示将 $i$ 的二进制表示中的最低位 $1$ 变成 $0$ 之后的数,显然 $i \textit{ and } (i-1) < i$,且 $ans[i \textit{ and } (i-1)]$ 已经被计算出来了,我们就能以 $O(1)$ 的时间得到 $ans[i]$。 时间复杂度 $O(n)$,空间复杂度 $O(1)$。 diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md index fa9134aadaf4..c048c7f16ad7 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md @@ -54,11 +54,13 @@ tags: ### 方法一:滑动窗口 + 哈希表 -我们可以使用滑动窗口的思想,维护一个滑动窗口,使得窗口内的字符串中不同字符的个数不超过 $k$ 个。窗口内不同字符个数的统计可以用哈希表 `cnt` 来维护。 +我们可以使用滑动窗口的思想,用一个哈希表 $\textit{cnt}$ 记录窗口中每个字符的出现次数,用 $\textit{l}$ 记录窗口的左边界。 -我们使用两个指针 $j$ 和 $i$ 分别表示滑动窗口的左右边界。我们先移动右边界 $i$,将字符 $s[i]$ 加入到窗口内,扩大滑动窗口,若此时窗口内不同字符的个数超过 $k$ 个,则移动左边界 $j$,缩小滑动窗口,直到窗口内不同字符的个数不超过 $k$ 个。此时我们可以更新答案的最大值,即 $ans = max(ans, i - j + 1)$。 +遍历字符串,每次将右边界的字符加入哈希表,如果哈希表中不同字符的个数超过了 $k$,则将左边界的字符从哈希表中删除,然后更新左边界 $\textit{l}$。 -时间复杂度 $O(n)$,空间复杂度 $O(\min(n, k))$。其中 $n$ 为字符串的长度。 +最后返回字符串的长度减去左边界的长度即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(k)$。其中 $n$ 为字符串的长度。 @@ -67,18 +69,16 @@ tags: ```python class Solution: def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int: + l = 0 cnt = Counter() - n = len(s) - ans = j = 0 - for i, c in enumerate(s): + for c in s: cnt[c] += 1 - while len(cnt) > k: - cnt[s[j]] -= 1 - if cnt[s[j]] == 0: - cnt.pop(s[j]) - j += 1 - ans = max(ans, i - j + 1) - return ans + if len(cnt) > k: + cnt[s[l]] -= 1 + if cnt[s[l]] == 0: + del cnt[s[l]] + l += 1 + return len(s) - l ``` #### Java @@ -87,22 +87,18 @@ class Solution: class Solution { public int lengthOfLongestSubstringKDistinct(String s, int k) { Map cnt = new HashMap<>(); - int n = s.length(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - char c = s.charAt(i); - cnt.put(c, cnt.getOrDefault(c, 0) + 1); - while (cnt.size() > k) { - char t = s.charAt(j); - cnt.put(t, cnt.getOrDefault(t, 0) - 1); - if (cnt.get(t) == 0) { - cnt.remove(t); + int l = 0; + char[] cs = s.toCharArray(); + for (char c : cs) { + cnt.merge(c, 1, Integer::sum); + if (cnt.size() > k) { + if (cnt.merge(cs[l], -1, Integer::sum) == 0) { + cnt.remove(cs[l]); } - ++j; + ++l; } - ans = Math.max(ans, i - j + 1); } - return ans; + return cs.length - l; } } ``` @@ -114,19 +110,17 @@ class Solution { public: int lengthOfLongestSubstringKDistinct(string s, int k) { unordered_map cnt; - int n = s.size(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - cnt[s[i]]++; - while (cnt.size() > k) { - if (--cnt[s[j]] == 0) { - cnt.erase(s[j]); + int l = 0; + for (char& c : s) { + ++cnt[c]; + if (cnt.size() > k) { + if (--cnt[s[l]] == 0) { + cnt.erase(s[l]); } - ++j; + ++l; } - ans = max(ans, i - j + 1); } - return ans; + return s.size() - l; } }; ``` @@ -134,21 +128,40 @@ public: #### Go ```go -func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) { +func lengthOfLongestSubstringKDistinct(s string, k int) int { cnt := map[byte]int{} - j := 0 - for i := range s { - cnt[s[i]]++ - for len(cnt) > k { - cnt[s[j]]-- - if cnt[s[j]] == 0 { - delete(cnt, s[j]) + l := 0 + for _, c := range s { + cnt[byte(c)]++ + if len(cnt) > k { + cnt[s[l]]-- + if cnt[s[l]] == 0 { + delete(cnt, s[l]) } - j++ + l++ } - ans = max(ans, i-j+1) } - return + return len(s) - l +} +``` + +#### TypeScript + +```ts +function lengthOfLongestSubstringKDistinct(s: string, k: number): number { + const cnt: Map = new Map(); + let l = 0; + for (const c of s) { + cnt.set(c, (cnt.get(c) ?? 0) + 1); + if (cnt.size > k) { + cnt.set(s[l], cnt.get(s[l])! - 1); + if (cnt.get(s[l]) === 0) { + cnt.delete(s[l]); + } + l++; + } + } + return s.length - l; } ``` diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md index 04562983b147..8643cc011245 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md @@ -50,7 +50,15 @@ tags: -### Solution 1 +### Solution 1: Sliding Window + Hash Table + +We can use the idea of a sliding window, with a hash table $\textit{cnt}$ to record the occurrence count of each character within the window, and $\textit{l}$ to denote the left boundary of the window. + +Iterate through the string, adding the character at the right boundary to the hash table each time. If the number of distinct characters in the hash table exceeds $k$, remove the character at the left boundary from the hash table, then update the left boundary $\textit{l}$. + +Finally, return the length of the string minus the length of the left boundary. + +The time complexity is $O(n)$, and the space complexity is $O(k)$. Here, $n$ is the length of the string. @@ -59,18 +67,16 @@ tags: ```python class Solution: def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int: + l = 0 cnt = Counter() - n = len(s) - ans = j = 0 - for i, c in enumerate(s): + for c in s: cnt[c] += 1 - while len(cnt) > k: - cnt[s[j]] -= 1 - if cnt[s[j]] == 0: - cnt.pop(s[j]) - j += 1 - ans = max(ans, i - j + 1) - return ans + if len(cnt) > k: + cnt[s[l]] -= 1 + if cnt[s[l]] == 0: + del cnt[s[l]] + l += 1 + return len(s) - l ``` #### Java @@ -79,22 +85,18 @@ class Solution: class Solution { public int lengthOfLongestSubstringKDistinct(String s, int k) { Map cnt = new HashMap<>(); - int n = s.length(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - char c = s.charAt(i); - cnt.put(c, cnt.getOrDefault(c, 0) + 1); - while (cnt.size() > k) { - char t = s.charAt(j); - cnt.put(t, cnt.getOrDefault(t, 0) - 1); - if (cnt.get(t) == 0) { - cnt.remove(t); + int l = 0; + char[] cs = s.toCharArray(); + for (char c : cs) { + cnt.merge(c, 1, Integer::sum); + if (cnt.size() > k) { + if (cnt.merge(cs[l], -1, Integer::sum) == 0) { + cnt.remove(cs[l]); } - ++j; + ++l; } - ans = Math.max(ans, i - j + 1); } - return ans; + return cs.length - l; } } ``` @@ -106,19 +108,17 @@ class Solution { public: int lengthOfLongestSubstringKDistinct(string s, int k) { unordered_map cnt; - int n = s.size(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - cnt[s[i]]++; - while (cnt.size() > k) { - if (--cnt[s[j]] == 0) { - cnt.erase(s[j]); + int l = 0; + for (char& c : s) { + ++cnt[c]; + if (cnt.size() > k) { + if (--cnt[s[l]] == 0) { + cnt.erase(s[l]); } - ++j; + ++l; } - ans = max(ans, i - j + 1); } - return ans; + return s.size() - l; } }; ``` @@ -126,21 +126,40 @@ public: #### Go ```go -func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) { +func lengthOfLongestSubstringKDistinct(s string, k int) int { cnt := map[byte]int{} - j := 0 - for i := range s { - cnt[s[i]]++ - for len(cnt) > k { - cnt[s[j]]-- - if cnt[s[j]] == 0 { - delete(cnt, s[j]) + l := 0 + for _, c := range s { + cnt[byte(c)]++ + if len(cnt) > k { + cnt[s[l]]-- + if cnt[s[l]] == 0 { + delete(cnt, s[l]) } - j++ + l++ } - ans = max(ans, i-j+1) } - return + return len(s) - l +} +``` + +#### TypeScript + +```ts +function lengthOfLongestSubstringKDistinct(s: string, k: number): number { + const cnt: Map = new Map(); + let l = 0; + for (const c of s) { + cnt.set(c, (cnt.get(c) ?? 0) + 1); + if (cnt.size > k) { + cnt.set(s[l], cnt.get(s[l])! - 1); + if (cnt.get(s[l]) === 0) { + cnt.delete(s[l]); + } + l++; + } + } + return s.length - l; } ``` diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp index 4c7a64f5dc07..55461d59a01c 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp @@ -2,18 +2,16 @@ class Solution { public: int lengthOfLongestSubstringKDistinct(string s, int k) { unordered_map cnt; - int n = s.size(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - cnt[s[i]]++; - while (cnt.size() > k) { - if (--cnt[s[j]] == 0) { - cnt.erase(s[j]); + int l = 0; + for (char& c : s) { + ++cnt[c]; + if (cnt.size() > k) { + if (--cnt[s[l]] == 0) { + cnt.erase(s[l]); } - ++j; + ++l; } - ans = max(ans, i - j + 1); } - return ans; + return s.size() - l; } }; \ No newline at end of file diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go index a70eb7c6cf17..9d88aa75a300 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go @@ -1,16 +1,15 @@ -func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) { +func lengthOfLongestSubstringKDistinct(s string, k int) int { cnt := map[byte]int{} - j := 0 - for i := range s { - cnt[s[i]]++ - for len(cnt) > k { - cnt[s[j]]-- - if cnt[s[j]] == 0 { - delete(cnt, s[j]) + l := 0 + for _, c := range s { + cnt[byte(c)]++ + if len(cnt) > k { + cnt[s[l]]-- + if cnt[s[l]] == 0 { + delete(cnt, s[l]) } - j++ + l++ } - ans = max(ans, i-j+1) } - return + return len(s) - l } \ No newline at end of file diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java index 556133f79cd1..d1f50fc755fd 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java @@ -1,21 +1,17 @@ class Solution { public int lengthOfLongestSubstringKDistinct(String s, int k) { Map cnt = new HashMap<>(); - int n = s.length(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - char c = s.charAt(i); - cnt.put(c, cnt.getOrDefault(c, 0) + 1); - while (cnt.size() > k) { - char t = s.charAt(j); - cnt.put(t, cnt.getOrDefault(t, 0) - 1); - if (cnt.get(t) == 0) { - cnt.remove(t); + int l = 0; + char[] cs = s.toCharArray(); + for (char c : cs) { + cnt.merge(c, 1, Integer::sum); + if (cnt.size() > k) { + if (cnt.merge(cs[l], -1, Integer::sum) == 0) { + cnt.remove(cs[l]); } - ++j; + ++l; } - ans = Math.max(ans, i - j + 1); } - return ans; + return cs.length - l; } } \ No newline at end of file diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py index e5f136e2c70e..3644fac6eda6 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py @@ -1,14 +1,12 @@ class Solution: def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int: + l = 0 cnt = Counter() - n = len(s) - ans = j = 0 - for i, c in enumerate(s): + for c in s: cnt[c] += 1 - while len(cnt) > k: - cnt[s[j]] -= 1 - if cnt[s[j]] == 0: - cnt.pop(s[j]) - j += 1 - ans = max(ans, i - j + 1) - return ans + if len(cnt) > k: + cnt[s[l]] -= 1 + if cnt[s[l]] == 0: + del cnt[s[l]] + l += 1 + return len(s) - l diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.ts b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.ts new file mode 100644 index 000000000000..2865634a94d6 --- /dev/null +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.ts @@ -0,0 +1,15 @@ +function lengthOfLongestSubstringKDistinct(s: string, k: number): number { + const cnt: Map = new Map(); + let l = 0; + for (const c of s) { + cnt.set(c, (cnt.get(c) ?? 0) + 1); + if (cnt.size > k) { + cnt.set(s[l], cnt.get(s[l])! - 1); + if (cnt.get(s[l]) === 0) { + cnt.delete(s[l]); + } + l++; + } + } + return s.length - l; +} diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/README.md b/solution/0300-0399/0341.Flatten Nested List Iterator/README.md index 616325863bc8..6a7fe407546a 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/README.md +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/README.md @@ -108,24 +108,23 @@ return res
    class NestedIterator: def __init__(self, nestedList: [NestedInteger]): - def dfs(nestedList): - for e in nestedList: - if e.isInteger(): - self.vals.append(e.getInteger()) + def dfs(ls): + for x in ls: + if x.isInteger(): + self.nums.append(x.getInteger()) else: - dfs(e.getList()) + dfs(x.getList()) - self.vals = [] + self.nums = [] + self.i = -1 dfs(nestedList) - self.cur = 0 def next(self) -> int: - res = self.vals[self.cur] - self.cur += 1 - return res + self.i += 1 + return self.nums[self.i] def hasNext(self) -> bool: - return self.cur < len(self.vals) + return self.i + 1 < len(self.nums) # Your NestedIterator object will be instantiated and called as such: @@ -149,38 +148,34 @@ class NestedIterator: * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { - - private List vals; - - private Iterator cur; + private List nums = new ArrayList<>(); + private int i = -1; public NestedIterator(List nestedList) { - vals = new ArrayList<>(); dfs(nestedList); - cur = vals.iterator(); } @Override public Integer next() { - return cur.next(); + return nums.get(++i); } @Override public boolean hasNext() { - return cur.hasNext(); + return i + 1 < nums.size(); } - private void dfs(List nestedList) { - for (NestedInteger e : nestedList) { - if (e.isInteger()) { - vals.add(e.getInteger()); + private void dfs(List ls) { + for (var x : ls) { + if (x.isInteger()) { + nums.add(x.getInteger()); } else { - dfs(e.getList()); + dfs(x.getList()); } } } @@ -217,30 +212,29 @@ public class NestedIterator implements Iterator { class NestedIterator { public: NestedIterator(vector& nestedList) { - dfs(nestedList); + auto dfs = [&](auto&& dfs, vector& ls) -> void { + for (auto& x : ls) { + if (x.isInteger()) { + nums.push_back(x.getInteger()); + } else { + dfs(dfs, x.getList()); + } + } + }; + dfs(dfs, nestedList); } int next() { - return vals[cur++]; + return nums[++i]; } bool hasNext() { - return cur < vals.size(); + return i + 1 < nums.size(); } private: - vector vals; - int cur = 0; - - void dfs(vector& nestedList) { - for (auto& e : nestedList) { - if (e.isInteger()) { - vals.push_back(e.getInteger()); - } else { - dfs(e.getList()); - } - } - } + vector nums; + int i = -1; }; /** @@ -280,34 +274,34 @@ private: */ type NestedIterator struct { - iterator []int - index, length int + nums []int + i int } func Constructor(nestedList []*NestedInteger) *NestedIterator { - result := make([]int, 0) - var traversal func(nodes []*NestedInteger) - traversal = func(nodes []*NestedInteger) { - for _, child := range nodes { - if child.IsInteger() { - result = append(result, child.GetInteger()) + var dfs func([]*NestedInteger) + nums := []int{} + i := -1 + dfs = func(ls []*NestedInteger) { + for _, x := range ls { + if x.IsInteger() { + nums = append(nums, x.GetInteger()) } else { - traversal(child.GetList()) + dfs(x.GetList()) } } } - traversal(nestedList) - return &NestedIterator{iterator: result, index: 0, length: len(result)} + dfs(nestedList) + return &NestedIterator{nums, i} } func (this *NestedIterator) Next() int { - res := this.iterator[this.index] - this.index++ - return res + this.i++ + return this.nums[this.i] } func (this *NestedIterator) HasNext() bool { - return this.index < this.length + return this.i+1 < len(this.nums) } ``` @@ -354,31 +348,27 @@ func (this *NestedIterator) HasNext() bool { */ class NestedIterator { - private vals: number[]; - private index: number; - + private nums: number[] = []; + private i = -1; constructor(nestedList: NestedInteger[]) { - this.index = 0; - this.vals = []; - this.dfs(nestedList); - } - - dfs(nestedList: NestedInteger[]) { - for (const v of nestedList) { - if (v.isInteger()) { - this.vals.push(v.getInteger()); - } else { - this.dfs(v.getList()); + const dfs = (ls: NestedInteger[]) => { + for (const x of ls) { + if (x.isInteger()) { + this.nums.push(x.getInteger()); + } else { + dfs(x.getList()); + } } - } + }; + dfs(nestedList); } hasNext(): boolean { - return this.index < this.vals.length; + return this.i + 1 < this.nums.length; } next(): number { - return this.vals[this.index++]; + return this.nums[++this.i]; } } @@ -399,8 +389,8 @@ class NestedIterator { // List(Vec) // } struct NestedIterator { - index: usize, - vals: Vec, + nums: Vec, + i: usize, } /** @@ -408,102 +398,30 @@ struct NestedIterator { * If you need a mutable reference, change it to `&mut self` instead. */ impl NestedIterator { - fn dfs(nestedList: &Vec, vals: &mut Vec) { - for ele in nestedList.iter() { - match ele { - NestedInteger::Int(val) => vals.push(*val), - NestedInteger::List(list) => Self::dfs(list, vals), - } - } - } - - fn new(nestedList: Vec) -> Self { - let mut vals = vec![]; - Self::dfs(&nestedList, &mut vals); - Self { vals, index: 0 } + fn new(nested_list: Vec) -> Self { + let mut nums = Vec::new(); + Self::dfs(&nested_list, &mut nums); + NestedIterator { nums, i: 0 } } fn next(&mut self) -> i32 { - let res = self.vals[self.index]; - self.index += 1; - res + let result = self.nums[self.i]; + self.i += 1; + result } fn has_next(&self) -> bool { - self.index < self.vals.len() + self.i < self.nums.len() } -} -``` - - - - - - - -### 方法二:直接展开 - -调用 hasNext 时,如果 nestedList 的第一个元素是列表类型,则不断展开这个元素,直到第一个元素是整数类型。 调用 Next 方法时,由于 `hasNext()` 方法已确保 nestedList 第一个元素为整数类型,直接返回即可。 - - - -#### Go - -```go -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * type NestedInteger struct { - * } - * - * // Return true if this NestedInteger holds a single integer, rather than a nested list. - * func (this NestedInteger) IsInteger() bool {} - * - * // Return the single integer that this NestedInteger holds, if it holds a single integer - * // The result is undefined if this NestedInteger holds a nested list - * // So before calling this method, you should have a check - * func (this NestedInteger) GetInteger() int {} - * - * // Set this NestedInteger to hold a single integer. - * func (n *NestedInteger) SetInteger(value int) {} - * - * // Set this NestedInteger to hold a nested list and adds a nested integer to it. - * func (this *NestedInteger) Add(elem NestedInteger) {} - * - * // Return the nested list that this NestedInteger holds, if it holds a nested list - * // The list length is zero if this NestedInteger holds a single integer - * // You can access NestedInteger's List element directly if you want to modify it - * func (this NestedInteger) GetList() []*NestedInteger {} - */ - -type NestedIterator struct { - nested *list.List -} - -func Constructor(nestedList []*NestedInteger) *NestedIterator { - nested := list.New() - for _, v := range nestedList { - nested.PushBack(v) - } - return &NestedIterator{nested: nested} -} -func (this *NestedIterator) Next() int { - res := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - return res.GetInteger() -} - -func (this *NestedIterator) HasNext() bool { - for this.nested.Len() > 0 && !this.nested.Front().Value.(*NestedInteger).IsInteger() { - front := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - nodes := front.GetList() - for i := len(nodes) - 1; i >= 0; i-- { - this.nested.PushFront(nodes[i]) - } - } - return this.nested.Len() > 0 + fn dfs(nested_list: &Vec, nums: &mut Vec) { + for ni in nested_list { + match ni { + NestedInteger::Int(x) => nums.push(*x), + NestedInteger::List(list) => Self::dfs(list, nums), + } + } + } } ``` diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md b/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md index 734693136192..52cf400e9057 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md @@ -106,24 +106,23 @@ return res class NestedIterator: def __init__(self, nestedList: [NestedInteger]): - def dfs(nestedList): - for e in nestedList: - if e.isInteger(): - self.vals.append(e.getInteger()) + def dfs(ls): + for x in ls: + if x.isInteger(): + self.nums.append(x.getInteger()) else: - dfs(e.getList()) + dfs(x.getList()) - self.vals = [] + self.nums = [] + self.i = -1 dfs(nestedList) - self.cur = 0 def next(self) -> int: - res = self.vals[self.cur] - self.cur += 1 - return res + self.i += 1 + return self.nums[self.i] def hasNext(self) -> bool: - return self.cur < len(self.vals) + return self.i + 1 < len(self.nums) # Your NestedIterator object will be instantiated and called as such: @@ -147,38 +146,34 @@ class NestedIterator: * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { - - private List vals; - - private Iterator cur; + private List nums = new ArrayList<>(); + private int i = -1; public NestedIterator(List nestedList) { - vals = new ArrayList<>(); dfs(nestedList); - cur = vals.iterator(); } @Override public Integer next() { - return cur.next(); + return nums.get(++i); } @Override public boolean hasNext() { - return cur.hasNext(); + return i + 1 < nums.size(); } - private void dfs(List nestedList) { - for (NestedInteger e : nestedList) { - if (e.isInteger()) { - vals.add(e.getInteger()); + private void dfs(List ls) { + for (var x : ls) { + if (x.isInteger()) { + nums.add(x.getInteger()); } else { - dfs(e.getList()); + dfs(x.getList()); } } } @@ -215,30 +210,29 @@ public class NestedIterator implements Iterator { class NestedIterator { public: NestedIterator(vector& nestedList) { - dfs(nestedList); + auto dfs = [&](auto&& dfs, vector& ls) -> void { + for (auto& x : ls) { + if (x.isInteger()) { + nums.push_back(x.getInteger()); + } else { + dfs(dfs, x.getList()); + } + } + }; + dfs(dfs, nestedList); } int next() { - return vals[cur++]; + return nums[++i]; } bool hasNext() { - return cur < vals.size(); + return i + 1 < nums.size(); } private: - vector vals; - int cur = 0; - - void dfs(vector& nestedList) { - for (auto& e : nestedList) { - if (e.isInteger()) { - vals.push_back(e.getInteger()); - } else { - dfs(e.getList()); - } - } - } + vector nums; + int i = -1; }; /** @@ -278,34 +272,34 @@ private: */ type NestedIterator struct { - iterator []int - index, length int + nums []int + i int } func Constructor(nestedList []*NestedInteger) *NestedIterator { - result := make([]int, 0) - var traversal func(nodes []*NestedInteger) - traversal = func(nodes []*NestedInteger) { - for _, child := range nodes { - if child.IsInteger() { - result = append(result, child.GetInteger()) + var dfs func([]*NestedInteger) + nums := []int{} + i := -1 + dfs = func(ls []*NestedInteger) { + for _, x := range ls { + if x.IsInteger() { + nums = append(nums, x.GetInteger()) } else { - traversal(child.GetList()) + dfs(x.GetList()) } } } - traversal(nestedList) - return &NestedIterator{iterator: result, index: 0, length: len(result)} + dfs(nestedList) + return &NestedIterator{nums, i} } func (this *NestedIterator) Next() int { - res := this.iterator[this.index] - this.index++ - return res + this.i++ + return this.nums[this.i] } func (this *NestedIterator) HasNext() bool { - return this.index < this.length + return this.i+1 < len(this.nums) } ``` @@ -352,31 +346,27 @@ func (this *NestedIterator) HasNext() bool { */ class NestedIterator { - private vals: number[]; - private index: number; - + private nums: number[] = []; + private i = -1; constructor(nestedList: NestedInteger[]) { - this.index = 0; - this.vals = []; - this.dfs(nestedList); - } - - dfs(nestedList: NestedInteger[]) { - for (const v of nestedList) { - if (v.isInteger()) { - this.vals.push(v.getInteger()); - } else { - this.dfs(v.getList()); + const dfs = (ls: NestedInteger[]) => { + for (const x of ls) { + if (x.isInteger()) { + this.nums.push(x.getInteger()); + } else { + dfs(x.getList()); + } } - } + }; + dfs(nestedList); } hasNext(): boolean { - return this.index < this.vals.length; + return this.i + 1 < this.nums.length; } next(): number { - return this.vals[this.index++]; + return this.nums[++this.i]; } } @@ -397,8 +387,8 @@ class NestedIterator { // List(Vec) // } struct NestedIterator { - index: usize, - vals: Vec, + nums: Vec, + i: usize, } /** @@ -406,100 +396,30 @@ struct NestedIterator { * If you need a mutable reference, change it to `&mut self` instead. */ impl NestedIterator { - fn dfs(nestedList: &Vec, vals: &mut Vec) { - for ele in nestedList.iter() { - match ele { - NestedInteger::Int(val) => vals.push(*val), - NestedInteger::List(list) => Self::dfs(list, vals), - } - } - } - - fn new(nestedList: Vec) -> Self { - let mut vals = vec![]; - Self::dfs(&nestedList, &mut vals); - Self { vals, index: 0 } + fn new(nested_list: Vec) -> Self { + let mut nums = Vec::new(); + Self::dfs(&nested_list, &mut nums); + NestedIterator { nums, i: 0 } } fn next(&mut self) -> i32 { - let res = self.vals[self.index]; - self.index += 1; - res + let result = self.nums[self.i]; + self.i += 1; + result } fn has_next(&self) -> bool { - self.index < self.vals.len() + self.i < self.nums.len() } -} -``` - - - - - - -### Solution 2 - - - -#### Go - -```go -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * type NestedInteger struct { - * } - * - * // Return true if this NestedInteger holds a single integer, rather than a nested list. - * func (this NestedInteger) IsInteger() bool {} - * - * // Return the single integer that this NestedInteger holds, if it holds a single integer - * // The result is undefined if this NestedInteger holds a nested list - * // So before calling this method, you should have a check - * func (this NestedInteger) GetInteger() int {} - * - * // Set this NestedInteger to hold a single integer. - * func (n *NestedInteger) SetInteger(value int) {} - * - * // Set this NestedInteger to hold a nested list and adds a nested integer to it. - * func (this *NestedInteger) Add(elem NestedInteger) {} - * - * // Return the nested list that this NestedInteger holds, if it holds a nested list - * // The list length is zero if this NestedInteger holds a single integer - * // You can access NestedInteger's List element directly if you want to modify it - * func (this NestedInteger) GetList() []*NestedInteger {} - */ - -type NestedIterator struct { - nested *list.List -} - -func Constructor(nestedList []*NestedInteger) *NestedIterator { - nested := list.New() - for _, v := range nestedList { - nested.PushBack(v) - } - return &NestedIterator{nested: nested} -} - -func (this *NestedIterator) Next() int { - res := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - return res.GetInteger() -} - -func (this *NestedIterator) HasNext() bool { - for this.nested.Len() > 0 && !this.nested.Front().Value.(*NestedInteger).IsInteger() { - front := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - nodes := front.GetList() - for i := len(nodes) - 1; i >= 0; i-- { - this.nested.PushFront(nodes[i]) - } - } - return this.nested.Len() > 0 + fn dfs(nested_list: &Vec, nums: &mut Vec) { + for ni in nested_list { + match ni { + NestedInteger::Int(x) => nums.push(*x), + NestedInteger::List(list) => Self::dfs(list, nums), + } + } + } } ``` diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp index 69d86e084e52..dde245ec010a 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp @@ -19,30 +19,29 @@ class NestedIterator { public: NestedIterator(vector& nestedList) { - dfs(nestedList); + auto dfs = [&](auto&& dfs, vector& ls) -> void { + for (auto& x : ls) { + if (x.isInteger()) { + nums.push_back(x.getInteger()); + } else { + dfs(dfs, x.getList()); + } + } + }; + dfs(dfs, nestedList); } int next() { - return vals[cur++]; + return nums[++i]; } bool hasNext() { - return cur < vals.size(); + return i + 1 < nums.size(); } private: - vector vals; - int cur = 0; - - void dfs(vector& nestedList) { - for (auto& e : nestedList) { - if (e.isInteger()) { - vals.push_back(e.getInteger()); - } else { - dfs(e.getList()); - } - } - } + vector nums; + int i = -1; }; /** diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go index 231ed7a9e0f4..197f4c40cf88 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go @@ -25,32 +25,32 @@ */ type NestedIterator struct { - iterator []int - index, length int + nums []int + i int } func Constructor(nestedList []*NestedInteger) *NestedIterator { - result := make([]int, 0) - var traversal func(nodes []*NestedInteger) - traversal = func(nodes []*NestedInteger) { - for _, child := range nodes { - if child.IsInteger() { - result = append(result, child.GetInteger()) + var dfs func([]*NestedInteger) + nums := []int{} + i := -1 + dfs = func(ls []*NestedInteger) { + for _, x := range ls { + if x.IsInteger() { + nums = append(nums, x.GetInteger()) } else { - traversal(child.GetList()) + dfs(x.GetList()) } } } - traversal(nestedList) - return &NestedIterator{iterator: result, index: 0, length: len(result)} + dfs(nestedList) + return &NestedIterator{nums, i} } func (this *NestedIterator) Next() int { - res := this.iterator[this.index] - this.index++ - return res + this.i++ + return this.nums[this.i] } func (this *NestedIterator) HasNext() bool { - return this.index < this.length + return this.i+1 < len(this.nums) } \ No newline at end of file diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java index 04b6ca8ae518..128e938680a1 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java @@ -11,38 +11,34 @@ * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { - - private List vals; - - private Iterator cur; + private List nums = new ArrayList<>(); + private int i = -1; public NestedIterator(List nestedList) { - vals = new ArrayList<>(); dfs(nestedList); - cur = vals.iterator(); } @Override public Integer next() { - return cur.next(); + return nums.get(++i); } @Override public boolean hasNext() { - return cur.hasNext(); + return i + 1 < nums.size(); } - private void dfs(List nestedList) { - for (NestedInteger e : nestedList) { - if (e.isInteger()) { - vals.add(e.getInteger()); + private void dfs(List ls) { + for (var x : ls) { + if (x.isInteger()) { + nums.add(x.getInteger()); } else { - dfs(e.getList()); + dfs(x.getList()); } } } diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py index 54cc88ffca22..5f2cae542301 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py @@ -23,24 +23,23 @@ class NestedIterator: def __init__(self, nestedList: [NestedInteger]): - def dfs(nestedList): - for e in nestedList: - if e.isInteger(): - self.vals.append(e.getInteger()) + def dfs(ls): + for x in ls: + if x.isInteger(): + self.nums.append(x.getInteger()) else: - dfs(e.getList()) + dfs(x.getList()) - self.vals = [] + self.nums = [] + self.i = -1 dfs(nestedList) - self.cur = 0 def next(self) -> int: - res = self.vals[self.cur] - self.cur += 1 - return res + self.i += 1 + return self.nums[self.i] def hasNext(self) -> bool: - return self.cur < len(self.vals) + return self.i + 1 < len(self.nums) # Your NestedIterator object will be instantiated and called as such: diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs index abf739460a20..e0dc3fa5f760 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs @@ -4,8 +4,8 @@ // List(Vec) // } struct NestedIterator { - index: usize, - vals: Vec, + nums: Vec, + i: usize, } /** @@ -13,28 +13,28 @@ struct NestedIterator { * If you need a mutable reference, change it to `&mut self` instead. */ impl NestedIterator { - fn dfs(nestedList: &Vec, vals: &mut Vec) { - for ele in nestedList.iter() { - match ele { - NestedInteger::Int(val) => vals.push(*val), - NestedInteger::List(list) => Self::dfs(list, vals), - } - } - } - - fn new(nestedList: Vec) -> Self { - let mut vals = vec![]; - Self::dfs(&nestedList, &mut vals); - Self { vals, index: 0 } + fn new(nested_list: Vec) -> Self { + let mut nums = Vec::new(); + Self::dfs(&nested_list, &mut nums); + NestedIterator { nums, i: 0 } } fn next(&mut self) -> i32 { - let res = self.vals[self.index]; - self.index += 1; - res + let result = self.nums[self.i]; + self.i += 1; + result } fn has_next(&self) -> bool { - self.index < self.vals.len() + self.i < self.nums.len() + } + + fn dfs(nested_list: &Vec, nums: &mut Vec) { + for ni in nested_list { + match ni { + NestedInteger::Int(x) => nums.push(*x), + NestedInteger::List(list) => Self::dfs(list, nums), + } + } } } diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts index f838f8105312..99d5f2fd029d 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts @@ -38,31 +38,27 @@ */ class NestedIterator { - private vals: number[]; - private index: number; - + private nums: number[] = []; + private i = -1; constructor(nestedList: NestedInteger[]) { - this.index = 0; - this.vals = []; - this.dfs(nestedList); - } - - dfs(nestedList: NestedInteger[]) { - for (const v of nestedList) { - if (v.isInteger()) { - this.vals.push(v.getInteger()); - } else { - this.dfs(v.getList()); + const dfs = (ls: NestedInteger[]) => { + for (const x of ls) { + if (x.isInteger()) { + this.nums.push(x.getInteger()); + } else { + dfs(x.getList()); + } } - } + }; + dfs(nestedList); } hasNext(): boolean { - return this.index < this.vals.length; + return this.i + 1 < this.nums.length; } next(): number { - return this.vals[this.index++]; + return this.nums[++this.i]; } } diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution2.go b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution2.go deleted file mode 100644 index 0a7520dd9a26..000000000000 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution2.go +++ /dev/null @@ -1,55 +0,0 @@ -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * type NestedInteger struct { - * } - * - * // Return true if this NestedInteger holds a single integer, rather than a nested list. - * func (this NestedInteger) IsInteger() bool {} - * - * // Return the single integer that this NestedInteger holds, if it holds a single integer - * // The result is undefined if this NestedInteger holds a nested list - * // So before calling this method, you should have a check - * func (this NestedInteger) GetInteger() int {} - * - * // Set this NestedInteger to hold a single integer. - * func (n *NestedInteger) SetInteger(value int) {} - * - * // Set this NestedInteger to hold a nested list and adds a nested integer to it. - * func (this *NestedInteger) Add(elem NestedInteger) {} - * - * // Return the nested list that this NestedInteger holds, if it holds a nested list - * // The list length is zero if this NestedInteger holds a single integer - * // You can access NestedInteger's List element directly if you want to modify it - * func (this NestedInteger) GetList() []*NestedInteger {} - */ - -type NestedIterator struct { - nested *list.List -} - -func Constructor(nestedList []*NestedInteger) *NestedIterator { - nested := list.New() - for _, v := range nestedList { - nested.PushBack(v) - } - return &NestedIterator{nested: nested} -} - -func (this *NestedIterator) Next() int { - res := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - return res.GetInteger() -} - -func (this *NestedIterator) HasNext() bool { - for this.nested.Len() > 0 && !this.nested.Front().Value.(*NestedInteger).IsInteger() { - front := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - nodes := front.GetList() - for i := len(nodes) - 1; i >= 0; i-- { - this.nested.PushFront(nodes[i]) - } - } - return this.nested.Len() > 0 -} \ No newline at end of file diff --git a/solution/0300-0399/0342.Power of Four/README.md b/solution/0300-0399/0342.Power of Four/README.md index 1fb23b3b6308..1e71bac29bc3 100644 --- a/solution/0300-0399/0342.Power of Four/README.md +++ b/solution/0300-0399/0342.Power of Four/README.md @@ -63,7 +63,13 @@ tags: -### 方法一 +### 方法一:位运算 + +如果一个数是 4 的幂次方,那么这个数必须是大于 $0$ 的。不妨假设这个数是 $4^x$,即 $2^{2x}$,那么这个数的二进制表示中有且仅有一个 $1$,且这个 $1$ 出现在偶数位上。 + +因此,我们首先判断这个数是否大于 $0$,然后判断这个数是否是 $2^{2x}$,即 $n$ 与 $n-1$ 的按位与结果是否为 $0$,最后判断这个数的 $1$ 是否出现在偶数位上,即 $n$ 与 $\textit{0xAAAAAAAA}$ 的按位与结果是否为 $0$。如果这三个条件都满足,那么这个数就是 4 的幂次方。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 diff --git a/solution/0300-0399/0342.Power of Four/README_EN.md b/solution/0300-0399/0342.Power of Four/README_EN.md index 785bb147db19..d74f994dc6c3 100644 --- a/solution/0300-0399/0342.Power of Four/README_EN.md +++ b/solution/0300-0399/0342.Power of Four/README_EN.md @@ -49,7 +49,13 @@ tags: -### Solution 1 +### Solution 1: Bit Manipulation + +If a number is a power of 4, then it must be greater than $0$. Suppose this number is $4^x$, which is $2^{2x}$. Therefore, its binary representation has only one $1$, and this $1$ appears at an even position. + +First, we check if the number is greater than $0$. Then, we verify if the number is $2^{2x}$ by checking if the bitwise AND of $n$ and $n-1$ is $0$. Finally, we check if the $1$ appears at an even position by verifying if the bitwise AND of $n$ and $\textit{0xAAAAAAAA}$ is $0$. If all three conditions are met, then the number is a power of 4. + +The time complexity is $O(1)$, and the space complexity is $O(1)$. diff --git a/solution/0300-0399/0343.Integer Break/README.md b/solution/0300-0399/0343.Integer Break/README.md index e85a34a05c96..c2585a7c6eb4 100644 --- a/solution/0300-0399/0343.Integer Break/README.md +++ b/solution/0300-0399/0343.Integer Break/README.md @@ -53,15 +53,22 @@ tags: ### 方法一:动态规划 -我们定义 $dp[i]$ 表示正整数 $n$ 能获得的最大乘积,初始化 $dp[1] = 1$。答案即为 $dp[n]$。 +我们定义 $f[i]$ 表示正整数 $i$ 拆分后能获得的最大乘积,初始时 $f[1] = 1$。答案即为 $f[n]$。 -状态转移方程为: +考虑 $i$ 最后拆分出的数字 $j$,其中 $j \in [1, i)$。对于 $i$ 拆分出的数字 $j$,有两种情况: + +1. 将 $i$ 拆分成 $i - j$ 和 $j$ 的和,不继续拆分,此时乘积为 $(i - j) \times j$; +2. 将 $i$ 拆分成 $i - j$ 和 $j$ 的和,继续拆分,此时乘积为 $f[i - j] \times j$。 + +因此,我们可以得到状态转移方程: $$ -dp[i] = max(dp[i], dp[i - j] \times j, (i - j) \times j) \quad (j \in [0, i)) +f[i] = \max(f[i], f[i - j] \times j, (i - j) \times j) \quad (j \in [0, i)) $$ -时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为正整数 $n$。 +最后返回 $f[n]$ 即可。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为给定的正整数。 @@ -70,11 +77,11 @@ $$ ```python class Solution: def integerBreak(self, n: int) -> int: - dp = [1] * (n + 1) + f = [1] * (n + 1) for i in range(2, n + 1): for j in range(1, i): - dp[i] = max(dp[i], dp[i - j] * j, (i - j) * j) - return dp[n] + f[i] = max(f[i], f[i - j] * j, (i - j) * j) + return f[n] ``` #### Java @@ -82,14 +89,14 @@ class Solution: ```java class Solution { public int integerBreak(int n) { - int[] dp = new int[n + 1]; - dp[1] = 1; + int[] f = new int[n + 1]; + f[1] = 1; for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { - dp[i] = Math.max(Math.max(dp[i], dp[i - j] * j), (i - j) * j); + f[i] = Math.max(Math.max(f[i], f[i - j] * j), (i - j) * j); } } - return dp[n]; + return f[n]; } } ``` @@ -100,14 +107,14 @@ class Solution { class Solution { public: int integerBreak(int n) { - vector dp(n + 1); - dp[1] = 1; + vector f(n + 1); + f[1] = 1; for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { - dp[i] = max(max(dp[i], dp[i - j] * j), (i - j) * j); + f[i] = max({f[i], f[i - j] * j, (i - j) * j}); } } - return dp[n]; + return f[n]; } }; ``` @@ -116,14 +123,14 @@ public: ```go func integerBreak(n int) int { - dp := make([]int, n+1) - dp[1] = 1 + f := make([]int, n+1) + f[1] = 1 for i := 2; i <= n; i++ { for j := 1; j < i; j++ { - dp[i] = max(max(dp[i], dp[i-j]*j), (i-j)*j) + f[i] = max(max(f[i], f[i-j]*j), (i-j)*j) } } - return dp[n] + return f[n] } ``` @@ -131,13 +138,13 @@ func integerBreak(n int) int { ```ts function integerBreak(n: number): number { - let dp = new Array(n + 1).fill(1); + const f = Array(n + 1).fill(1); for (let i = 3; i <= n; i++) { for (let j = 1; j < i; j++) { - dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]); + f[i] = Math.max(f[i], j * (i - j), j * f[i - j]); } } - return dp.pop(); + return f[n]; } ``` @@ -146,11 +153,50 @@ function integerBreak(n: number): number { ```rust impl Solution { pub fn integer_break(n: i32) -> i32 { - if n < 4 { - return n - 1; + let n = n as usize; + let mut f = vec![0; n + 1]; + f[1] = 1; + for i in 2..=n { + for j in 1..i { + f[i] = f[i].max(f[i - j] * j).max((i - j) * j); + } + } + f[n] as i32 + } +} +``` + +#### JavaScript + +```js +/** + * @param {number} n + * @return {number} + */ +var integerBreak = function (n) { + const f = Array(n + 1).fill(1); + for (let i = 2; i <= n; ++i) { + for (let j = 1; j < i; ++j) { + f[i] = Math.max(f[i], f[i - j] * j, (i - j) * j); + } + } + return f[n]; +}; +``` + +#### C# + +```cs +public class Solution { + public int IntegerBreak(int n) { + int[] f = new int[n + 1]; + f[1] = 1; + for (int i = 2; i <= n; ++i) { + for (int j = 1; j < i; ++j) { + f[i] = Math.Max(Math.Max(f[i], f[i - j] * j), (i - j) * j); + } } - let count = (n - 2) / 3; - (3i32).pow(count as u32) * (n - count * 3) + return f[n]; } } ``` @@ -158,12 +204,18 @@ impl Solution { #### C ```c +#define max(a, b) (((a) > (b)) ? (a) : (b)) + int integerBreak(int n) { - if (n < 4) { - return n - 1; + int* f = (int*) malloc((n + 1) * sizeof(int)); + f[1] = 1; + for (int i = 2; i <= n; ++i) { + f[i] = 0; + for (int j = 1; j < i; ++j) { + f[i] = max(f[i], max(f[i - j] * j, (i - j) * j)); + } } - int count = (n - 2) / 3; - return pow(3, count) * (n - count * 3); + return f[n]; } ``` @@ -175,7 +227,7 @@ int integerBreak(int n) { ### 方法二:数学 -当 $n \lt 4$ 时,$n$ 不能拆分成至少两个正整数的和,因此 $n - 1$ 是最大乘积。当 $n \ge 4$ 时,我们尽可能多地拆分 $3$,当剩下的最后一段为 $4$ 时,我们将其拆分为 $2 + 2$,这样乘积最大。 +当 $n \lt 4$ 时,由于题目要求至少拆分成两个整数,因此 $n - 1$ 是最大乘积。当 $n \ge 4$ 时,我们尽可能多地拆分 $3$,当剩下的最后一段为 $4$ 时,我们将其拆分为 $2 + 2$,这样乘积最大。 时间复杂度 $O(1)$,空间复杂度 $O(1)$。 @@ -269,6 +321,81 @@ function integerBreak(n: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn integer_break(n: i32) -> i32 { + if n < 4 { + return n - 1; + } + match n % 3 { + 0 => return (3 as i32).pow((n / 3) as u32), + 1 => return (3 as i32).pow((n / 3 - 1) as u32) * 4, + _ => return (3 as i32).pow((n / 3) as u32) * 2, + } + } +} +``` + +#### JavaScript + +```js +/** + * @param {number} n + * @return {number} + */ +var integerBreak = function (n) { + if (n < 4) { + return n - 1; + } + const m = Math.floor(n / 3); + if (n % 3 == 0) { + return 3 ** m; + } + if (n % 3 == 1) { + return 3 ** (m - 1) * 4; + } + return 3 ** m * 2; +}; +``` + +#### C# + +```cs +public class Solution { + public int IntegerBreak(int n) { + if (n < 4) { + return n - 1; + } + if (n % 3 == 0) { + return (int)Math.Pow(3, n / 3); + } + if (n % 3 == 1) { + return (int)Math.Pow(3, n / 3 - 1) * 4; + } + return (int)Math.Pow(3, n / 3) * 2; + } +} +``` + +#### C + +```c +int integerBreak(int n) { + if (n < 4) { + return n - 1; + } + if (n % 3 == 0) { + return (int) pow(3, n / 3); + } + if (n % 3 == 1) { + return (int) pow(3, n / 3 - 1) * 4; + } + return (int) pow(3, n / 3) * 2; +} +``` + diff --git a/solution/0300-0399/0343.Integer Break/README_EN.md b/solution/0300-0399/0343.Integer Break/README_EN.md index c5da4dcec24a..8b3ffb7eff47 100644 --- a/solution/0300-0399/0343.Integer Break/README_EN.md +++ b/solution/0300-0399/0343.Integer Break/README_EN.md @@ -51,7 +51,24 @@ tags: -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i]$ as the maximum product that can be obtained by splitting the positive integer $i$, with an initial condition of $f[1] = 1$. The answer is $f[n]$. + +Consider the last number $j$ split from $i$, where $j \in [1, i)$. For the number $j$ split from $i$, there are two cases: + +1. Split $i$ into the sum of $i - j$ and $j$, without further splitting, where the product is $(i - j) \times j$; +2. Split $i$ into the sum of $i - j$ and $j$, and continue splitting, where the product is $f[i - j] \times j$. + +Therefore, we can derive the state transition equation: + +$$ +f[i] = \max(f[i], f[i - j] \times j, (i - j) \times j) \quad (j \in [0, i)) +$$ + +Finally, returning $f[n]$ will suffice. + +The time complexity is $O(n^2)$, and the space complexity is $O(n)$. Here, $n$ is the given positive integer. @@ -60,11 +77,11 @@ tags: ```python class Solution: def integerBreak(self, n: int) -> int: - dp = [1] * (n + 1) + f = [1] * (n + 1) for i in range(2, n + 1): for j in range(1, i): - dp[i] = max(dp[i], dp[i - j] * j, (i - j) * j) - return dp[n] + f[i] = max(f[i], f[i - j] * j, (i - j) * j) + return f[n] ``` #### Java @@ -72,14 +89,14 @@ class Solution: ```java class Solution { public int integerBreak(int n) { - int[] dp = new int[n + 1]; - dp[1] = 1; + int[] f = new int[n + 1]; + f[1] = 1; for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { - dp[i] = Math.max(Math.max(dp[i], dp[i - j] * j), (i - j) * j); + f[i] = Math.max(Math.max(f[i], f[i - j] * j), (i - j) * j); } } - return dp[n]; + return f[n]; } } ``` @@ -90,14 +107,14 @@ class Solution { class Solution { public: int integerBreak(int n) { - vector dp(n + 1); - dp[1] = 1; + vector f(n + 1); + f[1] = 1; for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { - dp[i] = max(max(dp[i], dp[i - j] * j), (i - j) * j); + f[i] = max({f[i], f[i - j] * j, (i - j) * j}); } } - return dp[n]; + return f[n]; } }; ``` @@ -106,14 +123,14 @@ public: ```go func integerBreak(n int) int { - dp := make([]int, n+1) - dp[1] = 1 + f := make([]int, n+1) + f[1] = 1 for i := 2; i <= n; i++ { for j := 1; j < i; j++ { - dp[i] = max(max(dp[i], dp[i-j]*j), (i-j)*j) + f[i] = max(max(f[i], f[i-j]*j), (i-j)*j) } } - return dp[n] + return f[n] } ``` @@ -121,13 +138,13 @@ func integerBreak(n int) int { ```ts function integerBreak(n: number): number { - let dp = new Array(n + 1).fill(1); + const f = Array(n + 1).fill(1); for (let i = 3; i <= n; i++) { for (let j = 1; j < i; j++) { - dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]); + f[i] = Math.max(f[i], j * (i - j), j * f[i - j]); } } - return dp.pop(); + return f[n]; } ``` @@ -136,11 +153,50 @@ function integerBreak(n: number): number { ```rust impl Solution { pub fn integer_break(n: i32) -> i32 { - if n < 4 { - return n - 1; + let n = n as usize; + let mut f = vec![0; n + 1]; + f[1] = 1; + for i in 2..=n { + for j in 1..i { + f[i] = f[i].max(f[i - j] * j).max((i - j) * j); + } + } + f[n] as i32 + } +} +``` + +#### JavaScript + +```js +/** + * @param {number} n + * @return {number} + */ +var integerBreak = function (n) { + const f = Array(n + 1).fill(1); + for (let i = 2; i <= n; ++i) { + for (let j = 1; j < i; ++j) { + f[i] = Math.max(f[i], f[i - j] * j, (i - j) * j); + } + } + return f[n]; +}; +``` + +#### C# + +```cs +public class Solution { + public int IntegerBreak(int n) { + int[] f = new int[n + 1]; + f[1] = 1; + for (int i = 2; i <= n; ++i) { + for (int j = 1; j < i; ++j) { + f[i] = Math.Max(Math.Max(f[i], f[i - j] * j), (i - j) * j); + } } - let count = (n - 2) / 3; - (3i32).pow(count as u32) * (n - count * 3) + return f[n]; } } ``` @@ -148,12 +204,18 @@ impl Solution { #### C ```c +#define max(a, b) (((a) > (b)) ? (a) : (b)) + int integerBreak(int n) { - if (n < 4) { - return n - 1; + int* f = (int*) malloc((n + 1) * sizeof(int)); + f[1] = 1; + for (int i = 2; i <= n; ++i) { + f[i] = 0; + for (int j = 1; j < i; ++j) { + f[i] = max(f[i], max(f[i - j] * j, (i - j) * j)); + } } - int count = (n - 2) / 3; - return pow(3, count) * (n - count * 3); + return f[n]; } ``` @@ -163,7 +225,11 @@ int integerBreak(int n) { -### Solution 2 +### Solution 1: Mathematics + +When $n < 4$, since the problem requires splitting into at least two integers, $n - 1$ yields the maximum product. When $n \geq 4$, we split into as many $3$s as possible. If the last segment remaining is $4$, we split it into $2 + 2$ for the maximum product. + +The time complexity is $O(1)$, and the space complexity is $O(1)$. @@ -255,6 +321,81 @@ function integerBreak(n: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn integer_break(n: i32) -> i32 { + if n < 4 { + return n - 1; + } + match n % 3 { + 0 => return (3 as i32).pow((n / 3) as u32), + 1 => return (3 as i32).pow((n / 3 - 1) as u32) * 4, + _ => return (3 as i32).pow((n / 3) as u32) * 2, + } + } +} +``` + +#### JavaScript + +```js +/** + * @param {number} n + * @return {number} + */ +var integerBreak = function (n) { + if (n < 4) { + return n - 1; + } + const m = Math.floor(n / 3); + if (n % 3 == 0) { + return 3 ** m; + } + if (n % 3 == 1) { + return 3 ** (m - 1) * 4; + } + return 3 ** m * 2; +}; +``` + +#### C# + +```cs +public class Solution { + public int IntegerBreak(int n) { + if (n < 4) { + return n - 1; + } + if (n % 3 == 0) { + return (int)Math.Pow(3, n / 3); + } + if (n % 3 == 1) { + return (int)Math.Pow(3, n / 3 - 1) * 4; + } + return (int)Math.Pow(3, n / 3) * 2; + } +} +``` + +#### C + +```c +int integerBreak(int n) { + if (n < 4) { + return n - 1; + } + if (n % 3 == 0) { + return (int) pow(3, n / 3); + } + if (n % 3 == 1) { + return (int) pow(3, n / 3 - 1) * 4; + } + return (int) pow(3, n / 3) * 2; +} +``` + diff --git a/solution/0300-0399/0343.Integer Break/Solution.c b/solution/0300-0399/0343.Integer Break/Solution.c index 2cecd56a0f62..0dc021ee16f1 100644 --- a/solution/0300-0399/0343.Integer Break/Solution.c +++ b/solution/0300-0399/0343.Integer Break/Solution.c @@ -1,7 +1,13 @@ +#define max(a, b) (((a) > (b)) ? (a) : (b)) + int integerBreak(int n) { - if (n < 4) { - return n - 1; + int* f = (int*) malloc((n + 1) * sizeof(int)); + f[1] = 1; + for (int i = 2; i <= n; ++i) { + f[i] = 0; + for (int j = 1; j < i; ++j) { + f[i] = max(f[i], max(f[i - j] * j, (i - j) * j)); + } } - int count = (n - 2) / 3; - return pow(3, count) * (n - count * 3); + return f[n]; } \ No newline at end of file diff --git a/solution/0300-0399/0343.Integer Break/Solution.cpp b/solution/0300-0399/0343.Integer Break/Solution.cpp index 6ceba393ee4f..14722f3698d0 100644 --- a/solution/0300-0399/0343.Integer Break/Solution.cpp +++ b/solution/0300-0399/0343.Integer Break/Solution.cpp @@ -1,13 +1,13 @@ class Solution { public: int integerBreak(int n) { - vector dp(n + 1); - dp[1] = 1; + vector f(n + 1); + f[1] = 1; for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { - dp[i] = max(max(dp[i], dp[i - j] * j), (i - j) * j); + f[i] = max({f[i], f[i - j] * j, (i - j) * j}); } } - return dp[n]; + return f[n]; } }; \ No newline at end of file diff --git a/solution/0300-0399/0343.Integer Break/Solution.cs b/solution/0300-0399/0343.Integer Break/Solution.cs new file mode 100644 index 000000000000..e4cb8e81bb0b --- /dev/null +++ b/solution/0300-0399/0343.Integer Break/Solution.cs @@ -0,0 +1,12 @@ +public class Solution { + public int IntegerBreak(int n) { + int[] f = new int[n + 1]; + f[1] = 1; + for (int i = 2; i <= n; ++i) { + for (int j = 1; j < i; ++j) { + f[i] = Math.Max(Math.Max(f[i], f[i - j] * j), (i - j) * j); + } + } + return f[n]; + } +} \ No newline at end of file diff --git a/solution/0300-0399/0343.Integer Break/Solution.go b/solution/0300-0399/0343.Integer Break/Solution.go index c2de2799d04e..cc2818966521 100644 --- a/solution/0300-0399/0343.Integer Break/Solution.go +++ b/solution/0300-0399/0343.Integer Break/Solution.go @@ -1,10 +1,10 @@ func integerBreak(n int) int { - dp := make([]int, n+1) - dp[1] = 1 + f := make([]int, n+1) + f[1] = 1 for i := 2; i <= n; i++ { for j := 1; j < i; j++ { - dp[i] = max(max(dp[i], dp[i-j]*j), (i-j)*j) + f[i] = max(max(f[i], f[i-j]*j), (i-j)*j) } } - return dp[n] + return f[n] } \ No newline at end of file diff --git a/solution/0300-0399/0343.Integer Break/Solution.java b/solution/0300-0399/0343.Integer Break/Solution.java index ebc48c40f008..923f4f4811de 100644 --- a/solution/0300-0399/0343.Integer Break/Solution.java +++ b/solution/0300-0399/0343.Integer Break/Solution.java @@ -1,12 +1,12 @@ class Solution { public int integerBreak(int n) { - int[] dp = new int[n + 1]; - dp[1] = 1; + int[] f = new int[n + 1]; + f[1] = 1; for (int i = 2; i <= n; ++i) { for (int j = 1; j < i; ++j) { - dp[i] = Math.max(Math.max(dp[i], dp[i - j] * j), (i - j) * j); + f[i] = Math.max(Math.max(f[i], f[i - j] * j), (i - j) * j); } } - return dp[n]; + return f[n]; } } \ No newline at end of file diff --git a/solution/0300-0399/0343.Integer Break/Solution.js b/solution/0300-0399/0343.Integer Break/Solution.js new file mode 100644 index 000000000000..34b210f40172 --- /dev/null +++ b/solution/0300-0399/0343.Integer Break/Solution.js @@ -0,0 +1,13 @@ +/** + * @param {number} n + * @return {number} + */ +var integerBreak = function (n) { + const f = Array(n + 1).fill(1); + for (let i = 2; i <= n; ++i) { + for (let j = 1; j < i; ++j) { + f[i] = Math.max(f[i], f[i - j] * j, (i - j) * j); + } + } + return f[n]; +}; diff --git a/solution/0300-0399/0343.Integer Break/Solution.py b/solution/0300-0399/0343.Integer Break/Solution.py index faebd8134990..5c7fb26cd7fe 100644 --- a/solution/0300-0399/0343.Integer Break/Solution.py +++ b/solution/0300-0399/0343.Integer Break/Solution.py @@ -1,7 +1,7 @@ class Solution: def integerBreak(self, n: int) -> int: - dp = [1] * (n + 1) + f = [1] * (n + 1) for i in range(2, n + 1): for j in range(1, i): - dp[i] = max(dp[i], dp[i - j] * j, (i - j) * j) - return dp[n] + f[i] = max(f[i], f[i - j] * j, (i - j) * j) + return f[n] diff --git a/solution/0300-0399/0343.Integer Break/Solution.rs b/solution/0300-0399/0343.Integer Break/Solution.rs index cbd12dbf0bbf..2256aeee28fa 100644 --- a/solution/0300-0399/0343.Integer Break/Solution.rs +++ b/solution/0300-0399/0343.Integer Break/Solution.rs @@ -1,9 +1,13 @@ impl Solution { pub fn integer_break(n: i32) -> i32 { - if n < 4 { - return n - 1; + let n = n as usize; + let mut f = vec![0; n + 1]; + f[1] = 1; + for i in 2..=n { + for j in 1..i { + f[i] = f[i].max(f[i - j] * j).max((i - j) * j); + } } - let count = (n - 2) / 3; - (3i32).pow(count as u32) * (n - count * 3) + f[n] as i32 } } diff --git a/solution/0300-0399/0343.Integer Break/Solution.ts b/solution/0300-0399/0343.Integer Break/Solution.ts index bedef9889f27..5239b8eb68fd 100644 --- a/solution/0300-0399/0343.Integer Break/Solution.ts +++ b/solution/0300-0399/0343.Integer Break/Solution.ts @@ -1,9 +1,9 @@ function integerBreak(n: number): number { - let dp = new Array(n + 1).fill(1); + const f = Array(n + 1).fill(1); for (let i = 3; i <= n; i++) { for (let j = 1; j < i; j++) { - dp[i] = Math.max(dp[i], j * (i - j), j * dp[i - j]); + f[i] = Math.max(f[i], j * (i - j), j * f[i - j]); } } - return dp.pop(); + return f[n]; } diff --git a/solution/0300-0399/0343.Integer Break/Solution2.c b/solution/0300-0399/0343.Integer Break/Solution2.c new file mode 100644 index 000000000000..46a8519dcd79 --- /dev/null +++ b/solution/0300-0399/0343.Integer Break/Solution2.c @@ -0,0 +1,12 @@ +int integerBreak(int n) { + if (n < 4) { + return n - 1; + } + if (n % 3 == 0) { + return (int) pow(3, n / 3); + } + if (n % 3 == 1) { + return (int) pow(3, n / 3 - 1) * 4; + } + return (int) pow(3, n / 3) * 2; +} \ No newline at end of file diff --git a/solution/0300-0399/0343.Integer Break/Solution2.cs b/solution/0300-0399/0343.Integer Break/Solution2.cs new file mode 100644 index 000000000000..77a5a6375613 --- /dev/null +++ b/solution/0300-0399/0343.Integer Break/Solution2.cs @@ -0,0 +1,14 @@ +public class Solution { + public int IntegerBreak(int n) { + if (n < 4) { + return n - 1; + } + if (n % 3 == 0) { + return (int)Math.Pow(3, n / 3); + } + if (n % 3 == 1) { + return (int)Math.Pow(3, n / 3 - 1) * 4; + } + return (int)Math.Pow(3, n / 3) * 2; + } +} \ No newline at end of file diff --git a/solution/0300-0399/0343.Integer Break/Solution2.js b/solution/0300-0399/0343.Integer Break/Solution2.js new file mode 100644 index 000000000000..c1d5a9b5debc --- /dev/null +++ b/solution/0300-0399/0343.Integer Break/Solution2.js @@ -0,0 +1,17 @@ +/** + * @param {number} n + * @return {number} + */ +var integerBreak = function (n) { + if (n < 4) { + return n - 1; + } + const m = Math.floor(n / 3); + if (n % 3 == 0) { + return 3 ** m; + } + if (n % 3 == 1) { + return 3 ** (m - 1) * 4; + } + return 3 ** m * 2; +}; diff --git a/solution/0300-0399/0343.Integer Break/Solution2.rs b/solution/0300-0399/0343.Integer Break/Solution2.rs new file mode 100644 index 000000000000..031f1f1ad569 --- /dev/null +++ b/solution/0300-0399/0343.Integer Break/Solution2.rs @@ -0,0 +1,12 @@ +impl Solution { + pub fn integer_break(n: i32) -> i32 { + if n < 4 { + return n - 1; + } + match n % 3 { + 0 => return (3 as i32).pow((n / 3) as u32), + 1 => return (3 as i32).pow((n / 3 - 1) as u32) * 4, + _ => return (3 as i32).pow((n / 3) as u32) * 2, + } + } +} diff --git a/solution/0300-0399/0347.Top K Frequent Elements/README.md b/solution/0300-0399/0347.Top K Frequent Elements/README.md index 0a21210a0545..0ce1273eec34 100644 --- a/solution/0300-0399/0347.Top K Frequent Elements/README.md +++ b/solution/0300-0399/0347.Top K Frequent Elements/README.md @@ -62,7 +62,7 @@ tags: ### 方法一:哈希表 + 优先队列(小根堆) -我们可以使用一个哈希表 $\text{cnt}$ 统计每个元素出现的次数,然后使用一个小根堆(优先队列)来保存前 $k$ 个高频元素。 +我们可以使用一个哈希表 $\textit{cnt}$ 统计每个元素出现的次数,然后使用一个小根堆(优先队列)来保存前 $k$ 个高频元素。 我们首先遍历一遍数组,统计每个元素出现的次数,然后遍历哈希表,将元素和出现次数存入小根堆中。如果小根堆的大小超过了 $k$,我们就将堆顶元素弹出,保证堆的大小始终为 $k$。 diff --git a/solution/0300-0399/0347.Top K Frequent Elements/README_EN.md b/solution/0300-0399/0347.Top K Frequent Elements/README_EN.md index c72b5148eb7d..77a311335c84 100644 --- a/solution/0300-0399/0347.Top K Frequent Elements/README_EN.md +++ b/solution/0300-0399/0347.Top K Frequent Elements/README_EN.md @@ -54,7 +54,7 @@ tags: ### Solution 1: Hash Table + Priority Queue (Min Heap) -We can use a hash table $\text{cnt}$ to count the occurrence of each element, and then use a min heap (priority queue) to store the top $k$ frequent elements. +We can use a hash table $\textit{cnt}$ to count the occurrence of each element, and then use a min heap (priority queue) to store the top $k$ frequent elements. First, we traverse the array once to count the occurrence of each element. Then, we iterate through the hash table, storing each element and its count into the min heap. If the size of the min heap exceeds $k$, we pop the top element of the heap to ensure the heap size is always $k$. diff --git a/solution/0300-0399/0350.Intersection of Two Arrays II/README.md b/solution/0300-0399/0350.Intersection of Two Arrays II/README.md index 4e7a31d0fa6e..704fdabdeed8 100644 --- a/solution/0300-0399/0350.Intersection of Two Arrays II/README.md +++ b/solution/0300-0399/0350.Intersection of Two Arrays II/README.md @@ -64,11 +64,11 @@ tags: ### 方法一:哈希表 -我们可以用一个哈希表 $\text{cnt}$ 统计数组 $\text{nums1}$ 中每个元素出现的次数,然后遍历数组 $\text{nums2}$,如果元素 $x$ 在 $\text{cnt}$ 中,并且 $x$ 的出现次数大于 $0$,那么将 $x$ 加入答案,然后将 $x$ 的出现次数减一。 +我们可以用一个哈希表 $\textit{cnt}$ 统计数组 $\textit{nums1}$ 中每个元素出现的次数,然后遍历数组 $\textit{nums2}$,如果元素 $x$ 在 $\textit{cnt}$ 中,并且 $x$ 的出现次数大于 $0$,那么将 $x$ 加入答案,然后将 $x$ 的出现次数减一。 遍历结束后,返回答案数组即可。 -时间复杂度 $O(m + n)$,空间复杂度 $O(m)$。其中 $m$ 和 $n$ 分别是数组 $\text{nums1}$ 和 $\text{nums2}$ 的长度。 +时间复杂度 $O(m + n)$,空间复杂度 $O(m)$。其中 $m$ 和 $n$ 分别是数组 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度。 diff --git a/solution/0300-0399/0350.Intersection of Two Arrays II/README_EN.md b/solution/0300-0399/0350.Intersection of Two Arrays II/README_EN.md index cbbb237e372a..6f88a1410780 100644 --- a/solution/0300-0399/0350.Intersection of Two Arrays II/README_EN.md +++ b/solution/0300-0399/0350.Intersection of Two Arrays II/README_EN.md @@ -63,11 +63,11 @@ tags: ### Solution 1: Hash Table -We can use a hash table $\text{cnt}$ to count the occurrences of each element in the array $\text{nums1}$. Then, we iterate through the array $\text{nums2}$. If an element $x$ is in $\text{cnt}$ and the occurrence of $x$ is greater than $0$, we add $x$ to the answer and then decrement the occurrence of $x$ by one. +We can use a hash table $\textit{cnt}$ to count the occurrences of each element in the array $\textit{nums1}$. Then, we iterate through the array $\textit{nums2}$. If an element $x$ is in $\textit{cnt}$ and the occurrence of $x$ is greater than $0$, we add $x$ to the answer and then decrement the occurrence of $x$ by one. After the iteration is finished, we return the answer array. -The time complexity is $O(m + n)$, and the space complexity is $O(m)$. Here, $m$ and $n$ are the lengths of the arrays $\text{nums1}$ and $\text{nums2}$, respectively. +The time complexity is $O(m + n)$, and the space complexity is $O(m)$. Here, $m$ and $n$ are the lengths of the arrays $\textit{nums1}$ and $\textit{nums2}$, respectively. diff --git a/solution/0300-0399/0364.Nested List Weight Sum II/README.md b/solution/0300-0399/0364.Nested List Weight Sum II/README.md index 863445b2ff5e..b211f0779c41 100644 --- a/solution/0300-0399/0364.Nested List Weight Sum II/README.md +++ b/solution/0300-0399/0364.Nested List Weight Sum II/README.md @@ -64,31 +64,31 @@ tags: ### 方法一:DFS -我们不妨假设整数分别为 $a_1, a_2, \cdots, a_n$,它们的深度分别为 $d_1, d_2, \cdots, d_n$,最大深度为 $\text{maxDepth}$,那么答案就是: +我们不妨假设整数分别为 $a_1, a_2, \cdots, a_n$,它们的深度分别为 $d_1, d_2, \cdots, d_n$,最大深度为 $\textit{maxDepth}$,那么答案就是: $$ -a_1 \times \text{maxDepth} - a_1 \times d_1 + a_1 + a_2 \times \text{maxDepth} - a_2 \times d_2 + a_2 + \cdots + a_n \times \text{maxDepth} - a_n \times d_n + a_n +a_1 \times \textit{maxDepth} - a_1 \times d_1 + a_1 + a_2 \times \textit{maxDepth} - a_2 \times d_2 + a_2 + \cdots + a_n \times \textit{maxDepth} - a_n \times d_n + a_n $$ 即: $$ -(\text{maxDepth} + 1) \times (a_1 + a_2 + \cdots + a_n) - (a_1 \times d_1 + a_2 \times d_2 + \cdots + a_n \times d_n) +(\textit{maxDepth} + 1) \times (a_1 + a_2 + \cdots + a_n) - (a_1 \times d_1 + a_2 \times d_2 + \cdots + a_n \times d_n) $$ 如果我们记所有整数的和为 $s$,所有整数乘以深度的和为 $ws$,那么答案就是: $$ -(\text{maxDepth} + 1) \times s - ws +(\textit{maxDepth} + 1) \times s - ws $$ 因此,我们设计一个函数 $dfs(x, d)$,表示从 $x$ 开始,深度为 $d$ 开始搜索,函数 $dfs(x, d)$ 的执行过程如下: -- 我们先更新 $\text{maxDepth} = \max(\text{maxDepth}, d)$; +- 我们先更新 $\textit{maxDepth} = \max(\textit{maxDepth}, d)$; - 如果 $x$ 是一个整数,那么我们更新 $s = s + x$, $ws = ws + x \times d$; - 否则,我们递归地遍历 $x$ 的每一个元素 $y$,调用 $dfs(y, d + 1)$。 -我们遍历整个列表,对于每一个元素 $x$,我们调用 $dfs(x, 1)$,最终返回 $(\text{maxDepth} + 1) \times s - ws$ 即可。 +我们遍历整个列表,对于每一个元素 $x$,我们调用 $dfs(x, 1)$,最终返回 $(\textit{maxDepth} + 1) \times s - ws$ 即可。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为整数的个数。 diff --git a/solution/0300-0399/0364.Nested List Weight Sum II/README_EN.md b/solution/0300-0399/0364.Nested List Weight Sum II/README_EN.md index cb1f774da547..4ca8f0301878 100644 --- a/solution/0300-0399/0364.Nested List Weight Sum II/README_EN.md +++ b/solution/0300-0399/0364.Nested List Weight Sum II/README_EN.md @@ -62,31 +62,31 @@ tags: ### Solution 1: DFS -Let's assume the integers are $a_1, a_2, \cdots, a_n$, their depths are $d_1, d_2, \cdots, d_n$, the maximum depth is $\text{maxDepth}$, then the answer is: +Let's assume the integers are $a_1, a_2, \cdots, a_n$, their depths are $d_1, d_2, \cdots, d_n$, the maximum depth is $\textit{maxDepth}$, then the answer is: $$ -a_1 \times \text{maxDepth} - a_1 \times d_1 + a_1 + a_2 \times \text{maxDepth} - a_2 \times d_2 + a_2 + \cdots + a_n \times \text{maxDepth} - a_n \times d_n + a_n +a_1 \times \textit{maxDepth} - a_1 \times d_1 + a_1 + a_2 \times \textit{maxDepth} - a_2 \times d_2 + a_2 + \cdots + a_n \times \textit{maxDepth} - a_n \times d_n + a_n $$ which is: $$ -(\text{maxDepth} + 1) \times (a_1 + a_2 + \cdots + a_n) - (a_1 \times d_1 + a_2 \times d_2 + \cdots + a_n \times d_n) +(\textit{maxDepth} + 1) \times (a_1 + a_2 + \cdots + a_n) - (a_1 \times d_1 + a_2 \times d_2 + \cdots + a_n \times d_n) $$ If we denote the sum of all integers as $s$, and the sum of each integer multiplied by its depth as $ws$, then the answer is: $$ -(\text{maxDepth} + 1) \times s - ws +(\textit{maxDepth} + 1) \times s - ws $$ Therefore, we design a function $dfs(x, d)$, which starts searching from $x$ with depth $d$. The execution process of $dfs(x, d)$ is as follows: -- We first update $\text{maxDepth} = \max(\text{maxDepth}, d)$; +- We first update $\textit{maxDepth} = \max(\textit{maxDepth}, d)$; - If $x$ is an integer, then we update $s = s + x$, $ws = ws + x \times d$; - Otherwise, we recursively traverse each element $y$ of $x$, and call $dfs(y, d + 1)$. -We traverse the entire list, for each element $x$, we call $dfs(x, 1)$, and finally return $(\text{maxDepth} + 1) \times s - ws$. +We traverse the entire list, for each element $x$, we call $dfs(x, 1)$, and finally return $(\textit{maxDepth} + 1) \times s - ws$. The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the number of integers. diff --git a/solution/0300-0399/0365.Water and Jug Problem/README.md b/solution/0300-0399/0365.Water and Jug Problem/README.md index 47f5ea7fa8c2..7cc5f30f350c 100644 --- a/solution/0300-0399/0365.Water and Jug Problem/README.md +++ b/solution/0300-0399/0365.Water and Jug Problem/README.md @@ -76,7 +76,7 @@ tags: ### 方法一:DFS -我们不妨记 $\text{jug1Capacity}$ 为 $x$, $\text{jug2Capacity}$ 为 $y$, $\text{targetCapacity}$ 为 $z$。 +我们不妨记 $\textit{jug1Capacity}$ 为 $x$, $\textit{jug2Capacity}$ 为 $y$, $\textit{targetCapacity}$ 为 $z$。 接下来,我们设计一个函数 $dfs(i, j)$,表示当前 $jug1$ 中有 $i$ 升水,$jug2$ 中有 $j$ 升水,是否可以得到 $z$ 升水。 @@ -89,7 +89,7 @@ tags: 答案即为 $dfs(0, 0)$。 -时间复杂度 $O(x + y)$,空间复杂度 $O(x + y)$。其中 $x$ 和 $y$ 分别为 $\text{jug1Capacity}$ 和 $\text{jug2Capacity}$。 +时间复杂度 $O(x + y)$,空间复杂度 $O(x + y)$。其中 $x$ 和 $y$ 分别为 $\textit{jug1Capacity}$ 和 $\textit{jug2Capacity}$。 diff --git a/solution/0300-0399/0379.Design Phone Directory/README.md b/solution/0300-0399/0379.Design Phone Directory/README.md index 1b671e581f3d..02ffb8f3b06a 100644 --- a/solution/0300-0399/0379.Design Phone Directory/README.md +++ b/solution/0300-0399/0379.Design Phone Directory/README.md @@ -20,41 +20,37 @@ tags: -

    设计一个电话目录管理系统,让它支持以下功能:

    +

    设计一个电话目录管理系统,一开始有 maxNumbers 个位置能够储存号码。系统应该存储号码,检查某个位置是否为空,并清空给定的位置。

    -
      -
    1. get: 分配给用户一个未被使用的电话号码,获取失败请返回 -1
    2. -
    3. check: 检查指定的电话号码是否被使用
    4. -
    5. release: 释放掉一个电话号码,使其能够重新被分配
    6. -
    +

    实现 PhoneDirectory 类:

    -

     

    - -

    示例:

    - -
    // 初始化电话目录,包括 3 个电话号码:0,1 和 2。
    -PhoneDirectory directory = new PhoneDirectory(3);
    -
    -// 可以返回任意未分配的号码,这里我们假设它返回 0。
    -directory.get();
    -
    -// 假设,函数返回 1。
    -directory.get();
    -
    -// 号码 2 未分配,所以返回为 true。
    -directory.check(2);
    -
    -// 返回 2,分配后,只剩一个号码未被分配。
    -directory.get();
    -
    -// 此时,号码 2 已经被分配,所以返回 false。
    -directory.check(2);
    +
      +
    • PhoneDirectory(int maxNumbers) 电话目录初始有 maxNumbers 个可用位置。
    • +
    • int get() 提供一个未分配给任何人的号码。如果没有可用号码则返回 -1
    • +
    • bool check(int number) 如果位置 number 可用返回 true 否则返回 false
    • +
    • void release(int number) 回收或释放位置 number
    • +
    -// 释放号码 2,将该号码变回未分配状态。 -directory.release(2); +

     

    -// 号码 2 现在是未分配状态,所以返回 true。 -directory.check(2); +

    示例 1:

    + +
    +输入:
    +["PhoneDirectory", "get", "get", "check", "get", "check", "release", "check"]
    +[[3], [], [], [2], [], [2], [2], [2]]
    +输出:
    +[null, 0, 1, true, 2, false, null, true]
    +
    +解释:
    +PhoneDirectory phoneDirectory = new PhoneDirectory(3);
    +phoneDirectory.get();      // 它可以返回任意可用的数字。这里我们假设它返回 0。
    +phoneDirectory.get();      // 假设它返回 1。
    +phoneDirectory.check(2);   // 数字 2 可用,所以返回 true。
    +phoneDirectory.get();      // 返回剩下的唯一一个数字 2。
    +phoneDirectory.check(2);   // 数字 2 不再可用,所以返回 false。
    +phoneDirectory.release(2); // 将数字 2 释放回号码池。
    +phoneDirectory.check(2);   // 数字 2 重新可用,返回 true。
     

     

    @@ -62,9 +58,9 @@ directory.check(2);

    提示:

      -
    • 1 <= maxNumbers <= 10^4
    • +
    • 1 <= maxNumbers <= 104
    • 0 <= number < maxNumbers
    • -
    • 调用方法的总数处于区间 [0 - 20000] 之内
    • +
    • getcheck 和 release 最多被调用 2 * 104 次。
    diff --git a/solution/0300-0399/0391.Perfect Rectangle/README.md b/solution/0300-0399/0391.Perfect Rectangle/README.md index c69b02149e24..0292de82c3f3 100644 --- a/solution/0300-0399/0391.Perfect Rectangle/README.md +++ b/solution/0300-0399/0391.Perfect Rectangle/README.md @@ -51,7 +51,8 @@ tags:
    • 1 <= rectangles.length <= 2 * 104
    • rectangles[i].length == 4
    • -
    • -105 <= xi, yi, ai, bi <= 105
    • +
    • -105 <= xi < ai <= 105
    • +
    • -105 <= yi < bi <= 105
    diff --git a/solution/0300-0399/0391.Perfect Rectangle/README_EN.md b/solution/0300-0399/0391.Perfect Rectangle/README_EN.md index f10a51d19028..6c770c7548d7 100644 --- a/solution/0300-0399/0391.Perfect Rectangle/README_EN.md +++ b/solution/0300-0399/0391.Perfect Rectangle/README_EN.md @@ -52,7 +52,8 @@ tags:
    • 1 <= rectangles.length <= 2 * 104
    • rectangles[i].length == 4
    • -
    • -105 <= xi, yi, ai, bi <= 105
    • +
    • -105 <= xi < ai <= 105
    • +
    • -105 <= yi < bi <= 105
    diff --git a/solution/0400-0499/0416.Partition Equal Subset Sum/README.md b/solution/0400-0499/0416.Partition Equal Subset Sum/README.md index 11b26eb1296c..fd4551f364ff 100644 --- a/solution/0400-0499/0416.Partition Equal Subset Sum/README.md +++ b/solution/0400-0499/0416.Partition Equal Subset Sum/README.md @@ -60,7 +60,7 @@ tags: 考虑 $f[i][j]$,如果我们选取了第 $i$ 个数 $x$,那么 $f[i][j] = f[i - 1][j - x]$;如果我们没有选取第 $i$ 个数 $x$,那么 $f[i][j] = f[i - 1][j]$。因此状态转移方程为: $$ -f[i][j] = f[i - 1][j] \text{ or } f[i - 1][j - x] \text{ if } j \geq x +f[i][j] = f[i - 1][j] \textit{ or } f[i - 1][j - x] \textit{ if } j \geq x $$ 最终答案为 $f[n][m]$。 diff --git a/solution/0400-0499/0416.Partition Equal Subset Sum/README_EN.md b/solution/0400-0499/0416.Partition Equal Subset Sum/README_EN.md index 1138a5a641ab..1b1a01a59566 100644 --- a/solution/0400-0499/0416.Partition Equal Subset Sum/README_EN.md +++ b/solution/0400-0499/0416.Partition Equal Subset Sum/README_EN.md @@ -59,7 +59,7 @@ We define $f[i][j]$ to represent whether it is possible to select several number Considering $f[i][j]$, if we select the $i$-th number $x$, then $f[i][j] = f[i - 1][j - x]$. If we do not select the $i$-th number $x$, then $f[i][j] = f[i - 1][j]$. Therefore, the state transition equation is: $$ -f[i][j] = f[i - 1][j] \text{ or } f[i - 1][j - x] \text{ if } j \geq x +f[i][j] = f[i - 1][j] \textit{ or } f[i - 1][j - x] \textit{ if } j \geq x $$ The final answer is $f[n][m]$. diff --git a/solution/0400-0499/0457.Circular Array Loop/README.md b/solution/0400-0499/0457.Circular Array Loop/README.md index b8e08f322019..5d5a37f44f74 100644 --- a/solution/0400-0499/0457.Circular Array Loop/README.md +++ b/solution/0400-0499/0457.Circular Array Loop/README.md @@ -39,29 +39,33 @@ tags:

     

    -

    示例 1:

    - +

    示例 1:

    +
     输入:nums = [2,-1,1,2,2]
     输出:true
    -解释:存在循环,按下标 0 -> 2 -> 3 -> 0 。循环长度为 3 。
    +解释:图片展示了节点间如何连接。白色节点向前跳跃,而红色节点向后跳跃。
    +我们可以看到存在循环,按下标 0 -> 2 -> 3 -> 0 --> ...,并且其中的所有节点都是白色(以相同方向跳跃)。
     
    -

    示例 2:

    - +

    示例 2:

    +
    -输入:nums = [-1,2]
    +输入:nums = [-1,-2,-3,-4,-5,6]
     输出:false
    -解释:按下标 1 -> 1 -> 1 ... 的运动无法构成循环,因为循环的长度为 1 。根据定义,循环的长度必须大于 1 。
    +解释:图片展示了节点间如何连接。白色节点向前跳跃,而红色节点向后跳跃。
    +唯一的循环长度为 1,所以返回 false。
     
    -

    示例 3:

    - +

    示例 3:

    +
    -输入:nums = [-2,1,-1,-2,-2]
    -输出:false
    -解释:按下标 1 -> 2 -> 1 -> ... 的运动无法构成循环,因为 nums[1] 是正数,而 nums[2] 是负数。
    -所有 nums[seq[j]] 应当不是全正就是全负。
    +输入:nums = [1,-1,5,1,4] +输出:true +解释:图片展示了节点间如何连接。白色节点向前跳跃,而红色节点向后跳跃。 +我们可以看到存在循环,按下标 0 --> 1 --> 0 --> ...,当它的大小大于 1 时,它有一个向前跳的节点和一个向后跳的节点,所以 它不是一个循环。 +我们可以看到存在循环,按下标 3 --> 4 --> 3 --> ...,并且其中的所有节点都是白色(以相同方向跳跃)。 +

     

    diff --git a/solution/0400-0499/0457.Circular Array Loop/images/1723688159-qYjpWT-image.png b/solution/0400-0499/0457.Circular Array Loop/images/1723688159-qYjpWT-image.png new file mode 100644 index 000000000000..b2b309ca9d67 Binary files /dev/null and b/solution/0400-0499/0457.Circular Array Loop/images/1723688159-qYjpWT-image.png differ diff --git a/solution/0400-0499/0457.Circular Array Loop/images/1723688183-lRSkjp-image.png b/solution/0400-0499/0457.Circular Array Loop/images/1723688183-lRSkjp-image.png new file mode 100644 index 000000000000..b197c72f001a Binary files /dev/null and b/solution/0400-0499/0457.Circular Array Loop/images/1723688183-lRSkjp-image.png differ diff --git a/solution/0400-0499/0457.Circular Array Loop/images/1723688199-nhaMuF-image.png b/solution/0400-0499/0457.Circular Array Loop/images/1723688199-nhaMuF-image.png new file mode 100644 index 000000000000..6f81e15be35f Binary files /dev/null and b/solution/0400-0499/0457.Circular Array Loop/images/1723688199-nhaMuF-image.png differ diff --git a/solution/0400-0499/0464.Can I Win/README.md b/solution/0400-0499/0464.Can I Win/README.md index 7e65d5c648c8..d73ab18ab788 100644 --- a/solution/0400-0499/0464.Can I Win/README.md +++ b/solution/0400-0499/0464.Can I Win/README.md @@ -77,9 +77,9 @@ tags: 我们首先判断可以选择的所有整数的和是否小于目标值,如果是,说明无论如何都无法赢,直接返回 `false`。 -然后,我们设计一个函数 $\text{dfs}(mask, s)$,其中 `mask` 表示当前已选择的整数的状态,`s` 表示当前的累计和。函数返回值为当前玩家是否能赢。 +然后,我们设计一个函数 $\textit{dfs}(mask, s)$,其中 `mask` 表示当前已选择的整数的状态,`s` 表示当前的累计和。函数返回值为当前玩家是否能赢。 -函数 $\text{dfs}(mask, s)$ 的执行过程如下: +函数 $\textit{dfs}(mask, s)$ 的执行过程如下: 我们遍历 $1$ 到 $maxChoosableInteger$ 中的每个整数 $i$,如果 $i$ 还没有被选择,我们可以选择 $i$,如果选择 $i$ 后的累计和 $s + i$ 大于等于目标值 `desiredTotal`,或者对手选择 $i$ 后的结果是输的,那么当前玩家就是赢的,返回 `true`。 diff --git a/solution/0400-0499/0476.Number Complement/README.md b/solution/0400-0499/0476.Number Complement/README.md index ef94361032a1..152830c396a8 100644 --- a/solution/0400-0499/0476.Number Complement/README.md +++ b/solution/0400-0499/0476.Number Complement/README.md @@ -67,13 +67,13 @@ tags: 根据题目描述,我们可以通过异或运算来实现取反的操作,步骤如下: -我们首先找到 $\text{num}$ 的二进制表示中最高位的 $1$,位置记为 $k$。 +我们首先找到 $\textit{num}$ 的二进制表示中最高位的 $1$,位置记为 $k$。 然后,构造一个二进制数,第 $k$ 位为 $0$,其余低位为 $1$,即 $2^k - 1$; -最后,将 $\text{num}$ 与上述构造的二进制数进行异或运算,即可得到答案。 +最后,将 $\textit{num}$ 与上述构造的二进制数进行异或运算,即可得到答案。 -时间复杂度 $O(\log \text{num})$,其中 $\text{num}$ 为输入的整数。空间复杂度 $O(1)$。 +时间复杂度 $O(\log \textit{num})$,其中 $\textit{num}$ 为输入的整数。空间复杂度 $O(1)$。 diff --git a/solution/0400-0499/0476.Number Complement/README_EN.md b/solution/0400-0499/0476.Number Complement/README_EN.md index ea786621d6a4..5e9d87c4bc1d 100644 --- a/solution/0400-0499/0476.Number Complement/README_EN.md +++ b/solution/0400-0499/0476.Number Complement/README_EN.md @@ -61,13 +61,13 @@ tags: According to the problem description, we can use XOR operation to implement the flipping operation, the steps are as follows: -First, we find the highest bit of $1$ in the binary representation of $\text{num}$, and the position is denoted as $k$. +First, we find the highest bit of $1$ in the binary representation of $\textit{num}$, and the position is denoted as $k$. Then, we construct a binary number, where the $k$-th bit is $0$ and the rest of the lower bits are $1$, which is $2^k - 1$; -Finally, we perform XOR operation on $\text{num}$ and the constructed binary number to get the answer. +Finally, we perform XOR operation on $\textit{num}$ and the constructed binary number to get the answer. -The time complexity is $O(\log \text{num})$, where $\text{num}$ is the input integer. The space complexity is $O(1)$. +The time complexity is $O(\log \textit{num})$, where $\textit{num}$ is the input integer. The space complexity is $O(1)$. diff --git a/solution/0400-0499/0494.Target Sum/README.md b/solution/0400-0499/0494.Target Sum/README.md index 79680b9b0202..3308936b2552 100644 --- a/solution/0400-0499/0494.Target Sum/README.md +++ b/solution/0400-0499/0494.Target Sum/README.md @@ -69,27 +69,27 @@ tags: ### 方法一:动态规划 -我们记数组 $\text{nums}$ 所有元素的和为 $s$,添加负号的元素之和为 $x$,则添加正号的元素之和为 $s - x$,则有: +我们记数组 $\textit{nums}$ 所有元素的和为 $s$,添加负号的元素之和为 $x$,则添加正号的元素之和为 $s - x$,则有: $$ -(s - x) - x = \text{target} \Rightarrow x = \frac{s - \text{target}}{2} +(s - x) - x = \textit{target} \Rightarrow x = \frac{s - \textit{target}}{2} $$ -由于 $x \geq 0$,且 $x$ 为整数,所以 $s \geq \text{target}$ 且 $s - \text{target}$ 为偶数。如果不满足这两个条件,则直接返回 $0$。 +由于 $x \geq 0$,且 $x$ 为整数,所以 $s \geq \textit{target}$ 且 $s - \textit{target}$ 为偶数。如果不满足这两个条件,则直接返回 $0$。 -接下来,我们可以将问题转化为:在数组 $\text{nums}$ 中选取若干元素,使得这些元素之和等于 $\frac{s - \text{target}}{2}$,问有多少种选取方法。 +接下来,我们可以将问题转化为:在数组 $\textit{nums}$ 中选取若干元素,使得这些元素之和等于 $\frac{s - \textit{target}}{2}$,问有多少种选取方法。 -我们可以使用动态规划来解决这个问题。定义 $f[i][j]$ 表示在数组 $\text{nums}$ 的前 $i$ 个元素中选取若干元素,使得这些元素之和等于 $j$ 的选取方案数。 +我们可以使用动态规划来解决这个问题。定义 $f[i][j]$ 表示在数组 $\textit{nums}$ 的前 $i$ 个元素中选取若干元素,使得这些元素之和等于 $j$ 的选取方案数。 -对于 $\text{nums}[i - 1]$,我们有两种选择:选取或不选取。如果我们不选取 $\text{nums}[i - 1]$,则 $f[i][j] = f[i - 1][j]$;如果我们选取 $\text{nums}[i - 1]$,则 $f[i][j] = f[i - 1][j - \text{nums}[i - 1]]$。因此,状态转移方程为: +对于 $\textit{nums}[i - 1]$,我们有两种选择:选取或不选取。如果我们不选取 $\textit{nums}[i - 1]$,则 $f[i][j] = f[i - 1][j]$;如果我们选取 $\textit{nums}[i - 1]$,则 $f[i][j] = f[i - 1][j - \textit{nums}[i - 1]]$。因此,状态转移方程为: $$ -f[i][j] = f[i - 1][j] + f[i - 1][j - \text{nums}[i - 1]] +f[i][j] = f[i - 1][j] + f[i - 1][j - \textit{nums}[i - 1]] $$ -其中,选取的前提是 $j \geq \text{nums}[i - 1]$。 +其中,选取的前提是 $j \geq \textit{nums}[i - 1]$。 -最终答案即为 $f[m][n]$。其中 $m$ 为数组 $\text{nums}$ 的长度,而 $n = \frac{s - \text{target}}{2}$。 +最终答案即为 $f[m][n]$。其中 $m$ 为数组 $\textit{nums}$ 的长度,而 $n = \frac{s - \textit{target}}{2}$。 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。 @@ -282,7 +282,7 @@ var findTargetSumWays = function (nums, target) { ### 方法二:动态规划(空间优化) -我们可以发现,方法一中的状态转移方程中,$f[i][j]$ 的值只和 $f[i - 1][j]$ 以及 $f[i - 1][j - \text{nums}[i - 1]]$ 有关,因此我们去掉第一维空间,只使用一维数组即可。 +我们可以发现,方法一中的状态转移方程中,$f[i][j]$ 的值只和 $f[i - 1][j]$ 以及 $f[i - 1][j - \textit{nums}[i - 1]]$ 有关,因此我们去掉第一维空间,只使用一维数组即可。 时间复杂度 $O(m \times n)$,空间复杂度 $O(n)$。 diff --git a/solution/0400-0499/0494.Target Sum/README_EN.md b/solution/0400-0499/0494.Target Sum/README_EN.md index 776a50a94323..b8d7be99b24d 100644 --- a/solution/0400-0499/0494.Target Sum/README_EN.md +++ b/solution/0400-0499/0494.Target Sum/README_EN.md @@ -67,27 +67,27 @@ tags: ### Solution 1: Dynamic Programming -Let's denote the sum of all elements in the array $\text{nums}$ as $s$, and the sum of elements to which we assign a negative sign as $x$. Therefore, the sum of elements with a positive sign is $s - x$. We have: +Let's denote the sum of all elements in the array $\textit{nums}$ as $s$, and the sum of elements to which we assign a negative sign as $x$. Therefore, the sum of elements with a positive sign is $s - x$. We have: $$ -(s - x) - x = \text{target} \Rightarrow x = \frac{s - \text{target}}{2} +(s - x) - x = \textit{target} \Rightarrow x = \frac{s - \textit{target}}{2} $$ -Since $x \geq 0$ and $x$ must be an integer, it follows that $s \geq \text{target}$ and $s - \text{target}$ must be even. If these two conditions are not met, we directly return $0$. +Since $x \geq 0$ and $x$ must be an integer, it follows that $s \geq \textit{target}$ and $s - \textit{target}$ must be even. If these two conditions are not met, we directly return $0$. -Next, we can transform the problem into: selecting several elements from the array $\text{nums}$ such that the sum of these elements equals $\frac{s - \text{target}}{2}$. We are asked how many ways there are to make such a selection. +Next, we can transform the problem into: selecting several elements from the array $\textit{nums}$ such that the sum of these elements equals $\frac{s - \textit{target}}{2}$. We are asked how many ways there are to make such a selection. -We can use dynamic programming to solve this problem. Define $f[i][j]$ as the number of ways to select several elements from the first $i$ elements of the array $\text{nums}$ such that the sum of these elements equals $j$. +We can use dynamic programming to solve this problem. Define $f[i][j]$ as the number of ways to select several elements from the first $i$ elements of the array $\textit{nums}$ such that the sum of these elements equals $j$. -For $\text{nums}[i - 1]$, we have two choices: to select or not to select. If we do not select $\text{nums}[i - 1]$, then $f[i][j] = f[i - 1][j]$; if we do select $\text{nums}[i - 1]$, then $f[i][j] = f[i - 1][j - \text{nums}[i - 1]]$. Therefore, the state transition equation is: +For $\textit{nums}[i - 1]$, we have two choices: to select or not to select. If we do not select $\textit{nums}[i - 1]$, then $f[i][j] = f[i - 1][j]$; if we do select $\textit{nums}[i - 1]$, then $f[i][j] = f[i - 1][j - \textit{nums}[i - 1]]$. Therefore, the state transition equation is: $$ -f[i][j] = f[i - 1][j] + f[i - 1][j - \text{nums}[i - 1]] +f[i][j] = f[i - 1][j] + f[i - 1][j - \textit{nums}[i - 1]] $$ -This selection is based on the premise that $j \geq \text{nums}[i - 1]$. +This selection is based on the premise that $j \geq \textit{nums}[i - 1]$. -The final answer is $f[m][n]$, where $m$ is the length of the array $\text{nums}$, and $n = \frac{s - \text{target}}{2}$. +The final answer is $f[m][n]$, where $m$ is the length of the array $\textit{nums}$, and $n = \frac{s - \textit{target}}{2}$. The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. @@ -280,7 +280,7 @@ var findTargetSumWays = function (nums, target) { ### Solution 2: Dynamic Programming (Space Optimization) -We can observe that in the state transition equation of Solution 1, the value of $f[i][j]$ is only related to $f[i - 1][j]$ and $f[i - 1][j - \text{nums}[i - 1]]$. Therefore, we can eliminate the first dimension of the space and use only a one-dimensional array. +We can observe that in the state transition equation of Solution 1, the value of $f[i][j]$ is only related to $f[i - 1][j]$ and $f[i - 1][j - \textit{nums}[i - 1]]$. Therefore, we can eliminate the first dimension of the space and use only a one-dimensional array. The time complexity is $O(m \times n)$, and the space complexity is $O(n)$. diff --git a/solution/0500-0599/0510.Inorder Successor in BST II/README.md b/solution/0500-0599/0510.Inorder Successor in BST II/README.md index 4bc1701d3fa7..dc93a079a145 100644 --- a/solution/0500-0599/0510.Inorder Successor in BST II/README.md +++ b/solution/0500-0599/0510.Inorder Successor in BST II/README.md @@ -76,9 +76,9 @@ class Node { ### 方法一:分情况讨论 -如果 $\text{node}$ 有右子树,那么 $\text{node}$ 的中序后继节点是右子树中最左边的节点。 +如果 $\textit{node}$ 有右子树,那么 $\textit{node}$ 的中序后继节点是右子树中最左边的节点。 -如果 $\text{node}$ 没有右子树,那么如果 $\text{node}$ 是其父节点的右子树,我们就一直向上搜索,直到节点的父节点为空,或者节点是其父节点的左子树,此时父节点就是中序后继节点。 +如果 $\textit{node}$ 没有右子树,那么如果 $\textit{node}$ 是其父节点的右子树,我们就一直向上搜索,直到节点的父节点为空,或者节点是其父节点的左子树,此时父节点就是中序后继节点。 时间复杂度 $O(h)$,其中 $h$ 是二叉树的高度。空间复杂度 $O(1)$。 diff --git a/solution/0500-0599/0514.Freedom Trail/README.md b/solution/0500-0599/0514.Freedom Trail/README.md index cbf5121cede7..a4e424c4d1f7 100644 --- a/solution/0500-0599/0514.Freedom Trail/README.md +++ b/solution/0500-0599/0514.Freedom Trail/README.md @@ -81,7 +81,7 @@ tags: 我们可以先初始化 $f[0][j]$,其中 $j$ 是字符 $key[0]$ 在 $ring$ 中出现的位置。由于 $ring$ 的第 $j$ 个字符与 $12:00$ 方向对齐,因此我们只需要 $1$ 步即可拼写出 $key[0]$。此外,我们还需要 $min(j, n - j)$ 步将 $ring$ 旋转到 $12:00$ 方向。因此 $f[0][j]=min(j, n - j) + 1$。 -接下来,我们考虑当 $i \geq 1$ 时,状态如何转移。我们可以枚举 $key[i]$ 在 $ring$ 中的位置列表 $pos[key[i]]$,并枚举 $key[i-1]$ 在 $ring$ 中的位置列表 $pos[key[i-1]]$,然后更新 $f[i][j]$,即 $f[i][j]=\min_{k \in pos[key[i-1]]} f[i-1][k] + \min(\text{abs}(j - k), n - \text{abs}(j - k)) + 1$。 +接下来,我们考虑当 $i \geq 1$ 时,状态如何转移。我们可以枚举 $key[i]$ 在 $ring$ 中的位置列表 $pos[key[i]]$,并枚举 $key[i-1]$ 在 $ring$ 中的位置列表 $pos[key[i-1]]$,然后更新 $f[i][j]$,即 $f[i][j]=\min_{k \in pos[key[i-1]]} f[i-1][k] + \min(\textit{abs}(j - k), n - \textit{abs}(j - k)) + 1$。 最后,我们返回 $\min_{0 \leq j \lt n} f[m - 1][j]$ 即可。 diff --git a/solution/0500-0599/0514.Freedom Trail/README_EN.md b/solution/0500-0599/0514.Freedom Trail/README_EN.md index fa2703896e2d..c71e89f108e0 100644 --- a/solution/0500-0599/0514.Freedom Trail/README_EN.md +++ b/solution/0500-0599/0514.Freedom Trail/README_EN.md @@ -75,7 +75,7 @@ Then we define $f[i][j]$ as the minimum number of steps to spell the first $i+1$ We can first initialize $f[0][j]$, where $j$ is the position where the character $key[0]$ appears in $ring$. Since the $j$-th character of $ring$ is aligned with the $12:00$ direction, we only need $1$ step to spell $key[0]$. In addition, we need $min(j, n - j)$ steps to rotate $ring$ to the $12:00$ direction. Therefore, $f[0][j]=min(j, n - j) + 1$. -Next, we consider how the state transitions when $i \geq 1$. We can enumerate the position list $pos[key[i]]$ where $key[i]$ appears in $ring$, and enumerate the position list $pos[key[i-1]]$ where $key[i-1]$ appears in $ring$, and then update $f[i][j]$, i.e., $f[i][j]=\min_{k \in pos[key[i-1]]} f[i-1][k] + \min(\text{abs}(j - k), n - \text{abs}(j - k)) + 1$. +Next, we consider how the state transitions when $i \geq 1$. We can enumerate the position list $pos[key[i]]$ where $key[i]$ appears in $ring$, and enumerate the position list $pos[key[i-1]]$ where $key[i-1]$ appears in $ring$, and then update $f[i][j]$, i.e., $f[i][j]=\min_{k \in pos[key[i-1]]} f[i-1][k] + \min(\textit{abs}(j - k), n - \textit{abs}(j - k)) + 1$. Finally, we return $\min_{0 \leq j \lt n} f[m - 1][j]$. diff --git a/solution/0500-0599/0517.Super Washing Machines/README.md b/solution/0500-0599/0517.Super Washing Machines/README.md index 059d32586a40..f393ab044ed5 100644 --- a/solution/0500-0599/0517.Super Washing Machines/README.md +++ b/solution/0500-0599/0517.Super Washing Machines/README.md @@ -77,7 +77,7 @@ tags: 否则,假设洗衣机内的衣服总数为 $s$,那么最终每台洗衣机内的衣服数量都会变为 $k = s / n$。 -我们定义 $a_i$ 为第 $i$ 台洗衣机内的衣服数量与 $k$ 的差值,即 $a_i = \text{machines}[i] - k$。若 $a_i > 0$,则表示第 $i$ 台洗衣机内有多余的衣服,需要向相邻的洗衣机传递;若 $a_i < 0$,则表示第 $i$ 台洗衣机内缺少衣服,需要从相邻的洗衣机获得。 +我们定义 $a_i$ 为第 $i$ 台洗衣机内的衣服数量与 $k$ 的差值,即 $a_i = \textit{machines}[i] - k$。若 $a_i > 0$,则表示第 $i$ 台洗衣机内有多余的衣服,需要向相邻的洗衣机传递;若 $a_i < 0$,则表示第 $i$ 台洗衣机内缺少衣服,需要从相邻的洗衣机获得。 我们将前 $i$ 台洗衣机的衣服数量差值之和定义为 $s_i = \sum_{j=0}^{i-1} a_j$,如果把前 $i$ 台洗衣机视为一组,其余的洗衣机视为另一组。那么若 $s_i$ 为正数,表示第一组洗衣机内有多余的衣服,需要向第二组洗衣机传递;若 $s_i$ 为负数,表示第一组洗衣机内缺少衣服,需要从第二组洗衣机获得。 diff --git a/solution/0500-0599/0517.Super Washing Machines/README_EN.md b/solution/0500-0599/0517.Super Washing Machines/README_EN.md index 3952e5cc518c..2977a8a153c0 100644 --- a/solution/0500-0599/0517.Super Washing Machines/README_EN.md +++ b/solution/0500-0599/0517.Super Washing Machines/README_EN.md @@ -75,7 +75,7 @@ If the total number of clothes in the washing machines cannot be divided evenly Otherwise, suppose the total number of clothes in the washing machines is $s$, then the number of clothes in each washing machine will eventually become $k = s / n$. -We define $a_i$ as the difference between the number of clothes in the $i$-th washing machine and $k$, that is, $a_i = \text{machines}[i] - k$. If $a_i > 0$, it means that the $i$-th washing machine has extra clothes and needs to pass them to the adjacent washing machine; if $a_i < 0$, it means that the $i$-th washing machine lacks clothes and needs to get them from the adjacent washing machine. +We define $a_i$ as the difference between the number of clothes in the $i$-th washing machine and $k$, that is, $a_i = \textit{machines}[i] - k$. If $a_i > 0$, it means that the $i$-th washing machine has extra clothes and needs to pass them to the adjacent washing machine; if $a_i < 0$, it means that the $i$-th washing machine lacks clothes and needs to get them from the adjacent washing machine. We define the sum of the differences in the number of clothes in the first $i$ washing machines as $s_i = \sum_{j=0}^{i-1} a_j$. If we regard the first $i$ washing machines as one group and the remaining washing machines as another group. Then if $s_i$ is a positive number, it means that the first group of washing machines has extra clothes and needs to pass them to the second group of washing machines; if $s_i$ is a negative number, it means that the first group of washing machines lacks clothes and needs to get them from the second group of washing machines. diff --git a/solution/0500-0599/0523.Continuous Subarray Sum/README.md b/solution/0500-0599/0523.Continuous Subarray Sum/README.md index 5fa616e1e822..6b96ec4b6470 100644 --- a/solution/0500-0599/0523.Continuous Subarray Sum/README.md +++ b/solution/0500-0599/0523.Continuous Subarray Sum/README.md @@ -79,15 +79,15 @@ tags: ### 方法一:前缀和 + 哈希表 -根据题目描述,如果存在两个前缀和模 $k$ 的余数相同的位置 $i$ 和 $j$(不妨设 $j < i$),那么 $\text{nums}[j+1..i]$ 这个子数组的和是 $k$ 的倍数。 +根据题目描述,如果存在两个前缀和模 $k$ 的余数相同的位置 $i$ 和 $j$(不妨设 $j < i$),那么 $\textit{nums}[j+1..i]$ 这个子数组的和是 $k$ 的倍数。 因此,我们可以使用哈希表存储每个前缀和模 $k$ 的余数第一次出现的位置。初始时,我们在哈希表中存入一对键值对 $(0, -1)$,表示前缀和为 $0$ 的余数 $0$ 出现在位置 $-1$。 -遍历数组时,我们计算当前前缀和的模 $k$ 的余数,如果当前前缀和的模 $k$ 的余数没有在哈希表中出现过,我们就将当前前缀和的模 $k$ 的余数和对应的位置存入哈希表中。否则,如果当前前缀和的模 $k$ 的余数在哈希表中已经出现过,位置为 $j$,那么我们就找到了一个满足条件的子数组 $\text{nums}[j+1..i]$,因此返回 $\text{True}$。 +遍历数组时,我们计算当前前缀和的模 $k$ 的余数,如果当前前缀和的模 $k$ 的余数没有在哈希表中出现过,我们就将当前前缀和的模 $k$ 的余数和对应的位置存入哈希表中。否则,如果当前前缀和的模 $k$ 的余数在哈希表中已经出现过,位置为 $j$,那么我们就找到了一个满足条件的子数组 $\textit{nums}[j+1..i]$,因此返回 $\textit{True}$。 -遍历结束后,如果没有找到满足条件的子数组,我们返回 $\text{False}$。 +遍历结束后,如果没有找到满足条件的子数组,我们返回 $\textit{False}$。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{nums}$ 的长度。 diff --git a/solution/0500-0599/0523.Continuous Subarray Sum/README_EN.md b/solution/0500-0599/0523.Continuous Subarray Sum/README_EN.md index 00c540a86a7a..049ef24bff65 100644 --- a/solution/0500-0599/0523.Continuous Subarray Sum/README_EN.md +++ b/solution/0500-0599/0523.Continuous Subarray Sum/README_EN.md @@ -78,15 +78,15 @@ tags: ### Solution 1: Prefix Sum + Hash Table -According to the problem description, if there exist two positions $i$ and $j$ ($j < i$) where the remainders of the prefix sums modulo $k$ are the same, then the sum of the subarray $\text{nums}[j+1..i]$ is a multiple of $k$. +According to the problem description, if there exist two positions $i$ and $j$ ($j < i$) where the remainders of the prefix sums modulo $k$ are the same, then the sum of the subarray $\textit{nums}[j+1..i]$ is a multiple of $k$. Therefore, we can use a hash table to store the first occurrence of each remainder of the prefix sum modulo $k$. Initially, we store a key-value pair $(0, -1)$ in the hash table, indicating that the remainder $0$ of the prefix sum $0$ appears at position $-1$. -As we iterate through the array, we calculate the current prefix sum's remainder modulo $k$. If the current prefix sum's remainder modulo $k$ has not appeared in the hash table, we store the current prefix sum's remainder modulo $k$ and its corresponding position in the hash table. Otherwise, if the current prefix sum's remainder modulo $k$ has already appeared in the hash table at position $j$, then we have found a subarray $\text{nums}[j+1..i]$ that meets the conditions, and thus return $\text{True}$. +As we iterate through the array, we calculate the current prefix sum's remainder modulo $k$. If the current prefix sum's remainder modulo $k$ has not appeared in the hash table, we store the current prefix sum's remainder modulo $k$ and its corresponding position in the hash table. Otherwise, if the current prefix sum's remainder modulo $k$ has already appeared in the hash table at position $j$, then we have found a subarray $\textit{nums}[j+1..i]$ that meets the conditions, and thus return $\textit{True}$. -After completing the iteration, if no subarray meeting the conditions is found, we return $\text{False}$. +After completing the iteration, if no subarray meeting the conditions is found, we return $\textit{False}$. -The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\text{nums}$. +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/README.md b/solution/0500-0599/0530.Minimum Absolute Difference in BST/README.md index b5759e2fcdfa..1c4d16502b73 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/README.md +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/README.md @@ -61,7 +61,11 @@ tags: ### 方法一:中序遍历 -中序遍历二叉搜索树,获取当前节点与上个节点差值的最小值即可。 +题目需要我们求任意两个节点值之间的最小差值,而二叉搜索树的中序遍历是一个递增序列,因此我们只需要求中序遍历中相邻两个节点值之间的最小差值即可。 + +我们可以使用递归的方法来实现中序遍历,过程中用一个变量 $\textit{pre}$ 来保存前一个节点的值,这样我们就可以在遍历的过程中求出相邻两个节点值之间的最小差值。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉搜索树的节点个数。 @@ -75,17 +79,18 @@ tags: # self.left = left # self.right = right class Solution: - def getMinimumDifference(self, root: TreeNode) -> int: - def dfs(root): + def getMinimumDifference(self, root: Optional[TreeNode]) -> int: + def dfs(root: Optional[TreeNode]): if root is None: return dfs(root.left) - nonlocal ans, prev - ans = min(ans, abs(prev - root.val)) - prev = root.val + nonlocal pre, ans + ans = min(ans, root.val - pre) + pre = root.val dfs(root.right) - ans = prev = inf + pre = -inf + ans = inf dfs(root) return ans ``` @@ -109,13 +114,11 @@ class Solution: * } */ class Solution { - private int ans; - private int prev; - private int inf = Integer.MAX_VALUE; + private final int inf = 1 << 30; + private int ans = inf; + private int pre = -inf; public int getMinimumDifference(TreeNode root) { - ans = inf; - prev = inf; dfs(root); return ans; } @@ -125,8 +128,8 @@ class Solution { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); } } @@ -148,23 +151,21 @@ class Solution { */ class Solution { public: - const int inf = INT_MAX; - int ans; - int prev; - int getMinimumDifference(TreeNode* root) { - ans = inf, prev = inf; - dfs(root); + const int inf = 1 << 30; + int ans = inf, pre = -inf; + auto dfs = [&](auto&& dfs, TreeNode* root) -> void { + if (!root) { + return; + } + dfs(dfs, root->left); + ans = min(ans, root->val - pre); + pre = root->val; + dfs(dfs, root->right); + }; + dfs(dfs, root); return ans; } - - void dfs(TreeNode* root) { - if (!root) return; - dfs(root->left); - ans = min(ans, abs(prev - root->val)); - prev = root->val; - dfs(root->right); - } }; ``` @@ -180,27 +181,53 @@ public: * } */ func getMinimumDifference(root *TreeNode) int { - inf := 0x3f3f3f3f - ans, prev := inf, inf + const inf int = 1 << 30 + ans, pre := inf, -inf var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return } dfs(root.Left) - ans = min(ans, abs(prev-root.Val)) - prev = root.Val + ans = min(ans, root.Val-pre) + pre = root.Val dfs(root.Right) } dfs(root) return ans } +``` -func abs(x int) int { - if x < 0 { - return -x - } - return x +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getMinimumDifference(root: TreeNode | null): number { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); + }; + dfs(root); + return ans; } ``` @@ -225,69 +252,59 @@ func abs(x int) int { // } // } // } -use std::cell::RefCell; use std::rc::Rc; +use std::cell::RefCell; impl Solution { - #[allow(dead_code)] pub fn get_minimum_difference(root: Option>>) -> i32 { - let mut ret = i32::MAX; - let mut prev = i32::MAX; - Self::traverse(root, &mut prev, &mut ret); - ret - } - - #[allow(dead_code)] - fn traverse(root: Option>>, prev: &mut i32, ans: &mut i32) { - let left = root.as_ref().unwrap().borrow().left.clone(); - let right = root.as_ref().unwrap().borrow().right.clone(); - let val = root.as_ref().unwrap().borrow().val; - if !left.is_none() { - Self::traverse(left.clone(), prev, ans); - } - *ans = std::cmp::min(*ans, (*prev - val).abs()); - *prev = val; - if !right.is_none() { - Self::traverse(right.clone(), prev, ans); + const inf: i32 = 1 << 30; + let mut ans = inf; + let mut pre = -inf; + + fn dfs(node: Option>>, ans: &mut i32, pre: &mut i32) { + if let Some(n) = node { + let n = n.borrow(); + dfs(n.left.clone(), ans, pre); + *ans = (*ans).min(n.val - *pre); + *pre = n.val; + dfs(n.right.clone(), ans, pre); + } } + + dfs(root, &mut ans, &mut pre); + ans } } ``` -#### TypeScript +#### JavaScript -```ts +```js /** * Definition for a binary tree node. - * class TreeNode { - * val: number - * left: TreeNode | null - * right: TreeNode | null - * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) * } */ -function getMinimumDifference(root: TreeNode | null): number { - if (!root) return 0; - - let prev = Number.MIN_SAFE_INTEGER; - let min = Number.MAX_SAFE_INTEGER; - - const dfs = (node: TreeNode | null) => { - if (!node) return; - - dfs(node.left); - min = Math.min(min, node.val - prev); - prev = node.val; - dfs(node.right); +/** + * @param {TreeNode} root + * @return {number} + */ +var getMinimumDifference = function (root) { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = root => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); }; - dfs(root); - - return min; -} + return ans; +}; ``` diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/README_EN.md b/solution/0500-0599/0530.Minimum Absolute Difference in BST/README_EN.md index c844437fd016..ee82a161f1f6 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/README_EN.md +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/README_EN.md @@ -54,7 +54,13 @@ tags: -### Solution 1 +### Solution 1: Inorder Traversal + +The problem requires us to find the minimum difference between the values of any two nodes. Since the inorder traversal of a binary search tree is an increasing sequence, we only need to find the minimum difference between the values of two adjacent nodes in the inorder traversal. + +We can use a recursive method to implement the inorder traversal. During the process, we use a variable $\textit{pre}$ to save the value of the previous node. This way, we can calculate the minimum difference between the values of two adjacent nodes during the traversal. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary search tree. @@ -68,17 +74,18 @@ tags: # self.left = left # self.right = right class Solution: - def getMinimumDifference(self, root: TreeNode) -> int: - def dfs(root): + def getMinimumDifference(self, root: Optional[TreeNode]) -> int: + def dfs(root: Optional[TreeNode]): if root is None: return dfs(root.left) - nonlocal ans, prev - ans = min(ans, abs(prev - root.val)) - prev = root.val + nonlocal pre, ans + ans = min(ans, root.val - pre) + pre = root.val dfs(root.right) - ans = prev = inf + pre = -inf + ans = inf dfs(root) return ans ``` @@ -102,13 +109,11 @@ class Solution: * } */ class Solution { - private int ans; - private int prev; - private int inf = Integer.MAX_VALUE; + private final int inf = 1 << 30; + private int ans = inf; + private int pre = -inf; public int getMinimumDifference(TreeNode root) { - ans = inf; - prev = inf; dfs(root); return ans; } @@ -118,8 +123,8 @@ class Solution { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); } } @@ -141,23 +146,21 @@ class Solution { */ class Solution { public: - const int inf = INT_MAX; - int ans; - int prev; - int getMinimumDifference(TreeNode* root) { - ans = inf, prev = inf; - dfs(root); + const int inf = 1 << 30; + int ans = inf, pre = -inf; + auto dfs = [&](auto&& dfs, TreeNode* root) -> void { + if (!root) { + return; + } + dfs(dfs, root->left); + ans = min(ans, root->val - pre); + pre = root->val; + dfs(dfs, root->right); + }; + dfs(dfs, root); return ans; } - - void dfs(TreeNode* root) { - if (!root) return; - dfs(root->left); - ans = min(ans, abs(prev - root->val)); - prev = root->val; - dfs(root->right); - } }; ``` @@ -173,27 +176,53 @@ public: * } */ func getMinimumDifference(root *TreeNode) int { - inf := 0x3f3f3f3f - ans, prev := inf, inf + const inf int = 1 << 30 + ans, pre := inf, -inf var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return } dfs(root.Left) - ans = min(ans, abs(prev-root.Val)) - prev = root.Val + ans = min(ans, root.Val-pre) + pre = root.Val dfs(root.Right) } dfs(root) return ans } +``` -func abs(x int) int { - if x < 0 { - return -x - } - return x +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getMinimumDifference(root: TreeNode | null): number { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); + }; + dfs(root); + return ans; } ``` @@ -218,69 +247,59 @@ func abs(x int) int { // } // } // } -use std::cell::RefCell; use std::rc::Rc; +use std::cell::RefCell; impl Solution { - #[allow(dead_code)] pub fn get_minimum_difference(root: Option>>) -> i32 { - let mut ret = i32::MAX; - let mut prev = i32::MAX; - Self::traverse(root, &mut prev, &mut ret); - ret - } - - #[allow(dead_code)] - fn traverse(root: Option>>, prev: &mut i32, ans: &mut i32) { - let left = root.as_ref().unwrap().borrow().left.clone(); - let right = root.as_ref().unwrap().borrow().right.clone(); - let val = root.as_ref().unwrap().borrow().val; - if !left.is_none() { - Self::traverse(left.clone(), prev, ans); - } - *ans = std::cmp::min(*ans, (*prev - val).abs()); - *prev = val; - if !right.is_none() { - Self::traverse(right.clone(), prev, ans); + const inf: i32 = 1 << 30; + let mut ans = inf; + let mut pre = -inf; + + fn dfs(node: Option>>, ans: &mut i32, pre: &mut i32) { + if let Some(n) = node { + let n = n.borrow(); + dfs(n.left.clone(), ans, pre); + *ans = (*ans).min(n.val - *pre); + *pre = n.val; + dfs(n.right.clone(), ans, pre); + } } + + dfs(root, &mut ans, &mut pre); + ans } } ``` -#### TypeScript +#### JavaScript -```ts +```js /** * Definition for a binary tree node. - * class TreeNode { - * val: number - * left: TreeNode | null - * right: TreeNode | null - * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) * } */ -function getMinimumDifference(root: TreeNode | null): number { - if (!root) return 0; - - let prev = Number.MIN_SAFE_INTEGER; - let min = Number.MAX_SAFE_INTEGER; - - const dfs = (node: TreeNode | null) => { - if (!node) return; - - dfs(node.left); - min = Math.min(min, node.val - prev); - prev = node.val; - dfs(node.right); +/** + * @param {TreeNode} root + * @return {number} + */ +var getMinimumDifference = function (root) { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = root => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); }; - dfs(root); - - return min; -} + return ans; +}; ``` diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.cpp b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.cpp index 578e0615cd4b..aefc98065b5b 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.cpp +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.cpp @@ -11,21 +11,19 @@ */ class Solution { public: - const int inf = INT_MAX; - int ans; - int prev; - int getMinimumDifference(TreeNode* root) { - ans = inf, prev = inf; - dfs(root); + const int inf = 1 << 30; + int ans = inf, pre = -inf; + auto dfs = [&](auto&& dfs, TreeNode* root) -> void { + if (!root) { + return; + } + dfs(dfs, root->left); + ans = min(ans, root->val - pre); + pre = root->val; + dfs(dfs, root->right); + }; + dfs(dfs, root); return ans; } - - void dfs(TreeNode* root) { - if (!root) return; - dfs(root->left); - ans = min(ans, abs(prev - root->val)); - prev = root->val; - dfs(root->right); - } }; \ No newline at end of file diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.go b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.go index 7d7440f7d846..f007348398b7 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.go +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.go @@ -7,25 +7,18 @@ * } */ func getMinimumDifference(root *TreeNode) int { - inf := 0x3f3f3f3f - ans, prev := inf, inf + const inf int = 1 << 30 + ans, pre := inf, -inf var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return } dfs(root.Left) - ans = min(ans, abs(prev-root.Val)) - prev = root.Val + ans = min(ans, root.Val-pre) + pre = root.Val dfs(root.Right) } dfs(root) return ans -} - -func abs(x int) int { - if x < 0 { - return -x - } - return x } \ No newline at end of file diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.java b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.java index 190ac5efddae..3b0b48927800 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.java +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.java @@ -14,13 +14,11 @@ * } */ class Solution { - private int ans; - private int prev; - private int inf = Integer.MAX_VALUE; + private final int inf = 1 << 30; + private int ans = inf; + private int pre = -inf; public int getMinimumDifference(TreeNode root) { - ans = inf; - prev = inf; dfs(root); return ans; } @@ -30,8 +28,8 @@ private void dfs(TreeNode root) { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); } } \ No newline at end of file diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.js b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.js new file mode 100644 index 000000000000..ff16b30be4a6 --- /dev/null +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.js @@ -0,0 +1,26 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var getMinimumDifference = function (root) { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = root => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); + }; + dfs(root); + return ans; +}; diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.py b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.py index eda3e769918d..7862484bd303 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.py +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.py @@ -5,16 +5,17 @@ # self.left = left # self.right = right class Solution: - def getMinimumDifference(self, root: TreeNode) -> int: - def dfs(root): + def getMinimumDifference(self, root: Optional[TreeNode]) -> int: + def dfs(root: Optional[TreeNode]): if root is None: return dfs(root.left) - nonlocal ans, prev - ans = min(ans, abs(prev - root.val)) - prev = root.val + nonlocal pre, ans + ans = min(ans, root.val - pre) + pre = root.val dfs(root.right) - ans = prev = inf + pre = -inf + ans = inf dfs(root) return ans diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.rs b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.rs index cf5396d9060e..1deee6d8efca 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.rs +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.rs @@ -19,26 +19,22 @@ use std::cell::RefCell; use std::rc::Rc; impl Solution { - #[allow(dead_code)] pub fn get_minimum_difference(root: Option>>) -> i32 { - let mut ret = i32::MAX; - let mut prev = i32::MAX; - Self::traverse(root, &mut prev, &mut ret); - ret - } + const inf: i32 = 1 << 30; + let mut ans = inf; + let mut pre = -inf; - #[allow(dead_code)] - fn traverse(root: Option>>, prev: &mut i32, ans: &mut i32) { - let left = root.as_ref().unwrap().borrow().left.clone(); - let right = root.as_ref().unwrap().borrow().right.clone(); - let val = root.as_ref().unwrap().borrow().val; - if !left.is_none() { - Self::traverse(left.clone(), prev, ans); - } - *ans = std::cmp::min(*ans, (*prev - val).abs()); - *prev = val; - if !right.is_none() { - Self::traverse(right.clone(), prev, ans); + fn dfs(node: Option>>, ans: &mut i32, pre: &mut i32) { + if let Some(n) = node { + let n = n.borrow(); + dfs(n.left.clone(), ans, pre); + *ans = (*ans).min(n.val - *pre); + *pre = n.val; + dfs(n.right.clone(), ans, pre); + } } + + dfs(root, &mut ans, &mut pre); + ans } } diff --git a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.ts b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.ts index 61275353165c..c4d98f25156f 100644 --- a/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.ts +++ b/solution/0500-0599/0530.Minimum Absolute Difference in BST/Solution.ts @@ -11,22 +11,18 @@ * } * } */ -function getMinimumDifference(root: TreeNode | null): number { - if (!root) return 0; - - let prev = Number.MIN_SAFE_INTEGER; - let min = Number.MAX_SAFE_INTEGER; - - const dfs = (node: TreeNode | null) => { - if (!node) return; - dfs(node.left); - min = Math.min(min, node.val - prev); - prev = node.val; - dfs(node.right); +function getMinimumDifference(root: TreeNode | null): number { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); }; - dfs(root); - - return min; + return ans; } diff --git a/solution/0500-0599/0537.Complex Number Multiplication/README.md b/solution/0500-0599/0537.Complex Number Multiplication/README.md index c14888e5658f..1444dc1d55c3 100644 --- a/solution/0500-0599/0537.Complex Number Multiplication/README.md +++ b/solution/0500-0599/0537.Complex Number Multiplication/README.md @@ -60,7 +60,11 @@ tags: -### 方法一 +### 方法一:模拟 + +我们可以将复数字符串转换成对应的实部 $a$ 和虚部 $b$,然后根据复数乘法的公式 $(a_1 + b_1i) \times (a_2 + b_2i) = (a_1a_2 - b_1b_2) + (a_1b_2 + a_2b_1)i$ 计算出结果。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 @@ -69,9 +73,9 @@ tags: ```python class Solution: def complexNumberMultiply(self, num1: str, num2: str) -> str: - a, b = map(int, num1[:-1].split('+')) - c, d = map(int, num2[:-1].split('+')) - return f'{a * c - b * d}+{a * d + c * b}i' + a1, b1 = map(int, num1[:-1].split("+")) + a2, b2 = map(int, num2[:-1].split("+")) + return f"{a1 * a2 - b1 * b2}+{a1 * b2 + a2 * b1}i" ``` #### Java @@ -79,13 +83,15 @@ class Solution: ```java class Solution { public String complexNumberMultiply(String num1, String num2) { - String[] c1 = num1.split("\\+|i"); - String[] c2 = num2.split("\\+|i"); - int a = Integer.parseInt(c1[0]); - int b = Integer.parseInt(c1[1]); - int c = Integer.parseInt(c2[0]); - int d = Integer.parseInt(c2[1]); - return String.format("%d+%di", a * c - b * d, a * d + c * b); + int[] x = parse(num1); + int[] y = parse(num2); + int a1 = x[0], b1 = x[1], a2 = y[0], b2 = y[1]; + return (a1 * a2 - b1 * b2) + "+" + (a1 * b2 + a2 * b1) + "i"; + } + + private int[] parse(String s) { + var cs = s.substring(0, s.length() - 1).split("\\+"); + return new int[] {Integer.parseInt(cs[0]), Integer.parseInt(cs[1])}; } } ``` @@ -96,10 +102,10 @@ class Solution { class Solution { public: string complexNumberMultiply(string num1, string num2) { - int a, b, c, d; - sscanf(num1.c_str(), "%d+%di", &a, &b); - sscanf(num2.c_str(), "%d+%di", &c, &d); - return string(to_string(a * c - b * d) + "+" + to_string(a * d + c * b) + "i"); + int a1, b1, a2, b2; + sscanf(num1.c_str(), "%d+%di", &a1, &b1); + sscanf(num2.c_str(), "%d+%di", &a2, &b2); + return to_string(a1 * a2 - b1 * b2) + "+" + to_string(a1 * b2 + a2 * b1) + "i"; } }; ``` @@ -107,16 +113,10 @@ public: #### Go ```go -func complexNumberMultiply(num1, num2 string) string { - parse := func(num string) (a, b int) { - i := strings.IndexByte(num, '+') - a, _ = strconv.Atoi(num[:i]) - b, _ = strconv.Atoi(num[i+1 : len(num)-1]) - return - } - a, b := parse(num1) - c, d := parse(num2) - return fmt.Sprintf("%d+%di", a*c-b*d, a*d+b*c) +func complexNumberMultiply(num1 string, num2 string) string { + x, _ := strconv.ParseComplex(num1, 64) + y, _ := strconv.ParseComplex(num2, 64) + return fmt.Sprintf("%d+%di", int(real(x*y)), int(imag(x*y))) } ``` @@ -124,15 +124,9 @@ func complexNumberMultiply(num1, num2 string) string { ```ts function complexNumberMultiply(num1: string, num2: string): string { - let arr1 = num1.split('+'), - arr2 = num2.split('+'); - let r1 = Number(arr1[0]), - r2 = Number(arr2[0]); - let v1 = Number(arr1[1].substring(0, arr1[1].length - 1)), - v2 = Number(arr2[1].substring(0, arr2[1].length - 1)); - let ansR = r1 * r2 - v1 * v2; - let ansV = r1 * v2 + r2 * v1; - return `${ansR}+${ansV}i`; + const [a1, b1] = num1.slice(0, -1).split('+').map(Number); + const [a2, b2] = num2.slice(0, -1).split('+').map(Number); + return `${a1 * a2 - b1 * b2}+${a1 * b2 + a2 * b1}i`; } ``` diff --git a/solution/0500-0599/0537.Complex Number Multiplication/README_EN.md b/solution/0500-0599/0537.Complex Number Multiplication/README_EN.md index 0a60653680fb..a33b5e90c1c2 100644 --- a/solution/0500-0599/0537.Complex Number Multiplication/README_EN.md +++ b/solution/0500-0599/0537.Complex Number Multiplication/README_EN.md @@ -58,7 +58,11 @@ tags: -### Solution 1 +### Solution 1: Simulation + +We can convert the complex number string into its real part $a$ and imaginary part $b$, and then use the formula for complex number multiplication $(a_1 + b_1i) \times (a_2 + b_2i) = (a_1a_2 - b_1b_2) + (a_1b_2 + a_2b_1)i$ to calculate the result. + +The time complexity is $O(1)$, and the space complexity is $O(1)$. @@ -67,9 +71,9 @@ tags: ```python class Solution: def complexNumberMultiply(self, num1: str, num2: str) -> str: - a, b = map(int, num1[:-1].split('+')) - c, d = map(int, num2[:-1].split('+')) - return f'{a * c - b * d}+{a * d + c * b}i' + a1, b1 = map(int, num1[:-1].split("+")) + a2, b2 = map(int, num2[:-1].split("+")) + return f"{a1 * a2 - b1 * b2}+{a1 * b2 + a2 * b1}i" ``` #### Java @@ -77,13 +81,15 @@ class Solution: ```java class Solution { public String complexNumberMultiply(String num1, String num2) { - String[] c1 = num1.split("\\+|i"); - String[] c2 = num2.split("\\+|i"); - int a = Integer.parseInt(c1[0]); - int b = Integer.parseInt(c1[1]); - int c = Integer.parseInt(c2[0]); - int d = Integer.parseInt(c2[1]); - return String.format("%d+%di", a * c - b * d, a * d + c * b); + int[] x = parse(num1); + int[] y = parse(num2); + int a1 = x[0], b1 = x[1], a2 = y[0], b2 = y[1]; + return (a1 * a2 - b1 * b2) + "+" + (a1 * b2 + a2 * b1) + "i"; + } + + private int[] parse(String s) { + var cs = s.substring(0, s.length() - 1).split("\\+"); + return new int[] {Integer.parseInt(cs[0]), Integer.parseInt(cs[1])}; } } ``` @@ -94,10 +100,10 @@ class Solution { class Solution { public: string complexNumberMultiply(string num1, string num2) { - int a, b, c, d; - sscanf(num1.c_str(), "%d+%di", &a, &b); - sscanf(num2.c_str(), "%d+%di", &c, &d); - return string(to_string(a * c - b * d) + "+" + to_string(a * d + c * b) + "i"); + int a1, b1, a2, b2; + sscanf(num1.c_str(), "%d+%di", &a1, &b1); + sscanf(num2.c_str(), "%d+%di", &a2, &b2); + return to_string(a1 * a2 - b1 * b2) + "+" + to_string(a1 * b2 + a2 * b1) + "i"; } }; ``` @@ -105,16 +111,10 @@ public: #### Go ```go -func complexNumberMultiply(num1, num2 string) string { - parse := func(num string) (a, b int) { - i := strings.IndexByte(num, '+') - a, _ = strconv.Atoi(num[:i]) - b, _ = strconv.Atoi(num[i+1 : len(num)-1]) - return - } - a, b := parse(num1) - c, d := parse(num2) - return fmt.Sprintf("%d+%di", a*c-b*d, a*d+b*c) +func complexNumberMultiply(num1 string, num2 string) string { + x, _ := strconv.ParseComplex(num1, 64) + y, _ := strconv.ParseComplex(num2, 64) + return fmt.Sprintf("%d+%di", int(real(x*y)), int(imag(x*y))) } ``` @@ -122,15 +122,9 @@ func complexNumberMultiply(num1, num2 string) string { ```ts function complexNumberMultiply(num1: string, num2: string): string { - let arr1 = num1.split('+'), - arr2 = num2.split('+'); - let r1 = Number(arr1[0]), - r2 = Number(arr2[0]); - let v1 = Number(arr1[1].substring(0, arr1[1].length - 1)), - v2 = Number(arr2[1].substring(0, arr2[1].length - 1)); - let ansR = r1 * r2 - v1 * v2; - let ansV = r1 * v2 + r2 * v1; - return `${ansR}+${ansV}i`; + const [a1, b1] = num1.slice(0, -1).split('+').map(Number); + const [a2, b2] = num2.slice(0, -1).split('+').map(Number); + return `${a1 * a2 - b1 * b2}+${a1 * b2 + a2 * b1}i`; } ``` diff --git a/solution/0500-0599/0537.Complex Number Multiplication/Solution.cpp b/solution/0500-0599/0537.Complex Number Multiplication/Solution.cpp index 6d495a4f8cb9..a92eb2ea4aa9 100644 --- a/solution/0500-0599/0537.Complex Number Multiplication/Solution.cpp +++ b/solution/0500-0599/0537.Complex Number Multiplication/Solution.cpp @@ -1,9 +1,9 @@ class Solution { public: string complexNumberMultiply(string num1, string num2) { - int a, b, c, d; - sscanf(num1.c_str(), "%d+%di", &a, &b); - sscanf(num2.c_str(), "%d+%di", &c, &d); - return string(to_string(a * c - b * d) + "+" + to_string(a * d + c * b) + "i"); + int a1, b1, a2, b2; + sscanf(num1.c_str(), "%d+%di", &a1, &b1); + sscanf(num2.c_str(), "%d+%di", &a2, &b2); + return to_string(a1 * a2 - b1 * b2) + "+" + to_string(a1 * b2 + a2 * b1) + "i"; } }; \ No newline at end of file diff --git a/solution/0500-0599/0537.Complex Number Multiplication/Solution.go b/solution/0500-0599/0537.Complex Number Multiplication/Solution.go index 78ff5f4b1484..70a3125794f4 100644 --- a/solution/0500-0599/0537.Complex Number Multiplication/Solution.go +++ b/solution/0500-0599/0537.Complex Number Multiplication/Solution.go @@ -1,11 +1,5 @@ -func complexNumberMultiply(num1, num2 string) string { - parse := func(num string) (a, b int) { - i := strings.IndexByte(num, '+') - a, _ = strconv.Atoi(num[:i]) - b, _ = strconv.Atoi(num[i+1 : len(num)-1]) - return - } - a, b := parse(num1) - c, d := parse(num2) - return fmt.Sprintf("%d+%di", a*c-b*d, a*d+b*c) +func complexNumberMultiply(num1 string, num2 string) string { + x, _ := strconv.ParseComplex(num1, 64) + y, _ := strconv.ParseComplex(num2, 64) + return fmt.Sprintf("%d+%di", int(real(x*y)), int(imag(x*y))) } \ No newline at end of file diff --git a/solution/0500-0599/0537.Complex Number Multiplication/Solution.java b/solution/0500-0599/0537.Complex Number Multiplication/Solution.java index 92b77ace32f6..570b3092f4e1 100644 --- a/solution/0500-0599/0537.Complex Number Multiplication/Solution.java +++ b/solution/0500-0599/0537.Complex Number Multiplication/Solution.java @@ -1,11 +1,13 @@ class Solution { public String complexNumberMultiply(String num1, String num2) { - String[] c1 = num1.split("\\+|i"); - String[] c2 = num2.split("\\+|i"); - int a = Integer.parseInt(c1[0]); - int b = Integer.parseInt(c1[1]); - int c = Integer.parseInt(c2[0]); - int d = Integer.parseInt(c2[1]); - return String.format("%d+%di", a * c - b * d, a * d + c * b); + int[] x = parse(num1); + int[] y = parse(num2); + int a1 = x[0], b1 = x[1], a2 = y[0], b2 = y[1]; + return (a1 * a2 - b1 * b2) + "+" + (a1 * b2 + a2 * b1) + "i"; + } + + private int[] parse(String s) { + var cs = s.substring(0, s.length() - 1).split("\\+"); + return new int[] {Integer.parseInt(cs[0]), Integer.parseInt(cs[1])}; } } \ No newline at end of file diff --git a/solution/0500-0599/0537.Complex Number Multiplication/Solution.py b/solution/0500-0599/0537.Complex Number Multiplication/Solution.py index 6513c069de99..8263fe6e32c1 100644 --- a/solution/0500-0599/0537.Complex Number Multiplication/Solution.py +++ b/solution/0500-0599/0537.Complex Number Multiplication/Solution.py @@ -1,5 +1,5 @@ class Solution: def complexNumberMultiply(self, num1: str, num2: str) -> str: - a, b = map(int, num1[:-1].split('+')) - c, d = map(int, num2[:-1].split('+')) - return f'{a * c - b * d}+{a * d + c * b}i' + a1, b1 = map(int, num1[:-1].split("+")) + a2, b2 = map(int, num2[:-1].split("+")) + return f"{a1 * a2 - b1 * b2}+{a1 * b2 + a2 * b1}i" diff --git a/solution/0500-0599/0537.Complex Number Multiplication/Solution.ts b/solution/0500-0599/0537.Complex Number Multiplication/Solution.ts index 0c0589ad5267..1313663055aa 100644 --- a/solution/0500-0599/0537.Complex Number Multiplication/Solution.ts +++ b/solution/0500-0599/0537.Complex Number Multiplication/Solution.ts @@ -1,11 +1,5 @@ function complexNumberMultiply(num1: string, num2: string): string { - let arr1 = num1.split('+'), - arr2 = num2.split('+'); - let r1 = Number(arr1[0]), - r2 = Number(arr2[0]); - let v1 = Number(arr1[1].substring(0, arr1[1].length - 1)), - v2 = Number(arr2[1].substring(0, arr2[1].length - 1)); - let ansR = r1 * r2 - v1 * v2; - let ansV = r1 * v2 + r2 * v1; - return `${ansR}+${ansV}i`; + const [a1, b1] = num1.slice(0, -1).split('+').map(Number); + const [a2, b2] = num2.slice(0, -1).split('+').map(Number); + return `${a1 * a2 - b1 * b2}+${a1 * b2 + a2 * b1}i`; } diff --git a/solution/0500-0599/0541.Reverse String II/README.md b/solution/0500-0599/0541.Reverse String II/README.md index a6a3dfbada4d..34e9a41e10c2 100644 --- a/solution/0500-0599/0541.Reverse String II/README.md +++ b/solution/0500-0599/0541.Reverse String II/README.md @@ -56,7 +56,11 @@ tags: -### 方法一 +### 方法一:双指针 + +我们可以遍历字符串 $\textit{s}$,每次遍历 $\textit{2k}$ 个字符,然后利用双指针技巧,对这 $\textit{2k}$ 个字符中的前 $\textit{k}$ 个字符进行反转。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $\textit{s}$ 的长度。 @@ -65,10 +69,10 @@ tags: ```python class Solution: def reverseStr(self, s: str, k: int) -> str: - t = list(s) - for i in range(0, len(t), k << 1): - t[i : i + k] = reversed(t[i : i + k]) - return ''.join(t) + cs = list(s) + for i in range(0, len(cs), 2 * k): + cs[i : i + k] = reversed(cs[i : i + k]) + return "".join(cs) ``` #### Java @@ -76,15 +80,16 @@ class Solution: ```java class Solution { public String reverseStr(String s, int k) { - char[] chars = s.toCharArray(); - for (int i = 0; i < chars.length; i += (k << 1)) { - for (int st = i, ed = Math.min(chars.length - 1, i + k - 1); st < ed; ++st, --ed) { - char t = chars[st]; - chars[st] = chars[ed]; - chars[ed] = t; + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 0; i < n; i += k * 2) { + for (int l = i, r = Math.min(i + k - 1, n - 1); l < r; ++l, --r) { + char t = cs[l]; + cs[l] = cs[r]; + cs[r] = t; } } - return new String(chars); + return new String(cs); } } ``` @@ -95,7 +100,8 @@ class Solution { class Solution { public: string reverseStr(string s, int k) { - for (int i = 0, n = s.size(); i < n; i += (k << 1)) { + int n = s.size(); + for (int i = 0; i < n; i += 2 * k) { reverse(s.begin() + i, s.begin() + min(i + k, n)); } return s; @@ -107,13 +113,29 @@ public: ```go func reverseStr(s string, k int) string { - t := []byte(s) - for i := 0; i < len(t); i += (k << 1) { - for st, ed := i, min(i+k-1, len(t)-1); st < ed; st, ed = st+1, ed-1 { - t[st], t[ed] = t[ed], t[st] + cs := []byte(s) + n := len(cs) + for i := 0; i < n; i += 2 * k { + for l, r := i, min(i+k-1, n-1); l < r; l, r = l+1, r-1 { + cs[l], cs[r] = cs[r], cs[l] } } - return string(t) + return string(cs) +} +``` + +#### TypeScript + +```ts +function reverseStr(s: string, k: number): string { + const n = s.length; + const cs = s.split(''); + for (let i = 0; i < n; i += 2 * k) { + for (let l = i, r = Math.min(i + k - 1, n - 1); l < r; l++, r--) { + [cs[l], cs[r]] = [cs[r], cs[l]]; + } + } + return cs.join(''); } ``` diff --git a/solution/0500-0599/0541.Reverse String II/README_EN.md b/solution/0500-0599/0541.Reverse String II/README_EN.md index 5923f43e1fe5..4570c4d6afae 100644 --- a/solution/0500-0599/0541.Reverse String II/README_EN.md +++ b/solution/0500-0599/0541.Reverse String II/README_EN.md @@ -44,7 +44,11 @@ tags: -### Solution 1 +### Solution 1: Two Pointers + +We can traverse the string $\textit{s}$, iterating over every $\textit{2k}$ characters, and then use the two-pointer technique to reverse the first $\textit{k}$ characters among these $\textit{2k}$ characters. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $\textit{s}$. @@ -53,10 +57,10 @@ tags: ```python class Solution: def reverseStr(self, s: str, k: int) -> str: - t = list(s) - for i in range(0, len(t), k << 1): - t[i : i + k] = reversed(t[i : i + k]) - return ''.join(t) + cs = list(s) + for i in range(0, len(cs), 2 * k): + cs[i : i + k] = reversed(cs[i : i + k]) + return "".join(cs) ``` #### Java @@ -64,15 +68,16 @@ class Solution: ```java class Solution { public String reverseStr(String s, int k) { - char[] chars = s.toCharArray(); - for (int i = 0; i < chars.length; i += (k << 1)) { - for (int st = i, ed = Math.min(chars.length - 1, i + k - 1); st < ed; ++st, --ed) { - char t = chars[st]; - chars[st] = chars[ed]; - chars[ed] = t; + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 0; i < n; i += k * 2) { + for (int l = i, r = Math.min(i + k - 1, n - 1); l < r; ++l, --r) { + char t = cs[l]; + cs[l] = cs[r]; + cs[r] = t; } } - return new String(chars); + return new String(cs); } } ``` @@ -83,7 +88,8 @@ class Solution { class Solution { public: string reverseStr(string s, int k) { - for (int i = 0, n = s.size(); i < n; i += (k << 1)) { + int n = s.size(); + for (int i = 0; i < n; i += 2 * k) { reverse(s.begin() + i, s.begin() + min(i + k, n)); } return s; @@ -95,13 +101,29 @@ public: ```go func reverseStr(s string, k int) string { - t := []byte(s) - for i := 0; i < len(t); i += (k << 1) { - for st, ed := i, min(i+k-1, len(t)-1); st < ed; st, ed = st+1, ed-1 { - t[st], t[ed] = t[ed], t[st] + cs := []byte(s) + n := len(cs) + for i := 0; i < n; i += 2 * k { + for l, r := i, min(i+k-1, n-1); l < r; l, r = l+1, r-1 { + cs[l], cs[r] = cs[r], cs[l] } } - return string(t) + return string(cs) +} +``` + +#### TypeScript + +```ts +function reverseStr(s: string, k: number): string { + const n = s.length; + const cs = s.split(''); + for (let i = 0; i < n; i += 2 * k) { + for (let l = i, r = Math.min(i + k - 1, n - 1); l < r; l++, r--) { + [cs[l], cs[r]] = [cs[r], cs[l]]; + } + } + return cs.join(''); } ``` diff --git a/solution/0500-0599/0541.Reverse String II/Solution.cpp b/solution/0500-0599/0541.Reverse String II/Solution.cpp index 528788dee6aa..fb9bca75b1a6 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.cpp +++ b/solution/0500-0599/0541.Reverse String II/Solution.cpp @@ -1,7 +1,8 @@ class Solution { public: string reverseStr(string s, int k) { - for (int i = 0, n = s.size(); i < n; i += (k << 1)) { + int n = s.size(); + for (int i = 0; i < n; i += 2 * k) { reverse(s.begin() + i, s.begin() + min(i + k, n)); } return s; diff --git a/solution/0500-0599/0541.Reverse String II/Solution.go b/solution/0500-0599/0541.Reverse String II/Solution.go index 937f6a2ec171..7d3e1ae5e2b5 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.go +++ b/solution/0500-0599/0541.Reverse String II/Solution.go @@ -1,9 +1,10 @@ func reverseStr(s string, k int) string { - t := []byte(s) - for i := 0; i < len(t); i += (k << 1) { - for st, ed := i, min(i+k-1, len(t)-1); st < ed; st, ed = st+1, ed-1 { - t[st], t[ed] = t[ed], t[st] + cs := []byte(s) + n := len(cs) + for i := 0; i < n; i += 2 * k { + for l, r := i, min(i+k-1, n-1); l < r; l, r = l+1, r-1 { + cs[l], cs[r] = cs[r], cs[l] } } - return string(t) + return string(cs) } \ No newline at end of file diff --git a/solution/0500-0599/0541.Reverse String II/Solution.java b/solution/0500-0599/0541.Reverse String II/Solution.java index 743b7105f619..4d5d022938e9 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.java +++ b/solution/0500-0599/0541.Reverse String II/Solution.java @@ -1,13 +1,14 @@ class Solution { public String reverseStr(String s, int k) { - char[] chars = s.toCharArray(); - for (int i = 0; i < chars.length; i += (k << 1)) { - for (int st = i, ed = Math.min(chars.length - 1, i + k - 1); st < ed; ++st, --ed) { - char t = chars[st]; - chars[st] = chars[ed]; - chars[ed] = t; + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 0; i < n; i += k * 2) { + for (int l = i, r = Math.min(i + k - 1, n - 1); l < r; ++l, --r) { + char t = cs[l]; + cs[l] = cs[r]; + cs[r] = t; } } - return new String(chars); + return new String(cs); } } \ No newline at end of file diff --git a/solution/0500-0599/0541.Reverse String II/Solution.py b/solution/0500-0599/0541.Reverse String II/Solution.py index 3a7d74c5c837..2487b7a841e0 100644 --- a/solution/0500-0599/0541.Reverse String II/Solution.py +++ b/solution/0500-0599/0541.Reverse String II/Solution.py @@ -1,6 +1,6 @@ class Solution: def reverseStr(self, s: str, k: int) -> str: - t = list(s) - for i in range(0, len(t), k << 1): - t[i : i + k] = reversed(t[i : i + k]) - return ''.join(t) + cs = list(s) + for i in range(0, len(cs), 2 * k): + cs[i : i + k] = reversed(cs[i : i + k]) + return "".join(cs) diff --git a/solution/0500-0599/0541.Reverse String II/Solution.ts b/solution/0500-0599/0541.Reverse String II/Solution.ts new file mode 100644 index 000000000000..55ebb15a4612 --- /dev/null +++ b/solution/0500-0599/0541.Reverse String II/Solution.ts @@ -0,0 +1,10 @@ +function reverseStr(s: string, k: number): string { + const n = s.length; + const cs = s.split(''); + for (let i = 0; i < n; i += 2 * k) { + for (let l = i, r = Math.min(i + k - 1, n - 1); l < r; l++, r--) { + [cs[l], cs[r]] = [cs[r], cs[l]]; + } + } + return cs.join(''); +} diff --git a/solution/0500-0599/0542.01 Matrix/README.md b/solution/0500-0599/0542.01 Matrix/README.md index 1af062da84d4..23329b7a9a4c 100644 --- a/solution/0500-0599/0542.01 Matrix/README.md +++ b/solution/0500-0599/0542.01 Matrix/README.md @@ -62,11 +62,17 @@ tags: -### 方法一:多源 BFS +### 方法一:BFS -初始化结果矩阵 ans,所有 0 的距离为 0,所以 1 的距离为 -1。初始化队列 q 存储 BFS 需要检查的位置,并将所有 0 的位置入队。 +我们创建一个大小和 $\textit{mat}$ 一样的矩阵 $\textit{ans}$,并将所有的元素初始化为 $-1$。 -循环弹出队列 q 的元素 `p(i, j)`,检查邻居四个点。对于邻居 `(x, y)`,如果 `ans[x][y] = -1`,则更新 `ans[x][y] = ans[i][j] + 1`。同时将 `(x, y)` 入队。 +然后我们遍历 $\textit{mat}$,将所有的 $0$ 元素的坐标 $(i, j)$ 加入队列 $\textit{q}$,并将 $\textit{ans}[i][j]$ 设为 $0$。 + +接下来,我们使用广度优先搜索,从队列中取出一个元素 $(i, j)$,并遍历其四个方向,如果该方向的元素 $(x, y)$ 满足 $0 \leq x < m$, $0 \leq y < n$ 且 $\textit{ans}[x][y] = -1$,则将 $\textit{ans}[x][y]$ 设为 $\textit{ans}[i][j] + 1$,并将 $(x, y)$ 加入队列 $\textit{q}$。 + +最后返回 $\textit{ans}$。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为矩阵 $\textit{mat}$ 的行数和列数。 @@ -219,8 +225,7 @@ function updateMatrix(mat: number[][]): number[][] { } } const dirs: number[] = [-1, 0, 1, 0, -1]; - while (q.length) { - const [i, j] = q.shift()!; + for (const [i, j] of q) { for (let k = 0; k < 4; ++k) { const [x, y] = [i + dirs[k], j + dirs[k + 1]]; if (x >= 0 && x < m && y >= 0 && y < n && ans[x][y] === -1) { @@ -239,49 +244,38 @@ function updateMatrix(mat: number[][]): number[][] { use std::collections::VecDeque; impl Solution { - #[allow(dead_code)] pub fn update_matrix(mat: Vec>) -> Vec> { - let n: usize = mat.len(); - let m: usize = mat[0].len(); - let mut ret_vec: Vec> = vec![vec![-1; m]; n]; - // The inner tuple is of - let mut the_q: VecDeque<(usize, usize)> = VecDeque::new(); - let traverse_vec: Vec<(i32, i32)> = vec![(-1, 0), (1, 0), (0, 1), (0, -1)]; - - // Initialize the queue - for i in 0..n { - for j in 0..m { + let m = mat.len(); + let n = mat[0].len(); + let mut ans = vec![vec![-1; n]; m]; + let mut q = VecDeque::new(); + + for i in 0..m { + for j in 0..n { if mat[i][j] == 0 { - // For the zero cell, enqueue at first - the_q.push_back((i, j)); - // Set to 0 in return vector - ret_vec[i][j] = 0; + q.push_back((i, j)); + ans[i][j] = 0; } } } - while !the_q.is_empty() { - let (x, y) = the_q.front().unwrap().clone(); - the_q.pop_front(); - for pair in &traverse_vec { - let cur_x = pair.0 + (x as i32); - let cur_y = pair.1 + (y as i32); - if Solution::check_bounds(cur_x, cur_y, n as i32, m as i32) - && ret_vec[cur_x as usize][cur_y as usize] == -1 - { - // The current cell has not be updated yet, and is also in bound - ret_vec[cur_x as usize][cur_y as usize] = ret_vec[x][y] + 1; - the_q.push_back((cur_x as usize, cur_y as usize)); + let dirs = [-1, 0, 1, 0, -1]; + while let Some((i, j)) = q.pop_front() { + for k in 0..4 { + let x = i as isize + dirs[k]; + let y = j as isize + dirs[k + 1]; + if x >= 0 && x < m as isize && y >= 0 && y < n as isize { + let x = x as usize; + let y = y as usize; + if ans[x][y] == -1 { + ans[x][y] = ans[i][j] + 1; + q.push_back((x, y)); + } } } } - ret_vec - } - - #[allow(dead_code)] - pub fn check_bounds(i: i32, j: i32, n: i32, m: i32) -> bool { - i >= 0 && i < n && j >= 0 && j < m + ans } } ``` diff --git a/solution/0500-0599/0542.01 Matrix/README_EN.md b/solution/0500-0599/0542.01 Matrix/README_EN.md index a81f66566262..cde08787d2bd 100644 --- a/solution/0500-0599/0542.01 Matrix/README_EN.md +++ b/solution/0500-0599/0542.01 Matrix/README_EN.md @@ -56,7 +56,17 @@ tags: -### Solution 1 +### Solution 1: BFS + +We create a matrix $\textit{ans}$ of the same size as $\textit{mat}$ and initialize all elements to $-1$. + +Then, we traverse $\textit{mat}$, adding the coordinates $(i, j)$ of all $0$ elements to the queue $\textit{q}$, and setting $\textit{ans}[i][j]$ to $0$. + +Next, we use Breadth-First Search (BFS), removing an element $(i, j)$ from the queue and traversing its four directions. If the element in that direction $(x, y)$ satisfies $0 \leq x < m$, $0 \leq y < n$ and $\textit{ans}[x][y] = -1$, then we set $\textit{ans}[x][y]$ to $\textit{ans}[i][j] + 1$ and add $(x, y)$ to the queue $\textit{q}$. + +Finally, we return $\textit{ans}$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the number of rows and columns in the matrix $\textit{mat}$, respectively. @@ -209,8 +219,7 @@ function updateMatrix(mat: number[][]): number[][] { } } const dirs: number[] = [-1, 0, 1, 0, -1]; - while (q.length) { - const [i, j] = q.shift()!; + for (const [i, j] of q) { for (let k = 0; k < 4; ++k) { const [x, y] = [i + dirs[k], j + dirs[k + 1]]; if (x >= 0 && x < m && y >= 0 && y < n && ans[x][y] === -1) { @@ -229,49 +238,38 @@ function updateMatrix(mat: number[][]): number[][] { use std::collections::VecDeque; impl Solution { - #[allow(dead_code)] pub fn update_matrix(mat: Vec>) -> Vec> { - let n: usize = mat.len(); - let m: usize = mat[0].len(); - let mut ret_vec: Vec> = vec![vec![-1; m]; n]; - // The inner tuple is of - let mut the_q: VecDeque<(usize, usize)> = VecDeque::new(); - let traverse_vec: Vec<(i32, i32)> = vec![(-1, 0), (1, 0), (0, 1), (0, -1)]; - - // Initialize the queue - for i in 0..n { - for j in 0..m { + let m = mat.len(); + let n = mat[0].len(); + let mut ans = vec![vec![-1; n]; m]; + let mut q = VecDeque::new(); + + for i in 0..m { + for j in 0..n { if mat[i][j] == 0 { - // For the zero cell, enqueue at first - the_q.push_back((i, j)); - // Set to 0 in return vector - ret_vec[i][j] = 0; + q.push_back((i, j)); + ans[i][j] = 0; } } } - while !the_q.is_empty() { - let (x, y) = the_q.front().unwrap().clone(); - the_q.pop_front(); - for pair in &traverse_vec { - let cur_x = pair.0 + (x as i32); - let cur_y = pair.1 + (y as i32); - if Solution::check_bounds(cur_x, cur_y, n as i32, m as i32) - && ret_vec[cur_x as usize][cur_y as usize] == -1 - { - // The current cell has not be updated yet, and is also in bound - ret_vec[cur_x as usize][cur_y as usize] = ret_vec[x][y] + 1; - the_q.push_back((cur_x as usize, cur_y as usize)); + let dirs = [-1, 0, 1, 0, -1]; + while let Some((i, j)) = q.pop_front() { + for k in 0..4 { + let x = i as isize + dirs[k]; + let y = j as isize + dirs[k + 1]; + if x >= 0 && x < m as isize && y >= 0 && y < n as isize { + let x = x as usize; + let y = y as usize; + if ans[x][y] == -1 { + ans[x][y] = ans[i][j] + 1; + q.push_back((x, y)); + } } } } - ret_vec - } - - #[allow(dead_code)] - pub fn check_bounds(i: i32, j: i32, n: i32, m: i32) -> bool { - i >= 0 && i < n && j >= 0 && j < m + ans } } ``` diff --git a/solution/0500-0599/0542.01 Matrix/Solution.rs b/solution/0500-0599/0542.01 Matrix/Solution.rs index 4f6b1f7f3879..4913bce5d043 100644 --- a/solution/0500-0599/0542.01 Matrix/Solution.rs +++ b/solution/0500-0599/0542.01 Matrix/Solution.rs @@ -1,48 +1,37 @@ use std::collections::VecDeque; impl Solution { - #[allow(dead_code)] pub fn update_matrix(mat: Vec>) -> Vec> { - let n: usize = mat.len(); - let m: usize = mat[0].len(); - let mut ret_vec: Vec> = vec![vec![-1; m]; n]; - // The inner tuple is of - let mut the_q: VecDeque<(usize, usize)> = VecDeque::new(); - let traverse_vec: Vec<(i32, i32)> = vec![(-1, 0), (1, 0), (0, 1), (0, -1)]; + let m = mat.len(); + let n = mat[0].len(); + let mut ans = vec![vec![-1; n]; m]; + let mut q = VecDeque::new(); - // Initialize the queue - for i in 0..n { - for j in 0..m { + for i in 0..m { + for j in 0..n { if mat[i][j] == 0 { - // For the zero cell, enqueue at first - the_q.push_back((i, j)); - // Set to 0 in return vector - ret_vec[i][j] = 0; + q.push_back((i, j)); + ans[i][j] = 0; } } } - while !the_q.is_empty() { - let (x, y) = the_q.front().unwrap().clone(); - the_q.pop_front(); - for pair in &traverse_vec { - let cur_x = pair.0 + (x as i32); - let cur_y = pair.1 + (y as i32); - if Solution::check_bounds(cur_x, cur_y, n as i32, m as i32) - && ret_vec[cur_x as usize][cur_y as usize] == -1 - { - // The current cell has not be updated yet, and is also in bound - ret_vec[cur_x as usize][cur_y as usize] = ret_vec[x][y] + 1; - the_q.push_back((cur_x as usize, cur_y as usize)); + let dirs = [-1, 0, 1, 0, -1]; + while let Some((i, j)) = q.pop_front() { + for k in 0..4 { + let x = i as isize + dirs[k]; + let y = j as isize + dirs[k + 1]; + if x >= 0 && x < m as isize && y >= 0 && y < n as isize { + let x = x as usize; + let y = y as usize; + if ans[x][y] == -1 { + ans[x][y] = ans[i][j] + 1; + q.push_back((x, y)); + } } } } - ret_vec - } - - #[allow(dead_code)] - pub fn check_bounds(i: i32, j: i32, n: i32, m: i32) -> bool { - i >= 0 && i < n && j >= 0 && j < m + ans } } diff --git a/solution/0500-0599/0542.01 Matrix/Solution.ts b/solution/0500-0599/0542.01 Matrix/Solution.ts index d3ec5bf28194..d44cdb2d7e70 100644 --- a/solution/0500-0599/0542.01 Matrix/Solution.ts +++ b/solution/0500-0599/0542.01 Matrix/Solution.ts @@ -11,8 +11,7 @@ function updateMatrix(mat: number[][]): number[][] { } } const dirs: number[] = [-1, 0, 1, 0, -1]; - while (q.length) { - const [i, j] = q.shift()!; + for (const [i, j] of q) { for (let k = 0; k < 4; ++k) { const [x, y] = [i + dirs[k], j + dirs[k + 1]]; if (x >= 0 && x < m && y >= 0 && y < n && ans[x][y] === -1) { diff --git a/solution/0500-0599/0544.Output Contest Matches/README.md b/solution/0500-0599/0544.Output Contest Matches/README.md index 75765760356e..6a0ea9563e04 100644 --- a/solution/0500-0599/0544.Output Contest Matches/README.md +++ b/solution/0500-0599/0544.Output Contest Matches/README.md @@ -69,9 +69,11 @@ tags: ### 方法一:模拟 -假设 `team[i]` 为当前轮次中第 i 强的队伍。 +我们可以用一个长度为 $n$ 的数组 $s$ 来存储每个队伍的编号,然后模拟比赛的过程。 -每一轮,将第 i 支队伍变成 `"(" + team[i] + "," + team[n-1-i] + ")"`,并且每一轮淘汰一半的队伍。 +每一轮比赛,我们将数组 $s$ 中的前 $n$ 个元素两两配对,然后将胜者的编号存入数组 $s$ 的前 $n/2$ 个位置。然后,我们将 $n$ 减半,继续进行下一轮比赛,直到 $n$ 减半为 $1$,此时数组 $s$ 中的第一个元素即为最终的比赛匹配方案。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n \times \log n)$。其中 $n$ 为队伍的数量。 @@ -80,12 +82,12 @@ tags: ```python class Solution: def findContestMatch(self, n: int) -> str: - team = [str(i + 1) for i in range(n)] + s = [str(i + 1) for i in range(n)] while n > 1: for i in range(n >> 1): - team[i] = f'({team[i]},{team[n - 1 - i]})' + s[i] = f"({s[i]},{s[n - i - 1]})" n >>= 1 - return team[0] + return s[0] ``` #### Java @@ -93,16 +95,16 @@ class Solution: ```java class Solution { public String findContestMatch(int n) { - String[] team = new String[n]; + String[] s = new String[n]; for (int i = 0; i < n; ++i) { - team[i] = "" + (i + 1); + s[i] = String.valueOf(i + 1); } - for (; n > 1; n /= 2) { - for (int i = 0; i < n / 2; ++i) { - team[i] = "(" + team[i] + "," + team[n - 1 - i] + ")"; + for (; n > 1; n >>= 1) { + for (int i = 0; i < n >> 1; ++i) { + s[i] = String.format("(%s,%s)", s[i], s[n - i - 1]); } } - return team[0]; + return s[0]; } } ``` @@ -113,14 +115,16 @@ class Solution { class Solution { public: string findContestMatch(int n) { - vector team(n); - for (int i = 0; i < n; ++i) team[i] = to_string(i + 1); + vector s(n); + for (int i = 0; i < n; ++i) { + s[i] = to_string(i + 1); + } for (; n > 1; n >>= 1) { for (int i = 0; i < n >> 1; ++i) { - team[i] = "(" + team[i] + "," + team[n - 1 - i] + ")"; + s[i] = "(" + s[i] + "," + s[n - i - 1] + ")"; } } - return team[0]; + return s[0]; } }; ``` @@ -129,17 +133,30 @@ public: ```go func findContestMatch(n int) string { - team := make([]string, n) - for i := range team { - team[i] = strconv.Itoa(i + 1) + s := make([]string, n) + for i := 0; i < n; i++ { + s[i] = strconv.Itoa(i + 1) } - for n > 1 { + for ; n > 1; n >>= 1 { for i := 0; i < n>>1; i++ { - team[i] = "(" + team[i] + "," + team[n-1-i] + ")" + s[i] = fmt.Sprintf("(%s,%s)", s[i], s[n-i-1]) } - n >>= 1 } - return team[0] + return s[0] +} +``` + +#### TypeScript + +```ts +function findContestMatch(n: number): string { + const s: string[] = Array.from({ length: n }, (_, i) => (i + 1).toString()); + for (; n > 1; n >>= 1) { + for (let i = 0; i < n >> 1; ++i) { + s[i] = `(${s[i]},${s[n - i - 1]})`; + } + } + return s[0]; } ``` diff --git a/solution/0500-0599/0544.Output Contest Matches/README_EN.md b/solution/0500-0599/0544.Output Contest Matches/README_EN.md index f0a08ac564d7..ba2198e77d29 100644 --- a/solution/0500-0599/0544.Output Contest Matches/README_EN.md +++ b/solution/0500-0599/0544.Output Contest Matches/README_EN.md @@ -64,7 +64,13 @@ Since the third round will generate the final winner, you need to output the ans -### Solution 1 +### Solution 1: Simulation + +We can use an array $s$ of length $n$ to store the ID of each team, and then simulate the process of the matches. + +In each round of matches, we pair up the first $n$ elements in array $s$ two by two, and then store the ID of the winners in the first $n/2$ positions of array $s$. After that, we halve $n$ and continue to the next round of matches, until $n$ is reduced to $1$. At this point, the first element in array $s$ is the final match-up scheme. + +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of teams. @@ -73,12 +79,12 @@ Since the third round will generate the final winner, you need to output the ans ```python class Solution: def findContestMatch(self, n: int) -> str: - team = [str(i + 1) for i in range(n)] + s = [str(i + 1) for i in range(n)] while n > 1: for i in range(n >> 1): - team[i] = f'({team[i]},{team[n - 1 - i]})' + s[i] = f"({s[i]},{s[n - i - 1]})" n >>= 1 - return team[0] + return s[0] ``` #### Java @@ -86,16 +92,16 @@ class Solution: ```java class Solution { public String findContestMatch(int n) { - String[] team = new String[n]; + String[] s = new String[n]; for (int i = 0; i < n; ++i) { - team[i] = "" + (i + 1); + s[i] = String.valueOf(i + 1); } - for (; n > 1; n /= 2) { - for (int i = 0; i < n / 2; ++i) { - team[i] = "(" + team[i] + "," + team[n - 1 - i] + ")"; + for (; n > 1; n >>= 1) { + for (int i = 0; i < n >> 1; ++i) { + s[i] = String.format("(%s,%s)", s[i], s[n - i - 1]); } } - return team[0]; + return s[0]; } } ``` @@ -106,14 +112,16 @@ class Solution { class Solution { public: string findContestMatch(int n) { - vector team(n); - for (int i = 0; i < n; ++i) team[i] = to_string(i + 1); + vector s(n); + for (int i = 0; i < n; ++i) { + s[i] = to_string(i + 1); + } for (; n > 1; n >>= 1) { for (int i = 0; i < n >> 1; ++i) { - team[i] = "(" + team[i] + "," + team[n - 1 - i] + ")"; + s[i] = "(" + s[i] + "," + s[n - i - 1] + ")"; } } - return team[0]; + return s[0]; } }; ``` @@ -122,17 +130,30 @@ public: ```go func findContestMatch(n int) string { - team := make([]string, n) - for i := range team { - team[i] = strconv.Itoa(i + 1) + s := make([]string, n) + for i := 0; i < n; i++ { + s[i] = strconv.Itoa(i + 1) } - for n > 1 { + for ; n > 1; n >>= 1 { for i := 0; i < n>>1; i++ { - team[i] = "(" + team[i] + "," + team[n-1-i] + ")" + s[i] = fmt.Sprintf("(%s,%s)", s[i], s[n-i-1]) } - n >>= 1 } - return team[0] + return s[0] +} +``` + +#### TypeScript + +```ts +function findContestMatch(n: number): string { + const s: string[] = Array.from({ length: n }, (_, i) => (i + 1).toString()); + for (; n > 1; n >>= 1) { + for (let i = 0; i < n >> 1; ++i) { + s[i] = `(${s[i]},${s[n - i - 1]})`; + } + } + return s[0]; } ``` diff --git a/solution/0500-0599/0544.Output Contest Matches/Solution.cpp b/solution/0500-0599/0544.Output Contest Matches/Solution.cpp index 9c82aff11659..61a2e8360e80 100644 --- a/solution/0500-0599/0544.Output Contest Matches/Solution.cpp +++ b/solution/0500-0599/0544.Output Contest Matches/Solution.cpp @@ -1,13 +1,15 @@ class Solution { public: string findContestMatch(int n) { - vector team(n); - for (int i = 0; i < n; ++i) team[i] = to_string(i + 1); + vector s(n); + for (int i = 0; i < n; ++i) { + s[i] = to_string(i + 1); + } for (; n > 1; n >>= 1) { for (int i = 0; i < n >> 1; ++i) { - team[i] = "(" + team[i] + "," + team[n - 1 - i] + ")"; + s[i] = "(" + s[i] + "," + s[n - i - 1] + ")"; } } - return team[0]; + return s[0]; } }; \ No newline at end of file diff --git a/solution/0500-0599/0544.Output Contest Matches/Solution.go b/solution/0500-0599/0544.Output Contest Matches/Solution.go index 1e51283d70a0..edb7ea5eb04e 100644 --- a/solution/0500-0599/0544.Output Contest Matches/Solution.go +++ b/solution/0500-0599/0544.Output Contest Matches/Solution.go @@ -1,13 +1,12 @@ func findContestMatch(n int) string { - team := make([]string, n) - for i := range team { - team[i] = strconv.Itoa(i + 1) + s := make([]string, n) + for i := 0; i < n; i++ { + s[i] = strconv.Itoa(i + 1) } - for n > 1 { + for ; n > 1; n >>= 1 { for i := 0; i < n>>1; i++ { - team[i] = "(" + team[i] + "," + team[n-1-i] + ")" + s[i] = fmt.Sprintf("(%s,%s)", s[i], s[n-i-1]) } - n >>= 1 } - return team[0] + return s[0] } \ No newline at end of file diff --git a/solution/0500-0599/0544.Output Contest Matches/Solution.java b/solution/0500-0599/0544.Output Contest Matches/Solution.java index 986ae52900a0..be60130326c4 100644 --- a/solution/0500-0599/0544.Output Contest Matches/Solution.java +++ b/solution/0500-0599/0544.Output Contest Matches/Solution.java @@ -1,14 +1,14 @@ class Solution { public String findContestMatch(int n) { - String[] team = new String[n]; + String[] s = new String[n]; for (int i = 0; i < n; ++i) { - team[i] = "" + (i + 1); + s[i] = String.valueOf(i + 1); } - for (; n > 1; n /= 2) { - for (int i = 0; i < n / 2; ++i) { - team[i] = "(" + team[i] + "," + team[n - 1 - i] + ")"; + for (; n > 1; n >>= 1) { + for (int i = 0; i < n >> 1; ++i) { + s[i] = String.format("(%s,%s)", s[i], s[n - i - 1]); } } - return team[0]; + return s[0]; } } \ No newline at end of file diff --git a/solution/0500-0599/0544.Output Contest Matches/Solution.py b/solution/0500-0599/0544.Output Contest Matches/Solution.py index ddfcf132d8fa..6772b8dbbfcb 100644 --- a/solution/0500-0599/0544.Output Contest Matches/Solution.py +++ b/solution/0500-0599/0544.Output Contest Matches/Solution.py @@ -1,8 +1,8 @@ class Solution: def findContestMatch(self, n: int) -> str: - team = [str(i + 1) for i in range(n)] + s = [str(i + 1) for i in range(n)] while n > 1: for i in range(n >> 1): - team[i] = f'({team[i]},{team[n - 1 - i]})' + s[i] = f"({s[i]},{s[n - i - 1]})" n >>= 1 - return team[0] + return s[0] diff --git a/solution/0500-0599/0544.Output Contest Matches/Solution.ts b/solution/0500-0599/0544.Output Contest Matches/Solution.ts new file mode 100644 index 000000000000..9bd39d9682b5 --- /dev/null +++ b/solution/0500-0599/0544.Output Contest Matches/Solution.ts @@ -0,0 +1,9 @@ +function findContestMatch(n: number): string { + const s: string[] = Array.from({ length: n }, (_, i) => (i + 1).toString()); + for (; n > 1; n >>= 1) { + for (let i = 0; i < n >> 1; ++i) { + s[i] = `(${s[i]},${s[n - i - 1]})`; + } + } + return s[0]; +} diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/README.md b/solution/0500-0599/0545.Boundary of Binary Tree/README.md index 2abe265cb2a5..57937625d0e1 100644 --- a/solution/0500-0599/0545.Boundary of Binary Tree/README.md +++ b/solution/0500-0599/0545.Boundary of Binary Tree/README.md @@ -74,7 +74,24 @@ tags: -### 方法一 +### 方法一:DFS + +首先,如果树只有一个节点,那么直接返回这个节点的值的列表。 + +否则,我们可以通过深度优先搜索,找到二叉树的左边界、叶节点和右边界。 + +具体地,我们可以通过一个递归函数 $\textit{dfs}$ 来找到这三个部分。在 $\textit{dfs}$ 函数中,我们需要传入一个列表 $\textit{nums}$,一个节点 $\textit{root}$ 和一个整数 $\textit{i}$,其中 $\textit{nums}$ 用来存储当前部分的节点值,而 $\textit{root}$ 和 $\textit{i}$ 分别表示当前节点和当前部分的类型(左边界, 叶节点或右边界)。 + +函数的具体实现如下: + +- 如果 $\textit{root}$ 为空,那么直接返回。 +- 如果 $\textit{i} = 0$,那么我们需要找到左边界。如果 $\textit{root}$ 不是叶节点,那么我们将 $\textit{root}$ 的值加入到 $\textit{nums}$ 中。如果 $\textit{root}$ 有左子节点,那么我们递归地调用 $\textit{dfs}$ 函数,传入 $\textit{nums}$, $\textit{root}$ 的左子节点和 $\textit{i}$。否则,我们递归地调用 $\textit{dfs}$ 函数,传入 $\textit{nums}$, $\textit{root}$ 的右子节点和 $\textit{i}$。 +- 如果 $\textit{i} = 1$,那么我们需要找到叶节点。如果 $\textit{root}$ 是叶节点,那么我们将 $\textit{root}$ 的值加入到 $\textit{nums}$ 中。否则,我们递归地调用 $\textit{dfs}$ 函数,传入 $\textit{nums}$, $\textit{root}$ 的左子节点和 $\textit{i}$,以及 $\textit{nums}$, $\textit{root}$ 的右子节点和 $\textit{i}$。 +- 如果 $\textit{i} = 2$,那么我们需要找到右边界。如果 $\textit{root}$ 不是叶节点,那么我们将 $\textit{root}$ 的值加入到 $\textit{nums}$ 中,如果 $\textit{root}$ 有右子节点,那么我们递归地调用 $\textit{dfs}$ 函数,传入 $\textit{nums}$, $\textit{root}$ 的右子节点和 $\textit{i}$。否则,我们递归地调用 $\textit{dfs}$ 函数,传入 $\textit{nums}$, $\textit{root}$ 的左子节点和 $\textit{i}$。 + +我们分别调用 $\textit{dfs}$ 函数,找到左边界、叶节点和右边界,然后将这三个部分连接起来,即可得到答案。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。 @@ -88,127 +105,294 @@ tags: # self.left = left # self.right = right class Solution: - def boundaryOfBinaryTree(self, root: TreeNode) -> List[int]: - self.res = [] - if not root: - return self.res - # root - if not self.is_leaf(root): - self.res.append(root.val) - - # left boundary - t = root.left - while t: - if not self.is_leaf(t): - self.res.append(t.val) - t = t.left if t.left else t.right - - # leaves - self.add_leaves(root) - - # right boundary(reverse order) - s = [] - t = root.right - while t: - if not self.is_leaf(t): - s.append(t.val) - t = t.right if t.right else t.left - while s: - self.res.append(s.pop()) - - # output - return self.res - - def add_leaves(self, root): - if self.is_leaf(root): - self.res.append(root.val) - return - if root.left: - self.add_leaves(root.left) - if root.right: - self.add_leaves(root.right) - - def is_leaf(self, node) -> bool: - return node and node.left is None and node.right is None + def boundaryOfBinaryTree(self, root: Optional[TreeNode]) -> List[int]: + def dfs(nums: List[int], root: Optional[TreeNode], i: int): + if root is None: + return + if i == 0: + if root.left != root.right: + nums.append(root.val) + if root.left: + dfs(nums, root.left, i) + else: + dfs(nums, root.right, i) + elif i == 1: + if root.left == root.right: + nums.append(root.val) + else: + dfs(nums, root.left, i) + dfs(nums, root.right, i) + else: + if root.left != root.right: + nums.append(root.val) + if root.right: + dfs(nums, root.right, i) + else: + dfs(nums, root.left, i) + + ans = [root.val] + if root.left == root.right: + return ans + left, leaves, right = [], [], [] + dfs(left, root.left, 0) + dfs(leaves, root, 1) + dfs(right, root.right, 2) + ans += left + leaves + right[::-1] + return ans ``` #### Java ```java -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ class Solution { - private List res; - public List boundaryOfBinaryTree(TreeNode root) { - if (root == null) { - return Collections.emptyList(); + List ans = new ArrayList<>(); + ans.add(root.val); + if (root.left == root.right) { + return ans; } - res = new ArrayList<>(); + List left = new ArrayList<>(); + List leaves = new ArrayList<>(); + List right = new ArrayList<>(); + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + + ans.addAll(left); + ans.addAll(leaves); + Collections.reverse(right); + ans.addAll(right); + return ans; + } - // root - if (!isLeaf(root)) { - res.add(root.val); + private void dfs(List nums, TreeNode root, int i) { + if (root == null) { + return; } - - // left boundary - TreeNode t = root.left; - while (t != null) { - if (!isLeaf(t)) { - res.add(t.val); + if (i == 0) { + if (root.left != root.right) { + nums.add(root.val); + if (root.left != null) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i == 1) { + if (root.left == root.right) { + nums.add(root.val); + } else { + dfs(nums, root.left, i); + dfs(nums, root.right, i); + } + } else { + if (root.left != root.right) { + nums.add(root.val); + if (root.right != null) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } } - t = t.left == null ? t.right : t.left; } + } +} +``` - // leaves - addLeaves(root); +#### C++ - // right boundary(reverse order) - Deque s = new ArrayDeque<>(); - t = root.right; - while (t != null) { - if (!isLeaf(t)) { - s.offer(t.val); +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector boundaryOfBinaryTree(TreeNode* root) { + auto dfs = [&](auto&& dfs, vector& nums, TreeNode* root, int i) -> void { + if (!root) { + return; } - t = t.right == null ? t.left : t.right; - } - while (!s.isEmpty()) { - res.add(s.pollLast()); + if (i == 0) { + if (root->left != root->right) { + nums.push_back(root->val); + if (root->left) { + dfs(dfs, nums, root->left, i); + } else { + dfs(dfs, nums, root->right, i); + } + } + } else if (i == 1) { + if (root->left == root->right) { + nums.push_back(root->val); + } else { + dfs(dfs, nums, root->left, i); + dfs(dfs, nums, root->right, i); + } + } else { + if (root->left != root->right) { + nums.push_back(root->val); + if (root->right) { + dfs(dfs, nums, root->right, i); + } else { + dfs(dfs, nums, root->left, i); + } + } + } + }; + vector ans = {root->val}; + if (root->left == root->right) { + return ans; } + vector left, right, leaves; + dfs(dfs, left, root->left, 0); + dfs(dfs, leaves, root, 1); + dfs(dfs, right, root->right, 2); + ans.insert(ans.end(), left.begin(), left.end()); + ans.insert(ans.end(), leaves.begin(), leaves.end()); + ans.insert(ans.end(), right.rbegin(), right.rend()); + return ans; + } +}; +``` - // output - return res; +#### Go + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func boundaryOfBinaryTree(root *TreeNode) []int { + ans := []int{root.Val} + if root.Left == root.Right { + return ans + } + + left, leaves, right := []int{}, []int{}, []int{} + + var dfs func(nums *[]int, root *TreeNode, i int) + dfs = func(nums *[]int, root *TreeNode, i int) { + if root == nil { + return + } + if i == 0 { + if root.Left != root.Right { + *nums = append(*nums, root.Val) + if root.Left != nil { + dfs(nums, root.Left, i) + } else { + dfs(nums, root.Right, i) + } + } + } else if i == 1 { + if root.Left == root.Right { + *nums = append(*nums, root.Val) + } else { + dfs(nums, root.Left, i) + dfs(nums, root.Right, i) + } + } else { + if root.Left != root.Right { + *nums = append(*nums, root.Val) + if root.Right != nil { + dfs(nums, root.Right, i) + } else { + dfs(nums, root.Left, i) + } + } + } + } + + dfs(&left, root.Left, 0) + dfs(&leaves, root, 1) + dfs(&right, root.Right, 2) + + ans = append(ans, left...) + ans = append(ans, leaves...) + for i := len(right) - 1; i >= 0; i-- { + ans = append(ans, right[i]) + } + + return ans +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function boundaryOfBinaryTree(root: TreeNode | null): number[] { + const ans: number[] = [root.val]; + if (root.left === root.right) { + return ans; } - private void addLeaves(TreeNode root) { - if (isLeaf(root)) { - res.add(root.val); + const left: number[] = []; + const leaves: number[] = []; + const right: number[] = []; + + const dfs = function (nums: number[], root: TreeNode | null, i: number) { + if (!root) { return; } - if (root.left != null) { - addLeaves(root.left); - } - if (root.right != null) { - addLeaves(root.right); + if (i === 0) { + if (root.left !== root.right) { + nums.push(root.val); + if (root.left) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i === 1) { + if (root.left === root.right) { + nums.push(root.val); + } else { + dfs(nums, root.left, i); + dfs(nums, root.right, i); + } + } else { + if (root.left !== root.right) { + nums.push(root.val); + if (root.right) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } + } } - } + }; - private boolean isLeaf(TreeNode node) { - return node != null && node.left == null && node.right == null; - } + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + + return ans.concat(left).concat(leaves).concat(right.reverse()); } ``` @@ -228,56 +412,51 @@ class Solution { * @return {number[]} */ var boundaryOfBinaryTree = function (root) { - let leftBoundary = function (root, res) { - while (root) { - let curVal = root.val; - if (root.left) { - root = root.left; - } else if (root.right) { - root = root.right; - } else { - break; - } - res.push(curVal); + const ans = [root.val]; + if (root.left === root.right) { + return ans; + } + + const left = []; + const leaves = []; + const right = []; + + const dfs = function (nums, root, i) { + if (!root) { + return; } - }; - let rightBoundary = function (root, res) { - let stk = []; - while (root) { - let curVal = root.val; - if (root.right) { - root = root.right; - } else if (root.left) { - root = root.left; + if (i === 0) { + if (root.left !== root.right) { + nums.push(root.val); + if (root.left) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i === 1) { + if (root.left === root.right) { + nums.push(root.val); } else { - break; + dfs(nums, root.left, i); + dfs(nums, root.right, i); } - stk.push(curVal); - } - let len = stk.length; - for (let i = 0; i < len; i++) { - res.push(stk.pop()); - } - }; - let levelBoundary = function (root, res) { - if (root) { - levelBoundary(root.left, res); - if (!root.left && !root.right) { - res.push(root.val); + } else { + if (root.left !== root.right) { + nums.push(root.val); + if (root.right) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } } - levelBoundary(root.right, res); } }; - let res = []; - if (root) { - res.push(root.val); - leftBoundary(root.left, res); - if (root.left || root.right) { - levelBoundary(root, res); - } - rightBoundary(root.right, res); - } - return res; + + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + return ans.concat(left).concat(leaves).concat(right.reverse()); }; ``` diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/README_EN.md b/solution/0500-0599/0545.Boundary of Binary Tree/README_EN.md index efad223d37c2..1dc56084d68d 100644 --- a/solution/0500-0599/0545.Boundary of Binary Tree/README_EN.md +++ b/solution/0500-0599/0545.Boundary of Binary Tree/README_EN.md @@ -77,7 +77,24 @@ Concatenating everything results in [1] + [2] + [4,7,8,9,10] + [6,3] = [1,2,4,7, -### Solution 1 +### Solution 1: DFS + +First, if the tree has only one node, we directly return a list with the value of that node. + +Otherwise, we can use depth-first search (DFS) to find the left boundary, leaf nodes, and right boundary of the binary tree. + +Specifically, we can use a recursive function $\textit{dfs}$ to find these three parts. In the $\textit{dfs}$ function, we need to pass in a list $\textit{nums}$, a node $\textit{root}$, and an integer $\textit{i}$, where $\textit{nums}$ is used to store the current part's node values, and $\textit{root}$ and $\textit{i}$ represent the current node and the type of the current part (left boundary, leaf nodes, or right boundary), respectively. + +The function implementation is as follows: + +- If $\textit{root}$ is null, then directly return. +- If $\textit{i} = 0$, we need to find the left boundary. If $\textit{root}$ is not a leaf node, we add the value of $\textit{root}$ to $\textit{nums}$. If $\textit{root}$ has a left child, we recursively call the $\textit{dfs}$ function, passing in $\textit{nums}$, the left child of $\textit{root}$, and $\textit{i}$. Otherwise, we recursively call the $\textit{dfs}$ function, passing in $\textit{nums}$, the right child of $\textit{root}$, and $\textit{i}$. +- If $\textit{i} = 1$, we need to find the leaf nodes. If $\textit{root}$ is a leaf node, we add the value of $\textit{root}$ to $\textit{nums}$. Otherwise, we recursively call the $\textit{dfs}$ function, passing in $\textit{nums}$, the left child of $\textit{root}$ and $\textit{i}$, as well as $\textit{nums}$, the right child of $\textit{root}$ and $\textit{i}$. +- If $\textit{i} = 2$, we need to find the right boundary. If $\textit{root}$ is not a leaf node, we add the value of $\textit{root}$ to $\textit{nums}$. If $\textit{root}$ has a right child, we recursively call the $\textit{dfs}$ function, passing in $\textit{nums}$, the right child of $\textit{root}$, and $\textit{i}$. Otherwise, we recursively call the $\textit{dfs}$ function, passing in $\textit{nums}$, the left child of $\textit{root}$, and $\textit{i}$. + +We call the $\textit{dfs}$ function separately to find the left boundary, leaf nodes, and right boundary, and then concatenate these three parts to get the answer. + +The time complexity is $O(n)$ and the space complexity is $O(n)$, where $n$ is the number of nodes in the binary tree. @@ -91,127 +108,294 @@ Concatenating everything results in [1] + [2] + [4,7,8,9,10] + [6,3] = [1,2,4,7, # self.left = left # self.right = right class Solution: - def boundaryOfBinaryTree(self, root: TreeNode) -> List[int]: - self.res = [] - if not root: - return self.res - # root - if not self.is_leaf(root): - self.res.append(root.val) - - # left boundary - t = root.left - while t: - if not self.is_leaf(t): - self.res.append(t.val) - t = t.left if t.left else t.right - - # leaves - self.add_leaves(root) - - # right boundary(reverse order) - s = [] - t = root.right - while t: - if not self.is_leaf(t): - s.append(t.val) - t = t.right if t.right else t.left - while s: - self.res.append(s.pop()) - - # output - return self.res - - def add_leaves(self, root): - if self.is_leaf(root): - self.res.append(root.val) - return - if root.left: - self.add_leaves(root.left) - if root.right: - self.add_leaves(root.right) - - def is_leaf(self, node) -> bool: - return node and node.left is None and node.right is None + def boundaryOfBinaryTree(self, root: Optional[TreeNode]) -> List[int]: + def dfs(nums: List[int], root: Optional[TreeNode], i: int): + if root is None: + return + if i == 0: + if root.left != root.right: + nums.append(root.val) + if root.left: + dfs(nums, root.left, i) + else: + dfs(nums, root.right, i) + elif i == 1: + if root.left == root.right: + nums.append(root.val) + else: + dfs(nums, root.left, i) + dfs(nums, root.right, i) + else: + if root.left != root.right: + nums.append(root.val) + if root.right: + dfs(nums, root.right, i) + else: + dfs(nums, root.left, i) + + ans = [root.val] + if root.left == root.right: + return ans + left, leaves, right = [], [], [] + dfs(left, root.left, 0) + dfs(leaves, root, 1) + dfs(right, root.right, 2) + ans += left + leaves + right[::-1] + return ans ``` #### Java ```java -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ class Solution { - private List res; - public List boundaryOfBinaryTree(TreeNode root) { - if (root == null) { - return Collections.emptyList(); + List ans = new ArrayList<>(); + ans.add(root.val); + if (root.left == root.right) { + return ans; } - res = new ArrayList<>(); + List left = new ArrayList<>(); + List leaves = new ArrayList<>(); + List right = new ArrayList<>(); + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + + ans.addAll(left); + ans.addAll(leaves); + Collections.reverse(right); + ans.addAll(right); + return ans; + } - // root - if (!isLeaf(root)) { - res.add(root.val); + private void dfs(List nums, TreeNode root, int i) { + if (root == null) { + return; } - - // left boundary - TreeNode t = root.left; - while (t != null) { - if (!isLeaf(t)) { - res.add(t.val); + if (i == 0) { + if (root.left != root.right) { + nums.add(root.val); + if (root.left != null) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i == 1) { + if (root.left == root.right) { + nums.add(root.val); + } else { + dfs(nums, root.left, i); + dfs(nums, root.right, i); + } + } else { + if (root.left != root.right) { + nums.add(root.val); + if (root.right != null) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } } - t = t.left == null ? t.right : t.left; } + } +} +``` - // leaves - addLeaves(root); +#### C++ - // right boundary(reverse order) - Deque s = new ArrayDeque<>(); - t = root.right; - while (t != null) { - if (!isLeaf(t)) { - s.offer(t.val); +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector boundaryOfBinaryTree(TreeNode* root) { + auto dfs = [&](auto&& dfs, vector& nums, TreeNode* root, int i) -> void { + if (!root) { + return; } - t = t.right == null ? t.left : t.right; - } - while (!s.isEmpty()) { - res.add(s.pollLast()); + if (i == 0) { + if (root->left != root->right) { + nums.push_back(root->val); + if (root->left) { + dfs(dfs, nums, root->left, i); + } else { + dfs(dfs, nums, root->right, i); + } + } + } else if (i == 1) { + if (root->left == root->right) { + nums.push_back(root->val); + } else { + dfs(dfs, nums, root->left, i); + dfs(dfs, nums, root->right, i); + } + } else { + if (root->left != root->right) { + nums.push_back(root->val); + if (root->right) { + dfs(dfs, nums, root->right, i); + } else { + dfs(dfs, nums, root->left, i); + } + } + } + }; + vector ans = {root->val}; + if (root->left == root->right) { + return ans; } + vector left, right, leaves; + dfs(dfs, left, root->left, 0); + dfs(dfs, leaves, root, 1); + dfs(dfs, right, root->right, 2); + ans.insert(ans.end(), left.begin(), left.end()); + ans.insert(ans.end(), leaves.begin(), leaves.end()); + ans.insert(ans.end(), right.rbegin(), right.rend()); + return ans; + } +}; +``` - // output - return res; +#### Go + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func boundaryOfBinaryTree(root *TreeNode) []int { + ans := []int{root.Val} + if root.Left == root.Right { + return ans + } + + left, leaves, right := []int{}, []int{}, []int{} + + var dfs func(nums *[]int, root *TreeNode, i int) + dfs = func(nums *[]int, root *TreeNode, i int) { + if root == nil { + return + } + if i == 0 { + if root.Left != root.Right { + *nums = append(*nums, root.Val) + if root.Left != nil { + dfs(nums, root.Left, i) + } else { + dfs(nums, root.Right, i) + } + } + } else if i == 1 { + if root.Left == root.Right { + *nums = append(*nums, root.Val) + } else { + dfs(nums, root.Left, i) + dfs(nums, root.Right, i) + } + } else { + if root.Left != root.Right { + *nums = append(*nums, root.Val) + if root.Right != nil { + dfs(nums, root.Right, i) + } else { + dfs(nums, root.Left, i) + } + } + } + } + + dfs(&left, root.Left, 0) + dfs(&leaves, root, 1) + dfs(&right, root.Right, 2) + + ans = append(ans, left...) + ans = append(ans, leaves...) + for i := len(right) - 1; i >= 0; i-- { + ans = append(ans, right[i]) + } + + return ans +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function boundaryOfBinaryTree(root: TreeNode | null): number[] { + const ans: number[] = [root.val]; + if (root.left === root.right) { + return ans; } - private void addLeaves(TreeNode root) { - if (isLeaf(root)) { - res.add(root.val); + const left: number[] = []; + const leaves: number[] = []; + const right: number[] = []; + + const dfs = function (nums: number[], root: TreeNode | null, i: number) { + if (!root) { return; } - if (root.left != null) { - addLeaves(root.left); - } - if (root.right != null) { - addLeaves(root.right); + if (i === 0) { + if (root.left !== root.right) { + nums.push(root.val); + if (root.left) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i === 1) { + if (root.left === root.right) { + nums.push(root.val); + } else { + dfs(nums, root.left, i); + dfs(nums, root.right, i); + } + } else { + if (root.left !== root.right) { + nums.push(root.val); + if (root.right) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } + } } - } + }; - private boolean isLeaf(TreeNode node) { - return node != null && node.left == null && node.right == null; - } + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + + return ans.concat(left).concat(leaves).concat(right.reverse()); } ``` @@ -231,56 +415,51 @@ class Solution { * @return {number[]} */ var boundaryOfBinaryTree = function (root) { - let leftBoundary = function (root, res) { - while (root) { - let curVal = root.val; - if (root.left) { - root = root.left; - } else if (root.right) { - root = root.right; - } else { - break; - } - res.push(curVal); + const ans = [root.val]; + if (root.left === root.right) { + return ans; + } + + const left = []; + const leaves = []; + const right = []; + + const dfs = function (nums, root, i) { + if (!root) { + return; } - }; - let rightBoundary = function (root, res) { - let stk = []; - while (root) { - let curVal = root.val; - if (root.right) { - root = root.right; - } else if (root.left) { - root = root.left; + if (i === 0) { + if (root.left !== root.right) { + nums.push(root.val); + if (root.left) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i === 1) { + if (root.left === root.right) { + nums.push(root.val); } else { - break; + dfs(nums, root.left, i); + dfs(nums, root.right, i); } - stk.push(curVal); - } - let len = stk.length; - for (let i = 0; i < len; i++) { - res.push(stk.pop()); - } - }; - let levelBoundary = function (root, res) { - if (root) { - levelBoundary(root.left, res); - if (!root.left && !root.right) { - res.push(root.val); + } else { + if (root.left !== root.right) { + nums.push(root.val); + if (root.right) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } } - levelBoundary(root.right, res); } }; - let res = []; - if (root) { - res.push(root.val); - leftBoundary(root.left, res); - if (root.left || root.right) { - levelBoundary(root, res); - } - rightBoundary(root.right, res); - } - return res; + + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + return ans.concat(left).concat(leaves).concat(right.reverse()); }; ``` diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.cpp b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.cpp new file mode 100644 index 000000000000..3248893353a4 --- /dev/null +++ b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.cpp @@ -0,0 +1,59 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector boundaryOfBinaryTree(TreeNode* root) { + auto dfs = [&](auto&& dfs, vector& nums, TreeNode* root, int i) -> void { + if (!root) { + return; + } + if (i == 0) { + if (root->left != root->right) { + nums.push_back(root->val); + if (root->left) { + dfs(dfs, nums, root->left, i); + } else { + dfs(dfs, nums, root->right, i); + } + } + } else if (i == 1) { + if (root->left == root->right) { + nums.push_back(root->val); + } else { + dfs(dfs, nums, root->left, i); + dfs(dfs, nums, root->right, i); + } + } else { + if (root->left != root->right) { + nums.push_back(root->val); + if (root->right) { + dfs(dfs, nums, root->right, i); + } else { + dfs(dfs, nums, root->left, i); + } + } + } + }; + vector ans = {root->val}; + if (root->left == root->right) { + return ans; + } + vector left, right, leaves; + dfs(dfs, left, root->left, 0); + dfs(dfs, leaves, root, 1); + dfs(dfs, right, root->right, 2); + ans.insert(ans.end(), left.begin(), left.end()); + ans.insert(ans.end(), leaves.begin(), leaves.end()); + ans.insert(ans.end(), right.rbegin(), right.rend()); + return ans; + } +}; \ No newline at end of file diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.go b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.go new file mode 100644 index 000000000000..bb0efd2e76e8 --- /dev/null +++ b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.go @@ -0,0 +1,61 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func boundaryOfBinaryTree(root *TreeNode) []int { + ans := []int{root.Val} + if root.Left == root.Right { + return ans + } + + left, leaves, right := []int{}, []int{}, []int{} + + var dfs func(nums *[]int, root *TreeNode, i int) + dfs = func(nums *[]int, root *TreeNode, i int) { + if root == nil { + return + } + if i == 0 { + if root.Left != root.Right { + *nums = append(*nums, root.Val) + if root.Left != nil { + dfs(nums, root.Left, i) + } else { + dfs(nums, root.Right, i) + } + } + } else if i == 1 { + if root.Left == root.Right { + *nums = append(*nums, root.Val) + } else { + dfs(nums, root.Left, i) + dfs(nums, root.Right, i) + } + } else { + if root.Left != root.Right { + *nums = append(*nums, root.Val) + if root.Right != nil { + dfs(nums, root.Right, i) + } else { + dfs(nums, root.Left, i) + } + } + } + } + + dfs(&left, root.Left, 0) + dfs(&leaves, root, 1) + dfs(&right, root.Right, 2) + + ans = append(ans, left...) + ans = append(ans, leaves...) + for i := len(right) - 1; i >= 0; i-- { + ans = append(ans, right[i]) + } + + return ans +} \ No newline at end of file diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.java b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.java index 94c645ec0ab9..6d25d304c2a0 100644 --- a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.java +++ b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.java @@ -1,75 +1,53 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ class Solution { - private List res; - public List boundaryOfBinaryTree(TreeNode root) { - if (root == null) { - return Collections.emptyList(); - } - res = new ArrayList<>(); - - // root - if (!isLeaf(root)) { - res.add(root.val); - } - - // left boundary - TreeNode t = root.left; - while (t != null) { - if (!isLeaf(t)) { - res.add(t.val); - } - t = t.left == null ? t.right : t.left; - } - - // leaves - addLeaves(root); - - // right boundary(reverse order) - Deque s = new ArrayDeque<>(); - t = root.right; - while (t != null) { - if (!isLeaf(t)) { - s.offer(t.val); - } - t = t.right == null ? t.left : t.right; - } - while (!s.isEmpty()) { - res.add(s.pollLast()); - } - - // output - return res; + List ans = new ArrayList<>(); + ans.add(root.val); + if (root.left == root.right) { + return ans; + } + List left = new ArrayList<>(); + List leaves = new ArrayList<>(); + List right = new ArrayList<>(); + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + + ans.addAll(left); + ans.addAll(leaves); + Collections.reverse(right); + ans.addAll(right); + return ans; } - private void addLeaves(TreeNode root) { - if (isLeaf(root)) { - res.add(root.val); + private void dfs(List nums, TreeNode root, int i) { + if (root == null) { return; } - if (root.left != null) { - addLeaves(root.left); - } - if (root.right != null) { - addLeaves(root.right); + if (i == 0) { + if (root.left != root.right) { + nums.add(root.val); + if (root.left != null) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i == 1) { + if (root.left == root.right) { + nums.add(root.val); + } else { + dfs(nums, root.left, i); + dfs(nums, root.right, i); + } + } else { + if (root.left != root.right) { + nums.add(root.val); + if (root.right != null) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } + } } } - - private boolean isLeaf(TreeNode node) { - return node != null && node.left == null && node.right == null; - } } \ No newline at end of file diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.js b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.js index 932543256a70..26357ba055c0 100644 --- a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.js +++ b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.js @@ -11,54 +11,49 @@ * @return {number[]} */ var boundaryOfBinaryTree = function (root) { - let leftBoundary = function (root, res) { - while (root) { - let curVal = root.val; - if (root.left) { - root = root.left; - } else if (root.right) { - root = root.right; - } else { - break; - } - res.push(curVal); + const ans = [root.val]; + if (root.left === root.right) { + return ans; + } + + const left = []; + const leaves = []; + const right = []; + + const dfs = function (nums, root, i) { + if (!root) { + return; } - }; - let rightBoundary = function (root, res) { - let stk = []; - while (root) { - let curVal = root.val; - if (root.right) { - root = root.right; - } else if (root.left) { - root = root.left; + if (i === 0) { + if (root.left !== root.right) { + nums.push(root.val); + if (root.left) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i === 1) { + if (root.left === root.right) { + nums.push(root.val); } else { - break; + dfs(nums, root.left, i); + dfs(nums, root.right, i); } - stk.push(curVal); - } - let len = stk.length; - for (let i = 0; i < len; i++) { - res.push(stk.pop()); - } - }; - let levelBoundary = function (root, res) { - if (root) { - levelBoundary(root.left, res); - if (!root.left && !root.right) { - res.push(root.val); + } else { + if (root.left !== root.right) { + nums.push(root.val); + if (root.right) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } } - levelBoundary(root.right, res); } }; - let res = []; - if (root) { - res.push(root.val); - leftBoundary(root.left, res); - if (root.left || root.right) { - levelBoundary(root, res); - } - rightBoundary(root.right, res); - } - return res; + + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + return ans.concat(left).concat(leaves).concat(right.reverse()); }; diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.py b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.py index a003313013b0..2946bc6e888f 100644 --- a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.py +++ b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.py @@ -5,45 +5,37 @@ # self.left = left # self.right = right class Solution: - def boundaryOfBinaryTree(self, root: TreeNode) -> List[int]: - self.res = [] - if not root: - return self.res - # root - if not self.is_leaf(root): - self.res.append(root.val) + def boundaryOfBinaryTree(self, root: Optional[TreeNode]) -> List[int]: + def dfs(nums: List[int], root: Optional[TreeNode], i: int): + if root is None: + return + if i == 0: + if root.left != root.right: + nums.append(root.val) + if root.left: + dfs(nums, root.left, i) + else: + dfs(nums, root.right, i) + elif i == 1: + if root.left == root.right: + nums.append(root.val) + else: + dfs(nums, root.left, i) + dfs(nums, root.right, i) + else: + if root.left != root.right: + nums.append(root.val) + if root.right: + dfs(nums, root.right, i) + else: + dfs(nums, root.left, i) - # left boundary - t = root.left - while t: - if not self.is_leaf(t): - self.res.append(t.val) - t = t.left if t.left else t.right - - # leaves - self.add_leaves(root) - - # right boundary(reverse order) - s = [] - t = root.right - while t: - if not self.is_leaf(t): - s.append(t.val) - t = t.right if t.right else t.left - while s: - self.res.append(s.pop()) - - # output - return self.res - - def add_leaves(self, root): - if self.is_leaf(root): - self.res.append(root.val) - return - if root.left: - self.add_leaves(root.left) - if root.right: - self.add_leaves(root.right) - - def is_leaf(self, node) -> bool: - return node and node.left is None and node.right is None + ans = [root.val] + if root.left == root.right: + return ans + left, leaves, right = [], [], [] + dfs(left, root.left, 0) + dfs(leaves, root, 1) + dfs(right, root.right, 2) + ans += left + leaves + right[::-1] + return ans diff --git a/solution/0500-0599/0545.Boundary of Binary Tree/Solution.ts b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.ts new file mode 100644 index 000000000000..fda1e415eff3 --- /dev/null +++ b/solution/0500-0599/0545.Boundary of Binary Tree/Solution.ts @@ -0,0 +1,62 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function boundaryOfBinaryTree(root: TreeNode | null): number[] { + const ans: number[] = [root.val]; + if (root.left === root.right) { + return ans; + } + + const left: number[] = []; + const leaves: number[] = []; + const right: number[] = []; + + const dfs = function (nums: number[], root: TreeNode | null, i: number) { + if (!root) { + return; + } + if (i === 0) { + if (root.left !== root.right) { + nums.push(root.val); + if (root.left) { + dfs(nums, root.left, i); + } else { + dfs(nums, root.right, i); + } + } + } else if (i === 1) { + if (root.left === root.right) { + nums.push(root.val); + } else { + dfs(nums, root.left, i); + dfs(nums, root.right, i); + } + } else { + if (root.left !== root.right) { + nums.push(root.val); + if (root.right) { + dfs(nums, root.right, i); + } else { + dfs(nums, root.left, i); + } + } + } + }; + + dfs(left, root.left, 0); + dfs(leaves, root, 1); + dfs(right, root.right, 2); + + return ans.concat(left).concat(leaves).concat(right.reverse()); +} diff --git a/solution/0500-0599/0552.Student Attendance Record II/README.md b/solution/0500-0599/0552.Student Attendance Record II/README.md index d6de11d58552..d62167724f4a 100644 --- a/solution/0500-0599/0552.Student Attendance Record II/README.md +++ b/solution/0500-0599/0552.Student Attendance Record II/README.md @@ -152,36 +152,30 @@ class Solution { #### C++ ```cpp -int f[100010][2][3]; -const int mod = 1e9 + 7; - class Solution { public: int checkRecord(int n) { - this->n = n; + int f[n][2][3]; memset(f, -1, sizeof(f)); - return dfs(0, 0, 0); - } - - int dfs(int i, int j, int k) { - if (i >= n) { - return 1; - } - if (f[i][j][k] != -1) { - return f[i][j][k]; - } - int ans = dfs(i + 1, j, 0); - if (j == 0) { - ans = (ans + dfs(i + 1, j + 1, 0)) % mod; - } - if (k < 2) { - ans = (ans + dfs(i + 1, j, k + 1)) % mod; - } - return f[i][j][k] = ans; + const int mod = 1e9 + 7; + auto dfs = [&](auto&& dfs, int i, int j, int k) -> int { + if (i >= n) { + return 1; + } + if (f[i][j][k] != -1) { + return f[i][j][k]; + } + int ans = dfs(dfs, i + 1, j, 0); + if (j == 0) { + ans = (ans + dfs(dfs, i + 1, j + 1, 0)) % mod; + } + if (k < 2) { + ans = (ans + dfs(dfs, i + 1, j, k + 1)) % mod; + } + return f[i][j][k] = ans; + }; + return dfs(dfs, 0, 0, 0); } - -private: - int n; }; ``` diff --git a/solution/0500-0599/0552.Student Attendance Record II/README_EN.md b/solution/0500-0599/0552.Student Attendance Record II/README_EN.md index ea40097f1e71..d7e0d74bd576 100644 --- a/solution/0500-0599/0552.Student Attendance Record II/README_EN.md +++ b/solution/0500-0599/0552.Student Attendance Record II/README_EN.md @@ -134,36 +134,30 @@ class Solution { #### C++ ```cpp -int f[100010][2][3]; -const int mod = 1e9 + 7; - class Solution { public: int checkRecord(int n) { - this->n = n; + int f[n][2][3]; memset(f, -1, sizeof(f)); - return dfs(0, 0, 0); - } - - int dfs(int i, int j, int k) { - if (i >= n) { - return 1; - } - if (f[i][j][k] != -1) { - return f[i][j][k]; - } - int ans = dfs(i + 1, j, 0); - if (j == 0) { - ans = (ans + dfs(i + 1, j + 1, 0)) % mod; - } - if (k < 2) { - ans = (ans + dfs(i + 1, j, k + 1)) % mod; - } - return f[i][j][k] = ans; + const int mod = 1e9 + 7; + auto dfs = [&](auto&& dfs, int i, int j, int k) -> int { + if (i >= n) { + return 1; + } + if (f[i][j][k] != -1) { + return f[i][j][k]; + } + int ans = dfs(dfs, i + 1, j, 0); + if (j == 0) { + ans = (ans + dfs(dfs, i + 1, j + 1, 0)) % mod; + } + if (k < 2) { + ans = (ans + dfs(dfs, i + 1, j, k + 1)) % mod; + } + return f[i][j][k] = ans; + }; + return dfs(dfs, 0, 0, 0); } - -private: - int n; }; ``` diff --git a/solution/0500-0599/0552.Student Attendance Record II/Solution.cpp b/solution/0500-0599/0552.Student Attendance Record II/Solution.cpp index 56dd945f6afa..24fafaa6f326 100644 --- a/solution/0500-0599/0552.Student Attendance Record II/Solution.cpp +++ b/solution/0500-0599/0552.Student Attendance Record II/Solution.cpp @@ -1,31 +1,25 @@ -int f[100010][2][3]; -const int mod = 1e9 + 7; - class Solution { public: int checkRecord(int n) { - this->n = n; + int f[n][2][3]; memset(f, -1, sizeof(f)); - return dfs(0, 0, 0); + const int mod = 1e9 + 7; + auto dfs = [&](auto&& dfs, int i, int j, int k) -> int { + if (i >= n) { + return 1; + } + if (f[i][j][k] != -1) { + return f[i][j][k]; + } + int ans = dfs(dfs, i + 1, j, 0); + if (j == 0) { + ans = (ans + dfs(dfs, i + 1, j + 1, 0)) % mod; + } + if (k < 2) { + ans = (ans + dfs(dfs, i + 1, j, k + 1)) % mod; + } + return f[i][j][k] = ans; + }; + return dfs(dfs, 0, 0, 0); } - - int dfs(int i, int j, int k) { - if (i >= n) { - return 1; - } - if (f[i][j][k] != -1) { - return f[i][j][k]; - } - int ans = dfs(i + 1, j, 0); - if (j == 0) { - ans = (ans + dfs(i + 1, j + 1, 0)) % mod; - } - if (k < 2) { - ans = (ans + dfs(i + 1, j, k + 1)) % mod; - } - return f[i][j][k] = ans; - } - -private: - int n; -}; \ No newline at end of file +}; diff --git a/solution/0500-0599/0560.Subarray Sum Equals K/README.md b/solution/0500-0599/0560.Subarray Sum Equals K/README.md index 0112346d84f6..a49ab117c3b8 100644 --- a/solution/0500-0599/0560.Subarray Sum Equals K/README.md +++ b/solution/0500-0599/0560.Subarray Sum Equals K/README.md @@ -56,13 +56,13 @@ tags: ### 方法一:哈希表 + 前缀和 -我们定义一个哈希表 $\text{cnt}$,用于存储数组 $\text{nums}$ 的前缀和出现的次数。初始时,我们将 $\text{cnt}[0]$ 的值设为 $1$,表示前缀和 $0$ 出现了一次。 +我们定义一个哈希表 $\textit{cnt}$,用于存储数组 $\textit{nums}$ 的前缀和出现的次数。初始时,我们将 $\textit{cnt}[0]$ 的值设为 $1$,表示前缀和 $0$ 出现了一次。 -我们遍历数组 $\text{nums}$,计算前缀和 $\text{s}$,然后将 $\text{cnt}[s - k]$ 的值累加到答案中,并将 $\text{cnt}[s]$ 的值增加 $1$。 +我们遍历数组 $\textit{nums}$,计算前缀和 $\textit{s}$,然后将 $\textit{cnt}[s - k]$ 的值累加到答案中,并将 $\textit{cnt}[s]$ 的值增加 $1$。 遍历结束后,我们返回答案。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 diff --git a/solution/0500-0599/0572.Subtree of Another Tree/README.md b/solution/0500-0599/0572.Subtree of Another Tree/README.md index f0924ecb6949..009bf3921b95 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/README.md +++ b/solution/0500-0599/0572.Subtree of Another Tree/README.md @@ -61,7 +61,13 @@ tags: -### 方法一 +### 方法一:DFS + +我们定义一个辅助函数 $\textit{same}(p, q)$,用于判断以 $p$ 为根节点的树和以 $q$ 为根节点的树是否相等。如果两棵树的根节点的值相等,并且它们的左子树和右子树也分别相等,那么这两棵树是相等的。 + +在 $\textit{isSubtree}(\textit{root}, \textit{subRoot})$ 函数中,我们首先判断 $\textit{root}$ 是否为空,如果为空,则返回 $\text{false}$。否则,我们判断 $\textit{root}$ 和 $\textit{subRoot}$ 是否相等,如果相等,则返回 $\text{true}$。否则,我们递归地判断 $\textit{root}$ 的左子树和右子树是否包含 $\textit{subRoot}$。 + +时间复杂度 $O(n \times m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是树 $root$ 和树 $subRoot$ 的节点个数。 @@ -75,22 +81,16 @@ tags: # self.left = left # self.right = right class Solution: - def isSubtree(self, root: TreeNode, subRoot: TreeNode) -> bool: - def dfs(root1, root2): - if root1 is None and root2 is None: - return True - if root1 is None or root2 is None: - return False - return ( - root1.val == root2.val - and dfs(root1.left, root2.left) - and dfs(root1.right, root2.right) - ) + def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + def same(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: + if p is None or q is None: + return p is q + return p.val == q.val and same(p.left, q.left) and same(p.right, q.right) if root is None: return False return ( - dfs(root, subRoot) + same(root, subRoot) or self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot) ) @@ -119,19 +119,15 @@ class Solution { if (root == null) { return false; } - return dfs(root, subRoot) || isSubtree(root.left, subRoot) + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } - private boolean dfs(TreeNode root1, TreeNode root2) { - if (root1 == null && root2 == null) { - return true; - } - if (root1 == null || root2 == null) { - return false; + private boolean same(TreeNode p, TreeNode q) { + if (p == null || q == null) { + return p == q; } - return root1.val == root2.val && dfs(root1.left, root2.left) - && dfs(root1.right, root2.right); + return p.val == q.val && same(p.left, q.left) && same(p.right, q.right); } } ``` @@ -153,14 +149,17 @@ class Solution { class Solution { public: bool isSubtree(TreeNode* root, TreeNode* subRoot) { - if (!root) return 0; - return dfs(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); + if (!root) { + return false; + } + return same(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); } - bool dfs(TreeNode* root1, TreeNode* root2) { - if (!root1 && !root2) return 1; - if (!root1 || !root2) return 0; - return root1->val == root2->val && dfs(root1->left, root2->left) && dfs(root1->right, root2->right); + bool same(TreeNode* p, TreeNode* q) { + if (!p || !q) { + return p == q; + } + return p->val == q->val && same(p->left, q->left) && same(p->right, q->right); } }; ``` @@ -177,20 +176,17 @@ public: * } */ func isSubtree(root *TreeNode, subRoot *TreeNode) bool { + var same func(p, q *TreeNode) bool + same = func(p, q *TreeNode) bool { + if p == nil || q == nil { + return p == q + } + return p.Val == q.Val && same(p.Left, q.Left) && same(p.Right, q.Right) + } if root == nil { return false } - var dfs func(root1, root2 *TreeNode) bool - dfs = func(root1, root2 *TreeNode) bool { - if root1 == nil && root2 == nil { - return true - } - if root1 == nil || root2 == nil { - return false - } - return root1.Val == root2.Val && dfs(root1.Left, root2.Left) && dfs(root1.Right, root2.Right) - } - return dfs(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) + return same(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) } ``` @@ -210,22 +206,17 @@ func isSubtree(root *TreeNode, subRoot *TreeNode) bool { * } * } */ - -const dfs = (root: TreeNode | null, subRoot: TreeNode | null) => { - if (root == null && subRoot == null) { - return true; - } - if (root == null || subRoot == null || root.val !== subRoot.val) { - return false; - } - return dfs(root.left, subRoot.left) && dfs(root.right, subRoot.right); -}; - function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean { - if (root == null) { + const same = (p: TreeNode | null, q: TreeNode | null): boolean => { + if (!p || !q) { + return p === q; + } + return p.val === q.val && same(p.left, q.left) && same(p.right, q.right); + }; + if (!root) { return false; } - return dfs(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } ``` @@ -252,38 +243,36 @@ function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean { // } use std::cell::RefCell; use std::rc::Rc; -impl Solution { - fn dfs(root: &Option>>, sub_root: &Option>>) -> bool { - if root.is_none() && sub_root.is_none() { - return true; - } - if root.is_none() || sub_root.is_none() { - return false; - } - let root = root.as_ref().unwrap().borrow(); - let sub_root = sub_root.as_ref().unwrap().borrow(); - root.val == sub_root.val - && Self::dfs(&root.left, &sub_root.left) - && Self::dfs(&root.right, &sub_root.right) - } - fn help( - root: &Option>>, - sub_root: &Option>>, +impl Solution { + pub fn is_subtree( + root: Option>>, + sub_root: Option>>, ) -> bool { if root.is_none() { return false; } - Self::dfs(root, sub_root) - || Self::help(&root.as_ref().unwrap().borrow().left, sub_root) - || Self::help(&root.as_ref().unwrap().borrow().right, sub_root) + Self::same(&root, &sub_root) + || Self::is_subtree( + root.as_ref().unwrap().borrow().left.clone(), + sub_root.clone(), + ) + || Self::is_subtree( + root.as_ref().unwrap().borrow().right.clone(), + sub_root.clone(), + ) } - pub fn is_subtree( - root: Option>>, - sub_root: Option>>, - ) -> bool { - Self::help(&root, &sub_root) + fn same(p: &Option>>, q: &Option>>) -> bool { + match (p, q) { + (None, None) => true, + (Some(p), Some(q)) => { + let p = p.borrow(); + let q = q.borrow(); + p.val == q.val && Self::same(&p.left, &q.left) && Self::same(&p.right, &q.right) + } + _ => false, + } } } ``` @@ -305,19 +294,16 @@ impl Solution { * @return {boolean} */ var isSubtree = function (root, subRoot) { - if (!root) return false; - let dfs = function (root1, root2) { - if (!root1 && !root2) { - return true; + const same = (p, q) => { + if (!p || !q) { + return p === q; } - if (!root1 || !root2) { - return false; - } - return ( - root1.val == root2.val && dfs(root1.left, root2.left) && dfs(root1.right, root2.right) - ); + return p.val === q.val && same(p.left, q.left) && same(p.right, q.right); }; - return dfs(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + if (!root) { + return false; + } + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); }; ``` diff --git a/solution/0500-0599/0572.Subtree of Another Tree/README_EN.md b/solution/0500-0599/0572.Subtree of Another Tree/README_EN.md index 68c54ff47384..68d435145dba 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/README_EN.md +++ b/solution/0500-0599/0572.Subtree of Another Tree/README_EN.md @@ -55,7 +55,13 @@ tags: -### Solution 1 +### Solution 1: DFS + +We define a helper function $\textit{same}(p, q)$ to determine whether the tree rooted at $p$ and the tree rooted at $q$ are identical. If the root values of the two trees are equal, and their left and right subtrees are also respectively equal, then the two trees are identical. + +In the $\textit{isSubtree}(\textit{root}, \textit{subRoot})$ function, we first check if $\textit{root}$ is null. If it is, we return $\text{false}$. Otherwise, we check if $\textit{root}$ and $\textit{subRoot}$ are identical. If they are, we return $\text{true}$. Otherwise, we recursively check if the left or right subtree of $\textit{root}$ contains $\textit{subRoot}$. + +The time complexity is $O(n \times m)$, and the space complexity is $O(n)$. Here, $n$ and $m$ are the number of nodes in the trees $root$ and $subRoot$, respectively. @@ -69,22 +75,16 @@ tags: # self.left = left # self.right = right class Solution: - def isSubtree(self, root: TreeNode, subRoot: TreeNode) -> bool: - def dfs(root1, root2): - if root1 is None and root2 is None: - return True - if root1 is None or root2 is None: - return False - return ( - root1.val == root2.val - and dfs(root1.left, root2.left) - and dfs(root1.right, root2.right) - ) + def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + def same(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: + if p is None or q is None: + return p is q + return p.val == q.val and same(p.left, q.left) and same(p.right, q.right) if root is None: return False return ( - dfs(root, subRoot) + same(root, subRoot) or self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot) ) @@ -113,19 +113,15 @@ class Solution { if (root == null) { return false; } - return dfs(root, subRoot) || isSubtree(root.left, subRoot) + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } - private boolean dfs(TreeNode root1, TreeNode root2) { - if (root1 == null && root2 == null) { - return true; - } - if (root1 == null || root2 == null) { - return false; + private boolean same(TreeNode p, TreeNode q) { + if (p == null || q == null) { + return p == q; } - return root1.val == root2.val && dfs(root1.left, root2.left) - && dfs(root1.right, root2.right); + return p.val == q.val && same(p.left, q.left) && same(p.right, q.right); } } ``` @@ -147,14 +143,17 @@ class Solution { class Solution { public: bool isSubtree(TreeNode* root, TreeNode* subRoot) { - if (!root) return 0; - return dfs(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); + if (!root) { + return false; + } + return same(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); } - bool dfs(TreeNode* root1, TreeNode* root2) { - if (!root1 && !root2) return 1; - if (!root1 || !root2) return 0; - return root1->val == root2->val && dfs(root1->left, root2->left) && dfs(root1->right, root2->right); + bool same(TreeNode* p, TreeNode* q) { + if (!p || !q) { + return p == q; + } + return p->val == q->val && same(p->left, q->left) && same(p->right, q->right); } }; ``` @@ -171,20 +170,17 @@ public: * } */ func isSubtree(root *TreeNode, subRoot *TreeNode) bool { + var same func(p, q *TreeNode) bool + same = func(p, q *TreeNode) bool { + if p == nil || q == nil { + return p == q + } + return p.Val == q.Val && same(p.Left, q.Left) && same(p.Right, q.Right) + } if root == nil { return false } - var dfs func(root1, root2 *TreeNode) bool - dfs = func(root1, root2 *TreeNode) bool { - if root1 == nil && root2 == nil { - return true - } - if root1 == nil || root2 == nil { - return false - } - return root1.Val == root2.Val && dfs(root1.Left, root2.Left) && dfs(root1.Right, root2.Right) - } - return dfs(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) + return same(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) } ``` @@ -204,22 +200,17 @@ func isSubtree(root *TreeNode, subRoot *TreeNode) bool { * } * } */ - -const dfs = (root: TreeNode | null, subRoot: TreeNode | null) => { - if (root == null && subRoot == null) { - return true; - } - if (root == null || subRoot == null || root.val !== subRoot.val) { - return false; - } - return dfs(root.left, subRoot.left) && dfs(root.right, subRoot.right); -}; - function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean { - if (root == null) { + const same = (p: TreeNode | null, q: TreeNode | null): boolean => { + if (!p || !q) { + return p === q; + } + return p.val === q.val && same(p.left, q.left) && same(p.right, q.right); + }; + if (!root) { return false; } - return dfs(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } ``` @@ -246,38 +237,36 @@ function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean { // } use std::cell::RefCell; use std::rc::Rc; -impl Solution { - fn dfs(root: &Option>>, sub_root: &Option>>) -> bool { - if root.is_none() && sub_root.is_none() { - return true; - } - if root.is_none() || sub_root.is_none() { - return false; - } - let root = root.as_ref().unwrap().borrow(); - let sub_root = sub_root.as_ref().unwrap().borrow(); - root.val == sub_root.val - && Self::dfs(&root.left, &sub_root.left) - && Self::dfs(&root.right, &sub_root.right) - } - fn help( - root: &Option>>, - sub_root: &Option>>, +impl Solution { + pub fn is_subtree( + root: Option>>, + sub_root: Option>>, ) -> bool { if root.is_none() { return false; } - Self::dfs(root, sub_root) - || Self::help(&root.as_ref().unwrap().borrow().left, sub_root) - || Self::help(&root.as_ref().unwrap().borrow().right, sub_root) + Self::same(&root, &sub_root) + || Self::is_subtree( + root.as_ref().unwrap().borrow().left.clone(), + sub_root.clone(), + ) + || Self::is_subtree( + root.as_ref().unwrap().borrow().right.clone(), + sub_root.clone(), + ) } - pub fn is_subtree( - root: Option>>, - sub_root: Option>>, - ) -> bool { - Self::help(&root, &sub_root) + fn same(p: &Option>>, q: &Option>>) -> bool { + match (p, q) { + (None, None) => true, + (Some(p), Some(q)) => { + let p = p.borrow(); + let q = q.borrow(); + p.val == q.val && Self::same(&p.left, &q.left) && Self::same(&p.right, &q.right) + } + _ => false, + } } } ``` @@ -299,19 +288,16 @@ impl Solution { * @return {boolean} */ var isSubtree = function (root, subRoot) { - if (!root) return false; - let dfs = function (root1, root2) { - if (!root1 && !root2) { - return true; + const same = (p, q) => { + if (!p || !q) { + return p === q; } - if (!root1 || !root2) { - return false; - } - return ( - root1.val == root2.val && dfs(root1.left, root2.left) && dfs(root1.right, root2.right) - ); + return p.val === q.val && same(p.left, q.left) && same(p.right, q.right); }; - return dfs(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + if (!root) { + return false; + } + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); }; ``` diff --git a/solution/0500-0599/0572.Subtree of Another Tree/Solution.cpp b/solution/0500-0599/0572.Subtree of Another Tree/Solution.cpp index 5df522b7d91c..7317861b1588 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/Solution.cpp +++ b/solution/0500-0599/0572.Subtree of Another Tree/Solution.cpp @@ -12,13 +12,16 @@ class Solution { public: bool isSubtree(TreeNode* root, TreeNode* subRoot) { - if (!root) return 0; - return dfs(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); + if (!root) { + return false; + } + return same(root, subRoot) || isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot); } - bool dfs(TreeNode* root1, TreeNode* root2) { - if (!root1 && !root2) return 1; - if (!root1 || !root2) return 0; - return root1->val == root2->val && dfs(root1->left, root2->left) && dfs(root1->right, root2->right); + bool same(TreeNode* p, TreeNode* q) { + if (!p || !q) { + return p == q; + } + return p->val == q->val && same(p->left, q->left) && same(p->right, q->right); } -}; \ No newline at end of file +}; diff --git a/solution/0500-0599/0572.Subtree of Another Tree/Solution.go b/solution/0500-0599/0572.Subtree of Another Tree/Solution.go index 6825247884b2..6cedbb71b480 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/Solution.go +++ b/solution/0500-0599/0572.Subtree of Another Tree/Solution.go @@ -7,18 +7,15 @@ * } */ func isSubtree(root *TreeNode, subRoot *TreeNode) bool { + var same func(p, q *TreeNode) bool + same = func(p, q *TreeNode) bool { + if p == nil || q == nil { + return p == q + } + return p.Val == q.Val && same(p.Left, q.Left) && same(p.Right, q.Right) + } if root == nil { return false } - var dfs func(root1, root2 *TreeNode) bool - dfs = func(root1, root2 *TreeNode) bool { - if root1 == nil && root2 == nil { - return true - } - if root1 == nil || root2 == nil { - return false - } - return root1.Val == root2.Val && dfs(root1.Left, root2.Left) && dfs(root1.Right, root2.Right) - } - return dfs(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) -} \ No newline at end of file + return same(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) +} diff --git a/solution/0500-0599/0572.Subtree of Another Tree/Solution.java b/solution/0500-0599/0572.Subtree of Another Tree/Solution.java index c3ae0612630b..200e90cde7de 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/Solution.java +++ b/solution/0500-0599/0572.Subtree of Another Tree/Solution.java @@ -18,18 +18,14 @@ public boolean isSubtree(TreeNode root, TreeNode subRoot) { if (root == null) { return false; } - return dfs(root, subRoot) || isSubtree(root.left, subRoot) + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } - private boolean dfs(TreeNode root1, TreeNode root2) { - if (root1 == null && root2 == null) { - return true; + private boolean same(TreeNode p, TreeNode q) { + if (p == null || q == null) { + return p == q; } - if (root1 == null || root2 == null) { - return false; - } - return root1.val == root2.val && dfs(root1.left, root2.left) - && dfs(root1.right, root2.right); + return p.val == q.val && same(p.left, q.left) && same(p.right, q.right); } -} \ No newline at end of file +} diff --git a/solution/0500-0599/0572.Subtree of Another Tree/Solution.js b/solution/0500-0599/0572.Subtree of Another Tree/Solution.js index 15f24b5a66de..06234d59078a 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/Solution.js +++ b/solution/0500-0599/0572.Subtree of Another Tree/Solution.js @@ -12,17 +12,14 @@ * @return {boolean} */ var isSubtree = function (root, subRoot) { - if (!root) return false; - let dfs = function (root1, root2) { - if (!root1 && !root2) { - return true; + const same = (p, q) => { + if (!p || !q) { + return p === q; } - if (!root1 || !root2) { - return false; - } - return ( - root1.val == root2.val && dfs(root1.left, root2.left) && dfs(root1.right, root2.right) - ); + return p.val === q.val && same(p.left, q.left) && same(p.right, q.right); }; - return dfs(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + if (!root) { + return false; + } + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); }; diff --git a/solution/0500-0599/0572.Subtree of Another Tree/Solution.py b/solution/0500-0599/0572.Subtree of Another Tree/Solution.py index 43f60a9254c4..09d4222e5037 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/Solution.py +++ b/solution/0500-0599/0572.Subtree of Another Tree/Solution.py @@ -5,22 +5,16 @@ # self.left = left # self.right = right class Solution: - def isSubtree(self, root: TreeNode, subRoot: TreeNode) -> bool: - def dfs(root1, root2): - if root1 is None and root2 is None: - return True - if root1 is None or root2 is None: - return False - return ( - root1.val == root2.val - and dfs(root1.left, root2.left) - and dfs(root1.right, root2.right) - ) + def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + def same(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: + if p is None or q is None: + return p is q + return p.val == q.val and same(p.left, q.left) and same(p.right, q.right) if root is None: return False return ( - dfs(root, subRoot) + same(root, subRoot) or self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot) ) diff --git a/solution/0500-0599/0572.Subtree of Another Tree/Solution.rs b/solution/0500-0599/0572.Subtree of Another Tree/Solution.rs index 07f98f618515..a804d8e14cdc 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/Solution.rs +++ b/solution/0500-0599/0572.Subtree of Another Tree/Solution.rs @@ -18,37 +18,35 @@ // } use std::cell::RefCell; use std::rc::Rc; -impl Solution { - fn dfs(root: &Option>>, sub_root: &Option>>) -> bool { - if root.is_none() && sub_root.is_none() { - return true; - } - if root.is_none() || sub_root.is_none() { - return false; - } - let root = root.as_ref().unwrap().borrow(); - let sub_root = sub_root.as_ref().unwrap().borrow(); - root.val == sub_root.val - && Self::dfs(&root.left, &sub_root.left) - && Self::dfs(&root.right, &sub_root.right) - } - fn help( - root: &Option>>, - sub_root: &Option>>, +impl Solution { + pub fn is_subtree( + root: Option>>, + sub_root: Option>>, ) -> bool { if root.is_none() { return false; } - Self::dfs(root, sub_root) - || Self::help(&root.as_ref().unwrap().borrow().left, sub_root) - || Self::help(&root.as_ref().unwrap().borrow().right, sub_root) + Self::same(&root, &sub_root) + || Self::is_subtree( + root.as_ref().unwrap().borrow().left.clone(), + sub_root.clone(), + ) + || Self::is_subtree( + root.as_ref().unwrap().borrow().right.clone(), + sub_root.clone(), + ) } - pub fn is_subtree( - root: Option>>, - sub_root: Option>>, - ) -> bool { - Self::help(&root, &sub_root) + fn same(p: &Option>>, q: &Option>>) -> bool { + match (p, q) { + (None, None) => true, + (Some(p), Some(q)) => { + let p = p.borrow(); + let q = q.borrow(); + p.val == q.val && Self::same(&p.left, &q.left) && Self::same(&p.right, &q.right) + } + _ => false, + } } } diff --git a/solution/0500-0599/0572.Subtree of Another Tree/Solution.ts b/solution/0500-0599/0572.Subtree of Another Tree/Solution.ts index a8dea47075bf..bf40f48479c6 100644 --- a/solution/0500-0599/0572.Subtree of Another Tree/Solution.ts +++ b/solution/0500-0599/0572.Subtree of Another Tree/Solution.ts @@ -11,20 +11,15 @@ * } * } */ - -const dfs = (root: TreeNode | null, subRoot: TreeNode | null) => { - if (root == null && subRoot == null) { - return true; - } - if (root == null || subRoot == null || root.val !== subRoot.val) { - return false; - } - return dfs(root.left, subRoot.left) && dfs(root.right, subRoot.right); -}; - function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean { - if (root == null) { + const same = (p: TreeNode | null, q: TreeNode | null): boolean => { + if (!p || !q) { + return p === q; + } + return p.val === q.val && same(p.left, q.left) && same(p.right, q.right); + }; + if (!root) { return false; } - return dfs(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + return same(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } diff --git a/solution/0500-0599/0588.Design In-Memory File System/README.md b/solution/0500-0599/0588.Design In-Memory File System/README.md index 5d26f3be1525..b543fc76a3ce 100644 --- a/solution/0500-0599/0588.Design In-Memory File System/README.md +++ b/solution/0500-0599/0588.Design In-Memory File System/README.md @@ -7,6 +7,7 @@ tags: - 字典树 - 哈希表 - 字符串 + - 排序 --- diff --git a/solution/0500-0599/0588.Design In-Memory File System/README_EN.md b/solution/0500-0599/0588.Design In-Memory File System/README_EN.md index 786d2cf8b8c4..2831cf8a0865 100644 --- a/solution/0500-0599/0588.Design In-Memory File System/README_EN.md +++ b/solution/0500-0599/0588.Design In-Memory File System/README_EN.md @@ -7,6 +7,7 @@ tags: - Trie - Hash Table - String + - Sorting --- diff --git a/solution/0500-0599/0594.Longest Harmonious Subsequence/README.md b/solution/0500-0599/0594.Longest Harmonious Subsequence/README.md index f6cc7e8ee7e0..8336433ad055 100644 --- a/solution/0500-0599/0594.Longest Harmonious Subsequence/README.md +++ b/solution/0500-0599/0594.Longest Harmonious Subsequence/README.md @@ -67,9 +67,9 @@ tags: ### 方法一:哈希表 -我们可以用一个哈希表 $\text{cnt}$ 记录数组 $\text{nums}$ 中每个元素出现的次数,然后遍历哈希表中的每个键值对 $(x, c)$,如果哈希表中存在键 $x + 1$,那么 $\text{nums}$ 中元素 $x$ 和 $x + 1$ 出现的次数之和 $c + \text{cnt}[x + 1]$ 就是一个和谐子序列,我们只需要在所有和谐子序列中找到最大的长度即可。 +我们可以用一个哈希表 $\textit{cnt}$ 记录数组 $\textit{nums}$ 中每个元素出现的次数,然后遍历哈希表中的每个键值对 $(x, c)$,如果哈希表中存在键 $x + 1$,那么 $\textit{nums}$ 中元素 $x$ 和 $x + 1$ 出现的次数之和 $c + \textit{cnt}[x + 1]$ 就是一个和谐子序列,我们只需要在所有和谐子序列中找到最大的长度即可。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 diff --git a/solution/0500-0599/0594.Longest Harmonious Subsequence/README_EN.md b/solution/0500-0599/0594.Longest Harmonious Subsequence/README_EN.md index d57222ade3e8..b257e33ab7df 100644 --- a/solution/0500-0599/0594.Longest Harmonious Subsequence/README_EN.md +++ b/solution/0500-0599/0594.Longest Harmonious Subsequence/README_EN.md @@ -80,9 +80,9 @@ tags: ### Solution 1: Hash Table -We can use a hash table $\text{cnt}$ to record the occurrence count of each element in the array $\text{nums}$. Then, we iterate through each key-value pair $(x, c)$ in the hash table. If the key $x + 1$ exists in the hash table, then the sum of occurrences of elements $x$ and $x + 1$, $c + \text{cnt}[x + 1]$, forms a harmonious subsequence. We just need to find the maximum length among all harmonious subsequences. +We can use a hash table $\textit{cnt}$ to record the occurrence count of each element in the array $\textit{nums}$. Then, we iterate through each key-value pair $(x, c)$ in the hash table. If the key $x + 1$ exists in the hash table, then the sum of occurrences of elements $x$ and $x + 1$, $c + \textit{cnt}[x + 1]$, forms a harmonious subsequence. We just need to find the maximum length among all harmonious subsequences. -The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\text{nums}$. +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md index e81e6281b623..cc1828da9c51 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README.md @@ -67,30 +67,28 @@ tags: 这道题实际上是求在给定区间 $[l,..r]$ 中,数字的二进制表示不包含连续的 $1$ 的个数。个数与数的位数以及每个二进制位上的数字有关。我们可以用数位 DP 的思路来解决这道题。数位 DP 中,数的大小对复杂度的影响很小。 -对于区间 $[l,..r]$ 问题,我们一般会将其转化为 $[1,..r]$ 然后再减去 $[1,..l - 1]$ 的问题,即: +对于区间 $[l,..r]$ 问题,我们一般会将其转化为 $[0,..r]$ 然后再减去 $[0,..l - 1]$ 的问题,即: $$ -ans = \sum_{i=1}^{r} ans_i - \sum_{i=1}^{l-1} ans_i +ans = \sum_{i=0}^{r} ans_i - \sum_{i=0}^{l-1} ans_i $$ 不过对于本题而言,我们只需要求出区间 $[0,..r]$ 的值即可。 -这里我们用记忆化搜索来实现数位 DP。从起点向下搜索,到最底层得到方案数,一层层向上返回答案并累加,最后从搜索起点得到最终的答案。 +这里我们用记忆化搜索来实现数位 DP。基本步骤如下: -基本步骤如下: - -1. 将数字 $n$ 转为二进制数组 $a$,其中 $a[1]$ 为最低位,而 $a[len]$ 为最高位; -1. 根据题目信息,设计函数 $dfs()$,对于本题,我们定义 $dfs(pos, pre, limit)$,答案为 $dfs(len, 1, true)$。 +1. 将数字 $n$ 转为二进制字符串 $s$; +1. 根据题目信息,设计函数 $\textit{dfs}()$,对于本题,我们定义 $\textit{dfs}(\textit{pos}, \textit{pre}, \textit{limit})$,答案为 $\textit{dfs}(\textit{0}, 0, \textit{true})$。 其中: -- `pos` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,`pos` 的初始值为 `len`; +- `pos` 表示数字的位数,我们从数字的最高位开始,即二进制字符串的首字符; - `pre` 表示当前数字二进制位上的数字,对于本题,`pre` 的初始值为 `0`; -- `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1]$,否则,只能选择 $[0,..a[pos]]$。如果 `limit` 为 `true` 且已经取到了能取到的最大值,那么下一个 `limit` 同样为 `true`;如果 `limit` 为 `true` 但是还没有取到最大值,或者 `limit` 为 `false`,那么下一个 `limit` 为 `false`。 +- `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1]$,否则,只能选择 $[0,..s[\textit{pos}]]$。 关于函数的实现细节,可以参考下面的代码。 -时间复杂度 $O(\log n)$。 +时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为题目给定的数字。 相似题目: @@ -109,61 +107,50 @@ $$ class Solution: def findIntegers(self, n: int) -> int: @cache - def dfs(pos, pre, limit): - if pos <= 0: + def dfs(pos: int, pre: int, limit: bool) -> int: + if pos == len(s): return 1 - up = a[pos] if limit else 1 + up = int(s[pos]) if limit else 1 ans = 0 for i in range(up + 1): if pre == 1 and i == 1: continue - ans += dfs(pos - 1, i, limit and i == up) + ans += dfs(pos + 1, i, limit and i == up) return ans - a = [0] * 33 - l = 0 - while n: - l += 1 - a[l] = n & 1 - n >>= 1 - return dfs(l, 0, True) + s = bin(n)[2:] + return dfs(0, 0, True) ``` #### Java ```java class Solution { - private int[] a = new int[33]; - private int[][] dp = new int[33][2]; + private char[] s; + private Integer[][] f; public int findIntegers(int n) { - int len = 0; - while (n > 0) { - a[++len] = n & 1; - n >>= 1; - } - for (var e : dp) { - Arrays.fill(e, -1); - } - return dfs(len, 0, true); + s = Integer.toBinaryString(n).toCharArray(); + f = new Integer[s.length][2]; + return dfs(0, 0, true); } private int dfs(int pos, int pre, boolean limit) { - if (pos <= 0) { + if (pos >= s.length) { return 1; } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; + if (!limit && f[pos][pre] != null) { + return f[pos][pre]; } - int up = limit ? a[pos] : 1; + int up = limit ? s[pos] - '0' : 1; int ans = 0; for (int i = 0; i <= up; ++i) { if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + ans += dfs(pos + 1, i, limit && i == up); } } if (!limit) { - dp[pos][pre] = ans; + f[pos][pre] = ans; } return ans; } @@ -175,37 +162,32 @@ class Solution { ```cpp class Solution { public: - int a[33]; - int dp[33][2]; - int findIntegers(int n) { - int len = 0; - while (n) { - a[++len] = n & 1; - n >>= 1; - } - memset(dp, -1, sizeof dp); - return dfs(len, 0, true); - } - - int dfs(int pos, int pre, bool limit) { - if (pos <= 0) { - return 1; - } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; - } - int ans = 0; - int up = limit ? a[pos] : 1; - for (int i = 0; i <= up; ++i) { - if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + string s = bitset<32>(n).to_string(); + s = s.substr(s.find('1')); + int m = s.size(); + int f[m][2]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int { + if (pos >= m) { + return 1; } - } - if (!limit) { - dp[pos][pre] = ans; - } - return ans; + if (!limit && f[pos][pre] != -1) { + return f[pos][pre]; + } + int up = limit ? s[pos] - '0' : 1; + int ans = 0; + for (int i = 0; i <= up; ++i) { + if (!(pre == 1 && i == 1)) { + ans += dfs(dfs, pos + 1, i, limit && i == up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + }; + return dfs(dfs, 0, 0, true); } }; ``` @@ -214,41 +196,68 @@ public: ```go func findIntegers(n int) int { - a := make([]int, 33) - dp := make([][2]int, 33) - for i := range dp { - dp[i] = [2]int{-1, -1} - } - l := 0 - for n > 0 { - l++ - a[l] = n & 1 - n >>= 1 + s := strconv.FormatInt(int64(n), 2) + m := len(s) + f := make([][]int, m) + for i := range f { + f[i] = []int{-1, -1} } var dfs func(int, int, bool) int - dfs = func(pos, pre int, limit bool) int { - if pos <= 0 { + dfs = func(pos int, pre int, limit bool) int { + if pos >= m { return 1 } - if !limit && dp[pos][pre] != -1 { - return dp[pos][pre] + if !limit && f[pos][pre] != -1 { + return f[pos][pre] } up := 1 if limit { - up = a[pos] + up = int(s[pos] - '0') } ans := 0 for i := 0; i <= up; i++ { if !(pre == 1 && i == 1) { - ans += dfs(pos-1, i, limit && i == up) + ans += dfs(pos+1, i, limit && i == up) } } if !limit { - dp[pos][pre] = ans + f[pos][pre] = ans } return ans } - return dfs(l, 0, true) + return dfs(0, 0, true) +} +``` + +#### TypeScript + +```ts +function findIntegers(n: number): number { + const s = n.toString(2); + const m = s.length; + const f: number[][] = Array.from({ length: m }, () => [-1, -1]); + + function dfs(pos: number, pre: number, limit: boolean): number { + if (pos >= m) { + return 1; + } + if (!limit && f[pos][pre] !== -1) { + return f[pos][pre]; + } + const up = limit ? parseInt(s[pos]) : 1; + let ans = 0; + for (let i = 0; i <= up; ++i) { + if (!(pre === 1 && i === 1)) { + ans += dfs(pos + 1, i, limit && i === up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + } + + return dfs(0, 0, true); } ``` diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md index 73100c20f7d2..4d1cbe0d9b1f 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/README_EN.md @@ -62,7 +62,41 @@ Among them, only integer 3 disobeys the rule (two consecutive ones) and the othe -### Solution 1 +### Solution 1: Digit DP + +This problem is essentially about finding the number of numbers in the given interval $[l,..r]$ whose binary representation does not contain consecutive $1$s. The count is related to the number of digits and the digits in each binary position. We can solve this problem using the digit DP approach. In digit DP, the size of the number has little impact on the complexity. + +For the interval $[l,..r]$ problem, we generally convert it to the problem of $[0,..r]$ and then subtract the problem of $[0,..l - 1]$, i.e.: + +$$ +ans = \sum_{i=0}^{r} ans_i - \sum_{i=0}^{l-1} ans_i +$$ + +However, for this problem, we only need to find the value for the interval $[0,..r]$. + +Here we use memoization to implement digit DP. The basic steps are as follows: + +1. Convert the number $n$ to a binary string $s$; +1. According to the problem information, design the function $\textit{dfs}()$. For this problem, we define $\textit{dfs}(\textit{pos}, \textit{pre}, \textit{limit})$, and the answer is $\textit{dfs}(\textit{0}, 0, \textit{true})$. + +Where: + +- `pos` represents the digit position, starting from the highest digit of the number, i.e., the first character of the binary string; +- `pre` represents the digit at the current binary position. For this problem, the initial value of `pre` is `0`; +- `limit` represents the restriction on the digits that can be filled. If there is no restriction, then $[0,1]$ can be chosen; otherwise, only $[0,..s[\textit{pos}]]$ can be chosen. + +For the implementation details of the function, refer to the code below. + +Time complexity is $O(\log n)$, and space complexity is $O(\log n)$. Here, $n$ is the number given in the problem. + +Similar problems: + +- [233. Number of Digit One](https://github.com/doocs/leetcode/blob/main/solution/0200-0299/0233.Number%20of%20Digit%20One/README_EN.md) +- [357. Count Numbers with Unique Digits](https://github.com/doocs/leetcode/blob/main/solution/0300-0399/0357.Count%20Numbers%20with%20Unique%20Digits/README_EN.md) +- [788. Rotated Digits](https://github.com/doocs/leetcode/blob/main/solution/0700-0799/0788.Rotated%20Digits/README_EN.md) +- [902. Numbers At Most N Given Digit Set](https://github.com/doocs/leetcode/blob/main/solution/0900-0999/0902.Numbers%20At%20Most%20N%20Given%20Digit%20Set/README_EN.md) +- [1012. Numbers With Repeated Digits](https://github.com/doocs/leetcode/blob/main/solution/1000-1099/1012.Numbers%20With%20Repeated%20Digits/README_EN.md) +- [2376. Count Special Integers](https://github.com/doocs/leetcode/blob/main/solution/2300-2399/2376.Count%20Special%20Integers/README_EN.md) @@ -72,61 +106,50 @@ Among them, only integer 3 disobeys the rule (two consecutive ones) and the othe class Solution: def findIntegers(self, n: int) -> int: @cache - def dfs(pos, pre, limit): - if pos <= 0: + def dfs(pos: int, pre: int, limit: bool) -> int: + if pos == len(s): return 1 - up = a[pos] if limit else 1 + up = int(s[pos]) if limit else 1 ans = 0 for i in range(up + 1): if pre == 1 and i == 1: continue - ans += dfs(pos - 1, i, limit and i == up) + ans += dfs(pos + 1, i, limit and i == up) return ans - a = [0] * 33 - l = 0 - while n: - l += 1 - a[l] = n & 1 - n >>= 1 - return dfs(l, 0, True) + s = bin(n)[2:] + return dfs(0, 0, True) ``` #### Java ```java class Solution { - private int[] a = new int[33]; - private int[][] dp = new int[33][2]; + private char[] s; + private Integer[][] f; public int findIntegers(int n) { - int len = 0; - while (n > 0) { - a[++len] = n & 1; - n >>= 1; - } - for (var e : dp) { - Arrays.fill(e, -1); - } - return dfs(len, 0, true); + s = Integer.toBinaryString(n).toCharArray(); + f = new Integer[s.length][2]; + return dfs(0, 0, true); } private int dfs(int pos, int pre, boolean limit) { - if (pos <= 0) { + if (pos >= s.length) { return 1; } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; + if (!limit && f[pos][pre] != null) { + return f[pos][pre]; } - int up = limit ? a[pos] : 1; + int up = limit ? s[pos] - '0' : 1; int ans = 0; for (int i = 0; i <= up; ++i) { if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + ans += dfs(pos + 1, i, limit && i == up); } } if (!limit) { - dp[pos][pre] = ans; + f[pos][pre] = ans; } return ans; } @@ -138,37 +161,32 @@ class Solution { ```cpp class Solution { public: - int a[33]; - int dp[33][2]; - int findIntegers(int n) { - int len = 0; - while (n) { - a[++len] = n & 1; - n >>= 1; - } - memset(dp, -1, sizeof dp); - return dfs(len, 0, true); - } - - int dfs(int pos, int pre, bool limit) { - if (pos <= 0) { - return 1; - } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; - } - int ans = 0; - int up = limit ? a[pos] : 1; - for (int i = 0; i <= up; ++i) { - if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + string s = bitset<32>(n).to_string(); + s = s.substr(s.find('1')); + int m = s.size(); + int f[m][2]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int { + if (pos >= m) { + return 1; } - } - if (!limit) { - dp[pos][pre] = ans; - } - return ans; + if (!limit && f[pos][pre] != -1) { + return f[pos][pre]; + } + int up = limit ? s[pos] - '0' : 1; + int ans = 0; + for (int i = 0; i <= up; ++i) { + if (!(pre == 1 && i == 1)) { + ans += dfs(dfs, pos + 1, i, limit && i == up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + }; + return dfs(dfs, 0, 0, true); } }; ``` @@ -177,41 +195,68 @@ public: ```go func findIntegers(n int) int { - a := make([]int, 33) - dp := make([][2]int, 33) - for i := range dp { - dp[i] = [2]int{-1, -1} - } - l := 0 - for n > 0 { - l++ - a[l] = n & 1 - n >>= 1 + s := strconv.FormatInt(int64(n), 2) + m := len(s) + f := make([][]int, m) + for i := range f { + f[i] = []int{-1, -1} } var dfs func(int, int, bool) int - dfs = func(pos, pre int, limit bool) int { - if pos <= 0 { + dfs = func(pos int, pre int, limit bool) int { + if pos >= m { return 1 } - if !limit && dp[pos][pre] != -1 { - return dp[pos][pre] + if !limit && f[pos][pre] != -1 { + return f[pos][pre] } up := 1 if limit { - up = a[pos] + up = int(s[pos] - '0') } ans := 0 for i := 0; i <= up; i++ { if !(pre == 1 && i == 1) { - ans += dfs(pos-1, i, limit && i == up) + ans += dfs(pos+1, i, limit && i == up) } } if !limit { - dp[pos][pre] = ans + f[pos][pre] = ans } return ans } - return dfs(l, 0, true) + return dfs(0, 0, true) +} +``` + +#### TypeScript + +```ts +function findIntegers(n: number): number { + const s = n.toString(2); + const m = s.length; + const f: number[][] = Array.from({ length: m }, () => [-1, -1]); + + function dfs(pos: number, pre: number, limit: boolean): number { + if (pos >= m) { + return 1; + } + if (!limit && f[pos][pre] !== -1) { + return f[pos][pre]; + } + const up = limit ? parseInt(s[pos]) : 1; + let ans = 0; + for (let i = 0; i <= up; ++i) { + if (!(pre === 1 && i === 1)) { + ans += dfs(pos + 1, i, limit && i === up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + } + + return dfs(0, 0, true); } ``` diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp index 8bfb4af82c9a..1fcd6f6000aa 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.cpp @@ -1,35 +1,30 @@ class Solution { public: - int a[33]; - int dp[33][2]; - int findIntegers(int n) { - int len = 0; - while (n) { - a[++len] = n & 1; - n >>= 1; - } - memset(dp, -1, sizeof dp); - return dfs(len, 0, true); - } - - int dfs(int pos, int pre, bool limit) { - if (pos <= 0) { - return 1; - } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; - } - int ans = 0; - int up = limit ? a[pos] : 1; - for (int i = 0; i <= up; ++i) { - if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + string s = bitset<32>(n).to_string(); + s = s.substr(s.find('1')); + int m = s.size(); + int f[m][2]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int pos, int pre, bool limit) -> int { + if (pos >= m) { + return 1; + } + if (!limit && f[pos][pre] != -1) { + return f[pos][pre]; + } + int up = limit ? s[pos] - '0' : 1; + int ans = 0; + for (int i = 0; i <= up; ++i) { + if (!(pre == 1 && i == 1)) { + ans += dfs(dfs, pos + 1, i, limit && i == up); + } + } + if (!limit) { + f[pos][pre] = ans; } - } - if (!limit) { - dp[pos][pre] = ans; - } - return ans; + return ans; + }; + return dfs(dfs, 0, 0, true); } -}; \ No newline at end of file +}; diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go index de984b678cde..e68031cff719 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.go @@ -1,37 +1,32 @@ func findIntegers(n int) int { - a := make([]int, 33) - dp := make([][2]int, 33) - for i := range dp { - dp[i] = [2]int{-1, -1} - } - l := 0 - for n > 0 { - l++ - a[l] = n & 1 - n >>= 1 + s := strconv.FormatInt(int64(n), 2) + m := len(s) + f := make([][]int, m) + for i := range f { + f[i] = []int{-1, -1} } var dfs func(int, int, bool) int - dfs = func(pos, pre int, limit bool) int { - if pos <= 0 { + dfs = func(pos int, pre int, limit bool) int { + if pos >= m { return 1 } - if !limit && dp[pos][pre] != -1 { - return dp[pos][pre] + if !limit && f[pos][pre] != -1 { + return f[pos][pre] } up := 1 if limit { - up = a[pos] + up = int(s[pos] - '0') } ans := 0 for i := 0; i <= up; i++ { if !(pre == 1 && i == 1) { - ans += dfs(pos-1, i, limit && i == up) + ans += dfs(pos+1, i, limit && i == up) } } if !limit { - dp[pos][pre] = ans + f[pos][pre] = ans } return ans } - return dfs(l, 0, true) -} \ No newline at end of file + return dfs(0, 0, true) +} diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java index a2ee46c7d5f9..62eca7316533 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.java @@ -1,36 +1,30 @@ class Solution { - private int[] a = new int[33]; - private int[][] dp = new int[33][2]; + private char[] s; + private Integer[][] f; public int findIntegers(int n) { - int len = 0; - while (n > 0) { - a[++len] = n & 1; - n >>= 1; - } - for (var e : dp) { - Arrays.fill(e, -1); - } - return dfs(len, 0, true); + s = Integer.toBinaryString(n).toCharArray(); + f = new Integer[s.length][2]; + return dfs(0, 0, true); } private int dfs(int pos, int pre, boolean limit) { - if (pos <= 0) { + if (pos >= s.length) { return 1; } - if (!limit && dp[pos][pre] != -1) { - return dp[pos][pre]; + if (!limit && f[pos][pre] != null) { + return f[pos][pre]; } - int up = limit ? a[pos] : 1; + int up = limit ? s[pos] - '0' : 1; int ans = 0; for (int i = 0; i <= up; ++i) { if (!(pre == 1 && i == 1)) { - ans += dfs(pos - 1, i, limit && i == up); + ans += dfs(pos + 1, i, limit && i == up); } } if (!limit) { - dp[pos][pre] = ans; + f[pos][pre] = ans; } return ans; } -} \ No newline at end of file +} diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py index 82139a40c2f5..955334695803 100644 --- a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.py @@ -1,21 +1,16 @@ class Solution: def findIntegers(self, n: int) -> int: @cache - def dfs(pos, pre, limit): - if pos <= 0: + def dfs(pos: int, pre: int, limit: bool) -> int: + if pos == len(s): return 1 - up = a[pos] if limit else 1 + up = int(s[pos]) if limit else 1 ans = 0 for i in range(up + 1): if pre == 1 and i == 1: continue - ans += dfs(pos - 1, i, limit and i == up) + ans += dfs(pos + 1, i, limit and i == up) return ans - a = [0] * 33 - l = 0 - while n: - l += 1 - a[l] = n & 1 - n >>= 1 - return dfs(l, 0, True) + s = bin(n)[2:] + return dfs(0, 0, True) diff --git a/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.ts b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.ts new file mode 100644 index 000000000000..e22bdb39fb1b --- /dev/null +++ b/solution/0600-0699/0600.Non-negative Integers without Consecutive Ones/Solution.ts @@ -0,0 +1,27 @@ +function findIntegers(n: number): number { + const s = n.toString(2); + const m = s.length; + const f: number[][] = Array.from({ length: m }, () => [-1, -1]); + + function dfs(pos: number, pre: number, limit: boolean): number { + if (pos >= m) { + return 1; + } + if (!limit && f[pos][pre] !== -1) { + return f[pos][pre]; + } + const up = limit ? parseInt(s[pos]) : 1; + let ans = 0; + for (let i = 0; i <= up; ++i) { + if (!(pre === 1 && i === 1)) { + ans += dfs(pos + 1, i, limit && i === up); + } + } + if (!limit) { + f[pos][pre] = ans; + } + return ans; + } + + return dfs(0, 0, true); +} diff --git a/solution/0600-0699/0614.Second Degree Follower/README.md b/solution/0600-0699/0614.Second Degree Follower/README.md index 2b2afe78b2b4..63a461cf46b3 100644 --- a/solution/0600-0699/0614.Second Degree Follower/README.md +++ b/solution/0600-0699/0614.Second Degree Follower/README.md @@ -26,7 +26,7 @@ tags: | follower | varchar | +-------------+---------+ (followee, follower) 是该表的主键(具有唯一值的列的组合)。 -该表的每一行表示关注者关注了社交网络上的关注者。 +该表的每一行表示关注者关注了社交网络上的被关注者。 不会有用户关注他们自己。 diff --git a/solution/0600-0699/0616.Add Bold Tag in String/README_EN.md b/solution/0600-0699/0616.Add Bold Tag in String/README_EN.md index 46ddc02925e2..e369b1612c0d 100644 --- a/solution/0600-0699/0616.Add Bold Tag in String/README_EN.md +++ b/solution/0600-0699/0616.Add Bold Tag in String/README_EN.md @@ -66,7 +66,7 @@ Since now the four <b>'s are consecutive, we merge them: "<b&g

     

    -

    Note: This question is the same as 758: https://leetcode.com/problems/bold-words-in-string/

    +

    Note: This question is the same as 758. Bold Words in String.

    diff --git a/solution/0600-0699/0624.Maximum Distance in Arrays/README.md b/solution/0600-0699/0624.Maximum Distance in Arrays/README.md index a91d9c27f85f..e184709d06cd 100644 --- a/solution/0600-0699/0624.Maximum Distance in Arrays/README.md +++ b/solution/0600-0699/0624.Maximum Distance in Arrays/README.md @@ -9,7 +9,7 @@ tags: -# [624. 数组列表中的最大距离 🔒](https://leetcode.cn/problems/maximum-distance-in-arrays) +# [624. 数组列表中的最大距离](https://leetcode.cn/problems/maximum-distance-in-arrays) [English Version](/solution/0600-0699/0624.Maximum%20Distance%20in%20Arrays/README_EN.md) @@ -17,28 +17,40 @@ tags: -

    给定 m 个数组,每个数组都已经按照升序排好序了。现在你需要从两个不同的数组中选择两个整数(每个数组选一个)并且计算它们的距离。两个整数 a 和 b 之间的距离定义为它们差的绝对值 |a-b| 。你的任务就是去找到最大距离

    +

    给定 m 个数组,每个数组都已经按照升序排好序了。

    + +

    现在你需要从两个不同的数组中选择两个整数(每个数组选一个)并且计算它们的距离。两个整数 a 和 b 之间的距离定义为它们差的绝对值 |a-b| 。

    + +

    返回最大距离。

    示例 1:

    -
    输入: 
    -[[1,2,3],
    - [4,5],
    - [1,2,3]]
    -输出: 4
    +
    +输入:[[1,2,3],[4,5],[1,2,3]]
    +输出:4
     解释:
     一种得到答案 4 的方法是从第一个数组或者第三个数组中选择 1,同时从第二个数组中选择 5 。
     
    +

    示例 2:

    + +
    +输入:arrays = [[1],[1]]
    +输出:0
    +
    +

     

    -

    注意:

    +

    提示:

    -
      -
    1. 每个给定数组至少会有 1 个数字。列表中至少有两个非空数组。
    2. -
    3. 所有 m 个数组中的数字总数目在范围 [2, 10000] 内。
    4. -
    5. m 个数组中所有整数的范围在 [-10000, 10000] 内。
    6. -
    +
      +
    • m == arrays.length
    • +
    • 2 <= m <= 105
    • +
    • 1 <= arrays[i].length <= 500
    • +
    • -104 <= arrays[i][j] <= 104
    • +
    • arrays[i] 以 升序 排序。
    • +
    • 所有数组中最多有 105 个整数。
    • +

     

    @@ -136,6 +148,90 @@ func abs(x int) int { } ``` +#### TypeScript + +```ts +function maxDistance(arrays: number[][]): number { + const n = arrays.length; + let res = 0; + let [min, max] = [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]; + + for (let i = 0; i < n; i++) { + const a = arrays[i]; + res = Math.max(Math.max(a.at(-1)! - min, max - a[0]), res); + min = Math.min(min, a[0]); + max = Math.max(max, a.at(-1)!); + } + + return res; +} +``` + +#### JavaScript + +```js +/** + * @param {number[][]} arrays + * @return {number} + */ +var maxDistance = function (arrays) { + const n = arrays.length; + let res = 0; + let [min, max] = [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]; + + for (let i = 0; i < n; i++) { + const a = arrays[i]; + res = Math.max(Math.max(a.at(-1) - min, max - a[0]), res); + min = Math.min(min, a[0]); + max = Math.max(max, a.at(-1)); + } + + return res; +}; +``` + + + + + + + +### 方法二:一行 + + + +#### TypeScript + +```ts +const maxDistance = (arrays: number[][]): number => + arrays.reduce( + ([res, min, max], a) => [ + Math.max(Math.max(a.at(-1)! - min, max - a[0]), res), + Math.min(min, a[0]), + Math.max(max, a.at(-1)!), + ], + [0, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + )[0]; +``` + +#### JavaScript + +```js +/** + * @param {number[][]} arrays + * @return {number} + */ +var maxDistance = arrays => + arrays.reduce( + ([res, min, max], a) => [ + Math.max(Math.max(a.at(-1) - min, max - a[0]), res), + Math.min(min, a[0]), + Math.max(max, a.at(-1)), + ], + [0, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + )[0]; +``` + diff --git a/solution/0600-0699/0624.Maximum Distance in Arrays/README_EN.md b/solution/0600-0699/0624.Maximum Distance in Arrays/README_EN.md index 3b6e64bee5aa..d07ae857f88e 100644 --- a/solution/0600-0699/0624.Maximum Distance in Arrays/README_EN.md +++ b/solution/0600-0699/0624.Maximum Distance in Arrays/README_EN.md @@ -9,7 +9,7 @@ tags: -# [624. Maximum Distance in Arrays 🔒](https://leetcode.com/problems/maximum-distance-in-arrays) +# [624. Maximum Distance in Arrays](https://leetcode.com/problems/maximum-distance-in-arrays) [中文文档](/solution/0600-0699/0624.Maximum%20Distance%20in%20Arrays/README.md) @@ -139,6 +139,90 @@ func abs(x int) int { } ``` +#### TypeScript + +```ts +function maxDistance(arrays: number[][]): number { + const n = arrays.length; + let res = 0; + let [min, max] = [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]; + + for (let i = 0; i < n; i++) { + const a = arrays[i]; + res = Math.max(Math.max(a.at(-1)! - min, max - a[0]), res); + min = Math.min(min, a[0]); + max = Math.max(max, a.at(-1)!); + } + + return res; +} +``` + +#### JavaScript + +```js +/** + * @param {number[][]} arrays + * @return {number} + */ +var maxDistance = function (arrays) { + const n = arrays.length; + let res = 0; + let [min, max] = [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]; + + for (let i = 0; i < n; i++) { + const a = arrays[i]; + res = Math.max(Math.max(a.at(-1) - min, max - a[0]), res); + min = Math.min(min, a[0]); + max = Math.max(max, a.at(-1)); + } + + return res; +}; +``` + + + + + + + +### Solution 2: One-line solution + + + +#### TypeScript + +```ts +const maxDistance = (arrays: number[][]): number => + arrays.reduce( + ([res, min, max], a) => [ + Math.max(Math.max(a.at(-1)! - min, max - a[0]), res), + Math.min(min, a[0]), + Math.max(max, a.at(-1)!), + ], + [0, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + )[0]; +``` + +#### JavaScript + +```js +/** + * @param {number[][]} arrays + * @return {number} + */ +var maxDistance = arrays => + arrays.reduce( + ([res, min, max], a) => [ + Math.max(Math.max(a.at(-1) - min, max - a[0]), res), + Math.min(min, a[0]), + Math.max(max, a.at(-1)), + ], + [0, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + )[0]; +``` + diff --git a/solution/0600-0699/0624.Maximum Distance in Arrays/Solution.js b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution.js new file mode 100644 index 000000000000..6d7b30f2e765 --- /dev/null +++ b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution.js @@ -0,0 +1,18 @@ +/** + * @param {number[][]} arrays + * @return {number} + */ +var maxDistance = function (arrays) { + const n = arrays.length; + let res = 0; + let [min, max] = [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]; + + for (let i = 0; i < n; i++) { + const a = arrays[i]; + res = Math.max(Math.max(a.at(-1) - min, max - a[0]), res); + min = Math.min(min, a[0]); + max = Math.max(max, a.at(-1)); + } + + return res; +}; diff --git a/solution/0600-0699/0624.Maximum Distance in Arrays/Solution.ts b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution.ts new file mode 100644 index 000000000000..2e8473474a2e --- /dev/null +++ b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution.ts @@ -0,0 +1,14 @@ +function maxDistance(arrays: number[][]): number { + const n = arrays.length; + let res = 0; + let [min, max] = [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]; + + for (let i = 0; i < n; i++) { + const a = arrays[i]; + res = Math.max(Math.max(a.at(-1)! - min, max - a[0]), res); + min = Math.min(min, a[0]); + max = Math.max(max, a.at(-1)!); + } + + return res; +} diff --git a/solution/0600-0699/0624.Maximum Distance in Arrays/Solution2.js b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution2.js new file mode 100644 index 000000000000..b99d397cd2ca --- /dev/null +++ b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution2.js @@ -0,0 +1,13 @@ +/** + * @param {number[][]} arrays + * @return {number} + */ +var maxDistance = arrays => + arrays.reduce( + ([res, min, max], a) => [ + Math.max(Math.max(a.at(-1) - min, max - a[0]), res), + Math.min(min, a[0]), + Math.max(max, a.at(-1)), + ], + [0, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + )[0]; diff --git a/solution/0600-0699/0624.Maximum Distance in Arrays/Solution2.ts b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution2.ts new file mode 100644 index 000000000000..eb94781f75af --- /dev/null +++ b/solution/0600-0699/0624.Maximum Distance in Arrays/Solution2.ts @@ -0,0 +1,9 @@ +const maxDistance = (arrays: number[][]): number => + arrays.reduce( + ([res, min, max], a) => [ + Math.max(Math.max(a.at(-1)! - min, max - a[0]), res), + Math.min(min, a[0]), + Math.max(max, a.at(-1)!), + ], + [0, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY], + )[0]; diff --git a/solution/0600-0699/0638.Shopping Offers/README.md b/solution/0600-0699/0638.Shopping Offers/README.md index fd2918323354..26c28a6dc095 100644 --- a/solution/0600-0699/0638.Shopping Offers/README.md +++ b/solution/0600-0699/0638.Shopping Offers/README.md @@ -29,7 +29,7 @@ tags:

    返回 确切 满足购物清单所需花费的最低价格,你可以充分利用大礼包的优惠活动。你不能购买超出购物清单指定数量的物品,即使那样会降低整体价格。任意大礼包可无限次购买。

    -

     

    +

     

    示例 1:

    @@ -51,19 +51,18 @@ tags: 需要买 1A ,2B 和 1C ,所以付 ¥4 买 1A 和 1B(大礼包 1),以及 ¥3 购买 1B , ¥4 购买 1C 。 不可以购买超出待购清单的物品,尽管购买大礼包 2 更加便宜。
    -

     

    +

     

    提示:

      -
    • n == price.length
    • -
    • n == needs.length
    • -
    • 1 <= n <= 6
    • -
    • 0 <= price[i] <= 10
    • -
    • 0 <= needs[i] <= 10
    • -
    • 1 <= special.length <= 100
    • +
    • n == price.length == needs.length
    • +
    • 1 <= n <= 6
    • +
    • 0 <= price[i], needs[i] <= 10
    • +
    • 1 <= special.length <= 100
    • special[i].length == n + 1
    • -
    • 0 <= special[i][j] <= 50
    • +
    • 0 <= special[i][j] <= 50
    • +
    • 生成的输入对于 0 <= j <= n - 1 至少有一个 special[i][j] 非零。
    @@ -76,17 +75,17 @@ tags: 我们注意到,题目中物品的种类 $n \leq 6$,而每种物品需要购买的数量不超过 $10$,我们可以用 $4$ 个二进制位来表示每种物品需要购买的数量,这样,我们只需要最多 $6 \times 4 = 24$ 个二进制位来表示整个购物清单。 -我们首先将购物清单 $\text{needs}$ 转换为一个整数 $\text{mask}$,其中第 $i$ 个物品需要购买的数量存储在 $\text{mask}$ 的第 $i \times 4$ 位到第 $(i + 1) \times 4 - 1$ 位。例如,当 $\text{needs} = [1, 2, 1]$ 时,有 $\text{mask} = 0b0001 0010 0001$。 +我们首先将购物清单 $\textit{needs}$ 转换为一个整数 $\textit{mask}$,其中第 $i$ 个物品需要购买的数量存储在 $\textit{mask}$ 的第 $i \times 4$ 位到第 $(i + 1) \times 4 - 1$ 位。例如,当 $\textit{needs} = [1, 2, 1]$ 时,有 $\textit{mask} = 0b0001 0010 0001$。 -然后,我们设计一个函数 $\text{dfs}(cur)$,表示当前购物清单的状态为 $\text{cur}$ 时,我们需要花费的最少金额。那么答案即为 $\text{dfs}(\text{mask})$。 +然后,我们设计一个函数 $\textit{dfs}(cur)$,表示当前购物清单的状态为 $\textit{cur}$ 时,我们需要花费的最少金额。那么答案即为 $\textit{dfs}(\textit{mask})$。 -函数 $\text{dfs}(cur)$ 的计算方法如下: +函数 $\textit{dfs}(cur)$ 的计算方法如下: -- 我们首先计算当前购物清单 $\text{cur}$ 不使用大礼包时的花费,记为 $\text{ans}$。 -- 然后,我们遍历每一个大礼包 $\text{offer}$,如果当前购物清单 $\text{cur}$ 能够使用大礼包 $\text{offer}$,即 $\text{cur}$ 中每种物品的数量都不小于大礼包 $\text{offer}$ 中的数量,那么我们可以尝试使用这个大礼包。我们将 $\text{cur}$ 中每种物品的数量减去大礼包 $\text{offer}$ 中的数量,得到一个新的购物清单 $\text{nxt}$,然后递归计算 $\text{nxt}$ 的最少花费,并加上大礼包的价格 $\text{offer}[n]$,更新 $\text{ans}$,即 $\text{ans} = \min(\text{ans}, \text{offer}[n] + \text{dfs}(\text{nxt}))$。 -- 最后,返回 $\text{ans}$。 +- 我们首先计算当前购物清单 $\textit{cur}$ 不使用大礼包时的花费,记为 $\textit{ans}$。 +- 然后,我们遍历每一个大礼包 $\textit{offer}$,如果当前购物清单 $\textit{cur}$ 能够使用大礼包 $\textit{offer}$,即 $\textit{cur}$ 中每种物品的数量都不小于大礼包 $\textit{offer}$ 中的数量,那么我们可以尝试使用这个大礼包。我们将 $\textit{cur}$ 中每种物品的数量减去大礼包 $\textit{offer}$ 中的数量,得到一个新的购物清单 $\textit{nxt}$,然后递归计算 $\textit{nxt}$ 的最少花费,并加上大礼包的价格 $\textit{offer}[n]$,更新 $\textit{ans}$,即 $\textit{ans} = \min(\textit{ans}, \textit{offer}[n] + \textit{dfs}(\textit{nxt}))$。 +- 最后,返回 $\textit{ans}$。 -为了避免重复计算,我们使用一个哈希表 $\text{f}$ 记录每一个状态 $\text{cur}$ 对应的最少花费。 +为了避免重复计算,我们使用一个哈希表 $\textit{f}$ 记录每一个状态 $\textit{cur}$ 对应的最少花费。 时间复杂度 $O(n \times k \times m^n)$,其中 $n$ 表示物品的种类,而 $k$ 和 $m$ 分别表示大礼包的数量以及每种物品的最大需求量。空间复杂度 $O(n \times m^n)$。 diff --git a/solution/0600-0699/0638.Shopping Offers/README_EN.md b/solution/0600-0699/0638.Shopping Offers/README_EN.md index a08277e2168c..05f4f49a0de4 100644 --- a/solution/0600-0699/0638.Shopping Offers/README_EN.md +++ b/solution/0600-0699/0638.Shopping Offers/README_EN.md @@ -62,6 +62,7 @@ You cannot add more items, though only $9 for 2A ,2B and 1C.
  • 1 <= special.length <= 100
  • special[i].length == n + 1
  • 0 <= special[i][j] <= 50
  • +
  • The input is generated that at least one of special[i][j] is non-zero for 0 <= j <= n - 1.
  • @@ -74,17 +75,17 @@ You cannot add more items, though only $9 for 2A ,2B and 1C. We notice that the number of types of items $n \leq 6$ in the problem, and the quantity of each item needed does not exceed $10$. We can use $4$ binary bits to represent the quantity of each item needed. Thus, we only need at most $6 \times 4 = 24$ binary bits to represent the entire shopping list. -First, we convert the shopping list $\text{needs}$ into an integer $\text{mask}$, where the quantity of the $i$-th item needed is stored in the $i \times 4$ to $(i + 1) \times 4 - 1$ bits of $\text{mask}$. For example, when $\text{needs} = [1, 2, 1]$, we have $\text{mask} = 0b0001 0010 0001$. +First, we convert the shopping list $\textit{needs}$ into an integer $\textit{mask}$, where the quantity of the $i$-th item needed is stored in the $i \times 4$ to $(i + 1) \times 4 - 1$ bits of $\textit{mask}$. For example, when $\textit{needs} = [1, 2, 1]$, we have $\textit{mask} = 0b0001 0010 0001$. -Then, we design a function $\text{dfs}(cur)$, representing the minimum amount of money we need to spend when the current state of the shopping list is $\text{cur}$. Therefore, the answer is $\text{dfs}(\text{mask})$. +Then, we design a function $\textit{dfs}(cur)$, representing the minimum amount of money we need to spend when the current state of the shopping list is $\textit{cur}$. Therefore, the answer is $\textit{dfs}(\textit{mask})$. -The calculation method of the function $\text{dfs}(cur)$ is as follows: +The calculation method of the function $\textit{dfs}(cur)$ is as follows: -- First, we calculate the cost of the current shopping list $\text{cur}$ without using any bundles, denoted as $\text{ans}$. -- Then, we iterate through each bundle $\text{offer}$. If the current shopping list $\text{cur}$ can use the bundle $\text{offer}$, i.e., the quantity of each item in $\text{cur}$ is not less than that in the bundle $\text{offer}$, then we can try to use this bundle. We subtract the quantity of each item in the bundle $\text{offer}$ from $\text{cur}$, obtaining a new shopping list $\text{nxt}$, then recursively calculate the minimum cost of $\text{nxt}$ and add the price of the bundle $\text{offer}[n]$, updating $\text{ans}$, i.e., $\text{ans} = \min(\text{ans}, \text{offer}[n] + \text{dfs}(\text{nxt}))$. -- Finally, return $\text{ans}$. +- First, we calculate the cost of the current shopping list $\textit{cur}$ without using any bundles, denoted as $\textit{ans}$. +- Then, we iterate through each bundle $\textit{offer}$. If the current shopping list $\textit{cur}$ can use the bundle $\textit{offer}$, i.e., the quantity of each item in $\textit{cur}$ is not less than that in the bundle $\textit{offer}$, then we can try to use this bundle. We subtract the quantity of each item in the bundle $\textit{offer}$ from $\textit{cur}$, obtaining a new shopping list $\textit{nxt}$, then recursively calculate the minimum cost of $\textit{nxt}$ and add the price of the bundle $\textit{offer}[n]$, updating $\textit{ans}$, i.e., $\textit{ans} = \min(\textit{ans}, \textit{offer}[n] + \textit{dfs}(\textit{nxt}))$. +- Finally, return $\textit{ans}$. -To avoid repeated calculations, we use a hash table $\text{f}$ to record the minimum cost corresponding to each state $\text{cur}$. +To avoid repeated calculations, we use a hash table $\textit{f}$ to record the minimum cost corresponding to each state $\textit{cur}$. The time complexity is $O(n \times k \times m^n)$, where $n$ represents the types of items, and $k$ and $m$ respectively represent the number of bundles and the maximum demand for each type of item. The space complexity is $O(n \times m^n)$. diff --git a/solution/0600-0699/0642.Design Search Autocomplete System/README.md b/solution/0600-0699/0642.Design Search Autocomplete System/README.md index 4ecc38c9f5f8..3682d112a4ea 100644 --- a/solution/0600-0699/0642.Design Search Autocomplete System/README.md +++ b/solution/0600-0699/0642.Design Search Autocomplete System/README.md @@ -3,6 +3,7 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0600-0699/0642.Design%20Search%20Autocomplete%20System/README.md tags: + - 深度优先搜索 - 设计 - 字典树 - 字符串 diff --git a/solution/0600-0699/0642.Design Search Autocomplete System/README_EN.md b/solution/0600-0699/0642.Design Search Autocomplete System/README_EN.md index b1c22de7dffe..362a27913626 100644 --- a/solution/0600-0699/0642.Design Search Autocomplete System/README_EN.md +++ b/solution/0600-0699/0642.Design Search Autocomplete System/README_EN.md @@ -3,6 +3,7 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/0600-0699/0642.Design%20Search%20Autocomplete%20System/README_EN.md tags: + - Depth-First Search - Design - Trie - String diff --git a/solution/0600-0699/0650.2 Keys Keyboard/README.md b/solution/0600-0699/0650.2 Keys Keyboard/README.md index ba78770327fe..d51b7380a9ad 100644 --- a/solution/0600-0699/0650.2 Keys Keyboard/README.md +++ b/solution/0600-0699/0650.2 Keys Keyboard/README.md @@ -277,6 +277,48 @@ func minSteps(n int) int { } ``` +#### TypeScript + +```ts +function minSteps(n: number): number { + const dp = Array(n + 1).fill(1000); + dp[1] = 0; + + for (let i = 2; i <= n; i++) { + for (let j = 1, half = i / 2; j <= half; j++) { + if (i % j === 0) { + dp[i] = Math.min(dp[i], dp[j] + i / j); + } + } + } + + return dp[n]; +} +``` + +#### JavaScript + +```js +/** + * @param {number} n + * @return {number} + */ +var minSteps = function (n) { + const dp = Array(n + 1).fill(1000); + dp[1] = 0; + + for (let i = 2; i <= n; i++) { + for (let j = 1, half = i / 2; j <= half; j++) { + if (i % j === 0) { + dp[i] = Math.min(dp[i], dp[j] + i / j); + } + } + } + + return dp[n]; +}; +``` + diff --git a/solution/0600-0699/0650.2 Keys Keyboard/README_EN.md b/solution/0600-0699/0650.2 Keys Keyboard/README_EN.md index e7bb4600ebb1..6d2c02c659b9 100644 --- a/solution/0600-0699/0650.2 Keys Keyboard/README_EN.md +++ b/solution/0600-0699/0650.2 Keys Keyboard/README_EN.md @@ -256,6 +256,48 @@ func minSteps(n int) int { } ``` +#### TypeScript + +```ts +function minSteps(n: number): number { + const dp = Array(n + 1).fill(1000); + dp[1] = 0; + + for (let i = 2; i <= n; i++) { + for (let j = 1, half = i / 2; j <= half; j++) { + if (i % j === 0) { + dp[i] = Math.min(dp[i], dp[j] + i / j); + } + } + } + + return dp[n]; +} +``` + +#### JavaScript + +```js +/** + * @param {number} n + * @return {number} + */ +var minSteps = function (n) { + const dp = Array(n + 1).fill(1000); + dp[1] = 0; + + for (let i = 2; i <= n; i++) { + for (let j = 1, half = i / 2; j <= half; j++) { + if (i % j === 0) { + dp[i] = Math.min(dp[i], dp[j] + i / j); + } + } + } + + return dp[n]; +}; +``` + diff --git a/solution/0600-0699/0650.2 Keys Keyboard/Solution2.js b/solution/0600-0699/0650.2 Keys Keyboard/Solution2.js new file mode 100644 index 000000000000..45a43bd55def --- /dev/null +++ b/solution/0600-0699/0650.2 Keys Keyboard/Solution2.js @@ -0,0 +1,18 @@ +/** + * @param {number} n + * @return {number} + */ +var minSteps = function (n) { + const dp = Array(n + 1).fill(1000); + dp[1] = 0; + + for (let i = 2; i <= n; i++) { + for (let j = 1, half = i / 2; j <= half; j++) { + if (i % j === 0) { + dp[i] = Math.min(dp[i], dp[j] + i / j); + } + } + } + + return dp[n]; +}; diff --git a/solution/0600-0699/0650.2 Keys Keyboard/Solution2.ts b/solution/0600-0699/0650.2 Keys Keyboard/Solution2.ts new file mode 100644 index 000000000000..457c19dd1ea2 --- /dev/null +++ b/solution/0600-0699/0650.2 Keys Keyboard/Solution2.ts @@ -0,0 +1,14 @@ +function minSteps(n: number): number { + const dp = Array(n + 1).fill(1000); + dp[1] = 0; + + for (let i = 2; i <= n; i++) { + for (let j = 1, half = i / 2; j <= half; j++) { + if (i % j === 0) { + dp[i] = Math.min(dp[i], dp[j] + i / j); + } + } + } + + return dp[n]; +} diff --git a/solution/0600-0699/0664.Strange Printer/README.md b/solution/0600-0699/0664.Strange Printer/README.md index fdbc2fa97358..9ef146a0d673 100644 --- a/solution/0600-0699/0664.Strange Printer/README.md +++ b/solution/0600-0699/0664.Strange Printer/README.md @@ -67,9 +67,9 @@ tags: $$ f[i][j]= \begin{cases} -1, & \text{if } i=j \\ -f[i][j-1], & \text{if } s[i]=s[j] \\ -\min_{i \leq k < j} \{f[i][k]+f[k+1][j]\}, & \text{otherwise} +1, & \textit{if } i=j \\ +f[i][j-1], & \textit{if } s[i]=s[j] \\ +\min_{i \leq k < j} \{f[i][k]+f[k+1][j]\}, & \textit{otherwise} \end{cases} $$ diff --git a/solution/0600-0699/0664.Strange Printer/README_EN.md b/solution/0600-0699/0664.Strange Printer/README_EN.md index fa77002259dd..7e5385de0d3c 100644 --- a/solution/0600-0699/0664.Strange Printer/README_EN.md +++ b/solution/0600-0699/0664.Strange Printer/README_EN.md @@ -66,9 +66,9 @@ Consider $f[i][j]$, if $s[i] = s[j]$, we can print $s[j]$ when print $s[i]$, so $$ f[i][j]= \begin{cases} -1, & \text{if } i=j \\ -f[i][j-1], & \text{if } s[i]=s[j] \\ -\min_{i \leq k < j} \{f[i][k]+f[k+1][j]\}, & \text{otherwise} +1, & \textit{if } i=j \\ +f[i][j-1], & \textit{if } s[i]=s[j] \\ +\min_{i \leq k < j} \{f[i][k]+f[k+1][j]\}, & \textit{otherwise} \end{cases} $$ diff --git a/solution/0600-0699/0676.Implement Magic Dictionary/README.md b/solution/0600-0699/0676.Implement Magic Dictionary/README.md index beb9e9f3b4bf..f7f70ca3b0ac 100644 --- a/solution/0600-0699/0676.Implement Magic Dictionary/README.md +++ b/solution/0600-0699/0676.Implement Magic Dictionary/README.md @@ -89,28 +89,32 @@ magicDictionary.search("leetcoded"); // 返回 False ```python class Trie: - __slots__ = ["children", "is_end"] + __slots__ = "children", "is_end" def __init__(self): - self.children = {} + self.children: List[Optional[Trie]] = [None] * 26 self.is_end = False def insert(self, w: str) -> None: node = self for c in w: - if c not in node.children: - node.children[c] = Trie() - node = node.children[c] + idx = ord(c) - ord("a") + if node.children[idx] is None: + node.children[idx] = Trie() + node = node.children[idx] node.is_end = True def search(self, w: str) -> bool: - def dfs(i: int, node: Trie, diff: int) -> bool: + def dfs(i: int, node: Optional[Trie], diff: int) -> bool: if i == len(w): return diff == 1 and node.is_end - if w[i] in node.children and dfs(i + 1, node.children[w[i]], diff): + j = ord(w[i]) - ord("a") + if node.children[j] and dfs(i + 1, node.children[j], diff): return True return diff == 0 and any( - dfs(i + 1, node.children[c], 1) for c in node.children if c != w[i] + node.children[k] and dfs(i + 1, node.children[k], 1) + for k in range(26) + if k != j ) return dfs(0, self, 0) @@ -506,67 +510,4 @@ impl MagicDictionary { - - -### 方法二 - - - -#### Python3 - -```python -class Trie: - __slots__ = ["children", "is_end"] - - def __init__(self): - self.children: [Trie | None] = [None] * 26 - self.is_end = False - - def insert(self, w: str) -> None: - node = self - for c in w: - idx = ord(c) - ord("a") - if node.children[idx] is None: - node.children[idx] = Trie() - node = node.children[idx] - node.is_end = True - - def search(self, w: str) -> bool: - def dfs(i: int, node: [Trie | None], diff: int) -> bool: - if i == len(w): - return diff == 1 and node.is_end - j = ord(w[i]) - ord("a") - if node.children[j] and dfs(i + 1, node.children[j], diff): - return True - return diff == 0 and any( - node.children[k] and dfs(i + 1, node.children[k], 1) - for k in range(26) - if k != j - ) - - return dfs(0, self, 0) - - -class MagicDictionary: - def __init__(self): - self.trie = Trie() - - def buildDict(self, dictionary: List[str]) -> None: - for w in dictionary: - self.trie.insert(w) - - def search(self, searchWord: str) -> bool: - return self.trie.search(searchWord) - - -# Your MagicDictionary object will be instantiated and called as such: -# obj = MagicDictionary() -# obj.buildDict(dictionary) -# param_2 = obj.search(searchWord) -``` - - - - - diff --git a/solution/0600-0699/0676.Implement Magic Dictionary/README_EN.md b/solution/0600-0699/0676.Implement Magic Dictionary/README_EN.md index ff447ce4177c..0eb29d8d584a 100644 --- a/solution/0600-0699/0676.Implement Magic Dictionary/README_EN.md +++ b/solution/0600-0699/0676.Implement Magic Dictionary/README_EN.md @@ -81,28 +81,32 @@ The time complexity is $O(n \times l + q \times l \times |\Sigma|)$, and the spa ```python class Trie: - __slots__ = ["children", "is_end"] + __slots__ = "children", "is_end" def __init__(self): - self.children = {} + self.children: List[Optional[Trie]] = [None] * 26 self.is_end = False def insert(self, w: str) -> None: node = self for c in w: - if c not in node.children: - node.children[c] = Trie() - node = node.children[c] + idx = ord(c) - ord("a") + if node.children[idx] is None: + node.children[idx] = Trie() + node = node.children[idx] node.is_end = True def search(self, w: str) -> bool: - def dfs(i: int, node: Trie, diff: int) -> bool: + def dfs(i: int, node: Optional[Trie], diff: int) -> bool: if i == len(w): return diff == 1 and node.is_end - if w[i] in node.children and dfs(i + 1, node.children[w[i]], diff): + j = ord(w[i]) - ord("a") + if node.children[j] and dfs(i + 1, node.children[j], diff): return True return diff == 0 and any( - dfs(i + 1, node.children[c], 1) for c in node.children if c != w[i] + node.children[k] and dfs(i + 1, node.children[k], 1) + for k in range(26) + if k != j ) return dfs(0, self, 0) @@ -498,67 +502,4 @@ impl MagicDictionary { - - -### Solution 2 - - - -#### Python3 - -```python -class Trie: - __slots__ = ["children", "is_end"] - - def __init__(self): - self.children: [Trie | None] = [None] * 26 - self.is_end = False - - def insert(self, w: str) -> None: - node = self - for c in w: - idx = ord(c) - ord("a") - if node.children[idx] is None: - node.children[idx] = Trie() - node = node.children[idx] - node.is_end = True - - def search(self, w: str) -> bool: - def dfs(i: int, node: [Trie | None], diff: int) -> bool: - if i == len(w): - return diff == 1 and node.is_end - j = ord(w[i]) - ord("a") - if node.children[j] and dfs(i + 1, node.children[j], diff): - return True - return diff == 0 and any( - node.children[k] and dfs(i + 1, node.children[k], 1) - for k in range(26) - if k != j - ) - - return dfs(0, self, 0) - - -class MagicDictionary: - def __init__(self): - self.trie = Trie() - - def buildDict(self, dictionary: List[str]) -> None: - for w in dictionary: - self.trie.insert(w) - - def search(self, searchWord: str) -> bool: - return self.trie.search(searchWord) - - -# Your MagicDictionary object will be instantiated and called as such: -# obj = MagicDictionary() -# obj.buildDict(dictionary) -# param_2 = obj.search(searchWord) -``` - - - - - diff --git a/solution/0600-0699/0676.Implement Magic Dictionary/Solution2.py b/solution/0600-0699/0676.Implement Magic Dictionary/Solution2.py deleted file mode 100644 index b7c9051390d8..000000000000 --- a/solution/0600-0699/0676.Implement Magic Dictionary/Solution2.py +++ /dev/null @@ -1,48 +0,0 @@ -class Trie: - __slots__ = ["children", "is_end"] - - def __init__(self): - self.children: [Trie | None] = [None] * 26 - self.is_end = False - - def insert(self, w: str) -> None: - node = self - for c in w: - idx = ord(c) - ord("a") - if node.children[idx] is None: - node.children[idx] = Trie() - node = node.children[idx] - node.is_end = True - - def search(self, w: str) -> bool: - def dfs(i: int, node: [Trie | None], diff: int) -> bool: - if i == len(w): - return diff == 1 and node.is_end - j = ord(w[i]) - ord("a") - if node.children[j] and dfs(i + 1, node.children[j], diff): - return True - return diff == 0 and any( - node.children[k] and dfs(i + 1, node.children[k], 1) - for k in range(26) - if k != j - ) - - return dfs(0, self, 0) - - -class MagicDictionary: - def __init__(self): - self.trie = Trie() - - def buildDict(self, dictionary: List[str]) -> None: - for w in dictionary: - self.trie.insert(w) - - def search(self, searchWord: str) -> bool: - return self.trie.search(searchWord) - - -# Your MagicDictionary object will be instantiated and called as such: -# obj = MagicDictionary() -# obj.buildDict(dictionary) -# param_2 = obj.search(searchWord) diff --git a/solution/0600-0699/0682.Baseball Game/README.md b/solution/0600-0699/0682.Baseball Game/README.md index 307c7ac21455..a7b233a1ac75 100644 --- a/solution/0600-0699/0682.Baseball Game/README.md +++ b/solution/0600-0699/0682.Baseball Game/README.md @@ -88,7 +88,20 @@ tags: -### 方法一 +### 方法一:栈 + 模拟 + +我们可以使用栈来模拟这个过程。 + +遍历 $\textit{operations}$,对于每个操作: + +- 如果是 `+`,则将栈顶两个元素相加,然后将结果入栈; +- 如果是 `D`,则将栈顶元素的值乘以 2,然后将结果入栈; +- 如果是 `C`,则将栈顶元素出栈; +- 如果是数字,将数字入栈。 + +最后,将栈中的所有元素求和即为答案。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为 $\textit{operations}$ 的长度。 @@ -96,14 +109,14 @@ tags: ```python class Solution: - def calPoints(self, ops: List[str]) -> int: + def calPoints(self, operations: List[str]) -> int: stk = [] - for op in ops: - if op == '+': + for op in operations: + if op == "+": stk.append(stk[-1] + stk[-2]) - elif op == 'D': + elif op == "D": stk.append(stk[-1] << 1) - elif op == 'C': + elif op == "C": stk.pop() else: stk.append(int(op)) @@ -114,9 +127,9 @@ class Solution: ```java class Solution { - public int calPoints(String[] ops) { + public int calPoints(String[] operations) { Deque stk = new ArrayDeque<>(); - for (String op : ops) { + for (String op : operations) { if ("+".equals(op)) { int a = stk.pop(); int b = stk.peek(); @@ -140,20 +153,19 @@ class Solution { ```cpp class Solution { public: - int calPoints(vector& ops) { + int calPoints(vector& operations) { vector stk; - for (auto& op : ops) { + for (auto& op : operations) { int n = stk.size(); if (op == "+") { - int a = stk[n - 1]; - int b = stk[n - 2]; - stk.push_back(a + b); - } else if (op == "D") - stk.push_back(stk[n - 1] * 2); - else if (op == "C") + stk.push_back(stk[n - 1] + stk[n - 2]); + } else if (op == "D") { + stk.push_back(stk[n - 1] << 1); + } else if (op == "C") { stk.pop_back(); - else + } else { stk.push_back(stoi(op)); + } } return accumulate(stk.begin(), stk.end(), 0); } @@ -163,9 +175,9 @@ public: #### Go ```go -func calPoints(ops []string) int { +func calPoints(operations []string) (ans int) { var stk []int - for _, op := range ops { + for _, op := range operations { n := len(stk) switch op { case "+": @@ -179,32 +191,30 @@ func calPoints(ops []string) int { stk = append(stk, num) } } - ans := 0 - for _, score := range stk { - ans += score + for _, x := range stk { + ans += x } - return ans + return } ``` #### TypeScript ```ts -function calPoints(ops: string[]): number { - const stack = []; - for (const op of ops) { - const n = stack.length; +function calPoints(operations: string[]): number { + const stk: number[] = []; + for (const op of operations) { if (op === '+') { - stack.push(stack[n - 1] + stack[n - 2]); + stk.push(stk.at(-1)! + stk.at(-2)!); } else if (op === 'D') { - stack.push(stack[n - 1] * 2); + stk.push(stk.at(-1)! << 1); } else if (op === 'C') { - stack.pop(); + stk.pop(); } else { - stack.push(Number(op)); + stk.push(+op); } } - return stack.reduce((p, v) => p + v); + return stk.reduce((a, b) => a + b, 0); } ``` @@ -212,26 +222,26 @@ function calPoints(ops: string[]): number { ```rust impl Solution { - pub fn cal_points(ops: Vec) -> i32 { - let mut stack = vec![]; - for op in ops { + pub fn cal_points(operations: Vec) -> i32 { + let mut stk = vec![]; + for op in operations { match op.as_str() { "+" => { - let n = stack.len(); - stack.push(stack[n - 1] + stack[n - 2]); + let n = stk.len(); + stk.push(stk[n - 1] + stk[n - 2]); } "D" => { - stack.push(stack.last().unwrap() * 2); + stk.push(stk.last().unwrap() * 2); } "C" => { - stack.pop(); + stk.pop(); } n => { - stack.push(n.parse::().unwrap()); + stk.push(n.parse::().unwrap()); } } } - stack.into_iter().sum() + stk.into_iter().sum() } } ``` diff --git a/solution/0600-0699/0682.Baseball Game/README_EN.md b/solution/0600-0699/0682.Baseball Game/README_EN.md index 2f043c4daa95..4fc0adc33aa2 100644 --- a/solution/0600-0699/0682.Baseball Game/README_EN.md +++ b/solution/0600-0699/0682.Baseball Game/README_EN.md @@ -110,7 +110,20 @@ Since the record is empty, the total sum is 0. -### Solution 1 +### Solution 1: Stack + Simulation + +We can use a stack to simulate this process. + +Traverse $\textit{operations}$, for each operation: + +- If it is `+`, add the top two elements of the stack and push the result onto the stack; +- If it is `D`, multiply the top element of the stack by 2 and push the result onto the stack; +- If it is `C`, pop the top element of the stack; +- If it is a number, push the number onto the stack. + +Finally, sum all the elements in the stack to get the answer. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of $\textit{operations}$. @@ -118,14 +131,14 @@ Since the record is empty, the total sum is 0. ```python class Solution: - def calPoints(self, ops: List[str]) -> int: + def calPoints(self, operations: List[str]) -> int: stk = [] - for op in ops: - if op == '+': + for op in operations: + if op == "+": stk.append(stk[-1] + stk[-2]) - elif op == 'D': + elif op == "D": stk.append(stk[-1] << 1) - elif op == 'C': + elif op == "C": stk.pop() else: stk.append(int(op)) @@ -136,9 +149,9 @@ class Solution: ```java class Solution { - public int calPoints(String[] ops) { + public int calPoints(String[] operations) { Deque stk = new ArrayDeque<>(); - for (String op : ops) { + for (String op : operations) { if ("+".equals(op)) { int a = stk.pop(); int b = stk.peek(); @@ -162,20 +175,19 @@ class Solution { ```cpp class Solution { public: - int calPoints(vector& ops) { + int calPoints(vector& operations) { vector stk; - for (auto& op : ops) { + for (auto& op : operations) { int n = stk.size(); if (op == "+") { - int a = stk[n - 1]; - int b = stk[n - 2]; - stk.push_back(a + b); - } else if (op == "D") - stk.push_back(stk[n - 1] * 2); - else if (op == "C") + stk.push_back(stk[n - 1] + stk[n - 2]); + } else if (op == "D") { + stk.push_back(stk[n - 1] << 1); + } else if (op == "C") { stk.pop_back(); - else + } else { stk.push_back(stoi(op)); + } } return accumulate(stk.begin(), stk.end(), 0); } @@ -185,9 +197,9 @@ public: #### Go ```go -func calPoints(ops []string) int { +func calPoints(operations []string) (ans int) { var stk []int - for _, op := range ops { + for _, op := range operations { n := len(stk) switch op { case "+": @@ -201,32 +213,30 @@ func calPoints(ops []string) int { stk = append(stk, num) } } - ans := 0 - for _, score := range stk { - ans += score + for _, x := range stk { + ans += x } - return ans + return } ``` #### TypeScript ```ts -function calPoints(ops: string[]): number { - const stack = []; - for (const op of ops) { - const n = stack.length; +function calPoints(operations: string[]): number { + const stk: number[] = []; + for (const op of operations) { if (op === '+') { - stack.push(stack[n - 1] + stack[n - 2]); + stk.push(stk.at(-1)! + stk.at(-2)!); } else if (op === 'D') { - stack.push(stack[n - 1] * 2); + stk.push(stk.at(-1)! << 1); } else if (op === 'C') { - stack.pop(); + stk.pop(); } else { - stack.push(Number(op)); + stk.push(+op); } } - return stack.reduce((p, v) => p + v); + return stk.reduce((a, b) => a + b, 0); } ``` @@ -234,26 +244,26 @@ function calPoints(ops: string[]): number { ```rust impl Solution { - pub fn cal_points(ops: Vec) -> i32 { - let mut stack = vec![]; - for op in ops { + pub fn cal_points(operations: Vec) -> i32 { + let mut stk = vec![]; + for op in operations { match op.as_str() { "+" => { - let n = stack.len(); - stack.push(stack[n - 1] + stack[n - 2]); + let n = stk.len(); + stk.push(stk[n - 1] + stk[n - 2]); } "D" => { - stack.push(stack.last().unwrap() * 2); + stk.push(stk.last().unwrap() * 2); } "C" => { - stack.pop(); + stk.pop(); } n => { - stack.push(n.parse::().unwrap()); + stk.push(n.parse::().unwrap()); } } } - stack.into_iter().sum() + stk.into_iter().sum() } } ``` diff --git a/solution/0600-0699/0682.Baseball Game/Solution.cpp b/solution/0600-0699/0682.Baseball Game/Solution.cpp index 94b8acc34385..16c9050e13c0 100644 --- a/solution/0600-0699/0682.Baseball Game/Solution.cpp +++ b/solution/0600-0699/0682.Baseball Game/Solution.cpp @@ -1,19 +1,18 @@ class Solution { public: - int calPoints(vector& ops) { + int calPoints(vector& operations) { vector stk; - for (auto& op : ops) { + for (auto& op : operations) { int n = stk.size(); if (op == "+") { - int a = stk[n - 1]; - int b = stk[n - 2]; - stk.push_back(a + b); - } else if (op == "D") - stk.push_back(stk[n - 1] * 2); - else if (op == "C") + stk.push_back(stk[n - 1] + stk[n - 2]); + } else if (op == "D") { + stk.push_back(stk[n - 1] << 1); + } else if (op == "C") { stk.pop_back(); - else + } else { stk.push_back(stoi(op)); + } } return accumulate(stk.begin(), stk.end(), 0); } diff --git a/solution/0600-0699/0682.Baseball Game/Solution.go b/solution/0600-0699/0682.Baseball Game/Solution.go index 888e86f3f795..d894f2d4e309 100644 --- a/solution/0600-0699/0682.Baseball Game/Solution.go +++ b/solution/0600-0699/0682.Baseball Game/Solution.go @@ -1,6 +1,6 @@ -func calPoints(ops []string) int { +func calPoints(operations []string) (ans int) { var stk []int - for _, op := range ops { + for _, op := range operations { n := len(stk) switch op { case "+": @@ -14,9 +14,8 @@ func calPoints(ops []string) int { stk = append(stk, num) } } - ans := 0 - for _, score := range stk { - ans += score + for _, x := range stk { + ans += x } - return ans + return } \ No newline at end of file diff --git a/solution/0600-0699/0682.Baseball Game/Solution.java b/solution/0600-0699/0682.Baseball Game/Solution.java index 17e0705bdb06..dc31da6f4c1e 100644 --- a/solution/0600-0699/0682.Baseball Game/Solution.java +++ b/solution/0600-0699/0682.Baseball Game/Solution.java @@ -1,7 +1,7 @@ class Solution { - public int calPoints(String[] ops) { + public int calPoints(String[] operations) { Deque stk = new ArrayDeque<>(); - for (String op : ops) { + for (String op : operations) { if ("+".equals(op)) { int a = stk.pop(); int b = stk.peek(); diff --git a/solution/0600-0699/0682.Baseball Game/Solution.py b/solution/0600-0699/0682.Baseball Game/Solution.py index e7d359492799..124ace608b1c 100644 --- a/solution/0600-0699/0682.Baseball Game/Solution.py +++ b/solution/0600-0699/0682.Baseball Game/Solution.py @@ -1,12 +1,12 @@ class Solution: - def calPoints(self, ops: List[str]) -> int: + def calPoints(self, operations: List[str]) -> int: stk = [] - for op in ops: - if op == '+': + for op in operations: + if op == "+": stk.append(stk[-1] + stk[-2]) - elif op == 'D': + elif op == "D": stk.append(stk[-1] << 1) - elif op == 'C': + elif op == "C": stk.pop() else: stk.append(int(op)) diff --git a/solution/0600-0699/0682.Baseball Game/Solution.rs b/solution/0600-0699/0682.Baseball Game/Solution.rs index 66067e6a61c7..1450b3771566 100644 --- a/solution/0600-0699/0682.Baseball Game/Solution.rs +++ b/solution/0600-0699/0682.Baseball Game/Solution.rs @@ -1,23 +1,23 @@ impl Solution { - pub fn cal_points(ops: Vec) -> i32 { - let mut stack = vec![]; - for op in ops { + pub fn cal_points(operations: Vec) -> i32 { + let mut stk = vec![]; + for op in operations { match op.as_str() { "+" => { - let n = stack.len(); - stack.push(stack[n - 1] + stack[n - 2]); + let n = stk.len(); + stk.push(stk[n - 1] + stk[n - 2]); } "D" => { - stack.push(stack.last().unwrap() * 2); + stk.push(stk.last().unwrap() * 2); } "C" => { - stack.pop(); + stk.pop(); } n => { - stack.push(n.parse::().unwrap()); + stk.push(n.parse::().unwrap()); } } } - stack.into_iter().sum() + stk.into_iter().sum() } } diff --git a/solution/0600-0699/0682.Baseball Game/Solution.ts b/solution/0600-0699/0682.Baseball Game/Solution.ts index 64d5e296bfb1..18654da69180 100644 --- a/solution/0600-0699/0682.Baseball Game/Solution.ts +++ b/solution/0600-0699/0682.Baseball Game/Solution.ts @@ -1,16 +1,15 @@ -function calPoints(ops: string[]): number { - const stack = []; - for (const op of ops) { - const n = stack.length; +function calPoints(operations: string[]): number { + const stk: number[] = []; + for (const op of operations) { if (op === '+') { - stack.push(stack[n - 1] + stack[n - 2]); + stk.push(stk.at(-1)! + stk.at(-2)!); } else if (op === 'D') { - stack.push(stack[n - 1] * 2); + stk.push(stk.at(-1)! << 1); } else if (op === 'C') { - stack.pop(); + stk.pop(); } else { - stack.push(Number(op)); + stk.push(+op); } } - return stack.reduce((p, v) => p + v); + return stk.reduce((a, b) => a + b, 0); } diff --git a/solution/0600-0699/0691.Stickers to Spell Word/README.md b/solution/0600-0699/0691.Stickers to Spell Word/README.md index ba583ec999ee..dde145678425 100644 --- a/solution/0600-0699/0691.Stickers to Spell Word/README.md +++ b/solution/0600-0699/0691.Stickers to Spell Word/README.md @@ -69,11 +69,11 @@ tags: ### 方法一:BFS + 状态压缩 -我们注意到,字符串 $\text{target}$ 的长度不超过 $15$,我们可以使用一个长度为 $15$ 的二进制数来表示 $\text{target}$ 的每个字符是否被拼出,如果第 $i$ 位为 $1$,表示 $\text{target}$ 的第 $i$ 个字符已经被拼出,否则表示未被拼出。 +我们注意到,字符串 $\textit{target}$ 的长度不超过 $15$,我们可以使用一个长度为 $15$ 的二进制数来表示 $\textit{target}$ 的每个字符是否被拼出,如果第 $i$ 位为 $1$,表示 $\textit{target}$ 的第 $i$ 个字符已经被拼出,否则表示未被拼出。 -我们定义一个初始状态 $0$,表示所有字符都未被拼出,然后我们使用广度优先搜索的方法,从初始状态开始,每次搜索时,我们枚举所有的贴纸,对于每一张贴纸,我们尝试拼出 $\text{target}$ 的每一个字符,如果拼出了某个字符,我们就将对应的二进制数的第 $i$ 位设置为 $1$,表示该字符已经被拼出,然后我们继续搜索,直到我们拼出了 $\text{target}$ 的所有字符。 +我们定义一个初始状态 $0$,表示所有字符都未被拼出,然后我们使用广度优先搜索的方法,从初始状态开始,每次搜索时,我们枚举所有的贴纸,对于每一张贴纸,我们尝试拼出 $\textit{target}$ 的每一个字符,如果拼出了某个字符,我们就将对应的二进制数的第 $i$ 位设置为 $1$,表示该字符已经被拼出,然后我们继续搜索,直到我们拼出了 $\textit{target}$ 的所有字符。 -时间复杂度 $O(2^n \times m \times (l + n))$,空间复杂度 $O(2^n)$。其中 $n$ 是字符串 $\text{target}$ 的长度,而 $m$ 和 $l$ 分别是贴纸的数量和贴纸的平均长度。 +时间复杂度 $O(2^n \times m \times (l + n))$,空间复杂度 $O(2^n)$。其中 $n$ 是字符串 $\textit{target}$ 的长度,而 $m$ 和 $l$ 分别是贴纸的数量和贴纸的平均长度。 diff --git a/solution/0600-0699/0699.Falling Squares/README.md b/solution/0600-0699/0699.Falling Squares/README.md index b8fbd264d825..717b00ceb94e 100644 --- a/solution/0600-0699/0699.Falling Squares/README.md +++ b/solution/0600-0699/0699.Falling Squares/README.md @@ -72,12 +72,14 @@ tags: ### 方法一:线段树 -线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $log(width)$。更新某个元素的值,只需要更新 $log(width)$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用**懒标记**保证效率。 +根据题目描述,我们需要维护一个区间集合,支持区间的修改和查询操作。这种情况下,我们可以使用线段树来解决。 + +线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $\log(width)$,其中 $width$ 是区间的长度。更新某个元素的值,只需要更新 $\log(width)$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用**懒标记**保证效率。 - 线段树的每个节点代表一个区间; -- 线段树具有唯一的根节点,代表的区间是整个统计范围,如 $[1, N]$; +- 线段树具有唯一的根节点,代表的区间是整个统计范围,如 $[1, n]$; - 线段树的每个叶子节点代表一个长度为 1 的元区间 $[x, x]$; -- 对于每个内部节点 $[l, r]$,它的左儿子是 $[l, mid]$,右儿子是 $[mid + 1, r]$, 其中 $mid = ⌊(l + r) / 2⌋$ (即向下取整)。 +- 对于每个内部节点 $[l, r]$,它的左儿子是 $[l, mid]$,右儿子是 $[mid + 1, r]$, 其中 $\textit{mid} = \frac{l + r}{2}$; 对于本题,线段树节点维护的信息有: @@ -86,6 +88,8 @@ tags: 另外,由于数轴范围很大,达到 $10^8$,因此我们采用动态开点。 +时间复杂度方面,每次查询和修改的时间复杂度为 $O(\log n)$,总时间复杂度为 $O(n \log n)$。空间复杂度为 $O(n)$。 + #### Python3 @@ -388,7 +392,7 @@ func newNode(l, r int) *node { return &node{ l: l, r: r, - mid: int(uint(l+r) >> 1), + mid: (l + r) >> 1, } } @@ -474,6 +478,111 @@ func fallingSquares(positions [][]int) []int { } ``` +#### TypeScript + +```ts +class Node { + left: Node | null = null; + right: Node | null = null; + l: number; + r: number; + mid: number; + v: number = 0; + add: number = 0; + + constructor(l: number, r: number) { + this.l = l; + this.r = r; + this.mid = (l + r) >> 1; + } +} + +class SegmentTree { + private root: Node = new Node(1, 1e9); + + public modify(l: number, r: number, v: number): void { + this.modifyNode(l, r, v, this.root); + } + + private modifyNode(l: number, r: number, v: number, node: Node): void { + if (l > r) { + return; + } + if (node.l >= l && node.r <= r) { + node.v = v; + node.add = v; + return; + } + this.pushdown(node); + if (l <= node.mid) { + this.modifyNode(l, r, v, node.left!); + } + if (r > node.mid) { + this.modifyNode(l, r, v, node.right!); + } + this.pushup(node); + } + + public query(l: number, r: number): number { + return this.queryNode(l, r, this.root); + } + + private queryNode(l: number, r: number, node: Node): number { + if (l > r) { + return 0; + } + if (node.l >= l && node.r <= r) { + return node.v; + } + this.pushdown(node); + let v = 0; + if (l <= node.mid) { + v = Math.max(v, this.queryNode(l, r, node.left!)); + } + if (r > node.mid) { + v = Math.max(v, this.queryNode(l, r, node.right!)); + } + return v; + } + + private pushup(node: Node): void { + node.v = Math.max(node.left!.v, node.right!.v); + } + + private pushdown(node: Node): void { + if (node.left == null) { + node.left = new Node(node.l, node.mid); + } + if (node.right == null) { + node.right = new Node(node.mid + 1, node.r); + } + if (node.add != 0) { + let left = node.left, + right = node.right; + left!.add = node.add; + right!.add = node.add; + left!.v = node.add; + right!.v = node.add; + node.add = 0; + } + } +} + +function fallingSquares(positions: number[][]): number[] { + const ans: number[] = []; + const tree = new SegmentTree(); + let mx = 0; + for (const [l, w] of positions) { + const r = l + w - 1; + const h = tree.query(l, r) + w; + mx = Math.max(mx, h); + ans.push(mx); + tree.modify(l, r, h); + } + return ans; +} +``` + diff --git a/solution/0600-0699/0699.Falling Squares/README_EN.md b/solution/0600-0699/0699.Falling Squares/README_EN.md index a53d60a7a7b2..7f96d9c31475 100644 --- a/solution/0600-0699/0699.Falling Squares/README_EN.md +++ b/solution/0600-0699/0699.Falling Squares/README_EN.md @@ -68,7 +68,25 @@ Note that square 2 only brushes the right side of square 1, which does not count -### Solution 1 +### Solution 1: Segment Tree + +According to the problem description, we need to maintain a set of intervals that support modification and query operations. In this case, we can use a segment tree to solve the problem. + +A segment tree divides the entire interval into multiple non-contiguous sub-intervals, with the number of sub-intervals not exceeding $\log(width)$, where $width$ is the length of the interval. To update the value of an element, we only need to update $\log(width)$ intervals, and these intervals are all contained within a larger interval that includes the element. When modifying intervals, we need to use **lazy propagation** to ensure efficiency. + +- Each node of the segment tree represents an interval; +- The segment tree has a unique root node representing the entire statistical range, such as $[1, n]$; +- Each leaf node of the segment tree represents a primitive interval of length 1, $[x, x]$; +- For each internal node $[l, r]$, its left child is $[l, \textit{mid}]$, and its right child is $[\textit{mid} + 1, r]$, where $\textit{mid} = \frac{l + r}{2}$; + +For this problem, the information maintained by the segment tree nodes includes: + +1. The maximum height $v$ of the blocks in the interval +2. Lazy propagation marker $add$ + +Additionally, since the range of the number line is very large, up to $10^8$, we use dynamic node creation. + +In terms of time complexity, each query and modification has a time complexity of $O(\log n)$, and the total time complexity is $O(n \log n)$. The space complexity is $O(n)$. @@ -372,7 +390,7 @@ func newNode(l, r int) *node { return &node{ l: l, r: r, - mid: int(uint(l+r) >> 1), + mid: (l + r) >> 1, } } @@ -458,6 +476,111 @@ func fallingSquares(positions [][]int) []int { } ``` +#### TypeScript + +```ts +class Node { + left: Node | null = null; + right: Node | null = null; + l: number; + r: number; + mid: number; + v: number = 0; + add: number = 0; + + constructor(l: number, r: number) { + this.l = l; + this.r = r; + this.mid = (l + r) >> 1; + } +} + +class SegmentTree { + private root: Node = new Node(1, 1e9); + + public modify(l: number, r: number, v: number): void { + this.modifyNode(l, r, v, this.root); + } + + private modifyNode(l: number, r: number, v: number, node: Node): void { + if (l > r) { + return; + } + if (node.l >= l && node.r <= r) { + node.v = v; + node.add = v; + return; + } + this.pushdown(node); + if (l <= node.mid) { + this.modifyNode(l, r, v, node.left!); + } + if (r > node.mid) { + this.modifyNode(l, r, v, node.right!); + } + this.pushup(node); + } + + public query(l: number, r: number): number { + return this.queryNode(l, r, this.root); + } + + private queryNode(l: number, r: number, node: Node): number { + if (l > r) { + return 0; + } + if (node.l >= l && node.r <= r) { + return node.v; + } + this.pushdown(node); + let v = 0; + if (l <= node.mid) { + v = Math.max(v, this.queryNode(l, r, node.left!)); + } + if (r > node.mid) { + v = Math.max(v, this.queryNode(l, r, node.right!)); + } + return v; + } + + private pushup(node: Node): void { + node.v = Math.max(node.left!.v, node.right!.v); + } + + private pushdown(node: Node): void { + if (node.left == null) { + node.left = new Node(node.l, node.mid); + } + if (node.right == null) { + node.right = new Node(node.mid + 1, node.r); + } + if (node.add != 0) { + let left = node.left, + right = node.right; + left!.add = node.add; + right!.add = node.add; + left!.v = node.add; + right!.v = node.add; + node.add = 0; + } + } +} + +function fallingSquares(positions: number[][]): number[] { + const ans: number[] = []; + const tree = new SegmentTree(); + let mx = 0; + for (const [l, w] of positions) { + const r = l + w - 1; + const h = tree.query(l, r) + w; + mx = Math.max(mx, h); + ans.push(mx); + tree.modify(l, r, h); + } + return ans; +} +``` + diff --git a/solution/0600-0699/0699.Falling Squares/Solution.go b/solution/0600-0699/0699.Falling Squares/Solution.go index 39d06c2c0390..7c5c40617bfa 100644 --- a/solution/0600-0699/0699.Falling Squares/Solution.go +++ b/solution/0600-0699/0699.Falling Squares/Solution.go @@ -9,7 +9,7 @@ func newNode(l, r int) *node { return &node{ l: l, r: r, - mid: int(uint(l+r) >> 1), + mid: (l + r) >> 1, } } diff --git a/solution/0600-0699/0699.Falling Squares/Solution.ts b/solution/0600-0699/0699.Falling Squares/Solution.ts new file mode 100644 index 000000000000..9b399cc96660 --- /dev/null +++ b/solution/0600-0699/0699.Falling Squares/Solution.ts @@ -0,0 +1,100 @@ +class Node { + left: Node | null = null; + right: Node | null = null; + l: number; + r: number; + mid: number; + v: number = 0; + add: number = 0; + + constructor(l: number, r: number) { + this.l = l; + this.r = r; + this.mid = (l + r) >> 1; + } +} + +class SegmentTree { + private root: Node = new Node(1, 1e9); + + public modify(l: number, r: number, v: number): void { + this.modifyNode(l, r, v, this.root); + } + + private modifyNode(l: number, r: number, v: number, node: Node): void { + if (l > r) { + return; + } + if (node.l >= l && node.r <= r) { + node.v = v; + node.add = v; + return; + } + this.pushdown(node); + if (l <= node.mid) { + this.modifyNode(l, r, v, node.left!); + } + if (r > node.mid) { + this.modifyNode(l, r, v, node.right!); + } + this.pushup(node); + } + + public query(l: number, r: number): number { + return this.queryNode(l, r, this.root); + } + + private queryNode(l: number, r: number, node: Node): number { + if (l > r) { + return 0; + } + if (node.l >= l && node.r <= r) { + return node.v; + } + this.pushdown(node); + let v = 0; + if (l <= node.mid) { + v = Math.max(v, this.queryNode(l, r, node.left!)); + } + if (r > node.mid) { + v = Math.max(v, this.queryNode(l, r, node.right!)); + } + return v; + } + + private pushup(node: Node): void { + node.v = Math.max(node.left!.v, node.right!.v); + } + + private pushdown(node: Node): void { + if (node.left == null) { + node.left = new Node(node.l, node.mid); + } + if (node.right == null) { + node.right = new Node(node.mid + 1, node.r); + } + if (node.add != 0) { + let left = node.left, + right = node.right; + left!.add = node.add; + right!.add = node.add; + left!.v = node.add; + right!.v = node.add; + node.add = 0; + } + } +} + +function fallingSquares(positions: number[][]): number[] { + const ans: number[] = []; + const tree = new SegmentTree(); + let mx = 0; + for (const [l, w] of positions) { + const r = l + w - 1; + const h = tree.query(l, r) + w; + mx = Math.max(mx, h); + ans.push(mx); + tree.modify(l, r, h); + } + return ans; +} diff --git a/solution/0700-0799/0700.Search in a Binary Search Tree/README.md b/solution/0700-0799/0700.Search in a Binary Search Tree/README.md index 958511ec505d..13521493f3c9 100644 --- a/solution/0700-0799/0700.Search in a Binary Search Tree/README.md +++ b/solution/0700-0799/0700.Search in a Binary Search Tree/README.md @@ -57,7 +57,13 @@ tags: -### 方法一 +### 方法一:递归 + +我们判断当前节点是否为空或者当前节点的值是否等于目标值,如果是则返回当前节点。 + +否则,如果当前节点的值大于目标值,则递归搜索左子树,否则递归搜索右子树。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。 @@ -71,13 +77,13 @@ tags: # self.left = left # self.right = right class Solution: - def searchBST(self, root: TreeNode, val: int) -> TreeNode: + def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: if root is None or root.val == val: return root return ( - self.searchBST(root.right, val) - if root.val < val - else self.searchBST(root.left, val) + self.searchBST(root.left, val) + if root.val > val + else self.searchBST(root.right, val) ) ``` @@ -104,7 +110,7 @@ class Solution { if (root == null || root.val == val) { return root; } - return root.val < val ? searchBST(root.right, val) : searchBST(root.left, val); + return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val); } } ``` @@ -126,8 +132,10 @@ class Solution { class Solution { public: TreeNode* searchBST(TreeNode* root, int val) { - if (!root || root->val == val) return root; - return root->val < val ? searchBST(root->right, val) : searchBST(root->left, val); + if (!root || root->val == val) { + return root; + } + return root->val > val ? searchBST(root->left, val) : searchBST(root->right, val); } }; ``` @@ -143,14 +151,39 @@ public: * Right *TreeNode * } */ -func searchBST(root *TreeNode, val int) *TreeNode { - if root == nil || root.Val == val { - return root - } - if root.Val < val { - return searchBST(root.Right, val) - } - return searchBST(root.Left, val) + func searchBST(root *TreeNode, val int) *TreeNode { + if root == nil || root.Val == val { + return root + } + if root.Val > val { + return searchBST(root.Left, val) + } + return searchBST(root.Right, val) +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function searchBST(root: TreeNode | null, val: number): TreeNode | null { + if (root === null || root.val === val) { + return root; + } + return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val); } ``` diff --git a/solution/0700-0799/0700.Search in a Binary Search Tree/README_EN.md b/solution/0700-0799/0700.Search in a Binary Search Tree/README_EN.md index fb6fa50215c7..049b717c531f 100644 --- a/solution/0700-0799/0700.Search in a Binary Search Tree/README_EN.md +++ b/solution/0700-0799/0700.Search in a Binary Search Tree/README_EN.md @@ -53,7 +53,13 @@ tags: -### Solution 1 +### Solution 1: Recursion + +We check if the current node is null or if the current node's value equals the target value. If so, we return the current node. + +Otherwise, if the current node's value is greater than the target value, we recursively search the left subtree; otherwise, we recursively search the right subtree. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -67,13 +73,13 @@ tags: # self.left = left # self.right = right class Solution: - def searchBST(self, root: TreeNode, val: int) -> TreeNode: + def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: if root is None or root.val == val: return root return ( - self.searchBST(root.right, val) - if root.val < val - else self.searchBST(root.left, val) + self.searchBST(root.left, val) + if root.val > val + else self.searchBST(root.right, val) ) ``` @@ -100,7 +106,7 @@ class Solution { if (root == null || root.val == val) { return root; } - return root.val < val ? searchBST(root.right, val) : searchBST(root.left, val); + return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val); } } ``` @@ -122,8 +128,10 @@ class Solution { class Solution { public: TreeNode* searchBST(TreeNode* root, int val) { - if (!root || root->val == val) return root; - return root->val < val ? searchBST(root->right, val) : searchBST(root->left, val); + if (!root || root->val == val) { + return root; + } + return root->val > val ? searchBST(root->left, val) : searchBST(root->right, val); } }; ``` @@ -139,14 +147,39 @@ public: * Right *TreeNode * } */ -func searchBST(root *TreeNode, val int) *TreeNode { - if root == nil || root.Val == val { - return root - } - if root.Val < val { - return searchBST(root.Right, val) - } - return searchBST(root.Left, val) + func searchBST(root *TreeNode, val int) *TreeNode { + if root == nil || root.Val == val { + return root + } + if root.Val > val { + return searchBST(root.Left, val) + } + return searchBST(root.Right, val) +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function searchBST(root: TreeNode | null, val: number): TreeNode | null { + if (root === null || root.val === val) { + return root; + } + return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val); } ``` diff --git a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.cpp b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.cpp index 2c3786830adb..ec18024c4f57 100644 --- a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.cpp +++ b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.cpp @@ -12,7 +12,9 @@ class Solution { public: TreeNode* searchBST(TreeNode* root, int val) { - if (!root || root->val == val) return root; - return root->val < val ? searchBST(root->right, val) : searchBST(root->left, val); + if (!root || root->val == val) { + return root; + } + return root->val > val ? searchBST(root->left, val) : searchBST(root->right, val); } }; \ No newline at end of file diff --git a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.go b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.go index 4ec2b8988d96..34e342c08b15 100644 --- a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.go +++ b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.go @@ -6,12 +6,12 @@ * Right *TreeNode * } */ -func searchBST(root *TreeNode, val int) *TreeNode { - if root == nil || root.Val == val { - return root - } - if root.Val < val { - return searchBST(root.Right, val) - } - return searchBST(root.Left, val) + func searchBST(root *TreeNode, val int) *TreeNode { + if root == nil || root.Val == val { + return root + } + if root.Val > val { + return searchBST(root.Left, val) + } + return searchBST(root.Right, val) } \ No newline at end of file diff --git a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.java b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.java index 409bc8c052cf..dc4c04e43792 100644 --- a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.java +++ b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.java @@ -18,6 +18,6 @@ public TreeNode searchBST(TreeNode root, int val) { if (root == null || root.val == val) { return root; } - return root.val < val ? searchBST(root.right, val) : searchBST(root.left, val); + return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val); } } \ No newline at end of file diff --git a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.py b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.py index 9c20585abdc3..065a0025c62e 100644 --- a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.py +++ b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.py @@ -5,11 +5,11 @@ # self.left = left # self.right = right class Solution: - def searchBST(self, root: TreeNode, val: int) -> TreeNode: + def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: if root is None or root.val == val: return root return ( - self.searchBST(root.right, val) - if root.val < val - else self.searchBST(root.left, val) + self.searchBST(root.left, val) + if root.val > val + else self.searchBST(root.right, val) ) diff --git a/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.ts b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.ts new file mode 100644 index 000000000000..3be1e9eda77c --- /dev/null +++ b/solution/0700-0799/0700.Search in a Binary Search Tree/Solution.ts @@ -0,0 +1,20 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function searchBST(root: TreeNode | null, val: number): TreeNode | null { + if (root === null || root.val === val) { + return root; + } + return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val); +} diff --git a/solution/0700-0799/0701.Insert into a Binary Search Tree/README.md b/solution/0700-0799/0701.Insert into a Binary Search Tree/README.md index 0a970d21826e..2d395f9605ec 100644 --- a/solution/0700-0799/0701.Insert into a Binary Search Tree/README.md +++ b/solution/0700-0799/0701.Insert into a Binary Search Tree/README.md @@ -65,7 +65,15 @@ tags: -### 方法一 +### 方法一:递归 + +如果根节点为空,我们直接创建一个新节点,值为 $\textit{val}$,并返回。 + +如果根节点的值大于 $\textit{val}$,我们递归地将 $\textit{val}$ 插入到左子树中,并将左子树的根节点更新为返回后的根节点。 + +如果根节点的值小于 $\textit{val}$,我们递归地将 $\textit{val}$ 插入到右子树中,并将右子树的根节点更新为返回后的根节点。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。 @@ -79,17 +87,14 @@ tags: # self.left = left # self.right = right class Solution: - def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: - def dfs(root): - if root is None: - return TreeNode(val) - if root.val < val: - root.right = dfs(root.right) - else: - root.left = dfs(root.left) - return root - - return dfs(root) + def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: + if root is None: + return TreeNode(val) + if root.val > val: + root.left = self.insertIntoBST(root.left, val) + else: + root.right = self.insertIntoBST(root.right, val) + return root ``` #### Java @@ -111,15 +116,14 @@ class Solution: * } */ class Solution { - public TreeNode insertIntoBST(TreeNode root, int val) { if (root == null) { return new TreeNode(val); } - if (root.val < val) { - root.right = insertIntoBST(root.right, val); - } else { + if (root.val > val) { root.left = insertIntoBST(root.left, val); + } else { + root.right = insertIntoBST(root.right, val); } return root; } @@ -143,11 +147,14 @@ class Solution { class Solution { public: TreeNode* insertIntoBST(TreeNode* root, int val) { - if (!root) return new TreeNode(val); - if (root->val < val) - root->right = insertIntoBST(root->right, val); - else + if (!root) { + return new TreeNode(val); + } + if (root->val > val) { root->left = insertIntoBST(root->left, val); + } else { + root->right = insertIntoBST(root->right, val); + } return root; } }; @@ -168,10 +175,10 @@ func insertIntoBST(root *TreeNode, val int) *TreeNode { if root == nil { return &TreeNode{Val: val} } - if root.Val < val { - root.Right = insertIntoBST(root.Right, val) - } else { + if root.Val > val { root.Left = insertIntoBST(root.Left, val) + } else { + root.Right = insertIntoBST(root.Right, val) } return root } @@ -195,11 +202,14 @@ func insertIntoBST(root *TreeNode, val int) *TreeNode { */ function insertIntoBST(root: TreeNode | null, val: number): TreeNode | null { - if (!root) return new TreeNode(val); - - if (val < root.val) root.left = insertIntoBST(root.left, val); - else root.right = insertIntoBST(root.right, val); - + if (!root) { + return new TreeNode(val); + } + if (root.val > val) { + root.left = insertIntoBST(root.left, val); + } else { + root.right = insertIntoBST(root.right, val); + } return root; } ``` diff --git a/solution/0700-0799/0701.Insert into a Binary Search Tree/README_EN.md b/solution/0700-0799/0701.Insert into a Binary Search Tree/README_EN.md index 107ad4ecc1af..79547b0563dd 100644 --- a/solution/0700-0799/0701.Insert into a Binary Search Tree/README_EN.md +++ b/solution/0700-0799/0701.Insert into a Binary Search Tree/README_EN.md @@ -63,7 +63,15 @@ tags: -### Solution 1 +### Solution 1: Recursion + +If the root node is null, we directly create a new node with the value $\textit{val}$ and return it. + +If the root node's value is greater than $\textit{val}$, we recursively insert $\textit{val}$ into the left subtree and update the root of the left subtree with the returned root node. + +If the root node's value is less than $\textit{val}$, we recursively insert $\textit{val}$ into the right subtree and update the root of the right subtree with the returned root node. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -77,17 +85,14 @@ tags: # self.left = left # self.right = right class Solution: - def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: - def dfs(root): - if root is None: - return TreeNode(val) - if root.val < val: - root.right = dfs(root.right) - else: - root.left = dfs(root.left) - return root - - return dfs(root) + def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: + if root is None: + return TreeNode(val) + if root.val > val: + root.left = self.insertIntoBST(root.left, val) + else: + root.right = self.insertIntoBST(root.right, val) + return root ``` #### Java @@ -109,15 +114,14 @@ class Solution: * } */ class Solution { - public TreeNode insertIntoBST(TreeNode root, int val) { if (root == null) { return new TreeNode(val); } - if (root.val < val) { - root.right = insertIntoBST(root.right, val); - } else { + if (root.val > val) { root.left = insertIntoBST(root.left, val); + } else { + root.right = insertIntoBST(root.right, val); } return root; } @@ -141,11 +145,14 @@ class Solution { class Solution { public: TreeNode* insertIntoBST(TreeNode* root, int val) { - if (!root) return new TreeNode(val); - if (root->val < val) - root->right = insertIntoBST(root->right, val); - else + if (!root) { + return new TreeNode(val); + } + if (root->val > val) { root->left = insertIntoBST(root->left, val); + } else { + root->right = insertIntoBST(root->right, val); + } return root; } }; @@ -166,10 +173,10 @@ func insertIntoBST(root *TreeNode, val int) *TreeNode { if root == nil { return &TreeNode{Val: val} } - if root.Val < val { - root.Right = insertIntoBST(root.Right, val) - } else { + if root.Val > val { root.Left = insertIntoBST(root.Left, val) + } else { + root.Right = insertIntoBST(root.Right, val) } return root } @@ -193,11 +200,14 @@ func insertIntoBST(root *TreeNode, val int) *TreeNode { */ function insertIntoBST(root: TreeNode | null, val: number): TreeNode | null { - if (!root) return new TreeNode(val); - - if (val < root.val) root.left = insertIntoBST(root.left, val); - else root.right = insertIntoBST(root.right, val); - + if (!root) { + return new TreeNode(val); + } + if (root.val > val) { + root.left = insertIntoBST(root.left, val); + } else { + root.right = insertIntoBST(root.right, val); + } return root; } ``` diff --git a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.cpp b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.cpp index ea17aff06573..0cc792fd3971 100644 --- a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.cpp +++ b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.cpp @@ -12,11 +12,14 @@ class Solution { public: TreeNode* insertIntoBST(TreeNode* root, int val) { - if (!root) return new TreeNode(val); - if (root->val < val) - root->right = insertIntoBST(root->right, val); - else + if (!root) { + return new TreeNode(val); + } + if (root->val > val) { root->left = insertIntoBST(root->left, val); + } else { + root->right = insertIntoBST(root->right, val); + } return root; } }; \ No newline at end of file diff --git a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.go b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.go index 8091ce51921a..8ca9a7e14923 100644 --- a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.go +++ b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.go @@ -10,10 +10,10 @@ func insertIntoBST(root *TreeNode, val int) *TreeNode { if root == nil { return &TreeNode{Val: val} } - if root.Val < val { - root.Right = insertIntoBST(root.Right, val) - } else { + if root.Val > val { root.Left = insertIntoBST(root.Left, val) + } else { + root.Right = insertIntoBST(root.Right, val) } return root } \ No newline at end of file diff --git a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.java b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.java index ce930076c394..233875d33bb8 100644 --- a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.java +++ b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.java @@ -14,15 +14,14 @@ * } */ class Solution { - public TreeNode insertIntoBST(TreeNode root, int val) { if (root == null) { return new TreeNode(val); } - if (root.val < val) { - root.right = insertIntoBST(root.right, val); - } else { + if (root.val > val) { root.left = insertIntoBST(root.left, val); + } else { + root.right = insertIntoBST(root.right, val); } return root; } diff --git a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.py b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.py index 2198fa541c57..7a9a5e9c2545 100644 --- a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.py +++ b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.py @@ -5,14 +5,11 @@ # self.left = left # self.right = right class Solution: - def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: - def dfs(root): - if root is None: - return TreeNode(val) - if root.val < val: - root.right = dfs(root.right) - else: - root.left = dfs(root.left) - return root - - return dfs(root) + def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: + if root is None: + return TreeNode(val) + if root.val > val: + root.left = self.insertIntoBST(root.left, val) + else: + root.right = self.insertIntoBST(root.right, val) + return root diff --git a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.ts b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.ts index 531f58a99bc7..e32722ba2d95 100644 --- a/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.ts +++ b/solution/0700-0799/0701.Insert into a Binary Search Tree/Solution.ts @@ -13,10 +13,13 @@ */ function insertIntoBST(root: TreeNode | null, val: number): TreeNode | null { - if (!root) return new TreeNode(val); - - if (val < root.val) root.left = insertIntoBST(root.left, val); - else root.right = insertIntoBST(root.right, val); - + if (!root) { + return new TreeNode(val); + } + if (root.val > val) { + root.left = insertIntoBST(root.left, val); + } else { + root.right = insertIntoBST(root.right, val); + } return root; } diff --git a/solution/0700-0799/0704.Binary Search/README.md b/solution/0700-0799/0704.Binary Search/README.md index 15b289eaf7ef..293c01438e03 100644 --- a/solution/0700-0799/0704.Binary Search/README.md +++ b/solution/0700-0799/0704.Binary Search/README.md @@ -54,14 +54,14 @@ tags: 我们定义二分查找的左边界 $l=0$,右边界 $r=n-1$。 -每一次循环,我们计算中间位置 $\text{mid}=(l+r)/2$,然后比较 $\text{nums}[\text{mid}]$ 和 $\text{target}$ 的大小。 +每一次循环,我们计算中间位置 $\textit{mid}=(l+r)/2$,然后比较 $\textit{nums}[\textit{mid}]$ 和 $\textit{target}$ 的大小。 -- 如果 $\text{nums}[\text{mid}] \geq \text{target}$,说明 $\text{target}$ 在左半部分,我们将右边界 $r$ 移动到 $\text{mid}$; -- 否则,说明 $\text{target}$ 在右半部分,我们将左边界 $l$ 移动到 $\text{mid}+1$。 +- 如果 $\textit{nums}[\textit{mid}] \geq \textit{target}$,说明 $\textit{target}$ 在左半部分,我们将右边界 $r$ 移动到 $\textit{mid}$; +- 否则,说明 $\textit{target}$ 在右半部分,我们将左边界 $l$ 移动到 $\textit{mid}+1$。 -循环结束的条件是 $l diff --git a/solution/0700-0799/0704.Binary Search/README_EN.md b/solution/0700-0799/0704.Binary Search/README_EN.md index 1fa800eee3eb..316ff5daa8a2 100644 --- a/solution/0700-0799/0704.Binary Search/README_EN.md +++ b/solution/0700-0799/0704.Binary Search/README_EN.md @@ -58,14 +58,14 @@ tags: We define the left boundary $l=0$ and the right boundary $r=n-1$ for binary search. -In each iteration, we calculate the middle position $\text{mid}=(l+r)/2$, then compare the size of $\text{nums}[\text{mid}]$ and $\text{target}$. +In each iteration, we calculate the middle position $\textit{mid}=(l+r)/2$, then compare the size of $\textit{nums}[\textit{mid}]$ and $\textit{target}$. -- If $\text{nums}[\text{mid}] \geq \text{target}$, it means $\text{target}$ is in the left half, so we move the right boundary $r$ to $\text{mid}$; -- Otherwise, it means $\text{target}$ is in the right half, so we move the left boundary $l$ to $\text{mid}+1$. +- If $\textit{nums}[\textit{mid}] \geq \textit{target}$, it means $\textit{target}$ is in the left half, so we move the right boundary $r$ to $\textit{mid}$; +- Otherwise, it means $\textit{target}$ is in the right half, so we move the left boundary $l$ to $\textit{mid}+1$. -The loop ends when $l diff --git a/solution/0700-0799/0713.Subarray Product Less Than K/README.md b/solution/0700-0799/0713.Subarray Product Less Than K/README.md index fae69af2d105..9a3a24ce5353 100644 --- a/solution/0700-0799/0713.Subarray Product Less Than K/README.md +++ b/solution/0700-0799/0713.Subarray Product Less Than K/README.md @@ -26,7 +26,7 @@ tags:
     输入:nums = [10,5,2,6], k = 100
     输出:8
    -解释:8 个乘积小于 100 的子数组分别为:[10]、[5]、[2],、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。
    +解释:8 个乘积小于 100 的子数组分别为:[10]、[5]、[2]、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。
     需要注意的是 [10,5,2] 并不是乘积小于 100 的子数组。
     
    diff --git a/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README.md b/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README.md index 67b38127c0a8..a077238b27a8 100644 --- a/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README.md +++ b/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README.md @@ -226,6 +226,43 @@ function smallestDistancePair(nums: number[], k: number): number { } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +function smallestDistancePair(nums, k) { + nums.sort((a, b) => a - b); + const n = nums.length; + let left = 0, + right = nums[n - 1] - nums[0]; + + while (left < right) { + const mid = (left + right) >> 1; + let count = 0, + i = 0; + + for (let j = 0; j < n; j++) { + while (nums[j] - nums[i] > mid) { + i++; + } + count += j - i; + } + + if (count >= k) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; +} +``` + diff --git a/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README_EN.md b/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README_EN.md index d09dbe355c36..b4bcb86be3b0 100644 --- a/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README_EN.md +++ b/solution/0700-0799/0719.Find K-th Smallest Pair Distance/README_EN.md @@ -220,6 +220,43 @@ function smallestDistancePair(nums: number[], k: number): number { } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +function smallestDistancePair(nums, k) { + nums.sort((a, b) => a - b); + const n = nums.length; + let left = 0, + right = nums[n - 1] - nums[0]; + + while (left < right) { + const mid = (left + right) >> 1; + let count = 0, + i = 0; + + for (let j = 0; j < n; j++) { + while (nums[j] - nums[i] > mid) { + i++; + } + count += j - i; + } + + if (count >= k) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; +} +``` + diff --git a/solution/0700-0799/0719.Find K-th Smallest Pair Distance/Solution.js b/solution/0700-0799/0719.Find K-th Smallest Pair Distance/Solution.js new file mode 100644 index 000000000000..e9a48c161779 --- /dev/null +++ b/solution/0700-0799/0719.Find K-th Smallest Pair Distance/Solution.js @@ -0,0 +1,32 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +function smallestDistancePair(nums, k) { + nums.sort((a, b) => a - b); + const n = nums.length; + let left = 0, + right = nums[n - 1] - nums[0]; + + while (left < right) { + const mid = (left + right) >> 1; + let count = 0, + i = 0; + + for (let j = 0; j < n; j++) { + while (nums[j] - nums[i] > mid) { + i++; + } + count += j - i; + } + + if (count >= k) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; +} diff --git a/solution/0700-0799/0721.Accounts Merge/README.md b/solution/0700-0799/0721.Accounts Merge/README.md index 973a93b4613b..42c836d47d68 100644 --- a/solution/0700-0799/0721.Accounts Merge/README.md +++ b/solution/0700-0799/0721.Accounts Merge/README.md @@ -67,145 +67,355 @@ tags: -### 方法一 +### 方法一:并查集 + 哈希表 + +根据题目描述,我们可以使用并查集,将具有相同邮箱地址的账户合并在一起。 + +我们首先遍历所有的账户,对于第 $i$ 个账户,我们遍历其所有的邮箱地址,如果该邮箱地址在哈希表 $\textit{d}$ 中出现过,则使用并查集,将该账户的编号 $i$ 与之前出现过的邮箱地址所属的账户编号进行合并;否则,将该邮箱地址与账户的编号 $i$ 进行映射。 + +接下来,我们遍历所有的账户,对于第 $i$ 个账户,我们使用并查集找到其根节点,然后将该账户的所有邮箱地址添加到哈希表 $\textit{g}$ 中,其中键为根节点,值为该账户的所有邮箱地址。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为账户的数量。 #### Python3 ```python +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + class Solution: def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] - - n = len(accounts) - p = list(range(n)) - email_id = {} - for i, account in enumerate(accounts): - name = account[0] - for email in account[1:]: - if email in email_id: - p[find(i)] = find(email_id[email]) + uf = UnionFind(len(accounts)) + d = {} + for i, (_, *emails) in enumerate(accounts): + for email in emails: + if email in d: + uf.union(i, d[email]) else: - email_id[email] = i - mp = defaultdict(set) - for i, account in enumerate(accounts): - for email in account[1:]: - mp[find(i)].add(email) - - ans = [] - for i, emails in mp.items(): - t = [accounts[i][0]] - t.extend(sorted(emails)) - ans.append(t) - return ans + d[email] = i + g = defaultdict(set) + for i, (_, *emails) in enumerate(accounts): + root = uf.find(i) + g[root].update(emails) + return [[accounts[root][0]] + sorted(emails) for root, emails in g.items()] ``` #### Java ```java -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; - public List> accountsMerge(List> accounts) { - int n = accounts.size(); + public UnionFind(int n) { p = new int[n]; + size = new int[n]; for (int i = 0; i < n; ++i) { p[i] = i; + size[i] = 1; } - Map emailId = new HashMap<>(); + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public List> accountsMerge(List> accounts) { + int n = accounts.size(); + UnionFind uf = new UnionFind(n); + Map d = new HashMap<>(); for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - String name = account.get(0); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - if (emailId.containsKey(email)) { - p[find(i)] = find(emailId.get(email)); + for (int j = 1; j < accounts.get(i).size(); ++j) { + String email = accounts.get(i).get(j); + if (d.containsKey(email)) { + uf.union(i, d.get(email)); } else { - emailId.put(email, i); + d.put(email, i); } } } - Map> mp = new HashMap<>(); + Map> g = new HashMap<>(); for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - mp.computeIfAbsent(find(i), k -> new HashSet<>()).add(email); - } + int root = uf.find(i); + g.computeIfAbsent(root, k -> new HashSet<>()) + .addAll(accounts.get(i).subList(1, accounts.get(i).size())); + } + List> ans = new ArrayList<>(); + for (var e : g.entrySet()) { + List emails = new ArrayList<>(e.getValue()); + Collections.sort(emails); + ans.add(new ArrayList<>()); + ans.get(ans.size() - 1).add(accounts.get(e.getKey()).get(0)); + ans.get(ans.size() - 1).addAll(emails); + } + return ans; + } +} +``` + +#### C++ + +```cpp +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; } - List> res = new ArrayList<>(); - for (Map.Entry> entry : mp.entrySet()) { - List t = new LinkedList<>(); - t.addAll(entry.getValue()); - Collections.sort(t); - t.add(0, accounts.get(entry.getKey()).get(0)); - res.add(t); + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; } - return res; + return true; } - private int find(int x) { + int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } -} -``` -#### C++ +private: + vector p, size; +}; -```cpp class Solution { public: - vector p; - vector> accountsMerge(vector>& accounts) { int n = accounts.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - unordered_map emailId; + UnionFind uf(n); + unordered_map d; for (int i = 0; i < n; ++i) { - auto account = accounts[i]; - auto name = account[0]; - for (int j = 1; j < account.size(); ++j) { - string email = account[j]; - if (emailId.count(email)) - p[find(i)] = find(emailId[email]); - else - emailId[email] = i; + for (int j = 1; j < accounts[i].size(); ++j) { + const string& email = accounts[i][j]; + if (d.find(email) != d.end()) { + uf.unite(i, d[email]); + } else { + d[email] = i; + } } } - unordered_map> mp; + unordered_map> g; for (int i = 0; i < n; ++i) { - auto account = accounts[i]; - for (int j = 1; j < account.size(); ++j) { - string email = account[j]; - mp[find(i)].insert(email); - } + int root = uf.find(i); + g[root].insert(accounts[i].begin() + 1, accounts[i].end()); } vector> ans; - for (auto& [i, emails] : mp) { - vector t; - t.push_back(accounts[i][0]); - for (string email : emails) t.push_back(email); - sort(t.begin() + 1, t.end()); - ans.push_back(t); + for (const auto& [root, s] : g) { + vector emails(s.begin(), s.end()); + emails.insert(emails.begin(), accounts[root][0]); + ans.push_back(emails); } return ans; } +}; +``` - int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); +#### Go + +```go +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func accountsMerge(accounts [][]string) (ans [][]string) { + n := len(accounts) + uf := newUnionFind(n) + d := make(map[string]int) + for i := 0; i < n; i++ { + for _, email := range accounts[i][1:] { + if j, ok := d[email]; ok { + uf.union(i, j) + } else { + d[email] = i + } + } + } + g := make(map[int]map[string]struct{}) + for i := 0; i < n; i++ { + root := uf.find(i) + if _, ok := g[root]; !ok { + g[root] = make(map[string]struct{}) + } + for _, email := range accounts[i][1:] { + g[root][email] = struct{}{} + } + } + for root, s := range g { + emails := []string{} + for email := range s { + emails = append(emails, email) + } + sort.Strings(emails) + account := append([]string{accounts[root][0]}, emails...) + ans = append(ans, account) + } + return +} +``` + +#### TypeScript + +```ts +class UnionFind { + private p: number[]; + private size: number[]; + + constructor(n: number) { + this.p = new Array(n); + this.size = new Array(n); + for (let i = 0; i < n; ++i) { + this.p[i] = i; + this.size[i] = 1; } - return p[x]; } -}; + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + let pa = this.find(a), + pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function accountsMerge(accounts: string[][]): string[][] { + const n = accounts.length; + const uf = new UnionFind(n); + const d = new Map(); + + for (let i = 0; i < n; ++i) { + for (let j = 1; j < accounts[i].length; ++j) { + const email = accounts[i][j]; + if (d.has(email)) { + uf.union(i, d.get(email)!); + } else { + d.set(email, i); + } + } + } + + const g = new Map>(); + for (let i = 0; i < n; ++i) { + const root = uf.find(i); + if (!g.has(root)) { + g.set(root, new Set()); + } + const emailSet = g.get(root)!; + for (let j = 1; j < accounts[i].length; ++j) { + emailSet.add(accounts[i][j]); + } + } + + const ans: string[][] = []; + for (const [root, emails] of g.entries()) { + const emailList = Array.from(emails).sort(); + const mergedAccount = [accounts[root][0], ...emailList]; + ans.push(mergedAccount); + } + + return ans; +} ``` diff --git a/solution/0700-0799/0721.Accounts Merge/README_EN.md b/solution/0700-0799/0721.Accounts Merge/README_EN.md index 52a0a5965522..f1ba681e3783 100644 --- a/solution/0700-0799/0721.Accounts Merge/README_EN.md +++ b/solution/0700-0799/0721.Accounts Merge/README_EN.md @@ -65,145 +65,355 @@ We could return these lists in any order, for example the answer [['Mary' -### Solution 1 +### Solution 1: Union-Find + Hash Table + +Based on the problem description, we can use a union-find data structure to merge accounts with the same email address. The specific steps are as follows: + +First, we iterate through all the accounts. For the $i$th account, we iterate through all its email addresses. If an email address appears in the hash table $\textit{d}$, we use the union-find to merge the account's index $i$ with the previously appeared account's index; otherwise, we map this email address to the account's index $i$. + +Next, we iterate through all the accounts again. For the $i$th account, we use the union-find to find its root node, and then add all the email addresses of that account to the hash table $\textit{g}$, where the key is the root node, and the value is the account's email addresses. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of accounts. #### Python3 ```python +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + class Solution: def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] - - n = len(accounts) - p = list(range(n)) - email_id = {} - for i, account in enumerate(accounts): - name = account[0] - for email in account[1:]: - if email in email_id: - p[find(i)] = find(email_id[email]) + uf = UnionFind(len(accounts)) + d = {} + for i, (_, *emails) in enumerate(accounts): + for email in emails: + if email in d: + uf.union(i, d[email]) else: - email_id[email] = i - mp = defaultdict(set) - for i, account in enumerate(accounts): - for email in account[1:]: - mp[find(i)].add(email) - - ans = [] - for i, emails in mp.items(): - t = [accounts[i][0]] - t.extend(sorted(emails)) - ans.append(t) - return ans + d[email] = i + g = defaultdict(set) + for i, (_, *emails) in enumerate(accounts): + root = uf.find(i) + g[root].update(emails) + return [[accounts[root][0]] + sorted(emails) for root, emails in g.items()] ``` #### Java ```java -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; - public List> accountsMerge(List> accounts) { - int n = accounts.size(); + public UnionFind(int n) { p = new int[n]; + size = new int[n]; for (int i = 0; i < n; ++i) { p[i] = i; + size[i] = 1; } - Map emailId = new HashMap<>(); + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public List> accountsMerge(List> accounts) { + int n = accounts.size(); + UnionFind uf = new UnionFind(n); + Map d = new HashMap<>(); for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - String name = account.get(0); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - if (emailId.containsKey(email)) { - p[find(i)] = find(emailId.get(email)); + for (int j = 1; j < accounts.get(i).size(); ++j) { + String email = accounts.get(i).get(j); + if (d.containsKey(email)) { + uf.union(i, d.get(email)); } else { - emailId.put(email, i); + d.put(email, i); } } } - Map> mp = new HashMap<>(); + Map> g = new HashMap<>(); for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - mp.computeIfAbsent(find(i), k -> new HashSet<>()).add(email); - } + int root = uf.find(i); + g.computeIfAbsent(root, k -> new HashSet<>()) + .addAll(accounts.get(i).subList(1, accounts.get(i).size())); + } + List> ans = new ArrayList<>(); + for (var e : g.entrySet()) { + List emails = new ArrayList<>(e.getValue()); + Collections.sort(emails); + ans.add(new ArrayList<>()); + ans.get(ans.size() - 1).add(accounts.get(e.getKey()).get(0)); + ans.get(ans.size() - 1).addAll(emails); + } + return ans; + } +} +``` + +#### C++ + +```cpp +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; } - List> res = new ArrayList<>(); - for (Map.Entry> entry : mp.entrySet()) { - List t = new LinkedList<>(); - t.addAll(entry.getValue()); - Collections.sort(t); - t.add(0, accounts.get(entry.getKey()).get(0)); - res.add(t); + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; } - return res; + return true; } - private int find(int x) { + int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } -} -``` -#### C++ +private: + vector p, size; +}; -```cpp class Solution { public: - vector p; - vector> accountsMerge(vector>& accounts) { int n = accounts.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - unordered_map emailId; + UnionFind uf(n); + unordered_map d; for (int i = 0; i < n; ++i) { - auto account = accounts[i]; - auto name = account[0]; - for (int j = 1; j < account.size(); ++j) { - string email = account[j]; - if (emailId.count(email)) - p[find(i)] = find(emailId[email]); - else - emailId[email] = i; + for (int j = 1; j < accounts[i].size(); ++j) { + const string& email = accounts[i][j]; + if (d.find(email) != d.end()) { + uf.unite(i, d[email]); + } else { + d[email] = i; + } } } - unordered_map> mp; + unordered_map> g; for (int i = 0; i < n; ++i) { - auto account = accounts[i]; - for (int j = 1; j < account.size(); ++j) { - string email = account[j]; - mp[find(i)].insert(email); - } + int root = uf.find(i); + g[root].insert(accounts[i].begin() + 1, accounts[i].end()); } vector> ans; - for (auto& [i, emails] : mp) { - vector t; - t.push_back(accounts[i][0]); - for (string email : emails) t.push_back(email); - sort(t.begin() + 1, t.end()); - ans.push_back(t); + for (const auto& [root, s] : g) { + vector emails(s.begin(), s.end()); + emails.insert(emails.begin(), accounts[root][0]); + ans.push_back(emails); } return ans; } +}; +``` - int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); +#### Go + +```go +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func accountsMerge(accounts [][]string) (ans [][]string) { + n := len(accounts) + uf := newUnionFind(n) + d := make(map[string]int) + for i := 0; i < n; i++ { + for _, email := range accounts[i][1:] { + if j, ok := d[email]; ok { + uf.union(i, j) + } else { + d[email] = i + } + } + } + g := make(map[int]map[string]struct{}) + for i := 0; i < n; i++ { + root := uf.find(i) + if _, ok := g[root]; !ok { + g[root] = make(map[string]struct{}) + } + for _, email := range accounts[i][1:] { + g[root][email] = struct{}{} + } + } + for root, s := range g { + emails := []string{} + for email := range s { + emails = append(emails, email) + } + sort.Strings(emails) + account := append([]string{accounts[root][0]}, emails...) + ans = append(ans, account) + } + return +} +``` + +#### TypeScript + +```ts +class UnionFind { + private p: number[]; + private size: number[]; + + constructor(n: number) { + this.p = new Array(n); + this.size = new Array(n); + for (let i = 0; i < n; ++i) { + this.p[i] = i; + this.size[i] = 1; } - return p[x]; } -}; + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + let pa = this.find(a), + pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function accountsMerge(accounts: string[][]): string[][] { + const n = accounts.length; + const uf = new UnionFind(n); + const d = new Map(); + + for (let i = 0; i < n; ++i) { + for (let j = 1; j < accounts[i].length; ++j) { + const email = accounts[i][j]; + if (d.has(email)) { + uf.union(i, d.get(email)!); + } else { + d.set(email, i); + } + } + } + + const g = new Map>(); + for (let i = 0; i < n; ++i) { + const root = uf.find(i); + if (!g.has(root)) { + g.set(root, new Set()); + } + const emailSet = g.get(root)!; + for (let j = 1; j < accounts[i].length; ++j) { + emailSet.add(accounts[i][j]); + } + } + + const ans: string[][] = []; + for (const [root, emails] of g.entries()) { + const emailList = Array.from(emails).sort(); + const mergedAccount = [accounts[root][0], ...emailList]; + ans.push(mergedAccount); + } + + return ans; +} ``` diff --git a/solution/0700-0799/0721.Accounts Merge/Solutioin.java b/solution/0700-0799/0721.Accounts Merge/Solutioin.java deleted file mode 100644 index 3fbd05ffc0c6..000000000000 --- a/solution/0700-0799/0721.Accounts Merge/Solutioin.java +++ /dev/null @@ -1,48 +0,0 @@ -class Solution { - private int[] p; - - public List> accountsMerge(List> accounts) { - int n = accounts.size(); - p = new int[n]; - for (int i = 0; i < n; ++i) { - p[i] = i; - } - Map emailId = new HashMap<>(); - for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - String name = account.get(0); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - if (emailId.containsKey(email)) { - p[find(i)] = find(emailId.get(email)); - } else { - emailId.put(email, i); - } - } - } - Map> mp = new HashMap<>(); - for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - mp.computeIfAbsent(find(i), k -> new HashSet<>()).add(email); - } - } - List> res = new ArrayList<>(); - for (Map.Entry> entry : mp.entrySet()) { - List t = new LinkedList<>(); - t.addAll(entry.getValue()); - Collections.sort(t); - t.add(0, accounts.get(entry.getKey()).get(0)); - res.add(t); - } - return res; - } - - private int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); - } - return p[x]; - } -} \ No newline at end of file diff --git a/solution/0700-0799/0721.Accounts Merge/Solution.cpp b/solution/0700-0799/0721.Accounts Merge/Solution.cpp index 808f1bd0a0ec..2e7cc6832839 100644 --- a/solution/0700-0799/0721.Accounts Merge/Solution.cpp +++ b/solution/0700-0799/0721.Accounts Merge/Solution.cpp @@ -1,46 +1,64 @@ -class Solution { +class UnionFind { public: - vector p; + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } + + int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + +private: + vector p, size; +}; +class Solution { +public: vector> accountsMerge(vector>& accounts) { int n = accounts.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - unordered_map emailId; + UnionFind uf(n); + unordered_map d; for (int i = 0; i < n; ++i) { - auto account = accounts[i]; - auto name = account[0]; - for (int j = 1; j < account.size(); ++j) { - string email = account[j]; - if (emailId.count(email)) - p[find(i)] = find(emailId[email]); - else - emailId[email] = i; + for (int j = 1; j < accounts[i].size(); ++j) { + const string& email = accounts[i][j]; + if (d.find(email) != d.end()) { + uf.unite(i, d[email]); + } else { + d[email] = i; + } } } - unordered_map> mp; + unordered_map> g; for (int i = 0; i < n; ++i) { - auto account = accounts[i]; - for (int j = 1; j < account.size(); ++j) { - string email = account[j]; - mp[find(i)].insert(email); - } + int root = uf.find(i); + g[root].insert(accounts[i].begin() + 1, accounts[i].end()); } vector> ans; - for (auto& [i, emails] : mp) { - vector t; - t.push_back(accounts[i][0]); - for (string email : emails) t.push_back(email); - sort(t.begin() + 1, t.end()); - ans.push_back(t); + for (const auto& [root, s] : g) { + vector emails(s.begin(), s.end()); + emails.insert(emails.begin(), accounts[root][0]); + ans.push_back(emails); } return ans; } - - int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); - } - return p[x]; - } }; \ No newline at end of file diff --git a/solution/0700-0799/0721.Accounts Merge/Solution.go b/solution/0700-0799/0721.Accounts Merge/Solution.go new file mode 100644 index 000000000000..53cb032205b0 --- /dev/null +++ b/solution/0700-0799/0721.Accounts Merge/Solution.go @@ -0,0 +1,70 @@ +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func accountsMerge(accounts [][]string) (ans [][]string) { + n := len(accounts) + uf := newUnionFind(n) + d := make(map[string]int) + for i := 0; i < n; i++ { + for _, email := range accounts[i][1:] { + if j, ok := d[email]; ok { + uf.union(i, j) + } else { + d[email] = i + } + } + } + g := make(map[int]map[string]struct{}) + for i := 0; i < n; i++ { + root := uf.find(i) + if _, ok := g[root]; !ok { + g[root] = make(map[string]struct{}) + } + for _, email := range accounts[i][1:] { + g[root][email] = struct{}{} + } + } + for root, s := range g { + emails := []string{} + for email := range s { + emails = append(emails, email) + } + sort.Strings(emails) + account := append([]string{accounts[root][0]}, emails...) + ans = append(ans, account) + } + return +} \ No newline at end of file diff --git a/solution/0700-0799/0721.Accounts Merge/Solution.java b/solution/0700-0799/0721.Accounts Merge/Solution.java index 3fbd05ffc0c6..81b46ae39c97 100644 --- a/solution/0700-0799/0721.Accounts Merge/Solution.java +++ b/solution/0700-0799/0721.Accounts Merge/Solution.java @@ -1,48 +1,68 @@ -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; - public List> accountsMerge(List> accounts) { - int n = accounts.size(); + public UnionFind(int n) { p = new int[n]; + size = new int[n]; for (int i = 0; i < n; ++i) { p[i] = i; + size[i] = 1; + } + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; } - Map emailId = new HashMap<>(); + return true; + } +} + +class Solution { + public List> accountsMerge(List> accounts) { + int n = accounts.size(); + UnionFind uf = new UnionFind(n); + Map d = new HashMap<>(); for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - String name = account.get(0); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - if (emailId.containsKey(email)) { - p[find(i)] = find(emailId.get(email)); + for (int j = 1; j < accounts.get(i).size(); ++j) { + String email = accounts.get(i).get(j); + if (d.containsKey(email)) { + uf.union(i, d.get(email)); } else { - emailId.put(email, i); + d.put(email, i); } } } - Map> mp = new HashMap<>(); + Map> g = new HashMap<>(); for (int i = 0; i < n; ++i) { - List account = accounts.get(i); - for (int j = 1; j < account.size(); ++j) { - String email = account.get(j); - mp.computeIfAbsent(find(i), k -> new HashSet<>()).add(email); - } + int root = uf.find(i); + g.computeIfAbsent(root, k -> new HashSet<>()) + .addAll(accounts.get(i).subList(1, accounts.get(i).size())); } - List> res = new ArrayList<>(); - for (Map.Entry> entry : mp.entrySet()) { - List t = new LinkedList<>(); - t.addAll(entry.getValue()); - Collections.sort(t); - t.add(0, accounts.get(entry.getKey()).get(0)); - res.add(t); + List> ans = new ArrayList<>(); + for (var e : g.entrySet()) { + List emails = new ArrayList<>(e.getValue()); + Collections.sort(emails); + ans.add(new ArrayList<>()); + ans.get(ans.size() - 1).add(accounts.get(e.getKey()).get(0)); + ans.get(ans.size() - 1).addAll(emails); } - return res; - } - - private int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); - } - return p[x]; + return ans; } } \ No newline at end of file diff --git a/solution/0700-0799/0721.Accounts Merge/Solution.py b/solution/0700-0799/0721.Accounts Merge/Solution.py index e5723a330ec4..13901622b83b 100644 --- a/solution/0700-0799/0721.Accounts Merge/Solution.py +++ b/solution/0700-0799/0721.Accounts Merge/Solution.py @@ -1,28 +1,38 @@ +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + class Solution: def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] - - n = len(accounts) - p = list(range(n)) - email_id = {} - for i, account in enumerate(accounts): - name = account[0] - for email in account[1:]: - if email in email_id: - p[find(i)] = find(email_id[email]) + uf = UnionFind(len(accounts)) + d = {} + for i, (_, *emails) in enumerate(accounts): + for email in emails: + if email in d: + uf.union(i, d[email]) else: - email_id[email] = i - mp = defaultdict(set) - for i, account in enumerate(accounts): - for email in account[1:]: - mp[find(i)].add(email) - - ans = [] - for i, emails in mp.items(): - t = [accounts[i][0]] - t.extend(sorted(emails)) - ans.append(t) - return ans + d[email] = i + g = defaultdict(set) + for i, (_, *emails) in enumerate(accounts): + root = uf.find(i) + g[root].update(emails) + return [[accounts[root][0]] + sorted(emails) for root, emails in g.items()] diff --git a/solution/0700-0799/0721.Accounts Merge/Solution.ts b/solution/0700-0799/0721.Accounts Merge/Solution.ts new file mode 100644 index 000000000000..19f1a97799f2 --- /dev/null +++ b/solution/0700-0799/0721.Accounts Merge/Solution.ts @@ -0,0 +1,74 @@ +class UnionFind { + private p: number[]; + private size: number[]; + + constructor(n: number) { + this.p = new Array(n); + this.size = new Array(n); + for (let i = 0; i < n; ++i) { + this.p[i] = i; + this.size[i] = 1; + } + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + let pa = this.find(a), + pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function accountsMerge(accounts: string[][]): string[][] { + const n = accounts.length; + const uf = new UnionFind(n); + const d = new Map(); + + for (let i = 0; i < n; ++i) { + for (let j = 1; j < accounts[i].length; ++j) { + const email = accounts[i][j]; + if (d.has(email)) { + uf.union(i, d.get(email)!); + } else { + d.set(email, i); + } + } + } + + const g = new Map>(); + for (let i = 0; i < n; ++i) { + const root = uf.find(i); + if (!g.has(root)) { + g.set(root, new Set()); + } + const emailSet = g.get(root)!; + for (let j = 1; j < accounts[i].length; ++j) { + emailSet.add(accounts[i][j]); + } + } + + const ans: string[][] = []; + for (const [root, emails] of g.entries()) { + const emailList = Array.from(emails).sort(); + const mergedAccount = [accounts[root][0], ...emailList]; + ans.push(mergedAccount); + } + + return ans; +} diff --git a/solution/0700-0799/0723.Candy Crush/README.md b/solution/0700-0799/0723.Candy Crush/README.md index 0f192402f72e..63e161a4dcfb 100644 --- a/solution/0700-0799/0723.Candy Crush/README.md +++ b/solution/0700-0799/0723.Candy Crush/README.md @@ -71,7 +71,11 @@ tags: -### 方法一 +### 方法一:模拟 + +我们可以逐行和逐列遍历矩阵,找到连续三个相同的元素,将它们标记为负数。如果成功标记,我们需要将矩阵中的元素下移,直到没有元素可以下移为止。 + +时间复杂度 $O(m^2 \times n^2)$,其中 $m$ 和 $n$ 分别是矩阵的行数和列数。空间复杂度 $O(1)$。 @@ -85,37 +89,33 @@ class Solution: while run: run = False for i in range(m): - for j in range(n - 2): - if ( - board[i][j] != 0 - and abs(board[i][j]) == abs(board[i][j + 1]) - and abs(board[i][j]) == abs(board[i][j + 2]) + for j in range(2, n): + if board[i][j] and abs(board[i][j]) == abs(board[i][j - 1]) == abs( + board[i][j - 2] ): run = True - board[i][j] = board[i][j + 1] = board[i][j + 2] = -abs( + board[i][j] = board[i][j - 1] = board[i][j - 2] = -abs( board[i][j] ) for j in range(n): - for i in range(m - 2): - if ( - board[i][j] != 0 - and abs(board[i][j]) == abs(board[i + 1][j]) - and abs(board[i][j]) == abs(board[i + 2][j]) + for i in range(2, m): + if board[i][j] and abs(board[i][j]) == abs(board[i - 1][j]) == abs( + board[i - 2][j] ): run = True - board[i][j] = board[i + 1][j] = board[i + 2][j] = -abs( + board[i][j] = board[i - 1][j] = board[i - 2][j] = -abs( board[i][j] ) if run: for j in range(n): - curr = m - 1 + k = m - 1 for i in range(m - 1, -1, -1): if board[i][j] > 0: - board[curr][j] = board[i][j] - curr -= 1 - while curr > -1: - board[curr][j] = 0 - curr -= 1 + board[k][j] = board[i][j] + k -= 1 + while k >= 0: + board[k][j] = 0 + k -= 1 return board ``` @@ -126,42 +126,46 @@ class Solution { public int[][] candyCrush(int[][] board) { int m = board.length, n = board[0].length; boolean run = true; + while (run) { run = false; - for (int i = 0; i < m; ++i) { - for (int j = 0; j < n - 2; ++j) { - if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i][j + 1]) - && Math.abs(board[i][j]) == Math.abs(board[i][j + 2])) { + for (int i = 0; i < m; i++) { + for (int j = 2; j < n; j++) { + if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i][j - 1]) + && Math.abs(board[i][j]) == Math.abs(board[i][j - 2])) { run = true; - board[i][j] = board[i][j + 1] = board[i][j + 2] = -Math.abs(board[i][j]); + int val = Math.abs(board[i][j]); + board[i][j] = board[i][j - 1] = board[i][j - 2] = -val; } } } - for (int j = 0; j < n; ++j) { - for (int i = 0; i < m - 2; ++i) { - if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i + 1][j]) - && Math.abs(board[i][j]) == Math.abs(board[i + 2][j])) { + for (int j = 0; j < n; j++) { + for (int i = 2; i < m; i++) { + if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i - 1][j]) + && Math.abs(board[i][j]) == Math.abs(board[i - 2][j])) { run = true; - board[i][j] = board[i + 1][j] = board[i + 2][j] = -Math.abs(board[i][j]); + int val = Math.abs(board[i][j]); + board[i][j] = board[i - 1][j] = board[i - 2][j] = -val; } } } if (run) { - for (int j = 0; j < n; ++j) { - int curr = m - 1; - for (int i = m - 1; i >= 0; --i) { + for (int j = 0; j < n; j++) { + int k = m - 1; + for (int i = m - 1; i >= 0; i--) { if (board[i][j] > 0) { - board[curr][j] = board[i][j]; - --curr; + board[k][j] = board[i][j]; + k--; } } - while (curr > -1) { - board[curr][j] = 0; - --curr; + while (k >= 0) { + board[k][j] = 0; + k--; } } } } + return board; } } @@ -218,52 +222,114 @@ public: ```go func candyCrush(board [][]int) [][]int { - m, n := len(board), len(board[0]) + m := len(board) + n := len(board[0]) run := true + for run { run = false for i := 0; i < m; i++ { - for j := 0; j < n-2; j++ { - if board[i][j] != 0 && abs(board[i][j]) == abs(board[i][j+1]) && abs(board[i][j]) == abs(board[i][j+2]) { + for j := 2; j < n; j++ { + if board[i][j] != 0 && abs(board[i][j]) == abs(board[i][j-1]) && abs(board[i][j]) == abs(board[i][j-2]) { run = true - t := -abs(board[i][j]) - board[i][j], board[i][j+1], board[i][j+2] = t, t, t + val := abs(board[i][j]) + board[i][j] = -val + board[i][j-1] = -val + board[i][j-2] = -val } } } for j := 0; j < n; j++ { - for i := 0; i < m-2; i++ { - if board[i][j] != 0 && abs(board[i][j]) == abs(board[i+1][j]) && abs(board[i][j]) == abs(board[i+2][j]) { + for i := 2; i < m; i++ { + if board[i][j] != 0 && abs(board[i][j]) == abs(board[i-1][j]) && abs(board[i][j]) == abs(board[i-2][j]) { run = true - t := -abs(board[i][j]) - board[i][j], board[i+1][j], board[i+2][j] = t, t, t + val := abs(board[i][j]) + board[i][j] = -val + board[i-1][j] = -val + board[i-2][j] = -val } } } if run { for j := 0; j < n; j++ { - curr := m - 1 + k := m - 1 for i := m - 1; i >= 0; i-- { if board[i][j] > 0 { - board[curr][j] = board[i][j] - curr-- + board[k][j] = board[i][j] + k-- } } - for curr > -1 { - board[curr][j] = 0 - curr-- + for k >= 0 { + board[k][j] = 0 + k-- } } } } + return board } func abs(x int) int { - if x >= 0 { - return x + if x < 0 { + return -x } - return -x + return x +} +``` + +#### TypeScript + +```ts +function candyCrush(board: number[][]): number[][] { + const m = board.length; + const n = board[0].length; + let run = true; + while (run) { + run = false; + for (let i = 0; i < m; i++) { + for (let j = 2; j < n; j++) { + if ( + board[i][j] !== 0 && + Math.abs(board[i][j]) === Math.abs(board[i][j - 1]) && + Math.abs(board[i][j]) === Math.abs(board[i][j - 2]) + ) { + run = true; + const val = Math.abs(board[i][j]); + board[i][j] = board[i][j - 1] = board[i][j - 2] = -val; + } + } + } + for (let j = 0; j < n; j++) { + for (let i = 2; i < m; i++) { + if ( + board[i][j] !== 0 && + Math.abs(board[i][j]) === Math.abs(board[i - 1][j]) && + Math.abs(board[i][j]) === Math.abs(board[i - 2][j]) + ) { + run = true; + const val = Math.abs(board[i][j]); + board[i][j] = board[i - 1][j] = board[i - 2][j] = -val; + } + } + } + if (run) { + for (let j = 0; j < n; j++) { + let k = m - 1; + for (let i = m - 1; i >= 0; i--) { + if (board[i][j] > 0) { + board[k][j] = board[i][j]; + k--; + } + } + while (k >= 0) { + board[k][j] = 0; + k--; + } + } + } + } + return board; } ``` diff --git a/solution/0700-0799/0723.Candy Crush/README_EN.md b/solution/0700-0799/0723.Candy Crush/README_EN.md index ecf1d5548c52..946223f5170a 100644 --- a/solution/0700-0799/0723.Candy Crush/README_EN.md +++ b/solution/0700-0799/0723.Candy Crush/README_EN.md @@ -65,7 +65,11 @@ tags: -### Solution 1 +### Solution 1: Simulation + +We can traverse the matrix row by row and column by column to find three consecutive identical elements and mark them as negative numbers. If marking is successful, we need to move the elements in the matrix down until no elements can move down. + +The time complexity is $O(m^2 \times n^2)$, where $m$ and $n$ are the number of rows and columns of the matrix, respectively. The space complexity is $O(1)$. @@ -79,37 +83,33 @@ class Solution: while run: run = False for i in range(m): - for j in range(n - 2): - if ( - board[i][j] != 0 - and abs(board[i][j]) == abs(board[i][j + 1]) - and abs(board[i][j]) == abs(board[i][j + 2]) + for j in range(2, n): + if board[i][j] and abs(board[i][j]) == abs(board[i][j - 1]) == abs( + board[i][j - 2] ): run = True - board[i][j] = board[i][j + 1] = board[i][j + 2] = -abs( + board[i][j] = board[i][j - 1] = board[i][j - 2] = -abs( board[i][j] ) for j in range(n): - for i in range(m - 2): - if ( - board[i][j] != 0 - and abs(board[i][j]) == abs(board[i + 1][j]) - and abs(board[i][j]) == abs(board[i + 2][j]) + for i in range(2, m): + if board[i][j] and abs(board[i][j]) == abs(board[i - 1][j]) == abs( + board[i - 2][j] ): run = True - board[i][j] = board[i + 1][j] = board[i + 2][j] = -abs( + board[i][j] = board[i - 1][j] = board[i - 2][j] = -abs( board[i][j] ) if run: for j in range(n): - curr = m - 1 + k = m - 1 for i in range(m - 1, -1, -1): if board[i][j] > 0: - board[curr][j] = board[i][j] - curr -= 1 - while curr > -1: - board[curr][j] = 0 - curr -= 1 + board[k][j] = board[i][j] + k -= 1 + while k >= 0: + board[k][j] = 0 + k -= 1 return board ``` @@ -120,42 +120,46 @@ class Solution { public int[][] candyCrush(int[][] board) { int m = board.length, n = board[0].length; boolean run = true; + while (run) { run = false; - for (int i = 0; i < m; ++i) { - for (int j = 0; j < n - 2; ++j) { - if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i][j + 1]) - && Math.abs(board[i][j]) == Math.abs(board[i][j + 2])) { + for (int i = 0; i < m; i++) { + for (int j = 2; j < n; j++) { + if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i][j - 1]) + && Math.abs(board[i][j]) == Math.abs(board[i][j - 2])) { run = true; - board[i][j] = board[i][j + 1] = board[i][j + 2] = -Math.abs(board[i][j]); + int val = Math.abs(board[i][j]); + board[i][j] = board[i][j - 1] = board[i][j - 2] = -val; } } } - for (int j = 0; j < n; ++j) { - for (int i = 0; i < m - 2; ++i) { - if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i + 1][j]) - && Math.abs(board[i][j]) == Math.abs(board[i + 2][j])) { + for (int j = 0; j < n; j++) { + for (int i = 2; i < m; i++) { + if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i - 1][j]) + && Math.abs(board[i][j]) == Math.abs(board[i - 2][j])) { run = true; - board[i][j] = board[i + 1][j] = board[i + 2][j] = -Math.abs(board[i][j]); + int val = Math.abs(board[i][j]); + board[i][j] = board[i - 1][j] = board[i - 2][j] = -val; } } } if (run) { - for (int j = 0; j < n; ++j) { - int curr = m - 1; - for (int i = m - 1; i >= 0; --i) { + for (int j = 0; j < n; j++) { + int k = m - 1; + for (int i = m - 1; i >= 0; i--) { if (board[i][j] > 0) { - board[curr][j] = board[i][j]; - --curr; + board[k][j] = board[i][j]; + k--; } } - while (curr > -1) { - board[curr][j] = 0; - --curr; + while (k >= 0) { + board[k][j] = 0; + k--; } } } } + return board; } } @@ -212,52 +216,114 @@ public: ```go func candyCrush(board [][]int) [][]int { - m, n := len(board), len(board[0]) + m := len(board) + n := len(board[0]) run := true + for run { run = false for i := 0; i < m; i++ { - for j := 0; j < n-2; j++ { - if board[i][j] != 0 && abs(board[i][j]) == abs(board[i][j+1]) && abs(board[i][j]) == abs(board[i][j+2]) { + for j := 2; j < n; j++ { + if board[i][j] != 0 && abs(board[i][j]) == abs(board[i][j-1]) && abs(board[i][j]) == abs(board[i][j-2]) { run = true - t := -abs(board[i][j]) - board[i][j], board[i][j+1], board[i][j+2] = t, t, t + val := abs(board[i][j]) + board[i][j] = -val + board[i][j-1] = -val + board[i][j-2] = -val } } } for j := 0; j < n; j++ { - for i := 0; i < m-2; i++ { - if board[i][j] != 0 && abs(board[i][j]) == abs(board[i+1][j]) && abs(board[i][j]) == abs(board[i+2][j]) { + for i := 2; i < m; i++ { + if board[i][j] != 0 && abs(board[i][j]) == abs(board[i-1][j]) && abs(board[i][j]) == abs(board[i-2][j]) { run = true - t := -abs(board[i][j]) - board[i][j], board[i+1][j], board[i+2][j] = t, t, t + val := abs(board[i][j]) + board[i][j] = -val + board[i-1][j] = -val + board[i-2][j] = -val } } } if run { for j := 0; j < n; j++ { - curr := m - 1 + k := m - 1 for i := m - 1; i >= 0; i-- { if board[i][j] > 0 { - board[curr][j] = board[i][j] - curr-- + board[k][j] = board[i][j] + k-- } } - for curr > -1 { - board[curr][j] = 0 - curr-- + for k >= 0 { + board[k][j] = 0 + k-- } } } } + return board } func abs(x int) int { - if x >= 0 { - return x + if x < 0 { + return -x } - return -x + return x +} +``` + +#### TypeScript + +```ts +function candyCrush(board: number[][]): number[][] { + const m = board.length; + const n = board[0].length; + let run = true; + while (run) { + run = false; + for (let i = 0; i < m; i++) { + for (let j = 2; j < n; j++) { + if ( + board[i][j] !== 0 && + Math.abs(board[i][j]) === Math.abs(board[i][j - 1]) && + Math.abs(board[i][j]) === Math.abs(board[i][j - 2]) + ) { + run = true; + const val = Math.abs(board[i][j]); + board[i][j] = board[i][j - 1] = board[i][j - 2] = -val; + } + } + } + for (let j = 0; j < n; j++) { + for (let i = 2; i < m; i++) { + if ( + board[i][j] !== 0 && + Math.abs(board[i][j]) === Math.abs(board[i - 1][j]) && + Math.abs(board[i][j]) === Math.abs(board[i - 2][j]) + ) { + run = true; + const val = Math.abs(board[i][j]); + board[i][j] = board[i - 1][j] = board[i - 2][j] = -val; + } + } + } + if (run) { + for (let j = 0; j < n; j++) { + let k = m - 1; + for (let i = m - 1; i >= 0; i--) { + if (board[i][j] > 0) { + board[k][j] = board[i][j]; + k--; + } + } + while (k >= 0) { + board[k][j] = 0; + k--; + } + } + } + } + return board; } ``` diff --git a/solution/0700-0799/0723.Candy Crush/Solution.go b/solution/0700-0799/0723.Candy Crush/Solution.go index 1b38bb2651eb..13a79d4adc70 100644 --- a/solution/0700-0799/0723.Candy Crush/Solution.go +++ b/solution/0700-0799/0723.Candy Crush/Solution.go @@ -1,48 +1,55 @@ func candyCrush(board [][]int) [][]int { - m, n := len(board), len(board[0]) + m := len(board) + n := len(board[0]) run := true + for run { run = false for i := 0; i < m; i++ { - for j := 0; j < n-2; j++ { - if board[i][j] != 0 && abs(board[i][j]) == abs(board[i][j+1]) && abs(board[i][j]) == abs(board[i][j+2]) { + for j := 2; j < n; j++ { + if board[i][j] != 0 && abs(board[i][j]) == abs(board[i][j-1]) && abs(board[i][j]) == abs(board[i][j-2]) { run = true - t := -abs(board[i][j]) - board[i][j], board[i][j+1], board[i][j+2] = t, t, t + val := abs(board[i][j]) + board[i][j] = -val + board[i][j-1] = -val + board[i][j-2] = -val } } } for j := 0; j < n; j++ { - for i := 0; i < m-2; i++ { - if board[i][j] != 0 && abs(board[i][j]) == abs(board[i+1][j]) && abs(board[i][j]) == abs(board[i+2][j]) { + for i := 2; i < m; i++ { + if board[i][j] != 0 && abs(board[i][j]) == abs(board[i-1][j]) && abs(board[i][j]) == abs(board[i-2][j]) { run = true - t := -abs(board[i][j]) - board[i][j], board[i+1][j], board[i+2][j] = t, t, t + val := abs(board[i][j]) + board[i][j] = -val + board[i-1][j] = -val + board[i-2][j] = -val } } } if run { for j := 0; j < n; j++ { - curr := m - 1 + k := m - 1 for i := m - 1; i >= 0; i-- { if board[i][j] > 0 { - board[curr][j] = board[i][j] - curr-- + board[k][j] = board[i][j] + k-- } } - for curr > -1 { - board[curr][j] = 0 - curr-- + for k >= 0 { + board[k][j] = 0 + k-- } } } } + return board } func abs(x int) int { - if x >= 0 { - return x + if x < 0 { + return -x } - return -x + return x } \ No newline at end of file diff --git a/solution/0700-0799/0723.Candy Crush/Solution.java b/solution/0700-0799/0723.Candy Crush/Solution.java index f7348e9821c9..301297b502f7 100644 --- a/solution/0700-0799/0723.Candy Crush/Solution.java +++ b/solution/0700-0799/0723.Candy Crush/Solution.java @@ -2,42 +2,46 @@ class Solution { public int[][] candyCrush(int[][] board) { int m = board.length, n = board[0].length; boolean run = true; + while (run) { run = false; - for (int i = 0; i < m; ++i) { - for (int j = 0; j < n - 2; ++j) { - if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i][j + 1]) - && Math.abs(board[i][j]) == Math.abs(board[i][j + 2])) { + for (int i = 0; i < m; i++) { + for (int j = 2; j < n; j++) { + if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i][j - 1]) + && Math.abs(board[i][j]) == Math.abs(board[i][j - 2])) { run = true; - board[i][j] = board[i][j + 1] = board[i][j + 2] = -Math.abs(board[i][j]); + int val = Math.abs(board[i][j]); + board[i][j] = board[i][j - 1] = board[i][j - 2] = -val; } } } - for (int j = 0; j < n; ++j) { - for (int i = 0; i < m - 2; ++i) { - if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i + 1][j]) - && Math.abs(board[i][j]) == Math.abs(board[i + 2][j])) { + for (int j = 0; j < n; j++) { + for (int i = 2; i < m; i++) { + if (board[i][j] != 0 && Math.abs(board[i][j]) == Math.abs(board[i - 1][j]) + && Math.abs(board[i][j]) == Math.abs(board[i - 2][j])) { run = true; - board[i][j] = board[i + 1][j] = board[i + 2][j] = -Math.abs(board[i][j]); + int val = Math.abs(board[i][j]); + board[i][j] = board[i - 1][j] = board[i - 2][j] = -val; } } } if (run) { - for (int j = 0; j < n; ++j) { - int curr = m - 1; - for (int i = m - 1; i >= 0; --i) { + for (int j = 0; j < n; j++) { + int k = m - 1; + for (int i = m - 1; i >= 0; i--) { if (board[i][j] > 0) { - board[curr][j] = board[i][j]; - --curr; + board[k][j] = board[i][j]; + k--; } } - while (curr > -1) { - board[curr][j] = 0; - --curr; + while (k >= 0) { + board[k][j] = 0; + k--; } } } } + return board; } } \ No newline at end of file diff --git a/solution/0700-0799/0723.Candy Crush/Solution.py b/solution/0700-0799/0723.Candy Crush/Solution.py index 5264343d7f3d..9749812515db 100644 --- a/solution/0700-0799/0723.Candy Crush/Solution.py +++ b/solution/0700-0799/0723.Candy Crush/Solution.py @@ -5,35 +5,31 @@ def candyCrush(self, board: List[List[int]]) -> List[List[int]]: while run: run = False for i in range(m): - for j in range(n - 2): - if ( - board[i][j] != 0 - and abs(board[i][j]) == abs(board[i][j + 1]) - and abs(board[i][j]) == abs(board[i][j + 2]) + for j in range(2, n): + if board[i][j] and abs(board[i][j]) == abs(board[i][j - 1]) == abs( + board[i][j - 2] ): run = True - board[i][j] = board[i][j + 1] = board[i][j + 2] = -abs( + board[i][j] = board[i][j - 1] = board[i][j - 2] = -abs( board[i][j] ) for j in range(n): - for i in range(m - 2): - if ( - board[i][j] != 0 - and abs(board[i][j]) == abs(board[i + 1][j]) - and abs(board[i][j]) == abs(board[i + 2][j]) + for i in range(2, m): + if board[i][j] and abs(board[i][j]) == abs(board[i - 1][j]) == abs( + board[i - 2][j] ): run = True - board[i][j] = board[i + 1][j] = board[i + 2][j] = -abs( + board[i][j] = board[i - 1][j] = board[i - 2][j] = -abs( board[i][j] ) if run: for j in range(n): - curr = m - 1 + k = m - 1 for i in range(m - 1, -1, -1): if board[i][j] > 0: - board[curr][j] = board[i][j] - curr -= 1 - while curr > -1: - board[curr][j] = 0 - curr -= 1 + board[k][j] = board[i][j] + k -= 1 + while k >= 0: + board[k][j] = 0 + k -= 1 return board diff --git a/solution/0700-0799/0723.Candy Crush/Solution.ts b/solution/0700-0799/0723.Candy Crush/Solution.ts new file mode 100644 index 000000000000..85328a2e6cd6 --- /dev/null +++ b/solution/0700-0799/0723.Candy Crush/Solution.ts @@ -0,0 +1,50 @@ +function candyCrush(board: number[][]): number[][] { + const m = board.length; + const n = board[0].length; + let run = true; + while (run) { + run = false; + for (let i = 0; i < m; i++) { + for (let j = 2; j < n; j++) { + if ( + board[i][j] !== 0 && + Math.abs(board[i][j]) === Math.abs(board[i][j - 1]) && + Math.abs(board[i][j]) === Math.abs(board[i][j - 2]) + ) { + run = true; + const val = Math.abs(board[i][j]); + board[i][j] = board[i][j - 1] = board[i][j - 2] = -val; + } + } + } + for (let j = 0; j < n; j++) { + for (let i = 2; i < m; i++) { + if ( + board[i][j] !== 0 && + Math.abs(board[i][j]) === Math.abs(board[i - 1][j]) && + Math.abs(board[i][j]) === Math.abs(board[i - 2][j]) + ) { + run = true; + const val = Math.abs(board[i][j]); + board[i][j] = board[i - 1][j] = board[i - 2][j] = -val; + } + } + } + if (run) { + for (let j = 0; j < n; j++) { + let k = m - 1; + for (let i = m - 1; i >= 0; i--) { + if (board[i][j] > 0) { + board[k][j] = board[i][j]; + k--; + } + } + while (k >= 0) { + board[k][j] = 0; + k--; + } + } + } + } + return board; +} diff --git a/solution/0700-0799/0725.Split Linked List in Parts/README.md b/solution/0700-0799/0725.Split Linked List in Parts/README.md index 2c69b564ce9e..860b40b88de0 100644 --- a/solution/0700-0799/0725.Split Linked List in Parts/README.md +++ b/solution/0700-0799/0725.Split Linked List in Parts/README.md @@ -60,7 +60,13 @@ tags: -### 方法一 +### 方法一:模拟 + +我们先遍历链表,得到链表的长度 $n$,然后我们计算出平均长度 $\textit{cnt} = \lfloor \frac{n}{k} \rfloor$ 和余数 $\textit{mod} = n \bmod k$。那么对于前 $\textit{mod}$ 个部分,每个部分的长度为 $\textit{cnt} + 1$,其余部分的长度为 $\textit{cnt}$。 + +接下来,我们只需要遍历链表,将链表分割成 $k$ 个部分即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(k)$。其中 $n$ 为链表的长度。 @@ -69,29 +75,32 @@ tags: ```python # Definition for singly-linked list. # class ListNode: -# def __init__(self, x): -# self.val = x -# self.next = None - - +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next class Solution: - def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]: - n, cur = 0, root + def splitListToParts( + self, head: Optional[ListNode], k: int + ) -> List[Optional[ListNode]]: + n = 0 + cur = head while cur: n += 1 cur = cur.next - cur = root - width, remainder = divmod(n, k) - res = [None for _ in range(k)] + cnt, mod = divmod(n, k) + ans = [None] * k + cur = head for i in range(k): - head = cur - for j in range(width + (i < remainder) - 1): - if cur: - cur = cur.next - if cur: - cur.next, cur = None, cur.next - res[i] = head - return res + if cur is None: + break + ans[i] = cur + m = cnt + int(i < mod) + for _ in range(1, m): + cur = cur.next + nxt = cur.next + cur.next = None + cur = nxt + return ans ``` #### Java @@ -102,38 +111,147 @@ class Solution: * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode[] splitListToParts(ListNode root, int k) { + public ListNode[] splitListToParts(ListNode head, int k) { int n = 0; - ListNode cur = root; - while (cur != null) { + for (ListNode cur = head; cur != null; cur = cur.next) { ++n; - cur = cur.next; } - // width 表示每一部分至少含有的结点个数 - // remainder 表示前 remainder 部分,每一部分多出一个数 - int width = n / k, remainder = n % k; - ListNode[] res = new ListNode[k]; - cur = root; - for (int i = 0; i < k; ++i) { - ListNode head = cur; - for (int j = 0; j < width + ((i < remainder) ? 1 : 0) - 1; ++j) { - if (cur != null) { - cur = cur.next; - } + int cnt = n / k, mod = n % k; + ListNode[] ans = new ListNode[k]; + ListNode cur = head; + for (int i = 0; i < k && cur != null; ++i) { + ans[i] = cur; + int m = cnt + (i < mod ? 1 : 0); + for (int j = 1; j < m; ++j) { + cur = cur.next; } - if (cur != null) { - ListNode t = cur.next; - cur.next = null; - cur = t; + ListNode nxt = cur.next; + cur.next = null; + cur = nxt; + } + return ans; + } +} +``` + +#### C++ + +```cpp +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + vector splitListToParts(ListNode* head, int k) { + int n = 0; + for (ListNode* cur = head; cur != nullptr; cur = cur->next) { + ++n; + } + int cnt = n / k, mod = n % k; + vector ans(k, nullptr); + ListNode* cur = head; + for (int i = 0; i < k && cur != nullptr; ++i) { + ans[i] = cur; + int m = cnt + (i < mod ? 1 : 0); + for (int j = 1; j < m; ++j) { + cur = cur->next; } - res[i] = head; + ListNode* nxt = cur->next; + cur->next = nullptr; + cur = nxt; + } + return ans; + } +}; +``` + +#### Go + +```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func splitListToParts(head *ListNode, k int) []*ListNode { + n := 0 + for cur := head; cur != nil; cur = cur.Next { + n++ + } + + cnt := n / k + mod := n % k + ans := make([]*ListNode, k) + cur := head + + for i := 0; i < k && cur != nil; i++ { + ans[i] = cur + m := cnt + if i < mod { + m++ + } + for j := 1; j < m; j++ { + cur = cur.Next + } + next := cur.Next + cur.Next = nil + cur = next + } + + return ans +} +``` + +#### TypeScript + +```ts +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +function splitListToParts(head: ListNode | null, k: number): Array { + let n = 0; + for (let cur = head; cur !== null; cur = cur.next) { + n++; + } + const cnt = (n / k) | 0; + const mod = n % k; + const ans: Array = Array(k).fill(null); + let cur = head; + for (let i = 0; i < k && cur !== null; i++) { + ans[i] = cur; + let m = cnt + (i < mod ? 1 : 0); + for (let j = 1; j < m; j++) { + cur = cur.next!; } - return res; + let next = cur.next; + cur.next = null; + cur = next; } + return ans; } ``` diff --git a/solution/0700-0799/0725.Split Linked List in Parts/README_EN.md b/solution/0700-0799/0725.Split Linked List in Parts/README_EN.md index cb2023eec541..d88f7a817848 100644 --- a/solution/0700-0799/0725.Split Linked List in Parts/README_EN.md +++ b/solution/0700-0799/0725.Split Linked List in Parts/README_EN.md @@ -59,7 +59,13 @@ The input has been split into consecutive parts with size difference at most 1, -### Solution 1 +### Solution 1: Simulation + +First, we traverse the linked list to obtain its length $n$, and then we calculate the average length $\textit{cnt} = \lfloor \frac{n}{k} \rfloor$ and the remainder $\textit{mod} = n \bmod k$. For the first $\textit{mod}$ parts, each part has a length of $\textit{cnt} + 1$, while the lengths of the remaining parts are $\textit{cnt}$. + +Next, we just need to traverse the linked list and split it into $k$ parts. + +The time complexity is $O(n)$, and the space complexity is $O(k)$. Here, $n$ is the length of the linked list. @@ -68,29 +74,32 @@ The input has been split into consecutive parts with size difference at most 1, ```python # Definition for singly-linked list. # class ListNode: -# def __init__(self, x): -# self.val = x -# self.next = None - - +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next class Solution: - def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]: - n, cur = 0, root + def splitListToParts( + self, head: Optional[ListNode], k: int + ) -> List[Optional[ListNode]]: + n = 0 + cur = head while cur: n += 1 cur = cur.next - cur = root - width, remainder = divmod(n, k) - res = [None for _ in range(k)] + cnt, mod = divmod(n, k) + ans = [None] * k + cur = head for i in range(k): - head = cur - for j in range(width + (i < remainder) - 1): - if cur: - cur = cur.next - if cur: - cur.next, cur = None, cur.next - res[i] = head - return res + if cur is None: + break + ans[i] = cur + m = cnt + int(i < mod) + for _ in range(1, m): + cur = cur.next + nxt = cur.next + cur.next = None + cur = nxt + return ans ``` #### Java @@ -101,38 +110,147 @@ class Solution: * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode[] splitListToParts(ListNode root, int k) { + public ListNode[] splitListToParts(ListNode head, int k) { int n = 0; - ListNode cur = root; - while (cur != null) { + for (ListNode cur = head; cur != null; cur = cur.next) { ++n; - cur = cur.next; } - // width 表示每一部分至少含有的结点个数 - // remainder 表示前 remainder 部分,每一部分多出一个数 - int width = n / k, remainder = n % k; - ListNode[] res = new ListNode[k]; - cur = root; - for (int i = 0; i < k; ++i) { - ListNode head = cur; - for (int j = 0; j < width + ((i < remainder) ? 1 : 0) - 1; ++j) { - if (cur != null) { - cur = cur.next; - } + int cnt = n / k, mod = n % k; + ListNode[] ans = new ListNode[k]; + ListNode cur = head; + for (int i = 0; i < k && cur != null; ++i) { + ans[i] = cur; + int m = cnt + (i < mod ? 1 : 0); + for (int j = 1; j < m; ++j) { + cur = cur.next; } - if (cur != null) { - ListNode t = cur.next; - cur.next = null; - cur = t; + ListNode nxt = cur.next; + cur.next = null; + cur = nxt; + } + return ans; + } +} +``` + +#### C++ + +```cpp +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + vector splitListToParts(ListNode* head, int k) { + int n = 0; + for (ListNode* cur = head; cur != nullptr; cur = cur->next) { + ++n; + } + int cnt = n / k, mod = n % k; + vector ans(k, nullptr); + ListNode* cur = head; + for (int i = 0; i < k && cur != nullptr; ++i) { + ans[i] = cur; + int m = cnt + (i < mod ? 1 : 0); + for (int j = 1; j < m; ++j) { + cur = cur->next; } - res[i] = head; + ListNode* nxt = cur->next; + cur->next = nullptr; + cur = nxt; + } + return ans; + } +}; +``` + +#### Go + +```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func splitListToParts(head *ListNode, k int) []*ListNode { + n := 0 + for cur := head; cur != nil; cur = cur.Next { + n++ + } + + cnt := n / k + mod := n % k + ans := make([]*ListNode, k) + cur := head + + for i := 0; i < k && cur != nil; i++ { + ans[i] = cur + m := cnt + if i < mod { + m++ + } + for j := 1; j < m; j++ { + cur = cur.Next + } + next := cur.Next + cur.Next = nil + cur = next + } + + return ans +} +``` + +#### TypeScript + +```ts +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +function splitListToParts(head: ListNode | null, k: number): Array { + let n = 0; + for (let cur = head; cur !== null; cur = cur.next) { + n++; + } + const cnt = (n / k) | 0; + const mod = n % k; + const ans: Array = Array(k).fill(null); + let cur = head; + for (let i = 0; i < k && cur !== null; i++) { + ans[i] = cur; + let m = cnt + (i < mod ? 1 : 0); + for (let j = 1; j < m; j++) { + cur = cur.next!; } - return res; + let next = cur.next; + cur.next = null; + cur = next; } + return ans; } ``` diff --git a/solution/0700-0799/0725.Split Linked List in Parts/Solution.cpp b/solution/0700-0799/0725.Split Linked List in Parts/Solution.cpp new file mode 100644 index 000000000000..e2c895d0d963 --- /dev/null +++ b/solution/0700-0799/0725.Split Linked List in Parts/Solution.cpp @@ -0,0 +1,33 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + vector splitListToParts(ListNode* head, int k) { + int n = 0; + for (ListNode* cur = head; cur != nullptr; cur = cur->next) { + ++n; + } + int cnt = n / k, mod = n % k; + vector ans(k, nullptr); + ListNode* cur = head; + for (int i = 0; i < k && cur != nullptr; ++i) { + ans[i] = cur; + int m = cnt + (i < mod ? 1 : 0); + for (int j = 1; j < m; ++j) { + cur = cur->next; + } + ListNode* nxt = cur->next; + cur->next = nullptr; + cur = nxt; + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/0700-0799/0725.Split Linked List in Parts/Solution.go b/solution/0700-0799/0725.Split Linked List in Parts/Solution.go new file mode 100644 index 000000000000..1ea47bd7421c --- /dev/null +++ b/solution/0700-0799/0725.Split Linked List in Parts/Solution.go @@ -0,0 +1,34 @@ +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func splitListToParts(head *ListNode, k int) []*ListNode { + n := 0 + for cur := head; cur != nil; cur = cur.Next { + n++ + } + + cnt := n / k + mod := n % k + ans := make([]*ListNode, k) + cur := head + + for i := 0; i < k && cur != nil; i++ { + ans[i] = cur + m := cnt + if i < mod { + m++ + } + for j := 1; j < m; j++ { + cur = cur.Next + } + next := cur.Next + cur.Next = nil + cur = next + } + + return ans +} \ No newline at end of file diff --git a/solution/0700-0799/0725.Split Linked List in Parts/Solution.java b/solution/0700-0799/0725.Split Linked List in Parts/Solution.java index f59382fe22e8..fa75fd3addad 100644 --- a/solution/0700-0799/0725.Split Linked List in Parts/Solution.java +++ b/solution/0700-0799/0725.Split Linked List in Parts/Solution.java @@ -3,36 +3,30 @@ * public class ListNode { * int val; * ListNode next; - * ListNode(int x) { val = x; } + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { - public ListNode[] splitListToParts(ListNode root, int k) { + public ListNode[] splitListToParts(ListNode head, int k) { int n = 0; - ListNode cur = root; - while (cur != null) { + for (ListNode cur = head; cur != null; cur = cur.next) { ++n; - cur = cur.next; } - // width 表示每一部分至少含有的结点个数 - // remainder 表示前 remainder 部分,每一部分多出一个数 - int width = n / k, remainder = n % k; - ListNode[] res = new ListNode[k]; - cur = root; - for (int i = 0; i < k; ++i) { - ListNode head = cur; - for (int j = 0; j < width + ((i < remainder) ? 1 : 0) - 1; ++j) { - if (cur != null) { - cur = cur.next; - } + int cnt = n / k, mod = n % k; + ListNode[] ans = new ListNode[k]; + ListNode cur = head; + for (int i = 0; i < k && cur != null; ++i) { + ans[i] = cur; + int m = cnt + (i < mod ? 1 : 0); + for (int j = 1; j < m; ++j) { + cur = cur.next; } - if (cur != null) { - ListNode t = cur.next; - cur.next = null; - cur = t; - } - res[i] = head; + ListNode nxt = cur.next; + cur.next = null; + cur = nxt; } - return res; + return ans; } } \ No newline at end of file diff --git a/solution/0700-0799/0725.Split Linked List in Parts/Solution.py b/solution/0700-0799/0725.Split Linked List in Parts/Solution.py index 0033463d9046..2c72414dc4da 100644 --- a/solution/0700-0799/0725.Split Linked List in Parts/Solution.py +++ b/solution/0700-0799/0725.Split Linked List in Parts/Solution.py @@ -1,25 +1,28 @@ # Definition for singly-linked list. # class ListNode: -# def __init__(self, x): -# self.val = x -# self.next = None - - +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next class Solution: - def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]: - n, cur = 0, root + def splitListToParts( + self, head: Optional[ListNode], k: int + ) -> List[Optional[ListNode]]: + n = 0 + cur = head while cur: n += 1 cur = cur.next - cur = root - width, remainder = divmod(n, k) - res = [None for _ in range(k)] + cnt, mod = divmod(n, k) + ans = [None] * k + cur = head for i in range(k): - head = cur - for j in range(width + (i < remainder) - 1): - if cur: - cur = cur.next - if cur: - cur.next, cur = None, cur.next - res[i] = head - return res + if cur is None: + break + ans[i] = cur + m = cnt + int(i < mod) + for _ in range(1, m): + cur = cur.next + nxt = cur.next + cur.next = None + cur = nxt + return ans diff --git a/solution/0700-0799/0725.Split Linked List in Parts/Solution.ts b/solution/0700-0799/0725.Split Linked List in Parts/Solution.ts new file mode 100644 index 000000000000..dda11046b241 --- /dev/null +++ b/solution/0700-0799/0725.Split Linked List in Parts/Solution.ts @@ -0,0 +1,33 @@ +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +function splitListToParts(head: ListNode | null, k: number): Array { + let n = 0; + for (let cur = head; cur !== null; cur = cur.next) { + n++; + } + const cnt = (n / k) | 0; + const mod = n % k; + const ans: Array = Array(k).fill(null); + let cur = head; + for (let i = 0; i < k && cur !== null; i++) { + ans[i] = cur; + let m = cnt + (i < mod ? 1 : 0); + for (let j = 1; j < m; j++) { + cur = cur.next!; + } + let next = cur.next; + cur.next = null; + cur = next; + } + return ans; +} diff --git a/solution/0700-0799/0726.Number of Atoms/README.md b/solution/0700-0799/0726.Number of Atoms/README.md index d7d1da455232..898cfd3980a3 100644 --- a/solution/0700-0799/0726.Number of Atoms/README.md +++ b/solution/0700-0799/0726.Number of Atoms/README.md @@ -98,7 +98,49 @@ tags: #### Java ```java - +class Solution { + public String countOfAtoms(String formula) { + Map map = new HashMap<>(); + int[] stack = new int[1000]; + int top = 0, multiplier = 1, freq = 0; + char[] c = formula.toCharArray(); + for (int i = c.length - 1; i >= 0; i--) { + if (c[i] >= 'a' && c[i] <= 'z') { + int end = i--; + while (i >= 0 && c[i] >= 'a' && c[i] <= 'z') i--; + String key = new String(c, i, end - i + 1); + map.put(key, map.getOrDefault(key, 0) + Math.max(freq, 1) * multiplier); + freq = 0; + } else if (c[i] >= 'A' && c[i] <= 'Z') { + String key = new String(c, i, 1); + map.put(key, map.getOrDefault(key, 0) + Math.max(freq, 1) * multiplier); + freq = 0; + } else if (c[i] >= '0' && c[i] <= '9') { + freq = c[i] - '0'; + int p = 10; + while (i - 1 >= 0 && c[i - 1] >= '0' && c[i - 1] <= '9') { + freq += p * (c[--i] - '0'); + p *= 10; + } + } else if (c[i] == ')') { + stack[top++] = multiplier; + multiplier *= Math.max(freq, 1); + freq = 0; + } else { + multiplier = stack[--top]; + } + } + List keys = new ArrayList<>(map.keySet()); + Collections.sort(keys); + StringBuilder sb = new StringBuilder(); + for (String key : keys) { + sb.append(key); + int f = map.get(key); + if (f > 1) sb.append(f); + } + return sb.toString(); + } +} ``` #### C++ @@ -113,6 +155,146 @@ tags: ``` +#### TypeScript + +```ts +function countOfAtoms(formula: string): string { + const getCount = (formula: string, factor = 1) => { + const n = formula.length; + const cnt: Record = {}; + const s: string[] = []; + let [atom, c] = ['', 0]; + + for (let i = 0; i <= n; i++) { + if (formula[i] === '(') { + const stk: string[] = ['(']; + let j = i; + while (stk.length) { + j++; + if (formula[j] === '(') stk.push('('); + else if (formula[j] === ')') stk.pop(); + } + + const molecule = formula.slice(i + 1, j); + const nextFactor: string[] = []; + + while (isDigit(formula[++j])) { + nextFactor.push(formula[j]); + } + + const nextC = getCount(molecule, +nextFactor.join('') || 1); + for (const [atom, c] of Object.entries(nextC)) { + cnt[atom] = (cnt[atom] ?? 0) + c * factor; + } + + i = j - 1; + continue; + } + + if (s.length && (!formula[i] || isUpper(formula[i]))) { + [atom, c] = getAtom(s); + + c *= factor; + cnt[atom] = (cnt[atom] ?? 0) + c; + s.length = 0; + } + + s.push(formula[i]); + } + + return cnt; + }; + + return Object.entries(getCount(formula)) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([a, b]) => (b > 1 ? a + b : a)) + .join(''); +} + +const regex = { + atom: /(\D+)(\d+)?/, + isUpper: /[A-Z]+/, +}; +const getAtom = (s: string[]): [string, number] => { + const [_, atom, c] = regex.atom.exec(s.join(''))!; + return [atom, c ? +c : 1]; +}; +const isDigit = (ch: string) => !Number.isNaN(Number.parseInt(ch)); +const isUpper = (ch: string) => regex.isUpper.test(ch); +``` + +#### JavaScript + +```js +/** + * @param {string} formula + * @return {string} + */ +var countOfAtoms = function (formula) { + const getCount = (formula, factor = 1) => { + const n = formula.length; + const cnt = {}; + const s = []; + let [atom, c] = ['', 0]; + + for (let i = 0; i <= n; i++) { + if (formula[i] === '(') { + const stk = ['(']; + let j = i; + while (stk.length) { + j++; + if (formula[j] === '(') stk.push('('); + else if (formula[j] === ')') stk.pop(); + } + + const molecule = formula.slice(i + 1, j); + const nextFactor = []; + + while (isDigit(formula[++j])) { + nextFactor.push(formula[j]); + } + + const nextC = getCount(molecule, +nextFactor.join('') || 1); + for (const [atom, c] of Object.entries(nextC)) { + cnt[atom] = (cnt[atom] ?? 0) + c * factor; + } + + i = j - 1; + continue; + } + + if (s.length && (!formula[i] || isUpper(formula[i]))) { + [atom, c] = getAtom(s); + + c *= factor; + cnt[atom] = (cnt[atom] ?? 0) + c; + s.length = 0; + } + + s.push(formula[i]); + } + + return cnt; + }; + + return Object.entries(getCount(formula)) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([a, b]) => (b > 1 ? a + b : a)) + .join(''); +}; + +const regex = { + atom: /(\D+)(\d+)?/, + isUpper: /[A-Z]+/, +}; +const getAtom = s => { + const [_, atom, c] = regex.atom.exec(s.join('')); + return [atom, c ? +c : 1]; +}; +const isDigit = ch => !Number.isNaN(Number.parseInt(ch)); +const isUpper = ch => regex.isUpper.test(ch); +``` + diff --git a/solution/0700-0799/0726.Number of Atoms/README_EN.md b/solution/0700-0799/0726.Number of Atoms/README_EN.md index 641c1face2c9..c0c48f50c617 100644 --- a/solution/0700-0799/0726.Number of Atoms/README_EN.md +++ b/solution/0700-0799/0726.Number of Atoms/README_EN.md @@ -98,7 +98,49 @@ tags: #### Java ```java - +class Solution { + public String countOfAtoms(String formula) { + Map map = new HashMap<>(); + int[] stack = new int[1000]; + int top = 0, multiplier = 1, freq = 0; + char[] c = formula.toCharArray(); + for (int i = c.length - 1; i >= 0; i--) { + if (c[i] >= 'a' && c[i] <= 'z') { + int end = i--; + while (i >= 0 && c[i] >= 'a' && c[i] <= 'z') i--; + String key = new String(c, i, end - i + 1); + map.put(key, map.getOrDefault(key, 0) + Math.max(freq, 1) * multiplier); + freq = 0; + } else if (c[i] >= 'A' && c[i] <= 'Z') { + String key = new String(c, i, 1); + map.put(key, map.getOrDefault(key, 0) + Math.max(freq, 1) * multiplier); + freq = 0; + } else if (c[i] >= '0' && c[i] <= '9') { + freq = c[i] - '0'; + int p = 10; + while (i - 1 >= 0 && c[i - 1] >= '0' && c[i - 1] <= '9') { + freq += p * (c[--i] - '0'); + p *= 10; + } + } else if (c[i] == ')') { + stack[top++] = multiplier; + multiplier *= Math.max(freq, 1); + freq = 0; + } else { + multiplier = stack[--top]; + } + } + List keys = new ArrayList<>(map.keySet()); + Collections.sort(keys); + StringBuilder sb = new StringBuilder(); + for (String key : keys) { + sb.append(key); + int f = map.get(key); + if (f > 1) sb.append(f); + } + return sb.toString(); + } +} ``` #### C++ @@ -113,6 +155,146 @@ tags: ``` +#### TypeScript + +```ts +function countOfAtoms(formula: string): string { + const getCount = (formula: string, factor = 1) => { + const n = formula.length; + const cnt: Record = {}; + const s: string[] = []; + let [atom, c] = ['', 0]; + + for (let i = 0; i <= n; i++) { + if (formula[i] === '(') { + const stk: string[] = ['(']; + let j = i; + while (stk.length) { + j++; + if (formula[j] === '(') stk.push('('); + else if (formula[j] === ')') stk.pop(); + } + + const molecule = formula.slice(i + 1, j); + const nextFactor: string[] = []; + + while (isDigit(formula[++j])) { + nextFactor.push(formula[j]); + } + + const nextC = getCount(molecule, +nextFactor.join('') || 1); + for (const [atom, c] of Object.entries(nextC)) { + cnt[atom] = (cnt[atom] ?? 0) + c * factor; + } + + i = j - 1; + continue; + } + + if (s.length && (!formula[i] || isUpper(formula[i]))) { + [atom, c] = getAtom(s); + + c *= factor; + cnt[atom] = (cnt[atom] ?? 0) + c; + s.length = 0; + } + + s.push(formula[i]); + } + + return cnt; + }; + + return Object.entries(getCount(formula)) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([a, b]) => (b > 1 ? a + b : a)) + .join(''); +} + +const regex = { + atom: /(\D+)(\d+)?/, + isUpper: /[A-Z]+/, +}; +const getAtom = (s: string[]): [string, number] => { + const [_, atom, c] = regex.atom.exec(s.join(''))!; + return [atom, c ? +c : 1]; +}; +const isDigit = (ch: string) => !Number.isNaN(Number.parseInt(ch)); +const isUpper = (ch: string) => regex.isUpper.test(ch); +``` + +#### JavaScript + +```js +/** + * @param {string} formula + * @return {string} + */ +var countOfAtoms = function (formula) { + const getCount = (formula, factor = 1) => { + const n = formula.length; + const cnt = {}; + const s = []; + let [atom, c] = ['', 0]; + + for (let i = 0; i <= n; i++) { + if (formula[i] === '(') { + const stk = ['(']; + let j = i; + while (stk.length) { + j++; + if (formula[j] === '(') stk.push('('); + else if (formula[j] === ')') stk.pop(); + } + + const molecule = formula.slice(i + 1, j); + const nextFactor = []; + + while (isDigit(formula[++j])) { + nextFactor.push(formula[j]); + } + + const nextC = getCount(molecule, +nextFactor.join('') || 1); + for (const [atom, c] of Object.entries(nextC)) { + cnt[atom] = (cnt[atom] ?? 0) + c * factor; + } + + i = j - 1; + continue; + } + + if (s.length && (!formula[i] || isUpper(formula[i]))) { + [atom, c] = getAtom(s); + + c *= factor; + cnt[atom] = (cnt[atom] ?? 0) + c; + s.length = 0; + } + + s.push(formula[i]); + } + + return cnt; + }; + + return Object.entries(getCount(formula)) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([a, b]) => (b > 1 ? a + b : a)) + .join(''); +}; + +const regex = { + atom: /(\D+)(\d+)?/, + isUpper: /[A-Z]+/, +}; +const getAtom = s => { + const [_, atom, c] = regex.atom.exec(s.join('')); + return [atom, c ? +c : 1]; +}; +const isDigit = ch => !Number.isNaN(Number.parseInt(ch)); +const isUpper = ch => regex.isUpper.test(ch); +``` + diff --git a/solution/0700-0799/0726.Number of Atoms/Solution.java b/solution/0700-0799/0726.Number of Atoms/Solution.java new file mode 100644 index 000000000000..4a2cabc65937 --- /dev/null +++ b/solution/0700-0799/0726.Number of Atoms/Solution.java @@ -0,0 +1,43 @@ +class Solution { + public String countOfAtoms(String formula) { + Map map = new HashMap<>(); + int[] stack = new int[1000]; + int top = 0, multiplier = 1, freq = 0; + char[] c = formula.toCharArray(); + for (int i = c.length - 1; i >= 0; i--) { + if (c[i] >= 'a' && c[i] <= 'z') { + int end = i--; + while (i >= 0 && c[i] >= 'a' && c[i] <= 'z') i--; + String key = new String(c, i, end - i + 1); + map.put(key, map.getOrDefault(key, 0) + Math.max(freq, 1) * multiplier); + freq = 0; + } else if (c[i] >= 'A' && c[i] <= 'Z') { + String key = new String(c, i, 1); + map.put(key, map.getOrDefault(key, 0) + Math.max(freq, 1) * multiplier); + freq = 0; + } else if (c[i] >= '0' && c[i] <= '9') { + freq = c[i] - '0'; + int p = 10; + while (i - 1 >= 0 && c[i - 1] >= '0' && c[i - 1] <= '9') { + freq += p * (c[--i] - '0'); + p *= 10; + } + } else if (c[i] == ')') { + stack[top++] = multiplier; + multiplier *= Math.max(freq, 1); + freq = 0; + } else { + multiplier = stack[--top]; + } + } + List keys = new ArrayList<>(map.keySet()); + Collections.sort(keys); + StringBuilder sb = new StringBuilder(); + for (String key : keys) { + sb.append(key); + int f = map.get(key); + if (f > 1) sb.append(f); + } + return sb.toString(); + } +} diff --git a/solution/0700-0799/0726.Number of Atoms/Solution.js b/solution/0700-0799/0726.Number of Atoms/Solution.js new file mode 100644 index 000000000000..726bf59ac4d2 --- /dev/null +++ b/solution/0700-0799/0726.Number of Atoms/Solution.js @@ -0,0 +1,67 @@ +/** + * @param {string} formula + * @return {string} + */ +var countOfAtoms = function (formula) { + const getCount = (formula, factor = 1) => { + const n = formula.length; + const cnt = {}; + const s = []; + let [atom, c] = ['', 0]; + + for (let i = 0; i <= n; i++) { + if (formula[i] === '(') { + const stk = ['(']; + let j = i; + while (stk.length) { + j++; + if (formula[j] === '(') stk.push('('); + else if (formula[j] === ')') stk.pop(); + } + + const molecule = formula.slice(i + 1, j); + const nextFactor = []; + + while (isDigit(formula[++j])) { + nextFactor.push(formula[j]); + } + + const nextC = getCount(molecule, +nextFactor.join('') || 1); + for (const [atom, c] of Object.entries(nextC)) { + cnt[atom] = (cnt[atom] ?? 0) + c * factor; + } + + i = j - 1; + continue; + } + + if (s.length && (!formula[i] || isUpper(formula[i]))) { + [atom, c] = getAtom(s); + + c *= factor; + cnt[atom] = (cnt[atom] ?? 0) + c; + s.length = 0; + } + + s.push(formula[i]); + } + + return cnt; + }; + + return Object.entries(getCount(formula)) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([a, b]) => (b > 1 ? a + b : a)) + .join(''); +}; + +const regex = { + atom: /(\D+)(\d+)?/, + isUpper: /[A-Z]+/, +}; +const getAtom = s => { + const [_, atom, c] = regex.atom.exec(s.join('')); + return [atom, c ? +c : 1]; +}; +const isDigit = ch => !Number.isNaN(Number.parseInt(ch)); +const isUpper = ch => regex.isUpper.test(ch); diff --git a/solution/0700-0799/0726.Number of Atoms/Solution.ts b/solution/0700-0799/0726.Number of Atoms/Solution.ts new file mode 100644 index 000000000000..4ea850eb92a0 --- /dev/null +++ b/solution/0700-0799/0726.Number of Atoms/Solution.ts @@ -0,0 +1,63 @@ +function countOfAtoms(formula: string): string { + const getCount = (formula: string, factor = 1) => { + const n = formula.length; + const cnt: Record = {}; + const s: string[] = []; + let [atom, c] = ['', 0]; + + for (let i = 0; i <= n; i++) { + if (formula[i] === '(') { + const stk: string[] = ['(']; + let j = i; + while (stk.length) { + j++; + if (formula[j] === '(') stk.push('('); + else if (formula[j] === ')') stk.pop(); + } + + const molecule = formula.slice(i + 1, j); + const nextFactor: string[] = []; + + while (isDigit(formula[++j])) { + nextFactor.push(formula[j]); + } + + const nextC = getCount(molecule, +nextFactor.join('') || 1); + for (const [atom, c] of Object.entries(nextC)) { + cnt[atom] = (cnt[atom] ?? 0) + c * factor; + } + + i = j - 1; + continue; + } + + if (s.length && (!formula[i] || isUpper(formula[i]))) { + [atom, c] = getAtom(s); + + c *= factor; + cnt[atom] = (cnt[atom] ?? 0) + c; + s.length = 0; + } + + s.push(formula[i]); + } + + return cnt; + }; + + return Object.entries(getCount(formula)) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([a, b]) => (b > 1 ? a + b : a)) + .join(''); +} + +const regex = { + atom: /(\D+)(\d+)?/, + isUpper: /[A-Z]+/, +}; +const getAtom = (s: string[]): [string, number] => { + const [_, atom, c] = regex.atom.exec(s.join(''))!; + return [atom, c ? +c : 1]; +}; +const isDigit = (ch: string) => !Number.isNaN(Number.parseInt(ch)); +const isUpper = (ch: string) => regex.isUpper.test(ch); diff --git a/solution/0700-0799/0727.Minimum Window Subsequence/README.md b/solution/0700-0799/0727.Minimum Window Subsequence/README.md index da3875ac1a86..e18eafea5758 100644 --- a/solution/0700-0799/0727.Minimum Window Subsequence/README.md +++ b/solution/0700-0799/0727.Minimum Window Subsequence/README.md @@ -57,8 +57,8 @@ S = "abcdebdde", T = "bde" $$ f[i][j] = \begin{cases} -i, & j = 1 \text{ and } s1[i-1] = s2[j] \\ -f[i - 1][j - 1], & j > 1 \text{ and } s1[i-1] = s2[j-1] \\ +i, & j = 1 \textit{ and } s1[i-1] = s2[j] \\ +f[i - 1][j - 1], & j > 1 \textit{ and } s1[i-1] = s2[j-1] \\ f[i - 1][j], & s1[i-1] \ne s2[j-1] \end{cases} $$ diff --git a/solution/0700-0799/0737.Sentence Similarity II/README.md b/solution/0700-0799/0737.Sentence Similarity II/README.md index cdcff4c75a67..b07c7fa1c366 100644 --- a/solution/0700-0799/0737.Sentence Similarity II/README.md +++ b/solution/0700-0799/0737.Sentence Similarity II/README.md @@ -30,7 +30,7 @@ tags:

    两个句子是相似的,如果:

      -
    • 它们具有 相同的长度 (即相同的字数)
    • +
    • 它们具有 相同的长度 (即相同的词数)
    • sentence1[i] 和 sentence2[i] 是相似的
    diff --git a/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README.md b/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README.md index 2102e0123016..3ae8f7268b65 100644 --- a/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README.md +++ b/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README.md @@ -64,13 +64,13 @@ tags: ### 方法一:二分查找 -由于 $\text{letters}$ 是按照非递减顺序排序的,所以我们可以使用二分查找来找到大于 `target` 的最小字符。 +由于 $\textit{letters}$ 是按照非递减顺序排序的,所以我们可以使用二分查找来找到大于 `target` 的最小字符。 -我们定义二分查找的左边界 $l = 0$,右边界 $r = n$。对于每一次二分查找,我们计算中间位置 $mid = (l + r) / 2$,如果 $letters[mid] > \text{target}$,则说明我们需要在左半部分继续查找,即 $r = mid$;否则我们需要在右半部分继续查找,即 $l = mid + 1$。 +我们定义二分查找的左边界 $l = 0$,右边界 $r = n$。对于每一次二分查找,我们计算中间位置 $mid = (l + r) / 2$,如果 $letters[mid] > \textit{target}$,则说明我们需要在左半部分继续查找,即 $r = mid$;否则我们需要在右半部分继续查找,即 $l = mid + 1$。 最后我们返回 $letters[l \mod n]$ 即可。 -时间复杂度 $O(\log n)$,其中 $n$ 是 $\text{letters}$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(\log n)$,其中 $n$ 是 $\textit{letters}$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README_EN.md b/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README_EN.md index dcf32c88a094..fda3474a9c6c 100644 --- a/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README_EN.md +++ b/solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README_EN.md @@ -67,7 +67,7 @@ tags: Since `letters` is sorted in non-decreasing order, we can use binary search to find the smallest character that is larger than `target`. -We define the left boundary of the binary search as $l = 0$, and the right boundary as $r = n$. For each binary search, we calculate the middle position $mid = (l + r) / 2$. If $letters[mid] > \text{target}$, it means we need to continue searching in the left half, so we set $r = mid$. Otherwise, we need to continue searching in the right half, so we set $l = mid + 1$. +We define the left boundary of the binary search as $l = 0$, and the right boundary as $r = n$. For each binary search, we calculate the middle position $mid = (l + r) / 2$. If $letters[mid] > \textit{target}$, it means we need to continue searching in the left half, so we set $r = mid$. Otherwise, we need to continue searching in the right half, so we set $l = mid + 1$. Finally, we return $letters[l \mod n]$. diff --git a/solution/0700-0799/0756.Pyramid Transition Matrix/README.md b/solution/0700-0799/0756.Pyramid Transition Matrix/README.md index 41d3596c0188..edc215cc36bf 100644 --- a/solution/0700-0799/0756.Pyramid Transition Matrix/README.md +++ b/solution/0700-0799/0756.Pyramid Transition Matrix/README.md @@ -26,9 +26,9 @@ tags:
  • 例如,"ABC" 表示一个三角形图案,其中一个 “C” 块堆叠在一个 'A' 块(左)和一个 'B' 块(右)之上。请注意,这与 "BAC" 不同,"B" 在左下角,"A" 在右下角。
  • -

    你从底部的一排积木 bottom 开始,作为一个单一的字符串,你 必须 使用作为金字塔的底部。

    +

    你从作为单个字符串给出的底部的一排积木 bottom 开始,必须 将其作为金字塔的底部。

    -

    在给定 bottom 和 allowed 的情况下,如果你能一直构建到金字塔顶部,使金字塔中的 每个三角形图案 都是允许的,则返回 true ,否则返回 false

    +

    在给定 bottom 和 allowed 的情况下,如果你能一直构建到金字塔顶部,使金字塔中的 每个三角形图案 都是在 allowed 中的,则返回 true ,否则返回 false

     

    @@ -39,9 +39,9 @@ tags:
     输入:bottom = "BCD", allowed = ["BCC","CDE","CEA","FFF"]
     输出:true
    -解释:允许的三角形模式显示在右边。
    -从最底层(第3层)开始,我们可以在第2层构建“CE”,然后在第1层构建“E”。
    -金字塔中有三种三角形图案,分别是“BCC”、“CDE”和“CEA”。都是允许的。
    +解释:允许的三角形图案显示在右边。
    +从最底层(第 3 层)开始,我们可以在第 2 层构建“CE”,然后在第 1 层构建“E”。
    +金字塔中有三种三角形图案,分别是 “BCC”、“CDE” 和 “CEA”。都是允许的。
     

    示例 2:

    @@ -51,8 +51,8 @@ tags:
     输入:bottom = "AAAA", allowed = ["AAB","AAC","BCD","BBE","DEF"]
     输出:false
    -解释:允许的三角形模式显示在右边。
    -从最底层(游戏邦注:即第4个关卡)开始,创造第3个关卡有多种方法,但如果尝试所有可能性,你便会在创造第1个关卡前陷入困境。
    +解释:允许的三角形图案显示在右边。
    +从最底层(即第 4 层)开始,创造第 3 层有多种方法,但如果尝试所有可能性,你便会在创造第 1 层前陷入困境。
     

     

    @@ -63,7 +63,7 @@ tags:
  • 2 <= bottom.length <= 6
  • 0 <= allowed.length <= 216
  • allowed[i].length == 3
  • -
  • 所有输入字符串中的字母来自集合 {'A', 'B', 'C', 'D', 'E', 'F', 'G'}
  • +
  • 所有输入字符串中的字母来自集合 {'A', 'B', 'C', 'D', 'E', 'F'}
  •  allowed 中所有值都是 唯一的
  • diff --git a/solution/0700-0799/0758.Bold Words in String/README_EN.md b/solution/0700-0799/0758.Bold Words in String/README_EN.md index 0dc44c200429..a2c3b2603d8f 100644 --- a/solution/0700-0799/0758.Bold Words in String/README_EN.md +++ b/solution/0700-0799/0758.Bold Words in String/README_EN.md @@ -51,7 +51,7 @@ tags:

     

    -

    Note: This question is the same as 616: https://leetcode.com/problems/add-bold-tag-in-string/

    +

    Note: This question is the same as 616. Add Bold Tag in String.

    diff --git a/solution/0700-0799/0777.Swap Adjacent in LR String/README_EN.md b/solution/0700-0799/0777.Swap Adjacent in LR String/README_EN.md index 27e0e8b94adb..ab76e1f0608a 100644 --- a/solution/0700-0799/0777.Swap Adjacent in LR String/README_EN.md +++ b/solution/0700-0799/0777.Swap Adjacent in LR String/README_EN.md @@ -17,7 +17,7 @@ tags: -

    In a string composed of 'L', 'R', and 'X' characters, like "RXXLRXRXL", a move consists of either replacing one occurrence of "XL" with "LX", or replacing one occurrence of "RX" with "XR". Given the starting string start and the ending string end, return True if and only if there exists a sequence of moves to transform one string to the other.

    +

    In a string composed of 'L', 'R', and 'X' characters, like "RXXLRXRXL", a move consists of either replacing one occurrence of "XL" with "LX", or replacing one occurrence of "RX" with "XR". Given the starting string start and the ending string end, return True if and only if there exists a sequence of moves to transform start to end.

     

    Example 1:

    diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README.md b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README.md index 10c0cb8778cb..bcb964c9355f 100644 --- a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README.md +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README.md @@ -65,7 +65,11 @@ tags: ### 方法一:中序遍历 -中序遍历二叉搜索树,获取当前节点与上个节点差值的最小值即可。 +题目需要我们求任意两个节点值之间的最小差值,而二叉搜索树的中序遍历是一个递增序列,因此我们只需要求中序遍历中相邻两个节点值之间的最小差值即可。 + +我们可以使用递归的方法来实现中序遍历,过程中用一个变量 $\textit{pre}$ 来保存前一个节点的值,这样我们就可以在遍历的过程中求出相邻两个节点值之间的最小差值。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉搜索树的节点个数。 @@ -80,16 +84,17 @@ tags: # self.right = right class Solution: def minDiffInBST(self, root: Optional[TreeNode]) -> int: - def dfs(root): + def dfs(root: Optional[TreeNode]): if root is None: return dfs(root.left) - nonlocal ans, prev - ans = min(ans, abs(prev - root.val)) - prev = root.val + nonlocal pre, ans + ans = min(ans, root.val - pre) + pre = root.val dfs(root.right) - ans = prev = inf + pre = -inf + ans = inf dfs(root) return ans ``` @@ -113,13 +118,11 @@ class Solution: * } */ class Solution { - private int ans; - private int prev; - private int inf = Integer.MAX_VALUE; + private final int inf = 1 << 30; + private int ans = inf; + private int pre = -inf; public int minDiffInBST(TreeNode root) { - ans = inf; - prev = inf; dfs(root); return ans; } @@ -129,8 +132,8 @@ class Solution { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); } } @@ -152,23 +155,21 @@ class Solution { */ class Solution { public: - const int inf = INT_MAX; - int ans; - int prev; - int minDiffInBST(TreeNode* root) { - ans = inf, prev = inf; - dfs(root); + const int inf = 1 << 30; + int ans = inf, pre = -inf; + auto dfs = [&](auto&& dfs, TreeNode* root) -> void { + if (!root) { + return; + } + dfs(dfs, root->left); + ans = min(ans, root->val - pre); + pre = root->val; + dfs(dfs, root->right); + }; + dfs(dfs, root); return ans; } - - void dfs(TreeNode* root) { - if (!root) return; - dfs(root->left); - ans = min(ans, abs(prev - root->val)); - prev = root->val; - dfs(root->right); - } }; ``` @@ -184,43 +185,125 @@ public: * } */ func minDiffInBST(root *TreeNode) int { - inf := 0x3f3f3f3f - ans, prev := inf, inf + const inf int = 1 << 30 + ans, pre := inf, -inf var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return } dfs(root.Left) - ans = min(ans, abs(prev-root.Val)) - prev = root.Val + ans = min(ans, root.Val-pre) + pre = root.Val dfs(root.Right) } dfs(root) return ans } +``` -func abs(x int) int { - if x < 0 { - return -x - } - return x +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function minDiffInBST(root: TreeNode | null): number { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); + }; + dfs(root); + return ans; +} +``` + +#### Rust + +```rust +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::cell::RefCell; +use std::rc::Rc; +impl Solution { + pub fn min_diff_in_bst(root: Option>>) -> i32 { + const inf: i32 = 1 << 30; + let mut ans = inf; + let mut pre = -inf; + + fn dfs(node: Option>>, ans: &mut i32, pre: &mut i32) { + if let Some(n) = node { + let n = n.borrow(); + dfs(n.left.clone(), ans, pre); + *ans = (*ans).min(n.val - *pre); + *pre = n.val; + dfs(n.right.clone(), ans, pre); + } + } + + dfs(root, &mut ans, &mut pre); + ans + } } ``` #### JavaScript ```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ var minDiffInBST = function (root) { - let ans = Number.MAX_SAFE_INTEGER, - prev = Number.MAX_SAFE_INTEGER; + let [ans, pre] = [Infinity, -Infinity]; const dfs = root => { if (!root) { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); }; dfs(root); diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README_EN.md b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README_EN.md index 68cccd842c61..4c207c9590d9 100644 --- a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README_EN.md +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/README_EN.md @@ -54,7 +54,13 @@ tags: -### Solution 1 +### Solution 1: Inorder Traversal + +The problem requires us to find the minimum difference between the values of any two nodes. Since the inorder traversal of a binary search tree is an increasing sequence, we only need to find the minimum difference between the values of two adjacent nodes in the inorder traversal. + +We can use a recursive method to implement the inorder traversal. During the process, we use a variable $\textit{pre}$ to save the value of the previous node. This way, we can calculate the minimum difference between the values of two adjacent nodes during the traversal. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary search tree. @@ -69,16 +75,17 @@ tags: # self.right = right class Solution: def minDiffInBST(self, root: Optional[TreeNode]) -> int: - def dfs(root): + def dfs(root: Optional[TreeNode]): if root is None: return dfs(root.left) - nonlocal ans, prev - ans = min(ans, abs(prev - root.val)) - prev = root.val + nonlocal pre, ans + ans = min(ans, root.val - pre) + pre = root.val dfs(root.right) - ans = prev = inf + pre = -inf + ans = inf dfs(root) return ans ``` @@ -102,13 +109,11 @@ class Solution: * } */ class Solution { - private int ans; - private int prev; - private int inf = Integer.MAX_VALUE; + private final int inf = 1 << 30; + private int ans = inf; + private int pre = -inf; public int minDiffInBST(TreeNode root) { - ans = inf; - prev = inf; dfs(root); return ans; } @@ -118,8 +123,8 @@ class Solution { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); } } @@ -141,23 +146,21 @@ class Solution { */ class Solution { public: - const int inf = INT_MAX; - int ans; - int prev; - int minDiffInBST(TreeNode* root) { - ans = inf, prev = inf; - dfs(root); + const int inf = 1 << 30; + int ans = inf, pre = -inf; + auto dfs = [&](auto&& dfs, TreeNode* root) -> void { + if (!root) { + return; + } + dfs(dfs, root->left); + ans = min(ans, root->val - pre); + pre = root->val; + dfs(dfs, root->right); + }; + dfs(dfs, root); return ans; } - - void dfs(TreeNode* root) { - if (!root) return; - dfs(root->left); - ans = min(ans, abs(prev - root->val)); - prev = root->val; - dfs(root->right); - } }; ``` @@ -173,43 +176,125 @@ public: * } */ func minDiffInBST(root *TreeNode) int { - inf := 0x3f3f3f3f - ans, prev := inf, inf + const inf int = 1 << 30 + ans, pre := inf, -inf var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return } dfs(root.Left) - ans = min(ans, abs(prev-root.Val)) - prev = root.Val + ans = min(ans, root.Val-pre) + pre = root.Val dfs(root.Right) } dfs(root) return ans } +``` -func abs(x int) int { - if x < 0 { - return -x - } - return x +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function minDiffInBST(root: TreeNode | null): number { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); + }; + dfs(root); + return ans; +} +``` + +#### Rust + +```rust +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::cell::RefCell; +use std::rc::Rc; +impl Solution { + pub fn min_diff_in_bst(root: Option>>) -> i32 { + const inf: i32 = 1 << 30; + let mut ans = inf; + let mut pre = -inf; + + fn dfs(node: Option>>, ans: &mut i32, pre: &mut i32) { + if let Some(n) = node { + let n = n.borrow(); + dfs(n.left.clone(), ans, pre); + *ans = (*ans).min(n.val - *pre); + *pre = n.val; + dfs(n.right.clone(), ans, pre); + } + } + + dfs(root, &mut ans, &mut pre); + ans + } } ``` #### JavaScript ```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ var minDiffInBST = function (root) { - let ans = Number.MAX_SAFE_INTEGER, - prev = Number.MAX_SAFE_INTEGER; + let [ans, pre] = [Infinity, -Infinity]; const dfs = root => { if (!root) { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); }; dfs(root); diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.cpp b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.cpp index 64c21f404198..9857cb328afc 100644 --- a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.cpp +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.cpp @@ -11,21 +11,19 @@ */ class Solution { public: - const int inf = INT_MAX; - int ans; - int prev; - int minDiffInBST(TreeNode* root) { - ans = inf, prev = inf; - dfs(root); + const int inf = 1 << 30; + int ans = inf, pre = -inf; + auto dfs = [&](auto&& dfs, TreeNode* root) -> void { + if (!root) { + return; + } + dfs(dfs, root->left); + ans = min(ans, root->val - pre); + pre = root->val; + dfs(dfs, root->right); + }; + dfs(dfs, root); return ans; } - - void dfs(TreeNode* root) { - if (!root) return; - dfs(root->left); - ans = min(ans, abs(prev - root->val)); - prev = root->val; - dfs(root->right); - } }; \ No newline at end of file diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.go b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.go index 9182cbbff1ba..194ba212909a 100644 --- a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.go +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.go @@ -7,25 +7,18 @@ * } */ func minDiffInBST(root *TreeNode) int { - inf := 0x3f3f3f3f - ans, prev := inf, inf + const inf int = 1 << 30 + ans, pre := inf, -inf var dfs func(*TreeNode) dfs = func(root *TreeNode) { if root == nil { return } dfs(root.Left) - ans = min(ans, abs(prev-root.Val)) - prev = root.Val + ans = min(ans, root.Val-pre) + pre = root.Val dfs(root.Right) } dfs(root) return ans -} - -func abs(x int) int { - if x < 0 { - return -x - } - return x } \ No newline at end of file diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.java b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.java index 833beeb80409..5eb284d83307 100644 --- a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.java +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.java @@ -14,13 +14,11 @@ * } */ class Solution { - private int ans; - private int prev; - private int inf = Integer.MAX_VALUE; + private final int inf = 1 << 30; + private int ans = inf; + private int pre = -inf; public int minDiffInBST(TreeNode root) { - ans = inf; - prev = inf; dfs(root); return ans; } @@ -30,8 +28,8 @@ private void dfs(TreeNode root) { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); } } \ No newline at end of file diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.js b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.js index bd65098d3ae9..af7b45c90f94 100644 --- a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.js +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.js @@ -1,13 +1,24 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ var minDiffInBST = function (root) { - let ans = Number.MAX_SAFE_INTEGER, - prev = Number.MAX_SAFE_INTEGER; + let [ans, pre] = [Infinity, -Infinity]; const dfs = root => { if (!root) { return; } dfs(root.left); - ans = Math.min(ans, Math.abs(root.val - prev)); - prev = root.val; + ans = Math.min(ans, root.val - pre); + pre = root.val; dfs(root.right); }; dfs(root); diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.py b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.py index 3c538a0621ab..16dae22a1c60 100644 --- a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.py +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.py @@ -6,15 +6,16 @@ # self.right = right class Solution: def minDiffInBST(self, root: Optional[TreeNode]) -> int: - def dfs(root): + def dfs(root: Optional[TreeNode]): if root is None: return dfs(root.left) - nonlocal ans, prev - ans = min(ans, abs(prev - root.val)) - prev = root.val + nonlocal pre, ans + ans = min(ans, root.val - pre) + pre = root.val dfs(root.right) - ans = prev = inf + pre = -inf + ans = inf dfs(root) return ans diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.rs b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.rs new file mode 100644 index 000000000000..691909783076 --- /dev/null +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.rs @@ -0,0 +1,40 @@ +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::cell::RefCell; +use std::rc::Rc; +impl Solution { + pub fn min_diff_in_bst(root: Option>>) -> i32 { + const inf: i32 = 1 << 30; + let mut ans = inf; + let mut pre = -inf; + + fn dfs(node: Option>>, ans: &mut i32, pre: &mut i32) { + if let Some(n) = node { + let n = n.borrow(); + dfs(n.left.clone(), ans, pre); + *ans = (*ans).min(n.val - *pre); + *pre = n.val; + dfs(n.right.clone(), ans, pre); + } + } + + dfs(root, &mut ans, &mut pre); + ans + } +} diff --git a/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.ts b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.ts new file mode 100644 index 000000000000..9568814eb42f --- /dev/null +++ b/solution/0700-0799/0783.Minimum Distance Between BST Nodes/Solution.ts @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function minDiffInBST(root: TreeNode | null): number { + let [ans, pre] = [Infinity, -Infinity]; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; + } + dfs(root.left); + ans = Math.min(ans, root.val - pre); + pre = root.val; + dfs(root.right); + }; + dfs(root); + return ans; +} diff --git a/solution/0700-0799/0787.Cheapest Flights Within K Stops/README.md b/solution/0700-0799/0787.Cheapest Flights Within K Stops/README.md index d2247c9c4731..3a85807862ae 100644 --- a/solution/0700-0799/0787.Cheapest Flights Within K Stops/README.md +++ b/solution/0700-0799/0787.Cheapest Flights Within K Stops/README.md @@ -28,32 +28,36 @@ tags:

     

    示例 1:

    - +
     输入: 
    -n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
    -src = 0, dst = 2, k = 1
    -输出: 200
    -解释: 
    -城市航班图如下
    -
    -
    -从城市 0 到城市 2 在 1 站中转以内的最便宜价格是 200,如图中红色所示。
    +n = 4, flights = [[0,1,100],[1,2,100],[2,0,100],[1,3,600],[2,3,200]], src = 0, dst = 3, k = 1 +输出: 700 +解释: 城市航班图如上 +从城市 0 到城市 3 经过最多 1 站的最佳路径用红色标记,费用为 100 + 600 = 700。 +请注意,通过城市 [0, 1, 2, 3] 的路径更便宜,但无效,因为它经过了 2 站。 +

    示例 2:

    - +
     输入: 
    -n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
    -src = 0, dst = 2, k = 0
    -输出: 500
    +n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 1
    +输出: 200
     解释: 
    -城市航班图如下
    -
    -
    -从城市 0 到城市 2 在 0 站中转以内的最便宜价格是 500,如图中蓝色所示。
    +城市航班图如上 +从城市 0 到城市 2 经过最多 1 站的最佳路径标记为红色,费用为 100 + 100 = 200。 + -

     

    +

    示例 3:

    + +
    +输入:n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 0
    +输出:500
    +解释:
    +城市航班图如上
    +从城市 0 到城市 2 不经过站点的最佳路径标记为红色,费用为 500。
    +

    提示:

    diff --git a/solution/0700-0799/0787.Cheapest Flights Within K Stops/images/995.png b/solution/0700-0799/0787.Cheapest Flights Within K Stops/images/995.png deleted file mode 100644 index af24316fba88..000000000000 Binary files a/solution/0700-0799/0787.Cheapest Flights Within K Stops/images/995.png and /dev/null differ diff --git a/solution/0800-0899/0807.Max Increase to Keep City Skyline/README.md b/solution/0800-0899/0807.Max Increase to Keep City Skyline/README.md index 694dd93284e8..382955b9cae7 100644 --- a/solution/0800-0899/0807.Max Increase to Keep City Skyline/README.md +++ b/solution/0800-0899/0807.Max Increase to Keep City Skyline/README.md @@ -69,11 +69,11 @@ gridNew = [ [8, 4, 8, 7], ### 方法一:贪心 -根据题目描述,我们可以将每个单元格 $(i, j)$ 的值增加至第 $i$ 行的最大值和第 $j$ 列的最大值中的较小值,这样可以保证不影响天际线,即每个单元格增加的高度为 $\min(\text{rowMax}[i], \text{colMax}[j]) - \text{grid}[i][j]$。 +根据题目描述,我们可以将每个单元格 $(i, j)$ 的值增加至第 $i$ 行的最大值和第 $j$ 列的最大值中的较小值,这样可以保证不影响天际线,即每个单元格增加的高度为 $\min(\textit{rowMax}[i], \textit{colMax}[j]) - \textit{grid}[i][j]$。 -因此,我们可以先遍历一次矩阵,分别计算出每行和每列的最大值,记录在数组 $\text{rowMax}$ 和 $\text{colMax}$ 中,然后再遍历一次矩阵,计算出答案即可。 +因此,我们可以先遍历一次矩阵,分别计算出每行和每列的最大值,记录在数组 $\textit{rowMax}$ 和 $\textit{colMax}$ 中,然后再遍历一次矩阵,计算出答案即可。 -时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为矩阵 $\text{grid}$ 的边长。 +时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为矩阵 $\textit{grid}$ 的边长。 diff --git a/solution/0800-0899/0807.Max Increase to Keep City Skyline/README_EN.md b/solution/0800-0899/0807.Max Increase to Keep City Skyline/README_EN.md index 8e7d66a40dac..7aa55968344f 100644 --- a/solution/0800-0899/0807.Max Increase to Keep City Skyline/README_EN.md +++ b/solution/0800-0899/0807.Max Increase to Keep City Skyline/README_EN.md @@ -67,11 +67,11 @@ gridNew = [ [8, 4, 8, 7], ### Solution 1: Greedy -According to the problem description, we can increase the value of each cell $(i, j)$ to the smaller value between the maximum value of the $i$-th row and the $j$-th column, ensuring it does not affect the skyline. Thus, the height added to each cell is $\min(\text{rowMax}[i], \text{colMax}[j]) - \text{grid}[i][j]$. +According to the problem description, we can increase the value of each cell $(i, j)$ to the smaller value between the maximum value of the $i$-th row and the $j$-th column, ensuring it does not affect the skyline. Thus, the height added to each cell is $\min(\textit{rowMax}[i], \textit{colMax}[j]) - \textit{grid}[i][j]$. -Therefore, we can first traverse the matrix once to calculate the maximum value of each row and column, storing them in the arrays $\text{rowMax}$ and $\text{colMax}$, respectively. Then, we traverse the matrix again to compute the answer. +Therefore, we can first traverse the matrix once to calculate the maximum value of each row and column, storing them in the arrays $\textit{rowMax}$ and $\textit{colMax}$, respectively. Then, we traverse the matrix again to compute the answer. -The time complexity is $O(n^2)$, and the space complexity is $O(n)$, where $n$ is the side length of the matrix $\text{grid}$. +The time complexity is $O(n^2)$, and the space complexity is $O(n)$, where $n$ is the side length of the matrix $\textit{grid}$. diff --git a/solution/0800-0899/0813.Largest Sum of Averages/README.md b/solution/0800-0899/0813.Largest Sum of Averages/README.md index 1bf2aa20f898..8d0207f40fc9 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/README.md +++ b/solution/0800-0899/0813.Largest Sum of Averages/README.md @@ -64,17 +64,17 @@ nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 我们可以先预处理得到前缀和数组 $s$,方便快速得到子数组的和。 -然后设计一个函数 $dfs(i, k)$,表示从数组下标 $i$ 开始,最多分成 $k$ 组的最大平均值和。答案为 $dfs(0, k)$。函数 $dfs(i, k)$ 的执行逻辑如下: +接下来,我们设计一个函数 $\textit{dfs}(i, k)$,表示从数组下标 $i$ 开始,最多分成 $k$ 组的最大平均值和。答案为 $\textit{dfs}(0, k)$。 -当 $i=n$ 时,表示已经遍历到数组末尾,此时返回 $0$。 +函数 $\textit{dfs}(i, k)$ 的执行逻辑如下: -当 $k=1$ 时,表示只剩下一组,此时返回从下标 $i$ 开始到数组末尾的平均值。 +当 $i = n$ 时,表示已经遍历到数组末尾,此时返回 $0$。 -否则,我们在 $[i, ..n-1]$ 的范围内枚举分组的结束位置 $j$,计算从下标 $i$ 到下标 $j$ 的平均值,以及从下标 $j+1$ 开始,最多分成 $k-1$ 组的最大平均值和。取其中的最大值作为答案。 +当 $k = 1$ 时,表示只剩下一组,此时返回从下标 $i$ 开始到数组末尾的平均值。 -为了避免重复计算,我们可以用数组 $f$ 记忆化函数 $dfs(i, k)$ 的返回值。 +否则,我们在 $[i + 1, n)$ 的区间内枚举下一个分组的开始位置 $j$,计算从 $i$ 到 $j - 1$ 的平均值 $\frac{s[j] - s[i]}{j - i}$,加上 $\textit{dfs}(j, k - 1)$ 的结果,取所有结果的最大值。 -时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 `nums` 的长度。 +时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。 @@ -84,15 +84,14 @@ nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / class Solution: def largestSumOfAverages(self, nums: List[int], k: int) -> float: @cache - def dfs(i, k): + def dfs(i: int, k: int) -> float: if i == n: return 0 if k == 1: - return (s[-1] - s[i]) / (n - i) + return (s[n] - s[i]) / (n - i) ans = 0 - for j in range(i, n): - t = (s[j + 1] - s[i]) / (j - i + 1) + dfs(j + 1, k - 1) - ans = max(ans, t) + for j in range(i + 1, n): + ans = max(ans, (s[j] - s[i]) / (j - i) + dfs(j, k - 1)) return ans n = len(nums) @@ -111,7 +110,7 @@ class Solution { public double largestSumOfAverages(int[] nums, int k) { n = nums.length; s = new int[n + 1]; - f = new Double[n + 1][k + 1]; + f = new Double[n][k + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } @@ -129,9 +128,8 @@ class Solution { return f[i][k]; } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = Math.max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = Math.max(ans, (s[j] - s[i]) * 1.0 /(j - i) + dfs(j, k - 1)); } return f[i][k] = ans; } @@ -147,21 +145,28 @@ public: int n = nums.size(); int s[n + 1]; double f[n][k + 1]; + memset(f, 0, sizeof(f)); s[0] = 0; - memset(f, 0, sizeof f); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i]; - function dfs = [&](int i, int k) -> double { - if (i == n) return 0; - if (k == 1) return (s[n] - s[i]) * 1.0 / (n - i); - if (f[i][k]) return f[i][k]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + auto dfs = [&](auto&& dfs, int i, int k) -> double { + if (i == n) { + return 0; + } + if (k == 1) { + return (s[n] - s[i]) * 1.0 / (n - i); + } + if (f[i][k] > 0) { + return f[i][k]; + } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(dfs, j, k - 1)); } return f[i][k] = ans; }; - return dfs(0, k); + return dfs(dfs, 0, k); } }; ``` @@ -172,25 +177,27 @@ public: func largestSumOfAverages(nums []int, k int) float64 { n := len(nums) s := make([]int, n+1) - f := [110][110]float64{} - for i, v := range nums { - s[i+1] = s[i] + v + for i, x := range nums { + s[i+1] = s[i] + x } - var dfs func(i, k int) float64 + f := make([][]float64, n) + for i := range f { + f[i] = make([]float64, k+1) + } + var dfs func(int, int) float64 dfs = func(i, k int) float64 { if i == n { return 0 } - if k == 1 { - return float64(s[n]-s[i]) / float64(n-i) - } if f[i][k] > 0 { return f[i][k] } - var ans float64 - for j := i; j < n; j++ { - t := float64(s[j+1]-s[i])/float64(j-i+1) + dfs(j+1, k-1) - ans = math.Max(ans, t) + if k == 1 { + return float64(s[n]-s[i]) / float64(n-i) + } + ans := 0.0 + for j := i + 1; j < n; j++ { + ans = math.Max(ans, float64(s[j]-s[i])/float64(j-i)+dfs(j, k-1)) } f[i][k] = ans return ans @@ -199,6 +206,167 @@ func largestSumOfAverages(nums []int, k int) float64 { } ``` +#### TypeScript + +```ts +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0)); + const dfs = (i: number, k: number): number => { + if (i === n) { + return 0; + } + if (f[i][k] > 0) { + return f[i][k]; + } + if (k === 1) { + return (s[n] - s[i]) / (n - i); + } + for (let j = i + 1; j < n; j++) { + f[i][k] = Math.max(f[i][k], dfs(j, k - 1) + (s[j] - s[i]) / (j - i)); + } + return f[i][k]; + }; + return dfs(0, k); +} +``` + + + + + + + +### 方法二:动态规划 + +我们可以将方法一的记忆化搜索转化为动态规划。 + +定义 $f[i][j]$ 表示数组 $\textit{nums}$ 的前 $i$ 个元素最多分成 $j$ 组的最大平均值和。答案为 $f[n][k]$。 + +对于 $f[i][j]$,我们可以枚举上一组的结束位置 $h$,计算 $f[h][j-1]$,加上 $\frac{s[i]-s[h]}{i-h}$ 的结果,取所有结果的最大值。 + +时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def largestSumOfAverages(self, nums: List[int], k: int) -> float: + n = len(nums) + f = [[0] * (k + 1) for _ in range(n + 1)] + s = list(accumulate(nums, initial=0)) + for i in range(1, n + 1): + f[i][1] = s[i] / i + for j in range(2, min(i + 1, k + 1)): + for h in range(i): + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)) + return f[n][k] +``` + +#### Java + +```java +class Solution { + public double largestSumOfAverages(int[] nums, int k) { + int n = nums.length; + double[][] f = new double[n + 1][k + 1]; + int[] s = new int[n + 1]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= Math.min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + double largestSumOfAverages(vector& nums, int k) { + int n = nums.size(); + int s[n + 1]; + s[0] = 0; + double f[n + 1][k + 1]; + memset(f, 0, sizeof(f)); + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +}; +``` + +#### Go + +```go +func largestSumOfAverages(nums []int, k int) float64 { + n := len(nums) + s := make([]int, n+1) + for i, x := range nums { + s[i+1] = s[i] + x + } + f := make([][]float64, n+1) + for i := range f { + f[i] = make([]float64, k+1) + } + for i := 1; i <= n; i++ { + f[i][1] = float64(s[i]) / float64(i) + for j := 2; j <= min(i, k); j++ { + for h := 0; h < i; h++ { + f[i][j] = max(f[i][j], f[h][j-1]+float64(s[i]-s[h])/float64(i-h)) + } + } + } + return f[n][k] +} +``` + +#### TypeScript + +```ts +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0)); + for (let i = 1; i <= n; ++i) { + f[i][1] = s[i] / i; + for (let j = 2; j <= Math.min(i, k); ++j) { + for (let h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)); + } + } + } + return f[n][k]; +} +``` + diff --git a/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md b/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md index 6621ed69ee8f..5b9f70f25a4c 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md +++ b/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md @@ -58,7 +58,19 @@ That partition would lead to a score of 5 + 2 + 6 = 13, which is worse. -### Solution 1 +### Solution 1: Prefix Sum + Memoized Search + +We can preprocess to obtain the prefix sum array $s$, which allows us to quickly get the sum of subarrays. + +Next, we design a function $\textit{dfs}(i, k)$, which represents the maximum sum of averages when dividing the array starting from index $i$ into at most $k$ groups. The answer is $\textit{dfs}(0, k)$. + +The execution logic of the function $\textit{dfs}(i, k)$ is as follows: + +- When $i = n$, it means we have traversed to the end of the array, and we return $0$. +- When $k = 1$, it means there is only one group left, and we return the average value from index $i$ to the end of the array. +- Otherwise, we enumerate the starting position $j$ of the next group in the interval $[i + 1, n)$, calculate the average value from $i$ to $j - 1$ as $\frac{s[j] - s[i]}{j - i}$, add the result of $\textit{dfs}(j, k - 1)$, and take the maximum value of all results. + +The time complexity is $O(n^2 \times k)$, and the space complexity is $O(n \times k)$. Here, $n$ represents the length of the array $\textit{nums}$. @@ -68,15 +80,14 @@ That partition would lead to a score of 5 + 2 + 6 = 13, which is worse. class Solution: def largestSumOfAverages(self, nums: List[int], k: int) -> float: @cache - def dfs(i, k): + def dfs(i: int, k: int) -> float: if i == n: return 0 if k == 1: - return (s[-1] - s[i]) / (n - i) + return (s[n] - s[i]) / (n - i) ans = 0 - for j in range(i, n): - t = (s[j + 1] - s[i]) / (j - i + 1) + dfs(j + 1, k - 1) - ans = max(ans, t) + for j in range(i + 1, n): + ans = max(ans, (s[j] - s[i]) / (j - i) + dfs(j, k - 1)) return ans n = len(nums) @@ -95,7 +106,7 @@ class Solution { public double largestSumOfAverages(int[] nums, int k) { n = nums.length; s = new int[n + 1]; - f = new Double[n + 1][k + 1]; + f = new Double[n][k + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } @@ -113,9 +124,8 @@ class Solution { return f[i][k]; } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = Math.max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = Math.max(ans, (s[j] - s[i]) * 1.0 /(j - i) + dfs(j, k - 1)); } return f[i][k] = ans; } @@ -131,21 +141,28 @@ public: int n = nums.size(); int s[n + 1]; double f[n][k + 1]; + memset(f, 0, sizeof(f)); s[0] = 0; - memset(f, 0, sizeof f); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i]; - function dfs = [&](int i, int k) -> double { - if (i == n) return 0; - if (k == 1) return (s[n] - s[i]) * 1.0 / (n - i); - if (f[i][k]) return f[i][k]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + auto dfs = [&](auto&& dfs, int i, int k) -> double { + if (i == n) { + return 0; + } + if (k == 1) { + return (s[n] - s[i]) * 1.0 / (n - i); + } + if (f[i][k] > 0) { + return f[i][k]; + } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(dfs, j, k - 1)); } return f[i][k] = ans; }; - return dfs(0, k); + return dfs(dfs, 0, k); } }; ``` @@ -156,25 +173,27 @@ public: func largestSumOfAverages(nums []int, k int) float64 { n := len(nums) s := make([]int, n+1) - f := [110][110]float64{} - for i, v := range nums { - s[i+1] = s[i] + v + for i, x := range nums { + s[i+1] = s[i] + x + } + f := make([][]float64, n) + for i := range f { + f[i] = make([]float64, k+1) } - var dfs func(i, k int) float64 + var dfs func(int, int) float64 dfs = func(i, k int) float64 { if i == n { return 0 } - if k == 1 { - return float64(s[n]-s[i]) / float64(n-i) - } if f[i][k] > 0 { return f[i][k] } - var ans float64 - for j := i; j < n; j++ { - t := float64(s[j+1]-s[i])/float64(j-i+1) + dfs(j+1, k-1) - ans = math.Max(ans, t) + if k == 1 { + return float64(s[n]-s[i]) / float64(n-i) + } + ans := 0.0 + for j := i + 1; j < n; j++ { + ans = math.Max(ans, float64(s[j]-s[i])/float64(j-i)+dfs(j, k-1)) } f[i][k] = ans return ans @@ -183,6 +202,167 @@ func largestSumOfAverages(nums []int, k int) float64 { } ``` +#### TypeScript + +```ts +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0)); + const dfs = (i: number, k: number): number => { + if (i === n) { + return 0; + } + if (f[i][k] > 0) { + return f[i][k]; + } + if (k === 1) { + return (s[n] - s[i]) / (n - i); + } + for (let j = i + 1; j < n; j++) { + f[i][k] = Math.max(f[i][k], dfs(j, k - 1) + (s[j] - s[i]) / (j - i)); + } + return f[i][k]; + }; + return dfs(0, k); +} +``` + + + + + + + +### Solution 2: Dynamic Programming + +We can transform the memoized search from Solution 1 into dynamic programming. + +Define $f[i][j]$ to represent the maximum sum of averages when dividing the first $i$ elements of the array $\textit{nums}$ into at most $j$ groups. The answer is $f[n][k]$. + +For $f[i][j]$, we can enumerate the end position $h$ of the previous group, calculate $f[h][j-1]$, add the result of $\frac{s[i] - s[h]}{i - h}$, and take the maximum value of all results. + +The time complexity is $O(n^2 \times k)$, and the space complexity is $O(n \times k)$. Here, $n$ represents the length of the array $\textit{nums}$. + + + +#### Python3 + +```python +class Solution: + def largestSumOfAverages(self, nums: List[int], k: int) -> float: + n = len(nums) + f = [[0] * (k + 1) for _ in range(n + 1)] + s = list(accumulate(nums, initial=0)) + for i in range(1, n + 1): + f[i][1] = s[i] / i + for j in range(2, min(i + 1, k + 1)): + for h in range(i): + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)) + return f[n][k] +``` + +#### Java + +```java +class Solution { + public double largestSumOfAverages(int[] nums, int k) { + int n = nums.length; + double[][] f = new double[n + 1][k + 1]; + int[] s = new int[n + 1]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= Math.min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + double largestSumOfAverages(vector& nums, int k) { + int n = nums.size(); + int s[n + 1]; + s[0] = 0; + double f[n + 1][k + 1]; + memset(f, 0, sizeof(f)); + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +}; +``` + +#### Go + +```go +func largestSumOfAverages(nums []int, k int) float64 { + n := len(nums) + s := make([]int, n+1) + for i, x := range nums { + s[i+1] = s[i] + x + } + f := make([][]float64, n+1) + for i := range f { + f[i] = make([]float64, k+1) + } + for i := 1; i <= n; i++ { + f[i][1] = float64(s[i]) / float64(i) + for j := 2; j <= min(i, k); j++ { + for h := 0; h < i; h++ { + f[i][j] = max(f[i][j], f[h][j-1]+float64(s[i]-s[h])/float64(i-h)) + } + } + } + return f[n][k] +} +``` + +#### TypeScript + +```ts +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0)); + for (let i = 1; i <= n; ++i) { + f[i][1] = s[i] / i; + for (let j = 2; j <= Math.min(i, k); ++j) { + for (let h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)); + } + } + } + return f[n][k]; +} +``` + diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp b/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp index c790ce7f33a7..77d5123dbd61 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp @@ -4,20 +4,27 @@ class Solution { int n = nums.size(); int s[n + 1]; double f[n][k + 1]; + memset(f, 0, sizeof(f)); s[0] = 0; - memset(f, 0, sizeof f); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i]; - function dfs = [&](int i, int k) -> double { - if (i == n) return 0; - if (k == 1) return (s[n] - s[i]) * 1.0 / (n - i); - if (f[i][k]) return f[i][k]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + auto dfs = [&](auto&& dfs, int i, int k) -> double { + if (i == n) { + return 0; + } + if (k == 1) { + return (s[n] - s[i]) * 1.0 / (n - i); + } + if (f[i][k] > 0) { + return f[i][k]; + } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(dfs, j, k - 1)); } return f[i][k] = ans; }; - return dfs(0, k); + return dfs(dfs, 0, k); } -}; \ No newline at end of file +}; diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.go b/solution/0800-0899/0813.Largest Sum of Averages/Solution.go index 52f7f8ff4d65..e6d5d0eebe97 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.go +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.go @@ -1,28 +1,30 @@ func largestSumOfAverages(nums []int, k int) float64 { n := len(nums) s := make([]int, n+1) - f := [110][110]float64{} - for i, v := range nums { - s[i+1] = s[i] + v + for i, x := range nums { + s[i+1] = s[i] + x } - var dfs func(i, k int) float64 + f := make([][]float64, n) + for i := range f { + f[i] = make([]float64, k+1) + } + var dfs func(int, int) float64 dfs = func(i, k int) float64 { if i == n { return 0 } - if k == 1 { - return float64(s[n]-s[i]) / float64(n-i) - } if f[i][k] > 0 { return f[i][k] } - var ans float64 - for j := i; j < n; j++ { - t := float64(s[j+1]-s[i])/float64(j-i+1) + dfs(j+1, k-1) - ans = math.Max(ans, t) + if k == 1 { + return float64(s[n]-s[i]) / float64(n-i) + } + ans := 0.0 + for j := i + 1; j < n; j++ { + ans = math.Max(ans, float64(s[j]-s[i])/float64(j-i)+dfs(j, k-1)) } f[i][k] = ans return ans } return dfs(0, k) -} \ No newline at end of file +} diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.java b/solution/0800-0899/0813.Largest Sum of Averages/Solution.java index 4599ee5a7420..7b8e6f0e688d 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.java +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.java @@ -6,7 +6,7 @@ class Solution { public double largestSumOfAverages(int[] nums, int k) { n = nums.length; s = new int[n + 1]; - f = new Double[n + 1][k + 1]; + f = new Double[n][k + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } @@ -24,10 +24,9 @@ private double dfs(int i, int k) { return f[i][k]; } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = Math.max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = Math.max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(j, k - 1)); } return f[i][k] = ans; } -} \ No newline at end of file +} diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.py b/solution/0800-0899/0813.Largest Sum of Averages/Solution.py index 5f255b46bb0d..a27a4452c21a 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.py +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.py @@ -1,15 +1,14 @@ class Solution: def largestSumOfAverages(self, nums: List[int], k: int) -> float: @cache - def dfs(i, k): + def dfs(i: int, k: int) -> float: if i == n: return 0 if k == 1: - return (s[-1] - s[i]) / (n - i) + return (s[n] - s[i]) / (n - i) ans = 0 - for j in range(i, n): - t = (s[j + 1] - s[i]) / (j - i + 1) + dfs(j + 1, k - 1) - ans = max(ans, t) + for j in range(i + 1, n): + ans = max(ans, (s[j] - s[i]) / (j - i) + dfs(j, k - 1)) return ans n = len(nums) diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.ts b/solution/0800-0899/0813.Largest Sum of Averages/Solution.ts new file mode 100644 index 000000000000..4cb7a0c18208 --- /dev/null +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.ts @@ -0,0 +1,24 @@ +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0)); + const dfs = (i: number, k: number): number => { + if (i === n) { + return 0; + } + if (f[i][k] > 0) { + return f[i][k]; + } + if (k === 1) { + return (s[n] - s[i]) / (n - i); + } + for (let j = i + 1; j < n; j++) { + f[i][k] = Math.max(f[i][k], dfs(j, k - 1) + (s[j] - s[i]) / (j - i)); + } + return f[i][k]; + }; + return dfs(0, k); +} diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.cpp b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.cpp new file mode 100644 index 000000000000..b63c0a7992fe --- /dev/null +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.cpp @@ -0,0 +1,22 @@ +class Solution { +public: + double largestSumOfAverages(vector& nums, int k) { + int n = nums.size(); + int s[n + 1]; + s[0] = 0; + double f[n + 1][k + 1]; + memset(f, 0, sizeof(f)); + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +}; diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.go b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.go new file mode 100644 index 000000000000..d41dde665aa9 --- /dev/null +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.go @@ -0,0 +1,20 @@ +func largestSumOfAverages(nums []int, k int) float64 { + n := len(nums) + s := make([]int, n+1) + for i, x := range nums { + s[i+1] = s[i] + x + } + f := make([][]float64, n+1) + for i := range f { + f[i] = make([]float64, k+1) + } + for i := 1; i <= n; i++ { + f[i][1] = float64(s[i]) / float64(i) + for j := 2; j <= min(i, k); j++ { + for h := 0; h < i; h++ { + f[i][j] = max(f[i][j], f[h][j-1]+float64(s[i]-s[h])/float64(i-h)) + } + } + } + return f[n][k] +} diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.java b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.java new file mode 100644 index 000000000000..0baacbd295be --- /dev/null +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.java @@ -0,0 +1,19 @@ +class Solution { + public double largestSumOfAverages(int[] nums, int k) { + int n = nums.length; + double[][] f = new double[n + 1][k + 1]; + int[] s = new int[n + 1]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= Math.min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +} diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.py b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.py new file mode 100644 index 000000000000..0f4681532b11 --- /dev/null +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.py @@ -0,0 +1,11 @@ +class Solution: + def largestSumOfAverages(self, nums: List[int], k: int) -> float: + n = len(nums) + f = [[0] * (k + 1) for _ in range(n + 1)] + s = list(accumulate(nums, initial=0)) + for i in range(1, n + 1): + f[i][1] = s[i] / i + for j in range(2, min(i + 1, k + 1)): + for h in range(i): + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)) + return f[n][k] diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.ts b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.ts new file mode 100644 index 000000000000..245b54632dac --- /dev/null +++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.ts @@ -0,0 +1,17 @@ +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0)); + for (let i = 1; i <= n; ++i) { + f[i][1] = s[i] / i; + for (let j = 2; j <= Math.min(i, k); ++j) { + for (let h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)); + } + } + } + return f[n][k]; +} diff --git a/solution/0800-0899/0814.Binary Tree Pruning/README.md b/solution/0800-0899/0814.Binary Tree Pruning/README.md index e305386216d6..b20f50170db9 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/README.md +++ b/solution/0800-0899/0814.Binary Tree Pruning/README.md @@ -64,9 +64,13 @@ tags: -### 方法一:DFS +### 方法一:递归 -观察叶节点,当叶节点 `val` 为 0 时,便将该节点抹去。回溯,查看其父节点是否成为了新的叶节点,依照此规则自底向上。 +我们首先判断当前节点是否为空,如果为空则直接返回空节点。 + +否则,我们递归地对左右子树进行剪枝,并将剪枝后的左右子树重新赋值给当前节点的左右子节点。然后判断当前节点的值是否为 0 且左右子节点都为空,如果是则返回空节点,否则返回当前节点。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点个数。 @@ -82,10 +86,10 @@ tags: class Solution: def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: - return None + return root root.left = self.pruneTree(root.left) root.right = self.pruneTree(root.right) - if root.val == 0 and root.left is None and root.right is None: + if root.val == 0 and root.left == root.right: return None return root ``` @@ -140,10 +144,14 @@ class Solution { class Solution { public: TreeNode* pruneTree(TreeNode* root) { - if (!root) return nullptr; + if (!root) { + return root; + } root->left = pruneTree(root->left); root->right = pruneTree(root->right); - if (!root->val && !root->left && !root->right) return nullptr; + if (root->val == 0 && root->left == root->right) { + return nullptr; + } return root; } }; @@ -191,12 +199,12 @@ func pruneTree(root *TreeNode) *TreeNode { */ function pruneTree(root: TreeNode | null): TreeNode | null { - if (root == null) { + if (!root) { return root; } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && root.left == null && root.right == null) { + if (root.val === 0 && root.left === root.right) { return null; } return root; @@ -262,10 +270,12 @@ impl Solution { * @return {TreeNode} */ var pruneTree = function (root) { - if (!root) return null; + if (!root) { + return root; + } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && !root.left && !root.right) { + if (root.val === 0 && root.left === root.right) { return null; } return root; diff --git a/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md b/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md index 39d06266717c..85236c909250 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md +++ b/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md @@ -61,7 +61,13 @@ The diagram on the right represents the answer. -### Solution 1 +### Solution 1: Recursion + +First, we check if the current node is null. If it is, we directly return the null node. + +Otherwise, we recursively prune the left and right subtrees and reassign the pruned subtrees to the current node's left and right children. Then, we check if the current node's value is 0 and both its left and right children are null. If so, we return the null node; otherwise, we return the current node. + +Time complexity is $O(n)$, and space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -77,10 +83,10 @@ The diagram on the right represents the answer. class Solution: def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: - return None + return root root.left = self.pruneTree(root.left) root.right = self.pruneTree(root.right) - if root.val == 0 and root.left is None and root.right is None: + if root.val == 0 and root.left == root.right: return None return root ``` @@ -135,10 +141,14 @@ class Solution { class Solution { public: TreeNode* pruneTree(TreeNode* root) { - if (!root) return nullptr; + if (!root) { + return root; + } root->left = pruneTree(root->left); root->right = pruneTree(root->right); - if (!root->val && !root->left && !root->right) return nullptr; + if (root->val == 0 && root->left == root->right) { + return nullptr; + } return root; } }; @@ -186,12 +196,12 @@ func pruneTree(root *TreeNode) *TreeNode { */ function pruneTree(root: TreeNode | null): TreeNode | null { - if (root == null) { + if (!root) { return root; } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && root.left == null && root.right == null) { + if (root.val === 0 && root.left === root.right) { return null; } return root; @@ -257,10 +267,12 @@ impl Solution { * @return {TreeNode} */ var pruneTree = function (root) { - if (!root) return null; + if (!root) { + return root; + } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && !root.left && !root.right) { + if (root.val === 0 && root.left === root.right) { return null; } return root; diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp b/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp index a9f3cf3538d7..3affab559427 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp @@ -12,10 +12,14 @@ class Solution { public: TreeNode* pruneTree(TreeNode* root) { - if (!root) return nullptr; + if (!root) { + return root; + } root->left = pruneTree(root->left); root->right = pruneTree(root->right); - if (!root->val && !root->left && !root->right) return nullptr; + if (root->val == 0 && root->left == root->right) { + return nullptr; + } return root; } -}; \ No newline at end of file +}; diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.js b/solution/0800-0899/0814.Binary Tree Pruning/Solution.js index 402f8916795d..af8b610f2032 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.js +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.js @@ -11,10 +11,12 @@ * @return {TreeNode} */ var pruneTree = function (root) { - if (!root) return null; + if (!root) { + return root; + } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && !root.left && !root.right) { + if (root.val === 0 && root.left === root.right) { return null; } return root; diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.py b/solution/0800-0899/0814.Binary Tree Pruning/Solution.py index 339d237429ba..68e16641aff5 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.py +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.py @@ -7,9 +7,9 @@ class Solution: def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: - return None + return root root.left = self.pruneTree(root.left) root.right = self.pruneTree(root.right) - if root.val == 0 and root.left is None and root.right is None: + if root.val == 0 and root.left == root.right: return None return root diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts b/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts index 115665c66a60..b85a17d0dfe9 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts @@ -13,12 +13,12 @@ */ function pruneTree(root: TreeNode | null): TreeNode | null { - if (root == null) { + if (!root) { return root; } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && root.left == null && root.right == null) { + if (root.val === 0 && root.left === root.right) { return null; } return root; diff --git a/solution/0800-0899/0826.Most Profit Assigning Work/README.md b/solution/0800-0899/0826.Most Profit Assigning Work/README.md index 468f898113a8..1926bc576fe8 100644 --- a/solution/0800-0899/0826.Most Profit Assigning Work/README.md +++ b/solution/0800-0899/0826.Most Profit Assigning Work/README.md @@ -194,7 +194,7 @@ function maxProfitAssignment(difficulty: number[], profit: number[], worker: num ### 方法二:动态规划 -我们不妨记 $m = \max(\text{difficulty})$,定义一个长度为 $m + 1$ 的数组 $f$,其中 $f[i]$ 表示难度小于等于 $i$ 的工作中收益的最大值,初始时 $f[i] = 0$。 +我们不妨记 $m = \max(\textit{difficulty})$,定义一个长度为 $m + 1$ 的数组 $f$,其中 $f[i]$ 表示难度小于等于 $i$ 的工作中收益的最大值,初始时 $f[i] = 0$。 然后我们遍历工作,对于每个工作 $(d, p)$,我们更新 $f[d] = \max(f[d], p)$。 diff --git a/solution/0800-0899/0826.Most Profit Assigning Work/README_EN.md b/solution/0800-0899/0826.Most Profit Assigning Work/README_EN.md index d9edd25f594f..2a3b780e574a 100644 --- a/solution/0800-0899/0826.Most Profit Assigning Work/README_EN.md +++ b/solution/0800-0899/0826.Most Profit Assigning Work/README_EN.md @@ -194,7 +194,7 @@ function maxProfitAssignment(difficulty: number[], profit: number[], worker: num ### Solution 2: Dynamic Programming -Let's denote $m = \max(\text{difficulty})$ and define an array $f$ of length $m + 1$, where $f[i]$ represents the maximum profit among jobs with difficulty less than or equal to $i$, initially $f[i] = 0$. +Let's denote $m = \max(\textit{difficulty})$ and define an array $f$ of length $m + 1$, where $f[i]$ represents the maximum profit among jobs with difficulty less than or equal to $i$, initially $f[i] = 0$. Then, we iterate over the jobs, and for each job $(d, p)$, if $d \leq m$, we update $f[d] = \max(f[d], p)$. diff --git a/solution/0800-0899/0833.Find And Replace in String/README.md b/solution/0800-0899/0833.Find And Replace in String/README.md index fe2b0624dbac..b9ec81c138b2 100644 --- a/solution/0800-0899/0833.Find And Replace in String/README.md +++ b/solution/0800-0899/0833.Find And Replace in String/README.md @@ -4,6 +4,7 @@ difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0800-0899/0833.Find%20And%20Replace%20in%20String/README.md tags: - 数组 + - 哈希表 - 字符串 - 排序 --- diff --git a/solution/0800-0899/0833.Find And Replace in String/README_EN.md b/solution/0800-0899/0833.Find And Replace in String/README_EN.md index b6258aeed9e0..069120db7734 100644 --- a/solution/0800-0899/0833.Find And Replace in String/README_EN.md +++ b/solution/0800-0899/0833.Find And Replace in String/README_EN.md @@ -4,6 +4,7 @@ difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/0800-0899/0833.Find%20And%20Replace%20in%20String/README_EN.md tags: - Array + - Hash Table - String - Sorting --- diff --git a/solution/0800-0899/0839.Similar String Groups/README.md b/solution/0800-0899/0839.Similar String Groups/README.md index 5241ffdb57e6..04de423deb65 100644 --- a/solution/0800-0899/0839.Similar String Groups/README.md +++ b/solution/0800-0899/0839.Similar String Groups/README.md @@ -62,73 +62,111 @@ tags: -### 方法一 +### 方法一:并查集 + +我们可以枚举字符串列表中的任意两个字符串 $s$ 和 $t$,由于 $s$ 和 $t$ 是字母异位词,因此如果 $s$ 和 $t$ 的对应位置字符不同的数量不超过 $2$,那么 $s$ 和 $t$ 是相似的,我们就可以使用并查集将 $s$ 和 $t$ 合并,如果合并成功,那么相似字符串组的数量减少 $1$。 + +最终相似字符串组的数量就是并查集中连通分量的数量。 + +时间复杂度 $O(n^2 \times (m + \alpha(n)))$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是字符串列表的长度和字符串的长度,而 $\alpha(n)$ 是 Ackermann 函数的反函数,可以看成是一个很小的常数。 #### Python3 ```python +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + class Solution: def numSimilarGroups(self, strs: List[str]) -> int: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] - - n, l = len(strs), len(strs[0]) - p = list(range(n)) - for i in range(n): - for j in range(i + 1, n): - if sum(strs[i][k] != strs[j][k] for k in range(l)) <= 2: - p[find(i)] = find(j) - return sum(i == find(i) for i in range(n)) + n, m = len(strs), len(strs[0]) + uf = UnionFind(n) + for i, s in enumerate(strs): + for j, t in enumerate(strs[:i]): + if sum(s[k] != t[k] for k in range(m)) <= 2 and uf.union(i, j): + n -= 1 + return n ``` #### Java ```java -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; - public int numSimilarGroups(String[] strs) { - int n = strs.length; + public UnionFind(int n) { p = new int[n]; + size = new int[n]; for (int i = 0; i < n; ++i) { p[i] = i; + size[i] = 1; } - for (int i = 0; i < n; ++i) { - for (int j = i + 1; j < n; ++j) { - if (check(strs[i], strs[j])) { - p[find(i)] = find(j); - } - } - } - int res = 0; - for (int i = 0; i < n; ++i) { - if (i == find(i)) { - ++res; - } + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); } - return res; + return p[x]; } - private boolean check(String a, String b) { - int cnt = 0; - int n = a.length(); - for (int i = 0; i < n; ++i) { - if (a.charAt(i) != b.charAt(i)) { - ++cnt; - } + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; } - return cnt <= 2; + return true; } +} - private int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); +class Solution { + public int numSimilarGroups(String[] strs) { + int n = strs.length, m = strs[0].length(); + UnionFind uf = new UnionFind(n); + int cnt = n; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + int diff = 0; + for (int k = 0; k < m; ++k) { + if (strs[i].charAt(k) != strs[j].charAt(k)) { + ++diff; + } + } + if (diff <= 2 && uf.union(i, j)) { + --cnt; + } + } } - return p[x]; + return cnt; } } ``` @@ -136,79 +174,176 @@ class Solution { #### C++ ```cpp -class Solution { +class UnionFind { public: - vector p; - - int numSimilarGroups(vector& strs) { - int n = strs.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - for (int i = 0; i < n; ++i) - for (int j = i + 1; j < n; ++j) - if (check(strs[i], strs[j])) - p[find(i)] = find(j); - int ans = 0; - for (int i = 0; i < n; ++i) - if (i == find(i)) - ++ans; - return ans; + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); } - bool check(string a, string b) { - int cnt = 0; - for (int i = 0; i < a.size(); ++i) - if (a[i] != b[i]) - ++cnt; - return cnt <= 2; + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; } int find(int x) { - if (p[x] != x) p[x] = find(p[x]); + if (p[x] != x) { + p[x] = find(p[x]); + } return p[x]; } + +private: + vector p, size; +}; + +class Solution { +public: + int numSimilarGroups(vector& strs) { + int n = strs.size(), m = strs[0].size(); + int cnt = n; + UnionFind uf(n); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + int diff = 0; + for (int k = 0; k < m; ++k) { + diff += strs[i][k] != strs[j][k]; + } + if (diff <= 2 && uf.unite(i, j)) { + --cnt; + } + } + } + return cnt; + } }; ``` #### Go ```go -func numSimilarGroups(strs []string) int { - n := len(strs) +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { p := make([]int, n) + size := make([]int, n) for i := range p { p[i] = i + size[i] = 1 } - check := func(a, b string) bool { - cnt := 0 - for i := range a { - if a[i] != b[i] { - cnt++ - } - } - return cnt <= 2 + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) } - var find func(x int) int - find = func(x int) int { - if p[x] != x { - p[x] = find(p[x]) - } - return p[x] + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false } - for i := 0; i < n; i++ { - for j := i + 1; j < n; j++ { - if check(strs[i], strs[j]) { - p[find(i)] = find(j) - } - } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] } - ans := 0 - for i := 0; i < n; i++ { - if i == find(i) { - ans++ + return true +} + +func numSimilarGroups(strs []string) int { + n := len(strs) + uf := newUnionFind(n) + for i, s := range strs { + for j, t := range strs[:i] { + diff := 0 + for k := range s { + if s[k] != t[k] { + diff++ + } + } + if diff <= 2 && uf.union(i, j) { + n-- + } } } - return ans + return n +} +``` + +#### TypeScript + +```ts +class UnionFind { + private p: number[]; + private size: number[]; + + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + union(a: number, b: number): boolean { + const pa = this.find(a); + const pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } +} + +function numSimilarGroups(strs: string[]): number { + const n = strs.length; + const m = strs[0].length; + const uf = new UnionFind(n); + let cnt = n; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + let diff = 0; + for (let k = 0; k < m; ++k) { + if (strs[i][k] !== strs[j][k]) { + diff++; + } + } + if (diff <= 2 && uf.union(i, j)) { + cnt--; + } + } + } + return cnt; } ``` diff --git a/solution/0800-0899/0839.Similar String Groups/README_EN.md b/solution/0800-0899/0839.Similar String Groups/README_EN.md index 2efdadf25323..05324e77ccdc 100644 --- a/solution/0800-0899/0839.Similar String Groups/README_EN.md +++ b/solution/0800-0899/0839.Similar String Groups/README_EN.md @@ -60,73 +60,111 @@ tags: -### Solution 1 +### Solution 1: Union-Find + +We can enumerate any two strings $s$ and $t$ in the list of strings. Since $s$ and $t$ are anagrams, if the number of differing characters at corresponding positions between $s$ and $t$ does not exceed $2$, then $s$ and $t$ are similar. We can use the union-find data structure to merge $s$ and $t$. If the merge is successful, the number of similar string groups decreases by $1$. + +The final number of similar string groups is the number of connected components in the union-find structure. + +Time complexity is $O(n^2 \times (m + \alpha(n)))$, and space complexity is $O(n)$. Here, $n$ and $m$ are the length of the list of strings and the length of the strings, respectively, and $\alpha(n)$ is the inverse Ackermann function, which can be considered a very small constant. #### Python3 ```python +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + class Solution: def numSimilarGroups(self, strs: List[str]) -> int: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] - - n, l = len(strs), len(strs[0]) - p = list(range(n)) - for i in range(n): - for j in range(i + 1, n): - if sum(strs[i][k] != strs[j][k] for k in range(l)) <= 2: - p[find(i)] = find(j) - return sum(i == find(i) for i in range(n)) + n, m = len(strs), len(strs[0]) + uf = UnionFind(n) + for i, s in enumerate(strs): + for j, t in enumerate(strs[:i]): + if sum(s[k] != t[k] for k in range(m)) <= 2 and uf.union(i, j): + n -= 1 + return n ``` #### Java ```java -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; - public int numSimilarGroups(String[] strs) { - int n = strs.length; + public UnionFind(int n) { p = new int[n]; + size = new int[n]; for (int i = 0; i < n; ++i) { p[i] = i; + size[i] = 1; } - for (int i = 0; i < n; ++i) { - for (int j = i + 1; j < n; ++j) { - if (check(strs[i], strs[j])) { - p[find(i)] = find(j); - } - } - } - int res = 0; - for (int i = 0; i < n; ++i) { - if (i == find(i)) { - ++res; - } + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); } - return res; + return p[x]; } - private boolean check(String a, String b) { - int cnt = 0; - int n = a.length(); - for (int i = 0; i < n; ++i) { - if (a.charAt(i) != b.charAt(i)) { - ++cnt; - } + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; } - return cnt <= 2; + return true; } +} - private int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); +class Solution { + public int numSimilarGroups(String[] strs) { + int n = strs.length, m = strs[0].length(); + UnionFind uf = new UnionFind(n); + int cnt = n; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + int diff = 0; + for (int k = 0; k < m; ++k) { + if (strs[i].charAt(k) != strs[j].charAt(k)) { + ++diff; + } + } + if (diff <= 2 && uf.union(i, j)) { + --cnt; + } + } } - return p[x]; + return cnt; } } ``` @@ -134,79 +172,176 @@ class Solution { #### C++ ```cpp -class Solution { +class UnionFind { public: - vector p; - - int numSimilarGroups(vector& strs) { - int n = strs.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - for (int i = 0; i < n; ++i) - for (int j = i + 1; j < n; ++j) - if (check(strs[i], strs[j])) - p[find(i)] = find(j); - int ans = 0; - for (int i = 0; i < n; ++i) - if (i == find(i)) - ++ans; - return ans; + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); } - bool check(string a, string b) { - int cnt = 0; - for (int i = 0; i < a.size(); ++i) - if (a[i] != b[i]) - ++cnt; - return cnt <= 2; + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; } int find(int x) { - if (p[x] != x) p[x] = find(p[x]); + if (p[x] != x) { + p[x] = find(p[x]); + } return p[x]; } + +private: + vector p, size; +}; + +class Solution { +public: + int numSimilarGroups(vector& strs) { + int n = strs.size(), m = strs[0].size(); + int cnt = n; + UnionFind uf(n); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + int diff = 0; + for (int k = 0; k < m; ++k) { + diff += strs[i][k] != strs[j][k]; + } + if (diff <= 2 && uf.unite(i, j)) { + --cnt; + } + } + } + return cnt; + } }; ``` #### Go ```go -func numSimilarGroups(strs []string) int { - n := len(strs) +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { p := make([]int, n) + size := make([]int, n) for i := range p { p[i] = i + size[i] = 1 } - check := func(a, b string) bool { - cnt := 0 - for i := range a { - if a[i] != b[i] { - cnt++ - } - } - return cnt <= 2 + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) } - var find func(x int) int - find = func(x int) int { - if p[x] != x { - p[x] = find(p[x]) - } - return p[x] + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false } - for i := 0; i < n; i++ { - for j := i + 1; j < n; j++ { - if check(strs[i], strs[j]) { - p[find(i)] = find(j) - } - } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] } - ans := 0 - for i := 0; i < n; i++ { - if i == find(i) { - ans++ + return true +} + +func numSimilarGroups(strs []string) int { + n := len(strs) + uf := newUnionFind(n) + for i, s := range strs { + for j, t := range strs[:i] { + diff := 0 + for k := range s { + if s[k] != t[k] { + diff++ + } + } + if diff <= 2 && uf.union(i, j) { + n-- + } } } - return ans + return n +} +``` + +#### TypeScript + +```ts +class UnionFind { + private p: number[]; + private size: number[]; + + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + union(a: number, b: number): boolean { + const pa = this.find(a); + const pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } +} + +function numSimilarGroups(strs: string[]): number { + const n = strs.length; + const m = strs[0].length; + const uf = new UnionFind(n); + let cnt = n; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + let diff = 0; + for (let k = 0; k < m; ++k) { + if (strs[i][k] !== strs[j][k]) { + diff++; + } + } + if (diff <= 2 && uf.union(i, j)) { + cnt--; + } + } + } + return cnt; } ``` diff --git a/solution/0800-0899/0839.Similar String Groups/Solution.cpp b/solution/0800-0899/0839.Similar String Groups/Solution.cpp index fd8d47e0f343..58d60374ca97 100644 --- a/solution/0800-0899/0839.Similar String Groups/Solution.cpp +++ b/solution/0800-0899/0839.Similar String Groups/Solution.cpp @@ -1,32 +1,54 @@ -class Solution { +class UnionFind { public: - vector p; - - int numSimilarGroups(vector& strs) { - int n = strs.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - for (int i = 0; i < n; ++i) - for (int j = i + 1; j < n; ++j) - if (check(strs[i], strs[j])) - p[find(i)] = find(j); - int ans = 0; - for (int i = 0; i < n; ++i) - if (i == find(i)) - ++ans; - return ans; + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); } - bool check(string a, string b) { - int cnt = 0; - for (int i = 0; i < a.size(); ++i) - if (a[i] != b[i]) - ++cnt; - return cnt <= 2; + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; } int find(int x) { - if (p[x] != x) p[x] = find(p[x]); + if (p[x] != x) { + p[x] = find(p[x]); + } return p[x]; } -}; \ No newline at end of file + +private: + vector p, size; +}; + +class Solution { +public: + int numSimilarGroups(vector& strs) { + int n = strs.size(), m = strs[0].size(); + int cnt = n; + UnionFind uf(n); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + int diff = 0; + for (int k = 0; k < m; ++k) { + diff += strs[i][k] != strs[j][k]; + } + if (diff <= 2 && uf.unite(i, j)) { + --cnt; + } + } + } + return cnt; + } +}; diff --git a/solution/0800-0899/0839.Similar String Groups/Solution.go b/solution/0800-0899/0839.Similar String Groups/Solution.go index 7833d364f434..c35924f2b36d 100644 --- a/solution/0800-0899/0839.Similar String Groups/Solution.go +++ b/solution/0800-0899/0839.Similar String Groups/Solution.go @@ -1,37 +1,54 @@ -func numSimilarGroups(strs []string) int { - n := len(strs) +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { p := make([]int, n) + size := make([]int, n) for i := range p { p[i] = i + size[i] = 1 } - check := func(a, b string) bool { - cnt := 0 - for i := range a { - if a[i] != b[i] { - cnt++ - } - } - return cnt <= 2 + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) } - var find func(x int) int - find = func(x int) int { - if p[x] != x { - p[x] = find(p[x]) - } - return p[x] + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false } - for i := 0; i < n; i++ { - for j := i + 1; j < n; j++ { - if check(strs[i], strs[j]) { - p[find(i)] = find(j) - } - } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] } - ans := 0 - for i := 0; i < n; i++ { - if i == find(i) { - ans++ + return true +} + +func numSimilarGroups(strs []string) int { + n := len(strs) + uf := newUnionFind(n) + for i, s := range strs { + for j, t := range strs[:i] { + diff := 0 + for k := range s { + if s[k] != t[k] { + diff++ + } + } + if diff <= 2 && uf.union(i, j) { + n-- + } } } - return ans -} \ No newline at end of file + return n +} diff --git a/solution/0800-0899/0839.Similar String Groups/Solution.java b/solution/0800-0899/0839.Similar String Groups/Solution.java index b0ddcc219b9b..fda04e4f5398 100644 --- a/solution/0800-0899/0839.Similar String Groups/Solution.java +++ b/solution/0800-0899/0839.Similar String Groups/Solution.java @@ -1,43 +1,57 @@ -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; - public int numSimilarGroups(String[] strs) { - int n = strs.length; + public UnionFind(int n) { p = new int[n]; + size = new int[n]; for (int i = 0; i < n; ++i) { p[i] = i; + size[i] = 1; } - for (int i = 0; i < n; ++i) { - for (int j = i + 1; j < n; ++j) { - if (check(strs[i], strs[j])) { - p[find(i)] = find(j); - } - } - } - int res = 0; - for (int i = 0; i < n; ++i) { - if (i == find(i)) { - ++res; - } + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); } - return res; + return p[x]; } - private boolean check(String a, String b) { - int cnt = 0; - int n = a.length(); - for (int i = 0; i < n; ++i) { - if (a.charAt(i) != b.charAt(i)) { - ++cnt; - } + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; } - return cnt <= 2; + return true; } +} - private int find(int x) { - if (p[x] != x) { - p[x] = find(p[x]); +class Solution { + public int numSimilarGroups(String[] strs) { + int n = strs.length, m = strs[0].length(); + UnionFind uf = new UnionFind(n); + int cnt = n; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + int diff = 0; + for (int k = 0; k < m; ++k) { + if (strs[i].charAt(k) != strs[j].charAt(k)) { + ++diff; + } + } + if (diff <= 2 && uf.union(i, j)) { + --cnt; + } + } } - return p[x]; + return cnt; } -} \ No newline at end of file +} diff --git a/solution/0800-0899/0839.Similar String Groups/Solution.py b/solution/0800-0899/0839.Similar String Groups/Solution.py index 981ade74b1ab..603c38737b77 100644 --- a/solution/0800-0899/0839.Similar String Groups/Solution.py +++ b/solution/0800-0899/0839.Similar String Groups/Solution.py @@ -1,14 +1,32 @@ +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + class Solution: def numSimilarGroups(self, strs: List[str]) -> int: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] - - n, l = len(strs), len(strs[0]) - p = list(range(n)) - for i in range(n): - for j in range(i + 1, n): - if sum(strs[i][k] != strs[j][k] for k in range(l)) <= 2: - p[find(i)] = find(j) - return sum(i == find(i) for i in range(n)) + n, m = len(strs), len(strs[0]) + uf = UnionFind(n) + for i, s in enumerate(strs): + for j, t in enumerate(strs[:i]): + if sum(s[k] != t[k] for k in range(m)) <= 2 and uf.union(i, j): + n -= 1 + return n diff --git a/solution/0800-0899/0839.Similar String Groups/Solution.ts b/solution/0800-0899/0839.Similar String Groups/Solution.ts new file mode 100644 index 000000000000..61ea5051f3b0 --- /dev/null +++ b/solution/0800-0899/0839.Similar String Groups/Solution.ts @@ -0,0 +1,53 @@ +class UnionFind { + private p: number[]; + private size: number[]; + + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + union(a: number, b: number): boolean { + const pa = this.find(a); + const pb = this.find(b); + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } +} + +function numSimilarGroups(strs: string[]): number { + const n = strs.length; + const m = strs[0].length; + const uf = new UnionFind(n); + let cnt = n; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + let diff = 0; + for (let k = 0; k < m; ++k) { + if (strs[i][k] !== strs[j][k]) { + diff++; + } + } + if (diff <= 2 && uf.union(i, j)) { + cnt--; + } + } + } + return cnt; +} diff --git a/solution/0800-0899/0840.Magic Squares In Grid/README.md b/solution/0800-0899/0840.Magic Squares In Grid/README.md index 82b1eca486f5..2e9b56973f79 100644 --- a/solution/0800-0899/0840.Magic Squares In Grid/README.md +++ b/solution/0800-0899/0840.Magic Squares In Grid/README.md @@ -23,6 +23,8 @@ tags:

    给定一个由整数组成的row x col 的 grid,其中有多少个 3 × 3 的 “幻方” 子矩阵?(每个子矩阵都是连续的)。

    +

    注意:虽然幻方只能包含 1 到 9 的数字,但 grid 可以包含最多15的数字。

    +

     

    示例 1:

    @@ -276,9 +278,9 @@ function numMagicSquaresInside(grid: number[][]): number { if (i + 3 > m || j + 3 > n) { return 0; } - const cnt: number[] = new Array(16).fill(0); - const row: number[] = new Array(3).fill(0); - const col: number[] = new Array(3).fill(0); + const cnt: number[] = Array(16).fill(0); + const row: number[] = Array(3).fill(0); + const col: number[] = Array(3).fill(0); let [a, b] = [0, 0]; for (let x = i; x < i + 3; ++x) { for (let y = j; y < j + 3; ++y) { @@ -316,6 +318,158 @@ function numMagicSquaresInside(grid: number[][]): number { } ``` +#### JavaScript + +```js +function numMagicSquaresInside(grid) { + const m = grid.length; + const n = grid[0].length; + const check = (i, j) => { + if (i + 3 > m || j + 3 > n) { + return 0; + } + const cnt = Array(16).fill(0); + const row = Array(3).fill(0); + const col = Array(3).fill(0); + let [a, b] = [0, 0]; + for (let x = i; x < i + 3; ++x) { + for (let y = j; y < j + 3; ++y) { + const v = grid[x][y]; + if (v < 1 || v > 9 || ++cnt[v] > 1) { + return 0; + } + row[x - i] += v; + col[y - j] += v; + if (x - i === y - j) { + a += v; + } + if (x - i === 2 - (y - j)) { + b += v; + } + } + } + if (a !== b) { + return 0; + } + for (let k = 0; k < 3; ++k) { + if (row[k] !== a || col[k] !== a) { + return 0; + } + } + return 1; + }; + let ans = 0; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + ans += check(i, j); + } + } + return ans; +} +``` + + + + + + + +### Solution 2 + + + +#### TypeScript + +```ts +export function numMagicSquaresInside(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + if (m < 3 || n < 3) return 0; + + const check = (y: number, x: number) => { + const g = grid; + if (g[y + 1][x + 1] !== 5) return 0; + + const cells = [ + g[y][x], + g[y][x + 1], + g[y][x + 2], + g[y + 1][x + 2], + g[y + 2][x + 2], + g[y + 2][x + 1], + g[y + 2][x], + g[y + 1][x], + ]; + + const i = cells.indexOf(2); + if (i === -1) return 0; + cells.push(...cells.splice(0, i)); + + const circle = [2, 9, 4, 3, 8, 1, 6, 7]; + const reverseCircle = [2, 7, 6, 1, 8, 3, 4, 9]; + + if (cells.every((x, i) => x === circle[i])) return 1; + if (cells.every((x, i) => x === reverseCircle[i])) return 1; + + return 0; + }; + + let res = 0; + for (let i = 0; i < m - 2; i++) { + for (let j = 0; j < n - 2; j++) { + res += check(i, j); + } + } + + return res; +} +``` + +#### JavaScript + +```js +function numMagicSquaresInside(grid) { + const [m, n] = [grid.length, grid[0].length]; + if (m < 3 || n < 3) return 0; + + const check = (y, x) => { + const g = grid; + if (g[y + 1][x + 1] !== 5) return false; + + const cells = [ + g[y][x], + g[y][x + 1], + g[y][x + 2], + g[y + 1][x + 2], + g[y + 2][x + 2], + g[y + 2][x + 1], + g[y + 2][x], + g[y + 1][x], + ]; + + const i = cells.indexOf(2); + if (i === -1) return false; + cells.push(...cells.splice(0, i)); + + const circle = [2, 9, 4, 3, 8, 1, 6, 7]; + const reverseCircle = [2, 7, 6, 1, 8, 3, 4, 9]; + + if (cells.every((x, i) => x === circle[i])) return true; + if (cells.every((x, i) => x === reverseCircle[i])) return true; + + return false; + }; + + let res = 0; + for (let i = 0; i < m - 2; i++) { + for (let j = 0; j < n - 2; j++) { + res += +check(i, j); + } + } + + return res; +} +``` + diff --git a/solution/0800-0899/0840.Magic Squares In Grid/README_EN.md b/solution/0800-0899/0840.Magic Squares In Grid/README_EN.md index e159a7d89cd0..70ee41f412e2 100644 --- a/solution/0800-0899/0840.Magic Squares In Grid/README_EN.md +++ b/solution/0800-0899/0840.Magic Squares In Grid/README_EN.md @@ -19,9 +19,11 @@ tags: -

    A 3 x 3 magic square is a 3 x 3 grid filled with distinct numbers from 1 to 9 such that each row, column, and both diagonals all have the same sum.

    +

    A 3 x 3 magic square is a 3 x 3 grid filled with distinct numbers from 1 to 9 such that each row, column, and both diagonals all have the same sum.

    -

    Given a row x col grid of integers, how many 3 x 3 "magic square" subgrids are there?  (Each subgrid is contiguous).

    +

    Given a row x col grid of integers, how many 3 x 3 contiguous magic square subgrids are there?

    + +

    Note: while a magic square can only contain numbers from 1 to 9, grid may contain numbers up to 15.

     

    Example 1:

    @@ -60,7 +62,11 @@ In total, there is only one magic square inside the given grid. -### Solution 1 +### Solution 1: Enumeration + +We directly enumerate the top-left coordinates $(i, j)$ of each $3 \times 3$ sub-matrix, then check whether the sub-matrix satisfies the "magic square" condition. If it does, increment the answer by one. After enumeration, return the answer. + +Time complexity is $O(m \times n)$, where $m$ and $n$ are the number of rows and columns of the matrix, respectively. Space complexity is $O(1)$. @@ -268,9 +274,9 @@ function numMagicSquaresInside(grid: number[][]): number { if (i + 3 > m || j + 3 > n) { return 0; } - const cnt: number[] = new Array(16).fill(0); - const row: number[] = new Array(3).fill(0); - const col: number[] = new Array(3).fill(0); + const cnt: number[] = Array(16).fill(0); + const row: number[] = Array(3).fill(0); + const col: number[] = Array(3).fill(0); let [a, b] = [0, 0]; for (let x = i; x < i + 3; ++x) { for (let y = j; y < j + 3; ++y) { @@ -308,6 +314,158 @@ function numMagicSquaresInside(grid: number[][]): number { } ``` +#### JavaScript + +```js +function numMagicSquaresInside(grid) { + const m = grid.length; + const n = grid[0].length; + const check = (i, j) => { + if (i + 3 > m || j + 3 > n) { + return 0; + } + const cnt = Array(16).fill(0); + const row = Array(3).fill(0); + const col = Array(3).fill(0); + let [a, b] = [0, 0]; + for (let x = i; x < i + 3; ++x) { + for (let y = j; y < j + 3; ++y) { + const v = grid[x][y]; + if (v < 1 || v > 9 || ++cnt[v] > 1) { + return 0; + } + row[x - i] += v; + col[y - j] += v; + if (x - i === y - j) { + a += v; + } + if (x - i === 2 - (y - j)) { + b += v; + } + } + } + if (a !== b) { + return 0; + } + for (let k = 0; k < 3; ++k) { + if (row[k] !== a || col[k] !== a) { + return 0; + } + } + return 1; + }; + let ans = 0; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + ans += check(i, j); + } + } + return ans; +} +``` + + + + + + + +### Solution 2 + + + +#### TypeScript + +```ts +export function numMagicSquaresInside(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + if (m < 3 || n < 3) return 0; + + const check = (y: number, x: number) => { + const g = grid; + if (g[y + 1][x + 1] !== 5) return 0; + + const cells = [ + g[y][x], + g[y][x + 1], + g[y][x + 2], + g[y + 1][x + 2], + g[y + 2][x + 2], + g[y + 2][x + 1], + g[y + 2][x], + g[y + 1][x], + ]; + + const i = cells.indexOf(2); + if (i === -1) return 0; + cells.push(...cells.splice(0, i)); + + const circle = [2, 9, 4, 3, 8, 1, 6, 7]; + const reverseCircle = [2, 7, 6, 1, 8, 3, 4, 9]; + + if (cells.every((x, i) => x === circle[i])) return 1; + if (cells.every((x, i) => x === reverseCircle[i])) return 1; + + return 0; + }; + + let res = 0; + for (let i = 0; i < m - 2; i++) { + for (let j = 0; j < n - 2; j++) { + res += check(i, j); + } + } + + return res; +} +``` + +#### JavaScript + +```js +function numMagicSquaresInside(grid) { + const [m, n] = [grid.length, grid[0].length]; + if (m < 3 || n < 3) return 0; + + const check = (y, x) => { + const g = grid; + if (g[y + 1][x + 1] !== 5) return false; + + const cells = [ + g[y][x], + g[y][x + 1], + g[y][x + 2], + g[y + 1][x + 2], + g[y + 2][x + 2], + g[y + 2][x + 1], + g[y + 2][x], + g[y + 1][x], + ]; + + const i = cells.indexOf(2); + if (i === -1) return false; + cells.push(...cells.splice(0, i)); + + const circle = [2, 9, 4, 3, 8, 1, 6, 7]; + const reverseCircle = [2, 7, 6, 1, 8, 3, 4, 9]; + + if (cells.every((x, i) => x === circle[i])) return true; + if (cells.every((x, i) => x === reverseCircle[i])) return true; + + return false; + }; + + let res = 0; + for (let i = 0; i < m - 2; i++) { + for (let j = 0; j < n - 2; j++) { + res += +check(i, j); + } + } + + return res; +} +``` + diff --git a/solution/0800-0899/0840.Magic Squares In Grid/Solution.js b/solution/0800-0899/0840.Magic Squares In Grid/Solution.js new file mode 100644 index 000000000000..fc08cda6431c --- /dev/null +++ b/solution/0800-0899/0840.Magic Squares In Grid/Solution.js @@ -0,0 +1,45 @@ +function numMagicSquaresInside(grid) { + const m = grid.length; + const n = grid[0].length; + const check = (i, j) => { + if (i + 3 > m || j + 3 > n) { + return 0; + } + const cnt = Array(16).fill(0); + const row = Array(3).fill(0); + const col = Array(3).fill(0); + let [a, b] = [0, 0]; + for (let x = i; x < i + 3; ++x) { + for (let y = j; y < j + 3; ++y) { + const v = grid[x][y]; + if (v < 1 || v > 9 || ++cnt[v] > 1) { + return 0; + } + row[x - i] += v; + col[y - j] += v; + if (x - i === y - j) { + a += v; + } + if (x - i === 2 - (y - j)) { + b += v; + } + } + } + if (a !== b) { + return 0; + } + for (let k = 0; k < 3; ++k) { + if (row[k] !== a || col[k] !== a) { + return 0; + } + } + return 1; + }; + let ans = 0; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; ++j) { + ans += check(i, j); + } + } + return ans; +} diff --git a/solution/0800-0899/0840.Magic Squares In Grid/Solution.ts b/solution/0800-0899/0840.Magic Squares In Grid/Solution.ts index a6489d609510..0f8bd8e0a0f3 100644 --- a/solution/0800-0899/0840.Magic Squares In Grid/Solution.ts +++ b/solution/0800-0899/0840.Magic Squares In Grid/Solution.ts @@ -5,9 +5,9 @@ function numMagicSquaresInside(grid: number[][]): number { if (i + 3 > m || j + 3 > n) { return 0; } - const cnt: number[] = new Array(16).fill(0); - const row: number[] = new Array(3).fill(0); - const col: number[] = new Array(3).fill(0); + const cnt: number[] = Array(16).fill(0); + const row: number[] = Array(3).fill(0); + const col: number[] = Array(3).fill(0); let [a, b] = [0, 0]; for (let x = i; x < i + 3; ++x) { for (let y = j; y < j + 3; ++y) { diff --git a/solution/0800-0899/0840.Magic Squares In Grid/Solution2.js b/solution/0800-0899/0840.Magic Squares In Grid/Solution2.js new file mode 100644 index 000000000000..b93fe320dce7 --- /dev/null +++ b/solution/0800-0899/0840.Magic Squares In Grid/Solution2.js @@ -0,0 +1,41 @@ +function numMagicSquaresInside(grid) { + const [m, n] = [grid.length, grid[0].length]; + if (m < 3 || n < 3) return 0; + + const check = (y, x) => { + const g = grid; + if (g[y + 1][x + 1] !== 5) return false; + + const cells = [ + g[y][x], + g[y][x + 1], + g[y][x + 2], + g[y + 1][x + 2], + g[y + 2][x + 2], + g[y + 2][x + 1], + g[y + 2][x], + g[y + 1][x], + ]; + + const i = cells.indexOf(2); + if (i === -1) return false; + cells.push(...cells.splice(0, i)); + + const circle = [2, 9, 4, 3, 8, 1, 6, 7]; + const reverseCircle = [2, 7, 6, 1, 8, 3, 4, 9]; + + if (cells.every((x, i) => x === circle[i])) return true; + if (cells.every((x, i) => x === reverseCircle[i])) return true; + + return false; + }; + + let res = 0; + for (let i = 0; i < m - 2; i++) { + for (let j = 0; j < n - 2; j++) { + res += +check(i, j); + } + } + + return res; +} diff --git a/solution/0800-0899/0840.Magic Squares In Grid/Solution2.ts b/solution/0800-0899/0840.Magic Squares In Grid/Solution2.ts new file mode 100644 index 000000000000..2798cc4025b2 --- /dev/null +++ b/solution/0800-0899/0840.Magic Squares In Grid/Solution2.ts @@ -0,0 +1,41 @@ +function numMagicSquaresInside(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + if (m < 3 || n < 3) return 0; + + const check = (y: number, x: number) => { + const g = grid; + if (g[y + 1][x + 1] !== 5) return 0; + + const cells = [ + g[y][x], + g[y][x + 1], + g[y][x + 2], + g[y + 1][x + 2], + g[y + 2][x + 2], + g[y + 2][x + 1], + g[y + 2][x], + g[y + 1][x], + ]; + + const i = cells.indexOf(2); + if (i === -1) return 0; + cells.push(...cells.splice(0, i)); + + const circle = [2, 9, 4, 3, 8, 1, 6, 7]; + const reverseCircle = [2, 7, 6, 1, 8, 3, 4, 9]; + + if (cells.every((x, i) => x === circle[i])) return 1; + if (cells.every((x, i) => x === reverseCircle[i])) return 1; + + return 0; + }; + + let res = 0; + for (let i = 0; i < m - 2; i++) { + for (let j = 0; j < n - 2; j++) { + res += check(i, j); + } + } + + return res; +} diff --git a/solution/0800-0899/0841.Keys and Rooms/README.md b/solution/0800-0899/0841.Keys and Rooms/README.md index 809154145875..6230cebdffa9 100644 --- a/solution/0800-0899/0841.Keys and Rooms/README.md +++ b/solution/0800-0899/0841.Keys and Rooms/README.md @@ -20,7 +20,7 @@ tags:

    n 个房间,房间按从 0n - 1 编号。最初,除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而,你不能在没有获得钥匙的时候进入锁住的房间。

    -

    当你进入一个房间,你可能会在里面找到一套不同的钥匙,每把钥匙上都有对应的房间号,即表示钥匙可以打开的房间。你可以拿上所有钥匙去解锁其他房间。

    +

    当你进入一个房间,你可能会在里面找到一套 不同的钥匙,每把钥匙上都有对应的房间号,即表示钥匙可以打开的房间。你可以拿上所有钥匙去解锁其他房间。

    给你一个数组 rooms 其中 rooms[i] 是你进入 i 号房间可以获得的钥匙集合。如果能进入 所有 房间返回 true,否则返回 false

    diff --git a/solution/0800-0899/0848.Shifting Letters/README.md b/solution/0800-0899/0848.Shifting Letters/README.md index 7a47204150a0..297344cd8d95 100644 --- a/solution/0800-0899/0848.Shifting Letters/README.md +++ b/solution/0800-0899/0848.Shifting Letters/README.md @@ -71,7 +71,7 @@ tags: ### 方法一:后缀和 -对于字符串 $s$ 中的每个字符,我们需要计算其最终的偏移量,即 `shifts[i]` 与 `shifts[i + 1]` 与 `shifts[i + 2]` ... 的和。我们可以使用后缀和的思想,从后往前遍历 `shifts`,计算每个字符的最终偏移量,然后对 $26$ 取模,得到最终的字符。 +对于字符串 $s$ 中的每个字符,我们需要计算其最终的偏移量,即 $\textit{shifts}[i]$ 与 $\textit{shifts}[i + 1]$ 与 $\textit{shifts}[i + 2]$ ... 的和。我们可以使用后缀和的思想,从后往前遍历 $\textit{shifts}$,计算每个字符的最终偏移量,然后对 $26$ 取模,得到最终的字符。 时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。忽略答案的空间消耗,空间复杂度 $O(1)$。 @@ -91,29 +91,6 @@ class Solution: return ''.join(s) ``` -#### Python3 - -```python -class Solution: - def shiftingLetters(self, s: str, shifts: List[int]) -> str: - n = len(s) - d = [0] * (n + 1) - for i, c in enumerate(s): - v = ord(c) - ord('a') - d[i] += v - d[i + 1] -= v - for i, x in enumerate(shifts): - d[0] += x - d[i + 1] -= x - t = 0 - ans = [] - for i in range(n): - d[i] %= 26 - ans.append(ascii_lowercase[d[i]]) - d[i + 1] += d[i] - return ''.join(ans) -``` - #### Java ```java diff --git a/solution/0800-0899/0848.Shifting Letters/README_EN.md b/solution/0800-0899/0848.Shifting Letters/README_EN.md index 47a0f2a01423..56ad1fea51b3 100644 --- a/solution/0800-0899/0848.Shifting Letters/README_EN.md +++ b/solution/0800-0899/0848.Shifting Letters/README_EN.md @@ -65,7 +65,11 @@ After shifting the first 3 letters of s by 9, we have "rpl", the answe -### Solution 1 +### Solution 1: Suffix Sum + +For each character in the string $s$, we need to calculate its final shift amount, which is the sum of $\textit{shifts}[i]$, $\textit{shifts}[i + 1]$, $\textit{shifts}[i + 2]$, and so on. We can use the concept of suffix sum, traversing $\textit{shifts}$ from back to front, calculating the final shift amount for each character, and then taking modulo $26$ to get the final character. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. Ignoring the space consumption of the answer, the space complexity is $O(1)$. @@ -83,29 +87,6 @@ class Solution: return ''.join(s) ``` -#### Python3 - -```python -class Solution: - def shiftingLetters(self, s: str, shifts: List[int]) -> str: - n = len(s) - d = [0] * (n + 1) - for i, c in enumerate(s): - v = ord(c) - ord('a') - d[i] += v - d[i + 1] -= v - for i, x in enumerate(shifts): - d[0] += x - d[i + 1] -= x - t = 0 - ans = [] - for i in range(n): - d[i] %= 26 - ans.append(ascii_lowercase[d[i]]) - d[i + 1] += d[i] - return ''.join(ans) -``` - #### Java ```java diff --git a/solution/0800-0899/0848.Shifting Letters/Solution.py b/solution/0800-0899/0848.Shifting Letters/Solution.py index f0e0e8f17415..44ff7f0c7366 100644 --- a/solution/0800-0899/0848.Shifting Letters/Solution.py +++ b/solution/0800-0899/0848.Shifting Letters/Solution.py @@ -1,18 +1,9 @@ class Solution: def shiftingLetters(self, s: str, shifts: List[int]) -> str: - n = len(s) - d = [0] * (n + 1) - for i, c in enumerate(s): - v = ord(c) - ord('a') - d[i] += v - d[i + 1] -= v - for i, x in enumerate(shifts): - d[0] += x - d[i + 1] -= x - t = 0 - ans = [] - for i in range(n): - d[i] %= 26 - ans.append(ascii_lowercase[d[i]]) - d[i + 1] += d[i] - return ''.join(ans) + n, t = len(s), 0 + s = list(s) + for i in range(n - 1, -1, -1): + t += shifts[i] + j = (ord(s[i]) - ord("a") + t) % 26 + s[i] = ascii_lowercase[j] + return "".join(s) diff --git a/solution/0800-0899/0848.Shifting Letters/Solution2.py b/solution/0800-0899/0848.Shifting Letters/Solution2.py deleted file mode 100644 index 24835fc8e6a8..000000000000 --- a/solution/0800-0899/0848.Shifting Letters/Solution2.py +++ /dev/null @@ -1,9 +0,0 @@ -class Solution: - def shiftingLetters(self, s: str, shifts: List[int]) -> str: - n, t = len(s), 0 - s = list(s) - for i in range(n - 1, -1, -1): - t += shifts[i] - j = (ord(s[i]) - ord('a') + t) % 26 - s[i] = ascii_lowercase[j] - return ''.join(s) diff --git a/solution/0800-0899/0849.Maximize Distance to Closest Person/README.md b/solution/0800-0899/0849.Maximize Distance to Closest Person/README.md index 6c5b0fc0941e..91d16e0603ca 100644 --- a/solution/0800-0899/0849.Maximize Distance to Closest Person/README.md +++ b/solution/0800-0899/0849.Maximize Distance to Closest Person/README.md @@ -73,13 +73,13 @@ tags: ### 方法一:一次遍历 -我们定义两个变量 $first$ 和 $last$ 分别表示第一个人和最后一个人的位置,用变量 $d$ 表示两个人之间的最大距离。 +我们定义两个变量 $\textit{first}$ 和 $\textit{last}$ 分别表示第一个人和最后一个人的位置,用变量 $d$ 表示两个人之间的最大距离。 -然后遍历数组 $seats$,如果当前位置有人,如果此前 $last$ 更新过,说明此前有人,此时更新 $d = \max(d, i - last)$;如果此前 $first$ 没有更新过,说明此前没有人,此时更新 $first = i$。接下来更新 $last = i$。 +然后遍历数组 $\textit{seats}$,如果当前位置有人,如果此前 $\textit{last}$ 更新过,说明此前有人,此时更新 $d = \max(d, i - \textit{last})$;如果此前 $\textit{first}$ 没有更新过,说明此前没有人,此时更新 $\textit{first} = i$。接下来更新 $\textit{last} = i$。 -最后返回 $\max(first, n - last - 1, d / 2)$ 即可。 +最后返回 $\max(\textit{first}, n - \textit{last} - 1, d / 2)$ 即可。 -时间复杂度 $O(n)$,其中 $n$ 为数组 $seats$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{seats}$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/0800-0899/0849.Maximize Distance to Closest Person/README_EN.md b/solution/0800-0899/0849.Maximize Distance to Closest Person/README_EN.md index 70476b9f54f1..165ab1b9418e 100644 --- a/solution/0800-0899/0849.Maximize Distance to Closest Person/README_EN.md +++ b/solution/0800-0899/0849.Maximize Distance to Closest Person/README_EN.md @@ -69,7 +69,15 @@ This is the maximum distance possible, so the answer is 3. -### Solution 1 +### Solution 1: Single Traversal + +We define two variables $\textit{first}$ and $\textit{last}$ to represent the positions of the first and last person, respectively. We use the variable $d$ to represent the maximum distance between two people. + +Then, we traverse the array $\textit{seats}$. If the current position is occupied, and if $\textit{last}$ has been updated before, it means there was someone before, so we update $d = \max(d, i - \textit{last})$. If $\textit{first}$ has not been updated before, it means there was no one before, so we update $\textit{first} = i$. Next, we update $\textit{last} = i$. + +Finally, we return $\max(\textit{first}, n - \textit{last} - 1, d / 2)$. + +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{seats}$. The space complexity is $O(1)$. diff --git a/solution/0800-0899/0860.Lemonade Change/README.md b/solution/0800-0899/0860.Lemonade Change/README.md index cb68c6d4b627..76683943a9ae 100644 --- a/solution/0800-0899/0860.Lemonade Change/README.md +++ b/solution/0800-0899/0860.Lemonade Change/README.md @@ -196,10 +196,9 @@ func lemonadeChange(bills []int) bool { ```ts function lemonadeChange(bills: number[]): boolean { - let five = 0; - let ten = 0; - for (let bill of bills) { - switch (bill) { + let [five, ten] = [0, 0]; + for (const x of bills) { + switch (x) { case 5: five++; break; @@ -208,11 +207,44 @@ function lemonadeChange(bills: number[]): boolean { ten++; break; case 20: - if (ten !== 0) { - ten -= 1; - bill -= 10; + if (ten) { + ten--; + five--; + } else { + five -= 3; + } + break; + } + + if (five < 0) { + return false; + } + } + return true; +} +``` + +#### JavaScript + +```js +function lemonadeChange(bills) { + let [five, ten] = [0, 0]; + for (const x of bills) { + switch (x) { + case 5: + five++; + break; + case 10: + five--; + ten++; + break; + case 20: + if (ten) { + ten--; + five--; + } else { + five -= 3; } - five -= bill / 5 - 1; break; } @@ -262,4 +294,42 @@ impl Solution { + + +### 方法二:一行 + + + +#### TypeScript + +```ts +const lemonadeChange = (bills: number[], f = 0, t = 0): boolean => + bills.every( + x => ( + (!(x ^ 5) && ++f) || + (!(x ^ 10) && (--f, ++t)) || + (!(x ^ 20) && (t ? (f--, t--) : (f -= 3), 1)), + f >= 0 + ), + ); +``` + +#### JavaScript + +```js +const lemonadeChange = (bills, f = 0, t = 0) => + bills.every( + x => ( + (!(x ^ 5) && ++f) || + (!(x ^ 10) && (--f, ++t)) || + (!(x ^ 20) && (t ? (f--, t--) : (f -= 3), 1)), + f >= 0 + ), + ); +``` + + + + + diff --git a/solution/0800-0899/0860.Lemonade Change/README_EN.md b/solution/0800-0899/0860.Lemonade Change/README_EN.md index 17803978c430..fdb18b4e1cfa 100644 --- a/solution/0800-0899/0860.Lemonade Change/README_EN.md +++ b/solution/0800-0899/0860.Lemonade Change/README_EN.md @@ -181,10 +181,9 @@ func lemonadeChange(bills []int) bool { ```ts function lemonadeChange(bills: number[]): boolean { - let five = 0; - let ten = 0; - for (let bill of bills) { - switch (bill) { + let [five, ten] = [0, 0]; + for (const x of bills) { + switch (x) { case 5: five++; break; @@ -193,11 +192,44 @@ function lemonadeChange(bills: number[]): boolean { ten++; break; case 20: - if (ten !== 0) { - ten -= 1; - bill -= 10; + if (ten) { + ten--; + five--; + } else { + five -= 3; + } + break; + } + + if (five < 0) { + return false; + } + } + return true; +} +``` + +#### JavaScript + +```js +function lemonadeChange(bills) { + let [five, ten] = [0, 0]; + for (const x of bills) { + switch (x) { + case 5: + five++; + break; + case 10: + five--; + ten++; + break; + case 20: + if (ten) { + ten--; + five--; + } else { + five -= 3; } - five -= bill / 5 - 1; break; } @@ -247,4 +279,42 @@ impl Solution { + + +### Solution 2: One-liner + + + +#### TypeScript + +```ts +const lemonadeChange = (bills: number[], f = 0, t = 0): boolean => + bills.every( + x => ( + (!(x ^ 5) && ++f) || + (!(x ^ 10) && (--f, ++t)) || + (!(x ^ 20) && (t ? (f--, t--) : (f -= 3), 1)), + f >= 0 + ), + ); +``` + +#### JavaScript + +```js +const lemonadeChange = (bills, f = 0, t = 0) => + bills.every( + x => ( + (!(x ^ 5) && ++f) || + (!(x ^ 10) && (--f, ++t)) || + (!(x ^ 20) && (t ? (f--, t--) : (f -= 3), 1)), + f >= 0 + ), + ); +``` + + + + + diff --git a/solution/0800-0899/0860.Lemonade Change/Solution.js b/solution/0800-0899/0860.Lemonade Change/Solution.js new file mode 100644 index 000000000000..862baca9ee58 --- /dev/null +++ b/solution/0800-0899/0860.Lemonade Change/Solution.js @@ -0,0 +1,27 @@ +export function lemonadeChange(bills) { + let [five, ten] = [0, 0]; + for (const x of bills) { + switch (x) { + case 5: + five++; + break; + case 10: + five--; + ten++; + break; + case 20: + if (ten) { + ten--; + five--; + } else { + five -= 3; + } + break; + } + + if (five < 0) { + return false; + } + } + return true; +} diff --git a/solution/0800-0899/0860.Lemonade Change/Solution.ts b/solution/0800-0899/0860.Lemonade Change/Solution.ts index f5891b9105c1..f3a9550a8a9a 100644 --- a/solution/0800-0899/0860.Lemonade Change/Solution.ts +++ b/solution/0800-0899/0860.Lemonade Change/Solution.ts @@ -1,8 +1,7 @@ function lemonadeChange(bills: number[]): boolean { - let five = 0; - let ten = 0; - for (let bill of bills) { - switch (bill) { + let [five, ten] = [0, 0]; + for (const x of bills) { + switch (x) { case 5: five++; break; @@ -11,11 +10,12 @@ function lemonadeChange(bills: number[]): boolean { ten++; break; case 20: - if (ten !== 0) { - ten -= 1; - bill -= 10; + if (ten) { + ten--; + five--; + } else { + five -= 3; } - five -= bill / 5 - 1; break; } diff --git a/solution/0800-0899/0860.Lemonade Change/Solution2.js b/solution/0800-0899/0860.Lemonade Change/Solution2.js new file mode 100644 index 000000000000..6cc5fd8140e7 --- /dev/null +++ b/solution/0800-0899/0860.Lemonade Change/Solution2.js @@ -0,0 +1,9 @@ +const lemonadeChange = (bills, f = 0, t = 0) => + bills.every( + x => ( + (!(x ^ 5) && ++f) || + (!(x ^ 10) && (--f, ++t)) || + (!(x ^ 20) && (t ? (f--, t--) : (f -= 3), 1)), + f >= 0 + ), + ); diff --git a/solution/0800-0899/0860.Lemonade Change/Solution2.ts b/solution/0800-0899/0860.Lemonade Change/Solution2.ts new file mode 100644 index 000000000000..3537c47c652e --- /dev/null +++ b/solution/0800-0899/0860.Lemonade Change/Solution2.ts @@ -0,0 +1,9 @@ +const lemonadeChange = (bills: number[], f = 0, t = 0): boolean => + bills.every( + x => ( + (!(x ^ 5) && ++f) || + (!(x ^ 10) && (--f, ++t)) || + (!(x ^ 20) && (t ? (f--, t--) : (f -= 3), 1)), + f >= 0 + ), + ); diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/README.md b/solution/0800-0899/0872.Leaf-Similar Trees/README.md index a57e76dee965..06a54ad70c17 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/README.md +++ b/solution/0800-0899/0872.Leaf-Similar Trees/README.md @@ -65,7 +65,9 @@ tags: ### 方法一:DFS -后序遍历。 +我们可以使用深度优先搜索来遍历两棵树的叶子节点,分别将叶子节点的值存储在两个列表 $l_1$ 和 $l_2$ 中,最后比较两个列表是否相等。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为树的节点数。 @@ -80,13 +82,19 @@ tags: # self.right = right class Solution: def leafSimilar(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> bool: - def dfs(root): - if root is None: - return [] - ans = dfs(root.left) + dfs(root.right) - return ans or [root.val] - - return dfs(root1) == dfs(root2) + def dfs(root: Optional[TreeNode], nums: List[int]) -> None: + if root.left == root.right: + nums.append(root.val) + return + if root.left: + dfs(root.left, nums) + if root.right: + dfs(root.right, nums) + + l1, l2 = [], [] + dfs(root1, l1) + dfs(root2, l2) + return l1 == l2 ``` #### Java @@ -109,21 +117,24 @@ class Solution: */ class Solution { public boolean leafSimilar(TreeNode root1, TreeNode root2) { - List l1 = dfs(root1); - List l2 = dfs(root2); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + dfs(root1, l1); + dfs(root2, l2); return l1.equals(l2); } - private List dfs(TreeNode root) { - if (root == null) { - return new ArrayList<>(); + private void dfs(TreeNode root, List nums) { + if (root.left == root.right) { + nums.add(root.val); + return; } - List ans = dfs(root.left); - ans.addAll(dfs(root.right)); - if (ans.isEmpty()) { - ans.add(root.val); + if (root.left != null) { + dfs(root.left, nums); + } + if (root.right != null) { + dfs(root.right, nums); } - return ans; } } ``` @@ -145,16 +156,23 @@ class Solution { class Solution { public: bool leafSimilar(TreeNode* root1, TreeNode* root2) { - return dfs(root1) == dfs(root2); + vector l1, l2; + dfs(root1, l1); + dfs(root2, l2); + return l1 == l2; } - vector dfs(TreeNode* root) { - if (!root) return {}; - auto ans = dfs(root->left); - auto right = dfs(root->right); - ans.insert(ans.end(), right.begin(), right.end()); - if (ans.empty()) ans.push_back(root->val); - return ans; + void dfs(TreeNode* root, vector& nums) { + if (root->left == root->right) { + nums.push_back(root->val); + return; + } + if (root->left) { + dfs(root->left, nums); + } + if (root->right) { + dfs(root->right, nums); + } } }; ``` @@ -171,19 +189,23 @@ public: * } */ func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { - var dfs func(*TreeNode) []int - dfs = func(root *TreeNode) []int { - if root == nil { - return []int{} + l1, l2 := []int{}, []int{} + var dfs func(*TreeNode, *[]int) + dfs = func(root *TreeNode, nums *[]int) { + if root.Left == root.Right { + *nums = append(*nums, root.Val) + return + } + if root.Left != nil { + dfs(root.Left, nums) } - ans := dfs(root.Left) - ans = append(ans, dfs(root.Right)...) - if len(ans) == 0 { - ans = append(ans, root.Val) + if root.Right != nil { + dfs(root.Right, nums) } - return ans } - return reflect.DeepEqual(dfs(root1), dfs(root2)) + dfs(root1, &l1) + dfs(root2, &l2) + return reflect.DeepEqual(l1, l2) } ``` @@ -211,39 +233,31 @@ func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { use std::cell::RefCell; use std::rc::Rc; impl Solution { - #[allow(dead_code)] pub fn leaf_similar( root1: Option>>, root2: Option>>, ) -> bool { - let mut one_vec: Vec = Vec::new(); - let mut two_vec: Vec = Vec::new(); - - // Initialize the two vector - Self::traverse(&mut one_vec, root1); - Self::traverse(&mut two_vec, root2); - - one_vec == two_vec + let mut l1 = Vec::new(); + let mut l2 = Vec::new(); + Self::dfs(&root1, &mut l1); + Self::dfs(&root2, &mut l2); + l1 == l2 } - #[allow(dead_code)] - fn traverse(v: &mut Vec, root: Option>>) { - if root.is_none() { - return; - } - if Self::is_leaf_node(&root) { - v.push(root.as_ref().unwrap().borrow().val); + fn dfs(node: &Option>>, nums: &mut Vec) { + if let Some(n) = node { + let n = n.borrow(); + if n.left.is_none() && n.right.is_none() { + nums.push(n.val); + return; + } + if n.left.is_some() { + Self::dfs(&n.left, nums); + } + if n.right.is_some() { + Self::dfs(&n.right, nums); + } } - let left = root.as_ref().unwrap().borrow().left.clone(); - let right = root.as_ref().unwrap().borrow().right.clone(); - Self::traverse(v, left); - Self::traverse(v, right); - } - - #[allow(dead_code)] - fn is_leaf_node(node: &Option>>) -> bool { - node.as_ref().unwrap().borrow().left.is_none() - && node.as_ref().unwrap().borrow().right.is_none() } } ``` @@ -252,19 +266,19 @@ impl Solution { ```js var leafSimilar = function (root1, root2) { - const dfs = root => { - if (!root) { - return []; - } - let ans = [...dfs(root.left), ...dfs(root.right)]; - if (!ans.length) { - ans = [root.val]; + const l1 = []; + const l2 = []; + const dfs = (root, nums) => { + if (root.left === root.right) { + nums.push(root.val); + return; } - return ans; + root.left && dfs(root.left, nums); + root.right && dfs(root.right, nums); }; - const l1 = dfs(root1); - const l2 = dfs(root2); - return l1.toString() === l2.toString(); + dfs(root1, l1); + dfs(root2, l2); + return l1.join(',') === l2.join(','); }; ``` diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/README_EN.md b/solution/0800-0899/0872.Leaf-Similar Trees/README_EN.md index f2ffa8578b9a..61dfcd1f8ef6 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/README_EN.md +++ b/solution/0800-0899/0872.Leaf-Similar Trees/README_EN.md @@ -57,7 +57,11 @@ tags: -### Solution 1 +### Solution 1: DFS + +We can use Depth-First Search (DFS) to traverse the leaf nodes of the two trees, storing the values of the leaf nodes in two lists $l_1$ and $l_2$ respectively. Finally, we compare whether the two lists are equal. + +Time complexity is $O(n)$, and space complexity is $O(n)$. Here, $n$ is the number of nodes in the tree. @@ -72,13 +76,19 @@ tags: # self.right = right class Solution: def leafSimilar(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> bool: - def dfs(root): - if root is None: - return [] - ans = dfs(root.left) + dfs(root.right) - return ans or [root.val] - - return dfs(root1) == dfs(root2) + def dfs(root: Optional[TreeNode], nums: List[int]) -> None: + if root.left == root.right: + nums.append(root.val) + return + if root.left: + dfs(root.left, nums) + if root.right: + dfs(root.right, nums) + + l1, l2 = [], [] + dfs(root1, l1) + dfs(root2, l2) + return l1 == l2 ``` #### Java @@ -101,21 +111,24 @@ class Solution: */ class Solution { public boolean leafSimilar(TreeNode root1, TreeNode root2) { - List l1 = dfs(root1); - List l2 = dfs(root2); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + dfs(root1, l1); + dfs(root2, l2); return l1.equals(l2); } - private List dfs(TreeNode root) { - if (root == null) { - return new ArrayList<>(); + private void dfs(TreeNode root, List nums) { + if (root.left == root.right) { + nums.add(root.val); + return; + } + if (root.left != null) { + dfs(root.left, nums); } - List ans = dfs(root.left); - ans.addAll(dfs(root.right)); - if (ans.isEmpty()) { - ans.add(root.val); + if (root.right != null) { + dfs(root.right, nums); } - return ans; } } ``` @@ -137,16 +150,23 @@ class Solution { class Solution { public: bool leafSimilar(TreeNode* root1, TreeNode* root2) { - return dfs(root1) == dfs(root2); + vector l1, l2; + dfs(root1, l1); + dfs(root2, l2); + return l1 == l2; } - vector dfs(TreeNode* root) { - if (!root) return {}; - auto ans = dfs(root->left); - auto right = dfs(root->right); - ans.insert(ans.end(), right.begin(), right.end()); - if (ans.empty()) ans.push_back(root->val); - return ans; + void dfs(TreeNode* root, vector& nums) { + if (root->left == root->right) { + nums.push_back(root->val); + return; + } + if (root->left) { + dfs(root->left, nums); + } + if (root->right) { + dfs(root->right, nums); + } } }; ``` @@ -163,19 +183,23 @@ public: * } */ func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { - var dfs func(*TreeNode) []int - dfs = func(root *TreeNode) []int { - if root == nil { - return []int{} + l1, l2 := []int{}, []int{} + var dfs func(*TreeNode, *[]int) + dfs = func(root *TreeNode, nums *[]int) { + if root.Left == root.Right { + *nums = append(*nums, root.Val) + return } - ans := dfs(root.Left) - ans = append(ans, dfs(root.Right)...) - if len(ans) == 0 { - ans = append(ans, root.Val) + if root.Left != nil { + dfs(root.Left, nums) + } + if root.Right != nil { + dfs(root.Right, nums) } - return ans } - return reflect.DeepEqual(dfs(root1), dfs(root2)) + dfs(root1, &l1) + dfs(root2, &l2) + return reflect.DeepEqual(l1, l2) } ``` @@ -203,39 +227,31 @@ func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { use std::cell::RefCell; use std::rc::Rc; impl Solution { - #[allow(dead_code)] pub fn leaf_similar( root1: Option>>, root2: Option>>, ) -> bool { - let mut one_vec: Vec = Vec::new(); - let mut two_vec: Vec = Vec::new(); - - // Initialize the two vector - Self::traverse(&mut one_vec, root1); - Self::traverse(&mut two_vec, root2); - - one_vec == two_vec + let mut l1 = Vec::new(); + let mut l2 = Vec::new(); + Self::dfs(&root1, &mut l1); + Self::dfs(&root2, &mut l2); + l1 == l2 } - #[allow(dead_code)] - fn traverse(v: &mut Vec, root: Option>>) { - if root.is_none() { - return; - } - if Self::is_leaf_node(&root) { - v.push(root.as_ref().unwrap().borrow().val); + fn dfs(node: &Option>>, nums: &mut Vec) { + if let Some(n) = node { + let n = n.borrow(); + if n.left.is_none() && n.right.is_none() { + nums.push(n.val); + return; + } + if n.left.is_some() { + Self::dfs(&n.left, nums); + } + if n.right.is_some() { + Self::dfs(&n.right, nums); + } } - let left = root.as_ref().unwrap().borrow().left.clone(); - let right = root.as_ref().unwrap().borrow().right.clone(); - Self::traverse(v, left); - Self::traverse(v, right); - } - - #[allow(dead_code)] - fn is_leaf_node(node: &Option>>) -> bool { - node.as_ref().unwrap().borrow().left.is_none() - && node.as_ref().unwrap().borrow().right.is_none() } } ``` @@ -244,19 +260,19 @@ impl Solution { ```js var leafSimilar = function (root1, root2) { - const dfs = root => { - if (!root) { - return []; - } - let ans = [...dfs(root.left), ...dfs(root.right)]; - if (!ans.length) { - ans = [root.val]; + const l1 = []; + const l2 = []; + const dfs = (root, nums) => { + if (root.left === root.right) { + nums.push(root.val); + return; } - return ans; + root.left && dfs(root.left, nums); + root.right && dfs(root.right, nums); }; - const l1 = dfs(root1); - const l2 = dfs(root2); - return l1.toString() === l2.toString(); + dfs(root1, l1); + dfs(root2, l2); + return l1.join(',') === l2.join(','); }; ``` diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.cpp b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.cpp index 81181ea53450..c86895361887 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.cpp +++ b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.cpp @@ -12,15 +12,22 @@ class Solution { public: bool leafSimilar(TreeNode* root1, TreeNode* root2) { - return dfs(root1) == dfs(root2); + vector l1, l2; + dfs(root1, l1); + dfs(root2, l2); + return l1 == l2; } - vector dfs(TreeNode* root) { - if (!root) return {}; - auto ans = dfs(root->left); - auto right = dfs(root->right); - ans.insert(ans.end(), right.begin(), right.end()); - if (ans.empty()) ans.push_back(root->val); - return ans; + void dfs(TreeNode* root, vector& nums) { + if (root->left == root->right) { + nums.push_back(root->val); + return; + } + if (root->left) { + dfs(root->left, nums); + } + if (root->right) { + dfs(root->right, nums); + } } -}; \ No newline at end of file +}; diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.go b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.go index 9d23011b5940..08b717b4e3a4 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.go +++ b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.go @@ -7,17 +7,21 @@ * } */ func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { - var dfs func(*TreeNode) []int - dfs = func(root *TreeNode) []int { - if root == nil { - return []int{} + l1, l2 := []int{}, []int{} + var dfs func(*TreeNode, *[]int) + dfs = func(root *TreeNode, nums *[]int) { + if root.Left == root.Right { + *nums = append(*nums, root.Val) + return } - ans := dfs(root.Left) - ans = append(ans, dfs(root.Right)...) - if len(ans) == 0 { - ans = append(ans, root.Val) + if root.Left != nil { + dfs(root.Left, nums) + } + if root.Right != nil { + dfs(root.Right, nums) } - return ans } - return reflect.DeepEqual(dfs(root1), dfs(root2)) -} \ No newline at end of file + dfs(root1, &l1) + dfs(root2, &l2) + return reflect.DeepEqual(l1, l2) +} diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.java b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.java index b74fb7b31e06..5c85cb6b09cf 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.java +++ b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.java @@ -15,20 +15,23 @@ */ class Solution { public boolean leafSimilar(TreeNode root1, TreeNode root2) { - List l1 = dfs(root1); - List l2 = dfs(root2); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + dfs(root1, l1); + dfs(root2, l2); return l1.equals(l2); } - private List dfs(TreeNode root) { - if (root == null) { - return new ArrayList<>(); + private void dfs(TreeNode root, List nums) { + if (root.left == root.right) { + nums.add(root.val); + return; } - List ans = dfs(root.left); - ans.addAll(dfs(root.right)); - if (ans.isEmpty()) { - ans.add(root.val); + if (root.left != null) { + dfs(root.left, nums); + } + if (root.right != null) { + dfs(root.right, nums); } - return ans; } -} \ No newline at end of file +} diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.js b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.js index 5f1ea802d15b..e960061bf030 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.js +++ b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.js @@ -1,15 +1,15 @@ var leafSimilar = function (root1, root2) { - const dfs = root => { - if (!root) { - return []; + const l1 = []; + const l2 = []; + const dfs = (root, nums) => { + if (root.left === root.right) { + nums.push(root.val); + return; } - let ans = [...dfs(root.left), ...dfs(root.right)]; - if (!ans.length) { - ans = [root.val]; - } - return ans; + root.left && dfs(root.left, nums); + root.right && dfs(root.right, nums); }; - const l1 = dfs(root1); - const l2 = dfs(root2); - return l1.toString() === l2.toString(); + dfs(root1, l1); + dfs(root2, l2); + return l1.join(',') === l2.join(','); }; diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.py b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.py index 534feb86f5cc..8e1c53e59947 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.py +++ b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.py @@ -6,10 +6,16 @@ # self.right = right class Solution: def leafSimilar(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> bool: - def dfs(root): - if root is None: - return [] - ans = dfs(root.left) + dfs(root.right) - return ans or [root.val] + def dfs(root: Optional[TreeNode], nums: List[int]) -> None: + if root.left == root.right: + nums.append(root.val) + return + if root.left: + dfs(root.left, nums) + if root.right: + dfs(root.right, nums) - return dfs(root1) == dfs(root2) + l1, l2 = [], [] + dfs(root1, l1) + dfs(root2, l2) + return l1 == l2 diff --git a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.rs b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.rs index b26566fe67cc..e61a120c3cb8 100644 --- a/solution/0800-0899/0872.Leaf-Similar Trees/Solution.rs +++ b/solution/0800-0899/0872.Leaf-Similar Trees/Solution.rs @@ -19,38 +19,30 @@ use std::cell::RefCell; use std::rc::Rc; impl Solution { - #[allow(dead_code)] pub fn leaf_similar( root1: Option>>, root2: Option>>, ) -> bool { - let mut one_vec: Vec = Vec::new(); - let mut two_vec: Vec = Vec::new(); - - // Initialize the two vector - Self::traverse(&mut one_vec, root1); - Self::traverse(&mut two_vec, root2); - - one_vec == two_vec + let mut l1 = Vec::new(); + let mut l2 = Vec::new(); + Self::dfs(&root1, &mut l1); + Self::dfs(&root2, &mut l2); + l1 == l2 } - #[allow(dead_code)] - fn traverse(v: &mut Vec, root: Option>>) { - if root.is_none() { - return; - } - if Self::is_leaf_node(&root) { - v.push(root.as_ref().unwrap().borrow().val); + fn dfs(node: &Option>>, nums: &mut Vec) { + if let Some(n) = node { + let n = n.borrow(); + if n.left.is_none() && n.right.is_none() { + nums.push(n.val); + return; + } + if n.left.is_some() { + Self::dfs(&n.left, nums); + } + if n.right.is_some() { + Self::dfs(&n.right, nums); + } } - let left = root.as_ref().unwrap().borrow().left.clone(); - let right = root.as_ref().unwrap().borrow().right.clone(); - Self::traverse(v, left); - Self::traverse(v, right); - } - - #[allow(dead_code)] - fn is_leaf_node(node: &Option>>) -> bool { - node.as_ref().unwrap().borrow().left.is_none() - && node.as_ref().unwrap().borrow().right.is_none() } } diff --git a/solution/0800-0899/0875.Koko Eating Bananas/README.md b/solution/0800-0899/0875.Koko Eating Bananas/README.md index 375436e0b4f8..d3eed49cf0dd 100644 --- a/solution/0800-0899/0875.Koko Eating Bananas/README.md +++ b/solution/0800-0899/0875.Koko Eating Bananas/README.md @@ -71,7 +71,7 @@ tags: 我们注意到,如果珂珂能够以 $k$ 的速度在 $h$ 小时内吃完所有香蕉,那么她也可以以 $k' > k$ 的速度在 $h$ 小时内吃完所有香蕉。这存在着单调性,因此我们可以使用二分查找,找到最小的满足条件的 $k$。 -我们定义二分查找的左边界 $l = 1$,右边界 $r = \max(\text{piles})$。每一次二分,我们取中间值 $mid = \frac{l + r}{2}$,然后计算以 $mid$ 的速度吃香蕉需要的时间 $s$。如果 $s \leq h$,说明 $mid$ 的速度可以满足条件,我们将右边界 $r$ 更新为 $mid$;否则,我们将左边界 $l$ 更新为 $mid + 1$。最终,当 $l = r$ 时,我们找到了最小的满足条件的 $k$。 +我们定义二分查找的左边界 $l = 1$,右边界 $r = \max(\textit{piles})$。每一次二分,我们取中间值 $mid = \frac{l + r}{2}$,然后计算以 $mid$ 的速度吃香蕉需要的时间 $s$。如果 $s \leq h$,说明 $mid$ 的速度可以满足条件,我们将右边界 $r$ 更新为 $mid$;否则,我们将左边界 $l$ 更新为 $mid + 1$。最终,当 $l = r$ 时,我们找到了最小的满足条件的 $k$。 时间复杂度 $O(n \times \log M)$,其中 $n$ 和 $M$ 分别是数组 `piles` 的长度和最大值。空间复杂度 $O(1)$。 diff --git a/solution/0800-0899/0875.Koko Eating Bananas/README_EN.md b/solution/0800-0899/0875.Koko Eating Bananas/README_EN.md index 13a26d48b3fb..b8b6d373d6aa 100644 --- a/solution/0800-0899/0875.Koko Eating Bananas/README_EN.md +++ b/solution/0800-0899/0875.Koko Eating Bananas/README_EN.md @@ -66,7 +66,7 @@ tags: We notice that if Koko can eat all the bananas at a speed of $k$ within $h$ hours, then she can also eat all the bananas at a speed of $k' > k$ within $h$ hours. This shows monotonicity, so we can use binary search to find the smallest $k$ that satisfies the condition. -We define the left boundary of the binary search as $l = 1$, and the right boundary as $r = \max(\text{piles})$. For each binary search, we take the middle value $mid = \frac{l + r}{2}$, and then calculate the time $s$ required to eat bananas at a speed of $mid$. If $s \leq h$, it means that the speed of $mid$ can meet the condition, and we update the right boundary $r$ to $mid$; otherwise, we update the left boundary $l$ to $mid + 1$. Finally, when $l = r$, we find the smallest $k$ that satisfies the condition. +We define the left boundary of the binary search as $l = 1$, and the right boundary as $r = \max(\textit{piles})$. For each binary search, we take the middle value $mid = \frac{l + r}{2}$, and then calculate the time $s$ required to eat bananas at a speed of $mid$. If $s \leq h$, it means that the speed of $mid$ can meet the condition, and we update the right boundary $r$ to $mid$; otherwise, we update the left boundary $l$ to $mid + 1$. Finally, when $l = r$, we find the smallest $k$ that satisfies the condition. The time complexity is $O(n \times \log M)$, where $n$ and $M$ are the length and maximum value of the array `piles` respectively. The space complexity is $O(1)$. diff --git a/solution/0800-0899/0885.Spiral Matrix III/README.md b/solution/0800-0899/0885.Spiral Matrix III/README.md index 746fc2d2703b..db39ac38dcf8 100644 --- a/solution/0800-0899/0885.Spiral Matrix III/README.md +++ b/solution/0800-0899/0885.Spiral Matrix III/README.md @@ -173,6 +173,46 @@ func spiralMatrixIII(rows int, cols int, rStart int, cStart int) [][]int { } ``` +#### JavaScript + +```js +/** + * @param {number} rows + * @param {number} cols + * @param {number} rStart + * @param {number} cStart + * @return {number[][]} + */ +var spiralMatrixIII = function (rows, cols, rStart, cStart) { + const ans = []; + const totalCells = rows * cols; + const directions = [ + [0, 1], + [1, 0], + [0, -1], + [-1, 0], + ]; + let step = 0; + let d = 0; + let [r, c] = [rStart, cStart]; + ans.push([r, c]); + while (ans.length < totalCells) { + if (d === 0 || d === 2) { + step++; + } + for (let i = 0; i < step; i++) { + r += directions[d][0]; + c += directions[d][1]; + if (r >= 0 && r < rows && c >= 0 && c < cols) { + ans.push([r, c]); + } + } + d = (d + 1) % 4; + } + return ans; +}; +``` + diff --git a/solution/0800-0899/0885.Spiral Matrix III/README_EN.md b/solution/0800-0899/0885.Spiral Matrix III/README_EN.md index 42e57339a9b0..0408075aab7d 100644 --- a/solution/0800-0899/0885.Spiral Matrix III/README_EN.md +++ b/solution/0800-0899/0885.Spiral Matrix III/README_EN.md @@ -169,6 +169,46 @@ func spiralMatrixIII(rows int, cols int, rStart int, cStart int) [][]int { } ``` +#### JavaScript + +```js +/** + * @param {number} rows + * @param {number} cols + * @param {number} rStart + * @param {number} cStart + * @return {number[][]} + */ +var spiralMatrixIII = function (rows, cols, rStart, cStart) { + const ans = []; + const totalCells = rows * cols; + const directions = [ + [0, 1], + [1, 0], + [0, -1], + [-1, 0], + ]; + let step = 0; + let d = 0; + let [r, c] = [rStart, cStart]; + ans.push([r, c]); + while (ans.length < totalCells) { + if (d === 0 || d === 2) { + step++; + } + for (let i = 0; i < step; i++) { + r += directions[d][0]; + c += directions[d][1]; + if (r >= 0 && r < rows && c >= 0 && c < cols) { + ans.push([r, c]); + } + } + d = (d + 1) % 4; + } + return ans; +}; +``` + diff --git a/solution/0800-0899/0885.Spiral Matrix III/Solution.js b/solution/0800-0899/0885.Spiral Matrix III/Solution.js new file mode 100644 index 000000000000..01f66eeb78e6 --- /dev/null +++ b/solution/0800-0899/0885.Spiral Matrix III/Solution.js @@ -0,0 +1,35 @@ +/** + * @param {number} rows + * @param {number} cols + * @param {number} rStart + * @param {number} cStart + * @return {number[][]} + */ +var spiralMatrixIII = function (rows, cols, rStart, cStart) { + const ans = []; + const totalCells = rows * cols; + const directions = [ + [0, 1], + [1, 0], + [0, -1], + [-1, 0], + ]; + let step = 0; + let d = 0; + let [r, c] = [rStart, cStart]; + ans.push([r, c]); + while (ans.length < totalCells) { + if (d === 0 || d === 2) { + step++; + } + for (let i = 0; i < step; i++) { + r += directions[d][0]; + c += directions[d][1]; + if (r >= 0 && r < rows && c >= 0 && c < cols) { + ans.push([r, c]); + } + } + d = (d + 1) % 4; + } + return ans; +}; diff --git a/solution/0800-0899/0898.Bitwise ORs of Subarrays/README.md b/solution/0800-0899/0898.Bitwise ORs of Subarrays/README.md index 252448058aa7..02bdfb7ccd11 100644 --- a/solution/0800-0899/0898.Bitwise ORs of Subarrays/README.md +++ b/solution/0800-0899/0898.Bitwise ORs of Subarrays/README.md @@ -18,11 +18,11 @@ tags: -

    我们有一个非负整数数组 arr 。

    +

    给定一个整数数组 arr,返回所有 arr 的非空子数组的不同按位或的数量。

    -

    对于每个(连续的)子数组 sub = [arr[i], arr[i + 1], ..., arr[j]] ( i <= j),我们对 sub 中的每个元素进行按位或操作,获得结果 arr[i] | arr[i + 1] | ... | arr[j] 。

    +

    子数组的按位或是子数组中每个整数的按位或。含有一个整数的子数组的按位或就是该整数。

    -

    返回可能结果的数量。 多次出现的结果在最终答案中仅计算一次。

    +

    子数组 是数组内连续的非空元素序列。

     

    @@ -61,7 +61,7 @@ tags:
    • 1 <= nums.length <= 5 * 104
    • -
    • 0 <= nums[i] <= 109​​​​​​​
    • +
    • 0 <= nums[i] <= 109
    diff --git a/solution/0900-0999/0919.Complete Binary Tree Inserter/README.md b/solution/0900-0999/0919.Complete Binary Tree Inserter/README.md index ed07baa43e06..73b3f81ff64a 100644 --- a/solution/0900-0999/0919.Complete Binary Tree Inserter/README.md +++ b/solution/0900-0999/0919.Complete Binary Tree Inserter/README.md @@ -21,7 +21,7 @@ tags:

    完全二叉树 是每一层(除最后一层外)都是完全填充(即,节点数达到最大)的,并且所有的节点都尽可能地集中在左侧。

    -

    设计一种算法,将一个新节点插入到一个完整的二叉树中,并在插入后保持其完整。

    +

    设计一种算法,将一个新节点插入到一棵完全二叉树中,并在插入后保持其完整。

    实现 CBTInserter 类:

    diff --git a/solution/0900-0999/0925.Long Pressed Name/README.md b/solution/0900-0999/0925.Long Pressed Name/README.md index 12ec097abfb5..d0c698d7f1ee 100644 --- a/solution/0900-0999/0925.Long Pressed Name/README.md +++ b/solution/0900-0999/0925.Long Pressed Name/README.md @@ -56,9 +56,9 @@ tags: ### 方法一:双指针 -我们利用两个指针 $i$ 和 $j$ 分别指向字符串 $\text{typed}$ 和 $\text{name}$ 的第一个字符,然后开始遍历,如果 $\text{typed}[j] \neq \text{name}[i]$,说明两个字符串不匹配,直接返回 $\text{False}$。否则,我们找到连续相同的字符的下一个位置,分别记为 $x$ 和 $y$,如果 $x - i > y - j$,说明 $\text{typed}$ 中的字符个数小于 $\text{name}$ 中的字符个数,直接返回 $\text{False}$。否则,我们将 $i$ 和 $j$ 更新为 $x$ 和 $y$,继续遍历,直到 $i$ 和 $j$ 分别遍历完 $\text{name}$ 和 $\text{typed}$,返回 $\text{True}$。 +我们利用两个指针 $i$ 和 $j$ 分别指向字符串 $\textit{typed}$ 和 $\textit{name}$ 的第一个字符,然后开始遍历,如果 $\textit{typed}[j] \neq \textit{name}[i]$,说明两个字符串不匹配,直接返回 $\textit{False}$。否则,我们找到连续相同的字符的下一个位置,分别记为 $x$ 和 $y$,如果 $x - i > y - j$,说明 $\textit{typed}$ 中的字符个数小于 $\textit{name}$ 中的字符个数,直接返回 $\textit{False}$。否则,我们将 $i$ 和 $j$ 更新为 $x$ 和 $y$,继续遍历,直到 $i$ 和 $j$ 分别遍历完 $\textit{name}$ 和 $\textit{typed}$,返回 $\textit{True}$。 -时间复杂度 $O(m + n)$,其中 $m$ 和 $n$ 分别是字符串 $\text{name}$ 和 $\text{typed}$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(m + n)$,其中 $m$ 和 $n$ 分别是字符串 $\textit{name}$ 和 $\textit{typed}$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/0900-0999/0930.Binary Subarrays With Sum/README_EN.md b/solution/0900-0999/0930.Binary Subarrays With Sum/README_EN.md index 1a83755d57b8..d24e78a7fbff 100644 --- a/solution/0900-0999/0930.Binary Subarrays With Sum/README_EN.md +++ b/solution/0900-0999/0930.Binary Subarrays With Sum/README_EN.md @@ -24,49 +24,32 @@ tags:

    A subarray is a contiguous part of the array.

     

    -

    Example 1:

    -
     Input: nums = [1,0,1,0,1], goal = 2
    -
     Output: 4
    -
     Explanation: The 4 subarrays are bolded and underlined below:
    -
     [1,0,1,0,1]
    -
     [1,0,1,0,1]
    -
     [1,0,1,0,1]
    -
     [1,0,1,0,1]
    -
     

    Example 2:

    -
     Input: nums = [0,0,0,0,0], goal = 0
    -
     Output: 15
    -
     

     

    -

    Constraints:

      - -
    • 1 <= nums.length <= 3 * 104
    • - -
    • nums[i] is either 0 or 1.
    • - -
    • 0 <= goal <= nums.length
    • - +
    • 1 <= nums.length <= 3 * 104
    • +
    • nums[i] is either 0 or 1.
    • +
    • 0 <= goal <= nums.length
    diff --git a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README.md b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README.md index 5c36abdb0fe0..70740c3609d9 100644 --- a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README.md +++ b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README.md @@ -61,11 +61,13 @@ tags: ### 方法一:排序 + 贪心 -我们首先对数组进行排序,然后从前往后遍历数组,对于每个元素 `nums[i]`,如果它小于等于前一个元素 `nums[i - 1]`,那么我们将它增加到 `nums[i - 1] + 1`,那么操作的次数就是 `nums[i - 1] - nums[i] + 1`,累加到结果中。 +我们首先对数组 $\textit{nums}$ 进行排序,用一个变量 $\textit{y}$ 记录当前的最大值,初始时 $\textit{y} = -1$。 + +然后遍历数组 $\textit{nums}$,对于每个元素 $x$,我们将 $y$ 更新为 $\max(y + 1, x)$,并将操作次数 $y - x$ 累加到结果中。 遍历完成后,返回结果即可。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 `nums` 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 $\textit{nums}$ 的长度。 @@ -75,12 +77,10 @@ tags: class Solution: def minIncrementForUnique(self, nums: List[int]) -> int: nums.sort() - ans = 0 - for i in range(1, len(nums)): - if nums[i] <= nums[i - 1]: - d = nums[i - 1] - nums[i] + 1 - nums[i] += d - ans += d + ans, y = 0, -1 + for x in nums: + y = max(y + 1, x) + ans += y - x return ans ``` @@ -90,13 +90,10 @@ class Solution: class Solution { public int minIncrementForUnique(int[] nums) { Arrays.sort(nums); - int ans = 0; - for (int i = 1; i < nums.length; ++i) { - if (nums[i] <= nums[i - 1]) { - int d = nums[i - 1] - nums[i] + 1; - nums[i] += d; - ans += d; - } + int ans = 0, y = -1; + for (int x : nums) { + y = Math.max(y + 1, x); + ans += y - x; } return ans; } @@ -110,13 +107,10 @@ class Solution { public: int minIncrementForUnique(vector& nums) { sort(nums.begin(), nums.end()); - int ans = 0; - for (int i = 1; i < nums.size(); ++i) { - if (nums[i] <= nums[i - 1]) { - int d = nums[i - 1] - nums[i] + 1; - nums[i] += d; - ans += d; - } + int ans = 0, y = -1; + for (int x : nums) { + y = max(y + 1, x); + ans += y - x; } return ans; } @@ -128,12 +122,10 @@ public: ```go func minIncrementForUnique(nums []int) (ans int) { sort.Ints(nums) - for i := 1; i < len(nums); i++ { - if nums[i] <= nums[i-1] { - d := nums[i-1] - nums[i] + 1 - nums[i] += d - ans += d - } + y := -1 + for _, x := range nums { + y = max(y+1, x) + ans += y - x } return } @@ -144,12 +136,10 @@ func minIncrementForUnique(nums []int) (ans int) { ```ts function minIncrementForUnique(nums: number[]): number { nums.sort((a, b) => a - b); - let ans = 0; - for (let i = 1; i < nums.length; ++i) { - if (nums[i] <= nums[i - 1]) { - ans += nums[i - 1] - nums[i] + 1; - nums[i] = nums[i - 1] + 1; - } + let [ans, y] = [0, -1]; + for (const x of nums) { + y = Math.max(y + 1, x); + ans += y - x; } return ans; } @@ -163,13 +153,13 @@ function minIncrementForUnique(nums: number[]): number { ### 方法二:计数 + 贪心 -根据题目描述,结果数组的最大值 $m = \max(\text{nums}) + \text{len}(\text{nums})$,我们可以使用一个计数数组 `cnt` 来记录每个元素出现的次数。 +根据题目描述,结果数组的最大值 $m = \max(\textit{nums}) + \textit{len}(\textit{nums})$,我们可以使用一个计数数组 $\textit{cnt}$ 来记录每个元素出现的次数。 -然后从 $0$ 到 $m - 1$ 遍历,对于每个元素 $i$,如果它出现的次数 $\text{cnt}[i]$ 大于 $1$,那么我们将 $\text{cnt}[i] - 1$ 个元素增加到 $i + 1$,并将操作次数累加到结果中。 +然后从 $0$ 到 $m - 1$ 遍历,对于每个元素 $i$,如果它出现的次数 $\textit{cnt}[i]$ 大于 $1$,那么我们将 $\textit{cnt}[i] - 1$ 个元素增加到 $i + 1$,并将操作次数累加到结果中。 遍历完成后,返回结果即可。 -时间复杂度 $O(m)$,空间复杂度 $O(m)$。其中 $m$ 是数组 `nums` 的长度加上数组 `nums` 的最大值。 +时间复杂度 $O(m)$,空间复杂度 $O(m)$。其中 $m$ 是数组 $\textit{nums}$ 的长度加上数组的最大值。 diff --git a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README_EN.md b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README_EN.md index 1313b92c6ea6..54526c519914 100644 --- a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README_EN.md +++ b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/README_EN.md @@ -57,7 +57,15 @@ It can be shown with 5 or less moves that it is impossible for the array to have -### Solution 1 +### Solution 1: Sorting + Greedy + +First, we sort the array $\textit{nums}$, and use a variable $\textit{y}$ to record the current maximum value, initially $\textit{y} = -1$. + +Then, we iterate through the array $\textit{nums}$. For each element $x$, we update $y$ to $\max(y + 1, x)$, and accumulate the operation count $y - x$ into the result. + +After completing the iteration, we return the result. + +The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -67,12 +75,10 @@ It can be shown with 5 or less moves that it is impossible for the array to have class Solution: def minIncrementForUnique(self, nums: List[int]) -> int: nums.sort() - ans = 0 - for i in range(1, len(nums)): - if nums[i] <= nums[i - 1]: - d = nums[i - 1] - nums[i] + 1 - nums[i] += d - ans += d + ans, y = 0, -1 + for x in nums: + y = max(y + 1, x) + ans += y - x return ans ``` @@ -82,13 +88,10 @@ class Solution: class Solution { public int minIncrementForUnique(int[] nums) { Arrays.sort(nums); - int ans = 0; - for (int i = 1; i < nums.length; ++i) { - if (nums[i] <= nums[i - 1]) { - int d = nums[i - 1] - nums[i] + 1; - nums[i] += d; - ans += d; - } + int ans = 0, y = -1; + for (int x : nums) { + y = Math.max(y + 1, x); + ans += y - x; } return ans; } @@ -102,13 +105,10 @@ class Solution { public: int minIncrementForUnique(vector& nums) { sort(nums.begin(), nums.end()); - int ans = 0; - for (int i = 1; i < nums.size(); ++i) { - if (nums[i] <= nums[i - 1]) { - int d = nums[i - 1] - nums[i] + 1; - nums[i] += d; - ans += d; - } + int ans = 0, y = -1; + for (int x : nums) { + y = max(y + 1, x); + ans += y - x; } return ans; } @@ -120,12 +120,10 @@ public: ```go func minIncrementForUnique(nums []int) (ans int) { sort.Ints(nums) - for i := 1; i < len(nums); i++ { - if nums[i] <= nums[i-1] { - d := nums[i-1] - nums[i] + 1 - nums[i] += d - ans += d - } + y := -1 + for _, x := range nums { + y = max(y+1, x) + ans += y - x } return } @@ -136,12 +134,10 @@ func minIncrementForUnique(nums []int) (ans int) { ```ts function minIncrementForUnique(nums: number[]): number { nums.sort((a, b) => a - b); - let ans = 0; - for (let i = 1; i < nums.length; ++i) { - if (nums[i] <= nums[i - 1]) { - ans += nums[i - 1] - nums[i] + 1; - nums[i] = nums[i - 1] + 1; - } + let [ans, y] = [0, -1]; + for (const x of nums) { + y = Math.max(y + 1, x); + ans += y - x; } return ans; } @@ -155,13 +151,13 @@ function minIncrementForUnique(nums: number[]): number { ### Solution 2: Counting + Greedy -According to the problem description, the maximum value of the result array $m = \max(\text{nums}) + \text{len}(\text{nums})$. We can use a counting array `cnt` to record the occurrence times of each element. +According to the problem description, the maximum value of the result array $m = \max(\textit{nums}) + \textit{len}(\textit{nums})$. We can use a counting array $\textit{cnt}$ to record the occurrence count of each element. -Then, we iterate from $0$ to $m - 1$. For each element $i$, if its occurrence times $\text{cnt}[i]$ is greater than $1$, then we add $\text{cnt}[i] - 1$ elements to $i + 1$ and accumulate the operation times to the result. +Then, we iterate from $0$ to $m - 1$. For each element $i$, if its occurrence count $\textit{cnt}[i]$ is greater than $1$, then we add $\textit{cnt}[i] - 1$ elements to $i + 1$, and accumulate the operation count into the result. -After the iteration, we return the result. +After completing the iteration, we return the result. -The time complexity is $O(m)$, and the space complexity is $O(m)$. Here, $m$ is the length of the array `nums` plus the maximum value in the array `nums`. +The time complexity is $O(m)$, and the space complexity is $O(m)$. Here, $m$ is the length of the array $\textit{nums}$ plus the maximum value in the array. diff --git a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.cpp b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.cpp index 141f9e629b89..268c0354f83e 100644 --- a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.cpp +++ b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.cpp @@ -2,13 +2,10 @@ class Solution { public: int minIncrementForUnique(vector& nums) { sort(nums.begin(), nums.end()); - int ans = 0; - for (int i = 1; i < nums.size(); ++i) { - if (nums[i] <= nums[i - 1]) { - int d = nums[i - 1] - nums[i] + 1; - nums[i] += d; - ans += d; - } + int ans = 0, y = -1; + for (int x : nums) { + y = max(y + 1, x); + ans += y - x; } return ans; } diff --git a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.go b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.go index 08c6ed100afb..473c9050389d 100644 --- a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.go +++ b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.go @@ -1,12 +1,9 @@ -func minIncrementForUnique(nums []int) int { +func minIncrementForUnique(nums []int) (ans int) { sort.Ints(nums) - ans := 0 - for i := 1; i < len(nums); i++ { - if nums[i] <= nums[i-1] { - d := nums[i-1] - nums[i] + 1 - nums[i] += d - ans += d - } + y := -1 + for _, x := range nums { + y = max(y+1, x) + ans += y - x } - return ans + return } \ No newline at end of file diff --git a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.java b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.java index 79a7f668c065..2217b7c4b098 100644 --- a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.java +++ b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.java @@ -1,13 +1,10 @@ class Solution { public int minIncrementForUnique(int[] nums) { Arrays.sort(nums); - int ans = 0; - for (int i = 1; i < nums.length; ++i) { - if (nums[i] <= nums[i - 1]) { - int d = nums[i - 1] - nums[i] + 1; - nums[i] += d; - ans += d; - } + int ans = 0, y = -1; + for (int x : nums) { + y = Math.max(y + 1, x); + ans += y - x; } return ans; } diff --git a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.py b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.py index 9d439f599256..0c565cba79c8 100644 --- a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.py +++ b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.py @@ -1,10 +1,8 @@ class Solution: def minIncrementForUnique(self, nums: List[int]) -> int: nums.sort() - ans = 0 - for i in range(1, len(nums)): - if nums[i] <= nums[i - 1]: - d = nums[i - 1] - nums[i] + 1 - nums[i] += d - ans += d + ans, y = 0, -1 + for x in nums: + y = max(y + 1, x) + ans += y - x return ans diff --git a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.ts b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.ts index f69153a11a7f..62cf9a477f59 100644 --- a/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.ts +++ b/solution/0900-0999/0945.Minimum Increment to Make Array Unique/Solution.ts @@ -1,11 +1,9 @@ function minIncrementForUnique(nums: number[]): number { nums.sort((a, b) => a - b); - let ans = 0; - for (let i = 1; i < nums.length; ++i) { - if (nums[i] <= nums[i - 1]) { - ans += nums[i - 1] - nums[i] + 1; - nums[i] = nums[i - 1] + 1; - } + let [ans, y] = [0, -1]; + for (const x of nums) { + y = Math.max(y + 1, x); + ans += y - x; } return ans; } diff --git a/solution/0900-0999/0946.Validate Stack Sequences/README.md b/solution/0900-0999/0946.Validate Stack Sequences/README.md index c43f3658057a..0643f0b745b4 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/README.md +++ b/solution/0900-0999/0946.Validate Stack Sequences/README.md @@ -60,11 +60,9 @@ push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 ### 方法一:栈模拟 -遍历 `pushed` 序列,将每个数 `v` 依次压入栈中,压入后检查这个数是不是 `popped` 序列中下一个要弹出的值,如果是就循环把栈顶元素弹出。 +我们遍历 $\textit{pushed}$ 数组,对于当前遍历到的元素 $x$,我们将其压入栈 $\textit{stk}$ 中,然后判断栈顶元素是否和 $\textit{popped}$ 数组中下一个要弹出的元素相等,如果相等,我们就将栈顶元素弹出并将 $\textit{popped}$ 数组中下一个要弹出的元素的索引 $i$ 加一。最后,如果要弹出的元素都能按照 $\textit{popped}$ 数组的顺序弹出,返回 $\textit{true}$,否则返回 $\textit{false}$。 -遍历结束,如果 `popped` 序列已经到末尾,说明是一个合法的序列,否则不是。 - -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是 `pushed` 序列的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为 $\textit{pushed}$ 数组的长度。 @@ -73,13 +71,14 @@ push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 ```python class Solution: def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool: - j, stk = 0, [] - for v in pushed: - stk.append(v) - while stk and stk[-1] == popped[j]: + stk = [] + i = 0 + for x in pushed: + stk.append(x) + while stk and stk[-1] == popped[i]: stk.pop() - j += 1 - return j == len(pushed) + i += 1 + return i == len(popped) ``` #### Java @@ -88,15 +87,15 @@ class Solution: class Solution { public boolean validateStackSequences(int[] pushed, int[] popped) { Deque stk = new ArrayDeque<>(); - int j = 0; - for (int v : pushed) { - stk.push(v); - while (!stk.isEmpty() && stk.peek() == popped[j]) { + int i = 0; + for (int x : pushed) { + stk.push(x); + while (!stk.isEmpty() && stk.peek() == popped[i]) { stk.pop(); - ++j; + ++i; } } - return j == pushed.length; + return i == popped.length; } } ``` @@ -108,15 +107,15 @@ class Solution { public: bool validateStackSequences(vector& pushed, vector& popped) { stack stk; - int j = 0; - for (int v : pushed) { - stk.push(v); - while (!stk.empty() && stk.top() == popped[j]) { + int i = 0; + for (int x : pushed) { + stk.push(x); + while (stk.size() && stk.top() == popped[i]) { stk.pop(); - ++j; + ++i; } } - return j == pushed.size(); + return i == popped.size(); } }; ``` @@ -126,15 +125,15 @@ public: ```go func validateStackSequences(pushed []int, popped []int) bool { stk := []int{} - j := 0 - for _, v := range pushed { - stk = append(stk, v) - for len(stk) > 0 && stk[len(stk)-1] == popped[j] { + i := 0 + for _, x := range pushed { + stk = append(stk, x) + for len(stk) > 0 && stk[len(stk)-1] == popped[i] { stk = stk[:len(stk)-1] - j++ + i++ } } - return j == len(pushed) + return i == len(popped) } ``` @@ -142,16 +141,16 @@ func validateStackSequences(pushed []int, popped []int) bool { ```ts function validateStackSequences(pushed: number[], popped: number[]): boolean { - const stk = []; - let j = 0; - for (const v of pushed) { - stk.push(v); - while (stk.length && stk[stk.length - 1] == popped[j]) { + const stk: number[] = []; + let i = 0; + for (const x of pushed) { + stk.push(x); + while (stk.length && stk.at(-1)! === popped[i]) { stk.pop(); - ++j; + i++; } } - return j == pushed.length; + return i === popped.length; } ``` @@ -160,16 +159,16 @@ function validateStackSequences(pushed: number[], popped: number[]): boolean { ```rust impl Solution { pub fn validate_stack_sequences(pushed: Vec, popped: Vec) -> bool { - let mut stack = Vec::new(); + let mut stk: Vec = Vec::new(); let mut i = 0; - for &num in pushed.iter() { - stack.push(num); - while !stack.is_empty() && *stack.last().unwrap() == popped[i] { - stack.pop(); + for &x in &pushed { + stk.push(x); + while !stk.is_empty() && *stk.last().unwrap() == popped[i] { + stk.pop(); i += 1; } } - stack.len() == 0 + i == popped.len() } } ``` @@ -183,16 +182,16 @@ impl Solution { * @return {boolean} */ var validateStackSequences = function (pushed, popped) { - let stk = []; - let j = 0; - for (const v of pushed) { - stk.push(v); - while (stk.length && stk[stk.length - 1] == popped[j]) { + const stk = []; + let i = 0; + for (const x of pushed) { + stk.push(x); + while (stk.length && stk.at(-1) === popped[i]) { stk.pop(); - ++j; + i++; } } - return j == pushed.length; + return i === popped.length; }; ``` @@ -202,16 +201,17 @@ var validateStackSequences = function (pushed, popped) { public class Solution { public bool ValidateStackSequences(int[] pushed, int[] popped) { Stack stk = new Stack(); - int j = 0; - foreach (int x in pushed) - { + int i = 0; + + foreach (int x in pushed) { stk.Push(x); - while (stk.Count != 0 && stk.Peek() == popped[j]) { + while (stk.Count > 0 && stk.Peek() == popped[i]) { stk.Pop(); - ++j; + i++; } } - return stk.Count == 0; + + return i == popped.Length; } } ``` diff --git a/solution/0900-0999/0946.Validate Stack Sequences/README_EN.md b/solution/0900-0999/0946.Validate Stack Sequences/README_EN.md index da4100975da3..e837d2f87d45 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/README_EN.md +++ b/solution/0900-0999/0946.Validate Stack Sequences/README_EN.md @@ -58,7 +58,11 @@ pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 -### Solution 1 +### Solution 1: Stack Simulation + +We iterate through the $\textit{pushed}$ array. For the current element $x$ being iterated, we push it into the stack $\textit{stk}$. Then, we check if the top element of the stack is equal to the next element to be popped in the $\textit{popped}$ array. If they are equal, we pop the top element from the stack and increment the index $i$ of the next element to be popped in the $\textit{popped}$ array. Finally, if all elements can be popped in the order specified by the $\textit{popped}$ array, return $\textit{true}$; otherwise, return $\textit{false}$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the $\textit{pushed}$ array. @@ -67,13 +71,14 @@ pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 ```python class Solution: def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool: - j, stk = 0, [] - for v in pushed: - stk.append(v) - while stk and stk[-1] == popped[j]: + stk = [] + i = 0 + for x in pushed: + stk.append(x) + while stk and stk[-1] == popped[i]: stk.pop() - j += 1 - return j == len(pushed) + i += 1 + return i == len(popped) ``` #### Java @@ -82,15 +87,15 @@ class Solution: class Solution { public boolean validateStackSequences(int[] pushed, int[] popped) { Deque stk = new ArrayDeque<>(); - int j = 0; - for (int v : pushed) { - stk.push(v); - while (!stk.isEmpty() && stk.peek() == popped[j]) { + int i = 0; + for (int x : pushed) { + stk.push(x); + while (!stk.isEmpty() && stk.peek() == popped[i]) { stk.pop(); - ++j; + ++i; } } - return j == pushed.length; + return i == popped.length; } } ``` @@ -102,15 +107,15 @@ class Solution { public: bool validateStackSequences(vector& pushed, vector& popped) { stack stk; - int j = 0; - for (int v : pushed) { - stk.push(v); - while (!stk.empty() && stk.top() == popped[j]) { + int i = 0; + for (int x : pushed) { + stk.push(x); + while (stk.size() && stk.top() == popped[i]) { stk.pop(); - ++j; + ++i; } } - return j == pushed.size(); + return i == popped.size(); } }; ``` @@ -120,15 +125,15 @@ public: ```go func validateStackSequences(pushed []int, popped []int) bool { stk := []int{} - j := 0 - for _, v := range pushed { - stk = append(stk, v) - for len(stk) > 0 && stk[len(stk)-1] == popped[j] { + i := 0 + for _, x := range pushed { + stk = append(stk, x) + for len(stk) > 0 && stk[len(stk)-1] == popped[i] { stk = stk[:len(stk)-1] - j++ + i++ } } - return j == len(pushed) + return i == len(popped) } ``` @@ -136,16 +141,16 @@ func validateStackSequences(pushed []int, popped []int) bool { ```ts function validateStackSequences(pushed: number[], popped: number[]): boolean { - const stk = []; - let j = 0; - for (const v of pushed) { - stk.push(v); - while (stk.length && stk[stk.length - 1] == popped[j]) { + const stk: number[] = []; + let i = 0; + for (const x of pushed) { + stk.push(x); + while (stk.length && stk.at(-1)! === popped[i]) { stk.pop(); - ++j; + i++; } } - return j == pushed.length; + return i === popped.length; } ``` @@ -154,16 +159,16 @@ function validateStackSequences(pushed: number[], popped: number[]): boolean { ```rust impl Solution { pub fn validate_stack_sequences(pushed: Vec, popped: Vec) -> bool { - let mut stack = Vec::new(); + let mut stk: Vec = Vec::new(); let mut i = 0; - for &num in pushed.iter() { - stack.push(num); - while !stack.is_empty() && *stack.last().unwrap() == popped[i] { - stack.pop(); + for &x in &pushed { + stk.push(x); + while !stk.is_empty() && *stk.last().unwrap() == popped[i] { + stk.pop(); i += 1; } } - stack.len() == 0 + i == popped.len() } } ``` @@ -177,16 +182,16 @@ impl Solution { * @return {boolean} */ var validateStackSequences = function (pushed, popped) { - let stk = []; - let j = 0; - for (const v of pushed) { - stk.push(v); - while (stk.length && stk[stk.length - 1] == popped[j]) { + const stk = []; + let i = 0; + for (const x of pushed) { + stk.push(x); + while (stk.length && stk.at(-1) === popped[i]) { stk.pop(); - ++j; + i++; } } - return j == pushed.length; + return i === popped.length; }; ``` @@ -196,16 +201,17 @@ var validateStackSequences = function (pushed, popped) { public class Solution { public bool ValidateStackSequences(int[] pushed, int[] popped) { Stack stk = new Stack(); - int j = 0; - foreach (int x in pushed) - { + int i = 0; + + foreach (int x in pushed) { stk.Push(x); - while (stk.Count != 0 && stk.Peek() == popped[j]) { + while (stk.Count > 0 && stk.Peek() == popped[i]) { stk.Pop(); - ++j; + i++; } } - return stk.Count == 0; + + return i == popped.Length; } } ``` diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.cpp b/solution/0900-0999/0946.Validate Stack Sequences/Solution.cpp index 23c5e29fb158..47e56d9526b2 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.cpp +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.cpp @@ -2,14 +2,14 @@ class Solution { public: bool validateStackSequences(vector& pushed, vector& popped) { stack stk; - int j = 0; - for (int v : pushed) { - stk.push(v); - while (!stk.empty() && stk.top() == popped[j]) { + int i = 0; + for (int x : pushed) { + stk.push(x); + while (stk.size() && stk.top() == popped[i]) { stk.pop(); - ++j; + ++i; } } - return j == pushed.size(); + return i == popped.size(); } }; \ No newline at end of file diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.cs b/solution/0900-0999/0946.Validate Stack Sequences/Solution.cs index eb939e6252c7..d2ab729de5b7 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.cs +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.cs @@ -1,15 +1,16 @@ public class Solution { public bool ValidateStackSequences(int[] pushed, int[] popped) { Stack stk = new Stack(); - int j = 0; - foreach (int x in pushed) - { + int i = 0; + + foreach (int x in pushed) { stk.Push(x); - while (stk.Count != 0 && stk.Peek() == popped[j]) { + while (stk.Count > 0 && stk.Peek() == popped[i]) { stk.Pop(); - ++j; + i++; } } - return stk.Count == 0; + + return i == popped.Length; } -} +} \ No newline at end of file diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.go b/solution/0900-0999/0946.Validate Stack Sequences/Solution.go index 7216a0ab5e82..80099b6b98d2 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.go +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.go @@ -1,12 +1,12 @@ func validateStackSequences(pushed []int, popped []int) bool { stk := []int{} - j := 0 - for _, v := range pushed { - stk = append(stk, v) - for len(stk) > 0 && stk[len(stk)-1] == popped[j] { + i := 0 + for _, x := range pushed { + stk = append(stk, x) + for len(stk) > 0 && stk[len(stk)-1] == popped[i] { stk = stk[:len(stk)-1] - j++ + i++ } } - return j == len(pushed) + return i == len(popped) } \ No newline at end of file diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.java b/solution/0900-0999/0946.Validate Stack Sequences/Solution.java index aec88bfb9310..3a15272260ee 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.java +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.java @@ -1,14 +1,14 @@ class Solution { public boolean validateStackSequences(int[] pushed, int[] popped) { Deque stk = new ArrayDeque<>(); - int j = 0; - for (int v : pushed) { - stk.push(v); - while (!stk.isEmpty() && stk.peek() == popped[j]) { + int i = 0; + for (int x : pushed) { + stk.push(x); + while (!stk.isEmpty() && stk.peek() == popped[i]) { stk.pop(); - ++j; + ++i; } } - return j == pushed.length; + return i == popped.length; } } \ No newline at end of file diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.js b/solution/0900-0999/0946.Validate Stack Sequences/Solution.js index 64bd4910986e..da12ecdf91a3 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.js +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.js @@ -4,14 +4,14 @@ * @return {boolean} */ var validateStackSequences = function (pushed, popped) { - let stk = []; - let j = 0; - for (const v of pushed) { - stk.push(v); - while (stk.length && stk[stk.length - 1] == popped[j]) { + const stk = []; + let i = 0; + for (const x of pushed) { + stk.push(x); + while (stk.length && stk.at(-1) === popped[i]) { stk.pop(); - ++j; + i++; } } - return j == pushed.length; + return i === popped.length; }; diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.py b/solution/0900-0999/0946.Validate Stack Sequences/Solution.py index 25e1d6b0b771..d06286cbc523 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.py +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.py @@ -1,9 +1,10 @@ class Solution: def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool: - j, stk = 0, [] - for v in pushed: - stk.append(v) - while stk and stk[-1] == popped[j]: + stk = [] + i = 0 + for x in pushed: + stk.append(x) + while stk and stk[-1] == popped[i]: stk.pop() - j += 1 - return j == len(pushed) + i += 1 + return i == len(popped) diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.rs b/solution/0900-0999/0946.Validate Stack Sequences/Solution.rs index df75d0659a35..bc67c35b812d 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.rs +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.rs @@ -1,14 +1,14 @@ impl Solution { pub fn validate_stack_sequences(pushed: Vec, popped: Vec) -> bool { - let mut stack = Vec::new(); + let mut stk: Vec = Vec::new(); let mut i = 0; - for &num in pushed.iter() { - stack.push(num); - while !stack.is_empty() && *stack.last().unwrap() == popped[i] { - stack.pop(); + for &x in &pushed { + stk.push(x); + while !stk.is_empty() && *stk.last().unwrap() == popped[i] { + stk.pop(); i += 1; } } - stack.len() == 0 + i == popped.len() } } diff --git a/solution/0900-0999/0946.Validate Stack Sequences/Solution.ts b/solution/0900-0999/0946.Validate Stack Sequences/Solution.ts index 4eac7307db9d..d0f4d1a9d53b 100644 --- a/solution/0900-0999/0946.Validate Stack Sequences/Solution.ts +++ b/solution/0900-0999/0946.Validate Stack Sequences/Solution.ts @@ -1,12 +1,12 @@ function validateStackSequences(pushed: number[], popped: number[]): boolean { - const stk = []; - let j = 0; - for (const v of pushed) { - stk.push(v); - while (stk.length && stk[stk.length - 1] == popped[j]) { + const stk: number[] = []; + let i = 0; + for (const x of pushed) { + stk.push(x); + while (stk.length && stk.at(-1)! === popped[i]) { stk.pop(); - ++j; + i++; } } - return j == pushed.length; + return i === popped.length; } diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README.md b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README.md index b85e6131df0c..90f7b5ef95b9 100644 --- a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README.md +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README.md @@ -74,113 +74,531 @@ tags: -### 方法一 +### 方法一:并查集 + +我们可以用并查集维护石头之间的关系。如果两块石头在同一行或同一列,我们就认为它们之间有关系,可以通过并查集将它们连接起来。最后,我们统计并查集中有多少个连通分量,这个数值就是可以剩余的石头的数量,那么总共可以移除的石头数量就是石头总数减去剩余的石头数量。我们也可以在合并的时候,记录成功合并的次数,这个次数就是可以移除的石头的数量。 + +时间复杂度 $O(n^2 \times \alpha(n))$,空间复杂度 $O(n)$。其中 $n$ 为石头的数量。 #### Python3 ```python -class Solution: - def removeStones(self, stones: List[List[int]]) -> int: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True - n = 10010 - p = list(range(n << 1)) - for x, y in stones: - p[find(x)] = find(y + n) - s = {find(x) for x, _ in stones} - return len(stones) - len(s) +class Solution: + def removeStones(self, stones: List[List[int]]) -> int: + uf = UnionFind(len(stones)) + ans = 0 + for i, (x1, y1) in enumerate(stones): + for j, (x2, y2) in enumerate(stones[:i]): + if x1 == x2 or y1 == y2: + ans += uf.union(i, j) + return ans ``` #### Java ```java -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; + } + } + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { public int removeStones(int[][] stones) { - int n = 10010; - p = new int[n << 1]; - for (int i = 0; i < p.length; ++i) { - p[i] = i; + int n = stones.length; + UnionFind uf = new UnionFind(n); + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) { + ans += uf.union(i, j) ? 1 : 0; + } + } } - for (int[] stone : stones) { - p[find(stone[0])] = find(stone[1] + n); + return ans; + } +} +``` + +#### C++ + +```cpp +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; } - Set s = new HashSet<>(); - for (int[] stone : stones) { - s.add(find(stone[0])); + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } + + int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + +private: + vector p, size; +}; + +class Solution { +public: + int removeStones(vector>& stones) { + int n = stones.size(); + UnionFind uf(n); + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) { + ans += uf.unite(i, j); + } + } + } + return ans; + } +}; +``` + +#### Go + +```go +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func removeStones(stones [][]int) (ans int) { + n := len(stones) + uf := newUnionFind(n) + for i, s1 := range stones { + for j, s2 := range stones[:i] { + if s1[0] == s2[0] || s1[1] == s2[1] { + if uf.union(i, j) { + ans++ + } + } + } + } + return +} +``` + +#### TypeScript + +```ts +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function removeStones(stones: number[][]): number { + const n = stones.length; + const uf = new UnionFind(n); + let ans = 0; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + if (stones[i][0] === stones[j][0] || stones[i][1] === stones[j][1]) { + ans += uf.union(i, j) ? 1 : 0; + } + } + } + return ans; +} +``` + + + + + + + +### 方法二:并查集(优化) + +我们可以将石头的纵坐标加上一个偏移量,这样就可以将横坐标和纵坐标统一起来,然后用并查集维护横坐标和纵坐标之间的关系。 + +我们遍历每一块石头,将横坐标与纵坐标进行合并。 + +最后,我们再遍历所有石头,将每块石头的横坐标的根节点放到一个集合中,那么这个集合的数量就是可以剩余的石头的数量,总共可以移除的石头数量就是石头总数减去剩余的石头数量。 + +时间复杂度 $O(n \times \alpha(m))$,空间复杂度 $O(m)$。其中 $n$ 和 $m$ 分别为石头的数量和横纵坐标的最大值。 + + + +#### Python3 + +```python +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + +class Solution: + def removeStones(self, stones: List[List[int]]) -> int: + m = 10001 + uf = UnionFind(m << 1) + for x, y in stones: + uf.union(x, y + m) + return len(stones) - len({uf.find(x) for x, _ in stones}) +``` + +#### Java + +```java +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; } - return stones.length - s.size(); } - private int find(int x) { + public int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public int removeStones(int[][] stones) { + int m = 10001; + UnionFind uf = new UnionFind(m << 1); + for (var st : stones) { + uf.union(st[0], st[1] + m); + } + Set s = new HashSet<>(); + for (var st : stones) { + s.add(uf.find(st[0])); + } + return stones.length - s.size(); + } } ``` #### C++ ```cpp -class Solution { +class UnionFind { public: - vector p; + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } - int removeStones(vector>& stones) { - int n = 10010; - p.resize(n << 1); - for (int i = 0; i < p.size(); ++i) p[i] = i; - for (auto& stone : stones) p[find(stone[0])] = find(stone[1] + n); - unordered_set s; - for (auto& stone : stones) s.insert(find(stone[0])); - return stones.size() - s.size(); + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; } int find(int x) { - if (p[x] != x) p[x] = find(p[x]); + if (p[x] != x) { + p[x] = find(p[x]); + } return p[x]; } + +private: + vector p, size; +}; + +class Solution { +public: + int removeStones(vector>& stones) { + int m = 10001; + UnionFind uf(m << 1); + for (auto& st : stones) { + uf.unite(st[0], st[1] + m); + } + unordered_set s; + for (auto& st : stones) { + s.insert(uf.find(st[0])); + } + return stones.size() - s.size(); + } }; ``` #### Go ```go -func removeStones(stones [][]int) int { - n := 10010 - p := make([]int, n<<1) +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) for i := range p { p[i] = i + size[i] = 1 } - var find func(x int) int - find = func(x int) int { - if p[x] != x { - p[x] = find(p[x]) - } - return p[x] + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) } - for _, stone := range stones { - p[find(stone[0])] = find(stone[1] + n) + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func removeStones(stones [][]int) (ans int) { + m := 10001 + uf := newUnionFind(m << 1) + for _, st := range stones { + uf.union(st[0], st[1]+m) } - s := make(map[int]bool) - for _, stone := range stones { - s[find(stone[0])] = true + s := map[int]bool{} + for _, st := range stones { + s[uf.find(st[0])] = true } return len(stones) - len(s) } ``` +#### TypeScript + +```ts +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function removeStones(stones: number[][]): number { + const m = 10001; + const uf = new UnionFind(m << 1); + for (const [x, y] of stones) { + uf.union(x, y + m); + } + const s = new Set(); + for (const [x, _] of stones) { + s.add(uf.find(x)); + } + return stones.length - s.size; +} +``` + - + diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README_EN.md b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README_EN.md index da5f8f7d95fa..500e5ced4bc2 100644 --- a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README_EN.md +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/README_EN.md @@ -75,113 +75,531 @@ Stones [0,0] and [1,1] cannot be removed since they do not share a row/column wi -### Solution 1 +### Solution 1: Union-Find + +We can use a union-find data structure to maintain the relationships between stones. If two stones are in the same row or column, we consider them to be connected and use the union-find to link them together. In the end, we count how many connected components there are in the union-find, which corresponds to the number of stones that can remain. Therefore, the total number of stones that can be removed is the total number of stones minus the number of stones that can remain. We can also record the number of successful unions during the merge process, which equals the number of stones that can be removed. + +The time complexity is $O(n^2 \times \alpha(n))$, and the space complexity is $O(n)$. Here, $n$ is the number of stones. #### Python3 ```python -class Solution: - def removeStones(self, stones: List[List[int]]) -> int: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True - n = 10010 - p = list(range(n << 1)) - for x, y in stones: - p[find(x)] = find(y + n) - s = {find(x) for x, _ in stones} - return len(stones) - len(s) +class Solution: + def removeStones(self, stones: List[List[int]]) -> int: + uf = UnionFind(len(stones)) + ans = 0 + for i, (x1, y1) in enumerate(stones): + for j, (x2, y2) in enumerate(stones[:i]): + if x1 == x2 or y1 == y2: + ans += uf.union(i, j) + return ans ``` #### Java ```java -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; + } + } + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { public int removeStones(int[][] stones) { - int n = 10010; - p = new int[n << 1]; - for (int i = 0; i < p.length; ++i) { - p[i] = i; + int n = stones.length; + UnionFind uf = new UnionFind(n); + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) { + ans += uf.union(i, j) ? 1 : 0; + } + } } - for (int[] stone : stones) { - p[find(stone[0])] = find(stone[1] + n); + return ans; + } +} +``` + +#### C++ + +```cpp +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; } - Set s = new HashSet<>(); - for (int[] stone : stones) { - s.add(find(stone[0])); + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } + + int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + +private: + vector p, size; +}; + +class Solution { +public: + int removeStones(vector>& stones) { + int n = stones.size(); + UnionFind uf(n); + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) { + ans += uf.unite(i, j); + } + } + } + return ans; + } +}; +``` + +#### Go + +```go +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func removeStones(stones [][]int) (ans int) { + n := len(stones) + uf := newUnionFind(n) + for i, s1 := range stones { + for j, s2 := range stones[:i] { + if s1[0] == s2[0] || s1[1] == s2[1] { + if uf.union(i, j) { + ans++ + } + } + } + } + return +} +``` + +#### TypeScript + +```ts +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function removeStones(stones: number[][]): number { + const n = stones.length; + const uf = new UnionFind(n); + let ans = 0; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + if (stones[i][0] === stones[j][0] || stones[i][1] === stones[j][1]) { + ans += uf.union(i, j) ? 1 : 0; + } + } + } + return ans; +} +``` + + + + + + + +### Solution 2: Union-Find (Optimized) + +We can add an offset to the y-coordinates of the stones, allowing us to unify the x-coordinates and y-coordinates. Then, we use a union-find data structure to maintain the relationship between x-coordinates and y-coordinates. + +We iterate through each stone, merging its x-coordinate with its y-coordinate. + +Finally, we iterate through all the stones again, putting the root node of each stone's x-coordinate into a set. The number of elements in this set represents the number of stones that can remain. Therefore, the total number of stones that can be removed is the total number of stones minus the number of stones that can remain. + +The time complexity is $O(n \times \alpha(m))$, and the space complexity is $O(m)$. Here, $n$ and $m$ represent the number of stones and the maximum value of the coordinates, respectively. + + + +#### Python3 + +```python +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + +class Solution: + def removeStones(self, stones: List[List[int]]) -> int: + m = 10001 + uf = UnionFind(m << 1) + for x, y in stones: + uf.union(x, y + m) + return len(stones) - len({uf.find(x) for x, _ in stones}) +``` + +#### Java + +```java +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; } - return stones.length - s.size(); } - private int find(int x) { + public int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public int removeStones(int[][] stones) { + int m = 10001; + UnionFind uf = new UnionFind(m << 1); + for (var st : stones) { + uf.union(st[0], st[1] + m); + } + Set s = new HashSet<>(); + for (var st : stones) { + s.add(uf.find(st[0])); + } + return stones.length - s.size(); + } } ``` #### C++ ```cpp -class Solution { +class UnionFind { public: - vector p; + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } - int removeStones(vector>& stones) { - int n = 10010; - p.resize(n << 1); - for (int i = 0; i < p.size(); ++i) p[i] = i; - for (auto& stone : stones) p[find(stone[0])] = find(stone[1] + n); - unordered_set s; - for (auto& stone : stones) s.insert(find(stone[0])); - return stones.size() - s.size(); + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; } int find(int x) { - if (p[x] != x) p[x] = find(p[x]); + if (p[x] != x) { + p[x] = find(p[x]); + } return p[x]; } + +private: + vector p, size; +}; + +class Solution { +public: + int removeStones(vector>& stones) { + int m = 10001; + UnionFind uf(m << 1); + for (auto& st : stones) { + uf.unite(st[0], st[1] + m); + } + unordered_set s; + for (auto& st : stones) { + s.insert(uf.find(st[0])); + } + return stones.size() - s.size(); + } }; ``` #### Go ```go -func removeStones(stones [][]int) int { - n := 10010 - p := make([]int, n<<1) +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) for i := range p { p[i] = i + size[i] = 1 } - var find func(x int) int - find = func(x int) int { - if p[x] != x { - p[x] = find(p[x]) - } - return p[x] + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) } - for _, stone := range stones { - p[find(stone[0])] = find(stone[1] + n) + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func removeStones(stones [][]int) (ans int) { + m := 10001 + uf := newUnionFind(m << 1) + for _, st := range stones { + uf.union(st[0], st[1]+m) } - s := make(map[int]bool) - for _, stone := range stones { - s[find(stone[0])] = true + s := map[int]bool{} + for _, st := range stones { + s[uf.find(st[0])] = true } return len(stones) - len(s) } ``` +#### TypeScript + +```ts +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function removeStones(stones: number[][]): number { + const m = 10001; + const uf = new UnionFind(m << 1); + for (const [x, y] of stones) { + uf.union(x, y + m); + } + const s = new Set(); + for (const [x, _] of stones) { + s.add(uf.find(x)); + } + return stones.length - s.size; +} +``` + - + diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.cpp b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.cpp index 65b9cc19faeb..964f7cc9edd1 100644 --- a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.cpp +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.cpp @@ -1,19 +1,50 @@ -class Solution { +class UnionFind { public: - vector p; + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } - int removeStones(vector>& stones) { - int n = 10010; - p.resize(n << 1); - for (int i = 0; i < p.size(); ++i) p[i] = i; - for (auto& stone : stones) p[find(stone[0])] = find(stone[1] + n); - unordered_set s; - for (auto& stone : stones) s.insert(find(stone[0])); - return stones.size() - s.size(); + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; } int find(int x) { - if (p[x] != x) p[x] = find(p[x]); + if (p[x] != x) { + p[x] = find(p[x]); + } return p[x]; } + +private: + vector p, size; +}; + +class Solution { +public: + int removeStones(vector>& stones) { + int n = stones.size(); + UnionFind uf(n); + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) { + ans += uf.unite(i, j); + } + } + } + return ans; + } }; \ No newline at end of file diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.go b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.go index d26c7d3befbb..237421508ead 100644 --- a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.go +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.go @@ -1,22 +1,50 @@ -func removeStones(stones [][]int) int { - n := 10010 - p := make([]int, n<<1) +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) for i := range p { p[i] = i + size[i] = 1 } - var find func(x int) int - find = func(x int) int { - if p[x] != x { - p[x] = find(p[x]) - } - return p[x] + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false } - for _, stone := range stones { - p[find(stone[0])] = find(stone[1] + n) + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] } - s := make(map[int]bool) - for _, stone := range stones { - s[find(stone[0])] = true + return true +} + +func removeStones(stones [][]int) (ans int) { + n := len(stones) + uf := newUnionFind(n) + for i, s1 := range stones { + for j, s2 := range stones[:i] { + if s1[0] == s2[0] || s1[1] == s2[1] { + if uf.union(i, j) { + ans++ + } + } + } } - return len(stones) - len(s) + return } \ No newline at end of file diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.java b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.java index c58d5670722e..6360d5bcccff 100644 --- a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.java +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.java @@ -1,26 +1,51 @@ -class Solution { - private int[] p; +class UnionFind { + private final int[] p; + private final int[] size; - public int removeStones(int[][] stones) { - int n = 10010; - p = new int[n << 1]; - for (int i = 0; i < p.length; ++i) { + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { p[i] = i; + size[i] = 1; } - for (int[] stone : stones) { - p[find(stone[0])] = find(stone[1] + n); - } - Set s = new HashSet<>(); - for (int[] stone : stones) { - s.add(find(stone[0])); - } - return stones.length - s.size(); } - private int find(int x) { + public int find(int x) { if (p[x] != x) { p[x] = find(p[x]); } return p[x]; } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public int removeStones(int[][] stones) { + int n = stones.length; + UnionFind uf = new UnionFind(n); + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) { + ans += uf.union(i, j) ? 1 : 0; + } + } + } + return ans; + } } \ No newline at end of file diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.py b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.py index d9e7e561703a..2caf23d6f21b 100644 --- a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.py +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.py @@ -1,14 +1,32 @@ +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + class Solution: def removeStones(self, stones: List[List[int]]) -> int: - def find(x): - if p[x] != x: - p[x] = find(p[x]) - return p[x] - - n = 10010 - p = list(range(n << 1)) - for x, y in stones: - p[find(x)] = find(y + n) - - s = {find(x) for x, _ in stones} - return len(stones) - len(s) + uf = UnionFind(len(stones)) + ans = 0 + for i, (x1, y1) in enumerate(stones): + for j, (x2, y2) in enumerate(stones[:i]): + if x1 == x2 or y1 == y2: + ans += uf.union(i, j) + return ans diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.ts b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.ts new file mode 100644 index 000000000000..bad87164fe9a --- /dev/null +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution.ts @@ -0,0 +1,44 @@ +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function removeStones(stones: number[][]): number { + const n = stones.length; + const uf = new UnionFind(n); + let ans = 0; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + if (stones[i][0] === stones[j][0] || stones[i][1] === stones[j][1]) { + ans += uf.union(i, j) ? 1 : 0; + } + } + } + return ans; +} diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.cpp b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.cpp new file mode 100644 index 000000000000..b7c883083116 --- /dev/null +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.cpp @@ -0,0 +1,49 @@ +class UnionFind { +public: + UnionFind(int n) { + p = vector(n); + size = vector(n, 1); + iota(p.begin(), p.end(), 0); + } + + bool unite(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } + + int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + +private: + vector p, size; +}; + +class Solution { +public: + int removeStones(vector>& stones) { + int m = 10001; + UnionFind uf(m << 1); + for (auto& st : stones) { + uf.unite(st[0], st[1] + m); + } + unordered_set s; + for (auto& st : stones) { + s.insert(uf.find(st[0])); + } + return stones.size() - s.size(); + } +}; \ No newline at end of file diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.go b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.go new file mode 100644 index 000000000000..0f71b8f2584d --- /dev/null +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.go @@ -0,0 +1,48 @@ +type unionFind struct { + p, size []int +} + +func newUnionFind(n int) *unionFind { + p := make([]int, n) + size := make([]int, n) + for i := range p { + p[i] = i + size[i] = 1 + } + return &unionFind{p, size} +} + +func (uf *unionFind) find(x int) int { + if uf.p[x] != x { + uf.p[x] = uf.find(uf.p[x]) + } + return uf.p[x] +} + +func (uf *unionFind) union(a, b int) bool { + pa, pb := uf.find(a), uf.find(b) + if pa == pb { + return false + } + if uf.size[pa] > uf.size[pb] { + uf.p[pb] = pa + uf.size[pa] += uf.size[pb] + } else { + uf.p[pa] = pb + uf.size[pb] += uf.size[pa] + } + return true +} + +func removeStones(stones [][]int) (ans int) { + m := 10001 + uf := newUnionFind(m << 1) + for _, st := range stones { + uf.union(st[0], st[1]+m) + } + s := map[int]bool{} + for _, st := range stones { + s[uf.find(st[0])] = true + } + return len(stones) - len(s) +} \ No newline at end of file diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.java b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.java new file mode 100644 index 000000000000..fad77730e967 --- /dev/null +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.java @@ -0,0 +1,50 @@ +class UnionFind { + private final int[] p; + private final int[] size; + + public UnionFind(int n) { + p = new int[n]; + size = new int[n]; + for (int i = 0; i < n; ++i) { + p[i] = i; + size[i] = 1; + } + } + + public int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } + + public boolean union(int a, int b) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + if (size[pa] > size[pb]) { + p[pb] = pa; + size[pa] += size[pb]; + } else { + p[pa] = pb; + size[pb] += size[pa]; + } + return true; + } +} + +class Solution { + public int removeStones(int[][] stones) { + int m = 10001; + UnionFind uf = new UnionFind(m << 1); + for (var st : stones) { + uf.union(st[0], st[1] + m); + } + Set s = new HashSet<>(); + for (var st : stones) { + s.add(uf.find(st[0])); + } + return stones.length - s.size(); + } +} \ No newline at end of file diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.py b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.py new file mode 100644 index 000000000000..a1ae14907368 --- /dev/null +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.py @@ -0,0 +1,30 @@ +class UnionFind: + def __init__(self, n): + self.p = list(range(n)) + self.size = [1] * n + + def find(self, x): + if self.p[x] != x: + self.p[x] = self.find(self.p[x]) + return self.p[x] + + def union(self, a, b): + pa, pb = self.find(a), self.find(b) + if pa == pb: + return False + if self.size[pa] > self.size[pb]: + self.p[pb] = pa + self.size[pa] += self.size[pb] + else: + self.p[pa] = pb + self.size[pb] += self.size[pa] + return True + + +class Solution: + def removeStones(self, stones: List[List[int]]) -> int: + m = 10001 + uf = UnionFind(m << 1) + for x, y in stones: + uf.union(x, y + m) + return len(stones) - len({uf.find(x) for x, _ in stones}) diff --git a/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.ts b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.ts new file mode 100644 index 000000000000..83a5fbf69b38 --- /dev/null +++ b/solution/0900-0999/0947.Most Stones Removed with Same Row or Column/Solution2.ts @@ -0,0 +1,43 @@ +class UnionFind { + p: number[]; + size: number[]; + constructor(n: number) { + this.p = Array.from({ length: n }, (_, i) => i); + this.size = Array(n).fill(1); + } + + find(x: number): number { + if (this.p[x] !== x) { + this.p[x] = this.find(this.p[x]); + } + return this.p[x]; + } + + union(a: number, b: number): boolean { + const [pa, pb] = [this.find(a), this.find(b)]; + if (pa === pb) { + return false; + } + if (this.size[pa] > this.size[pb]) { + this.p[pb] = pa; + this.size[pa] += this.size[pb]; + } else { + this.p[pa] = pb; + this.size[pb] += this.size[pa]; + } + return true; + } +} + +function removeStones(stones: number[][]): number { + const m = 10001; + const uf = new UnionFind(m << 1); + for (const [x, y] of stones) { + uf.union(x, y + m); + } + const s = new Set(); + for (const [x, _] of stones) { + s.add(uf.find(x)); + } + return stones.length - s.size; +} diff --git a/solution/0900-0999/0948.Bag of Tokens/README.md b/solution/0900-0999/0948.Bag of Tokens/README.md index d3eb51ee73f0..96d19dc59304 100644 --- a/solution/0900-0999/0948.Bag of Tokens/README.md +++ b/solution/0900-0999/0948.Bag of Tokens/README.md @@ -85,7 +85,7 @@ tags: 因此,我们可以将令牌按照消耗能量的多少进行排序,然后使用双指针,一个指针从左向右遍历,一个指针从右向左遍历,每次遍历都尽可能地消耗能量得到分数,然后更新最大分数。如果当前能量不足以消耗当前令牌,那么我们就尝试使用分数来消耗当前令牌,如果分数不足以消耗当前令牌,那么我们就停止遍历。 -时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$。其中 $n$ 为令牌的数量。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是令牌的数量。 @@ -95,16 +95,16 @@ tags: class Solution: def bagOfTokensScore(self, tokens: List[int], power: int) -> int: tokens.sort() + ans = score = 0 i, j = 0, len(tokens) - 1 - ans = t = 0 while i <= j: if power >= tokens[i]: power -= tokens[i] - i, t = i + 1, t + 1 - ans = max(ans, t) - elif t: + score, i = score + 1, i + 1 + ans = max(ans, score) + elif score: power += tokens[j] - j, t = j - 1, t - 1 + score, j = score - 1, j - 1 else: break return ans @@ -116,16 +116,14 @@ class Solution: class Solution { public int bagOfTokensScore(int[] tokens, int power) { Arrays.sort(tokens); - int i = 0, j = tokens.length - 1; - int ans = 0, t = 0; - while (i <= j) { + int ans = 0, score = 0; + for (int i = 0, j = tokens.length - 1; i <= j;) { if (power >= tokens[i]) { power -= tokens[i++]; - ++t; - ans = Math.max(ans, t); - } else if (t > 0) { + ans = Math.max(ans, ++score); + } else if (score > 0) { power += tokens[j--]; - --t; + --score; } else { break; } @@ -142,15 +140,14 @@ class Solution { public: int bagOfTokensScore(vector& tokens, int power) { sort(tokens.begin(), tokens.end()); - int i = 0, j = tokens.size() - 1; - int ans = 0, t = 0; - while (i <= j) { + int ans = 0, score = 0; + for (int i = 0, j = tokens.size() - 1; i <= j;) { if (power >= tokens[i]) { power -= tokens[i++]; - ans = max(ans, ++t); - } else if (t) { + ans = max(ans, ++score); + } else if (score > 0) { power += tokens[j--]; - --t; + --score; } else { break; } @@ -163,23 +160,47 @@ public: #### Go ```go -func bagOfTokensScore(tokens []int, power int) int { +func bagOfTokensScore(tokens []int, power int) (ans int) { sort.Ints(tokens) i, j := 0, len(tokens)-1 - ans, t := 0, 0 + score := 0 for i <= j { if power >= tokens[i] { power -= tokens[i] - i, t = i+1, t+1 - ans = max(ans, t) - } else if t > 0 { + i++ + score++ + ans = max(ans, score) + } else if score > 0 { power += tokens[j] - j, t = j-1, t-1 + j-- + score-- } else { break } } - return ans + return +} +``` + +#### TypeScript + +```ts +function bagOfTokensScore(tokens: number[], power: number): number { + tokens.sort((a, b) => a - b); + let [i, j] = [0, tokens.length - 1]; + let [ans, score] = [0, 0]; + while (i <= j) { + if (power >= tokens[i]) { + power -= tokens[i++]; + ans = Math.max(ans, ++score); + } else if (score) { + power += tokens[j--]; + score--; + } else { + break; + } + } + return ans; } ``` diff --git a/solution/0900-0999/0948.Bag of Tokens/README_EN.md b/solution/0900-0999/0948.Bag of Tokens/README_EN.md index 24ddd7e9ea43..27640b569281 100644 --- a/solution/0900-0999/0948.Bag of Tokens/README_EN.md +++ b/solution/0900-0999/0948.Bag of Tokens/README_EN.md @@ -131,7 +131,13 @@ tags: -### Solution 1 +### Solution 1: Greedy + Sorting + Two Pointers + +There are two ways to use tokens: one is to consume energy to gain points, and the other is to consume points to gain energy. Obviously, we should consume as little energy as possible to gain as many points as possible. + +Therefore, we can sort the tokens by the amount of energy they consume, and then use two pointers: one moving from left to right and the other from right to left. In each iteration, we try to consume energy to gain points as much as possible, and then update the maximum score. If the current energy is not enough to consume the current token, we try to consume the current token using points. If the points are not enough to consume the current token, we stop the iteration. + +The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the number of tokens. @@ -141,16 +147,16 @@ tags: class Solution: def bagOfTokensScore(self, tokens: List[int], power: int) -> int: tokens.sort() + ans = score = 0 i, j = 0, len(tokens) - 1 - ans = t = 0 while i <= j: if power >= tokens[i]: power -= tokens[i] - i, t = i + 1, t + 1 - ans = max(ans, t) - elif t: + score, i = score + 1, i + 1 + ans = max(ans, score) + elif score: power += tokens[j] - j, t = j - 1, t - 1 + score, j = score - 1, j - 1 else: break return ans @@ -162,16 +168,14 @@ class Solution: class Solution { public int bagOfTokensScore(int[] tokens, int power) { Arrays.sort(tokens); - int i = 0, j = tokens.length - 1; - int ans = 0, t = 0; - while (i <= j) { + int ans = 0, score = 0; + for (int i = 0, j = tokens.length - 1; i <= j;) { if (power >= tokens[i]) { power -= tokens[i++]; - ++t; - ans = Math.max(ans, t); - } else if (t > 0) { + ans = Math.max(ans, ++score); + } else if (score > 0) { power += tokens[j--]; - --t; + --score; } else { break; } @@ -188,15 +192,14 @@ class Solution { public: int bagOfTokensScore(vector& tokens, int power) { sort(tokens.begin(), tokens.end()); - int i = 0, j = tokens.size() - 1; - int ans = 0, t = 0; - while (i <= j) { + int ans = 0, score = 0; + for (int i = 0, j = tokens.size() - 1; i <= j;) { if (power >= tokens[i]) { power -= tokens[i++]; - ans = max(ans, ++t); - } else if (t) { + ans = max(ans, ++score); + } else if (score > 0) { power += tokens[j--]; - --t; + --score; } else { break; } @@ -209,23 +212,47 @@ public: #### Go ```go -func bagOfTokensScore(tokens []int, power int) int { +func bagOfTokensScore(tokens []int, power int) (ans int) { sort.Ints(tokens) i, j := 0, len(tokens)-1 - ans, t := 0, 0 + score := 0 for i <= j { if power >= tokens[i] { power -= tokens[i] - i, t = i+1, t+1 - ans = max(ans, t) - } else if t > 0 { + i++ + score++ + ans = max(ans, score) + } else if score > 0 { power += tokens[j] - j, t = j-1, t-1 + j-- + score-- } else { break } } - return ans + return +} +``` + +#### TypeScript + +```ts +function bagOfTokensScore(tokens: number[], power: number): number { + tokens.sort((a, b) => a - b); + let [i, j] = [0, tokens.length - 1]; + let [ans, score] = [0, 0]; + while (i <= j) { + if (power >= tokens[i]) { + power -= tokens[i++]; + ans = Math.max(ans, ++score); + } else if (score) { + power += tokens[j--]; + score--; + } else { + break; + } + } + return ans; } ``` diff --git a/solution/0900-0999/0948.Bag of Tokens/Solution.cpp b/solution/0900-0999/0948.Bag of Tokens/Solution.cpp index 479ff7b4895e..ff642f24ff12 100644 --- a/solution/0900-0999/0948.Bag of Tokens/Solution.cpp +++ b/solution/0900-0999/0948.Bag of Tokens/Solution.cpp @@ -2,15 +2,14 @@ class Solution { public: int bagOfTokensScore(vector& tokens, int power) { sort(tokens.begin(), tokens.end()); - int i = 0, j = tokens.size() - 1; - int ans = 0, t = 0; - while (i <= j) { + int ans = 0, score = 0; + for (int i = 0, j = tokens.size() - 1; i <= j;) { if (power >= tokens[i]) { power -= tokens[i++]; - ans = max(ans, ++t); - } else if (t) { + ans = max(ans, ++score); + } else if (score > 0) { power += tokens[j--]; - --t; + --score; } else { break; } diff --git a/solution/0900-0999/0948.Bag of Tokens/Solution.go b/solution/0900-0999/0948.Bag of Tokens/Solution.go index 3a699daa3b5d..fa67e759711a 100644 --- a/solution/0900-0999/0948.Bag of Tokens/Solution.go +++ b/solution/0900-0999/0948.Bag of Tokens/Solution.go @@ -1,18 +1,20 @@ -func bagOfTokensScore(tokens []int, power int) int { +func bagOfTokensScore(tokens []int, power int) (ans int) { sort.Ints(tokens) i, j := 0, len(tokens)-1 - ans, t := 0, 0 + score := 0 for i <= j { if power >= tokens[i] { power -= tokens[i] - i, t = i+1, t+1 - ans = max(ans, t) - } else if t > 0 { + i++ + score++ + ans = max(ans, score) + } else if score > 0 { power += tokens[j] - j, t = j-1, t-1 + j-- + score-- } else { break } } - return ans + return } \ No newline at end of file diff --git a/solution/0900-0999/0948.Bag of Tokens/Solution.java b/solution/0900-0999/0948.Bag of Tokens/Solution.java index b03f5c96bf09..3a5fe8fd9629 100644 --- a/solution/0900-0999/0948.Bag of Tokens/Solution.java +++ b/solution/0900-0999/0948.Bag of Tokens/Solution.java @@ -1,16 +1,14 @@ class Solution { public int bagOfTokensScore(int[] tokens, int power) { Arrays.sort(tokens); - int i = 0, j = tokens.length - 1; - int ans = 0, t = 0; - while (i <= j) { + int ans = 0, score = 0; + for (int i = 0, j = tokens.length - 1; i <= j;) { if (power >= tokens[i]) { power -= tokens[i++]; - ++t; - ans = Math.max(ans, t); - } else if (t > 0) { + ans = Math.max(ans, ++score); + } else if (score > 0) { power += tokens[j--]; - --t; + --score; } else { break; } diff --git a/solution/0900-0999/0948.Bag of Tokens/Solution.py b/solution/0900-0999/0948.Bag of Tokens/Solution.py index 85ea4f759c86..af91e37cb927 100644 --- a/solution/0900-0999/0948.Bag of Tokens/Solution.py +++ b/solution/0900-0999/0948.Bag of Tokens/Solution.py @@ -1,16 +1,16 @@ class Solution: def bagOfTokensScore(self, tokens: List[int], power: int) -> int: tokens.sort() + ans = score = 0 i, j = 0, len(tokens) - 1 - ans = t = 0 while i <= j: if power >= tokens[i]: power -= tokens[i] - i, t = i + 1, t + 1 - ans = max(ans, t) - elif t: + score, i = score + 1, i + 1 + ans = max(ans, score) + elif score: power += tokens[j] - j, t = j - 1, t - 1 + score, j = score - 1, j - 1 else: break return ans diff --git a/solution/0900-0999/0948.Bag of Tokens/Solution.ts b/solution/0900-0999/0948.Bag of Tokens/Solution.ts new file mode 100644 index 000000000000..27159d810a8f --- /dev/null +++ b/solution/0900-0999/0948.Bag of Tokens/Solution.ts @@ -0,0 +1,17 @@ +function bagOfTokensScore(tokens: number[], power: number): number { + tokens.sort((a, b) => a - b); + let [i, j] = [0, tokens.length - 1]; + let [ans, score] = [0, 0]; + while (i <= j) { + if (power >= tokens[i]) { + power -= tokens[i++]; + ans = Math.max(ans, ++score); + } else if (score) { + power += tokens[j--]; + score--; + } else { + break; + } + } + return ans; +} diff --git a/solution/0900-0999/0956.Tallest Billboard/README.md b/solution/0900-0999/0956.Tallest Billboard/README.md index e745f9a2d972..9d919ef4ad0a 100644 --- a/solution/0900-0999/0956.Tallest Billboard/README.md +++ b/solution/0900-0999/0956.Tallest Billboard/README.md @@ -245,9 +245,9 @@ function tallestBillboard(rods: number[]): number { $$ \begin{aligned} f[i][j] &= f[i-1][j] \\ -f[i][j] &= max(f[i][j], f[i-1][j-rods[i-1]]) & \text{if } j \geq rods[i-1] \\ -f[i][j] &= max(f[i][j], f[i-1][j+rods[i-1]] + rods[i-1]) & \text{if } j + rods[i-1] \leq s \\ -f[i][j] &= max(f[i][j], f[i-1][rods[i-1]-j] + rods[i-1]-j) & \text{if } j \lt rods[i-1] +f[i][j] &= max(f[i][j], f[i-1][j-rods[i-1]]) & \textit{if } j \geq rods[i-1] \\ +f[i][j] &= max(f[i][j], f[i-1][j+rods[i-1]] + rods[i-1]) & \textit{if } j + rods[i-1] \leq s \\ +f[i][j] &= max(f[i][j], f[i-1][rods[i-1]-j] + rods[i-1]-j) & \textit{if } j \lt rods[i-1] \end{aligned} $$ diff --git a/solution/0900-0999/0959.Regions Cut By Slashes/README.md b/solution/0900-0999/0959.Regions Cut By Slashes/README.md index 6c7ce33e17e6..ec9f7d2195bb 100644 --- a/solution/0900-0999/0959.Regions Cut By Slashes/README.md +++ b/solution/0900-0999/0959.Regions Cut By Slashes/README.md @@ -279,6 +279,275 @@ func regionsBySlashes(grid []string) int { } ``` +#### TypeScript + +```ts +function regionsBySlashes(grid: string[]): number { + const find = (x: number) => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + + const union = (a: number, b: number) => { + const pa = find(a); + const pb = find(b); + if (pa !== pb) { + p[pa] = pb; + size--; + } + }; + + const n = grid.length; + let size = n * n * 4; + const p = Array.from({ length: size }, (_, i) => i); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const k = i * n + j; + if (i < n - 1) { + union(4 * k + 2, (k + n) * 4); + } + if (j < n - 1) { + union(4 * k + 1, (k + 1) * 4 + 3); + } + if (grid[i][j] === '/') { + union(4 * k, 4 * k + 3); + union(4 * k + 1, 4 * k + 2); + } else if (grid[i][j] === '\\') { + union(4 * k, 4 * k + 1); + union(4 * k + 2, 4 * k + 3); + } else { + union(4 * k, 4 * k + 1); + union(4 * k + 1, 4 * k + 2); + union(4 * k + 2, 4 * k + 3); + } + } + } + + return size; +} +``` + +#### JavaScript + +```js +/** + * @param {string[]} grid + * @return {number} + */ + +function regionsBySlashes(grid) { + const find = x => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + + const union = (a, b) => { + const pa = find(a); + const pb = find(b); + if (pa !== pb) { + p[pa] = pb; + size--; + } + }; + + const n = grid.length; + let size = n * n * 4; + const p = Array.from({ length: size }, (_, i) => i); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const k = i * n + j; + if (i < n - 1) { + union(4 * k + 2, (k + n) * 4); + } + if (j < n - 1) { + union(4 * k + 1, (k + 1) * 4 + 3); + } + if (grid[i][j] === '/') { + union(4 * k, 4 * k + 3); + union(4 * k + 1, 4 * k + 2); + } else if (grid[i][j] === '\\') { + union(4 * k, 4 * k + 1); + union(4 * k + 2, 4 * k + 3); + } else { + union(4 * k, 4 * k + 1); + union(4 * k + 1, 4 * k + 2); + union(4 * k + 2, 4 * k + 3); + } + } + } + + return size; +} +``` + + + + + + + +### 方法二:DFS + + + +#### TypeScript + +```ts +function regionsBySlashes(grid: string[]): number { + const createGraph = () => { + const n = grid.length; + const g = Array.from({ length: n * 2 }, () => Array(n * 2).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const [y, x] = [i * 2, j * 2]; + + switch (grid[i][j]) { + case '/': + g[y][x] = g[y + 1][x + 1] = 0; + g[y][x + 1] = g[y + 1][x] = 1; + break; + + case '\\': + g[y][x] = g[y + 1][x + 1] = 2; + g[y][x + 1] = g[y + 1][x] = 0; + break; + + default: + g[y][x] = g[y][x + 1] = g[y + 1][x] = g[y + 1][x + 1] = 0; + break; + } + } + } + + return g; + }; + + const isValid = (x: number) => 0 <= x && x < n; + const dfs = (i: number, j: number) => { + if (!isValid(i) || !isValid(j) || g[i][j]) return; + + g[i][j] = -1; + const dirs = [-1, 0, 1, 0, -1]; + const neighbours: number[] = []; + + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + + if (isValid(y) && isValid(x)) { + dfs(y, x); + neighbours.push(g[y][x]); + } else { + neighbours.push(-1); + } + } + + const [top, right, bottom, left] = neighbours; + if (top === 1 && right === 1) dfs(i - 1, j + 1); + if (bottom === 1 && left === 1) dfs(i + 1, j - 1); + if (top === 2 && left === 2) dfs(i - 1, j - 1); + if (bottom === 2 && right === 2) dfs(i + 1, j + 1); + }; + + const g = createGraph(); + const n = g.length; + let res = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (g[i][j] === 0) { + dfs(i, j); + res++; + } + } + } + + return res; +} +``` + +#### JavaScript + +```js +function regionsBySlashes(grid) { + const createGraph = () => { + const n = grid.length; + const g = Array.from({ length: n * 2 }, () => Array(n * 2).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const [y, x] = [i * 2, j * 2]; + + switch (grid[i][j]) { + case '/': + g[y][x] = g[y + 1][x + 1] = 0; + g[y][x + 1] = g[y + 1][x] = 1; + break; + + case '\\': + g[y][x] = g[y + 1][x + 1] = 2; + g[y][x + 1] = g[y + 1][x] = 0; + break; + + default: + g[y][x] = g[y][x + 1] = g[y + 1][x] = g[y + 1][x + 1] = 0; + break; + } + } + } + + return g; + }; + + const isValid = x => 0 <= x && x < n; + const dfs = (i, j) => { + if (!isValid(i) || !isValid(j) || g[i][j]) return; + + g[i][j] = -1; + const dirs = [-1, 0, 1, 0, -1]; + const neighbours = []; + + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + + if (isValid(y) && isValid(x)) { + dfs(y, x); + neighbours.push(g[y][x]); + } else { + neighbours.push(-1); + } + } + + const [top, right, bottom, left] = neighbours; + if (top === 1 && right === 1) dfs(i - 1, j + 1); + if (bottom === 1 && left === 1) dfs(i + 1, j - 1); + if (top === 2 && left === 2) dfs(i - 1, j - 1); + if (bottom === 2 && right === 2) dfs(i + 1, j + 1); + }; + + const g = createGraph(); + const n = g.length; + let res = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (g[i][j] === 0) { + dfs(i, j); + res++; + } + } + } + + return res; +} +``` + diff --git a/solution/0900-0999/0959.Regions Cut By Slashes/README_EN.md b/solution/0900-0999/0959.Regions Cut By Slashes/README_EN.md index 826f54d8a319..20202fba3a0b 100644 --- a/solution/0900-0999/0959.Regions Cut By Slashes/README_EN.md +++ b/solution/0900-0999/0959.Regions Cut By Slashes/README_EN.md @@ -65,7 +65,7 @@ tags: -### Solution 1 +### Solution 1: Union-Find @@ -269,6 +269,275 @@ func regionsBySlashes(grid []string) int { } ``` +#### TypeScript + +```ts +function regionsBySlashes(grid: string[]): number { + const find = (x: number) => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + + const union = (a: number, b: number) => { + const pa = find(a); + const pb = find(b); + if (pa !== pb) { + p[pa] = pb; + size--; + } + }; + + const n = grid.length; + let size = n * n * 4; + const p = Array.from({ length: size }, (_, i) => i); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const k = i * n + j; + if (i < n - 1) { + union(4 * k + 2, (k + n) * 4); + } + if (j < n - 1) { + union(4 * k + 1, (k + 1) * 4 + 3); + } + if (grid[i][j] === '/') { + union(4 * k, 4 * k + 3); + union(4 * k + 1, 4 * k + 2); + } else if (grid[i][j] === '\\') { + union(4 * k, 4 * k + 1); + union(4 * k + 2, 4 * k + 3); + } else { + union(4 * k, 4 * k + 1); + union(4 * k + 1, 4 * k + 2); + union(4 * k + 2, 4 * k + 3); + } + } + } + + return size; +} +``` + +#### JavaScript + +```js +/** + * @param {string[]} grid + * @return {number} + */ + +function regionsBySlashes(grid) { + const find = x => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + + const union = (a, b) => { + const pa = find(a); + const pb = find(b); + if (pa !== pb) { + p[pa] = pb; + size--; + } + }; + + const n = grid.length; + let size = n * n * 4; + const p = Array.from({ length: size }, (_, i) => i); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const k = i * n + j; + if (i < n - 1) { + union(4 * k + 2, (k + n) * 4); + } + if (j < n - 1) { + union(4 * k + 1, (k + 1) * 4 + 3); + } + if (grid[i][j] === '/') { + union(4 * k, 4 * k + 3); + union(4 * k + 1, 4 * k + 2); + } else if (grid[i][j] === '\\') { + union(4 * k, 4 * k + 1); + union(4 * k + 2, 4 * k + 3); + } else { + union(4 * k, 4 * k + 1); + union(4 * k + 1, 4 * k + 2); + union(4 * k + 2, 4 * k + 3); + } + } + } + + return size; +} +``` + + + + + + + +### Solution 2: DFS + + + +#### TypeScript + +```ts +function regionsBySlashes(grid: string[]): number { + const createGraph = () => { + const n = grid.length; + const g = Array.from({ length: n * 2 }, () => Array(n * 2).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const [y, x] = [i * 2, j * 2]; + + switch (grid[i][j]) { + case '/': + g[y][x] = g[y + 1][x + 1] = 0; + g[y][x + 1] = g[y + 1][x] = 1; + break; + + case '\\': + g[y][x] = g[y + 1][x + 1] = 2; + g[y][x + 1] = g[y + 1][x] = 0; + break; + + default: + g[y][x] = g[y][x + 1] = g[y + 1][x] = g[y + 1][x + 1] = 0; + break; + } + } + } + + return g; + }; + + const isValid = (x: number) => 0 <= x && x < n; + const dfs = (i: number, j: number) => { + if (!isValid(i) || !isValid(j) || g[i][j]) return; + + g[i][j] = -1; + const dirs = [-1, 0, 1, 0, -1]; + const neighbours: number[] = []; + + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + + if (isValid(y) && isValid(x)) { + dfs(y, x); + neighbours.push(g[y][x]); + } else { + neighbours.push(-1); + } + } + + const [top, right, bottom, left] = neighbours; + if (top === 1 && right === 1) dfs(i - 1, j + 1); + if (bottom === 1 && left === 1) dfs(i + 1, j - 1); + if (top === 2 && left === 2) dfs(i - 1, j - 1); + if (bottom === 2 && right === 2) dfs(i + 1, j + 1); + }; + + const g = createGraph(); + const n = g.length; + let res = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (g[i][j] === 0) { + dfs(i, j); + res++; + } + } + } + + return res; +} +``` + +#### JavaScript + +```js +function regionsBySlashes(grid) { + const createGraph = () => { + const n = grid.length; + const g = Array.from({ length: n * 2 }, () => Array(n * 2).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const [y, x] = [i * 2, j * 2]; + + switch (grid[i][j]) { + case '/': + g[y][x] = g[y + 1][x + 1] = 0; + g[y][x + 1] = g[y + 1][x] = 1; + break; + + case '\\': + g[y][x] = g[y + 1][x + 1] = 2; + g[y][x + 1] = g[y + 1][x] = 0; + break; + + default: + g[y][x] = g[y][x + 1] = g[y + 1][x] = g[y + 1][x + 1] = 0; + break; + } + } + } + + return g; + }; + + const isValid = x => 0 <= x && x < n; + const dfs = (i, j) => { + if (!isValid(i) || !isValid(j) || g[i][j]) return; + + g[i][j] = -1; + const dirs = [-1, 0, 1, 0, -1]; + const neighbours = []; + + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + + if (isValid(y) && isValid(x)) { + dfs(y, x); + neighbours.push(g[y][x]); + } else { + neighbours.push(-1); + } + } + + const [top, right, bottom, left] = neighbours; + if (top === 1 && right === 1) dfs(i - 1, j + 1); + if (bottom === 1 && left === 1) dfs(i + 1, j - 1); + if (top === 2 && left === 2) dfs(i - 1, j - 1); + if (bottom === 2 && right === 2) dfs(i + 1, j + 1); + }; + + const g = createGraph(); + const n = g.length; + let res = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (g[i][j] === 0) { + dfs(i, j); + res++; + } + } + } + + return res; +} +``` + diff --git a/solution/0900-0999/0959.Regions Cut By Slashes/Solution.js b/solution/0900-0999/0959.Regions Cut By Slashes/Solution.js new file mode 100644 index 000000000000..93275ea7a9b9 --- /dev/null +++ b/solution/0900-0999/0959.Regions Cut By Slashes/Solution.js @@ -0,0 +1,51 @@ +/** + * @param {string[]} grid + * @return {number} + */ + +function regionsBySlashes(grid) { + const find = x => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + + const union = (a, b) => { + const pa = find(a); + const pb = find(b); + if (pa !== pb) { + p[pa] = pb; + size--; + } + }; + + const n = grid.length; + let size = n * n * 4; + const p = Array.from({ length: size }, (_, i) => i); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const k = i * n + j; + if (i < n - 1) { + union(4 * k + 2, (k + n) * 4); + } + if (j < n - 1) { + union(4 * k + 1, (k + 1) * 4 + 3); + } + if (grid[i][j] === '/') { + union(4 * k, 4 * k + 3); + union(4 * k + 1, 4 * k + 2); + } else if (grid[i][j] === '\\') { + union(4 * k, 4 * k + 1); + union(4 * k + 2, 4 * k + 3); + } else { + union(4 * k, 4 * k + 1); + union(4 * k + 1, 4 * k + 2); + union(4 * k + 2, 4 * k + 3); + } + } + } + + return size; +} diff --git a/solution/0900-0999/0959.Regions Cut By Slashes/Solution.ts b/solution/0900-0999/0959.Regions Cut By Slashes/Solution.ts new file mode 100644 index 000000000000..c8019d2ffd82 --- /dev/null +++ b/solution/0900-0999/0959.Regions Cut By Slashes/Solution.ts @@ -0,0 +1,46 @@ +function regionsBySlashes(grid: string[]): number { + const find = (x: number) => { + if (p[x] !== x) { + p[x] = find(p[x]); + } + return p[x]; + }; + + const union = (a: number, b: number) => { + const pa = find(a); + const pb = find(b); + if (pa !== pb) { + p[pa] = pb; + size--; + } + }; + + const n = grid.length; + let size = n * n * 4; + const p = Array.from({ length: size }, (_, i) => i); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const k = i * n + j; + if (i < n - 1) { + union(4 * k + 2, (k + n) * 4); + } + if (j < n - 1) { + union(4 * k + 1, (k + 1) * 4 + 3); + } + if (grid[i][j] === '/') { + union(4 * k, 4 * k + 3); + union(4 * k + 1, 4 * k + 2); + } else if (grid[i][j] === '\\') { + union(4 * k, 4 * k + 1); + union(4 * k + 2, 4 * k + 3); + } else { + union(4 * k, 4 * k + 1); + union(4 * k + 1, 4 * k + 2); + union(4 * k + 2, 4 * k + 3); + } + } + } + + return size; +} diff --git a/solution/0900-0999/0959.Regions Cut By Slashes/Solution2.js b/solution/0900-0999/0959.Regions Cut By Slashes/Solution2.js new file mode 100644 index 000000000000..abe11132ffa5 --- /dev/null +++ b/solution/0900-0999/0959.Regions Cut By Slashes/Solution2.js @@ -0,0 +1,71 @@ +function regionsBySlashes(grid) { + const createGraph = () => { + const n = grid.length; + const g = Array.from({ length: n * 2 }, () => Array(n * 2).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const [y, x] = [i * 2, j * 2]; + + switch (grid[i][j]) { + case '/': + g[y][x] = g[y + 1][x + 1] = 0; + g[y][x + 1] = g[y + 1][x] = 1; + break; + + case '\\': + g[y][x] = g[y + 1][x + 1] = 2; + g[y][x + 1] = g[y + 1][x] = 0; + break; + + default: + g[y][x] = g[y][x + 1] = g[y + 1][x] = g[y + 1][x + 1] = 0; + break; + } + } + } + + return g; + }; + + const isValid = x => 0 <= x && x < n; + const dfs = (i, j) => { + if (!isValid(i) || !isValid(j) || g[i][j]) return; + + g[i][j] = -1; + const dirs = [-1, 0, 1, 0, -1]; + const neighbours = []; + + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + + if (isValid(y) && isValid(x)) { + dfs(y, x); + neighbours.push(g[y][x]); + } else { + neighbours.push(-1); + } + } + + const [top, right, bottom, left] = neighbours; + if (top === 1 && right === 1) dfs(i - 1, j + 1); + if (bottom === 1 && left === 1) dfs(i + 1, j - 1); + if (top === 2 && left === 2) dfs(i - 1, j - 1); + if (bottom === 2 && right === 2) dfs(i + 1, j + 1); + }; + + const g = createGraph(); + const n = g.length; + let res = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (g[i][j] === 0) { + dfs(i, j); + res++; + } + } + } + + return res; +} diff --git a/solution/0900-0999/0959.Regions Cut By Slashes/Solution2.ts b/solution/0900-0999/0959.Regions Cut By Slashes/Solution2.ts new file mode 100644 index 000000000000..7be3d87fcccb --- /dev/null +++ b/solution/0900-0999/0959.Regions Cut By Slashes/Solution2.ts @@ -0,0 +1,71 @@ +function regionsBySlashes(grid: string[]): number { + const createGraph = () => { + const n = grid.length; + const g = Array.from({ length: n * 2 }, () => Array(n * 2).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const [y, x] = [i * 2, j * 2]; + + switch (grid[i][j]) { + case '/': + g[y][x] = g[y + 1][x + 1] = 0; + g[y][x + 1] = g[y + 1][x] = 1; + break; + + case '\\': + g[y][x] = g[y + 1][x + 1] = 2; + g[y][x + 1] = g[y + 1][x] = 0; + break; + + default: + g[y][x] = g[y][x + 1] = g[y + 1][x] = g[y + 1][x + 1] = 0; + break; + } + } + } + + return g; + }; + + const isValid = (x: number) => 0 <= x && x < n; + const dfs = (i: number, j: number) => { + if (!isValid(i) || !isValid(j) || g[i][j]) return; + + g[i][j] = -1; + const dirs = [-1, 0, 1, 0, -1]; + const neighbours: number[] = []; + + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + + if (isValid(y) && isValid(x)) { + dfs(y, x); + neighbours.push(g[y][x]); + } else { + neighbours.push(-1); + } + } + + const [top, right, bottom, left] = neighbours; + if (top === 1 && right === 1) dfs(i - 1, j + 1); + if (bottom === 1 && left === 1) dfs(i + 1, j - 1); + if (top === 2 && left === 2) dfs(i - 1, j - 1); + if (bottom === 2 && right === 2) dfs(i + 1, j + 1); + }; + + const g = createGraph(); + const n = g.length; + let res = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if (g[i][j] === 0) { + dfs(i, j); + res++; + } + } + } + + return res; +} diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README.md b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README.md index 41251e625097..0f0c134573d4 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README.md +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README.md @@ -68,7 +68,13 @@ tags: -### 方法一 +### 方法一:DFS + +我们可以枚举所有长度为 $n$ 的数字的第一个数字,然后使用深度优先搜索的方法,递归地构造所有符合条件的数字。 + +具体地,我们首先定义一个边界值 $\textit{boundary} = 10^{n-1}$,表示我们需要构造的数字的最小值。然后,我们从 $1$ 到 $9$ 枚举第一个数字,对于每一个数字 $i$,我们递归地构造以 $i$ 为第一个数字的长度为 $n$ 的数字。 + +时间复杂度 $(n \times 2^n \times |\Sigma|)$,其中 $|\Sigma|$ 表示数字集合,本题中 $|\Sigma| = 9$。空间复杂度 $O(2^n)$。 @@ -77,20 +83,20 @@ tags: ```python class Solution: def numsSameConsecDiff(self, n: int, k: int) -> List[int]: - ans = [] - - def dfs(n, k, t): - if n == 0: - ans.append(t) + def dfs(x: int): + if x >= boundary: + ans.append(x) return - last = t % 10 + last = x % 10 if last + k <= 9: - dfs(n - 1, k, t * 10 + last + k) + dfs(x * 10 + last + k) if last - k >= 0 and k != 0: - dfs(n - 1, k, t * 10 + last - k) + dfs(x * 10 + last - k) + ans = [] + boundary = 10 ** (n - 1) for i in range(1, 10): - dfs(n - 1, k, i) + dfs(i) return ans ``` @@ -98,29 +104,30 @@ class Solution: ```java class Solution { + private List ans = new ArrayList<>(); + private int boundary; + private int k; + public int[] numsSameConsecDiff(int n, int k) { - List res = new ArrayList<>(); + this.k = k; + boundary = (int) Math.pow(10, n - 1); for (int i = 1; i < 10; ++i) { - dfs(n - 1, k, i, res); + dfs(i); } - int[] ans = new int[res.size()]; - for (int i = 0; i < res.size(); ++i) { - ans[i] = res.get(i); - } - return ans; + return ans.stream().mapToInt(i -> i).toArray(); } - private void dfs(int n, int k, int t, List res) { - if (n == 0) { - res.add(t); + private void dfs(int x) { + if (x >= boundary) { + ans.add(x); return; } - int last = t % 10; - if (last + k <= 9) { - dfs(n - 1, k, t * 10 + last + k, res); + int last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); } - if (last - k >= 0 && k != 0) { - dfs(n - 1, k, t * 10 + last - k, res); + if (k != 0 && last - k >= 0) { + dfs(x * 10 + last - k); } } } @@ -131,22 +138,26 @@ class Solution { ```cpp class Solution { public: - vector ans; - vector numsSameConsecDiff(int n, int k) { - for (int i = 1; i < 10; ++i) - dfs(n - 1, k, i); - return ans; - } - - void dfs(int n, int k, int t) { - if (n == 0) { - ans.push_back(t); - return; + vector ans; + int boundary = pow(10, n - 1); + auto dfs = [&](auto&& dfs, int x) { + if (x >= boundary) { + ans.push_back(x); + return; + } + int last = x % 10; + if (last + k < 10) { + dfs(dfs, x * 10 + last + k); + } + if (k != 0 && last - k >= 0) { + dfs(dfs, x * 10 + last - k); + } + }; + for (int i = 1; i < 10; ++i) { + dfs(dfs, i); } - int last = t % 10; - if (last + k <= 9) dfs(n - 1, k, t * 10 + last + k); - if (last - k >= 0 && k != 0) dfs(n - 1, k, t * 10 + last - k); + return ans; } }; ``` @@ -154,27 +165,26 @@ public: #### Go ```go -func numsSameConsecDiff(n int, k int) []int { - var ans []int - var dfs func(n, k, t int) - dfs = func(n, k, t int) { - if n == 0 { - ans = append(ans, t) +func numsSameConsecDiff(n int, k int) (ans []int) { + bounary := int(math.Pow10(n - 1)) + var dfs func(int) + dfs = func(x int) { + if x >= bounary { + ans = append(ans, x) return } - last := t % 10 - if last+k <= 9 { - dfs(n-1, k, t*10+last+k) + last := x % 10 + if last+k < 10 { + dfs(x*10 + last + k) } - if last-k >= 0 && k != 0 { - dfs(n-1, k, t*10+last-k) + if k > 0 && last-k >= 0 { + dfs(x*10 + last - k) } } - for i := 1; i < 10; i++ { - dfs(n-1, k, i) + dfs(i) } - return ans + return } ``` @@ -182,58 +192,57 @@ func numsSameConsecDiff(n int, k int) []int { ```ts function numsSameConsecDiff(n: number, k: number): number[] { - const ans = new Set(); + const ans: number[] = []; const boundary = 10 ** (n - 1); - - const dfs = (nums: number) => { - if (nums >= boundary) { - ans.add(nums); + const dfs = (x: number) => { + if (x >= boundary) { + ans.push(x); return; } - - const num = nums % 10; - for (const x of [num + k, num - k]) { - if (0 <= x && x < 10) { - dfs(nums * 10 + x); - } + const last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); + } + if (k > 0 && last - k >= 0) { + dfs(x * 10 + last - k); } }; - for (let i = 1; i < 10; i++) { dfs(i); } - - return [...ans]; + return ans; } ``` #### JavaScript ```js -function numsSameConsecDiff(n, k) { - const ans = new Set(); +/** + * @param {number} n + * @param {number} k + * @return {number[]} + */ +var numsSameConsecDiff = function (n, k) { + const ans = []; const boundary = 10 ** (n - 1); - - const dfs = nums => { - if (nums >= boundary) { - ans.add(nums); + const dfs = x => { + if (x >= boundary) { + ans.push(x); return; } - - const num = nums % 10; - for (const x of [num + k, num - k]) { - if (0 <= x && x < 10) { - dfs(nums * 10 + x); - } + const last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); + } + if (k > 0 && last - k >= 0) { + dfs(x * 10 + last - k); } }; - for (let i = 1; i < 10; i++) { dfs(i); } - - return [...ans]; -} + return ans; +}; ``` diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README_EN.md b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README_EN.md index 07361120c47c..df81fe1180a9 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README_EN.md +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/README_EN.md @@ -51,7 +51,13 @@ tags: -### Solution 1 +### Solution 1: DFS + +We can enumerate the first digit of all numbers of length $n$, and then use the depth-first search method to recursively construct all numbers that meet the conditions. + +Specifically, we first define a boundary value $\textit{boundary} = 10^{n-1}$, which represents the minimum value of the number we need to construct. Then, we enumerate the first digit from $1$ to $9$. For each digit $i$, we recursively construct the number of length $n$ with $i$ as the first digit. + +The time complexity is $(n \times 2^n \times |\Sigma|)$, where $|\Sigma|$ represents the set of digits, and in this problem $|\Sigma| = 9$. The space complexity is $O(2^n)$. @@ -60,20 +66,20 @@ tags: ```python class Solution: def numsSameConsecDiff(self, n: int, k: int) -> List[int]: - ans = [] - - def dfs(n, k, t): - if n == 0: - ans.append(t) + def dfs(x: int): + if x >= boundary: + ans.append(x) return - last = t % 10 + last = x % 10 if last + k <= 9: - dfs(n - 1, k, t * 10 + last + k) + dfs(x * 10 + last + k) if last - k >= 0 and k != 0: - dfs(n - 1, k, t * 10 + last - k) + dfs(x * 10 + last - k) + ans = [] + boundary = 10 ** (n - 1) for i in range(1, 10): - dfs(n - 1, k, i) + dfs(i) return ans ``` @@ -81,29 +87,30 @@ class Solution: ```java class Solution { + private List ans = new ArrayList<>(); + private int boundary; + private int k; + public int[] numsSameConsecDiff(int n, int k) { - List res = new ArrayList<>(); + this.k = k; + boundary = (int) Math.pow(10, n - 1); for (int i = 1; i < 10; ++i) { - dfs(n - 1, k, i, res); + dfs(i); } - int[] ans = new int[res.size()]; - for (int i = 0; i < res.size(); ++i) { - ans[i] = res.get(i); - } - return ans; + return ans.stream().mapToInt(i -> i).toArray(); } - private void dfs(int n, int k, int t, List res) { - if (n == 0) { - res.add(t); + private void dfs(int x) { + if (x >= boundary) { + ans.add(x); return; } - int last = t % 10; - if (last + k <= 9) { - dfs(n - 1, k, t * 10 + last + k, res); + int last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); } - if (last - k >= 0 && k != 0) { - dfs(n - 1, k, t * 10 + last - k, res); + if (k != 0 && last - k >= 0) { + dfs(x * 10 + last - k); } } } @@ -114,22 +121,26 @@ class Solution { ```cpp class Solution { public: - vector ans; - vector numsSameConsecDiff(int n, int k) { - for (int i = 1; i < 10; ++i) - dfs(n - 1, k, i); - return ans; - } - - void dfs(int n, int k, int t) { - if (n == 0) { - ans.push_back(t); - return; + vector ans; + int boundary = pow(10, n - 1); + auto dfs = [&](auto&& dfs, int x) { + if (x >= boundary) { + ans.push_back(x); + return; + } + int last = x % 10; + if (last + k < 10) { + dfs(dfs, x * 10 + last + k); + } + if (k != 0 && last - k >= 0) { + dfs(dfs, x * 10 + last - k); + } + }; + for (int i = 1; i < 10; ++i) { + dfs(dfs, i); } - int last = t % 10; - if (last + k <= 9) dfs(n - 1, k, t * 10 + last + k); - if (last - k >= 0 && k != 0) dfs(n - 1, k, t * 10 + last - k); + return ans; } }; ``` @@ -137,27 +148,26 @@ public: #### Go ```go -func numsSameConsecDiff(n int, k int) []int { - var ans []int - var dfs func(n, k, t int) - dfs = func(n, k, t int) { - if n == 0 { - ans = append(ans, t) +func numsSameConsecDiff(n int, k int) (ans []int) { + bounary := int(math.Pow10(n - 1)) + var dfs func(int) + dfs = func(x int) { + if x >= bounary { + ans = append(ans, x) return } - last := t % 10 - if last+k <= 9 { - dfs(n-1, k, t*10+last+k) + last := x % 10 + if last+k < 10 { + dfs(x*10 + last + k) } - if last-k >= 0 && k != 0 { - dfs(n-1, k, t*10+last-k) + if k > 0 && last-k >= 0 { + dfs(x*10 + last - k) } } - for i := 1; i < 10; i++ { - dfs(n-1, k, i) + dfs(i) } - return ans + return } ``` @@ -165,58 +175,57 @@ func numsSameConsecDiff(n int, k int) []int { ```ts function numsSameConsecDiff(n: number, k: number): number[] { - const ans = new Set(); + const ans: number[] = []; const boundary = 10 ** (n - 1); - - const dfs = (nums: number) => { - if (nums >= boundary) { - ans.add(nums); + const dfs = (x: number) => { + if (x >= boundary) { + ans.push(x); return; } - - const num = nums % 10; - for (const x of [num + k, num - k]) { - if (0 <= x && x < 10) { - dfs(nums * 10 + x); - } + const last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); + } + if (k > 0 && last - k >= 0) { + dfs(x * 10 + last - k); } }; - for (let i = 1; i < 10; i++) { dfs(i); } - - return [...ans]; + return ans; } ``` #### JavaScript ```js -function numsSameConsecDiff(n, k) { - const ans = new Set(); +/** + * @param {number} n + * @param {number} k + * @return {number[]} + */ +var numsSameConsecDiff = function (n, k) { + const ans = []; const boundary = 10 ** (n - 1); - - const dfs = nums => { - if (nums >= boundary) { - ans.add(nums); + const dfs = x => { + if (x >= boundary) { + ans.push(x); return; } - - const num = nums % 10; - for (const x of [num + k, num - k]) { - if (0 <= x && x < 10) { - dfs(nums * 10 + x); - } + const last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); + } + if (k > 0 && last - k >= 0) { + dfs(x * 10 + last - k); } }; - for (let i = 1; i < 10; i++) { dfs(i); } - - return [...ans]; -} + return ans; +}; ``` diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.cpp b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.cpp index 9e5b5b328b2c..93d2a7e66619 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.cpp +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.cpp @@ -1,20 +1,24 @@ class Solution { public: - vector ans; - vector numsSameConsecDiff(int n, int k) { - for (int i = 1; i < 10; ++i) - dfs(n - 1, k, i); - return ans; - } - - void dfs(int n, int k, int t) { - if (n == 0) { - ans.push_back(t); - return; + vector ans; + int boundary = pow(10, n - 1); + auto dfs = [&](auto&& dfs, int x) { + if (x >= boundary) { + ans.push_back(x); + return; + } + int last = x % 10; + if (last + k < 10) { + dfs(dfs, x * 10 + last + k); + } + if (k != 0 && last - k >= 0) { + dfs(dfs, x * 10 + last - k); + } + }; + for (int i = 1; i < 10; ++i) { + dfs(dfs, i); } - int last = t % 10; - if (last + k <= 9) dfs(n - 1, k, t * 10 + last + k); - if (last - k >= 0 && k != 0) dfs(n - 1, k, t * 10 + last - k); + return ans; } -}; \ No newline at end of file +}; diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.go b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.go index 4d14a3b227a0..dc737e606423 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.go +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.go @@ -1,22 +1,21 @@ -func numsSameConsecDiff(n int, k int) []int { - var ans []int - var dfs func(n, k, t int) - dfs = func(n, k, t int) { - if n == 0 { - ans = append(ans, t) +func numsSameConsecDiff(n int, k int) (ans []int) { + bounary := int(math.Pow10(n - 1)) + var dfs func(int) + dfs = func(x int) { + if x >= bounary { + ans = append(ans, x) return } - last := t % 10 - if last+k <= 9 { - dfs(n-1, k, t*10+last+k) + last := x % 10 + if last+k < 10 { + dfs(x*10 + last + k) } - if last-k >= 0 && k != 0 { - dfs(n-1, k, t*10+last-k) + if k > 0 && last-k >= 0 { + dfs(x*10 + last - k) } } - for i := 1; i < 10; i++ { - dfs(n-1, k, i) + dfs(i) } - return ans -} \ No newline at end of file + return +} diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.java b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.java index c4dd47c64720..1b11274810fc 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.java +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.java @@ -1,27 +1,28 @@ class Solution { + private List ans = new ArrayList<>(); + private int boundary; + private int k; + public int[] numsSameConsecDiff(int n, int k) { - List res = new ArrayList<>(); + this.k = k; + boundary = (int) Math.pow(10, n - 1); for (int i = 1; i < 10; ++i) { - dfs(n - 1, k, i, res); - } - int[] ans = new int[res.size()]; - for (int i = 0; i < res.size(); ++i) { - ans[i] = res.get(i); + dfs(i); } - return ans; + return ans.stream().mapToInt(i -> i).toArray(); } - private void dfs(int n, int k, int t, List res) { - if (n == 0) { - res.add(t); + private void dfs(int x) { + if (x >= boundary) { + ans.add(x); return; } - int last = t % 10; - if (last + k <= 9) { - dfs(n - 1, k, t * 10 + last + k, res); + int last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); } - if (last - k >= 0 && k != 0) { - dfs(n - 1, k, t * 10 + last - k, res); + if (k != 0 && last - k >= 0) { + dfs(x * 10 + last - k); } } -} \ No newline at end of file +} diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.js b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.js index 29fe44aa4c44..83f2a8eeb880 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.js +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.js @@ -1,24 +1,26 @@ -function numsSameConsecDiff(n, k) { - const ans = new Set(); +/** + * @param {number} n + * @param {number} k + * @return {number[]} + */ +var numsSameConsecDiff = function (n, k) { + const ans = []; const boundary = 10 ** (n - 1); - - const dfs = nums => { - if (nums >= boundary) { - ans.add(nums); + const dfs = x => { + if (x >= boundary) { + ans.push(x); return; } - - const num = nums % 10; - for (const x of [num + k, num - k]) { - if (0 <= x && x < 10) { - dfs(nums * 10 + x); - } + const last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); + } + if (k > 0 && last - k >= 0) { + dfs(x * 10 + last - k); } }; - for (let i = 1; i < 10; i++) { dfs(i); } - - return [...ans]; -} + return ans; +}; diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.py b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.py index 1705a5730439..049b2e22a246 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.py +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.py @@ -1,17 +1,17 @@ class Solution: def numsSameConsecDiff(self, n: int, k: int) -> List[int]: - ans = [] - - def dfs(n, k, t): - if n == 0: - ans.append(t) + def dfs(x: int): + if x >= boundary: + ans.append(x) return - last = t % 10 + last = x % 10 if last + k <= 9: - dfs(n - 1, k, t * 10 + last + k) + dfs(x * 10 + last + k) if last - k >= 0 and k != 0: - dfs(n - 1, k, t * 10 + last - k) + dfs(x * 10 + last - k) + ans = [] + boundary = 10 ** (n - 1) for i in range(1, 10): - dfs(n - 1, k, i) + dfs(i) return ans diff --git a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.ts b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.ts index 8da7c4da8a91..a35d9eb75248 100644 --- a/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.ts +++ b/solution/0900-0999/0967.Numbers With Same Consecutive Differences/Solution.ts @@ -1,24 +1,21 @@ function numsSameConsecDiff(n: number, k: number): number[] { - const ans = new Set(); + const ans: number[] = []; const boundary = 10 ** (n - 1); - - const dfs = (nums: number) => { - if (nums >= boundary) { - ans.add(nums); + const dfs = (x: number) => { + if (x >= boundary) { + ans.push(x); return; } - - const num = nums % 10; - for (const x of [num + k, num - k]) { - if (0 <= x && x < 10) { - dfs(nums * 10 + x); - } + const last = x % 10; + if (last + k < 10) { + dfs(x * 10 + last + k); + } + if (k > 0 && last - k >= 0) { + dfs(x * 10 + last - k); } }; - for (let i = 1; i < 10; i++) { dfs(i); } - - return [...ans]; + return ans; } diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README.md b/solution/0900-0999/0973.K Closest Points to Origin/README.md index d2c088e0e15a..c2619b2a8acc 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README.md @@ -71,7 +71,7 @@ tags: 我们将所有点按照与原点的距离从小到大排序,然后取前 $k$ 个点即可。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\text{points}$ 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\textit{points}$ 的长度。 @@ -155,7 +155,7 @@ impl Solution { 我们可以使用一个优先队列(大根堆)来维护距离原点最近的 $k$ 个点。 -时间复杂度 $O(n \times \log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\text{points}$ 的长度。 +时间复杂度 $O(n \times \log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\textit{points}$ 的长度。 @@ -285,7 +285,7 @@ function kClosest(points: number[][], k: number): number[][] { 二分查找结束后,我们只需要返回距离小于等于左边界的点即可。 -时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{points}$ 的长度,而 $M$ 为距离的最大值。 +时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{points}$ 的长度,而 $M$ 为距离的最大值。 diff --git a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md index 6a79fa85e7dc..5a6704413aee 100644 --- a/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md +++ b/solution/0900-0999/0973.K Closest Points to Origin/README_EN.md @@ -67,7 +67,7 @@ We only want the closest k = 1 points from the origin, so the answer is just [[- We sort all points by their distance from the origin in ascending order, and then take the first $k$ points. -The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\text{points}$. +The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\textit{points}$. @@ -151,7 +151,7 @@ impl Solution { We can use a priority queue (max heap) to maintain the $k$ closest points to the origin. -The time complexity is $O(n \times \log k)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array $\text{points}$. +The time complexity is $O(n \times \log k)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array $\textit{points}$. @@ -281,7 +281,7 @@ Therefore, we can use binary search to enumerate the distance. In each binary se After the binary search is finished, we just need to return the points whose distance is less than or equal to the left boundary. -The time complexity is $O(n \times \log M)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\text{points}$, and $M$ is the maximum value of the distance. +The time complexity is $O(n \times \log M)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{points}$, and $M$ is the maximum value of the distance. diff --git a/solution/0900-0999/0979.Distribute Coins in Binary Tree/README.md b/solution/0900-0999/0979.Distribute Coins in Binary Tree/README.md index 7602fd576171..c6ea3a99187d 100644 --- a/solution/0900-0999/0979.Distribute Coins in Binary Tree/README.md +++ b/solution/0900-0999/0979.Distribute Coins in Binary Tree/README.md @@ -61,9 +61,9 @@ tags: ### 方法一:DFS -我们定义一个函数 $\text{dfs(\text{node})}$,表示以 $\text{node}$ 为根节点的子树中,金币的超载量,即金币的数量减去节点数。如果 $\text{dfs(\text{node})}$ 为正数,表示该子树中金币的数量多于节点数,需要将多余的金币移出该子树;如果 $\text{dfs(\text{node})}$ 为负数,表示该子树中金币的数量少于节点数,需要将不足的金币移入该子树。 +我们定义一个函数 $\textit{dfs(\textit{node})}$,表示以 $\textit{node}$ 为根节点的子树中,金币的超载量,即金币的数量减去节点数。如果 $\textit{dfs(\textit{node})}$ 为正数,表示该子树中金币的数量多于节点数,需要将多余的金币移出该子树;如果 $\textit{dfs(\textit{node})}$ 为负数,表示该子树中金币的数量少于节点数,需要将不足的金币移入该子树。 -在函数 $\text{dfs(\text{node})}$ 中,我们首先遍历左右子树,获得左右子树的金币超载量 $\text{left}$ 和 $\text{right}$。那么当前移动的次数需要加上 $|\text{left}| + |\text{right}|$,即将左右子树中的金币移动到当前节点。然后,我们返回整个子树的金币超载量,即 $\text{left} + \text{right} + \text{node.val} - 1$。 +在函数 $\textit{dfs(\textit{node})}$ 中,我们首先遍历左右子树,获得左右子树的金币超载量 $\textit{left}$ 和 $\textit{right}$。那么当前移动的次数需要加上 $|\textit{left}| + |\textit{right}|$,即将左右子树中的金币移动到当前节点。然后,我们返回整个子树的金币超载量,即 $\textit{left} + \textit{right} + \textit{node.val} - 1$。 最后返回移动的次数即可。 diff --git a/solution/0900-0999/0979.Distribute Coins in Binary Tree/README_EN.md b/solution/0900-0999/0979.Distribute Coins in Binary Tree/README_EN.md index 33414a0a71cf..e808d017f80f 100644 --- a/solution/0900-0999/0979.Distribute Coins in Binary Tree/README_EN.md +++ b/solution/0900-0999/0979.Distribute Coins in Binary Tree/README_EN.md @@ -59,9 +59,9 @@ tags: ### Solution 1: DFS -We define a function $\text{dfs(node)}$, which represents the coin overload in the subtree rooted at $\text{node}$, i.e., the number of coins minus the number of nodes. If $\text{dfs(node)}$ is positive, it means the subtree has more coins than nodes, and the excess coins need to be moved out of the subtree; if $\text{dfs(node)}$ is negative, it means the subtree has fewer coins than nodes, and the shortfall needs to be moved into the subtree. +We define a function $\textit{dfs(node)}$, which represents the coin overload in the subtree rooted at $\textit{node}$, i.e., the number of coins minus the number of nodes. If $\textit{dfs(node)}$ is positive, it means the subtree has more coins than nodes, and the excess coins need to be moved out of the subtree; if $\textit{dfs(node)}$ is negative, it means the subtree has fewer coins than nodes, and the shortfall needs to be moved into the subtree. -In the function $\text{dfs(node)}$, we first traverse the left and right subtrees to obtain the coin overload $\text{left}$ and $\text{right}$ of the left and right subtrees, respectively. Then, the current number of moves needs to be increased by $|\text{left}| + |\text{right}|$, which means moving the coins from the left and right subtrees to the current node. After that, we return the coin overload of the entire subtree, which is $\text{left} + \text{right} + \text{node.val} - 1$. +In the function $\textit{dfs(node)}$, we first traverse the left and right subtrees to obtain the coin overload $\textit{left}$ and $\textit{right}$ of the left and right subtrees, respectively. Then, the current number of moves needs to be increased by $|\textit{left}| + |\textit{right}|$, which means moving the coins from the left and right subtrees to the current node. After that, we return the coin overload of the entire subtree, which is $\textit{left} + \textit{right} + \textit{node.val} - 1$. Finally, we return the number of moves. diff --git a/solution/0900-0999/0983.Minimum Cost For Tickets/README.md b/solution/0900-0999/0983.Minimum Cost For Tickets/README.md index e15b0e21a303..3bbdbc2ca3ab 100644 --- a/solution/0900-0999/0983.Minimum Cost For Tickets/README.md +++ b/solution/0900-0999/0983.Minimum Cost For Tickets/README.md @@ -78,12 +78,12 @@ tags: ### 方法一:记忆化搜索 + 二分查找 -我们定义一个函数 $\text{dfs(i)}$,表示从第 $i$ 次出行开始到最后一次出行结束所需的最小花费。那么答案为 $\text{dfs(0)}$。 +我们定义一个函数 $\textit{dfs(i)}$,表示从第 $i$ 次出行开始到最后一次出行结束所需的最小花费。那么答案为 $\textit{dfs(0)}$。 -函数 $\text{dfs(i)}$ 的执行过程如下: +函数 $\textit{dfs(i)}$ 的执行过程如下: - 如果 $i \geq n$,表示所有出行已经结束,返回 $0$; -- 否则,我们需要考虑三种购买方式,分别是购买 $1$ 天通行证、购买 $7$ 天通行证和购买 $30$ 天通行证。我们分别计算这三种购买方式的花费,并且利用二分查找,找到下一次出行的下标 $j$,然后递归调用 $\text{dfs(j)}$,最后返回这三种购买方式的最小花费。 +- 否则,我们需要考虑三种购买方式,分别是购买 $1$ 天通行证、购买 $7$ 天通行证和购买 $30$ 天通行证。我们分别计算这三种购买方式的花费,并且利用二分查找,找到下一次出行的下标 $j$,然后递归调用 $\textit{dfs(j)}$,最后返回这三种购买方式的最小花费。 为了避免重复计算,我们使用记忆化搜索,将已经计算过的结果保存起来。 @@ -247,9 +247,9 @@ function mincostTickets(days: number[], costs: number[]): number { ### 方法二:动态规划 -我们不妨记 $\text{days}$ 数组中的最后一天为 $m$,那么我们可以定义一个长度为 $m + 1$ 的数组 $f$,其中 $f[i]$ 表示从第 $1$ 天到第 $i$ 天的最小花费。 +我们不妨记 $\textit{days}$ 数组中的最后一天为 $m$,那么我们可以定义一个长度为 $m + 1$ 的数组 $f$,其中 $f[i]$ 表示从第 $1$ 天到第 $i$ 天的最小花费。 -我们可以按照 $\text{days}$ 数组中的日期递增的顺序,从第 $1$ 天开始,依次计算 $f[i]$ 的值。如果第 $i$ 天是出行的日期,那么我们可以考虑三种购买方式,分别是购买 $1$ 天通行证、购买 $7$ 天通行证和购买 $30$ 天通行证。我们分别计算这三种购买方式的花费,并且取这三种购买方式的最小花费作为 $f[i]$ 的值。如果第 $i$ 天不是出行的日期,那么 $f[i] = f[i - 1]$。 +我们可以按照 $\textit{days}$ 数组中的日期递增的顺序,从第 $1$ 天开始,依次计算 $f[i]$ 的值。如果第 $i$ 天是出行的日期,那么我们可以考虑三种购买方式,分别是购买 $1$ 天通行证、购买 $7$ 天通行证和购买 $30$ 天通行证。我们分别计算这三种购买方式的花费,并且取这三种购买方式的最小花费作为 $f[i]$ 的值。如果第 $i$ 天不是出行的日期,那么 $f[i] = f[i - 1]$。 最终答案为 $f[m]$。 diff --git a/solution/0900-0999/0983.Minimum Cost For Tickets/README_EN.md b/solution/0900-0999/0983.Minimum Cost For Tickets/README_EN.md index 4323db3959fe..4d70c7339522 100644 --- a/solution/0900-0999/0983.Minimum Cost For Tickets/README_EN.md +++ b/solution/0900-0999/0983.Minimum Cost For Tickets/README_EN.md @@ -78,12 +78,12 @@ In total, you spent $17 and covered all the days of your travel. ### Solution 1: Memoization Search + Binary Search -We define a function $\text{dfs(i)}$, which represents the minimum cost required from the $i$-th trip to the last trip. Thus, the answer is $\text{dfs(0)}$. +We define a function $\textit{dfs(i)}$, which represents the minimum cost required from the $i$-th trip to the last trip. Thus, the answer is $\textit{dfs(0)}$. -The execution process of the function $\text{dfs(i)}$ is as follows: +The execution process of the function $\textit{dfs(i)}$ is as follows: - If $i \geq n$, it means all trips have ended, return $0$; -- Otherwise, we need to consider three types of purchases: buying a 1-day pass, buying a 7-day pass, and buying a 30-day pass. We calculate the cost for these three purchasing methods separately and use binary search to find the index $j$ of the next trip, then recursively call $\text{dfs(j)}$, and finally return the minimum cost among these three purchasing methods. +- Otherwise, we need to consider three types of purchases: buying a 1-day pass, buying a 7-day pass, and buying a 30-day pass. We calculate the cost for these three purchasing methods separately and use binary search to find the index $j$ of the next trip, then recursively call $\textit{dfs(j)}$, and finally return the minimum cost among these three purchasing methods. To avoid repeated calculations, we use memoization search to save the results that have already been calculated. @@ -247,9 +247,9 @@ function mincostTickets(days: number[], costs: number[]): number { ### Solution 2: Dynamic Programming -Let's denote the last day in the $\text{days}$ array as $m$. We can define an array $f$ of length $m + 1$, where $f[i]$ represents the minimum cost from day $1$ to day $i$. +Let's denote the last day in the $\textit{days}$ array as $m$. We can define an array $f$ of length $m + 1$, where $f[i]$ represents the minimum cost from day $1$ to day $i$. -We can calculate the value of $f[i]$ in increasing order of the dates in the $\text{days}$ array, starting from day $1$. If day $i$ is a travel day, we can consider three purchasing options: buying a 1-day pass, buying a 7-day pass, and buying a 30-day pass. We calculate the cost for these three purchasing methods separately and take the minimum cost among these three as the value of $f[i]$. If day $i$ is not a travel day, then $f[i] = f[i - 1]$. +We can calculate the value of $f[i]$ in increasing order of the dates in the $\textit{days}$ array, starting from day $1$. If day $i$ is a travel day, we can consider three purchasing options: buying a 1-day pass, buying a 7-day pass, and buying a 30-day pass. We calculate the cost for these three purchasing methods separately and take the minimum cost among these three as the value of $f[i]$. If day $i$ is not a travel day, then $f[i] = f[i - 1]$. The final answer is $f[m]$. diff --git a/solution/0900-0999/0994.Rotting Oranges/README.md b/solution/0900-0999/0994.Rotting Oranges/README.md index 2b458272f51d..d0ec4e3e8868 100644 --- a/solution/0900-0999/0994.Rotting Oranges/README.md +++ b/solution/0900-0999/0994.Rotting Oranges/README.md @@ -76,7 +76,7 @@ tags: ### 方法一:BFS -我们首先遍历一遍整个网格,统计出新鲜橘子的数量,记为 $\text{cnt}$,并且将所有腐烂的橘子的坐标加入队列 $q$ 中。 +我们首先遍历一遍整个网格,统计出新鲜橘子的数量,记为 $\textit{cnt}$,并且将所有腐烂的橘子的坐标加入队列 $q$ 中。 接下来,我们进行广度优先搜索,每一轮搜索,我们将队列中的所有腐烂的橘子向四个方向腐烂新鲜橘子,直到队列为空或者新鲜橘子的数量为 $0$ 为止。 diff --git a/solution/0900-0999/0994.Rotting Oranges/README_EN.md b/solution/0900-0999/0994.Rotting Oranges/README_EN.md index 6fe41467c773..c1482642cdeb 100644 --- a/solution/0900-0999/0994.Rotting Oranges/README_EN.md +++ b/solution/0900-0999/0994.Rotting Oranges/README_EN.md @@ -72,7 +72,7 @@ tags: ### Solution 1: BFS -First, we traverse the entire grid once, count the number of fresh oranges, denoted as $\text{cnt}$, and add the coordinates of all rotten oranges to the queue $q$. +First, we traverse the entire grid once, count the number of fresh oranges, denoted as $\textit{cnt}$, and add the coordinates of all rotten oranges to the queue $q$. Next, we perform a breadth-first search. In each round of the search, we let all the rotten oranges in the queue rot the fresh oranges in four directions, until the queue is empty or the number of fresh oranges is $0$. diff --git a/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README.md b/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README.md index 239f2598b267..ab761d1188ba 100644 --- a/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README.md +++ b/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README.md @@ -238,9 +238,9 @@ impl Solution { ### 方法二:滑动窗口 -我们可以用一个变量 $\text{flipped}$ 来表示当前位置是否翻转,如果 $\text{flipped}$ 为 $1$,表示当前位置已经翻转,否则表示当前位置未翻转。对于翻转过的位置,我们可以将其值设置为 $-1$,这样我们就可以区分出哪些位置已经翻转过了。 +我们可以用一个变量 $\textit{flipped}$ 来表示当前位置是否翻转,如果 $\textit{flipped}$ 为 $1$,表示当前位置已经翻转,否则表示当前位置未翻转。对于翻转过的位置,我们可以将其值设置为 $-1$,这样我们就可以区分出哪些位置已经翻转过了。 -接下来我们从左到右遍历数组,对于每个位置 $i$,如果 $i \geq k$ 且 $i-k$ 位置的元素为 $-1$,那么当前位置的翻转状态应该与前一个位置的翻转状态相反。即 $\text{flipped} = \text{flipped} \oplus 1$。如果当前位置的元素与当前位置的翻转状态相同,那么我们需要翻转当前位置,此时我们判断一下 $i+k$ 是否超出了数组的长度,如果超出了数组的长度,那么就无法完成目标,返回 $-1$。否则我们将当前位置的翻转状态取反,同时将答案增加 $1$,并且将当前位置的元素设置为 $-1$。 +接下来我们从左到右遍历数组,对于每个位置 $i$,如果 $i \geq k$ 且 $i-k$ 位置的元素为 $-1$,那么当前位置的翻转状态应该与前一个位置的翻转状态相反。即 $\textit{flipped} = \textit{flipped} \oplus 1$。如果当前位置的元素与当前位置的翻转状态相同,那么我们需要翻转当前位置,此时我们判断一下 $i+k$ 是否超出了数组的长度,如果超出了数组的长度,那么就无法完成目标,返回 $-1$。否则我们将当前位置的翻转状态取反,同时将答案增加 $1$,并且将当前位置的元素设置为 $-1$。 这样当我们处理完数组中的所有元素时,返回答案即可。 diff --git a/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README_EN.md b/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README_EN.md index 0b765434e949..b05ee0398b2b 100644 --- a/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README_EN.md +++ b/solution/0900-0999/0995.Minimum Number of K Consecutive Bit Flips/README_EN.md @@ -236,9 +236,9 @@ impl Solution { ### Solution 2: Sliding Window -We can use a variable $\text{flipped}$ to indicate whether the current position has been flipped. If $\text{flipped} = 1$, it means the current position has already been flipped; otherwise, it means the current position has not been flipped. For positions that have been flipped, we can set their value to $-1$, allowing us to distinguish which positions have been flipped. +We can use a variable $\textit{flipped}$ to indicate whether the current position has been flipped. If $\textit{flipped} = 1$, it means the current position has already been flipped; otherwise, it means the current position has not been flipped. For positions that have been flipped, we can set their value to $-1$, allowing us to distinguish which positions have been flipped. -Next, we traverse the array from left to right. For each position $i$, if $i \geq k$ and the element at position $i-k$ is $-1$, then the flip state of the current position should be the opposite of the flip state of the previous position. That is, $\text{flipped} = \text{flipped} \oplus 1$. If the element at the current position is the same as the current flip state, then we need to flip the current position. At this point, we check if $i+k$ exceeds the length of the array. If it does, then it is impossible to achieve the goal, and we return $-1$. Otherwise, we invert the current flip state, increase the answer by $1$, and set the element at the current position to $-1$. +Next, we traverse the array from left to right. For each position $i$, if $i \geq k$ and the element at position $i-k$ is $-1$, then the flip state of the current position should be the opposite of the flip state of the previous position. That is, $\textit{flipped} = \textit{flipped} \oplus 1$. If the element at the current position is the same as the current flip state, then we need to flip the current position. At this point, we check if $i+k$ exceeds the length of the array. If it does, then it is impossible to achieve the goal, and we return $-1$. Otherwise, we invert the current flip state, increase the answer by $1$, and set the element at the current position to $-1$. By processing all elements in the array in this manner, we can return the answer upon completion. diff --git a/solution/0900-0999/0999.Available Captures for Rook/README.md b/solution/0900-0999/0999.Available Captures for Rook/README.md index 43e1a958ef57..4941ea9fd82a 100644 --- a/solution/0900-0999/0999.Available Captures for Rook/README.md +++ b/solution/0900-0999/0999.Available Captures for Rook/README.md @@ -18,49 +18,47 @@ tags: -

    在一个 8 x 8 的棋盘上,有一个白色的车(Rook),用字符 'R' 表示。棋盘上还可能存在空方块,白色的象(Bishop)以及黑色的卒(pawn),分别用字符 '.''B''p' 表示。不难看出,大写字符表示的是白棋,小写字符表示的是黑棋。

    +

    给定一个 8 x 8 的棋盘,只有一个 白色的车,用字符 'R' 表示。棋盘上还可能存在白色的象 'B' 以及黑色的卒 'p'。空方块用字符 '.' 表示。

    -

    车按国际象棋中的规则移动。东,西,南,北四个基本方向任选其一,然后一直向选定的方向移动,直到满足下列四个条件之一:

    +

    车可以按水平或竖直方向(上,下,左,右)移动任意个方格直到它遇到另一个棋子或棋盘的边界。如果它能够在一次移动中移动到棋子的方格,则能够 吃掉 棋子。

    -
      -
    • 棋手选择主动停下来。
    • -
    • 棋子因到达棋盘的边缘而停下。
    • -
    • 棋子移动到某一方格来捕获位于该方格上敌方(黑色)的卒,停在该方格内。
    • -
    • 车不能进入/越过已经放有其他友方棋子(白色的象)的方格,停在友方棋子前。
    • -
    +

    注意:车不能穿过其它棋子,比如象和卒。这意味着如果有其它棋子挡住了路径,车就不能够吃掉棋子。

    -

    你现在可以控制车移动一次,请你统计有多少敌方的卒处于你的捕获范围内(即,可以被一步捕获的棋子数)。

    +

    返回白车将能 吃掉卒的数量

     

    示例 1:

    -

    +

    -
    输入:[[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
    +
    +输入:[[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
     输出:3
     解释:
    -在本例中,车能够捕获所有的卒。
    +在本例中,车能够吃掉所有的卒。
     

    示例 2:

    -

    +

    -
    输入:[[".",".",".",".",".",".",".","."],[".","p","p","p","p","p",".","."],[".","p","p","B","p","p",".","."],[".","p","B","R","B","p",".","."],[".","p","p","B","p","p",".","."],[".","p","p","p","p","p",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
    +
    +输入:[[".",".",".",".",".",".",".","."],[".","p","p","p","p","p",".","."],[".","p","p","B","p","p",".","."],[".","p","B","R","B","p",".","."],[".","p","p","B","p","p",".","."],[".","p","p","p","p","p",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
     输出:0
     解释:
    -象阻止了车捕获任何卒。
    +象阻止了车吃掉任何卒。
     

    示例 3:

    -

    +

    -
    输入:[[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","p",".",".",".","."],["p","p",".","R",".","p","B","."],[".",".",".",".",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."]]
    +
    +输入:[[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","p",".",".",".","."],["p","p",".","R",".","p","B","."],[".",".",".",".",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."]]
     输出:3
     解释: 
    -车可以捕获位置 b5,d6 和 f5 的卒。
    +车可以吃掉位置 b5,d6 和 f5 的卒。
     

     

    @@ -68,9 +66,10 @@ tags:

    提示:

      -
    1. board.length == board[i].length == 8
    2. -
    3. board[i][j] 可以是 'R''.''B' 或 'p'
    4. -
    5. 只有一个格子上存在 board[i][j] == 'R'
    6. +
    7. board.length == 8
    8. +
    9. board[i].length == 8
    10. +
    11. board[i][j] 可以是 'R''.''B' 或 'p'
    12. +
    13. 只有一个格子上存在 board[i][j] == 'R'
    diff --git a/solution/0900-0999/0999.Available Captures for Rook/README_EN.md b/solution/0900-0999/0999.Available Captures for Rook/README_EN.md index bb7b39a4deaa..fd5d8142ec6d 100644 --- a/solution/0900-0999/0999.Available Captures for Rook/README_EN.md +++ b/solution/0900-0999/0999.Available Captures for Rook/README_EN.md @@ -18,36 +18,50 @@ tags: -

    On an 8 x 8 chessboard, there is exactly one white rook 'R' and some number of white bishops 'B', black pawns 'p', and empty squares '.'.

    +

    You are given an 8 x 8 matrix representing a chessboard. There is exactly one white rook represented by 'R', some number of white bishops 'B', and some number of black pawns 'p'. Empty squares are represented by '.'.

    -

    When the rook moves, it chooses one of four cardinal directions (north, east, south, or west), then moves in that direction until it chooses to stop, reaches the edge of the board, captures a black pawn, or is blocked by a white bishop. A rook is considered attacking a pawn if the rook can capture the pawn on the rook's turn. The number of available captures for the white rook is the number of pawns that the rook is attacking.

    +

    A rook can move any number of squares horizontally or vertically (up, down, left, right) until it reaches another piece or the edge of the board. A rook is attacking a pawn if it can move to the pawn's square in one move.

    -

    Return the number of available captures for the white rook.

    +

    Note: A rook cannot move through other pieces, such as bishops or pawns. This means a rook cannot attack a pawn if there is another piece blocking the path.

    + +

    Return the number of pawns the white rook is attacking.

     

    Example 1:

    -
    -Input: board = [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
    -Output: 3
    -Explanation: In this example, the rook is attacking all the pawns.
    -
    +
    +

    Input: board = [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]

    + +

    Output: 3

    + +

    Explanation:

    + +

    In this example, the rook is attacking all the pawns.

    +

    Example 2:

    -
    -Input: board = [[".",".",".",".",".",".",".","."],[".","p","p","p","p","p",".","."],[".","p","p","B","p","p",".","."],[".","p","B","R","B","p",".","."],[".","p","p","B","p","p",".","."],[".","p","p","p","p","p",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
    -Output: 0
    -Explanation: The bishops are blocking the rook from attacking any of the pawns.
    -
    +
    +

    Input: board = [[".",".",".",".",".",".","."],[".","p","p","p","p","p",".","."],[".","p","p","B","p","p",".","."],[".","p","B","R","B","p",".","."],[".","p","p","B","p","p",".","."],[".","p","p","p","p","p",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]

    + +

    Output: 0

    + +

    Explanation:

    + +

    The bishops are blocking the rook from attacking any of the pawns.

    +

    Example 3:

    -
    -Input: board = [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","p",".",".",".","."],["p","p",".","R",".","p","B","."],[".",".",".",".",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."]]
    -Output: 3
    -Explanation: The rook is attacking the pawns at positions b5, d6, and f5.
    -
    +
    +

    Input: board = [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","p",".",".",".","."],["p","p",".","R",".","p","B","."],[".",".",".",".",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."]]

    + +

    Output: 3

    + +

    Explanation:

    + +

    The rook is attacking the pawns at positions b5, d6, and f5.

    +

     

    Constraints:

    diff --git a/solution/1000-1099/1001.Grid Illumination/README.md b/solution/1000-1099/1001.Grid Illumination/README.md index ade460694bf2..953f3dcbcc94 100644 --- a/solution/1000-1099/1001.Grid Illumination/README.md +++ b/solution/1000-1099/1001.Grid Illumination/README.md @@ -80,15 +80,15 @@ tags: 假设一盏灯的坐标为 $(x, y)$,那么它所在的行的数值为 $x$,列的数值为 $y$,正对角线的数值为 $x-y$,反对角线的数值为 $x+y$。确定某一直线的唯一数值标识后,我们就可以通过哈希表来记录某一直线所拥有的灯的数目。 -我们遍历数组 $lamps$,将当前遍历到的灯所在的行、列和正、反对角线拥有灯的数目分别加 $1$。 +我们遍历数组 $\textit{lamps}$,将当前遍历到的灯所在的行、列和正、反对角线拥有灯的数目分别加 $1$。 -注意,在处理 $lamps$ 时,需要进行去重,因为我们将重复的灯看作同一盏灯。 +注意,在处理 $\textit{lamps}$ 时,需要进行去重,因为我们将重复的灯看作同一盏灯。 接下来,我们遍历 queries,判断当前查询点所在的行,列和正、反对角线是否有灯,如果有,则置 $1$,即该点在查询时是被照亮的。然后进行关闭操作,查找查询点所在的八近邻点及它本身是否有灯,如果有,将该点所在的行、列和正、反对角线的灯数目分别减 $1$,并且将灯从网格中去掉。 最后,返回答案数组即可。 -时间复杂度 $O(m + q)$,其中 $m$ 和 $q$ 分别为数组 $lamps$ 和 $queries$ 的长度。 +时间复杂度 $O(m + q)$,其中 $m$ 和 $q$ 分别为数组 $\textit{lamps}$ 和 $\textit{queries}$ 的长度。 diff --git a/solution/1000-1099/1001.Grid Illumination/README_EN.md b/solution/1000-1099/1001.Grid Illumination/README_EN.md index d1c7ce169b8d..ede31c937091 100644 --- a/solution/1000-1099/1001.Grid Illumination/README_EN.md +++ b/solution/1000-1099/1001.Grid Illumination/README_EN.md @@ -75,7 +75,19 @@ The 1st query asks if the lamp at grid[1][0] is illuminated or n -### Solution 1 +### Solution 1: Hash Table + +Suppose the coordinates of a lamp are $(x, y)$. Then, the row value is $x$, the column value is $y$, the main diagonal value is $x-y$, and the anti-diagonal value is $x+y$. Once we determine the unique value identifier for a line, we can use a hash table to record the number of lamps on that line. + +We traverse the array $\textit{lamps}$, and for each lamp, we increment the count of lamps in its row, column, main diagonal, and anti-diagonal by $1$. + +Note that when processing $\textit{lamps}$, we need to remove duplicates because we treat repeated lamps as the same lamp. + +Next, we traverse the queries and check if there are lamps in the row, column, main diagonal, or anti-diagonal of the current query point. If there are, we set the value to $1$, indicating that the point is illuminated during the query. Then, we perform the turn-off operation by checking the eight neighboring points of the query point and the point itself to see if there are any lamps. If there are, we decrement the count of lamps in the corresponding row, column, main diagonal, and anti-diagonal by $1$ and remove the lamp from the grid. + +Finally, we return the answer array. + +The time complexity is $O(m + q)$, where $m$ and $q$ are the lengths of the arrays $\textit{lamps}$ and $\textit{queries}$, respectively. diff --git a/solution/1000-1099/1002.Find Common Characters/README.md b/solution/1000-1099/1002.Find Common Characters/README.md index 1e94ecfcd7e1..8a082401a4a3 100644 --- a/solution/1000-1099/1002.Find Common Characters/README.md +++ b/solution/1000-1099/1002.Find Common Characters/README.md @@ -20,7 +20,7 @@ tags: -给你一个字符串数组 words ,请你找出所有在 words 的每个字符串中都出现的共用字符( 包括重复字符),并以数组形式返回。你可以按 任意顺序 返回答案。 +给你一个字符串数组 words ,请你找出所有在 words 的每个字符串中都出现的共用字符(包括重复字符),并以数组形式返回。你可以按 任意顺序 返回答案。

     

    @@ -58,7 +58,7 @@ tags: 我们用一个长度为 $26$ 的数组 $cnt$ 记录每个字符在所有字符串中出现的最小次数,最后遍历 $cnt$ 数组,将出现次数大于 $0$ 的字符加入答案即可。 -时间复杂度 $O(n \sum w_i)$,空间复杂度 $O(C)$。其中 $n$ 为字符串数组 $words$ 的长度,而 $w_i$ 为字符串数组 $words$ 中第 $i$ 个字符串的长度,另外 $C$ 为字符集的大小,本题中 $C = 26$。 +时间复杂度 $O(n \sum w_i)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 为字符串数组 $words$ 的长度,而 $w_i$ 为字符串数组 $words$ 中第 $i$ 个字符串的长度,另外 $|\Sigma|$ 为字符集的大小,本题中 $|\Sigma| = 26$。 @@ -69,13 +69,10 @@ class Solution: def commonChars(self, words: List[str]) -> List[str]: cnt = Counter(words[0]) for w in words: - ccnt = Counter(w) - for c in cnt.keys(): - cnt[c] = min(cnt[c], ccnt[c]) - ans = [] - for c, v in cnt.items(): - ans.extend([c] * v) - return ans + t = Counter(w) + for c in cnt: + cnt[c] = min(cnt[c], t[c]) + return list(cnt.elements()) ``` #### Java @@ -84,21 +81,19 @@ class Solution: class Solution { public List commonChars(String[] words) { int[] cnt = new int[26]; - Arrays.fill(cnt, 10000); - for (String w : words) { - int[] ccnt = new int[26]; + Arrays.fill(cnt, 20000); + for (var w : words) { + int[] t = new int[26]; for (int i = 0; i < w.length(); ++i) { - ++ccnt[w.charAt(i) - 'a']; + ++t[w.charAt(i) - 'a']; } for (int i = 0; i < 26; ++i) { - cnt[i] = Math.min(cnt[i], ccnt[i]); + cnt[i] = Math.min(cnt[i], t[i]); } } List ans = new ArrayList<>(); for (int i = 0; i < 26; ++i) { - while (cnt[i]-- > 0) { - ans.add(String.valueOf((char) (i + 'a'))); - } + ans.addAll(Collections.nCopies(cnt[i], String.valueOf((char) ('a' + i)))); } return ans; } @@ -111,21 +106,20 @@ class Solution { class Solution { public: vector commonChars(vector& words) { - int cnt[26]; - memset(cnt, 0x3f, sizeof(cnt)); - for (auto& w : words) { - int ccnt[26]{}; - for (char& c : w) { - ++ccnt[c - 'a']; + vector cnt(26, 20000); + for (const auto& w : words) { + vector t(26, 0); + for (char c : w) { + ++t[c - 'a']; } for (int i = 0; i < 26; ++i) { - cnt[i] = min(cnt[i], ccnt[i]); + cnt[i] = min(cnt[i], t[i]); } } vector ans; for (int i = 0; i < 26; ++i) { - while (cnt[i]--) { - ans.emplace_back(1, i + 'a'); + for (int j = 0; j < cnt[i]; ++j) { + ans.push_back(string(1, 'a' + i)); } } return ans; @@ -137,26 +131,25 @@ public: ```go func commonChars(words []string) (ans []string) { - cnt := [26]int{} + cnt := make([]int, 26) for i := range cnt { - cnt[i] = 1 << 30 + cnt[i] = 20000 } for _, w := range words { - ccnt := [26]int{} + t := make([]int, 26) for _, c := range w { - ccnt[c-'a']++ + t[c-'a']++ } - for i, v := range cnt { - cnt[i] = min(v, ccnt[i]) + for i := 0; i < 26; i++ { + cnt[i] = min(cnt[i], t[i]) } } - for i, v := range cnt { - for v > 0 { - ans = append(ans, string(i+'a')) - v-- + for i := 0; i < 26; i++ { + for j := 0; j < cnt[i]; j++ { + ans = append(ans, string('a'+rune(i))) } } - return + return ans } ``` @@ -164,22 +157,20 @@ func commonChars(words []string) (ans []string) { ```ts function commonChars(words: string[]): string[] { - const freq: number[] = Array(26).fill(Number.POSITIVE_INFINITY); + const cnt = Array(26).fill(20000); const aCode = 'a'.charCodeAt(0); - for (const word of words) { - const t: number[] = Array(26).fill(0); - for (const c of word) { - ++t[c.charCodeAt(0) - aCode]; + for (const w of words) { + const t = Array(26).fill(0); + for (const c of w) { + t[c.charCodeAt(0) - aCode]++; } - for (let i = 0; i < 26; ++i) { - freq[i] = Math.min(freq[i], t[i]); + for (let i = 0; i < 26; i++) { + cnt[i] = Math.min(cnt[i], t[i]); } } const ans: string[] = []; - for (let i = 0; i < 26; ++i) { - if (freq[i]) { - ans.push(...String.fromCharCode(i + aCode).repeat(freq[i])); - } + for (let i = 0; i < 26; i++) { + cnt[i] && ans.push(...String.fromCharCode(i + aCode).repeat(cnt[i])); } return ans; } diff --git a/solution/1000-1099/1002.Find Common Characters/README_EN.md b/solution/1000-1099/1002.Find Common Characters/README_EN.md index 4fc065f61dd0..0f6bea6930d0 100644 --- a/solution/1000-1099/1002.Find Common Characters/README_EN.md +++ b/solution/1000-1099/1002.Find Common Characters/README_EN.md @@ -45,7 +45,11 @@ tags: -### Solution 1 +### Solution 1: Counting + +We use an array $cnt$ of length $26$ to record the minimum number of times each character appears in all strings. Finally, we traverse the $cnt$ array and add characters with a count greater than $0$ to the answer. + +The time complexity is $O(n \sum w_i)$, and the space complexity is $O(|\Sigma|)$. Here, $n$ is the length of the string array $words$, $w_i$ is the length of the $i$-th string in the array $words$, and $|\Sigma|$ is the size of the character set, which is $26$ in this problem. @@ -56,13 +60,10 @@ class Solution: def commonChars(self, words: List[str]) -> List[str]: cnt = Counter(words[0]) for w in words: - ccnt = Counter(w) - for c in cnt.keys(): - cnt[c] = min(cnt[c], ccnt[c]) - ans = [] - for c, v in cnt.items(): - ans.extend([c] * v) - return ans + t = Counter(w) + for c in cnt: + cnt[c] = min(cnt[c], t[c]) + return list(cnt.elements()) ``` #### Java @@ -71,21 +72,19 @@ class Solution: class Solution { public List commonChars(String[] words) { int[] cnt = new int[26]; - Arrays.fill(cnt, 10000); - for (String w : words) { - int[] ccnt = new int[26]; + Arrays.fill(cnt, 20000); + for (var w : words) { + int[] t = new int[26]; for (int i = 0; i < w.length(); ++i) { - ++ccnt[w.charAt(i) - 'a']; + ++t[w.charAt(i) - 'a']; } for (int i = 0; i < 26; ++i) { - cnt[i] = Math.min(cnt[i], ccnt[i]); + cnt[i] = Math.min(cnt[i], t[i]); } } List ans = new ArrayList<>(); for (int i = 0; i < 26; ++i) { - while (cnt[i]-- > 0) { - ans.add(String.valueOf((char) (i + 'a'))); - } + ans.addAll(Collections.nCopies(cnt[i], String.valueOf((char) ('a' + i)))); } return ans; } @@ -98,21 +97,20 @@ class Solution { class Solution { public: vector commonChars(vector& words) { - int cnt[26]; - memset(cnt, 0x3f, sizeof(cnt)); - for (auto& w : words) { - int ccnt[26]{}; - for (char& c : w) { - ++ccnt[c - 'a']; + vector cnt(26, 20000); + for (const auto& w : words) { + vector t(26, 0); + for (char c : w) { + ++t[c - 'a']; } for (int i = 0; i < 26; ++i) { - cnt[i] = min(cnt[i], ccnt[i]); + cnt[i] = min(cnt[i], t[i]); } } vector ans; for (int i = 0; i < 26; ++i) { - while (cnt[i]--) { - ans.emplace_back(1, i + 'a'); + for (int j = 0; j < cnt[i]; ++j) { + ans.push_back(string(1, 'a' + i)); } } return ans; @@ -124,26 +122,25 @@ public: ```go func commonChars(words []string) (ans []string) { - cnt := [26]int{} + cnt := make([]int, 26) for i := range cnt { - cnt[i] = 1 << 30 + cnt[i] = 20000 } for _, w := range words { - ccnt := [26]int{} + t := make([]int, 26) for _, c := range w { - ccnt[c-'a']++ + t[c-'a']++ } - for i, v := range cnt { - cnt[i] = min(v, ccnt[i]) + for i := 0; i < 26; i++ { + cnt[i] = min(cnt[i], t[i]) } } - for i, v := range cnt { - for v > 0 { - ans = append(ans, string(i+'a')) - v-- + for i := 0; i < 26; i++ { + for j := 0; j < cnt[i]; j++ { + ans = append(ans, string('a'+rune(i))) } } - return + return ans } ``` @@ -151,22 +148,20 @@ func commonChars(words []string) (ans []string) { ```ts function commonChars(words: string[]): string[] { - const freq: number[] = Array(26).fill(Number.POSITIVE_INFINITY); + const cnt = Array(26).fill(20000); const aCode = 'a'.charCodeAt(0); - for (const word of words) { - const t: number[] = Array(26).fill(0); - for (const c of word) { - ++t[c.charCodeAt(0) - aCode]; + for (const w of words) { + const t = Array(26).fill(0); + for (const c of w) { + t[c.charCodeAt(0) - aCode]++; } - for (let i = 0; i < 26; ++i) { - freq[i] = Math.min(freq[i], t[i]); + for (let i = 0; i < 26; i++) { + cnt[i] = Math.min(cnt[i], t[i]); } } const ans: string[] = []; - for (let i = 0; i < 26; ++i) { - if (freq[i]) { - ans.push(...String.fromCharCode(i + aCode).repeat(freq[i])); - } + for (let i = 0; i < 26; i++) { + cnt[i] && ans.push(...String.fromCharCode(i + aCode).repeat(cnt[i])); } return ans; } diff --git a/solution/1000-1099/1002.Find Common Characters/Solution.cpp b/solution/1000-1099/1002.Find Common Characters/Solution.cpp index 3dcd528d4d3b..c25daaf09cd7 100644 --- a/solution/1000-1099/1002.Find Common Characters/Solution.cpp +++ b/solution/1000-1099/1002.Find Common Characters/Solution.cpp @@ -1,23 +1,22 @@ class Solution { public: vector commonChars(vector& words) { - int cnt[26]; - memset(cnt, 0x3f, sizeof(cnt)); - for (auto& w : words) { - int ccnt[26]{}; - for (char& c : w) { - ++ccnt[c - 'a']; + vector cnt(26, 20000); + for (const auto& w : words) { + vector t(26, 0); + for (char c : w) { + ++t[c - 'a']; } for (int i = 0; i < 26; ++i) { - cnt[i] = min(cnt[i], ccnt[i]); + cnt[i] = min(cnt[i], t[i]); } } vector ans; for (int i = 0; i < 26; ++i) { - while (cnt[i]--) { - ans.emplace_back(1, i + 'a'); + for (int j = 0; j < cnt[i]; ++j) { + ans.push_back(string(1, 'a' + i)); } } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1000-1099/1002.Find Common Characters/Solution.go b/solution/1000-1099/1002.Find Common Characters/Solution.go index fecc5ef12bf3..294121a173b8 100644 --- a/solution/1000-1099/1002.Find Common Characters/Solution.go +++ b/solution/1000-1099/1002.Find Common Characters/Solution.go @@ -1,22 +1,21 @@ func commonChars(words []string) (ans []string) { - cnt := [26]int{} + cnt := make([]int, 26) for i := range cnt { - cnt[i] = 1 << 30 + cnt[i] = 20000 } for _, w := range words { - ccnt := [26]int{} + t := make([]int, 26) for _, c := range w { - ccnt[c-'a']++ + t[c-'a']++ } - for i, v := range cnt { - cnt[i] = min(v, ccnt[i]) + for i := 0; i < 26; i++ { + cnt[i] = min(cnt[i], t[i]) } } - for i, v := range cnt { - for v > 0 { - ans = append(ans, string(i+'a')) - v-- + for i := 0; i < 26; i++ { + for j := 0; j < cnt[i]; j++ { + ans = append(ans, string('a'+rune(i))) } } - return -} \ No newline at end of file + return ans +} diff --git a/solution/1000-1099/1002.Find Common Characters/Solution.java b/solution/1000-1099/1002.Find Common Characters/Solution.java index 492a8b07370e..47524c0a3bf2 100644 --- a/solution/1000-1099/1002.Find Common Characters/Solution.java +++ b/solution/1000-1099/1002.Find Common Characters/Solution.java @@ -1,22 +1,20 @@ class Solution { public List commonChars(String[] words) { int[] cnt = new int[26]; - Arrays.fill(cnt, 10000); - for (String w : words) { - int[] ccnt = new int[26]; + Arrays.fill(cnt, 20000); + for (var w : words) { + int[] t = new int[26]; for (int i = 0; i < w.length(); ++i) { - ++ccnt[w.charAt(i) - 'a']; + ++t[w.charAt(i) - 'a']; } for (int i = 0; i < 26; ++i) { - cnt[i] = Math.min(cnt[i], ccnt[i]); + cnt[i] = Math.min(cnt[i], t[i]); } } List ans = new ArrayList<>(); for (int i = 0; i < 26; ++i) { - while (cnt[i]-- > 0) { - ans.add(String.valueOf((char) (i + 'a'))); - } + ans.addAll(Collections.nCopies(cnt[i], String.valueOf((char) ('a' + i)))); } return ans; } -} \ No newline at end of file +} diff --git a/solution/1000-1099/1002.Find Common Characters/Solution.py b/solution/1000-1099/1002.Find Common Characters/Solution.py index 5890567c612e..3ed29d57abca 100644 --- a/solution/1000-1099/1002.Find Common Characters/Solution.py +++ b/solution/1000-1099/1002.Find Common Characters/Solution.py @@ -2,10 +2,7 @@ class Solution: def commonChars(self, words: List[str]) -> List[str]: cnt = Counter(words[0]) for w in words: - ccnt = Counter(w) - for c in cnt.keys(): - cnt[c] = min(cnt[c], ccnt[c]) - ans = [] - for c, v in cnt.items(): - ans.extend([c] * v) - return ans + t = Counter(w) + for c in cnt: + cnt[c] = min(cnt[c], t[c]) + return list(cnt.elements()) diff --git a/solution/1000-1099/1002.Find Common Characters/Solution.ts b/solution/1000-1099/1002.Find Common Characters/Solution.ts index ddf461fa92c3..e89795680e96 100644 --- a/solution/1000-1099/1002.Find Common Characters/Solution.ts +++ b/solution/1000-1099/1002.Find Common Characters/Solution.ts @@ -1,20 +1,18 @@ function commonChars(words: string[]): string[] { - const freq: number[] = Array(26).fill(Number.POSITIVE_INFINITY); + const cnt = Array(26).fill(20000); const aCode = 'a'.charCodeAt(0); - for (const word of words) { - const t: number[] = Array(26).fill(0); - for (const c of word) { - ++t[c.charCodeAt(0) - aCode]; + for (const w of words) { + const t = Array(26).fill(0); + for (const c of w) { + t[c.charCodeAt(0) - aCode]++; } - for (let i = 0; i < 26; ++i) { - freq[i] = Math.min(freq[i], t[i]); + for (let i = 0; i < 26; i++) { + cnt[i] = Math.min(cnt[i], t[i]); } } const ans: string[] = []; - for (let i = 0; i < 26; ++i) { - if (freq[i]) { - ans.push(...String.fromCharCode(i + aCode).repeat(freq[i])); - } + for (let i = 0; i < 26; i++) { + cnt[i] && ans.push(...String.fromCharCode(i + aCode).repeat(cnt[i])); } return ans; } diff --git a/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README.md b/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README.md index e3b471d11db2..8a2a10385c29 100644 --- a/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README.md +++ b/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README.md @@ -73,11 +73,11 @@ tags: ### 方法一:栈 -我们观察题目中的操作,可以发现,每一次都会在字符串的任意位置插入字符串 `"abc"`,所以每次插入操作之后,字符串的长度都会增加 $3$。如果字符串 $s$ 有效,那么它的长度一定是 $3$ 的倍数。因此,我们先对字符串 $s$ 的长度进行判断,如果不是 $3$ 的倍数,那么 $s$ 一定无效,可以直接返回 `false`。 +我们观察题目中的操作,可以发现,每一次都会在字符串的任意位置插入字符串 $\textit{"abc"}$,所以每次插入操作之后,字符串的长度都会增加 $3$。如果字符串 $s$ 有效,那么它的长度一定是 $3$ 的倍数。因此,我们先对字符串 $s$ 的长度进行判断,如果不是 $3$ 的倍数,那么 $s$ 一定无效,可以直接返回 $\textit{false}$。 -接下来我们遍历字符串 $s$ 的每个字符 $c$,我们先将字符 $c$ 压入栈 $t$ 中。如果此时栈 $t$ 的长度大于等于 $3$,并且栈顶的三个元素组成了字符串 `"abc"`,那么我们就将栈顶的三个元素弹出。然后继续遍历字符串 $s$ 的下一个字符。 +接下来我们遍历字符串 $s$ 的每个字符 $c$,我们先将字符 $c$ 压入栈 $t$ 中。如果此时栈 $t$ 的长度大于等于 $3$,并且栈顶的三个元素组成了字符串 $\textit{"abc"}$,那么我们就将栈顶的三个元素弹出。然后继续遍历字符串 $s$ 的下一个字符。 -遍历结束之后,如果栈 $t$ 为空,那么说明字符串 $s$ 有效,返回 `true`,否则返回 `false`。 +遍历结束之后,如果栈 $t$ 为空,那么说明字符串 $s$ 有效,返回 $\textit{true}$;否则,返回 $\textit{false}$。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。 diff --git a/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README_EN.md b/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README_EN.md index 448573b651d0..e16aa8b35ceb 100644 --- a/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README_EN.md +++ b/solution/1000-1099/1003.Check If Word Is Valid After Substitutions/README_EN.md @@ -73,13 +73,13 @@ Thus, "abcabcababcc" is valid. ### Solution 1: Stack -If the string is valid, it's length must be the multiple of $3$. +We observe the operations in the problem and find that each time a string $\textit{"abc"}$ is inserted at any position in the string. Therefore, after each insertion operation, the length of the string increases by $3$. If the string $s$ is valid, its length must be a multiple of $3$. Thus, we first check the length of the string $s$. If it is not a multiple of $3$, then $s$ must be invalid, and we can directly return $\textit{false}$. -We traverse the string and push every character into the stack $t$. If the size of stack $t$ is greater than or equal to $3$ and the top three elements of stack $t$ constitute the string `"abc"`, we pop the top three elements. Then we continue to traverse the next character of the string $s$. +Next, we traverse each character $c$ in the string $s$. We first push the character $c$ onto the stack $t$. If the length of the stack $t$ is greater than or equal to $3$, and the top three elements of the stack form the string $\textit{"abc"}$, then we pop the top three elements from the stack. We then continue to traverse the next character in the string $s$. -When the traversal is over, if the stack $t$ is empty, the string $s$ is valid, return `true`, otherwise return `false`. +After the traversal, if the stack $t$ is empty, it means the string $s$ is valid, and we return $\textit{true}$; otherwise, we return $\textit{false}$. -The time complexity is $O(n)$ and the space complexity is $O(n)$. Where $n$ is the length of the string $s$. +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $s$. diff --git a/solution/1000-1099/1032.Stream of Characters/README.md b/solution/1000-1099/1032.Stream of Characters/README.md index 716fe6e52e8a..c593eec9a31d 100644 --- a/solution/1000-1099/1032.Stream of Characters/README.md +++ b/solution/1000-1099/1032.Stream of Characters/README.md @@ -202,14 +202,11 @@ class StreamChecker { ```cpp class Trie { -public: - vector children; - bool isEnd; - - Trie() - : children(26) - , isEnd(false) {} +private: + Trie* children[26]{}; + bool isEnd = false; +public: void insert(string& w) { Trie* node = this; reverse(w.begin(), w.end()); @@ -225,7 +222,7 @@ public: bool search(string& w) { Trie* node = this; - for (int i = w.size() - 1; ~i; --i) { + for (int i = w.size() - 1, j = 0; ~i && j < 201; --i, ++j) { int idx = w[i] - 'a'; if (!node->children[idx]) { return false; @@ -245,7 +242,7 @@ public: string s; StreamChecker(vector& words) { - for (auto&& w : words) { + for (auto& w : words) { trie->insert(w); } } diff --git a/solution/1000-1099/1032.Stream of Characters/README_EN.md b/solution/1000-1099/1032.Stream of Characters/README_EN.md index a54c0c876853..a0aab11d6413 100644 --- a/solution/1000-1099/1032.Stream of Characters/README_EN.md +++ b/solution/1000-1099/1032.Stream of Characters/README_EN.md @@ -189,14 +189,11 @@ class StreamChecker { ```cpp class Trie { -public: - vector children; - bool isEnd; - - Trie() - : children(26) - , isEnd(false) {} +private: + Trie* children[26]{}; + bool isEnd = false; +public: void insert(string& w) { Trie* node = this; reverse(w.begin(), w.end()); @@ -212,7 +209,7 @@ public: bool search(string& w) { Trie* node = this; - for (int i = w.size() - 1; ~i; --i) { + for (int i = w.size() - 1, j = 0; ~i && j < 201; --i, ++j) { int idx = w[i] - 'a'; if (!node->children[idx]) { return false; @@ -232,7 +229,7 @@ public: string s; StreamChecker(vector& words) { - for (auto&& w : words) { + for (auto& w : words) { trie->insert(w); } } diff --git a/solution/1000-1099/1032.Stream of Characters/Solution.cpp b/solution/1000-1099/1032.Stream of Characters/Solution.cpp index e6eb258dab88..8d7dd96d584f 100644 --- a/solution/1000-1099/1032.Stream of Characters/Solution.cpp +++ b/solution/1000-1099/1032.Stream of Characters/Solution.cpp @@ -1,12 +1,9 @@ class Trie { -public: - vector children; - bool isEnd; - - Trie() - : children(26) - , isEnd(false) {} +private: + Trie* children[26]{}; + bool isEnd = false; +public: void insert(string& w) { Trie* node = this; reverse(w.begin(), w.end()); @@ -22,7 +19,7 @@ class Trie { bool search(string& w) { Trie* node = this; - for (int i = w.size() - 1; ~i; --i) { + for (int i = w.size() - 1, j = 0; ~i && j < 201; --i, ++j) { int idx = w[i] - 'a'; if (!node->children[idx]) { return false; @@ -42,7 +39,7 @@ class StreamChecker { string s; StreamChecker(vector& words) { - for (auto&& w : words) { + for (auto& w : words) { trie->insert(w); } } @@ -57,4 +54,4 @@ class StreamChecker { * Your StreamChecker object will be instantiated and called as such: * StreamChecker* obj = new StreamChecker(words); * bool param_1 = obj->query(letter); - */ \ No newline at end of file + */ diff --git a/solution/1000-1099/1035.Uncrossed Lines/README.md b/solution/1000-1099/1035.Uncrossed Lines/README.md index 64fcc5e4d658..5d903db95ac8 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/README.md +++ b/solution/1000-1099/1035.Uncrossed Lines/README.md @@ -79,19 +79,15 @@ tags: ### 方法一:动态规划 -最长公共子序列问题。 +我们定义 $f[i][j]$ 表示 $\textit{nums1}$ 前 $i$ 个数和 $\textit{nums2}$ 前 $j$ 个数的最大连线数。初始时 $f[i][j] = 0$,答案即为 $f[m][n]$。 -定义 $dp[i][j]$ 表示数组 `nums1` 的前 $i$ 个元素和数组 `nums2` 的前 $j$ 个元素的最长公共子序列的长度。则有: +当 $\textit{nums1}[i-1] = \textit{nums2}[j-1]$ 时,我们可以在 $\textit{nums1}$ 的前 $i-1$ 个数和 $\textit{nums2}$ 的前 $j-1$ 个数的基础上增加一条连线,此时 $f[i][j] = f[i-1][j-1] + 1$。 -$$ -dp[i][j]= -\begin{cases} -dp[i-1][j-1]+1, & nums1[i-1]=nums2[j-1] \\ -\max(dp[i-1][j], dp[i][j-1]), & nums1[i-1]\neq nums2[j-1] -\end{cases} -$$ +当 $\textit{nums1}[i-1] \neq \textit{nums2}[j-1]$ 时,我们要么在 $\textit{nums1}$ 的前 $i-1$ 个数和 $\textit{nums2}$ 的前 $j$ 个数的基础上求解,要么在 $\textit{nums1}$ 的前 $i$ 个数和 $\textit{nums2}$ 的前 $j-1$ 个数的基础上求解,取两者的最大值,即 $f[i][j] = \max(f[i-1][j], f[i][j-1])$。 -时间复杂度 $O(m\times n)$,空间复杂度 $O(m\times n)$。其中 $m$, $n$ 分别为数组 `nums1` 和 `nums2` 的长度。 +最后返回 $f[m][n]$ 即可。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度。 @@ -101,14 +97,14 @@ $$ class Solution: def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[0] * (n + 1) for i in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - if nums1[i - 1] == nums2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] + 1 + f = [[0] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + if x == y: + f[i][j] = f[i - 1][j - 1] + 1 else: - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) - return dp[m][n] + f[i][j] = max(f[i - 1][j], f[i][j - 1]) + return f[m][n] ``` #### Java @@ -116,19 +112,18 @@ class Solution: ```java class Solution { public int maxUncrossedLines(int[] nums1, int[] nums2) { - int m = nums1.length; - int n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { + int m = nums1.length, n = nums2.length; + int[][] f = new int[m + 1][n + 1]; + for (int i = 1; i <= m; ++i) { + for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } } ``` @@ -140,17 +135,18 @@ class Solution { public: int maxUncrossedLines(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1)); + int f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } }; ``` @@ -160,20 +156,20 @@ public: ```go func maxUncrossedLines(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { if nums1[i-1] == nums2[j-1] { - dp[i][j] = dp[i-1][j-1] + 1 + f[i][j] = f[i-1][j-1] + 1 } else { - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + f[i][j] = max(f[i-1][j], f[i][j-1]) } } } - return dp[m][n] + return f[m][n] } ``` @@ -183,19 +179,45 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int { function maxUncrossedLines(nums1: number[], nums2: number[]): number { const m = nums1.length; const n = nums2.length; - const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)); + const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxUncrossedLines = function (nums1, nums2) { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + } + } + } + return f[m][n]; +}; +``` + diff --git a/solution/1000-1099/1035.Uncrossed Lines/README_EN.md b/solution/1000-1099/1035.Uncrossed Lines/README_EN.md index 58d5c1873e5c..e2b5065a2b39 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/README_EN.md +++ b/solution/1000-1099/1035.Uncrossed Lines/README_EN.md @@ -70,7 +70,17 @@ We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2] -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j]$ to represent the maximum number of connections between the first $i$ numbers of $\textit{nums1}$ and the first $j$ numbers of $\textit{nums2}$. Initially, $f[i][j] = 0$, and the answer is $f[m][n]$. + +When $\textit{nums1}[i-1] = \textit{nums2}[j-1]$, we can add a connection based on the first $i-1$ numbers of $\textit{nums1}$ and the first $j-1$ numbers of $\textit{nums2}$. In this case, $f[i][j] = f[i-1][j-1] + 1$. + +When $\textit{nums1}[i-1] \neq \textit{nums2}[j-1]$, we either solve based on the first $i-1$ numbers of $\textit{nums1}$ and the first $j$ numbers of $\textit{nums2}$, or solve based on the first $i$ numbers of $\textit{nums1}$ and the first $j-1$ numbers of $\textit{nums2}$, taking the maximum of the two. That is, $f[i][j] = \max(f[i-1][j], f[i][j-1])$. + +Finally, return $f[m][n]$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the lengths of $\textit{nums1}$ and $\textit{nums2}$, respectively. @@ -80,14 +90,14 @@ We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2] class Solution: def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[0] * (n + 1) for i in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - if nums1[i - 1] == nums2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] + 1 + f = [[0] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + if x == y: + f[i][j] = f[i - 1][j - 1] + 1 else: - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) - return dp[m][n] + f[i][j] = max(f[i - 1][j], f[i][j - 1]) + return f[m][n] ``` #### Java @@ -95,19 +105,18 @@ class Solution: ```java class Solution { public int maxUncrossedLines(int[] nums1, int[] nums2) { - int m = nums1.length; - int n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { + int m = nums1.length, n = nums2.length; + int[][] f = new int[m + 1][n + 1]; + for (int i = 1; i <= m; ++i) { + for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } } ``` @@ -119,17 +128,18 @@ class Solution { public: int maxUncrossedLines(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1)); + int f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } }; ``` @@ -139,20 +149,20 @@ public: ```go func maxUncrossedLines(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { if nums1[i-1] == nums2[j-1] { - dp[i][j] = dp[i-1][j-1] + 1 + f[i][j] = f[i-1][j-1] + 1 } else { - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + f[i][j] = max(f[i-1][j], f[i][j-1]) } } } - return dp[m][n] + return f[m][n] } ``` @@ -162,19 +172,45 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int { function maxUncrossedLines(nums1: number[], nums2: number[]): number { const m = nums1.length; const n = nums2.length; - const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)); + const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxUncrossedLines = function (nums1, nums2) { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + } + } + } + return f[m][n]; +}; +``` + diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp b/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp index 9d5e57169860..78f903049cca 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp @@ -2,16 +2,17 @@ class Solution { public: int maxUncrossedLines(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1)); + int f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } -}; \ No newline at end of file +}; diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.go b/solution/1000-1099/1035.Uncrossed Lines/Solution.go index c176c14388dc..3a25cfee7b9a 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.go +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.go @@ -1,17 +1,17 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { if nums1[i-1] == nums2[j-1] { - dp[i][j] = dp[i-1][j-1] + 1 + f[i][j] = f[i-1][j-1] + 1 } else { - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + f[i][j] = max(f[i-1][j], f[i][j-1]) } } } - return dp[m][n] -} \ No newline at end of file + return f[m][n] +} diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.java b/solution/1000-1099/1035.Uncrossed Lines/Solution.java index 292f14a655f9..00bb0ed57dfc 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.java +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.java @@ -1,17 +1,16 @@ class Solution { public int maxUncrossedLines(int[] nums1, int[] nums2) { - int m = nums1.length; - int n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { + int m = nums1.length, n = nums2.length; + int[][] f = new int[m + 1][n + 1]; + for (int i = 1; i <= m; ++i) { + for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } -} \ No newline at end of file +} diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.js b/solution/1000-1099/1035.Uncrossed Lines/Solution.js new file mode 100644 index 000000000000..13abac72f5ba --- /dev/null +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxUncrossedLines = function (nums1, nums2) { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + } + } + } + return f[m][n]; +}; diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.py b/solution/1000-1099/1035.Uncrossed Lines/Solution.py index 524bbe665f05..3f8d2f713c5d 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.py +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.py @@ -1,11 +1,11 @@ class Solution: def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[0] * (n + 1) for i in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - if nums1[i - 1] == nums2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] + 1 + f = [[0] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + if x == y: + f[i][j] = f[i - 1][j - 1] + 1 else: - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) - return dp[m][n] + f[i][j] = max(f[i - 1][j], f[i][j - 1]) + return f[m][n] diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.ts b/solution/1000-1099/1035.Uncrossed Lines/Solution.ts index aa7ec45c257a..5f0bee4e7f5a 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.ts +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.ts @@ -1,14 +1,15 @@ function maxUncrossedLines(nums1: number[], nums2: number[]): number { const m = nums1.length; const n = nums2.length; - const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)); + const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } diff --git a/solution/1000-1099/1062.Longest Repeating Substring/README.md b/solution/1000-1099/1062.Longest Repeating Substring/README.md index 234152076f8c..12a7cb773e4c 100644 --- a/solution/1000-1099/1062.Longest Repeating Substring/README.md +++ b/solution/1000-1099/1062.Longest Repeating Substring/README.md @@ -21,45 +21,42 @@ tags: -

    给定字符串 S,找出最长重复子串的长度。如果不存在重复子串就返回 0

    +

    给定字符串 s,找出最长重复子串的长度。如果不存在重复子串就返回 0

     

    示例 1:

    -
    输入:"abcd"
    +
    +输入:"abcd"
     输出:0
     解释:没有重复子串。
     

    示例 2:

    -
    输入:"abbaba"
    +
    +输入:"abbaba"
     输出:2
    -解释:最长的重复子串为 "ab" 和 "ba",每个出现 2 次。
    +解释:最长的重复子串为 "ab" 和 "ba",每个出现 2 次。
     

    示例 3:

    -
    输入:"aabcaabdaab"
    +
    +输入:"aabcaabdaab"
     输出:3
    -解释:最长的重复子串为 "aab",出现 3 次。
    +解释:最长的重复子串为 "aab",出现 3 次。
     
    -

    示例 4:

    - -
    输入:"aaaaa"
    -输出:4
    -解释:最长的重复子串为 "aaaa",出现 2 次。
    -

     

    提示:

    -
      -
    1. 字符串 S 仅包含从 'a' 到 'z' 的小写英文字母。
    2. -
    3. 1 <= S.length <= 1500
    4. -
    +
      +
    • 1 <= s.length <= 2000
    • +
    • 字符串 s 仅包含从 'a' 到 'z' 的小写英文字母。
    • +
    diff --git a/solution/1000-1099/1092.Shortest Common Supersequence/README.md b/solution/1000-1099/1092.Shortest Common Supersequence/README.md index 059371c6bc36..049ce2150adc 100644 --- a/solution/1000-1099/1092.Shortest Common Supersequence/README.md +++ b/solution/1000-1099/1092.Shortest Common Supersequence/README.md @@ -67,7 +67,7 @@ str2 = "cab" 是 "cabac" 的一个子串,因为我们可以删去 "cabac" 末 $$ f[i][j] = \begin{cases} -0 & i = 0 \text{ or } j = 0 \\ +0 & i = 0 \textit{ or } j = 0 \\ f[i - 1][j - 1] + 1 & str1[i - 1] = str2[j - 1] \\ \max(f[i - 1][j], f[i][j - 1]) & str1[i - 1] \neq str2[j - 1] \end{cases} diff --git a/solution/1100-1199/1110.Delete Nodes And Return Forest/README.md b/solution/1100-1199/1110.Delete Nodes And Return Forest/README.md index e48d1ae455c5..2a844c68816c 100644 --- a/solution/1100-1199/1110.Delete Nodes And Return Forest/README.md +++ b/solution/1100-1199/1110.Delete Nodes And Return Forest/README.md @@ -298,6 +298,180 @@ function delNodes(root: TreeNode | null, to_delete: number[]): Array { + if (!root) { + return null; + } + root.left = dfs(root.left); + root.right = dfs(root.right); + if (!s[root.val]) { + return root; + } + if (root.left) { + ans.push(root.left); + } + if (root.right) { + ans.push(root.right); + } + return null; + }; + if (dfs(root)) { + ans.push(root); + } + return ans; +}; +``` + + + + + + + +### 方法二:BFS + + + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ +export function delNodes(root: T, to_delete: number[]): Array { + if (!root) return []; + + const del = new Set(to_delete); + const res: T[] = []; + let q: TreeNode[] = [root]; + + while (q.length) { + const qNext: TreeNode[] = []; + + for (const node of q) { + if (node.left) { + qNext.push(node.left); + + if (del.has(node.left.val)) { + node.left = null; + } + } + + if (node.right) { + qNext.push(node.right); + + if (del.has(node.right.val)) { + node.right = null; + } + } + + if (del.has(node.val)) { + if (node.left) res.push(node.left); + if (node.right) res.push(node.right); + } + } + + q = qNext; + } + + if (!del.has(root.val)) res.push(root); + + return res; +} + +type T = TreeNode | null; +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number[]} to_delete + * @return {TreeNode[]} + */ +var delNodes = function (root, to_delete) { + if (!root) return []; + + const del = new Set(to_delete); + const res = []; + let q = [root]; + + while (q.length) { + const qNext = []; + + for (const node of q) { + if (node.left) { + qNext.push(node.left); + + if (del.has(node.left.val)) { + node.left = null; + } + } + + if (node.right) { + qNext.push(node.right); + + if (del.has(node.right.val)) { + node.right = null; + } + } + + if (del.has(node.val)) { + if (node.left) res.push(node.left); + if (node.right) res.push(node.right); + } + } + + q = qNext; + } + + if (!del.has(root.val)) res.push(root); + + return res; +}; +``` + diff --git a/solution/1100-1199/1110.Delete Nodes And Return Forest/README_EN.md b/solution/1100-1199/1110.Delete Nodes And Return Forest/README_EN.md index d134bbac3d5f..80f97a210679 100644 --- a/solution/1100-1199/1110.Delete Nodes And Return Forest/README_EN.md +++ b/solution/1100-1199/1110.Delete Nodes And Return Forest/README_EN.md @@ -294,6 +294,180 @@ function delNodes(root: TreeNode | null, to_delete: number[]): Array { + if (!root) { + return null; + } + root.left = dfs(root.left); + root.right = dfs(root.right); + if (!s[root.val]) { + return root; + } + if (root.left) { + ans.push(root.left); + } + if (root.right) { + ans.push(root.right); + } + return null; + }; + if (dfs(root)) { + ans.push(root); + } + return ans; +}; +``` + + + + + + + +### Solution 2: BFS + + + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ +export function delNodes(root: T, to_delete: number[]): Array { + if (!root) return []; + + const del = new Set(to_delete); + const res: T[] = []; + let q: TreeNode[] = [root]; + + while (q.length) { + const qNext: TreeNode[] = []; + + for (const node of q) { + if (node.left) { + qNext.push(node.left); + + if (del.has(node.left.val)) { + node.left = null; + } + } + + if (node.right) { + qNext.push(node.right); + + if (del.has(node.right.val)) { + node.right = null; + } + } + + if (del.has(node.val)) { + if (node.left) res.push(node.left); + if (node.right) res.push(node.right); + } + } + + q = qNext; + } + + if (!del.has(root.val)) res.push(root); + + return res; +} + +type T = TreeNode | null; +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number[]} to_delete + * @return {TreeNode[]} + */ +var delNodes = function (root, to_delete) { + if (!root) return []; + + const del = new Set(to_delete); + const res = []; + let q = [root]; + + while (q.length) { + const qNext = []; + + for (const node of q) { + if (node.left) { + qNext.push(node.left); + + if (del.has(node.left.val)) { + node.left = null; + } + } + + if (node.right) { + qNext.push(node.right); + + if (del.has(node.right.val)) { + node.right = null; + } + } + + if (del.has(node.val)) { + if (node.left) res.push(node.left); + if (node.right) res.push(node.right); + } + } + + q = qNext; + } + + if (!del.has(root.val)) res.push(root); + + return res; +}; +``` + diff --git a/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution.js b/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution.js new file mode 100644 index 000000000000..18c1bee863d0 --- /dev/null +++ b/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution.js @@ -0,0 +1,41 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number[]} to_delete + * @return {TreeNode[]} + */ +var delNodes = function (root, to_delete) { + const s = Array(1001).fill(false); + for (const x of to_delete) { + s[x] = true; + } + const ans = []; + const dfs = root => { + if (!root) { + return null; + } + root.left = dfs(root.left); + root.right = dfs(root.right); + if (!s[root.val]) { + return root; + } + if (root.left) { + ans.push(root.left); + } + if (root.right) { + ans.push(root.right); + } + return null; + }; + if (dfs(root)) { + ans.push(root); + } + return ans; +}; diff --git a/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution2.js b/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution2.js new file mode 100644 index 000000000000..3c37a6ebb7bf --- /dev/null +++ b/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution2.js @@ -0,0 +1,53 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number[]} to_delete + * @return {TreeNode[]} + */ +var delNodes = function (root, to_delete) { + if (!root) return []; + + const del = new Set(to_delete); + const res = []; + let q = [root]; + + while (q.length) { + const qNext = []; + + for (const node of q) { + if (node.left) { + qNext.push(node.left); + + if (del.has(node.left.val)) { + node.left = null; + } + } + + if (node.right) { + qNext.push(node.right); + + if (del.has(node.right.val)) { + node.right = null; + } + } + + if (del.has(node.val)) { + if (node.left) res.push(node.left); + if (node.right) res.push(node.right); + } + } + + q = qNext; + } + + if (!del.has(root.val)) res.push(root); + + return res; +}; diff --git a/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution2.ts b/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution2.ts new file mode 100644 index 000000000000..947201cade91 --- /dev/null +++ b/solution/1100-1199/1110.Delete Nodes And Return Forest/Solution2.ts @@ -0,0 +1,55 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ +export function delNodes(root: T, to_delete: number[]): Array { + if (!root) return []; + + const del = new Set(to_delete); + const res: T[] = []; + let q: TreeNode[] = [root]; + + while (q.length) { + const qNext: TreeNode[] = []; + + for (const node of q) { + if (node.left) { + qNext.push(node.left); + + if (del.has(node.left.val)) { + node.left = null; + } + } + + if (node.right) { + qNext.push(node.right); + + if (del.has(node.right.val)) { + node.right = null; + } + } + + if (del.has(node.val)) { + if (node.left) res.push(node.left); + if (node.right) res.push(node.right); + } + } + + q = qNext; + } + + if (!del.has(root.val)) res.push(root); + + return res; +} + +type T = TreeNode | null; diff --git a/solution/1100-1199/1122.Relative Sort Array/README.md b/solution/1100-1199/1122.Relative Sort Array/README.md index 11cc1e8f6037..f4da43168770 100644 --- a/solution/1100-1199/1122.Relative Sort Array/README.md +++ b/solution/1100-1199/1122.Relative Sort Array/README.md @@ -165,6 +165,26 @@ function relativeSortArray(arr1: number[], arr2: number[]): number[] { } ``` +#### Swift + +```swift +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var pos = [Int: Int]() + for (i, x) in arr2.enumerated() { + pos[x] = i + } + var arr = [(Int, Int)]() + for x in arr1 { + let j = pos[x] ?? arr2.count + arr.append((j, x)) + } + arr.sort { $0.0 < $1.0 || ($0.0 == $1.0 && $0.1 < $1.1) } + return arr.map { $0.1 } + } +} +``` + @@ -317,6 +337,40 @@ function relativeSortArray(arr1: number[], arr2: number[]): number[] { } ``` +#### Swift + +```swift +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var cnt = [Int](repeating: 0, count: 1001) + for x in arr1 { + cnt[x] += 1 + } + + guard let mi = arr1.min(), let mx = arr1.max() else { + return [] + } + + var ans = [Int]() + for x in arr2 { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + for x in mi...mx { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + return ans + } +} +``` + diff --git a/solution/1100-1199/1122.Relative Sort Array/README_EN.md b/solution/1100-1199/1122.Relative Sort Array/README_EN.md index 1f15b5be6144..914f2a4261b9 100644 --- a/solution/1100-1199/1122.Relative Sort Array/README_EN.md +++ b/solution/1100-1199/1122.Relative Sort Array/README_EN.md @@ -163,6 +163,26 @@ function relativeSortArray(arr1: number[], arr2: number[]): number[] { } ``` +#### Swift + +```swift +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var pos = [Int: Int]() + for (i, x) in arr2.enumerated() { + pos[x] = i + } + var arr = [(Int, Int)]() + for x in arr1 { + let j = pos[x] ?? arr2.count + arr.append((j, x)) + } + arr.sort { $0.0 < $1.0 || ($0.0 == $1.0 && $0.1 < $1.1) } + return arr.map { $0.1 } + } +} +``` + @@ -315,6 +335,40 @@ function relativeSortArray(arr1: number[], arr2: number[]): number[] { } ``` +#### Swift + +```swift +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var cnt = [Int](repeating: 0, count: 1001) + for x in arr1 { + cnt[x] += 1 + } + + guard let mi = arr1.min(), let mx = arr1.max() else { + return [] + } + + var ans = [Int]() + for x in arr2 { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + for x in mi...mx { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + return ans + } +} +``` + diff --git a/solution/1100-1199/1122.Relative Sort Array/Solution.swift b/solution/1100-1199/1122.Relative Sort Array/Solution.swift new file mode 100644 index 000000000000..af048342c47b --- /dev/null +++ b/solution/1100-1199/1122.Relative Sort Array/Solution.swift @@ -0,0 +1,15 @@ +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var pos = [Int: Int]() + for (i, x) in arr2.enumerated() { + pos[x] = i + } + var arr = [(Int, Int)]() + for x in arr1 { + let j = pos[x] ?? arr2.count + arr.append((j, x)) + } + arr.sort { $0.0 < $1.0 || ($0.0 == $1.0 && $0.1 < $1.1) } + return arr.map { $0.1 } + } +} diff --git a/solution/1100-1199/1122.Relative Sort Array/Solution2.swift b/solution/1100-1199/1122.Relative Sort Array/Solution2.swift new file mode 100644 index 000000000000..c9c4f512ca39 --- /dev/null +++ b/solution/1100-1199/1122.Relative Sort Array/Solution2.swift @@ -0,0 +1,29 @@ +class Solution { + func relativeSortArray(_ arr1: [Int], _ arr2: [Int]) -> [Int] { + var cnt = [Int](repeating: 0, count: 1001) + for x in arr1 { + cnt[x] += 1 + } + + guard let mi = arr1.min(), let mx = arr1.max() else { + return [] + } + + var ans = [Int]() + for x in arr2 { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + for x in mi...mx { + while cnt[x] > 0 { + ans.append(x) + cnt[x] -= 1 + } + } + + return ans + } +} diff --git a/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README.md b/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README.md index 098e5a5df0d0..f9333cb272f4 100644 --- a/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README.md +++ b/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README.md @@ -82,8 +82,8 @@ tags: $$ dfs(i, j) = \begin{cases} -0, & \text{if } i = j \\ -\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + \max_{i \leq t \leq k} \{arr[t]\} \max_{k < t \leq j} \{arr[t]\}\}, & \text{if } i < j +0, & \textit{if } i = j \\ +\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + \max_{i \leq t \leq k} \{arr[t]\} \max_{k < t \leq j} \{arr[t]\}\}, & \textit{if } i < j \end{cases} $$ @@ -91,8 +91,8 @@ $$ $$ dfs(i, j) = \begin{cases} -0, & \text{if } i = j \\ -\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + g[i][k] \cdot g[k + 1][j]\}, & \text{if } i < j +0, & \textit{if } i = j \\ +\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + g[i][k] \cdot g[k + 1][j]\}, & \textit{if } i < j \end{cases} $$ @@ -271,8 +271,8 @@ function mctFromLeafValues(arr: number[]): number { $$ f[i][j] = \begin{cases} -0, & \text{if } i = j \\ -\min_{i \leq k < j} \{f[i][k] + f[k + 1][j] + g[i][k] \cdot g[k + 1][j]\}, & \text{if } i < j +0, & \textit{if } i = j \\ +\min_{i \leq k < j} \{f[i][k] + f[k + 1][j] + g[i][k] \cdot g[k + 1][j]\}, & \textit{if } i < j \end{cases} $$ diff --git a/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README_EN.md b/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README_EN.md index 8f9e9930c653..7e8fc81fd461 100644 --- a/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README_EN.md +++ b/solution/1100-1199/1130.Minimum Cost Tree From Leaf Values/README_EN.md @@ -81,8 +81,8 @@ In summary, we can get: $$ dfs(i, j) = \begin{cases} -0, & \text{if } i = j \\ -\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + \max_{i \leq t \leq k} \{arr[t]\} \max_{k < t \leq j} \{arr[t]\}\}, & \text{if } i < j +0, & \textit{if } i = j \\ +\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + \max_{i \leq t \leq k} \{arr[t]\} \max_{k < t \leq j} \{arr[t]\}\}, & \textit{if } i < j \end{cases} $$ @@ -90,8 +90,8 @@ In the above recursive process, we can use the method of memoization search to a $$ dfs(i, j) = \begin{cases} -0, & \text{if } i = j \\ -\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + g[i][k] \cdot g[k + 1][j]\}, & \text{if } i < j +0, & \textit{if } i = j \\ +\min_{i \leq k < j} \{dfs(i, k) + dfs(k + 1, j) + g[i][k] \cdot g[k + 1][j]\}, & \textit{if } i < j \end{cases} $$ @@ -270,8 +270,8 @@ Define $f[i][j]$ to represent the minimum possible sum of all non-leaf node valu $$ f[i][j] = \begin{cases} -0, & \text{if } i = j \\ -\min_{i \leq k < j} \{f[i][k] + f[k + 1][j] + g[i][k] \cdot g[k + 1][j]\}, & \text{if } i < j +0, & \textit{if } i = j \\ +\min_{i \leq k < j} \{f[i][k] + f[k + 1][j] + g[i][k] \cdot g[k + 1][j]\}, & \textit{if } i < j \end{cases} $$ diff --git a/solution/1100-1199/1143.Longest Common Subsequence/README_EN.md b/solution/1100-1199/1143.Longest Common Subsequence/README_EN.md index d546d78b6132..d308081cda84 100644 --- a/solution/1100-1199/1143.Longest Common Subsequence/README_EN.md +++ b/solution/1100-1199/1143.Longest Common Subsequence/README_EN.md @@ -75,8 +75,8 @@ If the $i$th character of $text1$ and the $j$th character of $text2$ are the sam $$ f[i][j] = \begin{cases} -f[i - 1][j - 1] + 1, & \text{if } text1[i - 1] = text2[j - 1] \\ -\max(f[i - 1][j], f[i][j - 1]), & \text{if } text1[i - 1] \neq text2[j - 1] +f[i - 1][j - 1] + 1, & \textit{if } text1[i - 1] = text2[j - 1] \\ +\max(f[i - 1][j], f[i][j - 1]), & \textit{if } text1[i - 1] \neq text2[j - 1] \end{cases} $$ diff --git a/solution/1100-1199/1146.Snapshot Array/README.md b/solution/1100-1199/1146.Snapshot Array/README.md index 5c7ab4602280..cd8e9c5ec7e6 100644 --- a/solution/1100-1199/1146.Snapshot Array/README.md +++ b/solution/1100-1199/1146.Snapshot Array/README.md @@ -64,7 +64,7 @@ snapshotArr.get(0,0); // 获取 snap_id = 0 的快照中 array[0] 的值,返 ### 方法一:数组 + 二分查找 -我们维护一个长度为 $\text{length}$ 的数组,数组中的每个元素是一个列表,用来存储每次设置的值以及对应的快照 ID。 +我们维护一个长度为 $\textit{length}$ 的数组,数组中的每个元素是一个列表,用来存储每次设置的值以及对应的快照 ID。 调用 `set` 方法时,将值和快照 ID 添加到对应索引的列表中。时间复杂度 $O(1)$。 diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README.md b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README.md index cd4029c15600..d25ea1ac073d 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README.md +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README.md @@ -93,107 +93,6 @@ tags: #### Python3 -```python -class Solution: - def longestDecomposition(self, text: str) -> int: - n = len(text) - if n < 2: - return n - for i in range(n // 2 + 1): - if text[:i] == text[-i:]: - return 2 + self.longestDecomposition(text[i:-i]) - return 1 -``` - -#### Java - -```java -class Solution { - public int longestDecomposition(String text) { - int n = text.length(); - if (n < 2) { - return n; - } - for (int i = 1; i <= n >> 1; ++i) { - if (text.substring(0, i).equals(text.substring(n - i))) { - return 2 + longestDecomposition(text.substring(i, n - i)); - } - } - return 1; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int longestDecomposition(string text) { - int n = text.size(); - if (n < 2) return n; - for (int i = 1; i <= n >> 1; ++i) { - if (text.substr(0, i) == text.substr(n - i)) { - return 2 + longestDecomposition(text.substr(i, n - i - i)); - } - } - return 1; - } -}; -``` - -#### Go - -```go -func longestDecomposition(text string) int { - n := len(text) - if n < 2 { - return n - } - for i := 1; i <= n>>1; i++ { - if text[:i] == text[n-i:] { - return 2 + longestDecomposition(text[i:n-i]) - } - } - return 1 -} -``` - -#### TypeScript - -```ts -function longestDecomposition(text: string): number { - const n: number = text.length; - if (n < 2) { - return n; - } - for (let i: number = 1; i <= n >> 1; i++) { - if (text.slice(0, i) === text.slice(n - i)) { - return 2 + longestDecomposition(text.slice(i, n - i)); - } - } - return 1; -} -``` - - - - - - - -### 方法二:字符串哈希 - -**字符串哈希**是把一个任意长度的字符串映射成一个非负整数,并且其冲突的概率几乎为 $0$。字符串哈希用于计算字符串哈希值,快速判断两个字符串是否相等。 - -因此,在方法一的基础上,我们可以使用字符串哈希的方法,在 $O(1)$ 时间内比较两个字符串是否相等。 - -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串的长度。 - - - -#### Python3 - ```python class Solution: def longestDecomposition(self, text: str) -> int: @@ -343,7 +242,13 @@ function longestDecomposition(text: string): number { -### 方法三 +### 方法二:字符串哈希 + +**字符串哈希**是把一个任意长度的字符串映射成一个非负整数,并且其冲突的概率几乎为 $0$。字符串哈希用于计算字符串哈希值,快速判断两个字符串是否相等。 + +因此,在方法一的基础上,我们可以使用字符串哈希的方法,在 $O(1)$ 时间内比较两个字符串是否相等。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串的长度。 diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README_EN.md b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README_EN.md index a9a2ce5a2335..c1fe9fcb664c 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README_EN.md +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/README_EN.md @@ -91,107 +91,6 @@ The time complexity is $O(n^2)$, and the space complexity is $O(n)$ or $O(1)$. H #### Python3 -```python -class Solution: - def longestDecomposition(self, text: str) -> int: - n = len(text) - if n < 2: - return n - for i in range(n // 2 + 1): - if text[:i] == text[-i:]: - return 2 + self.longestDecomposition(text[i:-i]) - return 1 -``` - -#### Java - -```java -class Solution { - public int longestDecomposition(String text) { - int n = text.length(); - if (n < 2) { - return n; - } - for (int i = 1; i <= n >> 1; ++i) { - if (text.substring(0, i).equals(text.substring(n - i))) { - return 2 + longestDecomposition(text.substring(i, n - i)); - } - } - return 1; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int longestDecomposition(string text) { - int n = text.size(); - if (n < 2) return n; - for (int i = 1; i <= n >> 1; ++i) { - if (text.substr(0, i) == text.substr(n - i)) { - return 2 + longestDecomposition(text.substr(i, n - i - i)); - } - } - return 1; - } -}; -``` - -#### Go - -```go -func longestDecomposition(text string) int { - n := len(text) - if n < 2 { - return n - } - for i := 1; i <= n>>1; i++ { - if text[:i] == text[n-i:] { - return 2 + longestDecomposition(text[i:n-i]) - } - } - return 1 -} -``` - -#### TypeScript - -```ts -function longestDecomposition(text: string): number { - const n: number = text.length; - if (n < 2) { - return n; - } - for (let i: number = 1; i <= n >> 1; i++) { - if (text.slice(0, i) === text.slice(n - i)) { - return 2 + longestDecomposition(text.slice(i, n - i)); - } - } - return 1; -} -``` - - - - - - - -### Solution 2: String Hash - -**String hash** is to map a string of any length to a non-negative integer, and its collision probability is almost $0$. String hash is used to calculate the hash value of a string and quickly determine whether two strings are equal. - -Therefore, based on Solution 1, we can use the method of string hash to compare whether two strings are equal in $O(1)$ time. - -The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string. - - - -#### Python3 - ```python class Solution: def longestDecomposition(self, text: str) -> int: @@ -341,7 +240,13 @@ function longestDecomposition(text: string): number { -### Solution 3 +### Solution 2: String Hash + +**String hash** is to map a string of any length to a non-negative integer, and its collision probability is almost $0$. String hash is used to calculate the hash value of a string and quickly determine whether two strings are equal. + +Therefore, based on Solution 1, we can use the method of string hash to compare whether two strings are equal in $O(1)$ time. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string. diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.cpp b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.cpp index f085d2365677..3ebb1231799b 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.cpp +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.cpp @@ -1,13 +1,31 @@ class Solution { public: int longestDecomposition(string text) { - int n = text.size(); - if (n < 2) return n; - for (int i = 1; i <= n >> 1; ++i) { - if (text.substr(0, i) == text.substr(n - i)) { - return 2 + longestDecomposition(text.substr(i, n - i - i)); + int ans = 0; + auto check = [&](int i, int j, int k) -> bool { + while (k--) { + if (text[i++] != text[j++]) { + return false; + } + } + return true; + }; + for (int i = 0, j = text.size() - 1; i <= j;) { + bool ok = false; + for (int k = 1; i + k - 1 < j - k + 1; ++k) { + if (check(i, j - k + 1, k)) { + ans += 2; + i += k; + j -= k; + ok = true; + break; + } + } + if (!ok) { + ans += 1; + break; } } - return 1; + return ans; } }; \ No newline at end of file diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.go b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.go index 4c5d65be86ca..0c9364120ce0 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.go +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.go @@ -1,12 +1,19 @@ -func longestDecomposition(text string) int { - n := len(text) - if n < 2 { - return n - } - for i := 1; i <= n>>1; i++ { - if text[:i] == text[n-i:] { - return 2 + longestDecomposition(text[i:n-i]) +func longestDecomposition(text string) (ans int) { + for i, j := 0, len(text)-1; i <= j; { + ok := false + for k := 1; i+k-1 < j-k+1; k++ { + if text[i:i+k] == text[j-k+1:j+1] { + ans += 2 + i += k + j -= k + ok = true + break + } + } + if !ok { + ans++ + break } } - return 1 + return } \ No newline at end of file diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.java b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.java index 0c9e6fd429a4..60208724249d 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.java +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.java @@ -1,14 +1,31 @@ class Solution { public int longestDecomposition(String text) { - int n = text.length(); - if (n < 2) { - return n; + int ans = 0; + for (int i = 0, j = text.length() - 1; i <= j;) { + boolean ok = false; + for (int k = 1; i + k - 1 < j - k + 1; ++k) { + if (check(text, i, j - k + 1, k)) { + ans += 2; + i += k; + j -= k; + ok = true; + break; + } + } + if (!ok) { + ++ans; + break; + } } - for (int i = 1; i <= n >> 1; ++i) { - if (text.substring(0, i).equals(text.substring(n - i))) { - return 2 + longestDecomposition(text.substring(i, n - i)); + return ans; + } + + private boolean check(String s, int i, int j, int k) { + while (k-- > 0) { + if (s.charAt(i++) != s.charAt(j++)) { + return false; } } - return 1; + return true; } } \ No newline at end of file diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.py b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.py index 20fba192cdbc..30f40ad4ac56 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.py +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.py @@ -1,9 +1,19 @@ class Solution: def longestDecomposition(self, text: str) -> int: - n = len(text) - if n < 2: - return n - for i in range(n // 2 + 1): - if text[:i] == text[-i:]: - return 2 + self.longestDecomposition(text[i:-i]) - return 1 + ans = 0 + i, j = 0, len(text) - 1 + while i <= j: + k = 1 + ok = False + while i + k - 1 < j - k + 1: + if text[i : i + k] == text[j - k + 1 : j + 1]: + ans += 2 + i += k + j -= k + ok = True + break + k += 1 + if not ok: + ans += 1 + break + return ans diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.ts b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.ts index 0fe9ca2eaeb4..a413f70e20fb 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.ts +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution.ts @@ -1,12 +1,20 @@ function longestDecomposition(text: string): number { - const n: number = text.length; - if (n < 2) { - return n; - } - for (let i: number = 1; i <= n >> 1; i++) { - if (text.slice(0, i) === text.slice(n - i)) { - return 2 + longestDecomposition(text.slice(i, n - i)); + let ans = 0; + for (let i = 0, j = text.length - 1; i <= j; ) { + let ok = false; + for (let k = 1; i + k - 1 < j - k + 1; ++k) { + if (text.slice(i, i + k) === text.slice(j - k + 1, j + 1)) { + ans += 2; + i += k; + j -= k; + ok = true; + break; + } + } + if (!ok) { + ++ans; + break; } } - return 1; + return ans; } diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.cpp b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.cpp index 3ebb1231799b..1130d50a83db 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.cpp +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.cpp @@ -1,19 +1,27 @@ class Solution { public: int longestDecomposition(string text) { + using ull = unsigned long long; + int n = text.size(); + int base = 131; + ull p[n + 10]; + ull h[n + 10]; + p[0] = 1; + h[0] = 0; + for (int i = 0; i < n; ++i) { + int t = text[i] - 'a' + 1; + p[i + 1] = p[i] * base; + h[i + 1] = h[i] * base + t; + } + int ans = 0; - auto check = [&](int i, int j, int k) -> bool { - while (k--) { - if (text[i++] != text[j++]) { - return false; - } - } - return true; + auto get = [&](int l, int r) { + return h[r] - h[l - 1] * p[r - l + 1]; }; - for (int i = 0, j = text.size() - 1; i <= j;) { + for (int i = 0, j = n - 1; i <= j;) { bool ok = false; for (int k = 1; i + k - 1 < j - k + 1; ++k) { - if (check(i, j - k + 1, k)) { + if (get(i + 1, i + k) == get(j - k + 2, j + 1)) { ans += 2; i += k; j -= k; @@ -22,7 +30,7 @@ class Solution { } } if (!ok) { - ans += 1; + ++ans; break; } } diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.go b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.go index 0c9364120ce0..a708cefe7601 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.go +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.go @@ -1,8 +1,22 @@ func longestDecomposition(text string) (ans int) { - for i, j := 0, len(text)-1; i <= j; { + n := len(text) + base := 131 + h := make([]int, n+10) + p := make([]int, n+10) + p[0] = 1 + for i, c := range text { + t := int(c-'a') + 1 + p[i+1] = p[i] * base + h[i+1] = h[i]*base + t + } + get := func(l, r int) int { + return h[r] - h[l-1]*p[r-l+1] + } + + for i, j := 0, n-1; i <= j; { ok := false for k := 1; i+k-1 < j-k+1; k++ { - if text[i:i+k] == text[j-k+1:j+1] { + if get(i+1, i+k) == get(j-k+2, j+1) { ans += 2 i += k j -= k diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.java b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.java index 60208724249d..fc0350ab7f2d 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.java +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.java @@ -1,10 +1,23 @@ class Solution { + private long[] h; + private long[] p; + public int longestDecomposition(String text) { + int n = text.length(); + int base = 131; + h = new long[n + 10]; + p = new long[n + 10]; + p[0] = 1; + for (int i = 0; i < n; ++i) { + int t = text.charAt(i) - 'a' + 1; + h[i + 1] = h[i] * base + t; + p[i + 1] = p[i] * base; + } int ans = 0; - for (int i = 0, j = text.length() - 1; i <= j;) { + for (int i = 0, j = n - 1; i <= j;) { boolean ok = false; for (int k = 1; i + k - 1 < j - k + 1; ++k) { - if (check(text, i, j - k + 1, k)) { + if (get(i + 1, i + k) == get(j - k + 2, j + 1)) { ans += 2; i += k; j -= k; @@ -20,12 +33,7 @@ public int longestDecomposition(String text) { return ans; } - private boolean check(String s, int i, int j, int k) { - while (k-- > 0) { - if (s.charAt(i++) != s.charAt(j++)) { - return false; - } - } - return true; + private long get(int i, int j) { + return h[j] - h[i - 1] * p[j - i + 1]; } } \ No newline at end of file diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.py b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.py index 30f40ad4ac56..2024fa6706a3 100644 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.py +++ b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.py @@ -1,12 +1,25 @@ class Solution: def longestDecomposition(self, text: str) -> int: + def get(l, r): + return (h[r] - h[l - 1] * p[r - l + 1]) % mod + + n = len(text) + base = 131 + mod = int(1e9) + 7 + h = [0] * (n + 10) + p = [1] * (n + 10) + for i, c in enumerate(text): + t = ord(c) - ord('a') + 1 + h[i + 1] = (h[i] * base) % mod + t + p[i + 1] = (p[i] * base) % mod + ans = 0 - i, j = 0, len(text) - 1 + i, j = 0, n - 1 while i <= j: k = 1 ok = False while i + k - 1 < j - k + 1: - if text[i : i + k] == text[j - k + 1 : j + 1]: + if get(i + 1, i + k) == get(j - k + 2, j + 1): ans += 2 i += k j -= k diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.ts b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.ts deleted file mode 100644 index a413f70e20fb..000000000000 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution2.ts +++ /dev/null @@ -1,20 +0,0 @@ -function longestDecomposition(text: string): number { - let ans = 0; - for (let i = 0, j = text.length - 1; i <= j; ) { - let ok = false; - for (let k = 1; i + k - 1 < j - k + 1; ++k) { - if (text.slice(i, i + k) === text.slice(j - k + 1, j + 1)) { - ans += 2; - i += k; - j -= k; - ok = true; - break; - } - } - if (!ok) { - ++ans; - break; - } - } - return ans; -} diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.cpp b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.cpp deleted file mode 100644 index 1130d50a83db..000000000000 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.cpp +++ /dev/null @@ -1,39 +0,0 @@ -class Solution { -public: - int longestDecomposition(string text) { - using ull = unsigned long long; - int n = text.size(); - int base = 131; - ull p[n + 10]; - ull h[n + 10]; - p[0] = 1; - h[0] = 0; - for (int i = 0; i < n; ++i) { - int t = text[i] - 'a' + 1; - p[i + 1] = p[i] * base; - h[i + 1] = h[i] * base + t; - } - - int ans = 0; - auto get = [&](int l, int r) { - return h[r] - h[l - 1] * p[r - l + 1]; - }; - for (int i = 0, j = n - 1; i <= j;) { - bool ok = false; - for (int k = 1; i + k - 1 < j - k + 1; ++k) { - if (get(i + 1, i + k) == get(j - k + 2, j + 1)) { - ans += 2; - i += k; - j -= k; - ok = true; - break; - } - } - if (!ok) { - ++ans; - break; - } - } - return ans; - } -}; \ No newline at end of file diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.go b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.go deleted file mode 100644 index a708cefe7601..000000000000 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.go +++ /dev/null @@ -1,33 +0,0 @@ -func longestDecomposition(text string) (ans int) { - n := len(text) - base := 131 - h := make([]int, n+10) - p := make([]int, n+10) - p[0] = 1 - for i, c := range text { - t := int(c-'a') + 1 - p[i+1] = p[i] * base - h[i+1] = h[i]*base + t - } - get := func(l, r int) int { - return h[r] - h[l-1]*p[r-l+1] - } - - for i, j := 0, n-1; i <= j; { - ok := false - for k := 1; i+k-1 < j-k+1; k++ { - if get(i+1, i+k) == get(j-k+2, j+1) { - ans += 2 - i += k - j -= k - ok = true - break - } - } - if !ok { - ans++ - break - } - } - return -} \ No newline at end of file diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.java b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.java deleted file mode 100644 index fc0350ab7f2d..000000000000 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.java +++ /dev/null @@ -1,39 +0,0 @@ -class Solution { - private long[] h; - private long[] p; - - public int longestDecomposition(String text) { - int n = text.length(); - int base = 131; - h = new long[n + 10]; - p = new long[n + 10]; - p[0] = 1; - for (int i = 0; i < n; ++i) { - int t = text.charAt(i) - 'a' + 1; - h[i + 1] = h[i] * base + t; - p[i + 1] = p[i] * base; - } - int ans = 0; - for (int i = 0, j = n - 1; i <= j;) { - boolean ok = false; - for (int k = 1; i + k - 1 < j - k + 1; ++k) { - if (get(i + 1, i + k) == get(j - k + 2, j + 1)) { - ans += 2; - i += k; - j -= k; - ok = true; - break; - } - } - if (!ok) { - ++ans; - break; - } - } - return ans; - } - - private long get(int i, int j) { - return h[j] - h[i - 1] * p[j - i + 1]; - } -} \ No newline at end of file diff --git a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.py b/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.py deleted file mode 100644 index 2024fa6706a3..000000000000 --- a/solution/1100-1199/1147.Longest Chunked Palindrome Decomposition/Solution3.py +++ /dev/null @@ -1,32 +0,0 @@ -class Solution: - def longestDecomposition(self, text: str) -> int: - def get(l, r): - return (h[r] - h[l - 1] * p[r - l + 1]) % mod - - n = len(text) - base = 131 - mod = int(1e9) + 7 - h = [0] * (n + 10) - p = [1] * (n + 10) - for i, c in enumerate(text): - t = ord(c) - ord('a') + 1 - h[i + 1] = (h[i] * base) % mod + t - p[i + 1] = (p[i] * base) % mod - - ans = 0 - i, j = 0, n - 1 - while i <= j: - k = 1 - ok = False - while i + k - 1 < j - k + 1: - if get(i + 1, i + k) == get(j - k + 2, j + 1): - ans += 2 - i += k - j -= k - ok = True - break - k += 1 - if not ok: - ans += 1 - break - return ans diff --git a/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README.md b/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README.md index b641399ba0f9..b75ac79d36db 100644 --- a/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README.md +++ b/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README.md @@ -67,11 +67,11 @@ tags: ### 方法一:预处理 + 枚举 -我们可以先预处理出数组 $arr$ 以每个元素结尾和开头的最大子数组和,分别存入数组 $left$ 和 $right$ 中。 +我们可以先预处理出数组 $\textit{arr}$ 以每个元素结尾和开头的最大子数组和,分别存入数组 $\textit{left}$ 和 $\textit{right}$ 中。 -如果我们不删除任何元素,那么最大子数组和就是 $left[i]$ 或 $right[i]$ 中的最大值;如果我们删除一个元素,我们可以枚举 $[1..n-2]$ 中的每个位置 $i$,计算 $left[i-1] + right[i+1]$ 的值,取最大值即可。 +如果我们不删除任何元素,那么最大子数组和就是 $\textit{left}[i]$ 或 $\textit{right}[i]$ 中的最大值;如果我们删除一个元素,我们可以枚举 $[1..n-2]$ 中的每个位置 $i$,计算 $\textit{left}[i-1] + \textit{right}[i+1]$ 的值,取最大值即可。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $arr$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{arr}$ 的长度。 @@ -195,6 +195,33 @@ function maximumSum(arr: number[]): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn maximum_sum(arr: Vec) -> i32 { + let n = arr.len(); + let mut left = vec![0; n]; + let mut right = vec![0; n]; + let mut s = 0; + for i in 0..n { + s = (s.max(0)) + arr[i]; + left[i] = s; + } + s = 0; + for i in (0..n).rev() { + s = (s.max(0)) + arr[i]; + right[i] = s; + } + let mut ans = *left.iter().max().unwrap(); + for i in 1..n - 1 { + ans = ans.max(left[i - 1] + right[i + 1]); + } + ans + } +} +``` + diff --git a/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README_EN.md b/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README_EN.md index 8222a852b50a..3e2efdaf5f17 100644 --- a/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README_EN.md +++ b/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/README_EN.md @@ -63,11 +63,11 @@ tags: ### Solution 1: Preprocessing + Enumeration -We can first preprocess the array $arr$ to find the maximum subarray sum ending at and starting from each element, and store them in the arrays $left$ and $right$ respectively. +We can preprocess the array $\textit{arr}$ to find the maximum subarray sum ending and starting with each element, storing them in arrays $\textit{left}$ and $\textit{right}$, respectively. -If we do not delete any element, then the maximum subarray sum is the maximum value in $left[i]$ or $right[i]$. If we delete one element, we can enumerate each position $i$ in $[1..n-2]$, calculate the value of $left[i-1] + right[i+1]$, and take the maximum value. +If we do not delete any element, then the maximum subarray sum is the maximum value in $\textit{left}[i]$ or $\textit{right}[i]$; if we delete an element, we can enumerate each position $i$ in $[1..n-2]$, calculate the value of $\textit{left}[i-1] + \textit{right}[i+1]$, and take the maximum value. -The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $arr$. +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{arr}$. @@ -191,6 +191,33 @@ function maximumSum(arr: number[]): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn maximum_sum(arr: Vec) -> i32 { + let n = arr.len(); + let mut left = vec![0; n]; + let mut right = vec![0; n]; + let mut s = 0; + for i in 0..n { + s = (s.max(0)) + arr[i]; + left[i] = s; + } + s = 0; + for i in (0..n).rev() { + s = (s.max(0)) + arr[i]; + right[i] = s; + } + let mut ans = *left.iter().max().unwrap(); + for i in 1..n - 1 { + ans = ans.max(left[i - 1] + right[i + 1]); + } + ans + } +} +``` + diff --git a/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/Solution.rs b/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/Solution.rs new file mode 100644 index 000000000000..0bd19a675456 --- /dev/null +++ b/solution/1100-1199/1186.Maximum Subarray Sum with One Deletion/Solution.rs @@ -0,0 +1,22 @@ +impl Solution { + pub fn maximum_sum(arr: Vec) -> i32 { + let n = arr.len(); + let mut left = vec![0; n]; + let mut right = vec![0; n]; + let mut s = 0; + for i in 0..n { + s = (s.max(0)) + arr[i]; + left[i] = s; + } + s = 0; + for i in (0..n).rev() { + s = (s.max(0)) + arr[i]; + right[i] = s; + } + let mut ans = *left.iter().max().unwrap(); + for i in 1..n - 1 { + ans = ans.max(left[i - 1] + right[i + 1]); + } + ans + } +} diff --git a/solution/1100-1199/1190.Reverse Substrings Between Each Pair of Parentheses/README.md b/solution/1100-1199/1190.Reverse Substrings Between Each Pair of Parentheses/README.md index 7547ec2bfc4d..102f1dd13f0e 100644 --- a/solution/1100-1199/1190.Reverse Substrings Between Each Pair of Parentheses/README.md +++ b/solution/1100-1199/1190.Reverse Substrings Between Each Pair of Parentheses/README.md @@ -48,13 +48,6 @@ tags: 输出:"leetcode" 解释:先反转子字符串 "oc" ,接着反转 "etco" ,然后反转整个字符串。
    -

    示例 4:

    - -
    -输入:s = "a(bcdefghijkl(mno)p)q"
    -输出:"apmnolkjihgfedcbq"
    -
    -

     

    提示:

    diff --git a/solution/1200-1299/1208.Get Equal Substrings Within Budget/README.md b/solution/1200-1299/1208.Get Equal Substrings Within Budget/README.md index eb097e9454c4..a7aa549ff9a0 100644 --- a/solution/1200-1299/1208.Get Equal Substrings Within Budget/README.md +++ b/solution/1200-1299/1208.Get Equal Substrings Within Budget/README.md @@ -265,7 +265,7 @@ function equalSubstring(s: string, t: string, maxCost: number): number { ### 方法二:双指针 -我们可以维护两个指针 $l$ 和 $r$,初始时 $l = r = 0$;维护一个变量 $\text{cost}$,表示下标区间 $[l,..r]$ 之间的 ASCII 码值的差的绝对值之和。在每一步中,我们将 $r$ 向右移动一位,然后更新 $\text{cost} = \text{cost} + |s[r] - t[r]|$。如果 $\text{cost} \gt \text{maxCost}$,那么我们就循环将 $l$ 向右移动一位,并且减少 $\text{cost}$ 的值,直到 $\text{cost} \leq \text{maxCost}$。然后我们更新答案,即 $\text{ans} = \max(\text{ans}, r - l + 1)$。 +我们可以维护两个指针 $l$ 和 $r$,初始时 $l = r = 0$;维护一个变量 $\textit{cost}$,表示下标区间 $[l,..r]$ 之间的 ASCII 码值的差的绝对值之和。在每一步中,我们将 $r$ 向右移动一位,然后更新 $\textit{cost} = \textit{cost} + |s[r] - t[r]|$。如果 $\textit{cost} \gt \textit{maxCost}$,那么我们就循环将 $l$ 向右移动一位,并且减少 $\textit{cost}$ 的值,直到 $\textit{cost} \leq \textit{maxCost}$。然后我们更新答案,即 $\textit{ans} = \max(\textit{ans}, r - l + 1)$。 最后返回答案即可。 @@ -382,7 +382,7 @@ function equalSubstring(s: string, t: string, maxCost: number): number { 在方法二中,双指针维护的区间可能变短,也可能变长,由于题目只需要求出最大长度,我们可以维护一个单调变长的区间。 -具体地,我们用两个指针 $l$ 和 $r$ 指向区间的左右端点,初始时 $l = r = 0$。在每一步中,我们将 $r$ 向右移动一位,然后更新 $\text{cost} = \text{cost} + |s[r] - t[r]|$。如果 $\text{cost} \gt \text{maxCost}$,那么我们就将 $l$ 向右移动一位,并且减少 $\text{cost}$ 的值。 +具体地,我们用两个指针 $l$ 和 $r$ 指向区间的左右端点,初始时 $l = r = 0$。在每一步中,我们将 $r$ 向右移动一位,然后更新 $\textit{cost} = \textit{cost} + |s[r] - t[r]|$。如果 $\textit{cost} \gt \textit{maxCost}$,那么我们就将 $l$ 向右移动一位,并且减少 $\textit{cost}$ 的值。 最后返回 $n - l$ 即可。 diff --git a/solution/1200-1299/1208.Get Equal Substrings Within Budget/README_EN.md b/solution/1200-1299/1208.Get Equal Substrings Within Budget/README_EN.md index 4e1b62096976..4a1edd94ae9d 100644 --- a/solution/1200-1299/1208.Get Equal Substrings Within Budget/README_EN.md +++ b/solution/1200-1299/1208.Get Equal Substrings Within Budget/README_EN.md @@ -262,7 +262,7 @@ function equalSubstring(s: string, t: string, maxCost: number): number { ### Solution 2: Two Pointers -We can maintain two pointers $l$ and $r$, initially $l = r = 0$; maintain a variable $\text{cost}$, which represents the sum of the absolute values of the ASCII code differences in the index interval $[l,..r]$. In each step, we move $r$ to the right by one position, then update $\text{cost} = \text{cost} + |s[r] - t[r]|$. If $\text{cost} \gt \text{maxCost}$, then we loop to move $l$ to the right by one position, and decrease the value of $\text{cost}$, until $\text{cost} \leq \text{maxCost}$. Then we update the answer, that is, $\text{ans} = \max(\text{ans}, r - l + 1)$. +We can maintain two pointers $l$ and $r$, initially $l = r = 0$; maintain a variable $\textit{cost}$, which represents the sum of the absolute values of the ASCII code differences in the index interval $[l,..r]$. In each step, we move $r$ to the right by one position, then update $\textit{cost} = \textit{cost} + |s[r] - t[r]|$. If $\textit{cost} \gt \textit{maxCost}$, then we loop to move $l$ to the right by one position, and decrease the value of $\textit{cost}$, until $\textit{cost} \leq \textit{maxCost}$. Then we update the answer, that is, $\textit{ans} = \max(\textit{ans}, r - l + 1)$. Finally, return the answer. @@ -379,7 +379,7 @@ function equalSubstring(s: string, t: string, maxCost: number): number { In Solution 2, the interval maintained by the two pointers may become shorter or longer. Since the problem only requires the maximum length, we can maintain a monotonically increasing interval. -Specifically, we use two pointers $l$ and $r$ to point to the left and right endpoints of the interval, initially $l = r = 0$. In each step, we move $r$ to the right by one position, then update $\text{cost} = \text{cost} + |s[r] - t[r]|$. If $\text{cost} \gt \text{maxCost}$, then we move $l$ to the right by one position, and decrease the value of $\text{cost}$. +Specifically, we use two pointers $l$ and $r$ to point to the left and right endpoints of the interval, initially $l = r = 0$. In each step, we move $r$ to the right by one position, then update $\textit{cost} = \textit{cost} + |s[r] - t[r]|$. If $\textit{cost} \gt \textit{maxCost}$, then we move $l$ to the right by one position, and decrease the value of $\textit{cost}$. Finally, return $n - l$. diff --git a/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README.md b/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README.md index ccc4d129ec2f..3afed1acfac9 100644 --- a/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README.md +++ b/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README.md @@ -80,11 +80,11 @@ tags: ### 方法一:模拟 -我们创建一个矩阵 $g$ 来存放操作的结果。对于 $\text{indices}$ 中的每一对 $(r_i, c_i)$,我们将矩阵第 $r_i$ 行的所有数加 $1$,第 $c_i$ 列的所有元素加 $1$。 +我们创建一个矩阵 $g$ 来存放操作的结果。对于 $\textit{indices}$ 中的每一对 $(r_i, c_i)$,我们将矩阵第 $r_i$ 行的所有数加 $1$,第 $c_i$ 列的所有元素加 $1$。 模拟结束后,遍历矩阵,统计奇数的个数。 -时间复杂度 $O(k \times (m + n) + m \times n)$,空间复杂度 $O(m \times n)$。其中 $k$ 为 $\text{indices}$ 的长度。 +时间复杂度 $O(k \times (m + n) + m \times n)$,空间复杂度 $O(m \times n)$。其中 $k$ 为 $\textit{indices}$ 的长度。 @@ -190,11 +190,11 @@ func oddCells(m int, n int, indices [][]int) int { ### 方法二:空间优化 -我们可以使用行数组 $\text{row}$ 和列数组 $\text{col}$ 来记录每一行、每一列被增加的次数。对于 $\text{indices}$ 中的每一对 $(r_i, c_i)$,我们将 $\text{row}[r_i]$ 和 $\text{col}[c_i]$ 分别加 $1$。 +我们可以使用行数组 $\textit{row}$ 和列数组 $\textit{col}$ 来记录每一行、每一列被增加的次数。对于 $\textit{indices}$ 中的每一对 $(r_i, c_i)$,我们将 $\textit{row}[r_i]$ 和 $\textit{col}[c_i]$ 分别加 $1$。 -操作结束后,可以算出 $(i, j)$ 位置的计数为 $\text{row}[i]+\text{col}[j]$。遍历矩阵,统计奇数的个数。 +操作结束后,可以算出 $(i, j)$ 位置的计数为 $\textit{row}[i]+\textit{col}[j]$。遍历矩阵,统计奇数的个数。 -时间复杂度 $O(k + m \times n)$,空间复杂度 $O(m + n)$。其中 $k$ 为 $\text{indices}$ 的长度。 +时间复杂度 $O(k + m \times n)$,空间复杂度 $O(m + n)$。其中 $k$ 为 $\textit{indices}$ 的长度。 @@ -287,11 +287,11 @@ func oddCells(m int, n int, indices [][]int) int { ### 方法三:数学优化 -我们注意到,只有当 $\text{row}[i]$ 和 $\text{col}[j]$ 中恰好为“一奇一偶”时,矩阵 $(i, j)$ 位置的数才会是奇数。 +我们注意到,只有当 $\textit{row}[i]$ 和 $\textit{col}[j]$ 中恰好为“一奇一偶”时,矩阵 $(i, j)$ 位置的数才会是奇数。 -我们统计 $\text{row}$ 中的奇数个数,记为 $\text{cnt1}$;而 $\text{col}$ 中的奇数个数,记为 $\text{cnt2}$。那么最终得到的奇数个数为 $\text{cnt1} \times (n - \text{cnt2}) + \text{cnt2} \times (m - \text{cnt1})$。 +我们统计 $\textit{row}$ 中的奇数个数,记为 $\textit{cnt1}$;而 $\textit{col}$ 中的奇数个数,记为 $\textit{cnt2}$。那么最终得到的奇数个数为 $\textit{cnt1} \times (n - \textit{cnt2}) + \textit{cnt2} \times (m - \textit{cnt1})$。 -时间复杂度 $O(k + m + n)$,空间复杂度 $O(m + n)$。其中 $k$ 为 $\text{indices}$ 的长度。 +时间复杂度 $O(k + m + n)$,空间复杂度 $O(m + n)$。其中 $k$ 为 $\textit{indices}$ 的长度。 diff --git a/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README_EN.md b/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README_EN.md index 0f77e493498a..af5b2216ebf5 100644 --- a/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README_EN.md +++ b/solution/1200-1299/1252.Cells with Odd Values in a Matrix/README_EN.md @@ -71,11 +71,11 @@ The final matrix is [[1,3,1],[1,3,1]], which contains 6 odd numbers. ### Solution 1: Simulation -We create a matrix $g$ to store the result of operations. For each pair $(r_i, c_i)$ in $\text{indices}$, we add $1$ to all numbers in the $r_i$-th row of the matrix and add $1$ to all elements in the $c_i$-th column. +We create a matrix $g$ to store the result of operations. For each pair $(r_i, c_i)$ in $\textit{indices}$, we add $1$ to all numbers in the $r_i$-th row of the matrix and add $1$ to all elements in the $c_i$-th column. After the simulation ends, we traverse the matrix and count the number of odd numbers. -The time complexity is $O(k \times (m + n) + m \times n)$, and the space complexity is $O(m \times n)$. Here, $k$ is the length of $\text{indices}$. +The time complexity is $O(k \times (m + n) + m \times n)$, and the space complexity is $O(m \times n)$. Here, $k$ is the length of $\textit{indices}$. @@ -181,11 +181,11 @@ func oddCells(m int, n int, indices [][]int) int { ### Solution 2: Space Optimization -We can use a row array $\text{row}$ and a column array $\text{col}$ to record the number of times each row and column is incremented. For each pair $(r_i, c_i)$ in $\text{indices}$, we add $1$ to $\text{row}[r_i]$ and $\text{col}[c_i]$ respectively. +We can use a row array $\textit{row}$ and a column array $\textit{col}$ to record the number of times each row and column is incremented. For each pair $(r_i, c_i)$ in $\textit{indices}$, we add $1$ to $\textit{row}[r_i]$ and $\textit{col}[c_i]$ respectively. -After the operations are completed, the count at position $(i, j)$ can be calculated as $\text{row}[i] + \text{col}[j]$. We traverse the matrix and count the number of odd numbers. +After the operations are completed, the count at position $(i, j)$ can be calculated as $\textit{row}[i] + \textit{col}[j]$. We traverse the matrix and count the number of odd numbers. -The time complexity is $O(k + m \times n)$, and the space complexity is $O(m + n)$. Here, $k$ is the length of $\text{indices}$. +The time complexity is $O(k + m \times n)$, and the space complexity is $O(m + n)$. Here, $k$ is the length of $\textit{indices}$. @@ -278,11 +278,11 @@ func oddCells(m int, n int, indices [][]int) int { ### Solution 3: Mathematical Optimization -We notice that a number at position $(i, j)$ in the matrix will be odd only when exactly one of $\text{row}[i]$ and $\text{col}[j]$ is odd and the other is even. +We notice that a number at position $(i, j)$ in the matrix will be odd only when exactly one of $\textit{row}[i]$ and $\textit{col}[j]$ is odd and the other is even. -We count the number of odd numbers in $\text{row}$, denoted as $\text{cnt1}$, and the number of odd numbers in $\text{col}$, denoted as $\text{cnt2}$. Therefore, the final count of odd numbers is $\text{cnt1} \times (n - \text{cnt2}) + \text{cnt2} \times (m - \text{cnt1})$. +We count the number of odd numbers in $\textit{row}$, denoted as $\textit{cnt1}$, and the number of odd numbers in $\textit{col}$, denoted as $\textit{cnt2}$. Therefore, the final count of odd numbers is $\textit{cnt1} \times (n - \textit{cnt2}) + \textit{cnt2} \times (m - \textit{cnt1})$. -The time complexity is $O(k + m + n)$, and the space complexity is $O(m + n)$. Here, $k$ is the length of $\text{indices}$. +The time complexity is $O(k + m + n)$, and the space complexity is $O(m + n)$. Here, $k$ is the length of $\textit{indices}$. diff --git a/solution/1200-1299/1296.Divide Array in Sets of K Consecutive Numbers/README.md b/solution/1200-1299/1296.Divide Array in Sets of K Consecutive Numbers/README.md index 5fc673bb188c..07db0477d977 100644 --- a/solution/1200-1299/1296.Divide Array in Sets of K Consecutive Numbers/README.md +++ b/solution/1200-1299/1296.Divide Array in Sets of K Consecutive Numbers/README.md @@ -42,13 +42,6 @@ tags: 解释:数组可以分成 [1,2,3] , [2,3,4] , [3,4,5] 和 [9,10,11]。
    -

    示例 3:

    - -
    -输入:nums = [3,3,2,2,1,1], k = 3
    -输出:true
    -
    -

    示例 4:

    diff --git a/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README.md b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README.md
    index 16dcf92e41a5..c7ab76713fea 100644
    --- a/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README.md	
    +++ b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README.md	
    @@ -86,19 +86,312 @@ tags:
     #### Python3
     
     ```python
    -
    +class Solution:
    +    def isAnyMapping(
    +        self, words, row, col, bal, letToDig, digToLet, totalRows, totalCols
    +    ):
    +        # If traversed all columns.
    +        if col == totalCols:
    +            return bal == 0
    +
    +        # At the end of a particular column.
    +        if row == totalRows:
    +            return bal % 10 == 0 and self.isAnyMapping(
    +                words, 0, col + 1, bal // 10, letToDig, digToLet, totalRows, totalCols
    +            )
    +
    +        w = words[row]
    +
    +        # If the current string 'w' has no character in the ('col')th index.
    +        if col >= len(w):
    +            return self.isAnyMapping(
    +                words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols
    +            )
    +
    +        # Take the current character in the variable letter.
    +        letter = w[len(w) - 1 - col]
    +
    +        # Create a variable 'sign' to check whether we have to add it or subtract it.
    +        if row < totalRows - 1:
    +            sign = 1
    +        else:
    +            sign = -1
    +
    +        # If we have a prior valid mapping, then use that mapping.
    +        # The second condition is for the leading zeros.
    +        if letter in letToDig and (
    +            letToDig[letter] != 0
    +            or (letToDig[letter] == 0 and len(w) == 1)
    +            or col != len(w) - 1
    +        ):
    +
    +            return self.isAnyMapping(
    +                words,
    +                row + 1,
    +                col,
    +                bal + sign * letToDig[letter],
    +                letToDig,
    +                digToLet,
    +                totalRows,
    +                totalCols,
    +            )
    +
    +        # Choose a new mapping.
    +        else:
    +            for i in range(10):
    +                # If 'i'th mapping is valid then select it.
    +                if digToLet[i] == "-" and (
    +                    i != 0 or (i == 0 and len(w) == 1) or col != len(w) - 1
    +                ):
    +                    digToLet[i] = letter
    +                    letToDig[letter] = i
    +
    +                    # Call the function again with the new mapping.
    +                    if self.isAnyMapping(
    +                        words,
    +                        row + 1,
    +                        col,
    +                        bal + sign * letToDig[letter],
    +                        letToDig,
    +                        digToLet,
    +                        totalRows,
    +                        totalCols,
    +                    ):
    +                        return True
    +
    +                    # Unselect the mapping.
    +                    digToLet[i] = "-"
    +                    if letter in letToDig:
    +                        del letToDig[letter]
    +
    +        # If nothing is correct then just return false.
    +        return False
    +
    +    def isSolvable(self, words, result):
    +        # Add the string 'result' in the list 'words'.
    +        words.append(result)
    +
    +        # Initialize 'totalRows' with the size of the list.
    +        totalRows = len(words)
    +
    +        # Find the longest string in the list and set 'totalCols' with the size of that string.
    +        totalCols = max(len(word) for word in words)
    +
    +        # Create a HashMap for the letter to digit mapping.
    +        letToDig = {}
    +
    +        # Create a list for the digit to letter mapping.
    +        digToLet = ["-"] * 10
    +
    +        return self.isAnyMapping(
    +            words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols
    +        )
     ```
     
     #### Java
     
     ```java
    -
    +class Solution {
    +    private boolean isAnyMapping(List words, int row, int col, int bal,
    +        HashMap letToDig, char[] digToLet, int totalRows, int totalCols) {
    +        // If traversed all columns.
    +        if (col == totalCols) {
    +            return bal == 0;
    +        }
    +
    +        // At the end of a particular column.
    +        if (row == totalRows) {
    +            return (bal % 10 == 0
    +                && isAnyMapping(
    +                    words, 0, col + 1, bal / 10, letToDig, digToLet, totalRows, totalCols));
    +        }
    +
    +        String w = words.get(row);
    +
    +        // If the current string 'w' has no character in the ('col')th index.
    +        if (col >= w.length()) {
    +            return isAnyMapping(words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols);
    +        }
    +
    +        // Take the current character in the variable letter.
    +        char letter = w.charAt(w.length() - 1 - col);
    +
    +        // Create a variable 'sign' to check whether we have to add it or subtract it.
    +        int sign = (row < totalRows - 1) ? 1 : -1;
    +
    +        // If we have a prior valid mapping, then use that mapping.
    +        // The second condition is for the leading zeros.
    +        if (letToDig.containsKey(letter)
    +            && (letToDig.get(letter) != 0 || (letToDig.get(letter) == 0 && w.length() == 1)
    +                || col != w.length() - 1)) {
    +
    +            return isAnyMapping(words, row + 1, col, bal + sign * letToDig.get(letter), letToDig,
    +                digToLet, totalRows, totalCols);
    +
    +        } else {
    +            // Choose a new mapping.
    +            for (int i = 0; i < 10; i++) {
    +                // If 'i'th mapping is valid then select it.
    +                if (digToLet[i] == '-'
    +                    && (i != 0 || (i == 0 && w.length() == 1) || col != w.length() - 1)) {
    +                    digToLet[i] = letter;
    +                    letToDig.put(letter, i);
    +
    +                    // Call the function again with the new mapping.
    +                    if (isAnyMapping(words, row + 1, col, bal + sign * letToDig.get(letter),
    +                            letToDig, digToLet, totalRows, totalCols)) {
    +                        return true;
    +                    }
    +
    +                    // Unselect the mapping.
    +                    digToLet[i] = '-';
    +                    letToDig.remove(letter);
    +                }
    +            }
    +        }
    +
    +        // If nothing is correct then just return false.
    +        return false;
    +    }
    +
    +    public boolean isSolvable(String[] wordsArr, String result) {
    +        // Add the string 'result' in the list 'words'.
    +        List words = new ArrayList<>();
    +        for (String word : wordsArr) {
    +            words.add(word);
    +        }
    +        words.add(result);
    +
    +        int totalRows = words.size();
    +
    +        // Find the longest string in the list and set 'totalCols' with the size of that string.
    +        int totalCols = 0;
    +        for (String word : words) {
    +            if (totalCols < word.length()) {
    +                totalCols = word.length();
    +            }
    +        }
    +
    +        // Create a HashMap for the letter to digit mapping.
    +        HashMap letToDig = new HashMap<>();
    +
    +        // Create a char array for the digit to letter mapping.
    +        char[] digToLet = new char[10];
    +        for (int i = 0; i < 10; i++) {
    +            digToLet[i] = '-';
    +        }
    +
    +        return isAnyMapping(words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols);
    +    }
    +}
     ```
     
     #### C++
     
     ```cpp
    -
    +class Solution {
    +public:
    +    bool isAnyMapping(vector& words, int row, int col, int bal, unordered_map& letToDig,
    +        vector& digToLet, int totalRows, int totalCols) {
    +        // If traversed all columns.
    +        if (col == totalCols) {
    +            return bal == 0;
    +        }
    +
    +        // At the end of a particular column.
    +        if (row == totalRows) {
    +            return (bal % 10 == 0 && isAnyMapping(words, 0, col + 1, bal / 10, letToDig, digToLet, totalRows, totalCols));
    +        }
    +
    +        string w = words[row];
    +
    +        // If the current string 'W' has no character in the ('COL')th index.
    +        if (col >= w.length()) {
    +            return isAnyMapping(words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols);
    +        }
    +
    +        // Take the current character in the variable letter.
    +        char letter = w[w.length() - 1 - col];
    +
    +        // Create a variable 'SIGN' to check whether we have to add it or subtract it.
    +        int sign;
    +
    +        if (row < totalRows - 1) {
    +            sign = 1;
    +        } else {
    +            sign = -1;
    +        }
    +
    +        /*
    +            If we have a prior valid mapping, then use that mapping.
    +            The second condition is for the leading zeros.
    +        */
    +        if (letToDig.count(letter) && (letToDig[letter] != 0 || (letToDig[letter] == 0 && w.length() == 1) || col != w.length() - 1)) {
    +
    +            return isAnyMapping(words, row + 1, col, bal + sign * letToDig[letter],
    +                letToDig, digToLet, totalRows, totalCols);
    +
    +        }
    +        // Choose a new mapping.
    +        else {
    +            for (int i = 0; i < 10; i++) {
    +
    +                // If 'i'th mapping is valid then select it.
    +                if (digToLet[i] == '-' && (i != 0 || (i == 0 && w.length() == 1) || col != w.length() - 1)) {
    +                    digToLet[i] = letter;
    +                    letToDig[letter] = i;
    +
    +                    // Call the function again with the new mapping.
    +                    bool x = isAnyMapping(words, row + 1, col, bal + sign * letToDig[letter],
    +                        letToDig, digToLet, totalRows, totalCols);
    +
    +                    if (x == true) {
    +                        return true;
    +                    }
    +
    +                    // Unselect the mapping.
    +                    digToLet[i] = '-';
    +                    if (letToDig.find(letter) != letToDig.end()) {
    +                        letToDig.erase(letter);
    +                    }
    +                }
    +            }
    +        }
    +
    +        // If nothing is correct then just return false.
    +        return false;
    +    }
    +
    +    bool isSolvable(vector& words, string result) {
    +        // Add the string 'RESULT' in the vector 'WORDS'.
    +        words.push_back(result);
    +
    +        int totalRows;
    +        int totalCols;
    +
    +        // Initialize 'TOTALROWS' with the size of the vector.
    +        totalRows = words.size();
    +
    +        // Find the longest string in the vector and set 'TOTALCOLS' with the size of that string.
    +        totalCols = 0;
    +
    +        for (int i = 0; i < words.size(); i++) {
    +
    +            // If the current string is the longest then update 'TOTALCOLS' with its length.
    +            if (totalCols < words[i].size()) {
    +                totalCols = words[i].size();
    +            }
    +        }
    +
    +        // Create a HashMap for the letter to digit mapping.
    +        unordered_map letToDig;
    +
    +        // Create a vector for the digit to letter mapping.
    +        vector digToLet(10, '-');
    +
    +        return isAnyMapping(words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols);
    +    }
    +};
     ```
     
     #### Go
    diff --git a/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README_EN.md b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README_EN.md
    index 5d0c3a32f90a..36ffb1fadc5c 100644
    --- a/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README_EN.md	
    +++ b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/README_EN.md	
    @@ -83,19 +83,312 @@ Note that two different characters cannot map to the same digit.
     #### Python3
     
     ```python
    -
    +class Solution:
    +    def isAnyMapping(
    +        self, words, row, col, bal, letToDig, digToLet, totalRows, totalCols
    +    ):
    +        # If traversed all columns.
    +        if col == totalCols:
    +            return bal == 0
    +
    +        # At the end of a particular column.
    +        if row == totalRows:
    +            return bal % 10 == 0 and self.isAnyMapping(
    +                words, 0, col + 1, bal // 10, letToDig, digToLet, totalRows, totalCols
    +            )
    +
    +        w = words[row]
    +
    +        # If the current string 'w' has no character in the ('col')th index.
    +        if col >= len(w):
    +            return self.isAnyMapping(
    +                words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols
    +            )
    +
    +        # Take the current character in the variable letter.
    +        letter = w[len(w) - 1 - col]
    +
    +        # Create a variable 'sign' to check whether we have to add it or subtract it.
    +        if row < totalRows - 1:
    +            sign = 1
    +        else:
    +            sign = -1
    +
    +        # If we have a prior valid mapping, then use that mapping.
    +        # The second condition is for the leading zeros.
    +        if letter in letToDig and (
    +            letToDig[letter] != 0
    +            or (letToDig[letter] == 0 and len(w) == 1)
    +            or col != len(w) - 1
    +        ):
    +
    +            return self.isAnyMapping(
    +                words,
    +                row + 1,
    +                col,
    +                bal + sign * letToDig[letter],
    +                letToDig,
    +                digToLet,
    +                totalRows,
    +                totalCols,
    +            )
    +
    +        # Choose a new mapping.
    +        else:
    +            for i in range(10):
    +                # If 'i'th mapping is valid then select it.
    +                if digToLet[i] == "-" and (
    +                    i != 0 or (i == 0 and len(w) == 1) or col != len(w) - 1
    +                ):
    +                    digToLet[i] = letter
    +                    letToDig[letter] = i
    +
    +                    # Call the function again with the new mapping.
    +                    if self.isAnyMapping(
    +                        words,
    +                        row + 1,
    +                        col,
    +                        bal + sign * letToDig[letter],
    +                        letToDig,
    +                        digToLet,
    +                        totalRows,
    +                        totalCols,
    +                    ):
    +                        return True
    +
    +                    # Unselect the mapping.
    +                    digToLet[i] = "-"
    +                    if letter in letToDig:
    +                        del letToDig[letter]
    +
    +        # If nothing is correct then just return false.
    +        return False
    +
    +    def isSolvable(self, words, result):
    +        # Add the string 'result' in the list 'words'.
    +        words.append(result)
    +
    +        # Initialize 'totalRows' with the size of the list.
    +        totalRows = len(words)
    +
    +        # Find the longest string in the list and set 'totalCols' with the size of that string.
    +        totalCols = max(len(word) for word in words)
    +
    +        # Create a HashMap for the letter to digit mapping.
    +        letToDig = {}
    +
    +        # Create a list for the digit to letter mapping.
    +        digToLet = ["-"] * 10
    +
    +        return self.isAnyMapping(
    +            words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols
    +        )
     ```
     
     #### Java
     
     ```java
    -
    +class Solution {
    +    private boolean isAnyMapping(List words, int row, int col, int bal,
    +        HashMap letToDig, char[] digToLet, int totalRows, int totalCols) {
    +        // If traversed all columns.
    +        if (col == totalCols) {
    +            return bal == 0;
    +        }
    +
    +        // At the end of a particular column.
    +        if (row == totalRows) {
    +            return (bal % 10 == 0
    +                && isAnyMapping(
    +                    words, 0, col + 1, bal / 10, letToDig, digToLet, totalRows, totalCols));
    +        }
    +
    +        String w = words.get(row);
    +
    +        // If the current string 'w' has no character in the ('col')th index.
    +        if (col >= w.length()) {
    +            return isAnyMapping(words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols);
    +        }
    +
    +        // Take the current character in the variable letter.
    +        char letter = w.charAt(w.length() - 1 - col);
    +
    +        // Create a variable 'sign' to check whether we have to add it or subtract it.
    +        int sign = (row < totalRows - 1) ? 1 : -1;
    +
    +        // If we have a prior valid mapping, then use that mapping.
    +        // The second condition is for the leading zeros.
    +        if (letToDig.containsKey(letter)
    +            && (letToDig.get(letter) != 0 || (letToDig.get(letter) == 0 && w.length() == 1)
    +                || col != w.length() - 1)) {
    +
    +            return isAnyMapping(words, row + 1, col, bal + sign * letToDig.get(letter), letToDig,
    +                digToLet, totalRows, totalCols);
    +
    +        } else {
    +            // Choose a new mapping.
    +            for (int i = 0; i < 10; i++) {
    +                // If 'i'th mapping is valid then select it.
    +                if (digToLet[i] == '-'
    +                    && (i != 0 || (i == 0 && w.length() == 1) || col != w.length() - 1)) {
    +                    digToLet[i] = letter;
    +                    letToDig.put(letter, i);
    +
    +                    // Call the function again with the new mapping.
    +                    if (isAnyMapping(words, row + 1, col, bal + sign * letToDig.get(letter),
    +                            letToDig, digToLet, totalRows, totalCols)) {
    +                        return true;
    +                    }
    +
    +                    // Unselect the mapping.
    +                    digToLet[i] = '-';
    +                    letToDig.remove(letter);
    +                }
    +            }
    +        }
    +
    +        // If nothing is correct then just return false.
    +        return false;
    +    }
    +
    +    public boolean isSolvable(String[] wordsArr, String result) {
    +        // Add the string 'result' in the list 'words'.
    +        List words = new ArrayList<>();
    +        for (String word : wordsArr) {
    +            words.add(word);
    +        }
    +        words.add(result);
    +
    +        int totalRows = words.size();
    +
    +        // Find the longest string in the list and set 'totalCols' with the size of that string.
    +        int totalCols = 0;
    +        for (String word : words) {
    +            if (totalCols < word.length()) {
    +                totalCols = word.length();
    +            }
    +        }
    +
    +        // Create a HashMap for the letter to digit mapping.
    +        HashMap letToDig = new HashMap<>();
    +
    +        // Create a char array for the digit to letter mapping.
    +        char[] digToLet = new char[10];
    +        for (int i = 0; i < 10; i++) {
    +            digToLet[i] = '-';
    +        }
    +
    +        return isAnyMapping(words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols);
    +    }
    +}
     ```
     
     #### C++
     
     ```cpp
    -
    +class Solution {
    +public:
    +    bool isAnyMapping(vector& words, int row, int col, int bal, unordered_map& letToDig,
    +        vector& digToLet, int totalRows, int totalCols) {
    +        // If traversed all columns.
    +        if (col == totalCols) {
    +            return bal == 0;
    +        }
    +
    +        // At the end of a particular column.
    +        if (row == totalRows) {
    +            return (bal % 10 == 0 && isAnyMapping(words, 0, col + 1, bal / 10, letToDig, digToLet, totalRows, totalCols));
    +        }
    +
    +        string w = words[row];
    +
    +        // If the current string 'W' has no character in the ('COL')th index.
    +        if (col >= w.length()) {
    +            return isAnyMapping(words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols);
    +        }
    +
    +        // Take the current character in the variable letter.
    +        char letter = w[w.length() - 1 - col];
    +
    +        // Create a variable 'SIGN' to check whether we have to add it or subtract it.
    +        int sign;
    +
    +        if (row < totalRows - 1) {
    +            sign = 1;
    +        } else {
    +            sign = -1;
    +        }
    +
    +        /*
    +            If we have a prior valid mapping, then use that mapping.
    +            The second condition is for the leading zeros.
    +        */
    +        if (letToDig.count(letter) && (letToDig[letter] != 0 || (letToDig[letter] == 0 && w.length() == 1) || col != w.length() - 1)) {
    +
    +            return isAnyMapping(words, row + 1, col, bal + sign * letToDig[letter],
    +                letToDig, digToLet, totalRows, totalCols);
    +
    +        }
    +        // Choose a new mapping.
    +        else {
    +            for (int i = 0; i < 10; i++) {
    +
    +                // If 'i'th mapping is valid then select it.
    +                if (digToLet[i] == '-' && (i != 0 || (i == 0 && w.length() == 1) || col != w.length() - 1)) {
    +                    digToLet[i] = letter;
    +                    letToDig[letter] = i;
    +
    +                    // Call the function again with the new mapping.
    +                    bool x = isAnyMapping(words, row + 1, col, bal + sign * letToDig[letter],
    +                        letToDig, digToLet, totalRows, totalCols);
    +
    +                    if (x == true) {
    +                        return true;
    +                    }
    +
    +                    // Unselect the mapping.
    +                    digToLet[i] = '-';
    +                    if (letToDig.find(letter) != letToDig.end()) {
    +                        letToDig.erase(letter);
    +                    }
    +                }
    +            }
    +        }
    +
    +        // If nothing is correct then just return false.
    +        return false;
    +    }
    +
    +    bool isSolvable(vector& words, string result) {
    +        // Add the string 'RESULT' in the vector 'WORDS'.
    +        words.push_back(result);
    +
    +        int totalRows;
    +        int totalCols;
    +
    +        // Initialize 'TOTALROWS' with the size of the vector.
    +        totalRows = words.size();
    +
    +        // Find the longest string in the vector and set 'TOTALCOLS' with the size of that string.
    +        totalCols = 0;
    +
    +        for (int i = 0; i < words.size(); i++) {
    +
    +            // If the current string is the longest then update 'TOTALCOLS' with its length.
    +            if (totalCols < words[i].size()) {
    +                totalCols = words[i].size();
    +            }
    +        }
    +
    +        // Create a HashMap for the letter to digit mapping.
    +        unordered_map letToDig;
    +
    +        // Create a vector for the digit to letter mapping.
    +        vector digToLet(10, '-');
    +
    +        return isAnyMapping(words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols);
    +    }
    +};
     ```
     
     #### Go
    diff --git a/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.cpp b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.cpp
    new file mode 100644
    index 000000000000..f29cee665a08
    --- /dev/null
    +++ b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.cpp	
    @@ -0,0 +1,103 @@
    +class Solution {
    +public:
    +    bool isAnyMapping(vector& words, int row, int col, int bal, unordered_map& letToDig,
    +        vector& digToLet, int totalRows, int totalCols) {
    +        // If traversed all columns.
    +        if (col == totalCols) {
    +            return bal == 0;
    +        }
    +
    +        // At the end of a particular column.
    +        if (row == totalRows) {
    +            return (bal % 10 == 0 && isAnyMapping(words, 0, col + 1, bal / 10, letToDig, digToLet, totalRows, totalCols));
    +        }
    +
    +        string w = words[row];
    +
    +        // If the current string 'W' has no character in the ('COL')th index.
    +        if (col >= w.length()) {
    +            return isAnyMapping(words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols);
    +        }
    +
    +        // Take the current character in the variable letter.
    +        char letter = w[w.length() - 1 - col];
    +
    +        // Create a variable 'SIGN' to check whether we have to add it or subtract it.
    +        int sign;
    +
    +        if (row < totalRows - 1) {
    +            sign = 1;
    +        } else {
    +            sign = -1;
    +        }
    +
    +        /*
    +            If we have a prior valid mapping, then use that mapping.
    +            The second condition is for the leading zeros.
    +        */
    +        if (letToDig.count(letter) && (letToDig[letter] != 0 || (letToDig[letter] == 0 && w.length() == 1) || col != w.length() - 1)) {
    +
    +            return isAnyMapping(words, row + 1, col, bal + sign * letToDig[letter],
    +                letToDig, digToLet, totalRows, totalCols);
    +
    +        }
    +        // Choose a new mapping.
    +        else {
    +            for (int i = 0; i < 10; i++) {
    +
    +                // If 'i'th mapping is valid then select it.
    +                if (digToLet[i] == '-' && (i != 0 || (i == 0 && w.length() == 1) || col != w.length() - 1)) {
    +                    digToLet[i] = letter;
    +                    letToDig[letter] = i;
    +
    +                    // Call the function again with the new mapping.
    +                    bool x = isAnyMapping(words, row + 1, col, bal + sign * letToDig[letter],
    +                        letToDig, digToLet, totalRows, totalCols);
    +
    +                    if (x == true) {
    +                        return true;
    +                    }
    +
    +                    // Unselect the mapping.
    +                    digToLet[i] = '-';
    +                    if (letToDig.find(letter) != letToDig.end()) {
    +                        letToDig.erase(letter);
    +                    }
    +                }
    +            }
    +        }
    +
    +        // If nothing is correct then just return false.
    +        return false;
    +    }
    +
    +    bool isSolvable(vector& words, string result) {
    +        // Add the string 'RESULT' in the vector 'WORDS'.
    +        words.push_back(result);
    +
    +        int totalRows;
    +        int totalCols;
    +
    +        // Initialize 'TOTALROWS' with the size of the vector.
    +        totalRows = words.size();
    +
    +        // Find the longest string in the vector and set 'TOTALCOLS' with the size of that string.
    +        totalCols = 0;
    +
    +        for (int i = 0; i < words.size(); i++) {
    +
    +            // If the current string is the longest then update 'TOTALCOLS' with its length.
    +            if (totalCols < words[i].size()) {
    +                totalCols = words[i].size();
    +            }
    +        }
    +
    +        // Create a HashMap for the letter to digit mapping.
    +        unordered_map letToDig;
    +
    +        // Create a vector for the digit to letter mapping.
    +        vector digToLet(10, '-');
    +
    +        return isAnyMapping(words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols);
    +    }
    +};
    diff --git a/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.java b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.java
    new file mode 100644
    index 000000000000..035c8f1424ef
    --- /dev/null
    +++ b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.java	
    @@ -0,0 +1,93 @@
    +class Solution {
    +    private boolean isAnyMapping(List words, int row, int col, int bal,
    +        HashMap letToDig, char[] digToLet, int totalRows, int totalCols) {
    +        // If traversed all columns.
    +        if (col == totalCols) {
    +            return bal == 0;
    +        }
    +
    +        // At the end of a particular column.
    +        if (row == totalRows) {
    +            return (bal % 10 == 0
    +                && isAnyMapping(
    +                    words, 0, col + 1, bal / 10, letToDig, digToLet, totalRows, totalCols));
    +        }
    +
    +        String w = words.get(row);
    +
    +        // If the current string 'w' has no character in the ('col')th index.
    +        if (col >= w.length()) {
    +            return isAnyMapping(words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols);
    +        }
    +
    +        // Take the current character in the variable letter.
    +        char letter = w.charAt(w.length() - 1 - col);
    +
    +        // Create a variable 'sign' to check whether we have to add it or subtract it.
    +        int sign = (row < totalRows - 1) ? 1 : -1;
    +
    +        // If we have a prior valid mapping, then use that mapping.
    +        // The second condition is for the leading zeros.
    +        if (letToDig.containsKey(letter)
    +            && (letToDig.get(letter) != 0 || (letToDig.get(letter) == 0 && w.length() == 1)
    +                || col != w.length() - 1)) {
    +
    +            return isAnyMapping(words, row + 1, col, bal + sign * letToDig.get(letter), letToDig,
    +                digToLet, totalRows, totalCols);
    +
    +        } else {
    +            // Choose a new mapping.
    +            for (int i = 0; i < 10; i++) {
    +                // If 'i'th mapping is valid then select it.
    +                if (digToLet[i] == '-'
    +                    && (i != 0 || (i == 0 && w.length() == 1) || col != w.length() - 1)) {
    +                    digToLet[i] = letter;
    +                    letToDig.put(letter, i);
    +
    +                    // Call the function again with the new mapping.
    +                    if (isAnyMapping(words, row + 1, col, bal + sign * letToDig.get(letter),
    +                            letToDig, digToLet, totalRows, totalCols)) {
    +                        return true;
    +                    }
    +
    +                    // Unselect the mapping.
    +                    digToLet[i] = '-';
    +                    letToDig.remove(letter);
    +                }
    +            }
    +        }
    +
    +        // If nothing is correct then just return false.
    +        return false;
    +    }
    +
    +    public boolean isSolvable(String[] wordsArr, String result) {
    +        // Add the string 'result' in the list 'words'.
    +        List words = new ArrayList<>();
    +        for (String word : wordsArr) {
    +            words.add(word);
    +        }
    +        words.add(result);
    +
    +        int totalRows = words.size();
    +
    +        // Find the longest string in the list and set 'totalCols' with the size of that string.
    +        int totalCols = 0;
    +        for (String word : words) {
    +            if (totalCols < word.length()) {
    +                totalCols = word.length();
    +            }
    +        }
    +
    +        // Create a HashMap for the letter to digit mapping.
    +        HashMap letToDig = new HashMap<>();
    +
    +        // Create a char array for the digit to letter mapping.
    +        char[] digToLet = new char[10];
    +        for (int i = 0; i < 10; i++) {
    +            digToLet[i] = '-';
    +        }
    +
    +        return isAnyMapping(words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols);
    +    }
    +}
    diff --git a/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.py b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.py
    new file mode 100644
    index 000000000000..7a19318dc8d3
    --- /dev/null
    +++ b/solution/1300-1399/1307.Verbal Arithmetic Puzzle/Solution.py	
    @@ -0,0 +1,100 @@
    +class Solution:
    +    def isAnyMapping(
    +        self, words, row, col, bal, letToDig, digToLet, totalRows, totalCols
    +    ):
    +        # If traversed all columns.
    +        if col == totalCols:
    +            return bal == 0
    +
    +        # At the end of a particular column.
    +        if row == totalRows:
    +            return bal % 10 == 0 and self.isAnyMapping(
    +                words, 0, col + 1, bal // 10, letToDig, digToLet, totalRows, totalCols
    +            )
    +
    +        w = words[row]
    +
    +        # If the current string 'w' has no character in the ('col')th index.
    +        if col >= len(w):
    +            return self.isAnyMapping(
    +                words, row + 1, col, bal, letToDig, digToLet, totalRows, totalCols
    +            )
    +
    +        # Take the current character in the variable letter.
    +        letter = w[len(w) - 1 - col]
    +
    +        # Create a variable 'sign' to check whether we have to add it or subtract it.
    +        if row < totalRows - 1:
    +            sign = 1
    +        else:
    +            sign = -1
    +
    +        # If we have a prior valid mapping, then use that mapping.
    +        # The second condition is for the leading zeros.
    +        if letter in letToDig and (
    +            letToDig[letter] != 0
    +            or (letToDig[letter] == 0 and len(w) == 1)
    +            or col != len(w) - 1
    +        ):
    +
    +            return self.isAnyMapping(
    +                words,
    +                row + 1,
    +                col,
    +                bal + sign * letToDig[letter],
    +                letToDig,
    +                digToLet,
    +                totalRows,
    +                totalCols,
    +            )
    +
    +        # Choose a new mapping.
    +        else:
    +            for i in range(10):
    +                # If 'i'th mapping is valid then select it.
    +                if digToLet[i] == "-" and (
    +                    i != 0 or (i == 0 and len(w) == 1) or col != len(w) - 1
    +                ):
    +                    digToLet[i] = letter
    +                    letToDig[letter] = i
    +
    +                    # Call the function again with the new mapping.
    +                    if self.isAnyMapping(
    +                        words,
    +                        row + 1,
    +                        col,
    +                        bal + sign * letToDig[letter],
    +                        letToDig,
    +                        digToLet,
    +                        totalRows,
    +                        totalCols,
    +                    ):
    +                        return True
    +
    +                    # Unselect the mapping.
    +                    digToLet[i] = "-"
    +                    if letter in letToDig:
    +                        del letToDig[letter]
    +
    +        # If nothing is correct then just return false.
    +        return False
    +
    +    def isSolvable(self, words, result):
    +        # Add the string 'result' in the list 'words'.
    +        words.append(result)
    +
    +        # Initialize 'totalRows' with the size of the list.
    +        totalRows = len(words)
    +
    +        # Find the longest string in the list and set 'totalCols' with the size of that string.
    +        totalCols = max(len(word) for word in words)
    +
    +        # Create a HashMap for the letter to digit mapping.
    +        letToDig = {}
    +
    +        # Create a list for the digit to letter mapping.
    +        digToLet = ["-"] * 10
    +
    +        return self.isAnyMapping(
    +            words, 0, 0, 0, letToDig, digToLet, totalRows, totalCols
    +        )
    diff --git a/solution/1300-1399/1310.XOR Queries of a Subarray/README.md b/solution/1300-1399/1310.XOR Queries of a Subarray/README.md
    index 8a45d8beb143..8add1517a088 100644
    --- a/solution/1300-1399/1310.XOR Queries of a Subarray/README.md	
    +++ b/solution/1300-1399/1310.XOR Queries of a Subarray/README.md	
    @@ -73,18 +73,18 @@ tags:
     
     ### 方法一:前缀异或
     
    -我们可以用一个长度为 $n+1$ 的前缀异或数组 $s$ 来存储数组 $arr$ 的前缀异或结果,其中 $s[i] = s[i-1] \oplus arr[i-1]$,即 $s[i]$ 表示 $arr$ 中下标 $[0,i-1]$ 的元素的异或结果。
    +我们可以用一个长度为 $n+1$ 的前缀异或数组 $s$ 来存储数组 $\textit{arr}$ 的前缀异或结果,其中 $s[i] = s[i-1] \oplus \textit{arr}[i-1]$,即 $s[i]$ 表示 $\textit{arr}$ 的前 $i$ 个元素的异或结果。
     
     那么对于一个查询 $[l,r]$,我们可以得到:
     
     $$
     \begin{aligned}
    -arr[l] \oplus arr[l+1] \oplus \cdots \oplus arr[r] &= (arr[0] \oplus arr[1] \oplus \cdots \oplus arr[l-1]) \oplus (arr[0] \oplus arr[1] \oplus \cdots \oplus arr[r]) \\
    +\textit{arr}[l] \oplus \textit{arr}[l+1] \oplus \cdots \oplus \textit{arr}[r] &= (\textit{arr}[0] \oplus \textit{arr}[1] \oplus \cdots \oplus \textit{arr}[l-1]) \oplus (\textit{arr}[0] \oplus \textit{arr}[1] \oplus \cdots \oplus \textit{arr}[r]) \\
     &= s[l] \oplus s[r+1]
     \end{aligned}
     $$
     
    -时间复杂度 $O(n+m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 $arr$ 和查询数组 $queries$ 的长度。
    +时间复杂度 $O(n+m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 $\textit{arr}$ 的长度和查询数组 $\textit{queries}$ 的长度。
     
     
     
    @@ -162,15 +162,11 @@ func xorQueries(arr []int, queries [][]int) (ans []int) {
     ```ts
     function xorQueries(arr: number[], queries: number[][]): number[] {
         const n = arr.length;
    -    const s: number[] = new Array(n + 1).fill(0);
    +    const s: number[] = Array(n + 1).fill(0);
         for (let i = 0; i < n; ++i) {
             s[i + 1] = s[i] ^ arr[i];
         }
    -    const ans: number[] = [];
    -    for (const [l, r] of queries) {
    -        ans.push(s[r + 1] ^ s[l]);
    -    }
    -    return ans;
    +    return queries.map(([l, r]) => s[r + 1] ^ s[l]);
     }
     ```
     
    @@ -184,15 +180,11 @@ function xorQueries(arr: number[], queries: number[][]): number[] {
      */
     var xorQueries = function (arr, queries) {
         const n = arr.length;
    -    const s = new Array(n + 1).fill(0);
    +    const s = Array(n + 1).fill(0);
         for (let i = 0; i < n; ++i) {
             s[i + 1] = s[i] ^ arr[i];
         }
    -    const ans = [];
    -    for (const [l, r] of queries) {
    -        ans.push(s[r + 1] ^ s[l]);
    -    }
    -    return ans;
    +    return queries.map(([l, r]) => s[r + 1] ^ s[l]);
     };
     ```
     
    diff --git a/solution/1300-1399/1310.XOR Queries of a Subarray/README_EN.md b/solution/1300-1399/1310.XOR Queries of a Subarray/README_EN.md
    index 53b49c510c7e..c43ab5ea6bd1 100644
    --- a/solution/1300-1399/1310.XOR Queries of a Subarray/README_EN.md	
    +++ b/solution/1300-1399/1310.XOR Queries of a Subarray/README_EN.md	
    @@ -68,7 +68,20 @@ The XOR values for queries are:
     
     
     
    -### Solution 1
    +### Solution 1: Prefix XOR
    +
    +We can use a prefix XOR array $s$ of length $n+1$ to store the prefix XOR results of the array $\textit{arr}$, where $s[i] = s[i-1] \oplus \textit{arr}[i-1]$. That is, $s[i]$ represents the XOR result of the first $i$ elements of $\textit{arr}$.
    +
    +For a query $[l, r]$, we can obtain:
    +
    +$$
    +\begin{aligned}
    +\textit{arr}[l] \oplus \textit{arr}[l+1] \oplus \cdots \oplus \textit{arr}[r] &= (\textit{arr}[0] \oplus \textit{arr}[1] \oplus \cdots \oplus \textit{arr}[l-1]) \oplus (\textit{arr}[0] \oplus \textit{arr}[1] \oplus \cdots \oplus \textit{arr}[r]) \\
    +&= s[l] \oplus s[r+1]
    +\end{aligned}
    +$$
    +
    +Time complexity is $O(n+m)$, and space complexity is $O(n)$. Here, $n$ and $m$ are the lengths of the array $\textit{arr}$ and the query array $\textit{queries}$, respectively.
     
     
     
    @@ -146,15 +159,11 @@ func xorQueries(arr []int, queries [][]int) (ans []int) {
     ```ts
     function xorQueries(arr: number[], queries: number[][]): number[] {
         const n = arr.length;
    -    const s: number[] = new Array(n + 1).fill(0);
    +    const s: number[] = Array(n + 1).fill(0);
         for (let i = 0; i < n; ++i) {
             s[i + 1] = s[i] ^ arr[i];
         }
    -    const ans: number[] = [];
    -    for (const [l, r] of queries) {
    -        ans.push(s[r + 1] ^ s[l]);
    -    }
    -    return ans;
    +    return queries.map(([l, r]) => s[r + 1] ^ s[l]);
     }
     ```
     
    @@ -168,15 +177,11 @@ function xorQueries(arr: number[], queries: number[][]): number[] {
      */
     var xorQueries = function (arr, queries) {
         const n = arr.length;
    -    const s = new Array(n + 1).fill(0);
    +    const s = Array(n + 1).fill(0);
         for (let i = 0; i < n; ++i) {
             s[i + 1] = s[i] ^ arr[i];
         }
    -    const ans = [];
    -    for (const [l, r] of queries) {
    -        ans.push(s[r + 1] ^ s[l]);
    -    }
    -    return ans;
    +    return queries.map(([l, r]) => s[r + 1] ^ s[l]);
     };
     ```
     
    diff --git a/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.js b/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.js
    index 4149f6a26f8f..60a74b50d6e8 100644
    --- a/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.js	
    +++ b/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.js	
    @@ -5,13 +5,9 @@
      */
     var xorQueries = function (arr, queries) {
         const n = arr.length;
    -    const s = new Array(n + 1).fill(0);
    +    const s = Array(n + 1).fill(0);
         for (let i = 0; i < n; ++i) {
             s[i + 1] = s[i] ^ arr[i];
         }
    -    const ans = [];
    -    for (const [l, r] of queries) {
    -        ans.push(s[r + 1] ^ s[l]);
    -    }
    -    return ans;
    +    return queries.map(([l, r]) => s[r + 1] ^ s[l]);
     };
    diff --git a/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.ts b/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.ts
    index 84677bc83d7f..6c14df8493dd 100644
    --- a/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.ts	
    +++ b/solution/1300-1399/1310.XOR Queries of a Subarray/Solution.ts	
    @@ -1,12 +1,8 @@
     function xorQueries(arr: number[], queries: number[][]): number[] {
         const n = arr.length;
    -    const s: number[] = new Array(n + 1).fill(0);
    +    const s: number[] = Array(n + 1).fill(0);
         for (let i = 0; i < n; ++i) {
             s[i + 1] = s[i] ^ arr[i];
         }
    -    const ans: number[] = [];
    -    for (const [l, r] of queries) {
    -        ans.push(s[r + 1] ^ s[l]);
    -    }
    -    return ans;
    +    return queries.map(([l, r]) => s[r + 1] ^ s[l]);
     }
    diff --git a/solution/1300-1399/1311.Get Watched Videos by Your Friends/README.md b/solution/1300-1399/1311.Get Watched Videos by Your Friends/README.md
    index 3bc2a6c5382e..bc7fab1994d9 100644
    --- a/solution/1300-1399/1311.Get Watched Videos by Your Friends/README.md	
    +++ b/solution/1300-1399/1311.Get Watched Videos by Your Friends/README.md	
    @@ -79,7 +79,15 @@ C -> 2
     
     
     
    -### 方法一
    +### 方法一:BFS
    +
    +我们可以使用广度优先搜索的方法,从 $\textit{id}$ 出发,找到所有距离为 $\textit{level}$ 的好友,然后统计这些好友观看的视频。
    +
    +具体地,我们可以使用一个队列 $\textit{q}$ 来存储当前层的好友,初始时将 $\textit{id}$ 加入队列 $\textit{q}$ 中,用一个哈希表或者布尔数组 $\textit{vis}$ 来记录已经访问过的好友,然后进行 $\textit{level}$ 次循环,每次循环将队列中的所有好友出队,并将他们的好友加入队列,直到找到所有距禒为 $\textit{level}$ 的好友。
    +
    +然后,我们使用一个哈希表 $\textit{cnt}$ 来统计这些好友观看的视频及其频率,最后将哈希表中的键值对按照频率升序排序,如果频率相同,则按照视频名称升序排序。最后返回排序后的视频名称列表。
    +
    +时间复杂度 $O(n + m + v \times \log v)$,空间复杂度 $O(n + v)$。其中 $n$ 和 $m$ 分别是数组 $\textit{watchedVideos}$ 和 $\textit{friends}$ 的长度,而 $v$ 是所有好友观看的视频数量。
     
     
     
    @@ -94,26 +102,20 @@ class Solution:
             id: int,
             level: int,
         ) -> List[str]:
    -        n = len(friends)
    -        vis = [False] * n
             q = deque([id])
    -        vis[id] = True
    +        vis = {id}
             for _ in range(level):
    -            size = len(q)
    -            for _ in range(size):
    -                u = q.popleft()
    -                for v in friends[u]:
    -                    if not vis[v]:
    -                        q.append(v)
    -                        vis[v] = True
    -        freq = Counter()
    -        for _ in range(len(q)):
    -            u = q.pop()
    -            for w in watchedVideos[u]:
    -                freq[w] += 1
    -        videos = list(freq.items())
    -        videos.sort(key=lambda x: (x[1], x[0]))
    -        return [v[0] for v in videos]
    +            for _ in range(len(q)):
    +                i = q.popleft()
    +                for j in friends[i]:
    +                    if j not in vis:
    +                        vis.add(j)
    +                        q.append(j)
    +        cnt = Counter()
    +        for i in q:
    +            for v in watchedVideos[i]:
    +                cnt[v] += 1
    +        return sorted(cnt.keys(), key=lambda k: (cnt[k], k))
     ```
     
     #### Java
    @@ -122,44 +124,160 @@ class Solution:
     class Solution {
         public List watchedVideosByFriends(
             List> watchedVideos, int[][] friends, int id, int level) {
    +        Deque q = new ArrayDeque<>();
    +        q.offer(id);
             int n = friends.length;
             boolean[] vis = new boolean[n];
    -        Deque q = new LinkedList<>();
    -        q.offerLast(id);
             vis[id] = true;
             while (level-- > 0) {
    -            for (int i = q.size(); i > 0; --i) {
    -                int u = q.pollFirst();
    -                for (int v : friends[u]) {
    -                    if (!vis[v]) {
    -                        q.offerLast(v);
    -                        vis[v] = true;
    +            for (int k = q.size(); k > 0; --k) {
    +                int i = q.poll();
    +                for (int j : friends[i]) {
    +                    if (!vis[j]) {
    +                        vis[j] = true;
    +                        q.offer(j);
                         }
                     }
                 }
             }
    -        Map freq = new HashMap<>();
    -        while (!q.isEmpty()) {
    -            for (String w : watchedVideos.get(q.pollFirst())) {
    -                freq.put(w, freq.getOrDefault(w, 0) + 1);
    +        Map cnt = new HashMap<>();
    +        for (int i : q) {
    +            for (var v : watchedVideos.get(i)) {
    +                cnt.merge(v, 1, Integer::sum);
                 }
             }
    -        List> t = new ArrayList<>(freq.entrySet());
    -        t.sort((a, b) -> {
    -            if (a.getValue() > b.getValue()) {
    -                return 1;
    +        List ans = new ArrayList<>(cnt.keySet());
    +        ans.sort((a, b) -> {
    +            int x = cnt.get(a), y = cnt.get(b);
    +            return x == y ? a.compareTo(b) : Integer.compare(x, y);
    +        });
    +        return ans;
    +    }
    +}
    +```
    +
    +#### C++
    +
    +```cpp
    +class Solution {
    +public:
    +    vector watchedVideosByFriends(vector>& watchedVideos, vector>& friends, int id, int level) {
    +        queue q{{id}};
    +        int n = friends.size();
    +        vector vis(n);
    +        vis[id] = true;
    +        while (level--) {
    +            for (int k = q.size(); k; --k) {
    +                int i = q.front();
    +                q.pop();
    +                for (int j : friends[i]) {
    +                    if (!vis[j]) {
    +                        vis[j] = true;
    +                        q.push(j);
    +                    }
    +                }
                 }
    -            if (a.getValue() < b.getValue()) {
    -                return -1;
    +        }
    +        unordered_map cnt;
    +        while (!q.empty()) {
    +            int i = q.front();
    +            q.pop();
    +            for (const auto& v : watchedVideos[i]) {
    +                cnt[v]++;
                 }
    -            return a.getKey().compareTo(b.getKey());
    -        });
    -        List ans = new ArrayList<>();
    -        for (Map.Entry e : t) {
    -            ans.add(e.getKey());
             }
    +        vector ans;
    +        for (const auto& [key, _] : cnt) {
    +            ans.push_back(key);
    +        }
    +        sort(ans.begin(), ans.end(), [&cnt](const string& a, const string& b) {
    +            return cnt[a] == cnt[b] ? a < b : cnt[a] < cnt[b];
    +        });
             return ans;
         }
    +};
    +```
    +
    +#### Go
    +
    +```go
    +func watchedVideosByFriends(watchedVideos [][]string, friends [][]int, id int, level int) []string {
    +	q := []int{id}
    +	n := len(friends)
    +	vis := make([]bool, n)
    +	vis[id] = true
    +	for level > 0 {
    +		level--
    +		nextQ := []int{}
    +		for _, i := range q {
    +			for _, j := range friends[i] {
    +				if !vis[j] {
    +					vis[j] = true
    +					nextQ = append(nextQ, j)
    +				}
    +			}
    +		}
    +		q = nextQ
    +	}
    +	cnt := make(map[string]int)
    +	for _, i := range q {
    +		for _, v := range watchedVideos[i] {
    +			cnt[v]++
    +		}
    +	}
    +	ans := []string{}
    +	for key := range cnt {
    +		ans = append(ans, key)
    +	}
    +	sort.Slice(ans, func(i, j int) bool {
    +		if cnt[ans[i]] == cnt[ans[j]] {
    +			return ans[i] < ans[j]
    +		}
    +		return cnt[ans[i]] < cnt[ans[j]]
    +	})
    +	return ans
    +}
    +```
    +
    +#### TypeScript
    +
    +```ts
    +function watchedVideosByFriends(
    +    watchedVideos: string[][],
    +    friends: number[][],
    +    id: number,
    +    level: number,
    +): string[] {
    +    let q: number[] = [id];
    +    const n: number = friends.length;
    +    const vis: boolean[] = Array(n).fill(false);
    +    vis[id] = true;
    +    while (level-- > 0) {
    +        const nq: number[] = [];
    +        for (const i of q) {
    +            for (const j of friends[i]) {
    +                if (!vis[j]) {
    +                    vis[j] = true;
    +                    nq.push(j);
    +                }
    +            }
    +        }
    +        q = nq;
    +    }
    +    const cnt: { [key: string]: number } = {};
    +    for (const i of q) {
    +        for (const v of watchedVideos[i]) {
    +            cnt[v] = (cnt[v] || 0) + 1;
    +        }
    +    }
    +    const ans: string[] = Object.keys(cnt);
    +    ans.sort((a, b) => {
    +        if (cnt[a] === cnt[b]) {
    +            return a.localeCompare(b);
    +        }
    +        return cnt[a] - cnt[b];
    +    });
    +    return ans;
     }
     ```
     
    diff --git a/solution/1300-1399/1311.Get Watched Videos by Your Friends/README_EN.md b/solution/1300-1399/1311.Get Watched Videos by Your Friends/README_EN.md
    index 9db5bcfb0808..c80bf64698ac 100644
    --- a/solution/1300-1399/1311.Get Watched Videos by Your Friends/README_EN.md	
    +++ b/solution/1300-1399/1311.Get Watched Videos by Your Friends/README_EN.md	
    @@ -75,7 +75,15 @@ You have id = 0 (green color in the figure) and the only friend of your friends
     
     
     
    -### Solution 1
    +### Solution 1: BFS
    +
    +We can use the Breadth-First Search (BFS) method to start from $\textit{id}$ and find all friends at a distance of $\textit{level}$, then count the videos watched by these friends.
    +
    +Specifically, we can use a queue $\textit{q}$ to store the friends at the current level. Initially, add $\textit{id}$ to the queue $\textit{q}$. Use a hash table or a boolean array $\textit{vis}$ to record the friends that have already been visited. Then, perform $\textit{level}$ iterations, in each iteration dequeue all friends from the queue and enqueue their friends until all friends at distance $\textit{level}$ are found.
    +
    +Next, we use a hash table $\textit{cnt}$ to count the videos watched by these friends and their frequencies. Finally, sort the key-value pairs in the hash table in ascending order by frequency, and if frequencies are the same, sort by video name in ascending order. Return the sorted list of video names.
    +
    +Time complexity is $O(n + m + v \times \log v)$, and space complexity is $O(n + v)$. Here, $n$ and $m$ are the lengths of the arrays $\textit{watchedVideos}$ and $\textit{friends}$, respectively, and $v$ is the total number of videos watched by all friends.
     
     
     
    @@ -90,26 +98,20 @@ class Solution:
             id: int,
             level: int,
         ) -> List[str]:
    -        n = len(friends)
    -        vis = [False] * n
             q = deque([id])
    -        vis[id] = True
    +        vis = {id}
             for _ in range(level):
    -            size = len(q)
    -            for _ in range(size):
    -                u = q.popleft()
    -                for v in friends[u]:
    -                    if not vis[v]:
    -                        q.append(v)
    -                        vis[v] = True
    -        freq = Counter()
    -        for _ in range(len(q)):
    -            u = q.pop()
    -            for w in watchedVideos[u]:
    -                freq[w] += 1
    -        videos = list(freq.items())
    -        videos.sort(key=lambda x: (x[1], x[0]))
    -        return [v[0] for v in videos]
    +            for _ in range(len(q)):
    +                i = q.popleft()
    +                for j in friends[i]:
    +                    if j not in vis:
    +                        vis.add(j)
    +                        q.append(j)
    +        cnt = Counter()
    +        for i in q:
    +            for v in watchedVideos[i]:
    +                cnt[v] += 1
    +        return sorted(cnt.keys(), key=lambda k: (cnt[k], k))
     ```
     
     #### Java
    @@ -118,44 +120,160 @@ class Solution:
     class Solution {
         public List watchedVideosByFriends(
             List> watchedVideos, int[][] friends, int id, int level) {
    +        Deque q = new ArrayDeque<>();
    +        q.offer(id);
             int n = friends.length;
             boolean[] vis = new boolean[n];
    -        Deque q = new LinkedList<>();
    -        q.offerLast(id);
             vis[id] = true;
             while (level-- > 0) {
    -            for (int i = q.size(); i > 0; --i) {
    -                int u = q.pollFirst();
    -                for (int v : friends[u]) {
    -                    if (!vis[v]) {
    -                        q.offerLast(v);
    -                        vis[v] = true;
    +            for (int k = q.size(); k > 0; --k) {
    +                int i = q.poll();
    +                for (int j : friends[i]) {
    +                    if (!vis[j]) {
    +                        vis[j] = true;
    +                        q.offer(j);
                         }
                     }
                 }
             }
    -        Map freq = new HashMap<>();
    -        while (!q.isEmpty()) {
    -            for (String w : watchedVideos.get(q.pollFirst())) {
    -                freq.put(w, freq.getOrDefault(w, 0) + 1);
    +        Map cnt = new HashMap<>();
    +        for (int i : q) {
    +            for (var v : watchedVideos.get(i)) {
    +                cnt.merge(v, 1, Integer::sum);
                 }
             }
    -        List> t = new ArrayList<>(freq.entrySet());
    -        t.sort((a, b) -> {
    -            if (a.getValue() > b.getValue()) {
    -                return 1;
    +        List ans = new ArrayList<>(cnt.keySet());
    +        ans.sort((a, b) -> {
    +            int x = cnt.get(a), y = cnt.get(b);
    +            return x == y ? a.compareTo(b) : Integer.compare(x, y);
    +        });
    +        return ans;
    +    }
    +}
    +```
    +
    +#### C++
    +
    +```cpp
    +class Solution {
    +public:
    +    vector watchedVideosByFriends(vector>& watchedVideos, vector>& friends, int id, int level) {
    +        queue q{{id}};
    +        int n = friends.size();
    +        vector vis(n);
    +        vis[id] = true;
    +        while (level--) {
    +            for (int k = q.size(); k; --k) {
    +                int i = q.front();
    +                q.pop();
    +                for (int j : friends[i]) {
    +                    if (!vis[j]) {
    +                        vis[j] = true;
    +                        q.push(j);
    +                    }
    +                }
                 }
    -            if (a.getValue() < b.getValue()) {
    -                return -1;
    +        }
    +        unordered_map cnt;
    +        while (!q.empty()) {
    +            int i = q.front();
    +            q.pop();
    +            for (const auto& v : watchedVideos[i]) {
    +                cnt[v]++;
                 }
    -            return a.getKey().compareTo(b.getKey());
    -        });
    -        List ans = new ArrayList<>();
    -        for (Map.Entry e : t) {
    -            ans.add(e.getKey());
             }
    +        vector ans;
    +        for (const auto& [key, _] : cnt) {
    +            ans.push_back(key);
    +        }
    +        sort(ans.begin(), ans.end(), [&cnt](const string& a, const string& b) {
    +            return cnt[a] == cnt[b] ? a < b : cnt[a] < cnt[b];
    +        });
             return ans;
         }
    +};
    +```
    +
    +#### Go
    +
    +```go
    +func watchedVideosByFriends(watchedVideos [][]string, friends [][]int, id int, level int) []string {
    +	q := []int{id}
    +	n := len(friends)
    +	vis := make([]bool, n)
    +	vis[id] = true
    +	for level > 0 {
    +		level--
    +		nextQ := []int{}
    +		for _, i := range q {
    +			for _, j := range friends[i] {
    +				if !vis[j] {
    +					vis[j] = true
    +					nextQ = append(nextQ, j)
    +				}
    +			}
    +		}
    +		q = nextQ
    +	}
    +	cnt := make(map[string]int)
    +	for _, i := range q {
    +		for _, v := range watchedVideos[i] {
    +			cnt[v]++
    +		}
    +	}
    +	ans := []string{}
    +	for key := range cnt {
    +		ans = append(ans, key)
    +	}
    +	sort.Slice(ans, func(i, j int) bool {
    +		if cnt[ans[i]] == cnt[ans[j]] {
    +			return ans[i] < ans[j]
    +		}
    +		return cnt[ans[i]] < cnt[ans[j]]
    +	})
    +	return ans
    +}
    +```
    +
    +#### TypeScript
    +
    +```ts
    +function watchedVideosByFriends(
    +    watchedVideos: string[][],
    +    friends: number[][],
    +    id: number,
    +    level: number,
    +): string[] {
    +    let q: number[] = [id];
    +    const n: number = friends.length;
    +    const vis: boolean[] = Array(n).fill(false);
    +    vis[id] = true;
    +    while (level-- > 0) {
    +        const nq: number[] = [];
    +        for (const i of q) {
    +            for (const j of friends[i]) {
    +                if (!vis[j]) {
    +                    vis[j] = true;
    +                    nq.push(j);
    +                }
    +            }
    +        }
    +        q = nq;
    +    }
    +    const cnt: { [key: string]: number } = {};
    +    for (const i of q) {
    +        for (const v of watchedVideos[i]) {
    +            cnt[v] = (cnt[v] || 0) + 1;
    +        }
    +    }
    +    const ans: string[] = Object.keys(cnt);
    +    ans.sort((a, b) => {
    +        if (cnt[a] === cnt[b]) {
    +            return a.localeCompare(b);
    +        }
    +        return cnt[a] - cnt[b];
    +    });
    +    return ans;
     }
     ```
     
    diff --git a/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.cpp b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.cpp
    new file mode 100644
    index 000000000000..7b44db5a0c78
    --- /dev/null
    +++ b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.cpp	
    @@ -0,0 +1,37 @@
    +class Solution {
    +public:
    +    vector watchedVideosByFriends(vector>& watchedVideos, vector>& friends, int id, int level) {
    +        queue q{{id}};
    +        int n = friends.size();
    +        vector vis(n);
    +        vis[id] = true;
    +        while (level--) {
    +            for (int k = q.size(); k; --k) {
    +                int i = q.front();
    +                q.pop();
    +                for (int j : friends[i]) {
    +                    if (!vis[j]) {
    +                        vis[j] = true;
    +                        q.push(j);
    +                    }
    +                }
    +            }
    +        }
    +        unordered_map cnt;
    +        while (!q.empty()) {
    +            int i = q.front();
    +            q.pop();
    +            for (const auto& v : watchedVideos[i]) {
    +                cnt[v]++;
    +            }
    +        }
    +        vector ans;
    +        for (const auto& [key, _] : cnt) {
    +            ans.push_back(key);
    +        }
    +        sort(ans.begin(), ans.end(), [&cnt](const string& a, const string& b) {
    +            return cnt[a] == cnt[b] ? a < b : cnt[a] < cnt[b];
    +        });
    +        return ans;
    +    }
    +};
    diff --git a/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.go b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.go
    new file mode 100644
    index 000000000000..02a443655527
    --- /dev/null
    +++ b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.go	
    @@ -0,0 +1,36 @@
    +func watchedVideosByFriends(watchedVideos [][]string, friends [][]int, id int, level int) []string {
    +	q := []int{id}
    +	n := len(friends)
    +	vis := make([]bool, n)
    +	vis[id] = true
    +	for level > 0 {
    +		level--
    +		nextQ := []int{}
    +		for _, i := range q {
    +			for _, j := range friends[i] {
    +				if !vis[j] {
    +					vis[j] = true
    +					nextQ = append(nextQ, j)
    +				}
    +			}
    +		}
    +		q = nextQ
    +	}
    +	cnt := make(map[string]int)
    +	for _, i := range q {
    +		for _, v := range watchedVideos[i] {
    +			cnt[v]++
    +		}
    +	}
    +	ans := []string{}
    +	for key := range cnt {
    +		ans = append(ans, key)
    +	}
    +	sort.Slice(ans, func(i, j int) bool {
    +		if cnt[ans[i]] == cnt[ans[j]] {
    +			return ans[i] < ans[j]
    +		}
    +		return cnt[ans[i]] < cnt[ans[j]]
    +	})
    +	return ans
    +}
    diff --git a/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.java b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.java
    index df075cdf3775..68fd3190912b 100644
    --- a/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.java	
    +++ b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.java	
    @@ -1,42 +1,33 @@
     class Solution {
         public List watchedVideosByFriends(
             List> watchedVideos, int[][] friends, int id, int level) {
    +        Deque q = new ArrayDeque<>();
    +        q.offer(id);
             int n = friends.length;
             boolean[] vis = new boolean[n];
    -        Deque q = new LinkedList<>();
    -        q.offerLast(id);
             vis[id] = true;
             while (level-- > 0) {
    -            for (int i = q.size(); i > 0; --i) {
    -                int u = q.pollFirst();
    -                for (int v : friends[u]) {
    -                    if (!vis[v]) {
    -                        q.offerLast(v);
    -                        vis[v] = true;
    +            for (int k = q.size(); k > 0; --k) {
    +                int i = q.poll();
    +                for (int j : friends[i]) {
    +                    if (!vis[j]) {
    +                        vis[j] = true;
    +                        q.offer(j);
                         }
                     }
                 }
             }
    -        Map freq = new HashMap<>();
    -        while (!q.isEmpty()) {
    -            for (String w : watchedVideos.get(q.pollFirst())) {
    -                freq.put(w, freq.getOrDefault(w, 0) + 1);
    +        Map cnt = new HashMap<>();
    +        for (int i : q) {
    +            for (var v : watchedVideos.get(i)) {
    +                cnt.merge(v, 1, Integer::sum);
                 }
             }
    -        List> t = new ArrayList<>(freq.entrySet());
    -        t.sort((a, b) -> {
    -            if (a.getValue() > b.getValue()) {
    -                return 1;
    -            }
    -            if (a.getValue() < b.getValue()) {
    -                return -1;
    -            }
    -            return a.getKey().compareTo(b.getKey());
    +        List ans = new ArrayList<>(cnt.keySet());
    +        ans.sort((a, b) -> {
    +            int x = cnt.get(a), y = cnt.get(b);
    +            return x == y ? a.compareTo(b) : Integer.compare(x, y);
             });
    -        List ans = new ArrayList<>();
    -        for (Map.Entry e : t) {
    -            ans.add(e.getKey());
    -        }
             return ans;
         }
    -}
    \ No newline at end of file
    +}
    diff --git a/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.py b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.py
    index 41684ebc9640..6ff97cb7bbab 100644
    --- a/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.py	
    +++ b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.py	
    @@ -6,23 +6,17 @@ def watchedVideosByFriends(
             id: int,
             level: int,
         ) -> List[str]:
    -        n = len(friends)
    -        vis = [False] * n
             q = deque([id])
    -        vis[id] = True
    +        vis = {id}
             for _ in range(level):
    -            size = len(q)
    -            for _ in range(size):
    -                u = q.popleft()
    -                for v in friends[u]:
    -                    if not vis[v]:
    -                        q.append(v)
    -                        vis[v] = True
    -        freq = Counter()
    -        for _ in range(len(q)):
    -            u = q.pop()
    -            for w in watchedVideos[u]:
    -                freq[w] += 1
    -        videos = list(freq.items())
    -        videos.sort(key=lambda x: (x[1], x[0]))
    -        return [v[0] for v in videos]
    +            for _ in range(len(q)):
    +                i = q.popleft()
    +                for j in friends[i]:
    +                    if j not in vis:
    +                        vis.add(j)
    +                        q.append(j)
    +        cnt = Counter()
    +        for i in q:
    +            for v in watchedVideos[i]:
    +                cnt[v] += 1
    +        return sorted(cnt.keys(), key=lambda k: (cnt[k], k))
    diff --git a/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.ts b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.ts
    new file mode 100644
    index 000000000000..8ab4e2304a19
    --- /dev/null
    +++ b/solution/1300-1399/1311.Get Watched Videos by Your Friends/Solution.ts	
    @@ -0,0 +1,37 @@
    +function watchedVideosByFriends(
    +    watchedVideos: string[][],
    +    friends: number[][],
    +    id: number,
    +    level: number,
    +): string[] {
    +    let q: number[] = [id];
    +    const n: number = friends.length;
    +    const vis: boolean[] = Array(n).fill(false);
    +    vis[id] = true;
    +    while (level-- > 0) {
    +        const nq: number[] = [];
    +        for (const i of q) {
    +            for (const j of friends[i]) {
    +                if (!vis[j]) {
    +                    vis[j] = true;
    +                    nq.push(j);
    +                }
    +            }
    +        }
    +        q = nq;
    +    }
    +    const cnt: { [key: string]: number } = {};
    +    for (const i of q) {
    +        for (const v of watchedVideos[i]) {
    +            cnt[v] = (cnt[v] || 0) + 1;
    +        }
    +    }
    +    const ans: string[] = Object.keys(cnt);
    +    ans.sort((a, b) => {
    +        if (cnt[a] === cnt[b]) {
    +            return a.localeCompare(b);
    +        }
    +        return cnt[a] - cnt[b];
    +    });
    +    return ans;
    +}
    diff --git a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md
    index 16fea24c5faa..20c633d1c9fe 100644
    --- a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md	
    +++ b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README.md	
    @@ -329,6 +329,50 @@ function findTheCity(n: number, edges: number[][], distanceThreshold: number): n
     }
     ```
     
    +#### JavaScript
    +
    +```js
    +function findTheCity(n, edges, distanceThreshold) {
    +    const g = Array.from({ length: n }, () => Array(n).fill(Infinity));
    +    const dist = Array(n).fill(Infinity);
    +    const vis = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f][t] = g[t][f] = w;
    +    }
    +
    +    const dijkstra = u => {
    +        dist.fill(Infinity);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        for (let i = 0; i < n; ++i) {
    +            let k = -1;
    +            for (let j = 0; j < n; ++j) {
    +                if (!vis[j] && (k === -1 || dist[j] < dist[k])) {
    +                    k = j;
    +                }
    +            }
    +            vis[k] = true;
    +            for (let j = 0; j < n; ++j) {
    +                dist[j] = Math.min(dist[j], dist[k] + g[k][j]);
    +            }
    +        }
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = Infinity;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    +```
    +
     
     
     
    @@ -522,6 +566,152 @@ function findTheCity(n: number, edges: number[][], distanceThreshold: number): n
     }
     ```
     
    +#### JavaScript
    +
    +```js
    +function findTheCity(n, edges, distanceThreshold) {
    +    const g = Array.from({ length: n }, () => Array(n).fill(Infinity));
    +    for (const [f, t, w] of edges) {
    +        g[f][t] = g[t][f] = w;
    +    }
    +    for (let k = 0; k < n; ++k) {
    +        g[k][k] = 0;
    +        for (let i = 0; i < n; ++i) {
    +            for (let j = 0; j < n; ++j) {
    +                g[i][j] = Math.min(g[i][j], g[i][k] + g[k][j]);
    +            }
    +        }
    +    }
    +
    +    let ans = n,
    +        cnt = n + 1;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = g[i].filter(x => x <= distanceThreshold).length;
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +    return ans;
    +}
    +```
    +
    +
    +
    +
    +
    +
    +
    +### Solution 3
    +
    +
    +
    +#### TypeScript
    +
    +```ts
    +function findTheCity(n: number, edges: number[][], distanceThreshold: number): number {
    +    const MAX = Number.POSITIVE_INFINITY;
    +    const g = Array.from({ length: n }, () => new Map());
    +    const dist: number[] = Array(n).fill(MAX);
    +    const vis: boolean[] = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f].set(t, w);
    +        g[t].set(f, w);
    +    }
    +
    +    const dijkstra = (u: number): number => {
    +        dist.fill(MAX);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        const pq = new MinPriorityQueue();
    +        pq.enqueue(u, 0);
    +
    +        while (!pq.isEmpty()) {
    +            const u = pq.dequeue().element;
    +            if (vis[u]) continue;
    +            vis[u] = true;
    +
    +            for (const [v, w] of g[u]) {
    +                if (vis[v]) continue;
    +
    +                const wNext = dist[u] + w;
    +                if (wNext < dist[v]) {
    +                    dist[v] = wNext;
    +                    pq.enqueue(v, dist[v]);
    +                }
    +            }
    +        }
    +
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = MAX;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    +```
    +
    +#### JavaScript
    +
    +```js
    +export function findTheCity(n, edges, distanceThreshold) {
    +    const MAX = Number.POSITIVE_INFINITY;
    +    const g = Array.from({ length: n }, () => new Map());
    +    const dist = Array(n).fill(MAX);
    +    const vis = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f].set(t, w);
    +        g[t].set(f, w);
    +    }
    +
    +    const dijkstra = u => {
    +        dist.fill(MAX);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        const pq = new MinPriorityQueue();
    +        pq.enqueue(u, 0);
    +
    +        while (!pq.isEmpty()) {
    +            const u = pq.dequeue().element;
    +            if (vis[u]) continue;
    +            vis[u] = true;
    +
    +            for (const [v, w] of g[u]) {
    +                if (vis[v]) continue;
    +
    +                const wNext = dist[u] + w;
    +                if (wNext < dist[v]) {
    +                    dist[v] = wNext;
    +                    pq.enqueue(v, dist[v]);
    +                }
    +            }
    +        }
    +
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = MAX;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    +```
    +
     
     
     
    diff --git a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README_EN.md b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README_EN.md
    index 20d960a5eaa5..283121786a48 100644
    --- a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README_EN.md	
    +++ b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/README_EN.md	
    @@ -319,6 +319,50 @@ function findTheCity(n: number, edges: number[][], distanceThreshold: number): n
     }
     ```
     
    +#### JavaScript
    +
    +```js
    +function findTheCity(n, edges, distanceThreshold) {
    +    const g = Array.from({ length: n }, () => Array(n).fill(Infinity));
    +    const dist = Array(n).fill(Infinity);
    +    const vis = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f][t] = g[t][f] = w;
    +    }
    +
    +    const dijkstra = u => {
    +        dist.fill(Infinity);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        for (let i = 0; i < n; ++i) {
    +            let k = -1;
    +            for (let j = 0; j < n; ++j) {
    +                if (!vis[j] && (k === -1 || dist[j] < dist[k])) {
    +                    k = j;
    +                }
    +            }
    +            vis[k] = true;
    +            for (let j = 0; j < n; ++j) {
    +                dist[j] = Math.min(dist[j], dist[k] + g[k][j]);
    +            }
    +        }
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = Infinity;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    +```
    +
     
     
     
    @@ -504,6 +548,152 @@ function findTheCity(n: number, edges: number[][], distanceThreshold: number): n
     }
     ```
     
    +#### JavaScript
    +
    +```js
    +function findTheCity(n, edges, distanceThreshold) {
    +    const g = Array.from({ length: n }, () => Array(n).fill(Infinity));
    +    for (const [f, t, w] of edges) {
    +        g[f][t] = g[t][f] = w;
    +    }
    +    for (let k = 0; k < n; ++k) {
    +        g[k][k] = 0;
    +        for (let i = 0; i < n; ++i) {
    +            for (let j = 0; j < n; ++j) {
    +                g[i][j] = Math.min(g[i][j], g[i][k] + g[k][j]);
    +            }
    +        }
    +    }
    +
    +    let ans = n,
    +        cnt = n + 1;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = g[i].filter(x => x <= distanceThreshold).length;
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +    return ans;
    +}
    +```
    +
    +
    +
    +
    +
    +
    +
    +### Solution 3
    +
    +
    +
    +#### TypeScript
    +
    +```ts
    +function findTheCity(n: number, edges: number[][], distanceThreshold: number): number {
    +    const MAX = Number.POSITIVE_INFINITY;
    +    const g = Array.from({ length: n }, () => new Map());
    +    const dist: number[] = Array(n).fill(MAX);
    +    const vis: boolean[] = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f].set(t, w);
    +        g[t].set(f, w);
    +    }
    +
    +    const dijkstra = (u: number): number => {
    +        dist.fill(MAX);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        const pq = new MinPriorityQueue();
    +        pq.enqueue(u, 0);
    +
    +        while (!pq.isEmpty()) {
    +            const u = pq.dequeue().element;
    +            if (vis[u]) continue;
    +            vis[u] = true;
    +
    +            for (const [v, w] of g[u]) {
    +                if (vis[v]) continue;
    +
    +                const wNext = dist[u] + w;
    +                if (wNext < dist[v]) {
    +                    dist[v] = wNext;
    +                    pq.enqueue(v, dist[v]);
    +                }
    +            }
    +        }
    +
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = MAX;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    +```
    +
    +#### JavaScript
    +
    +```js
    +export function findTheCity(n, edges, distanceThreshold) {
    +    const MAX = Number.POSITIVE_INFINITY;
    +    const g = Array.from({ length: n }, () => new Map());
    +    const dist = Array(n).fill(MAX);
    +    const vis = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f].set(t, w);
    +        g[t].set(f, w);
    +    }
    +
    +    const dijkstra = u => {
    +        dist.fill(MAX);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        const pq = new MinPriorityQueue();
    +        pq.enqueue(u, 0);
    +
    +        while (!pq.isEmpty()) {
    +            const u = pq.dequeue().element;
    +            if (vis[u]) continue;
    +            vis[u] = true;
    +
    +            for (const [v, w] of g[u]) {
    +                if (vis[v]) continue;
    +
    +                const wNext = dist[u] + w;
    +                if (wNext < dist[v]) {
    +                    dist[v] = wNext;
    +                    pq.enqueue(v, dist[v]);
    +                }
    +            }
    +        }
    +
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = MAX;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    +```
    +
     
     
     
    diff --git a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution.js b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution.js
    new file mode 100644
    index 000000000000..df5b8032bf10
    --- /dev/null
    +++ b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution.js	
    @@ -0,0 +1,39 @@
    +function findTheCity(n, edges, distanceThreshold) {
    +    const g = Array.from({ length: n }, () => Array(n).fill(Infinity));
    +    const dist = Array(n).fill(Infinity);
    +    const vis = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f][t] = g[t][f] = w;
    +    }
    +
    +    const dijkstra = u => {
    +        dist.fill(Infinity);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        for (let i = 0; i < n; ++i) {
    +            let k = -1;
    +            for (let j = 0; j < n; ++j) {
    +                if (!vis[j] && (k === -1 || dist[j] < dist[k])) {
    +                    k = j;
    +                }
    +            }
    +            vis[k] = true;
    +            for (let j = 0; j < n; ++j) {
    +                dist[j] = Math.min(dist[j], dist[k] + g[k][j]);
    +            }
    +        }
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = Infinity;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    diff --git a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution2.js b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution2.js
    new file mode 100644
    index 000000000000..eefee56d3ee4
    --- /dev/null
    +++ b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution2.js	
    @@ -0,0 +1,25 @@
    +function findTheCity(n, edges, distanceThreshold) {
    +    const g = Array.from({ length: n }, () => Array(n).fill(Infinity));
    +    for (const [f, t, w] of edges) {
    +        g[f][t] = g[t][f] = w;
    +    }
    +    for (let k = 0; k < n; ++k) {
    +        g[k][k] = 0;
    +        for (let i = 0; i < n; ++i) {
    +            for (let j = 0; j < n; ++j) {
    +                g[i][j] = Math.min(g[i][j], g[i][k] + g[k][j]);
    +            }
    +        }
    +    }
    +
    +    let ans = n,
    +        cnt = n + 1;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = g[i].filter(x => x <= distanceThreshold).length;
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +    return ans;
    +}
    diff --git a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution3.js b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution3.js
    new file mode 100644
    index 000000000000..1ed22e36f6c5
    --- /dev/null
    +++ b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution3.js	
    @@ -0,0 +1,48 @@
    +export function findTheCity(n, edges, distanceThreshold) {
    +    const MAX = Number.POSITIVE_INFINITY;
    +    const g = Array.from({ length: n }, () => new Map());
    +    const dist = Array(n).fill(MAX);
    +    const vis = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f].set(t, w);
    +        g[t].set(f, w);
    +    }
    +
    +    const dijkstra = u => {
    +        dist.fill(MAX);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        const pq = new MinPriorityQueue();
    +        pq.enqueue(u, 0);
    +
    +        while (!pq.isEmpty()) {
    +            const u = pq.dequeue().element;
    +            if (vis[u]) continue;
    +            vis[u] = true;
    +
    +            for (const [v, w] of g[u]) {
    +                if (vis[v]) continue;
    +
    +                const wNext = dist[u] + w;
    +                if (wNext < dist[v]) {
    +                    dist[v] = wNext;
    +                    pq.enqueue(v, dist[v]);
    +                }
    +            }
    +        }
    +
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = MAX;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    diff --git a/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution3.ts b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution3.ts
    new file mode 100644
    index 000000000000..cd8545d7a82c
    --- /dev/null
    +++ b/solution/1300-1399/1334.Find the City With the Smallest Number of Neighbors at a Threshold Distance/Solution3.ts	
    @@ -0,0 +1,48 @@
    +function findTheCity(n: number, edges: number[][], distanceThreshold: number): number {
    +    const MAX = Number.POSITIVE_INFINITY;
    +    const g = Array.from({ length: n }, () => new Map());
    +    const dist: number[] = Array(n).fill(MAX);
    +    const vis: boolean[] = Array(n).fill(false);
    +    for (const [f, t, w] of edges) {
    +        g[f].set(t, w);
    +        g[t].set(f, w);
    +    }
    +
    +    const dijkstra = (u: number): number => {
    +        dist.fill(MAX);
    +        vis.fill(false);
    +        dist[u] = 0;
    +        const pq = new MinPriorityQueue();
    +        pq.enqueue(u, 0);
    +
    +        while (!pq.isEmpty()) {
    +            const u = pq.dequeue().element;
    +            if (vis[u]) continue;
    +            vis[u] = true;
    +
    +            for (const [v, w] of g[u]) {
    +                if (vis[v]) continue;
    +
    +                const wNext = dist[u] + w;
    +                if (wNext < dist[v]) {
    +                    dist[v] = wNext;
    +                    pq.enqueue(v, dist[v]);
    +                }
    +            }
    +        }
    +
    +        return dist.filter(d => d <= distanceThreshold).length;
    +    };
    +
    +    let ans = n;
    +    let cnt = MAX;
    +    for (let i = n - 1; i >= 0; --i) {
    +        const t = dijkstra(i);
    +        if (t < cnt) {
    +            cnt = t;
    +            ans = i;
    +        }
    +    }
    +
    +    return ans;
    +}
    diff --git a/solution/1300-1399/1380.Lucky Numbers in a Matrix/README.md b/solution/1300-1399/1380.Lucky Numbers in a Matrix/README.md
    index f654912945c9..76443f36dd12 100644
    --- a/solution/1300-1399/1380.Lucky Numbers in a Matrix/README.md	
    +++ b/solution/1300-1399/1380.Lucky Numbers in a Matrix/README.md	
    @@ -19,7 +19,7 @@ tags:
     
     
     
    -

    给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。

    +

    给你一个 m x n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。

    幸运数 是指矩阵中满足同时下列两个条件的元素:

    @@ -30,7 +30,7 @@ tags:

     

    -

    示例 1:

    +

    示例 1:

     输入:matrix = [[3,7,8],[9,11,13],[15,16,17]]
    @@ -38,7 +38,7 @@ tags:
     解释:15 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。
     
    -

    示例 2:

    +

    示例 2:

     输入:matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]]
    @@ -46,12 +46,12 @@ tags:
     解释:12 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。
     
    -

    示例 3:

    +

    示例 3:

     输入:matrix = [[7,8],[1,2]]
     输出:[7]
    -解释:7是唯一的幸运数字,因为它是行中的最小值,列中的最大值。
    +解释:7 是唯一的幸运数字,因为它是行中的最小值,列中的最大值。
     

     

    @@ -62,7 +62,7 @@ tags:
  • m == mat.length
  • n == mat[i].length
  • 1 <= n, m <= 50
  • -
  • 1 <= matrix[i][j] <= 10^5
  • +
  • 1 <= matrix[i][j] <= 105
  • 矩阵中的所有元素都是不同的
  • @@ -202,6 +202,36 @@ function luckyNumbers(matrix: number[][]): number[] { } ``` +#### JavaScript + +```js +/** + * @param {number[][]} matrix + * @return {number[]} + */ +var luckyNumbers = function (matrix) { + const m = matrix.length; + const n = matrix[0].length; + const rows = new Array(m).fill(1 << 30); + const cols = new Array(n).fill(0); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; j++) { + rows[i] = Math.min(rows[i], matrix[i][j]); + cols[j] = Math.max(cols[j], matrix[i][j]); + } + } + const ans = []; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; j++) { + if (rows[i] === cols[j]) { + ans.push(rows[i]); + } + } + } + return ans; +}; +``` + #### Rust ```rust diff --git a/solution/1300-1399/1380.Lucky Numbers in a Matrix/README_EN.md b/solution/1300-1399/1380.Lucky Numbers in a Matrix/README_EN.md index 208a413bd3fa..541f37076eb8 100644 --- a/solution/1300-1399/1380.Lucky Numbers in a Matrix/README_EN.md +++ b/solution/1300-1399/1380.Lucky Numbers in a Matrix/README_EN.md @@ -195,6 +195,36 @@ function luckyNumbers(matrix: number[][]): number[] { } ``` +#### JavaScript + +```js +/** + * @param {number[][]} matrix + * @return {number[]} + */ +var luckyNumbers = function (matrix) { + const m = matrix.length; + const n = matrix[0].length; + const rows = new Array(m).fill(1 << 30); + const cols = new Array(n).fill(0); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; j++) { + rows[i] = Math.min(rows[i], matrix[i][j]); + cols[j] = Math.max(cols[j], matrix[i][j]); + } + } + const ans = []; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; j++) { + if (rows[i] === cols[j]) { + ans.push(rows[i]); + } + } + } + return ans; +}; +``` + #### Rust ```rust diff --git a/solution/1300-1399/1380.Lucky Numbers in a Matrix/Solution.js b/solution/1300-1399/1380.Lucky Numbers in a Matrix/Solution.js new file mode 100644 index 000000000000..35010e1bfadd --- /dev/null +++ b/solution/1300-1399/1380.Lucky Numbers in a Matrix/Solution.js @@ -0,0 +1,25 @@ +/** + * @param {number[][]} matrix + * @return {number[]} + */ +var luckyNumbers = function (matrix) { + const m = matrix.length; + const n = matrix[0].length; + const rows = new Array(m).fill(1 << 30); + const cols = new Array(n).fill(0); + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; j++) { + rows[i] = Math.min(rows[i], matrix[i][j]); + cols[j] = Math.max(cols[j], matrix[i][j]); + } + } + const ans = []; + for (let i = 0; i < m; ++i) { + for (let j = 0; j < n; j++) { + if (rows[i] === cols[j]) { + ans.push(rows[i]); + } + } + } + return ans; +}; diff --git a/solution/1300-1399/1392.Longest Happy Prefix/README.md b/solution/1300-1399/1392.Longest Happy Prefix/README.md index d0e4490cf2cd..64ad42c7ae5f 100644 --- a/solution/1300-1399/1392.Longest Happy Prefix/README.md +++ b/solution/1300-1399/1392.Longest Happy Prefix/README.md @@ -197,4 +197,134 @@ impl Solution { + + +### 方法二:KMP 算法 + +根据题目描述,我们需要找到一个字符串的最长快乐前缀,即找到一个字符串的最长前缀,使得这个前缀同时也是这个字符串的后缀。我们可以使用 KMP 算法来解决这个问题。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串的长度。 + + + +#### Python3 + +```python +class Solution: + def longestPrefix(self, s: str) -> str: + s += "#" + n = len(s) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if s[i - 1] == s[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s[: next[-1]] +``` + +#### Java + +```java +class Solution { + public String longestPrefix(String s) { + s += "#"; + int n = s.length(); + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (s.charAt(i - 1) == s.charAt(j)) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.substring(0, next[n - 1]); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string longestPrefix(string s) { + s.push_back('#'); + int n = s.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (s[i - 1] == s[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.substr(0, next[n - 1]); + } +}; +``` + +#### Go + +```go +func longestPrefix(s string) string { + s += "#" + n := len(s) + next := make([]int, n) + next[0], next[1] = -1, 0 + for i, j := 2, 0; i < n; { + if s[i-1] == s[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return s[:next[n-1]] +} +``` + +#### TypeScript + +```ts +function longestPrefix(s: string): string { + s += '#'; + const n = s.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (s[i - 1] === s[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.slice(0, next[n - 1]); +} +``` + + + + + diff --git a/solution/1300-1399/1392.Longest Happy Prefix/README_EN.md b/solution/1300-1399/1392.Longest Happy Prefix/README_EN.md index 1cde8157af9b..5217bb2fddf0 100644 --- a/solution/1300-1399/1392.Longest Happy Prefix/README_EN.md +++ b/solution/1300-1399/1392.Longest Happy Prefix/README_EN.md @@ -195,4 +195,134 @@ impl Solution { + + +### Solution 2: KMP Algorithm + +According to the problem description, we need to find the longest happy prefix of a string, which is the longest prefix of the string that is also a suffix of the string. We can use the KMP algorithm to solve this problem. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string. + + + +#### Python3 + +```python +class Solution: + def longestPrefix(self, s: str) -> str: + s += "#" + n = len(s) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if s[i - 1] == s[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s[: next[-1]] +``` + +#### Java + +```java +class Solution { + public String longestPrefix(String s) { + s += "#"; + int n = s.length(); + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (s.charAt(i - 1) == s.charAt(j)) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.substring(0, next[n - 1]); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string longestPrefix(string s) { + s.push_back('#'); + int n = s.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (s[i - 1] == s[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.substr(0, next[n - 1]); + } +}; +``` + +#### Go + +```go +func longestPrefix(s string) string { + s += "#" + n := len(s) + next := make([]int, n) + next[0], next[1] = -1, 0 + for i, j := 2, 0; i < n; { + if s[i-1] == s[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return s[:next[n-1]] +} +``` + +#### TypeScript + +```ts +function longestPrefix(s: string): string { + s += '#'; + const n = s.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (s[i - 1] === s[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.slice(0, next[n - 1]); +} +``` + + + + + diff --git a/solution/1300-1399/1392.Longest Happy Prefix/Solution2.cpp b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.cpp new file mode 100644 index 000000000000..0fc84e2455b4 --- /dev/null +++ b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + string longestPrefix(string s) { + s.push_back('#'); + int n = s.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (s[i - 1] == s[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.substr(0, next[n - 1]); + } +}; diff --git a/solution/1300-1399/1392.Longest Happy Prefix/Solution2.go b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.go new file mode 100644 index 000000000000..5acb4cf5c7e8 --- /dev/null +++ b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.go @@ -0,0 +1,19 @@ +func longestPrefix(s string) string { + s += "#" + n := len(s) + next := make([]int, n) + next[0], next[1] = -1, 0 + for i, j := 2, 0; i < n; { + if s[i-1] == s[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return s[:next[n-1]] +} diff --git a/solution/1300-1399/1392.Longest Happy Prefix/Solution2.java b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.java new file mode 100644 index 000000000000..22f0f898324c --- /dev/null +++ b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.java @@ -0,0 +1,18 @@ +class Solution { + public String longestPrefix(String s) { + s += "#"; + int n = s.length(); + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (s.charAt(i - 1) == s.charAt(j)) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.substring(0, next[n - 1]); + } +} diff --git a/solution/1300-1399/1392.Longest Happy Prefix/Solution2.py b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.py new file mode 100644 index 000000000000..d3b9f63e8e3f --- /dev/null +++ b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.py @@ -0,0 +1,18 @@ +class Solution: + def longestPrefix(self, s: str) -> str: + s += "#" + n = len(s) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if s[i - 1] == s[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s[: next[-1]] diff --git a/solution/1300-1399/1392.Longest Happy Prefix/Solution2.ts b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.ts new file mode 100644 index 000000000000..56b46dd2cc75 --- /dev/null +++ b/solution/1300-1399/1392.Longest Happy Prefix/Solution2.ts @@ -0,0 +1,16 @@ +function longestPrefix(s: string): string { + s += '#'; + const n = s.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (s[i - 1] === s[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s.slice(0, next[n - 1]); +} diff --git a/solution/1300-1399/1395.Count Number of Teams/README.md b/solution/1300-1399/1395.Count Number of Teams/README.md index 12b866f75586..325d4a43255e 100644 --- a/solution/1300-1399/1395.Count Number of Teams/README.md +++ b/solution/1300-1399/1395.Count Number of Teams/README.md @@ -6,6 +6,7 @@ rating: 1343 source: 第 182 场周赛 Q2 tags: - 树状数组 + - 线段树 - 数组 - 动态规划 --- @@ -527,4 +528,108 @@ function numTeams(rating: number[]): number { + + +### 方法三:记忆化搜索 + + + +#### TypeScript + +```ts +function numTeams(rating: number[]): number { + const n = rating.length; + const f: Record = { + asc: Array.from({ length: n }, () => Array(3).fill(-1)), + desc: Array.from({ length: n }, () => Array(3).fill(-1)), + }; + + const fn = (i: number, available: number, type: Type) => { + if (!available) { + return 1; + } + if (f[type][i][available] !== -1) { + return f[type][i][available]; + } + + let ans = 0; + for (let j = i + 1; j < n; j++) { + if (rating[j] > rating[i]) { + if (type === 'asc') { + ans += fn(j, available - 1, 'asc'); + } + } else { + if (type === 'desc') { + ans += fn(j, available - 1, 'desc'); + } + } + } + f[type][i][available] = ans; + + return ans; + }; + + let ans = 0; + for (let i = 0; i < n; i++) { + ans += fn(i, 2, 'asc') + fn(i, 2, 'desc'); + } + + return ans; +} + +type Type = 'asc' | 'desc'; +``` + +#### JavaScript + +```js +/** + * @param {number[]} rating + * @return {number} + */ +var numTeams = function (rating) { + const n = rating.length; + const f = { + asc: Array.from({ length: n }, () => Array(3).fill(-1)), + desc: Array.from({ length: n }, () => Array(3).fill(-1)), + }; + + const fn = (i, available, type) => { + if (!available) { + return 1; + } + if (f[type][i][available] !== -1) { + return f[type][i][available]; + } + + let ans = 0; + for (let j = i + 1; j < n; j++) { + if (rating[j] > rating[i]) { + if (type === 'asc') { + ans += fn(j, available - 1, 'asc'); + } + } else { + if (type === 'desc') { + ans += fn(j, available - 1, 'desc'); + } + } + } + f[type][i][available] = ans; + + return ans; + }; + + let ans = 0; + for (let i = 0; i < n; i++) { + ans += fn(i, 2, 'asc') + fn(i, 2, 'desc'); + } + + return ans; +}; +``` + + + + + diff --git a/solution/1300-1399/1395.Count Number of Teams/README_EN.md b/solution/1300-1399/1395.Count Number of Teams/README_EN.md index bb1d7b846fc6..60b47941ce8b 100644 --- a/solution/1300-1399/1395.Count Number of Teams/README_EN.md +++ b/solution/1300-1399/1395.Count Number of Teams/README_EN.md @@ -6,6 +6,7 @@ rating: 1343 source: Weekly Contest 182 Q2 tags: - Binary Indexed Tree + - Segment Tree - Array - Dynamic Programming --- @@ -525,4 +526,108 @@ function numTeams(rating: number[]): number { + + +### Solution 3: Recursion + Memoization + + + +#### TypeScript + +```ts +function numTeams(rating: number[]): number { + const n = rating.length; + const f: Record = { + asc: Array.from({ length: n }, () => Array(3).fill(-1)), + desc: Array.from({ length: n }, () => Array(3).fill(-1)), + }; + + const fn = (i: number, available: number, type: Type) => { + if (!available) { + return 1; + } + if (f[type][i][available] !== -1) { + return f[type][i][available]; + } + + let ans = 0; + for (let j = i + 1; j < n; j++) { + if (rating[j] > rating[i]) { + if (type === 'asc') { + ans += fn(j, available - 1, 'asc'); + } + } else { + if (type === 'desc') { + ans += fn(j, available - 1, 'desc'); + } + } + } + f[type][i][available] = ans; + + return ans; + }; + + let ans = 0; + for (let i = 0; i < n; i++) { + ans += fn(i, 2, 'asc') + fn(i, 2, 'desc'); + } + + return ans; +} + +type Type = 'asc' | 'desc'; +``` + +#### JavaScript + +```js +/** + * @param {number[]} rating + * @return {number} + */ +var numTeams = function (rating) { + const n = rating.length; + const f = { + asc: Array.from({ length: n }, () => Array(3).fill(-1)), + desc: Array.from({ length: n }, () => Array(3).fill(-1)), + }; + + const fn = (i, available, type) => { + if (!available) { + return 1; + } + if (f[type][i][available] !== -1) { + return f[type][i][available]; + } + + let ans = 0; + for (let j = i + 1; j < n; j++) { + if (rating[j] > rating[i]) { + if (type === 'asc') { + ans += fn(j, available - 1, 'asc'); + } + } else { + if (type === 'desc') { + ans += fn(j, available - 1, 'desc'); + } + } + } + f[type][i][available] = ans; + + return ans; + }; + + let ans = 0; + for (let i = 0; i < n; i++) { + ans += fn(i, 2, 'asc') + fn(i, 2, 'desc'); + } + + return ans; +}; +``` + + + + + diff --git a/solution/1300-1399/1395.Count Number of Teams/Solution3.js b/solution/1300-1399/1395.Count Number of Teams/Solution3.js new file mode 100644 index 000000000000..46afa695a39a --- /dev/null +++ b/solution/1300-1399/1395.Count Number of Teams/Solution3.js @@ -0,0 +1,43 @@ +/** + * @param {number[]} rating + * @return {number} + */ +var numTeams = function (rating) { + const n = rating.length; + const f = { + asc: Array.from({ length: n }, () => Array(3).fill(-1)), + desc: Array.from({ length: n }, () => Array(3).fill(-1)), + }; + + const fn = (i, available, type) => { + if (!available) { + return 1; + } + if (f[type][i][available] !== -1) { + return f[type][i][available]; + } + + let ans = 0; + for (let j = i + 1; j < n; j++) { + if (rating[j] > rating[i]) { + if (type === 'asc') { + ans += fn(j, available - 1, 'asc'); + } + } else { + if (type === 'desc') { + ans += fn(j, available - 1, 'desc'); + } + } + } + f[type][i][available] = ans; + + return ans; + }; + + let ans = 0; + for (let i = 0; i < n; i++) { + ans += fn(i, 2, 'asc') + fn(i, 2, 'desc'); + } + + return ans; +}; diff --git a/solution/1300-1399/1395.Count Number of Teams/Solution3.ts b/solution/1300-1399/1395.Count Number of Teams/Solution3.ts new file mode 100644 index 000000000000..34e3bcfc59e8 --- /dev/null +++ b/solution/1300-1399/1395.Count Number of Teams/Solution3.ts @@ -0,0 +1,41 @@ +function numTeams(rating: number[]): number { + const n = rating.length; + const f: Record = { + asc: Array.from({ length: n }, () => Array(3).fill(-1)), + desc: Array.from({ length: n }, () => Array(3).fill(-1)), + }; + + const fn = (i: number, available: number, type: Type) => { + if (!available) { + return 1; + } + if (f[type][i][available] !== -1) { + return f[type][i][available]; + } + + let ans = 0; + for (let j = i + 1; j < n; j++) { + if (rating[j] > rating[i]) { + if (type === 'asc') { + ans += fn(j, available - 1, 'asc'); + } + } else { + if (type === 'desc') { + ans += fn(j, available - 1, 'desc'); + } + } + } + f[type][i][available] = ans; + + return ans; + }; + + let ans = 0; + for (let i = 0; i < n; i++) { + ans += fn(i, 2, 'asc') + fn(i, 2, 'desc'); + } + + return ans; +} + +type Type = 'asc' | 'desc'; diff --git "a/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README.md" "b/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README.md" index 5b3261fb50fa..7eec87147e5f 100644 --- "a/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README.md" +++ "b/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README.md" @@ -188,10 +188,10 @@ function numOfWays(n: number): number { 因此,我们定义 $f[i][j]$ 表示前 $i$ 行中,第 $i$ 行的涂色状态为 $j$ 的方案数。状态 $f[i][j]$ 由 $f[i - 1][k]$ 转移而来,其中 $k$ 是第 $i - 1$ 行的涂色状态,且 $k$ 和 $j$ 满足不同颜色相邻的要求。即: $$ -f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k] +f[i][j] = \sum_{k \in \textit{valid}(j)} f[i - 1][k] $$ -其中 $\text{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。 +其中 $\textit{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。 最终的答案即为 $f[n][j]$ 的总和,其中 $j$ 是任意合法的状态。 diff --git "a/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README_EN.md" "b/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README_EN.md" index 6470c015003e..901db62d70f8 100644 --- "a/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README_EN.md" +++ "b/solution/1400-1499/1411.Number of Ways to Paint N \303\227 3 Grid/README_EN.md" @@ -166,10 +166,10 @@ We notice that the grid only has $3$ columns, so there are at most $3^3=27$ diff Therefore, we define $f[i][j]$ to represent the number of schemes in the first $i$ rows, where the coloring state of the $i$th row is $j$. The state $f[i][j]$ is transferred from $f[i - 1][k]$, where $k$ is the coloring state of the $i - 1$th row, and $k$ and $j$ meet the requirement of different colors being adjacent. That is: $$ -f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k] +f[i][j] = \sum_{k \in \textit{valid}(j)} f[i - 1][k] $$ -where $\text{valid}(j)$ represents all legal predecessor states of state $j$. +where $\textit{valid}(j)$ represents all legal predecessor states of state $j$. The final answer is the sum of $f[n][j]$, where $j$ is any legal state. diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README.md b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README.md index e35ca074730d..a1a38a9e939b 100644 --- a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README.md +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README.md @@ -78,7 +78,19 @@ tags: -### 方法一 +### 方法一:哈希表 + 排序 + +我们可以用一个哈希表 $\textit{tables}$ 来存储每张餐桌点的菜品,用一个集合 $\textit{items}$ 来存储所有的菜品。 + +遍历 $\textit{orders}$,将每张餐桌点的菜品存入 $\textit{tables}$ 和 $\textit{items}$ 中。 + +然后我们将 $\textit{items}$ 排序,得到 $\textit{sortedItems}$。 + +接下来,我们构建答案数组 $\textit{ans}$,首先将标题行 $\textit{header}$ 加入 $\textit{ans}$,然后遍历排序后的 $\textit{tables}$,对于每张餐桌,我们用一个计数器 $\textit{cnt}$ 来统计每种菜品的数量,然后构建一行 $\textit{row}$,将其加入 $\textit{ans}$。 + +最后返回 $\textit{ans}$。 + +时间复杂度 $O(n + m \times \log m + k \times \log k + m \times k)$,空间复杂度 $O(n + m + k)$。其中 $n$ 是数组 $\textit{orders}$ 的长度,而 $m$ 和 $k$ 分别表示菜品种类数和餐桌数。 @@ -87,22 +99,18 @@ tags: ```python class Solution: def displayTable(self, orders: List[List[str]]) -> List[List[str]]: - tables = set() - foods = set() - mp = Counter() - for _, table, food in orders: - tables.add(int(table)) - foods.add(food) - mp[f'{table}.{food}'] += 1 - foods = sorted(list(foods)) - tables = sorted(list(tables)) - res = [['Table'] + foods] - for table in tables: - t = [str(table)] - for food in foods: - t.append(str(mp[f'{table}.{food}'])) - res.append(t) - return res + tables = defaultdict(list) + items = set() + for _, table, foodItem in orders: + tables[int(table)].append(foodItem) + items.add(foodItem) + sorted_items = sorted(items) + ans = [["Table"] + sorted_items] + for table in sorted(tables): + cnt = Counter(tables[table]) + row = [str(table)] + [str(cnt[item]) for item in sorted_items] + ans.append(row) + return ans ``` #### Java @@ -110,35 +118,34 @@ class Solution: ```java class Solution { public List> displayTable(List> orders) { - Set tables = new HashSet<>(); - Set foods = new HashSet<>(); - Map mp = new HashMap<>(); - for (List order : orders) { - int table = Integer.parseInt(order.get(1)); - String food = order.get(2); - tables.add(table); - foods.add(food); - String key = table + "." + food; - mp.put(key, mp.getOrDefault(key, 0) + 1); + TreeMap> tables = new TreeMap<>(); + Set items = new HashSet<>(); + for (List o : orders) { + int table = Integer.parseInt(o.get(1)); + String foodItem = o.get(2); + tables.computeIfAbsent(table, k -> new ArrayList<>()).add(foodItem); + items.add(foodItem); } - List t = new ArrayList<>(tables); - List f = new ArrayList<>(foods); - Collections.sort(t); - Collections.sort(f); - List> res = new ArrayList<>(); - List title = new ArrayList<>(); - title.add("Table"); - title.addAll(f); - res.add(title); - for (int table : t) { - List tmp = new ArrayList<>(); - tmp.add(String.valueOf(table)); - for (String food : f) { - tmp.add(String.valueOf(mp.getOrDefault(table + "." + food, 0))); + List sortedItems = new ArrayList<>(items); + Collections.sort(sortedItems); + List> ans = new ArrayList<>(); + List header = new ArrayList<>(); + header.add("Table"); + header.addAll(sortedItems); + ans.add(header); + for (Map.Entry> entry : tables.entrySet()) { + Map cnt = new HashMap<>(); + for (String item : entry.getValue()) { + cnt.merge(item, 1, Integer::sum); + } + List row = new ArrayList<>(); + row.add(String.valueOf(entry.getKey())); + for (String item : sortedItems) { + row.add(String.valueOf(cnt.getOrDefault(item, 0))); } - res.add(tmp); + ans.add(row); } - return res; + return ans; } } ``` @@ -149,36 +156,31 @@ class Solution { class Solution { public: vector> displayTable(vector>& orders) { - unordered_set tables; - unordered_set foods; - unordered_map mp; - for (auto& order : orders) { - int table = stoi(order[1]); - string food = order[2]; - tables.insert(table); - foods.insert(food); - ++mp[order[1] + "." + food]; + map> tables; + set sortedItems; + for (auto& o : orders) { + int table = stoi(o[1]); + string foodItem = o[2]; + tables[table].push_back(foodItem); + sortedItems.insert(foodItem); } - vector t; - t.assign(tables.begin(), tables.end()); - sort(t.begin(), t.end()); - vector f; - f.assign(foods.begin(), foods.end()); - sort(f.begin(), f.end()); - vector> res; - vector title; - title.push_back("Table"); - for (auto e : f) title.push_back(e); - res.push_back(title); - for (int table : t) { - vector tmp; - tmp.push_back(to_string(table)); - for (string food : f) { - tmp.push_back(to_string(mp[to_string(table) + "." + food])); + vector> ans; + vector header = {"Table"}; + header.insert(header.end(), sortedItems.begin(), sortedItems.end()); + ans.push_back(header); + for (auto& [table, items] : tables) { + unordered_map cnt; + for (string& item : items) { + cnt[item]++; + } + vector row; + row.push_back(to_string(table)); + for (const string& item : sortedItems) { + row.push_back(to_string(cnt[item])); } - res.push_back(tmp); + ans.push_back(row); } - return res; + return ans; } }; ``` @@ -187,43 +189,74 @@ public: ```go func displayTable(orders [][]string) [][]string { - tables := make(map[int]bool) - foods := make(map[string]bool) - mp := make(map[string]int) + tables := make(map[int]map[string]int) + items := make(map[string]bool) for _, order := range orders { - table, food := order[1], order[2] - t, _ := strconv.Atoi(table) - tables[t] = true - foods[food] = true - key := table + "." + food - mp[key] += 1 - } - var t []int - var f []string - for i := range tables { - t = append(t, i) + table, _ := strconv.Atoi(order[1]) + foodItem := order[2] + if tables[table] == nil { + tables[table] = make(map[string]int) + } + tables[table][foodItem]++ + items[foodItem] = true } - for i := range foods { - f = append(f, i) + sortedItems := make([]string, 0, len(items)) + for item := range items { + sortedItems = append(sortedItems, item) } - sort.Ints(t) - sort.Strings(f) - var res [][]string - var title []string - title = append(title, "Table") - for _, e := range f { - title = append(title, e) + sort.Strings(sortedItems) + ans := [][]string{} + header := append([]string{"Table"}, sortedItems...) + ans = append(ans, header) + tableNums := make([]int, 0, len(tables)) + for table := range tables { + tableNums = append(tableNums, table) } - res = append(res, title) - for _, table := range t { - var tmp []string - tmp = append(tmp, strconv.Itoa(table)) - for _, food := range f { - tmp = append(tmp, strconv.Itoa(mp[strconv.Itoa(table)+"."+food])) + sort.Ints(tableNums) + for _, table := range tableNums { + row := []string{strconv.Itoa(table)} + for _, item := range sortedItems { + count := tables[table][item] + row = append(row, strconv.Itoa(count)) } - res = append(res, tmp) + ans = append(ans, row) } - return res + return ans +} +``` + +#### TypeScript + +```ts +function displayTable(orders: string[][]): string[][] { + const tables: Record> = {}; + const items: Set = new Set(); + for (const [_, table, foodItem] of orders) { + const t = +table; + if (!tables[t]) { + tables[t] = {}; + } + if (!tables[t][foodItem]) { + tables[t][foodItem] = 0; + } + tables[t][foodItem]++; + items.add(foodItem); + } + const sortedItems = Array.from(items).sort(); + const ans: string[][] = []; + const header: string[] = ['Table', ...sortedItems]; + ans.push(header); + const sortedTableNumbers = Object.keys(tables) + .map(Number) + .sort((a, b) => a - b); + for (const table of sortedTableNumbers) { + const row: string[] = [table.toString()]; + for (const item of sortedItems) { + row.push((tables[table][item] || 0).toString()); + } + ans.push(row); + } + return ans; } ``` diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md index 79d27902b765..dd6bc86d1a53 100644 --- a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/README_EN.md @@ -106,7 +106,19 @@ For the table 12: James, Ratesh and Amadeus order "Fried Chicken". -### Solution 1 +### Solution 1: Hash Table + Sorting + +We can use a hash table $\textit{tables}$ to store the dishes ordered at each table, and a set $\textit{items}$ to store all the dishes. + +Traverse $\textit{orders}$, storing the dishes ordered at each table in $\textit{tables}$ and $\textit{items}$. + +Then we sort $\textit{items}$ to get $\textit{sortedItems}$. + +Next, we construct the answer array $\textit{ans}$. First, add the header row $\textit{header}$ to $\textit{ans}$. Then, traverse the sorted $\textit{tables}$. For each table, use a counter $\textit{cnt}$ to count the number of each dish, then construct a row $\textit{row}$ and add it to $\textit{ans}$. + +Finally, return $\textit{ans}$. + +The time complexity is $O(n + m \times \log m + k \times \log k + m \times k)$, and the space complexity is $O(n + m + k)$. Here, $n$ is the length of the array $\textit{orders}$, while $m$ and $k$ represent the number of dish types and the number of tables, respectively. @@ -115,22 +127,18 @@ For the table 12: James, Ratesh and Amadeus order "Fried Chicken". ```python class Solution: def displayTable(self, orders: List[List[str]]) -> List[List[str]]: - tables = set() - foods = set() - mp = Counter() - for _, table, food in orders: - tables.add(int(table)) - foods.add(food) - mp[f'{table}.{food}'] += 1 - foods = sorted(list(foods)) - tables = sorted(list(tables)) - res = [['Table'] + foods] - for table in tables: - t = [str(table)] - for food in foods: - t.append(str(mp[f'{table}.{food}'])) - res.append(t) - return res + tables = defaultdict(list) + items = set() + for _, table, foodItem in orders: + tables[int(table)].append(foodItem) + items.add(foodItem) + sorted_items = sorted(items) + ans = [["Table"] + sorted_items] + for table in sorted(tables): + cnt = Counter(tables[table]) + row = [str(table)] + [str(cnt[item]) for item in sorted_items] + ans.append(row) + return ans ``` #### Java @@ -138,35 +146,34 @@ class Solution: ```java class Solution { public List> displayTable(List> orders) { - Set tables = new HashSet<>(); - Set foods = new HashSet<>(); - Map mp = new HashMap<>(); - for (List order : orders) { - int table = Integer.parseInt(order.get(1)); - String food = order.get(2); - tables.add(table); - foods.add(food); - String key = table + "." + food; - mp.put(key, mp.getOrDefault(key, 0) + 1); + TreeMap> tables = new TreeMap<>(); + Set items = new HashSet<>(); + for (List o : orders) { + int table = Integer.parseInt(o.get(1)); + String foodItem = o.get(2); + tables.computeIfAbsent(table, k -> new ArrayList<>()).add(foodItem); + items.add(foodItem); } - List t = new ArrayList<>(tables); - List f = new ArrayList<>(foods); - Collections.sort(t); - Collections.sort(f); - List> res = new ArrayList<>(); - List title = new ArrayList<>(); - title.add("Table"); - title.addAll(f); - res.add(title); - for (int table : t) { - List tmp = new ArrayList<>(); - tmp.add(String.valueOf(table)); - for (String food : f) { - tmp.add(String.valueOf(mp.getOrDefault(table + "." + food, 0))); + List sortedItems = new ArrayList<>(items); + Collections.sort(sortedItems); + List> ans = new ArrayList<>(); + List header = new ArrayList<>(); + header.add("Table"); + header.addAll(sortedItems); + ans.add(header); + for (Map.Entry> entry : tables.entrySet()) { + Map cnt = new HashMap<>(); + for (String item : entry.getValue()) { + cnt.merge(item, 1, Integer::sum); + } + List row = new ArrayList<>(); + row.add(String.valueOf(entry.getKey())); + for (String item : sortedItems) { + row.add(String.valueOf(cnt.getOrDefault(item, 0))); } - res.add(tmp); + ans.add(row); } - return res; + return ans; } } ``` @@ -177,36 +184,31 @@ class Solution { class Solution { public: vector> displayTable(vector>& orders) { - unordered_set tables; - unordered_set foods; - unordered_map mp; - for (auto& order : orders) { - int table = stoi(order[1]); - string food = order[2]; - tables.insert(table); - foods.insert(food); - ++mp[order[1] + "." + food]; + map> tables; + set sortedItems; + for (auto& o : orders) { + int table = stoi(o[1]); + string foodItem = o[2]; + tables[table].push_back(foodItem); + sortedItems.insert(foodItem); } - vector t; - t.assign(tables.begin(), tables.end()); - sort(t.begin(), t.end()); - vector f; - f.assign(foods.begin(), foods.end()); - sort(f.begin(), f.end()); - vector> res; - vector title; - title.push_back("Table"); - for (auto e : f) title.push_back(e); - res.push_back(title); - for (int table : t) { - vector tmp; - tmp.push_back(to_string(table)); - for (string food : f) { - tmp.push_back(to_string(mp[to_string(table) + "." + food])); + vector> ans; + vector header = {"Table"}; + header.insert(header.end(), sortedItems.begin(), sortedItems.end()); + ans.push_back(header); + for (auto& [table, items] : tables) { + unordered_map cnt; + for (string& item : items) { + cnt[item]++; + } + vector row; + row.push_back(to_string(table)); + for (const string& item : sortedItems) { + row.push_back(to_string(cnt[item])); } - res.push_back(tmp); + ans.push_back(row); } - return res; + return ans; } }; ``` @@ -215,43 +217,74 @@ public: ```go func displayTable(orders [][]string) [][]string { - tables := make(map[int]bool) - foods := make(map[string]bool) - mp := make(map[string]int) + tables := make(map[int]map[string]int) + items := make(map[string]bool) for _, order := range orders { - table, food := order[1], order[2] - t, _ := strconv.Atoi(table) - tables[t] = true - foods[food] = true - key := table + "." + food - mp[key] += 1 - } - var t []int - var f []string - for i := range tables { - t = append(t, i) + table, _ := strconv.Atoi(order[1]) + foodItem := order[2] + if tables[table] == nil { + tables[table] = make(map[string]int) + } + tables[table][foodItem]++ + items[foodItem] = true } - for i := range foods { - f = append(f, i) + sortedItems := make([]string, 0, len(items)) + for item := range items { + sortedItems = append(sortedItems, item) } - sort.Ints(t) - sort.Strings(f) - var res [][]string - var title []string - title = append(title, "Table") - for _, e := range f { - title = append(title, e) + sort.Strings(sortedItems) + ans := [][]string{} + header := append([]string{"Table"}, sortedItems...) + ans = append(ans, header) + tableNums := make([]int, 0, len(tables)) + for table := range tables { + tableNums = append(tableNums, table) } - res = append(res, title) - for _, table := range t { - var tmp []string - tmp = append(tmp, strconv.Itoa(table)) - for _, food := range f { - tmp = append(tmp, strconv.Itoa(mp[strconv.Itoa(table)+"."+food])) + sort.Ints(tableNums) + for _, table := range tableNums { + row := []string{strconv.Itoa(table)} + for _, item := range sortedItems { + count := tables[table][item] + row = append(row, strconv.Itoa(count)) } - res = append(res, tmp) + ans = append(ans, row) } - return res + return ans +} +``` + +#### TypeScript + +```ts +function displayTable(orders: string[][]): string[][] { + const tables: Record> = {}; + const items: Set = new Set(); + for (const [_, table, foodItem] of orders) { + const t = +table; + if (!tables[t]) { + tables[t] = {}; + } + if (!tables[t][foodItem]) { + tables[t][foodItem] = 0; + } + tables[t][foodItem]++; + items.add(foodItem); + } + const sortedItems = Array.from(items).sort(); + const ans: string[][] = []; + const header: string[] = ['Table', ...sortedItems]; + ans.push(header); + const sortedTableNumbers = Object.keys(tables) + .map(Number) + .sort((a, b) => a - b); + for (const table of sortedTableNumbers) { + const row: string[] = [table.toString()]; + for (const item of sortedItems) { + row.push((tables[table][item] || 0).toString()); + } + ans.push(row); + } + return ans; } ``` diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.cpp b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.cpp index b7f8063cd2d6..dc02597f5995 100644 --- a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.cpp +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.cpp @@ -1,35 +1,30 @@ class Solution { public: vector> displayTable(vector>& orders) { - unordered_set tables; - unordered_set foods; - unordered_map mp; - for (auto& order : orders) { - int table = stoi(order[1]); - string food = order[2]; - tables.insert(table); - foods.insert(food); - ++mp[order[1] + "." + food]; + map> tables; + set sortedItems; + for (auto& o : orders) { + int table = stoi(o[1]); + string foodItem = o[2]; + tables[table].push_back(foodItem); + sortedItems.insert(foodItem); } - vector t; - t.assign(tables.begin(), tables.end()); - sort(t.begin(), t.end()); - vector f; - f.assign(foods.begin(), foods.end()); - sort(f.begin(), f.end()); - vector> res; - vector title; - title.push_back("Table"); - for (auto e : f) title.push_back(e); - res.push_back(title); - for (int table : t) { - vector tmp; - tmp.push_back(to_string(table)); - for (string food : f) { - tmp.push_back(to_string(mp[to_string(table) + "." + food])); + vector> ans; + vector header = {"Table"}; + header.insert(header.end(), sortedItems.begin(), sortedItems.end()); + ans.push_back(header); + for (auto& [table, items] : tables) { + unordered_map cnt; + for (string& item : items) { + cnt[item]++; } - res.push_back(tmp); + vector row; + row.push_back(to_string(table)); + for (const string& item : sortedItems) { + row.push_back(to_string(cnt[item])); + } + ans.push_back(row); } - return res; + return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.go b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.go index 7a438edb87d3..c5e85eae0ada 100644 --- a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.go +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.go @@ -1,39 +1,35 @@ func displayTable(orders [][]string) [][]string { - tables := make(map[int]bool) - foods := make(map[string]bool) - mp := make(map[string]int) + tables := make(map[int]map[string]int) + items := make(map[string]bool) for _, order := range orders { - table, food := order[1], order[2] - t, _ := strconv.Atoi(table) - tables[t] = true - foods[food] = true - key := table + "." + food - mp[key] += 1 - } - var t []int - var f []string - for i := range tables { - t = append(t, i) + table, _ := strconv.Atoi(order[1]) + foodItem := order[2] + if tables[table] == nil { + tables[table] = make(map[string]int) + } + tables[table][foodItem]++ + items[foodItem] = true } - for i := range foods { - f = append(f, i) + sortedItems := make([]string, 0, len(items)) + for item := range items { + sortedItems = append(sortedItems, item) } - sort.Ints(t) - sort.Strings(f) - var res [][]string - var title []string - title = append(title, "Table") - for _, e := range f { - title = append(title, e) + sort.Strings(sortedItems) + ans := [][]string{} + header := append([]string{"Table"}, sortedItems...) + ans = append(ans, header) + tableNums := make([]int, 0, len(tables)) + for table := range tables { + tableNums = append(tableNums, table) } - res = append(res, title) - for _, table := range t { - var tmp []string - tmp = append(tmp, strconv.Itoa(table)) - for _, food := range f { - tmp = append(tmp, strconv.Itoa(mp[strconv.Itoa(table)+"."+food])) + sort.Ints(tableNums) + for _, table := range tableNums { + row := []string{strconv.Itoa(table)} + for _, item := range sortedItems { + count := tables[table][item] + row = append(row, strconv.Itoa(count)) } - res = append(res, tmp) + ans = append(ans, row) } - return res -} \ No newline at end of file + return ans +} diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.java b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.java index 979eda166f2c..1278ccdddb78 100644 --- a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.java +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.java @@ -1,33 +1,32 @@ class Solution { public List> displayTable(List> orders) { - Set tables = new HashSet<>(); - Set foods = new HashSet<>(); - Map mp = new HashMap<>(); - for (List order : orders) { - int table = Integer.parseInt(order.get(1)); - String food = order.get(2); - tables.add(table); - foods.add(food); - String key = table + "." + food; - mp.put(key, mp.getOrDefault(key, 0) + 1); + TreeMap> tables = new TreeMap<>(); + Set items = new HashSet<>(); + for (List o : orders) { + int table = Integer.parseInt(o.get(1)); + String foodItem = o.get(2); + tables.computeIfAbsent(table, k -> new ArrayList<>()).add(foodItem); + items.add(foodItem); } - List t = new ArrayList<>(tables); - List f = new ArrayList<>(foods); - Collections.sort(t); - Collections.sort(f); - List> res = new ArrayList<>(); - List title = new ArrayList<>(); - title.add("Table"); - title.addAll(f); - res.add(title); - for (int table : t) { - List tmp = new ArrayList<>(); - tmp.add(String.valueOf(table)); - for (String food : f) { - tmp.add(String.valueOf(mp.getOrDefault(table + "." + food, 0))); + List sortedItems = new ArrayList<>(items); + Collections.sort(sortedItems); + List> ans = new ArrayList<>(); + List header = new ArrayList<>(); + header.add("Table"); + header.addAll(sortedItems); + ans.add(header); + for (Map.Entry> entry : tables.entrySet()) { + Map cnt = new HashMap<>(); + for (String item : entry.getValue()) { + cnt.merge(item, 1, Integer::sum); } - res.add(tmp); + List row = new ArrayList<>(); + row.add(String.valueOf(entry.getKey())); + for (String item : sortedItems) { + row.add(String.valueOf(cnt.getOrDefault(item, 0))); + } + ans.add(row); } - return res; + return ans; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.py b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.py index e602f22e225c..888ea4476689 100644 --- a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.py +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.py @@ -1,18 +1,14 @@ class Solution: def displayTable(self, orders: List[List[str]]) -> List[List[str]]: - tables = set() - foods = set() - mp = Counter() - for _, table, food in orders: - tables.add(int(table)) - foods.add(food) - mp[f'{table}.{food}'] += 1 - foods = sorted(list(foods)) - tables = sorted(list(tables)) - res = [['Table'] + foods] - for table in tables: - t = [str(table)] - for food in foods: - t.append(str(mp[f'{table}.{food}'])) - res.append(t) - return res + tables = defaultdict(list) + items = set() + for _, table, foodItem in orders: + tables[int(table)].append(foodItem) + items.add(foodItem) + sorted_items = sorted(items) + ans = [["Table"] + sorted_items] + for table in sorted(tables): + cnt = Counter(tables[table]) + row = [str(table)] + [str(cnt[item]) for item in sorted_items] + ans.append(row) + return ans diff --git a/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.ts b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.ts new file mode 100644 index 000000000000..a8d4d398a86c --- /dev/null +++ b/solution/1400-1499/1418.Display Table of Food Orders in a Restaurant/Solution.ts @@ -0,0 +1,30 @@ +function displayTable(orders: string[][]): string[][] { + const tables: Record> = {}; + const items: Set = new Set(); + for (const [_, table, foodItem] of orders) { + const t = +table; + if (!tables[t]) { + tables[t] = {}; + } + if (!tables[t][foodItem]) { + tables[t][foodItem] = 0; + } + tables[t][foodItem]++; + items.add(foodItem); + } + const sortedItems = Array.from(items).sort(); + const ans: string[][] = []; + const header: string[] = ['Table', ...sortedItems]; + ans.push(header); + const sortedTableNumbers = Object.keys(tables) + .map(Number) + .sort((a, b) => a - b); + for (const table of sortedTableNumbers) { + const row: string[] = [table.toString()]; + for (const item of sortedItems) { + row.push((tables[table][item] || 0).toString()); + } + ans.push(row); + } + return ans; +} diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md b/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md index 3bbc25b38b79..d50488763f9c 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md @@ -66,7 +66,13 @@ tags: -### 方法一 +### 方法一:计数 + +我们用两个变量 $l$ 和 $r$ 分别记录左子字符串中 $0$ 的数量和右子字符串中 $1$ 的数量。初始时 $l = 0$,而 $r$ 则等于字符串 $s$ 中 $1$ 的数量。 + +遍历字符串 $s$ 的前 $n - 1$ 个字符,对于每一个位置 $i$,如果 $s[i] = 0$,则 $l$ 自增 $1$,否则 $r$ 自减 $1$。然后我们更新答案为 $l + r$ 的最大值。 + +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$。 @@ -75,7 +81,13 @@ tags: ```python class Solution: def maxScore(self, s: str) -> int: - return max(s[:i].count('0') + s[i:].count('1') for i in range(1, len(s))) + l, r = 0, s.count("1") + ans = 0 + for x in s[:-1]: + l += int(x) ^ 1 + r -= int(x) + ans = max(ans, l + r) + return ans ``` #### Java @@ -83,20 +95,18 @@ class Solution: ```java class Solution { public int maxScore(String s) { - int ans = 0; - for (int i = 1; i < s.length(); ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - if (s.charAt(j) == '0') { - ++t; - } - } - for (int j = i; j < s.length(); ++j) { - if (s.charAt(j) == '1') { - ++t; - } + int l = 0, r = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++r; } - ans = Math.max(ans, t); + } + int ans = 0; + for (int i = 0; i < n - 1; ++i) { + l += (s.charAt(i) - '0') ^ 1; + r -= s.charAt(i) - '0'; + ans = Math.max(ans, l + r); } return ans; } @@ -109,16 +119,12 @@ class Solution { class Solution { public: int maxScore(string s) { + int l = 0, r = count(s.begin(), s.end(), '1'); int ans = 0; - for (int i = 1, n = s.size(); i < n; ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - t += s[j] == '0'; - } - for (int j = i; j < n; ++j) { - t += s[j] == '1'; - } - ans = max(ans, t); + for (int i = 0; i < s.size() - 1; ++i) { + l += (s[i] - '0') ^ 1; + r -= s[i] - '0'; + ans = max(ans, l + r); } return ans; } @@ -128,23 +134,17 @@ public: #### Go ```go -func maxScore(s string) int { - ans := 0 - for i, n := 1, len(s); i < n; i++ { - t := 0 - for j := 0; j < i; j++ { - if s[j] == '0' { - t++ - } - } - for j := i; j < n; j++ { - if s[j] == '1' { - t++ - } +func maxScore(s string) (ans int) { + l, r := 0, strings.Count(s, "1") + for _, c := range s[:len(s)-1] { + if c == '0' { + l++ + } else { + r-- } - ans = max(ans, t) + ans = max(ans, l+r) } - return ans + return } ``` @@ -152,27 +152,20 @@ func maxScore(s string) int { ```ts function maxScore(s: string): number { - const n = s.length; - let res = 0; - let score = 0; - if (s[0] === '0') { - score++; - } - for (let i = 1; i < n; i++) { - if (s[i] === '1') { - score++; - } + let [l, r] = [0, 0]; + for (const c of s) { + r += c === '1' ? 1 : 0; } - res = Math.max(res, score); - for (let i = 1; i < n - 1; i++) { + let ans = 0; + for (let i = 0; i < s.length - 1; ++i) { if (s[i] === '0') { - score++; - } else if (s[i] === '1') { - score--; + ++l; + } else { + --r; } - res = Math.max(res, score); + ans = Math.max(ans, l + r); } - return res; + return ans; } ``` @@ -181,28 +174,16 @@ function maxScore(s: string): number { ```rust impl Solution { pub fn max_score(s: String) -> i32 { - let n = s.len(); - let mut res = 0; - let mut score = 0; - let bs = s.as_bytes(); - if bs[0] == b'0' { - score += 1; - } - for i in 1..n { - if bs[i] == b'1' { - score += 1; - } - } - res = res.max(score); - for i in 1..n - 1 { - if bs[i] == b'0' { - score += 1; - } else if bs[i] == b'1' { - score -= 1; - } - res = res.max(score); + let mut l = 0; + let mut r = s.bytes().filter(|&b| b == b'1').count() as i32; + let mut ans = 0; + let cs = s.as_bytes(); + for i in 0..s.len() - 1 { + l += ((cs[i] - b'0') ^ 1) as i32; + r -= (cs[i] - b'0') as i32; + ans = ans.max(l + r); } - res + ans } } ``` @@ -211,96 +192,4 @@ impl Solution { - - -### 方法二 - - - -#### Python3 - -```python -class Solution: - def maxScore(self, s: str) -> int: - ans = t = (s[0] == '0') + s[1:].count('1') - for i in range(1, len(s) - 1): - t += 1 if s[i] == '0' else -1 - ans = max(ans, t) - return ans -``` - -#### Java - -```java -class Solution { - public int maxScore(String s) { - int t = 0; - if (s.charAt(0) == '0') { - t++; - } - for (int i = 1; i < s.length(); ++i) { - if (s.charAt(i) == '1') { - t++; - } - } - int ans = t; - for (int i = 1; i < s.length() - 1; ++i) { - t += s.charAt(i) == '0' ? 1 : -1; - ans = Math.max(ans, t); - } - return ans; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int maxScore(string s) { - int t = 0; - if (s[0] == '0') ++t; - for (int i = 1; i < s.size(); ++i) t += s[i] == '1'; - int ans = t; - for (int i = 1; i < s.size() - 1; ++i) { - t += s[i] == '0' ? 1 : -1; - ans = max(ans, t); - } - return ans; - } -}; -``` - -#### Go - -```go -func maxScore(s string) int { - t := 0 - if s[0] == '0' { - t++ - } - n := len(s) - for i := 1; i < n; i++ { - if s[i] == '1' { - t++ - } - } - ans := t - for i := 1; i < n-1; i++ { - if s[i] == '0' { - t++ - } else { - t-- - } - ans = max(ans, t) - } - return ans -} -``` - - - - - diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md b/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md index 835d2d1d96ed..bf81c6a27ca2 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md @@ -67,7 +67,13 @@ left = "01110" and right = "1", score = 2 + 1 = 3 -### Solution 1 +### Solution 1: Counting + +We use two variables $l$ and $r$ to record the number of 0s in the left substring and the number of 1s in the right substring, respectively. Initially, $l = 0$, and $r$ is equal to the number of 1s in the string $s$. + +We traverse the first $n - 1$ characters of the string $s$. For each position $i$, if $s[i] = 0$, then $l$ is incremented by 1; otherwise, $r$ is decremented by 1. Then we update the answer to be the maximum value of $l + r$. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. @@ -76,7 +82,13 @@ left = "01110" and right = "1", score = 2 + 1 = 3 ```python class Solution: def maxScore(self, s: str) -> int: - return max(s[:i].count('0') + s[i:].count('1') for i in range(1, len(s))) + l, r = 0, s.count("1") + ans = 0 + for x in s[:-1]: + l += int(x) ^ 1 + r -= int(x) + ans = max(ans, l + r) + return ans ``` #### Java @@ -84,20 +96,18 @@ class Solution: ```java class Solution { public int maxScore(String s) { - int ans = 0; - for (int i = 1; i < s.length(); ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - if (s.charAt(j) == '0') { - ++t; - } - } - for (int j = i; j < s.length(); ++j) { - if (s.charAt(j) == '1') { - ++t; - } + int l = 0, r = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++r; } - ans = Math.max(ans, t); + } + int ans = 0; + for (int i = 0; i < n - 1; ++i) { + l += (s.charAt(i) - '0') ^ 1; + r -= s.charAt(i) - '0'; + ans = Math.max(ans, l + r); } return ans; } @@ -110,16 +120,12 @@ class Solution { class Solution { public: int maxScore(string s) { + int l = 0, r = count(s.begin(), s.end(), '1'); int ans = 0; - for (int i = 1, n = s.size(); i < n; ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - t += s[j] == '0'; - } - for (int j = i; j < n; ++j) { - t += s[j] == '1'; - } - ans = max(ans, t); + for (int i = 0; i < s.size() - 1; ++i) { + l += (s[i] - '0') ^ 1; + r -= s[i] - '0'; + ans = max(ans, l + r); } return ans; } @@ -129,23 +135,17 @@ public: #### Go ```go -func maxScore(s string) int { - ans := 0 - for i, n := 1, len(s); i < n; i++ { - t := 0 - for j := 0; j < i; j++ { - if s[j] == '0' { - t++ - } - } - for j := i; j < n; j++ { - if s[j] == '1' { - t++ - } +func maxScore(s string) (ans int) { + l, r := 0, strings.Count(s, "1") + for _, c := range s[:len(s)-1] { + if c == '0' { + l++ + } else { + r-- } - ans = max(ans, t) + ans = max(ans, l+r) } - return ans + return } ``` @@ -153,27 +153,20 @@ func maxScore(s string) int { ```ts function maxScore(s: string): number { - const n = s.length; - let res = 0; - let score = 0; - if (s[0] === '0') { - score++; - } - for (let i = 1; i < n; i++) { - if (s[i] === '1') { - score++; - } + let [l, r] = [0, 0]; + for (const c of s) { + r += c === '1' ? 1 : 0; } - res = Math.max(res, score); - for (let i = 1; i < n - 1; i++) { + let ans = 0; + for (let i = 0; i < s.length - 1; ++i) { if (s[i] === '0') { - score++; - } else if (s[i] === '1') { - score--; + ++l; + } else { + --r; } - res = Math.max(res, score); + ans = Math.max(ans, l + r); } - return res; + return ans; } ``` @@ -182,28 +175,16 @@ function maxScore(s: string): number { ```rust impl Solution { pub fn max_score(s: String) -> i32 { - let n = s.len(); - let mut res = 0; - let mut score = 0; - let bs = s.as_bytes(); - if bs[0] == b'0' { - score += 1; - } - for i in 1..n { - if bs[i] == b'1' { - score += 1; - } - } - res = res.max(score); - for i in 1..n - 1 { - if bs[i] == b'0' { - score += 1; - } else if bs[i] == b'1' { - score -= 1; - } - res = res.max(score); + let mut l = 0; + let mut r = s.bytes().filter(|&b| b == b'1').count() as i32; + let mut ans = 0; + let cs = s.as_bytes(); + for i in 0..s.len() - 1 { + l += ((cs[i] - b'0') ^ 1) as i32; + r -= (cs[i] - b'0') as i32; + ans = ans.max(l + r); } - res + ans } } ``` @@ -212,96 +193,4 @@ impl Solution { - - -### Solution 2 - - - -#### Python3 - -```python -class Solution: - def maxScore(self, s: str) -> int: - ans = t = (s[0] == '0') + s[1:].count('1') - for i in range(1, len(s) - 1): - t += 1 if s[i] == '0' else -1 - ans = max(ans, t) - return ans -``` - -#### Java - -```java -class Solution { - public int maxScore(String s) { - int t = 0; - if (s.charAt(0) == '0') { - t++; - } - for (int i = 1; i < s.length(); ++i) { - if (s.charAt(i) == '1') { - t++; - } - } - int ans = t; - for (int i = 1; i < s.length() - 1; ++i) { - t += s.charAt(i) == '0' ? 1 : -1; - ans = Math.max(ans, t); - } - return ans; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int maxScore(string s) { - int t = 0; - if (s[0] == '0') ++t; - for (int i = 1; i < s.size(); ++i) t += s[i] == '1'; - int ans = t; - for (int i = 1; i < s.size() - 1; ++i) { - t += s[i] == '0' ? 1 : -1; - ans = max(ans, t); - } - return ans; - } -}; -``` - -#### Go - -```go -func maxScore(s string) int { - t := 0 - if s[0] == '0' { - t++ - } - n := len(s) - for i := 1; i < n; i++ { - if s[i] == '1' { - t++ - } - } - ans := t - for i := 1; i < n-1; i++ { - if s[i] == '0' { - t++ - } else { - t-- - } - ans = max(ans, t) - } - return ans -} -``` - - - - - diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp index f78ec22439dc..bf8dbbfefbf6 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp @@ -1,17 +1,13 @@ class Solution { public: int maxScore(string s) { + int l = 0, r = count(s.begin(), s.end(), '1'); int ans = 0; - for (int i = 1, n = s.size(); i < n; ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - t += s[j] == '0'; - } - for (int j = i; j < n; ++j) { - t += s[j] == '1'; - } - ans = max(ans, t); + for (int i = 0; i < s.size() - 1; ++i) { + l += (s[i] - '0') ^ 1; + r -= s[i] - '0'; + ans = max(ans, l + r); } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go index 901ebc0bb852..8c30ed90ece9 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go @@ -1,18 +1,12 @@ -func maxScore(s string) int { - ans := 0 - for i, n := 1, len(s); i < n; i++ { - t := 0 - for j := 0; j < i; j++ { - if s[j] == '0' { - t++ - } +func maxScore(s string) (ans int) { + l, r := 0, strings.Count(s, "1") + for _, c := range s[:len(s)-1] { + if c == '0' { + l++ + } else { + r-- } - for j := i; j < n; j++ { - if s[j] == '1' { - t++ - } - } - ans = max(ans, t) + ans = max(ans, l+r) } - return ans -} \ No newline at end of file + return +} diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java index e3dad9d463fe..62f0ab147858 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java @@ -1,20 +1,18 @@ class Solution { public int maxScore(String s) { - int ans = 0; - for (int i = 1; i < s.length(); ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - if (s.charAt(j) == '0') { - ++t; - } - } - for (int j = i; j < s.length(); ++j) { - if (s.charAt(j) == '1') { - ++t; - } + int l = 0, r = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++r; } - ans = Math.max(ans, t); + } + int ans = 0; + for (int i = 0; i < n - 1; ++i) { + l += (s.charAt(i) - '0') ^ 1; + r -= s.charAt(i) - '0'; + ans = Math.max(ans, l + r); } return ans; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py index ab07d81eec3e..57827a3472cf 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py @@ -1,3 +1,9 @@ class Solution: def maxScore(self, s: str) -> int: - return max(s[:i].count('0') + s[i:].count('1') for i in range(1, len(s))) + l, r = 0, s.count("1") + ans = 0 + for x in s[:-1]: + l += int(x) ^ 1 + r -= int(x) + ans = max(ans, l + r) + return ans diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs index 4f7142e3d759..a88411fb0c0f 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs @@ -1,26 +1,14 @@ impl Solution { pub fn max_score(s: String) -> i32 { - let n = s.len(); - let mut res = 0; - let mut score = 0; - let bs = s.as_bytes(); - if bs[0] == b'0' { - score += 1; + let mut l = 0; + let mut r = s.bytes().filter(|&b| b == b'1').count() as i32; + let mut ans = 0; + let cs = s.as_bytes(); + for i in 0..s.len() - 1 { + l += ((cs[i] - b'0') ^ 1) as i32; + r -= (cs[i] - b'0') as i32; + ans = ans.max(l + r); } - for i in 1..n { - if bs[i] == b'1' { - score += 1; - } - } - res = res.max(score); - for i in 1..n - 1 { - if bs[i] == b'0' { - score += 1; - } else if bs[i] == b'1' { - score -= 1; - } - res = res.max(score); - } - res + ans } } diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts index f8253a850377..398485704c0c 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts @@ -1,23 +1,16 @@ function maxScore(s: string): number { - const n = s.length; - let res = 0; - let score = 0; - if (s[0] === '0') { - score++; + let [l, r] = [0, 0]; + for (const c of s) { + r += c === '1' ? 1 : 0; } - for (let i = 1; i < n; i++) { - if (s[i] === '1') { - score++; - } - } - res = Math.max(res, score); - for (let i = 1; i < n - 1; i++) { + let ans = 0; + for (let i = 0; i < s.length - 1; ++i) { if (s[i] === '0') { - score++; - } else if (s[i] === '1') { - score--; + ++l; + } else { + --r; } - res = Math.max(res, score); + ans = Math.max(ans, l + r); } - return res; + return ans; } diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.cpp b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.cpp deleted file mode 100644 index 3109efd6356e..000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.cpp +++ /dev/null @@ -1,14 +0,0 @@ -class Solution { -public: - int maxScore(string s) { - int t = 0; - if (s[0] == '0') ++t; - for (int i = 1; i < s.size(); ++i) t += s[i] == '1'; - int ans = t; - for (int i = 1; i < s.size() - 1; ++i) { - t += s[i] == '0' ? 1 : -1; - ans = max(ans, t); - } - return ans; - } -}; \ No newline at end of file diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.go b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.go deleted file mode 100644 index 26aad8e48a85..000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.go +++ /dev/null @@ -1,22 +0,0 @@ -func maxScore(s string) int { - t := 0 - if s[0] == '0' { - t++ - } - n := len(s) - for i := 1; i < n; i++ { - if s[i] == '1' { - t++ - } - } - ans := t - for i := 1; i < n-1; i++ { - if s[i] == '0' { - t++ - } else { - t-- - } - ans = max(ans, t) - } - return ans -} \ No newline at end of file diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.java b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.java deleted file mode 100644 index 2af2f65f0d49..000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.java +++ /dev/null @@ -1,19 +0,0 @@ -class Solution { - public int maxScore(String s) { - int t = 0; - if (s.charAt(0) == '0') { - t++; - } - for (int i = 1; i < s.length(); ++i) { - if (s.charAt(i) == '1') { - t++; - } - } - int ans = t; - for (int i = 1; i < s.length() - 1; ++i) { - t += s.charAt(i) == '0' ? 1 : -1; - ans = Math.max(ans, t); - } - return ans; - } -} \ No newline at end of file diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.py b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.py deleted file mode 100644 index 04eb3724a077..000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.py +++ /dev/null @@ -1,7 +0,0 @@ -class Solution: - def maxScore(self, s: str) -> int: - ans = t = (s[0] == '0') + s[1:].count('1') - for i in range(1, len(s) - 1): - t += 1 if s[i] == '0' else -1 - ans = max(ans, t) - return ans diff --git a/solution/1400-1499/1424.Diagonal Traverse II/README.md b/solution/1400-1499/1424.Diagonal Traverse II/README.md index 48385ce57002..f515c1235455 100644 --- a/solution/1400-1499/1424.Diagonal Traverse II/README.md +++ b/solution/1400-1499/1424.Diagonal Traverse II/README.md @@ -77,9 +77,9 @@ tags: - 下一条对角线的 $i + j$ 的值比前一条对角线的大; - 在同一条对角线中的 $i + j$ 是相同的,而 $j$ 值是从小到大递增。 -因此,我们将所有数字以 `(i + j, j, nums[i][j])` 的形式存进 `arr`,然后按照前两项排序。最后返回 `arr` 所有元素第二项组成的数组即可。 +因此,我们将所有数字以 $(i, j, \textit{nums}[i][j])$ 的形式存进 $\textit{arr}$,然后按照前两项排序。最后返回 $\textit{arr}$ 所有元素下标为 $2$ 的值组成的数组即可。 -时间复杂度 $O(n\log n)$,其中 $n$ 是 `nums` 数组元素的个数。 +时间复杂度 $O(n \times \log n)$,其中 $n$ 是数组 $\textit{nums}$ 中元素的个数。空间复杂度 $O(n)$。 @@ -163,6 +163,21 @@ func findDiagonalOrder(nums [][]int) []int { } ``` +#### TypeScript + +```ts +function findDiagonalOrder(nums: number[][]): number[] { + const arr: number[][] = []; + for (let i = 0; i < nums.length; ++i) { + for (let j = 0; j < nums[i].length; ++j) { + arr.push([i + j, j, nums[i][j]]); + } + } + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => x[2]); +} +``` + #### C# ```cs diff --git a/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md b/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md index d3001f93376b..0e428edd54e2 100644 --- a/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md +++ b/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md @@ -53,7 +53,17 @@ tags: -### Solution 1 +### Solution 1: Sorting + +We observe that: + +- The value of $i + j$ is the same for each diagonal; +- The value of $i + j$ for the next diagonal is greater than that of the previous diagonal; +- Within the same diagonal, the value of $i + j$ is the same, and the value of $j$ increases from small to large. + +Therefore, we store all numbers in the form of $(i, j, \textit{nums}[i][j])$ into $\textit{arr}$, and then sort according to the first two items. Finally, return the array composed of the values at index 2 of all elements in $\textit{arr}$. + +The time complexity is $O(n \times \log n)$, where $n$ is the number of elements in the array $\textit{nums}$. The space complexity is $O(n)$. @@ -137,6 +147,21 @@ func findDiagonalOrder(nums [][]int) []int { } ``` +#### TypeScript + +```ts +function findDiagonalOrder(nums: number[][]): number[] { + const arr: number[][] = []; + for (let i = 0; i < nums.length; ++i) { + for (let j = 0; j < nums[i].length; ++j) { + arr.push([i + j, j, nums[i][j]]); + } + } + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => x[2]); +} +``` + #### C# ```cs diff --git a/solution/1400-1499/1424.Diagonal Traverse II/Solution.ts b/solution/1400-1499/1424.Diagonal Traverse II/Solution.ts new file mode 100644 index 000000000000..bd3c93ca6fd9 --- /dev/null +++ b/solution/1400-1499/1424.Diagonal Traverse II/Solution.ts @@ -0,0 +1,10 @@ +function findDiagonalOrder(nums: number[][]): number[] { + const arr: number[][] = []; + for (let i = 0; i < nums.length; ++i) { + for (let j = 0; j < nums[i].length; ++j) { + arr.push([i + j, j, nums[i][j]]); + } + } + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => x[2]); +} diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/README.md b/solution/1400-1499/1425.Constrained Subsequence Sum/README.md index f96e8760a7d7..3fd8621508fc 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/README.md +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/README.md @@ -67,6 +67,23 @@ tags: ### 方法一:动态规划 + 单调队列 +我们定义 $f[i]$ 表示以 $\textit{nums}[i]$ 结尾的满足条件的子序列的最大和。初始时 $f[i] = 0$,答案为 $\max_{0 \leq i \lt n} f(i)$。 + +我们注意到题目需要我们维护滑动窗口的最大值,这就是一个典型的单调队列应用场景。我们可以使用单调队列来优化动态规划的转移。 + +我们维护一个从队首到队尾单调递减的单调队列 $q$,队列中存储的是下标 $i$,初始时,我们将一个哨兵 $0$ 加入队列中。 + +我们遍历 $i$ 从 $0$ 到 $n - 1$,对于每个 $i$,我们执行以下操作: + +- 如果队首元素 $q[0]$ 满足 $i - q[0] > k$,说明队首元素已经不在滑动窗口内,我们需要从队首弹出队首元素; +- 然后,我们计算 $f[i] = \max(0, f[q[0]]) + \textit{nums}[i]$,表示我们将 $\textit{nums}[i]$ 加入滑动窗口后的最大子序列和; +- 接下来,我们更新答案 $\textit{ans} = \max(\textit{ans}, f[i])$; +- 最后,我们将 $i$ 加入队列尾部,并且保持队列的单调性,即如果 $f[q[\textit{back}]] \leq f[i]$,我们需要将队尾元素弹出,直到队列为空或者 $f[q[\textit{back}]] > f[i]$。 + +最终答案即为 $\textit{ans}$。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 + #### Python3 @@ -74,18 +91,18 @@ tags: ```python class Solution: def constrainedSubsetSum(self, nums: List[int], k: int) -> int: + q = deque([0]) n = len(nums) - dp = [0] * n + f = [0] * n ans = -inf - q = deque() - for i, v in enumerate(nums): - if q and i - q[0] > k: + for i, x in enumerate(nums): + while i - q[0] > k: q.popleft() - dp[i] = max(0, 0 if not q else dp[q[0]]) + v - while q and dp[q[-1]] <= dp[i]: + f[i] = max(0, f[q[0]]) + x + ans = max(ans, f[i]) + while q and f[q[-1]] <= f[i]: q.pop() q.append(i) - ans = max(ans, dp[i]) return ans ``` @@ -94,20 +111,21 @@ class Solution: ```java class Solution { public int constrainedSubsetSum(int[] nums, int k) { - int n = nums.length; - int[] dp = new int[n]; - int ans = Integer.MIN_VALUE; Deque q = new ArrayDeque<>(); + q.offer(0); + int n = nums.length; + int[] f = new int[n]; + int ans = -(1 << 30); for (int i = 0; i < n; ++i) { - if (!q.isEmpty() && i - q.peek() > k) { - q.poll(); + while (i - q.peekFirst() > k) { + q.pollFirst(); } - dp[i] = Math.max(0, q.isEmpty() ? 0 : dp[q.peek()]) + nums[i]; - while (!q.isEmpty() && dp[q.peekLast()] <= dp[i]) { + f[i] = Math.max(0, f[q.peekFirst()]) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.peekLast()] <= f[i]) { q.pollLast(); } - q.offer(i); - ans = Math.max(ans, dp[i]); + q.offerLast(i); } return ans; } @@ -120,15 +138,20 @@ class Solution { class Solution { public: int constrainedSubsetSum(vector& nums, int k) { + deque q = {0}; int n = nums.size(); - vector dp(n); + int f[n]; + f[0] = 0; int ans = INT_MIN; - deque q; for (int i = 0; i < n; ++i) { - if (!q.empty() && i - q.front() > k) q.pop_front(); - dp[i] = max(0, q.empty() ? 0 : dp[q.front()]) + nums[i]; - ans = max(ans, dp[i]); - while (!q.empty() && dp[q.back()] <= dp[i]) q.pop_back(); + while (i - q.front() > k) { + q.pop_front(); + } + f[i] = max(0, f[q.front()]) + nums[i]; + ans = max(ans, f[i]); + while (!q.empty() && f[q.back()] <= f[i]) { + q.pop_back(); + } q.push_back(i); } return ans; @@ -140,26 +163,202 @@ public: ```go func constrainedSubsetSum(nums []int, k int) int { + q := Deque{} + q.PushFront(0) n := len(nums) - dp := make([]int, n) - ans := math.MinInt32 - q := []int{} - for i, v := range nums { - if len(q) > 0 && i-q[0] > k { - q = q[1:] - } - dp[i] = v - if len(q) > 0 && dp[q[0]] > 0 { - dp[i] += dp[q[0]] + f := make([]int, n) + ans := nums[0] + for i, x := range nums { + for i-q.Front() > k { + q.PopFront() } - for len(q) > 0 && dp[q[len(q)-1]] < dp[i] { - q = q[:len(q)-1] + f[i] = max(0, f[q.Front()]) + x + ans = max(ans, f[i]) + for !q.Empty() && f[q.Back()] <= f[i] { + q.PopBack() } - q = append(q, i) - ans = max(ans, dp[i]) + q.PushBack(i) } return ans } + +// template +type Deque struct{ l, r []int } + +func (q Deque) Empty() bool { + return len(q.l) == 0 && len(q.r) == 0 +} + +func (q Deque) Size() int { + return len(q.l) + len(q.r) +} + +func (q *Deque) PushFront(v int) { + q.l = append(q.l, v) +} + +func (q *Deque) PushBack(v int) { + q.r = append(q.r, v) +} + +func (q *Deque) PopFront() (v int) { + if len(q.l) > 0 { + q.l, v = q.l[:len(q.l)-1], q.l[len(q.l)-1] + } else { + v, q.r = q.r[0], q.r[1:] + } + return +} + +func (q *Deque) PopBack() (v int) { + if len(q.r) > 0 { + q.r, v = q.r[:len(q.r)-1], q.r[len(q.r)-1] + } else { + v, q.l = q.l[0], q.l[1:] + } + return +} + +func (q Deque) Front() int { + if len(q.l) > 0 { + return q.l[len(q.l)-1] + } + return q.r[0] +} + +func (q Deque) Back() int { + if len(q.r) > 0 { + return q.r[len(q.r)-1] + } + return q.l[0] +} + +func (q Deque) Get(i int) int { + if i < len(q.l) { + return q.l[len(q.l)-1-i] + } + return q.r[i-len(q.l)] +} +``` + +#### TypeScript + +```ts +function constrainedSubsetSum(nums: number[], k: number): number { + const q = new Deque(); + const n = nums.length; + q.pushBack(0); + let ans = nums[0]; + const f: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + while (i - q.frontValue()! > k) { + q.popFront(); + } + f[i] = Math.max(0, f[q.frontValue()!]!) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.backValue()!]! <= f[i]) { + q.popBack(); + } + q.pushBack(i); + } + return ans; +} + +class Node { + value: T; + next: Node | null; + prev: Node | null; + + constructor(value: T) { + this.value = value; + this.next = null; + this.prev = null; + } +} + +class Deque { + private front: Node | null; + private back: Node | null; + private size: number; + + constructor() { + this.front = null; + this.back = null; + this.size = 0; + } + + pushFront(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.next = this.front; + this.front!.prev = newNode; + this.front = newNode; + } + this.size++; + } + + pushBack(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.prev = this.back; + this.back!.next = newNode; + this.back = newNode; + } + this.size++; + } + + popFront(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.front!.value; + this.front = this.front!.next; + if (this.front !== null) { + this.front.prev = null; + } else { + this.back = null; + } + this.size--; + return value; + } + + popBack(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.back!.value; + this.back = this.back!.prev; + if (this.back !== null) { + this.back.next = null; + } else { + this.front = null; + } + this.size--; + return value; + } + + frontValue(): T | undefined { + return this.front?.value; + } + + backValue(): T | undefined { + return this.back?.value; + } + + getSize(): number { + return this.size; + } + + isEmpty(): boolean { + return this.size === 0; + } +} ``` diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md b/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md index ba1cc253f159..f54456af1319 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md @@ -66,7 +66,24 @@ tags: -### Solution 1 +### Solution 1: Dynamic Programming + Monotonic Queue + +We define $f[i]$ to represent the maximum sum of the subsequence ending at $\textit{nums}[i]$ that meets the conditions. Initially, $f[i] = 0$, and the answer is $\max_{0 \leq i \lt n} f(i)$. + +We notice that the problem requires us to maintain the maximum value of a sliding window, which is a typical application scenario for a monotonic queue. We can use a monotonic queue to optimize the dynamic programming transition. + +We maintain a monotonic queue $q$ that is decreasing from the front to the back, storing the indices $i$. Initially, we add a sentinel $0$ to the queue. + +We traverse $i$ from $0$ to $n - 1$. For each $i$, we perform the following operations: + +- If the front element $q[0]$ satisfies $i - q[0] > k$, it means the front element is no longer within the sliding window, and we need to remove the front element from the queue; +- Then, we calculate $f[i] = \max(0, f[q[0]]) + \textit{nums}[i]$, which means we add $\textit{nums}[i]$ to the sliding window to get the maximum subsequence sum; +- Next, we update the answer $\textit{ans} = \max(\textit{ans}, f[i])$; +- Finally, we add $i$ to the back of the queue and maintain the monotonicity of the queue. If $f[q[\textit{back}]] \leq f[i]$, we need to remove the back element until the queue is empty or $f[q[\textit{back}]] > f[i]$. + +The final answer is $\textit{ans}$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -75,18 +92,18 @@ tags: ```python class Solution: def constrainedSubsetSum(self, nums: List[int], k: int) -> int: + q = deque([0]) n = len(nums) - dp = [0] * n + f = [0] * n ans = -inf - q = deque() - for i, v in enumerate(nums): - if q and i - q[0] > k: + for i, x in enumerate(nums): + while i - q[0] > k: q.popleft() - dp[i] = max(0, 0 if not q else dp[q[0]]) + v - while q and dp[q[-1]] <= dp[i]: + f[i] = max(0, f[q[0]]) + x + ans = max(ans, f[i]) + while q and f[q[-1]] <= f[i]: q.pop() q.append(i) - ans = max(ans, dp[i]) return ans ``` @@ -95,20 +112,21 @@ class Solution: ```java class Solution { public int constrainedSubsetSum(int[] nums, int k) { - int n = nums.length; - int[] dp = new int[n]; - int ans = Integer.MIN_VALUE; Deque q = new ArrayDeque<>(); + q.offer(0); + int n = nums.length; + int[] f = new int[n]; + int ans = -(1 << 30); for (int i = 0; i < n; ++i) { - if (!q.isEmpty() && i - q.peek() > k) { - q.poll(); + while (i - q.peekFirst() > k) { + q.pollFirst(); } - dp[i] = Math.max(0, q.isEmpty() ? 0 : dp[q.peek()]) + nums[i]; - while (!q.isEmpty() && dp[q.peekLast()] <= dp[i]) { + f[i] = Math.max(0, f[q.peekFirst()]) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.peekLast()] <= f[i]) { q.pollLast(); } - q.offer(i); - ans = Math.max(ans, dp[i]); + q.offerLast(i); } return ans; } @@ -121,15 +139,20 @@ class Solution { class Solution { public: int constrainedSubsetSum(vector& nums, int k) { + deque q = {0}; int n = nums.size(); - vector dp(n); + int f[n]; + f[0] = 0; int ans = INT_MIN; - deque q; for (int i = 0; i < n; ++i) { - if (!q.empty() && i - q.front() > k) q.pop_front(); - dp[i] = max(0, q.empty() ? 0 : dp[q.front()]) + nums[i]; - ans = max(ans, dp[i]); - while (!q.empty() && dp[q.back()] <= dp[i]) q.pop_back(); + while (i - q.front() > k) { + q.pop_front(); + } + f[i] = max(0, f[q.front()]) + nums[i]; + ans = max(ans, f[i]); + while (!q.empty() && f[q.back()] <= f[i]) { + q.pop_back(); + } q.push_back(i); } return ans; @@ -141,26 +164,202 @@ public: ```go func constrainedSubsetSum(nums []int, k int) int { + q := Deque{} + q.PushFront(0) n := len(nums) - dp := make([]int, n) - ans := math.MinInt32 - q := []int{} - for i, v := range nums { - if len(q) > 0 && i-q[0] > k { - q = q[1:] - } - dp[i] = v - if len(q) > 0 && dp[q[0]] > 0 { - dp[i] += dp[q[0]] + f := make([]int, n) + ans := nums[0] + for i, x := range nums { + for i-q.Front() > k { + q.PopFront() } - for len(q) > 0 && dp[q[len(q)-1]] < dp[i] { - q = q[:len(q)-1] + f[i] = max(0, f[q.Front()]) + x + ans = max(ans, f[i]) + for !q.Empty() && f[q.Back()] <= f[i] { + q.PopBack() } - q = append(q, i) - ans = max(ans, dp[i]) + q.PushBack(i) } return ans } + +// template +type Deque struct{ l, r []int } + +func (q Deque) Empty() bool { + return len(q.l) == 0 && len(q.r) == 0 +} + +func (q Deque) Size() int { + return len(q.l) + len(q.r) +} + +func (q *Deque) PushFront(v int) { + q.l = append(q.l, v) +} + +func (q *Deque) PushBack(v int) { + q.r = append(q.r, v) +} + +func (q *Deque) PopFront() (v int) { + if len(q.l) > 0 { + q.l, v = q.l[:len(q.l)-1], q.l[len(q.l)-1] + } else { + v, q.r = q.r[0], q.r[1:] + } + return +} + +func (q *Deque) PopBack() (v int) { + if len(q.r) > 0 { + q.r, v = q.r[:len(q.r)-1], q.r[len(q.r)-1] + } else { + v, q.l = q.l[0], q.l[1:] + } + return +} + +func (q Deque) Front() int { + if len(q.l) > 0 { + return q.l[len(q.l)-1] + } + return q.r[0] +} + +func (q Deque) Back() int { + if len(q.r) > 0 { + return q.r[len(q.r)-1] + } + return q.l[0] +} + +func (q Deque) Get(i int) int { + if i < len(q.l) { + return q.l[len(q.l)-1-i] + } + return q.r[i-len(q.l)] +} +``` + +#### TypeScript + +```ts +function constrainedSubsetSum(nums: number[], k: number): number { + const q = new Deque(); + const n = nums.length; + q.pushBack(0); + let ans = nums[0]; + const f: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + while (i - q.frontValue()! > k) { + q.popFront(); + } + f[i] = Math.max(0, f[q.frontValue()!]!) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.backValue()!]! <= f[i]) { + q.popBack(); + } + q.pushBack(i); + } + return ans; +} + +class Node { + value: T; + next: Node | null; + prev: Node | null; + + constructor(value: T) { + this.value = value; + this.next = null; + this.prev = null; + } +} + +class Deque { + private front: Node | null; + private back: Node | null; + private size: number; + + constructor() { + this.front = null; + this.back = null; + this.size = 0; + } + + pushFront(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.next = this.front; + this.front!.prev = newNode; + this.front = newNode; + } + this.size++; + } + + pushBack(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.prev = this.back; + this.back!.next = newNode; + this.back = newNode; + } + this.size++; + } + + popFront(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.front!.value; + this.front = this.front!.next; + if (this.front !== null) { + this.front.prev = null; + } else { + this.back = null; + } + this.size--; + return value; + } + + popBack(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.back!.value; + this.back = this.back!.prev; + if (this.back !== null) { + this.back.next = null; + } else { + this.front = null; + } + this.size--; + return value; + } + + frontValue(): T | undefined { + return this.front?.value; + } + + backValue(): T | undefined { + return this.back?.value; + } + + getSize(): number { + return this.size; + } + + isEmpty(): boolean { + return this.size === 0; + } +} ``` diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp index ddddd9b3b97f..a8c73b28dace 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp @@ -1,17 +1,22 @@ class Solution { public: int constrainedSubsetSum(vector& nums, int k) { + deque q = {0}; int n = nums.size(); - vector dp(n); + int f[n]; + f[0] = 0; int ans = INT_MIN; - deque q; for (int i = 0; i < n; ++i) { - if (!q.empty() && i - q.front() > k) q.pop_front(); - dp[i] = max(0, q.empty() ? 0 : dp[q.front()]) + nums[i]; - ans = max(ans, dp[i]); - while (!q.empty() && dp[q.back()] <= dp[i]) q.pop_back(); + while (i - q.front() > k) { + q.pop_front(); + } + f[i] = max(0, f[q.front()]) + nums[i]; + ans = max(ans, f[i]); + while (!q.empty() && f[q.back()] <= f[i]) { + q.pop_back(); + } q.push_back(i); } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go index 29433a5b8a94..328f87223c8e 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go @@ -1,21 +1,77 @@ func constrainedSubsetSum(nums []int, k int) int { + q := Deque{} + q.PushFront(0) n := len(nums) - dp := make([]int, n) - ans := math.MinInt32 - q := []int{} - for i, v := range nums { - if len(q) > 0 && i-q[0] > k { - q = q[1:] + f := make([]int, n) + ans := nums[0] + for i, x := range nums { + for i-q.Front() > k { + q.PopFront() } - dp[i] = v - if len(q) > 0 && dp[q[0]] > 0 { - dp[i] += dp[q[0]] + f[i] = max(0, f[q.Front()]) + x + ans = max(ans, f[i]) + for !q.Empty() && f[q.Back()] <= f[i] { + q.PopBack() } - for len(q) > 0 && dp[q[len(q)-1]] < dp[i] { - q = q[:len(q)-1] - } - q = append(q, i) - ans = max(ans, dp[i]) + q.PushBack(i) } return ans -} \ No newline at end of file +} + +// template +type Deque struct{ l, r []int } + +func (q Deque) Empty() bool { + return len(q.l) == 0 && len(q.r) == 0 +} + +func (q Deque) Size() int { + return len(q.l) + len(q.r) +} + +func (q *Deque) PushFront(v int) { + q.l = append(q.l, v) +} + +func (q *Deque) PushBack(v int) { + q.r = append(q.r, v) +} + +func (q *Deque) PopFront() (v int) { + if len(q.l) > 0 { + q.l, v = q.l[:len(q.l)-1], q.l[len(q.l)-1] + } else { + v, q.r = q.r[0], q.r[1:] + } + return +} + +func (q *Deque) PopBack() (v int) { + if len(q.r) > 0 { + q.r, v = q.r[:len(q.r)-1], q.r[len(q.r)-1] + } else { + v, q.l = q.l[0], q.l[1:] + } + return +} + +func (q Deque) Front() int { + if len(q.l) > 0 { + return q.l[len(q.l)-1] + } + return q.r[0] +} + +func (q Deque) Back() int { + if len(q.r) > 0 { + return q.r[len(q.r)-1] + } + return q.l[0] +} + +func (q Deque) Get(i int) int { + if i < len(q.l) { + return q.l[len(q.l)-1-i] + } + return q.r[i-len(q.l)] +} diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java index b9f2d95789a3..cae54e5014f3 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java @@ -1,20 +1,21 @@ class Solution { public int constrainedSubsetSum(int[] nums, int k) { - int n = nums.length; - int[] dp = new int[n]; - int ans = Integer.MIN_VALUE; Deque q = new ArrayDeque<>(); + q.offer(0); + int n = nums.length; + int[] f = new int[n]; + int ans = -(1 << 30); for (int i = 0; i < n; ++i) { - if (!q.isEmpty() && i - q.peek() > k) { - q.poll(); + while (i - q.peekFirst() > k) { + q.pollFirst(); } - dp[i] = Math.max(0, q.isEmpty() ? 0 : dp[q.peek()]) + nums[i]; - while (!q.isEmpty() && dp[q.peekLast()] <= dp[i]) { + f[i] = Math.max(0, f[q.peekFirst()]) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.peekLast()] <= f[i]) { q.pollLast(); } - q.offer(i); - ans = Math.max(ans, dp[i]); + q.offerLast(i); } return ans; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py index cdaade956239..0e76b39093b9 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py @@ -1,15 +1,15 @@ class Solution: def constrainedSubsetSum(self, nums: List[int], k: int) -> int: + q = deque([0]) n = len(nums) - dp = [0] * n + f = [0] * n ans = -inf - q = deque() - for i, v in enumerate(nums): - if q and i - q[0] > k: + for i, x in enumerate(nums): + while i - q[0] > k: q.popleft() - dp[i] = max(0, 0 if not q else dp[q[0]]) + v - while q and dp[q[-1]] <= dp[i]: + f[i] = max(0, f[q[0]]) + x + ans = max(ans, f[i]) + while q and f[q[-1]] <= f[i]: q.pop() q.append(i) - ans = max(ans, dp[i]) return ans diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.ts b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.ts new file mode 100644 index 000000000000..a4c4cb004804 --- /dev/null +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.ts @@ -0,0 +1,115 @@ +function constrainedSubsetSum(nums: number[], k: number): number { + const q = new Deque(); + const n = nums.length; + q.pushBack(0); + let ans = nums[0]; + const f: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + while (i - q.frontValue()! > k) { + q.popFront(); + } + f[i] = Math.max(0, f[q.frontValue()!]!) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.backValue()!]! <= f[i]) { + q.popBack(); + } + q.pushBack(i); + } + return ans; +} + +class Node { + value: T; + next: Node | null; + prev: Node | null; + + constructor(value: T) { + this.value = value; + this.next = null; + this.prev = null; + } +} + +class Deque { + private front: Node | null; + private back: Node | null; + private size: number; + + constructor() { + this.front = null; + this.back = null; + this.size = 0; + } + + pushFront(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.next = this.front; + this.front!.prev = newNode; + this.front = newNode; + } + this.size++; + } + + pushBack(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.prev = this.back; + this.back!.next = newNode; + this.back = newNode; + } + this.size++; + } + + popFront(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.front!.value; + this.front = this.front!.next; + if (this.front !== null) { + this.front.prev = null; + } else { + this.back = null; + } + this.size--; + return value; + } + + popBack(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.back!.value; + this.back = this.back!.prev; + if (this.back !== null) { + this.back.next = null; + } else { + this.front = null; + } + this.size--; + return value; + } + + frontValue(): T | undefined { + return this.front?.value; + } + + backValue(): T | undefined { + return this.back?.value; + } + + getSize(): number { + return this.size; + } + + isEmpty(): boolean { + return this.size === 0; + } +} diff --git a/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README.md b/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README.md index 015d48774a41..6d9f1b0bc2f0 100644 --- a/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README.md +++ b/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README.md @@ -73,7 +73,7 @@ tags: 我们可以使用二维前缀和来快速计算出每个子矩形中苹果的数量,定义 $s[i][j]$ 表示矩形前 $i$ 行,前 $j$ 列的子矩形中苹果的数量,那么 $s[i][j]$ 可以由 $s[i-1][j]$, $s[i][j-1]$, $s[i-1][j-1]$ 三个子矩形的苹果数量求得,具体的计算方法如下: $$ -s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + (pizza[i-1][j-1] == 'A') +s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + \textit{int}(pizza[i-1][j-1] == 'A') $$ 其中 $pizza[i-1][j-1]$ 表示矩形中第 $i$ 行,第 $j$ 列的字符,如果是苹果,则为 $1$,否则为 $0$。 diff --git a/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README_EN.md b/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README_EN.md index 1907b1f1ffcd..236675a85adf 100644 --- a/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README_EN.md +++ b/solution/1400-1499/1444.Number of Ways of Cutting a Pizza/README_EN.md @@ -69,7 +69,30 @@ tags: -### Solution 1 +### Solution 1: 2D Prefix Sum + Memoized Search + +We can use a 2D prefix sum to quickly calculate the number of apples in each sub-rectangle. Define $s[i][j]$ to represent the number of apples in the sub-rectangle that includes the first $i$ rows and the first $j$ columns. Then $s[i][j]$ can be derived from the number of apples in the three sub-rectangles $s[i-1][j]$, $s[i][j-1]$, and $s[i-1][j-1]$. The specific calculation method is as follows: + +$$ +s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + (pizza[i-1][j-1] == 'A') +$$ + +Here, $pizza[i-1][j-1]$ represents the character at the $i$-th row and $j$-th column in the rectangle. If it is an apple, it is $1$; otherwise, it is $0$. + +Next, we design a function $dfs(i, j, k)$, which represents the number of ways to cut the rectangle $(i, j, m-1, n-1)$ with $k$ cuts to get $k+1$ pieces of pizza. Here, $(i, j)$ and $(m-1, n-1)$ are the coordinates of the top-left and bottom-right corners of the rectangle, respectively. The calculation method of the function $dfs(i, j, k)$ is as follows: + +- If $k = 0$, it means no more cuts can be made. We need to check if there are any apples in the rectangle. If there are apples, return $1$; otherwise, return $0$. +- If $k \gt 0$, we need to enumerate the position of the last cut. If the last cut is horizontal, we need to enumerate the cutting position $x$, where $i \lt x \lt m$. If $s[x][n] - s[i][n] - s[x][j] + s[i][j] \gt 0$, it means there are apples in the upper piece of pizza, and we add the value of $dfs(x, j, k-1)$ to the answer. If the last cut is vertical, we need to enumerate the cutting position $y$, where $j \lt y \lt n$. If $s[m][y] - s[i][y] - s[m][j] + s[i][j] \gt 0$, it means there are apples in the left piece of pizza, and we add the value of $dfs(i, y, k-1)$ to the answer. + +The final answer is the value of $dfs(0, 0, k-1)$. + +To avoid repeated calculations, we can use memoized search. We use a 3D array $f$ to record the value of $dfs(i, j, k)$. When we need to calculate the value of $dfs(i, j, k)$, if $f[i][j][k]$ is not $-1$, it means we have already calculated it before, and we can directly return $f[i][j][k]$. Otherwise, we calculate the value of $dfs(i, j, k)$ according to the above method and save the result in $f[i][j][k]$. + +The time complexity is $O(m \times n \times k \times (m + n))$, and the space complexity is $O(m \times n \times k)$. Here, $m$ and $n$ are the number of rows and columns of the rectangle, respectively. + +Similar problems: + +- [2312. Selling Pieces of Wood](https://github.com/doocs/leetcode/blob/main/solution/2300-2399/2312.Selling%20Pieces%20of%20Wood/README_EN.md) diff --git a/solution/1400-1499/1446.Consecutive Characters/README.md b/solution/1400-1499/1446.Consecutive Characters/README.md index 49c56c0834ab..5a5d48043ae8 100644 --- a/solution/1400-1499/1446.Consecutive Characters/README.md +++ b/solution/1400-1499/1446.Consecutive Characters/README.md @@ -57,11 +57,11 @@ tags: ### 方法一:遍历计数 -我们定义一个变量 $t$,表示当前连续字符的长度,初始时 $t=1$。 +我们定义一个变量 $\textit{t}$,表示当前连续字符的长度,初始时 $\textit{t}=1$。 -接下来,我们从字符串 $s$ 的第二个字符开始遍历,如果当前字符与上一个字符相同,那么 $t = t + 1$,然后更新答案 $ans = \max(ans, t)$;否则,$t = 1$。 +接下来,我们从字符串 $s$ 的第二个字符开始遍历,如果当前字符与上一个字符相同,那么 $\textit{t} = \textit{t} + 1$,然后更新答案 $\textit{ans} = \max(\textit{ans}, \textit{t})$;否则 $\textit{t} = 1$。 -最后返回答案 $ans$ 即可。 +最后返回答案 $\textit{ans}$ 即可。 时间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/1400-1499/1446.Consecutive Characters/README_EN.md b/solution/1400-1499/1446.Consecutive Characters/README_EN.md index 8b138b4558bb..908094f98a0e 100644 --- a/solution/1400-1499/1446.Consecutive Characters/README_EN.md +++ b/solution/1400-1499/1446.Consecutive Characters/README_EN.md @@ -53,7 +53,15 @@ tags: -### Solution 1 +### Solution 1: Traversal and Counting + +We define a variable $\textit{t}$ to represent the length of the current consecutive characters, initially $\textit{t}=1$. + +Next, we traverse the string $s$ starting from the second character. If the current character is the same as the previous character, then $\textit{t} = \textit{t} + 1$, and update the answer $\textit{ans} = \max(\textit{ans}, \textit{t})$; otherwise, set $\textit{t} = 1$. + +Finally, return the answer $\textit{ans}$. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. diff --git a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README.md b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README.md index 4226d3de2fc6..42e1c4e79f41 100644 --- a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README.md +++ b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README.md @@ -70,9 +70,9 @@ favoriteCompanies[3]=["google"] 是 favoriteCompanies[0]=["leetco ### 方法一:哈希表 -将每个 `company` 字符串列表都转换为一个整数类型的集合。然后遍历每个集合,判断其是否是其他集合的子集,如果不是,则将其下标加入结果集。 +我们可以将每个公司映射到一个唯一的整数,然后对于每个人,我们将他们收藏的公司转换为整数集合,最后判断是否存在一个人的收藏公司是另一个人的子集。 -时间复杂度 $O(n^2 \times m)$,其中 $n$ 为 `favoriteCompanies` 的长度,$m$ 为 `favoriteCompanies[i]` 的最大长度。 +时间复杂度 $(n \times m \times k + n^2 \times m)$,空间复杂度 $O(n \times m)$。其中 $n$ 和 $m$ 分别是 `favoriteCompanies` 的长度和每个公司清单的平均长度,而 $k$ 是每个公司的平均长度。 @@ -81,25 +81,19 @@ favoriteCompanies[3]=["google"] 是 favoriteCompanies[0]=["leetco ```python class Solution: def peopleIndexes(self, favoriteCompanies: List[List[str]]) -> List[int]: - d = {} idx = 0 - t = [] - for v in favoriteCompanies: - for c in v: - if c not in d: - d[c] = idx + d = {} + n = len(favoriteCompanies) + nums = [set() for _ in range(n)] + for i, ss in enumerate(favoriteCompanies): + for s in ss: + if s not in d: + d[s] = idx idx += 1 - t.append({d[c] for c in v}) + nums[i].add(d[s]) ans = [] - for i, nums1 in enumerate(t): - ok = True - for j, nums2 in enumerate(t): - if i == j: - continue - if not (nums1 - nums2): - ok = False - break - if ok: + for i in range(n): + if not any(i != j and (nums[i] & nums[j]) == nums[i] for j in range(n)): ans.append(i) return ans ``` @@ -109,32 +103,26 @@ class Solution: ```java class Solution { public List peopleIndexes(List> favoriteCompanies) { + int n = favoriteCompanies.size(); Map d = new HashMap<>(); int idx = 0; - int n = favoriteCompanies.size(); - Set[] t = new Set[n]; + Set[] nums = new Set[n]; + Arrays.setAll(nums, i -> new HashSet<>()); for (int i = 0; i < n; ++i) { - var v = favoriteCompanies.get(i); - for (var c : v) { - if (!d.containsKey(c)) { - d.put(c, idx++); + var ss = favoriteCompanies.get(i); + for (var s : ss) { + if (!d.containsKey(s)) { + d.put(s, idx++); } + nums[i].add(d.get(s)); } - Set s = new HashSet<>(); - for (var c : v) { - s.add(d.get(c)); - } - t[i] = s; } List ans = new ArrayList<>(); for (int i = 0; i < n; ++i) { boolean ok = true; - for (int j = 0; j < n; ++j) { - if (i != j) { - if (t[j].containsAll(t[i])) { - ok = false; - break; - } + for (int j = 0; j < n && ok; ++j) { + if (i != j && nums[j].containsAll(nums[i])) { + ok = false; } } if (ok) { @@ -152,46 +140,43 @@ class Solution { class Solution { public: vector peopleIndexes(vector>& favoriteCompanies) { + int n = favoriteCompanies.size(); unordered_map d; - int idx = 0, n = favoriteCompanies.size(); - vector> t(n); + int idx = 0; + vector> nums(n); + for (int i = 0; i < n; ++i) { - auto v = favoriteCompanies[i]; - for (auto& c : v) { - if (!d.count(c)) { - d[c] = idx++; + for (const auto& s : favoriteCompanies[i]) { + if (!d.contains(s)) { + d[s] = idx++; } + nums[i].insert(d[s]); } - unordered_set s; - for (auto& c : v) { - s.insert(d[c]); - } - t[i] = s; } + + auto check = [](const unordered_set& a, const unordered_set& b) { + for (int x : a) { + if (!b.contains(x)) { + return false; + } + } + return true; + }; + vector ans; for (int i = 0; i < n; ++i) { bool ok = true; - for (int j = 0; j < n; ++j) { - if (i == j) continue; - if (check(t[i], t[j])) { + for (int j = 0; j < n && ok; ++j) { + if (i != j && check(nums[i], nums[j])) { ok = false; - break; } } if (ok) { ans.push_back(i); } } - return ans; - } - bool check(unordered_set& nums1, unordered_set& nums2) { - for (int v : nums1) { - if (!nums2.count(v)) { - return false; - } - } - return true; + return ans; } }; ``` @@ -199,27 +184,26 @@ public: #### Go ```go -func peopleIndexes(favoriteCompanies [][]string) []int { - d := map[string]int{} - idx, n := 0, len(favoriteCompanies) - t := make([]map[int]bool, n) - for i, v := range favoriteCompanies { - for _, c := range v { - if _, ok := d[c]; !ok { - d[c] = idx +func peopleIndexes(favoriteCompanies [][]string) (ans []int) { + n := len(favoriteCompanies) + d := make(map[string]int) + idx := 0 + nums := make([]map[int]struct{}, n) + + for i := 0; i < n; i++ { + nums[i] = make(map[int]struct{}) + for _, s := range favoriteCompanies[i] { + if _, ok := d[s]; !ok { + d[s] = idx idx++ } + nums[i][d[s]] = struct{}{} } - s := map[int]bool{} - for _, c := range v { - s[d[c]] = true - } - t[i] = s } - ans := []int{} - check := func(nums1, nums2 map[int]bool) bool { - for v, _ := range nums1 { - if _, ok := nums2[v]; !ok { + + check := func(a, b map[int]struct{}) bool { + for x := range a { + if _, ok := b[x]; !ok { return false } } @@ -227,20 +211,61 @@ func peopleIndexes(favoriteCompanies [][]string) []int { } for i := 0; i < n; i++ { ok := true - for j := 0; j < n; j++ { - if i == j { - continue - } - if check(t[i], t[j]) { + for j := 0; j < n && ok; j++ { + if i != j && check(nums[i], nums[j]) { ok = false - break } } if ok { ans = append(ans, i) } } - return ans + + return +} +``` + +#### TypeScript + +```ts +function peopleIndexes(favoriteCompanies: string[][]): number[] { + const n = favoriteCompanies.length; + const d: Map = new Map(); + let idx = 0; + const nums: Set[] = Array.from({ length: n }, () => new Set()); + + for (let i = 0; i < n; i++) { + for (const s of favoriteCompanies[i]) { + if (!d.has(s)) { + d.set(s, idx++); + } + nums[i].add(d.get(s)!); + } + } + + const check = (a: Set, b: Set): boolean => { + for (const x of a) { + if (!b.has(x)) { + return false; + } + } + return true; + }; + + const ans: number[] = []; + for (let i = 0; i < n; i++) { + let ok = true; + for (let j = 0; j < n && ok; j++) { + if (i !== j && check(nums[i], nums[j])) { + ok = false; + } + } + if (ok) { + ans.push(i); + } + } + + return ans; } ``` diff --git a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README_EN.md b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README_EN.md index c0566b5a0c31..563e9cb8be6d 100644 --- a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README_EN.md +++ b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/README_EN.md @@ -69,7 +69,11 @@ Other lists of favorite companies are not a subset of another list, therefore, t -### Solution 1 +### Solution 1: Hash Table + +We can map each company to a unique integer. Then, for each person, we convert their favorite companies into a set of integers. Finally, we check if the favorite companies of one person are a subset of another person's favorite companies. + +The time complexity is $(n \times m \times k + n^2 \times m)$, and the space complexity is $O(n \times m)$. Here, $n$ and $m$ are the lengths of `favoriteCompanies` and the average length of each company's list, respectively, and $k$ is the average length of each company. @@ -78,25 +82,19 @@ Other lists of favorite companies are not a subset of another list, therefore, t ```python class Solution: def peopleIndexes(self, favoriteCompanies: List[List[str]]) -> List[int]: - d = {} idx = 0 - t = [] - for v in favoriteCompanies: - for c in v: - if c not in d: - d[c] = idx + d = {} + n = len(favoriteCompanies) + nums = [set() for _ in range(n)] + for i, ss in enumerate(favoriteCompanies): + for s in ss: + if s not in d: + d[s] = idx idx += 1 - t.append({d[c] for c in v}) + nums[i].add(d[s]) ans = [] - for i, nums1 in enumerate(t): - ok = True - for j, nums2 in enumerate(t): - if i == j: - continue - if not (nums1 - nums2): - ok = False - break - if ok: + for i in range(n): + if not any(i != j and (nums[i] & nums[j]) == nums[i] for j in range(n)): ans.append(i) return ans ``` @@ -106,32 +104,26 @@ class Solution: ```java class Solution { public List peopleIndexes(List> favoriteCompanies) { + int n = favoriteCompanies.size(); Map d = new HashMap<>(); int idx = 0; - int n = favoriteCompanies.size(); - Set[] t = new Set[n]; + Set[] nums = new Set[n]; + Arrays.setAll(nums, i -> new HashSet<>()); for (int i = 0; i < n; ++i) { - var v = favoriteCompanies.get(i); - for (var c : v) { - if (!d.containsKey(c)) { - d.put(c, idx++); + var ss = favoriteCompanies.get(i); + for (var s : ss) { + if (!d.containsKey(s)) { + d.put(s, idx++); } + nums[i].add(d.get(s)); } - Set s = new HashSet<>(); - for (var c : v) { - s.add(d.get(c)); - } - t[i] = s; } List ans = new ArrayList<>(); for (int i = 0; i < n; ++i) { boolean ok = true; - for (int j = 0; j < n; ++j) { - if (i != j) { - if (t[j].containsAll(t[i])) { - ok = false; - break; - } + for (int j = 0; j < n && ok; ++j) { + if (i != j && nums[j].containsAll(nums[i])) { + ok = false; } } if (ok) { @@ -149,46 +141,43 @@ class Solution { class Solution { public: vector peopleIndexes(vector>& favoriteCompanies) { + int n = favoriteCompanies.size(); unordered_map d; - int idx = 0, n = favoriteCompanies.size(); - vector> t(n); + int idx = 0; + vector> nums(n); + for (int i = 0; i < n; ++i) { - auto v = favoriteCompanies[i]; - for (auto& c : v) { - if (!d.count(c)) { - d[c] = idx++; + for (const auto& s : favoriteCompanies[i]) { + if (!d.contains(s)) { + d[s] = idx++; } + nums[i].insert(d[s]); } - unordered_set s; - for (auto& c : v) { - s.insert(d[c]); - } - t[i] = s; } + + auto check = [](const unordered_set& a, const unordered_set& b) { + for (int x : a) { + if (!b.contains(x)) { + return false; + } + } + return true; + }; + vector ans; for (int i = 0; i < n; ++i) { bool ok = true; - for (int j = 0; j < n; ++j) { - if (i == j) continue; - if (check(t[i], t[j])) { + for (int j = 0; j < n && ok; ++j) { + if (i != j && check(nums[i], nums[j])) { ok = false; - break; } } if (ok) { ans.push_back(i); } } - return ans; - } - bool check(unordered_set& nums1, unordered_set& nums2) { - for (int v : nums1) { - if (!nums2.count(v)) { - return false; - } - } - return true; + return ans; } }; ``` @@ -196,27 +185,26 @@ public: #### Go ```go -func peopleIndexes(favoriteCompanies [][]string) []int { - d := map[string]int{} - idx, n := 0, len(favoriteCompanies) - t := make([]map[int]bool, n) - for i, v := range favoriteCompanies { - for _, c := range v { - if _, ok := d[c]; !ok { - d[c] = idx +func peopleIndexes(favoriteCompanies [][]string) (ans []int) { + n := len(favoriteCompanies) + d := make(map[string]int) + idx := 0 + nums := make([]map[int]struct{}, n) + + for i := 0; i < n; i++ { + nums[i] = make(map[int]struct{}) + for _, s := range favoriteCompanies[i] { + if _, ok := d[s]; !ok { + d[s] = idx idx++ } + nums[i][d[s]] = struct{}{} } - s := map[int]bool{} - for _, c := range v { - s[d[c]] = true - } - t[i] = s } - ans := []int{} - check := func(nums1, nums2 map[int]bool) bool { - for v, _ := range nums1 { - if _, ok := nums2[v]; !ok { + + check := func(a, b map[int]struct{}) bool { + for x := range a { + if _, ok := b[x]; !ok { return false } } @@ -224,20 +212,61 @@ func peopleIndexes(favoriteCompanies [][]string) []int { } for i := 0; i < n; i++ { ok := true - for j := 0; j < n; j++ { - if i == j { - continue - } - if check(t[i], t[j]) { + for j := 0; j < n && ok; j++ { + if i != j && check(nums[i], nums[j]) { ok = false - break } } if ok { ans = append(ans, i) } } - return ans + + return +} +``` + +#### TypeScript + +```ts +function peopleIndexes(favoriteCompanies: string[][]): number[] { + const n = favoriteCompanies.length; + const d: Map = new Map(); + let idx = 0; + const nums: Set[] = Array.from({ length: n }, () => new Set()); + + for (let i = 0; i < n; i++) { + for (const s of favoriteCompanies[i]) { + if (!d.has(s)) { + d.set(s, idx++); + } + nums[i].add(d.get(s)!); + } + } + + const check = (a: Set, b: Set): boolean => { + for (const x of a) { + if (!b.has(x)) { + return false; + } + } + return true; + }; + + const ans: number[] = []; + for (let i = 0; i < n; i++) { + let ok = true; + for (let j = 0; j < n && ok; j++) { + if (i !== j && check(nums[i], nums[j])) { + ok = false; + } + } + if (ok) { + ans.push(i); + } + } + + return ans; } ``` diff --git a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.cpp b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.cpp index 06b4998384e8..bf9bbc2192ae 100644 --- a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.cpp +++ b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.cpp @@ -1,45 +1,42 @@ class Solution { public: vector peopleIndexes(vector>& favoriteCompanies) { + int n = favoriteCompanies.size(); unordered_map d; - int idx = 0, n = favoriteCompanies.size(); - vector> t(n); + int idx = 0; + vector> nums(n); + for (int i = 0; i < n; ++i) { - auto v = favoriteCompanies[i]; - for (auto& c : v) { - if (!d.count(c)) { - d[c] = idx++; + for (const auto& s : favoriteCompanies[i]) { + if (!d.contains(s)) { + d[s] = idx++; } + nums[i].insert(d[s]); } - unordered_set s; - for (auto& c : v) { - s.insert(d[c]); - } - t[i] = s; } + + auto check = [](const unordered_set& a, const unordered_set& b) { + for (int x : a) { + if (!b.contains(x)) { + return false; + } + } + return true; + }; + vector ans; for (int i = 0; i < n; ++i) { bool ok = true; - for (int j = 0; j < n; ++j) { - if (i == j) continue; - if (check(t[i], t[j])) { + for (int j = 0; j < n && ok; ++j) { + if (i != j && check(nums[i], nums[j])) { ok = false; - break; } } if (ok) { ans.push_back(i); } } - return ans; - } - bool check(unordered_set& nums1, unordered_set& nums2) { - for (int v : nums1) { - if (!nums2.count(v)) { - return false; - } - } - return true; + return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.go b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.go index 03a26d384ca8..3f680e2545d4 100644 --- a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.go +++ b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.go @@ -1,24 +1,23 @@ -func peopleIndexes(favoriteCompanies [][]string) []int { - d := map[string]int{} - idx, n := 0, len(favoriteCompanies) - t := make([]map[int]bool, n) - for i, v := range favoriteCompanies { - for _, c := range v { - if _, ok := d[c]; !ok { - d[c] = idx +func peopleIndexes(favoriteCompanies [][]string) (ans []int) { + n := len(favoriteCompanies) + d := make(map[string]int) + idx := 0 + nums := make([]map[int]struct{}, n) + + for i := 0; i < n; i++ { + nums[i] = make(map[int]struct{}) + for _, s := range favoriteCompanies[i] { + if _, ok := d[s]; !ok { + d[s] = idx idx++ } + nums[i][d[s]] = struct{}{} } - s := map[int]bool{} - for _, c := range v { - s[d[c]] = true - } - t[i] = s } - ans := []int{} - check := func(nums1, nums2 map[int]bool) bool { - for v, _ := range nums1 { - if _, ok := nums2[v]; !ok { + + check := func(a, b map[int]struct{}) bool { + for x := range a { + if _, ok := b[x]; !ok { return false } } @@ -26,18 +25,15 @@ func peopleIndexes(favoriteCompanies [][]string) []int { } for i := 0; i < n; i++ { ok := true - for j := 0; j < n; j++ { - if i == j { - continue - } - if check(t[i], t[j]) { + for j := 0; j < n && ok; j++ { + if i != j && check(nums[i], nums[j]) { ok = false - break } } if ok { ans = append(ans, i) } } - return ans -} \ No newline at end of file + + return +} diff --git a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.java b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.java index 8b718f8bb063..c81d5aef30fe 100644 --- a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.java +++ b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.java @@ -1,31 +1,25 @@ class Solution { public List peopleIndexes(List> favoriteCompanies) { + int n = favoriteCompanies.size(); Map d = new HashMap<>(); int idx = 0; - int n = favoriteCompanies.size(); - Set[] t = new Set[n]; + Set[] nums = new Set[n]; + Arrays.setAll(nums, i -> new HashSet<>()); for (int i = 0; i < n; ++i) { - var v = favoriteCompanies.get(i); - for (var c : v) { - if (!d.containsKey(c)) { - d.put(c, idx++); + var ss = favoriteCompanies.get(i); + for (var s : ss) { + if (!d.containsKey(s)) { + d.put(s, idx++); } + nums[i].add(d.get(s)); } - Set s = new HashSet<>(); - for (var c : v) { - s.add(d.get(c)); - } - t[i] = s; } List ans = new ArrayList<>(); for (int i = 0; i < n; ++i) { boolean ok = true; - for (int j = 0; j < n; ++j) { - if (i != j) { - if (t[j].containsAll(t[i])) { - ok = false; - break; - } + for (int j = 0; j < n && ok; ++j) { + if (i != j && nums[j].containsAll(nums[i])) { + ok = false; } } if (ok) { @@ -34,4 +28,4 @@ public List peopleIndexes(List> favoriteCompanies) { } return ans; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.py b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.py index 33022ba4cb3c..3b53f8f92314 100644 --- a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.py +++ b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.py @@ -1,23 +1,17 @@ class Solution: def peopleIndexes(self, favoriteCompanies: List[List[str]]) -> List[int]: - d = {} idx = 0 - t = [] - for v in favoriteCompanies: - for c in v: - if c not in d: - d[c] = idx + d = {} + n = len(favoriteCompanies) + nums = [set() for _ in range(n)] + for i, ss in enumerate(favoriteCompanies): + for s in ss: + if s not in d: + d[s] = idx idx += 1 - t.append({d[c] for c in v}) + nums[i].add(d[s]) ans = [] - for i, nums1 in enumerate(t): - ok = True - for j, nums2 in enumerate(t): - if i == j: - continue - if not (nums1 - nums2): - ok = False - break - if ok: + for i in range(n): + if not any(i != j and (nums[i] & nums[j]) == nums[i] for j in range(n)): ans.append(i) return ans diff --git a/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.ts b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.ts new file mode 100644 index 000000000000..7bd4171f71cc --- /dev/null +++ b/solution/1400-1499/1452.People Whose List of Favorite Companies Is Not a Subset of Another List/Solution.ts @@ -0,0 +1,39 @@ +function peopleIndexes(favoriteCompanies: string[][]): number[] { + const n = favoriteCompanies.length; + const d: Map = new Map(); + let idx = 0; + const nums: Set[] = Array.from({ length: n }, () => new Set()); + + for (let i = 0; i < n; i++) { + for (const s of favoriteCompanies[i]) { + if (!d.has(s)) { + d.set(s, idx++); + } + nums[i].add(d.get(s)!); + } + } + + const check = (a: Set, b: Set): boolean => { + for (const x of a) { + if (!b.has(x)) { + return false; + } + } + return true; + }; + + const ans: number[] = []; + for (let i = 0; i < n; i++) { + let ok = true; + for (let j = 0; j < n && ok; j++) { + if (i !== j && check(nums[i], nums[j])) { + ok = false; + } + } + if (ok) { + ans.push(i); + } + } + + return ans; +} diff --git a/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README.md b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README.md index be513f0e7edf..393e48170f67 100644 --- a/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README.md +++ b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README.md @@ -69,13 +69,92 @@ tags: #### Python3 ```python - +class Solution: + def numPoints(self, darts: list[list[int]], r: int) -> int: + def countDarts(x, y): + count = 0 + for x1, y1 in darts: + if dist((x, y), (x1, y1)) <= r + 1e-7: + count += 1 + return count + + def possibleCenters(x1, y1, x2, y2): + dx, dy = x2 - x1, y2 - y1 + d = sqrt(dx * dx + dy * dy) + if d > 2 * r: + return [] + mid_x, mid_y = (x1 + x2) / 2, (y1 + y2) / 2 + dist_to_center = sqrt(r * r - (d / 2) * (d / 2)) + offset_x = dist_to_center * dy / d + offset_y = dist_to_center * -dx / d + return [ + (mid_x + offset_x, mid_y + offset_y), + (mid_x - offset_x, mid_y - offset_y), + ] + + n = len(darts) + max_darts = 1 + + for i in range(n): + for j in range(i + 1, n): + centers = possibleCenters( + darts[i][0], darts[i][1], darts[j][0], darts[j][1] + ) + for center in centers: + max_darts = max(max_darts, countDarts(center[0], center[1])) + + return max_darts ``` #### Java ```java - +class Solution { + public int numPoints(int[][] darts, int r) { + int n = darts.length; + int maxDarts = 1; + + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + List centers + = possibleCenters(darts[i][0], darts[i][1], darts[j][0], darts[j][1], r); + for (double[] center : centers) { + maxDarts = Math.max(maxDarts, countDarts(center[0], center[1], darts, r)); + } + } + } + return maxDarts; + } + + private List possibleCenters(int x1, int y1, int x2, int y2, int r) { + List centers = new ArrayList<>(); + double dx = x2 - x1; + double dy = y2 - y1; + double d = Math.sqrt(dx * dx + dy * dy); + if (d > 2 * r) { + return centers; + } + double midX = (x1 + x2) / 2.0; + double midY = (y1 + y2) / 2.0; + double distToCenter = Math.sqrt(r * r - (d / 2.0) * (d / 2.0)); + double offsetX = distToCenter * dy / d; + double offsetY = distToCenter * -dx / d; + + centers.add(new double[] {midX + offsetX, midY + offsetY}); + centers.add(new double[] {midX - offsetX, midY - offsetY}); + return centers; + } + + private int countDarts(double x, double y, int[][] darts, int r) { + int count = 0; + for (int[] dart : darts) { + if (Math.sqrt(Math.pow(dart[0] - x, 2) + Math.pow(dart[1] - y, 2)) <= r + 1e-7) { + count++; + } + } + return count; + } +} ``` #### C++ diff --git a/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README_EN.md b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README_EN.md index da18bb00e974..d9cfc301ad1f 100644 --- a/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README_EN.md +++ b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/README_EN.md @@ -67,13 +67,92 @@ tags: #### Python3 ```python - +class Solution: + def numPoints(self, darts: list[list[int]], r: int) -> int: + def countDarts(x, y): + count = 0 + for x1, y1 in darts: + if dist((x, y), (x1, y1)) <= r + 1e-7: + count += 1 + return count + + def possibleCenters(x1, y1, x2, y2): + dx, dy = x2 - x1, y2 - y1 + d = sqrt(dx * dx + dy * dy) + if d > 2 * r: + return [] + mid_x, mid_y = (x1 + x2) / 2, (y1 + y2) / 2 + dist_to_center = sqrt(r * r - (d / 2) * (d / 2)) + offset_x = dist_to_center * dy / d + offset_y = dist_to_center * -dx / d + return [ + (mid_x + offset_x, mid_y + offset_y), + (mid_x - offset_x, mid_y - offset_y), + ] + + n = len(darts) + max_darts = 1 + + for i in range(n): + for j in range(i + 1, n): + centers = possibleCenters( + darts[i][0], darts[i][1], darts[j][0], darts[j][1] + ) + for center in centers: + max_darts = max(max_darts, countDarts(center[0], center[1])) + + return max_darts ``` #### Java ```java - +class Solution { + public int numPoints(int[][] darts, int r) { + int n = darts.length; + int maxDarts = 1; + + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + List centers + = possibleCenters(darts[i][0], darts[i][1], darts[j][0], darts[j][1], r); + for (double[] center : centers) { + maxDarts = Math.max(maxDarts, countDarts(center[0], center[1], darts, r)); + } + } + } + return maxDarts; + } + + private List possibleCenters(int x1, int y1, int x2, int y2, int r) { + List centers = new ArrayList<>(); + double dx = x2 - x1; + double dy = y2 - y1; + double d = Math.sqrt(dx * dx + dy * dy); + if (d > 2 * r) { + return centers; + } + double midX = (x1 + x2) / 2.0; + double midY = (y1 + y2) / 2.0; + double distToCenter = Math.sqrt(r * r - (d / 2.0) * (d / 2.0)); + double offsetX = distToCenter * dy / d; + double offsetY = distToCenter * -dx / d; + + centers.add(new double[] {midX + offsetX, midY + offsetY}); + centers.add(new double[] {midX - offsetX, midY - offsetY}); + return centers; + } + + private int countDarts(double x, double y, int[][] darts, int r) { + int count = 0; + for (int[] dart : darts) { + if (Math.sqrt(Math.pow(dart[0] - x, 2) + Math.pow(dart[1] - y, 2)) <= r + 1e-7) { + count++; + } + } + return count; + } +} ``` #### C++ diff --git a/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/Solution.java b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/Solution.java new file mode 100644 index 000000000000..4c4974a19f1a --- /dev/null +++ b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/Solution.java @@ -0,0 +1,46 @@ +class Solution { + public int numPoints(int[][] darts, int r) { + int n = darts.length; + int maxDarts = 1; + + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + List centers + = possibleCenters(darts[i][0], darts[i][1], darts[j][0], darts[j][1], r); + for (double[] center : centers) { + maxDarts = Math.max(maxDarts, countDarts(center[0], center[1], darts, r)); + } + } + } + return maxDarts; + } + + private List possibleCenters(int x1, int y1, int x2, int y2, int r) { + List centers = new ArrayList<>(); + double dx = x2 - x1; + double dy = y2 - y1; + double d = Math.sqrt(dx * dx + dy * dy); + if (d > 2 * r) { + return centers; + } + double midX = (x1 + x2) / 2.0; + double midY = (y1 + y2) / 2.0; + double distToCenter = Math.sqrt(r * r - (d / 2.0) * (d / 2.0)); + double offsetX = distToCenter * dy / d; + double offsetY = distToCenter * -dx / d; + + centers.add(new double[] {midX + offsetX, midY + offsetY}); + centers.add(new double[] {midX - offsetX, midY - offsetY}); + return centers; + } + + private int countDarts(double x, double y, int[][] darts, int r) { + int count = 0; + for (int[] dart : darts) { + if (Math.sqrt(Math.pow(dart[0] - x, 2) + Math.pow(dart[1] - y, 2)) <= r + 1e-7) { + count++; + } + } + return count; + } +} diff --git a/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/Solution.py b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/Solution.py new file mode 100644 index 000000000000..1c70260041b2 --- /dev/null +++ b/solution/1400-1499/1453.Maximum Number of Darts Inside of a Circular Dartboard/Solution.py @@ -0,0 +1,35 @@ +class Solution: + def numPoints(self, darts: list[list[int]], r: int) -> int: + def countDarts(x, y): + count = 0 + for x1, y1 in darts: + if dist((x, y), (x1, y1)) <= r + 1e-7: + count += 1 + return count + + def possibleCenters(x1, y1, x2, y2): + dx, dy = x2 - x1, y2 - y1 + d = sqrt(dx * dx + dy * dy) + if d > 2 * r: + return [] + mid_x, mid_y = (x1 + x2) / 2, (y1 + y2) / 2 + dist_to_center = sqrt(r * r - (d / 2) * (d / 2)) + offset_x = dist_to_center * dy / d + offset_y = dist_to_center * -dx / d + return [ + (mid_x + offset_x, mid_y + offset_y), + (mid_x - offset_x, mid_y - offset_y), + ] + + n = len(darts) + max_darts = 1 + + for i in range(n): + for j in range(i + 1, n): + centers = possibleCenters( + darts[i][0], darts[i][1], darts[j][0], darts[j][1] + ) + for center in centers: + max_darts = max(max_darts, countDarts(center[0], center[1])) + + return max_darts diff --git a/solution/1400-1499/1454.Active Users/README.md b/solution/1400-1499/1454.Active Users/README.md index 2e1b05dd6cbc..c54b08a5e6da 100644 --- a/solution/1400-1499/1454.Active Users/README.md +++ b/solution/1400-1499/1454.Active Users/README.md @@ -104,7 +104,13 @@ id = 7 的用户 Jonathon 在不同的 6 天内登录了 7 次, , 6 天中有 5 -### 方法一 +### 方法一: 使用窗口函数 + +我们先将 `Logins` 表和 `Accounts` 表连接起来,并且去重,得到临时表 `T`。 + +然后我们使用窗口函数 `ROW_NUMBER()`,计算出每个用户 `id` 的登录日期的基准日期 `g`,如果用户连续登录 5 天,那么他们的 `g` 值是相同的。 + +最后,我们按照 `id` 和 `g` 进行分组,统计每个用户的登录次数,如果登录次数大于等于 5,那么这个用户就是活跃用户。 @@ -112,18 +118,30 @@ id = 7 的用户 Jonathon 在不同的 6 天内登录了 7 次, , 6 天中有 5 ```sql # Write your MySQL query statement below -WITH t AS - (SELECT *, - SUM(id) over(partition by id - ORDER BY login_date range interval 4 day preceding)/id cnt - FROM - (SELECT DISTINCT * - FROM Accounts - JOIN Logins using(id) ) tt ) - SELECT DISTINCT id, - name -FROM t -WHERE cnt=5; +WITH + T AS ( + SELECT DISTINCT * + FROM + Logins + JOIN Accounts USING (id) + ), + P AS ( + SELECT + *, + DATE_SUB( + login_date, + INTERVAL ROW_NUMBER() OVER ( + PARTITION BY id + ORDER BY login_date + ) DAY + ) g + FROM T + ) +SELECT DISTINCT id, name +FROM P +GROUP BY id, g +HAVING COUNT(*) >= 5 +ORDER BY 1; ``` diff --git a/solution/1400-1499/1454.Active Users/README_EN.md b/solution/1400-1499/1454.Active Users/README_EN.md index a5d1e7008e0a..77a9b3166f44 100644 --- a/solution/1400-1499/1454.Active Users/README_EN.md +++ b/solution/1400-1499/1454.Active Users/README_EN.md @@ -100,7 +100,13 @@ User Jonathan with id = 7 logged in 7 times in 6 different days, five of them we -### Solution 1 +### Solution 1: Using Window Functions + +First, we join the `Logins` table and the `Accounts` table, and remove duplicates to get the temporary table `T`. + +Then, we use the window function `ROW_NUMBER()` to calculate the base login date `g` for each user `id`. If a user logs in for 5 consecutive days, their `g` values are the same. + +Finally, we group by `id` and `g` to count the number of logins for each user. If the number of logins is greater than or equal to 5, then the user is considered active. @@ -108,18 +114,30 @@ User Jonathan with id = 7 logged in 7 times in 6 different days, five of them we ```sql # Write your MySQL query statement below -WITH t AS - (SELECT *, - SUM(id) over(partition by id - ORDER BY login_date range interval 4 day preceding)/id cnt - FROM - (SELECT DISTINCT * - FROM Accounts - JOIN Logins using(id) ) tt ) - SELECT DISTINCT id, - name -FROM t -WHERE cnt=5; +WITH + T AS ( + SELECT DISTINCT * + FROM + Logins + JOIN Accounts USING (id) + ), + P AS ( + SELECT + *, + DATE_SUB( + login_date, + INTERVAL ROW_NUMBER() OVER ( + PARTITION BY id + ORDER BY login_date + ) DAY + ) g + FROM T + ) +SELECT DISTINCT id, name +FROM P +GROUP BY id, g +HAVING COUNT(*) >= 5 +ORDER BY 1; ``` diff --git a/solution/1400-1499/1454.Active Users/Solution.sql b/solution/1400-1499/1454.Active Users/Solution.sql index 719eff9fce0c..36b04a638ef0 100644 --- a/solution/1400-1499/1454.Active Users/Solution.sql +++ b/solution/1400-1499/1454.Active Users/Solution.sql @@ -1,13 +1,25 @@ # Write your MySQL query statement below -WITH t AS - (SELECT *, - SUM(id) over(partition by id - ORDER BY login_date range interval 4 day preceding)/id cnt - FROM - (SELECT DISTINCT * - FROM Accounts - JOIN Logins using(id) ) tt ) - SELECT DISTINCT id, - name -FROM t -WHERE cnt=5; +WITH + T AS ( + SELECT DISTINCT * + FROM + Logins + JOIN Accounts USING (id) + ), + P AS ( + SELECT + *, + DATE_SUB( + login_date, + INTERVAL ROW_NUMBER() OVER ( + PARTITION BY id + ORDER BY login_date + ) DAY + ) g + FROM T + ) +SELECT DISTINCT id, name +FROM P +GROUP BY id, g +HAVING COUNT(*) >= 5 +ORDER BY 1; diff --git a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md index 62cb63f2eb80..b65cccfe7cad 100644 --- a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md +++ b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README.md @@ -71,9 +71,9 @@ tags: ### 方法一:字符串分割 -将 $sentence$ 按空格分割为 $words$,然后遍历 $words$,检查 $words[i]$ 是否是 $searchWord$ 的前缀,是则返回 $i+1$。若遍历结束,所有单词都不满足,返回 $-1$。 +我们将 $\textit{sentence}$ 按空格分割为 $\textit{words}$,然后遍历 $\textit{words}$,检查 $\textit{words}[i]$ 是否是 $\textit{searchWord}$ 的前缀,是则返回 $i+1$。若遍历结束,所有单词都不满足,返回 $-1$。 -时间复杂度 $O(mn)$。其中 $m$ 是 $sentence$ 的长度,而 $n$ 是 $searchWord$ 的长度。 +时间复杂度 $O(m \times n)$,空间复杂度 $O(m)$。其中 $m$ 和 $n$ 分别是 $\textit{sentence}$ 和 $\textit{searchWord}$ 的长度。 @@ -176,9 +176,9 @@ class Solution { * @return Integer */ function isPrefixOfWord($sentence, $searchWord) { - $arr = explode(' ', $sentence); - for ($i = 0; $i < count($arr); $i++) { - if (strpos($arr[$i], $searchWord) === 0) { + $words = explode(' ', $sentence); + for ($i = 0; $i < count($words); ++$i) { + if (strpos($words[$i], $searchWord) === 0) { return $i + 1; } } diff --git a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md index ff87165460c6..e97cf29ad731 100644 --- a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md +++ b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/README_EN.md @@ -67,7 +67,11 @@ tags: -### Solution 1 +### Solution 1: String Splitting + +We split $\textit{sentence}$ by spaces into $\textit{words}$, then iterate through $\textit{words}$ to check if $\textit{words}[i]$ is a prefix of $\textit{searchWord}$. If it is, we return $i+1$. If the iteration completes and no words satisfy the condition, we return $-1$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m)$. Here, $m$ and $n$ are the lengths of $\textit{sentence}$ and $\textit{searchWord}$, respectively. @@ -170,9 +174,9 @@ class Solution { * @return Integer */ function isPrefixOfWord($sentence, $searchWord) { - $arr = explode(' ', $sentence); - for ($i = 0; $i < count($arr); $i++) { - if (strpos($arr[$i], $searchWord) === 0) { + $words = explode(' ', $sentence); + for ($i = 0; $i < count($words); ++$i) { + if (strpos($words[$i], $searchWord) === 0) { return $i + 1; } } diff --git a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php index 2025bc4f3024..2e5d79c9f4e0 100644 --- a/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php +++ b/solution/1400-1499/1455.Check If a Word Occurs As a Prefix of Any Word in a Sentence/Solution.php @@ -5,9 +5,9 @@ class Solution { * @return Integer */ function isPrefixOfWord($sentence, $searchWord) { - $arr = explode(' ', $sentence); - for ($i = 0; $i < count($arr); $i++) { - if (strpos($arr[$i], $searchWord) === 0) { + $words = explode(' ', $sentence); + for ($i = 0; $i < count($words); ++$i) { + if (strpos($words[$i], $searchWord) === 0) { return $i + 1; } } diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README.md b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README.md index 2d5cc8c3efca..b40b63e101f3 100644 --- a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README.md +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README.md @@ -80,17 +80,16 @@ tags: ### 方法一:动态规划 -定义 $dp[i][j]$ 表示 $nums1$ 前 $i$ 个元素和 $nums2$ 前 $j$ 个元素得到的最大点积。 +我们定义 $f[i][j]$ 表示 $\textit{nums1}$ 的前 $i$ 个元素和 $\textit{nums2}$ 的前 $j$ 个元素构成的两个子序列的最大点积。初始时 $f[i][j] = -\infty$。 -那么有: +对于 $f[i][j]$,我们有以下几种情况: -$$ -dp[i][j]=max(dp[i-1][j], dp[i][j - 1], max(dp[i - 1][j - 1], 0) + nums1[i] \times nums2[j]) -$$ +1. 不选 $\textit{nums1}[i-1]$ 或者不选 $\textit{nums2}[j-1]$,即 $f[i][j] = \max(f[i-1][j], f[i][j-1])$; +2. 选 $\textit{nums1}[i-1]$ 和 $\textit{nums2}[j-1]$,即 $f[i][j] = \max(f[i][j], \max(0, f[i-1][j-1]) + \textit{nums1}[i-1] \times \textit{nums2}[j-1])$。 -答案为 $dp[m][n]$。 +最终答案即为 $f[m][n]$。 -时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是数组 $nums1$ 和 $nums2$ 的长度。 +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是数组 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度。 @@ -100,12 +99,12 @@ $$ class Solution: def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[-inf] * (n + 1) for _ in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - v = nums1[i - 1] * nums2[j - 1] - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1], max(dp[i - 1][j - 1], 0) + v) - return dp[-1][-1] + f = [[-inf] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + v = x * y + f[i][j] = max(f[i - 1][j], f[i][j - 1], max(0, f[i - 1][j - 1]) + v) + return f[m][n] ``` #### Java @@ -114,18 +113,18 @@ class Solution: class Solution { public int maxDotProduct(int[] nums1, int[] nums2) { int m = nums1.length, n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int[] e : dp) { - Arrays.fill(e, Integer.MIN_VALUE); + int[][] f = new int[m + 1][n + 1]; + for (var g : f) { + Arrays.fill(g, Integer.MIN_VALUE); } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - dp[i][j] = Math.max( - dp[i][j], Math.max(0, dp[i - 1][j - 1]) + nums1[i - 1] * nums2[j - 1]); + int v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + f[i][j] = Math.max(f[i][j], Math.max(f[i - 1][j - 1], 0) + v); } } - return dp[m][n]; + return f[m][n]; } } ``` @@ -137,15 +136,16 @@ class Solution { public: int maxDotProduct(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1, INT_MIN)); + int f[m + 1][n + 1]; + memset(f, 0xc0, sizeof f); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { int v = nums1[i - 1] * nums2[j - 1]; - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); - dp[i][j] = max(dp[i][j], max(0, dp[i - 1][j - 1]) + v); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); + f[i][j] = max(f[i][j], max(0, f[i - 1][j - 1]) + v); } } - return dp[m][n]; + return f[m][n]; } }; ``` @@ -155,21 +155,39 @@ public: ```go func maxDotProduct(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) - for j := range dp[i] { - dp[i][j] = math.MinInt32 + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) + for j := range f[i] { + f[i][j] = math.MinInt32 } } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { v := nums1[i-1] * nums2[j-1] - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) - dp[i][j] = max(dp[i][j], max(0, dp[i-1][j-1])+v) + f[i][j] = max(f[i-1][j], f[i][j-1]) + f[i][j] = max(f[i][j], max(0, f[i-1][j-1])+v) } } - return dp[m][n] + return f[m][n] +} +``` + +#### TypeScript + +```ts +function maxDotProduct(nums1: number[], nums2: number[]): number { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => -Infinity)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + const v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + f[i][j] = Math.max(f[i][j], Math.max(0, f[i - 1][j - 1]) + v); + } + } + return f[m][n]; } ``` @@ -177,23 +195,20 @@ func maxDotProduct(nums1 []int, nums2 []int) int { ```rust impl Solution { - #[allow(dead_code)] pub fn max_dot_product(nums1: Vec, nums2: Vec) -> i32 { - let n = nums1.len(); - let m = nums2.len(); - let mut dp = vec![vec![i32::MIN; m + 1]; n + 1]; - - // Begin the actual dp process - for i in 1..=n { - for j in 1..=m { - dp[i][j] = std::cmp::max( - std::cmp::max(dp[i - 1][j], dp[i][j - 1]), - std::cmp::max(dp[i - 1][j - 1], 0) + nums1[i - 1] * nums2[j - 1], - ); + let m = nums1.len(); + let n = nums2.len(); + let mut f = vec![vec![i32::MIN; n + 1]; m + 1]; + + for i in 1..=m { + for j in 1..=n { + let v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = f[i][j].max(f[i - 1][j]).max(f[i][j - 1]); + f[i][j] = f[i][j].max(f[i - 1][j - 1].max(0) + v); } } - dp[n][m] + f[m][n] } } ``` diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README_EN.md b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README_EN.md index 9adf9790e37f..f5a5e569010c 100644 --- a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README_EN.md +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/README_EN.md @@ -64,7 +64,18 @@ Their dot product is -1.
    -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j]$ to represent the maximum dot product of two subsequences formed by the first $i$ elements of $\textit{nums1}$ and the first $j$ elements of $\textit{nums2}$. Initially, $f[i][j] = -\infty$. + +For $f[i][j]$, we have the following cases: + +1. Do not select $\textit{nums1}[i-1]$ or do not select $\textit{nums2}[j-1]$, i.e., $f[i][j] = \max(f[i-1][j], f[i][j-1])$; +2. Select $\textit{nums1}[i-1]$ and $\textit{nums2}[j-1]$, i.e., $f[i][j] = \max(f[i][j], \max(0, f[i-1][j-1]) + \textit{nums1}[i-1] \times \textit{nums2}[j-1])$. + +The final answer is $f[m][n]$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the lengths of the arrays $\textit{nums1}$ and $\textit{nums2}$, respectively. @@ -74,12 +85,12 @@ Their dot product is -1.
    class Solution: def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[-inf] * (n + 1) for _ in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - v = nums1[i - 1] * nums2[j - 1] - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1], max(dp[i - 1][j - 1], 0) + v) - return dp[-1][-1] + f = [[-inf] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + v = x * y + f[i][j] = max(f[i - 1][j], f[i][j - 1], max(0, f[i - 1][j - 1]) + v) + return f[m][n] ``` #### Java @@ -88,18 +99,18 @@ class Solution: class Solution { public int maxDotProduct(int[] nums1, int[] nums2) { int m = nums1.length, n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int[] e : dp) { - Arrays.fill(e, Integer.MIN_VALUE); + int[][] f = new int[m + 1][n + 1]; + for (var g : f) { + Arrays.fill(g, Integer.MIN_VALUE); } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - dp[i][j] = Math.max( - dp[i][j], Math.max(0, dp[i - 1][j - 1]) + nums1[i - 1] * nums2[j - 1]); + int v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + f[i][j] = Math.max(f[i][j], Math.max(f[i - 1][j - 1], 0) + v); } } - return dp[m][n]; + return f[m][n]; } } ``` @@ -111,15 +122,16 @@ class Solution { public: int maxDotProduct(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1, INT_MIN)); + int f[m + 1][n + 1]; + memset(f, 0xc0, sizeof f); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { int v = nums1[i - 1] * nums2[j - 1]; - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); - dp[i][j] = max(dp[i][j], max(0, dp[i - 1][j - 1]) + v); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); + f[i][j] = max(f[i][j], max(0, f[i - 1][j - 1]) + v); } } - return dp[m][n]; + return f[m][n]; } }; ``` @@ -129,21 +141,39 @@ public: ```go func maxDotProduct(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) - for j := range dp[i] { - dp[i][j] = math.MinInt32 + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) + for j := range f[i] { + f[i][j] = math.MinInt32 } } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { v := nums1[i-1] * nums2[j-1] - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) - dp[i][j] = max(dp[i][j], max(0, dp[i-1][j-1])+v) + f[i][j] = max(f[i-1][j], f[i][j-1]) + f[i][j] = max(f[i][j], max(0, f[i-1][j-1])+v) } } - return dp[m][n] + return f[m][n] +} +``` + +#### TypeScript + +```ts +function maxDotProduct(nums1: number[], nums2: number[]): number { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => -Infinity)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + const v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + f[i][j] = Math.max(f[i][j], Math.max(0, f[i - 1][j - 1]) + v); + } + } + return f[m][n]; } ``` @@ -151,23 +181,20 @@ func maxDotProduct(nums1 []int, nums2 []int) int { ```rust impl Solution { - #[allow(dead_code)] pub fn max_dot_product(nums1: Vec, nums2: Vec) -> i32 { - let n = nums1.len(); - let m = nums2.len(); - let mut dp = vec![vec![i32::MIN; m + 1]; n + 1]; - - // Begin the actual dp process - for i in 1..=n { - for j in 1..=m { - dp[i][j] = std::cmp::max( - std::cmp::max(dp[i - 1][j], dp[i][j - 1]), - std::cmp::max(dp[i - 1][j - 1], 0) + nums1[i - 1] * nums2[j - 1], - ); + let m = nums1.len(); + let n = nums2.len(); + let mut f = vec![vec![i32::MIN; n + 1]; m + 1]; + + for i in 1..=m { + for j in 1..=n { + let v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = f[i][j].max(f[i - 1][j]).max(f[i][j - 1]); + f[i][j] = f[i][j].max(f[i - 1][j - 1].max(0) + v); } } - dp[n][m] + f[m][n] } } ``` diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.cpp b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.cpp index 47369f4a935b..c6447fbb6dc9 100644 --- a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.cpp +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.cpp @@ -2,14 +2,15 @@ class Solution { public: int maxDotProduct(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1, INT_MIN)); + int f[m + 1][n + 1]; + memset(f, 0xc0, sizeof f); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { int v = nums1[i - 1] * nums2[j - 1]; - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); - dp[i][j] = max(dp[i][j], max(0, dp[i - 1][j - 1]) + v); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); + f[i][j] = max(f[i][j], max(0, f[i - 1][j - 1]) + v); } } - return dp[m][n]; + return f[m][n]; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.go b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.go index e2c0e9a62a86..5236d579359a 100644 --- a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.go +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.go @@ -1,18 +1,18 @@ func maxDotProduct(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) - for j := range dp[i] { - dp[i][j] = math.MinInt32 + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) + for j := range f[i] { + f[i][j] = math.MinInt32 } } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { v := nums1[i-1] * nums2[j-1] - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) - dp[i][j] = max(dp[i][j], max(0, dp[i-1][j-1])+v) + f[i][j] = max(f[i-1][j], f[i][j-1]) + f[i][j] = max(f[i][j], max(0, f[i-1][j-1])+v) } } - return dp[m][n] -} \ No newline at end of file + return f[m][n] +} diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.java b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.java index 157c44cc9916..7bb198e1a950 100644 --- a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.java +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.java @@ -1,17 +1,17 @@ class Solution { public int maxDotProduct(int[] nums1, int[] nums2) { int m = nums1.length, n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int[] e : dp) { - Arrays.fill(e, Integer.MIN_VALUE); + int[][] f = new int[m + 1][n + 1]; + for (var g : f) { + Arrays.fill(g, Integer.MIN_VALUE); } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - dp[i][j] = Math.max( - dp[i][j], Math.max(0, dp[i - 1][j - 1]) + nums1[i - 1] * nums2[j - 1]); + int v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + f[i][j] = Math.max(f[i][j], Math.max(f[i - 1][j - 1], 0) + v); } } - return dp[m][n]; + return f[m][n]; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.py b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.py index 84386e628969..496562fed172 100644 --- a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.py +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.py @@ -1,9 +1,9 @@ class Solution: def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[-inf] * (n + 1) for _ in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - v = nums1[i - 1] * nums2[j - 1] - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1], max(dp[i - 1][j - 1], 0) + v) - return dp[-1][-1] + f = [[-inf] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + v = x * y + f[i][j] = max(f[i - 1][j], f[i][j - 1], max(0, f[i - 1][j - 1]) + v) + return f[m][n] diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.rs b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.rs index 01e12026e66b..02a6bb18bd05 100644 --- a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.rs +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.rs @@ -1,20 +1,17 @@ impl Solution { - #[allow(dead_code)] pub fn max_dot_product(nums1: Vec, nums2: Vec) -> i32 { - let n = nums1.len(); - let m = nums2.len(); - let mut dp = vec![vec![i32::MIN; m + 1]; n + 1]; + let m = nums1.len(); + let n = nums2.len(); + let mut f = vec![vec![i32::MIN; n + 1]; m + 1]; - // Begin the actual dp process - for i in 1..=n { - for j in 1..=m { - dp[i][j] = std::cmp::max( - std::cmp::max(dp[i - 1][j], dp[i][j - 1]), - std::cmp::max(dp[i - 1][j - 1], 0) + nums1[i - 1] * nums2[j - 1], - ); + for i in 1..=m { + for j in 1..=n { + let v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = f[i][j].max(f[i - 1][j]).max(f[i][j - 1]); + f[i][j] = f[i][j].max(f[i - 1][j - 1].max(0) + v); } } - dp[n][m] + f[m][n] } } diff --git a/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.ts b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.ts new file mode 100644 index 000000000000..c8e214478932 --- /dev/null +++ b/solution/1400-1499/1458.Max Dot Product of Two Subsequences/Solution.ts @@ -0,0 +1,13 @@ +function maxDotProduct(nums1: number[], nums2: number[]): number { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => -Infinity)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + const v = nums1[i - 1] * nums2[j - 1]; + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + f[i][j] = Math.max(f[i][j], Math.max(0, f[i - 1][j - 1]) + v); + } + } + return f[m][n]; +} diff --git a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README.md b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README.md index ddfdbf498330..7859034c9ab0 100644 --- a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README.md +++ b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README.md @@ -128,9 +128,19 @@ func canBeEqual(target []int, arr []int) bool { ```ts function canBeEqual(target: number[], arr: number[]): boolean { - target.sort((a, b) => a - b); - arr.sort((a, b) => a - b); - return target.join() === arr.join(); + target.sort(); + arr.sort(); + return target.every((x, i) => x === arr[i]); +} +``` + +#### JavaScript + +```js +function canBeEqual(target, arr) { + target.sort(); + arr.sort(); + return target.every((x, i) => x === arr[i]); } ``` @@ -273,6 +283,20 @@ function canBeEqual(target: number[], arr: number[]): boolean { } ``` +#### JavaScript + +```js +function canBeEqual(target, arr) { + const n = target.length; + const cnt = Array(1001).fill(0); + for (let i = 0; i < n; i++) { + cnt[target[i]]++; + cnt[arr[i]]--; + } + return cnt.every(v => !v); +} +``` + #### Rust ```rust diff --git a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README_EN.md b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README_EN.md index a04b2d8cade6..8e322a868508 100644 --- a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README_EN.md +++ b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/README_EN.md @@ -126,9 +126,19 @@ func canBeEqual(target []int, arr []int) bool { ```ts function canBeEqual(target: number[], arr: number[]): boolean { - target.sort((a, b) => a - b); - arr.sort((a, b) => a - b); - return target.join() === arr.join(); + target.sort(); + arr.sort(); + return target.every((x, i) => x === arr[i]); +} +``` + +#### JavaScript + +```js +function canBeEqual(target, arr) { + target.sort(); + arr.sort(); + return target.every((x, i) => x === arr[i]); } ``` @@ -271,6 +281,20 @@ function canBeEqual(target: number[], arr: number[]): boolean { } ``` +#### JavaScript + +```js +function canBeEqual(target, arr) { + const n = target.length; + const cnt = Array(1001).fill(0); + for (let i = 0; i < n; i++) { + cnt[target[i]]++; + cnt[arr[i]]--; + } + return cnt.every(v => !v); +} +``` + #### Rust ```rust diff --git a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution.js b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution.js new file mode 100644 index 000000000000..341b4f8b171d --- /dev/null +++ b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution.js @@ -0,0 +1,5 @@ +function canBeEqual(target, arr) { + target.sort(); + arr.sort(); + return target.every((x, i) => x === arr[i]); +} diff --git a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution.ts b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution.ts index 00ae9d07efa5..c1eaa1791176 100644 --- a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution.ts +++ b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution.ts @@ -1,5 +1,5 @@ function canBeEqual(target: number[], arr: number[]): boolean { - target.sort((a, b) => a - b); - arr.sort((a, b) => a - b); - return target.join() === arr.join(); + target.sort(); + arr.sort(); + return target.every((x, i) => x === arr[i]); } diff --git a/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution2.js b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution2.js new file mode 100644 index 000000000000..a4cc826b7b2b --- /dev/null +++ b/solution/1400-1499/1460.Make Two Arrays Equal by Reversing Subarrays/Solution2.js @@ -0,0 +1,9 @@ +function canBeEqual(target, arr) { + const n = target.length; + const cnt = Array(1001).fill(0); + for (let i = 0; i < n; i++) { + cnt[target[i]]++; + cnt[arr[i]]--; + } + return cnt.every(v => !v); +} diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README.md b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README.md index 472995117203..1ef619a84a80 100644 --- a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README.md +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README.md @@ -68,9 +68,11 @@ tags: ### 方法一:哈希表 -遍历字符串 $s$,用一个哈希表存储所有长度为 $k$ 的不同子串。只需要判断子串数能否达到 $2^k$ 即可。 +首先,对于一个长度为 $n$ 的字符串 $s$,长度为 $k$ 的子串的个数为 $n - k + 1$,如果 $n - k + 1 < 2^k$,则一定存在长度为 $k$ 的二进制串不是 $s$ 的子串,返回 `false`。 -时间复杂度 $O(n \times k)$,其中 $n$ 是字符串 $s$ 的长度,$k$ 是子串长度。 +接下来,我们遍历字符串 $s$,将所有长度为 $k$ 的子串存入集合 $ss$,最后判断集合 $ss$ 的大小是否等于 $2^k$。 + +时间复杂度 $O(n \times k)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。 @@ -79,8 +81,12 @@ tags: ```python class Solution: def hasAllCodes(self, s: str, k: int) -> bool: - ss = {s[i : i + k] for i in range(len(s) - k + 1)} - return len(ss) == 1 << k + n = len(s) + m = 1 << k + if n - k + 1 < m: + return False + ss = {s[i : i + k] for i in range(n - k + 1)} + return len(ss) == m ``` #### Java @@ -88,11 +94,16 @@ class Solution: ```java class Solution { public boolean hasAllCodes(String s, int k) { + int n = s.length(); + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } Set ss = new HashSet<>(); - for (int i = 0; i < s.length() - k + 1; ++i) { + for (int i = 0; i < n - k + 1; ++i) { ss.add(s.substring(i, i + k)); } - return ss.size() == 1 << k; + return ss.size() == m; } } ``` @@ -103,11 +114,16 @@ class Solution { class Solution { public: bool hasAllCodes(string s, int k) { + int n = s.size(); + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } unordered_set ss; - for (int i = 0; i + k <= s.size(); ++i) { + for (int i = 0; i + k <= n; ++i) { ss.insert(move(s.substr(i, k))); } - return ss.size() == 1 << k; + return ss.size() == m; } }; ``` @@ -116,11 +132,32 @@ public: ```go func hasAllCodes(s string, k int) bool { + n, m := len(s), 1<(); + for (let i = 0; i + k <= n; ++i) { + ss.add(s.slice(i, i + k)); + } + return ss.size === m; } ``` @@ -132,9 +169,9 @@ func hasAllCodes(s string, k int) bool { ### 方法二:滑动窗口 -方法一中,我们存储了所有长度为 $k$ 的不同子串,子串的处理需要 $O(k)$ 的时间,我们可以改用滑动窗口,每次添加最新字符时,删除窗口最左边的字符。此过程中用一个整型数字 $num$ 来存放子串。 +方法一中,我们存储了所有长度为 $k$ 的不同子串,子串的处理需要 $O(k)$ 的时间,我们可以改用滑动窗口,每次添加最新字符时,删除窗口最左边的字符。此过程中用一个整型数字 $x$ 来存放子串。 -时间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。 @@ -143,17 +180,19 @@ func hasAllCodes(s string, k int) bool { ```python class Solution: def hasAllCodes(self, s: str, k: int) -> bool: - if len(s) - k + 1 < (1 << k): + n = len(s) + m = 1 << k + if n - k + 1 < m: return False - vis = [False] * (1 << k) - num = int(s[:k], 2) - vis[num] = True - for i in range(k, len(s)): - a = (ord(s[i - k]) - ord('0')) << (k - 1) - b = ord(s[i]) - ord('0') - num = ((num - a) << 1) + b - vis[num] = True - return all(v for v in vis) + ss = set() + x = int(s[:k], 2) + ss.add(x) + for i in range(k, n): + a = int(s[i - k]) << (k - 1) + b = int(s[i]) + x = (x - a) << 1 | b + ss.add(x) + return len(ss) == m ``` #### Java @@ -162,19 +201,20 @@ class Solution: class Solution { public boolean hasAllCodes(String s, int k) { int n = s.length(); - if (n - k + 1 < (1 << k)) { + int m = 1 << k; + if (n - k + 1 < m) { return false; } - boolean[] vis = new boolean[1 << k]; - int num = Integer.parseInt(s.substring(0, k), 2); - vis[num] = true; + boolean[] ss = new boolean[m]; + int x = Integer.parseInt(s.substring(0, k), 2); + ss[x] = true; for (int i = k; i < n; ++i) { int a = (s.charAt(i - k) - '0') << (k - 1); int b = s.charAt(i) - '0'; - num = (num - a) << 1 | b; - vis[num] = true; + x = (x - a) << 1 | b; + ss[x] = true; } - for (boolean v : vis) { + for (boolean v : ss) { if (!v) { return false; } @@ -191,19 +231,21 @@ class Solution { public: bool hasAllCodes(string s, int k) { int n = s.size(); - if (n - k + 1 < (1 << k)) return false; - vector vis(1 << k); - int num = stoi(s.substr(0, k), nullptr, 2); - vis[num] = true; + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } + bool ss[m]; + memset(ss, false, sizeof(ss)); + int x = stoi(s.substr(0, k), nullptr, 2); + ss[x] = true; for (int i = k; i < n; ++i) { int a = (s[i - k] - '0') << (k - 1); int b = s[i] - '0'; - num = (num - a) << 1 | b; - vis[num] = true; + x = (x - a) << 1 | b; + ss[x] = true; } - for (bool v : vis) - if (!v) return false; - return true; + return all_of(ss, ss + m, [](bool v) { return v; }); } }; ``` @@ -212,22 +254,20 @@ public: ```go func hasAllCodes(s string, k int) bool { - n := len(s) - if n-k+1 < (1 << k) { + n, m := len(s), 1<(); + ss.add(x); + for (let i = k; i < n; ++i) { + const a = +s[i - k] << (k - 1); + const b = +s[i]; + x = ((x - a) << 1) | b; + ss.add(x); + } + return ss.size === m; +} +``` + diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README_EN.md b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README_EN.md index 599fbce9fc11..ea1a7d5013ad 100644 --- a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README_EN.md +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/README_EN.md @@ -64,7 +64,13 @@ tags: -### Solution 1 +### Solution 1: Hash Table + +First, for a string $s$ of length $n$, the number of substrings of length $k$ is $n - k + 1$. If $n - k + 1 < 2^k$, then there must exist a binary string of length $k$ that is not a substring of $s$, so we return `false`. + +Next, we traverse the string $s$ and store all substrings of length $k$ in a set $ss$. Finally, we check if the size of the set $ss$ is equal to $2^k$. + +The time complexity is $O(n \times k)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $s$. @@ -73,8 +79,12 @@ tags: ```python class Solution: def hasAllCodes(self, s: str, k: int) -> bool: - ss = {s[i : i + k] for i in range(len(s) - k + 1)} - return len(ss) == 1 << k + n = len(s) + m = 1 << k + if n - k + 1 < m: + return False + ss = {s[i : i + k] for i in range(n - k + 1)} + return len(ss) == m ``` #### Java @@ -82,11 +92,16 @@ class Solution: ```java class Solution { public boolean hasAllCodes(String s, int k) { + int n = s.length(); + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } Set ss = new HashSet<>(); - for (int i = 0; i < s.length() - k + 1; ++i) { + for (int i = 0; i < n - k + 1; ++i) { ss.add(s.substring(i, i + k)); } - return ss.size() == 1 << k; + return ss.size() == m; } } ``` @@ -97,11 +112,16 @@ class Solution { class Solution { public: bool hasAllCodes(string s, int k) { + int n = s.size(); + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } unordered_set ss; - for (int i = 0; i + k <= s.size(); ++i) { + for (int i = 0; i + k <= n; ++i) { ss.insert(move(s.substr(i, k))); } - return ss.size() == 1 << k; + return ss.size() == m; } }; ``` @@ -110,11 +130,32 @@ public: ```go func hasAllCodes(s string, k int) bool { + n, m := len(s), 1<(); + for (let i = 0; i + k <= n; ++i) { + ss.add(s.slice(i, i + k)); + } + return ss.size === m; } ``` @@ -124,7 +165,11 @@ func hasAllCodes(s string, k int) bool { -### Solution 2 +### Solution 2: Sliding Window + +In Solution 1, we stored all distinct substrings of length $k$, and processing each substring requires $O(k)$ time. We can instead use a sliding window, where each time we add the latest character, we remove the leftmost character from the window. During this process, we use an integer $x$ to store the substring. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string $s$. @@ -133,17 +178,19 @@ func hasAllCodes(s string, k int) bool { ```python class Solution: def hasAllCodes(self, s: str, k: int) -> bool: - if len(s) - k + 1 < (1 << k): + n = len(s) + m = 1 << k + if n - k + 1 < m: return False - vis = [False] * (1 << k) - num = int(s[:k], 2) - vis[num] = True - for i in range(k, len(s)): - a = (ord(s[i - k]) - ord('0')) << (k - 1) - b = ord(s[i]) - ord('0') - num = ((num - a) << 1) + b - vis[num] = True - return all(v for v in vis) + ss = set() + x = int(s[:k], 2) + ss.add(x) + for i in range(k, n): + a = int(s[i - k]) << (k - 1) + b = int(s[i]) + x = (x - a) << 1 | b + ss.add(x) + return len(ss) == m ``` #### Java @@ -152,19 +199,20 @@ class Solution: class Solution { public boolean hasAllCodes(String s, int k) { int n = s.length(); - if (n - k + 1 < (1 << k)) { + int m = 1 << k; + if (n - k + 1 < m) { return false; } - boolean[] vis = new boolean[1 << k]; - int num = Integer.parseInt(s.substring(0, k), 2); - vis[num] = true; + boolean[] ss = new boolean[m]; + int x = Integer.parseInt(s.substring(0, k), 2); + ss[x] = true; for (int i = k; i < n; ++i) { int a = (s.charAt(i - k) - '0') << (k - 1); int b = s.charAt(i) - '0'; - num = (num - a) << 1 | b; - vis[num] = true; + x = (x - a) << 1 | b; + ss[x] = true; } - for (boolean v : vis) { + for (boolean v : ss) { if (!v) { return false; } @@ -181,19 +229,21 @@ class Solution { public: bool hasAllCodes(string s, int k) { int n = s.size(); - if (n - k + 1 < (1 << k)) return false; - vector vis(1 << k); - int num = stoi(s.substr(0, k), nullptr, 2); - vis[num] = true; + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } + bool ss[m]; + memset(ss, false, sizeof(ss)); + int x = stoi(s.substr(0, k), nullptr, 2); + ss[x] = true; for (int i = k; i < n; ++i) { int a = (s[i - k] - '0') << (k - 1); int b = s[i] - '0'; - num = (num - a) << 1 | b; - vis[num] = true; + x = (x - a) << 1 | b; + ss[x] = true; } - for (bool v : vis) - if (!v) return false; - return true; + return all_of(ss, ss + m, [](bool v) { return v; }); } }; ``` @@ -202,22 +252,20 @@ public: ```go func hasAllCodes(s string, k int) bool { - n := len(s) - if n-k+1 < (1 << k) { + n, m := len(s), 1<(); + ss.add(x); + for (let i = k; i < n; ++i) { + const a = +s[i - k] << (k - 1); + const b = +s[i]; + x = ((x - a) << 1) | b; + ss.add(x); + } + return ss.size === m; +} +``` + diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.cpp b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.cpp index 4018b4114dfe..c6a218742482 100644 --- a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.cpp +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.cpp @@ -1,10 +1,15 @@ class Solution { public: bool hasAllCodes(string s, int k) { + int n = s.size(); + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } unordered_set ss; - for (int i = 0; i + k <= s.size(); ++i) { + for (int i = 0; i + k <= n; ++i) { ss.insert(move(s.substr(i, k))); } - return ss.size() == 1 << k; + return ss.size() == m; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.go b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.go index 2852e51db7b2..84dee7d873f9 100644 --- a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.go +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.go @@ -1,7 +1,11 @@ func hasAllCodes(s string, k int) bool { + n, m := len(s), 1< ss = new HashSet<>(); - for (int i = 0; i < s.length() - k + 1; ++i) { + for (int i = 0; i < n - k + 1; ++i) { ss.add(s.substring(i, i + k)); } - return ss.size() == 1 << k; + return ss.size() == m; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.py b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.py index 5fba4d31a174..1ef979e49c0e 100644 --- a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.py +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.py @@ -1,4 +1,8 @@ class Solution: def hasAllCodes(self, s: str, k: int) -> bool: - ss = {s[i : i + k] for i in range(len(s) - k + 1)} - return len(ss) == 1 << k + n = len(s) + m = 1 << k + if n - k + 1 < m: + return False + ss = {s[i : i + k] for i in range(n - k + 1)} + return len(ss) == m diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.ts b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.ts new file mode 100644 index 000000000000..870b869f4732 --- /dev/null +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution.ts @@ -0,0 +1,12 @@ +function hasAllCodes(s: string, k: number): boolean { + const n = s.length; + const m = 1 << k; + if (n - k + 1 < m) { + return false; + } + const ss = new Set(); + for (let i = 0; i + k <= n; ++i) { + ss.add(s.slice(i, i + k)); + } + return ss.size === m; +} diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.cpp b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.cpp index fa82b12a07c5..b364fa6c1644 100644 --- a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.cpp +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.cpp @@ -2,18 +2,20 @@ class Solution { public: bool hasAllCodes(string s, int k) { int n = s.size(); - if (n - k + 1 < (1 << k)) return false; - vector vis(1 << k); - int num = stoi(s.substr(0, k), nullptr, 2); - vis[num] = true; + int m = 1 << k; + if (n - k + 1 < m) { + return false; + } + bool ss[m]; + memset(ss, false, sizeof(ss)); + int x = stoi(s.substr(0, k), nullptr, 2); + ss[x] = true; for (int i = k; i < n; ++i) { int a = (s[i - k] - '0') << (k - 1); int b = s[i] - '0'; - num = (num - a) << 1 | b; - vis[num] = true; + x = (x - a) << 1 | b; + ss[x] = true; } - for (bool v : vis) - if (!v) return false; - return true; + return all_of(ss, ss + m, [](bool v) { return v; }); } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.go b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.go index ba3f68b1fe39..ad59761d8526 100644 --- a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.go +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.go @@ -1,23 +1,21 @@ func hasAllCodes(s string, k int) bool { - n := len(s) - if n-k+1 < (1 << k) { + n, m := len(s), 1< bool: - if len(s) - k + 1 < (1 << k): + n = len(s) + m = 1 << k + if n - k + 1 < m: return False - vis = [False] * (1 << k) - num = int(s[:k], 2) - vis[num] = True - for i in range(k, len(s)): - a = (ord(s[i - k]) - ord('0')) << (k - 1) - b = ord(s[i]) - ord('0') - num = ((num - a) << 1) + b - vis[num] = True - return all(v for v in vis) + ss = set() + x = int(s[:k], 2) + ss.add(x) + for i in range(k, n): + a = int(s[i - k]) << (k - 1) + b = int(s[i]) + x = (x - a) << 1 | b + ss.add(x) + return len(ss) == m diff --git a/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.ts b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.ts new file mode 100644 index 000000000000..3070c56d1cd6 --- /dev/null +++ b/solution/1400-1499/1461.Check If a String Contains All Binary Codes of Size K/Solution2.ts @@ -0,0 +1,17 @@ +function hasAllCodes(s: string, k: number): boolean { + const n = s.length; + const m = 1 << k; + if (n - k + 1 < m) { + return false; + } + let x = +`0b${s.slice(0, k)}`; + const ss = new Set(); + ss.add(x); + for (let i = k; i < n; ++i) { + const a = +s[i - k] << (k - 1); + const b = +s[i]; + x = ((x - a) << 1) | b; + ss.add(x); + } + return ss.size === m; +} diff --git a/solution/1400-1499/1462.Course Schedule IV/README.md b/solution/1400-1499/1462.Course Schedule IV/README.md index d662b1c7ad2f..9eecda829e10 100644 --- a/solution/1400-1499/1462.Course Schedule IV/README.md +++ b/solution/1400-1499/1462.Course Schedule IV/README.md @@ -233,7 +233,7 @@ function checkIfPrerequisite(n: number, prerequisites: number[][], queries: numb 在计算完所有节点对之间的可达性之后,对于每一个查询 $[a, b]$,我们直接返回 $f[a][b]$ 即可。 -时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为节点数。 +时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为节点数。 diff --git a/solution/1400-1499/1462.Course Schedule IV/README_EN.md b/solution/1400-1499/1462.Course Schedule IV/README_EN.md index 80fff691fe91..8f05842d9bb4 100644 --- a/solution/1400-1499/1462.Course Schedule IV/README_EN.md +++ b/solution/1400-1499/1462.Course Schedule IV/README_EN.md @@ -80,7 +80,19 @@ Course 0 is not a prerequisite of course 1, but the opposite is true. -### Solution 1 +### Solution 1: Floyd's Algorithm + +We create a 2D array $f$, where $f[i][j]$ indicates whether node $i$ can reach node $j$. + +Next, we iterate through the prerequisites array $prerequisites$. For each item $[a, b]$ in it, we set $f[a][b]$ to $true$. + +Then, we use Floyd's algorithm to compute the reachability between all pairs of nodes. + +Specifically, we use three nested loops: first enumerating the intermediate node $k$, then the starting node $i$, and finally the ending node $j$. For each iteration, if node $i$ can reach node $k$ and node $k$ can reach node $j$, then node $i$ can also reach node $j$, and we set $f[i][j]$ to $true$. + +After computing the reachability between all pairs of nodes, for each query $[a, b]$, we can directly return $f[a][b]$. + +The time complexity is $O(n^3)$, and the space complexity is $O(n^2)$, where $n$ is the number of nodes. @@ -202,7 +214,19 @@ function checkIfPrerequisite(n: number, prerequisites: number[][], queries: numb -### Solution 2 +### Solution 2: Topological Sorting + +Similar to Solution 1, we create a 2D array $f$, where $f[i][j]$ indicates whether node $i$ can reach node $j$. Additionally, we create an adjacency list $g$, where $g[i]$ represents all successor nodes of node $i$, and an array $indeg$, where $indeg[i]$ represents the in-degree of node $i$. + +Next, we iterate through the prerequisites array $prerequisites$. For each item $[a, b]$ in it, we update the adjacency list $g$ and the in-degree array $indeg$. + +Then, we use topological sorting to compute the reachability between all pairs of nodes. + +We define a queue $q$, initially adding all nodes with an in-degree of $0$ to the queue. Then, we continuously perform the following operations: remove the front node $i$ from the queue, then iterate through all nodes $j$ in $g[i]$, setting $f[i][j]$ to $true$. Next, we enumerate node $h$, and if $f[h][i]$ is $true$, we also set $f[h][j]$ to $true$. After this, we decrease the in-degree of $j$ by $1$. If the in-degree of $j$ becomes $0$, we add $j$ to the queue. + +After computing the reachability between all pairs of nodes, for each query $[a, b]$, we can directly return $f[a][b]$. + +The time complexity is $O(n^3)$, and the space complexity is $O(n^2)$, where $n$ is the number of nodes. diff --git a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README.md b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README.md index ba89373513f3..aa6ba42c903f 100644 --- a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README.md +++ b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README.md @@ -304,4 +304,100 @@ function longestSubarray(nums: number[]): number { + + +### 方法三:双指针(优化) + +方法二中,我们每次会循环移动左指针,直到 $cnt \leq 1$。由于题目求的是最长子数组,意味着我们不需要缩小子数组的长度,因此,如果 $\textit{cnt} \gt 1$,我们只移动左指针一次,右指针也继续向右移动。这样可以保证子数组的长度不会减小。 + +最后,我们返回的答案即为 $n - l - 1$,其中 $l$ 为左指针的位置。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 $nums$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def longestSubarray(self, nums: List[int]) -> int: + cnt = l = 0 + for x in nums: + cnt += x ^ 1 + if cnt > 1: + cnt -= nums[l] ^ 1 + l += 1 + return len(nums) - l - 1 +``` + +#### Java + +```java +class Solution { + public int longestSubarray(int[] nums) { + int ans = 0, cnt = 0, l = 0; + for (int x : nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.length - l - 1; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int longestSubarray(vector& nums) { + int ans = 0, cnt = 0, l = 0; + for (int x : nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.size() - l - 1; + } +}; +``` + +#### Go + +```go +func longestSubarray(nums []int) (ans int) { + cnt, l := 0, 0 + for _, x := range nums { + cnt += x ^ 1 + if cnt > 1 { + cnt -= nums[l] ^ 1 + l++ + } + } + return len(nums) - l - 1 +} +``` + +#### TypeScript + +```ts +function longestSubarray(nums: number[]): number { + let [cnt, l] = [0, 0]; + for (const x of nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.length - l - 1; +} +``` + + + + + diff --git a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README_EN.md b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README_EN.md index dded8ae77ffb..c539187f88cc 100644 --- a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README_EN.md +++ b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/README_EN.md @@ -303,4 +303,100 @@ function longestSubarray(nums: number[]): number { + + +### Solution 3: Two Pointers (Optimization) + +In Solution 2, we move the left pointer in a loop until $cnt \leq 1$. Since the problem asks for the longest subarray, it means we don't need to reduce the length of the subarray. Therefore, if $\textit{cnt} \gt 1$, we only move the left pointer once, and the right pointer continues to move to the right. This ensures that the length of the subarray does not decrease. + +Finally, the answer we return is $n - l - 1$, where $l$ is the position of the left pointer. + +The time complexity is $O(n)$, where $n$ is the length of the array $nums$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def longestSubarray(self, nums: List[int]) -> int: + cnt = l = 0 + for x in nums: + cnt += x ^ 1 + if cnt > 1: + cnt -= nums[l] ^ 1 + l += 1 + return len(nums) - l - 1 +``` + +#### Java + +```java +class Solution { + public int longestSubarray(int[] nums) { + int ans = 0, cnt = 0, l = 0; + for (int x : nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.length - l - 1; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int longestSubarray(vector& nums) { + int ans = 0, cnt = 0, l = 0; + for (int x : nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.size() - l - 1; + } +}; +``` + +#### Go + +```go +func longestSubarray(nums []int) (ans int) { + cnt, l := 0, 0 + for _, x := range nums { + cnt += x ^ 1 + if cnt > 1 { + cnt -= nums[l] ^ 1 + l++ + } + } + return len(nums) - l - 1 +} +``` + +#### TypeScript + +```ts +function longestSubarray(nums: number[]): number { + let [cnt, l] = [0, 0]; + for (const x of nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.length - l - 1; +} +``` + + + + + diff --git a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.cpp b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.cpp new file mode 100644 index 000000000000..782fa4074e10 --- /dev/null +++ b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.cpp @@ -0,0 +1,13 @@ +class Solution { +public: + int longestSubarray(vector& nums) { + int ans = 0, cnt = 0, l = 0; + for (int x : nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.size() - l - 1; + } +}; \ No newline at end of file diff --git a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.go b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.go new file mode 100644 index 000000000000..b35f6bbe1ab5 --- /dev/null +++ b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.go @@ -0,0 +1,11 @@ +func longestSubarray(nums []int) (ans int) { + cnt, l := 0, 0 + for _, x := range nums { + cnt += x ^ 1 + if cnt > 1 { + cnt -= nums[l] ^ 1 + l++ + } + } + return len(nums) - l - 1 +} \ No newline at end of file diff --git a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.java b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.java new file mode 100644 index 000000000000..939ac9ed5ad9 --- /dev/null +++ b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.java @@ -0,0 +1,12 @@ +class Solution { + public int longestSubarray(int[] nums) { + int ans = 0, cnt = 0, l = 0; + for (int x : nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.length - l - 1; + } +} \ No newline at end of file diff --git a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.py b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.py new file mode 100644 index 000000000000..9ecb4561fb35 --- /dev/null +++ b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.py @@ -0,0 +1,9 @@ +class Solution: + def longestSubarray(self, nums: List[int]) -> int: + cnt = l = 0 + for x in nums: + cnt += x ^ 1 + if cnt > 1: + cnt -= nums[l] ^ 1 + l += 1 + return len(nums) - l - 1 diff --git a/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.ts b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.ts new file mode 100644 index 000000000000..b14d30d363d2 --- /dev/null +++ b/solution/1400-1499/1493.Longest Subarray of 1's After Deleting One Element/Solution3.ts @@ -0,0 +1,10 @@ +function longestSubarray(nums: number[]): number { + let [cnt, l] = [0, 0]; + for (const x of nums) { + cnt += x ^ 1; + if (cnt > 1) { + cnt -= nums[l++] ^ 1; + } + } + return nums.length - l - 1; +} diff --git a/solution/1500-1599/1500.Design a File Sharing System/README.md b/solution/1500-1599/1500.Design a File Sharing System/README.md index 239a3715ecdf..4eea563d57ae 100644 --- a/solution/1500-1599/1500.Design a File Sharing System/README.md +++ b/solution/1500-1599/1500.Design a File Sharing System/README.md @@ -6,6 +6,7 @@ tags: - 设计 - 哈希表 - 数据流 + - 排序 - 堆(优先队列) --- @@ -19,9 +20,9 @@ tags: -

    我们需要使用一套文件分享系统来分享一个非常大的文件,该文件由 m 个从 1 到 m 编号的文件块组成。

    +

    我们需要使用一套文件分享系统来分享一个非常大的文件,该文件由 m 个从 1 到 m 编号的 文件块 组成。

    -

    当用户加入系统时,系统应为其注册一个独有的 ID。这个独有的 ID 应当被相应的用户使用一次,但是当用户离开系统时,其 ID 应可以被(后续新注册的用户)再次使用

    +

    当用户加入系统时,系统应为其注册 一个独有 的 ID。这个独有的 ID 应当被相应的用户使用 一次,但是当用户离开系统时,其 ID 应可以被(后续新注册的用户)再次使用

    用户可以请求文件中的某个指定的文件块,系统应当返回拥有这个文件块的所有用户的 ID。如果用户收到 ID 的非空列表,就表示成功接收到请求的文件块。

    diff --git a/solution/1500-1599/1500.Design a File Sharing System/README_EN.md b/solution/1500-1599/1500.Design a File Sharing System/README_EN.md index e7b1d7e2175d..6915f8e9a2ad 100644 --- a/solution/1500-1599/1500.Design a File Sharing System/README_EN.md +++ b/solution/1500-1599/1500.Design a File Sharing System/README_EN.md @@ -6,6 +6,7 @@ tags: - Design - Hash Table - Data Stream + - Sorting - Heap (Priority Queue) --- diff --git a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md index 982021b65e6e..25286920cca4 100644 --- a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md +++ b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README.md @@ -161,6 +161,54 @@ func rangeSum(nums []int, n int, left int, right int) (ans int) { } ``` +#### TypeScript + +```ts +function rangeSum(nums: number[], n: number, left: number, right: number): number { + let arr = Array((n * (n + 1)) / 2).fill(0); + const mod = 10 ** 9 + 7; + + for (let i = 0, s = 0, k = 0; i < n; i++, s = 0) { + for (let j = i; j < n; j++, k++) { + s += nums[j]; + arr[k] = s; + } + } + + let ans = 0; + arr = arr.sort((a, b) => a - b).slice(left - 1, right); + for (const x of arr) { + ans += x; + } + + return ans % mod; +} +``` + +#### JavaScript + +```js +function rangeSum(nums, n, left, right) { + let arr = Array((n * (n + 1)) / 2).fill(0); + const mod = 10 ** 9 + 7; + + for (let i = 0, s = 0, k = 0; i < n; i++, s = 0) { + for (let j = i; j < n; j++, k++) { + s += nums[j]; + arr[k] = s; + } + } + + let ans = 0; + arr = arr.sort((a, b) => a - b).slice(left - 1, right); + for (const x of arr) { + ans += x; + } + + return ans % mod; +} +``` + diff --git a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md index 9d2e4df2e369..6645ba6d28c4 100644 --- a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md +++ b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/README_EN.md @@ -65,7 +65,11 @@ tags: -### Solution 1 +### Solution 1: Sorting + +According to the problem statement, generate the `arr` array, sort it, and then sum all the elements in the range $[left-1,.. right-1]$ to get the result. + +Time complexity is $O(n^2 \times \log n)$, and space complexity is $O(n^2)$. Here, $n$ is the length of the array given in the problem. @@ -155,6 +159,54 @@ func rangeSum(nums []int, n int, left int, right int) (ans int) { } ``` +#### TypeScript + +```ts +function rangeSum(nums: number[], n: number, left: number, right: number): number { + let arr = Array((n * (n + 1)) / 2).fill(0); + const mod = 10 ** 9 + 7; + + for (let i = 0, s = 0, k = 0; i < n; i++, s = 0) { + for (let j = i; j < n; j++, k++) { + s += nums[j]; + arr[k] = s; + } + } + + let ans = 0; + arr = arr.sort((a, b) => a - b).slice(left - 1, right); + for (const x of arr) { + ans += x; + } + + return ans % mod; +} +``` + +#### JavaScript + +```js +function rangeSum(nums, n, left, right) { + let arr = Array((n * (n + 1)) / 2).fill(0); + const mod = 10 ** 9 + 7; + + for (let i = 0, s = 0, k = 0; i < n; i++, s = 0) { + for (let j = i; j < n; j++, k++) { + s += nums[j]; + arr[k] = s; + } + } + + let ans = 0; + arr = arr.sort((a, b) => a - b).slice(left - 1, right); + for (const x of arr) { + ans += x; + } + + return ans % mod; +} +``` + diff --git a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/Solution.js b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/Solution.js new file mode 100644 index 000000000000..83f07fdce38b --- /dev/null +++ b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/Solution.js @@ -0,0 +1,19 @@ +function rangeSum(nums, n, left, right) { + let arr = Array((n * (n + 1)) / 2).fill(0); + const mod = 10 ** 9 + 7; + + for (let i = 0, s = 0, k = 0; i < n; i++, s = 0) { + for (let j = i; j < n; j++, k++) { + s += nums[j]; + arr[k] = s; + } + } + + let ans = 0; + arr = arr.sort((a, b) => a - b).slice(left - 1, right); + for (const x of arr) { + ans += x; + } + + return ans % mod; +} diff --git a/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/Solution.ts b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/Solution.ts new file mode 100644 index 000000000000..22e1796afe0a --- /dev/null +++ b/solution/1500-1599/1508.Range Sum of Sorted Subarray Sums/Solution.ts @@ -0,0 +1,19 @@ +function rangeSum(nums: number[], n: number, left: number, right: number): number { + let arr = Array((n * (n + 1)) / 2).fill(0); + const mod = 10 ** 9 + 7; + + for (let i = 0, s = 0, k = 0; i < n; i++, s = 0) { + for (let j = i; j < n; j++, k++) { + s += nums[j]; + arr[k] = s; + } + } + + let ans = 0; + arr = arr.sort((a, b) => a - b).slice(left - 1, right); + for (const x of arr) { + ans += x; + } + + return ans % mod; +} diff --git a/solution/1500-1599/1510.Stone Game IV/README.md b/solution/1500-1599/1510.Stone Game IV/README.md index 1b8702110aa6..b268f3b525de 100644 --- a/solution/1500-1599/1510.Stone Game IV/README.md +++ b/solution/1500-1599/1510.Stone Game IV/README.md @@ -242,8 +242,8 @@ function winnerSquareGame(n: number): boolean { $$ f[i]= \begin{cases} -true, & \text{if } \exists j \in [1,..i], j^2 \leq i \text{ and } f[i-j^2] = false\\ -false, & \text{otherwise} +true, & \textit{if } \exists j \in [1,..i], j^2 \leq i \textit{ and } f[i-j^2] = false\\ +false, & \textit{otherwise} \end{cases} $$ diff --git a/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README.md b/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README.md index 946a912a6162..b0fe402ef0ad 100644 --- a/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README.md +++ b/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README.md @@ -91,7 +91,11 @@ tags: 我们注意到 $f[i]$ 只与 $f[i-1]$ 有关,因此可以只用一个变量来维护操作次数。 -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $target$ 的长度。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $target$ 的长度。空间复杂度 $O(1)$。 + +相似题目: + +- [3229. 使数组等于目标数组所需的最少操作次数](https://github.com/doocs/leetcode/blob/main/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README.md) diff --git a/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README_EN.md b/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README_EN.md index fe4370612f9d..0db551b52544 100644 --- a/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README_EN.md +++ b/solution/1500-1599/1526.Minimum Number of Increments on Subarrays to Form a Target Array/README_EN.md @@ -73,7 +73,21 @@ tags: -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i]$ as the minimum number of operations required to obtain $target[0,..i]$, initially setting $f[0] = target[0]$. + +For $target[i]$, if $target[i] \leq target[i-1]$, then $f[i] = f[i-1]$; otherwise, $f[i] = f[i-1] + target[i] - target[i-1]$. + +The final answer is $f[n-1]$. + +We notice that $f[i]$ only depends on $f[i-1]$, so we can maintain the operation count using just one variable. + +The time complexity is $O(n)$, where $n$ is the length of the array $target$. The space complexity is $O(1)$. + +Similar problems: + +- [3229. Minimum Operations to Make Array Equal to Target](https://github.com/doocs/leetcode/blob/main/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README_EN.md) diff --git a/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README.md b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README.md index 1c9be8fd9160..9aa18d9cce90 100644 --- a/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README.md +++ b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README.md @@ -270,6 +270,93 @@ func dfs(root *TreeNode, cnt []int, i int) { } ``` +#### TypeScript + +```ts +function countPairs(root: TreeNode | null, distance: number): number { + const pairs: number[][] = []; + + const dfs = (node: TreeNode | null): number[][] => { + if (!node) return []; + if (!node.left && !node.right) return [[node.val, 1]]; + + const left = dfs(node.left); + const right = dfs(node.right); + + for (const [x, dx] of left) { + for (const [y, dy] of right) { + if (dx + dy <= distance) { + pairs.push([x, y]); + } + } + } + + const res: number[][] = []; + for (const arr of [left, right]) { + for (const x of arr) { + if (++x[1] <= distance) res.push(x); + } + } + + return res; + }; + + dfs(root); + + return pairs.length; +} +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} distance + * @return {number} + */ +var countPairs = function (root, distance) { + const pairs = []; + + const dfs = node => { + if (!node) return []; + if (!node.left && !node.right) return [[node.val, 1]]; + + const left = dfs(node.left); + const right = dfs(node.right); + + for (const [x, dx] of left) { + for (const [y, dy] of right) { + if (dx + dy <= distance) { + pairs.push([x, y]); + } + } + } + + const res = []; + for (const arr of [left, right]) { + for (const x of arr) { + if (++x[1] <= distance) res.push(x); + } + } + + return res; + }; + + dfs(root); + + return pairs.length; +}; +``` + diff --git a/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README_EN.md b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README_EN.md index 8f970a762fca..6f73d2a52b3b 100644 --- a/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README_EN.md +++ b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/README_EN.md @@ -245,6 +245,93 @@ func dfs(root *TreeNode, cnt []int, i int) { } ``` +#### TypeScript + +```ts +function countPairs(root: TreeNode | null, distance: number): number { + const pairs: number[][] = []; + + const dfs = (node: TreeNode | null): number[][] => { + if (!node) return []; + if (!node.left && !node.right) return [[node.val, 1]]; + + const left = dfs(node.left); + const right = dfs(node.right); + + for (const [x, dx] of left) { + for (const [y, dy] of right) { + if (dx + dy <= distance) { + pairs.push([x, y]); + } + } + } + + const res: number[][] = []; + for (const arr of [left, right]) { + for (const x of arr) { + if (++x[1] <= distance) res.push(x); + } + } + + return res; + }; + + dfs(root); + + return pairs.length; +} +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} distance + * @return {number} + */ +var countPairs = function (root, distance) { + const pairs = []; + + const dfs = node => { + if (!node) return []; + if (!node.left && !node.right) return [[node.val, 1]]; + + const left = dfs(node.left); + const right = dfs(node.right); + + for (const [x, dx] of left) { + for (const [y, dy] of right) { + if (dx + dy <= distance) { + pairs.push([x, y]); + } + } + } + + const res = []; + for (const arr of [left, right]) { + for (const x of arr) { + if (++x[1] <= distance) res.push(x); + } + } + + return res; + }; + + dfs(root); + + return pairs.length; +}; +``` + diff --git a/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/Solution.js b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/Solution.js new file mode 100644 index 000000000000..e2969fafa217 --- /dev/null +++ b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/Solution.js @@ -0,0 +1,45 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} distance + * @return {number} + */ +var countPairs = function (root, distance) { + const pairs = []; + + const dfs = node => { + if (!node) return []; + if (!node.left && !node.right) return [[node.val, 1]]; + + const left = dfs(node.left); + const right = dfs(node.right); + + for (const [x, dx] of left) { + for (const [y, dy] of right) { + if (dx + dy <= distance) { + pairs.push([x, y]); + } + } + } + + const res = []; + for (const arr of [left, right]) { + for (const x of arr) { + if (++x[1] <= distance) res.push(x); + } + } + + return res; + }; + + dfs(root); + + return pairs.length; +}; diff --git a/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/Solution.ts b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/Solution.ts new file mode 100644 index 000000000000..2f65dca9127c --- /dev/null +++ b/solution/1500-1599/1530.Number of Good Leaf Nodes Pairs/Solution.ts @@ -0,0 +1,32 @@ +function countPairs(root: TreeNode | null, distance: number): number { + const pairs: number[][] = []; + + const dfs = (node: TreeNode | null): number[][] => { + if (!node) return []; + if (!node.left && !node.right) return [[node.val, 1]]; + + const left = dfs(node.left); + const right = dfs(node.right); + + for (const [x, dx] of left) { + for (const [y, dy] of right) { + if (dx + dy <= distance) { + pairs.push([x, y]); + } + } + } + + const res: number[][] = []; + for (const arr of [left, right]) { + for (const x of arr) { + if (++x[1] <= distance) res.push(x); + } + } + + return res; + }; + + dfs(root); + + return pairs.length; +} diff --git a/solution/1500-1599/1550.Three Consecutive Odds/README.md b/solution/1500-1599/1550.Three Consecutive Odds/README.md index 36d12e53d91a..a6129a9b336c 100644 --- a/solution/1500-1599/1550.Three Consecutive Odds/README.md +++ b/solution/1500-1599/1550.Three Consecutive Odds/README.md @@ -53,13 +53,13 @@ tags: ### 方法一:遍历 + 计数 -我们用一个变量 $\text{cnt}$ 记录当前连续奇数的个数。 +我们用一个变量 $\textit{cnt}$ 记录当前连续奇数的个数。 -接下来,我们遍历数组,如果当前元素是奇数,则 $\text{cnt}$ 加一,如果 $\text{cnt}$ 等于 3,则返回 $\text{True}$。如果当前元素是偶数,则 $\text{cnt}$ 置零。 +接下来,我们遍历数组,如果当前元素是奇数,则 $\textit{cnt}$ 加一,如果 $\textit{cnt}$ 等于 3,则返回 $\textit{True}$。如果当前元素是偶数,则 $\textit{cnt}$ 置零。 -遍历结束后,如果没有找到连续三个奇数,则返回 $\text{False}$。 +遍历结束后,如果没有找到连续三个奇数,则返回 $\textit{False}$。 -时间复杂度 $O(n)$,其中 $n$ 是数组 $\text{arr}$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(n)$,其中 $n$ 是数组 $\textit{arr}$ 的长度。空间复杂度 $O(1)$。 @@ -167,9 +167,9 @@ function threeConsecutiveOdds(arr: number[]): boolean { 根据位运算的性质,两个数进行按位与运算是奇数,当且仅当两个数都是奇数。如果有连续三个数按位与运算的结果是奇数,那么这三个数都是奇数。 -因此,我们只需要遍历数组,判断是否存在连续三个数的按位与结果是否是奇数即可,如果存在则返回 $\text{True}$,否则返回 $\text{False}$。 +因此,我们只需要遍历数组,判断是否存在连续三个数的按位与结果是否是奇数即可,如果存在则返回 $\textit{True}$,否则返回 $\textit{False}$。 -时间复杂度 $O(n)$,其中 $n$ 是数组 $\text{arr}$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(n)$,其中 $n$ 是数组 $\textit{arr}$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/1500-1599/1550.Three Consecutive Odds/README_EN.md b/solution/1500-1599/1550.Three Consecutive Odds/README_EN.md index f6b6381f1cee..79052357c5e5 100644 --- a/solution/1500-1599/1550.Three Consecutive Odds/README_EN.md +++ b/solution/1500-1599/1550.Three Consecutive Odds/README_EN.md @@ -53,13 +53,13 @@ Given an integer array arr, return true if there ### Solution 1: Iteration + Counting -We use a variable $\text{cnt}$ to record the current count of consecutive odd numbers. +We use a variable $\textit{cnt}$ to record the current count of consecutive odd numbers. -Next, we iterate through the array. If the current element is odd, then $\text{cnt}$ is incremented by one. If $\text{cnt}$ equals 3, then return $\text{True}$. If the current element is even, then $\text{cnt}$ is reset to zero. +Next, we iterate through the array. If the current element is odd, then $\textit{cnt}$ is incremented by one. If $\textit{cnt}$ equals 3, then return $\textit{True}$. If the current element is even, then $\textit{cnt}$ is reset to zero. -After the iteration, if three consecutive odd numbers are not found, then return $\text{False}$. +After the iteration, if three consecutive odd numbers are not found, then return $\textit{False}$. -The time complexity is $O(n)$, where $n$ is the length of the array $\text{arr}$. The space complexity is $O(1)$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{arr}$. The space complexity is $O(1)$. @@ -167,9 +167,9 @@ function threeConsecutiveOdds(arr: number[]): boolean { Based on the properties of bitwise operations, the result of a bitwise AND operation between two numbers is odd if and only if both numbers are odd. If there are three consecutive numbers whose bitwise AND result is odd, then these three numbers are all odd. -Therefore, we only need to iterate through the array and check if there exists three consecutive numbers whose bitwise AND result is odd. If such numbers exist, return $\text{True}$; otherwise, return $\text{False}$. +Therefore, we only need to iterate through the array and check if there exists three consecutive numbers whose bitwise AND result is odd. If such numbers exist, return $\textit{True}$; otherwise, return $\textit{False}$. -The time complexity is $O(n)$, where $n$ is the length of the array $\text{arr}$. The space complexity is $O(1)$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{arr}$. The space complexity is $O(1)$. diff --git a/solution/1500-1599/1552.Magnetic Force Between Two Balls/README.md b/solution/1500-1599/1552.Magnetic Force Between Two Balls/README.md index 254a569e2af6..6aa40c35c2a7 100644 --- a/solution/1500-1599/1552.Magnetic Force Between Two Balls/README.md +++ b/solution/1500-1599/1552.Magnetic Force Between Two Balls/README.md @@ -66,7 +66,7 @@ tags: 我们注意到,任意两球间的最小磁力越大,能够放入的球的数量就越少,这存在着单调性。我们可以使用二分查找,找到最大的最小磁力,使得能够放入的球的数量不小于 $m$。 -我们首先对篮子的位置进行排序,然后使用二分查找的方法,定义二分查找的左边界 $l = 1$,右边界 $r = \text{position}[n - 1]$,其中 $n$ 为篮子的数量。在每次二分查找的过程中,我们计算取中值 $m = (l + r + 1) / 2$,然后判断是否存在一种放置球的方法,使得能够放入的球的数量不小于 $m$。 +我们首先对篮子的位置进行排序,然后使用二分查找的方法,定义二分查找的左边界 $l = 1$,右边界 $r = \textit{position}[n - 1]$,其中 $n$ 为篮子的数量。在每次二分查找的过程中,我们计算取中值 $m = (l + r + 1) / 2$,然后判断是否存在一种放置球的方法,使得能够放入的球的数量不小于 $m$。 问题转换为判断一个给定的最小磁力 $f$ 是否能够放入 $m$ 个球。我们可以从左到右遍历篮子的位置,如果上一个球的位置与当前篮子的位置的距离大于等于 $f$,则说明可以在当前篮子放置一个球。最后判断放置的球的数量是否不小于 $m$ 即可。 diff --git a/solution/1500-1599/1552.Magnetic Force Between Two Balls/README_EN.md b/solution/1500-1599/1552.Magnetic Force Between Two Balls/README_EN.md index 1baf8b261e93..79b3601a09f7 100644 --- a/solution/1500-1599/1552.Magnetic Force Between Two Balls/README_EN.md +++ b/solution/1500-1599/1552.Magnetic Force Between Two Balls/README_EN.md @@ -64,7 +64,7 @@ tags: We notice that the greater the minimum magnetic force between any two balls, the fewer balls can be placed, which exhibits monotonicity. We can use binary search to find the maximum minimum magnetic force that allows the number of balls not less than $m$ to be placed. -First, we sort the positions of the baskets, and then use binary search with the left boundary $l = 1$ and the right boundary $r = \text{position}[n - 1]$, where $n$ is the number of baskets. In each binary search iteration, we calculate the midpoint $m = (l + r + 1) / 2$, and then determine if there is a way to place the balls such that the number of balls placed is not less than $m$. +First, we sort the positions of the baskets, and then use binary search with the left boundary $l = 1$ and the right boundary $r = \textit{position}[n - 1]$, where $n$ is the number of baskets. In each binary search iteration, we calculate the midpoint $m = (l + r + 1) / 2$, and then determine if there is a way to place the balls such that the number of balls placed is not less than $m$. The problem is transformed into determining whether a given minimum magnetic force $f$ can place $m$ balls. We can traverse the positions of the baskets from left to right, and if the distance between the position of the last ball and the current basket's position is greater than or equal to $f$, it indicates that a ball can be placed in the current basket. Finally, we check if the number of balls placed is not less than $m$. diff --git a/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README.md b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README.md index 37fc147aeb92..568014ba15f6 100644 --- a/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README.md +++ b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README.md @@ -295,6 +295,117 @@ func minDays(grid [][]int) int { } ``` +#### TypeScript + +```ts +function minDays(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + + const dfs = (i: number, j: number) => { + if (i < 0 || m <= i || j < 0 || n <= j || [0, 2].includes(grid[i][j])) return; + + grid[i][j] = 2; + const dir = [-1, 0, 1, 0, -1]; + for (let k = 0; k < 4; k++) { + const [y, x] = [i + dir[k], j + dir[k + 1]]; + dfs(y, x); + } + }; + + const count = () => { + let c = 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + dfs(i, j); + c++; + } + } + } + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 2) { + grid[i][j] = 1; + } + } + } + + return c; + }; + + if (count() !== 1) return 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + grid[i][j] = 0; + + if (count() !== 1) return 1; + + grid[i][j] = 1; + } + } + } + + return 2; +} +``` + +#### JavaScript + +```js +/** + * @param {number[][]} grid + * @return {number} + */ +var minDays = function (grid) { + const dirs = [-1, 0, 1, 0, -1]; + const [m, n] = [grid.length, grid[0].length]; + + const dfs = (i, j, visited) => { + if (i < 0 || m <= i || j < 0 || n <= j || grid[i][j] === 0 || visited[i][j]) { + return; + } + + visited[i][j] = true; + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + dfs(y, x, visited); + } + }; + + const count = () => { + const vis = Array.from({ length: m }, () => Array(n).fill(false)); + let c = 0; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1 && !vis[i][j]) { + c++; + dfs(i, j, vis); + } + } + } + return c; + }; + + if (count() !== 1) return 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + grid[i][j] = 0; + if (count() !== 1) return 1; + grid[i][j] = 1; + } + } + } + + return 2; +}; +``` + diff --git a/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README_EN.md b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README_EN.md index 76e9a2206e44..8c5a1bb17222 100644 --- a/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README_EN.md +++ b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/README_EN.md @@ -286,6 +286,117 @@ func minDays(grid [][]int) int { } ``` +#### TypeScript + +```ts +function minDays(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + + const dfs = (i: number, j: number) => { + if (i < 0 || m <= i || j < 0 || n <= j || [0, 2].includes(grid[i][j])) return; + + grid[i][j] = 2; + const dir = [-1, 0, 1, 0, -1]; + for (let k = 0; k < 4; k++) { + const [y, x] = [i + dir[k], j + dir[k + 1]]; + dfs(y, x); + } + }; + + const count = () => { + let c = 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + dfs(i, j); + c++; + } + } + } + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 2) { + grid[i][j] = 1; + } + } + } + + return c; + }; + + if (count() !== 1) return 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + grid[i][j] = 0; + + if (count() !== 1) return 1; + + grid[i][j] = 1; + } + } + } + + return 2; +} +``` + +#### JavaScript + +```js +/** + * @param {number[][]} grid + * @return {number} + */ +var minDays = function (grid) { + const dirs = [-1, 0, 1, 0, -1]; + const [m, n] = [grid.length, grid[0].length]; + + const dfs = (i, j, visited) => { + if (i < 0 || m <= i || j < 0 || n <= j || grid[i][j] === 0 || visited[i][j]) { + return; + } + + visited[i][j] = true; + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + dfs(y, x, visited); + } + }; + + const count = () => { + const vis = Array.from({ length: m }, () => Array(n).fill(false)); + let c = 0; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1 && !vis[i][j]) { + c++; + dfs(i, j, vis); + } + } + } + return c; + }; + + if (count() !== 1) return 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + grid[i][j] = 0; + if (count() !== 1) return 1; + grid[i][j] = 1; + } + } + } + + return 2; +}; +``` + diff --git a/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/Solution.js b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/Solution.js new file mode 100644 index 000000000000..8bf62047d183 --- /dev/null +++ b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/Solution.js @@ -0,0 +1,48 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +var minDays = function (grid) { + const dirs = [-1, 0, 1, 0, -1]; + const [m, n] = [grid.length, grid[0].length]; + + const dfs = (i, j, visited) => { + if (i < 0 || m <= i || j < 0 || n <= j || grid[i][j] === 0 || visited[i][j]) { + return; + } + + visited[i][j] = true; + for (let d = 0; d < 4; d++) { + const [y, x] = [i + dirs[d], j + dirs[d + 1]]; + dfs(y, x, visited); + } + }; + + const count = () => { + const vis = Array.from({ length: m }, () => Array(n).fill(false)); + let c = 0; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1 && !vis[i][j]) { + c++; + dfs(i, j, vis); + } + } + } + return c; + }; + + if (count() !== 1) return 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + grid[i][j] = 0; + if (count() !== 1) return 1; + grid[i][j] = 1; + } + } + } + + return 2; +}; diff --git a/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/Solution.ts b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/Solution.ts new file mode 100644 index 000000000000..7837bdadff4a --- /dev/null +++ b/solution/1500-1599/1568.Minimum Number of Days to Disconnect Island/Solution.ts @@ -0,0 +1,53 @@ +function minDays(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + + const dfs = (i: number, j: number) => { + if (i < 0 || m <= i || j < 0 || n <= j || [0, 2].includes(grid[i][j])) return; + + grid[i][j] = 2; + const dir = [-1, 0, 1, 0, -1]; + for (let k = 0; k < 4; k++) { + const [y, x] = [i + dir[k], j + dir[k + 1]]; + dfs(y, x); + } + }; + + const count = () => { + let c = 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + dfs(i, j); + c++; + } + } + } + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 2) { + grid[i][j] = 1; + } + } + } + + return c; + }; + + if (count() !== 1) return 0; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1) { + grid[i][j] = 0; + + if (count() !== 1) return 1; + + grid[i][j] = 1; + } + } + } + + return 2; +} diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README.md b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README.md index 8f7bb20b8ac7..b4da39eab1a0 100644 --- a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README.md +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README.md @@ -176,7 +176,7 @@ function minimumDeletions(s: string): number { const f = new Array(n + 1).fill(0); let b = 0; for (let i = 1; i <= n; ++i) { - if (s.charAt(i - 1) === 'b') { + if (s[i - 1] === 'b') { f[i] = f[i - 1]; ++b; } else { @@ -187,6 +187,29 @@ function minimumDeletions(s: string): number { } ``` +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + const n = s.length; + const f = new Array(n + 1).fill(0); + let b = 0; + for (let i = 1; i <= n; ++i) { + if (s[i - 1] === 'b') { + f[i] = f[i - 1]; + ++b; + } else { + f[i] = Math.min(f[i - 1] + 1, b); + } + } + return f[n]; +}; +``` + @@ -275,11 +298,10 @@ func minimumDeletions(s string) int { ```ts function minimumDeletions(s: string): number { - const n = s.length; - let ans = 0, - b = 0; - for (let i = 0; i < n; ++i) { - if (s.charAt(i) === 'b') { + let [ans, b] = [0, 0]; + + for (const ch of s) { + if (ch === 'b') { ++b; } else { ans = Math.min(ans + 1, b); @@ -289,6 +311,27 @@ function minimumDeletions(s: string): number { } ``` +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + let [ans, b] = [0, 0]; + + for (const ch of s) { + if (ch === 'b') { + ++b; + } else { + ans = Math.min(ans + 1, b); + } + } + return ans; +}; +``` + @@ -379,24 +422,90 @@ func minimumDeletions(s string) int { ```ts function minimumDeletions(s: string): number { - let lb = 0, - ra = 0; - const n = s.length; - for (let i = 0; i < n; ++i) { - if (s.charAt(i) === 'a') { - ++ra; - } + let ra = [...s].reduce((acc, x) => (x === 'a' ? acc + 1 : acc), 0); + let lb = 0; + + let ans = s.length; + for (const ch of s) { + if (ch === 'a') ra--; + ans = Math.min(ans, lb + ra); + if (ch === 'b') lb++; } - let ans = n; - for (let i = 0; i < n; ++i) { - ra -= s.charAt(i) === 'a' ? 1 : 0; + return ans; +} +``` + +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + let ra = [...s].reduce((acc, x) => (x === 'a' ? acc + 1 : acc), 0); + let lb = 0; + + let ans = s.length; + for (const ch of s) { + if (ch === 'a') ra--; ans = Math.min(ans, lb + ra); - lb += s.charAt(i) === 'b' ? 1 : 0; + if (ch === 'b') lb++; } return ans; +}; +``` + + + + + + + +### Solution 4: Stack + + + +#### TypeScript + +```ts +function minimumDeletions(s: string): number { + const stk: string[] = []; + let res = 0; + + for (const ch of s) { + if (stk.at(-1) === 'b' && ch === 'a') { + stk.pop(); + res++; + } else stk.push(ch); + } + + return res; } ``` +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + const stk = []; + let res = 0; + + for (const ch of s) { + if (stk.at(-1) === 'b' && ch === 'a') { + stk.pop(); + res++; + } else stk.push(ch); + } + + return res; +}; +``` + diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README_EN.md b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README_EN.md index 70df45432b4e..b3716da42bbe 100644 --- a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README_EN.md +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/README_EN.md @@ -174,7 +174,7 @@ function minimumDeletions(s: string): number { const f = new Array(n + 1).fill(0); let b = 0; for (let i = 1; i <= n; ++i) { - if (s.charAt(i - 1) === 'b') { + if (s[i - 1] === 'b') { f[i] = f[i - 1]; ++b; } else { @@ -185,6 +185,29 @@ function minimumDeletions(s: string): number { } ``` +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + const n = s.length; + const f = new Array(n + 1).fill(0); + let b = 0; + for (let i = 1; i <= n; ++i) { + if (s[i - 1] === 'b') { + f[i] = f[i - 1]; + ++b; + } else { + f[i] = Math.min(f[i - 1] + 1, b); + } + } + return f[n]; +}; +``` + @@ -273,11 +296,10 @@ func minimumDeletions(s string) int { ```ts function minimumDeletions(s: string): number { - const n = s.length; - let ans = 0, - b = 0; - for (let i = 0; i < n; ++i) { - if (s.charAt(i) === 'b') { + let [ans, b] = [0, 0]; + + for (const ch of s) { + if (ch === 'b') { ++b; } else { ans = Math.min(ans + 1, b); @@ -287,13 +309,34 @@ function minimumDeletions(s: string): number { } ``` +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + let [ans, b] = [0, 0]; + + for (const ch of s) { + if (ch === 'b') { + ++b; + } else { + ans = Math.min(ans + 1, b); + } + } + return ans; +}; +``` + -### Solution 3 +### Solution 3: Two-Variable Method @@ -377,24 +420,90 @@ func minimumDeletions(s string) int { ```ts function minimumDeletions(s: string): number { - let lb = 0, - ra = 0; - const n = s.length; - for (let i = 0; i < n; ++i) { - if (s.charAt(i) === 'a') { - ++ra; - } + let ra = [...s].reduce((acc, x) => (x === 'a' ? acc + 1 : acc), 0); + let lb = 0; + + let ans = s.length; + for (const ch of s) { + if (ch === 'a') ra--; + ans = Math.min(ans, lb + ra); + if (ch === 'b') lb++; } - let ans = n; - for (let i = 0; i < n; ++i) { - ra -= s.charAt(i) === 'a' ? 1 : 0; + return ans; +} +``` + +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + let ra = [...s].reduce((acc, x) => (x === 'a' ? acc + 1 : acc), 0); + let lb = 0; + + let ans = s.length; + for (const ch of s) { + if (ch === 'a') ra--; ans = Math.min(ans, lb + ra); - lb += s.charAt(i) === 'b' ? 1 : 0; + if (ch === 'b') lb++; } return ans; +}; +``` + + + + + + + +### Solution 4: Stack + + + +#### TypeScript + +```ts +function minimumDeletions(s: string): number { + const stk: string[] = []; + let res = 0; + + for (const ch of s) { + if (stk.at(-1) === 'b' && ch === 'a') { + stk.pop(); + res++; + } else stk.push(ch); + } + + return res; } ``` +#### JavaScript + +```js +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + const stk = []; + let res = 0; + + for (const ch of s) { + if (stk.at(-1) === 'b' && ch === 'a') { + stk.pop(); + res++; + } else stk.push(ch); + } + + return res; +}; +``` + diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution.js b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution.js new file mode 100644 index 000000000000..be8720c89781 --- /dev/null +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution.js @@ -0,0 +1,18 @@ +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + const n = s.length; + const f = new Array(n + 1).fill(0); + let b = 0; + for (let i = 1; i <= n; ++i) { + if (s[i - 1] === 'b') { + f[i] = f[i - 1]; + ++b; + } else { + f[i] = Math.min(f[i - 1] + 1, b); + } + } + return f[n]; +}; diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution.ts b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution.ts index 9800753821a5..db2e4b1872fb 100644 --- a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution.ts +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution.ts @@ -3,7 +3,7 @@ function minimumDeletions(s: string): number { const f = new Array(n + 1).fill(0); let b = 0; for (let i = 1; i <= n; ++i) { - if (s.charAt(i - 1) === 'b') { + if (s[i - 1] === 'b') { f[i] = f[i - 1]; ++b; } else { diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution2.js b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution2.js new file mode 100644 index 000000000000..8a53f2b5e23e --- /dev/null +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution2.js @@ -0,0 +1,16 @@ +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + let [ans, b] = [0, 0]; + + for (const ch of s) { + if (ch === 'b') { + ++b; + } else { + ans = Math.min(ans + 1, b); + } + } + return ans; +}; diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution2.ts b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution2.ts index 35cdc37e29f9..bc0de452db10 100644 --- a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution2.ts +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution2.ts @@ -1,9 +1,8 @@ function minimumDeletions(s: string): number { - const n = s.length; - let ans = 0, - b = 0; - for (let i = 0; i < n; ++i) { - if (s.charAt(i) === 'b') { + let [ans, b] = [0, 0]; + + for (const ch of s) { + if (ch === 'b') { ++b; } else { ans = Math.min(ans + 1, b); diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution3.js b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution3.js new file mode 100644 index 000000000000..09f288807680 --- /dev/null +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution3.js @@ -0,0 +1,16 @@ +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + let ra = [...s].reduce((acc, x) => (x === 'a' ? acc + 1 : acc), 0); + let lb = 0; + + let ans = s.length; + for (const ch of s) { + if (ch === 'a') ra--; + ans = Math.min(ans, lb + ra); + if (ch === 'b') lb++; + } + return ans; +}; diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution3.ts b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution3.ts index 0364c8ddafe8..07f6bfcd39a0 100644 --- a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution3.ts +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution3.ts @@ -1,17 +1,12 @@ function minimumDeletions(s: string): number { - let lb = 0, - ra = 0; - const n = s.length; - for (let i = 0; i < n; ++i) { - if (s.charAt(i) === 'a') { - ++ra; - } - } - let ans = n; - for (let i = 0; i < n; ++i) { - ra -= s.charAt(i) === 'a' ? 1 : 0; + let ra = [...s].reduce((acc, x) => (x === 'a' ? acc + 1 : acc), 0); + let lb = 0; + + let ans = s.length; + for (const ch of s) { + if (ch === 'a') ra--; ans = Math.min(ans, lb + ra); - lb += s.charAt(i) === 'b' ? 1 : 0; + if (ch === 'b') lb++; } return ans; } diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution4.js b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution4.js new file mode 100644 index 000000000000..1a1407694242 --- /dev/null +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution4.js @@ -0,0 +1,17 @@ +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function (s) { + const stk = []; + let res = 0; + + for (const ch of s) { + if (stk.at(-1) === 'b' && ch === 'a') { + stk.pop(); + res++; + } else stk.push(ch); + } + + return res; +}; diff --git a/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution4.ts b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution4.ts new file mode 100644 index 000000000000..e1531241673d --- /dev/null +++ b/solution/1600-1699/1653.Minimum Deletions to Make String Balanced/Solution4.ts @@ -0,0 +1,13 @@ +function minimumDeletions(s: string): number { + const stk: string[] = []; + let res = 0; + + for (const ch of s) { + if (stk.at(-1) === 'b' && ch === 'a') { + stk.pop(); + res++; + } else stk.push(ch); + } + + return res; +} diff --git a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README.md b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README.md index 1e02b6deb825..53f1b9987766 100644 --- a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README.md +++ b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README.md @@ -76,27 +76,33 @@ nums[3] + nums[0] = 3 + 1 = 4. ### 方法一:差分数组 -我们不妨设 $a$ 为 $nums[i]$ 和 $nums[n-i-1]$ 的较小值,设 $b$ 为 $nums[i]$ 和 $nums[n-i-1]$ 的较大值。 +假设最终的数组中,数对 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的和为 $s$。 -假设经过替换后,两数之和为 $x$。由题意,我们知道 $x$ 最小值为 $2$,即两个数替换为 $1$;最大值为 $2 \times limit$,即两个数都替换为 $limit$。因此 $x$ 的取值范围是 $[2,... 2 \times limit]$。 +我们不妨设 $x$ 为 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的较小值,设 $y$ 为 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的较大值。 -如何求出对于不同的 $x$,需要替换的最少次数呢? +对于每一对数,我们有以下几种情况: -我们分析发现: +- 如果不需要替换,那么 $x + y = s$。 +- 如果替换一次,那么 $x + 1 \le s \le y + \textit{limit}$。 +- 如果替换两次,那么 $2 \le s \le x$ 或 $y + \textit{limit} + 1 \le s \le 2 \times \textit{limit}$。 -- 如果 $x = a + b$,那么我们需要替换的次数为 $0$,即当前的数对已经满足互补的要求; -- 否则如果 $1 + a \le x \le limit + b $,那么我们需要替换的次数为 $1$,即把其中一个数替换即可; -- 否则如果 $2 \le x \le 2 \times limit$,那么我们需要替换的次数为 $2$,即把两个数都替换。 +即: -因此,我们可以遍历每一对数,执行如下操作: +- 在 $[2,..x]$ 范围内,需要替换 $2$ 次。 +- 在 $[x+1,..x+y-1]$ 范围内,需要替换 $1$ 次。 +- 在 $[x+y]$ 时,不需要替换。 +- 在 $[x+y+1,..y + \textit{limit}]$ 范围内,需要替换 $1$ 次。 +- 在 $[y + \textit{limit} + 1,..2 \times \textit{limit}]$ 范围内,需要替换 $2$ 次。 -1. 先将 $[2,... 2 \times limit]$ 范围需要的操作次数加 $2$。 -1. 再将 $[1 + a,... limit + b]$ 范围需要的操作次数减 $1$。 -1. 最后将 $[a + b,... a + b]$ 范围需要的操作次数减 $1$。 +我们枚举每一个数对,利用差分数组,更新每个数对在不同区间范围内的替换次数。 -可以发现,这实际上是在对一个连续区间内的元素进行加减操作,因此我们可以使用差分数组来实现。 +最后,我们求出下标 $2$ 到 $2 \times \textit{limit}$ 的前缀和中的最小值,即为最少的替换次数。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 + +相似题目: + +- [3224. 使差值相等的最少数组改动次数](https://github.com/doocs/leetcode/blob/main/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README.md) @@ -105,27 +111,20 @@ nums[3] + nums[0] = 3 + 1 = 4. ```python class Solution: def minMoves(self, nums: List[int], limit: int) -> int: - d = [0] * (limit * 2 + 2) + d = [0] * (2 * limit + 2) n = len(nums) - - for i in range(n >> 1): - a, b = min(nums[i], nums[n - i - 1]), max(nums[i], nums[n - i - 1]) - + for i in range(n // 2): + x, y = nums[i], nums[-i - 1] + if x > y: + x, y = y, x d[2] += 2 - d[limit * 2 + 1] -= 2 - - d[a + 1] -= 1 - d[b + limit + 1] += 1 - - d[a + b] -= 1 - d[a + b + 1] += 1 - - ans, s = n, 0 - for v in d[2 : limit * 2 + 1]: - s += v - if ans > s: - ans = s - return ans + d[x + 1] -= 2 + d[x + 1] += 1 + d[x + y] -= 1 + d[x + y + 1] += 1 + d[y + limit + 1] -= 1 + d[y + limit + 1] += 2 + return min(accumulate(d[2:])) ``` #### Java @@ -133,27 +132,23 @@ class Solution: ```java class Solution { public int minMoves(int[] nums, int limit) { + int[] d = new int[2 * limit + 2]; int n = nums.length; - int[] d = new int[limit * 2 + 2]; - for (int i = 0; i < n >> 1; ++i) { - int a = Math.min(nums[i], nums[n - i - 1]); - int b = Math.max(nums[i], nums[n - i - 1]); - + for (int i = 0; i < n / 2; ++i) { + int x = Math.min(nums[i], nums[n - i - 1]); + int y = Math.max(nums[i], nums[n - i - 1]); d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } - int ans = n, s = 0; - for (int i = 2; i <= limit * 2; ++i) { + int ans = n; + for (int i = 2, s = 0; i < d.length; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = Math.min(ans, s); } return ans; } @@ -167,26 +162,25 @@ class Solution { public: int minMoves(vector& nums, int limit) { int n = nums.size(); - vector d(limit * 2 + 2); - for (int i = 0; i < n >> 1; ++i) { - int a = min(nums[i], nums[n - i - 1]); - int b = max(nums[i], nums[n - i - 1]); - + int d[limit * 2 + 2]; + memset(d, 0, sizeof(d)); + for (int i = 0; i < n / 2; ++i) { + int x = nums[i], y = nums[n - i - 1]; + if (x > y) { + swap(x, y); + } d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } - int ans = n, s = 0; - for (int i = 2; i <= limit * 2; ++i) { + int ans = n; + for (int i = 2, s = 0; i <= limit * 2; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = min(ans, s); } return ans; } @@ -197,25 +191,25 @@ public: ```go func minMoves(nums []int, limit int) int { - d := make([]int, limit*2+2) n := len(nums) - for i := 0; i < n>>1; i++ { - a, b := min(nums[i], nums[n-i-1]), max(nums[i], nums[n-i-1]) + d := make([]int, 2*limit+2) + for i := 0; i < n/2; i++ { + x, y := nums[i], nums[n-1-i] + if x > y { + x, y = y, x + } d[2] += 2 - d[limit*2+1] -= 2 - - d[a+1] -= 1 - d[b+limit+1] += 1 - - d[a+b] -= 1 - d[a+b+1] += 1 + d[x+1] -= 2 + d[x+1] += 1 + d[x+y] -= 1 + d[x+y+1] += 1 + d[y+limit+1] -= 1 + d[y+limit+1] += 2 } ans, s := n, 0 - for _, v := range d[2 : limit*2+1] { - s += v - if ans > s { - ans = s - } + for _, x := range d[2:] { + s += x + ans = min(ans, s) } return ans } @@ -228,25 +222,21 @@ function minMoves(nums: number[], limit: number): number { const n = nums.length; const d: number[] = Array(limit * 2 + 2).fill(0); for (let i = 0; i < n >> 1; ++i) { - const a = Math.min(nums[i], nums[n - i - 1]); - const b = Math.max(nums[i], nums[n - i - 1]); - + const x = Math.min(nums[i], nums[n - 1 - i]); + const y = Math.max(nums[i], nums[n - 1 - i]); d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } let ans = n; let s = 0; - for (let i = 2; i <= limit * 2; ++i) { + for (let i = 2; i < d.length; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = Math.min(ans, s); } return ans; } diff --git a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README_EN.md b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README_EN.md index e4758d80752a..c269e60b8043 100644 --- a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README_EN.md +++ b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/README_EN.md @@ -74,27 +74,33 @@ Therefore, nums[i] + nums[n-1-i] = 4 for every i, so nums is complementary. ### Solution 1: Difference Array -Let's denote $a$ as the smaller value between $nums[i]$ and $nums[n-i-1]$, and $b$ as the larger value between $nums[i]$ and $nums[n-i-1]$. +Assume that in the final array, the sum of the pair $\textit{nums}[i]$ and $\textit{nums}[n-i-1]$ is $s$. -Suppose that after replacement, the sum of the two numbers is $x$. From the problem, we know that the minimum value of $x$ is $2$, which means both numbers are replaced by $1$; the maximum value is $2 \times limit$, which means both numbers are replaced by $limit$. Therefore, the range of $x$ is $[2,... 2 \times limit]$. +Let's denote $x$ as the smaller value between $\textit{nums}[i]$ and $\textit{nums}[n-i-1]$, and $y$ as the larger value. -How to find the minimum number of replacements for different $x$? +For each pair of numbers, we have the following scenarios: -We analyze and find: +- If no replacement is needed, then $x + y = s$. +- If one replacement is made, then $x + 1 \le s \le y + \textit{limit}$. +- If two replacements are made, then $2 \le s \le x$ or $y + \textit{limit} + 1 \le s \le 2 \times \textit{limit}$. -- If $x = a + b$, then the number of replacements we need is $0$, which means the current pair of numbers already meets the complement requirement; -- Otherwise, if $1 + a \le x \le limit + b $, then the number of replacements we need is $1$, which means we can replace one of the numbers; -- Otherwise, if $2 \le x \le 2 \times limit$, then the number of replacements we need is $2$, which means we need to replace both numbers. +That is: -Therefore, we can iterate over each pair of numbers and perform the following operations: +- In the range $[2,..x]$, $2$ replacements are needed. +- In the range $[x+1,..x+y-1]$, $1$ replacement is needed. +- At $[x+y]$, no replacement is needed. +- In the range $[x+y+1,..y + \textit{limit}]$, $1$ replacement is needed. +- In the range $[y + \textit{limit} + 1,..2 \times \textit{limit}]$, $2$ replacements are needed. -1. First, add $2$ to the number of operations required in the range $[2,... 2 \times limit]$. -1. Then, subtract $1$ from the number of operations required in the range $[1 + a,... limit + b]$. -1. Finally, subtract $1$ from the number of operations required in the range $[a + b,... a + b]$. +We enumerate each pair of numbers and use a difference array to update the number of replacements needed in different ranges for each pair. -We can see that this is actually adding and subtracting elements in a continuous interval, so we can use a difference array to implement it. +Finally, we find the minimum value among the prefix sums from index $2$ to $2 \times \textit{limit}$, which is the minimum number of replacements needed. -The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $nums$. +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. + +Similar problems: + +- [3224. Minimum Array Changes to Make Differences Equal](https://github.com/doocs/leetcode/blob/main/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README_EN.md) @@ -103,27 +109,20 @@ The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is ```python class Solution: def minMoves(self, nums: List[int], limit: int) -> int: - d = [0] * (limit * 2 + 2) + d = [0] * (2 * limit + 2) n = len(nums) - - for i in range(n >> 1): - a, b = min(nums[i], nums[n - i - 1]), max(nums[i], nums[n - i - 1]) - + for i in range(n // 2): + x, y = nums[i], nums[-i - 1] + if x > y: + x, y = y, x d[2] += 2 - d[limit * 2 + 1] -= 2 - - d[a + 1] -= 1 - d[b + limit + 1] += 1 - - d[a + b] -= 1 - d[a + b + 1] += 1 - - ans, s = n, 0 - for v in d[2 : limit * 2 + 1]: - s += v - if ans > s: - ans = s - return ans + d[x + 1] -= 2 + d[x + 1] += 1 + d[x + y] -= 1 + d[x + y + 1] += 1 + d[y + limit + 1] -= 1 + d[y + limit + 1] += 2 + return min(accumulate(d[2:])) ``` #### Java @@ -131,27 +130,23 @@ class Solution: ```java class Solution { public int minMoves(int[] nums, int limit) { + int[] d = new int[2 * limit + 2]; int n = nums.length; - int[] d = new int[limit * 2 + 2]; - for (int i = 0; i < n >> 1; ++i) { - int a = Math.min(nums[i], nums[n - i - 1]); - int b = Math.max(nums[i], nums[n - i - 1]); - + for (int i = 0; i < n / 2; ++i) { + int x = Math.min(nums[i], nums[n - i - 1]); + int y = Math.max(nums[i], nums[n - i - 1]); d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } - int ans = n, s = 0; - for (int i = 2; i <= limit * 2; ++i) { + int ans = n; + for (int i = 2, s = 0; i < d.length; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = Math.min(ans, s); } return ans; } @@ -165,26 +160,25 @@ class Solution { public: int minMoves(vector& nums, int limit) { int n = nums.size(); - vector d(limit * 2 + 2); - for (int i = 0; i < n >> 1; ++i) { - int a = min(nums[i], nums[n - i - 1]); - int b = max(nums[i], nums[n - i - 1]); - + int d[limit * 2 + 2]; + memset(d, 0, sizeof(d)); + for (int i = 0; i < n / 2; ++i) { + int x = nums[i], y = nums[n - i - 1]; + if (x > y) { + swap(x, y); + } d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } - int ans = n, s = 0; - for (int i = 2; i <= limit * 2; ++i) { + int ans = n; + for (int i = 2, s = 0; i <= limit * 2; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = min(ans, s); } return ans; } @@ -195,25 +189,25 @@ public: ```go func minMoves(nums []int, limit int) int { - d := make([]int, limit*2+2) n := len(nums) - for i := 0; i < n>>1; i++ { - a, b := min(nums[i], nums[n-i-1]), max(nums[i], nums[n-i-1]) + d := make([]int, 2*limit+2) + for i := 0; i < n/2; i++ { + x, y := nums[i], nums[n-1-i] + if x > y { + x, y = y, x + } d[2] += 2 - d[limit*2+1] -= 2 - - d[a+1] -= 1 - d[b+limit+1] += 1 - - d[a+b] -= 1 - d[a+b+1] += 1 + d[x+1] -= 2 + d[x+1] += 1 + d[x+y] -= 1 + d[x+y+1] += 1 + d[y+limit+1] -= 1 + d[y+limit+1] += 2 } ans, s := n, 0 - for _, v := range d[2 : limit*2+1] { - s += v - if ans > s { - ans = s - } + for _, x := range d[2:] { + s += x + ans = min(ans, s) } return ans } @@ -226,25 +220,21 @@ function minMoves(nums: number[], limit: number): number { const n = nums.length; const d: number[] = Array(limit * 2 + 2).fill(0); for (let i = 0; i < n >> 1; ++i) { - const a = Math.min(nums[i], nums[n - i - 1]); - const b = Math.max(nums[i], nums[n - i - 1]); - + const x = Math.min(nums[i], nums[n - 1 - i]); + const y = Math.max(nums[i], nums[n - 1 - i]); d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } let ans = n; let s = 0; - for (let i = 2; i <= limit * 2; ++i) { + for (let i = 2; i < d.length; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = Math.min(ans, s); } return ans; } diff --git a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.cpp b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.cpp index 4fd464b0d54f..06d2beb31078 100644 --- a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.cpp +++ b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.cpp @@ -2,26 +2,25 @@ class Solution { public: int minMoves(vector& nums, int limit) { int n = nums.size(); - vector d(limit * 2 + 2); - for (int i = 0; i < n >> 1; ++i) { - int a = min(nums[i], nums[n - i - 1]); - int b = max(nums[i], nums[n - i - 1]); - + int d[limit * 2 + 2]; + memset(d, 0, sizeof(d)); + for (int i = 0; i < n / 2; ++i) { + int x = nums[i], y = nums[n - i - 1]; + if (x > y) { + swap(x, y); + } d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } - int ans = n, s = 0; - for (int i = 2; i <= limit * 2; ++i) { + int ans = n; + for (int i = 2, s = 0; i <= limit * 2; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = min(ans, s); } return ans; } diff --git a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.go b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.go index 98ecd9d1bd84..77135e1f86f8 100644 --- a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.go +++ b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.go @@ -1,23 +1,23 @@ func minMoves(nums []int, limit int) int { - d := make([]int, limit*2+2) n := len(nums) - for i := 0; i < n>>1; i++ { - a, b := min(nums[i], nums[n-i-1]), max(nums[i], nums[n-i-1]) + d := make([]int, 2*limit+2) + for i := 0; i < n/2; i++ { + x, y := nums[i], nums[n-1-i] + if x > y { + x, y = y, x + } d[2] += 2 - d[limit*2+1] -= 2 - - d[a+1] -= 1 - d[b+limit+1] += 1 - - d[a+b] -= 1 - d[a+b+1] += 1 + d[x+1] -= 2 + d[x+1] += 1 + d[x+y] -= 1 + d[x+y+1] += 1 + d[y+limit+1] -= 1 + d[y+limit+1] += 2 } ans, s := n, 0 - for _, v := range d[2 : limit*2+1] { - s += v - if ans > s { - ans = s - } + for _, x := range d[2:] { + s += x + ans = min(ans, s) } return ans } \ No newline at end of file diff --git a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.java b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.java index 44f2f7df6af8..ff415a4cad2b 100644 --- a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.java +++ b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.java @@ -1,26 +1,22 @@ class Solution { public int minMoves(int[] nums, int limit) { + int[] d = new int[2 * limit + 2]; int n = nums.length; - int[] d = new int[limit * 2 + 2]; - for (int i = 0; i < n >> 1; ++i) { - int a = Math.min(nums[i], nums[n - i - 1]); - int b = Math.max(nums[i], nums[n - i - 1]); - + for (int i = 0; i < n / 2; ++i) { + int x = Math.min(nums[i], nums[n - i - 1]); + int y = Math.max(nums[i], nums[n - i - 1]); d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } - int ans = n, s = 0; - for (int i = 2; i <= limit * 2; ++i) { + int ans = n; + for (int i = 2, s = 0; i < d.length; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = Math.min(ans, s); } return ans; } diff --git a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.py b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.py index 866fcf6fb3a5..6ed848e04757 100644 --- a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.py +++ b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.py @@ -1,23 +1,16 @@ class Solution: def minMoves(self, nums: List[int], limit: int) -> int: - d = [0] * (limit * 2 + 2) + d = [0] * (2 * limit + 2) n = len(nums) - - for i in range(n >> 1): - a, b = min(nums[i], nums[n - i - 1]), max(nums[i], nums[n - i - 1]) - + for i in range(n // 2): + x, y = nums[i], nums[-i - 1] + if x > y: + x, y = y, x d[2] += 2 - d[limit * 2 + 1] -= 2 - - d[a + 1] -= 1 - d[b + limit + 1] += 1 - - d[a + b] -= 1 - d[a + b + 1] += 1 - - ans, s = n, 0 - for v in d[2 : limit * 2 + 1]: - s += v - if ans > s: - ans = s - return ans + d[x + 1] -= 2 + d[x + 1] += 1 + d[x + y] -= 1 + d[x + y + 1] += 1 + d[y + limit + 1] -= 1 + d[y + limit + 1] += 2 + return min(accumulate(d[2:])) diff --git a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.ts b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.ts index 4a8b405cb856..6e45ff4da48e 100644 --- a/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.ts +++ b/solution/1600-1699/1674.Minimum Moves to Make Array Complementary/Solution.ts @@ -2,25 +2,21 @@ function minMoves(nums: number[], limit: number): number { const n = nums.length; const d: number[] = Array(limit * 2 + 2).fill(0); for (let i = 0; i < n >> 1; ++i) { - const a = Math.min(nums[i], nums[n - i - 1]); - const b = Math.max(nums[i], nums[n - i - 1]); - + const x = Math.min(nums[i], nums[n - 1 - i]); + const y = Math.max(nums[i], nums[n - 1 - i]); d[2] += 2; - d[limit * 2 + 1] -= 2; - - d[a + 1] -= 1; - d[b + limit + 1] += 1; - - d[a + b] -= 1; - d[a + b + 1] += 1; + d[x + 1] -= 2; + d[x + 1] += 1; + d[x + y] -= 1; + d[x + y + 1] += 1; + d[y + limit + 1] -= 1; + d[y + limit + 1] += 2; } let ans = n; let s = 0; - for (let i = 2; i <= limit * 2; ++i) { + for (let i = 2; i < d.length; ++i) { s += d[i]; - if (ans > s) { - ans = s; - } + ans = Math.min(ans, s); } return ans; } diff --git a/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README.md b/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README.md index 652b8db2dea7..f5722029abf4 100644 --- a/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README.md +++ b/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README.md @@ -129,10 +129,10 @@ tags: 状态转移方程为: $$ -f[i] = \min_{j \in [i - maxBoxes, i - 1]} \left(f[j] + \sum_{k = j + 1}^i \text{cost}(k)\right) +f[i] = \min_{j \in [i - maxBoxes, i - 1]} \left(f[j] + \sum_{k = j + 1}^i \textit{cost}(k)\right) $$ -其中 $\sum_{k = j + 1}^i \text{cost}(k)$ 表示通过一次运输,把 $[j+1,..i]$ 这些箱子送往对应的码头所需要的行程数。这部分行程数可以通过前缀和快速计算出来。 +其中 $\sum_{k = j + 1}^i \textit{cost}(k)$ 表示通过一次运输,把 $[j+1,..i]$ 这些箱子送往对应的码头所需要的行程数。这部分行程数可以通过前缀和快速计算出来。 简单举个例子,假设我们取出了 $1, 2, 3$ 这三个箱子,需要送往 $4, 4, 5$ 这三个码头,那么我们首先要从仓库到 $4$ 号码头,然后再从 $4$ 号码头到 $5$ 号码头,最后再从 $5$ 号码头回到仓库。可以发现,从仓库到码头,以及从码头到仓库,需要花费 $2$ 趟行程,而从码头到码头的行程数,取决于相邻两个码头是否相同,如果不相同,那么行程数会增加 $1$,否则不变。因此,我们可以通过前缀和,计算出码头之间的行程数,再加上首尾两趟行程,就能把 $[j+1,..i]$ 这些箱子送往对应的码头所需要的行程数计算出来。 diff --git a/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README_EN.md b/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README_EN.md index 4307ebf39c33..724de9eb7858 100644 --- a/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README_EN.md +++ b/solution/1600-1699/1687.Delivering Boxes from Storage to Ports/README_EN.md @@ -112,10 +112,10 @@ Therefore, we can enumerate the index $j$ of the last box transported in the las The state transition equation is: $$ -f[i] = \min_{j \in [i - maxBoxes, i - 1]} \left(f[j] + \sum_{k = j + 1}^i \text{cost}(k)\right) +f[i] = \min_{j \in [i - maxBoxes, i - 1]} \left(f[j] + \sum_{k = j + 1}^i \textit{cost}(k)\right) $$ -Where $\sum_{k = j + 1}^i \text{cost}(k)$ represents the number of trips required to deliver the boxes in $[j+1,..i]$ to their corresponding docks in one trip. This part of the trip count can be quickly calculated using prefix sums. +Where $\sum_{k = j + 1}^i \textit{cost}(k)$ represents the number of trips required to deliver the boxes in $[j+1,..i]$ to their corresponding docks in one trip. This part of the trip count can be quickly calculated using prefix sums. For example, suppose we take out boxes $1, 2, 3$ and need to deliver them to docks $4, 4, 5$. We first go from the warehouse to dock $4$, then from dock $4$ to dock $5$, and finally from dock $5$ back to the warehouse. It can be seen that it takes $2$ trips to go from the warehouse to the dock and from the dock back to the warehouse. The number of trips from dock to dock depends on whether the two adjacent docks are the same. If they are not the same, the number of trips will increase by $1$, otherwise it remains the same. Therefore, we can calculate the number of trips between docks using prefix sums, and add two trips for the start and end, to calculate the number of trips required to deliver the boxes in $[j+1,..i]$ to their corresponding docks. diff --git a/solution/1700-1799/1720.Decode XORed Array/README.md b/solution/1700-1799/1720.Decode XORed Array/README.md index 37f409d75530..560febe26024 100644 --- a/solution/1700-1799/1720.Decode XORed Array/README.md +++ b/solution/1700-1799/1720.Decode XORed Array/README.md @@ -66,22 +66,22 @@ tags: 根据题目描述,有: $$ -\text{encoded}[i] = \text{arr}[i] \oplus \text{arr}[i + 1] +\textit{encoded}[i] = \textit{arr}[i] \oplus \textit{arr}[i + 1] $$ -如果我们将等式两边同时异或上 $\text{arr}[i]$,那么就会得到: +如果我们将等式两边同时异或上 $\textit{arr}[i]$,那么就会得到: $$ -\text{arr}[i] \oplus \text{arr}[i] \oplus \text{arr}[i + 1] = \text{arr}[i] \oplus \text{encoded}[i] +\textit{arr}[i] \oplus \textit{arr}[i] \oplus \textit{arr}[i + 1] = \textit{arr}[i] \oplus \textit{encoded}[i] $$ 即: $$ -\text{arr}[i + 1] = \text{arr}[i] \oplus \text{encoded}[i] +\textit{arr}[i + 1] = \textit{arr}[i] \oplus \textit{encoded}[i] $$ -根据上述推导,我们可以从 $\text{first}$ 开始,依次计算出数组 $\text{arr}$ 的每一个元素。 +根据上述推导,我们可以从 $\textit{first}$ 开始,依次计算出数组 $\textit{arr}$ 的每一个元素。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。 diff --git a/solution/1700-1799/1720.Decode XORed Array/README_EN.md b/solution/1700-1799/1720.Decode XORed Array/README_EN.md index 625288c83a8a..3d92af479bec 100644 --- a/solution/1700-1799/1720.Decode XORed Array/README_EN.md +++ b/solution/1700-1799/1720.Decode XORed Array/README_EN.md @@ -64,22 +64,22 @@ tags: Based on the problem description, we have: $$ -\text{encoded}[i] = \text{arr}[i] \oplus \text{arr}[i + 1] +\textit{encoded}[i] = \textit{arr}[i] \oplus \textit{arr}[i + 1] $$ -If we XOR both sides of the equation with $\text{arr}[i]$, we get: +If we XOR both sides of the equation with $\textit{arr}[i]$, we get: $$ -\text{arr}[i] \oplus \text{arr}[i] \oplus \text{arr}[i + 1] = \text{arr}[i] \oplus \text{encoded}[i] +\textit{arr}[i] \oplus \textit{arr}[i] \oplus \textit{arr}[i + 1] = \textit{arr}[i] \oplus \textit{encoded}[i] $$ Which simplifies to: $$ -\text{arr}[i + 1] = \text{arr}[i] \oplus \text{encoded}[i] +\textit{arr}[i + 1] = \textit{arr}[i] \oplus \textit{encoded}[i] $$ -Following the derivation above, we can start with $\text{first}$ and sequentially calculate every element of the array $\text{arr}$. +Following the derivation above, we can start with $\textit{first}$ and sequentially calculate every element of the array $\textit{arr}$. The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the array. diff --git a/solution/1700-1799/1788.Maximize the Beauty of the Garden/README.md b/solution/1700-1799/1788.Maximize the Beauty of the Garden/README.md index fbd00f36c537..44c6ab18ad96 100644 --- a/solution/1700-1799/1788.Maximize the Beauty of the Garden/README.md +++ b/solution/1700-1799/1788.Maximize the Beauty of the Garden/README.md @@ -5,6 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1700-1799/1788.Ma tags: - 贪心 - 数组 + - 哈希表 - 前缀和 --- @@ -18,7 +19,7 @@ tags: -

    有一个花园,有 n 朵花,这些花都有一个用整数表示的美观度。这些花被种在一条线上。给定一个长度为 n 的整数类型数组 flowers ,每一个 flowers[i] 表示第 i 朵花的美观度。

    +

    有一个花园,有 n 朵花,这些花都有一个用整数表示的美观度。这些花被种在一条线上。给定一个长度为 n 的整数类型数组 flowers ,每一个 flowers[i] 表示第 i 朵花的美观度。

    一个花园满足下列条件时,该花园是有效的。

    @@ -31,29 +32,32 @@ tags:

    返回你去除了任意朵花(也可以不去除任意一朵)之后形成的有效花园中最大可能的美观度。

    -

     

    +

     

    -

    示例 1:

    +

    示例 1:

    -
    输入: flowers = [1,2,3,1,2]
    +
    +输入: flowers = [1,2,3,1,2]
     输出: 8
     解释: 你可以修整为有效花园 [2,3,1,2] 来达到总美观度 2 + 3 + 1 + 2 = 8。
    -

    示例 2:

    +

    示例 2:

    -
    输入: flowers = [100,1,1,-3,1]
    +
    +输入: flowers = [100,1,1,-3,1]
     输出: 3
     解释: 你可以修整为有效花园 [1,1,1] 来达到总美观度 1 + 1 + 1 = 3。
     
    -

    示例 3:

    +

    示例 3:

    -
    输入: flowers = [-1,-2,0,-1]
    +
    +输入: flowers = [-1,-2,0,-1]
     输出: -2
     解释: 你可以修整为有效花园 [-1,-1] 来达到总美观度 -1 + -1 = -2。
     
    -

     

    +

     

    提示:

    diff --git a/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md b/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md index 4c13c9e72aa7..08179c3e044b 100644 --- a/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md +++ b/solution/1700-1799/1788.Maximize the Beauty of the Garden/README_EN.md @@ -5,6 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1700-1799/1788.Ma tags: - Greedy - Array + - Hash Table - Prefix Sum --- diff --git a/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README.md b/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README.md index 1d3b75baccca..5ff2512acec4 100644 --- a/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README.md +++ b/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README.md @@ -3,8 +3,9 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/1800-1899/1820.Maximum%20Number%20of%20Accepted%20Invitations/README.md tags: + - 深度优先搜索 + - 图 - 数组 - - 回溯 - 矩阵 --- diff --git a/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README_EN.md b/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README_EN.md index 60e153fb9c77..32891870d539 100644 --- a/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README_EN.md +++ b/solution/1800-1899/1820.Maximum Number of Accepted Invitations/README_EN.md @@ -3,8 +3,9 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/1800-1899/1820.Maximum%20Number%20of%20Accepted%20Invitations/README_EN.md tags: + - Depth-First Search + - Graph - Array - - Backtracking - Matrix --- diff --git a/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README.md b/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README.md index 2026613cd79d..f97322ec25b3 100644 --- a/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README.md +++ b/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README.md @@ -69,7 +69,7 @@ tags: $$ \begin{aligned} -\text{ans} &= (a_1 \wedge b_1) \oplus (a_1 \wedge b_2) ... (a_1 \wedge b_m) \\ +\textit{ans} &= (a_1 \wedge b_1) \oplus (a_1 \wedge b_2) ... (a_1 \wedge b_m) \\ &\quad \oplus (a_2 \wedge b_1) \oplus (a_2 \wedge b_2) ... (a_2 \wedge b_m) \\ &\quad \oplus \cdots \\ &\quad \oplus (a_n \wedge b_1) \oplus (a_n \wedge b_2) ... (a_n \wedge b_m) \\ @@ -79,7 +79,7 @@ $$ 由于布尔代数中,异或运算就是不进位的加法,与运算就是乘法,所以上式可以简化为: $$ -\text{ans} = (a_1 \oplus a_2 \oplus \cdots \oplus a_n) \wedge (b_1 \oplus b_2 \oplus \cdots \oplus b_m) +\textit{ans} = (a_1 \oplus a_2 \oplus \cdots \oplus a_n) \wedge (b_1 \oplus b_2 \oplus \cdots \oplus b_m) $$ 即,数组 $arr1$ 的异或和与数组 $arr2$ 的异或和的与运算结果。 diff --git a/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README_EN.md b/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README_EN.md index a3ae9b3edfd6..04e6b209b39d 100644 --- a/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README_EN.md +++ b/solution/1800-1899/1835.Find XOR Sum of All Pairs Bitwise AND/README_EN.md @@ -70,7 +70,7 @@ Assume that the elements of array $arr1$ are $a_1, a_2, ..., a_n$, and the eleme $$ \begin{aligned} -\text{ans} &= (a_1 \wedge b_1) \oplus (a_1 \wedge b_2) ... (a_1 \wedge b_m) \\ +\textit{ans} &= (a_1 \wedge b_1) \oplus (a_1 \wedge b_2) ... (a_1 \wedge b_m) \\ &\quad \oplus (a_2 \wedge b_1) \oplus (a_2 \wedge b_2) ... (a_2 \wedge b_m) \\ &\quad \oplus \cdots \\ &\quad \oplus (a_n \wedge b_1) \oplus (a_n \wedge b_2) ... (a_n \wedge b_m) \\ @@ -80,7 +80,7 @@ $$ Since in Boolean algebra, the XOR operation is addition without carry, and the AND operation is multiplication, the above formula can be simplified as: $$ -\text{ans} = (a_1 \oplus a_2 \oplus \cdots \oplus a_n) \wedge (b_1 \oplus b_2 \oplus \cdots \oplus b_m) +\textit{ans} = (a_1 \oplus a_2 \oplus \cdots \oplus a_n) \wedge (b_1 \oplus b_2 \oplus \cdots \oplus b_m) $$ That is, the bitwise AND of the XOR sum of array $arr1$ and the XOR sum of array $arr2$. diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md index b429e2b9e0d9..6c7f379d1ddb 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README.md @@ -87,7 +87,7 @@ tags: 在二分查找之前,我们需要先判断是否有可能在规定时间内到达。如果列车数量大于向上取整的规定时间,那么一定无法在规定时间内到达,直接返回 $-1$。 -接下来,我们定义二分的左右边界为 $l = 1$, $r = 10^7 + 1$,然后我们每次取中间值 $\text{mid} = \frac{l + r}{2}$,判断是否满足条件。如果满足条件,我们将右边界移动到 $\text{mid}$,否则将左边界移动到 $\text{mid} + 1$。 +接下来,我们定义二分的左右边界为 $l = 1$, $r = 10^7 + 1$,然后我们每次取中间值 $\textit{mid} = \frac{l + r}{2}$,判断是否满足条件。如果满足条件,我们将右边界移动到 $\textit{mid}$,否则将左边界移动到 $\textit{mid} + 1$。 问题转化为判断一个速度值 $v$ 是否能够在规定时间内到达。我们可以遍历每一趟列车,计算每一趟列车的运行时间 $t = \frac{d}{v}$,如果是最后一趟列车,我们直接加上 $t$,否则我们向上取整加上 $t$。最后判断总时间是否小于等于规定时间,如果是则说明满足条件。 diff --git a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md index 48acea1aa2c9..a5c22968be5c 100644 --- a/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md +++ b/solution/1800-1899/1870.Minimum Speed to Arrive on Time/README_EN.md @@ -87,7 +87,7 @@ We notice that if a speed value $v$ allows us to arrive within the stipulated ti Before conducting the binary search, we need to first determine if it is possible to arrive within the stipulated time. If the number of trains is greater than the ceiling of the stipulated time, then it is definitely impossible to arrive within the stipulated time, and we should directly return $-1$. -Next, we define the left and right boundaries for the binary search as $l = 1$, $r = 10^7 + 1$, and then we take the middle value $\text{mid} = \frac{l + r}{2}$ each time to check if it meets the condition. If it does, we move the right boundary to $\text{mid}$; otherwise, we move the left boundary to $\text{mid} + 1$. +Next, we define the left and right boundaries for the binary search as $l = 1$, $r = 10^7 + 1$, and then we take the middle value $\textit{mid} = \frac{l + r}{2}$ each time to check if it meets the condition. If it does, we move the right boundary to $\textit{mid}$; otherwise, we move the left boundary to $\textit{mid} + 1$. The problem is transformed into determining whether a speed value $v$ can allow us to arrive within the stipulated time. We can traverse each train trip, calculate the running time of each trip $t = \frac{d}{v}$, if it is the last trip, we directly add $t$; otherwise, we round up and add $t$. Finally, we check if the total time is less than or equal to the stipulated time, if so, it means the condition is met. diff --git a/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README.md b/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README.md index c71aa41c7ab4..47a865c2a7a1 100644 --- a/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README.md +++ b/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README.md @@ -91,7 +91,7 @@ tags: 由于我们可以选择跳过或者不跳过第 $i$ 条道路的休息时间,因此我们可以列出状态转移方程: $$ -f[i][j]=\min\left\{\begin{aligned} \lceil f[i-1][j]+\frac{d_i}{s}\rceil & \text{不跳过第 $i$ 条道路的休息时间} \\ f[i-1][j-1]+\frac{d_i}{s} & \text{跳过第 $i$ 条道路的休息时间} \end{aligned}\right. +f[i][j]=\min\left\{\begin{aligned} \lceil f[i-1][j]+\frac{d_i}{s}\rceil & \textit{不跳过第 $i$ 条道路的休息时间} \\ f[i-1][j-1]+\frac{d_i}{s} & \textit{跳过第 $i$ 条道路的休息时间} \end{aligned}\right. $$ 其中 $\lceil x\rceil$ 表示将 $x$ 向上取整。需要注意的是,由于我们需要保证恰好跳过 $j$ 次休息时间,因此我们必须有 $j\le i$;另外,如果 $j=0$,不能跳过任何休息时间。 diff --git a/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README_EN.md b/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README_EN.md index 0484509ca530..0599c4e55362 100644 --- a/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README_EN.md +++ b/solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README_EN.md @@ -89,7 +89,7 @@ We define $f[i][j]$ as the shortest time considering the first $i$ roads and exa Since we can choose to skip or not skip the rest time of the $i$-th road, we can list the state transition equation: $$ -f[i][j]=\min\left\{\begin{aligned} \lceil f[i-1][j]+\frac{d_i}{s}\rceil & \text{Do not skip the rest time of the $i$-th road} \\ f[i-1][j-1]+\frac{d_i}{s} & \text{Skip the rest time of the $i$-th road} \end{aligned}\right. +f[i][j]=\min\left\{\begin{aligned} \lceil f[i-1][j]+\frac{d_i}{s}\rceil & \textit{Do not skip the rest time of the $i$-th road} \\ f[i-1][j-1]+\frac{d_i}{s} & \textit{Skip the rest time of the $i$-th road} \end{aligned}\right. $$ Where $\lceil x\rceil$ represents rounding $x$ up. It should be noted that since we need to ensure that exactly $j$ rest times are skipped, we must have $j\le i$; moreover, if $j=0$, no rest time can be skipped. diff --git a/solution/1900-1999/1902.Depth of BST Given Insertion Order/README.md b/solution/1900-1999/1902.Depth of BST Given Insertion Order/README.md index 7f87c780c5a5..64fa02a9f62b 100644 --- a/solution/1900-1999/1902.Depth of BST Given Insertion Order/README.md +++ b/solution/1900-1999/1902.Depth of BST Given Insertion Order/README.md @@ -5,6 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1900-1999/1902.De tags: - 树 - 二叉搜索树 + - 数组 - 二叉树 - 有序集合 --- diff --git a/solution/1900-1999/1902.Depth of BST Given Insertion Order/README_EN.md b/solution/1900-1999/1902.Depth of BST Given Insertion Order/README_EN.md index 185590cb27c6..3119b08f1aea 100644 --- a/solution/1900-1999/1902.Depth of BST Given Insertion Order/README_EN.md +++ b/solution/1900-1999/1902.Depth of BST Given Insertion Order/README_EN.md @@ -5,6 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/1900-1999/1902.De tags: - Tree - Binary Search Tree + - Array - Binary Tree - Ordered Set --- diff --git a/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README.md b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README.md index 7ef328b99dec..416d0b878b35 100644 --- a/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README.md +++ b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README.md @@ -80,7 +80,32 @@ tags: #### Python3 ```python - +class Solution: + def waysToBuildRooms(self, prevRoom: List[int]) -> int: + modulo = 10**9 + 7 + ingoing = defaultdict(set) + outgoing = defaultdict(set) + + for i in range(1, len(prevRoom)): + ingoing[i].add(prevRoom[i]) + outgoing[prevRoom[i]].add(i) + ans = [1] + + def recurse(i): + if len(outgoing[i]) == 0: + return 1 + + nodes_in_tree = 0 + for v in outgoing[i]: + cn = recurse(v) + if nodes_in_tree != 0: + ans[0] *= comb(nodes_in_tree + cn, cn) + ans[0] %= modulo + nodes_in_tree += cn + return nodes_in_tree + 1 + + recurse(0) + return ans[0] % modulo ``` #### Java diff --git a/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md index c560e572345c..f306ec994eb0 100644 --- a/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md +++ b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/README_EN.md @@ -104,7 +104,32 @@ tags: #### Python3 ```python - +class Solution: + def waysToBuildRooms(self, prevRoom: List[int]) -> int: + modulo = 10**9 + 7 + ingoing = defaultdict(set) + outgoing = defaultdict(set) + + for i in range(1, len(prevRoom)): + ingoing[i].add(prevRoom[i]) + outgoing[prevRoom[i]].add(i) + ans = [1] + + def recurse(i): + if len(outgoing[i]) == 0: + return 1 + + nodes_in_tree = 0 + for v in outgoing[i]: + cn = recurse(v) + if nodes_in_tree != 0: + ans[0] *= comb(nodes_in_tree + cn, cn) + ans[0] %= modulo + nodes_in_tree += cn + return nodes_in_tree + 1 + + recurse(0) + return ans[0] % modulo ``` #### Java diff --git a/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/Solution.py b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/Solution.py new file mode 100644 index 000000000000..f3f7d0ad8b0c --- /dev/null +++ b/solution/1900-1999/1916.Count Ways to Build Rooms in an Ant Colony/Solution.py @@ -0,0 +1,26 @@ +class Solution: + def waysToBuildRooms(self, prevRoom: List[int]) -> int: + modulo = 10**9 + 7 + ingoing = defaultdict(set) + outgoing = defaultdict(set) + + for i in range(1, len(prevRoom)): + ingoing[i].add(prevRoom[i]) + outgoing[prevRoom[i]].add(i) + ans = [1] + + def recurse(i): + if len(outgoing[i]) == 0: + return 1 + + nodes_in_tree = 0 + for v in outgoing[i]: + cn = recurse(v) + if nodes_in_tree != 0: + ans[0] *= comb(nodes_in_tree + cn, cn) + ans[0] %= modulo + nodes_in_tree += cn + return nodes_in_tree + 1 + + recurse(0) + return ans[0] % modulo diff --git a/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README.md b/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README.md index 3af675abd569..5bbeaa09e599 100644 --- a/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README.md +++ b/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README.md @@ -69,10 +69,10 @@ tags: 因此,我们定义 $f[i][j]$ 表示前 $i$ 列中,第 $i$ 列的涂色状态为 $j$ 的方案数。状态 $f[i][j]$ 由 $f[i - 1][k]$ 转移而来,其中 $k$ 是第 $i - 1$ 列的涂色状态,且 $k$ 和 $j$ 满足不同颜色相邻的要求。即: $$ -f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k] +f[i][j] = \sum_{k \in \textit{valid}(j)} f[i - 1][k] $$ -其中 $\text{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。 +其中 $\textit{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。 最终的答案即为 $f[n][j]$ 的总和,其中 $j$ 是任意合法的状态。 diff --git a/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README_EN.md b/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README_EN.md index d27ad61cb964..9f89d7d33664 100644 --- a/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README_EN.md +++ b/solution/1900-1999/1931.Painting a Grid With Three Different Colors/README_EN.md @@ -67,10 +67,10 @@ We notice that the number of rows in the grid does not exceed $5$, so there are Therefore, we define $f[i][j]$ to represent the number of schemes in the first $i$ columns, where the coloring state of the $i$th column is $j$. The state $f[i][j]$ is transferred from $f[i - 1][k]$, where $k$ is the coloring state of the $i - 1$th column, and $k$ and $j$ meet the requirement of different colors being adjacent. That is: $$ -f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k] +f[i][j] = \sum_{k \in \textit{valid}(j)} f[i - 1][k] $$ -where $\text{valid}(j)$ represents all legal predecessor states of state $j$. +where $\textit{valid}(j)$ represents all legal predecessor states of state $j$. The final answer is the sum of $f[n][j]$, where $j$ is any legal state. diff --git a/solution/1900-1999/1937.Maximum Number of Points with Cost/README.md b/solution/1900-1999/1937.Maximum Number of Points with Cost/README.md index 3d7c0c60e402..b81992770f5b 100644 --- a/solution/1900-1999/1937.Maximum Number of Points with Cost/README.md +++ b/solution/1900-1999/1937.Maximum Number of Points with Cost/README.md @@ -7,6 +7,7 @@ source: 第 250 场周赛 Q3 tags: - 数组 - 动态规划 + - 矩阵 --- diff --git a/solution/1900-1999/1937.Maximum Number of Points with Cost/README_EN.md b/solution/1900-1999/1937.Maximum Number of Points with Cost/README_EN.md index 94be6938d7f0..f2ca388eb3cf 100644 --- a/solution/1900-1999/1937.Maximum Number of Points with Cost/README_EN.md +++ b/solution/1900-1999/1937.Maximum Number of Points with Cost/README_EN.md @@ -7,6 +7,7 @@ source: Weekly Contest 250 Q3 tags: - Array - Dynamic Programming + - Matrix --- diff --git a/solution/1900-1999/1938.Maximum Genetic Difference Query/README.md b/solution/1900-1999/1938.Maximum Genetic Difference Query/README.md index fd2a5f2dfa96..bdddeea9ad9f 100644 --- a/solution/1900-1999/1938.Maximum Genetic Difference Query/README.md +++ b/solution/1900-1999/1938.Maximum Genetic Difference Query/README.md @@ -6,8 +6,10 @@ rating: 2502 source: 第 250 场周赛 Q4 tags: - 位运算 + - 深度优先搜索 - 字典树 - 数组 + - 哈希表 --- diff --git a/solution/1900-1999/1938.Maximum Genetic Difference Query/README_EN.md b/solution/1900-1999/1938.Maximum Genetic Difference Query/README_EN.md index 400437007f2a..c0dc61dcfd69 100644 --- a/solution/1900-1999/1938.Maximum Genetic Difference Query/README_EN.md +++ b/solution/1900-1999/1938.Maximum Genetic Difference Query/README_EN.md @@ -6,8 +6,10 @@ rating: 2502 source: Weekly Contest 250 Q4 tags: - Bit Manipulation + - Depth-First Search - Trie - Array + - Hash Table --- diff --git a/solution/1900-1999/1958.Check if Move is Legal/README.md b/solution/1900-1999/1958.Check if Move is Legal/README.md index e223c1056766..c1eb86ca94cd 100644 --- a/solution/1900-1999/1958.Check if Move is Legal/README.md +++ b/solution/1900-1999/1958.Check if Move is Legal/README.md @@ -70,9 +70,9 @@ tags: ### 方法一:枚举 -我们枚举所有可能的方向,对于每个方向 $(a, b)$,我们从 $(\textit{rMove}, \textit{cMove})$ 出发,用一个变量 $\textit{cnt}$ 记录我们走过的格子数,如果我们在走的过程中遇到了颜色为 $\textit{color}$ 的格子,且 $\textit{cnt} > 1$,那么我们就找到了一个好线段,返回 $\text{true}$。 +我们枚举所有可能的方向,对于每个方向 $(a, b)$,我们从 $(\textit{rMove}, \textit{cMove})$ 出发,用一个变量 $\textit{cnt}$ 记录我们走过的格子数,如果我们在走的过程中遇到了颜色为 $\textit{color}$ 的格子,且 $\textit{cnt} > 1$,那么我们就找到了一个好线段,返回 $\textit{true}$。 -枚举结束后,如果我们没有找到任何好线段,那么返回 $\text{false}$。 +枚举结束后,如果我们没有找到任何好线段,那么返回 $\textit{false}$。 时间复杂度 $O(m + n)$,其中 $m$ 为 $\textit{board}$ 的行数,而 $n$ 为 $\textit{board}$ 的列数,本题中 $m = n = 8$。空间复杂度 $O(1)$。 diff --git a/solution/1900-1999/1958.Check if Move is Legal/README_EN.md b/solution/1900-1999/1958.Check if Move is Legal/README_EN.md index 14a577ecb54e..ec946ff5fcba 100644 --- a/solution/1900-1999/1958.Check if Move is Legal/README_EN.md +++ b/solution/1900-1999/1958.Check if Move is Legal/README_EN.md @@ -64,9 +64,9 @@ The two good lines with the chosen cell as an endpoint are annotated above with ### Solution 1: Enumeration -We enumerate all possible directions. For each direction $(a, b)$, we start from $(\textit{rMove}, \textit{cMove})$ and use a variable $\textit{cnt}$ to record the number of cells we have passed. If, during our traversal, we encounter a cell of color $\textit{color}$ and $\textit{cnt} > 1$, then we have found a good line segment and return $\text{true}$. +We enumerate all possible directions. For each direction $(a, b)$, we start from $(\textit{rMove}, \textit{cMove})$ and use a variable $\textit{cnt}$ to record the number of cells we have passed. If, during our traversal, we encounter a cell of color $\textit{color}$ and $\textit{cnt} > 1$, then we have found a good line segment and return $\textit{true}$. -If no good line segments are found after the enumeration, we return $\text{false}$. +If no good line segments are found after the enumeration, we return $\textit{false}$. The time complexity is $O(m + n)$, where $m$ is the number of rows and $n$ is the number of columns in $\textit{board}$, with $m = n = 8$ in this problem. The space complexity is $O(1)$. diff --git a/solution/1900-1999/1971.Find if Path Exists in Graph/README.md b/solution/1900-1999/1971.Find if Path Exists in Graph/README.md index f6e85b380868..b31c2f87b025 100644 --- a/solution/1900-1999/1971.Find if Path Exists in Graph/README.md +++ b/solution/1900-1999/1971.Find if Path Exists in Graph/README.md @@ -268,7 +268,7 @@ fn dfs(i: usize, destination: usize, vis: &mut Vec, g: &Vec 具体地,我们定义一个队列 $q$,初始时将 `source` 加入队列。另外,我们用一个集合 `vis` 记录已经访问过的顶点,避免重复访问。 -接下来,我们不断从队列中取出顶点 $i$,如果 $i = \text{destination}$,则说明存在从 `source` 到 `destination` 的路径,返回 `true`。否则,我们遍历 $i$ 的所有邻接顶点 $j$,如果 $j$ 没有被访问过,我们将 $j$ 加入队列 $q$,并且标记 $j$ 为已访问。 +接下来,我们不断从队列中取出顶点 $i$,如果 $i = \textit{destination}$,则说明存在从 `source` 到 `destination` 的路径,返回 `true`。否则,我们遍历 $i$ 的所有邻接顶点 $j$,如果 $j$ 没有被访问过,我们将 $j$ 加入队列 $q$,并且标记 $j$ 为已访问。 最后,如果队列为空,说明不存在从 `source` 到 `destination` 的路径,返回 `false`。 diff --git a/solution/1900-1999/1971.Find if Path Exists in Graph/README_EN.md b/solution/1900-1999/1971.Find if Path Exists in Graph/README_EN.md index 7c77c68d6fb4..90c191aa18fc 100644 --- a/solution/1900-1999/1971.Find if Path Exists in Graph/README_EN.md +++ b/solution/1900-1999/1971.Find if Path Exists in Graph/README_EN.md @@ -266,7 +266,7 @@ We can also use BFS to determine whether there is a path from `source` to `desti Specifically, we define a queue $q$ and initially add `source` to the queue. In addition, we use a set `vis` to record the vertices that have been visited to avoid repeated visits. -Next, we continuously take out the vertex $i$ from the queue. If $i = \text{destination}$, it means that there is a path from `source` to `destination`, and we return `true`. Otherwise, we traverse all adjacent vertices $j$ of $i$. If $j$ has not been visited, we add $j$ to the queue $q$ and mark $j$ as visited. +Next, we continuously take out the vertex $i$ from the queue. If $i = \textit{destination}$, it means that there is a path from `source` to `destination`, and we return `true`. Otherwise, we traverse all adjacent vertices $j$ of $i$. If $j$ has not been visited, we add $j$ to the queue $q$ and mark $j$ as visited. Finally, if the queue is empty, it means that there is no path from `source` to `destination`, and we return `false`. diff --git a/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README.md b/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README.md index b2eaf9741054..4a3a003aeb30 100644 --- a/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README.md +++ b/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README.md @@ -92,7 +92,7 @@ tags: 设 $f[i][j]$ 表示前 $i$ 行是否能选出元素和为 $j$,则有状态转移方程: $$ -f[i][j] = \begin{cases} 1 & \text{如果存在 } x \in row[i] \text{ 使得 } f[i - 1][j - x] = 1 \\ 0 & \text{否则} \end{cases} +f[i][j] = \begin{cases} 1 & \textit{如果存在 } x \in row[i] \textit{ 使得 } f[i - 1][j - x] = 1 \\ 0 & \textit{否则} \end{cases} $$ 其中 $row[i]$ 表示第 $i$ 行的元素集合。 diff --git a/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README_EN.md b/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README_EN.md index 3edbf948ad8f..355e68a7aeaa 100644 --- a/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README_EN.md +++ b/solution/1900-1999/1981.Minimize the Difference Between Target and Chosen Elements/README_EN.md @@ -84,7 +84,7 @@ The absolute difference is 1. Let $f[i][j]$ represent whether it is possible to select elements from the first $i$ rows with a sum of $j$. Then we have the state transition equation: $$ -f[i][j] = \begin{cases} 1 & \text{if there exists } x \in row[i] \text{ such that } f[i - 1][j - x] = 1 \\ 0 & \text{otherwise} \end{cases} +f[i][j] = \begin{cases} 1 & \textit{if there exists } x \in row[i] \textit{ such that } f[i - 1][j - x] = 1 \\ 0 & \textit{otherwise} \end{cases} $$ where $row[i]$ represents the set of elements in the $i$-th row. diff --git a/solution/1900-1999/1998.GCD Sort of an Array/README.md b/solution/1900-1999/1998.GCD Sort of an Array/README.md index c4bcdff6afb1..1369b8566480 100644 --- a/solution/1900-1999/1998.GCD Sort of an Array/README.md +++ b/solution/1900-1999/1998.GCD Sort of an Array/README.md @@ -34,29 +34,32 @@ tags:

    示例 1:

    -
    输入:nums = [7,21,3]
    +
    +输入:nums = [7,21,3]
     输出:true
     解释:可以执行下述操作完成对 [7,21,3] 的排序:
    -- 交换 7 和 21 因为 gcd(7,21) = 7 。nums = [21,7,3]
    -- 交换 21 和 3 因为 gcd(21,3) = 3 。nums = [3,7,21]
    +- 交换 7 和 21 因为 gcd(7,21) = 7 。nums = [21,7,3]
    +- 交换 21 和 3 因为 gcd(21,3) = 3 。nums = [3,7,21]
     

    示例 2:

    -
    输入:nums = [5,2,6,2]
    +
    +输入:nums = [5,2,6,2]
     输出:false
     解释:无法完成排序,因为 5 不能与其他元素交换。
     

    示例 3:

    -
    输入:nums = [10,5,9,3,15]
    +
    +输入:nums = [10,5,9,3,15]
     输出:true
     解释:
     可以执行下述操作完成对 [10,5,9,3,15] 的排序:
    -- 交换 10 和 15 因为 gcd(10,15) = 5 。nums = [15,5,9,3,10]
    -- 交换 15 和 3 因为 gcd(15,3) = 3 。nums = [3,5,9,15,10]
    -- 交换 10 和 15 因为 gcd(10,15) = 5 。nums = [3,5,9,10,15]
    +- 交换 10 和 15 因为 gcd(10,15) = 5 。nums = [15,5,9,3,10]
    +- 交换 15 和 3 因为 gcd(15,3) = 3 。nums = [3,5,9,15,10]
    +- 交换 10 和 15 因为 gcd(10,15) = 5 。nums = [3,5,9,10,15]
     

     

    diff --git a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README.md b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README.md index 56472db80a8b..c708d7b27a77 100644 --- a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README.md +++ b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README.md @@ -94,11 +94,15 @@ tags: -### 方法一:差分有序哈希表 +### 方法一:差分思想 + 哈希表 -我们利用差分思想,使用有序哈希表 `height` 记录每个位置的高度变化,`cnt` 记录建筑物的数量变化。对有序哈希表求前缀和,即可得到每个位置的高度和建筑物数量。 +我们可以利用差分思想,用一个哈希表 $\textit{cnt}$ 记录每个位置的建筑物数量变化,用另一个哈希表 $\textit{d}$ 记录每个位置的高度变化。 -最后遍历有序哈希表,对于每个位置,如果高度和建筑物数量都不为 0,则说明该位置有建筑物,判断此时的建筑物是否与上个建筑物的平均高度相同,如果相同,则合并,否则加入结果集。 +接下来,我们对哈希表 $\textit{d}$ 按照键值进行排序,用一个变量 $\textit{s}$ 记录当前位置的高度和,用一个变量 $\textit{m}$ 记录当前位置的建筑物数量。 + +然后遍历哈希表 $\textit{d}$,对于每个位置,如果 $\textit{m}$ 不为 0,说明此前有建筑物,我们计算出平均高度,如果当前位置的建筑物与上个建筑物的平均高度相同,则合并,否则加入结果集。 + +最后返回结果集即可。 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为建筑物数量。 @@ -109,25 +113,26 @@ tags: ```python class Solution: def averageHeightOfBuildings(self, buildings: List[List[int]]) -> List[List[int]]: - height = defaultdict(int) cnt = defaultdict(int) - for s, e, h in buildings: - cnt[s] += 1 - cnt[e] -= 1 - height[s] += h - height[e] -= h + d = defaultdict(int) + for start, end, height in buildings: + cnt[start] += 1 + cnt[end] -= 1 + d[start] += height + d[end] -= height + s = m = 0 + last = -1 ans = [] - i = h = n = 0 - for j in sorted(cnt.keys()): - if n: - t = [i, j, h // n] - if ans and ans[-1][1] == i and ans[-1][2] == t[-1]: - ans[-1][1] = j + for k, v in sorted(d.items()): + if m: + avg = s // m + if ans and ans[-1][2] == avg and ans[-1][1] == last: + ans[-1][1] = k else: - ans.append(t) - i = j - h += height[j] - n += cnt[j] + ans.append([last, k, avg]) + s += v + m += cnt[k] + last = k return ans ``` @@ -136,36 +141,34 @@ class Solution: ```java class Solution { public int[][] averageHeightOfBuildings(int[][] buildings) { - TreeMap height = new TreeMap<>(); - TreeMap cnt = new TreeMap<>(); - for (var v : buildings) { - int s = v[0], e = v[1], h = v[2]; - cnt.put(s, cnt.getOrDefault(s, 0) + 1); - cnt.put(e, cnt.getOrDefault(e, 0) - 1); - height.put(s, height.getOrDefault(s, 0) + h); - height.put(e, height.getOrDefault(e, 0) - h); + Map cnt = new HashMap<>(); + TreeMap d = new TreeMap<>(); + for (var e : buildings) { + int start = e[0], end = e[1], height = e[2]; + cnt.merge(start, 1, Integer::sum); + cnt.merge(end, -1, Integer::sum); + d.merge(start, height, Integer::sum); + d.merge(end, -height, Integer::sum); } - int i = 0, h = 0, n = 0; - List res = new ArrayList<>(); - for (int j : cnt.keySet()) { - if (n > 0) { - int[] t = new int[] {i, j, h / n}; - int k = res.size() - 1; - if (k >= 0 && res.get(k)[1] == i && res.get(k)[2] == t[2]) { - res.get(k)[1] = j; + int s = 0, m = 0; + int last = -1; + List ans = new ArrayList<>(); + for (var e : d.entrySet()) { + int k = e.getKey(), v = e.getValue(); + if (m > 0) { + int avg = s / m; + if (!ans.isEmpty() && ans.get(ans.size() - 1)[2] == avg + && ans.get(ans.size() - 1)[1] == last) { + ans.get(ans.size() - 1)[1] = k; } else { - res.add(t); + ans.add(new int[] {last, k, avg}); } } - h += height.get(j); - n += cnt.get(j); - i = j; - } - int[][] ans = new int[res.size()][3]; - for (i = 0; i < ans.length; ++i) { - ans[i] = res.get(i); + s += v; + m += cnt.get(k); + last = k; } - return ans; + return ans.toArray(new int[0][]); } } ``` @@ -176,27 +179,35 @@ class Solution { class Solution { public: vector> averageHeightOfBuildings(vector>& buildings) { - map height, cnt; - for (auto& v : buildings) { - int s = v[0], e = v[1], h = v[2]; - cnt[s]++, cnt[e]--; - height[s] += h, height[e] -= h; + unordered_map cnt; + map d; + + for (const auto& e : buildings) { + int start = e[0], end = e[1], height = e[2]; + cnt[start]++; + cnt[end]--; + d[start] += height; + d[end] -= height; } + + int s = 0, m = 0; + int last = -1; vector> ans; - int i = 0, h = 0, n = 0; - for (auto& [j, _] : cnt) { - if (n) { - vector t = {i, j, h / n}; - if (ans.size() && ans.back()[1] == i && ans.back()[2] == t[2]) { - ans.back()[1] = j; + + for (const auto& [k, v] : d) { + if (m > 0) { + int avg = s / m; + if (!ans.empty() && ans.back()[2] == avg && ans.back()[1] == last) { + ans.back()[1] = k; } else { - ans.push_back(t); + ans.push_back({last, k, avg}); } } - i = j; - h += height[j]; - n += cnt[j]; + s += v; + m += cnt[k]; + last = k; } + return ans; } }; @@ -206,39 +217,80 @@ public: ```go func averageHeightOfBuildings(buildings [][]int) [][]int { - height := make(map[int]int) cnt := make(map[int]int) - for _, v := range buildings { - s, e, h := v[0], v[1], v[2] - cnt[s]++ - cnt[e]-- - height[s] += h - height[e] -= h + d := make(map[int]int) + + for _, e := range buildings { + start, end, height := e[0], e[1], e[2] + cnt[start]++ + cnt[end]-- + d[start] += height + d[end] -= height } - keys := make([]int, len(cnt)) - for k := range cnt { + + s, m := 0, 0 + last := -1 + var ans [][]int + + keys := make([]int, 0, len(d)) + for k := range d { keys = append(keys, k) } sort.Ints(keys) - i, h, n := 0, 0, 0 - ans := [][]int{} - for _, j := range keys { - if n > 0 { - t := []int{i, j, h / n} - if len(ans) > 0 && ans[len(ans)-1][1] == i && ans[len(ans)-1][2] == t[2] { - ans[len(ans)-1][1] = j + + for _, k := range keys { + v := d[k] + if m > 0 { + avg := s / m + if len(ans) > 0 && ans[len(ans)-1][2] == avg && ans[len(ans)-1][1] == last { + ans[len(ans)-1][1] = k } else { - ans = append(ans, t) + ans = append(ans, []int{last, k, avg}) } } - i = j - h += height[j] - n += cnt[j] + s += v + m += cnt[k] + last = k } + return ans } ``` +#### TypeScript + +```ts +function averageHeightOfBuildings(buildings: number[][]): number[][] { + const cnt = new Map(); + const d = new Map(); + for (const [start, end, height] of buildings) { + cnt.set(start, (cnt.get(start) || 0) + 1); + cnt.set(end, (cnt.get(end) || 0) - 1); + d.set(start, (d.get(start) || 0) + height); + d.set(end, (d.get(end) || 0) - height); + } + let [s, m] = [0, 0]; + let last = -1; + const ans: number[][] = []; + const sortedKeys = Array.from(d.keys()).sort((a, b) => a - b); + for (const k of sortedKeys) { + const v = d.get(k)!; + if (m > 0) { + const avg = Math.floor(s / m); + if (ans.length > 0 && ans.at(-1)![2] === avg && ans.at(-1)![1] === last) { + ans[ans.length - 1][1] = k; + } else { + ans.push([last, k, avg]); + } + } + s += v; + m += cnt.get(k)!; + last = k; + } + return ans; +} +``` + diff --git a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README_EN.md b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README_EN.md index 3dd6827cdc45..cea37106ad1c 100644 --- a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README_EN.md +++ b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/README_EN.md @@ -95,11 +95,15 @@ We cannot group the segments together because an empty space with no buildings s -### Solution 1: Differential Ordered Hash Table +### Solution 1: Difference Array + Hash Table -We use the differential idea and an ordered hash table `height` to record the height change at each position, and `cnt` to record the change in the number of buildings. By calculating the prefix sum of the ordered hash table, we can get the height and the number of buildings at each position. +We can use the difference array concept, utilizing a hash table $\textit{cnt}$ to record the change in the number of buildings at each position, and another hash table $\textit{d}$ to record the change in height at each position. -Finally, we traverse the ordered hash table. For each position, if both the height and the number of buildings are not zero, it means that there is a building at this position. We then check whether the average height of the building at this time is the same as that of the previous building. If it is the same, we merge them; otherwise, we add it to the result set. +Next, we sort the hash table $\textit{d}$ by its keys, use a variable $\textit{s}$ to record the current total height, and a variable $\textit{m}$ to record the current number of buildings. + +Then, we traverse the hash table $\textit{d}$. For each position, if $\textit{m}$ is not 0, it means there are buildings at the previous positions. We calculate the average height. If the average height of the buildings at the current position is the same as that of the previous buildings, we merge them; otherwise, we add the current position to the result set. + +Finally, we return the result set. The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of buildings. @@ -110,25 +114,26 @@ The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. ```python class Solution: def averageHeightOfBuildings(self, buildings: List[List[int]]) -> List[List[int]]: - height = defaultdict(int) cnt = defaultdict(int) - for s, e, h in buildings: - cnt[s] += 1 - cnt[e] -= 1 - height[s] += h - height[e] -= h + d = defaultdict(int) + for start, end, height in buildings: + cnt[start] += 1 + cnt[end] -= 1 + d[start] += height + d[end] -= height + s = m = 0 + last = -1 ans = [] - i = h = n = 0 - for j in sorted(cnt.keys()): - if n: - t = [i, j, h // n] - if ans and ans[-1][1] == i and ans[-1][2] == t[-1]: - ans[-1][1] = j + for k, v in sorted(d.items()): + if m: + avg = s // m + if ans and ans[-1][2] == avg and ans[-1][1] == last: + ans[-1][1] = k else: - ans.append(t) - i = j - h += height[j] - n += cnt[j] + ans.append([last, k, avg]) + s += v + m += cnt[k] + last = k return ans ``` @@ -137,36 +142,34 @@ class Solution: ```java class Solution { public int[][] averageHeightOfBuildings(int[][] buildings) { - TreeMap height = new TreeMap<>(); - TreeMap cnt = new TreeMap<>(); - for (var v : buildings) { - int s = v[0], e = v[1], h = v[2]; - cnt.put(s, cnt.getOrDefault(s, 0) + 1); - cnt.put(e, cnt.getOrDefault(e, 0) - 1); - height.put(s, height.getOrDefault(s, 0) + h); - height.put(e, height.getOrDefault(e, 0) - h); + Map cnt = new HashMap<>(); + TreeMap d = new TreeMap<>(); + for (var e : buildings) { + int start = e[0], end = e[1], height = e[2]; + cnt.merge(start, 1, Integer::sum); + cnt.merge(end, -1, Integer::sum); + d.merge(start, height, Integer::sum); + d.merge(end, -height, Integer::sum); } - int i = 0, h = 0, n = 0; - List res = new ArrayList<>(); - for (int j : cnt.keySet()) { - if (n > 0) { - int[] t = new int[] {i, j, h / n}; - int k = res.size() - 1; - if (k >= 0 && res.get(k)[1] == i && res.get(k)[2] == t[2]) { - res.get(k)[1] = j; + int s = 0, m = 0; + int last = -1; + List ans = new ArrayList<>(); + for (var e : d.entrySet()) { + int k = e.getKey(), v = e.getValue(); + if (m > 0) { + int avg = s / m; + if (!ans.isEmpty() && ans.get(ans.size() - 1)[2] == avg + && ans.get(ans.size() - 1)[1] == last) { + ans.get(ans.size() - 1)[1] = k; } else { - res.add(t); + ans.add(new int[] {last, k, avg}); } } - h += height.get(j); - n += cnt.get(j); - i = j; - } - int[][] ans = new int[res.size()][3]; - for (i = 0; i < ans.length; ++i) { - ans[i] = res.get(i); + s += v; + m += cnt.get(k); + last = k; } - return ans; + return ans.toArray(new int[0][]); } } ``` @@ -177,27 +180,35 @@ class Solution { class Solution { public: vector> averageHeightOfBuildings(vector>& buildings) { - map height, cnt; - for (auto& v : buildings) { - int s = v[0], e = v[1], h = v[2]; - cnt[s]++, cnt[e]--; - height[s] += h, height[e] -= h; + unordered_map cnt; + map d; + + for (const auto& e : buildings) { + int start = e[0], end = e[1], height = e[2]; + cnt[start]++; + cnt[end]--; + d[start] += height; + d[end] -= height; } + + int s = 0, m = 0; + int last = -1; vector> ans; - int i = 0, h = 0, n = 0; - for (auto& [j, _] : cnt) { - if (n) { - vector t = {i, j, h / n}; - if (ans.size() && ans.back()[1] == i && ans.back()[2] == t[2]) { - ans.back()[1] = j; + + for (const auto& [k, v] : d) { + if (m > 0) { + int avg = s / m; + if (!ans.empty() && ans.back()[2] == avg && ans.back()[1] == last) { + ans.back()[1] = k; } else { - ans.push_back(t); + ans.push_back({last, k, avg}); } } - i = j; - h += height[j]; - n += cnt[j]; + s += v; + m += cnt[k]; + last = k; } + return ans; } }; @@ -207,39 +218,80 @@ public: ```go func averageHeightOfBuildings(buildings [][]int) [][]int { - height := make(map[int]int) cnt := make(map[int]int) - for _, v := range buildings { - s, e, h := v[0], v[1], v[2] - cnt[s]++ - cnt[e]-- - height[s] += h - height[e] -= h + d := make(map[int]int) + + for _, e := range buildings { + start, end, height := e[0], e[1], e[2] + cnt[start]++ + cnt[end]-- + d[start] += height + d[end] -= height } - keys := make([]int, len(cnt)) - for k := range cnt { + + s, m := 0, 0 + last := -1 + var ans [][]int + + keys := make([]int, 0, len(d)) + for k := range d { keys = append(keys, k) } sort.Ints(keys) - i, h, n := 0, 0, 0 - ans := [][]int{} - for _, j := range keys { - if n > 0 { - t := []int{i, j, h / n} - if len(ans) > 0 && ans[len(ans)-1][1] == i && ans[len(ans)-1][2] == t[2] { - ans[len(ans)-1][1] = j + + for _, k := range keys { + v := d[k] + if m > 0 { + avg := s / m + if len(ans) > 0 && ans[len(ans)-1][2] == avg && ans[len(ans)-1][1] == last { + ans[len(ans)-1][1] = k } else { - ans = append(ans, t) + ans = append(ans, []int{last, k, avg}) } } - i = j - h += height[j] - n += cnt[j] + s += v + m += cnt[k] + last = k } + return ans } ``` +#### TypeScript + +```ts +function averageHeightOfBuildings(buildings: number[][]): number[][] { + const cnt = new Map(); + const d = new Map(); + for (const [start, end, height] of buildings) { + cnt.set(start, (cnt.get(start) || 0) + 1); + cnt.set(end, (cnt.get(end) || 0) - 1); + d.set(start, (d.get(start) || 0) + height); + d.set(end, (d.get(end) || 0) - height); + } + let [s, m] = [0, 0]; + let last = -1; + const ans: number[][] = []; + const sortedKeys = Array.from(d.keys()).sort((a, b) => a - b); + for (const k of sortedKeys) { + const v = d.get(k)!; + if (m > 0) { + const avg = Math.floor(s / m); + if (ans.length > 0 && ans.at(-1)![2] === avg && ans.at(-1)![1] === last) { + ans[ans.length - 1][1] = k; + } else { + ans.push([last, k, avg]); + } + } + s += v; + m += cnt.get(k)!; + last = k; + } + return ans; +} +``` + diff --git a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.cpp b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.cpp index 3a34325ab1ce..6bfd728a7bbf 100644 --- a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.cpp +++ b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.cpp @@ -1,27 +1,35 @@ class Solution { public: vector> averageHeightOfBuildings(vector>& buildings) { - map height, cnt; - for (auto& v : buildings) { - int s = v[0], e = v[1], h = v[2]; - cnt[s]++, cnt[e]--; - height[s] += h, height[e] -= h; + unordered_map cnt; + map d; + + for (const auto& e : buildings) { + int start = e[0], end = e[1], height = e[2]; + cnt[start]++; + cnt[end]--; + d[start] += height; + d[end] -= height; } + + int s = 0, m = 0; + int last = -1; vector> ans; - int i = 0, h = 0, n = 0; - for (auto& [j, _] : cnt) { - if (n) { - vector t = {i, j, h / n}; - if (ans.size() && ans.back()[1] == i && ans.back()[2] == t[2]) { - ans.back()[1] = j; + + for (const auto& [k, v] : d) { + if (m > 0) { + int avg = s / m; + if (!ans.empty() && ans.back()[2] == avg && ans.back()[1] == last) { + ans.back()[1] = k; } else { - ans.push_back(t); + ans.push_back({last, k, avg}); } } - i = j; - h += height[j]; - n += cnt[j]; + s += v; + m += cnt[k]; + last = k; } + return ans; } -}; \ No newline at end of file +}; diff --git a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.go b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.go index a781b304a795..42d8ef6b7bbd 100644 --- a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.go +++ b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.go @@ -1,32 +1,39 @@ func averageHeightOfBuildings(buildings [][]int) [][]int { - height := make(map[int]int) cnt := make(map[int]int) - for _, v := range buildings { - s, e, h := v[0], v[1], v[2] - cnt[s]++ - cnt[e]-- - height[s] += h - height[e] -= h + d := make(map[int]int) + + for _, e := range buildings { + start, end, height := e[0], e[1], e[2] + cnt[start]++ + cnt[end]-- + d[start] += height + d[end] -= height } - keys := make([]int, len(cnt)) - for k := range cnt { + + s, m := 0, 0 + last := -1 + var ans [][]int + + keys := make([]int, 0, len(d)) + for k := range d { keys = append(keys, k) } sort.Ints(keys) - i, h, n := 0, 0, 0 - ans := [][]int{} - for _, j := range keys { - if n > 0 { - t := []int{i, j, h / n} - if len(ans) > 0 && ans[len(ans)-1][1] == i && ans[len(ans)-1][2] == t[2] { - ans[len(ans)-1][1] = j + + for _, k := range keys { + v := d[k] + if m > 0 { + avg := s / m + if len(ans) > 0 && ans[len(ans)-1][2] == avg && ans[len(ans)-1][1] == last { + ans[len(ans)-1][1] = k } else { - ans = append(ans, t) + ans = append(ans, []int{last, k, avg}) } } - i = j - h += height[j] - n += cnt[j] + s += v + m += cnt[k] + last = k } + return ans -} \ No newline at end of file +} diff --git a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.java b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.java index 92ce24df1384..f7ce7abf52ac 100644 --- a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.java +++ b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.java @@ -1,34 +1,32 @@ class Solution { public int[][] averageHeightOfBuildings(int[][] buildings) { - TreeMap height = new TreeMap<>(); - TreeMap cnt = new TreeMap<>(); - for (var v : buildings) { - int s = v[0], e = v[1], h = v[2]; - cnt.put(s, cnt.getOrDefault(s, 0) + 1); - cnt.put(e, cnt.getOrDefault(e, 0) - 1); - height.put(s, height.getOrDefault(s, 0) + h); - height.put(e, height.getOrDefault(e, 0) - h); + Map cnt = new HashMap<>(); + TreeMap d = new TreeMap<>(); + for (var e : buildings) { + int start = e[0], end = e[1], height = e[2]; + cnt.merge(start, 1, Integer::sum); + cnt.merge(end, -1, Integer::sum); + d.merge(start, height, Integer::sum); + d.merge(end, -height, Integer::sum); } - int i = 0, h = 0, n = 0; - List res = new ArrayList<>(); - for (int j : cnt.keySet()) { - if (n > 0) { - int[] t = new int[] {i, j, h / n}; - int k = res.size() - 1; - if (k >= 0 && res.get(k)[1] == i && res.get(k)[2] == t[2]) { - res.get(k)[1] = j; + int s = 0, m = 0; + int last = -1; + List ans = new ArrayList<>(); + for (var e : d.entrySet()) { + int k = e.getKey(), v = e.getValue(); + if (m > 0) { + int avg = s / m; + if (!ans.isEmpty() && ans.get(ans.size() - 1)[2] == avg + && ans.get(ans.size() - 1)[1] == last) { + ans.get(ans.size() - 1)[1] = k; } else { - res.add(t); + ans.add(new int[] {last, k, avg}); } } - h += height.get(j); - n += cnt.get(j); - i = j; + s += v; + m += cnt.get(k); + last = k; } - int[][] ans = new int[res.size()][3]; - for (i = 0; i < ans.length; ++i) { - ans[i] = res.get(i); - } - return ans; + return ans.toArray(new int[0][]); } -} \ No newline at end of file +} diff --git a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.py b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.py index 10afd336d636..92f2d2613fa6 100644 --- a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.py +++ b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.py @@ -1,22 +1,23 @@ class Solution: def averageHeightOfBuildings(self, buildings: List[List[int]]) -> List[List[int]]: - height = defaultdict(int) cnt = defaultdict(int) - for s, e, h in buildings: - cnt[s] += 1 - cnt[e] -= 1 - height[s] += h - height[e] -= h + d = defaultdict(int) + for start, end, height in buildings: + cnt[start] += 1 + cnt[end] -= 1 + d[start] += height + d[end] -= height + s = m = 0 + last = -1 ans = [] - i = h = n = 0 - for j in sorted(cnt.keys()): - if n: - t = [i, j, h // n] - if ans and ans[-1][1] == i and ans[-1][2] == t[-1]: - ans[-1][1] = j + for k, v in sorted(d.items()): + if m: + avg = s // m + if ans and ans[-1][2] == avg and ans[-1][1] == last: + ans[-1][1] = k else: - ans.append(t) - i = j - h += height[j] - n += cnt[j] + ans.append([last, k, avg]) + s += v + m += cnt[k] + last = k return ans diff --git a/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.ts b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.ts new file mode 100644 index 000000000000..f15a6abb0f45 --- /dev/null +++ b/solution/2000-2099/2015.Average Height of Buildings in Each Segment/Solution.ts @@ -0,0 +1,29 @@ +function averageHeightOfBuildings(buildings: number[][]): number[][] { + const cnt = new Map(); + const d = new Map(); + for (const [start, end, height] of buildings) { + cnt.set(start, (cnt.get(start) || 0) + 1); + cnt.set(end, (cnt.get(end) || 0) - 1); + d.set(start, (d.get(start) || 0) + height); + d.set(end, (d.get(end) || 0) - height); + } + let [s, m] = [0, 0]; + let last = -1; + const ans: number[][] = []; + const sortedKeys = Array.from(d.keys()).sort((a, b) => a - b); + for (const k of sortedKeys) { + const v = d.get(k)!; + if (m > 0) { + const avg = Math.floor(s / m); + if (ans.length > 0 && ans.at(-1)![2] === avg && ans.at(-1)![1] === last) { + ans[ans.length - 1][1] = k; + } else { + ans.push([last, k, avg]); + } + } + s += v; + m += cnt.get(k)!; + last = k; + } + return ans; +} diff --git a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README.md b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README.md index 2071ad30aa07..3a79b01b00a7 100644 --- a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README.md +++ b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README.md @@ -67,9 +67,11 @@ tags: ### 方法一:维护前缀最小值 -我们用变量 $mi$ 表示当前遍历到的元素中的最小值,用变量 $ans$ 表示最大差值,初始时 $mi$ 为 $+\infty$,而 $ans$ 为 $-1$。 +我们用一个变量 $\textit{mi}$ 表示当前遍历到的元素中的最小值,用一个变量 $\textit{ans}$ 表示最大差值,初始时 $\textit{mi}$ 为 $+\infty$,而 $\textit{ans}$ 为 $-1$。 -遍历数组,对于当前遍历到的元素 $x$,如果 $x \gt mi$,则更新 $ans$ 为 $max(ans, x - mi)$,否则更新 $mi = x$。 +遍历数组,对于当前遍历到的元素 $x$,如果 $x \gt \textit{mi}$,则更新 $\textit{ans}$ 为 $\max(\textit{ans}, x - \textit{mi})$,否则更新 $\textit{mi} = x$。 + +遍历结束后,返回 $\textit{ans}$。 遍历结束后,返回 $ans$。 @@ -152,14 +154,15 @@ func maximumDifference(nums []int) int { ```ts function maximumDifference(nums: number[]): number { - const n = nums.length; - let min = nums[0]; - let res = -1; - for (let i = 1; i < n; i++) { - res = Math.max(res, nums[i] - min); - min = Math.min(min, nums[i]); + let [ans, mi] = [-1, Infinity]; + for (const x of nums) { + if (x > mi) { + ans = Math.max(ans, x - mi); + } else { + mi = x; + } } - return res === 0 ? -1 : res; + return ans; } ``` @@ -168,16 +171,18 @@ function maximumDifference(nums: number[]): number { ```rust impl Solution { pub fn maximum_difference(nums: Vec) -> i32 { - let mut min = nums[0]; - let mut res = -1; - for i in 1..nums.len() { - res = res.max(nums[i] - min); - min = min.min(nums[i]); - } - match res { - 0 => -1, - _ => res, + let mut mi = i32::MAX; + let mut ans = -1; + + for &x in &nums { + if x > mi { + ans = ans.max(x - mi); + } else { + mi = x; + } } + + ans } } ``` @@ -190,10 +195,9 @@ impl Solution { * @return {number} */ var maximumDifference = function (nums) { - let mi = 1 << 30; - let ans = -1; + let [ans, mi] = [-1, Infinity]; for (const x of nums) { - if (mi < x) { + if (x > mi) { ans = Math.max(ans, x - mi); } else { mi = x; diff --git a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README_EN.md b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README_EN.md index 6e674cdebac2..5bc56c0574bc 100644 --- a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README_EN.md +++ b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/README_EN.md @@ -68,13 +68,13 @@ The maximum difference occurs with i = 0 and j = 3, nums[j] - nums[i] = 10 - 1 = ### Solution 1: Maintaining Prefix Minimum -We use the variable $mi$ to represent the minimum value of the elements we have traversed so far, and the variable $ans$ to represent the maximum difference. Initially, $mi$ is set to $+\infty$, and $ans$ is set to $-1$. +We use a variable $\textit{mi}$ to represent the minimum value among the elements currently being traversed, and a variable $\textit{ans}$ to represent the maximum difference. Initially, $\textit{mi}$ is set to $+\infty$, and $\textit{ans}$ is set to $-1$. -We traverse the array. For the current element $x$, if $x > mi$, then we update $ans$ to be $max(ans, x - mi)$, otherwise we update $mi = x$. +Traverse the array. For the current element $x$, if $x \gt \textit{mi}$, update $\textit{ans}$ to $\max(\textit{ans}, x - \textit{mi})$. Otherwise, update $\textit{mi}$ to $x$. -After the traversal, we return $ans$. +After the traversal, return $\textit{ans}$. -The time complexity is $O(n)$, where $n$ is the length of the array. The space complexity is $O(1)$. +Time complexity is $O(n)$, where $n$ is the length of the array. Space complexity is $O(1)$. @@ -153,14 +153,15 @@ func maximumDifference(nums []int) int { ```ts function maximumDifference(nums: number[]): number { - const n = nums.length; - let min = nums[0]; - let res = -1; - for (let i = 1; i < n; i++) { - res = Math.max(res, nums[i] - min); - min = Math.min(min, nums[i]); + let [ans, mi] = [-1, Infinity]; + for (const x of nums) { + if (x > mi) { + ans = Math.max(ans, x - mi); + } else { + mi = x; + } } - return res === 0 ? -1 : res; + return ans; } ``` @@ -169,16 +170,18 @@ function maximumDifference(nums: number[]): number { ```rust impl Solution { pub fn maximum_difference(nums: Vec) -> i32 { - let mut min = nums[0]; - let mut res = -1; - for i in 1..nums.len() { - res = res.max(nums[i] - min); - min = min.min(nums[i]); - } - match res { - 0 => -1, - _ => res, + let mut mi = i32::MAX; + let mut ans = -1; + + for &x in &nums { + if x > mi { + ans = ans.max(x - mi); + } else { + mi = x; + } } + + ans } } ``` @@ -191,10 +194,9 @@ impl Solution { * @return {number} */ var maximumDifference = function (nums) { - let mi = 1 << 30; - let ans = -1; + let [ans, mi] = [-1, Infinity]; for (const x of nums) { - if (mi < x) { + if (x > mi) { ans = Math.max(ans, x - mi); } else { mi = x; diff --git a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.js b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.js index b274f98f7762..b10ebb15e957 100644 --- a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.js +++ b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.js @@ -3,10 +3,9 @@ * @return {number} */ var maximumDifference = function (nums) { - let mi = 1 << 30; - let ans = -1; + let [ans, mi] = [-1, Infinity]; for (const x of nums) { - if (mi < x) { + if (x > mi) { ans = Math.max(ans, x - mi); } else { mi = x; diff --git a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.rs b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.rs index a89640cfab55..4e952543ff0f 100644 --- a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.rs +++ b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.rs @@ -1,14 +1,16 @@ impl Solution { pub fn maximum_difference(nums: Vec) -> i32 { - let mut min = nums[0]; - let mut res = -1; - for i in 1..nums.len() { - res = res.max(nums[i] - min); - min = min.min(nums[i]); - } - match res { - 0 => -1, - _ => res, + let mut mi = i32::MAX; + let mut ans = -1; + + for &x in &nums { + if x > mi { + ans = ans.max(x - mi); + } else { + mi = x; + } } + + ans } } diff --git a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.ts b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.ts index 82f7d1c160a0..9cb41459a4de 100644 --- a/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.ts +++ b/solution/2000-2099/2016.Maximum Difference Between Increasing Elements/Solution.ts @@ -1,10 +1,11 @@ function maximumDifference(nums: number[]): number { - const n = nums.length; - let min = nums[0]; - let res = -1; - for (let i = 1; i < n; i++) { - res = Math.max(res, nums[i] - min); - min = Math.min(min, nums[i]); + let [ans, mi] = [-1, Infinity]; + for (const x of nums) { + if (x > mi) { + ans = Math.max(ans, x - mi); + } else { + mi = x; + } } - return res === 0 ? -1 : res; + return ans; } diff --git a/solution/2000-2099/2028.Find Missing Observations/README.md b/solution/2000-2099/2028.Find Missing Observations/README.md index 8ca34e9873b1..b9902128353e 100644 --- a/solution/2000-2099/2028.Find Missing Observations/README.md +++ b/solution/2000-2099/2028.Find Missing Observations/README.md @@ -82,7 +82,7 @@ tags: ### 方法一:构造 -根据题目描述,所有数字之和为 $(n + m) \times \text{mean}$,已知的数字之和为 $\sum_{i=0}^{m-1} \text{rolls}[i]$,那么缺失的数字之和为 $s = (n + m) \times \text{mean} - \sum_{i=0}^{m-1} \text{rolls}[i]$。 +根据题目描述,所有数字之和为 $(n + m) \times \textit{mean}$,已知的数字之和为 $\sum_{i=0}^{m-1} \textit{rolls}[i]$,那么缺失的数字之和为 $s = (n + m) \times \textit{mean} - \sum_{i=0}^{m-1} \textit{rolls}[i]$。 如果 $s \gt n \times 6$ 或者 $s \lt n$,说明不存在满足条件的答案,返回空数组。 diff --git a/solution/2000-2099/2028.Find Missing Observations/README_EN.md b/solution/2000-2099/2028.Find Missing Observations/README_EN.md index c069a29c629e..7f7cb203655f 100644 --- a/solution/2000-2099/2028.Find Missing Observations/README_EN.md +++ b/solution/2000-2099/2028.Find Missing Observations/README_EN.md @@ -72,7 +72,7 @@ tags: ### Solution 1: Construction -According to the problem description, the sum of all numbers is $(n + m) \times \text{mean}$, and the sum of known numbers is $\sum_{i=0}^{m-1} \text{rolls}[i]$. Therefore, the sum of the missing numbers is $s = (n + m) \times \text{mean} - \sum_{i=0}^{m-1} \text{rolls}[i]$. +According to the problem description, the sum of all numbers is $(n + m) \times \textit{mean}$, and the sum of known numbers is $\sum_{i=0}^{m-1} \textit{rolls}[i]$. Therefore, the sum of the missing numbers is $s = (n + m) \times \textit{mean} - \sum_{i=0}^{m-1} \textit{rolls}[i]$. If $s \gt n \times 6$ or $s \lt n$, it means there is no answer that satisfies the conditions, so we return an empty array. diff --git a/solution/2000-2099/2029.Stone Game IX/README.md b/solution/2000-2099/2029.Stone Game IX/README.md index a58260bfbd69..2ec9b2248a1c 100644 --- a/solution/2000-2099/2029.Stone Game IX/README.md +++ b/solution/2000-2099/2029.Stone Game IX/README.md @@ -225,6 +225,96 @@ function stoneGameIX(stones: number[]): boolean { } ``` +#### JavaScript + +```js +function stoneGameIX(stones) { + const c1 = Array(3).fill(0); + for (const x of stones) { + ++c1[x % 3]; + } + const c2 = [c1[0], c1[2], c1[1]]; + const check = cnt => { + if (--cnt[1] < 0) { + return false; + } + let r = 1 + Math.min(cnt[1], cnt[2]) * 2 + cnt[0]; + if (cnt[1] > cnt[2]) { + --cnt[1]; + ++r; + } + return r % 2 === 1 && cnt[1] !== cnt[2]; + }; + return check(c1) || check(c2); +} +``` + + + + + + + +### Solution 2: Simulation + + + +#### TypeScript + +```ts +function stoneGameIX(stones: number[]): boolean { + if (stones.length === 1) return false; + + const cnt = Array(3).fill(0); + for (const x of stones) cnt[x % 3]++; + + const check = (x: number, cnt: number[]): boolean => { + let c = 1; + if (--cnt[x] < 0) return false; + + while (cnt[1] || cnt[2]) { + if (cnt[x]) { + cnt[x]--; + x = x === 1 ? 2 : 1; + } else return (c + cnt[0]) % 2 === 1; + c++; + } + + return false; + }; + + return check(1, [...cnt]) || check(2, [...cnt]); +} +``` + +#### JavaScript + +```js +function stoneGameIX(stones) { + if (stones.length === 1) return false; + + const cnt = Array(3).fill(0); + for (const x of stones) cnt[x % 3]++; + + const check = (x, cnt) => { + let c = 1; + if (--cnt[x] < 0) return false; + + while (cnt[1] || cnt[2]) { + if (cnt[x]) { + cnt[x]--; + x = x === 1 ? 2 : 1; + } else return (c + cnt[0]) % 2 === 1; + c++; + } + + return false; + }; + + return check(1, [...cnt]) || check(2, [...cnt]); +} +``` + diff --git a/solution/2000-2099/2029.Stone Game IX/README_EN.md b/solution/2000-2099/2029.Stone Game IX/README_EN.md index 43242fed1ec3..d3b055319b20 100644 --- a/solution/2000-2099/2029.Stone Game IX/README_EN.md +++ b/solution/2000-2099/2029.Stone Game IX/README_EN.md @@ -218,6 +218,96 @@ function stoneGameIX(stones: number[]): boolean { } ``` +#### JavaScript + +```js +function stoneGameIX(stones) { + const c1 = Array(3).fill(0); + for (const x of stones) { + ++c1[x % 3]; + } + const c2 = [c1[0], c1[2], c1[1]]; + const check = cnt => { + if (--cnt[1] < 0) { + return false; + } + let r = 1 + Math.min(cnt[1], cnt[2]) * 2 + cnt[0]; + if (cnt[1] > cnt[2]) { + --cnt[1]; + ++r; + } + return r % 2 === 1 && cnt[1] !== cnt[2]; + }; + return check(c1) || check(c2); +} +``` + + + + + + + +### Solution 2: Simulation + + + +#### TypeScript + +```ts +function stoneGameIX(stones: number[]): boolean { + if (stones.length === 1) return false; + + const cnt = Array(3).fill(0); + for (const x of stones) cnt[x % 3]++; + + const check = (x: number, cnt: number[]): boolean => { + let c = 1; + if (--cnt[x] < 0) return false; + + while (cnt[1] || cnt[2]) { + if (cnt[x]) { + cnt[x]--; + x = x === 1 ? 2 : 1; + } else return (c + cnt[0]) % 2 === 1; + c++; + } + + return false; + }; + + return check(1, [...cnt]) || check(2, [...cnt]); +} +``` + +#### JavaScript + +```js +function stoneGameIX(stones) { + if (stones.length === 1) return false; + + const cnt = Array(3).fill(0); + for (const x of stones) cnt[x % 3]++; + + const check = (x, cnt) => { + let c = 1; + if (--cnt[x] < 0) return false; + + while (cnt[1] || cnt[2]) { + if (cnt[x]) { + cnt[x]--; + x = x === 1 ? 2 : 1; + } else return (c + cnt[0]) % 2 === 1; + c++; + } + + return false; + }; + + return check(1, [...cnt]) || check(2, [...cnt]); +} +``` + diff --git a/solution/2000-2099/2029.Stone Game IX/Solution.js b/solution/2000-2099/2029.Stone Game IX/Solution.js new file mode 100644 index 000000000000..417f2d256177 --- /dev/null +++ b/solution/2000-2099/2029.Stone Game IX/Solution.js @@ -0,0 +1,19 @@ +function stoneGameIX(stones) { + const c1 = Array(3).fill(0); + for (const x of stones) { + ++c1[x % 3]; + } + const c2 = [c1[0], c1[2], c1[1]]; + const check = cnt => { + if (--cnt[1] < 0) { + return false; + } + let r = 1 + Math.min(cnt[1], cnt[2]) * 2 + cnt[0]; + if (cnt[1] > cnt[2]) { + --cnt[1]; + ++r; + } + return r % 2 === 1 && cnt[1] !== cnt[2]; + }; + return check(c1) || check(c2); +} diff --git a/solution/2000-2099/2029.Stone Game IX/Solution2.js b/solution/2000-2099/2029.Stone Game IX/Solution2.js new file mode 100644 index 000000000000..562c579fc8a1 --- /dev/null +++ b/solution/2000-2099/2029.Stone Game IX/Solution2.js @@ -0,0 +1,23 @@ +function stoneGameIX(stones) { + if (stones.length === 1) return false; + + const cnt = Array(3).fill(0); + for (const x of stones) cnt[x % 3]++; + + const check = (x, cnt) => { + let c = 1; + if (--cnt[x] < 0) return false; + + while (cnt[1] || cnt[2]) { + if (cnt[x]) { + cnt[x]--; + x = x === 1 ? 2 : 1; + } else return (c + cnt[0]) % 2 === 1; + c++; + } + + return false; + }; + + return check(1, [...cnt]) || check(2, [...cnt]); +} diff --git a/solution/2000-2099/2029.Stone Game IX/Solution2.ts b/solution/2000-2099/2029.Stone Game IX/Solution2.ts new file mode 100644 index 000000000000..1e8218c5f072 --- /dev/null +++ b/solution/2000-2099/2029.Stone Game IX/Solution2.ts @@ -0,0 +1,23 @@ +function stoneGameIX(stones: number[]): boolean { + if (stones.length === 1) return false; + + const cnt = Array(3).fill(0); + for (const x of stones) cnt[x % 3]++; + + const check = (x: number, cnt: number[]): boolean => { + let c = 1; + if (--cnt[x] < 0) return false; + + while (cnt[1] || cnt[2]) { + if (cnt[x]) { + cnt[x]--; + x = x === 1 ? 2 : 1; + } else return (c + cnt[0]) % 2 === 1; + c++; + } + + return false; + }; + + return check(1, [...cnt]) || check(2, [...cnt]); +} diff --git a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md index f41f8fe27b6c..689849e6061c 100644 --- a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md +++ b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md @@ -77,19 +77,19 @@ tags: ### 方法一:二分查找 -我们可以二分枚举乘积的值 $p$,定义二分的区间为 $[l, r]$,其中 $l = -\text{max}(|\text{nums1}[0]|, |\text{nums1}[n - 1]|) \times \text{max}(|\text{nums2}[0]|, |\text{nums2}[n - 1]|)$, $r = -l$。 +我们可以二分枚举乘积的值 $p$,定义二分的区间为 $[l, r]$,其中 $l = -\textit{max}(|\textit{nums1}[0]|, |\textit{nums1}[n - 1]|) \times \textit{max}(|\textit{nums2}[0]|, |\textit{nums2}[n - 1]|)$, $r = -l$。 对于每个 $p$,我们计算出乘积小于等于 $p$ 的乘积的个数,如果这个个数大于等于 $k$,那么说明第 $k$ 小的乘积一定小于等于 $p$,我们就可以将区间右端点缩小到 $p$,否则我们将区间左端点增大到 $p + 1$。 -那么问题的关键就是如何计算乘积小于等于 $p$ 的乘积的个数。我们可以枚举 $\text{nums1}$ 中的每个数 $x$,分类讨论: +那么问题的关键就是如何计算乘积小于等于 $p$ 的乘积的个数。我们可以枚举 $\textit{nums1}$ 中的每个数 $x$,分类讨论: -- 如果 $x > 0$,那么 $x \times \text{nums2}[i]$ 随着 $i$ 的增大是单调递增的,我们可以使用二分查找找到最小的 $i$,使得 $x \times \text{nums2}[i] > p$,那么 $i$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\text{cnt}$ 中; -- 如果 $x < 0$,那么 $x \times \text{nums2}[i]$ 随着 $i$ 的增大是单调递减的,我们可以使用二分查找找到最小的 $i$,使得 $x \times \text{nums2}[i] \leq p$,那么 $n - i$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\text{cnt}$ 中; -- 如果 $x = 0$,那么 $x \times \text{nums2}[i] = 0$,如果 $p \geq 0$,那么 $n$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\text{cnt}$ 中。 +- 如果 $x > 0$,那么 $x \times \textit{nums2}[i]$ 随着 $i$ 的增大是单调递增的,我们可以使用二分查找找到最小的 $i$,使得 $x \times \textit{nums2}[i] > p$,那么 $i$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\textit{cnt}$ 中; +- 如果 $x < 0$,那么 $x \times \textit{nums2}[i]$ 随着 $i$ 的增大是单调递减的,我们可以使用二分查找找到最小的 $i$,使得 $x \times \textit{nums2}[i] \leq p$,那么 $n - i$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\textit{cnt}$ 中; +- 如果 $x = 0$,那么 $x \times \textit{nums2}[i] = 0$,如果 $p \geq 0$,那么 $n$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\textit{cnt}$ 中。 这样我们就可以通过二分查找找到第 $k$ 小的乘积。 -时间复杂度 $O(m \times \log n \times \log M)$,其中 $m$ 和 $n$ 分别为 $\text{nums1}$ 和 $\text{nums2}$ 的长度,而 $M$ 为 $\text{nums1}$ 和 $\text{nums2}$ 中的最大值的绝对值。 +时间复杂度 $O(m \times \log n \times \log M)$,其中 $m$ 和 $n$ 分别为 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度,而 $M$ 为 $\textit{nums1}$ 和 $\textit{nums2}$ 中的最大值的绝对值。 diff --git a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md index 6921c75cba41..3f8742d1afed 100644 --- a/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md +++ b/solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README_EN.md @@ -78,19 +78,19 @@ The 3rd smallest product is -6. ### Solution 1: Binary Search -We can use binary search to enumerate the value of the product $p$, defining the binary search interval as $[l, r]$, where $l = -\text{max}(|\text{nums1}[0]|, |\text{nums1}[n - 1]|) \times \text{max}(|\text{nums2}[0]|, |\text{nums2}[n - 1]|)$, $r = -l$. +We can use binary search to enumerate the value of the product $p$, defining the binary search interval as $[l, r]$, where $l = -\textit{max}(|\textit{nums1}[0]|, |\textit{nums1}[n - 1]|) \times \textit{max}(|\textit{nums2}[0]|, |\textit{nums2}[n - 1]|)$, $r = -l$. For each $p$, we calculate the number of products less than or equal to $p$. If this number is greater than or equal to $k$, it means the $k$-th smallest product must be less than or equal to $p$, so we can reduce the right endpoint of the interval to $p$. Otherwise, we increase the left endpoint of the interval to $p + 1$. -The key to the problem is how to calculate the number of products less than or equal to $p$. We can enumerate each number $x$ in $\text{nums1}$ and discuss in cases: +The key to the problem is how to calculate the number of products less than or equal to $p$. We can enumerate each number $x$ in $\textit{nums1}$ and discuss in cases: -- If $x > 0$, then $x \times \text{nums2}[i]$ is monotonically increasing as $i$ increases. We can use binary search to find the smallest $i$ such that $x \times \text{nums2}[i] > p$. Then, $i$ is the number of products less than or equal to $p$, which is accumulated into the count $\text{cnt}$; -- If $x < 0$, then $x \times \text{nums2}[i]$ is monotonically decreasing as $i$ increases. We can use binary search to find the smallest $i$ such that $x \times \text{nums2}[i] \leq p$. Then, $n - i$ is the number of products less than or equal to $p$, which is accumulated into the count $\text{cnt}$; -- If $x = 0$, then $x \times \text{nums2}[i] = 0$. If $p \geq 0$, then $n$ is the number of products less than or equal to $p$, which is accumulated into the count $\text{cnt}$. +- If $x > 0$, then $x \times \textit{nums2}[i]$ is monotonically increasing as $i$ increases. We can use binary search to find the smallest $i$ such that $x \times \textit{nums2}[i] > p$. Then, $i$ is the number of products less than or equal to $p$, which is accumulated into the count $\textit{cnt}$; +- If $x < 0$, then $x \times \textit{nums2}[i]$ is monotonically decreasing as $i$ increases. We can use binary search to find the smallest $i$ such that $x \times \textit{nums2}[i] \leq p$. Then, $n - i$ is the number of products less than or equal to $p$, which is accumulated into the count $\textit{cnt}$; +- If $x = 0$, then $x \times \textit{nums2}[i] = 0$. If $p \geq 0$, then $n$ is the number of products less than or equal to $p$, which is accumulated into the count $\textit{cnt}$. This way, we can find the $k$-th smallest product through binary search. -The time complexity is $O(m \times \log n \times \log M)$, where $m$ and $n$ are the lengths of $\text{nums1}$ and $\text{nums2}$, respectively, and $M$ is the maximum absolute value in $\text{nums1}$ and $\text{nums2}$. +The time complexity is $O(m \times \log n \times \log M)$, where $m$ and $n$ are the lengths of $\textit{nums1}$ and $\textit{nums2}$, respectively, and $M$ is the maximum absolute value in $\textit{nums1}$ and $\textit{nums2}$. diff --git a/solution/2000-2099/2047.Number of Valid Words in a Sentence/README.md b/solution/2000-2099/2047.Number of Valid Words in a Sentence/README.md index e1dd7c62b333..24c1e18c1cca 100644 --- a/solution/2000-2099/2047.Number of Valid Words in a Sentence/README.md +++ b/solution/2000-2099/2047.Number of Valid Words in a Sentence/README.md @@ -77,7 +77,25 @@ tags: -### 方法一 +### 方法一:模拟 + +我们首先将句子按空格分割成单词,然后对每个单词进行检查,判断是否为有效单词。 + +对于每个单词,我们可以使用一个布尔变量 $\textit{st}$ 来记录是否已经出现过连字符,然后遍历单词中的每个字符,根据题目描述的规则进行判断。 + +对于每个字符 $s[i]$,我们有以下几种情况: + +- 如果 $s[i]$ 是数字,那么 $s$ 不是有效单词,直接返回 $\text{false}$; +- 如果 $s[i]$ 是标点符号('!'、'.'、',')且 $i < \text{len}(s) - 1$,那么 $s$ 不是有效单词,直接返回 $\text{false}$; +- 如果 $s[i]$ 是连字符,那么我们需要判断是否满足以下条件: + - 连字符只能出现一次; + - 连字符不能出现在单词的开头或结尾; + - 连字符两侧必须是字母; +- 如果 $s[i]$ 是字母,那么我们不需要做任何处理。 + +最后,我们统计出句子中的有效单词数即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是句子的长度。 @@ -86,24 +104,23 @@ tags: ```python class Solution: def countValidWords(self, sentence: str) -> int: - def check(token): - hyphen = False - for i, c in enumerate(token): - if c.isdigit() or (c in '!.,' and i < len(token) - 1): + def check(s: str) -> bool: + st = False + for i, c in enumerate(s): + if c.isdigit() or (c in "!.," and i < len(s) - 1): return False - if c == '-': + if c == "-": if ( - hyphen - or i == 0 - or i == len(token) - 1 - or not token[i - 1].islower() - or not token[i + 1].islower() + st + or i in (0, len(s) - 1) + or not s[i - 1].isalpha() + or not s[i + 1].isalpha() ): return False - hyphen = True + st = True return True - return sum(check(token) for token in sentence.split()) + return sum(check(s) for s in sentence.split()) ``` #### Java @@ -112,76 +129,142 @@ class Solution: class Solution { public int countValidWords(String sentence) { int ans = 0; - for (String token : sentence.split(" ")) { - if (check(token)) { - ++ans; - } + for (String s : sentence.split(" ")) { + ans += check(s.toCharArray()); } return ans; } - private boolean check(String token) { - int n = token.length(); - if (n == 0) { - return false; + private int check(char[] s) { + if (s.length == 0) { + return 0; } - boolean hyphen = false; - for (int i = 0; i < n; ++i) { - char c = token.charAt(i); - if (Character.isDigit(c) || (i < n - 1 && (c == '!' || c == '.' || c == ','))) { - return false; + boolean st = false; + for (int i = 0; i < s.length; ++i) { + if (Character.isDigit(s[i])) { + return 0; + } + if ((s[i] == '!' || s[i] == '.' || s[i] == ',') && i < s.length - 1) { + return 0; } - if (c == '-') { - if (hyphen || i == 0 || i == n - 1 || !Character.isLetter(token.charAt(i - 1)) - || !Character.isLetter(token.charAt(i + 1))) { - return false; + if (s[i] == '-') { + if (st || i == 0 || i == s.length - 1) { + return 0; } - hyphen = true; + if (!Character.isAlphabetic(s[i - 1]) || !Character.isAlphabetic(s[i + 1])) { + return 0; + } + st = true; } } - return true; + return 1; } } ``` -#### TypeScript +#### C++ -```ts -function countValidWords(sentence: string): number { - let words = sentence.trim().split(/\s+/); - let ans = 0; - for (let word of words) { - if (isValied(word)) { - ans++; +```cpp +class Solution { +public: + int countValidWords(string sentence) { + auto check = [](const string& s) -> int { + bool st = false; + for (int i = 0; i < s.length(); ++i) { + if (isdigit(s[i])) { + return 0; + } + if ((s[i] == '!' || s[i] == '.' || s[i] == ',') && i < s.length() - 1) { + return 0; + } + if (s[i] == '-') { + if (st || i == 0 || i == s.length() - 1) { + return 0; + } + if (!isalpha(s[i - 1]) || !isalpha(s[i + 1])) { + return 0; + } + st = true; + } + } + return 1; + }; + + int ans = 0; + stringstream ss(sentence); + string s; + while (ss >> s) { + ans += check(s); } + return ans; } - return ans; +}; +``` + +#### Go + +```go +func countValidWords(sentence string) (ans int) { + check := func(s string) int { + if len(s) == 0 { + return 0 + } + st := false + for i, r := range s { + if unicode.IsDigit(r) { + return 0 + } + if (r == '!' || r == '.' || r == ',') && i < len(s)-1 { + return 0 + } + if r == '-' { + if st || i == 0 || i == len(s)-1 { + return 0 + } + if !unicode.IsLetter(rune(s[i-1])) || !unicode.IsLetter(rune(s[i+1])) { + return 0 + } + st = true + } + } + return 1 + } + for _, s := range strings.Fields(sentence) { + ans += check(s) + } + return ans } +``` + +#### TypeScript -function isValied(str: string): boolean { - let n = str.length; - let hasLine = false; - for (let i = 0; i < n; i++) { - const char = str.charAt(i); - if (/^[0-9]$/.test(char)) { - return false; +```ts +function countValidWords(sentence: string): number { + const check = (s: string): number => { + if (s.length === 0) { + return 0; } - if (char == '-') { - if (hasLine) return false; - else { - hasLine = true; + let st = false; + for (let i = 0; i < s.length; ++i) { + if (/\d/.test(s[i])) { + return 0; } - let pre = str.charAt(i - 1), - post = str.charAt(i + 1); - if (!/^[a-z]$/g.test(pre) || !/^[a-z]$/g.test(post)) { - return false; + if (['!', '.', ','].includes(s[i]) && i < s.length - 1) { + return 0; + } + if (s[i] === '-') { + if (st || [0, s.length - 1].includes(i)) { + return 0; + } + if (!/[a-zA-Z]/.test(s[i - 1]) || !/[a-zA-Z]/.test(s[i + 1])) { + return 0; + } + st = true; } } - if (/^[\!\.\,\s]$/.test(char) && i != n - 1) { - return false; - } - } - return true; + return 1; + }; + return sentence.split(/\s+/).reduce((acc, s) => acc + check(s), 0); } ``` diff --git a/solution/2000-2099/2047.Number of Valid Words in a Sentence/README_EN.md b/solution/2000-2099/2047.Number of Valid Words in a Sentence/README_EN.md index 81fc9791d496..97a1f297178e 100644 --- a/solution/2000-2099/2047.Number of Valid Words in a Sentence/README_EN.md +++ b/solution/2000-2099/2047.Number of Valid Words in a Sentence/README_EN.md @@ -75,7 +75,25 @@ tags: -### Solution 1 +### Solution 1: Simulation + +First, we split the sentence into words by spaces, and then check each word to determine if it is a valid word. + +For each word, we can use a boolean variable $\textit{st}$ to record whether a hyphen has already appeared, and then traverse each character in the word, judging according to the rules described in the problem. + +For each character $s[i]$, we have the following cases: + +- If $s[i]$ is a digit, then $s$ is not a valid word, and we return $\text{false}$ directly; +- If $s[i]$ is a punctuation mark ('!', '.', ','), and $i < \text{len}(s) - 1$, then $s$ is not a valid word, and we return $\text{false}$ directly; +- If $s[i]$ is a hyphen, then we need to check if the following conditions are met: + - The hyphen can only appear once; + - The hyphen cannot appear at the beginning or end of the word; + - Both sides of the hyphen must be letters; +- If $s[i]$ is a letter, then we do not need to do anything. + +Finally, we count the number of valid words in the sentence. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the sentence. @@ -84,24 +102,23 @@ tags: ```python class Solution: def countValidWords(self, sentence: str) -> int: - def check(token): - hyphen = False - for i, c in enumerate(token): - if c.isdigit() or (c in '!.,' and i < len(token) - 1): + def check(s: str) -> bool: + st = False + for i, c in enumerate(s): + if c.isdigit() or (c in "!.," and i < len(s) - 1): return False - if c == '-': + if c == "-": if ( - hyphen - or i == 0 - or i == len(token) - 1 - or not token[i - 1].islower() - or not token[i + 1].islower() + st + or i in (0, len(s) - 1) + or not s[i - 1].isalpha() + or not s[i + 1].isalpha() ): return False - hyphen = True + st = True return True - return sum(check(token) for token in sentence.split()) + return sum(check(s) for s in sentence.split()) ``` #### Java @@ -110,76 +127,142 @@ class Solution: class Solution { public int countValidWords(String sentence) { int ans = 0; - for (String token : sentence.split(" ")) { - if (check(token)) { - ++ans; - } + for (String s : sentence.split(" ")) { + ans += check(s.toCharArray()); } return ans; } - private boolean check(String token) { - int n = token.length(); - if (n == 0) { - return false; + private int check(char[] s) { + if (s.length == 0) { + return 0; } - boolean hyphen = false; - for (int i = 0; i < n; ++i) { - char c = token.charAt(i); - if (Character.isDigit(c) || (i < n - 1 && (c == '!' || c == '.' || c == ','))) { - return false; + boolean st = false; + for (int i = 0; i < s.length; ++i) { + if (Character.isDigit(s[i])) { + return 0; + } + if ((s[i] == '!' || s[i] == '.' || s[i] == ',') && i < s.length - 1) { + return 0; } - if (c == '-') { - if (hyphen || i == 0 || i == n - 1 || !Character.isLetter(token.charAt(i - 1)) - || !Character.isLetter(token.charAt(i + 1))) { - return false; + if (s[i] == '-') { + if (st || i == 0 || i == s.length - 1) { + return 0; } - hyphen = true; + if (!Character.isAlphabetic(s[i - 1]) || !Character.isAlphabetic(s[i + 1])) { + return 0; + } + st = true; } } - return true; + return 1; } } ``` -#### TypeScript +#### C++ -```ts -function countValidWords(sentence: string): number { - let words = sentence.trim().split(/\s+/); - let ans = 0; - for (let word of words) { - if (isValied(word)) { - ans++; +```cpp +class Solution { +public: + int countValidWords(string sentence) { + auto check = [](const string& s) -> int { + bool st = false; + for (int i = 0; i < s.length(); ++i) { + if (isdigit(s[i])) { + return 0; + } + if ((s[i] == '!' || s[i] == '.' || s[i] == ',') && i < s.length() - 1) { + return 0; + } + if (s[i] == '-') { + if (st || i == 0 || i == s.length() - 1) { + return 0; + } + if (!isalpha(s[i - 1]) || !isalpha(s[i + 1])) { + return 0; + } + st = true; + } + } + return 1; + }; + + int ans = 0; + stringstream ss(sentence); + string s; + while (ss >> s) { + ans += check(s); } + return ans; } - return ans; +}; +``` + +#### Go + +```go +func countValidWords(sentence string) (ans int) { + check := func(s string) int { + if len(s) == 0 { + return 0 + } + st := false + for i, r := range s { + if unicode.IsDigit(r) { + return 0 + } + if (r == '!' || r == '.' || r == ',') && i < len(s)-1 { + return 0 + } + if r == '-' { + if st || i == 0 || i == len(s)-1 { + return 0 + } + if !unicode.IsLetter(rune(s[i-1])) || !unicode.IsLetter(rune(s[i+1])) { + return 0 + } + st = true + } + } + return 1 + } + for _, s := range strings.Fields(sentence) { + ans += check(s) + } + return ans } +``` + +#### TypeScript -function isValied(str: string): boolean { - let n = str.length; - let hasLine = false; - for (let i = 0; i < n; i++) { - const char = str.charAt(i); - if (/^[0-9]$/.test(char)) { - return false; +```ts +function countValidWords(sentence: string): number { + const check = (s: string): number => { + if (s.length === 0) { + return 0; } - if (char == '-') { - if (hasLine) return false; - else { - hasLine = true; + let st = false; + for (let i = 0; i < s.length; ++i) { + if (/\d/.test(s[i])) { + return 0; } - let pre = str.charAt(i - 1), - post = str.charAt(i + 1); - if (!/^[a-z]$/g.test(pre) || !/^[a-z]$/g.test(post)) { - return false; + if (['!', '.', ','].includes(s[i]) && i < s.length - 1) { + return 0; + } + if (s[i] === '-') { + if (st || [0, s.length - 1].includes(i)) { + return 0; + } + if (!/[a-zA-Z]/.test(s[i - 1]) || !/[a-zA-Z]/.test(s[i + 1])) { + return 0; + } + st = true; } } - if (/^[\!\.\,\s]$/.test(char) && i != n - 1) { - return false; - } - } - return true; + return 1; + }; + return sentence.split(/\s+/).reduce((acc, s) => acc + check(s), 0); } ``` diff --git a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.cpp b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.cpp new file mode 100644 index 000000000000..03130bb72da4 --- /dev/null +++ b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.cpp @@ -0,0 +1,34 @@ +class Solution { +public: + int countValidWords(string sentence) { + auto check = [](const string& s) -> int { + bool st = false; + for (int i = 0; i < s.length(); ++i) { + if (isdigit(s[i])) { + return 0; + } + if ((s[i] == '!' || s[i] == '.' || s[i] == ',') && i < s.length() - 1) { + return 0; + } + if (s[i] == '-') { + if (st || i == 0 || i == s.length() - 1) { + return 0; + } + if (!isalpha(s[i - 1]) || !isalpha(s[i + 1])) { + return 0; + } + st = true; + } + } + return 1; + }; + + int ans = 0; + stringstream ss(sentence); + string s; + while (ss >> s) { + ans += check(s); + } + return ans; + } +}; diff --git a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.go b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.go new file mode 100644 index 000000000000..f797f22162e3 --- /dev/null +++ b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.go @@ -0,0 +1,30 @@ +func countValidWords(sentence string) (ans int) { + check := func(s string) int { + if len(s) == 0 { + return 0 + } + st := false + for i, r := range s { + if unicode.IsDigit(r) { + return 0 + } + if (r == '!' || r == '.' || r == ',') && i < len(s)-1 { + return 0 + } + if r == '-' { + if st || i == 0 || i == len(s)-1 { + return 0 + } + if !unicode.IsLetter(rune(s[i-1])) || !unicode.IsLetter(rune(s[i+1])) { + return 0 + } + st = true + } + } + return 1 + } + for _, s := range strings.Fields(sentence) { + ans += check(s) + } + return ans +} diff --git a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.java b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.java index 7891058179e9..3772c1674ea7 100644 --- a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.java +++ b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.java @@ -1,33 +1,34 @@ class Solution { public int countValidWords(String sentence) { int ans = 0; - for (String token : sentence.split(" ")) { - if (check(token)) { - ++ans; - } + for (String s : sentence.split(" ")) { + ans += check(s.toCharArray()); } return ans; } - private boolean check(String token) { - int n = token.length(); - if (n == 0) { - return false; + private int check(char[] s) { + if (s.length == 0) { + return 0; } - boolean hyphen = false; - for (int i = 0; i < n; ++i) { - char c = token.charAt(i); - if (Character.isDigit(c) || (i < n - 1 && (c == '!' || c == '.' || c == ','))) { - return false; + boolean st = false; + for (int i = 0; i < s.length; ++i) { + if (Character.isDigit(s[i])) { + return 0; + } + if ((s[i] == '!' || s[i] == '.' || s[i] == ',') && i < s.length - 1) { + return 0; } - if (c == '-') { - if (hyphen || i == 0 || i == n - 1 || !Character.isLetter(token.charAt(i - 1)) - || !Character.isLetter(token.charAt(i + 1))) { - return false; + if (s[i] == '-') { + if (st || i == 0 || i == s.length - 1) { + return 0; + } + if (!Character.isAlphabetic(s[i - 1]) || !Character.isAlphabetic(s[i + 1])) { + return 0; } - hyphen = true; + st = true; } } - return true; + return 1; } -} \ No newline at end of file +} diff --git a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.py b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.py index 655d0647af88..b30b623eb13f 100644 --- a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.py +++ b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.py @@ -1,20 +1,19 @@ class Solution: def countValidWords(self, sentence: str) -> int: - def check(token): - hyphen = False - for i, c in enumerate(token): - if c.isdigit() or (c in '!.,' and i < len(token) - 1): + def check(s: str) -> bool: + st = False + for i, c in enumerate(s): + if c.isdigit() or (c in "!.," and i < len(s) - 1): return False - if c == '-': + if c == "-": if ( - hyphen - or i == 0 - or i == len(token) - 1 - or not token[i - 1].islower() - or not token[i + 1].islower() + st + or i in (0, len(s) - 1) + or not s[i - 1].isalpha() + or not s[i + 1].isalpha() ): return False - hyphen = True + st = True return True - return sum(check(token) for token in sentence.split()) + return sum(check(s) for s in sentence.split()) diff --git a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.ts b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.ts index 67c093614a96..0de784cbeedc 100644 --- a/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.ts +++ b/solution/2000-2099/2047.Number of Valid Words in a Sentence/Solution.ts @@ -1,36 +1,27 @@ function countValidWords(sentence: string): number { - let words = sentence.trim().split(/\s+/); - let ans = 0; - for (let word of words) { - if (isValied(word)) { - ans++; + const check = (s: string): number => { + if (s.length === 0) { + return 0; } - } - return ans; -} - -function isValied(str: string): boolean { - let n = str.length; - let hasLine = false; - for (let i = 0; i < n; i++) { - const char = str.charAt(i); - if (/^[0-9]$/.test(char)) { - return false; - } - if (char == '-') { - if (hasLine) return false; - else { - hasLine = true; + let st = false; + for (let i = 0; i < s.length; ++i) { + if (/\d/.test(s[i])) { + return 0; } - let pre = str.charAt(i - 1), - post = str.charAt(i + 1); - if (!/^[a-z]$/g.test(pre) || !/^[a-z]$/g.test(post)) { - return false; + if (['!', '.', ','].includes(s[i]) && i < s.length - 1) { + return 0; + } + if (s[i] === '-') { + if (st || [0, s.length - 1].includes(i)) { + return 0; + } + if (!/[a-zA-Z]/.test(s[i - 1]) || !/[a-zA-Z]/.test(s[i + 1])) { + return 0; + } + st = true; } } - if (/^[\!\.\,\s]$/.test(char) && i != n - 1) { - return false; - } - } - return true; + return 1; + }; + return sentence.split(/\s+/).reduce((acc, s) => acc + check(s), 0); } diff --git a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README.md b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README.md index 769aa0117601..6638a4ebf040 100644 --- a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README.md +++ b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README.md @@ -88,7 +88,22 @@ tags: -### 方法一:记忆化搜索 +### 方法一:前缀和 + 记忆化搜索 + +我们用一个数组 $\textit{nums}$ 记录每个单词的长度,数组的长度记为 $n$。然后我们定义一个长度为 $n + 1$ 的前缀和数组 $\textit{s}$,其中 $\textit{s}[i]$ 表示前 $i$ 个单词的长度之和。 + +接下来,我们设计一个函数 $\textit{dfs}(i)$,表示从第 $i$ 个单词开始分隔句子的最小成本。那么答案为 $\textit{dfs}(0)$。 + +函数 $\textit{dfs}(i)$ 的执行过程如下: + +- 如果从第 $i$ 个单词开始到最后一个单词的长度之和加上单词之间的空格数小于等于 $k$,那么这些单词可以放在最后一行,成本为 $0$。 +- 否则,我们枚举下一个开始分隔的单词的位置 $j$,使得从第 $i$ 个单词到第 $j-1$ 个单词的长度之和加上单词之间的空格数小于等于 $k$。那么 $\textit{dfs}(j)$ 表示从第 $j$ 个单词开始分隔句子的最小成本,而 $(k - m)^2$ 表示将第 $i$ 个单词到第 $j-1$ 个单词放在一行的成本,其中 $m$ 表示从第 $i$ 个单词到第 $j-1$ 个单词的长度之和加上单词之间的空格数。我们枚举所有的 $j$,取最小值即可。 + +答案即为 $\textit{dfs}(0)$。 + +为了避免重复计算,我们可以使用记忆化搜索。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为单词的个数。 @@ -98,18 +113,19 @@ tags: class Solution: def minimumCost(self, sentence: str, k: int) -> int: @cache - def dfs(i): - if s[-1] - s[i] + n - i - 1 <= k: + def dfs(i: int) -> int: + if s[n] - s[i] + n - i - 1 <= k: return 0 - ans, j = inf, i + 1 - while j < n and (t := s[j] - s[i] + j - i - 1) <= k: - ans = min(ans, (k - t) ** 2 + dfs(j)) + ans = inf + j = i + 1 + while j < n and (m := s[j] - s[i] + j - i - 1) <= k: + ans = min(ans, dfs(j) + (k - m) ** 2) j += 1 return ans - t = [len(w) for w in sentence.split()] - n = len(t) - s = list(accumulate(t, initial=0)) + nums = [len(s) for s in sentence.split()] + n = len(nums) + s = list(accumulate(nums, initial=0)) return dfs(0) ``` @@ -117,40 +133,36 @@ class Solution: ```java class Solution { - private static final int INF = Integer.MAX_VALUE; - private int[] memo; + private Integer[] f; private int[] s; + private int k; private int n; public int minimumCost(String sentence, int k) { + this.k = k; String[] words = sentence.split(" "); n = words.length; + f = new Integer[n]; s = new int[n + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + words[i].length(); } - memo = new int[n]; - Arrays.fill(memo, INF); - return dfs(0, k); + return dfs(0); } - private int dfs(int i, int k) { - if (memo[i] != INF) { - return memo[i]; - } + private int dfs(int i) { if (s[n] - s[i] + n - i - 1 <= k) { - memo[i] = 0; return 0; } - int ans = INF; - for (int j = i + 1; j < n; ++j) { - int t = s[j] - s[i] + j - i - 1; - if (t <= k) { - ans = Math.min(ans, (k - t) * (k - t) + dfs(j, k)); - } + if (f[i] != null) { + return f[i]; + } + int ans = Integer.MAX_VALUE; + for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + int m = s[j] - s[i] + j - i - 1; + ans = Math.min(ans, dfs(j) + (k - m) * (k - m)); } - memo[i] = ans; - return ans; + return f[i] = ans; } } ``` @@ -160,34 +172,31 @@ class Solution { ```cpp class Solution { public: - const int inf = INT_MAX; - int n; - int minimumCost(string sentence, int k) { - istringstream is(sentence); - vector words; - string word; - while (is >> word) words.push_back(word); - n = words.size(); - vector s(n + 1); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + words[i].size(); - vector memo(n, inf); - return dfs(0, k, s, memo); - } - - int dfs(int i, int k, vector& s, vector& memo) { - if (memo[i] != inf) return memo[i]; - if (s[n] - s[i] + n - i - 1 <= k) { - memo[i] = 0; - return 0; - } - int ans = inf; - for (int j = i + 1; j < n; ++j) { - int t = s[j] - s[i] + j - i - 1; - if (t <= k) ans = min(ans, (k - t) * (k - t) + dfs(j, k, s, memo)); + istringstream iss(sentence); + vector s = {0}; + string w; + while (iss >> w) { + s.push_back(s.back() + w.size()); } - memo[i] = ans; - return ans; + int n = s.size() - 1; + int f[n]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (s[n] - s[i] + n - i - 1 <= k) { + return 0; + } + if (f[i] != -1) { + return f[i]; + } + int ans = INT_MAX; + for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + int m = s[j] - s[i] + j - i - 1; + ans = min(ans, dfs(dfs, j) + (k - m) * (k - m)); + } + return f[i] = ans; + }; + return dfs(dfs, 0); } }; ``` @@ -196,40 +205,63 @@ public: ```go func minimumCost(sentence string, k int) int { - words := strings.Split(sentence, " ") - n := len(words) - inf := math.MaxInt32 - s := make([]int, n+1) - for i, word := range words { - s[i+1] = s[i] + len(word) + s := []int{0} + for _, w := range strings.Split(sentence, " ") { + s = append(s, s[len(s)-1]+len(w)) } - memo := make([]int, n) - for i := range memo { - memo[i] = inf + n := len(s) - 1 + f := make([]int, n) + for i := range f { + f[i] = -1 } var dfs func(int) int dfs = func(i int) int { - if memo[i] != inf { - return memo[i] - } if s[n]-s[i]+n-i-1 <= k { - memo[i] = 0 return 0 } - ans := inf - for j := i + 1; j < n; j++ { - t := s[j] - s[i] + j - i - 1 - if t <= k { - ans = min(ans, (k-t)*(k-t)+dfs(j)) - } + if f[i] != -1 { + return f[i] } - memo[i] = ans + ans := math.MaxInt32 + for j := i + 1; j < n && s[j]-s[i]+j-i-1 <= k; j++ { + m := s[j] - s[i] + j - i - 1 + ans = min(ans, dfs(j)+(k-m)*(k-m)) + } + f[i] = ans return ans } return dfs(0) } ``` +#### TypeScript + +```ts +function minimumCost(sentence: string, k: number): number { + const s: number[] = [0]; + for (const w of sentence.split(' ')) { + s.push(s.at(-1)! + w.length); + } + const n = s.length - 1; + const f: number[] = Array(n).fill(-1); + const dfs = (i: number): number => { + if (s[n] - s[i] + n - i - 1 <= k) { + return 0; + } + if (f[i] !== -1) { + return f[i]; + } + let ans = Infinity; + for (let j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + const m = s[j] - s[i] + j - i - 1; + ans = Math.min(ans, dfs(j) + (k - m) ** 2); + } + return (f[i] = ans); + }; + return dfs(0); +} +``` + diff --git a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README_EN.md b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README_EN.md index d08bc2c2c603..60ca5691d154 100644 --- a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README_EN.md +++ b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README_EN.md @@ -87,7 +87,22 @@ The cost of the last row is not included in the total cost, and since there is o -### Solution 1 +### Solution 1: Prefix Sum + Memoized Search + +We use an array $\textit{nums}$ to record the length of each word, and let the length of the array be $n$. Then we define a prefix sum array $\textit{s}$ of length $n + 1$, where $\textit{s}[i]$ represents the sum of the lengths of the first $i$ words. + +Next, we design a function $\textit{dfs}(i)$, which represents the minimum cost of splitting the sentence starting from the $i$-th word. The answer is $\textit{dfs}(0)$. + +The execution process of the function $\textit{dfs}(i)$ is as follows: + +- If the sum of the lengths of the words from the $i$-th word to the last word plus the number of spaces between the words is less than or equal to $k$, then these words can be placed on the last line, and the cost is $0$. +- Otherwise, we enumerate the position $j$ of the next word to start splitting, such that the sum of the lengths of the words from the $i$-th word to the $(j-1)$-th word plus the number of spaces between the words is less than or equal to $k$. Then $\textit{dfs}(j)$ represents the minimum cost of splitting the sentence starting from the $j$-th word, and $(k - m)^2$ represents the cost of placing the words from the $i$-th word to the $(j-1)$-th word on one line, where $m$ represents the sum of the lengths of the words from the $i$-th word to the $(j-1)$-th word plus the number of spaces between the words. We enumerate all $j$ and take the minimum value. + +The answer is $\textit{dfs}(0)$. + +To avoid repeated calculations, we can use memoized search. + +The time complexity is $O(n^2)$, and the space complexity is $O(n)$. Here, $n$ is the number of words. @@ -97,18 +112,19 @@ The cost of the last row is not included in the total cost, and since there is o class Solution: def minimumCost(self, sentence: str, k: int) -> int: @cache - def dfs(i): - if s[-1] - s[i] + n - i - 1 <= k: + def dfs(i: int) -> int: + if s[n] - s[i] + n - i - 1 <= k: return 0 - ans, j = inf, i + 1 - while j < n and (t := s[j] - s[i] + j - i - 1) <= k: - ans = min(ans, (k - t) ** 2 + dfs(j)) + ans = inf + j = i + 1 + while j < n and (m := s[j] - s[i] + j - i - 1) <= k: + ans = min(ans, dfs(j) + (k - m) ** 2) j += 1 return ans - t = [len(w) for w in sentence.split()] - n = len(t) - s = list(accumulate(t, initial=0)) + nums = [len(s) for s in sentence.split()] + n = len(nums) + s = list(accumulate(nums, initial=0)) return dfs(0) ``` @@ -116,40 +132,36 @@ class Solution: ```java class Solution { - private static final int INF = Integer.MAX_VALUE; - private int[] memo; + private Integer[] f; private int[] s; + private int k; private int n; public int minimumCost(String sentence, int k) { + this.k = k; String[] words = sentence.split(" "); n = words.length; + f = new Integer[n]; s = new int[n + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + words[i].length(); } - memo = new int[n]; - Arrays.fill(memo, INF); - return dfs(0, k); + return dfs(0); } - private int dfs(int i, int k) { - if (memo[i] != INF) { - return memo[i]; - } + private int dfs(int i) { if (s[n] - s[i] + n - i - 1 <= k) { - memo[i] = 0; return 0; } - int ans = INF; - for (int j = i + 1; j < n; ++j) { - int t = s[j] - s[i] + j - i - 1; - if (t <= k) { - ans = Math.min(ans, (k - t) * (k - t) + dfs(j, k)); - } + if (f[i] != null) { + return f[i]; + } + int ans = Integer.MAX_VALUE; + for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + int m = s[j] - s[i] + j - i - 1; + ans = Math.min(ans, dfs(j) + (k - m) * (k - m)); } - memo[i] = ans; - return ans; + return f[i] = ans; } } ``` @@ -159,34 +171,31 @@ class Solution { ```cpp class Solution { public: - const int inf = INT_MAX; - int n; - int minimumCost(string sentence, int k) { - istringstream is(sentence); - vector words; - string word; - while (is >> word) words.push_back(word); - n = words.size(); - vector s(n + 1); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + words[i].size(); - vector memo(n, inf); - return dfs(0, k, s, memo); - } - - int dfs(int i, int k, vector& s, vector& memo) { - if (memo[i] != inf) return memo[i]; - if (s[n] - s[i] + n - i - 1 <= k) { - memo[i] = 0; - return 0; - } - int ans = inf; - for (int j = i + 1; j < n; ++j) { - int t = s[j] - s[i] + j - i - 1; - if (t <= k) ans = min(ans, (k - t) * (k - t) + dfs(j, k, s, memo)); + istringstream iss(sentence); + vector s = {0}; + string w; + while (iss >> w) { + s.push_back(s.back() + w.size()); } - memo[i] = ans; - return ans; + int n = s.size() - 1; + int f[n]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (s[n] - s[i] + n - i - 1 <= k) { + return 0; + } + if (f[i] != -1) { + return f[i]; + } + int ans = INT_MAX; + for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + int m = s[j] - s[i] + j - i - 1; + ans = min(ans, dfs(dfs, j) + (k - m) * (k - m)); + } + return f[i] = ans; + }; + return dfs(dfs, 0); } }; ``` @@ -195,40 +204,63 @@ public: ```go func minimumCost(sentence string, k int) int { - words := strings.Split(sentence, " ") - n := len(words) - inf := math.MaxInt32 - s := make([]int, n+1) - for i, word := range words { - s[i+1] = s[i] + len(word) + s := []int{0} + for _, w := range strings.Split(sentence, " ") { + s = append(s, s[len(s)-1]+len(w)) } - memo := make([]int, n) - for i := range memo { - memo[i] = inf + n := len(s) - 1 + f := make([]int, n) + for i := range f { + f[i] = -1 } var dfs func(int) int dfs = func(i int) int { - if memo[i] != inf { - return memo[i] - } if s[n]-s[i]+n-i-1 <= k { - memo[i] = 0 return 0 } - ans := inf - for j := i + 1; j < n; j++ { - t := s[j] - s[i] + j - i - 1 - if t <= k { - ans = min(ans, (k-t)*(k-t)+dfs(j)) - } + if f[i] != -1 { + return f[i] } - memo[i] = ans + ans := math.MaxInt32 + for j := i + 1; j < n && s[j]-s[i]+j-i-1 <= k; j++ { + m := s[j] - s[i] + j - i - 1 + ans = min(ans, dfs(j)+(k-m)*(k-m)) + } + f[i] = ans return ans } return dfs(0) } ``` +#### TypeScript + +```ts +function minimumCost(sentence: string, k: number): number { + const s: number[] = [0]; + for (const w of sentence.split(' ')) { + s.push(s.at(-1)! + w.length); + } + const n = s.length - 1; + const f: number[] = Array(n).fill(-1); + const dfs = (i: number): number => { + if (s[n] - s[i] + n - i - 1 <= k) { + return 0; + } + if (f[i] !== -1) { + return f[i]; + } + let ans = Infinity; + for (let j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + const m = s[j] - s[i] + j - i - 1; + ans = Math.min(ans, dfs(j) + (k - m) ** 2); + } + return (f[i] = ans); + }; + return dfs(0); +} +``` + diff --git a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.cpp b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.cpp index 54dd9c745a0d..49ab761d9984 100644 --- a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.cpp +++ b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.cpp @@ -1,32 +1,29 @@ class Solution { public: - const int inf = INT_MAX; - int n; - int minimumCost(string sentence, int k) { - istringstream is(sentence); - vector words; - string word; - while (is >> word) words.push_back(word); - n = words.size(); - vector s(n + 1); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + words[i].size(); - vector memo(n, inf); - return dfs(0, k, s, memo); - } - - int dfs(int i, int k, vector& s, vector& memo) { - if (memo[i] != inf) return memo[i]; - if (s[n] - s[i] + n - i - 1 <= k) { - memo[i] = 0; - return 0; - } - int ans = inf; - for (int j = i + 1; j < n; ++j) { - int t = s[j] - s[i] + j - i - 1; - if (t <= k) ans = min(ans, (k - t) * (k - t) + dfs(j, k, s, memo)); + istringstream iss(sentence); + vector s = {0}; + string w; + while (iss >> w) { + s.push_back(s.back() + w.size()); } - memo[i] = ans; - return ans; + int n = s.size() - 1; + int f[n]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (s[n] - s[i] + n - i - 1 <= k) { + return 0; + } + if (f[i] != -1) { + return f[i]; + } + int ans = INT_MAX; + for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + int m = s[j] - s[i] + j - i - 1; + ans = min(ans, dfs(dfs, j) + (k - m) * (k - m)); + } + return f[i] = ans; + }; + return dfs(dfs, 0); } -}; \ No newline at end of file +}; diff --git a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.go b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.go index 88054f75bbde..93061027e8b2 100644 --- a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.go +++ b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.go @@ -1,33 +1,28 @@ func minimumCost(sentence string, k int) int { - words := strings.Split(sentence, " ") - n := len(words) - inf := math.MaxInt32 - s := make([]int, n+1) - for i, word := range words { - s[i+1] = s[i] + len(word) + s := []int{0} + for _, w := range strings.Split(sentence, " ") { + s = append(s, s[len(s)-1]+len(w)) } - memo := make([]int, n) - for i := range memo { - memo[i] = inf + n := len(s) - 1 + f := make([]int, n) + for i := range f { + f[i] = -1 } var dfs func(int) int dfs = func(i int) int { - if memo[i] != inf { - return memo[i] - } if s[n]-s[i]+n-i-1 <= k { - memo[i] = 0 return 0 } - ans := inf - for j := i + 1; j < n; j++ { - t := s[j] - s[i] + j - i - 1 - if t <= k { - ans = min(ans, (k-t)*(k-t)+dfs(j)) - } + if f[i] != -1 { + return f[i] + } + ans := math.MaxInt32 + for j := i + 1; j < n && s[j]-s[i]+j-i-1 <= k; j++ { + m := s[j] - s[i] + j - i - 1 + ans = min(ans, dfs(j)+(k-m)*(k-m)) } - memo[i] = ans + f[i] = ans return ans } return dfs(0) -} \ No newline at end of file +} diff --git a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.java b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.java index 144b71888ae7..e698e9a7b9af 100644 --- a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.java +++ b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.java @@ -1,37 +1,33 @@ class Solution { - private static final int INF = Integer.MAX_VALUE; - private int[] memo; + private Integer[] f; private int[] s; + private int k; private int n; public int minimumCost(String sentence, int k) { + this.k = k; String[] words = sentence.split(" "); n = words.length; + f = new Integer[n]; s = new int[n + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + words[i].length(); } - memo = new int[n]; - Arrays.fill(memo, INF); - return dfs(0, k); + return dfs(0); } - private int dfs(int i, int k) { - if (memo[i] != INF) { - return memo[i]; - } + private int dfs(int i) { if (s[n] - s[i] + n - i - 1 <= k) { - memo[i] = 0; return 0; } - int ans = INF; - for (int j = i + 1; j < n; ++j) { - int t = s[j] - s[i] + j - i - 1; - if (t <= k) { - ans = Math.min(ans, (k - t) * (k - t) + dfs(j, k)); - } + if (f[i] != null) { + return f[i]; + } + int ans = Integer.MAX_VALUE; + for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + int m = s[j] - s[i] + j - i - 1; + ans = Math.min(ans, dfs(j) + (k - m) * (k - m)); } - memo[i] = ans; - return ans; + return f[i] = ans; } -} \ No newline at end of file +} diff --git a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.py b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.py index 555aee438031..0d7b0f108f2b 100644 --- a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.py +++ b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.py @@ -1,16 +1,17 @@ class Solution: def minimumCost(self, sentence: str, k: int) -> int: @cache - def dfs(i): - if s[-1] - s[i] + n - i - 1 <= k: + def dfs(i: int) -> int: + if s[n] - s[i] + n - i - 1 <= k: return 0 - ans, j = inf, i + 1 - while j < n and (t := s[j] - s[i] + j - i - 1) <= k: - ans = min(ans, (k - t) ** 2 + dfs(j)) + ans = inf + j = i + 1 + while j < n and (m := s[j] - s[i] + j - i - 1) <= k: + ans = min(ans, dfs(j) + (k - m) ** 2) j += 1 return ans - t = [len(w) for w in sentence.split()] - n = len(t) - s = list(accumulate(t, initial=0)) + nums = [len(s) for s in sentence.split()] + n = len(nums) + s = list(accumulate(nums, initial=0)) return dfs(0) diff --git a/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.ts b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.ts new file mode 100644 index 000000000000..961dd1d7abd8 --- /dev/null +++ b/solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/Solution.ts @@ -0,0 +1,23 @@ +function minimumCost(sentence: string, k: number): number { + const s: number[] = [0]; + for (const w of sentence.split(' ')) { + s.push(s.at(-1)! + w.length); + } + const n = s.length - 1; + const f: number[] = Array(n).fill(-1); + const dfs = (i: number): number => { + if (s[n] - s[i] + n - i - 1 <= k) { + return 0; + } + if (f[i] !== -1) { + return f[i]; + } + let ans = Infinity; + for (let j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) { + const m = s[j] - s[i] + j - i - 1; + ans = Math.min(ans, dfs(j) + (k - m) ** 2); + } + return (f[i] = ans); + }; + return dfs(0); +} diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/README.md b/solution/2000-2099/2053.Kth Distinct String in an Array/README.md index 4c1ed23414fe..9d987e9158b1 100644 --- a/solution/2000-2099/2053.Kth Distinct String in an Array/README.md +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/README.md @@ -72,7 +72,11 @@ arr 中所有字符串都是独一无二的,所以返回第 1 个字符串 "aa -### 方法一 +### 方法一:哈希表 + 计数 + +我们可以用一个哈希表 $\textit{cnt}$ 记录每个字符串出现的次数,然后再遍历一次数组,对于每个字符串,如果它出现的次数为 $1$,那么就将 $k$ 减一,直到 $k$ 减为 $0$,返回当前字符串即可。 + +时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 为数组 $\textit{arr}$ 所有字符串的长度之和。 @@ -81,13 +85,13 @@ arr 中所有字符串都是独一无二的,所以返回第 1 个字符串 "aa ```python class Solution: def kthDistinct(self, arr: List[str], k: int) -> str: - counter = Counter(arr) - for v in arr: - if counter[v] == 1: + cnt = Counter(arr) + for s in arr: + if cnt[s] == 1: k -= 1 if k == 0: - return v - return '' + return s + return "" ``` #### Java @@ -95,16 +99,13 @@ class Solution: ```java class Solution { public String kthDistinct(String[] arr, int k) { - Map counter = new HashMap<>(); - for (String v : arr) { - counter.put(v, counter.getOrDefault(v, 0) + 1); + Map cnt = new HashMap<>(); + for (String s : arr) { + cnt.merge(s, 1, Integer::sum); } - for (String v : arr) { - if (counter.get(v) == 1) { - --k; - if (k == 0) { - return v; - } + for (String s : arr) { + if (cnt.get(s) == 1 && --k == 0) { + return s; } } return ""; @@ -118,12 +119,13 @@ class Solution { class Solution { public: string kthDistinct(vector& arr, int k) { - unordered_map counter; - for (auto& v : arr) ++counter[v]; - for (auto& v : arr) { - if (counter[v] == 1) { - --k; - if (k == 0) return v; + unordered_map cnt; + for (const auto& s : arr) { + ++cnt[s]; + } + for (const auto& s : arr) { + if (cnt[s] == 1 && --k == 0) { + return s; } } return ""; @@ -135,15 +137,15 @@ public: ```go func kthDistinct(arr []string, k int) string { - counter := make(map[string]int) - for _, v := range arr { - counter[v]++ + cnt := map[string]int{} + for _, s := range arr { + cnt[s]++ } - for _, v := range arr { - if counter[v] == 1 { + for _, s := range arr { + if cnt[s] == 1 { k-- if k == 0 { - return v + return s } } } @@ -151,6 +153,72 @@ func kthDistinct(arr []string, k int) string { } ``` +#### TypeScript + +```ts +function kthDistinct(arr: string[], k: number): string { + const cnt = new Map(); + for (const s of arr) { + cnt.set(s, (cnt.get(s) || 0) + 1); + } + for (const s of arr) { + if (cnt.get(s) === 1 && --k === 0) { + return s; + } + } + return ''; +} +``` + +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn kth_distinct(arr: Vec, mut k: i32) -> String { + let mut cnt = HashMap::new(); + + for s in &arr { + *cnt.entry(s).or_insert(0) += 1; + } + + for s in &arr { + if *cnt.get(s).unwrap() == 1 { + k -= 1; + if k == 0 { + return s.clone(); + } + } + } + + "".to_string() + } +} +``` + +#### JavaScript + +```js +/** + * @param {string[]} arr + * @param {number} k + * @return {string} + */ +var kthDistinct = function (arr, k) { + const cnt = new Map(); + for (const s of arr) { + cnt.set(s, (cnt.get(s) || 0) + 1); + } + for (const s of arr) { + if (cnt.get(s) === 1 && --k === 0) { + return s; + } + } + return ''; +}; +``` + diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/README_EN.md b/solution/2000-2099/2053.Kth Distinct String in an Array/README_EN.md index ed9fe534b1c1..a57e156b4e15 100644 --- a/solution/2000-2099/2053.Kth Distinct String in an Array/README_EN.md +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/README_EN.md @@ -73,7 +73,11 @@ The only distinct string is "b". Since there are fewer than 3 distinct -### Solution 1 +### Solution 1: Hash Table + Counting + +We can use a hash table $\textit{cnt}$ to record the number of occurrences of each string. Then, we traverse the array once more. For each string, if its occurrence count is $1$, we decrement $k$ by one. When $k$ reaches $0$, we return the current string. + +Time complexity is $O(L)$, and space complexity is $O(L)$, where $L$ is the total length of all strings in the array $\textit{arr}$. @@ -82,13 +86,13 @@ The only distinct string is "b". Since there are fewer than 3 distinct ```python class Solution: def kthDistinct(self, arr: List[str], k: int) -> str: - counter = Counter(arr) - for v in arr: - if counter[v] == 1: + cnt = Counter(arr) + for s in arr: + if cnt[s] == 1: k -= 1 if k == 0: - return v - return '' + return s + return "" ``` #### Java @@ -96,16 +100,13 @@ class Solution: ```java class Solution { public String kthDistinct(String[] arr, int k) { - Map counter = new HashMap<>(); - for (String v : arr) { - counter.put(v, counter.getOrDefault(v, 0) + 1); + Map cnt = new HashMap<>(); + for (String s : arr) { + cnt.merge(s, 1, Integer::sum); } - for (String v : arr) { - if (counter.get(v) == 1) { - --k; - if (k == 0) { - return v; - } + for (String s : arr) { + if (cnt.get(s) == 1 && --k == 0) { + return s; } } return ""; @@ -119,12 +120,13 @@ class Solution { class Solution { public: string kthDistinct(vector& arr, int k) { - unordered_map counter; - for (auto& v : arr) ++counter[v]; - for (auto& v : arr) { - if (counter[v] == 1) { - --k; - if (k == 0) return v; + unordered_map cnt; + for (const auto& s : arr) { + ++cnt[s]; + } + for (const auto& s : arr) { + if (cnt[s] == 1 && --k == 0) { + return s; } } return ""; @@ -136,15 +138,15 @@ public: ```go func kthDistinct(arr []string, k int) string { - counter := make(map[string]int) - for _, v := range arr { - counter[v]++ + cnt := map[string]int{} + for _, s := range arr { + cnt[s]++ } - for _, v := range arr { - if counter[v] == 1 { + for _, s := range arr { + if cnt[s] == 1 { k-- if k == 0 { - return v + return s } } } @@ -152,6 +154,72 @@ func kthDistinct(arr []string, k int) string { } ``` +#### TypeScript + +```ts +function kthDistinct(arr: string[], k: number): string { + const cnt = new Map(); + for (const s of arr) { + cnt.set(s, (cnt.get(s) || 0) + 1); + } + for (const s of arr) { + if (cnt.get(s) === 1 && --k === 0) { + return s; + } + } + return ''; +} +``` + +#### Rust + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn kth_distinct(arr: Vec, mut k: i32) -> String { + let mut cnt = HashMap::new(); + + for s in &arr { + *cnt.entry(s).or_insert(0) += 1; + } + + for s in &arr { + if *cnt.get(s).unwrap() == 1 { + k -= 1; + if k == 0 { + return s.clone(); + } + } + } + + "".to_string() + } +} +``` + +#### JavaScript + +```js +/** + * @param {string[]} arr + * @param {number} k + * @return {string} + */ +var kthDistinct = function (arr, k) { + const cnt = new Map(); + for (const s of arr) { + cnt.set(s, (cnt.get(s) || 0) + 1); + } + for (const s of arr) { + if (cnt.get(s) === 1 && --k === 0) { + return s; + } + } + return ''; +}; +``` + diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.cpp b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.cpp index b31ef8e13ea4..2cace2549e0d 100644 --- a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.cpp +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.cpp @@ -1,14 +1,15 @@ class Solution { public: string kthDistinct(vector& arr, int k) { - unordered_map counter; - for (auto& v : arr) ++counter[v]; - for (auto& v : arr) { - if (counter[v] == 1) { - --k; - if (k == 0) return v; + unordered_map cnt; + for (const auto& s : arr) { + ++cnt[s]; + } + for (const auto& s : arr) { + if (cnt[s] == 1 && --k == 0) { + return s; } } return ""; } -}; \ No newline at end of file +}; diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.go b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.go index 02116bc2cb0d..5ba5cfd3c1ff 100644 --- a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.go +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.go @@ -1,15 +1,15 @@ func kthDistinct(arr []string, k int) string { - counter := make(map[string]int) - for _, v := range arr { - counter[v]++ + cnt := map[string]int{} + for _, s := range arr { + cnt[s]++ } - for _, v := range arr { - if counter[v] == 1 { + for _, s := range arr { + if cnt[s] == 1 { k-- if k == 0 { - return v + return s } } } return "" -} \ No newline at end of file +} diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.java b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.java index ebf7e38bc007..fd70caa4067e 100644 --- a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.java +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.java @@ -1,17 +1,14 @@ class Solution { public String kthDistinct(String[] arr, int k) { - Map counter = new HashMap<>(); - for (String v : arr) { - counter.put(v, counter.getOrDefault(v, 0) + 1); + Map cnt = new HashMap<>(); + for (String s : arr) { + cnt.merge(s, 1, Integer::sum); } - for (String v : arr) { - if (counter.get(v) == 1) { - --k; - if (k == 0) { - return v; - } + for (String s : arr) { + if (cnt.get(s) == 1 && --k == 0) { + return s; } } return ""; } -} \ No newline at end of file +} diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.js b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.js new file mode 100644 index 000000000000..fa91e3f66587 --- /dev/null +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.js @@ -0,0 +1,17 @@ +/** + * @param {string[]} arr + * @param {number} k + * @return {string} + */ +var kthDistinct = function (arr, k) { + const cnt = new Map(); + for (const s of arr) { + cnt.set(s, (cnt.get(s) || 0) + 1); + } + for (const s of arr) { + if (cnt.get(s) === 1 && --k === 0) { + return s; + } + } + return ''; +}; diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.py b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.py index 3949ae806eff..171e56be193d 100644 --- a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.py +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.py @@ -1,9 +1,9 @@ class Solution: def kthDistinct(self, arr: List[str], k: int) -> str: - counter = Counter(arr) - for v in arr: - if counter[v] == 1: + cnt = Counter(arr) + for s in arr: + if cnt[s] == 1: k -= 1 if k == 0: - return v - return '' + return s + return "" diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.rs b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.rs new file mode 100644 index 000000000000..fc6885f2802e --- /dev/null +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.rs @@ -0,0 +1,22 @@ +use std::collections::HashMap; + +impl Solution { + pub fn kth_distinct(arr: Vec, mut k: i32) -> String { + let mut cnt = HashMap::new(); + + for s in &arr { + *cnt.entry(s).or_insert(0) += 1; + } + + for s in &arr { + if *cnt.get(s).unwrap() == 1 { + k -= 1; + if k == 0 { + return s.clone(); + } + } + } + + "".to_string() + } +} diff --git a/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.ts b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.ts new file mode 100644 index 000000000000..c9501b49a3fc --- /dev/null +++ b/solution/2000-2099/2053.Kth Distinct String in an Array/Solution.ts @@ -0,0 +1,12 @@ +function kthDistinct(arr: string[], k: number): string { + const cnt = new Map(); + for (const s of arr) { + cnt.set(s, (cnt.get(s) || 0) + 1); + } + for (const s of arr) { + if (cnt.get(s) === 1 && --k === 0) { + return s; + } + } + return ''; +} diff --git a/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README.md b/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README.md index c771acaebd79..227b49a7aea6 100644 --- a/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README.md +++ b/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README.md @@ -97,7 +97,7 @@ tags: ### 方法一:直接遍历 -根据题目描述,我们需要找出链表的第一个临界点和最后一个临界点位置 $\text{first}$ 和 $\text{last}$,这样可以计算出最大距离 $\text{maxDistance} = \text{last} - \text{first}$。对于最小距离 $\text{minDistance}$,我们需要遍历链表,计算相邻两个临界点之间的距离,取最小值即可。 +根据题目描述,我们需要找出链表的第一个临界点和最后一个临界点位置 $\textit{first}$ 和 $\textit{last}$,这样可以计算出最大距离 $\textit{maxDistance} = \textit{last} - \textit{first}$。对于最小距离 $\textit{minDistance}$,我们需要遍历链表,计算相邻两个临界点之间的距离,取最小值即可。 时间复杂度 $O(n)$,其中 $n$ 是链表的长度。空间复杂度 $O(1)$。 diff --git a/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README_EN.md b/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README_EN.md index 1675eed3844c..e88b1ec8718b 100644 --- a/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README_EN.md +++ b/solution/2000-2099/2058.Find the Minimum and Maximum Number of Nodes Between Critical Points/README_EN.md @@ -79,7 +79,7 @@ Note that the last node is not considered a local maxima because it does not hav ### Solution 1: Direct Traversal -Based on the problem description, we need to find the positions of the first and last critical points in the linked list, $\text{first}$ and $\text{last}$, respectively. This allows us to calculate the maximum distance $\text{maxDistance} = \text{last} - \text{first}$. For the minimum distance $\text{minDistance}$, we need to traverse the linked list, calculate the distance between two adjacent critical points, and take the minimum value. +Based on the problem description, we need to find the positions of the first and last critical points in the linked list, $\textit{first}$ and $\textit{last}$, respectively. This allows us to calculate the maximum distance $\textit{maxDistance} = \textit{last} - \textit{first}$. For the minimum distance $\textit{minDistance}$, we need to traverse the linked list, calculate the distance between two adjacent critical points, and take the minimum value. The time complexity is $O(n)$, where $n$ is the length of the linked list. The space complexity is $O(1)$. diff --git a/solution/2000-2099/2065.Maximum Path Quality of a Graph/README.md b/solution/2000-2099/2065.Maximum Path Quality of a Graph/README.md index 1d43c5a7acd3..8fdfc6e964d9 100644 --- a/solution/2000-2099/2065.Maximum Path Quality of a Graph/README.md +++ b/solution/2000-2099/2065.Maximum Path Quality of a Graph/README.md @@ -102,20 +102,20 @@ tags: ### 方法一:DFS -我们观察题目的数据范围,可以发现从 $0$ 开始的每条合法路径的边数不超过 $\frac{\text{maxTime}}{\min(time_j)} = \frac{100}{10} = 10$ 条,并且每个节点至多有四条边,所以我们可以直接使用朴素的 DFS 暴力搜索所有合法路径。 +我们观察题目的数据范围,可以发现从 $0$ 开始的每条合法路径的边数不超过 $\frac{\textit{maxTime}}{\min(time_j)} = \frac{100}{10} = 10$ 条,并且每个节点至多有四条边,所以我们可以直接使用朴素的 DFS 暴力搜索所有合法路径。 -我们先将图的边存储在邻接表表 $g$ 中,然后我们设计一个函数 $\text{dfs}(u, \text{cost}, \text{value})$,其中 $u$ 表示当前节点编号,而 $\text{cost}$ 和 $\text{value}$ 分别表示当前路径的花费时间和价值。另外,使用一个长度为 $n$ 的数组 $\text{vis}$ 记录每个节点是否被访问过。初始时,我们将节点 $0$ 标记为已访问。 +我们先将图的边存储在邻接表表 $g$ 中,然后我们设计一个函数 $\textit{dfs}(u, \textit{cost}, \textit{value})$,其中 $u$ 表示当前节点编号,而 $\textit{cost}$ 和 $\textit{value}$ 分别表示当前路径的花费时间和价值。另外,使用一个长度为 $n$ 的数组 $\textit{vis}$ 记录每个节点是否被访问过。初始时,我们将节点 $0$ 标记为已访问。 -函数 $\text{dfs}(u, \text{cost}, \text{value})$ 的逻辑如下: +函数 $\textit{dfs}(u, \textit{cost}, \textit{value})$ 的逻辑如下: -- 如果当前节点编号 $u$ 等于 $0$,表示我们已经回到了起点,那么我们更新答案为 $\max(\text{ans}, \text{value})$; -- 遍历当前节点 $u$ 的所有邻居节点 $v$,如果当前路径的花费时间加上边 $(u, v)$ 的时间 $t$ 不超过 $\text{maxTime}$,那么我们可以选择继续访问节点 $v$; - - 如果节点 $v$ 已经被访问过,那么我们直接递归调用 $\text{dfs}(v, \text{cost} + t, \text{value})$; - - 如果节点 $v$ 没有被访问过,我们标记节点 $v$ 为已访问,然后递归调用 $\text{dfs}(v, \text{cost} + t, \text{value} + \text{values}[v])$,最后恢复节点 $v$ 的访问状态。 +- 如果当前节点编号 $u$ 等于 $0$,表示我们已经回到了起点,那么我们更新答案为 $\max(\textit{ans}, \textit{value})$; +- 遍历当前节点 $u$ 的所有邻居节点 $v$,如果当前路径的花费时间加上边 $(u, v)$ 的时间 $t$ 不超过 $\textit{maxTime}$,那么我们可以选择继续访问节点 $v$; + - 如果节点 $v$ 已经被访问过,那么我们直接递归调用 $\textit{dfs}(v, \textit{cost} + t, \textit{value})$; + - 如果节点 $v$ 没有被访问过,我们标记节点 $v$ 为已访问,然后递归调用 $\textit{dfs}(v, \textit{cost} + t, \textit{value} + \textit{values}[v])$,最后恢复节点 $v$ 的访问状态。 -在主函数中,我们调用 $\text{dfs}(0, 0, \text{values}[0])$,并返回答案 $\text{ans}$ 即可。 +在主函数中,我们调用 $\textit{dfs}(0, 0, \textit{values}[0])$,并返回答案 $\textit{ans}$ 即可。 -时间复杂度 $O(n + m + 4^{\frac{\text{maxTime}}{\min(time_j)}})$,空间复杂度 $O(n + m + \frac{\text{maxTime}}{\min(time_j)})$。其中 $n$ 和 $m$ 分别表示节点数和边数。 +时间复杂度 $O(n + m + 4^{\frac{\textit{maxTime}}{\min(time_j)}})$,空间复杂度 $O(n + m + \frac{\textit{maxTime}}{\min(time_j)})$。其中 $n$ 和 $m$ 分别表示节点数和边数。 diff --git a/solution/2000-2099/2065.Maximum Path Quality of a Graph/README_EN.md b/solution/2000-2099/2065.Maximum Path Quality of a Graph/README_EN.md index 65daca6cdcbc..7597aa91d9b9 100644 --- a/solution/2000-2099/2065.Maximum Path Quality of a Graph/README_EN.md +++ b/solution/2000-2099/2065.Maximum Path Quality of a Graph/README_EN.md @@ -83,20 +83,20 @@ The nodes visited are 0, 1, and 3, giving a maximal path quality of 1 + 2 + 4 = ### Solution 1: DFS -We observe the data range of the problem and find that the number of edges in each valid path starting from $0$ does not exceed $\frac{\text{maxTime}}{\min(time_j)} = \frac{100}{10} = 10$, and each node has at most four edges. Therefore, we can directly use naive DFS to brute-force search all valid paths. +We observe the data range of the problem and find that the number of edges in each valid path starting from $0$ does not exceed $\frac{\textit{maxTime}}{\min(time_j)} = \frac{100}{10} = 10$, and each node has at most four edges. Therefore, we can directly use naive DFS to brute-force search all valid paths. -First, we store the edges of the graph in the adjacency list $g$. Then, we design a function $\text{dfs}(u, \text{cost}, \text{value})$, where $u$ represents the current node number, and $\text{cost}$ and $\text{value}$ respectively represent the cost time and value of the current path. Additionally, we use an array $\text{vis}$ of length $n$ to record whether each node has been visited. Initially, we mark node $0$ as visited. +First, we store the edges of the graph in the adjacency list $g$. Then, we design a function $\textit{dfs}(u, \textit{cost}, \textit{value})$, where $u$ represents the current node number, and $\textit{cost}$ and $\textit{value}$ respectively represent the cost time and value of the current path. Additionally, we use an array $\textit{vis}$ of length $n$ to record whether each node has been visited. Initially, we mark node $0$ as visited. -The logic of the function $\text{dfs}(u, \text{cost}, \text{value})$ is as follows: +The logic of the function $\textit{dfs}(u, \textit{cost}, \textit{value})$ is as follows: -- If the current node number $u$ equals $0$, it means we have returned to the starting point, so we update the answer to $\max(\text{ans}, \text{value})$; -- For each neighbor node $v$ of the current node $u$, if the current path's cost time plus the time $t$ of the edge $(u, v)$ does not exceed $\text{maxTime}$, then we can choose to continue visiting node $v$; - - If node $v$ has already been visited, we directly recursively call $\text{dfs}(v, \text{cost} + t, \text{value})$; - - If node $v$ has not been visited, we mark node $v$ as visited, then recursively call $\text{dfs}(v, \text{cost} + t, \text{value} + \text{values}[v])$, and finally restore the visit status of node $v$. +- If the current node number $u$ equals $0$, it means we have returned to the starting point, so we update the answer to $\max(\textit{ans}, \textit{value})$; +- For each neighbor node $v$ of the current node $u$, if the current path's cost time plus the time $t$ of the edge $(u, v)$ does not exceed $\textit{maxTime}$, then we can choose to continue visiting node $v$; + - If node $v$ has already been visited, we directly recursively call $\textit{dfs}(v, \textit{cost} + t, \textit{value})$; + - If node $v$ has not been visited, we mark node $v$ as visited, then recursively call $\textit{dfs}(v, \textit{cost} + t, \textit{value} + \textit{values}[v])$, and finally restore the visit status of node $v$. -In the main function, we call $\text{dfs}(0, 0, \text{values}[0])$ and return the answer $\text{ans}$. +In the main function, we call $\textit{dfs}(0, 0, \textit{values}[0])$ and return the answer $\textit{ans}$. -The time complexity is $O(n + m + 4^{\frac{\text{maxTime}}{\min(time_j)}})$, and the space complexity is $O(n + m + \frac{\text{maxTime}}{\min(time_j)})$. Here, $n$ and $m$ respectively represent the number of nodes and edges. +The time complexity is $O(n + m + 4^{\frac{\textit{maxTime}}{\min(time_j)}})$, and the space complexity is $O(n + m + \frac{\textit{maxTime}}{\min(time_j)})$. Here, $n$ and $m$ respectively represent the number of nodes and edges. diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md b/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md index 4b7367038f07..270790dde6a7 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/README.md @@ -71,7 +71,7 @@ tags: 根据题目描述,当第 $k$ 个人完成购票时,在第 $k$ 个人前面的所有人,购买的票数都不会超过第 $k$ 个人购买的票数,而在第 $k$ 个人后面的所有人,购买的票数都不会超过第 $k$ 个人购买的票数减 $1$。 -因此,我们可以遍历整个队伍,对于第 $i$ 个人,如果 $i \leq k$,购票时间为 $\min(\text{tickets}[i], \text{tickets}[k])$,否则购票时间为 $\min(\text{tickets}[i], \text{tickets}[k] - 1)$。我们将所有人的购票时间相加即可。 +因此,我们可以遍历整个队伍,对于第 $i$ 个人,如果 $i \leq k$,购票时间为 $\min(\textit{tickets}[i], \textit{tickets}[k])$,否则购票时间为 $\min(\textit{tickets}[i], \textit{tickets}[k] - 1)$。我们将所有人的购票时间相加即可。 时间复杂度 $O(n)$,其中 $n$ 为队伍的长度。空间复杂度 $O(1)$。 diff --git a/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md b/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md index ef0f47936e57..1a6e414d287f 100644 --- a/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md +++ b/solution/2000-2099/2073.Time Needed to Buy Tickets/README_EN.md @@ -71,7 +71,7 @@ The person at position 0 has successfully bought 5 tickets and it took 4 + According to the problem description, when the $k^{th}$ person finishes buying tickets, all the people in front of the $k^{th}$ person will not buy more tickets than the $k^{th}$ person, and all the people behind the $k^{th}$ person will not buy more tickets than the $k^{th}$ person minus $1$. -Therefore, we can traverse the entire queue. For the $i^{th}$ person, if $i \leq k$, the time to buy tickets is $\min(\text{tickets}[i], \text{tickets}[k])$; otherwise, the time to buy tickets is $\min(\text{tickets}[i], \text{tickets}[k] - 1)$. We sum the buying time for all people to get the result. +Therefore, we can traverse the entire queue. For the $i^{th}$ person, if $i \leq k$, the time to buy tickets is $\min(\textit{tickets}[i], \textit{tickets}[k])$; otherwise, the time to buy tickets is $\min(\textit{tickets}[i], \textit{tickets}[k] - 1)$. We sum the buying time for all people to get the result. The time complexity is $O(n)$, where $n$ is the length of the queue. The space complexity is $O(1)$. diff --git a/solution/2000-2099/2075.Decode the Slanted Ciphertext/README.md b/solution/2000-2099/2075.Decode the Slanted Ciphertext/README.md index b8f28226ae24..f3f9ebd38534 100644 --- a/solution/2000-2099/2075.Decode the Slanted Ciphertext/README.md +++ b/solution/2000-2099/2075.Decode the Slanted Ciphertext/README.md @@ -96,7 +96,7 @@ tags: ### 方法一:模拟 -我们先计算出矩阵的列数 $cols = \text{len}(encodedText) / rows$,然后按照题目描述的规则,从左上角开始遍历矩阵,将字符添加到答案中。 +我们先计算出矩阵的列数 $cols = \textit{len}(encodedText) / rows$,然后按照题目描述的规则,从左上角开始遍历矩阵,将字符添加到答案中。 最后返回答案,注意去掉末尾的空格。 diff --git a/solution/2000-2099/2075.Decode the Slanted Ciphertext/README_EN.md b/solution/2000-2099/2075.Decode the Slanted Ciphertext/README_EN.md index 551264b06d6b..df7a604d70d6 100644 --- a/solution/2000-2099/2075.Decode the Slanted Ciphertext/README_EN.md +++ b/solution/2000-2099/2075.Decode the Slanted Ciphertext/README_EN.md @@ -82,7 +82,7 @@ The blue arrows show how we can find originalText from encodedText. ### Solution 1: Simulation -First, we calculate the number of columns in the matrix $cols = \text{len}(encodedText) / rows$. Then, following the rules described in the problem, we start traversing the matrix from the top left corner, adding characters to the answer. +First, we calculate the number of columns in the matrix $cols = \textit{len}(encodedText) / rows$. Then, following the rules described in the problem, we start traversing the matrix from the top left corner, adding characters to the answer. Finally, we return the answer, making sure to remove any trailing spaces. diff --git a/solution/2000-2099/2079.Watering Plants/README.md b/solution/2000-2099/2079.Watering Plants/README.md index 68eaa9001400..9406d7e023c3 100644 --- a/solution/2000-2099/2079.Watering Plants/README.md +++ b/solution/2000-2099/2079.Watering Plants/README.md @@ -90,12 +90,12 @@ tags: ### 方法一:模拟 -我们可以模拟给植物浇水的过程,用一个变量 $\text{water}$ 表示当前水罐中的水量,初始时 $\text{water} = \text{capacity}$。 +我们可以模拟给植物浇水的过程,用一个变量 $\textit{water}$ 表示当前水罐中的水量,初始时 $\textit{water} = \textit{capacity}$。 我们遍历植物,对于每一株植物: -- 如果当前水罐中的水量足够浇灌这株植物,我们就向前移动一步,浇灌这株植物,同时更新 $\text{water} = \text{water} - \text{plants}[i]$。 -- 否则我们就需要返回河边重新装满水罐,再次走到当前位置,然后向前移动一步,此时我们需要的步数为 $i \times 2 + 1$,然后我们浇灌这株植物,更新 $\text{water} = \text{capacity} - \text{plants}[i]$。 +- 如果当前水罐中的水量足够浇灌这株植物,我们就向前移动一步,浇灌这株植物,同时更新 $\textit{water} = \textit{water} - \textit{plants}[i]$。 +- 否则我们就需要返回河边重新装满水罐,再次走到当前位置,然后向前移动一步,此时我们需要的步数为 $i \times 2 + 1$,然后我们浇灌这株植物,更新 $\textit{water} = \textit{capacity} - \textit{plants}[i]$。 最后返回总的步数即可。 diff --git a/solution/2000-2099/2079.Watering Plants/README_EN.md b/solution/2000-2099/2079.Watering Plants/README_EN.md index 7bb0ed125688..7eb2ffb0dc80 100644 --- a/solution/2000-2099/2079.Watering Plants/README_EN.md +++ b/solution/2000-2099/2079.Watering Plants/README_EN.md @@ -89,12 +89,12 @@ Steps needed = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 + 6 + 6 + 7 = 49. ### Solution 1: Simulation -We can simulate the process of watering the plants. We use a variable $\text{water}$ to represent the current amount of water in the watering can, initially $\text{water} = \text{capacity}$. +We can simulate the process of watering the plants. We use a variable $\textit{water}$ to represent the current amount of water in the watering can, initially $\textit{water} = \textit{capacity}$. We traverse the plants. For each plant: -- If the current amount of water in the watering can is enough to water this plant, we move forward one step, water this plant, and update $\text{water} = \text{water} - \text{plants}[i]$. -- Otherwise, we need to return to the river to refill the watering can, walk back to the current position, and then move forward one step. The number of steps we need is $i \times 2 + 1$. Then we water this plant and update $\text{water} = \text{capacity} - \text{plants}[i]$. +- If the current amount of water in the watering can is enough to water this plant, we move forward one step, water this plant, and update $\textit{water} = \textit{water} - \textit{plants}[i]$. +- Otherwise, we need to return to the river to refill the watering can, walk back to the current position, and then move forward one step. The number of steps we need is $i \times 2 + 1$. Then we water this plant and update $\textit{water} = \textit{capacity} - \textit{plants}[i]$. Finally, return the total number of steps. diff --git a/solution/2000-2099/2080.Range Frequency Queries/README.md b/solution/2000-2099/2080.Range Frequency Queries/README.md index 24521896eaa0..3e5f7b21a2f5 100644 --- a/solution/2000-2099/2080.Range Frequency Queries/README.md +++ b/solution/2000-2099/2080.Range Frequency Queries/README.md @@ -70,9 +70,9 @@ rangeFreqQuery.query(0, 11, 33); // 返回 2 。33 在整个子数组中出现 2 ### 方法一:哈希表 -我们用一个哈希表 $g$ 来存储每个值对应的下标数组。在构造函数中,我们遍历数组 $\text{arr}$,将每个值对应的下标加入到哈希表中。 +我们用一个哈希表 $g$ 来存储每个值对应的下标数组。在构造函数中,我们遍历数组 $\textit{arr}$,将每个值对应的下标加入到哈希表中。 -在查询函数中,我们首先判断哈希表中是否存在给定的值。如果不存在,说明该值在数组中不存在,直接返回 $0$。否则,我们获取该值对应的下标数组 $\text{idx}$。然后我们使用二分查找找到下标数组中第一个大于等于 $\text{left}$ 的下标 $l$,以及第一个大于 $\text{right}$ 的下标 $r$。最后返回 $r - l$ 即可。 +在查询函数中,我们首先判断哈希表中是否存在给定的值。如果不存在,说明该值在数组中不存在,直接返回 $0$。否则,我们获取该值对应的下标数组 $\textit{idx}$。然后我们使用二分查找找到下标数组中第一个大于等于 $\textit{left}$ 的下标 $l$,以及第一个大于 $\textit{right}$ 的下标 $r$。最后返回 $r - l$ 即可。 时间复杂度方面,构造函数的时间复杂度为 $O(n)$,查询函数的时间复杂度为 $O(\log n)$。其中 $n$ 为数组的长度。空间复杂度为 $O(n)$。 diff --git a/solution/2000-2099/2080.Range Frequency Queries/README_EN.md b/solution/2000-2099/2080.Range Frequency Queries/README_EN.md index 66309cc1300a..7945cfe3ed4e 100644 --- a/solution/2000-2099/2080.Range Frequency Queries/README_EN.md +++ b/solution/2000-2099/2080.Range Frequency Queries/README_EN.md @@ -69,9 +69,9 @@ rangeFreqQuery.query(0, 11, 33); // return 2. The value 33 occurs 2 times in the ### Solution 1: Hash Table -We use a hash table $g$ to store the array of indices corresponding to each value. In the constructor, we traverse the array $\text{arr}$, adding the index corresponding to each value to the hash table. +We use a hash table $g$ to store the array of indices corresponding to each value. In the constructor, we traverse the array $\textit{arr}$, adding the index corresponding to each value to the hash table. -In the query function, we first check whether the given value exists in the hash table. If it does not exist, it means that the value does not exist in the array, so we directly return $0$. Otherwise, we get the index array $\text{idx}$ corresponding to the value. Then we use binary search to find the first index $l$ that is greater than or equal to $\text{left}$, and the first index $r$ that is greater than $\text{right}$. Finally, we return $r - l$. +In the query function, we first check whether the given value exists in the hash table. If it does not exist, it means that the value does not exist in the array, so we directly return $0$. Otherwise, we get the index array $\textit{idx}$ corresponding to the value. Then we use binary search to find the first index $l$ that is greater than or equal to $\textit{left}$, and the first index $r$ that is greater than $\textit{right}$. Finally, we return $r - l$. In terms of time complexity, the time complexity of the constructor is $O(n)$, and the time complexity of the query function is $O(\log n)$. The space complexity is $O(n)$. Where $n$ is the length of the array. diff --git a/solution/2000-2099/2088.Count Fertile Pyramids in a Land/README.md b/solution/2000-2099/2088.Count Fertile Pyramids in a Land/README.md index 7cecc25f4b6d..932d9f5c69d4 100644 --- a/solution/2000-2099/2088.Count Fertile Pyramids in a Land/README.md +++ b/solution/2000-2099/2088.Count Fertile Pyramids in a Land/README.md @@ -112,7 +112,7 @@ tags: 我们定义 $f[i][j]$ 表示以 $(i, j)$ 为顶点的金字塔的最大高度,那么有如下状态转移方程: $$ -f[i][j] = \begin{cases} 0 & \text{grid}[i][j] = 0 \\ \min(f[i + 1][j - 1], f[i + 1][j], f[i + 1][j + 1]) + 1 & \text{grid}[i][j] = 1 \end{cases} +f[i][j] = \begin{cases} 0 & \textit{grid}[i][j] = 0 \\ \min(f[i + 1][j - 1], f[i + 1][j], f[i + 1][j + 1]) + 1 & \textit{grid}[i][j] = 1 \end{cases} $$ 因此,我们可以从下往上、从左往右遍历网格,计算出所有的 $f[i][j]$,并累加所有的 $f[i][j]$ 即可得到正金字塔的个数。 @@ -120,7 +120,7 @@ $$ 接下来,我们考虑倒金字塔的个数。与金字塔类似,我们定义 $g[i][j]$ 表示以 $(i, j)$ 为顶点的倒金字塔的最大高度,那么有如下状态转移方程: $$ -g[i][j] = \begin{cases} 0 & \text{grid}[i][j] = 0 \\ \min(g[i - 1][j - 1], g[i - 1][j], g[i - 1][j + 1]) + 1 & \text{grid}[i][j] = 1 \end{cases} +g[i][j] = \begin{cases} 0 & \textit{grid}[i][j] = 0 \\ \min(g[i - 1][j - 1], g[i - 1][j], g[i - 1][j + 1]) + 1 & \textit{grid}[i][j] = 1 \end{cases} $$ 因此,我们可以从上往下、从左往右遍历网格,计算出所有的 $g[i][j]$,并累加所有的 $g[i][j]$ 即可得到倒金字塔的个数。 diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README.md b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README.md index d0f756c1a57a..008460230c35 100644 --- a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README.md +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README.md @@ -80,7 +80,15 @@ tags: -### 方法一 +### 方法一:计数 + 枚举 + +我们先统计 $\textit{digits}$ 中每个数字出现的次数,记录在数组或哈希表 $\textit{cnt}$ 中。 + +然后,我们在 $[100, 1000)$ 的范围内枚举所有的偶数,判断这个偶数的每一位数字是否都不超过 $\textit{cnt}$ 中对应的数字的次数。如果是,则将这个偶数加入答案数组中。 + +最后,返回答案数组。 + +时间复杂度 $O(k \times 10^k)$,其中 $k$ 是目标偶数的位数,本题中 $k = 3$。忽略答案的空间消耗,空间复杂度 $O(1)$。 @@ -89,17 +97,16 @@ tags: ```python class Solution: def findEvenNumbers(self, digits: List[int]) -> List[int]: + cnt = Counter(digits) ans = [] - counter = Counter(digits) - for i in range(100, 1000, 2): - t = [] - k = i - while k: - t.append(k % 10) - k //= 10 - cnt = Counter(t) - if all([counter[i] >= cnt[i] for i in range(10)]): - ans.append(i) + for x in range(100, 1000, 2): + cnt1 = Counter() + y = x + while y: + y, v = divmod(y, 10) + cnt1[v] += 1 + if all(cnt[i] >= cnt1[i] for i in range(10)): + ans.append(x) return ans ``` @@ -108,37 +115,25 @@ class Solution: ```java class Solution { public int[] findEvenNumbers(int[] digits) { - int[] counter = count(digits); + int[] cnt = new int[10]; + for (int x : digits) { + ++cnt[x]; + } List ans = new ArrayList<>(); - for (int i = 100; i < 1000; i += 2) { - int[] t = new int[3]; - for (int j = 0, k = i; k > 0; ++j) { - t[j] = k % 10; - k /= 10; + for (int x = 100; x < 1000; x += 2) { + int[] cnt1 = new int[10]; + for (int y = x; y > 0; y /= 10) { + ++cnt1[y % 10]; } - int[] cnt = count(t); - if (check(counter, cnt)) { - ans.add(i); + boolean ok = true; + for (int i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; } - } - return ans.stream().mapToInt(Integer::valueOf).toArray(); - } - - private boolean check(int[] cnt1, int[] cnt2) { - for (int i = 0; i < 10; ++i) { - if (cnt1[i] < cnt2[i]) { - return false; + if (ok) { + ans.add(x); } } - return true; - } - - private int[] count(int[] nums) { - int[] counter = new int[10]; - for (int num : nums) { - ++counter[num]; - } - return counter; + return ans.stream().mapToInt(i -> i).toArray(); } } ``` @@ -149,71 +144,51 @@ class Solution { class Solution { public: vector findEvenNumbers(vector& digits) { - vector counter = count(digits); + int cnt[10]{}; + for (int x : digits) { + ++cnt[x]; + } vector ans; - for (int i = 100; i < 1000; i += 2) { - vector t(3); - for (int j = 0, k = i; k > 0; ++j) { - t[j] = k % 10; - k /= 10; + for (int x = 100; x < 1000; x += 2) { + int cnt1[10]{}; + for (int y = x; y; y /= 10) { + ++cnt1[y % 10]; + } + bool ok = true; + for (int i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push_back(x); } - vector cnt = count(t); - if (check(counter, cnt)) ans.push_back(i); } return ans; } - - vector count(vector& nums) { - vector counter(10); - for (int num : nums) ++counter[num]; - return counter; - } - - bool check(vector& cnt1, vector& cnt2) { - for (int i = 0; i < 10; ++i) - if (cnt1[i] < cnt2[i]) - return false; - return true; - } }; ``` #### Go ```go -func findEvenNumbers(digits []int) []int { - counter := count(digits) - var ans []int - for i := 100; i < 1000; i += 2 { - t := make([]int, 3) - k := i - for j := 0; k > 0; j++ { - t[j] = k % 10 - k /= 10 +func findEvenNumbers(digits []int) (ans []int) { + cnt := [10]int{} + for _, x := range digits { + cnt[x]++ + } + for x := 100; x < 1000; x += 2 { + cnt1 := [10]int{} + for y := x; y > 0; y /= 10 { + cnt1[y%10]++ } - cnt := count(t) - if check(counter, cnt) { - ans = append(ans, i) + ok := true + for i := 0; i < 10 && ok; i++ { + ok = cnt[i] >= cnt1[i] } - } - return ans -} - -func count(nums []int) []int { - counter := make([]int, 10) - for _, num := range nums { - counter[num]++ - } - return counter -} - -func check(cnt1, cnt2 []int) bool { - for i := 0; i < 10; i++ { - if cnt1[i] < cnt2[i] { - return false + if ok { + ans = append(ans, x) } } - return true + return } ``` @@ -221,30 +196,56 @@ func check(cnt1, cnt2 []int) bool { ```ts function findEvenNumbers(digits: number[]): number[] { - let record = new Array(10).fill(0); - for (let digit of digits) { - record[digit]++; + const cnt: number[] = Array(10).fill(0); + for (const x of digits) { + ++cnt[x]; } - let ans = []; - for (let i = 100; i < 1000; i += 2) { - if (check(record, String(i))) { - ans.push(i); + const ans: number[] = []; + for (let x = 100; x < 1000; x += 2) { + const cnt1: number[] = Array(10).fill(0); + for (let y = x; y; y = Math.floor(y / 10)) { + ++cnt1[y % 10]; + } + let ok = true; + for (let i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push(x); } } return ans; } +``` -function check(target: Array, digits: string): boolean { - let record = new Array(10).fill(0); - for (let digit of digits) { - record[digit]++; +#### JavaScript + +```js +/** + * @param {number[]} digits + * @return {number[]} + */ +var findEvenNumbers = function (digits) { + const cnt = Array(10).fill(0); + for (const x of digits) { + ++cnt[x]; } - - for (let i = 0; i < 10; i++) { - if (record[i] > target[i]) return false; + const ans = []; + for (let x = 100; x < 1000; x += 2) { + const cnt1 = Array(10).fill(0); + for (let y = x; y; y = Math.floor(y / 10)) { + ++cnt1[y % 10]; + } + let ok = true; + for (let i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push(x); + } } - return true; -} + return ans; +}; ``` diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README_EN.md b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README_EN.md index ee8e5f560b6f..fb7079434fd7 100644 --- a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README_EN.md +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/README_EN.md @@ -76,7 +76,15 @@ In this example, the digit 8 is used twice each time in 288, 828, and 882. -### Solution 1 +### Solution 1: Counting + Enumeration + +First, we count the occurrence of each digit in $\textit{digits}$, recording it in an array or hash table $\textit{cnt}$. + +Then, we enumerate all even numbers in the range $[100, 1000)$, checking if each digit of the even number does not exceed the corresponding digit's count in $\textit{cnt}$. If so, we add this even number to the answer array. + +Finally, we return the answer array. + +The time complexity is $O(k \times 10^k)$, where $k$ is the number of digits of the target even number, which is $3$ in this problem. Ignoring the space consumed by the answer, the space complexity is $O(1)$. @@ -85,17 +93,16 @@ In this example, the digit 8 is used twice each time in 288, 828, and 882. ```python class Solution: def findEvenNumbers(self, digits: List[int]) -> List[int]: + cnt = Counter(digits) ans = [] - counter = Counter(digits) - for i in range(100, 1000, 2): - t = [] - k = i - while k: - t.append(k % 10) - k //= 10 - cnt = Counter(t) - if all([counter[i] >= cnt[i] for i in range(10)]): - ans.append(i) + for x in range(100, 1000, 2): + cnt1 = Counter() + y = x + while y: + y, v = divmod(y, 10) + cnt1[v] += 1 + if all(cnt[i] >= cnt1[i] for i in range(10)): + ans.append(x) return ans ``` @@ -104,37 +111,25 @@ class Solution: ```java class Solution { public int[] findEvenNumbers(int[] digits) { - int[] counter = count(digits); + int[] cnt = new int[10]; + for (int x : digits) { + ++cnt[x]; + } List ans = new ArrayList<>(); - for (int i = 100; i < 1000; i += 2) { - int[] t = new int[3]; - for (int j = 0, k = i; k > 0; ++j) { - t[j] = k % 10; - k /= 10; + for (int x = 100; x < 1000; x += 2) { + int[] cnt1 = new int[10]; + for (int y = x; y > 0; y /= 10) { + ++cnt1[y % 10]; } - int[] cnt = count(t); - if (check(counter, cnt)) { - ans.add(i); + boolean ok = true; + for (int i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; } - } - return ans.stream().mapToInt(Integer::valueOf).toArray(); - } - - private boolean check(int[] cnt1, int[] cnt2) { - for (int i = 0; i < 10; ++i) { - if (cnt1[i] < cnt2[i]) { - return false; + if (ok) { + ans.add(x); } } - return true; - } - - private int[] count(int[] nums) { - int[] counter = new int[10]; - for (int num : nums) { - ++counter[num]; - } - return counter; + return ans.stream().mapToInt(i -> i).toArray(); } } ``` @@ -145,71 +140,51 @@ class Solution { class Solution { public: vector findEvenNumbers(vector& digits) { - vector counter = count(digits); + int cnt[10]{}; + for (int x : digits) { + ++cnt[x]; + } vector ans; - for (int i = 100; i < 1000; i += 2) { - vector t(3); - for (int j = 0, k = i; k > 0; ++j) { - t[j] = k % 10; - k /= 10; + for (int x = 100; x < 1000; x += 2) { + int cnt1[10]{}; + for (int y = x; y; y /= 10) { + ++cnt1[y % 10]; + } + bool ok = true; + for (int i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push_back(x); } - vector cnt = count(t); - if (check(counter, cnt)) ans.push_back(i); } return ans; } - - vector count(vector& nums) { - vector counter(10); - for (int num : nums) ++counter[num]; - return counter; - } - - bool check(vector& cnt1, vector& cnt2) { - for (int i = 0; i < 10; ++i) - if (cnt1[i] < cnt2[i]) - return false; - return true; - } }; ``` #### Go ```go -func findEvenNumbers(digits []int) []int { - counter := count(digits) - var ans []int - for i := 100; i < 1000; i += 2 { - t := make([]int, 3) - k := i - for j := 0; k > 0; j++ { - t[j] = k % 10 - k /= 10 +func findEvenNumbers(digits []int) (ans []int) { + cnt := [10]int{} + for _, x := range digits { + cnt[x]++ + } + for x := 100; x < 1000; x += 2 { + cnt1 := [10]int{} + for y := x; y > 0; y /= 10 { + cnt1[y%10]++ } - cnt := count(t) - if check(counter, cnt) { - ans = append(ans, i) + ok := true + for i := 0; i < 10 && ok; i++ { + ok = cnt[i] >= cnt1[i] } - } - return ans -} - -func count(nums []int) []int { - counter := make([]int, 10) - for _, num := range nums { - counter[num]++ - } - return counter -} - -func check(cnt1, cnt2 []int) bool { - for i := 0; i < 10; i++ { - if cnt1[i] < cnt2[i] { - return false + if ok { + ans = append(ans, x) } } - return true + return } ``` @@ -217,30 +192,56 @@ func check(cnt1, cnt2 []int) bool { ```ts function findEvenNumbers(digits: number[]): number[] { - let record = new Array(10).fill(0); - for (let digit of digits) { - record[digit]++; + const cnt: number[] = Array(10).fill(0); + for (const x of digits) { + ++cnt[x]; } - let ans = []; - for (let i = 100; i < 1000; i += 2) { - if (check(record, String(i))) { - ans.push(i); + const ans: number[] = []; + for (let x = 100; x < 1000; x += 2) { + const cnt1: number[] = Array(10).fill(0); + for (let y = x; y; y = Math.floor(y / 10)) { + ++cnt1[y % 10]; + } + let ok = true; + for (let i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push(x); } } return ans; } +``` -function check(target: Array, digits: string): boolean { - let record = new Array(10).fill(0); - for (let digit of digits) { - record[digit]++; +#### JavaScript + +```js +/** + * @param {number[]} digits + * @return {number[]} + */ +var findEvenNumbers = function (digits) { + const cnt = Array(10).fill(0); + for (const x of digits) { + ++cnt[x]; } - - for (let i = 0; i < 10; i++) { - if (record[i] > target[i]) return false; + const ans = []; + for (let x = 100; x < 1000; x += 2) { + const cnt1 = Array(10).fill(0); + for (let y = x; y; y = Math.floor(y / 10)) { + ++cnt1[y % 10]; + } + let ok = true; + for (let i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push(x); + } } - return true; -} + return ans; +}; ``` diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.cpp b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.cpp index eb6290978853..8dc6cd3cd995 100644 --- a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.cpp +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.cpp @@ -1,30 +1,24 @@ class Solution { public: vector findEvenNumbers(vector& digits) { - vector counter = count(digits); + int cnt[10]{}; + for (int x : digits) { + ++cnt[x]; + } vector ans; - for (int i = 100; i < 1000; i += 2) { - vector t(3); - for (int j = 0, k = i; k > 0; ++j) { - t[j] = k % 10; - k /= 10; + for (int x = 100; x < 1000; x += 2) { + int cnt1[10]{}; + for (int y = x; y; y /= 10) { + ++cnt1[y % 10]; + } + bool ok = true; + for (int i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push_back(x); } - vector cnt = count(t); - if (check(counter, cnt)) ans.push_back(i); } return ans; } - - vector count(vector& nums) { - vector counter(10); - for (int num : nums) ++counter[num]; - return counter; - } - - bool check(vector& cnt1, vector& cnt2) { - for (int i = 0; i < 10; ++i) - if (cnt1[i] < cnt2[i]) - return false; - return true; - } }; \ No newline at end of file diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.go b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.go index 5ea9c776dfab..81d3e42fa166 100644 --- a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.go +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.go @@ -1,34 +1,20 @@ -func findEvenNumbers(digits []int) []int { - counter := count(digits) - var ans []int - for i := 100; i < 1000; i += 2 { - t := make([]int, 3) - k := i - for j := 0; k > 0; j++ { - t[j] = k % 10 - k /= 10 +func findEvenNumbers(digits []int) (ans []int) { + cnt := [10]int{} + for _, x := range digits { + cnt[x]++ + } + for x := 100; x < 1000; x += 2 { + cnt1 := [10]int{} + for y := x; y > 0; y /= 10 { + cnt1[y%10]++ } - cnt := count(t) - if check(counter, cnt) { - ans = append(ans, i) + ok := true + for i := 0; i < 10 && ok; i++ { + ok = cnt[i] >= cnt1[i] } - } - return ans -} - -func count(nums []int) []int { - counter := make([]int, 10) - for _, num := range nums { - counter[num]++ - } - return counter -} - -func check(cnt1, cnt2 []int) bool { - for i := 0; i < 10; i++ { - if cnt1[i] < cnt2[i] { - return false + if ok { + ans = append(ans, x) } } - return true + return } \ No newline at end of file diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.java b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.java index 8aa69394d934..faf22b41d2df 100644 --- a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.java +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.java @@ -1,35 +1,23 @@ class Solution { public int[] findEvenNumbers(int[] digits) { - int[] counter = count(digits); + int[] cnt = new int[10]; + for (int x : digits) { + ++cnt[x]; + } List ans = new ArrayList<>(); - for (int i = 100; i < 1000; i += 2) { - int[] t = new int[3]; - for (int j = 0, k = i; k > 0; ++j) { - t[j] = k % 10; - k /= 10; + for (int x = 100; x < 1000; x += 2) { + int[] cnt1 = new int[10]; + for (int y = x; y > 0; y /= 10) { + ++cnt1[y % 10]; } - int[] cnt = count(t); - if (check(counter, cnt)) { - ans.add(i); + boolean ok = true; + for (int i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; } - } - return ans.stream().mapToInt(Integer::valueOf).toArray(); - } - - private boolean check(int[] cnt1, int[] cnt2) { - for (int i = 0; i < 10; ++i) { - if (cnt1[i] < cnt2[i]) { - return false; + if (ok) { + ans.add(x); } } - return true; - } - - private int[] count(int[] nums) { - int[] counter = new int[10]; - for (int num : nums) { - ++counter[num]; - } - return counter; + return ans.stream().mapToInt(i -> i).toArray(); } } \ No newline at end of file diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.js b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.js new file mode 100644 index 000000000000..6643c301be76 --- /dev/null +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.js @@ -0,0 +1,25 @@ +/** + * @param {number[]} digits + * @return {number[]} + */ +var findEvenNumbers = function (digits) { + const cnt = Array(10).fill(0); + for (const x of digits) { + ++cnt[x]; + } + const ans = []; + for (let x = 100; x < 1000; x += 2) { + const cnt1 = Array(10).fill(0); + for (let y = x; y; y = Math.floor(y / 10)) { + ++cnt1[y % 10]; + } + let ok = true; + for (let i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push(x); + } + } + return ans; +}; diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.py b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.py index 1060bac2963d..27d01eb4a03f 100644 --- a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.py +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.py @@ -1,14 +1,13 @@ class Solution: def findEvenNumbers(self, digits: List[int]) -> List[int]: + cnt = Counter(digits) ans = [] - counter = Counter(digits) - for i in range(100, 1000, 2): - t = [] - k = i - while k: - t.append(k % 10) - k //= 10 - cnt = Counter(t) - if all([counter[i] >= cnt[i] for i in range(10)]): - ans.append(i) + for x in range(100, 1000, 2): + cnt1 = Counter() + y = x + while y: + y, v = divmod(y, 10) + cnt1[v] += 1 + if all(cnt[i] >= cnt1[i] for i in range(10)): + ans.append(x) return ans diff --git a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.ts b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.ts index c90ca3ad3416..54a1e2bd0576 100644 --- a/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.ts +++ b/solution/2000-2099/2094.Finding 3-Digit Even Numbers/Solution.ts @@ -1,25 +1,21 @@ function findEvenNumbers(digits: number[]): number[] { - let record = new Array(10).fill(0); - for (let digit of digits) { - record[digit]++; + const cnt: number[] = Array(10).fill(0); + for (const x of digits) { + ++cnt[x]; } - let ans = []; - for (let i = 100; i < 1000; i += 2) { - if (check(record, String(i))) { - ans.push(i); + const ans: number[] = []; + for (let x = 100; x < 1000; x += 2) { + const cnt1: number[] = Array(10).fill(0); + for (let y = x; y; y = Math.floor(y / 10)) { + ++cnt1[y % 10]; + } + let ok = true; + for (let i = 0; i < 10 && ok; ++i) { + ok = cnt[i] >= cnt1[i]; + } + if (ok) { + ans.push(x); } } return ans; } - -function check(target: Array, digits: string): boolean { - let record = new Array(10).fill(0); - for (let digit of digits) { - record[digit]++; - } - - for (let i = 0; i < 10; i++) { - if (record[i] > target[i]) return false; - } - return true; -} diff --git a/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README.md b/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README.md index 75130395fb9d..6cacbc5c9134 100644 --- a/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README.md +++ b/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README.md @@ -81,7 +81,13 @@ tags: -### 方法一 +### 方法一:快慢指针 + +快慢指针法是一种用于解决链表中的问题的常用技巧。我们可以维护两个指针,一个慢指针 $\textit{slow}$ 和一个快指针 $\textit{fast}$。初始时 $\textit{slow}$ 指向一个虚拟节点,该虚拟节点的 $\textit{next}$ 指针指向链表的头节点 $\textit{head}$,而 $\textit{fast}$ 指向链表的头节点 $\textit{head}$。 + +然后,我们每次将慢指针向后移动一个位置,将快指针向后移动两个位置,直到快指针到达链表的末尾。此时,慢指针指向的节点的下一个节点就是链表的中间节点。我们将慢指针指向的节点的 $\textit{next}$ 指针指向下下个节点,即可删除中间节点。 + +时间复杂度 $O(n)$,其中 $n$ 是链表的长度。空间复杂度 $O(1)$。 @@ -197,15 +203,14 @@ func deleteMiddle(head *ListNode) *ListNode { */ function deleteMiddle(head: ListNode | null): ListNode | null { - if (!head || !head.next) return null; - let fast = head.next, - slow = head; - while (fast.next && fast.next.next) { + const dummy = new ListNode(0, head); + let [slow, fast] = [dummy, head]; + while (fast && fast.next) { slow = slow.next; fast = fast.next.next; } slow.next = slow.next.next; - return head; + return dummy.next; } ``` diff --git a/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README_EN.md b/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README_EN.md index 3f244977be91..4bef07b444f8 100644 --- a/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README_EN.md +++ b/solution/2000-2099/2095.Delete the Middle Node of a Linked List/README_EN.md @@ -73,7 +73,13 @@ Node 0 with value 2 is the only node remaining after removing node 1.
    -### Solution 1 +### Solution 1: Fast and Slow Pointers + +The fast and slow pointer technique is a common method used to solve problems related to linked lists. We can maintain two pointers, a slow pointer $\textit{slow}$ and a fast pointer $\textit{fast}$. Initially, $\textit{slow}$ points to a dummy node, whose $\textit{next}$ pointer points to the head node $\textit{head}$ of the list, while $\textit{fast}$ points to the head node $\textit{head}$. + +Then, we move the slow pointer one position backward and the fast pointer two positions backward each time, until the fast pointer reaches the end of the list. At this point, the node next to the node pointed by the slow pointer is the middle node of the list. We can remove the middle node by setting the $\textit{next}$ pointer of the node pointed by the slow pointer to point to the next next node. + +The time complexity is $O(n)$, where $n$ is the length of the list. The space complexity is $O(1)$. @@ -189,15 +195,14 @@ func deleteMiddle(head *ListNode) *ListNode { */ function deleteMiddle(head: ListNode | null): ListNode | null { - if (!head || !head.next) return null; - let fast = head.next, - slow = head; - while (fast.next && fast.next.next) { + const dummy = new ListNode(0, head); + let [slow, fast] = [dummy, head]; + while (fast && fast.next) { slow = slow.next; fast = fast.next.next; } slow.next = slow.next.next; - return head; + return dummy.next; } ``` diff --git a/solution/2000-2099/2095.Delete the Middle Node of a Linked List/Solution.ts b/solution/2000-2099/2095.Delete the Middle Node of a Linked List/Solution.ts index 6b62c2971002..28c984b082d6 100644 --- a/solution/2000-2099/2095.Delete the Middle Node of a Linked List/Solution.ts +++ b/solution/2000-2099/2095.Delete the Middle Node of a Linked List/Solution.ts @@ -11,13 +11,12 @@ */ function deleteMiddle(head: ListNode | null): ListNode | null { - if (!head || !head.next) return null; - let fast = head.next, - slow = head; - while (fast.next && fast.next.next) { + const dummy = new ListNode(0, head); + let [slow, fast] = [dummy, head]; + while (fast && fast.next) { slow = slow.next; fast = fast.next.next; } slow.next = slow.next.next; - return head; + return dummy.next; } diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README.md b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README.md index c7e958f93e46..907de5036c28 100644 --- a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README.md +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README.md @@ -72,7 +72,11 @@ tags: -### 方法一 +### 方法一:最近公共祖先 + DFS + +我们可以先找到节点 $\textit{startValue}$ 和 $\textit{destValue}$ 的最近公共祖先,记为 $\textit{node}$,然后分别从 $\textit{node}$ 出发,找到 $\textit{startValue}$ 和 $\textit{destValue}$ 的路径。那么从 $\textit{startValue}$ 到 $\textit{node}$ 的路径就是 $\textit{U}$ 的个数,从 $\textit{node}$ 到 $\textit{destValue}$ 的路径就是 $\textit{path}$ 的路径,最后将这两个路径拼接起来即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点数。 @@ -85,115 +89,410 @@ tags: # self.val = val # self.left = left # self.right = right + + class Solution: def getDirections( self, root: Optional[TreeNode], startValue: int, destValue: int ) -> str: - edges = defaultdict(list) - ans = None - visited = set() - - def traverse(root): - if not root: - return - if root.left: - edges[root.val].append([root.left.val, 'L']) - edges[root.left.val].append([root.val, 'U']) - if root.right: - edges[root.val].append([root.right.val, 'R']) - edges[root.right.val].append([root.val, 'U']) - traverse(root.left) - traverse(root.right) - - def dfs(start, dest, t): - nonlocal ans - if start in visited: - return - if start == dest: - if ans is None or len(ans) > len(t): - ans = ''.join(t) - return - visited.add(start) - for d, k in edges[start]: - t.append(k) - dfs(d, dest, t) - t.pop() - - traverse(root) - dfs(startValue, destValue, []) - return ans + def lca(node: Optional[TreeNode], p: int, q: int): + if node is None or node.val in (p, q): + return node + left = lca(node.left, p, q) + right = lca(node.right, p, q) + if left and right: + return node + return left or right + + def dfs(node: Optional[TreeNode], x: int, path: List[str]): + if node is None: + return False + if node.val == x: + return True + path.append("L") + if dfs(node.left, x, path): + return True + path[-1] = "R" + if dfs(node.right, x, path): + return True + path.pop() + return False + + node = lca(root, startValue, destValue) + + path_to_start = [] + path_to_dest = [] + + dfs(node, startValue, path_to_start) + dfs(node, destValue, path_to_dest) + + return "U" * len(path_to_start) + "".join(path_to_dest) ``` #### Java ```java +class Solution { + public String getDirections(TreeNode root, int startValue, int destValue) { + TreeNode node = lca(root, startValue, destValue); + StringBuilder pathToStart = new StringBuilder(); + StringBuilder pathToDest = new StringBuilder(); + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return "U".repeat(pathToStart.length()) + pathToDest.toString(); + } + + private TreeNode lca(TreeNode node, int p, int q) { + if (node == null || node.val == p || node.val == q) { + return node; + } + TreeNode left = lca(node.left, p, q); + TreeNode right = lca(node.right, p, q); + if (left != null && right != null) { + return node; + } + return left != null ? left : right; + } + + private boolean dfs(TreeNode node, int x, StringBuilder path) { + if (node == null) { + return false; + } + if (node.val == x) { + return true; + } + path.append('L'); + if (dfs(node.left, x, path)) { + return true; + } + path.setCharAt(path.length() - 1, 'R'); + if (dfs(node.right, x, path)) { + return true; + } + path.deleteCharAt(path.length() - 1); + return false; + } +} +``` + +#### C++ + +```cpp /** * Definition for a binary tree node. - * public class TreeNode { + * struct TreeNode { * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; */ class Solution { - private Map>> edges; - private Set visited; - private String ans; +public: + string getDirections(TreeNode* root, int startValue, int destValue) { + TreeNode* node = lca(root, startValue, destValue); + string pathToStart, pathToDest; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return string(pathToStart.size(), 'U') + pathToDest; + } - public String getDirections(TreeNode root, int startValue, int destValue) { - edges = new HashMap<>(); - visited = new HashSet<>(); - ans = null; - traverse(root); - dfs(startValue, destValue, new ArrayList<>()); - return ans; +private: + TreeNode* lca(TreeNode* node, int p, int q) { + if (node == nullptr || node->val == p || node->val == q) { + return node; + } + TreeNode* left = lca(node->left, p, q); + TreeNode* right = lca(node->right, p, q); + if (left != nullptr && right != nullptr) { + return node; + } + return left != nullptr ? left : right; } - private void traverse(TreeNode root) { - if (root == null) { - return; + bool dfs(TreeNode* node, int x, string& path) { + if (node == nullptr) { + return false; + } + if (node->val == x) { + return true; + } + path.push_back('L'); + if (dfs(node->left, x, path)) { + return true; + } + path.back() = 'R'; + if (dfs(node->right, x, path)) { + return true; + } + path.pop_back(); + return false; + } +}; +``` + +#### Go + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func getDirections(root *TreeNode, startValue int, destValue int) string { + var lca func(node *TreeNode, p, q int) *TreeNode + lca = func(node *TreeNode, p, q int) *TreeNode { + if node == nil || node.Val == p || node.Val == q { + return node + } + left := lca(node.Left, p, q) + right := lca(node.Right, p, q) + if left != nil && right != nil { + return node + } + if left != nil { + return left + } + return right + } + var dfs func(node *TreeNode, x int, path *[]byte) bool + dfs = func(node *TreeNode, x int, path *[]byte) bool { + if node == nil { + return false + } + if node.Val == x { + return true + } + *path = append(*path, 'L') + if dfs(node.Left, x, path) { + return true + } + (*path)[len(*path)-1] = 'R' + if dfs(node.Right, x, path) { + return true + } + *path = (*path)[:len(*path)-1] + return false + } + + node := lca(root, startValue, destValue) + pathToStart := []byte{} + pathToDest := []byte{} + dfs(node, startValue, &pathToStart) + dfs(node, destValue, &pathToDest) + return string(bytes.Repeat([]byte{'U'}, len(pathToStart))) + string(pathToDest) +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getDirections(root: TreeNode | null, startValue: number, destValue: number): string { + const lca = (node: TreeNode | null, p: number, q: number): TreeNode | null => { + if (node === null || [p, q].includes(node.val)) { + return node; + } + const left = lca(node.left, p, q); + const right = lca(node.right, p, q); + + return left && right ? node : (left ?? right); + }; + + const dfs = (node: TreeNode | null, x: number, path: string[]): boolean => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + + const node = lca(root, startValue, destValue); + const pathToStart: string[] = []; + const pathToDest: string[] = []; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return 'U'.repeat(pathToStart.length) + pathToDest.join(''); +} +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} startValue + * @param {number} destValue + * @return {string} + */ +var getDirections = function (root, startValue, destValue) { + const lca = (node, p, q) => { + if (node === null || [p, q].includes(node.val)) { + return node; + } + const left = lca(node.left, p, q); + const right = lca(node.right, p, q); + + return left && right ? node : (left ?? right); + }; + + const dfs = (node, x, path) => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; } - if (root.left != null) { - edges.computeIfAbsent(root.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.left.val), "L")); - edges.computeIfAbsent(root.left.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.val), "U")); + path.push('L'); + if (dfs(node.left, x, path)) { + return true; } - if (root.right != null) { - edges.computeIfAbsent(root.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.right.val), "R")); - edges.computeIfAbsent(root.right.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.val), "U")); + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + + const node = lca(root, startValue, destValue); + const pathToStart = []; + const pathToDest = []; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return 'U'.repeat(pathToStart.length) + pathToDest.join(''); +}; +``` + + + + + + + +### 方法二:最近公共祖先 + DFS(优化) + +我们可以从 $\textit{root}$ 出发,找到 $\textit{startValue}$ 和 $\textit{destValue}$ 的路径,记为 $\textit{pathToStart}$ 和 $\textit{pathToDest}$,然后去除 $\textit{pathToStart}$ 和 $\textit{pathToDest}$ 的最长公共前缀,此时 $\textit{pathToStart}$ 的路径长度就是答案中 $\textit{U}$ 的个数,而 $\textit{pathToDest}$ 的路径就是答案中的路径,我们只需要将这两个路径拼接起来即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点数。 + + + +#### Python3 + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + + +class Solution: + def getDirections( + self, root: Optional[TreeNode], startValue: int, destValue: int + ) -> str: + def dfs(node: Optional[TreeNode], x: int, path: List[str]): + if node is None: + return False + if node.val == x: + return True + path.append("L") + if dfs(node.left, x, path): + return True + path[-1] = "R" + if dfs(node.right, x, path): + return True + path.pop() + return False + + path_to_start = [] + path_to_dest = [] + + dfs(root, startValue, path_to_start) + dfs(root, destValue, path_to_dest) + i = 0 + while ( + i < len(path_to_start) + and i < len(path_to_dest) + and path_to_start[i] == path_to_dest[i] + ): + i += 1 + return "U" * (len(path_to_start) - i) + "".join(path_to_dest[i:]) +``` + +#### Java + +```java +class Solution { + public String getDirections(TreeNode root, int startValue, int destValue) { + StringBuilder pathToStart = new StringBuilder(); + StringBuilder pathToDest = new StringBuilder(); + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + int i = 0; + while (i < pathToStart.length() && i < pathToDest.length() + && pathToStart.charAt(i) == pathToDest.charAt(i)) { + ++i; } - traverse(root.left); - traverse(root.right); + return "U".repeat(pathToStart.length() - i) + pathToDest.substring(i); } - private void dfs(int start, int dest, List t) { - if (visited.contains(start)) { - return; + private boolean dfs(TreeNode node, int x, StringBuilder path) { + if (node == null) { + return false; } - if (start == dest) { - if (ans == null || ans.length() > t.size()) { - ans = String.join("", t); - } - return; + if (node.val == x) { + return true; } - visited.add(start); - if (edges.containsKey(start)) { - for (List item : edges.get(start)) { - t.add(item.get(1)); - dfs(Integer.parseInt(item.get(0)), dest, t); - t.remove(t.size() - 1); - } + path.append('L'); + if (dfs(node.left, x, path)) { + return true; } + path.setCharAt(path.length() - 1, 'R'); + if (dfs(node.right, x, path)) { + return true; + } + path.deleteCharAt(path.length() - 1); + return false; } } ``` @@ -214,47 +513,176 @@ class Solution { */ class Solution { public: - unordered_map>> edges; - unordered_set visited; - string ans; - string getDirections(TreeNode* root, int startValue, int destValue) { - ans = ""; - traverse(root); - string t = ""; - dfs(startValue, destValue, t); - return ans; + string pathToStart, pathToDest; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + int i = 0; + while (i < pathToStart.size() && i < pathToDest.size() && pathToStart[i] == pathToDest[i]) { + i++; + } + return string(pathToStart.size() - i, 'U') + pathToDest.substr(i); } - void traverse(TreeNode* root) { - if (!root) return; - if (root->left) { - edges[root->val].push_back({root->left->val, 'L'}); - edges[root->left->val].push_back({root->val, 'U'}); +private: + bool dfs(TreeNode* node, int x, string& path) { + if (node == nullptr) { + return false; + } + if (node->val == x) { + return true; + } + path.push_back('L'); + if (dfs(node->left, x, path)) { + return true; } - if (root->right) { - edges[root->val].push_back({root->right->val, 'R'}); - edges[root->right->val].push_back({root->val, 'U'}); + path.back() = 'R'; + if (dfs(node->right, x, path)) { + return true; } - traverse(root->left); - traverse(root->right); + path.pop_back(); + return false; } +}; +``` + +#### Go + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func getDirections(root *TreeNode, startValue int, destValue int) string { + var dfs func(node *TreeNode, x int, path *[]byte) bool + dfs = func(node *TreeNode, x int, path *[]byte) bool { + if node == nil { + return false + } + if node.Val == x { + return true + } + *path = append(*path, 'L') + if dfs(node.Left, x, path) { + return true + } + (*path)[len(*path)-1] = 'R' + if dfs(node.Right, x, path) { + return true + } + *path = (*path)[:len(*path)-1] + return false + } + + pathToStart := []byte{} + pathToDest := []byte{} + dfs(root, startValue, &pathToStart) + dfs(root, destValue, &pathToDest) + i := 0 + for i < len(pathToStart) && i < len(pathToDest) && pathToStart[i] == pathToDest[i] { + i++ + } + return string(bytes.Repeat([]byte{'U'}, len(pathToStart)-i)) + string(pathToDest[i:]) +} +``` - void dfs(int start, int dest, string& t) { - if (visited.count(start)) return; - if (start == dest) { - if (ans == "" || ans.size() > t.size()) ans = t; - return; +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getDirections(root: TreeNode | null, startValue: number, destValue: number): string { + const dfs = (node: TreeNode | null, x: number, path: string[]): boolean => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + const pathToStart: string[] = []; + const pathToDest: string[] = []; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + let i = 0; + while (pathToStart[i] === pathToDest[i]) { + ++i; + } + return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join(''); +} +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} startValue + * @param {number} destValue + * @return {string} + */ +var getDirections = function (root, startValue, destValue) { + const dfs = (node, x, path) => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; } - visited.insert(start); - if (edges.count(start)) { - for (auto& item : edges[start]) { - t += item.second; - dfs(item.first, dest, t); - t.pop_back(); - } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; } + path.pop(); + return false; + }; + const pathToStart = []; + const pathToDest = []; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + let i = 0; + while (pathToStart[i] === pathToDest[i]) { + ++i; } + return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join(''); }; ``` diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README_EN.md b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README_EN.md index f83a49ec6545..58782483df63 100644 --- a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README_EN.md +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/README_EN.md @@ -68,7 +68,11 @@ tags: -### Solution 1 +### Solution 1: Lowest Common Ancestor + DFS + +We can first find the lowest common ancestor of nodes $\textit{startValue}$ and $\textit{destValue}$, denoted as $\textit{node}$. Then, starting from $\textit{node}$, we find the paths to $\textit{startValue}$ and $\textit{destValue}$ respectively. The path from $\textit{startValue}$ to $\textit{node}$ will consist of a number of $\textit{U}$s, and the path from $\textit{node}$ to $\textit{destValue}$ will be the $\textit{path}$. Finally, we concatenate these two paths. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -81,115 +85,410 @@ tags: # self.val = val # self.left = left # self.right = right + + class Solution: def getDirections( self, root: Optional[TreeNode], startValue: int, destValue: int ) -> str: - edges = defaultdict(list) - ans = None - visited = set() - - def traverse(root): - if not root: - return - if root.left: - edges[root.val].append([root.left.val, 'L']) - edges[root.left.val].append([root.val, 'U']) - if root.right: - edges[root.val].append([root.right.val, 'R']) - edges[root.right.val].append([root.val, 'U']) - traverse(root.left) - traverse(root.right) - - def dfs(start, dest, t): - nonlocal ans - if start in visited: - return - if start == dest: - if ans is None or len(ans) > len(t): - ans = ''.join(t) - return - visited.add(start) - for d, k in edges[start]: - t.append(k) - dfs(d, dest, t) - t.pop() - - traverse(root) - dfs(startValue, destValue, []) - return ans + def lca(node: Optional[TreeNode], p: int, q: int): + if node is None or node.val in (p, q): + return node + left = lca(node.left, p, q) + right = lca(node.right, p, q) + if left and right: + return node + return left or right + + def dfs(node: Optional[TreeNode], x: int, path: List[str]): + if node is None: + return False + if node.val == x: + return True + path.append("L") + if dfs(node.left, x, path): + return True + path[-1] = "R" + if dfs(node.right, x, path): + return True + path.pop() + return False + + node = lca(root, startValue, destValue) + + path_to_start = [] + path_to_dest = [] + + dfs(node, startValue, path_to_start) + dfs(node, destValue, path_to_dest) + + return "U" * len(path_to_start) + "".join(path_to_dest) ``` #### Java ```java +class Solution { + public String getDirections(TreeNode root, int startValue, int destValue) { + TreeNode node = lca(root, startValue, destValue); + StringBuilder pathToStart = new StringBuilder(); + StringBuilder pathToDest = new StringBuilder(); + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return "U".repeat(pathToStart.length()) + pathToDest.toString(); + } + + private TreeNode lca(TreeNode node, int p, int q) { + if (node == null || node.val == p || node.val == q) { + return node; + } + TreeNode left = lca(node.left, p, q); + TreeNode right = lca(node.right, p, q); + if (left != null && right != null) { + return node; + } + return left != null ? left : right; + } + + private boolean dfs(TreeNode node, int x, StringBuilder path) { + if (node == null) { + return false; + } + if (node.val == x) { + return true; + } + path.append('L'); + if (dfs(node.left, x, path)) { + return true; + } + path.setCharAt(path.length() - 1, 'R'); + if (dfs(node.right, x, path)) { + return true; + } + path.deleteCharAt(path.length() - 1); + return false; + } +} +``` + +#### C++ + +```cpp /** * Definition for a binary tree node. - * public class TreeNode { + * struct TreeNode { * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; */ class Solution { - private Map>> edges; - private Set visited; - private String ans; +public: + string getDirections(TreeNode* root, int startValue, int destValue) { + TreeNode* node = lca(root, startValue, destValue); + string pathToStart, pathToDest; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return string(pathToStart.size(), 'U') + pathToDest; + } - public String getDirections(TreeNode root, int startValue, int destValue) { - edges = new HashMap<>(); - visited = new HashSet<>(); - ans = null; - traverse(root); - dfs(startValue, destValue, new ArrayList<>()); - return ans; +private: + TreeNode* lca(TreeNode* node, int p, int q) { + if (node == nullptr || node->val == p || node->val == q) { + return node; + } + TreeNode* left = lca(node->left, p, q); + TreeNode* right = lca(node->right, p, q); + if (left != nullptr && right != nullptr) { + return node; + } + return left != nullptr ? left : right; } - private void traverse(TreeNode root) { - if (root == null) { - return; + bool dfs(TreeNode* node, int x, string& path) { + if (node == nullptr) { + return false; + } + if (node->val == x) { + return true; + } + path.push_back('L'); + if (dfs(node->left, x, path)) { + return true; + } + path.back() = 'R'; + if (dfs(node->right, x, path)) { + return true; + } + path.pop_back(); + return false; + } +}; +``` + +#### Go + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func getDirections(root *TreeNode, startValue int, destValue int) string { + var lca func(node *TreeNode, p, q int) *TreeNode + lca = func(node *TreeNode, p, q int) *TreeNode { + if node == nil || node.Val == p || node.Val == q { + return node + } + left := lca(node.Left, p, q) + right := lca(node.Right, p, q) + if left != nil && right != nil { + return node + } + if left != nil { + return left + } + return right + } + var dfs func(node *TreeNode, x int, path *[]byte) bool + dfs = func(node *TreeNode, x int, path *[]byte) bool { + if node == nil { + return false + } + if node.Val == x { + return true + } + *path = append(*path, 'L') + if dfs(node.Left, x, path) { + return true + } + (*path)[len(*path)-1] = 'R' + if dfs(node.Right, x, path) { + return true + } + *path = (*path)[:len(*path)-1] + return false + } + + node := lca(root, startValue, destValue) + pathToStart := []byte{} + pathToDest := []byte{} + dfs(node, startValue, &pathToStart) + dfs(node, destValue, &pathToDest) + return string(bytes.Repeat([]byte{'U'}, len(pathToStart))) + string(pathToDest) +} +``` + +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getDirections(root: TreeNode | null, startValue: number, destValue: number): string { + const lca = (node: TreeNode | null, p: number, q: number): TreeNode | null => { + if (node === null || [p, q].includes(node.val)) { + return node; + } + const left = lca(node.left, p, q); + const right = lca(node.right, p, q); + + return left && right ? node : (left ?? right); + }; + + const dfs = (node: TreeNode | null, x: number, path: string[]): boolean => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + + const node = lca(root, startValue, destValue); + const pathToStart: string[] = []; + const pathToDest: string[] = []; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return 'U'.repeat(pathToStart.length) + pathToDest.join(''); +} +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} startValue + * @param {number} destValue + * @return {string} + */ +var getDirections = function (root, startValue, destValue) { + const lca = (node, p, q) => { + if (node === null || [p, q].includes(node.val)) { + return node; + } + const left = lca(node.left, p, q); + const right = lca(node.right, p, q); + + return left && right ? node : (left ?? right); + }; + + const dfs = (node, x, path) => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; } - if (root.left != null) { - edges.computeIfAbsent(root.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.left.val), "L")); - edges.computeIfAbsent(root.left.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.val), "U")); + path.push('L'); + if (dfs(node.left, x, path)) { + return true; } - if (root.right != null) { - edges.computeIfAbsent(root.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.right.val), "R")); - edges.computeIfAbsent(root.right.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.val), "U")); + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + + const node = lca(root, startValue, destValue); + const pathToStart = []; + const pathToDest = []; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return 'U'.repeat(pathToStart.length) + pathToDest.join(''); +}; +``` + + + + + + + +### Solution 2: Lowest Common Ancestor + DFS (Optimized) + +We can start from $\textit{root}$, find the paths to $\textit{startValue}$ and $\textit{destValue}$, denoted as $\textit{pathToStart}$ and $\textit{pathToDest}$, respectively. Then, remove the longest common prefix of $\textit{pathToStart}$ and $\textit{pathToDest}$. At this point, the length of $\textit{pathToStart}$ is the number of $\textit{U}$s in the answer, and the path of $\textit{pathToDest}$ is the path in the answer. We just need to concatenate these two paths. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. + + + +#### Python3 + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + + +class Solution: + def getDirections( + self, root: Optional[TreeNode], startValue: int, destValue: int + ) -> str: + def dfs(node: Optional[TreeNode], x: int, path: List[str]): + if node is None: + return False + if node.val == x: + return True + path.append("L") + if dfs(node.left, x, path): + return True + path[-1] = "R" + if dfs(node.right, x, path): + return True + path.pop() + return False + + path_to_start = [] + path_to_dest = [] + + dfs(root, startValue, path_to_start) + dfs(root, destValue, path_to_dest) + i = 0 + while ( + i < len(path_to_start) + and i < len(path_to_dest) + and path_to_start[i] == path_to_dest[i] + ): + i += 1 + return "U" * (len(path_to_start) - i) + "".join(path_to_dest[i:]) +``` + +#### Java + +```java +class Solution { + public String getDirections(TreeNode root, int startValue, int destValue) { + StringBuilder pathToStart = new StringBuilder(); + StringBuilder pathToDest = new StringBuilder(); + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + int i = 0; + while (i < pathToStart.length() && i < pathToDest.length() + && pathToStart.charAt(i) == pathToDest.charAt(i)) { + ++i; } - traverse(root.left); - traverse(root.right); + return "U".repeat(pathToStart.length() - i) + pathToDest.substring(i); } - private void dfs(int start, int dest, List t) { - if (visited.contains(start)) { - return; + private boolean dfs(TreeNode node, int x, StringBuilder path) { + if (node == null) { + return false; } - if (start == dest) { - if (ans == null || ans.length() > t.size()) { - ans = String.join("", t); - } - return; + if (node.val == x) { + return true; } - visited.add(start); - if (edges.containsKey(start)) { - for (List item : edges.get(start)) { - t.add(item.get(1)); - dfs(Integer.parseInt(item.get(0)), dest, t); - t.remove(t.size() - 1); - } + path.append('L'); + if (dfs(node.left, x, path)) { + return true; } + path.setCharAt(path.length() - 1, 'R'); + if (dfs(node.right, x, path)) { + return true; + } + path.deleteCharAt(path.length() - 1); + return false; } } ``` @@ -210,47 +509,176 @@ class Solution { */ class Solution { public: - unordered_map>> edges; - unordered_set visited; - string ans; - string getDirections(TreeNode* root, int startValue, int destValue) { - ans = ""; - traverse(root); - string t = ""; - dfs(startValue, destValue, t); - return ans; + string pathToStart, pathToDest; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + int i = 0; + while (i < pathToStart.size() && i < pathToDest.size() && pathToStart[i] == pathToDest[i]) { + i++; + } + return string(pathToStart.size() - i, 'U') + pathToDest.substr(i); } - void traverse(TreeNode* root) { - if (!root) return; - if (root->left) { - edges[root->val].push_back({root->left->val, 'L'}); - edges[root->left->val].push_back({root->val, 'U'}); +private: + bool dfs(TreeNode* node, int x, string& path) { + if (node == nullptr) { + return false; + } + if (node->val == x) { + return true; + } + path.push_back('L'); + if (dfs(node->left, x, path)) { + return true; } - if (root->right) { - edges[root->val].push_back({root->right->val, 'R'}); - edges[root->right->val].push_back({root->val, 'U'}); + path.back() = 'R'; + if (dfs(node->right, x, path)) { + return true; } - traverse(root->left); - traverse(root->right); + path.pop_back(); + return false; } +}; +``` + +#### Go + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func getDirections(root *TreeNode, startValue int, destValue int) string { + var dfs func(node *TreeNode, x int, path *[]byte) bool + dfs = func(node *TreeNode, x int, path *[]byte) bool { + if node == nil { + return false + } + if node.Val == x { + return true + } + *path = append(*path, 'L') + if dfs(node.Left, x, path) { + return true + } + (*path)[len(*path)-1] = 'R' + if dfs(node.Right, x, path) { + return true + } + *path = (*path)[:len(*path)-1] + return false + } + + pathToStart := []byte{} + pathToDest := []byte{} + dfs(root, startValue, &pathToStart) + dfs(root, destValue, &pathToDest) + i := 0 + for i < len(pathToStart) && i < len(pathToDest) && pathToStart[i] == pathToDest[i] { + i++ + } + return string(bytes.Repeat([]byte{'U'}, len(pathToStart)-i)) + string(pathToDest[i:]) +} +``` - void dfs(int start, int dest, string& t) { - if (visited.count(start)) return; - if (start == dest) { - if (ans == "" || ans.size() > t.size()) ans = t; - return; +#### TypeScript + +```ts +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getDirections(root: TreeNode | null, startValue: number, destValue: number): string { + const dfs = (node: TreeNode | null, x: number, path: string[]): boolean => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + const pathToStart: string[] = []; + const pathToDest: string[] = []; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + let i = 0; + while (pathToStart[i] === pathToDest[i]) { + ++i; + } + return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join(''); +} +``` + +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} startValue + * @param {number} destValue + * @return {string} + */ +var getDirections = function (root, startValue, destValue) { + const dfs = (node, x, path) => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; } - visited.insert(start); - if (edges.count(start)) { - for (auto& item : edges[start]) { - t += item.second; - dfs(item.first, dest, t); - t.pop_back(); - } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; } + path.pop(); + return false; + }; + const pathToStart = []; + const pathToDest = []; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + let i = 0; + while (pathToStart[i] === pathToDest[i]) { + ++i; } + return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join(''); }; ``` diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.cpp b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.cpp index 8b85567ffb3c..f847e2980ae1 100644 --- a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.cpp +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.cpp @@ -11,45 +11,43 @@ */ class Solution { public: - unordered_map>> edges; - unordered_set visited; - string ans; - string getDirections(TreeNode* root, int startValue, int destValue) { - ans = ""; - traverse(root); - string t = ""; - dfs(startValue, destValue, t); - return ans; + TreeNode* node = lca(root, startValue, destValue); + string pathToStart, pathToDest; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return string(pathToStart.size(), 'U') + pathToDest; } - void traverse(TreeNode* root) { - if (!root) return; - if (root->left) { - edges[root->val].push_back({root->left->val, 'L'}); - edges[root->left->val].push_back({root->val, 'U'}); +private: + TreeNode* lca(TreeNode* node, int p, int q) { + if (node == nullptr || node->val == p || node->val == q) { + return node; } - if (root->right) { - edges[root->val].push_back({root->right->val, 'R'}); - edges[root->right->val].push_back({root->val, 'U'}); + TreeNode* left = lca(node->left, p, q); + TreeNode* right = lca(node->right, p, q); + if (left != nullptr && right != nullptr) { + return node; } - traverse(root->left); - traverse(root->right); + return left != nullptr ? left : right; } - void dfs(int start, int dest, string& t) { - if (visited.count(start)) return; - if (start == dest) { - if (ans == "" || ans.size() > t.size()) ans = t; - return; + bool dfs(TreeNode* node, int x, string& path) { + if (node == nullptr) { + return false; + } + if (node->val == x) { + return true; + } + path.push_back('L'); + if (dfs(node->left, x, path)) { + return true; } - visited.insert(start); - if (edges.count(start)) { - for (auto& item : edges[start]) { - t += item.second; - dfs(item.first, dest, t); - t.pop_back(); - } + path.back() = 'R'; + if (dfs(node->right, x, path)) { + return true; } + path.pop_back(); + return false; } -}; \ No newline at end of file +}; diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.go b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.go new file mode 100644 index 000000000000..6e01984cb6c6 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.go @@ -0,0 +1,51 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func getDirections(root *TreeNode, startValue int, destValue int) string { + var lca func(node *TreeNode, p, q int) *TreeNode + lca = func(node *TreeNode, p, q int) *TreeNode { + if node == nil || node.Val == p || node.Val == q { + return node + } + left := lca(node.Left, p, q) + right := lca(node.Right, p, q) + if left != nil && right != nil { + return node + } + if left != nil { + return left + } + return right + } + var dfs func(node *TreeNode, x int, path *[]byte) bool + dfs = func(node *TreeNode, x int, path *[]byte) bool { + if node == nil { + return false + } + if node.Val == x { + return true + } + *path = append(*path, 'L') + if dfs(node.Left, x, path) { + return true + } + (*path)[len(*path)-1] = 'R' + if dfs(node.Right, x, path) { + return true + } + *path = (*path)[:len(*path)-1] + return false + } + + node := lca(root, startValue, destValue) + pathToStart := []byte{} + pathToDest := []byte{} + dfs(node, startValue, &pathToStart) + dfs(node, destValue, &pathToDest) + return string(bytes.Repeat([]byte{'U'}, len(pathToStart))) + string(pathToDest) +} diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.java b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.java index 79a6ea48a0a1..7d20d1033ed9 100644 --- a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.java +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.java @@ -1,69 +1,41 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ class Solution { - private Map>> edges; - private Set visited; - private String ans; - public String getDirections(TreeNode root, int startValue, int destValue) { - edges = new HashMap<>(); - visited = new HashSet<>(); - ans = null; - traverse(root); - dfs(startValue, destValue, new ArrayList<>()); - return ans; + TreeNode node = lca(root, startValue, destValue); + StringBuilder pathToStart = new StringBuilder(); + StringBuilder pathToDest = new StringBuilder(); + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return "U".repeat(pathToStart.length()) + pathToDest.toString(); } - private void traverse(TreeNode root) { - if (root == null) { - return; - } - if (root.left != null) { - edges.computeIfAbsent(root.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.left.val), "L")); - edges.computeIfAbsent(root.left.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.val), "U")); + private TreeNode lca(TreeNode node, int p, int q) { + if (node == null || node.val == p || node.val == q) { + return node; } - if (root.right != null) { - edges.computeIfAbsent(root.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.right.val), "R")); - edges.computeIfAbsent(root.right.val, k -> new ArrayList<>()) - .add(Arrays.asList(String.valueOf(root.val), "U")); + TreeNode left = lca(node.left, p, q); + TreeNode right = lca(node.right, p, q); + if (left != null && right != null) { + return node; } - traverse(root.left); - traverse(root.right); + return left != null ? left : right; } - private void dfs(int start, int dest, List t) { - if (visited.contains(start)) { - return; + private boolean dfs(TreeNode node, int x, StringBuilder path) { + if (node == null) { + return false; + } + if (node.val == x) { + return true; } - if (start == dest) { - if (ans == null || ans.length() > t.size()) { - ans = String.join("", t); - } - return; + path.append('L'); + if (dfs(node.left, x, path)) { + return true; } - visited.add(start); - if (edges.containsKey(start)) { - for (List item : edges.get(start)) { - t.add(item.get(1)); - dfs(Integer.parseInt(item.get(0)), dest, t); - t.remove(t.size() - 1); - } + path.setCharAt(path.length() - 1, 'R'); + if (dfs(node.right, x, path)) { + return true; } + path.deleteCharAt(path.length() - 1); + return false; } -} \ No newline at end of file +} diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.js b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.js new file mode 100644 index 000000000000..cf11074f0553 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.js @@ -0,0 +1,51 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} startValue + * @param {number} destValue + * @return {string} + */ +var getDirections = function (root, startValue, destValue) { + const lca = (node, p, q) => { + if (node === null || [p, q].includes(node.val)) { + return node; + } + const left = lca(node.left, p, q); + const right = lca(node.right, p, q); + + return left && right ? node : (left ?? right); + }; + + const dfs = (node, x, path) => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + + const node = lca(root, startValue, destValue); + const pathToStart = []; + const pathToDest = []; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return 'U'.repeat(pathToStart.length) + pathToDest.join(''); +}; diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.py b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.py index 063713ad935b..2963576fc9e6 100644 --- a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.py +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.py @@ -4,40 +4,41 @@ # self.val = val # self.left = left # self.right = right + + class Solution: def getDirections( self, root: Optional[TreeNode], startValue: int, destValue: int ) -> str: - edges = defaultdict(list) - ans = None - visited = set() + def lca(node: Optional[TreeNode], p: int, q: int): + if node is None or node.val in (p, q): + return node + left = lca(node.left, p, q) + right = lca(node.right, p, q) + if left and right: + return node + return left or right + + def dfs(node: Optional[TreeNode], x: int, path: List[str]): + if node is None: + return False + if node.val == x: + return True + path.append("L") + if dfs(node.left, x, path): + return True + path[-1] = "R" + if dfs(node.right, x, path): + return True + path.pop() + return False + + node = lca(root, startValue, destValue) - def traverse(root): - if not root: - return - if root.left: - edges[root.val].append([root.left.val, 'L']) - edges[root.left.val].append([root.val, 'U']) - if root.right: - edges[root.val].append([root.right.val, 'R']) - edges[root.right.val].append([root.val, 'U']) - traverse(root.left) - traverse(root.right) + path_to_start = [] + path_to_dest = [] - def dfs(start, dest, t): - nonlocal ans - if start in visited: - return - if start == dest: - if ans is None or len(ans) > len(t): - ans = ''.join(t) - return - visited.add(start) - for d, k in edges[start]: - t.append(k) - dfs(d, dest, t) - t.pop() + dfs(node, startValue, path_to_start) + dfs(node, destValue, path_to_dest) - traverse(root) - dfs(startValue, destValue, []) - return ans + return "U" * len(path_to_start) + "".join(path_to_dest) diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.ts b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.ts new file mode 100644 index 000000000000..5c028830da79 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution.ts @@ -0,0 +1,51 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getDirections(root: TreeNode | null, startValue: number, destValue: number): string { + const lca = (node: TreeNode | null, p: number, q: number): TreeNode | null => { + if (node === null || [p, q].includes(node.val)) { + return node; + } + const left = lca(node.left, p, q); + const right = lca(node.right, p, q); + + return left && right ? node : (left ?? right); + }; + + const dfs = (node: TreeNode | null, x: number, path: string[]): boolean => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + + const node = lca(root, startValue, destValue); + const pathToStart: string[] = []; + const pathToDest: string[] = []; + dfs(node, startValue, pathToStart); + dfs(node, destValue, pathToDest); + return 'U'.repeat(pathToStart.length) + pathToDest.join(''); +} diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.cpp b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.cpp new file mode 100644 index 000000000000..a41bdeceac75 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.cpp @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + string getDirections(TreeNode* root, int startValue, int destValue) { + string pathToStart, pathToDest; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + int i = 0; + while (i < pathToStart.size() && i < pathToDest.size() && pathToStart[i] == pathToDest[i]) { + i++; + } + return string(pathToStart.size() - i, 'U') + pathToDest.substr(i); + } + +private: + bool dfs(TreeNode* node, int x, string& path) { + if (node == nullptr) { + return false; + } + if (node->val == x) { + return true; + } + path.push_back('L'); + if (dfs(node->left, x, path)) { + return true; + } + path.back() = 'R'; + if (dfs(node->right, x, path)) { + return true; + } + path.pop_back(); + return false; + } +}; diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.go b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.go new file mode 100644 index 000000000000..9bebac83bd57 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.go @@ -0,0 +1,39 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func getDirections(root *TreeNode, startValue int, destValue int) string { + var dfs func(node *TreeNode, x int, path *[]byte) bool + dfs = func(node *TreeNode, x int, path *[]byte) bool { + if node == nil { + return false + } + if node.Val == x { + return true + } + *path = append(*path, 'L') + if dfs(node.Left, x, path) { + return true + } + (*path)[len(*path)-1] = 'R' + if dfs(node.Right, x, path) { + return true + } + *path = (*path)[:len(*path)-1] + return false + } + + pathToStart := []byte{} + pathToDest := []byte{} + dfs(root, startValue, &pathToStart) + dfs(root, destValue, &pathToDest) + i := 0 + for i < len(pathToStart) && i < len(pathToDest) && pathToStart[i] == pathToDest[i] { + i++ + } + return string(bytes.Repeat([]byte{'U'}, len(pathToStart)-i)) + string(pathToDest[i:]) +} diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.java b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.java new file mode 100644 index 000000000000..cc9de2feb49f --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.java @@ -0,0 +1,33 @@ +class Solution { + public String getDirections(TreeNode root, int startValue, int destValue) { + StringBuilder pathToStart = new StringBuilder(); + StringBuilder pathToDest = new StringBuilder(); + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + int i = 0; + while (i < pathToStart.length() && i < pathToDest.length() + && pathToStart.charAt(i) == pathToDest.charAt(i)) { + ++i; + } + return "U".repeat(pathToStart.length() - i) + pathToDest.substring(i); + } + + private boolean dfs(TreeNode node, int x, StringBuilder path) { + if (node == null) { + return false; + } + if (node.val == x) { + return true; + } + path.append('L'); + if (dfs(node.left, x, path)) { + return true; + } + path.setCharAt(path.length() - 1, 'R'); + if (dfs(node.right, x, path)) { + return true; + } + path.deleteCharAt(path.length() - 1); + return false; + } +} diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.js b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.js new file mode 100644 index 000000000000..4a1ff8a30ec2 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.js @@ -0,0 +1,43 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} startValue + * @param {number} destValue + * @return {string} + */ +var getDirections = function (root, startValue, destValue) { + const dfs = (node, x, path) => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + const pathToStart = []; + const pathToDest = []; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + let i = 0; + while (pathToStart[i] === pathToDest[i]) { + ++i; + } + return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join(''); +}; diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.py b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.py new file mode 100644 index 000000000000..0e75b115b0d7 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.py @@ -0,0 +1,39 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + + +class Solution: + def getDirections( + self, root: Optional[TreeNode], startValue: int, destValue: int + ) -> str: + def dfs(node: Optional[TreeNode], x: int, path: List[str]): + if node is None: + return False + if node.val == x: + return True + path.append("L") + if dfs(node.left, x, path): + return True + path[-1] = "R" + if dfs(node.right, x, path): + return True + path.pop() + return False + + path_to_start = [] + path_to_dest = [] + + dfs(root, startValue, path_to_start) + dfs(root, destValue, path_to_dest) + i = 0 + while ( + i < len(path_to_start) + and i < len(path_to_dest) + and path_to_start[i] == path_to_dest[i] + ): + i += 1 + return "U" * (len(path_to_start) - i) + "".join(path_to_dest[i:]) diff --git a/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.ts b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.ts new file mode 100644 index 000000000000..c9c209c5dbd3 --- /dev/null +++ b/solution/2000-2099/2096.Step-By-Step Directions From a Binary Tree Node to Another/Solution2.ts @@ -0,0 +1,43 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +function getDirections(root: TreeNode | null, startValue: number, destValue: number): string { + const dfs = (node: TreeNode | null, x: number, path: string[]): boolean => { + if (node === null) { + return false; + } + if (node.val === x) { + return true; + } + path.push('L'); + if (dfs(node.left, x, path)) { + return true; + } + path[path.length - 1] = 'R'; + if (dfs(node.right, x, path)) { + return true; + } + path.pop(); + return false; + }; + const pathToStart: string[] = []; + const pathToDest: string[] = []; + dfs(root, startValue, pathToStart); + dfs(root, destValue, pathToDest); + let i = 0; + while (pathToStart[i] === pathToDest[i]) { + ++i; + } + return 'U'.repeat(pathToStart.length - i) + pathToDest.slice(i).join(''); +} diff --git a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README.md b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README.md index 3dc021a1729e..0bd10f01d81b 100644 --- a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README.md +++ b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README.md @@ -107,7 +107,7 @@ class Solution: else: mi1 = x ans = max(ans - mi1 + mx1, ans - mi2 + mx2, -1) - return -1 if ans % 2 else ans + return -1 if ans < 0 else ans ``` #### Java @@ -141,8 +141,8 @@ class Solution { mi1 = nums[i]; } } - ans = Math.max(-1, Math.max(ans - mi1 + mx1, ans - mi2 + mx2)); - return ans % 2 != 0 ? -1 : ans; + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? -1 : ans; } } ``` @@ -180,7 +180,7 @@ public: } } ans = max(ans - mi1 + mx1, ans - mi2 + mx2); - return ans % 2 || ans < 0 ? -1 : ans; + return ans < 0 ? -1 : ans; } }; ``` @@ -216,13 +216,50 @@ func largestEvenSum(nums []int, k int) int64 { } } ans = max(-1, max(ans-mi1+mx1, ans-mi2+mx2)) - if ans%2 != 0 { + if ans%2 < 0 { return -1 } return int64(ans) } ``` +#### TypeScript + +```ts +function largestEvenSum(nums: number[], k: number): number { + nums.sort((a, b) => a - b); + let ans = 0; + const n = nums.length; + for (let i = 0; i < k; ++i) { + ans += nums[n - i - 1]; + } + if (ans % 2 === 0) { + return ans; + } + const inf = 1 << 29; + let mx1 = -inf, + mx2 = -inf; + for (let i = 0; i < n - k; ++i) { + if (nums[i] % 2 === 1) { + mx1 = nums[i]; + } else { + mx2 = nums[i]; + } + } + let mi1 = inf, + mi2 = inf; + for (let i = n - 1; i >= n - k; --i) { + if (nums[i] % 2 === 1) { + mi2 = nums[i]; + } else { + mi1 = nums[i]; + } + } + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? -1 : ans; +} +``` + diff --git a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README_EN.md b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README_EN.md index 9090b2463b12..2538ca9cc7aa 100644 --- a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README_EN.md +++ b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/README_EN.md @@ -67,7 +67,20 @@ No subsequence of nums with length 1 has an even sum. -### Solution 1 +### Solution 1: Greedy + Sorting + +We notice that the problem involves selecting a subsequence, so we can consider sorting the array first. + +Next, we greedily select the largest $k$ numbers. If the sum of these numbers is even, we directly return this sum $ans$. + +Otherwise, we have two greedy strategies: + +1. Among the largest $k$ numbers, find the smallest even number $mi1$, and then among the remaining $n - k$ numbers, find the largest odd number $mx1$. Replace $mi1$ with $mx1$. If such a replacement exists, then the sum after replacement $ans - mi1 + mx1$ is guaranteed to be even; +2. Among the largest $k$ numbers, find the smallest odd number $mi2$, and then among the remaining $n - k$ numbers, find the largest even number $mx2$. Replace $mi2$ with $mx2$. If such a replacement exists, then the sum after replacement $ans - mi2 + mx2$ is guaranteed to be even. + +We take the largest even sum as the answer. If no even sum exists, return $-1$. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array. @@ -94,7 +107,7 @@ class Solution: else: mi1 = x ans = max(ans - mi1 + mx1, ans - mi2 + mx2, -1) - return -1 if ans % 2 else ans + return -1 if ans < 0 else ans ``` #### Java @@ -128,8 +141,8 @@ class Solution { mi1 = nums[i]; } } - ans = Math.max(-1, Math.max(ans - mi1 + mx1, ans - mi2 + mx2)); - return ans % 2 != 0 ? -1 : ans; + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? -1 : ans; } } ``` @@ -167,7 +180,7 @@ public: } } ans = max(ans - mi1 + mx1, ans - mi2 + mx2); - return ans % 2 || ans < 0 ? -1 : ans; + return ans < 0 ? -1 : ans; } }; ``` @@ -203,13 +216,50 @@ func largestEvenSum(nums []int, k int) int64 { } } ans = max(-1, max(ans-mi1+mx1, ans-mi2+mx2)) - if ans%2 != 0 { + if ans%2 < 0 { return -1 } return int64(ans) } ``` +#### TypeScript + +```ts +function largestEvenSum(nums: number[], k: number): number { + nums.sort((a, b) => a - b); + let ans = 0; + const n = nums.length; + for (let i = 0; i < k; ++i) { + ans += nums[n - i - 1]; + } + if (ans % 2 === 0) { + return ans; + } + const inf = 1 << 29; + let mx1 = -inf, + mx2 = -inf; + for (let i = 0; i < n - k; ++i) { + if (nums[i] % 2 === 1) { + mx1 = nums[i]; + } else { + mx2 = nums[i]; + } + } + let mi1 = inf, + mi2 = inf; + for (let i = n - 1; i >= n - k; --i) { + if (nums[i] % 2 === 1) { + mi2 = nums[i]; + } else { + mi1 = nums[i]; + } + } + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? -1 : ans; +} +``` + diff --git a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.cpp b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.cpp index 7d0894f60488..d280c2090cbf 100644 --- a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.cpp +++ b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.cpp @@ -28,6 +28,6 @@ class Solution { } } ans = max(ans - mi1 + mx1, ans - mi2 + mx2); - return ans % 2 || ans < 0 ? -1 : ans; + return ans < 0 ? -1 : ans; } }; \ No newline at end of file diff --git a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.go b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.go index b0319c30d274..49a2c4f081d1 100644 --- a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.go +++ b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.go @@ -26,7 +26,7 @@ func largestEvenSum(nums []int, k int) int64 { } } ans = max(-1, max(ans-mi1+mx1, ans-mi2+mx2)) - if ans%2 != 0 { + if ans%2 < 0 { return -1 } return int64(ans) diff --git a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.java b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.java index 4a268601e149..0cb10b68b372 100644 --- a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.java +++ b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.java @@ -26,7 +26,7 @@ public long largestEvenSum(int[] nums, int k) { mi1 = nums[i]; } } - ans = Math.max(-1, Math.max(ans - mi1 + mx1, ans - mi2 + mx2)); - return ans % 2 != 0 ? -1 : ans; + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? -1 : ans; } } \ No newline at end of file diff --git a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.py b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.py index ce4ab3bcc3bb..483525449645 100644 --- a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.py +++ b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.py @@ -18,4 +18,4 @@ def largestEvenSum(self, nums: List[int], k: int) -> int: else: mi1 = x ans = max(ans - mi1 + mx1, ans - mi2 + mx2, -1) - return -1 if ans % 2 else ans + return -1 if ans < 0 else ans diff --git a/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.ts b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.ts new file mode 100644 index 000000000000..60a8d46616d5 --- /dev/null +++ b/solution/2000-2099/2098.Subsequence of Size K With the Largest Even Sum/Solution.ts @@ -0,0 +1,32 @@ +function largestEvenSum(nums: number[], k: number): number { + nums.sort((a, b) => a - b); + let ans = 0; + const n = nums.length; + for (let i = 0; i < k; ++i) { + ans += nums[n - i - 1]; + } + if (ans % 2 === 0) { + return ans; + } + const inf = 1 << 29; + let mx1 = -inf, + mx2 = -inf; + for (let i = 0; i < n - k; ++i) { + if (nums[i] % 2 === 1) { + mx1 = nums[i]; + } else { + mx2 = nums[i]; + } + } + let mi1 = inf, + mi2 = inf; + for (let i = n - 1; i >= n - k; --i) { + if (nums[i] % 2 === 1) { + mi2 = nums[i]; + } else { + mi1 = nums[i]; + } + } + ans = Math.max(ans - mi1 + mx1, ans - mi2 + mx2); + return ans < 0 ? -1 : ans; +} diff --git a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README.md b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README.md index f4f49b5bb21a..a0c24322cf7e 100644 --- a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README.md +++ b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README.md @@ -69,7 +69,13 @@ tags: -### 方法一 +### 方法一:排序 + +我们先创建一个索引数组 $\textit{idx}$,数组中的每个元素是数组 $\textit{nums}$ 的下标。然后我们根据数组 $\textit{nums}$ 的值对索引数组 $\textit{idx}$ 进行排序,排序的规则是 $\textit{nums}[i] < \textit{nums}[j]$,其中 $i$ 和 $j$ 是索引数组 $\textit{idx}$ 中的两个下标。 + +排序完成后,我们取索引数组 $\textit{idx}$ 的最后 $k$ 个元素,这 $k$ 个元素对应的就是数组 $\textit{nums}$ 中最大的 $k$ 个元素。然后我们对这 $k$ 个下标进行排序,得到的就是最大的 $k$ 个元素在数组 $\textit{nums}$ 中的顺序。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组的长度。 @@ -78,9 +84,8 @@ tags: ```python class Solution: def maxSubsequence(self, nums: List[int], k: int) -> List[int]: - idx = list(range(len(nums))) - idx.sort(key=lambda i: nums[i]) - return [nums[i] for i in sorted(idx[-k:])] + idx = sorted(range(len(nums)), key=lambda i: nums[i])[-k:] + return [nums[i] for i in sorted(idx)] ``` #### Java @@ -88,64 +93,55 @@ class Solution: ```java class Solution { public int[] maxSubsequence(int[] nums, int k) { - int[] ans = new int[k]; - List idx = new ArrayList<>(); int n = nums.length; + Integer[] idx = new Integer[n]; for (int i = 0; i < n; ++i) { - idx.add(i); + idx[i] = i; } - idx.sort(Comparator.comparingInt(i -> - nums[i])); - int[] t = new int[k]; - for (int i = 0; i < k; ++i) { - t[i] = idx.get(i); - } - Arrays.sort(t); - for (int i = 0; i < k; ++i) { - ans[i] = nums[t[i]]; + Arrays.sort(idx, (i, j) -> nums[i] - nums[j]); + Arrays.sort(idx, n - k, n); + int[] ans = new int[k]; + for (int i = n - k; i < n; ++i) { + ans[i - (n - k)] = nums[idx[i]]; } return ans; } } ``` -#### C++ - -```cpp -class Solution { -public: - vector maxSubsequence(vector& nums, int k) { - int n = nums.size(); - vector> vals; - for (int i = 0; i < n; ++i) vals.push_back({i, nums[i]}); - sort(vals.begin(), vals.end(), [&](auto x1, auto x2) { - return x1.second > x2.second; - }); - sort(vals.begin(), vals.begin() + k); - vector ans; - for (int i = 0; i < k; ++i) ans.push_back(vals[i].second); - return ans; - } -}; -``` - #### Go ```go func maxSubsequence(nums []int, k int) []int { - idx := make([]int, len(nums)) + n := len(nums) + idx := make([]int, n) for i := range idx { idx[i] = i } - sort.Slice(idx, func(i, j int) bool { return nums[idx[i]] > nums[idx[j]] }) - sort.Ints(idx[:k]) + sort.Slice(idx, func(i, j int) bool { return nums[idx[i]] < nums[idx[j]] }) + sort.Ints(idx[n-k:]) ans := make([]int, k) - for i, j := range idx[:k] { - ans[i] = nums[j] + for i := n - k; i < n; i++ { + ans[i-(n-k)] = nums[idx[i]] } return ans } ``` +#### TypeScript + +```ts +function maxSubsequence(nums: number[], k: number): number[] { + const n = nums.length; + const idx: number[] = Array.from({ length: n }, (_, i) => i); + idx.sort((i, j) => nums[i] - nums[j]); + return idx + .slice(n - k) + .sort((i, j) => i - j) + .map(i => nums[i]); +} +``` + diff --git a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README_EN.md b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README_EN.md index 93d2dba9f011..e8465c8bb972 100644 --- a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README_EN.md +++ b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/README_EN.md @@ -70,7 +70,13 @@ Another possible subsequence is [4, 3]. -### Solution 1 +### Solution 1: Sorting + +First, we create an index array $\textit{idx}$, where each element is an index of the array $\textit{nums}$. Then, we sort the index array $\textit{idx}$ based on the values in $\textit{nums}$, with the sorting rule being $\textit{nums}[i] < \textit{nums}[j]$, where $i$ and $j$ are two indices in the index array $\textit{idx}$. + +After sorting, we take the last $k$ elements of the index array $\textit{idx}$. These $k$ elements correspond to the largest $k$ elements in the array $\textit{nums}$. Then, we sort these $k$ indices to get the order of the largest $k$ elements in the array $\textit{nums}$. + +The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array. @@ -79,9 +85,8 @@ Another possible subsequence is [4, 3]. ```python class Solution: def maxSubsequence(self, nums: List[int], k: int) -> List[int]: - idx = list(range(len(nums))) - idx.sort(key=lambda i: nums[i]) - return [nums[i] for i in sorted(idx[-k:])] + idx = sorted(range(len(nums)), key=lambda i: nums[i])[-k:] + return [nums[i] for i in sorted(idx)] ``` #### Java @@ -89,64 +94,55 @@ class Solution: ```java class Solution { public int[] maxSubsequence(int[] nums, int k) { - int[] ans = new int[k]; - List idx = new ArrayList<>(); int n = nums.length; + Integer[] idx = new Integer[n]; for (int i = 0; i < n; ++i) { - idx.add(i); + idx[i] = i; } - idx.sort(Comparator.comparingInt(i -> - nums[i])); - int[] t = new int[k]; - for (int i = 0; i < k; ++i) { - t[i] = idx.get(i); - } - Arrays.sort(t); - for (int i = 0; i < k; ++i) { - ans[i] = nums[t[i]]; + Arrays.sort(idx, (i, j) -> nums[i] - nums[j]); + Arrays.sort(idx, n - k, n); + int[] ans = new int[k]; + for (int i = n - k; i < n; ++i) { + ans[i - (n - k)] = nums[idx[i]]; } return ans; } } ``` -#### C++ - -```cpp -class Solution { -public: - vector maxSubsequence(vector& nums, int k) { - int n = nums.size(); - vector> vals; - for (int i = 0; i < n; ++i) vals.push_back({i, nums[i]}); - sort(vals.begin(), vals.end(), [&](auto x1, auto x2) { - return x1.second > x2.second; - }); - sort(vals.begin(), vals.begin() + k); - vector ans; - for (int i = 0; i < k; ++i) ans.push_back(vals[i].second); - return ans; - } -}; -``` - #### Go ```go func maxSubsequence(nums []int, k int) []int { - idx := make([]int, len(nums)) + n := len(nums) + idx := make([]int, n) for i := range idx { idx[i] = i } - sort.Slice(idx, func(i, j int) bool { return nums[idx[i]] > nums[idx[j]] }) - sort.Ints(idx[:k]) + sort.Slice(idx, func(i, j int) bool { return nums[idx[i]] < nums[idx[j]] }) + sort.Ints(idx[n-k:]) ans := make([]int, k) - for i, j := range idx[:k] { - ans[i] = nums[j] + for i := n - k; i < n; i++ { + ans[i-(n-k)] = nums[idx[i]] } return ans } ``` +#### TypeScript + +```ts +function maxSubsequence(nums: number[], k: number): number[] { + const n = nums.length; + const idx: number[] = Array.from({ length: n }, (_, i) => i); + idx.sort((i, j) => nums[i] - nums[j]); + return idx + .slice(n - k) + .sort((i, j) => i - j) + .map(i => nums[i]); +} +``` + diff --git a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.cpp b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.cpp index fcc326c5028a..60350b1b94b0 100644 --- a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.cpp +++ b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.cpp @@ -2,14 +2,16 @@ class Solution { public: vector maxSubsequence(vector& nums, int k) { int n = nums.size(); - vector> vals; - for (int i = 0; i < n; ++i) vals.push_back({i, nums[i]}); - sort(vals.begin(), vals.end(), [&](auto x1, auto x2) { - return x1.second > x2.second; - }); - sort(vals.begin(), vals.begin() + k); - vector ans; - for (int i = 0; i < k; ++i) ans.push_back(vals[i].second); + vector idx(n); + for (int i = 0; i < n; ++i) { + idx[i] = i; + } + sort(idx.begin(), idx.end(), [&](int i, int j) { return nums[i] < nums[j]; }); + sort(idx.begin() + (n - k), idx.end()); + vector ans(k); + for (int i = n - k; i < n; ++i) { + ans[i - (n - k)] = nums[idx[i]]; + } return ans; } }; \ No newline at end of file diff --git a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.go b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.go index 1c5a5e2a663e..6dac3c53afae 100644 --- a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.go +++ b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.go @@ -1,13 +1,14 @@ func maxSubsequence(nums []int, k int) []int { - idx := make([]int, len(nums)) + n := len(nums) + idx := make([]int, n) for i := range idx { idx[i] = i } - sort.Slice(idx, func(i, j int) bool { return nums[idx[i]] > nums[idx[j]] }) - sort.Ints(idx[:k]) + sort.Slice(idx, func(i, j int) bool { return nums[idx[i]] < nums[idx[j]] }) + sort.Ints(idx[n-k:]) ans := make([]int, k) - for i, j := range idx[:k] { - ans[i] = nums[j] + for i := n - k; i < n; i++ { + ans[i-(n-k)] = nums[idx[i]] } return ans } \ No newline at end of file diff --git a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.java b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.java index 4220a22cbc3c..c4286fe13513 100644 --- a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.java +++ b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.java @@ -1,19 +1,15 @@ class Solution { public int[] maxSubsequence(int[] nums, int k) { - int[] ans = new int[k]; - List idx = new ArrayList<>(); int n = nums.length; + Integer[] idx = new Integer[n]; for (int i = 0; i < n; ++i) { - idx.add(i); - } - idx.sort(Comparator.comparingInt(i -> - nums[i])); - int[] t = new int[k]; - for (int i = 0; i < k; ++i) { - t[i] = idx.get(i); + idx[i] = i; } - Arrays.sort(t); - for (int i = 0; i < k; ++i) { - ans[i] = nums[t[i]]; + Arrays.sort(idx, (i, j) -> nums[i] - nums[j]); + Arrays.sort(idx, n - k, n); + int[] ans = new int[k]; + for (int i = n - k; i < n; ++i) { + ans[i - (n - k)] = nums[idx[i]]; } return ans; } diff --git a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.py b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.py index ed68ad97710d..22f2f72f4b6f 100644 --- a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.py +++ b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.py @@ -1,5 +1,4 @@ class Solution: def maxSubsequence(self, nums: List[int], k: int) -> List[int]: - idx = list(range(len(nums))) - idx.sort(key=lambda i: nums[i]) - return [nums[i] for i in sorted(idx[-k:])] + idx = sorted(range(len(nums)), key=lambda i: nums[i])[-k:] + return [nums[i] for i in sorted(idx)] diff --git a/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.ts b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.ts new file mode 100644 index 000000000000..7a8af12d4545 --- /dev/null +++ b/solution/2000-2099/2099.Find Subsequence of Length K With the Largest Sum/Solution.ts @@ -0,0 +1,9 @@ +function maxSubsequence(nums: number[], k: number): number[] { + const n = nums.length; + const idx: number[] = Array.from({ length: n }, (_, i) => i); + idx.sort((i, j) => nums[i] - nums[j]); + return idx + .slice(n - k) + .sort((i, j) => i - j) + .map(i => nums[i]); +} diff --git a/solution/2100-2199/2101.Detonate the Maximum Bombs/README.md b/solution/2100-2199/2101.Detonate the Maximum Bombs/README.md index 4121be84afe0..2c9dc84bc545 100644 --- a/solution/2100-2199/2101.Detonate the Maximum Bombs/README.md +++ b/solution/2100-2199/2101.Detonate the Maximum Bombs/README.md @@ -90,11 +90,11 @@ tags: 我们定义一个长度为 $n$ 的数组 $g$,其中 $g[i]$ 表示炸弹 $i$ 的爆炸范围内可以引爆的所有炸弹的下标。 -然后,我们遍历所有炸弹,对于两个炸弹 $(x_1, y_1, r_1)$ 和 $(x_2, y_2, r_2)$,我们计算它们之间的距离 $\text{dist} = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}$。如果 $\text{dist} \leq r_1$,那么炸弹 $i$ 的爆炸范围内可以引爆炸弹 $j$,我们就将 $j$ 添加到 $g[i]$ 中。如果 $\text{dist} \leq r_2$,那么炸弹 $j$ 的爆炸范围内可以引爆炸弹 $i$,我们就将 $i$ 添加到 $g[j]$ 中。 +然后,我们遍历所有炸弹,对于两个炸弹 $(x_1, y_1, r_1)$ 和 $(x_2, y_2, r_2)$,我们计算它们之间的距离 $\textit{dist} = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}$。如果 $\textit{dist} \leq r_1$,那么炸弹 $i$ 的爆炸范围内可以引爆炸弹 $j$,我们就将 $j$ 添加到 $g[i]$ 中。如果 $\textit{dist} \leq r_2$,那么炸弹 $j$ 的爆炸范围内可以引爆炸弹 $i$,我们就将 $i$ 添加到 $g[j]$ 中。 接下来,我们遍历所有炸弹,对于每个炸弹 $k$,我们使用广度优先搜索计算炸弹 $k$ 的爆炸范围内可以引爆的所有炸弹的下标,并记录下来。如果这些炸弹的数量等于 $n$,那么我们就可以引爆所有炸弹,直接返回 $n$。否则,我们记录下来这些炸弹的数量,并返回最大值。 -时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为炸弹的数量。 +时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为炸弹的数量。 diff --git a/solution/2100-2199/2101.Detonate the Maximum Bombs/README_EN.md b/solution/2100-2199/2101.Detonate the Maximum Bombs/README_EN.md index 56cd25ab4440..247bc7976b1a 100644 --- a/solution/2100-2199/2101.Detonate the Maximum Bombs/README_EN.md +++ b/solution/2100-2199/2101.Detonate the Maximum Bombs/README_EN.md @@ -85,11 +85,11 @@ Thus all 5 bombs are detonated. We define an array $g$ of length $n$, where $g[i]$ represents the indices of all bombs that can be triggered by bomb $i$ within its explosion range. -Next, we iterate over all bombs. For two bombs $(x_1, y_1, r_1)$ and $(x_2, y_2, r_2)$, we calculate the distance between them $\text{dist} = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}$. If $\text{dist} \leq r_1$, then bomb $i$ can trigger bomb $j$ within its explosion range, so we add $j$ to $g[i]$. If $\text{dist} \leq r_2$, then bomb $j$ can trigger bomb $i$ within its explosion range, so we add $i$ to $g[j]$. +Next, we iterate over all bombs. For two bombs $(x_1, y_1, r_1)$ and $(x_2, y_2, r_2)$, we calculate the distance between them $\textit{dist} = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}$. If $\textit{dist} \leq r_1$, then bomb $i$ can trigger bomb $j$ within its explosion range, so we add $j$ to $g[i]$. If $\textit{dist} \leq r_2$, then bomb $j$ can trigger bomb $i$ within its explosion range, so we add $i$ to $g[j]$. Next, we iterate over all bombs. For each bomb $k$, we use breadth-first search to calculate the indices of all bombs that can be triggered by bomb $k$ within its explosion range and record them. If the number of these bombs equals $n$, then we can trigger all bombs and directly return $n$. Otherwise, we record the number of these bombs and return the maximum value. -The time complexity is $O(n^2)$ and the space complexity is $O(n^2)$, where $n$ is the number of bombs. +The time complexity is $O(n^3)$ and the space complexity is $O(n^2)$, where $n$ is the number of bombs. diff --git a/solution/2100-2199/2105.Watering Plants II/README.md b/solution/2100-2199/2105.Watering Plants II/README.md index 0e26c1bfe8e9..06db9282fa10 100644 --- a/solution/2100-2199/2105.Watering Plants II/README.md +++ b/solution/2100-2199/2105.Watering Plants II/README.md @@ -88,7 +88,7 @@ tags: ### 方法一:双指针 + 模拟 -我们用两个变量 $a$ 和 $b$ 分别表示 Alice 和 Bob 的水量,初始时 $a = \text{capacityA}$, $b = \text{capacityB}$。然后用两个指针 $i$ 和 $j$ 分别指向植物数组的头尾,然后模拟 Alice 和 Bob 从两端向中间浇水的过程。 +我们用两个变量 $a$ 和 $b$ 分别表示 Alice 和 Bob 的水量,初始时 $a = \textit{capacityA}$, $b = \textit{capacityB}$。然后用两个指针 $i$ 和 $j$ 分别指向植物数组的头尾,然后模拟 Alice 和 Bob 从两端向中间浇水的过程。 当 $i < j$ 时,我们分别判断 Alice 和 Bob 的水量是否足够浇水,如果不够,我们就重新灌满水罐。然后更新 $a$ 和 $b$ 的水量,同时移动指针 $i$ 和 $j$。最后我们还需要判断 $i$ 和 $j$ 是否相等,如果相等,我们还需要判断 $\max(a, b)$ 是否小于植物的水量,如果小于,我们需要再次重新灌满水罐。 diff --git a/solution/2100-2199/2105.Watering Plants II/README_EN.md b/solution/2100-2199/2105.Watering Plants II/README_EN.md index 9667b8f70b25..42b3a76e27e4 100644 --- a/solution/2100-2199/2105.Watering Plants II/README_EN.md +++ b/solution/2100-2199/2105.Watering Plants II/README_EN.md @@ -89,7 +89,7 @@ So, the total number of times they have to refill is 0. ### Solution 1: Two Pointers + Simulation -We use two variables $a$ and $b$ to represent the amount of water Alice and Bob have, initially $a = \text{capacityA}$, $b = \text{capacityB}$. Then we use two pointers $i$ and $j$ to point to the head and tail of the plant array, and simulate the process of Alice and Bob watering from both ends to the middle. +We use two variables $a$ and $b$ to represent the amount of water Alice and Bob have, initially $a = \textit{capacityA}$, $b = \textit{capacityB}$. Then we use two pointers $i$ and $j$ to point to the head and tail of the plant array, and simulate the process of Alice and Bob watering from both ends to the middle. When $i < j$, we judge whether Alice and Bob have enough water to water the plants. If not, we refill the watering cans. Then we update the amount of water $a$ and $b$, and move the pointers $i$ and $j$. Finally, we need to judge whether $i$ and $j$ are equal. If they are equal, we need to judge whether $\max(a, b)$ is less than the amount of water the plant needs. If it is less, we need to refill the watering cans again. diff --git a/solution/2100-2199/2109.Adding Spaces to a String/README.md b/solution/2100-2199/2109.Adding Spaces to a String/README.md index 4f75e2efc33f..e0125ea6d600 100644 --- a/solution/2100-2199/2109.Adding Spaces to a String/README.md +++ b/solution/2100-2199/2109.Adding Spaces to a String/README.md @@ -82,7 +82,7 @@ tags: ### 方法一:双指针 -我们可以用双指针 $i$ 和 $j$ 分别指向字符串 $s$ 和数组 $\text{spaces}$ 的头部,然后从头到尾遍历字符串 $s$,当 $i$ 等于 $\text{spaces}[j]$ 时,我们往结果字符串中添加一个空格,然后 $j$ 自增 $1$。接下来,我们将 $s[i]$ 添加到结果字符串中,然后 $i$ 自增 $1$。继续这个过程,直到遍历完字符串 $s$。 +我们可以用双指针 $i$ 和 $j$ 分别指向字符串 $s$ 和数组 $\textit{spaces}$ 的头部,然后从头到尾遍历字符串 $s$,当 $i$ 等于 $\textit{spaces}[j]$ 时,我们往结果字符串中添加一个空格,然后 $j$ 自增 $1$。接下来,我们将 $s[i]$ 添加到结果字符串中,然后 $i$ 自增 $1$。继续这个过程,直到遍历完字符串 $s$。 时间复杂度 $O(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是字符串 $s$ 和数组 $spaces$ 的长度。 diff --git a/solution/2100-2199/2109.Adding Spaces to a String/README_EN.md b/solution/2100-2199/2109.Adding Spaces to a String/README_EN.md index 5b2b1df3dc77..80a9bde8db1f 100644 --- a/solution/2100-2199/2109.Adding Spaces to a String/README_EN.md +++ b/solution/2100-2199/2109.Adding Spaces to a String/README_EN.md @@ -78,7 +78,7 @@ We are also able to place spaces before the first character of the string. ### Solution 1: Two Pointers -We can use two pointers $i$ and $j$ to point to the beginning of the string $s$ and the array $\text{spaces}$, respectively. Then, we iterate through the string $s$ from the beginning to the end. When $i$ equals $\text{spaces}[j]$, we add a space to the result string, and then increment $j$ by $1$. Next, we add $s[i]$ to the result string, and then increment $i$ by $1$. We continue this process until we have iterated through the entire string $s$. +We can use two pointers $i$ and $j$ to point to the beginning of the string $s$ and the array $\textit{spaces}$, respectively. Then, we iterate through the string $s$ from the beginning to the end. When $i$ equals $\textit{spaces}[j]$, we add a space to the result string, and then increment $j$ by $1$. Next, we add $s[i]$ to the result string, and then increment $i$ by $1$. We continue this process until we have iterated through the entire string $s$. The time complexity is $O(n + m)$, and the space complexity is $O(n + m)$, where $n$ and $m$ are the lengths of the string $s$ and the array $spaces$, respectively. diff --git a/solution/2100-2199/2122.Recover the Original Array/README.md b/solution/2100-2199/2122.Recover the Original Array/README.md index 958bb9fda703..c23dc5f4956c 100644 --- a/solution/2100-2199/2122.Recover the Original Array/README.md +++ b/solution/2100-2199/2122.Recover the Original Array/README.md @@ -7,6 +7,7 @@ source: 第 273 场周赛 Q4 tags: - 数组 - 哈希表 + - 双指针 - 枚举 - 排序 --- diff --git a/solution/2100-2199/2122.Recover the Original Array/README_EN.md b/solution/2100-2199/2122.Recover the Original Array/README_EN.md index b96a6c1b200b..1e91a07ee2b4 100644 --- a/solution/2100-2199/2122.Recover the Original Array/README_EN.md +++ b/solution/2100-2199/2122.Recover the Original Array/README_EN.md @@ -7,6 +7,7 @@ source: Weekly Contest 273 Q4 tags: - Array - Hash Table + - Two Pointers - Enumeration - Sorting --- diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md index 3cb82b49879c..72be8ac8af7a 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README.md @@ -92,9 +92,9 @@ tags: 我们注意到,题目中给定的字符串只包含小写字母,并且每个字符串的字母至多出现一次。因此,我们可以用一个长度为 $26$ 的二进制数表示一个字符串,其中第 $i$ 位为 $1$ 表示字符串中包含第 $i$ 个小写字母,为 $0$ 表示字符串中不包含第 $i$ 个小写字母。 -我们可以将字符串数组 $\text{startWords}$ 中的每个字符串转换为一个二进制数,并将这些二进制数存储到一个集合 $\text{s}$ 中。对于字符串数组 $\text{targetWords}$ 中的每个字符串,我们首先将其转换为一个二进制数,然后枚举这个字符串中的每个字母,将这个字母从二进制数中去掉,再检查是否存在一个二进制数在集合 $\text{s}$ 中,使得这个二进制数与去掉的字母的二进制数的异或结果在集合 $\text{s}$ 中,如果存在,那么这个字符串可以由 $\text{startWords}$ 中的某个字符串执行转换操作获得,答案加一。然后我们跳过这个字符串,继续处理下一个字符串。 +我们可以将字符串数组 $\textit{startWords}$ 中的每个字符串转换为一个二进制数,并将这些二进制数存储到一个集合 $\textit{s}$ 中。对于字符串数组 $\textit{targetWords}$ 中的每个字符串,我们首先将其转换为一个二进制数,然后枚举这个字符串中的每个字母,将这个字母从二进制数中去掉,再检查是否存在一个二进制数在集合 $\textit{s}$ 中,使得这个二进制数与去掉的字母的二进制数的异或结果在集合 $\textit{s}$ 中,如果存在,那么这个字符串可以由 $\textit{startWords}$ 中的某个字符串执行转换操作获得,答案加一。然后我们跳过这个字符串,继续处理下一个字符串。 -时间复杂度 $O(n \times |\Sigma|)$,空间复杂度 $O(n)$。其中 $n$ 为字符串数组 $\text{targetWords}$ 的长度,而 $|\Sigma|$ 为字符串中的字符集大小,本题中 $|\Sigma| = 26$。 +时间复杂度 $O(n \times |\Sigma|)$,空间复杂度 $O(n)$。其中 $n$ 为字符串数组 $\textit{targetWords}$ 的长度,而 $|\Sigma|$ 为字符串中的字符集大小,本题中 $|\Sigma| = 26$。 diff --git a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md index ed5472a92d16..6f6fbf58081e 100644 --- a/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md +++ b/solution/2100-2199/2135.Count Words Obtained After Adding a Letter/README_EN.md @@ -90,9 +90,9 @@ tags: We notice that the given strings only contain lowercase letters, and each letter in a string appears at most once. Therefore, we can represent a string with a binary number of length $26$, where the $i$-th bit being $1$ indicates that the string contains the $i$-th lowercase letter, and $0$ indicates the absence of the $i$-th lowercase letter. -We can convert each string in the array $\text{startWords}$ into a binary number and store these binary numbers in a set $\text{s}$. For each string in the array $\text{targetWords}$, we first convert it into a binary number, then enumerate each letter in this string, remove this letter from the binary number, and check if there exists a binary number in the set $\text{s}$ such that the XOR result of this binary number with the removed letter's binary number is in the set $\text{s}$. If such a binary number exists, then this string can be obtained by performing a transformation operation on some string in $\text{startWords}$, and we increment the answer by one. Then, we skip this string and continue processing the next string. +We can convert each string in the array $\textit{startWords}$ into a binary number and store these binary numbers in a set $\textit{s}$. For each string in the array $\textit{targetWords}$, we first convert it into a binary number, then enumerate each letter in this string, remove this letter from the binary number, and check if there exists a binary number in the set $\textit{s}$ such that the XOR result of this binary number with the removed letter's binary number is in the set $\textit{s}$. If such a binary number exists, then this string can be obtained by performing a transformation operation on some string in $\textit{startWords}$, and we increment the answer by one. Then, we skip this string and continue processing the next string. -The time complexity is $O(n \times |\Sigma|)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string array $\text{targetWords}$, and $|\Sigma|$ is the size of the character set in the string, which is $26$ in this problem. +The time complexity is $O(n \times |\Sigma|)$, and the space complexity is $O(n)$. Here, $n$ is the length of the string array $\textit{targetWords}$, and $|\Sigma|$ is the size of the character set in the string, which is $26$ in this problem. diff --git a/solution/2100-2199/2138.Divide a String Into Groups of Size k/README.md b/solution/2100-2199/2138.Divide a String Into Groups of Size k/README.md index e6b38a5adcbe..ead465936994 100644 --- a/solution/2100-2199/2138.Divide a String Into Groups of Size k/README.md +++ b/solution/2100-2199/2138.Divide a String Into Groups of Size k/README.md @@ -73,7 +73,7 @@ tags: ### 方法一:模拟 -我们可以直接模拟题目描述的过程,将字符串 $s$ 按照长度 $k$ 进行分组,然后对于最后一组不足 $k$ 个字符的情况,使用字符 $\text{fill}$ 进行填充。 +我们可以直接模拟题目描述的过程,将字符串 $s$ 按照长度 $k$ 进行分组,然后对于最后一组不足 $k$ 个字符的情况,使用字符 $\textit{fill}$ 进行填充。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。 diff --git a/solution/2100-2199/2138.Divide a String Into Groups of Size k/README_EN.md b/solution/2100-2199/2138.Divide a String Into Groups of Size k/README_EN.md index 93ce54ac04d5..80acdefcd317 100644 --- a/solution/2100-2199/2138.Divide a String Into Groups of Size k/README_EN.md +++ b/solution/2100-2199/2138.Divide a String Into Groups of Size k/README_EN.md @@ -73,7 +73,7 @@ Thus, the 4 groups formed are "abc", "def", "ghi", ### Solution 1: Simulation -We can directly simulate the process described in the problem statement, dividing the string $s$ into groups of length $k$. For the last group, if it contains fewer than $k$ characters, we use the character $\text{fill}$ to pad it. +We can directly simulate the process described in the problem statement, dividing the string $s$ into groups of length $k$. For the last group, if it contains fewer than $k$ characters, we use the character $\textit{fill}$ to pad it. The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $s$. diff --git a/solution/2100-2199/2149.Rearrange Array Elements by Sign/README.md b/solution/2100-2199/2149.Rearrange Array Elements by Sign/README.md index ef55109061bb..f0d2d3f0ca2a 100644 --- a/solution/2100-2199/2149.Rearrange Array Elements by Sign/README.md +++ b/solution/2100-2199/2149.Rearrange Array Elements by Sign/README.md @@ -76,7 +76,15 @@ nums 中的正整数是 [3,1,2] ,负整数是 [-2,-5,-4] 。 -### 方法一 +### 方法一:双指针 + +我们先创建一个长度为 $n$ 的数组 $\textit{ans}$,然后使用两个指针 $i$ 和 $j$ 分别指向 $\textit{ans}$ 的偶数下标和奇数下标,初始时 $i = 0$, $j = 1$。 + +遍历数组 $\textit{nums}$,如果当前元素 $x$ 为正整数,则将 $x$ 放入 $\textit{ans}[i]$,并将 $i$ 增加 $2$;否则将 $x$ 放入 $\textit{ans}[j]$,并将 $j$ 增加 $2$。 + +最后返回 $\textit{ans}$ 即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -87,12 +95,12 @@ class Solution: def rearrangeArray(self, nums: List[int]) -> List[int]: ans = [0] * len(nums) i, j = 0, 1 - for num in nums: - if num > 0: - ans[i] = num + for x in nums: + if x > 0: + ans[i] = x i += 2 else: - ans[j] = num + ans[j] = x j += 2 return ans ``` @@ -101,16 +109,15 @@ class Solution: ```java class Solution { - public int[] rearrangeArray(int[] nums) { int[] ans = new int[nums.length]; int i = 0, j = 1; - for (int num : nums) { - if (num > 0) { - ans[i] = num; + for (int x : nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } @@ -127,12 +134,12 @@ public: vector rearrangeArray(vector& nums) { vector ans(nums.size()); int i = 0, j = 1; - for (int num : nums) { - if (num > 0) { - ans[i] = num; + for (int x : nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } @@ -147,12 +154,12 @@ public: func rearrangeArray(nums []int) []int { ans := make([]int, len(nums)) i, j := 0, 1 - for _, num := range nums { - if num > 0 { - ans[i] = num + for _, x := range nums { + if x > 0 { + ans[i] = x i += 2 } else { - ans[j] = num + ans[j] = x j += 2 } } @@ -164,15 +171,14 @@ func rearrangeArray(nums []int) []int { ```ts function rearrangeArray(nums: number[]): number[] { - let ans = []; - let i = 0, - j = 1; - for (let num of nums) { - if (num > 0) { - ans[i] = num; + const ans: number[] = Array(nums.length); + let [i, j] = [0, 1]; + for (const x of nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } diff --git a/solution/2100-2199/2149.Rearrange Array Elements by Sign/README_EN.md b/solution/2100-2199/2149.Rearrange Array Elements by Sign/README_EN.md index e7b040c53704..efaf2d931dd3 100644 --- a/solution/2100-2199/2149.Rearrange Array Elements by Sign/README_EN.md +++ b/solution/2100-2199/2149.Rearrange Array Elements by Sign/README_EN.md @@ -73,7 +73,15 @@ It is not required to do the modifications in-place. -### Solution 1 +### Solution 1: Two Pointers + +First, we create an array $\textit{ans}$ of length $n$. Then, we use two pointers $i$ and $j$ to point to the even and odd indices of $\textit{ans}$, respectively, with initial values $i = 0$, $j = 1$. + +We iterate through the array $\textit{nums}$. If the current element $x$ is a positive integer, then we place $x$ into $\textit{ans}[i]$ and increase $i$ by $2$; otherwise, we place $x$ into $\textit{ans}[j]$ and increase $j$ by $2$. + +Finally, we return $\textit{ans}$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -84,12 +92,12 @@ class Solution: def rearrangeArray(self, nums: List[int]) -> List[int]: ans = [0] * len(nums) i, j = 0, 1 - for num in nums: - if num > 0: - ans[i] = num + for x in nums: + if x > 0: + ans[i] = x i += 2 else: - ans[j] = num + ans[j] = x j += 2 return ans ``` @@ -98,16 +106,15 @@ class Solution: ```java class Solution { - public int[] rearrangeArray(int[] nums) { int[] ans = new int[nums.length]; int i = 0, j = 1; - for (int num : nums) { - if (num > 0) { - ans[i] = num; + for (int x : nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } @@ -124,12 +131,12 @@ public: vector rearrangeArray(vector& nums) { vector ans(nums.size()); int i = 0, j = 1; - for (int num : nums) { - if (num > 0) { - ans[i] = num; + for (int x : nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } @@ -144,12 +151,12 @@ public: func rearrangeArray(nums []int) []int { ans := make([]int, len(nums)) i, j := 0, 1 - for _, num := range nums { - if num > 0 { - ans[i] = num + for _, x := range nums { + if x > 0 { + ans[i] = x i += 2 } else { - ans[j] = num + ans[j] = x j += 2 } } @@ -161,15 +168,14 @@ func rearrangeArray(nums []int) []int { ```ts function rearrangeArray(nums: number[]): number[] { - let ans = []; - let i = 0, - j = 1; - for (let num of nums) { - if (num > 0) { - ans[i] = num; + const ans: number[] = Array(nums.length); + let [i, j] = [0, 1]; + for (const x of nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } diff --git a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.cpp b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.cpp index 3cf5a6c6805d..ef006cab32ae 100644 --- a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.cpp +++ b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.cpp @@ -3,12 +3,12 @@ class Solution { vector rearrangeArray(vector& nums) { vector ans(nums.size()); int i = 0, j = 1; - for (int num : nums) { - if (num > 0) { - ans[i] = num; + for (int x : nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } diff --git a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.go b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.go index 21dc6cb2ea3a..69a4188de246 100644 --- a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.go +++ b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.go @@ -1,12 +1,12 @@ func rearrangeArray(nums []int) []int { ans := make([]int, len(nums)) i, j := 0, 1 - for _, num := range nums { - if num > 0 { - ans[i] = num + for _, x := range nums { + if x > 0 { + ans[i] = x i += 2 } else { - ans[j] = num + ans[j] = x j += 2 } } diff --git a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.java b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.java index e93356096877..2da89d9ca372 100644 --- a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.java +++ b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.java @@ -1,14 +1,13 @@ class Solution { - public int[] rearrangeArray(int[] nums) { int[] ans = new int[nums.length]; int i = 0, j = 1; - for (int num : nums) { - if (num > 0) { - ans[i] = num; + for (int x : nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } diff --git a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.py b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.py index 54a7aff4a005..7ec9860e76f4 100644 --- a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.py +++ b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.py @@ -2,11 +2,11 @@ class Solution: def rearrangeArray(self, nums: List[int]) -> List[int]: ans = [0] * len(nums) i, j = 0, 1 - for num in nums: - if num > 0: - ans[i] = num + for x in nums: + if x > 0: + ans[i] = x i += 2 else: - ans[j] = num + ans[j] = x j += 2 return ans diff --git a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.ts b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.ts index b8e40aee94d3..c9f9c64e12ac 100644 --- a/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.ts +++ b/solution/2100-2199/2149.Rearrange Array Elements by Sign/Solution.ts @@ -1,13 +1,12 @@ function rearrangeArray(nums: number[]): number[] { - let ans = []; - let i = 0, - j = 1; - for (let num of nums) { - if (num > 0) { - ans[i] = num; + const ans: number[] = Array(nums.length); + let [i, j] = [0, 1]; + for (const x of nums) { + if (x > 0) { + ans[i] = x; i += 2; } else { - ans[j] = num; + ans[j] = x; j += 2; } } diff --git a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README.md b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README.md index 30ca9fd942ca..6a8a3a4ac525 100644 --- a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README.md +++ b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README.md @@ -64,7 +64,13 @@ tags: -### 方法一 +### 方法一:哈希表 + +我们用一个哈希表 $\textit{cnt}$ 记录每个数字出现的次数,然后遍历哈希表,对于每个数字及其出现次数 $(x, v)$,如果 $v = 1$ 且 $\textit{cnt}[x - 1] = 0$ 且 $\textit{cnt}[x + 1] = 0$,则 $x$ 是一个孤独数字,将其加入答案数组中。 + +遍历结束后,返回答案数组即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -73,30 +79,28 @@ tags: ```python class Solution: def findLonely(self, nums: List[int]) -> List[int]: - counter = Counter(nums) - ans = [] - for num, cnt in counter.items(): - if cnt == 1 and counter[num - 1] == 0 and counter[num + 1] == 0: - ans.append(num) - return ans + cnt = Counter(nums) + return [ + x for x, v in cnt.items() if v == 1 and cnt[x - 1] == 0 and cnt[x + 1] == 0 + ] ``` #### Java ```java class Solution { - public List findLonely(int[] nums) { - Map counter = new HashMap<>(); - for (int num : nums) { - counter.put(num, counter.getOrDefault(num, 0) + 1); + Map cnt = new HashMap<>(); + for (int x : nums) { + cnt.merge(x, 1, Integer::sum); } List ans = new ArrayList<>(); - counter.forEach((k, v) -> { - if (v == 1 && !counter.containsKey(k - 1) && !counter.containsKey(k + 1)) { - ans.add(k); + for (var e : cnt.entrySet()) { + int x = e.getKey(), v = e.getValue(); + if (v == 1 && !cnt.containsKey(x - 1) && !cnt.containsKey(x + 1)) { + ans.add(x); } - }); + } return ans; } } @@ -108,12 +112,15 @@ class Solution { class Solution { public: vector findLonely(vector& nums) { - unordered_map counter; - for (int num : nums) ++counter[num]; + unordered_map cnt; + for (int x : nums) { + cnt[x]++; + } vector ans; - for (auto& e : counter) { - int k = e.first, v = e.second; - if (v == 1 && !counter.count(k - 1) && !counter.count(k + 1)) ans.push_back(k); + for (auto& [x, v] : cnt) { + if (v == 1 && !cnt.contains(x - 1) && !cnt.contains(x + 1)) { + ans.push_back(x); + } } return ans; } @@ -123,18 +130,17 @@ public: #### Go ```go -func findLonely(nums []int) []int { - counter := make(map[int]int) - for _, num := range nums { - counter[num]++ +func findLonely(nums []int) (ans []int) { + cnt := map[int]int{} + for _, x := range nums { + cnt[x]++ } - var ans []int - for k, v := range counter { - if v == 1 && counter[k-1] == 0 && counter[k+1] == 0 { - ans = append(ans, k) + for x, v := range cnt { + if v == 1 && cnt[x-1] == 0 && cnt[x+1] == 0 { + ans = append(ans, x) } } - return ans + return } ``` @@ -142,14 +148,14 @@ func findLonely(nums []int) []int { ```ts function findLonely(nums: number[]): number[] { - let hashMap: Map = new Map(); - for (let num of nums) { - hashMap.set(num, (hashMap.get(num) || 0) + 1); + const cnt: Map = new Map(); + for (const x of nums) { + cnt.set(x, (cnt.get(x) || 0) + 1); } - let ans: Array = []; - for (let [num, count] of hashMap.entries()) { - if (count == 1 && !hashMap.get(num - 1) && !hashMap.get(num + 1)) { - ans.push(num); + const ans: number[] = []; + for (const [x, v] of cnt) { + if (v === 1 && !cnt.has(x - 1) && !cnt.has(x + 1)) { + ans.push(x); } } return ans; diff --git a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README_EN.md b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README_EN.md index bc490d0563c9..8905b9d5fb93 100644 --- a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README_EN.md +++ b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/README_EN.md @@ -65,7 +65,13 @@ Note that [5, 1] may also be returned. -### Solution 1 +### Solution 1: Hash Table + +We use a hash table $\textit{cnt}$ to record the occurrence count of each number. Then, we iterate through the hash table. For each number and its occurrence count $(x, v)$, if $v = 1$ and $\textit{cnt}[x - 1] = 0$ and $\textit{cnt}[x + 1] = 0$, then $x$ is a lonely number, and we add it to the answer array. + +After finishing the iteration, we return the answer array. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -74,30 +80,28 @@ Note that [5, 1] may also be returned. ```python class Solution: def findLonely(self, nums: List[int]) -> List[int]: - counter = Counter(nums) - ans = [] - for num, cnt in counter.items(): - if cnt == 1 and counter[num - 1] == 0 and counter[num + 1] == 0: - ans.append(num) - return ans + cnt = Counter(nums) + return [ + x for x, v in cnt.items() if v == 1 and cnt[x - 1] == 0 and cnt[x + 1] == 0 + ] ``` #### Java ```java class Solution { - public List findLonely(int[] nums) { - Map counter = new HashMap<>(); - for (int num : nums) { - counter.put(num, counter.getOrDefault(num, 0) + 1); + Map cnt = new HashMap<>(); + for (int x : nums) { + cnt.merge(x, 1, Integer::sum); } List ans = new ArrayList<>(); - counter.forEach((k, v) -> { - if (v == 1 && !counter.containsKey(k - 1) && !counter.containsKey(k + 1)) { - ans.add(k); + for (var e : cnt.entrySet()) { + int x = e.getKey(), v = e.getValue(); + if (v == 1 && !cnt.containsKey(x - 1) && !cnt.containsKey(x + 1)) { + ans.add(x); } - }); + } return ans; } } @@ -109,12 +113,15 @@ class Solution { class Solution { public: vector findLonely(vector& nums) { - unordered_map counter; - for (int num : nums) ++counter[num]; + unordered_map cnt; + for (int x : nums) { + cnt[x]++; + } vector ans; - for (auto& e : counter) { - int k = e.first, v = e.second; - if (v == 1 && !counter.count(k - 1) && !counter.count(k + 1)) ans.push_back(k); + for (auto& [x, v] : cnt) { + if (v == 1 && !cnt.contains(x - 1) && !cnt.contains(x + 1)) { + ans.push_back(x); + } } return ans; } @@ -124,18 +131,17 @@ public: #### Go ```go -func findLonely(nums []int) []int { - counter := make(map[int]int) - for _, num := range nums { - counter[num]++ +func findLonely(nums []int) (ans []int) { + cnt := map[int]int{} + for _, x := range nums { + cnt[x]++ } - var ans []int - for k, v := range counter { - if v == 1 && counter[k-1] == 0 && counter[k+1] == 0 { - ans = append(ans, k) + for x, v := range cnt { + if v == 1 && cnt[x-1] == 0 && cnt[x+1] == 0 { + ans = append(ans, x) } } - return ans + return } ``` @@ -143,14 +149,14 @@ func findLonely(nums []int) []int { ```ts function findLonely(nums: number[]): number[] { - let hashMap: Map = new Map(); - for (let num of nums) { - hashMap.set(num, (hashMap.get(num) || 0) + 1); + const cnt: Map = new Map(); + for (const x of nums) { + cnt.set(x, (cnt.get(x) || 0) + 1); } - let ans: Array = []; - for (let [num, count] of hashMap.entries()) { - if (count == 1 && !hashMap.get(num - 1) && !hashMap.get(num + 1)) { - ans.push(num); + const ans: number[] = []; + for (const [x, v] of cnt) { + if (v === 1 && !cnt.has(x - 1) && !cnt.has(x + 1)) { + ans.push(x); } } return ans; diff --git a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.cpp b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.cpp index 4cdb56deec98..49e8ae3b1871 100644 --- a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.cpp +++ b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.cpp @@ -1,12 +1,15 @@ class Solution { public: vector findLonely(vector& nums) { - unordered_map counter; - for (int num : nums) ++counter[num]; + unordered_map cnt; + for (int x : nums) { + cnt[x]++; + } vector ans; - for (auto& e : counter) { - int k = e.first, v = e.second; - if (v == 1 && !counter.count(k - 1) && !counter.count(k + 1)) ans.push_back(k); + for (auto& [x, v] : cnt) { + if (v == 1 && !cnt.contains(x - 1) && !cnt.contains(x + 1)) { + ans.push_back(x); + } } return ans; } diff --git a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.go b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.go index d8f651526bc1..380a25d4b828 100644 --- a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.go +++ b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.go @@ -1,13 +1,12 @@ -func findLonely(nums []int) []int { - counter := make(map[int]int) - for _, num := range nums { - counter[num]++ +func findLonely(nums []int) (ans []int) { + cnt := map[int]int{} + for _, x := range nums { + cnt[x]++ } - var ans []int - for k, v := range counter { - if v == 1 && counter[k-1] == 0 && counter[k+1] == 0 { - ans = append(ans, k) + for x, v := range cnt { + if v == 1 && cnt[x-1] == 0 && cnt[x+1] == 0 { + ans = append(ans, x) } } - return ans + return } \ No newline at end of file diff --git a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.java b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.java index 6ac1cd88650c..34a22b0321da 100644 --- a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.java +++ b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.java @@ -1,16 +1,16 @@ class Solution { - public List findLonely(int[] nums) { - Map counter = new HashMap<>(); - for (int num : nums) { - counter.put(num, counter.getOrDefault(num, 0) + 1); + Map cnt = new HashMap<>(); + for (int x : nums) { + cnt.merge(x, 1, Integer::sum); } List ans = new ArrayList<>(); - counter.forEach((k, v) -> { - if (v == 1 && !counter.containsKey(k - 1) && !counter.containsKey(k + 1)) { - ans.add(k); + for (var e : cnt.entrySet()) { + int x = e.getKey(), v = e.getValue(); + if (v == 1 && !cnt.containsKey(x - 1) && !cnt.containsKey(x + 1)) { + ans.add(x); } - }); + } return ans; } } \ No newline at end of file diff --git a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.py b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.py index 6bc384044f1a..945eea586c78 100644 --- a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.py +++ b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.py @@ -1,8 +1,6 @@ class Solution: def findLonely(self, nums: List[int]) -> List[int]: - counter = Counter(nums) - ans = [] - for num, cnt in counter.items(): - if cnt == 1 and counter[num - 1] == 0 and counter[num + 1] == 0: - ans.append(num) - return ans + cnt = Counter(nums) + return [ + x for x, v in cnt.items() if v == 1 and cnt[x - 1] == 0 and cnt[x + 1] == 0 + ] diff --git a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.ts b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.ts index 44c85163005a..561ea0f3cfb7 100644 --- a/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.ts +++ b/solution/2100-2199/2150.Find All Lonely Numbers in the Array/Solution.ts @@ -1,12 +1,12 @@ function findLonely(nums: number[]): number[] { - let hashMap: Map = new Map(); - for (let num of nums) { - hashMap.set(num, (hashMap.get(num) || 0) + 1); + const cnt: Map = new Map(); + for (const x of nums) { + cnt.set(x, (cnt.get(x) || 0) + 1); } - let ans: Array = []; - for (let [num, count] of hashMap.entries()) { - if (count == 1 && !hashMap.get(num - 1) && !hashMap.get(num + 1)) { - ans.push(num); + const ans: number[] = []; + for (const [x, v] of cnt) { + if (v === 1 && !cnt.has(x - 1) && !cnt.has(x + 1)) { + ans.push(x); } } return ans; diff --git a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README.md b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README.md index bca847888e4c..f4af2f9077b3 100644 --- a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README.md +++ b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README.md @@ -71,7 +71,13 @@ tags: -### 方法一 +### 方法一:哈希表 + +我们用一个哈希表 $\textit{s}$ 记录数组 $\textit{nums}$ 中的所有数字。 + +接下来,我们从 $\textit{original}$ 开始,如果 $\textit{original}$ 在 $\textit{s}$ 中,我们将 $\textit{original}$ 乘以 $2$,直到 $\textit{original}$ 不在 $\textit{s}$ 中,返回 $\textit{original}$。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 @@ -110,9 +116,10 @@ class Solution { class Solution { public: int findFinalValue(vector& nums, int original) { - unordered_set s; - for (int num : nums) s.insert(num); - while (s.count(original)) original <<= 1; + unordered_set s(nums.begin(), nums.end()); + while (s.contains(original)) { + original <<= 1; + } return original; } }; @@ -122,9 +129,9 @@ public: ```go func findFinalValue(nums []int, original int) int { - s := make(map[int]bool) - for _, num := range nums { - s[num] = true + s := map[int]bool{} + for _, x := range nums { + s[x] = true } for s[original] { original <<= 1 @@ -137,9 +144,9 @@ func findFinalValue(nums []int, original int) int { ```ts function findFinalValue(nums: number[], original: number): number { - let set: Set = new Set(nums); - while (set.has(original)) { - original *= 2; + const s: Set = new Set([...nums]); + while (s.has(original)) { + original <<= 1; } return original; } diff --git a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README_EN.md b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README_EN.md index 98b26eff9d52..6d4f23cb49bf 100644 --- a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README_EN.md +++ b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/README_EN.md @@ -69,7 +69,13 @@ tags: -### Solution 1 +### Solution 1: Hash Table + +We use a hash table $\textit{s}$ to record all the numbers in the array $\textit{nums}$. + +Next, starting from $\textit{original}$, if $\textit{original}$ is in $\textit{s}$, we multiply $\textit{original}$ by $2$ until $\textit{original}$ is not in $\textit{s}$ anymore, then return $\textit{original}$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -108,9 +114,10 @@ class Solution { class Solution { public: int findFinalValue(vector& nums, int original) { - unordered_set s; - for (int num : nums) s.insert(num); - while (s.count(original)) original <<= 1; + unordered_set s(nums.begin(), nums.end()); + while (s.contains(original)) { + original <<= 1; + } return original; } }; @@ -120,9 +127,9 @@ public: ```go func findFinalValue(nums []int, original int) int { - s := make(map[int]bool) - for _, num := range nums { - s[num] = true + s := map[int]bool{} + for _, x := range nums { + s[x] = true } for s[original] { original <<= 1 @@ -135,9 +142,9 @@ func findFinalValue(nums []int, original int) int { ```ts function findFinalValue(nums: number[], original: number): number { - let set: Set = new Set(nums); - while (set.has(original)) { - original *= 2; + const s: Set = new Set([...nums]); + while (s.has(original)) { + original <<= 1; } return original; } diff --git a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.cpp b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.cpp index 230789e06eb0..49f771e205d5 100644 --- a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.cpp +++ b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.cpp @@ -1,9 +1,10 @@ class Solution { public: int findFinalValue(vector& nums, int original) { - unordered_set s; - for (int num : nums) s.insert(num); - while (s.count(original)) original <<= 1; + unordered_set s(nums.begin(), nums.end()); + while (s.contains(original)) { + original <<= 1; + } return original; } }; \ No newline at end of file diff --git a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.go b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.go index 9d20d42cd7b7..0bf0675015e1 100644 --- a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.go +++ b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.go @@ -1,7 +1,7 @@ func findFinalValue(nums []int, original int) int { - s := make(map[int]bool) - for _, num := range nums { - s[num] = true + s := map[int]bool{} + for _, x := range nums { + s[x] = true } for s[original] { original <<= 1 diff --git a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.ts b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.ts index d44e4f74b484..137178dd9ed2 100644 --- a/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.ts +++ b/solution/2100-2199/2154.Keep Multiplying Found Values by Two/Solution.ts @@ -1,7 +1,7 @@ function findFinalValue(nums: number[], original: number): number { - let set: Set = new Set(nums); - while (set.has(original)) { - original *= 2; + const s: Set = new Set([...nums]); + while (s.has(original)) { + original <<= 1; } return original; } diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README.md b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README.md index afa9f90ecb61..c9b3b2dcf910 100644 --- a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README.md +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README.md @@ -84,7 +84,15 @@ tags: -### 方法一 +### 方法一:前缀和 + +我们从 $i = 0$ 开始,用两个变量 $\textit{l0}$ 和 $\textit{r1}$ 分别记录 $i$ 左侧和右侧的 $1$ 的个数,初始时 $\textit{l0} = 0$,而 $\textit{r1} = \sum \textit{nums}$。 + +我们遍历数组 $\textit{nums}$,对于每个 $i$,更新 $\textit{l0}$ 和 $\textit{r1}$,计算当前分组得分 $t = \textit{l0} + \textit{r1}$,如果 $t$ 等于当前最大分组得分 $\textit{mx}$,则将 $i$ 加入答案数组,如果 $t$ 大于 $\textit{mx}$,则更新 $\textit{mx}$ 为 $t$,并将答案数组清空,然后将 $i$ 加入答案数组。 + +遍历结束后,返回答案数组。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 @@ -93,20 +101,18 @@ tags: ```python class Solution: def maxScoreIndices(self, nums: List[int]) -> List[int]: - left, right = 0, sum(nums) - mx = right + l0, r1 = 0, sum(nums) + mx = r1 ans = [0] - for i, num in enumerate(nums): - if num == 0: - left += 1 - else: - right -= 1 - t = left + right + for i, x in enumerate(nums, 1): + l0 += x ^ 1 + r1 -= x + t = l0 + r1 if mx == t: - ans.append(i + 1) + ans.append(i) elif mx < t: mx = t - ans = [i + 1] + ans = [i] return ans ``` @@ -114,37 +120,26 @@ class Solution: ```java class Solution { - public List maxScoreIndices(int[] nums) { - int left = 0, right = sum(nums); - int mx = right; + int l0 = 0, r1 = Arrays.stream(nums).sum(); + int mx = r1; List ans = new ArrayList<>(); ans.add(0); - for (int i = 0; i < nums.length; ++i) { - if (nums[i] == 0) { - ++left; - } else { - --right; - } - int t = left + right; + for (int i = 1; i <= nums.length; ++i) { + int x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + int t = l0 + r1; if (mx == t) { - ans.add(i + 1); + ans.add(i); } else if (mx < t) { mx = t; ans.clear(); - ans.add(i + 1); + ans.add(i); } } return ans; } - - private int sum(int[] nums) { - int s = 0; - for (int num : nums) { - s += num; - } - return s; - } } ``` @@ -154,22 +149,19 @@ class Solution { class Solution { public: vector maxScoreIndices(vector& nums) { - int left = 0, right = accumulate(nums.begin(), nums.end(), 0); - int mx = right; - vector ans; - ans.push_back(0); - for (int i = 0; i < nums.size(); ++i) { - if (nums[i] == 0) - ++left; - else - --right; - int t = left + right; - if (mx == t) - ans.push_back(i + 1); - else if (mx < t) { + int l0 = 0, r1 = accumulate(nums.begin(), nums.end(), 0); + int mx = r1; + vector ans = {0}; + for (int i = 1; i <= nums.size(); ++i) { + int x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + int t = l0 + r1; + if (mx == t) { + ans.push_back(i); + } else if (mx < t) { mx = t; - ans.clear(); - ans.push_back(i + 1); + ans = {i}; } } return ans; @@ -181,19 +173,16 @@ public: ```go func maxScoreIndices(nums []int) []int { - left, right := 0, 0 - for _, num := range nums { - right += num + l0, r1 := 0, 0 + for _, x := range nums { + r1 += x } - mx := right + mx := r1 ans := []int{0} - for i, num := range nums { - if num == 0 { - left++ - } else { - right-- - } - t := left + right + for i, x := range nums { + l0 += x ^ 1 + r1 -= x + t := l0 + r1 if mx == t { ans = append(ans, i+1) } else if mx < t { @@ -210,22 +199,19 @@ func maxScoreIndices(nums []int) []int { ```ts function maxScoreIndices(nums: number[]): number[] { const n = nums.length; - const total = nums.reduce((a, c) => a + c, 0); - let left = 0, - right = total; - let record: Array = [total]; - for (const num of nums) { - if (num == 0) { - left++; - } else { - right--; - } - record.push(left + right); - } - const max = Math.max(...record); - let ans: Array = []; - for (let i = 0; i <= n; i++) { - if (record[i] == max) { + let [l0, r1] = [0, nums.reduce((a, b) => a + b, 0)]; + let mx = r1; + const ans: number[] = [0]; + for (let i = 1; i <= n; ++i) { + const x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + const t = l0 + r1; + if (mx === t) { + ans.push(i); + } else if (mx < t) { + mx = t; + ans.length = 0; ans.push(i); } } @@ -233,6 +219,34 @@ function maxScoreIndices(nums: number[]): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn max_score_indices(nums: Vec) -> Vec { + let mut l0 = 0; + let mut r1: i32 = nums.iter().sum(); + let mut mx = r1; + let mut ans = vec![0]; + + for i in 1..=nums.len() { + let x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + let t = l0 + r1; + if mx == t { + ans.push(i as i32); + } else if mx < t { + mx = t; + ans = vec![i as i32]; + } + } + + ans + } +} +``` + diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README_EN.md b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README_EN.md index 32825443cbf7..2ef4a231ff1c 100644 --- a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README_EN.md +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/README_EN.md @@ -85,7 +85,15 @@ Only index 0 has the highest possible division score 2. -### Solution 1 +### Solution 1: Prefix Sum + +We start from $i = 0$, using two variables $\textit{l0}$ and $\textit{r1}$ to respectively record the number of $1$s to the left and right of $i$. Initially, $\textit{l0} = 0$, while $\textit{r1} = \sum \textit{nums}$. + +We iterate through the array $\textit{nums}$. For each $i$, we update $\textit{l0}$ and $\textit{r1}$, calculate the current grouping score $t = \textit{l0} + \textit{r1}$. If $t$ equals the current maximum grouping score $\textit{mx}$, then we add $i$ to the answer array. If $t$ is greater than $\textit{mx}$, we update $\textit{mx}$ to $t$, clear the answer array, and then add $i$ to the answer array. + +After the iteration ends, we return the answer array. + +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. @@ -94,20 +102,18 @@ Only index 0 has the highest possible division score 2. ```python class Solution: def maxScoreIndices(self, nums: List[int]) -> List[int]: - left, right = 0, sum(nums) - mx = right + l0, r1 = 0, sum(nums) + mx = r1 ans = [0] - for i, num in enumerate(nums): - if num == 0: - left += 1 - else: - right -= 1 - t = left + right + for i, x in enumerate(nums, 1): + l0 += x ^ 1 + r1 -= x + t = l0 + r1 if mx == t: - ans.append(i + 1) + ans.append(i) elif mx < t: mx = t - ans = [i + 1] + ans = [i] return ans ``` @@ -115,37 +121,26 @@ class Solution: ```java class Solution { - public List maxScoreIndices(int[] nums) { - int left = 0, right = sum(nums); - int mx = right; + int l0 = 0, r1 = Arrays.stream(nums).sum(); + int mx = r1; List ans = new ArrayList<>(); ans.add(0); - for (int i = 0; i < nums.length; ++i) { - if (nums[i] == 0) { - ++left; - } else { - --right; - } - int t = left + right; + for (int i = 1; i <= nums.length; ++i) { + int x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + int t = l0 + r1; if (mx == t) { - ans.add(i + 1); + ans.add(i); } else if (mx < t) { mx = t; ans.clear(); - ans.add(i + 1); + ans.add(i); } } return ans; } - - private int sum(int[] nums) { - int s = 0; - for (int num : nums) { - s += num; - } - return s; - } } ``` @@ -155,22 +150,19 @@ class Solution { class Solution { public: vector maxScoreIndices(vector& nums) { - int left = 0, right = accumulate(nums.begin(), nums.end(), 0); - int mx = right; - vector ans; - ans.push_back(0); - for (int i = 0; i < nums.size(); ++i) { - if (nums[i] == 0) - ++left; - else - --right; - int t = left + right; - if (mx == t) - ans.push_back(i + 1); - else if (mx < t) { + int l0 = 0, r1 = accumulate(nums.begin(), nums.end(), 0); + int mx = r1; + vector ans = {0}; + for (int i = 1; i <= nums.size(); ++i) { + int x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + int t = l0 + r1; + if (mx == t) { + ans.push_back(i); + } else if (mx < t) { mx = t; - ans.clear(); - ans.push_back(i + 1); + ans = {i}; } } return ans; @@ -182,19 +174,16 @@ public: ```go func maxScoreIndices(nums []int) []int { - left, right := 0, 0 - for _, num := range nums { - right += num + l0, r1 := 0, 0 + for _, x := range nums { + r1 += x } - mx := right + mx := r1 ans := []int{0} - for i, num := range nums { - if num == 0 { - left++ - } else { - right-- - } - t := left + right + for i, x := range nums { + l0 += x ^ 1 + r1 -= x + t := l0 + r1 if mx == t { ans = append(ans, i+1) } else if mx < t { @@ -211,22 +200,19 @@ func maxScoreIndices(nums []int) []int { ```ts function maxScoreIndices(nums: number[]): number[] { const n = nums.length; - const total = nums.reduce((a, c) => a + c, 0); - let left = 0, - right = total; - let record: Array = [total]; - for (const num of nums) { - if (num == 0) { - left++; - } else { - right--; - } - record.push(left + right); - } - const max = Math.max(...record); - let ans: Array = []; - for (let i = 0; i <= n; i++) { - if (record[i] == max) { + let [l0, r1] = [0, nums.reduce((a, b) => a + b, 0)]; + let mx = r1; + const ans: number[] = [0]; + for (let i = 1; i <= n; ++i) { + const x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + const t = l0 + r1; + if (mx === t) { + ans.push(i); + } else if (mx < t) { + mx = t; + ans.length = 0; ans.push(i); } } @@ -234,6 +220,34 @@ function maxScoreIndices(nums: number[]): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn max_score_indices(nums: Vec) -> Vec { + let mut l0 = 0; + let mut r1: i32 = nums.iter().sum(); + let mut mx = r1; + let mut ans = vec![0]; + + for i in 1..=nums.len() { + let x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + let t = l0 + r1; + if mx == t { + ans.push(i as i32); + } else if mx < t { + mx = t; + ans = vec![i as i32]; + } + } + + ans + } +} +``` + diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.cpp b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.cpp index e2c840cb8671..f03017a72e49 100644 --- a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.cpp +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.cpp @@ -1,22 +1,19 @@ class Solution { public: vector maxScoreIndices(vector& nums) { - int left = 0, right = accumulate(nums.begin(), nums.end(), 0); - int mx = right; - vector ans; - ans.push_back(0); - for (int i = 0; i < nums.size(); ++i) { - if (nums[i] == 0) - ++left; - else - --right; - int t = left + right; - if (mx == t) - ans.push_back(i + 1); - else if (mx < t) { + int l0 = 0, r1 = accumulate(nums.begin(), nums.end(), 0); + int mx = r1; + vector ans = {0}; + for (int i = 1; i <= nums.size(); ++i) { + int x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + int t = l0 + r1; + if (mx == t) { + ans.push_back(i); + } else if (mx < t) { mx = t; - ans.clear(); - ans.push_back(i + 1); + ans = {i}; } } return ans; diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.go b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.go index 77368d38418c..a241280358aa 100644 --- a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.go +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.go @@ -1,17 +1,14 @@ func maxScoreIndices(nums []int) []int { - left, right := 0, 0 - for _, num := range nums { - right += num + l0, r1 := 0, 0 + for _, x := range nums { + r1 += x } - mx := right + mx := r1 ans := []int{0} - for i, num := range nums { - if num == 0 { - left++ - } else { - right-- - } - t := left + right + for i, x := range nums { + l0 += x ^ 1 + r1 -= x + t := l0 + r1 if mx == t { ans = append(ans, i+1) } else if mx < t { diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.java b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.java index abb45aa11d3a..1a76ab445d32 100644 --- a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.java +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.java @@ -1,33 +1,22 @@ class Solution { - public List maxScoreIndices(int[] nums) { - int left = 0, right = sum(nums); - int mx = right; + int l0 = 0, r1 = Arrays.stream(nums).sum(); + int mx = r1; List ans = new ArrayList<>(); ans.add(0); - for (int i = 0; i < nums.length; ++i) { - if (nums[i] == 0) { - ++left; - } else { - --right; - } - int t = left + right; + for (int i = 1; i <= nums.length; ++i) { + int x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + int t = l0 + r1; if (mx == t) { - ans.add(i + 1); + ans.add(i); } else if (mx < t) { mx = t; ans.clear(); - ans.add(i + 1); + ans.add(i); } } return ans; } - - private int sum(int[] nums) { - int s = 0; - for (int num : nums) { - s += num; - } - return s; - } } \ No newline at end of file diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.py b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.py index 08306c5f4b4d..7eee78e794f4 100644 --- a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.py +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.py @@ -1,17 +1,15 @@ class Solution: def maxScoreIndices(self, nums: List[int]) -> List[int]: - left, right = 0, sum(nums) - mx = right + l0, r1 = 0, sum(nums) + mx = r1 ans = [0] - for i, num in enumerate(nums): - if num == 0: - left += 1 - else: - right -= 1 - t = left + right + for i, x in enumerate(nums, 1): + l0 += x ^ 1 + r1 -= x + t = l0 + r1 if mx == t: - ans.append(i + 1) + ans.append(i) elif mx < t: mx = t - ans = [i + 1] + ans = [i] return ans diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.rs b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.rs new file mode 100644 index 000000000000..7c1d77ac2718 --- /dev/null +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.rs @@ -0,0 +1,23 @@ +impl Solution { + pub fn max_score_indices(nums: Vec) -> Vec { + let mut l0 = 0; + let mut r1: i32 = nums.iter().sum(); + let mut mx = r1; + let mut ans = vec![0]; + + for i in 1..=nums.len() { + let x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + let t = l0 + r1; + if mx == t { + ans.push(i as i32); + } else if mx < t { + mx = t; + ans = vec![i as i32]; + } + } + + ans + } +} diff --git a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.ts b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.ts index 9dfb2fa8d293..b65d600083e1 100644 --- a/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.ts +++ b/solution/2100-2199/2155.All Divisions With the Highest Score of a Binary Array/Solution.ts @@ -1,21 +1,18 @@ function maxScoreIndices(nums: number[]): number[] { const n = nums.length; - const total = nums.reduce((a, c) => a + c, 0); - let left = 0, - right = total; - let record: Array = [total]; - for (const num of nums) { - if (num == 0) { - left++; - } else { - right--; - } - record.push(left + right); - } - const max = Math.max(...record); - let ans: Array = []; - for (let i = 0; i <= n; i++) { - if (record[i] == max) { + let [l0, r1] = [0, nums.reduce((a, b) => a + b, 0)]; + let mx = r1; + const ans: number[] = [0]; + for (let i = 1; i <= n; ++i) { + const x = nums[i - 1]; + l0 += x ^ 1; + r1 -= x; + const t = l0 + r1; + if (mx === t) { + ans.push(i); + } else if (mx < t) { + mx = t; + ans.length = 0; ans.push(i); } } diff --git a/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README.md b/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README.md index 3b08ead4205f..b35b103695d8 100644 --- a/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README.md +++ b/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README.md @@ -82,7 +82,7 @@ tags: 我们可以将奇数下标和偶数下标分别取出来,然后对奇数下标的数组进行非递增排序,对偶数下标的数组进行非递减排序,最后再将两个数组合并即可。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 diff --git a/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README_EN.md b/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README_EN.md index 65c07384fae8..920283dc8969 100644 --- a/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README_EN.md +++ b/solution/2100-2199/2164.Sort Even and Odd Indices Independently/README_EN.md @@ -80,7 +80,7 @@ The resultant array formed is [2,1], which is the same as the initial array. We can extract the elements at odd and even indices separately, then sort the array of odd indices in non-increasing order and the array of even indices in non-decreasing order. Finally, merge the two arrays back together. -The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\text{nums}$. +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. diff --git a/solution/2100-2199/2187.Minimum Time to Complete Trips/README.md b/solution/2100-2199/2187.Minimum Time to Complete Trips/README.md index d7a230d9cdfb..0b0fd49d0c98 100644 --- a/solution/2100-2199/2187.Minimum Time to Complete Trips/README.md +++ b/solution/2100-2199/2187.Minimum Time to Complete Trips/README.md @@ -69,7 +69,7 @@ tags: 我们注意到,如果我们能在 $t$ 时间内至少完成 $totalTrips$ 趟旅途,那么在 $t' > t$ 时间内也能至少完成 $totalTrips$ 趟旅途。因此我们可以使用二分查找的方法来找到最小的 $t$。 -我们定义二分查找的左边界 $l = 1$,右边界 $r = \min(time) \times \text{totalTrips}$。每一次二分查找,我们计算中间值 $\text{mid} = \frac{l + r}{2}$,然后计算在 $\text{mid}$ 时间内能完成的旅途数目。如果这个数目大于等于 $\text{totalTrips}$,那么我们将右边界缩小到 $\text{mid}$,否则我们将左边界扩大到 $\text{mid} + 1$。 +我们定义二分查找的左边界 $l = 1$,右边界 $r = \min(time) \times \textit{totalTrips}$。每一次二分查找,我们计算中间值 $\textit{mid} = \frac{l + r}{2}$,然后计算在 $\textit{mid}$ 时间内能完成的旅途数目。如果这个数目大于等于 $\textit{totalTrips}$,那么我们将右边界缩小到 $\textit{mid}$,否则我们将左边界扩大到 $\textit{mid} + 1$。 最后返回左边界即可。 diff --git a/solution/2100-2199/2187.Minimum Time to Complete Trips/README_EN.md b/solution/2100-2199/2187.Minimum Time to Complete Trips/README_EN.md index 47bf8c42401a..bb82d5a43b74 100644 --- a/solution/2100-2199/2187.Minimum Time to Complete Trips/README_EN.md +++ b/solution/2100-2199/2187.Minimum Time to Complete Trips/README_EN.md @@ -69,7 +69,7 @@ So the minimum time needed to complete 1 trip is 2. We notice that if we can complete at least $totalTrips$ trips in $t$ time, then we can also complete at least $totalTrips$ trips in $t' > t$ time. Therefore, we can use the method of binary search to find the smallest $t$. -We define the left boundary of the binary search as $l = 1$, and the right boundary as $r = \min(time) \times totalTrips$. For each binary search, we calculate the middle value $\text{mid} = \frac{l + r}{2}$, and then calculate the number of trips that can be completed in $\text{mid}$ time. If this number is greater than or equal to $totalTrips$, then we reduce the right boundary to $\text{mid}$, otherwise we increase the left boundary to $\text{mid} + 1$. +We define the left boundary of the binary search as $l = 1$, and the right boundary as $r = \min(time) \times totalTrips$. For each binary search, we calculate the middle value $\textit{mid} = \frac{l + r}{2}$, and then calculate the number of trips that can be completed in $\textit{mid}$ time. If this number is greater than or equal to $totalTrips$, then we reduce the right boundary to $\textit{mid}$, otherwise we increase the left boundary to $\textit{mid} + 1$. Finally, return the left boundary. diff --git a/solution/2100-2199/2189.Number of Ways to Build House of Cards/README.md b/solution/2100-2199/2189.Number of Ways to Build House of Cards/README.md index a0717156e998..f7b856ad7218 100644 --- a/solution/2100-2199/2189.Number of Ways to Build House of Cards/README.md +++ b/solution/2100-2199/2189.Number of Ways to Build House of Cards/README.md @@ -21,13 +21,13 @@ tags:
    • 一个 纸牌屋 由一行或多行 三角形 和水平纸牌组成。
    • -
    • 三角形 是由两张卡片相互靠在一起形成的。
    • -
    • 一张卡片必须水平放置在一行中 所有相邻 的三角形之间。
    • -
    • 比第一行高的任何三角形都必须放在前一行的水平牌上。
    • +
    • 三角形 是由两张纸牌相互靠在一起形成的。
    • +
    • 一张纸牌必须水平放置在一行中 所有相邻 的三角形之间。
    • +
    • 比第一行高的任何三角形都必须放在前一行的水平纸牌上。
    • 每个三角形都被放置在行中 最左边 的可用位置。
    -

    返回使用所有 n 张卡片可以构建的不同纸牌屋的数量。如果存在一行两个纸牌屋包含不同数量的纸牌,那么两个纸牌屋被认为是不同的。

    +

    返回使用所有 n纸牌可以构建的不同纸牌屋的数量。如果存在一行两个纸牌屋包含不同数量的纸牌,那么两个纸牌屋被认为是不同的。

     

    diff --git a/solution/2100-2199/2191.Sort the Jumbled Numbers/README.md b/solution/2100-2199/2191.Sort the Jumbled Numbers/README.md index b54f88cacd5e..440e1badfa36 100644 --- a/solution/2100-2199/2191.Sort the Jumbled Numbers/README.md +++ b/solution/2100-2199/2191.Sort the Jumbled Numbers/README.md @@ -224,6 +224,34 @@ function sortJumbled(mapping: number[], nums: number[]): number[] { } ``` +#### JavaScript + +```js +/** + * @param {number[]} mapping + * @param {number[]} nums + * @return {number[]} + */ +var sortJumbled = function (mapping, nums) { + const n = nums.length; + const f = x => { + if (x === 0) { + return mapping[0]; + } + let y = 0; + for (let k = 1; x; x = (x / 10) | 0) { + const v = mapping[x % 10]; + y += v * k; + k *= 10; + } + return y; + }; + const arr = nums.map((x, i) => [f(x), i]); + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => nums[x[1]]); +}; +``` + #### Rust ```rust diff --git a/solution/2100-2199/2191.Sort the Jumbled Numbers/README_EN.md b/solution/2100-2199/2191.Sort the Jumbled Numbers/README_EN.md index c60368d7e450..8a445e2046f4 100644 --- a/solution/2100-2199/2191.Sort the Jumbled Numbers/README_EN.md +++ b/solution/2100-2199/2191.Sort the Jumbled Numbers/README_EN.md @@ -222,6 +222,34 @@ function sortJumbled(mapping: number[], nums: number[]): number[] { } ``` +#### JavaScript + +```js +/** + * @param {number[]} mapping + * @param {number[]} nums + * @return {number[]} + */ +var sortJumbled = function (mapping, nums) { + const n = nums.length; + const f = x => { + if (x === 0) { + return mapping[0]; + } + let y = 0; + for (let k = 1; x; x = (x / 10) | 0) { + const v = mapping[x % 10]; + y += v * k; + k *= 10; + } + return y; + }; + const arr = nums.map((x, i) => [f(x), i]); + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => nums[x[1]]); +}; +``` + #### Rust ```rust diff --git a/solution/2100-2199/2191.Sort the Jumbled Numbers/Solution.js b/solution/2100-2199/2191.Sort the Jumbled Numbers/Solution.js new file mode 100644 index 000000000000..180d16e2936e --- /dev/null +++ b/solution/2100-2199/2191.Sort the Jumbled Numbers/Solution.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} mapping + * @param {number[]} nums + * @return {number[]} + */ +var sortJumbled = function (mapping, nums) { + const n = nums.length; + const f = x => { + if (x === 0) { + return mapping[0]; + } + let y = 0; + for (let k = 1; x; x = (x / 10) | 0) { + const v = mapping[x % 10]; + y += v * k; + k *= 10; + } + return y; + }; + const arr = nums.map((x, i) => [f(x), i]); + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => nums[x[1]]); +}; diff --git a/solution/2100-2199/2193.Minimum Number of Moves to Make Palindrome/README.md b/solution/2100-2199/2193.Minimum Number of Moves to Make Palindrome/README.md index eee2067b848d..032ab320f5ab 100644 --- a/solution/2100-2199/2193.Minimum Number of Moves to Make Palindrome/README.md +++ b/solution/2100-2199/2193.Minimum Number of Moves to Make Palindrome/README.md @@ -81,9 +81,9 @@ tags: 构造回文串的过程,实际上是每次选择一对字母并把它们交换到字符串头尾的过程。考虑字母 $x$ 和字母 $y$ 哪个先选,分以下情况讨论: -- 字母 $x$ 和 $y$ 的位置满足 $\underbrace{\cdots}_{a\text{ 个}}x\underbrace{\cdots}_{b\text{ 个}}y\underbrace{\cdots}_{c\text{ 个}}y\underbrace{\cdots}_{d\text{ 个}}x\underbrace{\cdots}_{e\text{ 个}}$。如果先把 $x$ 换到头尾,再把 $y$ 换到头尾,那么需要 $(a + e) + (b + d)$ 次交换;如果先换 $y$ 再换 $x$,那么需要 $(a + b + 1 + d + e + 1) + (a + e)$ 次交换。显然先换 $x$ 更优。 -- 字母 $x$ 和 $y$ 的位置满足 $\underbrace{\cdots}_{a\text{ 个}}x\underbrace{\cdots}_{b\text{ 个}}y\underbrace{\cdots}_{c\text{ 个}}x\underbrace{\cdots}_{d\text{ 个}}y\underbrace{\cdots}_{e\text{ 个}}$。如果先换 $x$ 再换 $y$,那么需要 $(a + d + e + 1) + (a + b + e)$ 次交换;如果先换 $y$ 再换 $x$,那么需要 $(a + b + 1 + e) + (a + d + e)$ 次交换。先换哪个都一样。 -- 字母 $x$ 和 $y$ 的位置满足 $\underbrace{\cdots}_{a\text{ 个}}x\underbrace{\cdots}_{b\text{ 个}}x\underbrace{\cdots}_{c\text{ 个}}y\underbrace{\cdots}_{d\text{ 个}}y\underbrace{\cdots}_{e\text{ 个}}$。如果先换 $x$ 再换 $y$,那么需要 $(a + c + d + e + 2) + (a + b + c + e)$ 次交换;如果先换 $y$ 再换 $x$,那么需要 $(a + b + c + 2 + e) + (a + c + d + e)$ 次交换。先换哪个都一样。 +- 字母 $x$ 和 $y$ 的位置满足 $\underbrace{\cdots}_{a\textit{ 个}}x\underbrace{\cdots}_{b\textit{ 个}}y\underbrace{\cdots}_{c\textit{ 个}}y\underbrace{\cdots}_{d\textit{ 个}}x\underbrace{\cdots}_{e\textit{ 个}}$。如果先把 $x$ 换到头尾,再把 $y$ 换到头尾,那么需要 $(a + e) + (b + d)$ 次交换;如果先换 $y$ 再换 $x$,那么需要 $(a + b + 1 + d + e + 1) + (a + e)$ 次交换。显然先换 $x$ 更优。 +- 字母 $x$ 和 $y$ 的位置满足 $\underbrace{\cdots}_{a\textit{ 个}}x\underbrace{\cdots}_{b\textit{ 个}}y\underbrace{\cdots}_{c\textit{ 个}}x\underbrace{\cdots}_{d\textit{ 个}}y\underbrace{\cdots}_{e\textit{ 个}}$。如果先换 $x$ 再换 $y$,那么需要 $(a + d + e + 1) + (a + b + e)$ 次交换;如果先换 $y$ 再换 $x$,那么需要 $(a + b + 1 + e) + (a + d + e)$ 次交换。先换哪个都一样。 +- 字母 $x$ 和 $y$ 的位置满足 $\underbrace{\cdots}_{a\textit{ 个}}x\underbrace{\cdots}_{b\textit{ 个}}x\underbrace{\cdots}_{c\textit{ 个}}y\underbrace{\cdots}_{d\textit{ 个}}y\underbrace{\cdots}_{e\textit{ 个}}$。如果先换 $x$ 再换 $y$,那么需要 $(a + c + d + e + 2) + (a + b + c + e)$ 次交换;如果先换 $y$ 再换 $x$,那么需要 $(a + b + c + 2 + e) + (a + c + d + e)$ 次交换。先换哪个都一样。 上述讨论可以得到结论:每次交换最外边出现的字母不劣。因此贪心解法成立。 diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/README.md b/solution/2100-2199/2196.Create Binary Tree From Descriptions/README.md index 16cddcc4ce3f..72463fd7b921 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/README.md +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/README.md @@ -73,7 +73,17 @@ tags: -### 方法一 +### 方法一:哈希表 + +我们可以用一个哈希表 $\textit{nodes}$ 来存储所有节点,其中键为节点的值,值为节点本身,用一个集合 $\textit{children}$ 来存储所有的子节点。 + +遍历 $\textit{descriptions}$,对于每个描述 $[\textit{parent}, \textit{child}, \textit{isLeft}]$,如果 $\textit{parent}$ 不在 $\textit{nodes}$ 中,我们就将 $\textit{parent}$ 加入 $\textit{nodes}$,并初始化一个值为 $\textit{parent}$ 的节点。如果 $\textit{child}$ 不在 $\textit{nodes}$ 中,我们就将 $\textit{child}$ 加入 $\textit{nodes}$,并初始化一个值为 $\textit{child}$ 的节点。然后我们将 $\textit{child}$ 加入 $\textit{children}$。 + +如果 $\textit{isLeft}$ 为真,我们就将 $\textit{child}$ 作为 $\textit{parent}$ 的左子节点,否则我们就将 $\textit{child}$ 作为 $\textit{parent}$ 的右子节点。 + +最后,我们遍历 $\textit{nodes}$,如果某个节点的值不在 $\textit{children}$ 中,那么这个节点就是根节点,我们返回这个节点。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是 $\textit{descriptions}$ 的长度。 @@ -88,21 +98,20 @@ tags: # self.right = right class Solution: def createBinaryTree(self, descriptions: List[List[int]]) -> Optional[TreeNode]: - g = defaultdict(TreeNode) - vis = set() - for p, c, left in descriptions: - if p not in g: - g[p] = TreeNode(p) - if c not in g: - g[c] = TreeNode(c) - if left: - g[p].left = g[c] + nodes = defaultdict(TreeNode) + children = set() + for parent, child, isLeft in descriptions: + if parent not in nodes: + nodes[parent] = TreeNode(parent) + if child not in nodes: + nodes[child] = TreeNode(child) + children.add(child) + if isLeft: + nodes[parent].left = nodes[child] else: - g[p].right = g[c] - vis.add(c) - for v, node in g.items(): - if v not in vis: - return node + nodes[parent].right = nodes[child] + root = (set(nodes.keys()) - children).pop() + return nodes[root] ``` #### Java @@ -125,26 +134,26 @@ class Solution: */ class Solution { public TreeNode createBinaryTree(int[][] descriptions) { - Map m = new HashMap<>(); - Set vis = new HashSet<>(); - for (int[] d : descriptions) { - int p = d[0], c = d[1], isLeft = d[2]; - if (!m.containsKey(p)) { - m.put(p, new TreeNode(p)); + Map nodes = new HashMap<>(); + Set children = new HashSet<>(); + for (var d : descriptions) { + int parent = d[0], child = d[1], isLeft = d[2]; + if (!nodes.containsKey(parent)) { + nodes.put(parent, new TreeNode(parent)); } - if (!m.containsKey(c)) { - m.put(c, new TreeNode(c)); + if (!nodes.containsKey(child)) { + nodes.put(child, new TreeNode(child)); } if (isLeft == 1) { - m.get(p).left = m.get(c); + nodes.get(parent).left = nodes.get(child); } else { - m.get(p).right = m.get(c); + nodes.get(parent).right = nodes.get(child); } - vis.add(c); + children.add(child); } - for (Map.Entry entry : m.entrySet()) { - if (!vis.contains(entry.getKey())) { - return entry.getValue(); + for (var e : nodes.entrySet()) { + if (!children.contains(e.getKey())) { + return e.getValue(); } } return null; @@ -169,20 +178,27 @@ class Solution { class Solution { public: TreeNode* createBinaryTree(vector>& descriptions) { - unordered_map m; - unordered_set vis; - for (auto& d : descriptions) { - int p = d[0], c = d[1], left = d[2]; - if (!m.count(p)) m[p] = new TreeNode(p); - if (!m.count(c)) m[c] = new TreeNode(c); - if (left) - m[p]->left = m[c]; - else - m[p]->right = m[c]; - vis.insert(c); + unordered_map nodes; + unordered_set children; + for (const auto& d : descriptions) { + int parent = d[0], child = d[1], isLeft = d[2]; + if (!nodes.contains(parent)) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes.contains(child)) { + nodes[child] = new TreeNode(child); + } + if (isLeft) { + nodes[parent]->left = nodes[child]; + } else { + nodes[parent]->right = nodes[child]; + } + children.insert(child); } - for (auto& [v, node] : m) { - if (!vis.count(v)) return node; + for (const auto& [k, v] : nodes) { + if (!children.contains(k)) { + return v; + } } return nullptr; } @@ -201,27 +217,26 @@ public: * } */ func createBinaryTree(descriptions [][]int) *TreeNode { - m := make(map[int]*TreeNode) - vis := make(map[int]bool) + nodes := map[int]*TreeNode{} + children := map[int]bool{} for _, d := range descriptions { - p, c, left := d[0], d[1], d[2] - if m[p] == nil { - m[p] = &TreeNode{Val: p} + parent, child, isLeft := d[0], d[1], d[2] + if _, ok := nodes[parent]; !ok { + nodes[parent] = &TreeNode{Val: parent} } - if m[c] == nil { - m[c] = &TreeNode{Val: c} + if _, ok := nodes[child]; !ok { + nodes[child] = &TreeNode{Val: child} } - if left == 1 { - m[p].Left = m[c] + if isLeft == 1 { + nodes[parent].Left = nodes[child] } else { - m[p].Right = m[c] + nodes[parent].Right = nodes[child] } - vis[c] = true + children[child] = true } - - for v, node := range m { - if !vis[v] { - return node + for k, v := range nodes { + if _, ok := children[k]; !ok { + return v } } return nil @@ -246,34 +261,27 @@ func createBinaryTree(descriptions [][]int) *TreeNode { */ function createBinaryTree(descriptions: number[][]): TreeNode | null { - const map = new Map(); - const isRoot = new Map(); + const nodes: Record = {}; + const children = new Set(); for (const [parent, child, isLeft] of descriptions) { - let [left, right] = map.get(parent) ?? [0, 0]; + if (!nodes[parent]) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes[child]) { + nodes[child] = new TreeNode(child); + } if (isLeft) { - left = child; + nodes[parent].left = nodes[child]; } else { - right = child; - } - if (!isRoot.has(parent)) { - isRoot.set(parent, true); + nodes[parent].right = nodes[child]; } - isRoot.set(child, false); - map.set(parent, [left, right]); + children.add(child); } - const dfs = (val: number) => { - if (val === 0) { - return null; - } - const [left, right] = map.get(val) ?? [0, 0]; - return new TreeNode(val, dfs(left), dfs(right)); - }; - for (const [key, val] of isRoot.entries()) { - if (val) { - return dfs(key); + for (const [k, v] of Object.entries(nodes)) { + if (!children.has(+k)) { + return v; } } - return null; } ``` @@ -299,49 +307,87 @@ function createBinaryTree(descriptions: number[][]): TreeNode | null { // } // } use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::rc::Rc; impl Solution { - fn dfs(val: i32, map: &HashMap) -> Option>> { - if val == 0 { - return None; - } - let mut left = None; - let mut right = None; - if let Some(&[l_val, r_val]) = map.get(&val) { - left = Self::dfs(l_val, map); - right = Self::dfs(r_val, map); - } - Some(Rc::new(RefCell::new(TreeNode { val, left, right }))) - } - pub fn create_binary_tree(descriptions: Vec>) -> Option>> { - let mut map = HashMap::new(); - let mut is_root = HashMap::new(); - for description in descriptions.iter() { - let (parent, child, is_left) = (description[0], description[1], description[2] == 1); - let [mut left, mut right] = map.get(&parent).unwrap_or(&[0, 0]); - if is_left { - left = child; + let mut nodes = HashMap::new(); + let mut children = HashSet::new(); + + for d in descriptions { + let parent = d[0]; + let child = d[1]; + let is_left = d[2]; + + nodes + .entry(parent) + .or_insert_with(|| Rc::new(RefCell::new(TreeNode::new(parent)))); + nodes + .entry(child) + .or_insert_with(|| Rc::new(RefCell::new(TreeNode::new(child)))); + + if is_left == 1 { + nodes.get(&parent).unwrap().borrow_mut().left = + Some(Rc::clone(nodes.get(&child).unwrap())); } else { - right = child; + nodes.get(&parent).unwrap().borrow_mut().right = + Some(Rc::clone(nodes.get(&child).unwrap())); } - if !is_root.contains_key(&parent) { - is_root.insert(parent, true); - } - is_root.insert(child, false); - map.insert(parent, [left, right]); + + children.insert(child); } - for key in is_root.keys() { - if *is_root.get(key).unwrap() { - return Self::dfs(*key, &map); + + for (key, node) in &nodes { + if !children.contains(key) { + return Some(Rc::clone(node)); } } + None } } ``` +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {number[][]} descriptions + * @return {TreeNode} + */ +var createBinaryTree = function (descriptions) { + const nodes = {}; + const children = new Set(); + for (const [parent, child, isLeft] of descriptions) { + if (!nodes[parent]) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes[child]) { + nodes[child] = new TreeNode(child); + } + if (isLeft) { + nodes[parent].left = nodes[child]; + } else { + nodes[parent].right = nodes[child]; + } + children.add(child); + } + for (const [k, v] of Object.entries(nodes)) { + if (!children.has(+k)) { + return v; + } + } +}; +``` + diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/README_EN.md b/solution/2100-2199/2196.Create Binary Tree From Descriptions/README_EN.md index 375aa87e0889..14cbe187ccd6 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/README_EN.md +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/README_EN.md @@ -68,7 +68,17 @@ The resulting binary tree is shown in the diagram. -### Solution 1 +### Solution 1: Hash Table + +We can use a hash table $\textit{nodes}$ to store all nodes, where the keys are the values of the nodes, and the values are the nodes themselves. Additionally, we use a set $\textit{children}$ to store all child nodes. + +We iterate through the $\textit{descriptions}$, and for each description $[\textit{parent}, \textit{child}, \textit{isLeft}]$, if $\textit{parent}$ is not in $\textit{nodes}$, we add $\textit{parent}$ to $\textit{nodes}$ and initialize a node with the value $\textit{parent}$. If $\textit{child}$ is not in $\textit{nodes}$, we add $\textit{child}$ to $\textit{nodes}$ and initialize a node with the value $\textit{child}$. Then, we add $\textit{child}$ to $\textit{children}$. + +If $\textit{isLeft}$ is true, we set $\textit{child}$ as the left child of $\textit{parent}$; otherwise, we set $\textit{child}$ as the right child of $\textit{parent}$. + +Finally, we iterate through $\textit{nodes}$, and if a node's value is not in $\textit{children}$, then this node is the root node, and we return this node. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of $\textit{descriptions}$. @@ -83,21 +93,20 @@ The resulting binary tree is shown in the diagram. # self.right = right class Solution: def createBinaryTree(self, descriptions: List[List[int]]) -> Optional[TreeNode]: - g = defaultdict(TreeNode) - vis = set() - for p, c, left in descriptions: - if p not in g: - g[p] = TreeNode(p) - if c not in g: - g[c] = TreeNode(c) - if left: - g[p].left = g[c] + nodes = defaultdict(TreeNode) + children = set() + for parent, child, isLeft in descriptions: + if parent not in nodes: + nodes[parent] = TreeNode(parent) + if child not in nodes: + nodes[child] = TreeNode(child) + children.add(child) + if isLeft: + nodes[parent].left = nodes[child] else: - g[p].right = g[c] - vis.add(c) - for v, node in g.items(): - if v not in vis: - return node + nodes[parent].right = nodes[child] + root = (set(nodes.keys()) - children).pop() + return nodes[root] ``` #### Java @@ -120,26 +129,26 @@ class Solution: */ class Solution { public TreeNode createBinaryTree(int[][] descriptions) { - Map m = new HashMap<>(); - Set vis = new HashSet<>(); - for (int[] d : descriptions) { - int p = d[0], c = d[1], isLeft = d[2]; - if (!m.containsKey(p)) { - m.put(p, new TreeNode(p)); + Map nodes = new HashMap<>(); + Set children = new HashSet<>(); + for (var d : descriptions) { + int parent = d[0], child = d[1], isLeft = d[2]; + if (!nodes.containsKey(parent)) { + nodes.put(parent, new TreeNode(parent)); } - if (!m.containsKey(c)) { - m.put(c, new TreeNode(c)); + if (!nodes.containsKey(child)) { + nodes.put(child, new TreeNode(child)); } if (isLeft == 1) { - m.get(p).left = m.get(c); + nodes.get(parent).left = nodes.get(child); } else { - m.get(p).right = m.get(c); + nodes.get(parent).right = nodes.get(child); } - vis.add(c); + children.add(child); } - for (Map.Entry entry : m.entrySet()) { - if (!vis.contains(entry.getKey())) { - return entry.getValue(); + for (var e : nodes.entrySet()) { + if (!children.contains(e.getKey())) { + return e.getValue(); } } return null; @@ -164,20 +173,27 @@ class Solution { class Solution { public: TreeNode* createBinaryTree(vector>& descriptions) { - unordered_map m; - unordered_set vis; - for (auto& d : descriptions) { - int p = d[0], c = d[1], left = d[2]; - if (!m.count(p)) m[p] = new TreeNode(p); - if (!m.count(c)) m[c] = new TreeNode(c); - if (left) - m[p]->left = m[c]; - else - m[p]->right = m[c]; - vis.insert(c); + unordered_map nodes; + unordered_set children; + for (const auto& d : descriptions) { + int parent = d[0], child = d[1], isLeft = d[2]; + if (!nodes.contains(parent)) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes.contains(child)) { + nodes[child] = new TreeNode(child); + } + if (isLeft) { + nodes[parent]->left = nodes[child]; + } else { + nodes[parent]->right = nodes[child]; + } + children.insert(child); } - for (auto& [v, node] : m) { - if (!vis.count(v)) return node; + for (const auto& [k, v] : nodes) { + if (!children.contains(k)) { + return v; + } } return nullptr; } @@ -196,27 +212,26 @@ public: * } */ func createBinaryTree(descriptions [][]int) *TreeNode { - m := make(map[int]*TreeNode) - vis := make(map[int]bool) + nodes := map[int]*TreeNode{} + children := map[int]bool{} for _, d := range descriptions { - p, c, left := d[0], d[1], d[2] - if m[p] == nil { - m[p] = &TreeNode{Val: p} + parent, child, isLeft := d[0], d[1], d[2] + if _, ok := nodes[parent]; !ok { + nodes[parent] = &TreeNode{Val: parent} } - if m[c] == nil { - m[c] = &TreeNode{Val: c} + if _, ok := nodes[child]; !ok { + nodes[child] = &TreeNode{Val: child} } - if left == 1 { - m[p].Left = m[c] + if isLeft == 1 { + nodes[parent].Left = nodes[child] } else { - m[p].Right = m[c] + nodes[parent].Right = nodes[child] } - vis[c] = true + children[child] = true } - - for v, node := range m { - if !vis[v] { - return node + for k, v := range nodes { + if _, ok := children[k]; !ok { + return v } } return nil @@ -241,34 +256,27 @@ func createBinaryTree(descriptions [][]int) *TreeNode { */ function createBinaryTree(descriptions: number[][]): TreeNode | null { - const map = new Map(); - const isRoot = new Map(); + const nodes: Record = {}; + const children = new Set(); for (const [parent, child, isLeft] of descriptions) { - let [left, right] = map.get(parent) ?? [0, 0]; + if (!nodes[parent]) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes[child]) { + nodes[child] = new TreeNode(child); + } if (isLeft) { - left = child; + nodes[parent].left = nodes[child]; } else { - right = child; - } - if (!isRoot.has(parent)) { - isRoot.set(parent, true); + nodes[parent].right = nodes[child]; } - isRoot.set(child, false); - map.set(parent, [left, right]); + children.add(child); } - const dfs = (val: number) => { - if (val === 0) { - return null; - } - const [left, right] = map.get(val) ?? [0, 0]; - return new TreeNode(val, dfs(left), dfs(right)); - }; - for (const [key, val] of isRoot.entries()) { - if (val) { - return dfs(key); + for (const [k, v] of Object.entries(nodes)) { + if (!children.has(+k)) { + return v; } } - return null; } ``` @@ -294,49 +302,87 @@ function createBinaryTree(descriptions: number[][]): TreeNode | null { // } // } use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::rc::Rc; impl Solution { - fn dfs(val: i32, map: &HashMap) -> Option>> { - if val == 0 { - return None; - } - let mut left = None; - let mut right = None; - if let Some(&[l_val, r_val]) = map.get(&val) { - left = Self::dfs(l_val, map); - right = Self::dfs(r_val, map); - } - Some(Rc::new(RefCell::new(TreeNode { val, left, right }))) - } - pub fn create_binary_tree(descriptions: Vec>) -> Option>> { - let mut map = HashMap::new(); - let mut is_root = HashMap::new(); - for description in descriptions.iter() { - let (parent, child, is_left) = (description[0], description[1], description[2] == 1); - let [mut left, mut right] = map.get(&parent).unwrap_or(&[0, 0]); - if is_left { - left = child; + let mut nodes = HashMap::new(); + let mut children = HashSet::new(); + + for d in descriptions { + let parent = d[0]; + let child = d[1]; + let is_left = d[2]; + + nodes + .entry(parent) + .or_insert_with(|| Rc::new(RefCell::new(TreeNode::new(parent)))); + nodes + .entry(child) + .or_insert_with(|| Rc::new(RefCell::new(TreeNode::new(child)))); + + if is_left == 1 { + nodes.get(&parent).unwrap().borrow_mut().left = + Some(Rc::clone(nodes.get(&child).unwrap())); } else { - right = child; + nodes.get(&parent).unwrap().borrow_mut().right = + Some(Rc::clone(nodes.get(&child).unwrap())); } - if !is_root.contains_key(&parent) { - is_root.insert(parent, true); - } - is_root.insert(child, false); - map.insert(parent, [left, right]); + + children.insert(child); } - for key in is_root.keys() { - if *is_root.get(key).unwrap() { - return Self::dfs(*key, &map); + + for (key, node) in &nodes { + if !children.contains(key) { + return Some(Rc::clone(node)); } } + None } } ``` +#### JavaScript + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {number[][]} descriptions + * @return {TreeNode} + */ +var createBinaryTree = function (descriptions) { + const nodes = {}; + const children = new Set(); + for (const [parent, child, isLeft] of descriptions) { + if (!nodes[parent]) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes[child]) { + nodes[child] = new TreeNode(child); + } + if (isLeft) { + nodes[parent].left = nodes[child]; + } else { + nodes[parent].right = nodes[child]; + } + children.add(child); + } + for (const [k, v] of Object.entries(nodes)) { + if (!children.has(+k)) { + return v; + } + } +}; +``` + diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.cpp b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.cpp index d12c0cba56bf..0d8588f7f937 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.cpp +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.cpp @@ -12,20 +12,27 @@ class Solution { public: TreeNode* createBinaryTree(vector>& descriptions) { - unordered_map m; - unordered_set vis; - for (auto& d : descriptions) { - int p = d[0], c = d[1], left = d[2]; - if (!m.count(p)) m[p] = new TreeNode(p); - if (!m.count(c)) m[c] = new TreeNode(c); - if (left) - m[p]->left = m[c]; - else - m[p]->right = m[c]; - vis.insert(c); + unordered_map nodes; + unordered_set children; + for (const auto& d : descriptions) { + int parent = d[0], child = d[1], isLeft = d[2]; + if (!nodes.contains(parent)) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes.contains(child)) { + nodes[child] = new TreeNode(child); + } + if (isLeft) { + nodes[parent]->left = nodes[child]; + } else { + nodes[parent]->right = nodes[child]; + } + children.insert(child); } - for (auto& [v, node] : m) { - if (!vis.count(v)) return node; + for (const auto& [k, v] : nodes) { + if (!children.contains(k)) { + return v; + } } return nullptr; } diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.go b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.go index 334b411af5f8..31b0390dfb31 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.go +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.go @@ -7,27 +7,26 @@ * } */ func createBinaryTree(descriptions [][]int) *TreeNode { - m := make(map[int]*TreeNode) - vis := make(map[int]bool) + nodes := map[int]*TreeNode{} + children := map[int]bool{} for _, d := range descriptions { - p, c, left := d[0], d[1], d[2] - if m[p] == nil { - m[p] = &TreeNode{Val: p} + parent, child, isLeft := d[0], d[1], d[2] + if _, ok := nodes[parent]; !ok { + nodes[parent] = &TreeNode{Val: parent} } - if m[c] == nil { - m[c] = &TreeNode{Val: c} + if _, ok := nodes[child]; !ok { + nodes[child] = &TreeNode{Val: child} } - if left == 1 { - m[p].Left = m[c] + if isLeft == 1 { + nodes[parent].Left = nodes[child] } else { - m[p].Right = m[c] + nodes[parent].Right = nodes[child] } - vis[c] = true + children[child] = true } - - for v, node := range m { - if !vis[v] { - return node + for k, v := range nodes { + if _, ok := children[k]; !ok { + return v } } return nil diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.java b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.java index 75f78ca9afb2..8738d5125981 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.java +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.java @@ -15,26 +15,26 @@ */ class Solution { public TreeNode createBinaryTree(int[][] descriptions) { - Map m = new HashMap<>(); - Set vis = new HashSet<>(); - for (int[] d : descriptions) { - int p = d[0], c = d[1], isLeft = d[2]; - if (!m.containsKey(p)) { - m.put(p, new TreeNode(p)); + Map nodes = new HashMap<>(); + Set children = new HashSet<>(); + for (var d : descriptions) { + int parent = d[0], child = d[1], isLeft = d[2]; + if (!nodes.containsKey(parent)) { + nodes.put(parent, new TreeNode(parent)); } - if (!m.containsKey(c)) { - m.put(c, new TreeNode(c)); + if (!nodes.containsKey(child)) { + nodes.put(child, new TreeNode(child)); } if (isLeft == 1) { - m.get(p).left = m.get(c); + nodes.get(parent).left = nodes.get(child); } else { - m.get(p).right = m.get(c); + nodes.get(parent).right = nodes.get(child); } - vis.add(c); + children.add(child); } - for (Map.Entry entry : m.entrySet()) { - if (!vis.contains(entry.getKey())) { - return entry.getValue(); + for (var e : nodes.entrySet()) { + if (!children.contains(e.getKey())) { + return e.getValue(); } } return null; diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.js b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.js new file mode 100644 index 000000000000..6e0112d2fc5d --- /dev/null +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.js @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {number[][]} descriptions + * @return {TreeNode} + */ +var createBinaryTree = function (descriptions) { + const nodes = {}; + const children = new Set(); + for (const [parent, child, isLeft] of descriptions) { + if (!nodes[parent]) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes[child]) { + nodes[child] = new TreeNode(child); + } + if (isLeft) { + nodes[parent].left = nodes[child]; + } else { + nodes[parent].right = nodes[child]; + } + children.add(child); + } + for (const [k, v] of Object.entries(nodes)) { + if (!children.has(+k)) { + return v; + } + } +}; diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.py b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.py index 5ba59d85c833..919cb67b1c3a 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.py +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.py @@ -6,18 +6,17 @@ # self.right = right class Solution: def createBinaryTree(self, descriptions: List[List[int]]) -> Optional[TreeNode]: - g = defaultdict(TreeNode) - vis = set() - for p, c, left in descriptions: - if p not in g: - g[p] = TreeNode(p) - if c not in g: - g[c] = TreeNode(c) - if left: - g[p].left = g[c] + nodes = defaultdict(TreeNode) + children = set() + for parent, child, isLeft in descriptions: + if parent not in nodes: + nodes[parent] = TreeNode(parent) + if child not in nodes: + nodes[child] = TreeNode(child) + children.add(child) + if isLeft: + nodes[parent].left = nodes[child] else: - g[p].right = g[c] - vis.add(c) - for v, node in g.items(): - if v not in vis: - return node + nodes[parent].right = nodes[child] + root = (set(nodes.keys()) - children).pop() + return nodes[root] diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.rs b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.rs index 26f76b3b3891..7ae68c26d409 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.rs +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.rs @@ -17,44 +17,42 @@ // } // } use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::rc::Rc; impl Solution { - fn dfs(val: i32, map: &HashMap) -> Option>> { - if val == 0 { - return None; - } - let mut left = None; - let mut right = None; - if let Some(&[l_val, r_val]) = map.get(&val) { - left = Self::dfs(l_val, map); - right = Self::dfs(r_val, map); - } - Some(Rc::new(RefCell::new(TreeNode { val, left, right }))) - } - pub fn create_binary_tree(descriptions: Vec>) -> Option>> { - let mut map = HashMap::new(); - let mut is_root = HashMap::new(); - for description in descriptions.iter() { - let (parent, child, is_left) = (description[0], description[1], description[2] == 1); - let [mut left, mut right] = map.get(&parent).unwrap_or(&[0, 0]); - if is_left { - left = child; + let mut nodes = HashMap::new(); + let mut children = HashSet::new(); + + for d in descriptions { + let parent = d[0]; + let child = d[1]; + let is_left = d[2]; + + nodes + .entry(parent) + .or_insert_with(|| Rc::new(RefCell::new(TreeNode::new(parent)))); + nodes + .entry(child) + .or_insert_with(|| Rc::new(RefCell::new(TreeNode::new(child)))); + + if is_left == 1 { + nodes.get(&parent).unwrap().borrow_mut().left = + Some(Rc::clone(nodes.get(&child).unwrap())); } else { - right = child; - } - if !is_root.contains_key(&parent) { - is_root.insert(parent, true); + nodes.get(&parent).unwrap().borrow_mut().right = + Some(Rc::clone(nodes.get(&child).unwrap())); } - is_root.insert(child, false); - map.insert(parent, [left, right]); + + children.insert(child); } - for key in is_root.keys() { - if *is_root.get(key).unwrap() { - return Self::dfs(*key, &map); + + for (key, node) in &nodes { + if !children.contains(key) { + return Some(Rc::clone(node)); } } + None } } diff --git a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.ts b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.ts index 5ae7f108a558..e87e7bf5f8ec 100644 --- a/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.ts +++ b/solution/2100-2199/2196.Create Binary Tree From Descriptions/Solution.ts @@ -13,32 +13,25 @@ */ function createBinaryTree(descriptions: number[][]): TreeNode | null { - const map = new Map(); - const isRoot = new Map(); + const nodes: Record = {}; + const children = new Set(); for (const [parent, child, isLeft] of descriptions) { - let [left, right] = map.get(parent) ?? [0, 0]; + if (!nodes[parent]) { + nodes[parent] = new TreeNode(parent); + } + if (!nodes[child]) { + nodes[child] = new TreeNode(child); + } if (isLeft) { - left = child; + nodes[parent].left = nodes[child]; } else { - right = child; + nodes[parent].right = nodes[child]; } - if (!isRoot.has(parent)) { - isRoot.set(parent, true); - } - isRoot.set(child, false); - map.set(parent, [left, right]); + children.add(child); } - const dfs = (val: number) => { - if (val === 0) { - return null; - } - const [left, right] = map.get(val) ?? [0, 0]; - return new TreeNode(val, dfs(left), dfs(right)); - }; - for (const [key, val] of isRoot.entries()) { - if (val) { - return dfs(key); + for (const [k, v] of Object.entries(nodes)) { + if (!children.has(+k)) { + return v; } } - return null; } diff --git a/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README.md b/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README.md index a428de4ddbd4..00faf635c668 100644 --- a/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README.md +++ b/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README.md @@ -85,7 +85,7 @@ tags: ### 方法一:栈 -如果存在三个相邻的数 $x$, $y$, $z$ 可以进行合并,那么我们先合并 $x$ 和 $y$,再合并 $z$ 的结果,与先合并 $y$ 和 $z$,再合并 $x$ 的结果是一样的,结果均为 $\text{LCM}(x, y, z)$。 +如果存在三个相邻的数 $x$, $y$, $z$ 可以进行合并,那么我们先合并 $x$ 和 $y$,再合并 $z$ 的结果,与先合并 $y$ 和 $z$,再合并 $x$ 的结果是一样的,结果均为 $\textit{LCM}(x, y, z)$。 因此,我们可以总是优先合并左侧相邻的数,再将合并后的结果与右侧相邻的数进行合并。 diff --git a/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README_EN.md b/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README_EN.md index 860a78e33ae4..35de06154de5 100644 --- a/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README_EN.md +++ b/solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README_EN.md @@ -83,7 +83,7 @@ Note that there are other ways to obtain the same resultant array. ### Solution 1: Stack -If there exist three adjacent numbers $x$, $y$, $z$ that can be merged, then the result of first merging $x$ and $y$, then merging $z$, is the same as the result of first merging $y$ and $z$, then merging $x$. Both results are $\text{LCM}(x, y, z)$. +If there exist three adjacent numbers $x$, $y$, $z$ that can be merged, then the result of first merging $x$ and $y$, then merging $z$, is the same as the result of first merging $y$ and $z$, then merging $x$. Both results are $\textit{LCM}(x, y, z)$. Therefore, we can always prefer to merge the adjacent numbers on the left, and then merge the result with the adjacent number on the right. diff --git a/solution/2200-2299/2202.Maximize the Topmost Element After K Moves/README.md b/solution/2200-2299/2202.Maximize the Topmost Element After K Moves/README.md index 799703ce18a0..b7b94a2e49b4 100644 --- a/solution/2200-2299/2202.Maximize the Topmost Element After K Moves/README.md +++ b/solution/2200-2299/2202.Maximize the Topmost Element After K Moves/README.md @@ -19,18 +19,18 @@ tags: -

    给你一个下标从 0 开始的整数数组 nums ,它表示一个 ,其中 nums[0] 是栈顶的元素。

    +

    给你一个下标从 0 开始的整数数组 nums ,它表示一个 ,其中 nums[0] 是堆顶的元素。

    每一次操作中,你可以执行以下操作 之一 :

      -
    • 如果栈非空,那么 删除 栈顶端的元素。
    • -
    • 如果存在 1 个或者多个被删除的元素,你可以从它们中选择任何一个,添加 回栈顶,这个元素成为新的栈顶元素。
    • +
    • 如果堆非空,那么 删除 堆顶端的元素。
    • +
    • 如果存在 1 个或者多个被删除的元素,你可以从它们中选择任何一个,添加 回堆顶,这个元素成为新的堆顶元素。

    同时给你一个整数 k ,它表示你总共需要执行操作的次数。

    -

    请你返回 恰好 执行 k 次操作以后,栈顶元素的 最大值 。如果执行完 k 次操作以后,栈一定为空,请你返回 -1 。

    +

    请你返回 恰好 执行 k 次操作以后,堆顶元素的 最大值 。如果执行完 k 次操作以后,堆一定为空,请你返回 -1 。

     

    @@ -40,12 +40,12 @@ tags: 输入:nums = [5,2,2,4,0,6], k = 4 输出:5 解释: -4 次操作后,栈顶元素为 5 的方法之一为: -- 第 1 次操作:删除栈顶元素 5 ,栈变为 [2,2,4,0,6] 。 -- 第 2 次操作:删除栈顶元素 2 ,栈变为 [2,4,0,6] 。 -- 第 3 次操作:删除栈顶元素 2 ,栈变为 [4,0,6] 。 -- 第 4 次操作:将 5 添加回栈顶,栈变为 [5,4,0,6] 。 -注意,这不是最后栈顶元素为 5 的唯一方式。但可以证明,4 次操作以后 5 是能得到的最大栈顶元素。 +4 次操作后,堆顶元素为 5 的方法之一为: +- 第 1 次操作:删除堆顶元素 5 ,堆变为 [2,2,4,0,6] 。 +- 第 2 次操作:删除堆顶元素 2 ,堆变为 [2,4,0,6] 。 +- 第 3 次操作:删除堆顶元素 2 ,堆变为 [4,0,6] 。 +- 第 4 次操作:将 5 添加回堆顶,堆变为 [5,4,0,6] 。 +注意,这不是最后堆顶元素为 5 的唯一方式。但可以证明,4 次操作以后 5 是能得到的最大堆顶元素。

    示例 2:

    @@ -54,8 +54,8 @@ tags: 输入:nums = [2], k = 1 输出:-1 解释: -第 1 次操作中,我们唯一的选择是将栈顶元素弹出栈。 -由于 1 次操作后无法得到一个非空的栈,所以我们返回 -1 。 +第 1 次操作中,我们唯一的选择是将堆顶元素弹出堆。 +由于 1 次操作后无法得到一个非空的堆,所以我们返回 -1 。

     

    diff --git a/solution/2200-2299/2213.Longest Substring of One Repeating Character/README.md b/solution/2200-2299/2213.Longest Substring of One Repeating Character/README.md index 212a42c21ddc..df14378ba428 100644 --- a/solution/2200-2299/2213.Longest Substring of One Repeating Character/README.md +++ b/solution/2200-2299/2213.Longest Substring of One Repeating Character/README.md @@ -72,7 +72,7 @@ tags: ### 方法一:线段树 -线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $\log(\text{width})$。更新某个元素的值,只需要更新 $\log(\text{width})$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用**懒标记**保证效率。 +线段树将整个区间分割为多个不连续的子区间,子区间的数量不超过 $\log(\textit{width})$。更新某个元素的值,只需要更新 $\log(\textit{width})$ 个区间,并且这些区间都包含在一个包含该元素的大区间内。区间修改时,需要使用**懒标记**保证效率。 - 线段树的每个节点代表一个区间; - 线段树具有唯一的根节点,代表的区间是整个统计范围,如 $[1, n]$; diff --git a/solution/2200-2299/2213.Longest Substring of One Repeating Character/README_EN.md b/solution/2200-2299/2213.Longest Substring of One Repeating Character/README_EN.md index 57b1824ce85d..0da37c9b62ed 100644 --- a/solution/2200-2299/2213.Longest Substring of One Repeating Character/README_EN.md +++ b/solution/2200-2299/2213.Longest Substring of One Repeating Character/README_EN.md @@ -72,7 +72,7 @@ Thus, we return [2,3]. ### Solution 1: Segment Tree -The segment tree divides the entire interval into multiple non-continuous sub-intervals, and the number of sub-intervals does not exceed $\log(\text{width})$. To update the value of an element, you only need to update $\log(\text{width})$ intervals, and these intervals are all contained in a large interval that contains the element. When modifying the interval, you need to use **lazy tags** to ensure efficiency. +The segment tree divides the entire interval into multiple non-continuous sub-intervals, and the number of sub-intervals does not exceed $\log(\textit{width})$. To update the value of an element, you only need to update $\log(\textit{width})$ intervals, and these intervals are all contained in a large interval that contains the element. When modifying the interval, you need to use **lazy tags** to ensure efficiency. - Each node of the segment tree represents an interval; - The segment tree has a unique root node, which represents the entire statistical range, such as $[1, n]$; diff --git a/solution/2200-2299/2225.Find Players With Zero or One Losses/README.md b/solution/2200-2299/2225.Find Players With Zero or One Losses/README.md index e985faeb63f3..1e68fa33c348 100644 --- a/solution/2200-2299/2225.Find Players With Zero or One Losses/README.md +++ b/solution/2200-2299/2225.Find Players With Zero or One Losses/README.md @@ -84,11 +84,11 @@ tags: ### 方法一:哈希表 + 排序 -我们用一个哈希表 $\text{cnt}$ 记录每个玩家输掉的比赛场次。 +我们用一个哈希表 $\textit{cnt}$ 记录每个玩家输掉的比赛场次。 -然后遍历哈希表,将输掉 $0$ 场比赛的玩家放入 $\text{ans}[0]$,将输掉 $1$ 场比赛的玩家放入 $\text{ans}[1]$。 +然后遍历哈希表,将输掉 $0$ 场比赛的玩家放入 $\textit{ans}[0]$,将输掉 $1$ 场比赛的玩家放入 $\textit{ans}[1]$。 -最后将 $\text{ans}[0]$ 和 $\text{ans}[1]$ 按照升序排序,返回结果。 +最后将 $\textit{ans}[0]$ 和 $\textit{ans}[1]$ 按照升序排序,返回结果。 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为比赛场次数。 diff --git a/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README.md b/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README.md index dcdf52b7e82f..9666fb60ed64 100644 --- a/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README.md +++ b/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README.md @@ -59,7 +59,7 @@ tags: ### 方法一:枚举 -我们可以枚举购买钢笔的数量 $x$,对于每个 $x$,我们最多可以购买铅笔的数量为 $\frac{total - x \times cost1}{cost2}$,那么数量加 $1$ 即为 $x$ 的方案数。我们累加所有的 $x$ 的方案数,即为答案。 +我们可以枚举购买钢笔的数量 $x$,对于每个 $x$,我们最多可以购买铅笔的数量为 $\frac{\textit{total} - x \times \textit{cost1}}{\textit{cost2}}$,那么数量加 $1$ 即为 $x$ 的方案数。我们累加所有的 $x$ 的方案数,即为答案。 时间复杂度 $O(\frac{total}{cost1})$,空间复杂度 $O(1)$。 diff --git a/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README_EN.md b/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README_EN.md index 7e6f4037e915..d98e1e4472a5 100644 --- a/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README_EN.md +++ b/solution/2200-2299/2240.Number of Ways to Buy Pens and Pencils/README_EN.md @@ -57,7 +57,11 @@ The total number of ways to buy pens and pencils is 5 + 3 + 1 = 9. -### Solution 1 +### Solution 1: Enumeration + +We can enumerate the number of pens to buy, denoted as $x$. For each $x$, the maximum number of pencils we can buy is $\frac{\textit{total} - x \times \textit{cost1}}{\textit{cost2}}$. The number of ways for each $x$ is this value plus 1. We sum up the number of ways for all $x$ to get the answer. + +The time complexity is $O(\frac{\textit{total}}{\textit{cost1}})$, and the space complexity is $O(1)$. diff --git a/solution/2200-2299/2241.Design an ATM Machine/README.md b/solution/2200-2299/2241.Design an ATM Machine/README.md index 503ca9a2b6c9..82009c6b5aa7 100644 --- a/solution/2200-2299/2241.Design an ATM Machine/README.md +++ b/solution/2200-2299/2241.Design an ATM Machine/README.md @@ -239,6 +239,48 @@ func (this *ATM) Withdraw(amount int) []int { */ ``` +#### TypeScript + +```ts +class ATM { + private cnt: number[]; + private d: number[]; + + constructor() { + this.cnt = [0, 0, 0, 0, 0]; + this.d = [20, 50, 100, 200, 500]; + } + + deposit(banknotesCount: number[]): void { + for (let i = 0; i < banknotesCount.length; i++) { + this.cnt[i] += banknotesCount[i]; + } + } + + withdraw(amount: number): number[] { + let ans = [0, 0, 0, 0, 0]; + for (let i = 4; i >= 0; i--) { + ans[i] = Math.min(Math.floor(amount / this.d[i]), this.cnt[i]); + amount -= ans[i] * this.d[i]; + } + if (amount > 0) { + return [-1]; + } + for (let i = 0; i < ans.length; i++) { + this.cnt[i] -= ans[i]; + } + return ans; + } +} + +/** + * Your ATM object will be instantiated and called as such: + * var obj = new ATM() + * obj.deposit(banknotesCount) + * var param_2 = obj.withdraw(amount) + */ +``` + diff --git a/solution/2200-2299/2241.Design an ATM Machine/README_EN.md b/solution/2200-2299/2241.Design an ATM Machine/README_EN.md index a35605b8ec5d..3c24e07cb1e5 100644 --- a/solution/2200-2299/2241.Design an ATM Machine/README_EN.md +++ b/solution/2200-2299/2241.Design an ATM Machine/README_EN.md @@ -82,7 +82,13 @@ atm.withdraw(550); // Returns [0,1,0,0,1]. The machine uses 1 $50 banknot -### Solution 1 +### Solution 1: Simulation + +We use an array $d$ to record the denominations of the bills and an array $cnt$ to record the number of bills for each denomination. + +For the `deposit` operation, we only need to add the number of bills for the corresponding denomination. The time complexity is $O(1)$. + +For the `withdraw` operation, we enumerate the bills from largest to smallest denomination, taking out as many bills as possible without exceeding the $amount$. Then, we subtract the total value of the withdrawn bills from $amount$. If $amount$ is still greater than $0$ at the end, it means it's not possible to withdraw the $amount$ with the available bills, and we return $-1$. Otherwise, we return the number of bills withdrawn. The time complexity is $O(1)$. @@ -239,6 +245,48 @@ func (this *ATM) Withdraw(amount int) []int { */ ``` +#### TypeScript + +```ts +class ATM { + private cnt: number[]; + private d: number[]; + + constructor() { + this.cnt = [0, 0, 0, 0, 0]; + this.d = [20, 50, 100, 200, 500]; + } + + deposit(banknotesCount: number[]): void { + for (let i = 0; i < banknotesCount.length; i++) { + this.cnt[i] += banknotesCount[i]; + } + } + + withdraw(amount: number): number[] { + let ans = [0, 0, 0, 0, 0]; + for (let i = 4; i >= 0; i--) { + ans[i] = Math.min(Math.floor(amount / this.d[i]), this.cnt[i]); + amount -= ans[i] * this.d[i]; + } + if (amount > 0) { + return [-1]; + } + for (let i = 0; i < ans.length; i++) { + this.cnt[i] -= ans[i]; + } + return ans; + } +} + +/** + * Your ATM object will be instantiated and called as such: + * var obj = new ATM() + * obj.deposit(banknotesCount) + * var param_2 = obj.withdraw(amount) + */ +``` + diff --git a/solution/2200-2299/2241.Design an ATM Machine/Solution.ts b/solution/2200-2299/2241.Design an ATM Machine/Solution.ts new file mode 100644 index 000000000000..e51670a0d37f --- /dev/null +++ b/solution/2200-2299/2241.Design an ATM Machine/Solution.ts @@ -0,0 +1,37 @@ +class ATM { + private cnt: number[]; + private d: number[]; + + constructor() { + this.cnt = [0, 0, 0, 0, 0]; + this.d = [20, 50, 100, 200, 500]; + } + + deposit(banknotesCount: number[]): void { + for (let i = 0; i < banknotesCount.length; i++) { + this.cnt[i] += banknotesCount[i]; + } + } + + withdraw(amount: number): number[] { + let ans = [0, 0, 0, 0, 0]; + for (let i = 4; i >= 0; i--) { + ans[i] = Math.min(Math.floor(amount / this.d[i]), this.cnt[i]); + amount -= ans[i] * this.d[i]; + } + if (amount > 0) { + return [-1]; + } + for (let i = 0; i < ans.length; i++) { + this.cnt[i] -= ans[i]; + } + return ans; + } +} + +/** + * Your ATM object will be instantiated and called as such: + * var obj = new ATM() + * obj.deposit(banknotesCount) + * var param_2 = obj.withdraw(amount) + */ diff --git a/solution/2200-2299/2246.Longest Path With Different Adjacent Characters/README_EN.md b/solution/2200-2299/2246.Longest Path With Different Adjacent Characters/README_EN.md index 11eb45889295..164819159882 100644 --- a/solution/2200-2299/2246.Longest Path With Different Adjacent Characters/README_EN.md +++ b/solution/2200-2299/2246.Longest Path With Different Adjacent Characters/README_EN.md @@ -69,7 +69,7 @@ It can be proven that there is no longer path that satisfies the conditions. First, we construct an adjacency list $g$ based on the array $parent$, where $g[i]$ represents all child nodes of node $i$. -Then we start DFS from the root node. For each node $i$, we traverse each child node $j$ in $g[i]$. If $s[i] \neq s[j]$, then we can start from node $i$, pass through node $j$, and reach a leaf node. The length of this path is $x = 1 + \text{dfs}(j)$. We use $mx$ to record the longest path length starting from node $i$. At the same time, we update the answer $ans = \max(ans, mx + x)$ during the traversal process. +Then we start DFS from the root node. For each node $i$, we traverse each child node $j$ in $g[i]$. If $s[i] \neq s[j]$, then we can start from node $i$, pass through node $j$, and reach a leaf node. The length of this path is $x = 1 + \textit{dfs}(j)$. We use $mx$ to record the longest path length starting from node $i$. At the same time, we update the answer $ans = \max(ans, mx + x)$ during the traversal process. Finally, we return $ans + 1$. diff --git a/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README.md b/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README.md index 38cc90cc5e64..09df5942ff2c 100644 --- a/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README.md +++ b/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README.md @@ -81,7 +81,7 @@ tags: 考虑 $f[i][j]$ 如何进行状态转移。对于 $f[i]$,我们枚举所有城市 $j$,如果 $i$ 的第 $j$ 位为 $1$,那么我们就可以从其它城市 $h$ 经过公路到达城市 $j$,此时 $f[i][j]$ 的值为 $f[i][h]+cost(h, j)$ 的最大值,其中 $cost(h, j)$ 表示从城市 $h$ 到城市 $j$ 的旅行费用。因此,我们可以得到状态转移方程: $$ -f[i][j]=\max_{h \in \text{city}}\{f[i \backslash j][h]+cost(h, j)\} +f[i][j]=\max_{h \in \textit{city}}\{f[i \backslash j][h]+cost(h, j)\} $$ 其中 $i \backslash j$ 表示将 $i$ 的第 $j$ 位变为 $0$。 diff --git a/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README_EN.md b/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README_EN.md index 41885867f0eb..66626105ebb1 100644 --- a/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README_EN.md +++ b/solution/2200-2299/2247.Maximum Cost of Trip With K Highways/README_EN.md @@ -79,7 +79,7 @@ We use $f[i][j]$ to represent the maximum travel cost when the cities that have Consider how $f[i][j]$ transitions. For $f[i]$, we enumerate all cities $j$. If the $j$-th bit of $i$ is $1$, then we can reach city $j$ from other city $h$ through the road, at this time the value of $f[i][j]$ is the maximum value of $f[i][h]+cost(h, j)$, where $cost(h, j)$ represents the travel cost from city $h$ to city $j$. Therefore, we can get the state transition equation: $$ -f[i][j]=\max_{h \in \text{city}}\{f[i \backslash j][h]+cost(h, j)\} +f[i][j]=\max_{h \in \textit{city}}\{f[i \backslash j][h]+cost(h, j)\} $$ where $i \backslash j$ represents changing the $j$-th bit of $i$ to $0$. diff --git a/solution/2200-2299/2266.Count Number of Texts/README.md b/solution/2200-2299/2266.Count Number of Texts/README.md index e407c0c1bcca..5ebb28674041 100644 --- a/solution/2200-2299/2266.Count Number of Texts/README.md +++ b/solution/2200-2299/2266.Count Number of Texts/README.md @@ -23,7 +23,7 @@ tags:

    Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。

    -

    +

    为了 打出 一个字母,Alice 需要  对应字母 i 次,i 是该字母在这个按键上所处的位置。

    @@ -46,7 +46,8 @@ tags:

    示例 1:

    -
    输入:pressedKeys = "22233"
    +
    +输入:pressedKeys = "22233"
     输出:8
     解释:
     Alice 可能发出的文字信息包括:
    @@ -56,7 +57,8 @@ Alice 可能发出的文字信息包括:
     
     

    示例 2:

    -
    输入:pressedKeys = "222222222222222222222222222222222222"
    +
    +输入:pressedKeys = "222222222222222222222222222222222222"
     输出:82876089
     解释:
     总共有 2082876103 种 Alice 可能发出的文字信息。
    diff --git a/solution/2200-2299/2278.Percentage of Letter in String/README.md b/solution/2200-2299/2278.Percentage of Letter in String/README.md
    index 8c1d7fc62de1..f07378e54608 100644
    --- a/solution/2200-2299/2278.Percentage of Letter in String/README.md	
    +++ b/solution/2200-2299/2278.Percentage of Letter in String/README.md	
    @@ -55,7 +55,11 @@ tags:
     
     
     
    -### 方法一
    +### 方法一:计数
    +
    +我们可以遍历字符串 $\textit{s}$,统计其中等于 $\textit{letter}$ 的字符的个数,然后根据公式 $\textit{count} \times 100 \, / \, \textit{len}(\textit{s})$ 计算百分比。
    +
    +时间复杂度 $O(n)$,其中 $n$ 为字符串 $\textit{s}$ 的长度。空间复杂度 $O(1)$。
     
     
     
    @@ -89,9 +93,7 @@ class Solution {
     class Solution {
     public:
         int percentageLetter(string s, char letter) {
    -        int cnt = 0;
    -        for (char& c : s) cnt += c == letter;
    -        return cnt * 100 / s.size();
    +        return 100 * ranges::count(s, letter) / s.size();
         }
     };
     ```
    @@ -100,13 +102,7 @@ public:
     
     ```go
     func percentageLetter(s string, letter byte) int {
    -	cnt := 0
    -	for i := range s {
    -		if s[i] == letter {
    -			cnt++
    -		}
    -	}
    -	return cnt * 100 / len(s)
    +	return strings.Count(s, string(letter)) * 100 / len(s)
     }
     ```
     
    @@ -114,12 +110,8 @@ func percentageLetter(s string, letter byte) int {
     
     ```ts
     function percentageLetter(s: string, letter: string): number {
    -    let count = 0;
    -    let total = s.length;
    -    for (let i of s) {
    -        if (i === letter) count++;
    -    }
    -    return Math.floor((count / total) * 100);
    +    const count = s.split('').filter(c => c === letter).length;
    +    return Math.floor((100 * count) / s.length);
     }
     ```
     
    @@ -128,13 +120,8 @@ function percentageLetter(s: string, letter: string): number {
     ```rust
     impl Solution {
         pub fn percentage_letter(s: String, letter: char) -> i32 {
    -        let mut count = 0;
    -        for c in s.chars() {
    -            if c == letter {
    -                count += 1;
    -            }
    -        }
    -        ((count * 100) / s.len()) as i32
    +        let count = s.chars().filter(|&c| c == letter).count();
    +        (100 * count as i32 / s.len() as i32) as i32
         }
     }
     ```
    diff --git a/solution/2200-2299/2278.Percentage of Letter in String/README_EN.md b/solution/2200-2299/2278.Percentage of Letter in String/README_EN.md
    index 2152a2dc0ff7..60c71ac9de8e 100644
    --- a/solution/2200-2299/2278.Percentage of Letter in String/README_EN.md	
    +++ b/solution/2200-2299/2278.Percentage of Letter in String/README_EN.md	
    @@ -53,7 +53,11 @@ The percentage of characters in s that equal the letter 'k' is 0%, so we
     
     
     
    -### Solution 1
    +### Solution 1: Counting
    +
    +We can traverse the string $\textit{s}$ and count the number of characters that are equal to $\textit{letter}$. Then, we calculate the percentage using the formula $\textit{count} \times 100 \, / \, \textit{len}(\textit{s})$.
    +
    +Time complexity is $O(n)$, where $n$ is the length of the string $\textit{s}$. Space complexity is $O(1)$.
     
     
     
    @@ -87,9 +91,7 @@ class Solution {
     class Solution {
     public:
         int percentageLetter(string s, char letter) {
    -        int cnt = 0;
    -        for (char& c : s) cnt += c == letter;
    -        return cnt * 100 / s.size();
    +        return 100 * ranges::count(s, letter) / s.size();
         }
     };
     ```
    @@ -98,13 +100,7 @@ public:
     
     ```go
     func percentageLetter(s string, letter byte) int {
    -	cnt := 0
    -	for i := range s {
    -		if s[i] == letter {
    -			cnt++
    -		}
    -	}
    -	return cnt * 100 / len(s)
    +	return strings.Count(s, string(letter)) * 100 / len(s)
     }
     ```
     
    @@ -112,12 +108,8 @@ func percentageLetter(s string, letter byte) int {
     
     ```ts
     function percentageLetter(s: string, letter: string): number {
    -    let count = 0;
    -    let total = s.length;
    -    for (let i of s) {
    -        if (i === letter) count++;
    -    }
    -    return Math.floor((count / total) * 100);
    +    const count = s.split('').filter(c => c === letter).length;
    +    return Math.floor((100 * count) / s.length);
     }
     ```
     
    @@ -126,13 +118,8 @@ function percentageLetter(s: string, letter: string): number {
     ```rust
     impl Solution {
         pub fn percentage_letter(s: String, letter: char) -> i32 {
    -        let mut count = 0;
    -        for c in s.chars() {
    -            if c == letter {
    -                count += 1;
    -            }
    -        }
    -        ((count * 100) / s.len()) as i32
    +        let count = s.chars().filter(|&c| c == letter).count();
    +        (100 * count as i32 / s.len() as i32) as i32
         }
     }
     ```
    diff --git a/solution/2200-2299/2278.Percentage of Letter in String/Solution.cpp b/solution/2200-2299/2278.Percentage of Letter in String/Solution.cpp
    index 055559d6c2cd..a8eea05b52f6 100644
    --- a/solution/2200-2299/2278.Percentage of Letter in String/Solution.cpp	
    +++ b/solution/2200-2299/2278.Percentage of Letter in String/Solution.cpp	
    @@ -1,8 +1,6 @@
     class Solution {
     public:
         int percentageLetter(string s, char letter) {
    -        int cnt = 0;
    -        for (char& c : s) cnt += c == letter;
    -        return cnt * 100 / s.size();
    +        return 100 * ranges::count(s, letter) / s.size();
         }
    -};
    \ No newline at end of file
    +};
    diff --git a/solution/2200-2299/2278.Percentage of Letter in String/Solution.go b/solution/2200-2299/2278.Percentage of Letter in String/Solution.go
    index 2bb7eacd1817..0ae12142cc52 100644
    --- a/solution/2200-2299/2278.Percentage of Letter in String/Solution.go	
    +++ b/solution/2200-2299/2278.Percentage of Letter in String/Solution.go	
    @@ -1,9 +1,3 @@
     func percentageLetter(s string, letter byte) int {
    -	cnt := 0
    -	for i := range s {
    -		if s[i] == letter {
    -			cnt++
    -		}
    -	}
    -	return cnt * 100 / len(s)
    -}
    \ No newline at end of file
    +	return strings.Count(s, string(letter)) * 100 / len(s)
    +}
    diff --git a/solution/2200-2299/2278.Percentage of Letter in String/Solution.rs b/solution/2200-2299/2278.Percentage of Letter in String/Solution.rs
    index 5d3cee347cba..616221e7c685 100644
    --- a/solution/2200-2299/2278.Percentage of Letter in String/Solution.rs	
    +++ b/solution/2200-2299/2278.Percentage of Letter in String/Solution.rs	
    @@ -1,11 +1,6 @@
     impl Solution {
         pub fn percentage_letter(s: String, letter: char) -> i32 {
    -        let mut count = 0;
    -        for c in s.chars() {
    -            if c == letter {
    -                count += 1;
    -            }
    -        }
    -        ((count * 100) / s.len()) as i32
    +        let count = s.chars().filter(|&c| c == letter).count();
    +        (100 * count as i32 / s.len() as i32) as i32
         }
     }
    diff --git a/solution/2200-2299/2278.Percentage of Letter in String/Solution.ts b/solution/2200-2299/2278.Percentage of Letter in String/Solution.ts
    index fdd2298b5231..d6d43008df7f 100644
    --- a/solution/2200-2299/2278.Percentage of Letter in String/Solution.ts	
    +++ b/solution/2200-2299/2278.Percentage of Letter in String/Solution.ts	
    @@ -1,8 +1,4 @@
     function percentageLetter(s: string, letter: string): number {
    -    let count = 0;
    -    let total = s.length;
    -    for (let i of s) {
    -        if (i === letter) count++;
    -    }
    -    return Math.floor((count / total) * 100);
    +    const count = s.split('').filter(c => c === letter).length;
    +    return Math.floor((100 * count) / s.length);
     }
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README.md b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README.md
    index 9383d4f33594..c83b11fb6bca 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README.md	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README.md	
    @@ -74,6 +74,10 @@ tags:
     
     ### 方法一:排序 + 贪心
     
    +我们首先将每个背包的剩余容量计算出来,然后对剩余容量进行排序,接着我们从小到大遍历剩余容量,将额外的石头放入背包中,直到额外的石头用完或者背包的剩余容量用完为止,返回此时的背包数量即可。
    +
    +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为背包的数量。
    +
     
     
     #### Python3
    @@ -83,14 +87,14 @@ class Solution:
         def maximumBags(
             self, capacity: List[int], rocks: List[int], additionalRocks: int
         ) -> int:
    -        d = [a - b for a, b in zip(capacity, rocks)]
    -        d.sort()
    -        ans = 0
    -        for v in d:
    -            if v <= additionalRocks:
    -                ans += 1
    -                additionalRocks -= v
    -        return ans
    +        for i, x in enumerate(rocks):
    +            capacity[i] -= x
    +        capacity.sort()
    +        for i, x in enumerate(capacity):
    +            additionalRocks -= x
    +            if additionalRocks < 0:
    +                return i
    +        return len(capacity)
     ```
     
     #### Java
    @@ -98,22 +102,18 @@ class Solution:
     ```java
     class Solution {
         public int maximumBags(int[] capacity, int[] rocks, int additionalRocks) {
    -        int n = capacity.length;
    -        int[] d = new int[n];
    +        int n = rocks.length;
             for (int i = 0; i < n; ++i) {
    -            d[i] = capacity[i] - rocks[i];
    +            capacity[i] -= rocks[i];
             }
    -        Arrays.sort(d);
    -        int ans = 0;
    -        for (int v : d) {
    -            if (v <= additionalRocks) {
    -                ++ans;
    -                additionalRocks -= v;
    -            } else {
    -                break;
    +        Arrays.sort(capacity);
    +        for (int i = 0; i < n; ++i) {
    +            additionalRocks -= capacity[i];
    +            if (additionalRocks < 0) {
    +                return i;
                 }
             }
    -        return ans;
    +        return n;
         }
     }
     ```
    @@ -124,17 +124,18 @@ class Solution {
     class Solution {
     public:
         int maximumBags(vector& capacity, vector& rocks, int additionalRocks) {
    -        int n = capacity.size();
    -        vector d(n);
    -        for (int i = 0; i < n; ++i) d[i] = capacity[i] - rocks[i];
    -        sort(d.begin(), d.end());
    -        int ans = 0;
    -        for (int& v : d) {
    -            if (v > additionalRocks) break;
    -            ++ans;
    -            additionalRocks -= v;
    +        int n = rocks.size();
    +        for (int i = 0; i < n; ++i) {
    +            capacity[i] -= rocks[i];
             }
    -        return ans;
    +        ranges::sort(capacity);
    +        for (int i = 0; i < n; ++i) {
    +            additionalRocks -= capacity[i];
    +            if (additionalRocks < 0) {
    +                return i;
    +            }
    +        }
    +        return n;
         }
     };
     ```
    @@ -143,21 +144,17 @@ public:
     
     ```go
     func maximumBags(capacity []int, rocks []int, additionalRocks int) int {
    -	n := len(capacity)
    -	d := make([]int, n)
    -	for i, v := range capacity {
    -		d[i] = v - rocks[i]
    +	for i, x := range rocks {
    +		capacity[i] -= x
     	}
    -	sort.Ints(d)
    -	ans := 0
    -	for _, v := range d {
    -		if v > additionalRocks {
    -			break
    +	sort.Ints(capacity)
    +	for i, x := range capacity {
    +		additionalRocks -= x
    +		if additionalRocks < 0 {
    +			return i
     		}
    -		ans++
    -		additionalRocks -= v
     	}
    -	return ans
    +	return len(capacity)
     }
     ```
     
    @@ -165,15 +162,18 @@ func maximumBags(capacity []int, rocks []int, additionalRocks int) int {
     
     ```ts
     function maximumBags(capacity: number[], rocks: number[], additionalRocks: number): number {
    -    const n = capacity.length;
    -    const diffs = capacity.map((c, i) => c - rocks[i]);
    -    diffs.sort((a, b) => a - b);
    -    let ans = 0;
    -    for (let i = 0; i < n && (diffs[i] === 0 || diffs[i] <= additionalRocks); i++) {
    -        ans++;
    -        additionalRocks -= diffs[i];
    +    const n = rocks.length;
    +    for (let i = 0; i < n; ++i) {
    +        capacity[i] -= rocks[i];
    +    }
    +    capacity.sort((a, b) => a - b);
    +    for (let i = 0; i < n; ++i) {
    +        additionalRocks -= capacity[i];
    +        if (additionalRocks < 0) {
    +            return i;
    +        }
         }
    -    return ans;
    +    return n;
     }
     ```
     
    @@ -181,20 +181,18 @@ function maximumBags(capacity: number[], rocks: number[], additionalRocks: numbe
     
     ```rust
     impl Solution {
    -    pub fn maximum_bags(capacity: Vec, rocks: Vec, mut additional_rocks: i32) -> i32 {
    -        let n = capacity.len();
    -        let mut diffs = vec![0; n];
    -        for i in 0..n {
    -            diffs[i] = capacity[i] - rocks[i];
    +    pub fn maximum_bags(mut capacity: Vec, rocks: Vec, mut additional_rocks: i32) -> i32 {
    +        for i in 0..rocks.len() {
    +            capacity[i] -= rocks[i];
             }
    -        diffs.sort();
    -        for i in 0..n {
    -            if diffs[i] > additional_rocks {
    +        capacity.sort();
    +        for i in 0..capacity.len() {
    +            additional_rocks -= capacity[i];
    +            if additional_rocks < 0 {
                     return i as i32;
                 }
    -            additional_rocks -= diffs[i];
             }
    -        n as i32
    +        capacity.len() as i32
         }
     }
     ```
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README_EN.md b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README_EN.md
    index 8b53a9d2dcb7..5b35dca0954b 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README_EN.md	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/README_EN.md	
    @@ -70,7 +70,11 @@ Note that we did not use all of the additional rocks.
     
     
     
    -### Solution 1
    +### Solution 1: Sorting + Greedy
    +
    +First, we calculate the remaining capacity of each bag, then sort the remaining capacities. Next, we traverse the remaining capacities from smallest to largest, putting the extra stones into the bags until the extra stones are used up or the remaining capacities of the bags are exhausted. Finally, we return the number of bags at this point.
    +
    +Time complexity is $O(n \times \log n)$, and space complexity is $O(\log n)$. Here, $n$ is the number of bags.
     
     
     
    @@ -81,14 +85,14 @@ class Solution:
         def maximumBags(
             self, capacity: List[int], rocks: List[int], additionalRocks: int
         ) -> int:
    -        d = [a - b for a, b in zip(capacity, rocks)]
    -        d.sort()
    -        ans = 0
    -        for v in d:
    -            if v <= additionalRocks:
    -                ans += 1
    -                additionalRocks -= v
    -        return ans
    +        for i, x in enumerate(rocks):
    +            capacity[i] -= x
    +        capacity.sort()
    +        for i, x in enumerate(capacity):
    +            additionalRocks -= x
    +            if additionalRocks < 0:
    +                return i
    +        return len(capacity)
     ```
     
     #### Java
    @@ -96,22 +100,18 @@ class Solution:
     ```java
     class Solution {
         public int maximumBags(int[] capacity, int[] rocks, int additionalRocks) {
    -        int n = capacity.length;
    -        int[] d = new int[n];
    +        int n = rocks.length;
             for (int i = 0; i < n; ++i) {
    -            d[i] = capacity[i] - rocks[i];
    +            capacity[i] -= rocks[i];
             }
    -        Arrays.sort(d);
    -        int ans = 0;
    -        for (int v : d) {
    -            if (v <= additionalRocks) {
    -                ++ans;
    -                additionalRocks -= v;
    -            } else {
    -                break;
    +        Arrays.sort(capacity);
    +        for (int i = 0; i < n; ++i) {
    +            additionalRocks -= capacity[i];
    +            if (additionalRocks < 0) {
    +                return i;
                 }
             }
    -        return ans;
    +        return n;
         }
     }
     ```
    @@ -122,17 +122,18 @@ class Solution {
     class Solution {
     public:
         int maximumBags(vector& capacity, vector& rocks, int additionalRocks) {
    -        int n = capacity.size();
    -        vector d(n);
    -        for (int i = 0; i < n; ++i) d[i] = capacity[i] - rocks[i];
    -        sort(d.begin(), d.end());
    -        int ans = 0;
    -        for (int& v : d) {
    -            if (v > additionalRocks) break;
    -            ++ans;
    -            additionalRocks -= v;
    +        int n = rocks.size();
    +        for (int i = 0; i < n; ++i) {
    +            capacity[i] -= rocks[i];
             }
    -        return ans;
    +        ranges::sort(capacity);
    +        for (int i = 0; i < n; ++i) {
    +            additionalRocks -= capacity[i];
    +            if (additionalRocks < 0) {
    +                return i;
    +            }
    +        }
    +        return n;
         }
     };
     ```
    @@ -141,21 +142,17 @@ public:
     
     ```go
     func maximumBags(capacity []int, rocks []int, additionalRocks int) int {
    -	n := len(capacity)
    -	d := make([]int, n)
    -	for i, v := range capacity {
    -		d[i] = v - rocks[i]
    +	for i, x := range rocks {
    +		capacity[i] -= x
     	}
    -	sort.Ints(d)
    -	ans := 0
    -	for _, v := range d {
    -		if v > additionalRocks {
    -			break
    +	sort.Ints(capacity)
    +	for i, x := range capacity {
    +		additionalRocks -= x
    +		if additionalRocks < 0 {
    +			return i
     		}
    -		ans++
    -		additionalRocks -= v
     	}
    -	return ans
    +	return len(capacity)
     }
     ```
     
    @@ -163,15 +160,18 @@ func maximumBags(capacity []int, rocks []int, additionalRocks int) int {
     
     ```ts
     function maximumBags(capacity: number[], rocks: number[], additionalRocks: number): number {
    -    const n = capacity.length;
    -    const diffs = capacity.map((c, i) => c - rocks[i]);
    -    diffs.sort((a, b) => a - b);
    -    let ans = 0;
    -    for (let i = 0; i < n && (diffs[i] === 0 || diffs[i] <= additionalRocks); i++) {
    -        ans++;
    -        additionalRocks -= diffs[i];
    +    const n = rocks.length;
    +    for (let i = 0; i < n; ++i) {
    +        capacity[i] -= rocks[i];
    +    }
    +    capacity.sort((a, b) => a - b);
    +    for (let i = 0; i < n; ++i) {
    +        additionalRocks -= capacity[i];
    +        if (additionalRocks < 0) {
    +            return i;
    +        }
         }
    -    return ans;
    +    return n;
     }
     ```
     
    @@ -179,20 +179,18 @@ function maximumBags(capacity: number[], rocks: number[], additionalRocks: numbe
     
     ```rust
     impl Solution {
    -    pub fn maximum_bags(capacity: Vec, rocks: Vec, mut additional_rocks: i32) -> i32 {
    -        let n = capacity.len();
    -        let mut diffs = vec![0; n];
    -        for i in 0..n {
    -            diffs[i] = capacity[i] - rocks[i];
    +    pub fn maximum_bags(mut capacity: Vec, rocks: Vec, mut additional_rocks: i32) -> i32 {
    +        for i in 0..rocks.len() {
    +            capacity[i] -= rocks[i];
             }
    -        diffs.sort();
    -        for i in 0..n {
    -            if diffs[i] > additional_rocks {
    +        capacity.sort();
    +        for i in 0..capacity.len() {
    +            additional_rocks -= capacity[i];
    +            if additional_rocks < 0 {
                     return i as i32;
                 }
    -            additional_rocks -= diffs[i];
             }
    -        n as i32
    +        capacity.len() as i32
         }
     }
     ```
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.cpp b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.cpp
    index 0cc800926f79..1c829c8bc6db 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.cpp	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.cpp	
    @@ -1,16 +1,17 @@
     class Solution {
     public:
         int maximumBags(vector& capacity, vector& rocks, int additionalRocks) {
    -        int n = capacity.size();
    -        vector d(n);
    -        for (int i = 0; i < n; ++i) d[i] = capacity[i] - rocks[i];
    -        sort(d.begin(), d.end());
    -        int ans = 0;
    -        for (int& v : d) {
    -            if (v > additionalRocks) break;
    -            ++ans;
    -            additionalRocks -= v;
    +        int n = rocks.size();
    +        for (int i = 0; i < n; ++i) {
    +            capacity[i] -= rocks[i];
             }
    -        return ans;
    +        ranges::sort(capacity);
    +        for (int i = 0; i < n; ++i) {
    +            additionalRocks -= capacity[i];
    +            if (additionalRocks < 0) {
    +                return i;
    +            }
    +        }
    +        return n;
         }
    -};
    \ No newline at end of file
    +};
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.go b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.go
    index b4b1f56386b3..71750d79224c 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.go	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.go	
    @@ -1,17 +1,13 @@
     func maximumBags(capacity []int, rocks []int, additionalRocks int) int {
    -	n := len(capacity)
    -	d := make([]int, n)
    -	for i, v := range capacity {
    -		d[i] = v - rocks[i]
    +	for i, x := range rocks {
    +		capacity[i] -= x
     	}
    -	sort.Ints(d)
    -	ans := 0
    -	for _, v := range d {
    -		if v > additionalRocks {
    -			break
    +	sort.Ints(capacity)
    +	for i, x := range capacity {
    +		additionalRocks -= x
    +		if additionalRocks < 0 {
    +			return i
     		}
    -		ans++
    -		additionalRocks -= v
     	}
    -	return ans
    -}
    \ No newline at end of file
    +	return len(capacity)
    +}
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.java b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.java
    index a05c54f6caef..3c4f5cdadbde 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.java	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.java	
    @@ -1,20 +1,16 @@
     class Solution {
         public int maximumBags(int[] capacity, int[] rocks, int additionalRocks) {
    -        int n = capacity.length;
    -        int[] d = new int[n];
    +        int n = rocks.length;
             for (int i = 0; i < n; ++i) {
    -            d[i] = capacity[i] - rocks[i];
    +            capacity[i] -= rocks[i];
             }
    -        Arrays.sort(d);
    -        int ans = 0;
    -        for (int v : d) {
    -            if (v <= additionalRocks) {
    -                ++ans;
    -                additionalRocks -= v;
    -            } else {
    -                break;
    +        Arrays.sort(capacity);
    +        for (int i = 0; i < n; ++i) {
    +            additionalRocks -= capacity[i];
    +            if (additionalRocks < 0) {
    +                return i;
                 }
             }
    -        return ans;
    +        return n;
         }
    -}
    \ No newline at end of file
    +}
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.py b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.py
    index 009adf577a2f..c6aba5308427 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.py	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.py	
    @@ -2,11 +2,11 @@ class Solution:
         def maximumBags(
             self, capacity: List[int], rocks: List[int], additionalRocks: int
         ) -> int:
    -        d = [a - b for a, b in zip(capacity, rocks)]
    -        d.sort()
    -        ans = 0
    -        for v in d:
    -            if v <= additionalRocks:
    -                ans += 1
    -                additionalRocks -= v
    -        return ans
    +        for i, x in enumerate(rocks):
    +            capacity[i] -= x
    +        capacity.sort()
    +        for i, x in enumerate(capacity):
    +            additionalRocks -= x
    +            if additionalRocks < 0:
    +                return i
    +        return len(capacity)
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.rs b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.rs
    index 77645fee3728..5339d5e7cf37 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.rs	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.rs	
    @@ -1,17 +1,15 @@
     impl Solution {
    -    pub fn maximum_bags(capacity: Vec, rocks: Vec, mut additional_rocks: i32) -> i32 {
    -        let n = capacity.len();
    -        let mut diffs = vec![0; n];
    -        for i in 0..n {
    -            diffs[i] = capacity[i] - rocks[i];
    +    pub fn maximum_bags(mut capacity: Vec, rocks: Vec, mut additional_rocks: i32) -> i32 {
    +        for i in 0..rocks.len() {
    +            capacity[i] -= rocks[i];
             }
    -        diffs.sort();
    -        for i in 0..n {
    -            if diffs[i] > additional_rocks {
    +        capacity.sort();
    +        for i in 0..capacity.len() {
    +            additional_rocks -= capacity[i];
    +            if additional_rocks < 0 {
                     return i as i32;
                 }
    -            additional_rocks -= diffs[i];
             }
    -        n as i32
    +        capacity.len() as i32
         }
     }
    diff --git a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.ts b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.ts
    index 863e3a13e9b8..7cd56e4e530d 100644
    --- a/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.ts	
    +++ b/solution/2200-2299/2279.Maximum Bags With Full Capacity of Rocks/Solution.ts	
    @@ -1,11 +1,14 @@
     function maximumBags(capacity: number[], rocks: number[], additionalRocks: number): number {
    -    const n = capacity.length;
    -    const diffs = capacity.map((c, i) => c - rocks[i]);
    -    diffs.sort((a, b) => a - b);
    -    let ans = 0;
    -    for (let i = 0; i < n && (diffs[i] === 0 || diffs[i] <= additionalRocks); i++) {
    -        ans++;
    -        additionalRocks -= diffs[i];
    +    const n = rocks.length;
    +    for (let i = 0; i < n; ++i) {
    +        capacity[i] -= rocks[i];
         }
    -    return ans;
    +    capacity.sort((a, b) => a - b);
    +    for (let i = 0; i < n; ++i) {
    +        additionalRocks -= capacity[i];
    +        if (additionalRocks < 0) {
    +            return i;
    +        }
    +    }
    +    return n;
     }
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README.md b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README.md
    index 54a2cb136451..bdba152559ba 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README.md	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README.md	
    @@ -69,9 +69,9 @@ num[2] = '0' 。数字 2 在 num 中出现了 0 次。
     
     ### 方法一:计数 + 枚举
     
    -统计字符串中每个数字出现的次数,然后枚举每个数字,判断其出现的次数是否与其值相等,若都相等则返回 `true`,否则返回 `false`。
    +我们可以用一个长度为 $10$ 的数组 $\textit{cnt}$ 统计字符串 $\textit{num}$ 中每个数字出现的次数,然后再枚举字符串 $\textit{num}$ 中的每个数字,判断其出现的次数是否等于该数字本身。如果对于所有的数字都满足这个条件,那么返回 $\text{true}$,否则返回 $\text{false}$。
     
    -时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 是字符串 `num` 的长度,而 $C$ 是数字的个数。本题中 $C=10$。
    +时间复杂度 $O(n)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 是字符串 $\textit{num}$ 的长度,而 $|\Sigma|$ 是数字的取值范围,即 $10$。
     
     
     
    @@ -80,8 +80,8 @@ num[2] = '0' 。数字 2 在 num 中出现了 0 次。
     ```python
     class Solution:
         def digitCount(self, num: str) -> bool:
    -        cnt = Counter(num)
    -        return all(cnt[str(i)] == int(v) for i, v in enumerate(num))
    +        cnt = Counter(int(x) for x in num)
    +        return all(cnt[i] == int(x) for i, x in enumerate(num))
     ```
     
     #### Java
    @@ -95,7 +95,7 @@ class Solution {
                 ++cnt[num.charAt(i) - '0'];
             }
             for (int i = 0; i < n; ++i) {
    -            if (cnt[i] != num.charAt(i) - '0') {
    +            if (num.charAt(i) - '0' != cnt[i]) {
                     return false;
                 }
             }
    @@ -132,8 +132,8 @@ func digitCount(num string) bool {
     	for _, c := range num {
     		cnt[c-'0']++
     	}
    -	for i, v := range num {
    -		if cnt[i] != int(v-'0') {
    +	for i, c := range num {
    +		if int(c-'0') != cnt[i] {
     			return false
     		}
     	}
    @@ -145,15 +145,16 @@ func digitCount(num string) bool {
     
     ```ts
     function digitCount(num: string): boolean {
    -    const n = num.length;
    -    const count = new Array(10).fill(0);
    -    for (let i = 0; i < n; i++) {
    -        count[i] = Number(num[i]);
    -    }
    +    const cnt: number[] = Array(10).fill(0);
         for (const c of num) {
    -        count[c]--;
    +        ++cnt[+c];
    +    }
    +    for (let i = 0; i < num.length; ++i) {
    +        if (cnt[i] !== +num[i]) {
    +            return false;
    +        }
         }
    -    return count.every(v => v === 0);
    +    return true;
     }
     ```
     
    @@ -162,16 +163,18 @@ function digitCount(num: string): boolean {
     ```rust
     impl Solution {
         pub fn digit_count(num: String) -> bool {
    -        let s = num.as_bytes();
    -        let n = num.len();
    -        let mut count = [0; 10];
    -        for i in 0..n {
    -            count[i] = s[i] - b'0';
    +        let mut cnt = vec![0; 10];
    +        for c in num.chars() {
    +            let x = c.to_digit(10).unwrap() as usize;
    +            cnt[x] += 1;
             }
    -        for c in s {
    -            count[(c - b'0') as usize] -= 1;
    +        for (i, c) in num.chars().enumerate() {
    +            let x = c.to_digit(10).unwrap() as usize;
    +            if cnt[i] != x {
    +                return false;
    +            }
             }
    -        count.iter().all(|v| *v == 0)
    +        true
         }
     }
     ```
    @@ -180,15 +183,12 @@ impl Solution {
     
     ```c
     bool digitCount(char* num) {
    -    int count[10] = {0};
    -    for (int i = 0; num[i]; i++) {
    -        count[i] = num[i] - '0';
    -    }
    -    for (int i = 0; num[i]; i++) {
    -        count[num[i] - '0']--;
    +    int cnt[10] = {0};
    +    for (int i = 0; num[i] != '\0'; ++i) {
    +        ++cnt[num[i] - '0'];
         }
    -    for (int i = 0; i < 10; i++) {
    -        if (count[i] != 0) {
    +    for (int i = 0; num[i] != '\0'; ++i) {
    +        if (cnt[i] != num[i] - '0') {
                 return false;
             }
         }
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README_EN.md b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README_EN.md
    index 28e6796c0d1d..bda13d68dedc 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README_EN.md	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/README_EN.md	
    @@ -65,7 +65,11 @@ The indices 0 and 1 both violate the condition, so return false.
     
     
     
    -### Solution 1
    +### Solution 1: Counting + Enumeration
    +
    +We can use an array $\textit{cnt}$ of length $10$ to count the occurrences of each digit in the string $\textit{num}$. Then, we enumerate each digit in the string $\textit{num}$ and check if its occurrence count equals the digit itself. If this condition is satisfied for all digits, we return $\text{true}$; otherwise, we return $\text{false}$.
    +
    +The time complexity is $O(n)$, and the space complexity is $O(|\Sigma|)$. Here, $n$ is the length of the string $\textit{num}$, and $|\Sigma|$ is the range of possible digit values, which is $10$.
     
     
     
    @@ -74,8 +78,8 @@ The indices 0 and 1 both violate the condition, so return false.
     ```python
     class Solution:
         def digitCount(self, num: str) -> bool:
    -        cnt = Counter(num)
    -        return all(cnt[str(i)] == int(v) for i, v in enumerate(num))
    +        cnt = Counter(int(x) for x in num)
    +        return all(cnt[i] == int(x) for i, x in enumerate(num))
     ```
     
     #### Java
    @@ -89,7 +93,7 @@ class Solution {
                 ++cnt[num.charAt(i) - '0'];
             }
             for (int i = 0; i < n; ++i) {
    -            if (cnt[i] != num.charAt(i) - '0') {
    +            if (num.charAt(i) - '0' != cnt[i]) {
                     return false;
                 }
             }
    @@ -126,8 +130,8 @@ func digitCount(num string) bool {
     	for _, c := range num {
     		cnt[c-'0']++
     	}
    -	for i, v := range num {
    -		if cnt[i] != int(v-'0') {
    +	for i, c := range num {
    +		if int(c-'0') != cnt[i] {
     			return false
     		}
     	}
    @@ -139,15 +143,16 @@ func digitCount(num string) bool {
     
     ```ts
     function digitCount(num: string): boolean {
    -    const n = num.length;
    -    const count = new Array(10).fill(0);
    -    for (let i = 0; i < n; i++) {
    -        count[i] = Number(num[i]);
    -    }
    +    const cnt: number[] = Array(10).fill(0);
         for (const c of num) {
    -        count[c]--;
    +        ++cnt[+c];
    +    }
    +    for (let i = 0; i < num.length; ++i) {
    +        if (cnt[i] !== +num[i]) {
    +            return false;
    +        }
         }
    -    return count.every(v => v === 0);
    +    return true;
     }
     ```
     
    @@ -156,16 +161,18 @@ function digitCount(num: string): boolean {
     ```rust
     impl Solution {
         pub fn digit_count(num: String) -> bool {
    -        let s = num.as_bytes();
    -        let n = num.len();
    -        let mut count = [0; 10];
    -        for i in 0..n {
    -            count[i] = s[i] - b'0';
    +        let mut cnt = vec![0; 10];
    +        for c in num.chars() {
    +            let x = c.to_digit(10).unwrap() as usize;
    +            cnt[x] += 1;
             }
    -        for c in s {
    -            count[(c - b'0') as usize] -= 1;
    +        for (i, c) in num.chars().enumerate() {
    +            let x = c.to_digit(10).unwrap() as usize;
    +            if cnt[i] != x {
    +                return false;
    +            }
             }
    -        count.iter().all(|v| *v == 0)
    +        true
         }
     }
     ```
    @@ -174,15 +181,12 @@ impl Solution {
     
     ```c
     bool digitCount(char* num) {
    -    int count[10] = {0};
    -    for (int i = 0; num[i]; i++) {
    -        count[i] = num[i] - '0';
    -    }
    -    for (int i = 0; num[i]; i++) {
    -        count[num[i] - '0']--;
    +    int cnt[10] = {0};
    +    for (int i = 0; num[i] != '\0'; ++i) {
    +        ++cnt[num[i] - '0'];
         }
    -    for (int i = 0; i < 10; i++) {
    -        if (count[i] != 0) {
    +    for (int i = 0; num[i] != '\0'; ++i) {
    +        if (cnt[i] != num[i] - '0') {
                 return false;
             }
         }
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.c b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.c
    index 1eaaa0c1c712..8d8993c37928 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.c	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.c	
    @@ -1,13 +1,10 @@
     bool digitCount(char* num) {
    -    int count[10] = {0};
    -    for (int i = 0; num[i]; i++) {
    -        count[i] = num[i] - '0';
    +    int cnt[10] = {0};
    +    for (int i = 0; num[i] != '\0'; ++i) {
    +        ++cnt[num[i] - '0'];
         }
    -    for (int i = 0; num[i]; i++) {
    -        count[num[i] - '0']--;
    -    }
    -    for (int i = 0; i < 10; i++) {
    -        if (count[i] != 0) {
    +    for (int i = 0; num[i] != '\0'; ++i) {
    +        if (cnt[i] != num[i] - '0') {
                 return false;
             }
         }
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.go b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.go
    index c0c28be166b2..abb22e8f7a4f 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.go	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.go	
    @@ -3,8 +3,8 @@ func digitCount(num string) bool {
     	for _, c := range num {
     		cnt[c-'0']++
     	}
    -	for i, v := range num {
    -		if cnt[i] != int(v-'0') {
    +	for i, c := range num {
    +		if int(c-'0') != cnt[i] {
     			return false
     		}
     	}
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.java b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.java
    index a0be9313ccc2..c00aef7ccdca 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.java	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.java	
    @@ -6,7 +6,7 @@ public boolean digitCount(String num) {
                 ++cnt[num.charAt(i) - '0'];
             }
             for (int i = 0; i < n; ++i) {
    -            if (cnt[i] != num.charAt(i) - '0') {
    +            if (num.charAt(i) - '0' != cnt[i]) {
                     return false;
                 }
             }
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.py b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.py
    index e45e6a98dc36..9ee307c6e7c4 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.py	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.py	
    @@ -1,4 +1,4 @@
     class Solution:
         def digitCount(self, num: str) -> bool:
    -        cnt = Counter(num)
    -        return all(cnt[str(i)] == int(v) for i, v in enumerate(num))
    +        cnt = Counter(int(x) for x in num)
    +        return all(cnt[i] == int(x) for i, x in enumerate(num))
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.rs b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.rs
    index a67463dc882e..ef4c68f936e2 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.rs	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.rs	
    @@ -1,14 +1,16 @@
     impl Solution {
         pub fn digit_count(num: String) -> bool {
    -        let s = num.as_bytes();
    -        let n = num.len();
    -        let mut count = [0; 10];
    -        for i in 0..n {
    -            count[i] = s[i] - b'0';
    +        let mut cnt = vec![0; 10];
    +        for c in num.chars() {
    +            let x = c.to_digit(10).unwrap() as usize;
    +            cnt[x] += 1;
             }
    -        for c in s {
    -            count[(c - b'0') as usize] -= 1;
    +        for (i, c) in num.chars().enumerate() {
    +            let x = c.to_digit(10).unwrap() as usize;
    +            if cnt[i] != x {
    +                return false;
    +            }
             }
    -        count.iter().all(|v| *v == 0)
    +        true
         }
     }
    diff --git a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.ts b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.ts
    index 0b2d74eaf97a..4771e2d7da88 100644
    --- a/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.ts	
    +++ b/solution/2200-2299/2283.Check if Number Has Equal Digit Count and Digit Value/Solution.ts	
    @@ -1,11 +1,12 @@
     function digitCount(num: string): boolean {
    -    const n = num.length;
    -    const count = new Array(10).fill(0);
    -    for (let i = 0; i < n; i++) {
    -        count[i] = Number(num[i]);
    -    }
    +    const cnt: number[] = Array(10).fill(0);
         for (const c of num) {
    -        count[c]--;
    +        ++cnt[+c];
    +    }
    +    for (let i = 0; i < num.length; ++i) {
    +        if (cnt[i] !== +num[i]) {
    +            return false;
    +        }
         }
    -    return count.every(v => v === 0);
    +    return true;
     }
    diff --git a/solution/2200-2299/2284.Sender With Largest Word Count/README.md b/solution/2200-2299/2284.Sender With Largest Word Count/README.md
    index 1c4543072a1c..4d5e3d7921cd 100644
    --- a/solution/2200-2299/2284.Sender With Largest Word Count/README.md	
    +++ b/solution/2200-2299/2284.Sender With Largest Word Count/README.md	
    @@ -77,9 +77,9 @@ Charlie 总共发出了 5 个单词。
     
     ### 方法一:哈希表 + 枚举
     
    -我们用哈希表 `cnt` 统计每个发件人的单词数,然后枚举每个发件人,找到单词数最多且字典序最大的发件人即可。
    +我们可以用一个哈希表 $\textit{cnt}$ 记录每个发件人的单词数,然后遍历哈希表找到单词数最多的发件人,如果有多个发件人发出最多单词数,我们返回字典序最大的名字。
     
    -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为 `messages` 的长度。
    +时间复杂度 $O(n + L)$,空间复杂度 $O(n)$,其中 $n$ 是消息的数量,而 $L$ 是所有消息的总长度。
     
     
     
    @@ -89,12 +89,12 @@ Charlie 总共发出了 5 个单词。
     class Solution:
         def largestWordCount(self, messages: List[str], senders: List[str]) -> str:
             cnt = Counter()
    -        for msg, sender in zip(messages, senders):
    -            cnt[sender] += msg.count(' ') + 1
    -        ans = ''
    -        for sender, v in cnt.items():
    -            if cnt[ans] < v or (cnt[ans] == v and ans < sender):
    -                ans = sender
    +        for message, sender in zip(messages, senders):
    +            cnt[sender] += message.count(" ") + 1
    +        ans = senders[0]
    +        for k, v in cnt.items():
    +            if cnt[ans] < v or (cnt[ans] == v and ans < k):
    +                ans = k
             return ans
     ```
     
    @@ -103,9 +103,8 @@ class Solution:
     ```java
     class Solution {
         public String largestWordCount(String[] messages, String[] senders) {
    -        Map cnt = new HashMap<>();
    -        int n = senders.length;
    -        for (int i = 0; i < n; ++i) {
    +        Map cnt = new HashMap<>(senders.length);
    +        for (int i = 0; i < messages.length; ++i) {
                 int v = 1;
                 for (int j = 0; j < messages[i].length(); ++j) {
                     if (messages[i].charAt(j) == ' ') {
    @@ -116,10 +115,10 @@ class Solution {
             }
             String ans = senders[0];
             for (var e : cnt.entrySet()) {
    -            String sender = e.getKey();
    -            if (cnt.get(ans) < cnt.get(sender)
    -                || (cnt.get(ans) == cnt.get(sender) && ans.compareTo(sender) < 0)) {
    -                ans = sender;
    +            String k = e.getKey();
    +            int v = e.getValue();
    +            if (cnt.get(ans) < v || (cnt.get(ans) == v && ans.compareTo(k) < 0)) {
    +                ans = k;
                 }
             }
             return ans;
    @@ -134,15 +133,14 @@ class Solution {
     public:
         string largestWordCount(vector& messages, vector& senders) {
             unordered_map cnt;
    -        int n = senders.size();
    -        for (int i = 0; i < n; ++i) {
    +        for (int i = 0; i < messages.size(); ++i) {
                 int v = count(messages[i].begin(), messages[i].end(), ' ') + 1;
                 cnt[senders[i]] += v;
             }
             string ans = senders[0];
    -        for (auto& [sender, v] : cnt) {
    -            if (cnt[ans] < v || (cnt[ans] == v && ans < sender)) {
    -                ans = sender;
    +        for (auto& [k, v] : cnt) {
    +            if (cnt[ans] < v || (cnt[ans] == v && ans < k)) {
    +                ans = k;
                 }
             }
             return ans;
    @@ -153,18 +151,42 @@ public:
     #### Go
     
     ```go
    -func largestWordCount(messages []string, senders []string) (ans string) {
    -	cnt := map[string]int{}
    -	for i, msg := range messages {
    -		v := strings.Count(msg, " ") + 1
    +func largestWordCount(messages []string, senders []string) string {
    +	cnt := make(map[string]int)
    +	for i, message := range messages {
    +		v := strings.Count(message, " ") + 1
     		cnt[senders[i]] += v
     	}
    -	for sender, v := range cnt {
    -		if cnt[ans] < v || (cnt[ans] == v && ans < sender) {
    -			ans = sender
    +
    +	ans := senders[0]
    +	for k, v := range cnt {
    +		if cnt[ans] < v || (cnt[ans] == v && ans < k) {
    +			ans = k
     		}
     	}
    -	return
    +	return ans
    +}
    +```
    +
    +#### TypeScript
    +
    +```ts
    +function largestWordCount(messages: string[], senders: string[]): string {
    +    const cnt: { [key: string]: number } = {};
    +
    +    for (let i = 0; i < messages.length; ++i) {
    +        const v = messages[i].split(' ').length;
    +        cnt[senders[i]] = (cnt[senders[i]] || 0) + v;
    +    }
    +
    +    let ans = senders[0];
    +    for (const k in cnt) {
    +        if (cnt[ans] < cnt[k] || (cnt[ans] === cnt[k] && ans < k)) {
    +            ans = k;
    +        }
    +    }
    +
    +    return ans;
     }
     ```
     
    diff --git a/solution/2200-2299/2284.Sender With Largest Word Count/README_EN.md b/solution/2200-2299/2284.Sender With Largest Word Count/README_EN.md
    index bc3c4199d849..7610f2edae0b 100644
    --- a/solution/2200-2299/2284.Sender With Largest Word Count/README_EN.md	
    +++ b/solution/2200-2299/2284.Sender With Largest Word Count/README_EN.md	
    @@ -75,7 +75,11 @@ Since there is a tie for the largest word count, we return the sender with the l
     
     
     
    -### Solution 1
    +### Solution 1: Hash Table + Enumeration
    +
    +We can use a hash table $\textit{cnt}$ to record the word count for each sender. Then, we traverse the hash table to find the sender with the highest word count. If there are multiple senders with the highest word count, we return the name that is lexicographically largest.
    +
    +The time complexity is $O(n + L)$, and the space complexity is $O(n)$, where $n$ is the number of messages and $L$ is the total length of all messages.
     
     
     
    @@ -85,12 +89,12 @@ Since there is a tie for the largest word count, we return the sender with the l
     class Solution:
         def largestWordCount(self, messages: List[str], senders: List[str]) -> str:
             cnt = Counter()
    -        for msg, sender in zip(messages, senders):
    -            cnt[sender] += msg.count(' ') + 1
    -        ans = ''
    -        for sender, v in cnt.items():
    -            if cnt[ans] < v or (cnt[ans] == v and ans < sender):
    -                ans = sender
    +        for message, sender in zip(messages, senders):
    +            cnt[sender] += message.count(" ") + 1
    +        ans = senders[0]
    +        for k, v in cnt.items():
    +            if cnt[ans] < v or (cnt[ans] == v and ans < k):
    +                ans = k
             return ans
     ```
     
    @@ -99,9 +103,8 @@ class Solution:
     ```java
     class Solution {
         public String largestWordCount(String[] messages, String[] senders) {
    -        Map cnt = new HashMap<>();
    -        int n = senders.length;
    -        for (int i = 0; i < n; ++i) {
    +        Map cnt = new HashMap<>(senders.length);
    +        for (int i = 0; i < messages.length; ++i) {
                 int v = 1;
                 for (int j = 0; j < messages[i].length(); ++j) {
                     if (messages[i].charAt(j) == ' ') {
    @@ -112,10 +115,10 @@ class Solution {
             }
             String ans = senders[0];
             for (var e : cnt.entrySet()) {
    -            String sender = e.getKey();
    -            if (cnt.get(ans) < cnt.get(sender)
    -                || (cnt.get(ans) == cnt.get(sender) && ans.compareTo(sender) < 0)) {
    -                ans = sender;
    +            String k = e.getKey();
    +            int v = e.getValue();
    +            if (cnt.get(ans) < v || (cnt.get(ans) == v && ans.compareTo(k) < 0)) {
    +                ans = k;
                 }
             }
             return ans;
    @@ -130,15 +133,14 @@ class Solution {
     public:
         string largestWordCount(vector& messages, vector& senders) {
             unordered_map cnt;
    -        int n = senders.size();
    -        for (int i = 0; i < n; ++i) {
    +        for (int i = 0; i < messages.size(); ++i) {
                 int v = count(messages[i].begin(), messages[i].end(), ' ') + 1;
                 cnt[senders[i]] += v;
             }
             string ans = senders[0];
    -        for (auto& [sender, v] : cnt) {
    -            if (cnt[ans] < v || (cnt[ans] == v && ans < sender)) {
    -                ans = sender;
    +        for (auto& [k, v] : cnt) {
    +            if (cnt[ans] < v || (cnt[ans] == v && ans < k)) {
    +                ans = k;
                 }
             }
             return ans;
    @@ -149,18 +151,42 @@ public:
     #### Go
     
     ```go
    -func largestWordCount(messages []string, senders []string) (ans string) {
    -	cnt := map[string]int{}
    -	for i, msg := range messages {
    -		v := strings.Count(msg, " ") + 1
    +func largestWordCount(messages []string, senders []string) string {
    +	cnt := make(map[string]int)
    +	for i, message := range messages {
    +		v := strings.Count(message, " ") + 1
     		cnt[senders[i]] += v
     	}
    -	for sender, v := range cnt {
    -		if cnt[ans] < v || (cnt[ans] == v && ans < sender) {
    -			ans = sender
    +
    +	ans := senders[0]
    +	for k, v := range cnt {
    +		if cnt[ans] < v || (cnt[ans] == v && ans < k) {
    +			ans = k
     		}
     	}
    -	return
    +	return ans
    +}
    +```
    +
    +#### TypeScript
    +
    +```ts
    +function largestWordCount(messages: string[], senders: string[]): string {
    +    const cnt: { [key: string]: number } = {};
    +
    +    for (let i = 0; i < messages.length; ++i) {
    +        const v = messages[i].split(' ').length;
    +        cnt[senders[i]] = (cnt[senders[i]] || 0) + v;
    +    }
    +
    +    let ans = senders[0];
    +    for (const k in cnt) {
    +        if (cnt[ans] < cnt[k] || (cnt[ans] === cnt[k] && ans < k)) {
    +            ans = k;
    +        }
    +    }
    +
    +    return ans;
     }
     ```
     
    diff --git a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.cpp b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.cpp
    index b6fca900db87..81a2fcfff0bf 100644
    --- a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.cpp	
    +++ b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.cpp	
    @@ -2,15 +2,14 @@ class Solution {
     public:
         string largestWordCount(vector& messages, vector& senders) {
             unordered_map cnt;
    -        int n = senders.size();
    -        for (int i = 0; i < n; ++i) {
    +        for (int i = 0; i < messages.size(); ++i) {
                 int v = count(messages[i].begin(), messages[i].end(), ' ') + 1;
                 cnt[senders[i]] += v;
             }
             string ans = senders[0];
    -        for (auto& [sender, v] : cnt) {
    -            if (cnt[ans] < v || (cnt[ans] == v && ans < sender)) {
    -                ans = sender;
    +        for (auto& [k, v] : cnt) {
    +            if (cnt[ans] < v || (cnt[ans] == v && ans < k)) {
    +                ans = k;
                 }
             }
             return ans;
    diff --git a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.go b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.go
    index 3390d6bcaa84..c174ee24cb14 100644
    --- a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.go	
    +++ b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.go	
    @@ -1,13 +1,15 @@
    -func largestWordCount(messages []string, senders []string) (ans string) {
    -	cnt := map[string]int{}
    -	for i, msg := range messages {
    -		v := strings.Count(msg, " ") + 1
    +func largestWordCount(messages []string, senders []string) string {
    +	cnt := make(map[string]int)
    +	for i, message := range messages {
    +		v := strings.Count(message, " ") + 1
     		cnt[senders[i]] += v
     	}
    -	for sender, v := range cnt {
    -		if cnt[ans] < v || (cnt[ans] == v && ans < sender) {
    -			ans = sender
    +
    +	ans := senders[0]
    +	for k, v := range cnt {
    +		if cnt[ans] < v || (cnt[ans] == v && ans < k) {
    +			ans = k
     		}
     	}
    -	return
    +	return ans
     }
    \ No newline at end of file
    diff --git a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.java b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.java
    index 1bcbd1cfc1d2..550e5ceff480 100644
    --- a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.java	
    +++ b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.java	
    @@ -1,8 +1,7 @@
     class Solution {
         public String largestWordCount(String[] messages, String[] senders) {
    -        Map cnt = new HashMap<>();
    -        int n = senders.length;
    -        for (int i = 0; i < n; ++i) {
    +        Map cnt = new HashMap<>(senders.length);
    +        for (int i = 0; i < messages.length; ++i) {
                 int v = 1;
                 for (int j = 0; j < messages[i].length(); ++j) {
                     if (messages[i].charAt(j) == ' ') {
    @@ -13,10 +12,10 @@ public String largestWordCount(String[] messages, String[] senders) {
             }
             String ans = senders[0];
             for (var e : cnt.entrySet()) {
    -            String sender = e.getKey();
    -            if (cnt.get(ans) < cnt.get(sender)
    -                || (cnt.get(ans) == cnt.get(sender) && ans.compareTo(sender) < 0)) {
    -                ans = sender;
    +            String k = e.getKey();
    +            int v = e.getValue();
    +            if (cnt.get(ans) < v || (cnt.get(ans) == v && ans.compareTo(k) < 0)) {
    +                ans = k;
                 }
             }
             return ans;
    diff --git a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.py b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.py
    index ec1a17e5b238..d3dbfc2b61a8 100644
    --- a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.py	
    +++ b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.py	
    @@ -1,10 +1,10 @@
     class Solution:
         def largestWordCount(self, messages: List[str], senders: List[str]) -> str:
             cnt = Counter()
    -        for msg, sender in zip(messages, senders):
    -            cnt[sender] += msg.count(' ') + 1
    -        ans = ''
    -        for sender, v in cnt.items():
    -            if cnt[ans] < v or (cnt[ans] == v and ans < sender):
    -                ans = sender
    +        for message, sender in zip(messages, senders):
    +            cnt[sender] += message.count(" ") + 1
    +        ans = senders[0]
    +        for k, v in cnt.items():
    +            if cnt[ans] < v or (cnt[ans] == v and ans < k):
    +                ans = k
             return ans
    diff --git a/solution/2200-2299/2284.Sender With Largest Word Count/Solution.ts b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.ts
    new file mode 100644
    index 000000000000..4c5330bc10ba
    --- /dev/null
    +++ b/solution/2200-2299/2284.Sender With Largest Word Count/Solution.ts	
    @@ -0,0 +1,17 @@
    +function largestWordCount(messages: string[], senders: string[]): string {
    +    const cnt: { [key: string]: number } = {};
    +
    +    for (let i = 0; i < messages.length; ++i) {
    +        const v = messages[i].split(' ').length;
    +        cnt[senders[i]] = (cnt[senders[i]] || 0) + v;
    +    }
    +
    +    let ans = senders[0];
    +    for (const k in cnt) {
    +        if (cnt[ans] < cnt[k] || (cnt[ans] === cnt[k] && ans < k)) {
    +            ans = k;
    +        }
    +    }
    +
    +    return ans;
    +}
    diff --git a/solution/2200-2299/2285.Maximum Total Importance of Roads/README.md b/solution/2200-2299/2285.Maximum Total Importance of Roads/README.md
    index ce52b7fe8508..aa8bea422c83 100644
    --- a/solution/2200-2299/2285.Maximum Total Importance of Roads/README.md	
    +++ b/solution/2200-2299/2285.Maximum Total Importance of Roads/README.md	
    @@ -83,7 +83,7 @@ tags:
     
     ### 方法一:贪心 + 排序
     
    -我们考虑每个城市对所有道路的总重要性的贡献度,记录在数组 $\text{deg}$ 中。然后将 $\text{deg}$ 按贡献度从小到大排序,为城市依次分配 $[1, 2, ..., n]$。
    +我们考虑每个城市对所有道路的总重要性的贡献度,记录在数组 $\textit{deg}$ 中。然后将 $\textit{deg}$ 按贡献度从小到大排序,为城市依次分配 $[1, 2, ..., n]$。
     
     时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。
     
    diff --git a/solution/2200-2299/2285.Maximum Total Importance of Roads/README_EN.md b/solution/2200-2299/2285.Maximum Total Importance of Roads/README_EN.md
    index f5553a84d30d..fd43db7cc0e5 100644
    --- a/solution/2200-2299/2285.Maximum Total Importance of Roads/README_EN.md	
    +++ b/solution/2200-2299/2285.Maximum Total Importance of Roads/README_EN.md	
    @@ -79,7 +79,7 @@ It can be shown that we cannot obtain a greater total importance than 20.
     
     ### Solution 1: Greedy + Sorting
     
    -We consider the contribution of each city to the total importance of all roads, recorded in the array $\text{deg}$. Then, we sort $\text{deg}$ by contribution from smallest to largest and allocate $[1, 2, ..., n]$ to the cities in order.
    +We consider the contribution of each city to the total importance of all roads, recorded in the array $\textit{deg}$. Then, we sort $\textit{deg}$ by contribution from smallest to largest and allocate $[1, 2, ..., n]$ to the cities in order.
     
     The time complexity is $O(n \log n)$, and the space complexity is $O(n)$.
     
    diff --git a/solution/2200-2299/2293.Min Max Game/README.md b/solution/2200-2299/2293.Min Max Game/README.md
    index 4f7e26fcfc8f..dfd9109d849f 100644
    --- a/solution/2200-2299/2293.Min Max Game/README.md	
    +++ b/solution/2200-2299/2293.Min Max Game/README.md	
    @@ -77,7 +77,7 @@ tags:
     
     根据题意,我们可以模拟整个过程,最后剩下的数字即为答案。在实现上,我们不需要额外创建数组,直接在原数组上进行操作即可。
     
    -时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 `nums` 的长度。
    +时间复杂度 $O(n)$,其中 $n$ 是数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。
     
     
     
    diff --git a/solution/2200-2299/2293.Min Max Game/README_EN.md b/solution/2200-2299/2293.Min Max Game/README_EN.md
    index 4591bb10b2c6..f78dee5b0e82 100644
    --- a/solution/2200-2299/2293.Min Max Game/README_EN.md	
    +++ b/solution/2200-2299/2293.Min Max Game/README_EN.md	
    @@ -69,7 +69,11 @@ Third: nums = [1]
     
     
     
    -### Solution 1
    +### Solution 1: Simulation
    +
    +According to the problem statement, we can simulate the entire process, and the remaining number will be the answer. In implementation, we do not need to create an additional array; we can directly operate on the original array.
    +
    +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$.
     
     
     
    diff --git a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md
    index bbcd842bc17c..69b53d410c10 100644
    --- a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md	
    +++ b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README.md	
    @@ -83,9 +83,9 @@ tags:
     
     ### 方法一:贪心 + 排序
     
    -题目是要求划分子序列,而不是子数组,因此子序列中的元素可以不连续。我们可以将数组 `nums` 排序,假设当前子序列的第一个元素为 $a$,则子序列中的最大值和最小值的差值不会超过 $k$。因此我们可以遍历数组 `nums`,如果当前元素 $b$ 与 $a$ 的差值大于 $k$,则更新 $a$ 为 $b$,并将子序列数目加 1。遍历结束后,即可得到最少子序列数目,注意初始时子序列数目为 $1$。
    +题目要求划分子序列,而不是子数组,因此子序列中的元素可以不连续。我们可以将数组 $\textit{nums}$ 排序,假设当前子序列的第一个元素为 $a$,则子序列中的最大值和最小值的差值不会超过 $k$。因此我们可以遍历数组 $\textit{nums}$,如果当前元素 $b$ 与 $a$ 的差值大于 $k$,则更新 $a$ 为 $b$,并将子序列数目加 1。遍历结束后,即可得到最少子序列数目,注意初始时子序列数目为 $1$。
     
    -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 `nums` 的长度。
    +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。
     
     
     
    diff --git a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md
    index bbf4c0002ffc..3b4c283347c2 100644
    --- a/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md	
    +++ b/solution/2200-2299/2294.Partition Array Such That Maximum Difference Is K/README_EN.md	
    @@ -79,7 +79,11 @@ Since three subsequences were created, we return 3. It can be shown that 3 is th
     
     
     
    -### Solution 1
    +### Solution 1: Greedy + Sorting
    +
    +The problem requires dividing into subsequences, not subarrays, so the elements in a subsequence can be non-continuous. We can sort the array $\textit{nums}$. Assuming the first element of the current subsequence is $a$, the difference between the maximum and minimum values in the subsequence will not exceed $k$. Therefore, we can iterate through the array $\textit{nums}$. If the difference between the current element $b$ and $a$ is greater than $k$, then update $a$ to $b$ and increase the number of subsequences by 1. After the iteration, we can obtain the minimum number of subsequences, noting that the initial number of subsequences is $1$.
    +
    +The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\textit{nums}$.
     
     
     
    diff --git a/solution/2200-2299/2295.Replace Elements in an Array/README.md b/solution/2200-2299/2295.Replace Elements in an Array/README.md
    index 3509330051a0..81ccb2e8f493 100644
    --- a/solution/2200-2299/2295.Replace Elements in an Array/README.md	
    +++ b/solution/2200-2299/2295.Replace Elements in an Array/README.md	
    @@ -78,11 +78,11 @@ tags:
     
     ### 方法一:哈希表
     
    -我们先用哈希表 $d$ 记录数组 `nums` 中每个数字的下标,然后遍历操作数组 `operations`,对于每个操作 $[a, b]$,我们将 $a$ 在 `nums` 中的下标 $d[a]$ 对应的数字替换为 $b$,并更新 $d$ 中 $b$ 的下标为 $d[a]$。
    +我们先用哈希表 $d$ 记录数组 $\textit{nums}$ 中每个数字的下标,然后遍历操作数组 $\textit{operations}$,对于每个操作 $[x, y]$,我们将 $x$ 在 $\textit{nums}$ 中的下标 $d[x]$ 对应的数字替换为 $y$,并更新 $d$ 中 $y$ 的下标为 $d[x]$。
     
    -最后返回 `nums` 即可。
    +最后返回 $\textit{nums}$ 即可。
     
    -时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 `nums` 和 `operations` 的长度。
    +时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 $\textit{nums}$ 的长度和操作数组 $\textit{operations}$ 的长度。
     
     
     
    @@ -91,10 +91,10 @@ tags:
     ```python
     class Solution:
         def arrayChange(self, nums: List[int], operations: List[List[int]]) -> List[int]:
    -        d = {v: i for i, v in enumerate(nums)}
    -        for a, b in operations:
    -            nums[d[a]] = b
    -            d[b] = d[a]
    +        d = {x: i for i, x in enumerate(nums)}
    +        for x, y in operations:
    +            nums[d[x]] = y
    +            d[y] = d[x]
             return nums
     ```
     
    @@ -103,14 +103,15 @@ class Solution:
     ```java
     class Solution {
         public int[] arrayChange(int[] nums, int[][] operations) {
    -        Map d = new HashMap<>();
    -        for (int i = 0; i < nums.length; ++i) {
    +        int n = nums.length;
    +        Map d = new HashMap<>(n);
    +        for (int i = 0; i < n; ++i) {
                 d.put(nums[i], i);
             }
             for (var op : operations) {
    -            int a = op[0], b = op[1];
    -            nums[d.get(a)] = b;
    -            d.put(b, d.get(a));
    +            int x = op[0], y = op[1];
    +            nums[d.get(x)] = y;
    +            d.put(y, d.get(x));
             }
             return nums;
         }
    @@ -128,9 +129,9 @@ public:
                 d[nums[i]] = i;
             }
             for (auto& op : operations) {
    -            int a = op[0], b = op[1];
    -            nums[d[a]] = b;
    -            d[b] = d[a];
    +            int x = op[0], y = op[1];
    +            nums[d[x]] = y;
    +            d[y] = d[x];
             }
             return nums;
         }
    @@ -142,13 +143,13 @@ public:
     ```go
     func arrayChange(nums []int, operations [][]int) []int {
     	d := map[int]int{}
    -	for i, v := range nums {
    -		d[v] = i
    +	for i, x := range nums {
    +		d[x] = i
     	}
     	for _, op := range operations {
    -		a, b := op[0], op[1]
    -		nums[d[a]] = b
    -		d[b] = d[a]
    +		x, y := op[0], op[1]
    +		nums[d[x]] = y
    +		d[y] = d[x]
     	}
     	return nums
     }
    @@ -158,10 +159,10 @@ func arrayChange(nums []int, operations [][]int) []int {
     
     ```ts
     function arrayChange(nums: number[], operations: number[][]): number[] {
    -    const d = new Map(nums.map((v, i) => [v, i]));
    -    for (const [a, b] of operations) {
    -        nums[d.get(a)] = b;
    -        d.set(b, d.get(a));
    +    const d: Map = new Map(nums.map((x, i) => [x, i]));
    +    for (const [x, y] of operations) {
    +        nums[d.get(x)!] = y;
    +        d.set(y, d.get(x)!);
         }
         return nums;
     }
    diff --git a/solution/2200-2299/2295.Replace Elements in an Array/README_EN.md b/solution/2200-2299/2295.Replace Elements in an Array/README_EN.md
    index 8ed95085bc8b..a09cb860bfc1 100644
    --- a/solution/2200-2299/2295.Replace Elements in an Array/README_EN.md	
    +++ b/solution/2200-2299/2295.Replace Elements in an Array/README_EN.md	
    @@ -78,11 +78,11 @@ We return the array [2,1].
     
     ### Solution 1: Hash Table
     
    -First, we use a hash table $d$ to record the index of each number in the array `nums`. Then, we iterate through the operation array `operations`. For each operation $[a, b]$, we replace the number at index $d[a]$ in `nums` with $b$, and update the index of $b$ in $d$ to $d[a]$.
    +First, we use a hash table $d$ to record the indices of each number in the array $\textit{nums}$. Then, we iterate through the operation array $\textit{operations}$. For each operation $[x, y]$, we replace the number at index $d[x]$ in $\textit{nums}$ with $y$, and update the index of $y$ in $d$ to $d[x]$.
     
    -Finally, we return `nums`.
    +Finally, we return $\textit{nums}$.
     
    -The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Here, $n$ and $m$ are the lengths of the arrays `nums` and `operations`, respectively.
    +The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Here, $n$ and $m$ are the lengths of the array $\textit{nums}$ and the operation array $\textit{operations}$, respectively.
     
     
     
    @@ -91,10 +91,10 @@ The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Here, $n$
     ```python
     class Solution:
         def arrayChange(self, nums: List[int], operations: List[List[int]]) -> List[int]:
    -        d = {v: i for i, v in enumerate(nums)}
    -        for a, b in operations:
    -            nums[d[a]] = b
    -            d[b] = d[a]
    +        d = {x: i for i, x in enumerate(nums)}
    +        for x, y in operations:
    +            nums[d[x]] = y
    +            d[y] = d[x]
             return nums
     ```
     
    @@ -103,14 +103,15 @@ class Solution:
     ```java
     class Solution {
         public int[] arrayChange(int[] nums, int[][] operations) {
    -        Map d = new HashMap<>();
    -        for (int i = 0; i < nums.length; ++i) {
    +        int n = nums.length;
    +        Map d = new HashMap<>(n);
    +        for (int i = 0; i < n; ++i) {
                 d.put(nums[i], i);
             }
             for (var op : operations) {
    -            int a = op[0], b = op[1];
    -            nums[d.get(a)] = b;
    -            d.put(b, d.get(a));
    +            int x = op[0], y = op[1];
    +            nums[d.get(x)] = y;
    +            d.put(y, d.get(x));
             }
             return nums;
         }
    @@ -128,9 +129,9 @@ public:
                 d[nums[i]] = i;
             }
             for (auto& op : operations) {
    -            int a = op[0], b = op[1];
    -            nums[d[a]] = b;
    -            d[b] = d[a];
    +            int x = op[0], y = op[1];
    +            nums[d[x]] = y;
    +            d[y] = d[x];
             }
             return nums;
         }
    @@ -142,13 +143,13 @@ public:
     ```go
     func arrayChange(nums []int, operations [][]int) []int {
     	d := map[int]int{}
    -	for i, v := range nums {
    -		d[v] = i
    +	for i, x := range nums {
    +		d[x] = i
     	}
     	for _, op := range operations {
    -		a, b := op[0], op[1]
    -		nums[d[a]] = b
    -		d[b] = d[a]
    +		x, y := op[0], op[1]
    +		nums[d[x]] = y
    +		d[y] = d[x]
     	}
     	return nums
     }
    @@ -158,10 +159,10 @@ func arrayChange(nums []int, operations [][]int) []int {
     
     ```ts
     function arrayChange(nums: number[], operations: number[][]): number[] {
    -    const d = new Map(nums.map((v, i) => [v, i]));
    -    for (const [a, b] of operations) {
    -        nums[d.get(a)] = b;
    -        d.set(b, d.get(a));
    +    const d: Map = new Map(nums.map((x, i) => [x, i]));
    +    for (const [x, y] of operations) {
    +        nums[d.get(x)!] = y;
    +        d.set(y, d.get(x)!);
         }
         return nums;
     }
    diff --git a/solution/2200-2299/2295.Replace Elements in an Array/Solution.cpp b/solution/2200-2299/2295.Replace Elements in an Array/Solution.cpp
    index 6f6be5c0e774..71b95a9b7b27 100644
    --- a/solution/2200-2299/2295.Replace Elements in an Array/Solution.cpp	
    +++ b/solution/2200-2299/2295.Replace Elements in an Array/Solution.cpp	
    @@ -6,9 +6,9 @@ class Solution {
                 d[nums[i]] = i;
             }
             for (auto& op : operations) {
    -            int a = op[0], b = op[1];
    -            nums[d[a]] = b;
    -            d[b] = d[a];
    +            int x = op[0], y = op[1];
    +            nums[d[x]] = y;
    +            d[y] = d[x];
             }
             return nums;
         }
    diff --git a/solution/2200-2299/2295.Replace Elements in an Array/Solution.go b/solution/2200-2299/2295.Replace Elements in an Array/Solution.go
    index c4ff655230e6..c043ebc8c922 100644
    --- a/solution/2200-2299/2295.Replace Elements in an Array/Solution.go	
    +++ b/solution/2200-2299/2295.Replace Elements in an Array/Solution.go	
    @@ -1,12 +1,12 @@
     func arrayChange(nums []int, operations [][]int) []int {
     	d := map[int]int{}
    -	for i, v := range nums {
    -		d[v] = i
    +	for i, x := range nums {
    +		d[x] = i
     	}
     	for _, op := range operations {
    -		a, b := op[0], op[1]
    -		nums[d[a]] = b
    -		d[b] = d[a]
    +		x, y := op[0], op[1]
    +		nums[d[x]] = y
    +		d[y] = d[x]
     	}
     	return nums
     }
    \ No newline at end of file
    diff --git a/solution/2200-2299/2295.Replace Elements in an Array/Solution.java b/solution/2200-2299/2295.Replace Elements in an Array/Solution.java
    index c17fe88d5393..0ad2c0e567ba 100644
    --- a/solution/2200-2299/2295.Replace Elements in an Array/Solution.java	
    +++ b/solution/2200-2299/2295.Replace Elements in an Array/Solution.java	
    @@ -1,13 +1,14 @@
     class Solution {
         public int[] arrayChange(int[] nums, int[][] operations) {
    -        Map d = new HashMap<>();
    -        for (int i = 0; i < nums.length; ++i) {
    +        int n = nums.length;
    +        Map d = new HashMap<>(n);
    +        for (int i = 0; i < n; ++i) {
                 d.put(nums[i], i);
             }
             for (var op : operations) {
    -            int a = op[0], b = op[1];
    -            nums[d.get(a)] = b;
    -            d.put(b, d.get(a));
    +            int x = op[0], y = op[1];
    +            nums[d.get(x)] = y;
    +            d.put(y, d.get(x));
             }
             return nums;
         }
    diff --git a/solution/2200-2299/2295.Replace Elements in an Array/Solution.py b/solution/2200-2299/2295.Replace Elements in an Array/Solution.py
    index cc9ef4fe10e4..57097e05cdc4 100644
    --- a/solution/2200-2299/2295.Replace Elements in an Array/Solution.py	
    +++ b/solution/2200-2299/2295.Replace Elements in an Array/Solution.py	
    @@ -1,7 +1,7 @@
     class Solution:
         def arrayChange(self, nums: List[int], operations: List[List[int]]) -> List[int]:
    -        d = {v: i for i, v in enumerate(nums)}
    -        for a, b in operations:
    -            nums[d[a]] = b
    -            d[b] = d[a]
    +        d = {x: i for i, x in enumerate(nums)}
    +        for x, y in operations:
    +            nums[d[x]] = y
    +            d[y] = d[x]
             return nums
    diff --git a/solution/2200-2299/2295.Replace Elements in an Array/Solution.ts b/solution/2200-2299/2295.Replace Elements in an Array/Solution.ts
    index 1a0503287b42..37a87013c6c9 100644
    --- a/solution/2200-2299/2295.Replace Elements in an Array/Solution.ts	
    +++ b/solution/2200-2299/2295.Replace Elements in an Array/Solution.ts	
    @@ -1,8 +1,8 @@
     function arrayChange(nums: number[], operations: number[][]): number[] {
    -    const d = new Map(nums.map((v, i) => [v, i]));
    -    for (const [a, b] of operations) {
    -        nums[d.get(a)] = b;
    -        d.set(b, d.get(a));
    +    const d: Map = new Map(nums.map((x, i) => [x, i]));
    +    for (const [x, y] of operations) {
    +        nums[d.get(x)!] = y;
    +        d.set(y, d.get(x)!);
         }
         return nums;
     }
    diff --git a/solution/2200-2299/2296.Design a Text Editor/README_EN.md b/solution/2200-2299/2296.Design a Text Editor/README_EN.md
    index 18a663629271..daa68bca89b2 100644
    --- a/solution/2200-2299/2296.Design a Text Editor/README_EN.md	
    +++ b/solution/2200-2299/2296.Design a Text Editor/README_EN.md	
    @@ -101,7 +101,7 @@ textEditor.cursorRight(6); // return "practi"
     
     We can use two stacks, `left` and `right`, where the `left` stack stores the characters to the left of the cursor, and the `right` stack stores the characters to the right of the cursor.
     
    --   When the `addText` method is called, we push the characters from `text` onto the `left` stack one by one. The time complexity is $O(|\text{text}|)$.
    +-   When the `addText` method is called, we push the characters from `text` onto the `left` stack one by one. The time complexity is $O(|\textit{text}|)$.
     -   When the `deleteText` method is called, we pop characters from the `left` stack up to $k$ times. The time complexity is $O(k)$.
     -   When the `cursorLeft` method is called, we pop characters from the `left` stack up to $k$ times, then push the popped characters onto the `right` stack, and finally return up to $10$ characters from the `left` stack. The time complexity is $O(k)$.
     -   When the `cursorRight` method is called, we pop characters from the `right` stack up to $k$ times, then push the popped characters onto the `left` stack, and finally return up to $10$ characters from the `left` stack. The time complexity is $O(k)$.
    diff --git a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md
    index 4f6ea9b5c3fa..5eb9b132567c 100644
    --- a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md	
    +++ b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README.md	
    @@ -78,10 +78,10 @@ tags:
     我们定义 $f[i][j]$ 表示从第一行出发,到达第 $i$ 行第 $j$ 列的最小路径代价。由于每次只能从上一行的某一列移动到当前行的某一列,因此 $f[i][j]$ 的值可以从 $f[i - 1][k]$ 转移而来,其中 $k$ 的取值范围为 $[0, n - 1]$。因此状态转移方程为:
     
     $$
    -f[i][j] = \min_{0 \leq k < n} \{f[i - 1][k] + \text{moveCost}[grid[i - 1][k]][j] + grid[i][j]\}
    +f[i][j] = \min_{0 \leq k < n} \{f[i - 1][k] + \textit{moveCost}[grid[i - 1][k]][j] + grid[i][j]\}
     $$
     
    -其中 $\text{moveCost}[grid[i - 1][k]][j]$ 表示从第 $i - 1$ 行第 $k$ 列移动到第 $i$ 行第 $j$ 列的代价。
    +其中 $\textit{moveCost}[grid[i - 1][k]][j]$ 表示从第 $i - 1$ 行第 $k$ 列移动到第 $i$ 行第 $j$ 列的代价。
     
     最终答案即为 $\min_{0 \leq j < n} \{f[m - 1][j]\}$。
     
    diff --git a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md
    index a6cf4c68b7f8..9afaab6168d0 100644
    --- a/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md	
    +++ b/solution/2300-2399/2304.Minimum Path Cost in a Grid/README_EN.md	
    @@ -74,10 +74,10 @@ So the total cost of this path is 5 + 1 = 6.
     We define $f[i][j]$ to represent the minimum path cost from the first row to the $i$th row and $j$th column. Since we can only move from a column in the previous row to a column in the current row, the value of $f[i][j]$ can be transferred from $f[i - 1][k]$, where the range of $k$ is $[0, n - 1]$. Therefore, the state transition equation is:
     
     $$
    -f[i][j] = \min_{0 \leq k < n} \{f[i - 1][k] + \text{moveCost}[grid[i - 1][k]][j] + grid[i][j]\}
    +f[i][j] = \min_{0 \leq k < n} \{f[i - 1][k] + \textit{moveCost}[grid[i - 1][k]][j] + grid[i][j]\}
     $$
     
    -where $\text{moveCost}[grid[i - 1][k]][j]$ represents the cost of moving from the $k$th column of the $i - 1$th row to the $j$th column of the $i$th row.
    +where $\textit{moveCost}[grid[i - 1][k]][j]$ represents the cost of moving from the $k$th column of the $i - 1$th row to the $j$th column of the $i$th row.
     
     The final answer is $\min_{0 \leq j < n} \{f[m - 1][j]\}$.
     
    diff --git a/solution/2300-2399/2324.Product Sales Analysis IV/README_EN.md b/solution/2300-2399/2324.Product Sales Analysis IV/README_EN.md
    index 0cb4d7d3160c..980157a73f55 100644
    --- a/solution/2300-2399/2324.Product Sales Analysis IV/README_EN.md	
    +++ b/solution/2300-2399/2324.Product Sales Analysis IV/README_EN.md	
    @@ -94,7 +94,7 @@ User 101:
         - Spent 7 * 15 = 105 on product 3.
     User 101 spent the most money on product 3.
     User 102:
    -    - Spent (9 + 7) * 10 = 150 on product 1.
    +    - Spent (9 + 6) * 10 = 150 on product 1.
         - Spent 6 * 25 = 150 on product 2.
         - Spent 10 * 15 = 150 on product 3.
     User 102 spent the most money on products 1, 2, and 3.
    diff --git a/solution/2300-2399/2326.Spiral Matrix IV/README.md b/solution/2300-2399/2326.Spiral Matrix IV/README.md
    index beb216d8be18..d383fdda5be1 100644
    --- a/solution/2300-2399/2326.Spiral Matrix IV/README.md	
    +++ b/solution/2300-2399/2326.Spiral Matrix IV/README.md	
    @@ -65,11 +65,11 @@ tags:
     
     ### 方法一:模拟
     
    -我们定义一个二维数组 $\text{ans}$,用来存放链表中的元素,初始时全部填充为 $-1$。定义三个变量 $i, j, k$,分别表示当前的行、列和方向。定义一个数组 $\text{dirs}$,表示四个方向的偏移量。
    +我们定义一个二维数组 $\textit{ans}$,用来存放链表中的元素,初始时全部填充为 $-1$。定义三个变量 $i, j, k$,分别表示当前的行、列和方向。定义一个数组 $\textit{dirs}$,表示四个方向的偏移量。
     
    -然后我们开始遍历链表,每次遍历一个节点,就将当前节点的值填充到 $\text{ans}[i][j]$ 中,然后更新链表的指针,如果链表为空,说明所有的元素都已经填充完毕,退出循环。
    +然后我们开始遍历链表,每次遍历一个节点,就将当前节点的值填充到 $\textit{ans}[i][j]$ 中,然后更新链表的指针,如果链表为空,说明所有的元素都已经填充完毕,退出循环。
     
    -否则,我们需要找到下一个元素的位置,我们可以通过当前位置 $(i, j)$ 和当前方向 $k$ 来计算下一个位置 $(x, y)$,如果 $(x, y)$ 在矩阵的范围内,并且 $\text{ans}[x][y]$ 为 $-1$,说明 $(x, y)$ 还没有被填充过,我们就将 $(x, y)$ 作为下一个位置,否则我们需要更换方向。
    +否则,我们需要找到下一个元素的位置,我们可以通过当前位置 $(i, j)$ 和当前方向 $k$ 来计算下一个位置 $(x, y)$,如果 $(x, y)$ 在矩阵的范围内,并且 $\textit{ans}[x][y]$ 为 $-1$,说明 $(x, y)$ 还没有被填充过,我们就将 $(x, y)$ 作为下一个位置,否则我们需要更换方向。
     
     遍历完链表之后,我们就得到了一个螺旋矩阵,返回即可。
     
    diff --git a/solution/2300-2399/2326.Spiral Matrix IV/README_EN.md b/solution/2300-2399/2326.Spiral Matrix IV/README_EN.md
    index 0bfc63775c8a..f53ce3ace7e5 100644
    --- a/solution/2300-2399/2326.Spiral Matrix IV/README_EN.md	
    +++ b/solution/2300-2399/2326.Spiral Matrix IV/README_EN.md	
    @@ -65,11 +65,11 @@ The last space in the matrix is set to -1.
    ### Solution 1: Simulation -We define a two-dimensional array $\text{ans}$ to store the elements in the linked list, initially all filled with $-1$. We define three variables $i, j, k$, representing the current row, column, and direction respectively. We define an array $\text{dirs}$ to represent the offsets of the four directions. +We define a two-dimensional array $\textit{ans}$ to store the elements in the linked list, initially all filled with $-1$. We define three variables $i, j, k$, representing the current row, column, and direction respectively. We define an array $\textit{dirs}$ to represent the offsets of the four directions. -Then we start traversing the linked list. Each time we traverse a node, we fill the current node's value into $\text{ans}[i][j]$, then update the linked list pointer. If the linked list is empty, it means all elements have been filled and we exit the loop. +Then we start traversing the linked list. Each time we traverse a node, we fill the current node's value into $\textit{ans}[i][j]$, then update the linked list pointer. If the linked list is empty, it means all elements have been filled and we exit the loop. -Otherwise, we need to find the position of the next element. We can calculate the next position $(x, y)$ through the current position $(i, j)$ and the current direction $k$. If $(x, y)$ is within the range of the matrix, and $\text{ans}[x][y]$ is $-1$, it means $(x, y)$ has not been filled yet, so we take $(x, y)$ as the next position. Otherwise, we need to change the direction. +Otherwise, we need to find the position of the next element. We can calculate the next position $(x, y)$ through the current position $(i, j)$ and the current direction $k$. If $(x, y)$ is within the range of the matrix, and $\textit{ans}[x][y]$ is $-1$, it means $(x, y)$ has not been filled yet, so we take $(x, y)$ as the next position. Otherwise, we need to change the direction. After traversing the linked list, we get a spiral matrix and return it. diff --git a/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README.md b/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README.md index 700b60087432..d06d2e49acb6 100644 --- a/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README.md +++ b/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README.md @@ -84,7 +84,7 @@ OR 运算节点的值为 True OR False = True 。 对于当前节点 $\textit{root}$: -- 如果其左孩子为空,说明当前节点是叶子节点。如果当前节点的值为 $1$,则返回 $\text{true}$,否则返回 $\text{false}$; +- 如果其左孩子为空,说明当前节点是叶子节点。如果当前节点的值为 $1$,则返回 $\textit{true}$,否则返回 $\textit{false}$; - 如果当前节点的值为 $2$,则返回其左孩子和右孩子的递归结果的逻辑或,否则返回其左孩子和右孩子的递归结果的逻辑与。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点个数。 diff --git a/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README_EN.md b/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README_EN.md index b137ba6200fe..82de05e0db76 100644 --- a/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README_EN.md +++ b/solution/2300-2399/2331.Evaluate Boolean Binary Tree/README_EN.md @@ -82,7 +82,7 @@ We can use recursion to solve this problem. For the current node $\textit{root}$: -- If its left child is null, it means the current node is a leaf node. If the value of the current node is $1$, then return $\text{true}$; otherwise, return $\text{false}$; +- If its left child is null, it means the current node is a leaf node. If the value of the current node is $1$, then return $\textit{true}$; otherwise, return $\textit{false}$; - If the value of the current node is $2$, then return the logical OR of the recursion results of its left and right children; otherwise, return the logical AND of the recursion results of its left and right children. The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. diff --git a/solution/2300-2399/2334.Subarray With Elements Greater Than Varying Threshold/README.md b/solution/2300-2399/2334.Subarray With Elements Greater Than Varying Threshold/README.md index 2715c2822e1b..bd2448c8485d 100644 --- a/solution/2300-2399/2334.Subarray With Elements Greater Than Varying Threshold/README.md +++ b/solution/2300-2399/2334.Subarray With Elements Greater Than Varying Threshold/README.md @@ -71,7 +71,7 @@ tags: $v$ 在数组 $nums$ 中的下标为 $i$,若下标 $i-1$ 对应的元素遍历过,可以将 $i-1$ 与 $i$ 进行合并,同理,若下标 $i+1$ 对应的元素也遍历过了,将 $i$ 与 $i+1$ 合并。合并过程中更新连通块的大小。 -$v$ 作为当前连通块的最小值,当前连通块的大小为 $size[find(i)]$,若 $v>\frac{\text{threshold}}{size[find(i)]}$,说明找到了满足条件的子数组,返回 $true$。 +$v$ 作为当前连通块的最小值,当前连通块的大小为 $size[find(i)]$,若 $v>\frac{\textit{threshold}}{size[find(i)]}$,说明找到了满足条件的子数组,返回 $true$。 否则遍历结束,返回 $-1$。 @@ -277,7 +277,7 @@ func validSubarraySize(nums []int, threshold int) int { 利用单调栈,得到以当前元素 $nums[i]$ 作为最小元素的左右边界 $left[i]$(左边第一个比 $nums[i]$ 小的元素的位置), $right[i]$(右边第一个比 $nums[i]$ 小的元素的位置)。 -那么对于当前元素 $nums[i]$,有 $k=right[i]-left[i]-1$,若 $nums[i]>\frac{\text{threshold}}{k}$,说明找到了满足条件的子数组,返回 $true$。 +那么对于当前元素 $nums[i]$,有 $k=right[i]-left[i]-1$,若 $nums[i]>\frac{\textit{threshold}}{k}$,说明找到了满足条件的子数组,返回 $true$。 否则遍历结束,返回 $-1$。 diff --git a/solution/2300-2399/2349.Design a Number Container System/README.md b/solution/2300-2399/2349.Design a Number Container System/README.md index 75e89b38e3e0..0de3381c8461 100644 --- a/solution/2300-2399/2349.Design a Number Container System/README.md +++ b/solution/2300-2399/2349.Design a Number Container System/README.md @@ -74,7 +74,15 @@ nc.find(10); // 数字 10 所在下标为 2 ,3 和 5 。最小下标为 2 , -### 方法一:哈希表 +### 方法一:哈希表 + 有序集合 + +我们用一个哈希表 $d$ 记录下标和数字的映射关系,用一个哈希表 $g$ 记录每个数字对应的下标集合,这里我们可以使用有序集合来存储下标,这样我们就可以方便地找到最小下标。 + +调用 `change` 方法时,我们先判断下标是否已经存在,如果存在,我们就将原来的数字从对应的下标集合中删除,然后将新的数字添加到对应的下标集合中。时间复杂度 $O(\log n)$。 + +调用 `find` 方法时,我们直接返回对应数字的下标集合的第一个元素即可。时间复杂度 $O(1)$。 + +空间复杂度 $O(n)$。其中 $n$ 为数字的个数。 @@ -85,20 +93,21 @@ from sortedcontainers import SortedSet class NumberContainers: + def __init__(self): - self.mp = {} - self.t = defaultdict(SortedSet) + self.d = {} + self.g = defaultdict(SortedSet) def change(self, index: int, number: int) -> None: - if index in self.mp: - v = self.mp[index] - self.t[v].remove(index) - self.mp[index] = number - self.t[number].add(index) + if index in self.d: + old_number = self.d[index] + self.g[old_number].remove(index) + self.d[index] = number + self.g[number].add(index) def find(self, number: int) -> int: - s = self.t[number] - return s[0] if s else -1 + ids = self.g[number] + return ids[0] if ids else -1 # Your NumberContainers object will be instantiated and called as such: @@ -111,26 +120,24 @@ class NumberContainers: ```java class NumberContainers { - private Map mp = new HashMap<>(); - private Map> t = new HashMap<>(); + private Map d = new HashMap<>(); + private Map> g = new HashMap<>(); public NumberContainers() { } public void change(int index, int number) { - if (mp.containsKey(index)) { - int v = mp.get(index); - t.get(v).remove(index); - if (t.get(v).isEmpty()) { - t.remove(v); - } + if (d.containsKey(index)) { + int oldNumber = d.get(index); + g.get(oldNumber).remove(index); } - mp.put(index, number); - t.computeIfAbsent(number, k -> new TreeSet<>()).add(index); + d.put(index, number); + g.computeIfAbsent(number, k -> new TreeSet<>()).add(index); } public int find(int number) { - return t.containsKey(number) ? t.get(number).first() : -1; + var ids = g.get(number); + return ids == null || ids.isEmpty() ? -1 : ids.first(); } } @@ -147,26 +154,28 @@ class NumberContainers { ```cpp class NumberContainers { public: - map mp; - map> t; - NumberContainers() { } void change(int index, int number) { - auto it = mp.find(index); - if (it != mp.end()) { - t[it->second].erase(index); - it->second = number; - } else - mp[index] = number; - t[number].insert(index); + if (d.contains(index)) { + int oldNumber = d[index]; + g[oldNumber].erase(index); + if (g[oldNumber].empty()) { + g.erase(oldNumber); + } + } + d[index] = number; + g[number].insert(index); } int find(int number) { - auto it = t.find(number); - return it == t.end() || it->second.empty() ? -1 : *it->second.begin(); + return g.contains(number) ? *g[number].begin() : -1; } + +private: + unordered_map d; + unordered_map> g; }; /** @@ -181,8 +190,8 @@ public: ```go type NumberContainers struct { - mp map[int]int - t map[int]*redblacktree.Tree + d map[int]int + g map[int]*redblacktree.Tree } func Constructor() NumberContainers { @@ -190,22 +199,21 @@ func Constructor() NumberContainers { } func (this *NumberContainers) Change(index int, number int) { - if num, ok := this.mp[index]; ok { - this.t[num].Remove(index) + if oldNumber, ok := this.d[index]; ok { + this.g[oldNumber].Remove(index) } - this.mp[index] = number - if this.t[number] == nil { - this.t[number] = redblacktree.NewWithIntComparator() + this.d[index] = number + if _, ok := this.g[number]; !ok { + this.g[number] = redblacktree.NewWithIntComparator() } - this.t[number].Put(index, nil) + this.g[number].Put(index, nil) } func (this *NumberContainers) Find(number int) int { - s, ok := this.t[number] - if !ok || s.Size() == 0 { - return -1 + if ids, ok := this.g[number]; ok && ids.Size() > 0 { + return ids.Left().Key.(int) } - return s.Left().Key.(int) + return -1 } /** @@ -216,6 +224,532 @@ func (this *NumberContainers) Find(number int) int { */ ``` +#### TypeScript + +```ts +class NumberContainers { + private d = new Map(); + private g = new Map>(); + constructor() {} + + change(index: number, number: number): void { + if (this.d.has(index)) { + const oldNumber = this.d.get(index)!; + this.g.get(oldNumber)!.delete(index); + if (!this.g.get(oldNumber)!.size()) { + this.g.delete(oldNumber); + } + } + this.d.set(index, number); + if (!this.g.has(number)) { + this.g.set(number, new TreeSet()); + } + this.g.get(number)!.add(index); + } + + find(number: number): number { + return this.g.has(number) ? this.g.get(number)!.first()! : -1; + } +} + +type Compare = (lhs: T, rhs: T) => number; + +class RBTreeNode { + data: T; + count: number; + left: RBTreeNode | null; + right: RBTreeNode | null; + parent: RBTreeNode | null; + color: number; + constructor(data: T) { + this.data = data; + this.left = this.right = this.parent = null; + this.color = 0; + this.count = 1; + } + + sibling(): RBTreeNode | null { + if (!this.parent) return null; // sibling null if no parent + return this.isOnLeft() ? this.parent.right : this.parent.left; + } + + isOnLeft(): boolean { + return this === this.parent!.left; + } + + hasRedChild(): boolean { + return ( + Boolean(this.left && this.left.color === 0) || + Boolean(this.right && this.right.color === 0) + ); + } +} + +class RBTree { + root: RBTreeNode | null; + lt: (l: T, r: T) => boolean; + constructor(compare: Compare = (l: T, r: T) => (l < r ? -1 : l > r ? 1 : 0)) { + this.root = null; + this.lt = (l: T, r: T) => compare(l, r) < 0; + } + + rotateLeft(pt: RBTreeNode): void { + const right = pt.right!; + pt.right = right.left; + + if (pt.right) pt.right.parent = pt; + right.parent = pt.parent; + + if (!pt.parent) this.root = right; + else if (pt === pt.parent.left) pt.parent.left = right; + else pt.parent.right = right; + + right.left = pt; + pt.parent = right; + } + + rotateRight(pt: RBTreeNode): void { + const left = pt.left!; + pt.left = left.right; + + if (pt.left) pt.left.parent = pt; + left.parent = pt.parent; + + if (!pt.parent) this.root = left; + else if (pt === pt.parent.left) pt.parent.left = left; + else pt.parent.right = left; + + left.right = pt; + pt.parent = left; + } + + swapColor(p1: RBTreeNode, p2: RBTreeNode): void { + const tmp = p1.color; + p1.color = p2.color; + p2.color = tmp; + } + + swapData(p1: RBTreeNode, p2: RBTreeNode): void { + const tmp = p1.data; + p1.data = p2.data; + p2.data = tmp; + } + + fixAfterInsert(pt: RBTreeNode): void { + let parent = null; + let grandParent = null; + + while (pt !== this.root && pt.color !== 1 && pt.parent?.color === 0) { + parent = pt.parent; + grandParent = pt.parent.parent; + + /* Case : A + Parent of pt is left child of Grand-parent of pt */ + if (parent === grandParent?.left) { + const uncle = grandParent.right; + + /* Case : 1 + The uncle of pt is also red + Only Recoloring required */ + if (uncle && uncle.color === 0) { + grandParent.color = 0; + parent.color = 1; + uncle.color = 1; + pt = grandParent; + } else { + /* Case : 2 + pt is right child of its parent + Left-rotation required */ + if (pt === parent.right) { + this.rotateLeft(parent); + pt = parent; + parent = pt.parent; + } + + /* Case : 3 + pt is left child of its parent + Right-rotation required */ + this.rotateRight(grandParent); + this.swapColor(parent!, grandParent); + pt = parent!; + } + } else { + /* Case : B + Parent of pt is right child of Grand-parent of pt */ + const uncle = grandParent!.left; + + /* Case : 1 + The uncle of pt is also red + Only Recoloring required */ + if (uncle != null && uncle.color === 0) { + grandParent!.color = 0; + parent.color = 1; + uncle.color = 1; + pt = grandParent!; + } else { + /* Case : 2 + pt is left child of its parent + Right-rotation required */ + if (pt === parent.left) { + this.rotateRight(parent); + pt = parent; + parent = pt.parent; + } + + /* Case : 3 + pt is right child of its parent + Left-rotation required */ + this.rotateLeft(grandParent!); + this.swapColor(parent!, grandParent!); + pt = parent!; + } + } + } + this.root!.color = 1; + } + + delete(val: T): boolean { + const node = this.find(val); + if (!node) return false; + node.count--; + if (!node.count) this.deleteNode(node); + return true; + } + + deleteAll(val: T): boolean { + const node = this.find(val); + if (!node) return false; + this.deleteNode(node); + return true; + } + + deleteNode(v: RBTreeNode): void { + const u = BSTreplace(v); + + // True when u and v are both black + const uvBlack = (u === null || u.color === 1) && v.color === 1; + const parent = v.parent!; + + if (!u) { + // u is null therefore v is leaf + if (v === this.root) this.root = null; + // v is root, making root null + else { + if (uvBlack) { + // u and v both black + // v is leaf, fix double black at v + this.fixDoubleBlack(v); + } else { + // u or v is red + if (v.sibling()) { + // sibling is not null, make it red" + v.sibling()!.color = 0; + } + } + // delete v from the tree + if (v.isOnLeft()) parent.left = null; + else parent.right = null; + } + return; + } + + if (!v.left || !v.right) { + // v has 1 child + if (v === this.root) { + // v is root, assign the value of u to v, and delete u + v.data = u.data; + v.left = v.right = null; + } else { + // Detach v from tree and move u up + if (v.isOnLeft()) parent.left = u; + else parent.right = u; + u.parent = parent; + if (uvBlack) this.fixDoubleBlack(u); + // u and v both black, fix double black at u + else u.color = 1; // u or v red, color u black + } + return; + } + + // v has 2 children, swap data with successor and recurse + this.swapData(u, v); + this.deleteNode(u); + + // find node that replaces a deleted node in BST + function BSTreplace(x: RBTreeNode): RBTreeNode | null { + // when node have 2 children + if (x.left && x.right) return successor(x.right); + // when leaf + if (!x.left && !x.right) return null; + // when single child + return x.left ?? x.right; + } + // find node that do not have a left child + // in the subtree of the given node + function successor(x: RBTreeNode): RBTreeNode { + let temp = x; + while (temp.left) temp = temp.left; + return temp; + } + } + + fixDoubleBlack(x: RBTreeNode): void { + if (x === this.root) return; // Reached root + + const sibling = x.sibling(); + const parent = x.parent!; + if (!sibling) { + // No sibiling, double black pushed up + this.fixDoubleBlack(parent); + } else { + if (sibling.color === 0) { + // Sibling red + parent.color = 0; + sibling.color = 1; + if (sibling.isOnLeft()) this.rotateRight(parent); + // left case + else this.rotateLeft(parent); // right case + this.fixDoubleBlack(x); + } else { + // Sibling black + if (sibling.hasRedChild()) { + // at least 1 red children + if (sibling.left && sibling.left.color === 0) { + if (sibling.isOnLeft()) { + // left left + sibling.left.color = sibling.color; + sibling.color = parent.color; + this.rotateRight(parent); + } else { + // right left + sibling.left.color = parent.color; + this.rotateRight(sibling); + this.rotateLeft(parent); + } + } else { + if (sibling.isOnLeft()) { + // left right + sibling.right!.color = parent.color; + this.rotateLeft(sibling); + this.rotateRight(parent); + } else { + // right right + sibling.right!.color = sibling.color; + sibling.color = parent.color; + this.rotateLeft(parent); + } + } + parent.color = 1; + } else { + // 2 black children + sibling.color = 0; + if (parent.color === 1) this.fixDoubleBlack(parent); + else parent.color = 1; + } + } + } + } + + insert(data: T): boolean { + // search for a position to insert + let parent = this.root; + while (parent) { + if (this.lt(data, parent.data)) { + if (!parent.left) break; + else parent = parent.left; + } else if (this.lt(parent.data, data)) { + if (!parent.right) break; + else parent = parent.right; + } else break; + } + + // insert node into parent + const node = new RBTreeNode(data); + if (!parent) this.root = node; + else if (this.lt(node.data, parent.data)) parent.left = node; + else if (this.lt(parent.data, node.data)) parent.right = node; + else { + parent.count++; + return false; + } + node.parent = parent; + this.fixAfterInsert(node); + return true; + } + + find(data: T): RBTreeNode | null { + let p = this.root; + while (p) { + if (this.lt(data, p.data)) { + p = p.left; + } else if (this.lt(p.data, data)) { + p = p.right; + } else break; + } + return p ?? null; + } + + *inOrder(root: RBTreeNode = this.root!): Generator { + if (!root) return; + for (const v of this.inOrder(root.left!)) yield v; + yield root.data; + for (const v of this.inOrder(root.right!)) yield v; + } + + *reverseInOrder(root: RBTreeNode = this.root!): Generator { + if (!root) return; + for (const v of this.reverseInOrder(root.right!)) yield v; + yield root.data; + for (const v of this.reverseInOrder(root.left!)) yield v; + } +} + +class TreeSet { + _size: number; + tree: RBTree; + compare: Compare; + constructor( + collection: T[] | Compare = [], + compare: Compare = (l: T, r: T) => (l < r ? -1 : l > r ? 1 : 0), + ) { + if (typeof collection === 'function') { + compare = collection; + collection = []; + } + this._size = 0; + this.compare = compare; + this.tree = new RBTree(compare); + for (const val of collection) this.add(val); + } + + size(): number { + return this._size; + } + + has(val: T): boolean { + return !!this.tree.find(val); + } + + add(val: T): boolean { + const successful = this.tree.insert(val); + this._size += successful ? 1 : 0; + return successful; + } + + delete(val: T): boolean { + const deleted = this.tree.deleteAll(val); + this._size -= deleted ? 1 : 0; + return deleted; + } + + ceil(val: T): T | undefined { + let p = this.tree.root; + let higher = null; + while (p) { + if (this.compare(p.data, val) >= 0) { + higher = p; + p = p.left; + } else { + p = p.right; + } + } + return higher?.data; + } + + floor(val: T): T | undefined { + let p = this.tree.root; + let lower = null; + while (p) { + if (this.compare(val, p.data) >= 0) { + lower = p; + p = p.right; + } else { + p = p.left; + } + } + return lower?.data; + } + + higher(val: T): T | undefined { + let p = this.tree.root; + let higher = null; + while (p) { + if (this.compare(val, p.data) < 0) { + higher = p; + p = p.left; + } else { + p = p.right; + } + } + return higher?.data; + } + + lower(val: T): T | undefined { + let p = this.tree.root; + let lower = null; + while (p) { + if (this.compare(p.data, val) < 0) { + lower = p; + p = p.right; + } else { + p = p.left; + } + } + return lower?.data; + } + + first(): T | undefined { + return this.tree.inOrder().next().value; + } + + last(): T | undefined { + return this.tree.reverseInOrder().next().value; + } + + shift(): T | undefined { + const first = this.first(); + if (first === undefined) return undefined; + this.delete(first); + return first; + } + + pop(): T | undefined { + const last = this.last(); + if (last === undefined) return undefined; + this.delete(last); + return last; + } + + *[Symbol.iterator](): Generator { + for (const val of this.values()) yield val; + } + + *keys(): Generator { + for (const val of this.values()) yield val; + } + + *values(): Generator { + for (const val of this.tree.inOrder()) yield val; + return undefined; + } + + /** + * Return a generator for reverse order traversing the set + */ + *rvalues(): Generator { + for (const val of this.tree.reverseInOrder()) yield val; + return undefined; + } +} + +/** + * Your NumberContainers object will be instantiated and called as such: + * var obj = new NumberContainers() + * obj.change(index,number) + * var param_2 = obj.find(number) + */ +``` + diff --git a/solution/2300-2399/2349.Design a Number Container System/README_EN.md b/solution/2300-2399/2349.Design a Number Container System/README_EN.md index 2b5447bae3f3..8b0950666fad 100644 --- a/solution/2300-2399/2349.Design a Number Container System/README_EN.md +++ b/solution/2300-2399/2349.Design a Number Container System/README_EN.md @@ -72,7 +72,15 @@ nc.find(10); // Number 10 is at the indices 2, 3, and 5. The smallest index that -### Solution 1 +### Solution 1: Hash Table + Ordered Set + +We use a hash table $d$ to record the mapping relationship between indices and numbers, and another hash table $g$ to record the set of indices corresponding to each number. Here, we can use an ordered set to store the indices, which allows us to conveniently find the smallest index. + +When calling the `change` method, we first check if the index already exists. If it does, we remove the original number from its corresponding index set and then add the new number to the corresponding index set. The time complexity is $O(\log n)$. + +When calling the `find` method, we simply return the first element of the index set corresponding to the number. The time complexity is $O(1)$. + +The space complexity is $O(n)$, where $n$ is the number of numbers. @@ -83,20 +91,21 @@ from sortedcontainers import SortedSet class NumberContainers: + def __init__(self): - self.mp = {} - self.t = defaultdict(SortedSet) + self.d = {} + self.g = defaultdict(SortedSet) def change(self, index: int, number: int) -> None: - if index in self.mp: - v = self.mp[index] - self.t[v].remove(index) - self.mp[index] = number - self.t[number].add(index) + if index in self.d: + old_number = self.d[index] + self.g[old_number].remove(index) + self.d[index] = number + self.g[number].add(index) def find(self, number: int) -> int: - s = self.t[number] - return s[0] if s else -1 + ids = self.g[number] + return ids[0] if ids else -1 # Your NumberContainers object will be instantiated and called as such: @@ -109,26 +118,24 @@ class NumberContainers: ```java class NumberContainers { - private Map mp = new HashMap<>(); - private Map> t = new HashMap<>(); + private Map d = new HashMap<>(); + private Map> g = new HashMap<>(); public NumberContainers() { } public void change(int index, int number) { - if (mp.containsKey(index)) { - int v = mp.get(index); - t.get(v).remove(index); - if (t.get(v).isEmpty()) { - t.remove(v); - } + if (d.containsKey(index)) { + int oldNumber = d.get(index); + g.get(oldNumber).remove(index); } - mp.put(index, number); - t.computeIfAbsent(number, k -> new TreeSet<>()).add(index); + d.put(index, number); + g.computeIfAbsent(number, k -> new TreeSet<>()).add(index); } public int find(int number) { - return t.containsKey(number) ? t.get(number).first() : -1; + var ids = g.get(number); + return ids == null || ids.isEmpty() ? -1 : ids.first(); } } @@ -145,26 +152,28 @@ class NumberContainers { ```cpp class NumberContainers { public: - map mp; - map> t; - NumberContainers() { } void change(int index, int number) { - auto it = mp.find(index); - if (it != mp.end()) { - t[it->second].erase(index); - it->second = number; - } else - mp[index] = number; - t[number].insert(index); + if (d.contains(index)) { + int oldNumber = d[index]; + g[oldNumber].erase(index); + if (g[oldNumber].empty()) { + g.erase(oldNumber); + } + } + d[index] = number; + g[number].insert(index); } int find(int number) { - auto it = t.find(number); - return it == t.end() || it->second.empty() ? -1 : *it->second.begin(); + return g.contains(number) ? *g[number].begin() : -1; } + +private: + unordered_map d; + unordered_map> g; }; /** @@ -179,8 +188,8 @@ public: ```go type NumberContainers struct { - mp map[int]int - t map[int]*redblacktree.Tree + d map[int]int + g map[int]*redblacktree.Tree } func Constructor() NumberContainers { @@ -188,22 +197,21 @@ func Constructor() NumberContainers { } func (this *NumberContainers) Change(index int, number int) { - if num, ok := this.mp[index]; ok { - this.t[num].Remove(index) + if oldNumber, ok := this.d[index]; ok { + this.g[oldNumber].Remove(index) } - this.mp[index] = number - if this.t[number] == nil { - this.t[number] = redblacktree.NewWithIntComparator() + this.d[index] = number + if _, ok := this.g[number]; !ok { + this.g[number] = redblacktree.NewWithIntComparator() } - this.t[number].Put(index, nil) + this.g[number].Put(index, nil) } func (this *NumberContainers) Find(number int) int { - s, ok := this.t[number] - if !ok || s.Size() == 0 { - return -1 + if ids, ok := this.g[number]; ok && ids.Size() > 0 { + return ids.Left().Key.(int) } - return s.Left().Key.(int) + return -1 } /** @@ -214,6 +222,532 @@ func (this *NumberContainers) Find(number int) int { */ ``` +#### TypeScript + +```ts +class NumberContainers { + private d = new Map(); + private g = new Map>(); + constructor() {} + + change(index: number, number: number): void { + if (this.d.has(index)) { + const oldNumber = this.d.get(index)!; + this.g.get(oldNumber)!.delete(index); + if (!this.g.get(oldNumber)!.size()) { + this.g.delete(oldNumber); + } + } + this.d.set(index, number); + if (!this.g.has(number)) { + this.g.set(number, new TreeSet()); + } + this.g.get(number)!.add(index); + } + + find(number: number): number { + return this.g.has(number) ? this.g.get(number)!.first()! : -1; + } +} + +type Compare = (lhs: T, rhs: T) => number; + +class RBTreeNode { + data: T; + count: number; + left: RBTreeNode | null; + right: RBTreeNode | null; + parent: RBTreeNode | null; + color: number; + constructor(data: T) { + this.data = data; + this.left = this.right = this.parent = null; + this.color = 0; + this.count = 1; + } + + sibling(): RBTreeNode | null { + if (!this.parent) return null; // sibling null if no parent + return this.isOnLeft() ? this.parent.right : this.parent.left; + } + + isOnLeft(): boolean { + return this === this.parent!.left; + } + + hasRedChild(): boolean { + return ( + Boolean(this.left && this.left.color === 0) || + Boolean(this.right && this.right.color === 0) + ); + } +} + +class RBTree { + root: RBTreeNode | null; + lt: (l: T, r: T) => boolean; + constructor(compare: Compare = (l: T, r: T) => (l < r ? -1 : l > r ? 1 : 0)) { + this.root = null; + this.lt = (l: T, r: T) => compare(l, r) < 0; + } + + rotateLeft(pt: RBTreeNode): void { + const right = pt.right!; + pt.right = right.left; + + if (pt.right) pt.right.parent = pt; + right.parent = pt.parent; + + if (!pt.parent) this.root = right; + else if (pt === pt.parent.left) pt.parent.left = right; + else pt.parent.right = right; + + right.left = pt; + pt.parent = right; + } + + rotateRight(pt: RBTreeNode): void { + const left = pt.left!; + pt.left = left.right; + + if (pt.left) pt.left.parent = pt; + left.parent = pt.parent; + + if (!pt.parent) this.root = left; + else if (pt === pt.parent.left) pt.parent.left = left; + else pt.parent.right = left; + + left.right = pt; + pt.parent = left; + } + + swapColor(p1: RBTreeNode, p2: RBTreeNode): void { + const tmp = p1.color; + p1.color = p2.color; + p2.color = tmp; + } + + swapData(p1: RBTreeNode, p2: RBTreeNode): void { + const tmp = p1.data; + p1.data = p2.data; + p2.data = tmp; + } + + fixAfterInsert(pt: RBTreeNode): void { + let parent = null; + let grandParent = null; + + while (pt !== this.root && pt.color !== 1 && pt.parent?.color === 0) { + parent = pt.parent; + grandParent = pt.parent.parent; + + /* Case : A + Parent of pt is left child of Grand-parent of pt */ + if (parent === grandParent?.left) { + const uncle = grandParent.right; + + /* Case : 1 + The uncle of pt is also red + Only Recoloring required */ + if (uncle && uncle.color === 0) { + grandParent.color = 0; + parent.color = 1; + uncle.color = 1; + pt = grandParent; + } else { + /* Case : 2 + pt is right child of its parent + Left-rotation required */ + if (pt === parent.right) { + this.rotateLeft(parent); + pt = parent; + parent = pt.parent; + } + + /* Case : 3 + pt is left child of its parent + Right-rotation required */ + this.rotateRight(grandParent); + this.swapColor(parent!, grandParent); + pt = parent!; + } + } else { + /* Case : B + Parent of pt is right child of Grand-parent of pt */ + const uncle = grandParent!.left; + + /* Case : 1 + The uncle of pt is also red + Only Recoloring required */ + if (uncle != null && uncle.color === 0) { + grandParent!.color = 0; + parent.color = 1; + uncle.color = 1; + pt = grandParent!; + } else { + /* Case : 2 + pt is left child of its parent + Right-rotation required */ + if (pt === parent.left) { + this.rotateRight(parent); + pt = parent; + parent = pt.parent; + } + + /* Case : 3 + pt is right child of its parent + Left-rotation required */ + this.rotateLeft(grandParent!); + this.swapColor(parent!, grandParent!); + pt = parent!; + } + } + } + this.root!.color = 1; + } + + delete(val: T): boolean { + const node = this.find(val); + if (!node) return false; + node.count--; + if (!node.count) this.deleteNode(node); + return true; + } + + deleteAll(val: T): boolean { + const node = this.find(val); + if (!node) return false; + this.deleteNode(node); + return true; + } + + deleteNode(v: RBTreeNode): void { + const u = BSTreplace(v); + + // True when u and v are both black + const uvBlack = (u === null || u.color === 1) && v.color === 1; + const parent = v.parent!; + + if (!u) { + // u is null therefore v is leaf + if (v === this.root) this.root = null; + // v is root, making root null + else { + if (uvBlack) { + // u and v both black + // v is leaf, fix double black at v + this.fixDoubleBlack(v); + } else { + // u or v is red + if (v.sibling()) { + // sibling is not null, make it red" + v.sibling()!.color = 0; + } + } + // delete v from the tree + if (v.isOnLeft()) parent.left = null; + else parent.right = null; + } + return; + } + + if (!v.left || !v.right) { + // v has 1 child + if (v === this.root) { + // v is root, assign the value of u to v, and delete u + v.data = u.data; + v.left = v.right = null; + } else { + // Detach v from tree and move u up + if (v.isOnLeft()) parent.left = u; + else parent.right = u; + u.parent = parent; + if (uvBlack) this.fixDoubleBlack(u); + // u and v both black, fix double black at u + else u.color = 1; // u or v red, color u black + } + return; + } + + // v has 2 children, swap data with successor and recurse + this.swapData(u, v); + this.deleteNode(u); + + // find node that replaces a deleted node in BST + function BSTreplace(x: RBTreeNode): RBTreeNode | null { + // when node have 2 children + if (x.left && x.right) return successor(x.right); + // when leaf + if (!x.left && !x.right) return null; + // when single child + return x.left ?? x.right; + } + // find node that do not have a left child + // in the subtree of the given node + function successor(x: RBTreeNode): RBTreeNode { + let temp = x; + while (temp.left) temp = temp.left; + return temp; + } + } + + fixDoubleBlack(x: RBTreeNode): void { + if (x === this.root) return; // Reached root + + const sibling = x.sibling(); + const parent = x.parent!; + if (!sibling) { + // No sibiling, double black pushed up + this.fixDoubleBlack(parent); + } else { + if (sibling.color === 0) { + // Sibling red + parent.color = 0; + sibling.color = 1; + if (sibling.isOnLeft()) this.rotateRight(parent); + // left case + else this.rotateLeft(parent); // right case + this.fixDoubleBlack(x); + } else { + // Sibling black + if (sibling.hasRedChild()) { + // at least 1 red children + if (sibling.left && sibling.left.color === 0) { + if (sibling.isOnLeft()) { + // left left + sibling.left.color = sibling.color; + sibling.color = parent.color; + this.rotateRight(parent); + } else { + // right left + sibling.left.color = parent.color; + this.rotateRight(sibling); + this.rotateLeft(parent); + } + } else { + if (sibling.isOnLeft()) { + // left right + sibling.right!.color = parent.color; + this.rotateLeft(sibling); + this.rotateRight(parent); + } else { + // right right + sibling.right!.color = sibling.color; + sibling.color = parent.color; + this.rotateLeft(parent); + } + } + parent.color = 1; + } else { + // 2 black children + sibling.color = 0; + if (parent.color === 1) this.fixDoubleBlack(parent); + else parent.color = 1; + } + } + } + } + + insert(data: T): boolean { + // search for a position to insert + let parent = this.root; + while (parent) { + if (this.lt(data, parent.data)) { + if (!parent.left) break; + else parent = parent.left; + } else if (this.lt(parent.data, data)) { + if (!parent.right) break; + else parent = parent.right; + } else break; + } + + // insert node into parent + const node = new RBTreeNode(data); + if (!parent) this.root = node; + else if (this.lt(node.data, parent.data)) parent.left = node; + else if (this.lt(parent.data, node.data)) parent.right = node; + else { + parent.count++; + return false; + } + node.parent = parent; + this.fixAfterInsert(node); + return true; + } + + find(data: T): RBTreeNode | null { + let p = this.root; + while (p) { + if (this.lt(data, p.data)) { + p = p.left; + } else if (this.lt(p.data, data)) { + p = p.right; + } else break; + } + return p ?? null; + } + + *inOrder(root: RBTreeNode = this.root!): Generator { + if (!root) return; + for (const v of this.inOrder(root.left!)) yield v; + yield root.data; + for (const v of this.inOrder(root.right!)) yield v; + } + + *reverseInOrder(root: RBTreeNode = this.root!): Generator { + if (!root) return; + for (const v of this.reverseInOrder(root.right!)) yield v; + yield root.data; + for (const v of this.reverseInOrder(root.left!)) yield v; + } +} + +class TreeSet { + _size: number; + tree: RBTree; + compare: Compare; + constructor( + collection: T[] | Compare = [], + compare: Compare = (l: T, r: T) => (l < r ? -1 : l > r ? 1 : 0), + ) { + if (typeof collection === 'function') { + compare = collection; + collection = []; + } + this._size = 0; + this.compare = compare; + this.tree = new RBTree(compare); + for (const val of collection) this.add(val); + } + + size(): number { + return this._size; + } + + has(val: T): boolean { + return !!this.tree.find(val); + } + + add(val: T): boolean { + const successful = this.tree.insert(val); + this._size += successful ? 1 : 0; + return successful; + } + + delete(val: T): boolean { + const deleted = this.tree.deleteAll(val); + this._size -= deleted ? 1 : 0; + return deleted; + } + + ceil(val: T): T | undefined { + let p = this.tree.root; + let higher = null; + while (p) { + if (this.compare(p.data, val) >= 0) { + higher = p; + p = p.left; + } else { + p = p.right; + } + } + return higher?.data; + } + + floor(val: T): T | undefined { + let p = this.tree.root; + let lower = null; + while (p) { + if (this.compare(val, p.data) >= 0) { + lower = p; + p = p.right; + } else { + p = p.left; + } + } + return lower?.data; + } + + higher(val: T): T | undefined { + let p = this.tree.root; + let higher = null; + while (p) { + if (this.compare(val, p.data) < 0) { + higher = p; + p = p.left; + } else { + p = p.right; + } + } + return higher?.data; + } + + lower(val: T): T | undefined { + let p = this.tree.root; + let lower = null; + while (p) { + if (this.compare(p.data, val) < 0) { + lower = p; + p = p.right; + } else { + p = p.left; + } + } + return lower?.data; + } + + first(): T | undefined { + return this.tree.inOrder().next().value; + } + + last(): T | undefined { + return this.tree.reverseInOrder().next().value; + } + + shift(): T | undefined { + const first = this.first(); + if (first === undefined) return undefined; + this.delete(first); + return first; + } + + pop(): T | undefined { + const last = this.last(); + if (last === undefined) return undefined; + this.delete(last); + return last; + } + + *[Symbol.iterator](): Generator { + for (const val of this.values()) yield val; + } + + *keys(): Generator { + for (const val of this.values()) yield val; + } + + *values(): Generator { + for (const val of this.tree.inOrder()) yield val; + return undefined; + } + + /** + * Return a generator for reverse order traversing the set + */ + *rvalues(): Generator { + for (const val of this.tree.reverseInOrder()) yield val; + return undefined; + } +} + +/** + * Your NumberContainers object will be instantiated and called as such: + * var obj = new NumberContainers() + * obj.change(index,number) + * var param_2 = obj.find(number) + */ +``` + diff --git a/solution/2300-2399/2349.Design a Number Container System/Solution.cpp b/solution/2300-2399/2349.Design a Number Container System/Solution.cpp index 812ebd94c930..c96d6bfc577f 100644 --- a/solution/2300-2399/2349.Design a Number Container System/Solution.cpp +++ b/solution/2300-2399/2349.Design a Number Container System/Solution.cpp @@ -1,25 +1,27 @@ class NumberContainers { public: - map mp; - map> t; - NumberContainers() { } void change(int index, int number) { - auto it = mp.find(index); - if (it != mp.end()) { - t[it->second].erase(index); - it->second = number; - } else - mp[index] = number; - t[number].insert(index); + if (d.contains(index)) { + int oldNumber = d[index]; + g[oldNumber].erase(index); + if (g[oldNumber].empty()) { + g.erase(oldNumber); + } + } + d[index] = number; + g[number].insert(index); } int find(int number) { - auto it = t.find(number); - return it == t.end() || it->second.empty() ? -1 : *it->second.begin(); + return g.contains(number) ? *g[number].begin() : -1; } + +private: + unordered_map d; + unordered_map> g; }; /** diff --git a/solution/2300-2399/2349.Design a Number Container System/Solution.go b/solution/2300-2399/2349.Design a Number Container System/Solution.go index 980c474ec2e3..b2ea51905f60 100644 --- a/solution/2300-2399/2349.Design a Number Container System/Solution.go +++ b/solution/2300-2399/2349.Design a Number Container System/Solution.go @@ -1,6 +1,6 @@ type NumberContainers struct { - mp map[int]int - t map[int]*redblacktree.Tree + d map[int]int + g map[int]*redblacktree.Tree } func Constructor() NumberContainers { @@ -8,22 +8,21 @@ func Constructor() NumberContainers { } func (this *NumberContainers) Change(index int, number int) { - if num, ok := this.mp[index]; ok { - this.t[num].Remove(index) + if oldNumber, ok := this.d[index]; ok { + this.g[oldNumber].Remove(index) } - this.mp[index] = number - if this.t[number] == nil { - this.t[number] = redblacktree.NewWithIntComparator() + this.d[index] = number + if _, ok := this.g[number]; !ok { + this.g[number] = redblacktree.NewWithIntComparator() } - this.t[number].Put(index, nil) + this.g[number].Put(index, nil) } func (this *NumberContainers) Find(number int) int { - s, ok := this.t[number] - if !ok || s.Size() == 0 { - return -1 + if ids, ok := this.g[number]; ok && ids.Size() > 0 { + return ids.Left().Key.(int) } - return s.Left().Key.(int) + return -1 } /** diff --git a/solution/2300-2399/2349.Design a Number Container System/Solution.java b/solution/2300-2399/2349.Design a Number Container System/Solution.java index b5f43bd667f0..90e4d6913acd 100644 --- a/solution/2300-2399/2349.Design a Number Container System/Solution.java +++ b/solution/2300-2399/2349.Design a Number Container System/Solution.java @@ -1,24 +1,22 @@ class NumberContainers { - private Map mp = new HashMap<>(); - private Map> t = new HashMap<>(); + private Map d = new HashMap<>(); + private Map> g = new HashMap<>(); public NumberContainers() { } public void change(int index, int number) { - if (mp.containsKey(index)) { - int v = mp.get(index); - t.get(v).remove(index); - if (t.get(v).isEmpty()) { - t.remove(v); - } + if (d.containsKey(index)) { + int oldNumber = d.get(index); + g.get(oldNumber).remove(index); } - mp.put(index, number); - t.computeIfAbsent(number, k -> new TreeSet<>()).add(index); + d.put(index, number); + g.computeIfAbsent(number, k -> new TreeSet<>()).add(index); } public int find(int number) { - return t.containsKey(number) ? t.get(number).first() : -1; + var ids = g.get(number); + return ids == null || ids.isEmpty() ? -1 : ids.first(); } } diff --git a/solution/2300-2399/2349.Design a Number Container System/Solution.py b/solution/2300-2399/2349.Design a Number Container System/Solution.py index babe82453f10..8cba7dc3ccb9 100644 --- a/solution/2300-2399/2349.Design a Number Container System/Solution.py +++ b/solution/2300-2399/2349.Design a Number Container System/Solution.py @@ -2,20 +2,21 @@ class NumberContainers: + def __init__(self): - self.mp = {} - self.t = defaultdict(SortedSet) + self.d = {} + self.g = defaultdict(SortedSet) def change(self, index: int, number: int) -> None: - if index in self.mp: - v = self.mp[index] - self.t[v].remove(index) - self.mp[index] = number - self.t[number].add(index) + if index in self.d: + old_number = self.d[index] + self.g[old_number].remove(index) + self.d[index] = number + self.g[number].add(index) def find(self, number: int) -> int: - s = self.t[number] - return s[0] if s else -1 + ids = self.g[number] + return ids[0] if ids else -1 # Your NumberContainers object will be instantiated and called as such: diff --git a/solution/2300-2399/2349.Design a Number Container System/Solution.ts b/solution/2300-2399/2349.Design a Number Container System/Solution.ts new file mode 100644 index 000000000000..e720b01a5275 --- /dev/null +++ b/solution/2300-2399/2349.Design a Number Container System/Solution.ts @@ -0,0 +1,521 @@ +class NumberContainers { + private d = new Map(); + private g = new Map>(); + constructor() {} + + change(index: number, number: number): void { + if (this.d.has(index)) { + const oldNumber = this.d.get(index)!; + this.g.get(oldNumber)!.delete(index); + if (!this.g.get(oldNumber)!.size()) { + this.g.delete(oldNumber); + } + } + this.d.set(index, number); + if (!this.g.has(number)) { + this.g.set(number, new TreeSet()); + } + this.g.get(number)!.add(index); + } + + find(number: number): number { + return this.g.has(number) ? this.g.get(number)!.first()! : -1; + } +} + +type Compare = (lhs: T, rhs: T) => number; + +class RBTreeNode { + data: T; + count: number; + left: RBTreeNode | null; + right: RBTreeNode | null; + parent: RBTreeNode | null; + color: number; + constructor(data: T) { + this.data = data; + this.left = this.right = this.parent = null; + this.color = 0; + this.count = 1; + } + + sibling(): RBTreeNode | null { + if (!this.parent) return null; // sibling null if no parent + return this.isOnLeft() ? this.parent.right : this.parent.left; + } + + isOnLeft(): boolean { + return this === this.parent!.left; + } + + hasRedChild(): boolean { + return ( + Boolean(this.left && this.left.color === 0) || + Boolean(this.right && this.right.color === 0) + ); + } +} + +class RBTree { + root: RBTreeNode | null; + lt: (l: T, r: T) => boolean; + constructor(compare: Compare = (l: T, r: T) => (l < r ? -1 : l > r ? 1 : 0)) { + this.root = null; + this.lt = (l: T, r: T) => compare(l, r) < 0; + } + + rotateLeft(pt: RBTreeNode): void { + const right = pt.right!; + pt.right = right.left; + + if (pt.right) pt.right.parent = pt; + right.parent = pt.parent; + + if (!pt.parent) this.root = right; + else if (pt === pt.parent.left) pt.parent.left = right; + else pt.parent.right = right; + + right.left = pt; + pt.parent = right; + } + + rotateRight(pt: RBTreeNode): void { + const left = pt.left!; + pt.left = left.right; + + if (pt.left) pt.left.parent = pt; + left.parent = pt.parent; + + if (!pt.parent) this.root = left; + else if (pt === pt.parent.left) pt.parent.left = left; + else pt.parent.right = left; + + left.right = pt; + pt.parent = left; + } + + swapColor(p1: RBTreeNode, p2: RBTreeNode): void { + const tmp = p1.color; + p1.color = p2.color; + p2.color = tmp; + } + + swapData(p1: RBTreeNode, p2: RBTreeNode): void { + const tmp = p1.data; + p1.data = p2.data; + p2.data = tmp; + } + + fixAfterInsert(pt: RBTreeNode): void { + let parent = null; + let grandParent = null; + + while (pt !== this.root && pt.color !== 1 && pt.parent?.color === 0) { + parent = pt.parent; + grandParent = pt.parent.parent; + + /* Case : A + Parent of pt is left child of Grand-parent of pt */ + if (parent === grandParent?.left) { + const uncle = grandParent.right; + + /* Case : 1 + The uncle of pt is also red + Only Recoloring required */ + if (uncle && uncle.color === 0) { + grandParent.color = 0; + parent.color = 1; + uncle.color = 1; + pt = grandParent; + } else { + /* Case : 2 + pt is right child of its parent + Left-rotation required */ + if (pt === parent.right) { + this.rotateLeft(parent); + pt = parent; + parent = pt.parent; + } + + /* Case : 3 + pt is left child of its parent + Right-rotation required */ + this.rotateRight(grandParent); + this.swapColor(parent!, grandParent); + pt = parent!; + } + } else { + /* Case : B + Parent of pt is right child of Grand-parent of pt */ + const uncle = grandParent!.left; + + /* Case : 1 + The uncle of pt is also red + Only Recoloring required */ + if (uncle != null && uncle.color === 0) { + grandParent!.color = 0; + parent.color = 1; + uncle.color = 1; + pt = grandParent!; + } else { + /* Case : 2 + pt is left child of its parent + Right-rotation required */ + if (pt === parent.left) { + this.rotateRight(parent); + pt = parent; + parent = pt.parent; + } + + /* Case : 3 + pt is right child of its parent + Left-rotation required */ + this.rotateLeft(grandParent!); + this.swapColor(parent!, grandParent!); + pt = parent!; + } + } + } + this.root!.color = 1; + } + + delete(val: T): boolean { + const node = this.find(val); + if (!node) return false; + node.count--; + if (!node.count) this.deleteNode(node); + return true; + } + + deleteAll(val: T): boolean { + const node = this.find(val); + if (!node) return false; + this.deleteNode(node); + return true; + } + + deleteNode(v: RBTreeNode): void { + const u = BSTreplace(v); + + // True when u and v are both black + const uvBlack = (u === null || u.color === 1) && v.color === 1; + const parent = v.parent!; + + if (!u) { + // u is null therefore v is leaf + if (v === this.root) this.root = null; + // v is root, making root null + else { + if (uvBlack) { + // u and v both black + // v is leaf, fix double black at v + this.fixDoubleBlack(v); + } else { + // u or v is red + if (v.sibling()) { + // sibling is not null, make it red" + v.sibling()!.color = 0; + } + } + // delete v from the tree + if (v.isOnLeft()) parent.left = null; + else parent.right = null; + } + return; + } + + if (!v.left || !v.right) { + // v has 1 child + if (v === this.root) { + // v is root, assign the value of u to v, and delete u + v.data = u.data; + v.left = v.right = null; + } else { + // Detach v from tree and move u up + if (v.isOnLeft()) parent.left = u; + else parent.right = u; + u.parent = parent; + if (uvBlack) this.fixDoubleBlack(u); + // u and v both black, fix double black at u + else u.color = 1; // u or v red, color u black + } + return; + } + + // v has 2 children, swap data with successor and recurse + this.swapData(u, v); + this.deleteNode(u); + + // find node that replaces a deleted node in BST + function BSTreplace(x: RBTreeNode): RBTreeNode | null { + // when node have 2 children + if (x.left && x.right) return successor(x.right); + // when leaf + if (!x.left && !x.right) return null; + // when single child + return x.left ?? x.right; + } + // find node that do not have a left child + // in the subtree of the given node + function successor(x: RBTreeNode): RBTreeNode { + let temp = x; + while (temp.left) temp = temp.left; + return temp; + } + } + + fixDoubleBlack(x: RBTreeNode): void { + if (x === this.root) return; // Reached root + + const sibling = x.sibling(); + const parent = x.parent!; + if (!sibling) { + // No sibiling, double black pushed up + this.fixDoubleBlack(parent); + } else { + if (sibling.color === 0) { + // Sibling red + parent.color = 0; + sibling.color = 1; + if (sibling.isOnLeft()) this.rotateRight(parent); + // left case + else this.rotateLeft(parent); // right case + this.fixDoubleBlack(x); + } else { + // Sibling black + if (sibling.hasRedChild()) { + // at least 1 red children + if (sibling.left && sibling.left.color === 0) { + if (sibling.isOnLeft()) { + // left left + sibling.left.color = sibling.color; + sibling.color = parent.color; + this.rotateRight(parent); + } else { + // right left + sibling.left.color = parent.color; + this.rotateRight(sibling); + this.rotateLeft(parent); + } + } else { + if (sibling.isOnLeft()) { + // left right + sibling.right!.color = parent.color; + this.rotateLeft(sibling); + this.rotateRight(parent); + } else { + // right right + sibling.right!.color = sibling.color; + sibling.color = parent.color; + this.rotateLeft(parent); + } + } + parent.color = 1; + } else { + // 2 black children + sibling.color = 0; + if (parent.color === 1) this.fixDoubleBlack(parent); + else parent.color = 1; + } + } + } + } + + insert(data: T): boolean { + // search for a position to insert + let parent = this.root; + while (parent) { + if (this.lt(data, parent.data)) { + if (!parent.left) break; + else parent = parent.left; + } else if (this.lt(parent.data, data)) { + if (!parent.right) break; + else parent = parent.right; + } else break; + } + + // insert node into parent + const node = new RBTreeNode(data); + if (!parent) this.root = node; + else if (this.lt(node.data, parent.data)) parent.left = node; + else if (this.lt(parent.data, node.data)) parent.right = node; + else { + parent.count++; + return false; + } + node.parent = parent; + this.fixAfterInsert(node); + return true; + } + + find(data: T): RBTreeNode | null { + let p = this.root; + while (p) { + if (this.lt(data, p.data)) { + p = p.left; + } else if (this.lt(p.data, data)) { + p = p.right; + } else break; + } + return p ?? null; + } + + *inOrder(root: RBTreeNode = this.root!): Generator { + if (!root) return; + for (const v of this.inOrder(root.left!)) yield v; + yield root.data; + for (const v of this.inOrder(root.right!)) yield v; + } + + *reverseInOrder(root: RBTreeNode = this.root!): Generator { + if (!root) return; + for (const v of this.reverseInOrder(root.right!)) yield v; + yield root.data; + for (const v of this.reverseInOrder(root.left!)) yield v; + } +} + +class TreeSet { + _size: number; + tree: RBTree; + compare: Compare; + constructor( + collection: T[] | Compare = [], + compare: Compare = (l: T, r: T) => (l < r ? -1 : l > r ? 1 : 0), + ) { + if (typeof collection === 'function') { + compare = collection; + collection = []; + } + this._size = 0; + this.compare = compare; + this.tree = new RBTree(compare); + for (const val of collection) this.add(val); + } + + size(): number { + return this._size; + } + + has(val: T): boolean { + return !!this.tree.find(val); + } + + add(val: T): boolean { + const successful = this.tree.insert(val); + this._size += successful ? 1 : 0; + return successful; + } + + delete(val: T): boolean { + const deleted = this.tree.deleteAll(val); + this._size -= deleted ? 1 : 0; + return deleted; + } + + ceil(val: T): T | undefined { + let p = this.tree.root; + let higher = null; + while (p) { + if (this.compare(p.data, val) >= 0) { + higher = p; + p = p.left; + } else { + p = p.right; + } + } + return higher?.data; + } + + floor(val: T): T | undefined { + let p = this.tree.root; + let lower = null; + while (p) { + if (this.compare(val, p.data) >= 0) { + lower = p; + p = p.right; + } else { + p = p.left; + } + } + return lower?.data; + } + + higher(val: T): T | undefined { + let p = this.tree.root; + let higher = null; + while (p) { + if (this.compare(val, p.data) < 0) { + higher = p; + p = p.left; + } else { + p = p.right; + } + } + return higher?.data; + } + + lower(val: T): T | undefined { + let p = this.tree.root; + let lower = null; + while (p) { + if (this.compare(p.data, val) < 0) { + lower = p; + p = p.right; + } else { + p = p.left; + } + } + return lower?.data; + } + + first(): T | undefined { + return this.tree.inOrder().next().value; + } + + last(): T | undefined { + return this.tree.reverseInOrder().next().value; + } + + shift(): T | undefined { + const first = this.first(); + if (first === undefined) return undefined; + this.delete(first); + return first; + } + + pop(): T | undefined { + const last = this.last(); + if (last === undefined) return undefined; + this.delete(last); + return last; + } + + *[Symbol.iterator](): Generator { + for (const val of this.values()) yield val; + } + + *keys(): Generator { + for (const val of this.values()) yield val; + } + + *values(): Generator { + for (const val of this.tree.inOrder()) yield val; + return undefined; + } + + /** + * Return a generator for reverse order traversing the set + */ + *rvalues(): Generator { + for (const val of this.tree.reverseInOrder()) yield val; + return undefined; + } +} + +/** + * Your NumberContainers object will be instantiated and called as such: + * var obj = new NumberContainers() + * obj.change(index,number) + * var param_2 = obj.find(number) + */ diff --git a/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README.md b/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README.md index a3cc8407d5b4..d69f4bcca811 100644 --- a/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README.md +++ b/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README.md @@ -80,12 +80,12 @@ tags: 即: $$ -dfs(i) = \text{OR} +dfs(i) = \textit{OR} \begin{cases} true,&i \ge n\\ -dfs(i+2),&i+1 < n\ \text{and}\ \textit{nums}[i] = \textit{nums}[i+1]\\ -dfs(i+3),&i+2 < n\ \text{and}\ \textit{nums}[i] = \textit{nums}[i+1] = \textit{nums}[i+2]\\ -dfs(i+3),&i+2 < n\ \text{and}\ \textit{nums}[i+1] - \textit{nums}[i] = 1\ \text{and}\ \textit{nums}[i+2] - \textit{nums}[i+1] = 1 +dfs(i+2),&i+1 < n\ \textit{and}\ \textit{nums}[i] = \textit{nums}[i+1]\\ +dfs(i+3),&i+2 < n\ \textit{and}\ \textit{nums}[i] = \textit{nums}[i+1] = \textit{nums}[i+2]\\ +dfs(i+3),&i+2 < n\ \textit{and}\ \textit{nums}[i+1] - \textit{nums}[i] = 1\ \textit{and}\ \textit{nums}[i+2] - \textit{nums}[i+1] = 1 \end{cases} $$ @@ -248,12 +248,12 @@ function validPartition(nums: number[]): boolean { 状态转移方程如下: $$ -f[i] = \text{OR} +f[i] = \textit{OR} \begin{cases} true,&i = 0\\ -f[i-2],&i-2 \ge 0\ \text{and}\ \textit{nums}[i-1] = \textit{nums}[i-2]\\ -f[i-3],&i-3 \ge 0\ \text{and}\ \textit{nums}[i-1] = \textit{nums}[i-2] = \textit{nums}[i-3]\\ -f[i-3],&i-3 \ge 0\ \text{and}\ \textit{nums}[i-1] - \textit{nums}[i-2] = 1\ \text{and}\ \textit{nums}[i-2] - \textit{nums}[i-3] = 1 +f[i-2],&i-2 \ge 0\ \textit{and}\ \textit{nums}[i-1] = \textit{nums}[i-2]\\ +f[i-3],&i-3 \ge 0\ \textit{and}\ \textit{nums}[i-1] = \textit{nums}[i-2] = \textit{nums}[i-3]\\ +f[i-3],&i-3 \ge 0\ \textit{and}\ \textit{nums}[i-1] - \textit{nums}[i-2] = 1\ \textit{and}\ \textit{nums}[i-2] - \textit{nums}[i-3] = 1 \end{cases} $$ diff --git a/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README_EN.md b/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README_EN.md index 470bf722492a..1fb1739e20a8 100644 --- a/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README_EN.md +++ b/solution/2300-2399/2369.Check if There is a Valid Partition For The Array/README_EN.md @@ -78,12 +78,12 @@ The execution process of the function $dfs(i)$ is as follows: That is: $$ -dfs(i) = \text{OR} +dfs(i) = \textit{OR} \begin{cases} true,&i \ge n\\ -dfs(i+2),&i+1 < n\ \text{and}\ \textit{nums}[i] = \textit{nums}[i+1]\\ -dfs(i+3),&i+2 < n\ \text{and}\ \textit{nums}[i] = \textit{nums}[i+1] = \textit{nums}[i+2]\\ -dfs(i+3),&i+2 < n\ \text{and}\ \textit{nums}[i+1] - \textit{nums}[i] = 1\ \text{and}\ \textit{nums}[i+2] - \textit{nums}[i+1] = 1 +dfs(i+2),&i+1 < n\ \textit{and}\ \textit{nums}[i] = \textit{nums}[i+1]\\ +dfs(i+3),&i+2 < n\ \textit{and}\ \textit{nums}[i] = \textit{nums}[i+1] = \textit{nums}[i+2]\\ +dfs(i+3),&i+2 < n\ \textit{and}\ \textit{nums}[i+1] - \textit{nums}[i] = 1\ \textit{and}\ \textit{nums}[i+2] - \textit{nums}[i+1] = 1 \end{cases} $$ @@ -246,12 +246,12 @@ Let $f[i]$ represent whether there is a valid partition for the first $i$ elemen The state transition equation is as follows: $$ -f[i] = \text{OR} +f[i] = \textit{OR} \begin{cases} true,&i = 0\\ -f[i-2],&i-2 \ge 0\ \text{and}\ \textit{nums}[i-1] = \textit{nums}[i-2]\\ -f[i-3],&i-3 \ge 0\ \text{and}\ \textit{nums}[i-1] = \textit{nums}[i-2] = \textit{nums}[i-3]\\ -f[i-3],&i-3 \ge 0\ \text{and}\ \textit{nums}[i-1] - \textit{nums}[i-2] = 1\ \text{and}\ \textit{nums}[i-2] - \textit{nums}[i-3] = 1 +f[i-2],&i-2 \ge 0\ \textit{and}\ \textit{nums}[i-1] = \textit{nums}[i-2]\\ +f[i-3],&i-3 \ge 0\ \textit{and}\ \textit{nums}[i-1] = \textit{nums}[i-2] = \textit{nums}[i-3]\\ +f[i-3],&i-3 \ge 0\ \textit{and}\ \textit{nums}[i-1] - \textit{nums}[i-2] = 1\ \textit{and}\ \textit{nums}[i-2] - \textit{nums}[i-3] = 1 \end{cases} $$ diff --git a/solution/2300-2399/2384.Largest Palindromic Number/README.md b/solution/2300-2399/2384.Largest Palindromic Number/README.md index 27443e9a2929..36212a3c6149 100644 --- a/solution/2300-2399/2384.Largest Palindromic Number/README.md +++ b/solution/2300-2399/2384.Largest Palindromic Number/README.md @@ -8,6 +8,7 @@ tags: - 贪心 - 哈希表 - 字符串 + - 计数 --- diff --git a/solution/2300-2399/2384.Largest Palindromic Number/README_EN.md b/solution/2300-2399/2384.Largest Palindromic Number/README_EN.md index 3393a54cfb6b..6106b2406945 100644 --- a/solution/2300-2399/2384.Largest Palindromic Number/README_EN.md +++ b/solution/2300-2399/2384.Largest Palindromic Number/README_EN.md @@ -8,6 +8,7 @@ tags: - Greedy - Hash Table - String + - Counting --- diff --git a/solution/2300-2399/2385.Amount of Time for Binary Tree to Be Infected/README.md b/solution/2300-2399/2385.Amount of Time for Binary Tree to Be Infected/README.md index 6e7b9df44cbc..c5879e5c7c7d 100644 --- a/solution/2300-2399/2385.Amount of Time for Binary Tree to Be Infected/README.md +++ b/solution/2300-2399/2385.Amount of Time for Binary Tree to Be Infected/README.md @@ -74,9 +74,9 @@ tags: ### 方法一:两次 DFS -我们先通过一次 $\text{DFS}$ 建图,得到一个邻接表 $g$,其中 $g[node]$ 表示与节点 $node$ 相连的所有节点。 +我们先通过一次 $\textit{DFS}$ 建图,得到一个邻接表 $g$,其中 $g[node]$ 表示与节点 $node$ 相连的所有节点。 -然后,我们以 $start$ 作为起点,通过 $\text{DFS}$ 搜索整棵树,找到最远距离,即为答案。 +然后,我们以 $start$ 作为起点,通过 $\textit{DFS}$ 搜索整棵树,找到最远距离,即为答案。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点个数。 diff --git a/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README.md b/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README.md index 540904b95e0c..7e95a8206c7d 100644 --- a/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README.md +++ b/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README.md @@ -88,7 +88,7 @@ tags: 根据题目描述,每一辆垃圾车从房子 $0$ 出发,收集其中一种垃圾,按顺序前进,直到到达该种垃圾最后出现的房子下标为止。 -因此,我们可以用一个哈希表 $\text{last}$ 记录每种垃圾最后出现的房子下标。我们假设第 $i$ 种垃圾最后一次出现在第 $j$ 个房子,那么第 $i$ 辆车所需要的行驶时间为 $\text{travel}[0] + \text{travel}[1] + \cdots + \text{travel}[j-1]$。注意,如果 $j = 0$,则不需要行驶时间。我们通过前缀和累计所有车辆的行驶时间,加上每种垃圾的总收集时间,即可得到答案。 +因此,我们可以用一个哈希表 $\textit{last}$ 记录每种垃圾最后出现的房子下标。我们假设第 $i$ 种垃圾最后一次出现在第 $j$ 个房子,那么第 $i$ 辆车所需要的行驶时间为 $\textit{travel}[0] + \textit{travel}[1] + \cdots + \textit{travel}[j-1]$。注意,如果 $j = 0$,则不需要行驶时间。我们通过前缀和累计所有车辆的行驶时间,加上每种垃圾的总收集时间,即可得到答案。 时间复杂度 $O(n)$,空间复杂度 $O(k)$,其中 $n$ 和 $k$ 分别是垃圾的数量和种类。本题中 $k = 3$。 diff --git a/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README_EN.md b/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README_EN.md index 4c6400d0066e..e28b752fc57e 100644 --- a/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README_EN.md +++ b/solution/2300-2399/2391.Minimum Amount of Time to Collect Garbage/README_EN.md @@ -88,7 +88,7 @@ It takes a total of 7 + 15 + 15 = 37 minutes to collect all the garbage. According to the problem description, each garbage truck starts from house $0$, collects one type of garbage, and moves forward in order until it reaches the house index where this type of garbage last appears. -Therefore, we can use a hash table $\text{last}$ to record the house index where each type of garbage last appears. We assume that the $i$-th type of garbage last appears in the $j$-th house, then the driving time required for the $i$-th truck is $\text{travel}[0] + \text{travel}[1] + \cdots + \text{travel}[j-1]$. Note, if $j = 0$, no driving time is needed. We accumulate the driving time of all vehicles, add the total collection time of each type of garbage, and we can get the answer. +Therefore, we can use a hash table $\textit{last}$ to record the house index where each type of garbage last appears. We assume that the $i$-th type of garbage last appears in the $j$-th house, then the driving time required for the $i$-th truck is $\textit{travel}[0] + \textit{travel}[1] + \cdots + \textit{travel}[j-1]$. Note, if $j = 0$, no driving time is needed. We accumulate the driving time of all vehicles, add the total collection time of each type of garbage, and we can get the answer. The time complexity is $O(n)$, and the space complexity is $O(k)$, where $n$ and $k$ are the number and types of garbage, respectively. In this problem, $k = 3$. diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md index 68056afc595f..e0a075621613 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README.md @@ -81,11 +81,21 @@ tags: ### 方法一:前缀树 -用前缀树维护所有字符串的前缀以及每个前缀出现的次数。 +我们可以用前缀树来维护所有字符串的前缀以及每个前缀出现的次数。 -然后遍历每个字符串,累加每个前缀的出现次数即可。 +定义前缀树节点结构体 `Trie`,包含两个属性: -时间复杂度 $O(n \times m)$。其中 $n$, $m$ 分别为字符串数组 `words` 的长度和其中字符串的最大长度。 +- `children`:长度为 26 的数组,用于存储当前节点的子节点。 +- `cnt`:当前节点的出现次数。 + +定义前缀树的两个方法: + +- `insert`:插入一个字符串,将其前缀插入前缀树。 +- `search`:搜索一个字符串,返回其前缀的出现次数。 + +我们遍历所有字符串,将每个字符串插入前缀树中。然后再遍历所有字符串,对每个字符串调用 `search` 方法,累加每个前缀的出现次数即可。 + +时间复杂度 $O(L)$,空间复杂度 $O(L)$,其中 $L$ 是所有字符串的总长度。 @@ -93,6 +103,8 @@ tags: ```python class Trie: + __slots__ = "children", "cnt" + def __init__(self): self.children = [None] * 26 self.cnt = 0 @@ -100,7 +112,7 @@ class Trie: def insert(self, w): node = self for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] @@ -110,7 +122,7 @@ class Trie: node = self ans = 0 for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: return ans node = node.children[idx] @@ -180,19 +192,17 @@ class Solution { ```cpp class Trie { private: - vector children; - int cnt; + Trie* children[26]{}; + int cnt = 0; public: - Trie() - : children(26) - , cnt(0) {} - void insert(string& w) { Trie* node = this; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) node->children[idx] = new Trie(); + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } node = node->children[idx]; ++node->cnt; } @@ -203,7 +213,9 @@ public: int ans = 0; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) return ans; + if (!node->children[idx]) { + return ans; + } node = node->children[idx]; ans += node->cnt; } @@ -279,42 +291,6 @@ func sumPrefixScores(words []string) []int { #### TypeScript -```ts -function sumPrefixScores(words: string[]): number[] { - const map = new Map(); - - for (const word of words) { - const n = word.length; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - map.set(s, (map.get(s) ?? 0) + 1); - } - } - - return words.map(word => { - const n = word.length; - let count = 0; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - count += map.get(s); - } - return count; - }); -} -``` - - - - - - - -### 方法二 - - - -#### TypeScript - ```ts class Trie { children: Array; @@ -357,11 +333,7 @@ function sumPrefixScores(words: string[]): number[] { for (const w of words) { trie.insert(w); } - let ans = []; - for (const w of words) { - ans.push(trie.search(w)); - } - return ans; + return words.map(w => trie.search(w)); } ``` diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md index 683e26331437..808ab3f98788 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/README_EN.md @@ -79,13 +79,23 @@ Each prefix has a score of one, so the total is answer[0] = 1 + 1 + 1 + 1 = 4. -### Solution 1: Trie +### Solution 1: Prefix Tree -Use a trie to maintain the prefixes of all strings and the occurrence count of each prefix. +We can use a prefix tree to maintain all prefixes of the strings and count the occurrences of each prefix. -Then, traverse each string, accumulating the occurrence count of each prefix. +Define the prefix tree node structure `Trie`, which includes two properties: -The time complexity is $O(n \times m)$. Here, $n$ and $m$ are the length of the string array `words` and the maximum length of the strings in it, respectively. +- `children`: An array of length 26 used to store the current node's children. +- `cnt`: The occurrence count of the current node. + +Define two methods for the prefix tree: + +- `insert`: Inserts a string, adding its prefixes into the prefix tree. +- `search`: Searches for a string and returns the occurrence count of its prefixes. + +We traverse all strings, inserting each string into the prefix tree. Then we traverse all strings again, calling the `search` method for each string and summing up the occurrence counts of each prefix. + +Time complexity is $O(L)$, and space complexity is $O(L)$, where $L$ is the total length of all strings. @@ -93,6 +103,8 @@ The time complexity is $O(n \times m)$. Here, $n$ and $m$ are the length of the ```python class Trie: + __slots__ = "children", "cnt" + def __init__(self): self.children = [None] * 26 self.cnt = 0 @@ -100,7 +112,7 @@ class Trie: def insert(self, w): node = self for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] @@ -110,7 +122,7 @@ class Trie: node = self ans = 0 for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: return ans node = node.children[idx] @@ -180,19 +192,17 @@ class Solution { ```cpp class Trie { private: - vector children; - int cnt; + Trie* children[26]{}; + int cnt = 0; public: - Trie() - : children(26) - , cnt(0) {} - void insert(string& w) { Trie* node = this; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) node->children[idx] = new Trie(); + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } node = node->children[idx]; ++node->cnt; } @@ -203,7 +213,9 @@ public: int ans = 0; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) return ans; + if (!node->children[idx]) { + return ans; + } node = node->children[idx]; ans += node->cnt; } @@ -279,42 +291,6 @@ func sumPrefixScores(words []string) []int { #### TypeScript -```ts -function sumPrefixScores(words: string[]): number[] { - const map = new Map(); - - for (const word of words) { - const n = word.length; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - map.set(s, (map.get(s) ?? 0) + 1); - } - } - - return words.map(word => { - const n = word.length; - let count = 0; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - count += map.get(s); - } - return count; - }); -} -``` - - - - - - - -### Solution 2 - - - -#### TypeScript - ```ts class Trie { children: Array; @@ -357,11 +333,7 @@ function sumPrefixScores(words: string[]): number[] { for (const w of words) { trie.insert(w); } - let ans = []; - for (const w of words) { - ans.push(trie.search(w)); - } - return ans; + return words.map(w => trie.search(w)); } ``` diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp index 648733eaa6e9..4df8ce5e3723 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.cpp @@ -1,18 +1,16 @@ class Trie { private: - vector children; - int cnt; + Trie* children[26]{}; + int cnt = 0; public: - Trie() - : children(26) - , cnt(0) {} - void insert(string& w) { Trie* node = this; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) node->children[idx] = new Trie(); + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } node = node->children[idx]; ++node->cnt; } @@ -23,7 +21,9 @@ class Trie { int ans = 0; for (char c : w) { int idx = c - 'a'; - if (!node->children[idx]) return ans; + if (!node->children[idx]) { + return ans; + } node = node->children[idx]; ans += node->cnt; } @@ -44,4 +44,4 @@ class Solution { } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py index 73579eb37031..bef821c310c9 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.py @@ -1,4 +1,6 @@ class Trie: + __slots__ = "children", "cnt" + def __init__(self): self.children = [None] * 26 self.cnt = 0 @@ -6,7 +8,7 @@ def __init__(self): def insert(self, w): node = self for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] @@ -16,7 +18,7 @@ def search(self, w): node = self ans = 0 for c in w: - idx = ord(c) - ord('a') + idx = ord(c) - ord("a") if node.children[idx] is None: return ans node = node.children[idx] diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts index 8dbbaf5a2ff8..a898ba5ece89 100644 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts +++ b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution.ts @@ -1,21 +1,43 @@ -function sumPrefixScores(words: string[]): number[] { - const map = new Map(); +class Trie { + children: Array; + cnt: number; + + constructor() { + this.children = Array(26); + this.cnt = 0; + } - for (const word of words) { - const n = word.length; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - map.set(s, (map.get(s) ?? 0) + 1); + insert(w: string): void { + let node = this; + for (const c of w) { + const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + node.cnt++; } } - return words.map(word => { - const n = word.length; - let count = 0; - for (let i = 1; i <= n; i++) { - const s = word.slice(0, i); - count += map.get(s); + search(w: string): number { + let node = this; + let ans = 0; + for (const c of w) { + const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); + if (!node.children[idx]) { + return ans; + } + node = node.children[idx]; + ans += node.cnt; } - return count; - }); + return ans; + } +} + +function sumPrefixScores(words: string[]): number[] { + const trie = new Trie(); + for (const w of words) { + trie.insert(w); + } + return words.map(w => trie.search(w)); } diff --git a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution2.ts b/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution2.ts deleted file mode 100644 index fa8217675a44..000000000000 --- a/solution/2400-2499/2416.Sum of Prefix Scores of Strings/Solution2.ts +++ /dev/null @@ -1,47 +0,0 @@ -class Trie { - children: Array; - cnt: number; - - constructor() { - this.children = Array(26); - this.cnt = 0; - } - - insert(w: string): void { - let node = this; - for (const c of w) { - const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); - if (!node.children[idx]) { - node.children[idx] = new Trie(); - } - node = node.children[idx]; - node.cnt++; - } - } - - search(w: string): number { - let node = this; - let ans = 0; - for (const c of w) { - const idx = c.charCodeAt(0) - 'a'.charCodeAt(0); - if (!node.children[idx]) { - return ans; - } - node = node.children[idx]; - ans += node.cnt; - } - return ans; - } -} - -function sumPrefixScores(words: string[]): number[] { - const trie = new Trie(); - for (const w of words) { - trie.insert(w); - } - let ans = []; - for (const w of words) { - ans.push(trie.search(w)); - } - return ans; -} diff --git a/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README.md b/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README.md index 445c9a76d3b3..4ab489e60e02 100644 --- a/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README.md +++ b/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README.md @@ -67,9 +67,9 @@ tags: ### 方法一:暴力枚举 -我们直接遍历数组 $\text{queries}$ 中的每个单词 $s$,再遍历数组 $\text{dictionary}$ 中的每个单词 $t$,如果存在一个单词 $t$ 与 $s$ 的编辑距离小于 $3$,则将 $s$ 加入答案数组中,然后退出内层循环的遍历。如果不存在这样的单词 $t$,则继续遍历下一个单词 $s$。 +我们直接遍历数组 $\textit{queries}$ 中的每个单词 $s$,再遍历数组 $\textit{dictionary}$ 中的每个单词 $t$,如果存在一个单词 $t$ 与 $s$ 的编辑距离小于 $3$,则将 $s$ 加入答案数组中,然后退出内层循环的遍历。如果不存在这样的单词 $t$,则继续遍历下一个单词 $s$。 -时间复杂度 $O(m \times n \times l)$,其中 $m$ 和 $n$ 分别是数组 $\text{queries}$ 和 $\text{dictionary}$ 的长度,而 $l$ 是单词的长度。 +时间复杂度 $O(m \times n \times l)$,其中 $m$ 和 $n$ 分别是数组 $\textit{queries}$ 和 $\textit{dictionary}$ 的长度,而 $l$ 是单词的长度。 diff --git a/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README_EN.md b/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README_EN.md index 7d08b933b83d..129e720d9db6 100644 --- a/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README_EN.md +++ b/solution/2400-2499/2452.Words Within Two Edits of Dictionary/README_EN.md @@ -66,9 +66,9 @@ Applying any two edits to "yes" cannot make it equal to "not" ### Solution 1: Brute Force Enumeration -We directly traverse each word $s$ in the array $\text{queries}$, and then traverse each word $t$ in the array $\text{dictionary}$. If there exists a word $t$ whose edit distance from $s$ is less than $3$, we add $s$ to the answer array and then exit the inner loop. If there is no such word $t$, we continue to traverse the next word $s$. +We directly traverse each word $s$ in the array $\textit{queries}$, and then traverse each word $t$ in the array $\textit{dictionary}$. If there exists a word $t$ whose edit distance from $s$ is less than $3$, we add $s$ to the answer array and then exit the inner loop. If there is no such word $t$, we continue to traverse the next word $s$. -The time complexity is $O(m \times n \times l)$, where $m$ and $n$ are the lengths of the arrays $\text{queries}$ and $\text{dictionary}$ respectively, and $l$ is the length of the word. +The time complexity is $O(m \times n \times l)$, where $m$ and $n$ are the lengths of the arrays $\textit{queries}$ and $\textit{dictionary}$ respectively, and $l$ is the length of the word. diff --git a/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README.md b/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README.md index 6b7769b4edb4..6c9b10368fd0 100644 --- a/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README.md +++ b/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README.md @@ -81,9 +81,9 @@ tags: 综上,可以得到: $$ -\text{ans} = \begin{cases} -n, & n \gt 1 \text{ 且 } n \text{ 为奇数} \\ -\frac{n}{2}, & n \text{ 为其它} \\ +\textit{ans} = \begin{cases} +n, & n \gt 1 \textit{ 且 } n \textit{ 为奇数} \\ +\frac{n}{2}, & n \textit{ 为其它} \\ \end{cases} $$ diff --git a/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README_EN.md b/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README_EN.md index d71da0ef5817..b715562f2429 100644 --- a/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README_EN.md +++ b/solution/2400-2499/2481.Minimum Cuts to Divide a Circle/README_EN.md @@ -73,9 +73,9 @@ Also note that the first cut will not divide the circle into distinct parts. In summary, we can get: $$ -\text{ans} = \begin{cases} -n, & n \gt 1 \text{ and } n \text{ is odd} \\ -\frac{n}{2}, & n \text{ is even} \\ +\textit{ans} = \begin{cases} +n, & n \gt 1 \textit{ and } n \textit{ is odd} \\ +\frac{n}{2}, & n \textit{ is even} \\ \end{cases} $$ diff --git a/solution/2500-2599/2518.Number of Great Partitions/README.md b/solution/2500-2599/2518.Number of Great Partitions/README.md index badaa2171d00..d2f2e12f1d83 100644 --- a/solution/2500-2599/2518.Number of Great Partitions/README.md +++ b/solution/2500-2599/2518.Number of Great Partitions/README.md @@ -80,8 +80,8 @@ tags: $$ f[i][j] = \left\{ \begin{aligned} -&f[i - 1][j] & \text{如果不选第 } i \text{ 个元素} \\ -&f[i - 1][j - nums[i - 1]] & \text{如果选第 } i \text{ 个元素} +&f[i - 1][j] & \textit{如果不选第 } i \textit{ 个元素} \\ +&f[i - 1][j - nums[i - 1]] & \textit{如果选第 } i \textit{ 个元素} \end{aligned} \right. $$ diff --git a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README.md b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README.md index 562650aeba64..a38fdaea70ed 100644 --- a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README.md +++ b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README.md @@ -70,13 +70,15 @@ tags: ### 方法一:计数 + 枚举 -我们先用两个长度为 $26$ 的数组分别统计字符串 $word1$ 和 $word2$ 中每个字母的出现次数,记为 $cnt1$ 和 $cnt2$。 +我们先用两个长度为 $26$ 的数组 $\textit{cnt1}$ 和 $\textit{cnt2}$ 分别记录字符串 $\textit{word1}$ 和 $\textit{word2}$ 中每个字符的出现次数。 -然后我们枚举 $cnt1$ 中的每个字母,接着枚举 $cnt2$ 中的每个字母,如果 $cnt1[i]$ 和 $cnt2[j]$ 都不为 $0$,那么我们就可以交换 $word1$ 中的第 $i$ 个字母和 $word2$ 中的第 $j$ 个字母。如果交换后 $word1$ 和 $word2$ 中不同字母的数目相等,那么就返回 `true`,否则,我们撤销此次交换,继续枚举。 +然后我们分别统计 $\textit{word1}$ 和 $\textit{word2}$ 中不同字符的个数,分别记为 $x$ 和 $y$。 -如果枚举完所有的字母对,仍然没有找到一种交换方式,那么就返回 `false`。 +接下来我们枚举 $\textit{word1}$ 中的每个字符 $c1$ 和 $\textit{word2}$ 中的每个字符 $c2$,如果 $c1 = c2$,那么我们只需要判断 $x$ 和 $y$ 是否相等;否则,我们需要判断 $x - (\textit{cnt1}[c1] = 1) + (\textit{cnt1}[c2] = 0)$ 和 $y - (\textit{cnt2}[c2] = 1) + (\textit{cnt2}[c1] = 0)$ 是否相等。如果相等,那么我们就找到了一种方案,返回 $\text{true}$。 -时间复杂度 $O(n + C^3)$,空间复杂度 $O(C)$,其中 $n$ 是字符串的长度,而 $C$ 是字符集的大小。本题中 $C = 26$。 +如果我们枚举完所有的字符都没有找到合适的方案,那么我们就返回 $\text{false}$。 + +时间复杂度 $O(m + n + |\Sigma|^2)$,其中 $m$ 和 $n$ 分别是字符串 $\textit{word1}$ 和 $\textit{word2}$ 的长度,而 $\Sigma$ 是字符集,本题中字符集为小写字母,所以 $|\Sigma| = 26$。 @@ -85,21 +87,19 @@ tags: ```python class Solution: def isItPossible(self, word1: str, word2: str) -> bool: - cnt1 = [0] * 26 - cnt2 = [0] * 26 - for c in word1: - cnt1[ord(c) - ord('a')] += 1 - for c in word2: - cnt2[ord(c) - ord('a')] += 1 - for i, a in enumerate(cnt1): - for j, b in enumerate(cnt2): - if a and b: - cnt1[i], cnt2[j] = cnt1[i] - 1, cnt2[j] - 1 - cnt1[j], cnt2[i] = cnt1[j] + 1, cnt2[i] + 1 - if sum(v > 0 for v in cnt1) == sum(v > 0 for v in cnt2): + cnt1 = Counter(word1) + cnt2 = Counter(word2) + x, y = len(cnt1), len(cnt2) + for c1, v1 in cnt1.items(): + for c2, v2 in cnt2.items(): + if c1 == c2: + if x == y: + return True + else: + a = x - (v1 == 1) + (cnt1[c2] == 0) + b = y - (v2 == 1) + (cnt2[c1] == 0) + if a == b: return True - cnt1[i], cnt2[j] = cnt1[i] + 1, cnt2[j] + 1 - cnt1[j], cnt2[i] = cnt1[j] - 1, cnt2[i] - 1 return False ``` @@ -110,35 +110,31 @@ class Solution { public boolean isItPossible(String word1, String word2) { int[] cnt1 = new int[26]; int[] cnt2 = new int[26]; + int x = 0, y = 0; for (int i = 0; i < word1.length(); ++i) { - ++cnt1[word1.charAt(i) - 'a']; + if (++cnt1[word1.charAt(i) - 'a'] == 1) { + ++x; + } } for (int i = 0; i < word2.length(); ++i) { - ++cnt2[word2.charAt(i) - 'a']; + if (++cnt2[word2.charAt(i) - 'a'] == 1) { + ++y; + } } for (int i = 0; i < 26; ++i) { for (int j = 0; j < 26; ++j) { if (cnt1[i] > 0 && cnt2[j] > 0) { - --cnt1[i]; - --cnt2[j]; - ++cnt1[j]; - ++cnt2[i]; - int d = 0; - for (int k = 0; k < 26; ++k) { - if (cnt1[k] > 0) { - ++d; + if (i == j) { + if (x == y) { + return true; } - if (cnt2[k] > 0) { - --d; + } else { + int a = x - (cnt1[i] == 1 ? 1 : 0) + (cnt1[j] == 0 ? 1 : 0); + int b = y - (cnt2[j] == 1 ? 1 : 0) + (cnt2[i] == 0 ? 1 : 0); + if (a == b) { + return true; } } - if (d == 0) { - return true; - } - ++cnt1[i]; - ++cnt2[j]; - --cnt1[j]; - --cnt2[i]; } } } @@ -155,35 +151,31 @@ public: bool isItPossible(string word1, string word2) { int cnt1[26]{}; int cnt2[26]{}; + int x = 0, y = 0; for (char& c : word1) { - ++cnt1[c - 'a']; + if (++cnt1[c - 'a'] == 1) { + ++x; + } } for (char& c : word2) { - ++cnt2[c - 'a']; + if (++cnt2[c - 'a'] == 1) { + ++y; + } } for (int i = 0; i < 26; ++i) { for (int j = 0; j < 26; ++j) { if (cnt1[i] > 0 && cnt2[j] > 0) { - --cnt1[i]; - --cnt2[j]; - ++cnt1[j]; - ++cnt2[i]; - int d = 0; - for (int k = 0; k < 26; ++k) { - if (cnt1[k] > 0) { - ++d; + if (i == j) { + if (x == y) { + return true; } - if (cnt2[k] > 0) { - --d; + } else { + int a = x - (cnt1[i] == 1 ? 1 : 0) + (cnt1[j] == 0 ? 1 : 0); + int b = y - (cnt2[j] == 1 ? 1 : 0) + (cnt2[i] == 0 ? 1 : 0); + if (a == b) { + return true; } } - if (d == 0) { - return true; - } - ++cnt1[i]; - ++cnt2[j]; - --cnt1[j]; - --cnt2[i]; } } } @@ -198,31 +190,47 @@ public: func isItPossible(word1 string, word2 string) bool { cnt1 := [26]int{} cnt2 := [26]int{} + x, y := 0, 0 for _, c := range word1 { cnt1[c-'a']++ + if cnt1[c-'a'] == 1 { + x++ + } } for _, c := range word2 { cnt2[c-'a']++ + if cnt2[c-'a'] == 1 { + y++ + } } for i := range cnt1 { for j := range cnt2 { if cnt1[i] > 0 && cnt2[j] > 0 { - cnt1[i], cnt2[j] = cnt1[i]-1, cnt2[j]-1 - cnt1[j], cnt2[i] = cnt1[j]+1, cnt2[i]+1 - d := 0 - for k, a := range cnt1 { - if a > 0 { - d++ + if i == j { + if x == y { + return true } - if cnt2[k] > 0 { - d-- + } else { + a := x + if cnt1[i] == 1 { + a-- + } + if cnt1[j] == 0 { + a++ + } + + b := y + if cnt2[j] == 1 { + b-- + } + if cnt2[i] == 0 { + b++ + } + + if a == b { + return true } } - if d == 0 { - return true - } - cnt1[i], cnt2[j] = cnt1[i]+1, cnt2[j]+1 - cnt1[j], cnt2[i] = cnt1[j]-1, cnt2[i]-1 } } } @@ -230,6 +238,48 @@ func isItPossible(word1 string, word2 string) bool { } ``` +#### TypeScript + +```ts +function isItPossible(word1: string, word2: string): boolean { + const cnt1: number[] = Array(26).fill(0); + const cnt2: number[] = Array(26).fill(0); + let [x, y] = [0, 0]; + + for (const c of word1) { + if (++cnt1[c.charCodeAt(0) - 'a'.charCodeAt(0)] === 1) { + ++x; + } + } + + for (const c of word2) { + if (++cnt2[c.charCodeAt(0) - 'a'.charCodeAt(0)] === 1) { + ++y; + } + } + + for (let i = 0; i < 26; ++i) { + for (let j = 0; j < 26; ++j) { + if (cnt1[i] > 0 && cnt2[j] > 0) { + if (i === j) { + if (x === y) { + return true; + } + } else { + const a = x - (cnt1[i] === 1 ? 1 : 0) + (cnt1[j] === 0 ? 1 : 0); + const b = y - (cnt2[j] === 1 ? 1 : 0) + (cnt2[i] === 0 ? 1 : 0); + if (a === b) { + return true; + } + } + } + } + } + + return false; +} +``` + diff --git a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README_EN.md b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README_EN.md index 9a1bb1fc3f55..2ab7bf03fb51 100644 --- a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README_EN.md +++ b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/README_EN.md @@ -65,7 +65,17 @@ tags: -### Solution 1 +### Solution 1: Counting + Enumeration + +We first use two arrays $\textit{cnt1}$ and $\textit{cnt2}$ of length $26$ to record the frequency of each character in the strings $\textit{word1}$ and $\textit{word2}$, respectively. + +Then, we count the number of distinct characters in $\textit{word1}$ and $\textit{word2}$, denoted as $x$ and $y$ respectively. + +Next, we enumerate each character $c1$ in $\textit{word1}$ and each character $c2$ in $\textit{word2}$. If $c1 = c2$, we only need to check if $x$ and $y$ are equal; otherwise, we need to check if $x - (\textit{cnt1}[c1] = 1) + (\textit{cnt1}[c2] = 0)$ and $y - (\textit{cnt2}[c2] = 1) + (\textit{cnt2}[c1] = 0)$ are equal. If they are equal, then we have found a solution and return $\text{true}$. + +If we have enumerated all characters and have not found a suitable solution, we return $\text{false}$. + +The time complexity is $O(m + n + |\Sigma|^2)$, where $m$ and $n$ are the lengths of the strings $\textit{word1}$ and $\textit{word2}$, and $\Sigma$ is the character set. In this problem, the character set consists of lowercase letters, so $|\Sigma| = 26$. @@ -74,21 +84,19 @@ tags: ```python class Solution: def isItPossible(self, word1: str, word2: str) -> bool: - cnt1 = [0] * 26 - cnt2 = [0] * 26 - for c in word1: - cnt1[ord(c) - ord('a')] += 1 - for c in word2: - cnt2[ord(c) - ord('a')] += 1 - for i, a in enumerate(cnt1): - for j, b in enumerate(cnt2): - if a and b: - cnt1[i], cnt2[j] = cnt1[i] - 1, cnt2[j] - 1 - cnt1[j], cnt2[i] = cnt1[j] + 1, cnt2[i] + 1 - if sum(v > 0 for v in cnt1) == sum(v > 0 for v in cnt2): + cnt1 = Counter(word1) + cnt2 = Counter(word2) + x, y = len(cnt1), len(cnt2) + for c1, v1 in cnt1.items(): + for c2, v2 in cnt2.items(): + if c1 == c2: + if x == y: + return True + else: + a = x - (v1 == 1) + (cnt1[c2] == 0) + b = y - (v2 == 1) + (cnt2[c1] == 0) + if a == b: return True - cnt1[i], cnt2[j] = cnt1[i] + 1, cnt2[j] + 1 - cnt1[j], cnt2[i] = cnt1[j] - 1, cnt2[i] - 1 return False ``` @@ -99,35 +107,31 @@ class Solution { public boolean isItPossible(String word1, String word2) { int[] cnt1 = new int[26]; int[] cnt2 = new int[26]; + int x = 0, y = 0; for (int i = 0; i < word1.length(); ++i) { - ++cnt1[word1.charAt(i) - 'a']; + if (++cnt1[word1.charAt(i) - 'a'] == 1) { + ++x; + } } for (int i = 0; i < word2.length(); ++i) { - ++cnt2[word2.charAt(i) - 'a']; + if (++cnt2[word2.charAt(i) - 'a'] == 1) { + ++y; + } } for (int i = 0; i < 26; ++i) { for (int j = 0; j < 26; ++j) { if (cnt1[i] > 0 && cnt2[j] > 0) { - --cnt1[i]; - --cnt2[j]; - ++cnt1[j]; - ++cnt2[i]; - int d = 0; - for (int k = 0; k < 26; ++k) { - if (cnt1[k] > 0) { - ++d; + if (i == j) { + if (x == y) { + return true; } - if (cnt2[k] > 0) { - --d; + } else { + int a = x - (cnt1[i] == 1 ? 1 : 0) + (cnt1[j] == 0 ? 1 : 0); + int b = y - (cnt2[j] == 1 ? 1 : 0) + (cnt2[i] == 0 ? 1 : 0); + if (a == b) { + return true; } } - if (d == 0) { - return true; - } - ++cnt1[i]; - ++cnt2[j]; - --cnt1[j]; - --cnt2[i]; } } } @@ -144,35 +148,31 @@ public: bool isItPossible(string word1, string word2) { int cnt1[26]{}; int cnt2[26]{}; + int x = 0, y = 0; for (char& c : word1) { - ++cnt1[c - 'a']; + if (++cnt1[c - 'a'] == 1) { + ++x; + } } for (char& c : word2) { - ++cnt2[c - 'a']; + if (++cnt2[c - 'a'] == 1) { + ++y; + } } for (int i = 0; i < 26; ++i) { for (int j = 0; j < 26; ++j) { if (cnt1[i] > 0 && cnt2[j] > 0) { - --cnt1[i]; - --cnt2[j]; - ++cnt1[j]; - ++cnt2[i]; - int d = 0; - for (int k = 0; k < 26; ++k) { - if (cnt1[k] > 0) { - ++d; + if (i == j) { + if (x == y) { + return true; } - if (cnt2[k] > 0) { - --d; + } else { + int a = x - (cnt1[i] == 1 ? 1 : 0) + (cnt1[j] == 0 ? 1 : 0); + int b = y - (cnt2[j] == 1 ? 1 : 0) + (cnt2[i] == 0 ? 1 : 0); + if (a == b) { + return true; } } - if (d == 0) { - return true; - } - ++cnt1[i]; - ++cnt2[j]; - --cnt1[j]; - --cnt2[i]; } } } @@ -187,31 +187,47 @@ public: func isItPossible(word1 string, word2 string) bool { cnt1 := [26]int{} cnt2 := [26]int{} + x, y := 0, 0 for _, c := range word1 { cnt1[c-'a']++ + if cnt1[c-'a'] == 1 { + x++ + } } for _, c := range word2 { cnt2[c-'a']++ + if cnt2[c-'a'] == 1 { + y++ + } } for i := range cnt1 { for j := range cnt2 { if cnt1[i] > 0 && cnt2[j] > 0 { - cnt1[i], cnt2[j] = cnt1[i]-1, cnt2[j]-1 - cnt1[j], cnt2[i] = cnt1[j]+1, cnt2[i]+1 - d := 0 - for k, a := range cnt1 { - if a > 0 { - d++ + if i == j { + if x == y { + return true } - if cnt2[k] > 0 { - d-- + } else { + a := x + if cnt1[i] == 1 { + a-- + } + if cnt1[j] == 0 { + a++ + } + + b := y + if cnt2[j] == 1 { + b-- + } + if cnt2[i] == 0 { + b++ + } + + if a == b { + return true } } - if d == 0 { - return true - } - cnt1[i], cnt2[j] = cnt1[i]+1, cnt2[j]+1 - cnt1[j], cnt2[i] = cnt1[j]-1, cnt2[i]-1 } } } @@ -219,6 +235,48 @@ func isItPossible(word1 string, word2 string) bool { } ``` +#### TypeScript + +```ts +function isItPossible(word1: string, word2: string): boolean { + const cnt1: number[] = Array(26).fill(0); + const cnt2: number[] = Array(26).fill(0); + let [x, y] = [0, 0]; + + for (const c of word1) { + if (++cnt1[c.charCodeAt(0) - 'a'.charCodeAt(0)] === 1) { + ++x; + } + } + + for (const c of word2) { + if (++cnt2[c.charCodeAt(0) - 'a'.charCodeAt(0)] === 1) { + ++y; + } + } + + for (let i = 0; i < 26; ++i) { + for (let j = 0; j < 26; ++j) { + if (cnt1[i] > 0 && cnt2[j] > 0) { + if (i === j) { + if (x === y) { + return true; + } + } else { + const a = x - (cnt1[i] === 1 ? 1 : 0) + (cnt1[j] === 0 ? 1 : 0); + const b = y - (cnt2[j] === 1 ? 1 : 0) + (cnt2[i] === 0 ? 1 : 0); + if (a === b) { + return true; + } + } + } + } + } + + return false; +} +``` + diff --git a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.cpp b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.cpp index b309ff49b9c9..dc00fc6f1685 100644 --- a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.cpp +++ b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.cpp @@ -3,35 +3,31 @@ class Solution { bool isItPossible(string word1, string word2) { int cnt1[26]{}; int cnt2[26]{}; + int x = 0, y = 0; for (char& c : word1) { - ++cnt1[c - 'a']; + if (++cnt1[c - 'a'] == 1) { + ++x; + } } for (char& c : word2) { - ++cnt2[c - 'a']; + if (++cnt2[c - 'a'] == 1) { + ++y; + } } for (int i = 0; i < 26; ++i) { for (int j = 0; j < 26; ++j) { if (cnt1[i] > 0 && cnt2[j] > 0) { - --cnt1[i]; - --cnt2[j]; - ++cnt1[j]; - ++cnt2[i]; - int d = 0; - for (int k = 0; k < 26; ++k) { - if (cnt1[k] > 0) { - ++d; + if (i == j) { + if (x == y) { + return true; } - if (cnt2[k] > 0) { - --d; + } else { + int a = x - (cnt1[i] == 1 ? 1 : 0) + (cnt1[j] == 0 ? 1 : 0); + int b = y - (cnt2[j] == 1 ? 1 : 0) + (cnt2[i] == 0 ? 1 : 0); + if (a == b) { + return true; } } - if (d == 0) { - return true; - } - ++cnt1[i]; - ++cnt2[j]; - --cnt1[j]; - --cnt2[i]; } } } diff --git a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.go b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.go index 06c7beb3201b..30ce21c70eaa 100644 --- a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.go +++ b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.go @@ -1,31 +1,47 @@ func isItPossible(word1 string, word2 string) bool { cnt1 := [26]int{} cnt2 := [26]int{} + x, y := 0, 0 for _, c := range word1 { cnt1[c-'a']++ + if cnt1[c-'a'] == 1 { + x++ + } } for _, c := range word2 { cnt2[c-'a']++ + if cnt2[c-'a'] == 1 { + y++ + } } for i := range cnt1 { for j := range cnt2 { if cnt1[i] > 0 && cnt2[j] > 0 { - cnt1[i], cnt2[j] = cnt1[i]-1, cnt2[j]-1 - cnt1[j], cnt2[i] = cnt1[j]+1, cnt2[i]+1 - d := 0 - for k, a := range cnt1 { - if a > 0 { - d++ + if i == j { + if x == y { + return true } - if cnt2[k] > 0 { - d-- + } else { + a := x + if cnt1[i] == 1 { + a-- + } + if cnt1[j] == 0 { + a++ + } + + b := y + if cnt2[j] == 1 { + b-- + } + if cnt2[i] == 0 { + b++ + } + + if a == b { + return true } } - if d == 0 { - return true - } - cnt1[i], cnt2[j] = cnt1[i]+1, cnt2[j]+1 - cnt1[j], cnt2[i] = cnt1[j]-1, cnt2[i]-1 } } } diff --git a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.java b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.java index 1d94b88e3e93..1f994d523444 100644 --- a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.java +++ b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.java @@ -2,35 +2,31 @@ class Solution { public boolean isItPossible(String word1, String word2) { int[] cnt1 = new int[26]; int[] cnt2 = new int[26]; + int x = 0, y = 0; for (int i = 0; i < word1.length(); ++i) { - ++cnt1[word1.charAt(i) - 'a']; + if (++cnt1[word1.charAt(i) - 'a'] == 1) { + ++x; + } } for (int i = 0; i < word2.length(); ++i) { - ++cnt2[word2.charAt(i) - 'a']; + if (++cnt2[word2.charAt(i) - 'a'] == 1) { + ++y; + } } for (int i = 0; i < 26; ++i) { for (int j = 0; j < 26; ++j) { if (cnt1[i] > 0 && cnt2[j] > 0) { - --cnt1[i]; - --cnt2[j]; - ++cnt1[j]; - ++cnt2[i]; - int d = 0; - for (int k = 0; k < 26; ++k) { - if (cnt1[k] > 0) { - ++d; + if (i == j) { + if (x == y) { + return true; } - if (cnt2[k] > 0) { - --d; + } else { + int a = x - (cnt1[i] == 1 ? 1 : 0) + (cnt1[j] == 0 ? 1 : 0); + int b = y - (cnt2[j] == 1 ? 1 : 0) + (cnt2[i] == 0 ? 1 : 0); + if (a == b) { + return true; } } - if (d == 0) { - return true; - } - ++cnt1[i]; - ++cnt2[j]; - --cnt1[j]; - --cnt2[i]; } } } diff --git a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.py b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.py index bc82518581c3..e4df0cbf5175 100644 --- a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.py +++ b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.py @@ -1,18 +1,16 @@ class Solution: def isItPossible(self, word1: str, word2: str) -> bool: - cnt1 = [0] * 26 - cnt2 = [0] * 26 - for c in word1: - cnt1[ord(c) - ord('a')] += 1 - for c in word2: - cnt2[ord(c) - ord('a')] += 1 - for i, a in enumerate(cnt1): - for j, b in enumerate(cnt2): - if a and b: - cnt1[i], cnt2[j] = cnt1[i] - 1, cnt2[j] - 1 - cnt1[j], cnt2[i] = cnt1[j] + 1, cnt2[i] + 1 - if sum(v > 0 for v in cnt1) == sum(v > 0 for v in cnt2): + cnt1 = Counter(word1) + cnt2 = Counter(word2) + x, y = len(cnt1), len(cnt2) + for c1, v1 in cnt1.items(): + for c2, v2 in cnt2.items(): + if c1 == c2: + if x == y: + return True + else: + a = x - (v1 == 1) + (cnt1[c2] == 0) + b = y - (v2 == 1) + (cnt2[c1] == 0) + if a == b: return True - cnt1[i], cnt2[j] = cnt1[i] + 1, cnt2[j] + 1 - cnt1[j], cnt2[i] = cnt1[j] - 1, cnt2[i] - 1 return False diff --git a/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.ts b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.ts new file mode 100644 index 000000000000..f88b74a61e25 --- /dev/null +++ b/solution/2500-2599/2531.Make Number of Distinct Characters Equal/Solution.ts @@ -0,0 +1,37 @@ +function isItPossible(word1: string, word2: string): boolean { + const cnt1: number[] = Array(26).fill(0); + const cnt2: number[] = Array(26).fill(0); + let [x, y] = [0, 0]; + + for (const c of word1) { + if (++cnt1[c.charCodeAt(0) - 'a'.charCodeAt(0)] === 1) { + ++x; + } + } + + for (const c of word2) { + if (++cnt2[c.charCodeAt(0) - 'a'.charCodeAt(0)] === 1) { + ++y; + } + } + + for (let i = 0; i < 26; ++i) { + for (let j = 0; j < 26; ++j) { + if (cnt1[i] > 0 && cnt2[j] > 0) { + if (i === j) { + if (x === y) { + return true; + } + } else { + const a = x - (cnt1[i] === 1 ? 1 : 0) + (cnt1[j] === 0 ? 1 : 0); + const b = y - (cnt2[j] === 1 ? 1 : 0) + (cnt2[i] === 0 ? 1 : 0); + if (a === b) { + return true; + } + } + } + } + } + + return false; +} diff --git a/solution/2500-2599/2581.Count Number of Possible Root Nodes/README.md b/solution/2500-2599/2581.Count Number of Possible Root Nodes/README.md index 1d847a9b9b80..28dbc7e14f8e 100644 --- a/solution/2500-2599/2581.Count Number of Possible Root Nodes/README.md +++ b/solution/2500-2599/2581.Count Number of Possible Root Nodes/README.md @@ -7,6 +7,7 @@ source: 第 99 场双周赛 Q4 tags: - 树 - 深度优先搜索 + - 数组 - 哈希表 - 动态规划 --- diff --git a/solution/2500-2599/2581.Count Number of Possible Root Nodes/README_EN.md b/solution/2500-2599/2581.Count Number of Possible Root Nodes/README_EN.md index 233efe70d307..b3534e82768d 100644 --- a/solution/2500-2599/2581.Count Number of Possible Root Nodes/README_EN.md +++ b/solution/2500-2599/2581.Count Number of Possible Root Nodes/README_EN.md @@ -7,6 +7,7 @@ source: Biweekly Contest 99 Q4 tags: - Tree - Depth-First Search + - Array - Hash Table - Dynamic Programming --- diff --git a/solution/2500-2599/2597.The Number of Beautiful Subsets/README.md b/solution/2500-2599/2597.The Number of Beautiful Subsets/README.md index 5eb293e05828..5d2ddbf2c5da 100644 --- a/solution/2500-2599/2597.The Number of Beautiful Subsets/README.md +++ b/solution/2500-2599/2597.The Number of Beautiful Subsets/README.md @@ -6,8 +6,11 @@ rating: 2023 source: 第 337 场周赛 Q3 tags: - 数组 + - 哈希表 + - 数学 - 动态规划 - 回溯 + - 组合数学 - 排序 --- diff --git a/solution/2500-2599/2597.The Number of Beautiful Subsets/README_EN.md b/solution/2500-2599/2597.The Number of Beautiful Subsets/README_EN.md index 174bbcb250cf..e16e0924eea2 100644 --- a/solution/2500-2599/2597.The Number of Beautiful Subsets/README_EN.md +++ b/solution/2500-2599/2597.The Number of Beautiful Subsets/README_EN.md @@ -6,8 +6,11 @@ rating: 2023 source: Weekly Contest 337 Q3 tags: - Array + - Hash Table + - Math - Dynamic Programming - Backtracking + - Combinatorics - Sorting --- diff --git a/solution/2600-2699/2618.Check if Object Instance of Class/README.md b/solution/2600-2699/2618.Check if Object Instance of Class/README.md index 4010fa0ef3f6..65676d420fd2 100644 --- a/solution/2600-2699/2618.Check if Object Instance of Class/README.md +++ b/solution/2600-2699/2618.Check if Object Instance of Class/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2618.Check%20if%20Object%20Instance%20of%20Class/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2618.Check if Object Instance of Class/README_EN.md b/solution/2600-2699/2618.Check if Object Instance of Class/README_EN.md index 5158ed9c07ae..4cfec4dc7f06 100644 --- a/solution/2600-2699/2618.Check if Object Instance of Class/README_EN.md +++ b/solution/2600-2699/2618.Check if Object Instance of Class/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2618.Check%20if%20Object%20Instance%20of%20Class/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2619.Array Prototype Last/README.md b/solution/2600-2699/2619.Array Prototype Last/README.md index ca0b9cdb7fa5..3a8cba617042 100644 --- a/solution/2600-2699/2619.Array Prototype Last/README.md +++ b/solution/2600-2699/2619.Array Prototype Last/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2619.Array%20Prototype%20Last/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2619.Array Prototype Last/README_EN.md b/solution/2600-2699/2619.Array Prototype Last/README_EN.md index f031997d092e..373432678041 100644 --- a/solution/2600-2699/2619.Array Prototype Last/README_EN.md +++ b/solution/2600-2699/2619.Array Prototype Last/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2619.Array%20Prototype%20Last/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2620.Counter/README.md b/solution/2600-2699/2620.Counter/README.md index 8e48a33cc6a4..b25ea70cbe7d 100644 --- a/solution/2600-2699/2620.Counter/README.md +++ b/solution/2600-2699/2620.Counter/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2620.Counter/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2620.Counter/README_EN.md b/solution/2600-2699/2620.Counter/README_EN.md index 480792a04ffc..ba99baba0876 100644 --- a/solution/2600-2699/2620.Counter/README_EN.md +++ b/solution/2600-2699/2620.Counter/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2620.Counter/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2621.Sleep/README.md b/solution/2600-2699/2621.Sleep/README.md index 2607dfdc0a1d..88f995e11453 100644 --- a/solution/2600-2699/2621.Sleep/README.md +++ b/solution/2600-2699/2621.Sleep/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2621.Sleep/README.md +tags: + - JavaScript --- @@ -70,6 +72,23 @@ async function sleep(millis: number): Promise { */ ``` +#### JavaScript + +```js +/** + * @param {number} millis + * @return {Promise} + */ +async function sleep(millis) { + return new Promise(r => setTimeout(r, millis)); +} + +/** + * let t = Date.now() + * sleep(100).then(() => console.log(Date.now() - t)) // 100 + */ +``` + diff --git a/solution/2600-2699/2621.Sleep/README_EN.md b/solution/2600-2699/2621.Sleep/README_EN.md index 4d33630e3513..e90b69edc9ba 100644 --- a/solution/2600-2699/2621.Sleep/README_EN.md +++ b/solution/2600-2699/2621.Sleep/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2621.Sleep/README_EN.md +tags: + - JavaScript --- @@ -67,6 +69,23 @@ async function sleep(millis: number): Promise { */ ``` +#### JavaScript + +```js +/** + * @param {number} millis + * @return {Promise} + */ +async function sleep(millis) { + return new Promise(r => setTimeout(r, millis)); +} + +/** + * let t = Date.now() + * sleep(100).then(() => console.log(Date.now() - t)) // 100 + */ +``` + diff --git a/solution/2600-2699/2621.Sleep/Solution.js b/solution/2600-2699/2621.Sleep/Solution.js new file mode 100644 index 000000000000..91bd9ae81b5a --- /dev/null +++ b/solution/2600-2699/2621.Sleep/Solution.js @@ -0,0 +1,12 @@ +/** + * @param {number} millis + * @return {Promise} + */ +async function sleep(millis) { + return new Promise(r => setTimeout(r, millis)); +} + +/** + * let t = Date.now() + * sleep(100).then(() => console.log(Date.now() - t)) // 100 + */ diff --git a/solution/2600-2699/2622.Cache With Time Limit/README.md b/solution/2600-2699/2622.Cache With Time Limit/README.md index 8e82c507e892..9a7827f8bbf0 100644 --- a/solution/2600-2699/2622.Cache With Time Limit/README.md +++ b/solution/2600-2699/2622.Cache With Time Limit/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2622.Cache%20With%20Time%20Limit/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2622.Cache With Time Limit/README_EN.md b/solution/2600-2699/2622.Cache With Time Limit/README_EN.md index d45502ca5671..db9da4463e5f 100644 --- a/solution/2600-2699/2622.Cache With Time Limit/README_EN.md +++ b/solution/2600-2699/2622.Cache With Time Limit/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2622.Cache%20With%20Time%20Limit/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2623.Memoize/README.md b/solution/2600-2699/2623.Memoize/README.md index c63c0f4f9d24..1c6d49e34f7d 100644 --- a/solution/2600-2699/2623.Memoize/README.md +++ b/solution/2600-2699/2623.Memoize/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2623.Memoize/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2623.Memoize/README_EN.md b/solution/2600-2699/2623.Memoize/README_EN.md index b5650216d740..9362ae300fbf 100644 --- a/solution/2600-2699/2623.Memoize/README_EN.md +++ b/solution/2600-2699/2623.Memoize/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2623.Memoize/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2624.Snail Traversal/README.md b/solution/2600-2699/2624.Snail Traversal/README.md index 1b9165b67bc0..01b426c24c92 100644 --- a/solution/2600-2699/2624.Snail Traversal/README.md +++ b/solution/2600-2699/2624.Snail Traversal/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2624.Snail%20Traversal/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2624.Snail Traversal/README_EN.md b/solution/2600-2699/2624.Snail Traversal/README_EN.md index dd5ce9780343..f294e8578723 100644 --- a/solution/2600-2699/2624.Snail Traversal/README_EN.md +++ b/solution/2600-2699/2624.Snail Traversal/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2624.Snail%20Traversal/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2625.Flatten Deeply Nested Array/README.md b/solution/2600-2699/2625.Flatten Deeply Nested Array/README.md index 58614620dda1..4adbade14276 100644 --- a/solution/2600-2699/2625.Flatten Deeply Nested Array/README.md +++ b/solution/2600-2699/2625.Flatten Deeply Nested Array/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2625.Flatten%20Deeply%20Nested%20Array/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2625.Flatten Deeply Nested Array/README_EN.md b/solution/2600-2699/2625.Flatten Deeply Nested Array/README_EN.md index fb0fee5f4726..b255894ca8d4 100644 --- a/solution/2600-2699/2625.Flatten Deeply Nested Array/README_EN.md +++ b/solution/2600-2699/2625.Flatten Deeply Nested Array/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2625.Flatten%20Deeply%20Nested%20Array/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2626.Array Reduce Transformation/README.md b/solution/2600-2699/2626.Array Reduce Transformation/README.md index 2b657d046471..f47dd920e3f5 100644 --- a/solution/2600-2699/2626.Array Reduce Transformation/README.md +++ b/solution/2600-2699/2626.Array Reduce Transformation/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2626.Array%20Reduce%20Transformation/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2626.Array Reduce Transformation/README_EN.md b/solution/2600-2699/2626.Array Reduce Transformation/README_EN.md index 2a90977ebc78..27f8a1d18cf3 100644 --- a/solution/2600-2699/2626.Array Reduce Transformation/README_EN.md +++ b/solution/2600-2699/2626.Array Reduce Transformation/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2626.Array%20Reduce%20Transformation/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2627.Debounce/README.md b/solution/2600-2699/2627.Debounce/README.md index 8dc2581327e8..2c10bc5bea9f 100644 --- a/solution/2600-2699/2627.Debounce/README.md +++ b/solution/2600-2699/2627.Debounce/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2627.Debounce/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2627.Debounce/README_EN.md b/solution/2600-2699/2627.Debounce/README_EN.md index 53b0386323bb..b919eaffadc0 100644 --- a/solution/2600-2699/2627.Debounce/README_EN.md +++ b/solution/2600-2699/2627.Debounce/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2627.Debounce/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2628.JSON Deep Equal/README.md b/solution/2600-2699/2628.JSON Deep Equal/README.md index 4dd1baac9ac6..116b15bd49aa 100644 --- a/solution/2600-2699/2628.JSON Deep Equal/README.md +++ b/solution/2600-2699/2628.JSON Deep Equal/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2628.JSON%20Deep%20Equal/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2628.JSON Deep Equal/README_EN.md b/solution/2600-2699/2628.JSON Deep Equal/README_EN.md index caf60f00660d..b12036f9625b 100644 --- a/solution/2600-2699/2628.JSON Deep Equal/README_EN.md +++ b/solution/2600-2699/2628.JSON Deep Equal/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2628.JSON%20Deep%20Equal/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2629.Function Composition/README.md b/solution/2600-2699/2629.Function Composition/README.md index 59c74ccaaef6..bfd4d51827b5 100644 --- a/solution/2600-2699/2629.Function Composition/README.md +++ b/solution/2600-2699/2629.Function Composition/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2629.Function%20Composition/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2629.Function Composition/README_EN.md b/solution/2600-2699/2629.Function Composition/README_EN.md index 81c0019bdd40..0160c912c89e 100644 --- a/solution/2600-2699/2629.Function Composition/README_EN.md +++ b/solution/2600-2699/2629.Function Composition/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2629.Function%20Composition/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2630.Memoize II/README.md b/solution/2600-2699/2630.Memoize II/README.md index 3cc90235199f..00265c59c2cc 100644 --- a/solution/2600-2699/2630.Memoize II/README.md +++ b/solution/2600-2699/2630.Memoize II/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2630.Memoize%20II/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2630.Memoize II/README_EN.md b/solution/2600-2699/2630.Memoize II/README_EN.md index 07cccacc86e9..207733a8bab5 100644 --- a/solution/2600-2699/2630.Memoize II/README_EN.md +++ b/solution/2600-2699/2630.Memoize II/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2630.Memoize%20II/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2631.Group By/README.md b/solution/2600-2699/2631.Group By/README.md index 0abb58a8c60f..3c5e539ed4be 100644 --- a/solution/2600-2699/2631.Group By/README.md +++ b/solution/2600-2699/2631.Group By/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2631.Group%20By/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2631.Group By/README_EN.md b/solution/2600-2699/2631.Group By/README_EN.md index beb0325d01fd..6e7b2d8ff58f 100644 --- a/solution/2600-2699/2631.Group By/README_EN.md +++ b/solution/2600-2699/2631.Group By/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2631.Group%20By/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2632.Curry/README.md b/solution/2600-2699/2632.Curry/README.md index 1f5132254043..74963be01d17 100644 --- a/solution/2600-2699/2632.Curry/README.md +++ b/solution/2600-2699/2632.Curry/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2632.Curry/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2632.Curry/README_EN.md b/solution/2600-2699/2632.Curry/README_EN.md index 6a4cad22f3a5..33f0c95cb1fb 100644 --- a/solution/2600-2699/2632.Curry/README_EN.md +++ b/solution/2600-2699/2632.Curry/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2632.Curry/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2633.Convert Object to JSON String/README.md b/solution/2600-2699/2633.Convert Object to JSON String/README.md index 1b767f038976..210e00ccf57b 100644 --- a/solution/2600-2699/2633.Convert Object to JSON String/README.md +++ b/solution/2600-2699/2633.Convert Object to JSON String/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2633.Convert%20Object%20to%20JSON%20String/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2633.Convert Object to JSON String/README_EN.md b/solution/2600-2699/2633.Convert Object to JSON String/README_EN.md index 32d350c81c52..a864ff8f9541 100644 --- a/solution/2600-2699/2633.Convert Object to JSON String/README_EN.md +++ b/solution/2600-2699/2633.Convert Object to JSON String/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2633.Convert%20Object%20to%20JSON%20String/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2634.Filter Elements from Array/README.md b/solution/2600-2699/2634.Filter Elements from Array/README.md index a518f356f96b..ea27ac99451f 100644 --- a/solution/2600-2699/2634.Filter Elements from Array/README.md +++ b/solution/2600-2699/2634.Filter Elements from Array/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2634.Filter%20Elements%20from%20Array/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2634.Filter Elements from Array/README_EN.md b/solution/2600-2699/2634.Filter Elements from Array/README_EN.md index 2550be75e4d9..097565619cb6 100644 --- a/solution/2600-2699/2634.Filter Elements from Array/README_EN.md +++ b/solution/2600-2699/2634.Filter Elements from Array/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2634.Filter%20Elements%20from%20Array/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README.md b/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README.md index 75d7169cd14d..0ba2d1da822c 100644 --- a/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README.md +++ b/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2635.Apply%20Transform%20Over%20Each%20Element%20in%20Array/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README_EN.md b/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README_EN.md index 281605339a33..db792a0eb7e5 100644 --- a/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README_EN.md +++ b/solution/2600-2699/2635.Apply Transform Over Each Element in Array/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2635.Apply%20Transform%20Over%20Each%20Element%20in%20Array/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2636.Promise Pool/README.md b/solution/2600-2699/2636.Promise Pool/README.md index 83a4bbd5bd06..898388a15eea 100644 --- a/solution/2600-2699/2636.Promise Pool/README.md +++ b/solution/2600-2699/2636.Promise Pool/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2636.Promise%20Pool/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2636.Promise Pool/README_EN.md b/solution/2600-2699/2636.Promise Pool/README_EN.md index 02ad36332fba..36c831d7a8b5 100644 --- a/solution/2600-2699/2636.Promise Pool/README_EN.md +++ b/solution/2600-2699/2636.Promise Pool/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2636.Promise%20Pool/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2637.Promise Time Limit/README.md b/solution/2600-2699/2637.Promise Time Limit/README.md index df62ccc21b98..af945c10a5cb 100644 --- a/solution/2600-2699/2637.Promise Time Limit/README.md +++ b/solution/2600-2699/2637.Promise Time Limit/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2637.Promise%20Time%20Limit/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2637.Promise Time Limit/README_EN.md b/solution/2600-2699/2637.Promise Time Limit/README_EN.md index 8b863db922d0..7ca4eac739ce 100644 --- a/solution/2600-2699/2637.Promise Time Limit/README_EN.md +++ b/solution/2600-2699/2637.Promise Time Limit/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2637.Promise%20Time%20Limit/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2638.Count the Number of K-Free Subsets/README.md b/solution/2600-2699/2638.Count the Number of K-Free Subsets/README.md index 05e5117c7c9b..4d62f577b7dd 100644 --- a/solution/2600-2699/2638.Count the Number of K-Free Subsets/README.md +++ b/solution/2600-2699/2638.Count the Number of K-Free Subsets/README.md @@ -4,7 +4,9 @@ difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2638.Count%20the%20Number%20of%20K-Free%20Subsets/README.md tags: - 数组 + - 数学 - 动态规划 + - 组合数学 - 排序 --- diff --git a/solution/2600-2699/2638.Count the Number of K-Free Subsets/README_EN.md b/solution/2600-2699/2638.Count the Number of K-Free Subsets/README_EN.md index 99e97811a4dd..745c83ab6a21 100644 --- a/solution/2600-2699/2638.Count the Number of K-Free Subsets/README_EN.md +++ b/solution/2600-2699/2638.Count the Number of K-Free Subsets/README_EN.md @@ -4,7 +4,9 @@ difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2638.Count%20the%20Number%20of%20K-Free%20Subsets/README_EN.md tags: - Array + - Math - Dynamic Programming + - Combinatorics - Sorting --- diff --git a/solution/2600-2699/2648.Generate Fibonacci Sequence/README.md b/solution/2600-2699/2648.Generate Fibonacci Sequence/README.md index af8f1ab392ec..ff2162967d02 100644 --- a/solution/2600-2699/2648.Generate Fibonacci Sequence/README.md +++ b/solution/2600-2699/2648.Generate Fibonacci Sequence/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2648.Generate%20Fibonacci%20Sequence/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2648.Generate Fibonacci Sequence/README_EN.md b/solution/2600-2699/2648.Generate Fibonacci Sequence/README_EN.md index 0e0f9604ef33..48a12877e23b 100644 --- a/solution/2600-2699/2648.Generate Fibonacci Sequence/README_EN.md +++ b/solution/2600-2699/2648.Generate Fibonacci Sequence/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2648.Generate%20Fibonacci%20Sequence/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2649.Nested Array Generator/README.md b/solution/2600-2699/2649.Nested Array Generator/README.md index 2d2fed70cb75..fa5260b4ddb8 100644 --- a/solution/2600-2699/2649.Nested Array Generator/README.md +++ b/solution/2600-2699/2649.Nested Array Generator/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2649.Nested%20Array%20Generator/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2649.Nested Array Generator/README_EN.md b/solution/2600-2699/2649.Nested Array Generator/README_EN.md index 6a4cb1cf6641..63f2a3cb2119 100644 --- a/solution/2600-2699/2649.Nested Array Generator/README_EN.md +++ b/solution/2600-2699/2649.Nested Array Generator/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2649.Nested%20Array%20Generator/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2650.Design Cancellable Function/README.md b/solution/2600-2699/2650.Design Cancellable Function/README.md index cb6daeff1e14..40c12a6f6d44 100644 --- a/solution/2600-2699/2650.Design Cancellable Function/README.md +++ b/solution/2600-2699/2650.Design Cancellable Function/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2650.Design%20Cancellable%20Function/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2650.Design Cancellable Function/README_EN.md b/solution/2600-2699/2650.Design Cancellable Function/README_EN.md index 38464a395127..7096b6774fce 100644 --- a/solution/2600-2699/2650.Design Cancellable Function/README_EN.md +++ b/solution/2600-2699/2650.Design Cancellable Function/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2650.Design%20Cancellable%20Function/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2665.Counter II/README.md b/solution/2600-2699/2665.Counter II/README.md index 246494a7183c..a18684863cef 100644 --- a/solution/2600-2699/2665.Counter II/README.md +++ b/solution/2600-2699/2665.Counter II/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2665.Counter%20II/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2665.Counter II/README_EN.md b/solution/2600-2699/2665.Counter II/README_EN.md index aa013e790a85..05fe6a7f1e9c 100644 --- a/solution/2600-2699/2665.Counter II/README_EN.md +++ b/solution/2600-2699/2665.Counter II/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2665.Counter%20II/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2666.Allow One Function Call/README.md b/solution/2600-2699/2666.Allow One Function Call/README.md index 4f4a3e6c685e..9839fb8d772d 100644 --- a/solution/2600-2699/2666.Allow One Function Call/README.md +++ b/solution/2600-2699/2666.Allow One Function Call/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2666.Allow%20One%20Function%20Call/README.md +tags: + - JavaScript --- @@ -70,9 +72,10 @@ onceFn(4, 6, 8); // undefined, fn 没有被调用 #### TypeScript ```ts -function once any>( - fn: T, -): (...args: Parameters) => ReturnType | undefined { +type JSONValue = null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue }; +type OnceFn = (...args: JSONValue[]) => JSONValue | undefined; + +function once(fn: Function): OnceFn { let called = false; return function (...args) { if (!called) { @@ -91,6 +94,32 @@ function once any>( */ ``` +#### JavaScript + +```js +/** + * @param {Function} fn + * @return {Function} + */ +var once = function (fn) { + let called = false; + return function (...args) { + if (!called) { + called = true; + return fn(...args); + } + }; +}; + +/** + * let fn = (a,b,c) => (a + b + c) + * let onceFn = once(fn) + * + * onceFn(1,2,3); // 6 + * onceFn(2,3,6); // returns undefined without calling fn + */ +``` + diff --git a/solution/2600-2699/2666.Allow One Function Call/README_EN.md b/solution/2600-2699/2666.Allow One Function Call/README_EN.md index 540b24580e47..85c014f464e8 100644 --- a/solution/2600-2699/2666.Allow One Function Call/README_EN.md +++ b/solution/2600-2699/2666.Allow One Function Call/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2666.Allow%20One%20Function%20Call/README_EN.md +tags: + - JavaScript --- @@ -68,9 +70,10 @@ onceFn(4, 6, 8); // undefined, fn was not called #### TypeScript ```ts -function once any>( - fn: T, -): (...args: Parameters) => ReturnType | undefined { +type JSONValue = null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue }; +type OnceFn = (...args: JSONValue[]) => JSONValue | undefined; + +function once(fn: Function): OnceFn { let called = false; return function (...args) { if (!called) { @@ -89,6 +92,32 @@ function once any>( */ ``` +#### JavaScript + +```js +/** + * @param {Function} fn + * @return {Function} + */ +var once = function (fn) { + let called = false; + return function (...args) { + if (!called) { + called = true; + return fn(...args); + } + }; +}; + +/** + * let fn = (a,b,c) => (a + b + c) + * let onceFn = once(fn) + * + * onceFn(1,2,3); // 6 + * onceFn(2,3,6); // returns undefined without calling fn + */ +``` + diff --git a/solution/2600-2699/2666.Allow One Function Call/Solution.js b/solution/2600-2699/2666.Allow One Function Call/Solution.js new file mode 100644 index 000000000000..a0f9bec40a3f --- /dev/null +++ b/solution/2600-2699/2666.Allow One Function Call/Solution.js @@ -0,0 +1,21 @@ +/** + * @param {Function} fn + * @return {Function} + */ +var once = function (fn) { + let called = false; + return function (...args) { + if (!called) { + called = true; + return fn(...args); + } + }; +}; + +/** + * let fn = (a,b,c) => (a + b + c) + * let onceFn = once(fn) + * + * onceFn(1,2,3); // 6 + * onceFn(2,3,6); // returns undefined without calling fn + */ diff --git a/solution/2600-2699/2666.Allow One Function Call/Solution.ts b/solution/2600-2699/2666.Allow One Function Call/Solution.ts index 958ae80a932d..af5db873190d 100644 --- a/solution/2600-2699/2666.Allow One Function Call/Solution.ts +++ b/solution/2600-2699/2666.Allow One Function Call/Solution.ts @@ -1,6 +1,7 @@ -function once any>( - fn: T, -): (...args: Parameters) => ReturnType | undefined { +type JSONValue = null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue }; +type OnceFn = (...args: JSONValue[]) => JSONValue | undefined; + +function once(fn: Function): OnceFn { let called = false; return function (...args) { if (!called) { diff --git a/solution/2600-2699/2667.Create Hello World Function/README.md b/solution/2600-2699/2667.Create Hello World Function/README.md index a207569bbf76..b20883c2a8f1 100644 --- a/solution/2600-2699/2667.Create Hello World Function/README.md +++ b/solution/2600-2699/2667.Create Hello World Function/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2667.Create%20Hello%20World%20Function/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2667.Create Hello World Function/README_EN.md b/solution/2600-2699/2667.Create Hello World Function/README_EN.md index fba21f6b7d30..dcaa7bc28e67 100644 --- a/solution/2600-2699/2667.Create Hello World Function/README_EN.md +++ b/solution/2600-2699/2667.Create Hello World Function/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2667.Create%20Hello%20World%20Function/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2675.Array of Objects to Matrix/README.md b/solution/2600-2699/2675.Array of Objects to Matrix/README.md index 61e698afc686..6ba4bea80cdc 100644 --- a/solution/2600-2699/2675.Array of Objects to Matrix/README.md +++ b/solution/2600-2699/2675.Array of Objects to Matrix/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2675.Array%20of%20Objects%20to%20Matrix/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2675.Array of Objects to Matrix/README_EN.md b/solution/2600-2699/2675.Array of Objects to Matrix/README_EN.md index 605cdc2c77fc..9d11b2ab02a5 100644 --- a/solution/2600-2699/2675.Array of Objects to Matrix/README_EN.md +++ b/solution/2600-2699/2675.Array of Objects to Matrix/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2675.Array%20of%20Objects%20to%20Matrix/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2676.Throttle/README.md b/solution/2600-2699/2676.Throttle/README.md index 270f5e6af358..d64755a78db9 100644 --- a/solution/2600-2699/2676.Throttle/README.md +++ b/solution/2600-2699/2676.Throttle/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2676.Throttle/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2676.Throttle/README_EN.md b/solution/2600-2699/2676.Throttle/README_EN.md index f27e1be70378..878b7b0a57b1 100644 --- a/solution/2600-2699/2676.Throttle/README_EN.md +++ b/solution/2600-2699/2676.Throttle/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2676.Throttle/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2677.Chunk Array/README.md b/solution/2600-2699/2677.Chunk Array/README.md index ef96c795d514..48aa928491c1 100644 --- a/solution/2600-2699/2677.Chunk Array/README.md +++ b/solution/2600-2699/2677.Chunk Array/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2677.Chunk%20Array/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2677.Chunk Array/README_EN.md b/solution/2600-2699/2677.Chunk Array/README_EN.md index a4742655ba88..ec56ca8fe736 100644 --- a/solution/2600-2699/2677.Chunk Array/README_EN.md +++ b/solution/2600-2699/2677.Chunk Array/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2677.Chunk%20Array/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2685.Count the Number of Complete Components/README.md b/solution/2600-2699/2685.Count the Number of Complete Components/README.md index 523f109cef19..893eaa679360 100644 --- a/solution/2600-2699/2685.Count the Number of Complete Components/README.md +++ b/solution/2600-2699/2685.Count the Number of Complete Components/README.md @@ -234,4 +234,61 @@ func countCompleteComponents(n int, edges [][]int) (ans int) { + + +### 方法二:取巧做法 + +要解决的问题: + +1. 如何保存每一个节点与其它点联通状态 +2. 如何判断多个点是否是一个联通图 + +对于第一点:实际上就是保存了当前到每个点的联通点集合(包括自己),方便后续判等。 +第二点:有了第一点之后,如果是连通图中的点就有: + +1. 此点包含此联通图中所有的点(包括自己) +2. 并且只包含此联通图中的点 + +拿示例一举例: + +- 5 包含的联通点有且只有自己,所以是连通图 +- 0 包含 0、1、2,同理 1、2 点也是 +- 3 和 4 也是包含自己和彼此 +- 基于以上就有以下代码实现: + + + +#### C++ + +```cpp +class Solution { +public: + int countCompleteComponents(int n, vector>& edges) { + int ans = 0; + vector> m(n + 1, set()); + for (int i = 0; i < n; i++) { + m[i].insert(i); + } + for (auto x : edges) { + m[x[0]].insert(x[1]); + m[x[1]].insert(x[0]); + } + map, int> s; + for (int i = 0; i < n; i++) { + s[m[i]]++; + } + for (auto& [x, y] : s) { + if (y == x.size()) { + ans++; + } + } + return ans; + } +}; +``` + + + + + diff --git a/solution/2600-2699/2685.Count the Number of Complete Components/README_EN.md b/solution/2600-2699/2685.Count the Number of Complete Components/README_EN.md index fb6077f89507..0332511b3815 100644 --- a/solution/2600-2699/2685.Count the Number of Complete Components/README_EN.md +++ b/solution/2600-2699/2685.Count the Number of Complete Components/README_EN.md @@ -222,4 +222,61 @@ func countCompleteComponents(n int, edges [][]int) (ans int) { + + +### Solution 2: Simple Method + +Problems needed to solve: + +1. How do we maintain the link state between each node and the others? 如 +2. How can one determine whether multiple points form a connected graph? + +For the first one: we can maintain each node's connection set(including itself). + +For the second one: After solving the first one, we can see: + +- the node itself includes every node in the connected graph(including itself). +- and only connected to the nodes in the connected graph. + +Take example 1 to explain: + +- Node 5's connected node is itself, so it is a connected graph. +- Node 0's connected 0, 1, 2. Same as nodes 1, 2. +- Nodes 3 and 4 also include themselves and each other. + + + +#### C++ + +```cpp +class Solution { +public: + int countCompleteComponents(int n, vector>& edges) { + int ans = 0; + vector> m(n + 1, set()); + for (int i = 0; i < n; i++) { + m[i].insert(i); + } + for (auto x : edges) { + m[x[0]].insert(x[1]); + m[x[1]].insert(x[0]); + } + map, int> s; + for (int i = 0; i < n; i++) { + s[m[i]]++; + } + for (auto& [x, y] : s) { + if (y == x.size()) { + ans++; + } + } + return ans; + } +}; +``` + + + + + diff --git a/solution/2600-2699/2685.Count the Number of Complete Components/Solution2.cpp b/solution/2600-2699/2685.Count the Number of Complete Components/Solution2.cpp new file mode 100644 index 000000000000..8e0c02591947 --- /dev/null +++ b/solution/2600-2699/2685.Count the Number of Complete Components/Solution2.cpp @@ -0,0 +1,24 @@ +class Solution { +public: + int countCompleteComponents(int n, vector>& edges) { + int ans = 0; + vector> m(n + 1, set()); + for (int i = 0; i < n; i++) { + m[i].insert(i); + } + for (auto x : edges) { + m[x[0]].insert(x[1]); + m[x[1]].insert(x[0]); + } + map, int> s; + for (int i = 0; i < n; i++) { + s[m[i]]++; + } + for (auto& [x, y] : s) { + if (y == x.size()) { + ans++; + } + } + return ans; + } +}; diff --git a/solution/2600-2699/2690.Infinite Method Object/README.md b/solution/2600-2699/2690.Infinite Method Object/README.md index e28269c1c932..0d0f7243a441 100644 --- a/solution/2600-2699/2690.Infinite Method Object/README.md +++ b/solution/2600-2699/2690.Infinite Method Object/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2690.Infinite%20Method%20Object/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2690.Infinite Method Object/README_EN.md b/solution/2600-2699/2690.Infinite Method Object/README_EN.md index e0f6c08fbe8a..180d7ca3569f 100644 --- a/solution/2600-2699/2690.Infinite Method Object/README_EN.md +++ b/solution/2600-2699/2690.Infinite Method Object/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2690.Infinite%20Method%20Object/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2691.Immutability Helper/README.md b/solution/2600-2699/2691.Immutability Helper/README.md index 664293f6c1f4..272564d361c1 100644 --- a/solution/2600-2699/2691.Immutability Helper/README.md +++ b/solution/2600-2699/2691.Immutability Helper/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2691.Immutability%20Helper/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2691.Immutability Helper/README_EN.md b/solution/2600-2699/2691.Immutability Helper/README_EN.md index bd8f48beb53e..8bd539e665b4 100644 --- a/solution/2600-2699/2691.Immutability Helper/README_EN.md +++ b/solution/2600-2699/2691.Immutability Helper/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2691.Immutability%20Helper/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2692.Make Object Immutable/README.md b/solution/2600-2699/2692.Make Object Immutable/README.md index a6d0287a165c..5a7ca5779009 100644 --- a/solution/2600-2699/2692.Make Object Immutable/README.md +++ b/solution/2600-2699/2692.Make Object Immutable/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2692.Make%20Object%20Immutable/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2692.Make Object Immutable/README_EN.md b/solution/2600-2699/2692.Make Object Immutable/README_EN.md index a367e0d1a25f..fdf12be28e4c 100644 --- a/solution/2600-2699/2692.Make Object Immutable/README_EN.md +++ b/solution/2600-2699/2692.Make Object Immutable/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2692.Make%20Object%20Immutable/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2693.Call Function with Custom Context/README.md b/solution/2600-2699/2693.Call Function with Custom Context/README.md index c5578a9994a2..b1b51a2d87ad 100644 --- a/solution/2600-2699/2693.Call Function with Custom Context/README.md +++ b/solution/2600-2699/2693.Call Function with Custom Context/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2693.Call%20Function%20with%20Custom%20Context/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2693.Call Function with Custom Context/README_EN.md b/solution/2600-2699/2693.Call Function with Custom Context/README_EN.md index 81db4dfc947b..f1cb25d366db 100644 --- a/solution/2600-2699/2693.Call Function with Custom Context/README_EN.md +++ b/solution/2600-2699/2693.Call Function with Custom Context/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2693.Call%20Function%20with%20Custom%20Context/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2694.Event Emitter/README.md b/solution/2600-2699/2694.Event Emitter/README.md index 02b6a605e7bd..c21976f360c4 100644 --- a/solution/2600-2699/2694.Event Emitter/README.md +++ b/solution/2600-2699/2694.Event Emitter/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2694.Event%20Emitter/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2694.Event Emitter/README_EN.md b/solution/2600-2699/2694.Event Emitter/README_EN.md index 7fd188f6e212..e7c28c1bf15b 100644 --- a/solution/2600-2699/2694.Event Emitter/README_EN.md +++ b/solution/2600-2699/2694.Event Emitter/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2694.Event%20Emitter/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2695.Array Wrapper/README.md b/solution/2600-2699/2695.Array Wrapper/README.md index 0e49aaf1bf7e..0a6a052a5091 100644 --- a/solution/2600-2699/2695.Array Wrapper/README.md +++ b/solution/2600-2699/2695.Array Wrapper/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2695.Array%20Wrapper/README.md +tags: + - JavaScript --- diff --git a/solution/2600-2699/2695.Array Wrapper/README_EN.md b/solution/2600-2699/2695.Array Wrapper/README_EN.md index 504182dfacf7..f0f22c682c92 100644 --- a/solution/2600-2699/2695.Array Wrapper/README_EN.md +++ b/solution/2600-2699/2695.Array Wrapper/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2600-2699/2695.Array%20Wrapper/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2700.Differences Between Two Objects/README.md b/solution/2700-2799/2700.Differences Between Two Objects/README.md index e90695d816ea..3cd5166bb23d 100644 --- a/solution/2700-2799/2700.Differences Between Two Objects/README.md +++ b/solution/2700-2799/2700.Differences Between Two Objects/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2700.Differences%20Between%20Two%20Objects/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2700.Differences Between Two Objects/README_EN.md b/solution/2700-2799/2700.Differences Between Two Objects/README_EN.md index f59bf738997e..c534ca533f29 100644 --- a/solution/2700-2799/2700.Differences Between Two Objects/README_EN.md +++ b/solution/2700-2799/2700.Differences Between Two Objects/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2700.Differences%20Between%20Two%20Objects/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2703.Return Length of Arguments Passed/README.md b/solution/2700-2799/2703.Return Length of Arguments Passed/README.md index a6453c056230..b5ba38f9e014 100644 --- a/solution/2700-2799/2703.Return Length of Arguments Passed/README.md +++ b/solution/2700-2799/2703.Return Length of Arguments Passed/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2703.Return%20Length%20of%20Arguments%20Passed/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2703.Return Length of Arguments Passed/README_EN.md b/solution/2700-2799/2703.Return Length of Arguments Passed/README_EN.md index 3796664da488..f067cdbbbe75 100644 --- a/solution/2700-2799/2703.Return Length of Arguments Passed/README_EN.md +++ b/solution/2700-2799/2703.Return Length of Arguments Passed/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2703.Return%20Length%20of%20Arguments%20Passed/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2704.To Be Or Not To Be/README.md b/solution/2700-2799/2704.To Be Or Not To Be/README.md index 9915e3bab6c6..9ac0e880f76f 100644 --- a/solution/2700-2799/2704.To Be Or Not To Be/README.md +++ b/solution/2700-2799/2704.To Be Or Not To Be/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2704.To%20Be%20Or%20Not%20To%20Be/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2704.To Be Or Not To Be/README_EN.md b/solution/2700-2799/2704.To Be Or Not To Be/README_EN.md index 58d778f9104a..b6aca190b49b 100644 --- a/solution/2700-2799/2704.To Be Or Not To Be/README_EN.md +++ b/solution/2700-2799/2704.To Be Or Not To Be/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2704.To%20Be%20Or%20Not%20To%20Be/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2705.Compact Object/README.md b/solution/2700-2799/2705.Compact Object/README.md index b367915c2e75..6987fe28decd 100644 --- a/solution/2700-2799/2705.Compact Object/README.md +++ b/solution/2700-2799/2705.Compact Object/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2705.Compact%20Object/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2705.Compact Object/README_EN.md b/solution/2700-2799/2705.Compact Object/README_EN.md index 746b47f13110..05de9e12eb11 100644 --- a/solution/2700-2799/2705.Compact Object/README_EN.md +++ b/solution/2700-2799/2705.Compact Object/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2705.Compact%20Object/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README.md b/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README.md index 156ce91fde6a..9ceb53f29ed7 100644 --- a/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README.md +++ b/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README.md @@ -88,7 +88,7 @@ tags: 在这个过程中,我们可以维护两个数组 `rowMax` 和 `colMax`,分别记录每一行和每一列的最大递增长度。初始时,这两个数组的所有元素都为 $0$。 -对于每个值对应的所有单元格位置,我们按照位置顺序遍历,对于每个位置 $(i, j)$,我们可以计算出以该位置为终点的最大递增长度为 $1 + \max(\text{rowMax}[i], \text{colMax}[j])$,更新答案,然后更新 `rowMax[i]` 和 `colMax[j]`。 +对于每个值对应的所有单元格位置,我们按照位置顺序遍历,对于每个位置 $(i, j)$,我们可以计算出以该位置为终点的最大递增长度为 $1 + \max(\textit{rowMax}[i], \textit{colMax}[j])$,更新答案,然后更新 `rowMax[i]` 和 `colMax[j]`。 最后返回答案即可。 diff --git a/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README_EN.md b/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README_EN.md index 00a2665eeb8f..dd24f265ea7f 100644 --- a/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README_EN.md +++ b/solution/2700-2799/2713.Maximum Strictly Increasing Cells in a Matrix/README_EN.md @@ -87,7 +87,7 @@ Based on the problem description, the value of the cells we move through in sequ During this process, we can maintain two arrays `rowMax` and `colMax`, which record the maximum increasing length of each row and column, respectively. Initially, all elements of these two arrays are $0$. -For all cell positions corresponding to each value, we traverse them in order of position. For each position $(i, j)$, we can calculate the maximum increasing length ending at that position as $1 + \max(\text{rowMax}[i], \text{colMax}[j])$, update the answer, and then update `rowMax[i]` and `colMax[j]`. +For all cell positions corresponding to each value, we traverse them in order of position. For each position $(i, j)$, we can calculate the maximum increasing length ending at that position as $1 + \max(\textit{rowMax}[i], \textit{colMax}[j])$, update the answer, and then update `rowMax[i]` and `colMax[j]`. Finally, return the answer. diff --git a/solution/2700-2799/2715.Timeout Cancellation/README.md b/solution/2700-2799/2715.Timeout Cancellation/README.md index b3089e631804..cb4c31d8b51b 100644 --- a/solution/2700-2799/2715.Timeout Cancellation/README.md +++ b/solution/2700-2799/2715.Timeout Cancellation/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2715.Timeout%20Cancellation/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2715.Timeout Cancellation/README_EN.md b/solution/2700-2799/2715.Timeout Cancellation/README_EN.md index c6fc2ea36366..15363e2955c7 100644 --- a/solution/2700-2799/2715.Timeout Cancellation/README_EN.md +++ b/solution/2700-2799/2715.Timeout Cancellation/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2715.Timeout%20Cancellation/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README.md b/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README.md index b034bae7bbbc..c0d03de79098 100644 --- a/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README.md +++ b/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2721.Execute%20Asynchronous%20Functions%20in%20Parallel/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README_EN.md b/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README_EN.md index 9176a300b945..a97cbb8814f6 100644 --- a/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README_EN.md +++ b/solution/2700-2799/2721.Execute Asynchronous Functions in Parallel/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2721.Execute%20Asynchronous%20Functions%20in%20Parallel/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2722.Join Two Arrays by ID/README.md b/solution/2700-2799/2722.Join Two Arrays by ID/README.md index c4495ab866e7..d8daec5ae35f 100644 --- a/solution/2700-2799/2722.Join Two Arrays by ID/README.md +++ b/solution/2700-2799/2722.Join Two Arrays by ID/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2722.Join%20Two%20Arrays%20by%20ID/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2722.Join Two Arrays by ID/README_EN.md b/solution/2700-2799/2722.Join Two Arrays by ID/README_EN.md index 7bb80d8d6435..7668d78a61e7 100644 --- a/solution/2700-2799/2722.Join Two Arrays by ID/README_EN.md +++ b/solution/2700-2799/2722.Join Two Arrays by ID/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2722.Join%20Two%20Arrays%20by%20ID/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2723.Add Two Promises/README.md b/solution/2700-2799/2723.Add Two Promises/README.md index a32454416e03..d44069ef82f9 100644 --- a/solution/2700-2799/2723.Add Two Promises/README.md +++ b/solution/2700-2799/2723.Add Two Promises/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2723.Add%20Two%20Promises/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2723.Add Two Promises/README_EN.md b/solution/2700-2799/2723.Add Two Promises/README_EN.md index f9f845f1d75a..153e34cb361f 100644 --- a/solution/2700-2799/2723.Add Two Promises/README_EN.md +++ b/solution/2700-2799/2723.Add Two Promises/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2723.Add%20Two%20Promises/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2724.Sort By/README.md b/solution/2700-2799/2724.Sort By/README.md index 868065d394a5..66628b6b2c7e 100644 --- a/solution/2700-2799/2724.Sort By/README.md +++ b/solution/2700-2799/2724.Sort By/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2724.Sort%20By/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2724.Sort By/README_EN.md b/solution/2700-2799/2724.Sort By/README_EN.md index 13cf9d441a89..f466c2a21c5d 100644 --- a/solution/2700-2799/2724.Sort By/README_EN.md +++ b/solution/2700-2799/2724.Sort By/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2724.Sort%20By/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2725.Interval Cancellation/README.md b/solution/2700-2799/2725.Interval Cancellation/README.md index 6e1d331c850e..be00a38c6a5b 100644 --- a/solution/2700-2799/2725.Interval Cancellation/README.md +++ b/solution/2700-2799/2725.Interval Cancellation/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2725.Interval%20Cancellation/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2725.Interval Cancellation/README_EN.md b/solution/2700-2799/2725.Interval Cancellation/README_EN.md index 8659ea454371..3a169ee99ad3 100644 --- a/solution/2700-2799/2725.Interval Cancellation/README_EN.md +++ b/solution/2700-2799/2725.Interval Cancellation/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2725.Interval%20Cancellation/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2726.Calculator with Method Chaining/README.md b/solution/2700-2799/2726.Calculator with Method Chaining/README.md index db2d35206cff..0ef3a20113f0 100644 --- a/solution/2700-2799/2726.Calculator with Method Chaining/README.md +++ b/solution/2700-2799/2726.Calculator with Method Chaining/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2726.Calculator%20with%20Method%20Chaining/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2726.Calculator with Method Chaining/README_EN.md b/solution/2700-2799/2726.Calculator with Method Chaining/README_EN.md index 730be544e838..3a7e66745552 100644 --- a/solution/2700-2799/2726.Calculator with Method Chaining/README_EN.md +++ b/solution/2700-2799/2726.Calculator with Method Chaining/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2726.Calculator%20with%20Method%20Chaining/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2727.Is Object Empty/README.md b/solution/2700-2799/2727.Is Object Empty/README.md index 224c733fd60c..ecf6a8279d57 100644 --- a/solution/2700-2799/2727.Is Object Empty/README.md +++ b/solution/2700-2799/2727.Is Object Empty/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2727.Is%20Object%20Empty/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2727.Is Object Empty/README_EN.md b/solution/2700-2799/2727.Is Object Empty/README_EN.md index 7e97ee20a30f..336b222e1f1e 100644 --- a/solution/2700-2799/2727.Is Object Empty/README_EN.md +++ b/solution/2700-2799/2727.Is Object Empty/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2727.Is%20Object%20Empty/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README.md b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README.md index b3ac96e7b960..ef91e6305fee 100644 --- a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README.md +++ b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README.md @@ -182,4 +182,109 @@ function longestSemiRepetitiveSubstring(s: string): number { + + +### 方法二:双指针(优化) + +由于题目只需要我们找到最长的半重复子字符串的长度,因此,每次当区间内相邻字符相等的个数超过 $1$ 时,我们可以只移动左指针 $l$ 一次,右指针 $r$ 继续向右移动。这样可以保证子字符串的长度不会减小。 + +最后答案为 $n - l$,其中 $n$ 是字符串的长度。 + +时间复杂度 $O(n)$,其中 $n$ 是字符串的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def longestSemiRepetitiveSubstring(self, s: str) -> int: + n = len(s) + cnt = l = 0 + for i in range(1, n): + cnt += s[i] == s[i - 1] + if cnt > 1: + cnt -= s[l] == s[l + 1] + l += 1 + return n - l +``` + +#### Java + +```java +class Solution { + public int longestSemiRepetitiveSubstring(String s) { + int n = s.length(); + int cnt = 0, l = 0; + for (int i = 1; i < n; ++i) { + cnt += s.charAt(i) == s.charAt(i - 1) ? 1 : 0; + if (cnt > 1) { + cnt -= s.charAt(l) == s.charAt(++l) ? 1 : 0; + } + } + return n - l; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int longestSemiRepetitiveSubstring(string s) { + int n = s.length(); + int cnt = 0, l = 0; + for (int i = 1; i < n; ++i) { + cnt += s[i] == s[i - 1] ? 1 : 0; + if (cnt > 1) { + cnt -= s[l] == s[++l] ? 1 : 0; + } + } + return n - l; + } +}; +``` + +#### Go + +```go +func longestSemiRepetitiveSubstring(s string) (ans int) { + cnt, l := 0, 0 + for i, c := range s[1:] { + if byte(c) == s[i] { + cnt++ + } + if cnt > 1 { + if s[l] == s[l+1] { + cnt-- + } + l++ + } + } + return len(s) - l +} +``` + +#### TypeScript + +```ts +function longestSemiRepetitiveSubstring(s: string): number { + const n = s.length; + let [cnt, l] = [0, 0]; + for (let i = 1; i < n; ++i) { + cnt += s[i] === s[i - 1] ? 1 : 0; + if (cnt > 1) { + cnt -= s[l] === s[l + 1] ? 1 : 0; + ++l; + } + } + return n - l; +} +``` + + + + + diff --git a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README_EN.md b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README_EN.md index da8ad2a201bc..0374324861d9 100644 --- a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README_EN.md +++ b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/README_EN.md @@ -180,4 +180,109 @@ function longestSemiRepetitiveSubstring(s: string): number { + + +### Solution 2: Two Pointers (Optimization) + +Since the problem only requires us to find the length of the longest semi-repetitive substring, each time the number of adjacent identical characters in the interval exceeds $1$, we can move the left pointer $l$ once, while the right pointer $r$ continues to move to the right. This ensures that the length of the substring does not decrease. + +Finally, the answer is $n - l$, where $n$ is the length of the string. + +The time complexity is $O(n)$, where $n$ is the length of the string. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def longestSemiRepetitiveSubstring(self, s: str) -> int: + n = len(s) + cnt = l = 0 + for i in range(1, n): + cnt += s[i] == s[i - 1] + if cnt > 1: + cnt -= s[l] == s[l + 1] + l += 1 + return n - l +``` + +#### Java + +```java +class Solution { + public int longestSemiRepetitiveSubstring(String s) { + int n = s.length(); + int cnt = 0, l = 0; + for (int i = 1; i < n; ++i) { + cnt += s.charAt(i) == s.charAt(i - 1) ? 1 : 0; + if (cnt > 1) { + cnt -= s.charAt(l) == s.charAt(++l) ? 1 : 0; + } + } + return n - l; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int longestSemiRepetitiveSubstring(string s) { + int n = s.length(); + int cnt = 0, l = 0; + for (int i = 1; i < n; ++i) { + cnt += s[i] == s[i - 1] ? 1 : 0; + if (cnt > 1) { + cnt -= s[l] == s[++l] ? 1 : 0; + } + } + return n - l; + } +}; +``` + +#### Go + +```go +func longestSemiRepetitiveSubstring(s string) (ans int) { + cnt, l := 0, 0 + for i, c := range s[1:] { + if byte(c) == s[i] { + cnt++ + } + if cnt > 1 { + if s[l] == s[l+1] { + cnt-- + } + l++ + } + } + return len(s) - l +} +``` + +#### TypeScript + +```ts +function longestSemiRepetitiveSubstring(s: string): number { + const n = s.length; + let [cnt, l] = [0, 0]; + for (let i = 1; i < n; ++i) { + cnt += s[i] === s[i - 1] ? 1 : 0; + if (cnt > 1) { + cnt -= s[l] === s[l + 1] ? 1 : 0; + ++l; + } + } + return n - l; +} +``` + + + + + diff --git a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.cpp b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.cpp new file mode 100644 index 000000000000..f5495ccd0a02 --- /dev/null +++ b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + int longestSemiRepetitiveSubstring(string s) { + int n = s.length(); + int cnt = 0, l = 0; + for (int i = 1; i < n; ++i) { + cnt += s[i] == s[i - 1] ? 1 : 0; + if (cnt > 1) { + cnt -= s[l] == s[++l] ? 1 : 0; + } + } + return n - l; + } +}; \ No newline at end of file diff --git a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.go b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.go new file mode 100644 index 000000000000..97a8f174e8ad --- /dev/null +++ b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.go @@ -0,0 +1,15 @@ +func longestSemiRepetitiveSubstring(s string) (ans int) { + cnt, l := 0, 0 + for i, c := range s[1:] { + if byte(c) == s[i] { + cnt++ + } + if cnt > 1 { + if s[l] == s[l+1] { + cnt-- + } + l++ + } + } + return len(s) - l +} \ No newline at end of file diff --git a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.java b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.java new file mode 100644 index 000000000000..5d5d1132c358 --- /dev/null +++ b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.java @@ -0,0 +1,13 @@ +class Solution { + public int longestSemiRepetitiveSubstring(String s) { + int n = s.length(); + int cnt = 0, l = 0; + for (int i = 1; i < n; ++i) { + cnt += s.charAt(i) == s.charAt(i - 1) ? 1 : 0; + if (cnt > 1) { + cnt -= s.charAt(l) == s.charAt(++l) ? 1 : 0; + } + } + return n - l; + } +} \ No newline at end of file diff --git a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.py b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.py new file mode 100644 index 000000000000..b9d9050f85cc --- /dev/null +++ b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.py @@ -0,0 +1,10 @@ +class Solution: + def longestSemiRepetitiveSubstring(self, s: str) -> int: + n = len(s) + cnt = l = 0 + for i in range(1, n): + cnt += s[i] == s[i - 1] + if cnt > 1: + cnt -= s[l] == s[l + 1] + l += 1 + return n - l diff --git a/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.ts b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.ts new file mode 100644 index 000000000000..0ddf01458958 --- /dev/null +++ b/solution/2700-2799/2730.Find the Longest Semi-Repetitive Substring/Solution2.ts @@ -0,0 +1,12 @@ +function longestSemiRepetitiveSubstring(s: string): number { + const n = s.length; + let [cnt, l] = [0, 0]; + for (let i = 1; i < n; ++i) { + cnt += s[i] === s[i - 1] ? 1 : 0; + if (cnt > 1) { + cnt -= s[l] === s[l + 1] ? 1 : 0; + ++l; + } + } + return n - l; +} diff --git a/solution/2700-2799/2740.Find the Value of the Partition/README.md b/solution/2700-2799/2740.Find the Value of the Partition/README.md index d3d5ea2c6139..6983f98b48e5 100644 --- a/solution/2700-2799/2740.Find the Value of the Partition/README.md +++ b/solution/2700-2799/2740.Find the Value of the Partition/README.md @@ -135,6 +135,34 @@ func findValueOfPartition(nums []int) int { } ``` +#### TypeScript + +```ts +function findValueOfPartition(nums: number[]): number { + nums.sort((a, b) => a - b); + let ans = Infinity; + for (let i = 1; i < nums.length; ++i) { + ans = Math.min(ans, Math.abs(nums[i] - nums[i - 1])); + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn find_value_of_partition(mut nums: Vec) -> i32 { + nums.sort(); + let mut ans = i32::MAX; + for i in 1..nums.len() { + ans = ans.min(nums[i] - nums[i - 1]); + } + ans + } +} +``` + diff --git a/solution/2700-2799/2740.Find the Value of the Partition/README_EN.md b/solution/2700-2799/2740.Find the Value of the Partition/README_EN.md index 141c414f9431..d7e4ae811c8b 100644 --- a/solution/2700-2799/2740.Find the Value of the Partition/README_EN.md +++ b/solution/2700-2799/2740.Find the Value of the Partition/README_EN.md @@ -135,6 +135,34 @@ func findValueOfPartition(nums []int) int { } ``` +#### TypeScript + +```ts +function findValueOfPartition(nums: number[]): number { + nums.sort((a, b) => a - b); + let ans = Infinity; + for (let i = 1; i < nums.length; ++i) { + ans = Math.min(ans, Math.abs(nums[i] - nums[i - 1])); + } + return ans; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn find_value_of_partition(mut nums: Vec) -> i32 { + nums.sort(); + let mut ans = i32::MAX; + for i in 1..nums.len() { + ans = ans.min(nums[i] - nums[i - 1]); + } + ans + } +} +``` + diff --git a/solution/2700-2799/2740.Find the Value of the Partition/Solution.rs b/solution/2700-2799/2740.Find the Value of the Partition/Solution.rs new file mode 100644 index 000000000000..ce1a3d37c83a --- /dev/null +++ b/solution/2700-2799/2740.Find the Value of the Partition/Solution.rs @@ -0,0 +1,10 @@ +impl Solution { + pub fn find_value_of_partition(mut nums: Vec) -> i32 { + nums.sort(); + let mut ans = i32::MAX; + for i in 1..nums.len() { + ans = ans.min(nums[i] - nums[i - 1]); + } + ans + } +} diff --git a/solution/2700-2799/2740.Find the Value of the Partition/Solution.ts b/solution/2700-2799/2740.Find the Value of the Partition/Solution.ts new file mode 100644 index 000000000000..c52ecffffa6e --- /dev/null +++ b/solution/2700-2799/2740.Find the Value of the Partition/Solution.ts @@ -0,0 +1,8 @@ +function findValueOfPartition(nums: number[]): number { + nums.sort((a, b) => a - b); + let ans = Infinity; + for (let i = 1; i < nums.length; ++i) { + ans = Math.min(ans, Math.abs(nums[i] - nums[i - 1])); + } + return ans; +} diff --git a/solution/2700-2799/2741.Special Permutations/README.md b/solution/2700-2799/2741.Special Permutations/README.md index 0ece2b854703..37965fd979f2 100644 --- a/solution/2700-2799/2741.Special Permutations/README.md +++ b/solution/2700-2799/2741.Special Permutations/README.md @@ -72,7 +72,7 @@ $$ f[i][j]= \begin{cases} 1, & i=2^j\\ -\sum_{k=0}^{n-1}f[i \oplus 2^j][k], & i \neq 2^j \text{且} \text{nums}[j] \text{与} \text{nums}[k] \text{满足题目要求}\\ +\sum_{k=0}^{n-1}f[i \oplus 2^j][k], & i \neq 2^j \textit{且} \textit{nums}[j] \textit{与} \textit{nums}[k] \textit{满足题目要求}\\ \end{cases} $$ diff --git a/solution/2700-2799/2741.Special Permutations/README_EN.md b/solution/2700-2799/2741.Special Permutations/README_EN.md index daa009047eec..4e28f9ab8191 100644 --- a/solution/2700-2799/2741.Special Permutations/README_EN.md +++ b/solution/2700-2799/2741.Special Permutations/README_EN.md @@ -72,7 +72,7 @@ $$ f[i][j]= \begin{cases} 1, & i=2^j\\ -\sum_{k=0}^{n-1}f[i \oplus 2^j][k], & i \neq 2^j \text{ and nums}[j] \text{ and nums}[k] \text{ meet the requirements of the problem}\\ +\sum_{k=0}^{n-1}f[i \oplus 2^j][k], & i \neq 2^j \textit{ and nums}[j] \textit{ and nums}[k] \textit{ meet the requirements of the problem}\\ \end{cases} $$ diff --git a/solution/2700-2799/2747.Count Zero Request Servers/README.md b/solution/2700-2799/2747.Count Zero Request Servers/README.md index 4620843d987c..9bbe13024789 100644 --- a/solution/2700-2799/2747.Count Zero Request Servers/README.md +++ b/solution/2700-2799/2747.Count Zero Request Servers/README.md @@ -78,7 +78,7 @@ tags: 对于每个查询 $q = (r, i)$,其窗口左边界为 $l = r - x$,我们需要统计在窗口 $[l, r]$ 内有多少个服务器收到了请求。我们用双指针 $j$ 和 $k$ 分别维护窗口的左右边界,初始时 $j = k = 0$。每一次,如果 $k$ 指向的日志的时间小于等于 $r$,我们就将其加入到窗口中,然后将 $k$ 向右移动一位。如果 $j$ 指向的日志的时间小于 $l$,我们就将其从窗口中移除,然后将 $j$ 向右移动一位。在移动的过程中,我们需要统计窗口中有多少个不同的服务器,这可以使用哈希表来实现。移动结束后,当前时间区间中没有收到请求的服务器数目就是 $n$ 减去哈希表中不同的服务器数目。 -时间复杂度 $O(l \times \log l + m \times \log m + n)$,空间复杂度 $O(l + m)$。其中 $l$ 和 $n$ 分别是数组 $\text{logs}$ 的长度和服务器的数量,而 $m$ 是数组 $\text{queries}$ 的长度。 +时间复杂度 $O(l \times \log l + m \times \log m + n)$,空间复杂度 $O(l + m)$。其中 $l$ 和 $n$ 分别是数组 $\textit{logs}$ 的长度和服务器的数量,而 $m$ 是数组 $\textit{queries}$ 的长度。 diff --git a/solution/2700-2799/2747.Count Zero Request Servers/README_EN.md b/solution/2700-2799/2747.Count Zero Request Servers/README_EN.md index 1c6a234423f9..86c17b3d8188 100644 --- a/solution/2700-2799/2747.Count Zero Request Servers/README_EN.md +++ b/solution/2700-2799/2747.Count Zero Request Servers/README_EN.md @@ -78,7 +78,7 @@ We can sort all the queries by time from smallest to largest, and then process e For each query $q = (r, i)$, its window left boundary is $l = r - x$, and we need to count how many servers received requests within the window $[l, r]$. We use two pointers $j$ and $k$ to maintain the left and right boundaries of the window, initially $j = k = 0$. Each time, if the log time pointed by $k$ is less than or equal to $r$, we add it to the window, and then move $k$ to the right by one. If the log time pointed by $j$ is less than $l$, we remove it from the window, and then move $j$ to the right by one. During the movement, we need to count how many different servers are in the window, which can be implemented using a hash table. After the movement, the number of servers that did not receive requests in the current time interval is $n$ minus the number of different servers in the hash table. -The time complexity is $O(l \times \log l + m \times \log m + n)$, and the space complexity is $O(l + m)$. Here, $l$ and $n$ are the lengths of the arrays $\text{logs}$ and the number of servers, respectively, while $m$ is the length of the array $\text{queries}$. +The time complexity is $O(l \times \log l + m \times \log m + n)$, and the space complexity is $O(l + m)$. Here, $l$ and $n$ are the lengths of the arrays $\textit{logs}$ and the number of servers, respectively, while $m$ is the length of the array $\textit{queries}$. diff --git a/solution/2700-2799/2748.Number of Beautiful Pairs/README.md b/solution/2700-2799/2748.Number of Beautiful Pairs/README.md index 4cf22d60ac53..3772d10b027f 100644 --- a/solution/2700-2799/2748.Number of Beautiful Pairs/README.md +++ b/solution/2700-2799/2748.Number of Beautiful Pairs/README.md @@ -72,13 +72,13 @@ i = 0 和 j = 2 :nums[0] 的第一个数字是 1 ,nums[2] 的最后一个数 ### 方法一:计数 -我们可以用一个长度为 $10$ 的数组 $\text{cnt}$ 来记录每个数字的第一个数字出现的次数。 +我们可以用一个长度为 $10$ 的数组 $\textit{cnt}$ 来记录每个数字的第一个数字出现的次数。 -遍历数组 $\text{nums}$,对于每个数字 $x$,我们枚举 $0$ 到 $9$ 的每个数字 $y$,如果 $\text{cnt}[y]$ 不为 $0$ 且 $\text{gcd}(x b\mod 10, y) = 1$,则答案加上 $\text{cnt}[y]$。然后,我们将 $x$ 的第一个数字出现的次数加 $1$。 +遍历数组 $\textit{nums}$,对于每个数字 $x$,我们枚举 $0$ 到 $9$ 的每个数字 $y$,如果 $\textit{cnt}[y]$ 不为 $0$ 且 $\textit{gcd}(x b\mod 10, y) = 1$,则答案加上 $\textit{cnt}[y]$。然后,我们将 $x$ 的第一个数字出现的次数加 $1$。 遍历结束后,返回答案即可。 -时间复杂度 $O(n \times (k + \log M))$,空间复杂度 $O(k + \log M)$。其中 $n$ 为数组 $\text{nums}$ 的长度,而 $k$ 和 $M$ 分别表示数组 $\text{nums}$ 中的数字的种类以及最大值。 +时间复杂度 $O(n \times (k + \log M))$,空间复杂度 $O(k + \log M)$。其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $k$ 和 $M$ 分别表示数组 $\textit{nums}$ 中的数字的种类以及最大值。 diff --git a/solution/2700-2799/2748.Number of Beautiful Pairs/README_EN.md b/solution/2700-2799/2748.Number of Beautiful Pairs/README_EN.md index 5b9a2ea903ea..4a8ee4a47c18 100644 --- a/solution/2700-2799/2748.Number of Beautiful Pairs/README_EN.md +++ b/solution/2700-2799/2748.Number of Beautiful Pairs/README_EN.md @@ -71,13 +71,13 @@ Thus, we return 2. ### Solution 1: Counting -We can use an array $\text{cnt}$ of length $10$ to record the count of the first digit of each number. +We can use an array $\textit{cnt}$ of length $10$ to record the count of the first digit of each number. -Iterate through the array $\text{nums}$. For each number $x$, we enumerate each digit $y$ from $0$ to $9$. If $\text{cnt}[y]$ is not $0$ and $\text{gcd}(x \mod 10, y) = 1$, then the answer is incremented by $\text{cnt}[y]$. Then, we increment the count of the first digit of $x$ by $1$. +Iterate through the array $\textit{nums}$. For each number $x$, we enumerate each digit $y$ from $0$ to $9$. If $\textit{cnt}[y]$ is not $0$ and $\textit{gcd}(x \mod 10, y) = 1$, then the answer is incremented by $\textit{cnt}[y]$. Then, we increment the count of the first digit of $x$ by $1$. After the iteration, return the answer. -The time complexity is $O(n \times (k + \log M))$, and the space complexity is $O(k + \log M)$. Here, $n$ is the length of the array $\text{nums}$, while $k$ and $M$ respectively represent the number of distinct numbers and the maximum value in the array $\text{nums}$. +The time complexity is $O(n \times (k + \log M))$, and the space complexity is $O(k + \log M)$. Here, $n$ is the length of the array $\textit{nums}$, while $k$ and $M$ respectively represent the number of distinct numbers and the maximum value in the array $\textit{nums}$. diff --git a/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README.md b/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README.md index 991a8d0fe2fa..7b4bba65a2fe 100644 --- a/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README.md +++ b/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README.md @@ -66,9 +66,9 @@ tags: ### 方法一:枚举 -如果我们操作了 $k$ 次,那么问题实际上就变成了:判断 $\text{num1} - k \times \text{num2}$ 能否拆分成 $k$ 个 $2^i$ 之和。 +如果我们操作了 $k$ 次,那么问题实际上就变成了:判断 $\textit{num1} - k \times \textit{num2}$ 能否拆分成 $k$ 个 $2^i$ 之和。 -我们不妨假设 $x = \text{num1} - k \times \text{num2}$,接下来分类讨论: +我们不妨假设 $x = \textit{num1} - k \times \textit{num2}$,接下来分类讨论: - 如果 $x \lt 0$,那么 $x$ 无法拆分成 $k$ 个 $2^i$ 之和,因为 $2^i \gt 0$,显然无解; - 如果 $x$ 的二进制表示中 $1$ 的个数大于 $k$,此时也是无解; @@ -151,6 +151,23 @@ func makeTheIntegerZero(num1 int, num2 int) int { } ``` +#### TypeScript + +```ts +function makeTheIntegerZero(num1: number, num2: number): number { + for (let k = 1; ; ++k) { + let x = num1 - k * num2; + if (x < 0) { + break; + } + if (x.toString(2).replace(/0/g, '').length <= k && k <= x) { + return k; + } + } + return -1; +} +``` + diff --git a/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README_EN.md b/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README_EN.md index a130bb5ac313..a017d3e80647 100644 --- a/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README_EN.md +++ b/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/README_EN.md @@ -64,9 +64,9 @@ It can be proven, that 3 is the minimum number of operations that we need to per ### Solution 1: Enumeration -If we operate $k$ times, then the problem essentially becomes: determining whether $\text{num1} - k \times \text{num2}$ can be split into the sum of $k$ $2^i$s. +If we operate $k$ times, then the problem essentially becomes: determining whether $\textit{num1} - k \times \textit{num2}$ can be split into the sum of $k$ $2^i$s. -Let's assume $x = \text{num1} - k \times \text{num2}$. Next, we discuss in categories: +Let's assume $x = \textit{num1} - k \times \textit{num2}$. Next, we discuss in categories: - If $x < 0$, then $x$ cannot be split into the sum of $k$ $2^i$s, because $2^i > 0$, which obviously has no solution; - If the number of $1$s in the binary representation of $x$ is greater than $k$, there is also no solution in this case; @@ -149,6 +149,23 @@ func makeTheIntegerZero(num1 int, num2 int) int { } ``` +#### TypeScript + +```ts +function makeTheIntegerZero(num1: number, num2: number): number { + for (let k = 1; ; ++k) { + let x = num1 - k * num2; + if (x < 0) { + break; + } + if (x.toString(2).replace(/0/g, '').length <= k && k <= x) { + return k; + } + } + return -1; +} +``` + diff --git a/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/Solution.ts b/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/Solution.ts new file mode 100644 index 000000000000..ff5d8db66c33 --- /dev/null +++ b/solution/2700-2799/2749.Minimum Operations to Make the Integer Zero/Solution.ts @@ -0,0 +1,12 @@ +function makeTheIntegerZero(num1: number, num2: number): number { + for (let k = 1; ; ++k) { + let x = num1 - k * num2; + if (x < 0) { + break; + } + if (x.toString(2).replace(/0/g, '').length <= k && k <= x) { + return k; + } + } + return -1; +} diff --git a/solution/2700-2799/2751.Robot Collisions/README.md b/solution/2700-2799/2751.Robot Collisions/README.md index ed0bb46be82e..276c770bb457 100644 --- a/solution/2700-2799/2751.Robot Collisions/README.md +++ b/solution/2700-2799/2751.Robot Collisions/README.md @@ -90,25 +90,186 @@ tags: #### Python3 ```python +class Solution: + def survivedRobotsHealths( + self, positions: List[int], healths: List[int], directions: str + ) -> List[int]: + n = len(positions) + indices = list(range(n)) + stack = [] + + indices.sort(key=lambda i: positions[i]) + + for currentIndex in indices: + if directions[currentIndex] == "R": + stack.append(currentIndex) + else: + while stack and healths[currentIndex] > 0: + topIndex = stack.pop() + + if healths[topIndex] > healths[currentIndex]: + healths[topIndex] -= 1 + healths[currentIndex] = 0 + stack.append(topIndex) + elif healths[topIndex] < healths[currentIndex]: + healths[currentIndex] -= 1 + healths[topIndex] = 0 + else: + healths[currentIndex] = 0 + healths[topIndex] = 0 + + result = [health for health in healths if health > 0] + return result ``` #### Java ```java - +class Solution { + public List survivedRobotsHealths(int[] positions, int[] healths, String directions) { + int n = positions.length; + Integer[] indices = new Integer[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + + Arrays.sort(indices, (i, j) -> Integer.compare(positions[i], positions[j])); + + Stack stack = new Stack<>(); + + for (int currentIndex : indices) { + if (directions.charAt(currentIndex) == 'R') { + stack.push(currentIndex); + } else { + while (!stack.isEmpty() && healths[currentIndex] > 0) { + int topIndex = stack.pop(); + + if (healths[topIndex] > healths[currentIndex]) { + healths[topIndex] -= 1; + healths[currentIndex] = 0; + stack.push(topIndex); + } else if (healths[topIndex] < healths[currentIndex]) { + healths[currentIndex] -= 1; + healths[topIndex] = 0; + } else { + healths[currentIndex] = 0; + healths[topIndex] = 0; + } + } + } + } + + List result = new ArrayList<>(); + for (int health : healths) { + if (health > 0) { + result.add(health); + } + } + + return result; + } +} ``` #### C++ ```cpp - +class Solution { +public: + vector survivedRobotsHealths(vector& positions, vector& healths, string directions) { + int n = positions.size(); + vector indices(n); + + iota(indices.begin(), indices.end(), 0); + stack st; + + auto lambda = [&](int i, int j) { return positions[i] < positions[j]; }; + + sort(begin(indices), end(indices), lambda); + + vector result; + for (int currentIndex : indices) { + if (directions[currentIndex] == 'R') { + st.push(currentIndex); + } else { + while (!st.empty() && healths[currentIndex] > 0) { + int topIndex = st.top(); + st.pop(); + + if (healths[topIndex] > healths[currentIndex]) { + healths[topIndex] -= 1; + healths[currentIndex] = 0; + st.push(topIndex); + } else if (healths[topIndex] < healths[currentIndex]) { + healths[currentIndex] -= 1; + healths[topIndex] = 0; + } else { + healths[currentIndex] = 0; + healths[topIndex] = 0; + } + } + } + } + + for (int i = 0; i < n; ++i) { + if (healths[i] > 0) { + result.push_back(healths[i]); + } + } + return result; + } +}; ``` #### Go ```go - +func survivedRobotsHealths(positions []int, healths []int, directions string) []int { + n := len(positions) + indices := make([]int, n) + for i := range indices { + indices[i] = i + } + + sort.Slice(indices, func(i, j int) bool { + return positions[indices[i]] < positions[indices[j]] + }) + + stack := []int{} + + for _, currentIndex := range indices { + if directions[currentIndex] == 'R' { + stack = append(stack, currentIndex) + } else { + for len(stack) > 0 && healths[currentIndex] > 0 { + topIndex := stack[len(stack)-1] + stack = stack[:len(stack)-1] + + if healths[topIndex] > healths[currentIndex] { + healths[topIndex] -= 1 + healths[currentIndex] = 0 + stack = append(stack, topIndex) + } else if healths[topIndex] < healths[currentIndex] { + healths[currentIndex] -= 1 + healths[topIndex] = 0 + } else { + healths[currentIndex] = 0 + healths[topIndex] = 0 + } + } + } + } + + result := []int{} + for _, health := range healths { + if health > 0 { + result = append(result, health) + } + } + + return result +} ``` diff --git a/solution/2700-2799/2751.Robot Collisions/README_EN.md b/solution/2700-2799/2751.Robot Collisions/README_EN.md index f624b21067c2..d3516d9da029 100644 --- a/solution/2700-2799/2751.Robot Collisions/README_EN.md +++ b/solution/2700-2799/2751.Robot Collisions/README_EN.md @@ -90,25 +90,186 @@ tags: #### Python3 ```python +class Solution: + def survivedRobotsHealths( + self, positions: List[int], healths: List[int], directions: str + ) -> List[int]: + n = len(positions) + indices = list(range(n)) + stack = [] + + indices.sort(key=lambda i: positions[i]) + + for currentIndex in indices: + if directions[currentIndex] == "R": + stack.append(currentIndex) + else: + while stack and healths[currentIndex] > 0: + topIndex = stack.pop() + + if healths[topIndex] > healths[currentIndex]: + healths[topIndex] -= 1 + healths[currentIndex] = 0 + stack.append(topIndex) + elif healths[topIndex] < healths[currentIndex]: + healths[currentIndex] -= 1 + healths[topIndex] = 0 + else: + healths[currentIndex] = 0 + healths[topIndex] = 0 + + result = [health for health in healths if health > 0] + return result ``` #### Java ```java - +class Solution { + public List survivedRobotsHealths(int[] positions, int[] healths, String directions) { + int n = positions.length; + Integer[] indices = new Integer[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + + Arrays.sort(indices, (i, j) -> Integer.compare(positions[i], positions[j])); + + Stack stack = new Stack<>(); + + for (int currentIndex : indices) { + if (directions.charAt(currentIndex) == 'R') { + stack.push(currentIndex); + } else { + while (!stack.isEmpty() && healths[currentIndex] > 0) { + int topIndex = stack.pop(); + + if (healths[topIndex] > healths[currentIndex]) { + healths[topIndex] -= 1; + healths[currentIndex] = 0; + stack.push(topIndex); + } else if (healths[topIndex] < healths[currentIndex]) { + healths[currentIndex] -= 1; + healths[topIndex] = 0; + } else { + healths[currentIndex] = 0; + healths[topIndex] = 0; + } + } + } + } + + List result = new ArrayList<>(); + for (int health : healths) { + if (health > 0) { + result.add(health); + } + } + + return result; + } +} ``` #### C++ ```cpp - +class Solution { +public: + vector survivedRobotsHealths(vector& positions, vector& healths, string directions) { + int n = positions.size(); + vector indices(n); + + iota(indices.begin(), indices.end(), 0); + stack st; + + auto lambda = [&](int i, int j) { return positions[i] < positions[j]; }; + + sort(begin(indices), end(indices), lambda); + + vector result; + for (int currentIndex : indices) { + if (directions[currentIndex] == 'R') { + st.push(currentIndex); + } else { + while (!st.empty() && healths[currentIndex] > 0) { + int topIndex = st.top(); + st.pop(); + + if (healths[topIndex] > healths[currentIndex]) { + healths[topIndex] -= 1; + healths[currentIndex] = 0; + st.push(topIndex); + } else if (healths[topIndex] < healths[currentIndex]) { + healths[currentIndex] -= 1; + healths[topIndex] = 0; + } else { + healths[currentIndex] = 0; + healths[topIndex] = 0; + } + } + } + } + + for (int i = 0; i < n; ++i) { + if (healths[i] > 0) { + result.push_back(healths[i]); + } + } + return result; + } +}; ``` #### Go ```go - +func survivedRobotsHealths(positions []int, healths []int, directions string) []int { + n := len(positions) + indices := make([]int, n) + for i := range indices { + indices[i] = i + } + + sort.Slice(indices, func(i, j int) bool { + return positions[indices[i]] < positions[indices[j]] + }) + + stack := []int{} + + for _, currentIndex := range indices { + if directions[currentIndex] == 'R' { + stack = append(stack, currentIndex) + } else { + for len(stack) > 0 && healths[currentIndex] > 0 { + topIndex := stack[len(stack)-1] + stack = stack[:len(stack)-1] + + if healths[topIndex] > healths[currentIndex] { + healths[topIndex] -= 1 + healths[currentIndex] = 0 + stack = append(stack, topIndex) + } else if healths[topIndex] < healths[currentIndex] { + healths[currentIndex] -= 1 + healths[topIndex] = 0 + } else { + healths[currentIndex] = 0 + healths[topIndex] = 0 + } + } + } + } + + result := []int{} + for _, health := range healths { + if health > 0 { + result = append(result, health) + } + } + + return result +} ``` diff --git a/solution/2700-2799/2751.Robot Collisions/Solution.cpp b/solution/2700-2799/2751.Robot Collisions/Solution.cpp new file mode 100644 index 000000000000..0743eac1fed2 --- /dev/null +++ b/solution/2700-2799/2751.Robot Collisions/Solution.cpp @@ -0,0 +1,45 @@ +class Solution { +public: + vector survivedRobotsHealths(vector& positions, vector& healths, string directions) { + int n = positions.size(); + vector indices(n); + + iota(indices.begin(), indices.end(), 0); + stack st; + + auto lambda = [&](int i, int j) { return positions[i] < positions[j]; }; + + sort(begin(indices), end(indices), lambda); + + vector result; + for (int currentIndex : indices) { + if (directions[currentIndex] == 'R') { + st.push(currentIndex); + } else { + while (!st.empty() && healths[currentIndex] > 0) { + int topIndex = st.top(); + st.pop(); + + if (healths[topIndex] > healths[currentIndex]) { + healths[topIndex] -= 1; + healths[currentIndex] = 0; + st.push(topIndex); + } else if (healths[topIndex] < healths[currentIndex]) { + healths[currentIndex] -= 1; + healths[topIndex] = 0; + } else { + healths[currentIndex] = 0; + healths[topIndex] = 0; + } + } + } + } + + for (int i = 0; i < n; ++i) { + if (healths[i] > 0) { + result.push_back(healths[i]); + } + } + return result; + } +}; diff --git a/solution/2700-2799/2751.Robot Collisions/Solution.go b/solution/2700-2799/2751.Robot Collisions/Solution.go new file mode 100644 index 000000000000..bf12096531e5 --- /dev/null +++ b/solution/2700-2799/2751.Robot Collisions/Solution.go @@ -0,0 +1,45 @@ +func survivedRobotsHealths(positions []int, healths []int, directions string) []int { + n := len(positions) + indices := make([]int, n) + for i := range indices { + indices[i] = i + } + + sort.Slice(indices, func(i, j int) bool { + return positions[indices[i]] < positions[indices[j]] + }) + + stack := []int{} + + for _, currentIndex := range indices { + if directions[currentIndex] == 'R' { + stack = append(stack, currentIndex) + } else { + for len(stack) > 0 && healths[currentIndex] > 0 { + topIndex := stack[len(stack)-1] + stack = stack[:len(stack)-1] + + if healths[topIndex] > healths[currentIndex] { + healths[topIndex] -= 1 + healths[currentIndex] = 0 + stack = append(stack, topIndex) + } else if healths[topIndex] < healths[currentIndex] { + healths[currentIndex] -= 1 + healths[topIndex] = 0 + } else { + healths[currentIndex] = 0 + healths[topIndex] = 0 + } + } + } + } + + result := []int{} + for _, health := range healths { + if health > 0 { + result = append(result, health) + } + } + + return result +} \ No newline at end of file diff --git a/solution/2700-2799/2751.Robot Collisions/Solution.java b/solution/2700-2799/2751.Robot Collisions/Solution.java new file mode 100644 index 000000000000..59e12be376c0 --- /dev/null +++ b/solution/2700-2799/2751.Robot Collisions/Solution.java @@ -0,0 +1,44 @@ +class Solution { + public List survivedRobotsHealths(int[] positions, int[] healths, String directions) { + int n = positions.length; + Integer[] indices = new Integer[n]; + for (int i = 0; i < n; i++) { + indices[i] = i; + } + + Arrays.sort(indices, (i, j) -> Integer.compare(positions[i], positions[j])); + + Stack stack = new Stack<>(); + + for (int currentIndex : indices) { + if (directions.charAt(currentIndex) == 'R') { + stack.push(currentIndex); + } else { + while (!stack.isEmpty() && healths[currentIndex] > 0) { + int topIndex = stack.pop(); + + if (healths[topIndex] > healths[currentIndex]) { + healths[topIndex] -= 1; + healths[currentIndex] = 0; + stack.push(topIndex); + } else if (healths[topIndex] < healths[currentIndex]) { + healths[currentIndex] -= 1; + healths[topIndex] = 0; + } else { + healths[currentIndex] = 0; + healths[topIndex] = 0; + } + } + } + } + + List result = new ArrayList<>(); + for (int health : healths) { + if (health > 0) { + result.add(health); + } + } + + return result; + } +} \ No newline at end of file diff --git a/solution/2700-2799/2751.Robot Collisions/Solution.py b/solution/2700-2799/2751.Robot Collisions/Solution.py new file mode 100644 index 000000000000..ed103f23961c --- /dev/null +++ b/solution/2700-2799/2751.Robot Collisions/Solution.py @@ -0,0 +1,30 @@ +class Solution: + def survivedRobotsHealths( + self, positions: List[int], healths: List[int], directions: str + ) -> List[int]: + n = len(positions) + indices = list(range(n)) + stack = [] + + indices.sort(key=lambda i: positions[i]) + + for currentIndex in indices: + if directions[currentIndex] == "R": + stack.append(currentIndex) + else: + while stack and healths[currentIndex] > 0: + topIndex = stack.pop() + + if healths[topIndex] > healths[currentIndex]: + healths[topIndex] -= 1 + healths[currentIndex] = 0 + stack.append(topIndex) + elif healths[topIndex] < healths[currentIndex]: + healths[currentIndex] -= 1 + healths[topIndex] = 0 + else: + healths[currentIndex] = 0 + healths[topIndex] = 0 + + result = [health for health in healths if health > 0] + return result diff --git a/solution/2700-2799/2754.Bind Function to Context/README.md b/solution/2700-2799/2754.Bind Function to Context/README.md index 9efc28374931..2cca992456f6 100644 --- a/solution/2700-2799/2754.Bind Function to Context/README.md +++ b/solution/2700-2799/2754.Bind Function to Context/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2754.Bind%20Function%20to%20Context/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2754.Bind Function to Context/README_EN.md b/solution/2700-2799/2754.Bind Function to Context/README_EN.md index 687902e2b305..14031683dd66 100644 --- a/solution/2700-2799/2754.Bind Function to Context/README_EN.md +++ b/solution/2700-2799/2754.Bind Function to Context/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2754.Bind%20Function%20to%20Context/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2755.Deep Merge of Two Objects/README.md b/solution/2700-2799/2755.Deep Merge of Two Objects/README.md index 2a61b2c6abba..c6f50e6741ae 100644 --- a/solution/2700-2799/2755.Deep Merge of Two Objects/README.md +++ b/solution/2700-2799/2755.Deep Merge of Two Objects/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2755.Deep%20Merge%20of%20Two%20Objects/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2755.Deep Merge of Two Objects/README_EN.md b/solution/2700-2799/2755.Deep Merge of Two Objects/README_EN.md index 40abd15bf3ee..b9b571a02bc6 100644 --- a/solution/2700-2799/2755.Deep Merge of Two Objects/README_EN.md +++ b/solution/2700-2799/2755.Deep Merge of Two Objects/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2755.Deep%20Merge%20of%20Two%20Objects/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2756.Query Batching/README.md b/solution/2700-2799/2756.Query Batching/README.md index a97c42c91288..916db200ff9c 100644 --- a/solution/2700-2799/2756.Query Batching/README.md +++ b/solution/2700-2799/2756.Query Batching/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2756.Query%20Batching/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2756.Query Batching/README_EN.md b/solution/2700-2799/2756.Query Batching/README_EN.md index c0ee5ff3c856..02f77f02aed2 100644 --- a/solution/2700-2799/2756.Query Batching/README_EN.md +++ b/solution/2700-2799/2756.Query Batching/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2756.Query%20Batching/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2757.Generate Circular Array Values/README.md b/solution/2700-2799/2757.Generate Circular Array Values/README.md index 85291ef28a0e..091ce7045b56 100644 --- a/solution/2700-2799/2757.Generate Circular Array Values/README.md +++ b/solution/2700-2799/2757.Generate Circular Array Values/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2757.Generate%20Circular%20Array%20Values/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2757.Generate Circular Array Values/README_EN.md b/solution/2700-2799/2757.Generate Circular Array Values/README_EN.md index aa40722172e7..e8d23eae7185 100644 --- a/solution/2700-2799/2757.Generate Circular Array Values/README_EN.md +++ b/solution/2700-2799/2757.Generate Circular Array Values/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2757.Generate%20Circular%20Array%20Values/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2758.Next Day/README.md b/solution/2700-2799/2758.Next Day/README.md index 6b751e685861..cb299b325fb8 100644 --- a/solution/2700-2799/2758.Next Day/README.md +++ b/solution/2700-2799/2758.Next Day/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2758.Next%20Day/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2758.Next Day/README_EN.md b/solution/2700-2799/2758.Next Day/README_EN.md index 5d192314d755..fc1ead2b72c8 100644 --- a/solution/2700-2799/2758.Next Day/README_EN.md +++ b/solution/2700-2799/2758.Next Day/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2758.Next%20Day/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2759.Convert JSON String to Object/README.md b/solution/2700-2799/2759.Convert JSON String to Object/README.md index e5dc5a42aa86..523aea2f72ff 100644 --- a/solution/2700-2799/2759.Convert JSON String to Object/README.md +++ b/solution/2700-2799/2759.Convert JSON String to Object/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2759.Convert%20JSON%20String%20to%20Object/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2759.Convert JSON String to Object/README_EN.md b/solution/2700-2799/2759.Convert JSON String to Object/README_EN.md index 3e03d4f86f09..20f89fa1bed7 100644 --- a/solution/2700-2799/2759.Convert JSON String to Object/README_EN.md +++ b/solution/2700-2799/2759.Convert JSON String to Object/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2759.Convert%20JSON%20String%20to%20Object/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2766.Relocate Marbles/README.md b/solution/2700-2799/2766.Relocate Marbles/README.md index 297f0e86fcb5..9095f6273251 100644 --- a/solution/2700-2799/2766.Relocate Marbles/README.md +++ b/solution/2700-2799/2766.Relocate Marbles/README.md @@ -23,7 +23,7 @@ tags:

    给你一个下标从 0 开始的整数数组 nums ,表示一些石块的初始位置。再给你两个长度 相等 下标从 0 开始的整数数组 moveFrom 和 moveTo 。

    -

    在 moveFrom.length 次操作内,你可以改变石块的位置。在第 i 次操作中,你将位置在 moveFrom[i] 的所有石块移到位置 moveTo[i] 。

    +

    在 moveFrom.length 次操作内,你将改变石块的位置。在第 i 次操作中,你将位置在 moveFrom[i] 的所有石块移到位置 moveTo[i] 。

    完成这些操作后,请你按升序返回所有  石块的位置。

    @@ -168,9 +168,7 @@ function relocateMarbles(nums: number[], moveFrom: number[], moveTo: number[]): pos.delete(moveFrom[i]); pos.add(moveTo[i]); } - const ans = [...pos]; - ans.sort((a, b) => a - b); - return ans; + return [...pos].sort((a, b) => a - b); } ``` diff --git a/solution/2700-2799/2766.Relocate Marbles/README_EN.md b/solution/2700-2799/2766.Relocate Marbles/README_EN.md index 2d4cddb4f23b..d7e70c8f2913 100644 --- a/solution/2700-2799/2766.Relocate Marbles/README_EN.md +++ b/solution/2700-2799/2766.Relocate Marbles/README_EN.md @@ -166,9 +166,7 @@ function relocateMarbles(nums: number[], moveFrom: number[], moveTo: number[]): pos.delete(moveFrom[i]); pos.add(moveTo[i]); } - const ans = [...pos]; - ans.sort((a, b) => a - b); - return ans; + return [...pos].sort((a, b) => a - b); } ``` diff --git a/solution/2700-2799/2766.Relocate Marbles/Solution.ts b/solution/2700-2799/2766.Relocate Marbles/Solution.ts index d70f4163b3fc..8ee7ccf89211 100644 --- a/solution/2700-2799/2766.Relocate Marbles/Solution.ts +++ b/solution/2700-2799/2766.Relocate Marbles/Solution.ts @@ -4,7 +4,5 @@ function relocateMarbles(nums: number[], moveFrom: number[], moveTo: number[]): pos.delete(moveFrom[i]); pos.add(moveTo[i]); } - const ans = [...pos]; - ans.sort((a, b) => a - b); - return ans; + return [...pos].sort((a, b) => a - b); } diff --git a/solution/2700-2799/2774.Array Upper Bound/README.md b/solution/2700-2799/2774.Array Upper Bound/README.md index e2fb9d4e5098..27bacb4f20f6 100644 --- a/solution/2700-2799/2774.Array Upper Bound/README.md +++ b/solution/2700-2799/2774.Array Upper Bound/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2774.Array%20Upper%20Bound/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2774.Array Upper Bound/README_EN.md b/solution/2700-2799/2774.Array Upper Bound/README_EN.md index 9c91426f9446..1e837d175be0 100644 --- a/solution/2700-2799/2774.Array Upper Bound/README_EN.md +++ b/solution/2700-2799/2774.Array Upper Bound/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2774.Array%20Upper%20Bound/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2775.Undefined to Null/README.md b/solution/2700-2799/2775.Undefined to Null/README.md index 281b26483b81..993dc6a97861 100644 --- a/solution/2700-2799/2775.Undefined to Null/README.md +++ b/solution/2700-2799/2775.Undefined to Null/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2775.Undefined%20to%20Null/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2775.Undefined to Null/README_EN.md b/solution/2700-2799/2775.Undefined to Null/README_EN.md index 38ad410d1378..a62bd2ba5c42 100644 --- a/solution/2700-2799/2775.Undefined to Null/README_EN.md +++ b/solution/2700-2799/2775.Undefined to Null/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2775.Undefined%20to%20Null/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README.md b/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README.md index 333ad4ea7c13..f7565fafba95 100644 --- a/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README.md +++ b/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2776.Convert%20Callback%20Based%20Function%20to%20Promise%20Based%20Function/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README_EN.md b/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README_EN.md index 59d164cc4c40..e5448e6750c4 100644 --- a/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README_EN.md +++ b/solution/2700-2799/2776.Convert Callback Based Function to Promise Based Function/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2776.Convert%20Callback%20Based%20Function%20to%20Promise%20Based%20Function/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2777.Date Range Generator/README.md b/solution/2700-2799/2777.Date Range Generator/README.md index cb1e1a541417..7246ac35503a 100644 --- a/solution/2700-2799/2777.Date Range Generator/README.md +++ b/solution/2700-2799/2777.Date Range Generator/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2777.Date%20Range%20Generator/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2777.Date Range Generator/README_EN.md b/solution/2700-2799/2777.Date Range Generator/README_EN.md index 4d3f7aa7401f..adc8810482ce 100644 --- a/solution/2700-2799/2777.Date Range Generator/README_EN.md +++ b/solution/2700-2799/2777.Date Range Generator/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2777.Date%20Range%20Generator/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2793.Status of Flight Tickets/README.md b/solution/2700-2799/2793.Status of Flight Tickets/README.md index 0a79d90731ac..5c0e4ddcd4b8 100644 --- a/solution/2700-2799/2793.Status of Flight Tickets/README.md +++ b/solution/2700-2799/2793.Status of Flight Tickets/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2793.Status%20of%20Flight%20Tickets/README.md +tags: + - 数据库 --- diff --git a/solution/2700-2799/2793.Status of Flight Tickets/README_EN.md b/solution/2700-2799/2793.Status of Flight Tickets/README_EN.md index 635a8abfb75b..c9a7309614de 100644 --- a/solution/2700-2799/2793.Status of Flight Tickets/README_EN.md +++ b/solution/2700-2799/2793.Status of Flight Tickets/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2793.Status%20of%20Flight%20Tickets/README_EN.md +tags: + - Database --- diff --git a/solution/2700-2799/2794.Create Object from Two Arrays/README.md b/solution/2700-2799/2794.Create Object from Two Arrays/README.md index dfa181524b59..d144a5151170 100644 --- a/solution/2700-2799/2794.Create Object from Two Arrays/README.md +++ b/solution/2700-2799/2794.Create Object from Two Arrays/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2794.Create%20Object%20from%20Two%20Arrays/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2794.Create Object from Two Arrays/README_EN.md b/solution/2700-2799/2794.Create Object from Two Arrays/README_EN.md index b0796a953f43..7d652d70cb74 100644 --- a/solution/2700-2799/2794.Create Object from Two Arrays/README_EN.md +++ b/solution/2700-2799/2794.Create Object from Two Arrays/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2794.Create%20Object%20from%20Two%20Arrays/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README.md b/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README.md index d4cabdc46533..9dae14734282 100644 --- a/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README.md +++ b/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2795.Parallel%20Execution%20of%20Promises%20for%20Individual%20Results%20Retrieval/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README_EN.md b/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README_EN.md index 920ec1b149b7..ba33c3d3c8cc 100644 --- a/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README_EN.md +++ b/solution/2700-2799/2795.Parallel Execution of Promises for Individual Results Retrieval/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2795.Parallel%20Execution%20of%20Promises%20for%20Individual%20Results%20Retrieval/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2796.Repeat String/README.md b/solution/2700-2799/2796.Repeat String/README.md index fc5d4927ebe5..563c760fab8d 100644 --- a/solution/2700-2799/2796.Repeat String/README.md +++ b/solution/2700-2799/2796.Repeat String/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2796.Repeat%20String/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2796.Repeat String/README_EN.md b/solution/2700-2799/2796.Repeat String/README_EN.md index 916af0430545..a167ce16d00c 100644 --- a/solution/2700-2799/2796.Repeat String/README_EN.md +++ b/solution/2700-2799/2796.Repeat String/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2796.Repeat%20String/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2797.Partial Function with Placeholders/README.md b/solution/2700-2799/2797.Partial Function with Placeholders/README.md index 40e9a3cf7d64..2c39dc6601a6 100644 --- a/solution/2700-2799/2797.Partial Function with Placeholders/README.md +++ b/solution/2700-2799/2797.Partial Function with Placeholders/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2797.Partial%20Function%20with%20Placeholders/README.md +tags: + - JavaScript --- diff --git a/solution/2700-2799/2797.Partial Function with Placeholders/README_EN.md b/solution/2700-2799/2797.Partial Function with Placeholders/README_EN.md index 25453033c44c..b8499eeb8754 100644 --- a/solution/2700-2799/2797.Partial Function with Placeholders/README_EN.md +++ b/solution/2700-2799/2797.Partial Function with Placeholders/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2700-2799/2797.Partial%20Function%20with%20Placeholders/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2800.Shortest String That Contains Three Strings/README.md b/solution/2800-2899/2800.Shortest String That Contains Three Strings/README.md index 703812a4e9a5..6835bb8fd92c 100644 --- a/solution/2800-2899/2800.Shortest String That Contains Three Strings/README.md +++ b/solution/2800-2899/2800.Shortest String That Contains Three Strings/README.md @@ -288,4 +288,230 @@ impl Solution { + + +### 方法二:枚举 + KMP + +我们可以使用 KMP 算法来优化字符串的合并过程。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是三个字符串的长度之和。 + + + +#### Python3 + +```python +class Solution: + def minimumString(self, a: str, b: str, c: str) -> str: + def f(s: str, t: str) -> str: + if s in t: + return t + if t in s: + return s + p = t + "#" + s + "$" + n = len(p) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if p[i - 1] == p[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s + t[next[-1] :] + + ans = "" + for a, b, c in permutations((a, b, c)): + s = f(f(a, b), c) + if ans == "" or len(s) < len(ans) or (len(s) == len(ans) and s < ans): + ans = s + return ans +``` + +#### Java + +```java +class Solution { + public String minimumString(String a, String b, String c) { + String[] s = {a, b, c}; + int[][] perm = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 1, 0}, {2, 0, 1}}; + String ans = ""; + for (var p : perm) { + int i = p[0], j = p[1], k = p[2]; + String t = f(f(s[i], s[j]), s[k]); + if ("".equals(ans) || t.length() < ans.length() + || (t.length() == ans.length() && t.compareTo(ans) < 0)) { + ans = t; + } + } + return ans; + } + + private String f(String s, String t) { + if (s.contains(t)) { + return s; + } + if (t.contains(s)) { + return t; + } + char[] p = (t + "#" + s + "$").toCharArray(); + int n = p.length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (p[i - 1] == p[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.substring(next[n - 1]); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string minimumString(string a, string b, string c) { + vector s = {a, b, c}; + vector> perm = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 1, 0}, {2, 0, 1}}; + string ans = ""; + for (auto& p : perm) { + int i = p[0], j = p[1], k = p[2]; + string t = f(f(s[i], s[j]), s[k]); + if (ans == "" || t.size() < ans.size() || (t.size() == ans.size() && t < ans)) { + ans = t; + } + } + return ans; + } + + string f(string s, string t) { + if (s.find(t) != string::npos) { + return s; + } + if (t.find(s) != string::npos) { + return t; + } + string p = t + "#" + s + "$"; + int n = p.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (p[i - 1] == p[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.substr(next[n - 1]); + }; +}; +``` + +#### Go + +```go +func minimumString(a string, b string, c string) string { + f := func(s, t string) string { + if strings.Contains(s, t) { + return s + } + if strings.Contains(t, s) { + return t + } + p := t + "#" + s + "$" + n := len(p) + next := make([]int, n) + next[0] = -1 + for i, j := 2, 0; i < n; { + if p[i-1] == p[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return s + t[next[n-1]:] + } + s := [3]string{a, b, c} + ans := "" + for _, p := range [][]int{{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 0, 1}, {2, 1, 0}} { + i, j, k := p[0], p[1], p[2] + t := f(f(s[i], s[j]), s[k]) + if ans == "" || len(t) < len(ans) || (len(t) == len(ans) && t < ans) { + ans = t + } + } + return ans +} +``` + +#### TypeScript + +```ts +function minimumString(a: string, b: string, c: string): string { + const f = (s: string, t: string): string => { + if (s.includes(t)) { + return s; + } + if (t.includes(s)) { + return t; + } + const p = t + '#' + s + '$'; + const n = p.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (p[i - 1] === p[j]) { + next[i++] = ++j; + } else if (j) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.slice(next[n - 1]); + }; + const s: string[] = [a, b, c]; + const perm: number[][] = [ + [0, 1, 2], + [0, 2, 1], + [1, 0, 2], + [1, 2, 0], + [2, 0, 1], + [2, 1, 0], + ]; + let ans = ''; + for (const [i, j, k] of perm) { + const t = f(f(s[i], s[j]), s[k]); + if (ans === '' || t.length < ans.length || (t.length === ans.length && t < ans)) { + ans = t; + } + } + return ans; +} +``` + + + + + diff --git a/solution/2800-2899/2800.Shortest String That Contains Three Strings/README_EN.md b/solution/2800-2899/2800.Shortest String That Contains Three Strings/README_EN.md index 3c56ba047947..194cb863451b 100644 --- a/solution/2800-2899/2800.Shortest String That Contains Three Strings/README_EN.md +++ b/solution/2800-2899/2800.Shortest String That Contains Three Strings/README_EN.md @@ -288,4 +288,230 @@ impl Solution { + + +### Solution 2: Enumeration + KMP + +We can use the KMP algorithm to optimize the string merging process. + +Time complexity is $O(n)$, and space complexity is $O(n)$. Here, $n$ is the sum of the lengths of the three strings. + + + +#### Python3 + +```python +class Solution: + def minimumString(self, a: str, b: str, c: str) -> str: + def f(s: str, t: str) -> str: + if s in t: + return t + if t in s: + return s + p = t + "#" + s + "$" + n = len(p) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if p[i - 1] == p[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s + t[next[-1] :] + + ans = "" + for a, b, c in permutations((a, b, c)): + s = f(f(a, b), c) + if ans == "" or len(s) < len(ans) or (len(s) == len(ans) and s < ans): + ans = s + return ans +``` + +#### Java + +```java +class Solution { + public String minimumString(String a, String b, String c) { + String[] s = {a, b, c}; + int[][] perm = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 1, 0}, {2, 0, 1}}; + String ans = ""; + for (var p : perm) { + int i = p[0], j = p[1], k = p[2]; + String t = f(f(s[i], s[j]), s[k]); + if ("".equals(ans) || t.length() < ans.length() + || (t.length() == ans.length() && t.compareTo(ans) < 0)) { + ans = t; + } + } + return ans; + } + + private String f(String s, String t) { + if (s.contains(t)) { + return s; + } + if (t.contains(s)) { + return t; + } + char[] p = (t + "#" + s + "$").toCharArray(); + int n = p.length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (p[i - 1] == p[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.substring(next[n - 1]); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string minimumString(string a, string b, string c) { + vector s = {a, b, c}; + vector> perm = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 1, 0}, {2, 0, 1}}; + string ans = ""; + for (auto& p : perm) { + int i = p[0], j = p[1], k = p[2]; + string t = f(f(s[i], s[j]), s[k]); + if (ans == "" || t.size() < ans.size() || (t.size() == ans.size() && t < ans)) { + ans = t; + } + } + return ans; + } + + string f(string s, string t) { + if (s.find(t) != string::npos) { + return s; + } + if (t.find(s) != string::npos) { + return t; + } + string p = t + "#" + s + "$"; + int n = p.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (p[i - 1] == p[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.substr(next[n - 1]); + }; +}; +``` + +#### Go + +```go +func minimumString(a string, b string, c string) string { + f := func(s, t string) string { + if strings.Contains(s, t) { + return s + } + if strings.Contains(t, s) { + return t + } + p := t + "#" + s + "$" + n := len(p) + next := make([]int, n) + next[0] = -1 + for i, j := 2, 0; i < n; { + if p[i-1] == p[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return s + t[next[n-1]:] + } + s := [3]string{a, b, c} + ans := "" + for _, p := range [][]int{{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 0, 1}, {2, 1, 0}} { + i, j, k := p[0], p[1], p[2] + t := f(f(s[i], s[j]), s[k]) + if ans == "" || len(t) < len(ans) || (len(t) == len(ans) && t < ans) { + ans = t + } + } + return ans +} +``` + +#### TypeScript + +```ts +function minimumString(a: string, b: string, c: string): string { + const f = (s: string, t: string): string => { + if (s.includes(t)) { + return s; + } + if (t.includes(s)) { + return t; + } + const p = t + '#' + s + '$'; + const n = p.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (p[i - 1] === p[j]) { + next[i++] = ++j; + } else if (j) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.slice(next[n - 1]); + }; + const s: string[] = [a, b, c]; + const perm: number[][] = [ + [0, 1, 2], + [0, 2, 1], + [1, 0, 2], + [1, 2, 0], + [2, 0, 1], + [2, 1, 0], + ]; + let ans = ''; + for (const [i, j, k] of perm) { + const t = f(f(s[i], s[j]), s[k]); + if (ans === '' || t.length < ans.length || (t.length === ans.length && t < ans)) { + ans = t; + } + } + return ans; +} +``` + + + + + diff --git a/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.cpp b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.cpp new file mode 100644 index 000000000000..d07a8213f6bc --- /dev/null +++ b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.cpp @@ -0,0 +1,40 @@ +class Solution { +public: + string minimumString(string a, string b, string c) { + vector s = {a, b, c}; + vector> perm = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 1, 0}, {2, 0, 1}}; + string ans = ""; + for (auto& p : perm) { + int i = p[0], j = p[1], k = p[2]; + string t = f(f(s[i], s[j]), s[k]); + if (ans == "" || t.size() < ans.size() || (t.size() == ans.size() && t < ans)) { + ans = t; + } + } + return ans; + } + + string f(string s, string t) { + if (s.find(t) != string::npos) { + return s; + } + if (t.find(s) != string::npos) { + return t; + } + string p = t + "#" + s + "$"; + int n = p.size(); + int next[n]; + next[0] = -1; + next[1] = 0; + for (int i = 2, j = 0; i < n;) { + if (p[i - 1] == p[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.substr(next[n - 1]); + }; +}; diff --git a/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.go b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.go new file mode 100644 index 000000000000..69277ed1cca0 --- /dev/null +++ b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.go @@ -0,0 +1,37 @@ +func minimumString(a string, b string, c string) string { + f := func(s, t string) string { + if strings.Contains(s, t) { + return s + } + if strings.Contains(t, s) { + return t + } + p := t + "#" + s + "$" + n := len(p) + next := make([]int, n) + next[0] = -1 + for i, j := 2, 0; i < n; { + if p[i-1] == p[j] { + j++ + next[i] = j + i++ + } else if j > 0 { + j = next[j] + } else { + next[i] = 0 + i++ + } + } + return s + t[next[n-1]:] + } + s := [3]string{a, b, c} + ans := "" + for _, p := range [][]int{{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 0, 1}, {2, 1, 0}} { + i, j, k := p[0], p[1], p[2] + t := f(f(s[i], s[j]), s[k]) + if ans == "" || len(t) < len(ans) || (len(t) == len(ans) && t < ans) { + ans = t + } + } + return ans +} diff --git a/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.java b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.java new file mode 100644 index 000000000000..31a8d31b4f3a --- /dev/null +++ b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.java @@ -0,0 +1,39 @@ +class Solution { + public String minimumString(String a, String b, String c) { + String[] s = {a, b, c}; + int[][] perm = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 1, 0}, {2, 0, 1}}; + String ans = ""; + for (var p : perm) { + int i = p[0], j = p[1], k = p[2]; + String t = f(f(s[i], s[j]), s[k]); + if ("".equals(ans) || t.length() < ans.length() + || (t.length() == ans.length() && t.compareTo(ans) < 0)) { + ans = t; + } + } + return ans; + } + + private String f(String s, String t) { + if (s.contains(t)) { + return s; + } + if (t.contains(s)) { + return t; + } + char[] p = (t + "#" + s + "$").toCharArray(); + int n = p.length; + int[] next = new int[n]; + next[0] = -1; + for (int i = 2, j = 0; i < n;) { + if (p[i - 1] == p[j]) { + next[i++] = ++j; + } else if (j > 0) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.substring(next[n - 1]); + } +} diff --git a/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.py b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.py new file mode 100644 index 000000000000..7de9d467ba27 --- /dev/null +++ b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.py @@ -0,0 +1,30 @@ +class Solution: + def minimumString(self, a: str, b: str, c: str) -> str: + def f(s: str, t: str) -> str: + if s in t: + return t + if t in s: + return s + p = t + "#" + s + "$" + n = len(p) + next = [0] * n + next[0] = -1 + i, j = 2, 0 + while i < n: + if p[i - 1] == p[j]: + j += 1 + next[i] = j + i += 1 + elif j: + j = next[j] + else: + next[i] = 0 + i += 1 + return s + t[next[-1] :] + + ans = "" + for a, b, c in permutations((a, b, c)): + s = f(f(a, b), c) + if ans == "" or len(s) < len(ans) or (len(s) == len(ans) and s < ans): + ans = s + return ans diff --git a/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.ts b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.ts new file mode 100644 index 000000000000..ecaffc506ee3 --- /dev/null +++ b/solution/2800-2899/2800.Shortest String That Contains Three Strings/Solution2.ts @@ -0,0 +1,41 @@ +function minimumString(a: string, b: string, c: string): string { + const f = (s: string, t: string): string => { + if (s.includes(t)) { + return s; + } + if (t.includes(s)) { + return t; + } + const p = t + '#' + s + '$'; + const n = p.length; + const next: number[] = Array(n).fill(0); + next[0] = -1; + for (let i = 2, j = 0; i < n; ) { + if (p[i - 1] === p[j]) { + next[i++] = ++j; + } else if (j) { + j = next[j]; + } else { + next[i++] = 0; + } + } + return s + t.slice(next[n - 1]); + }; + const s: string[] = [a, b, c]; + const perm: number[][] = [ + [0, 1, 2], + [0, 2, 1], + [1, 0, 2], + [1, 2, 0], + [2, 0, 1], + [2, 1, 0], + ]; + let ans = ''; + for (const [i, j, k] of perm) { + const t = f(f(s[i], s[j]), s[k]); + if (ans === '' || t.length < ans.length || (t.length === ans.length && t < ans)) { + ans = t; + } + } + return ans; +} diff --git a/solution/2800-2899/2803.Factorial Generator/README.md b/solution/2800-2899/2803.Factorial Generator/README.md index f6cf94a711fb..81cef38d3940 100644 --- a/solution/2800-2899/2803.Factorial Generator/README.md +++ b/solution/2800-2899/2803.Factorial Generator/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2803.Factorial%20Generator/README.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2803.Factorial Generator/README_EN.md b/solution/2800-2899/2803.Factorial Generator/README_EN.md index aa1c6618d658..835f0db09c1e 100644 --- a/solution/2800-2899/2803.Factorial Generator/README_EN.md +++ b/solution/2800-2899/2803.Factorial Generator/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2803.Factorial%20Generator/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2804.Array Prototype ForEach/README.md b/solution/2800-2899/2804.Array Prototype ForEach/README.md index 3f9d8411e259..3c229e443e8d 100644 --- a/solution/2800-2899/2804.Array Prototype ForEach/README.md +++ b/solution/2800-2899/2804.Array Prototype ForEach/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2804.Array%20Prototype%20ForEach/README.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2804.Array Prototype ForEach/README_EN.md b/solution/2800-2899/2804.Array Prototype ForEach/README_EN.md index 740cf473818c..ebae3a2b49e1 100644 --- a/solution/2800-2899/2804.Array Prototype ForEach/README_EN.md +++ b/solution/2800-2899/2804.Array Prototype ForEach/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2804.Array%20Prototype%20ForEach/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2805.Custom Interval/README.md b/solution/2800-2899/2805.Custom Interval/README.md index 985f65d2bbea..e98c804a265c 100644 --- a/solution/2800-2899/2805.Custom Interval/README.md +++ b/solution/2800-2899/2805.Custom Interval/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2805.Custom%20Interval/README.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2805.Custom Interval/README_EN.md b/solution/2800-2899/2805.Custom Interval/README_EN.md index 87d320b8e806..4dd385cff197 100644 --- a/solution/2800-2899/2805.Custom Interval/README_EN.md +++ b/solution/2800-2899/2805.Custom Interval/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2805.Custom%20Interval/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2820.Election Results/README.md b/solution/2800-2899/2820.Election Results/README.md index 761e0bf9fee4..c656c6428c57 100644 --- a/solution/2800-2899/2820.Election Results/README.md +++ b/solution/2800-2899/2820.Election Results/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2820.Election%20Results/README.md +tags: + - 数据库 --- diff --git a/solution/2800-2899/2820.Election Results/README_EN.md b/solution/2800-2899/2820.Election Results/README_EN.md index cb090789ea85..daf1cdb09e1a 100644 --- a/solution/2800-2899/2820.Election Results/README_EN.md +++ b/solution/2800-2899/2820.Election Results/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2820.Election%20Results/README_EN.md +tags: + - Database --- diff --git a/solution/2800-2899/2821.Delay the Resolution of Each Promise/README.md b/solution/2800-2899/2821.Delay the Resolution of Each Promise/README.md index 4593531c0184..1c93e9f109bf 100644 --- a/solution/2800-2899/2821.Delay the Resolution of Each Promise/README.md +++ b/solution/2800-2899/2821.Delay the Resolution of Each Promise/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2821.Delay%20the%20Resolution%20of%20Each%20Promise/README.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2821.Delay the Resolution of Each Promise/README_EN.md b/solution/2800-2899/2821.Delay the Resolution of Each Promise/README_EN.md index 3809fbe31e8e..eab4885d253a 100644 --- a/solution/2800-2899/2821.Delay the Resolution of Each Promise/README_EN.md +++ b/solution/2800-2899/2821.Delay the Resolution of Each Promise/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2821.Delay%20the%20Resolution%20of%20Each%20Promise/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2822.Inversion of Object/README.md b/solution/2800-2899/2822.Inversion of Object/README.md index 100037565b13..fef09427b52c 100644 --- a/solution/2800-2899/2822.Inversion of Object/README.md +++ b/solution/2800-2899/2822.Inversion of Object/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2822.Inversion%20of%20Object/README.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2822.Inversion of Object/README_EN.md b/solution/2800-2899/2822.Inversion of Object/README_EN.md index 45a35931e6be..e5f9fb67735c 100644 --- a/solution/2800-2899/2822.Inversion of Object/README_EN.md +++ b/solution/2800-2899/2822.Inversion of Object/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2822.Inversion%20of%20Object/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2823.Deep Object Filter/README.md b/solution/2800-2899/2823.Deep Object Filter/README.md index 6ce29b13fd65..8a7477c2a66f 100644 --- a/solution/2800-2899/2823.Deep Object Filter/README.md +++ b/solution/2800-2899/2823.Deep Object Filter/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2823.Deep%20Object%20Filter/README.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2823.Deep Object Filter/README_EN.md b/solution/2800-2899/2823.Deep Object Filter/README_EN.md index c8a702e4a9da..6df8bfe6ed53 100644 --- a/solution/2800-2899/2823.Deep Object Filter/README_EN.md +++ b/solution/2800-2899/2823.Deep Object Filter/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2823.Deep%20Object%20Filter/README_EN.md +tags: + - JavaScript --- diff --git a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md index 3634817955d0..7b1fa3d3b7ba 100644 --- a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md +++ b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md @@ -144,18 +144,18 @@ public: int n = num.size(); int f[n][25]; memset(f, -1, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](auto&& dfs, int i, int k) -> int { if (i == n) { return k == 0 ? 0 : n; } if (f[i][k] != -1) { return f[i][k]; } - f[i][k] = dfs(i + 1, k) + 1; - f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25)); + f[i][k] = dfs(dfs, i + 1, k) + 1; + f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25)); return f[i][k]; }; - return dfs(0, 0); + return dfs(dfs, 0, 0); } }; ``` diff --git a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md index de2bc8aaa406..6308ad3d9db7 100644 --- a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md +++ b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md @@ -141,18 +141,18 @@ public: int n = num.size(); int f[n][25]; memset(f, -1, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](auto&& dfs, int i, int k) -> int { if (i == n) { return k == 0 ? 0 : n; } if (f[i][k] != -1) { return f[i][k]; } - f[i][k] = dfs(i + 1, k) + 1; - f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25)); + f[i][k] = dfs(dfs, i + 1, k) + 1; + f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25)); return f[i][k]; }; - return dfs(0, 0); + return dfs(dfs, 0, 0); } }; ``` diff --git a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp index 673601a4d7bb..e8a8ee38b3f0 100644 --- a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp +++ b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp @@ -4,17 +4,17 @@ class Solution { int n = num.size(); int f[n][25]; memset(f, -1, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](auto&& dfs, int i, int k) -> int { if (i == n) { return k == 0 ? 0 : n; } if (f[i][k] != -1) { return f[i][k]; } - f[i][k] = dfs(i + 1, k) + 1; - f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25)); + f[i][k] = dfs(dfs, i + 1, k) + 1; + f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25)); return f[i][k]; }; - return dfs(0, 0); + return dfs(dfs, 0, 0); } }; \ No newline at end of file diff --git a/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README.md b/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README.md index d23ab089fe8e..d5b4a743ab76 100644 --- a/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README.md +++ b/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README.md @@ -59,7 +59,13 @@ tags: -### 方法一 +### 方法一:分情况讨论 + +如果起点和终点相同,那么只有当 $t \neq 1$ 时,才能在给定时间到达终点。 + +否则,我们可以计算出起点和终点的横纵坐标之差,然后取最大值,如果最大值小于等于给定时间,那么就可以在给定时间到达终点。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 @@ -143,8 +149,9 @@ function isReachableAtTime(sx: number, sy: number, fx: number, fy: number, t: nu ```cs public class Solution { public bool IsReachableAtTime(int sx, int sy, int fx, int fy, int t) { - if (sx == fx && sy == fy) + if (sx == fx && sy == fy) { return t != 1; + } return Math.Max(Math.Abs(sx - fx), Math.Abs(sy - fy)) <= t; } } diff --git a/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README_EN.md b/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README_EN.md index 2db4ad1b539c..387cdc8de267 100644 --- a/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README_EN.md +++ b/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/README_EN.md @@ -57,7 +57,13 @@ tags: -### Solution 1 +### Solution 1: Case Discussion + +If the starting point and the destination are the same, then we can only reach the destination within the given time if $t \neq 1$. + +Otherwise, we can calculate the difference in the x and y coordinates between the starting point and the destination, and then take the maximum value. If the maximum value is less than or equal to the given time, then we can reach the destination within the given time. + +The time complexity is $O(1)$, and the space complexity is $O(1)$. @@ -141,8 +147,9 @@ function isReachableAtTime(sx: number, sy: number, fx: number, fy: number, t: nu ```cs public class Solution { public bool IsReachableAtTime(int sx, int sy, int fx, int fy, int t) { - if (sx == fx && sy == fy) + if (sx == fx && sy == fy) { return t != 1; + } return Math.Max(Math.Abs(sx - fx), Math.Abs(sy - fy)) <= t; } } diff --git a/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/Solution.cs b/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/Solution.cs index 4e3f78d7f391..376d61513e22 100644 --- a/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/Solution.cs +++ b/solution/2800-2899/2849.Determine if a Cell Is Reachable at a Given Time/Solution.cs @@ -1,7 +1,8 @@ public class Solution { public bool IsReachableAtTime(int sx, int sy, int fx, int fy, int t) { - if (sx == fx && sy == fy) + if (sx == fx && sy == fy) { return t != 1; + } return Math.Max(Math.Abs(sx - fx), Math.Abs(sy - fy)) <= t; } } diff --git a/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README.md b/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README.md index 0ee00e17913b..bb710b3dd427 100644 --- a/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README.md +++ b/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README.md @@ -180,6 +180,91 @@ class Solution { } ``` + + + + + + +### 方法二:状态压缩动态规划 + +我们可以把所有值为 $0$ 的单元格坐标 $(i, j)$ 放入数组 $left$ 中,如果单元格的值 $v$ 大于 $1$,那么我们把 $v-1$ 个坐标 $(i, j)$ 放入数组 $right$ 中。那么问题就转化为,每个 $right$ 中的坐标 $(i, j)$ 都要移动到 $left$ 中的一个坐标 $(x, y)$,求最少的移动次数。 + +我们记 $left$ 的长度为 $n$,那么我们可以使用 $n$ 位二进制数来表示 $left$ 中的每个坐标是否被 $right$ 中的坐标填充,其中 $1$ 表示被填充,而 $0$ 表示未被填充。初始时 $f[i] = \infty$,其余 $f[0]=0$。 + +考虑 $f[i]$,记当前 $i$ 的二进制表示中 $1$ 的个数为 $k$,我们在 $[0..n)$ 的范围内枚举 $j$,如果 $i$ 的第 $j$ 位为 $1$,那么 $f[i]$ 可以由 $f[i \oplus (1 << j)]$ 转移而来,转移的代价为 $cal(left[k-1], right[j])$,其中 $cal$ 表示两个坐标之间的曼哈顿距离。最终答案为 $f[(1 << n) - 1]$。 + +时间复杂度 $O(n \times 2^n)$,空间复杂度 $O(2^n)$。其中 $n$ 表示 $left$ 的长度,本题中 $n \le 9$。 + + + +#### Python3 + +```python +class Solution: + def minimumMoves(self, grid: List[List[int]]) -> int: + def cal(a: tuple, b: tuple) -> int: + return abs(a[0] - b[0]) + abs(a[1] - b[1]) + + left, right = [], [] + for i in range(3): + for j in range(3): + if grid[i][j] == 0: + left.append((i, j)) + else: + for _ in range(grid[i][j] - 1): + right.append((i, j)) + + n = len(left) + f = [inf] * (1 << n) + f[0] = 0 + for i in range(1, 1 << n): + k = i.bit_count() + for j in range(n): + if i >> j & 1: + f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j])) + return f[-1] +``` + +#### Java + +```java +class Solution { + public int minimumMoves(int[][] grid) { + List left = new ArrayList<>(); + List right = new ArrayList<>(); + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + if (grid[i][j] == 0) { + left.add(new int[] {i, j}); + } else { + for (int k = 1; k < grid[i][j]; ++k) { + right.add(new int[] {i, j}); + } + } + } + } + int n = left.size(); + int[] f = new int[1 << n]; + Arrays.fill(f, 1 << 30); + f[0] = 0; + for (int i = 1; i < 1 << n; ++i) { + int k = Integer.bitCount(i); + for (int j = 0; j < n; ++j) { + if ((i >> j & 1) == 1) { + f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j))); + } + } + } + return f[(1 << n) - 1]; + } + + private int cal(int[] a, int[] b) { + return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]); + } +} +``` + #### C++ ```cpp @@ -306,89 +391,4 @@ function minimumMoves(grid: number[][]): number { - - -### 方法二:状态压缩动态规划 - -我们可以把所有值为 $0$ 的单元格坐标 $(i, j)$ 放入数组 $left$ 中,如果单元格的值 $v$ 大于 $1$,那么我们把 $v-1$ 个坐标 $(i, j)$ 放入数组 $right$ 中。那么问题就转化为,每个 $right$ 中的坐标 $(i, j)$ 都要移动到 $left$ 中的一个坐标 $(x, y)$,求最少的移动次数。 - -我们记 $left$ 的长度为 $n$,那么我们可以使用 $n$ 位二进制数来表示 $left$ 中的每个坐标是否被 $right$ 中的坐标填充,其中 $1$ 表示被填充,而 $0$ 表示未被填充。初始时 $f[i] = \infty$,其余 $f[0]=0$。 - -考虑 $f[i]$,记当前 $i$ 的二进制表示中 $1$ 的个数为 $k$,我们在 $[0..n)$ 的范围内枚举 $j$,如果 $i$ 的第 $j$ 位为 $1$,那么 $f[i]$ 可以由 $f[i \oplus (1 << j)]$ 转移而来,转移的代价为 $cal(left[k-1], right[j])$,其中 $cal$ 表示两个坐标之间的曼哈顿距离。最终答案为 $f[(1 << n) - 1]$。 - -时间复杂度 $O(n \times 2^n)$,空间复杂度 $O(2^n)$。其中 $n$ 表示 $left$ 的长度,本题中 $n \le 9$。 - - - -#### Python3 - -```python -class Solution: - def minimumMoves(self, grid: List[List[int]]) -> int: - def cal(a: tuple, b: tuple) -> int: - return abs(a[0] - b[0]) + abs(a[1] - b[1]) - - left, right = [], [] - for i in range(3): - for j in range(3): - if grid[i][j] == 0: - left.append((i, j)) - else: - for _ in range(grid[i][j] - 1): - right.append((i, j)) - - n = len(left) - f = [inf] * (1 << n) - f[0] = 0 - for i in range(1, 1 << n): - k = i.bit_count() - for j in range(n): - if i >> j & 1: - f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j])) - return f[-1] -``` - -#### Java - -```java -class Solution { - public int minimumMoves(int[][] grid) { - List left = new ArrayList<>(); - List right = new ArrayList<>(); - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - if (grid[i][j] == 0) { - left.add(new int[] {i, j}); - } else { - for (int k = 1; k < grid[i][j]; ++k) { - right.add(new int[] {i, j}); - } - } - } - } - int n = left.size(); - int[] f = new int[1 << n]; - Arrays.fill(f, 1 << 30); - f[0] = 0; - for (int i = 1; i < 1 << n; ++i) { - int k = Integer.bitCount(i); - for (int j = 0; j < n; ++j) { - if ((i >> j & 1) == 1) { - f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j))); - } - } - } - return f[(1 << n) - 1]; - } - - private int cal(int[] a, int[] b) { - return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]); - } -} -``` - - - - - diff --git a/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README_EN.md b/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README_EN.md index ed438d555fb9..5d21c5379092 100644 --- a/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README_EN.md +++ b/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/README_EN.md @@ -174,6 +174,91 @@ class Solution { } ``` + + + + + + +### Solution 2: State Compression Dynamic Programming + +We can put all the coordinates $(i, j)$ of cells with a value of $0$ into an array $left$. If the value $v$ of a cell is greater than $1$, we put $v-1$ coordinates $(i, j)$ into an array $right$. The problem then becomes that each coordinate $(i, j)$ in $right$ needs to be moved to a coordinate $(x, y)$ in $left$, and we need to find the minimum number of moves. + +Let's denote the length of $left$ as $n$. We can use an $n$-bit binary number to represent whether each coordinate in $left$ is filled by a coordinate in $right$, where $1$ represents being filled, and $0$ represents not being filled. Initially, $f[i] = \infty$, and the rest $f[0]=0$. + +Consider $f[i]$, let the number of $1$s in the binary representation of $i$ be $k$. We enumerate $j$ in the range $[0..n)$, if the $j$th bit of $i$ is $1$, then $f[i]$ can be transferred from $f[i \oplus (1 << j)]$, and the cost of the transfer is $cal(left[k-1], right[j])$, where $cal$ represents the Manhattan distance between two coordinates. The final answer is $f[(1 << n) - 1]$. + +The time complexity is $O(n \times 2^n)$, and the space complexity is $O(2^n)$. Here, $n$ is the length of $left$, and in this problem, $n \le 9$. + + + +#### Python3 + +```python +class Solution: + def minimumMoves(self, grid: List[List[int]]) -> int: + def cal(a: tuple, b: tuple) -> int: + return abs(a[0] - b[0]) + abs(a[1] - b[1]) + + left, right = [], [] + for i in range(3): + for j in range(3): + if grid[i][j] == 0: + left.append((i, j)) + else: + for _ in range(grid[i][j] - 1): + right.append((i, j)) + + n = len(left) + f = [inf] * (1 << n) + f[0] = 0 + for i in range(1, 1 << n): + k = i.bit_count() + for j in range(n): + if i >> j & 1: + f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j])) + return f[-1] +``` + +#### Java + +```java +class Solution { + public int minimumMoves(int[][] grid) { + List left = new ArrayList<>(); + List right = new ArrayList<>(); + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + if (grid[i][j] == 0) { + left.add(new int[] {i, j}); + } else { + for (int k = 1; k < grid[i][j]; ++k) { + right.add(new int[] {i, j}); + } + } + } + } + int n = left.size(); + int[] f = new int[1 << n]; + Arrays.fill(f, 1 << 30); + f[0] = 0; + for (int i = 1; i < 1 << n; ++i) { + int k = Integer.bitCount(i); + for (int j = 0; j < n; ++j) { + if ((i >> j & 1) == 1) { + f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j))); + } + } + } + return f[(1 << n) - 1]; + } + + private int cal(int[] a, int[] b) { + return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]); + } +} +``` + #### C++ ```cpp @@ -300,89 +385,4 @@ function minimumMoves(grid: number[][]): number { - - -### Solution 2: State Compression Dynamic Programming - -We can put all the coordinates $(i, j)$ of cells with a value of $0$ into an array $left$. If the value $v$ of a cell is greater than $1$, we put $v-1$ coordinates $(i, j)$ into an array $right$. The problem then becomes that each coordinate $(i, j)$ in $right$ needs to be moved to a coordinate $(x, y)$ in $left$, and we need to find the minimum number of moves. - -Let's denote the length of $left$ as $n$. We can use an $n$-bit binary number to represent whether each coordinate in $left$ is filled by a coordinate in $right$, where $1$ represents being filled, and $0$ represents not being filled. Initially, $f[i] = \infty$, and the rest $f[0]=0$. - -Consider $f[i]$, let the number of $1$s in the binary representation of $i$ be $k$. We enumerate $j$ in the range $[0..n)$, if the $j$th bit of $i$ is $1$, then $f[i]$ can be transferred from $f[i \oplus (1 << j)]$, and the cost of the transfer is $cal(left[k-1], right[j])$, where $cal$ represents the Manhattan distance between two coordinates. The final answer is $f[(1 << n) - 1]$. - -The time complexity is $O(n \times 2^n)$, and the space complexity is $O(2^n)$. Here, $n$ is the length of $left$, and in this problem, $n \le 9$. - - - -#### Python3 - -```python -class Solution: - def minimumMoves(self, grid: List[List[int]]) -> int: - def cal(a: tuple, b: tuple) -> int: - return abs(a[0] - b[0]) + abs(a[1] - b[1]) - - left, right = [], [] - for i in range(3): - for j in range(3): - if grid[i][j] == 0: - left.append((i, j)) - else: - for _ in range(grid[i][j] - 1): - right.append((i, j)) - - n = len(left) - f = [inf] * (1 << n) - f[0] = 0 - for i in range(1, 1 << n): - k = i.bit_count() - for j in range(n): - if i >> j & 1: - f[i] = min(f[i], f[i ^ (1 << j)] + cal(left[k - 1], right[j])) - return f[-1] -``` - -#### Java - -```java -class Solution { - public int minimumMoves(int[][] grid) { - List left = new ArrayList<>(); - List right = new ArrayList<>(); - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - if (grid[i][j] == 0) { - left.add(new int[] {i, j}); - } else { - for (int k = 1; k < grid[i][j]; ++k) { - right.add(new int[] {i, j}); - } - } - } - } - int n = left.size(); - int[] f = new int[1 << n]; - Arrays.fill(f, 1 << 30); - f[0] = 0; - for (int i = 1; i < 1 << n; ++i) { - int k = Integer.bitCount(i); - for (int j = 0; j < n; ++j) { - if ((i >> j & 1) == 1) { - f[i] = Math.min(f[i], f[i ^ (1 << j)] + cal(left.get(k - 1), right.get(j))); - } - } - } - return f[(1 << n) - 1]; - } - - private int cal(int[] a, int[] b) { - return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]); - } -} -``` - - - - - diff --git a/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution.cpp b/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution2.cpp similarity index 100% rename from solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution.cpp rename to solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution2.cpp diff --git a/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution.go b/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution2.go similarity index 100% rename from solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution.go rename to solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution2.go diff --git a/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution.ts b/solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution2.ts similarity index 100% rename from solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution.ts rename to solution/2800-2899/2850.Minimum Moves to Spread Stones Over Grid/Solution2.ts diff --git a/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README.md b/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README.md index dbf5509786a4..c12c29a77c75 100644 --- a/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README.md +++ b/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README.md @@ -3,9 +3,10 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2863.Maximum%20Length%20of%20Semi-Decreasing%20Subarrays/README.md tags: + - 栈 - 数组 - - 哈希表 - 排序 + - 单调栈 --- diff --git a/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README_EN.md b/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README_EN.md index e105f445388c..ade4347e4ff3 100644 --- a/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README_EN.md +++ b/solution/2800-2899/2863.Maximum Length of Semi-Decreasing Subarrays/README_EN.md @@ -3,9 +3,10 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2863.Maximum%20Length%20of%20Semi-Decreasing%20Subarrays/README_EN.md tags: + - Stack - Array - - Hash Table - Sorting + - Monotonic Stack --- diff --git a/solution/2800-2899/2865.Beautiful Towers I/README.md b/solution/2800-2899/2865.Beautiful Towers I/README.md index 421a86d5f463..485a5227c4a5 100644 --- a/solution/2800-2899/2865.Beautiful Towers I/README.md +++ b/solution/2800-2899/2865.Beautiful Towers I/README.md @@ -230,8 +230,8 @@ function maximumSumOfHeights(maxHeights: number[]): number { $$ f[i]= \begin{cases} -f[i-1]+heights[i],&\text{if } heights[i]\geq heights[i-1]\\ -heights[i]\times(i-j)+f[j],&\text{if } heights[i] diff --git a/solution/2800-2899/2877.Create a DataFrame from List/README_EN.md b/solution/2800-2899/2877.Create a DataFrame from List/README_EN.md index 32afc51ca9dd..edf701da0859 100644 --- a/solution/2800-2899/2877.Create a DataFrame from List/README_EN.md +++ b/solution/2800-2899/2877.Create a DataFrame from List/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2877.Create%20a%20DataFrame%20from%20List/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2878.Get the Size of a DataFrame/README.md b/solution/2800-2899/2878.Get the Size of a DataFrame/README.md index 9660a5cdb261..f8ac06b407d7 100644 --- a/solution/2800-2899/2878.Get the Size of a DataFrame/README.md +++ b/solution/2800-2899/2878.Get the Size of a DataFrame/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2878.Get%20the%20Size%20of%20a%20DataFrame/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2878.Get the Size of a DataFrame/README_EN.md b/solution/2800-2899/2878.Get the Size of a DataFrame/README_EN.md index b46e2458fa5f..44aafb3521ad 100644 --- a/solution/2800-2899/2878.Get the Size of a DataFrame/README_EN.md +++ b/solution/2800-2899/2878.Get the Size of a DataFrame/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2878.Get%20the%20Size%20of%20a%20DataFrame/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2879.Display the First Three Rows/README.md b/solution/2800-2899/2879.Display the First Three Rows/README.md index 700d7332cfe9..f92ecef09dc7 100644 --- a/solution/2800-2899/2879.Display the First Three Rows/README.md +++ b/solution/2800-2899/2879.Display the First Three Rows/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2879.Display%20the%20First%20Three%20Rows/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2879.Display the First Three Rows/README_EN.md b/solution/2800-2899/2879.Display the First Three Rows/README_EN.md index 333b19d90384..9725066b10ca 100644 --- a/solution/2800-2899/2879.Display the First Three Rows/README_EN.md +++ b/solution/2800-2899/2879.Display the First Three Rows/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2879.Display%20the%20First%20Three%20Rows/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2880.Select Data/README.md b/solution/2800-2899/2880.Select Data/README.md index ca31248031f6..499237bb2f32 100644 --- a/solution/2800-2899/2880.Select Data/README.md +++ b/solution/2800-2899/2880.Select Data/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2880.Select%20Data/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2880.Select Data/README_EN.md b/solution/2800-2899/2880.Select Data/README_EN.md index 8171f65bcc5e..12b460402074 100644 --- a/solution/2800-2899/2880.Select Data/README_EN.md +++ b/solution/2800-2899/2880.Select Data/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2880.Select%20Data/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2881.Create a New Column/README.md b/solution/2800-2899/2881.Create a New Column/README.md index 74d3e4c670bc..08a5525b4709 100644 --- a/solution/2800-2899/2881.Create a New Column/README.md +++ b/solution/2800-2899/2881.Create a New Column/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2881.Create%20a%20New%20Column/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2881.Create a New Column/README_EN.md b/solution/2800-2899/2881.Create a New Column/README_EN.md index 4fd045a988ab..ecd3c86203ab 100644 --- a/solution/2800-2899/2881.Create a New Column/README_EN.md +++ b/solution/2800-2899/2881.Create a New Column/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2881.Create%20a%20New%20Column/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2882.Drop Duplicate Rows/README.md b/solution/2800-2899/2882.Drop Duplicate Rows/README.md index d8aeab0f6458..95ae1ad2542b 100644 --- a/solution/2800-2899/2882.Drop Duplicate Rows/README.md +++ b/solution/2800-2899/2882.Drop Duplicate Rows/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2882.Drop%20Duplicate%20Rows/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2882.Drop Duplicate Rows/README_EN.md b/solution/2800-2899/2882.Drop Duplicate Rows/README_EN.md index fb7f0143196d..8d5c27c61209 100644 --- a/solution/2800-2899/2882.Drop Duplicate Rows/README_EN.md +++ b/solution/2800-2899/2882.Drop Duplicate Rows/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2882.Drop%20Duplicate%20Rows/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2883.Drop Missing Data/README.md b/solution/2800-2899/2883.Drop Missing Data/README.md index 1e4ff66875c0..99fe13d35746 100644 --- a/solution/2800-2899/2883.Drop Missing Data/README.md +++ b/solution/2800-2899/2883.Drop Missing Data/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2883.Drop%20Missing%20Data/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2883.Drop Missing Data/README_EN.md b/solution/2800-2899/2883.Drop Missing Data/README_EN.md index 64f0838e4c8f..abc89e35ef8e 100644 --- a/solution/2800-2899/2883.Drop Missing Data/README_EN.md +++ b/solution/2800-2899/2883.Drop Missing Data/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2883.Drop%20Missing%20Data/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2884.Modify Columns/README.md b/solution/2800-2899/2884.Modify Columns/README.md index d4b2eccf7a70..fa9f451c1ab7 100644 --- a/solution/2800-2899/2884.Modify Columns/README.md +++ b/solution/2800-2899/2884.Modify Columns/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2884.Modify%20Columns/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2884.Modify Columns/README_EN.md b/solution/2800-2899/2884.Modify Columns/README_EN.md index 80f207ac1be1..01542f5b8611 100644 --- a/solution/2800-2899/2884.Modify Columns/README_EN.md +++ b/solution/2800-2899/2884.Modify Columns/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2884.Modify%20Columns/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2885.Rename Columns/README.md b/solution/2800-2899/2885.Rename Columns/README.md index d550d2185c24..e0cd4a02ee73 100644 --- a/solution/2800-2899/2885.Rename Columns/README.md +++ b/solution/2800-2899/2885.Rename Columns/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2885.Rename%20Columns/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2885.Rename Columns/README_EN.md b/solution/2800-2899/2885.Rename Columns/README_EN.md index e24aab23a786..f57d8137e20c 100644 --- a/solution/2800-2899/2885.Rename Columns/README_EN.md +++ b/solution/2800-2899/2885.Rename Columns/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2885.Rename%20Columns/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2886.Change Data Type/README.md b/solution/2800-2899/2886.Change Data Type/README.md index 38ea16abdbc1..cfc18d75f36c 100644 --- a/solution/2800-2899/2886.Change Data Type/README.md +++ b/solution/2800-2899/2886.Change Data Type/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2886.Change%20Data%20Type/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2886.Change Data Type/README_EN.md b/solution/2800-2899/2886.Change Data Type/README_EN.md index 062bacbfe3ea..f4ab80750444 100644 --- a/solution/2800-2899/2886.Change Data Type/README_EN.md +++ b/solution/2800-2899/2886.Change Data Type/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2886.Change%20Data%20Type/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2887.Fill Missing Data/README.md b/solution/2800-2899/2887.Fill Missing Data/README.md index 3e6078bbb8a7..3776c79465fb 100644 --- a/solution/2800-2899/2887.Fill Missing Data/README.md +++ b/solution/2800-2899/2887.Fill Missing Data/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2887.Fill%20Missing%20Data/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2887.Fill Missing Data/README_EN.md b/solution/2800-2899/2887.Fill Missing Data/README_EN.md index 86778d37f36c..7233e0fa47d0 100644 --- a/solution/2800-2899/2887.Fill Missing Data/README_EN.md +++ b/solution/2800-2899/2887.Fill Missing Data/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2887.Fill%20Missing%20Data/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2888.Reshape Data Concatenate/README.md b/solution/2800-2899/2888.Reshape Data Concatenate/README.md index cc3aa84a48f8..2563dbf6407c 100644 --- a/solution/2800-2899/2888.Reshape Data Concatenate/README.md +++ b/solution/2800-2899/2888.Reshape Data Concatenate/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2888.Reshape%20Data%20Concatenate/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2888.Reshape Data Concatenate/README_EN.md b/solution/2800-2899/2888.Reshape Data Concatenate/README_EN.md index 5b45dd97d008..3b42ddab775c 100644 --- a/solution/2800-2899/2888.Reshape Data Concatenate/README_EN.md +++ b/solution/2800-2899/2888.Reshape Data Concatenate/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2888.Reshape%20Data%20Concatenate/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2889.Reshape Data Pivot/README.md b/solution/2800-2899/2889.Reshape Data Pivot/README.md index 8923d1fc11d4..bd8120bc5778 100644 --- a/solution/2800-2899/2889.Reshape Data Pivot/README.md +++ b/solution/2800-2899/2889.Reshape Data Pivot/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2889.Reshape%20Data%20Pivot/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2889.Reshape Data Pivot/README_EN.md b/solution/2800-2899/2889.Reshape Data Pivot/README_EN.md index 9680804a47b2..28249d662920 100644 --- a/solution/2800-2899/2889.Reshape Data Pivot/README_EN.md +++ b/solution/2800-2899/2889.Reshape Data Pivot/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2889.Reshape%20Data%20Pivot/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2890.Reshape Data Melt/README.md b/solution/2800-2899/2890.Reshape Data Melt/README.md index 161eee0fa89f..b4acedbc6077 100644 --- a/solution/2800-2899/2890.Reshape Data Melt/README.md +++ b/solution/2800-2899/2890.Reshape Data Melt/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2890.Reshape%20Data%20Melt/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2890.Reshape Data Melt/README_EN.md b/solution/2800-2899/2890.Reshape Data Melt/README_EN.md index 407efa672910..46f20e1fe894 100644 --- a/solution/2800-2899/2890.Reshape Data Melt/README_EN.md +++ b/solution/2800-2899/2890.Reshape Data Melt/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2890.Reshape%20Data%20Melt/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2891.Method Chaining/README.md b/solution/2800-2899/2891.Method Chaining/README.md index 8706dee377ed..7475f5d65277 100644 --- a/solution/2800-2899/2891.Method Chaining/README.md +++ b/solution/2800-2899/2891.Method Chaining/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2891.Method%20Chaining/README.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2891.Method Chaining/README_EN.md b/solution/2800-2899/2891.Method Chaining/README_EN.md index 920428e4cd7f..946ce123a15d 100644 --- a/solution/2800-2899/2891.Method Chaining/README_EN.md +++ b/solution/2800-2899/2891.Method Chaining/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/2800-2899/2891.Method%20Chaining/README_EN.md +tags: + - Pandas --- diff --git a/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README.md b/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README.md index 823141e72cc2..22b8b60cf291 100644 --- a/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README.md +++ b/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README.md @@ -76,7 +76,7 @@ tags: ### 方法一:位运算 + 贪心 -根据题目描述,对于一个操作,我们可以将 $nums[i]$ 变为 $nums[i] \text{ AND } nums[j]$,将 $nums[j]$ 变为 $nums[i] \text{ OR } nums[j]$。我们不妨按位考虑,两个 $1$ 或两个 $0$ 进行这样的操作,结果都不会改变,如果是 $1$ 和 $0$ 进行这样的操作,结果会变成 $0$ 和 $1$,也即是说,我们可以将 $1$ 转移到 $0$ 上,而 $0$ 不会转移到 $1$ 上。 +根据题目描述,对于一个操作,我们可以将 $nums[i]$ 变为 $nums[i] \textit{ AND } nums[j]$,将 $nums[j]$ 变为 $nums[i] \textit{ OR } nums[j]$。我们不妨按位考虑,两个 $1$ 或两个 $0$ 进行这样的操作,结果都不会改变,如果是 $1$ 和 $0$ 进行这样的操作,结果会变成 $0$ 和 $1$,也即是说,我们可以将 $1$ 转移到 $0$ 上,而 $0$ 不会转移到 $1$ 上。 因此,我们可以用一个数组 $cnt$ 统计每个位置上 $1$ 的个数,然后从中选择 $k$ 个数。由于要使得平方和最大,每次选择的数要尽可能大。这是因为,假设两个数的平方和为 $a^2 + b^2$(其中 $a \gt b$),将两个数平方和变成 $(a + c)^2 + (b - c)^2 = a^2 + b^2 + 2c(a - b) + 2c^2 \gt a^2 + b^2$。因此,为了最大化平方和,我们应该让一个数字尽可能大。 diff --git a/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README_EN.md b/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README_EN.md index 259b35944606..da6294cf1553 100644 --- a/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README_EN.md +++ b/solution/2800-2899/2897.Apply Operations on Array to Maximize Sum of Squares/README_EN.md @@ -74,7 +74,7 @@ It can be shown that this is the maximum value we can get. ### Solution 1: Bitwise Operation + Greedy -According to the problem description, for an operation, we can change $nums[i]$ to $nums[i] \text{ AND } nums[j]$, and change $nums[j]$ to $nums[i] \text{ OR } nums[j]$. Let's consider the bits of the numbers. If two bits are both $1$ or both $0$, the result of the operation will not change the bits. If two bits are different, the result of the operation will change the bits to $0$ and $1$, respectively. Therefore, we can move $1$ bits to $0$ bits, but not vice versa. +According to the problem description, for an operation, we can change $nums[i]$ to $nums[i] \textit{ AND } nums[j]$, and change $nums[j]$ to $nums[i] \textit{ OR } nums[j]$. Let's consider the bits of the numbers. If two bits are both $1$ or both $0$, the result of the operation will not change the bits. If two bits are different, the result of the operation will change the bits to $0$ and $1$, respectively. Therefore, we can move $1$ bits to $0$ bits, but not vice versa. We can use an array $cnt$ to count the number of $1$ bits in each position, and then select $k$ numbers from them. To maximize the sum of squares, we should choose the largest numbers as much as possible. This is because, assuming the sum of squares of two numbers is $a^2 + b^2$ (where $a \gt b$), changing them to $(a + c)^2 + (b - c)^2 = a^2 + b^2 + 2c(a - b) + 2c^2 \gt a^2 + b^2$ will increase the sum of squares. Therefore, to maximize the sum of squares, we should choose the largest number. diff --git a/solution/2800-2899/2899.Last Visited Integers/README.md b/solution/2800-2899/2899.Last Visited Integers/README.md index c030ac79f138..b320cec12a16 100644 --- a/solution/2800-2899/2899.Last Visited Integers/README.md +++ b/solution/2800-2899/2899.Last Visited Integers/README.md @@ -61,7 +61,7 @@ tags: 1.处理 nums[0]:nums 中的第一个元素是 1。我们将其放在 seen 的前面。现在,seen == [1]。 2.处理 nums[1]:下一个元素是 -1。这是 -1 的第一次出现,所以 k == 1。我们找到 seen 中的第一个元素,即 1。把 1 添加到 ans。现在,ans == [1]。 3.处理 nums[2]:下一个元素是 2。我们将其放在 seen 的前面。现在,seen == [2, 1]。 -4.处理 nums[3]:下一个元素是 -1。这个 -1 与 第一个 -1 不连续,因为中间有个 2。因此,k 重置为 1。seen 中的第一个元素是 2,所以我们把 2 添加到 ans。现在,ans == [2, 2]。 +4.处理 nums[3]:下一个元素是 -1。这个 -1 与 第一个 -1 不连续,因为中间有个 2。因此,k 重置为 1。seen 中的第一个元素是 2,所以我们把 2 添加到 ans。现在,ans == [1, 2]。 5.处理 nums[4]:又一个 -1。它与前一个 -1 相邻,所以 k == 2。seen 中的第 2 个元素是 1。把 1 添加到 ans。最终,ans == [1, 2, 1]。
    diff --git a/solution/2900-2999/2956.Find Common Elements Between Two Arrays/README.md b/solution/2900-2999/2956.Find Common Elements Between Two Arrays/README.md index 43429501f930..e40547edf99b 100644 --- a/solution/2900-2999/2956.Find Common Elements Between Two Arrays/README.md +++ b/solution/2900-2999/2956.Find Common Elements Between Two Arrays/README.md @@ -19,36 +19,54 @@ tags: -

    给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,它们分别含有 n 和 m 个元素。

    - -

    请你计算以下两个数值:

    +

    给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,它们分别含有 n 和 m 个元素。请你计算以下两个数值:

      -
    • 统计 0 <= i < n 中的下标 i ,满足 nums1[i] 在 nums2 中 至少 出现了一次。
    • -
    • 统计 0 <= i < m 中的下标 i ,满足 nums2[i] 在 nums1 中 至少 出现了一次。
    • +
    • answer1:使得 nums1[i] 在 nums2 中出现的下标 i 的数量。
    • +
    • answer2:使得 nums2[i] 在 nums1 中出现的下标 i 的数量。
    -

    请你返回一个长度为 2 的整数数组 answer ,按顺序 分别为以上两个数值。

    +

    返回 [answer1, answer2]

     

    示例 1:

    -
    -输入:nums1 = [4,3,2,3,1], nums2 = [2,2,5,2,3,6]
    -输出:[3,4]
    -解释:分别计算两个数值:
    -- nums1 中下标为 1 ,2 和 3 的元素在 nums2 中至少出现了一次,所以第一个值为 3 。
    -- nums2 中下标为 0 ,1 ,3 和 4 的元素在 nums1 中至少出现了一次,所以第二个值为 4 。
    -
    +
    +

    输入:nums1 = [2,3,2], nums2 = [1,2]

    + +

    输出:[2,1]

    + +

    解释:

    + +

    +

    示例 2:

    -
    -输入:nums1 = [3,4,2,3], nums2 = [1,5]
    -输出:[0,0]
    -解释:两个数组中没有公共元素,所以两个值都为 0 。
    -
    +
    +

    输入:nums1 = [4,3,2,3,1], nums2 = [2,2,5,2,3,6]

    + +

    输出:[3,4]

    + +

    解释:

    + +

    nums1 中下标在 1,2,3 的元素在 nums2 中也存在。所以 answer1 为 3。

    + +

    nums2 中下标在 0,1,3,4 的元素在 nums1 中也存在。所以 answer2 为 4。

    +
    + +

    示例 3:

    + +
    +

    输入:nums1 = [3,4,2,3], nums2 = [1,5]

    + +

    输出:[0,0]

    + +

    解释:

    + +

    nums1 和 nums2 中没有相同的数字,所以答案是 [0,0]。

    +

     

    diff --git a/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README.md b/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README.md index cfda725e63bd..2c94f18124a6 100644 --- a/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README.md +++ b/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README.md @@ -123,7 +123,7 @@ class Solution: for mask in range(1 << n): g = [[inf] * n for _ in range(n)] for u, v, w in roads: - if mask >> u & 1 and mask > v & 1: + if mask >> u & 1 and mask >> v & 1: g[u][v] = min(g[u][v], w) g[v][u] = min(g[v][u], w) for k in range(n): diff --git a/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README_EN.md b/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README_EN.md index 25f003b42b0a..45f6717a7d28 100644 --- a/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README_EN.md +++ b/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/README_EN.md @@ -117,7 +117,7 @@ class Solution: for mask in range(1 << n): g = [[inf] * n for _ in range(n)] for u, v, w in roads: - if mask >> u & 1 and mask > v & 1: + if mask >> u & 1 and mask >> v & 1: g[u][v] = min(g[u][v], w) g[v][u] = min(g[v][u], w) for k in range(n): diff --git a/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/Solution.py b/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/Solution.py index 3ab1fdac6262..80bb9851a5dd 100644 --- a/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/Solution.py +++ b/solution/2900-2999/2959.Number of Possible Sets of Closing Branches/Solution.py @@ -4,7 +4,7 @@ def numberOfSets(self, n: int, maxDistance: int, roads: List[List[int]]) -> int: for mask in range(1 << n): g = [[inf] * n for _ in range(n)] for u, v, w in roads: - if mask >> u & 1 and mask > v & 1: + if mask >> u & 1 and mask >> v & 1: g[u][v] = min(g[u][v], w) g[v][u] = min(g[v][u], w) for k in range(n): diff --git a/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README.md b/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README.md index 2d9dd8dd08c5..84626ae37db8 100644 --- a/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README.md +++ b/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README.md @@ -89,14 +89,14 @@ tags: $$ \begin{aligned} -\text{left} &= \sum_{k = i}^{(i + j) / 2 - 1} (nums[(i + j) / 2] - nums[k]) \\ +\textit{left} &= \sum_{k = i}^{(i + j) / 2 - 1} (nums[(i + j) / 2] - nums[k]) \\ &= ((i + j) / 2 - i) \times nums[(i + j) / 2] - \sum_{k = i}^{(i + j) / 2 - 1} nums[k] \end{aligned} $$ $$ \begin{aligned} -\text{right} &= \sum_{k = (i + j) / 2 + 1}^{j} (nums[k] - nums[(i + j) / 2]) \\ +\textit{right} &= \sum_{k = (i + j) / 2 + 1}^{j} (nums[k] - nums[(i + j) / 2]) \\ &= \sum_{k = (i + j) / 2 + 1}^{j} nums[k] - (j - (i + j) / 2) \times nums[(i + j) / 2] \end{aligned} $$ diff --git a/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README_EN.md b/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README_EN.md index b4a4ad056a70..60a7e045c7e7 100644 --- a/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README_EN.md +++ b/solution/2900-2999/2968.Apply Operations to Maximize Frequency Score/README_EN.md @@ -87,14 +87,14 @@ To determine whether such a subarray exists, we can use prefix sum. We first def $$ \begin{aligned} -\text{left} &= \sum_{k = i}^{(i + j) / 2 - 1} (nums[(i + j) / 2] - nums[k]) \\ +\textit{left} &= \sum_{k = i}^{(i + j) / 2 - 1} (nums[(i + j) / 2] - nums[k]) \\ &= ((i + j) / 2 - i) \times nums[(i + j) / 2] - \sum_{k = i}^{(i + j) / 2 - 1} nums[k] \end{aligned} $$ $$ \begin{aligned} -\text{right} &= \sum_{k = (i + j) / 2 + 1}^{j} (nums[k] - nums[(i + j) / 2]) \\ +\textit{right} &= \sum_{k = (i + j) / 2 + 1}^{j} (nums[k] - nums[(i + j) / 2]) \\ &= \sum_{k = (i + j) / 2 + 1}^{j} nums[k] - (j - (i + j) / 2) \times nums[(i + j) / 2] \end{aligned} $$ diff --git a/solution/2900-2999/2977.Minimum Cost to Convert String II/README.md b/solution/2900-2999/2977.Minimum Cost to Convert String II/README.md index 846a3b81d365..baf125482dc9 100644 --- a/solution/2900-2999/2977.Minimum Cost to Convert String II/README.md +++ b/solution/2900-2999/2977.Minimum Cost to Convert String II/README.md @@ -116,7 +116,7 @@ $$ dfs(i) = \begin{cases} 0, & i \geq |source| \\ dfs(i + 1), & source[i] = target[i] \\ -\min_{i \leq j < |source|} \{ dfs(j + 1) + g[x][y] \}, & \text{otherwise} +\min_{i \leq j < |source|} \{ dfs(j + 1) + g[x][y] \}, & \textit{otherwise} \end{cases} $$ diff --git a/solution/2900-2999/2977.Minimum Cost to Convert String II/README_EN.md b/solution/2900-2999/2977.Minimum Cost to Convert String II/README_EN.md index 09e91005bf5b..be244d1e8adf 100644 --- a/solution/2900-2999/2977.Minimum Cost to Convert String II/README_EN.md +++ b/solution/2900-2999/2977.Minimum Cost to Convert String II/README_EN.md @@ -112,7 +112,7 @@ $$ dfs(i) = \begin{cases} 0, & i \geq |source| \\ dfs(i + 1), & source[i] = target[i] \\ -\min_{i \leq j < |source|} \{ dfs(j + 1) + g[x][y] \}, & \text{otherwise} +\min_{i \leq j < |source|} \{ dfs(j + 1) + g[x][y] \}, & \textit{otherwise} \end{cases} $$ diff --git a/solution/2900-2999/2992.Number of Self-Divisible Permutations/README.md b/solution/2900-2999/2992.Number of Self-Divisible Permutations/README.md index 4aad8e74116f..b87df04d77b9 100644 --- a/solution/2900-2999/2992.Number of Self-Divisible Permutations/README.md +++ b/solution/2900-2999/2992.Number of Self-Divisible Permutations/README.md @@ -4,9 +4,9 @@ difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/2900-2999/2992.Number%20of%20Self-Divisible%20Permutations/README.md tags: - 位运算 - - 递归 - 数组 - 动态规划 + - 回溯 - 状态压缩 --- diff --git a/solution/2900-2999/2992.Number of Self-Divisible Permutations/README_EN.md b/solution/2900-2999/2992.Number of Self-Divisible Permutations/README_EN.md index e00b54a2c7e6..1f3deec3b736 100644 --- a/solution/2900-2999/2992.Number of Self-Divisible Permutations/README_EN.md +++ b/solution/2900-2999/2992.Number of Self-Divisible Permutations/README_EN.md @@ -4,9 +4,9 @@ difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/2900-2999/2992.Number%20of%20Self-Divisible%20Permutations/README_EN.md tags: - Bit Manipulation - - Recursion - Array - Dynamic Programming + - Backtracking - Bitmask --- diff --git a/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README.md b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README.md index a0a2145ded85..b174ef493049 100644 --- a/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README.md +++ b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README.md @@ -245,7 +245,17 @@ tags: -### 方法一 +### 方法一:二分查找 + 数位 DP + +我们注意到,如果 $\textit{num}$ 增大,数字 $1$ 到 $\textit{num}$ 的总价值也会增大。因此,我们可以使用二分查找的方法找到最大的廉价数字。 + +我们定义二分查找的左边界 $l = 1$,由于每 $2^x + 1$ 个数中至少有一个数字是有价值的,而总价值不超过 $10^15$,因此我们可以设定二分查找的右边界 $r = 10^{18}$。 + +接下来,我们进行二分查找,对于每一个 $\textit{mid}$,我们使用数位 DP 的方法计算出 $1$ 到 $\textit{mid}$ 的总价值,如果总价值不超过 $k$,则说明 $\textit{mid}$ 是一个廉价数字,我们将左边界 $l$ 更新为 $\textit{mid}$,否则我们将右边界 $r$ 更新为 $\textit{mid} - 1$。 + +最后,我们返回左边界 $l$ 即可。 + +时间复杂度 $O(\log^2 k)$,空间复杂度 $O(\log k)$。 @@ -332,7 +342,7 @@ public: ll l = 1, r = 1e17; ll num = 0; ll f[65][65]; - function dfs = [&](int pos, int cnt, bool limit) -> ll { + auto dfs = [&](auto&& dfs, int pos, int cnt, bool limit) -> ll { if (pos == 0) { return cnt; } @@ -342,7 +352,7 @@ public: int up = limit ? num >> (pos - 1) & 1 : 1; ll ans = 0; for (int i = 0; i <= up; ++i) { - ans += dfs(pos - 1, cnt + (i == 1 && pos % x == 0), limit && i == up); + ans += dfs(dfs, pos - 1, cnt + (i == 1 && pos % x == 0), limit && i == up); } if (!limit) { f[pos][cnt] = ans; @@ -354,7 +364,7 @@ public: num = mid; memset(f, -1, sizeof(f)); int pos = 64 - __builtin_clzll(mid); - if (dfs(pos, 0, true) <= k) { + if (dfs(dfs, pos, 0, true) <= k) { l = mid; } else { r = mid - 1; @@ -416,6 +426,56 @@ func findMaximumNumber(k int64, x int) int64 { } ``` +#### TypeScript + +```ts +function findMaximumNumber(k: number, x: number): number { + let [l, r] = [1n, 10n ** 17n]; + let num: bigint; + const f: bigint[][] = Array.from({ length: 65 }, () => Array(65).fill(-1n)); + + const dfs = (pos: number, cnt: number, limit: boolean): bigint => { + if (pos === 0) { + return BigInt(cnt); + } + if (!limit && f[pos][cnt] !== -1n) { + return f[pos][cnt]; + } + let ans: bigint = 0n; + let up: number = 1; + if (limit) { + up = Number((num >> BigInt(pos - 1)) & 1n); + } + for (let i = 0; i <= up; i++) { + let v: number = cnt; + if (i === 1 && pos % x === 0) { + v++; + } + ans += dfs(pos - 1, v, limit && i === up); + } + if (!limit) { + f[pos][cnt] = ans; + } + return ans; + }; + + while (l < r) { + let mid: bigint = (l + r + 1n) >> 1n; + num = mid; + let m: number = num.toString(2).length; + for (let i = 0; i < f.length; i++) { + f[i].fill(-1n); + } + if (dfs(m, 0, true) <= BigInt(k)) { + l = mid; + } else { + r = mid - 1n; + } + } + return Number(l); +} +``` + diff --git a/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README_EN.md b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README_EN.md index c9900a07c7ad..0671febffa62 100644 --- a/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README_EN.md +++ b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/README_EN.md @@ -249,7 +249,17 @@ tags: -### Solution 1 +### Solution 1: Binary Search + Digit DP + +We notice that if $\textit{num}$ increases, the total value from $1$ to $\textit{num}$ also increases. Therefore, we can use a binary search method to find the largest cheap number. + +We define the left boundary of the binary search as $l = 1$. Since there is at least one valuable number in every $2^x + 1$ numbers, and the total value does not exceed $10^{15}$, we can set the right boundary of the binary search as $r = 10^{18}$. + +Next, we perform a binary search. For each $\textit{mid}$, we use the digit DP method to calculate the total value from $1$ to $\textit{mid}$. If the total value does not exceed $k$, it means $\textit{mid}$ is a cheap number, and we update the left boundary $l$ to $\textit{mid}$. Otherwise, we update the right boundary $r$ to $\textit{mid} - 1$. + +Finally, we return the left boundary $l$. + +The time complexity is $O(\log^2 k)$, and the space complexity is $O(\log k)$. @@ -336,7 +346,7 @@ public: ll l = 1, r = 1e17; ll num = 0; ll f[65][65]; - function dfs = [&](int pos, int cnt, bool limit) -> ll { + auto dfs = [&](auto&& dfs, int pos, int cnt, bool limit) -> ll { if (pos == 0) { return cnt; } @@ -346,7 +356,7 @@ public: int up = limit ? num >> (pos - 1) & 1 : 1; ll ans = 0; for (int i = 0; i <= up; ++i) { - ans += dfs(pos - 1, cnt + (i == 1 && pos % x == 0), limit && i == up); + ans += dfs(dfs, pos - 1, cnt + (i == 1 && pos % x == 0), limit && i == up); } if (!limit) { f[pos][cnt] = ans; @@ -358,7 +368,7 @@ public: num = mid; memset(f, -1, sizeof(f)); int pos = 64 - __builtin_clzll(mid); - if (dfs(pos, 0, true) <= k) { + if (dfs(dfs, pos, 0, true) <= k) { l = mid; } else { r = mid - 1; @@ -420,6 +430,56 @@ func findMaximumNumber(k int64, x int) int64 { } ``` +#### TypeScript + +```ts +function findMaximumNumber(k: number, x: number): number { + let [l, r] = [1n, 10n ** 17n]; + let num: bigint; + const f: bigint[][] = Array.from({ length: 65 }, () => Array(65).fill(-1n)); + + const dfs = (pos: number, cnt: number, limit: boolean): bigint => { + if (pos === 0) { + return BigInt(cnt); + } + if (!limit && f[pos][cnt] !== -1n) { + return f[pos][cnt]; + } + let ans: bigint = 0n; + let up: number = 1; + if (limit) { + up = Number((num >> BigInt(pos - 1)) & 1n); + } + for (let i = 0; i <= up; i++) { + let v: number = cnt; + if (i === 1 && pos % x === 0) { + v++; + } + ans += dfs(pos - 1, v, limit && i === up); + } + if (!limit) { + f[pos][cnt] = ans; + } + return ans; + }; + + while (l < r) { + let mid: bigint = (l + r + 1n) >> 1n; + num = mid; + let m: number = num.toString(2).length; + for (let i = 0; i < f.length; i++) { + f[i].fill(-1n); + } + if (dfs(m, 0, true) <= BigInt(k)) { + l = mid; + } else { + r = mid - 1n; + } + } + return Number(l); +} +``` + diff --git a/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/Solution.cpp b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/Solution.cpp index 8f6dd46c4c83..c2417f413581 100644 --- a/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/Solution.cpp +++ b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/Solution.cpp @@ -5,7 +5,7 @@ class Solution { ll l = 1, r = 1e17; ll num = 0; ll f[65][65]; - function dfs = [&](int pos, int cnt, bool limit) -> ll { + auto dfs = [&](auto&& dfs, int pos, int cnt, bool limit) -> ll { if (pos == 0) { return cnt; } @@ -15,7 +15,7 @@ class Solution { int up = limit ? num >> (pos - 1) & 1 : 1; ll ans = 0; for (int i = 0; i <= up; ++i) { - ans += dfs(pos - 1, cnt + (i == 1 && pos % x == 0), limit && i == up); + ans += dfs(dfs, pos - 1, cnt + (i == 1 && pos % x == 0), limit && i == up); } if (!limit) { f[pos][cnt] = ans; @@ -27,7 +27,7 @@ class Solution { num = mid; memset(f, -1, sizeof(f)); int pos = 64 - __builtin_clzll(mid); - if (dfs(pos, 0, true) <= k) { + if (dfs(dfs, pos, 0, true) <= k) { l = mid; } else { r = mid - 1; @@ -35,4 +35,4 @@ class Solution { } return l; } -}; \ No newline at end of file +}; diff --git a/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/Solution.ts b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/Solution.ts new file mode 100644 index 000000000000..12f875d23343 --- /dev/null +++ b/solution/3000-3099/3007.Maximum Number That Sum of the Prices Is Less Than or Equal to K/Solution.ts @@ -0,0 +1,45 @@ +function findMaximumNumber(k: number, x: number): number { + let [l, r] = [1n, 10n ** 17n]; + let num: bigint; + const f: bigint[][] = Array.from({ length: 65 }, () => Array(65).fill(-1n)); + + const dfs = (pos: number, cnt: number, limit: boolean): bigint => { + if (pos === 0) { + return BigInt(cnt); + } + if (!limit && f[pos][cnt] !== -1n) { + return f[pos][cnt]; + } + let ans: bigint = 0n; + let up: number = 1; + if (limit) { + up = Number((num >> BigInt(pos - 1)) & 1n); + } + for (let i = 0; i <= up; i++) { + let v: number = cnt; + if (i === 1 && pos % x === 0) { + v++; + } + ans += dfs(pos - 1, v, limit && i === up); + } + if (!limit) { + f[pos][cnt] = ans; + } + return ans; + }; + + while (l < r) { + let mid: bigint = (l + r + 1n) >> 1n; + num = mid; + let m: number = num.toString(2).length; + for (let i = 0; i < f.length; i++) { + f[i].fill(-1n); + } + if (dfs(m, 0, true) <= BigInt(k)) { + l = mid; + } else { + r = mid - 1n; + } + } + return Number(l); +} diff --git a/solution/3000-3099/3011.Find if Array Can Be Sorted/README.md b/solution/3000-3099/3011.Find if Array Can Be Sorted/README.md index 713e7117307a..1bd91af4aed1 100644 --- a/solution/3000-3099/3011.Find if Array Can Be Sorted/README.md +++ b/solution/3000-3099/3011.Find if Array Can Be Sorted/README.md @@ -22,9 +22,9 @@ tags:

    给你一个下标从 0 开始且全是  整数的数组 nums 。

    -

    一次 操作 中,如果两个 相邻 元素在二进制下数位为 1 的数目 相同 ,那么你可以将这两个元素交换。你可以执行这个操作 任意次 (也可以 0 次)。

    +

    一次 操作 中,如果两个 相邻 元素在二进制下 设置位 的数目 相同 ,那么你可以将这两个元素交换。你可以执行这个操作 任意次 (也可以 0 次)。

    -

    如果你可以使数组变有序,请你返回 true ,否则返回 false 。

    +

    如果你可以使数组变为非降序,请你返回 true ,否则返回 false 。

     

    @@ -34,7 +34,7 @@ tags: 输入:nums = [8,4,2,30,15] 输出:true 解释:我们先观察每个元素的二进制表示。 2 ,4 和 8 分别都只有一个数位为 1 ,分别为 "10" ,"100" 和 "1000" 。15 和 30 分别有 4 个数位为 1 :"1111" 和 "11110" 。 -我们可以通过 4 个操作使数组有序: +我们可以通过 4 个操作使数组非降序: - 交换 nums[0] 和 nums[1] 。8 和 4 分别只有 1 个数位为 1 。数组变为 [4,8,2,30,15] 。 - 交换 nums[1] 和 nums[2] 。8 和 2 分别只有 1 个数位为 1 。数组变为 [4,2,8,30,15] 。 - 交换 nums[0] 和 nums[1] 。4 和 2 分别只有 1 个数位为 1 。数组变为 [2,4,8,30,15] 。 @@ -48,7 +48,7 @@ tags:
     输入:nums = [1,2,3,4,5]
     输出:true
    -解释:数组已经是有序的,所以我们返回 true 。
    +解释:数组已经是非降序的,所以我们返回 true 。
     

    示例 3:

    @@ -56,7 +56,7 @@ tags:
     输入:nums = [3,16,8,4,2]
     输出:false
    -解释:无法通过操作使数组变为有序。
    +解释:无法通过操作使数组变为非降序。
     

     

    diff --git a/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README.md b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README.md index 7e0a1dab7f5b..e11174c7661b 100644 --- a/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README.md +++ b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README.md @@ -189,6 +189,83 @@ function minimumPushes(word: string): number { } ``` +#### JavaScript + +```js +function minimumPushes(word) { + const cnt = Array(26).fill(0); + for (const c of word) { + ++cnt[c.charCodeAt(0) - 'a'.charCodeAt(0)]; + } + cnt.sort((a, b) => b - a); + let ans = 0; + for (let i = 0; i < 26; ++i) { + ans += (((i / 8) | 0) + 1) * cnt[i]; + } + return ans; +} +``` + + + + + + + +### 方法二:优先队列(大根堆) + + + +#### TypeScript + +```ts +function minimumPushes(word: string): number { + const pq = new MaxPriorityQueue(); + const cnt = new Map(); + let [i, res] = [0, 0]; + + for (const x of word) { + cnt.set(x, (cnt.get(x) ?? 0) + 1); + } + + for (const [x, c] of cnt) { + pq.enqueue(x, c); + } + + while (!pq.isEmpty()) { + const c = pq.dequeue().priority; + res += c * (((i++ / 8) | 0) + 1); + } + + return res; +} +``` + +#### JavaScript + +```js +function minimumPushes(word) { + const pq = new MaxPriorityQueue(); + const cnt = new Map(); + let [i, res] = [0, 0]; + + for (const x of word) { + cnt.set(x, (cnt.get(x) ?? 0) + 1); + } + + for (const [x, c] of cnt) { + pq.enqueue(x, c); + } + + while (!pq.isEmpty()) { + const c = pq.dequeue().priority; + res += c * (((i++ / 8) | 0) + 1); + } + + return res; +} +``` + diff --git a/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README_EN.md b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README_EN.md index ed9a33d2f0aa..1d470861064a 100644 --- a/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README_EN.md +++ b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/README_EN.md @@ -187,6 +187,83 @@ function minimumPushes(word: string): number { } ``` +#### JavaScript + +```js +function minimumPushes(word) { + const cnt = Array(26).fill(0); + for (const c of word) { + ++cnt[c.charCodeAt(0) - 'a'.charCodeAt(0)]; + } + cnt.sort((a, b) => b - a); + let ans = 0; + for (let i = 0; i < 26; ++i) { + ans += (((i / 8) | 0) + 1) * cnt[i]; + } + return ans; +} +``` + + + + + + + +### Solution 2: Priority Queue + + + +#### TypeScript + +```ts +function minimumPushes(word: string): number { + const pq = new MaxPriorityQueue(); + const cnt = new Map(); + let [i, res] = [0, 0]; + + for (const x of word) { + cnt.set(x, (cnt.get(x) ?? 0) + 1); + } + + for (const [x, c] of cnt) { + pq.enqueue(x, c); + } + + while (!pq.isEmpty()) { + const c = pq.dequeue().priority; + res += c * (((i++ / 8) | 0) + 1); + } + + return res; +} +``` + +#### JavaScript + +```js +function minimumPushes(word) { + const pq = new MaxPriorityQueue(); + const cnt = new Map(); + let [i, res] = [0, 0]; + + for (const x of word) { + cnt.set(x, (cnt.get(x) ?? 0) + 1); + } + + for (const [x, c] of cnt) { + pq.enqueue(x, c); + } + + while (!pq.isEmpty()) { + const c = pq.dequeue().priority; + res += c * (((i++ / 8) | 0) + 1); + } + + return res; +} +``` + diff --git a/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution.js b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution.js new file mode 100644 index 000000000000..67bebe50efea --- /dev/null +++ b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution.js @@ -0,0 +1,12 @@ +function minimumPushes(word) { + const cnt = Array(26).fill(0); + for (const c of word) { + ++cnt[c.charCodeAt(0) - 'a'.charCodeAt(0)]; + } + cnt.sort((a, b) => b - a); + let ans = 0; + for (let i = 0; i < 26; ++i) { + ans += (((i / 8) | 0) + 1) * cnt[i]; + } + return ans; +} diff --git a/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution2.js b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution2.js new file mode 100644 index 000000000000..f98f1bee7636 --- /dev/null +++ b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution2.js @@ -0,0 +1,20 @@ +function minimumPushes(word) { + const pq = new MaxPriorityQueue(); + const cnt = new Map(); + let [i, res] = [0, 0]; + + for (const x of word) { + cnt.set(x, (cnt.get(x) ?? 0) + 1); + } + + for (const [x, c] of cnt) { + pq.enqueue(x, c); + } + + while (!pq.isEmpty()) { + const c = pq.dequeue().priority; + res += c * (((i++ / 8) | 0) + 1); + } + + return res; +} diff --git a/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution2.ts b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution2.ts new file mode 100644 index 000000000000..7a7be327aadc --- /dev/null +++ b/solution/3000-3099/3016.Minimum Number of Pushes to Type Word II/Solution2.ts @@ -0,0 +1,20 @@ +function minimumPushes(word: string): number { + const pq = new MaxPriorityQueue(); + const cnt = new Map(); + let [i, res] = [0, 0]; + + for (const x of word) { + cnt.set(x, (cnt.get(x) ?? 0) + 1); + } + + for (const [x, c] of cnt) { + pq.enqueue(x, c); + } + + while (!pq.isEmpty()) { + const c = pq.dequeue().priority; + res += c * (((i++ / 8) | 0) + 1); + } + + return res; +} diff --git a/solution/3000-3099/3047.Find the Largest Area of Square Inside Two Rectangles/README_EN.md b/solution/3000-3099/3047.Find the Largest Area of Square Inside Two Rectangles/README_EN.md index 6ec1f35cbc79..7b8cad13919a 100644 --- a/solution/3000-3099/3047.Find the Largest Area of Square Inside Two Rectangles/README_EN.md +++ b/solution/3000-3099/3047.Find the Largest Area of Square Inside Two Rectangles/README_EN.md @@ -20,39 +20,52 @@ tags: -

    There exist n rectangles in a 2D plane. You are given two 0-indexed 2D integer arrays bottomLeft and topRight, both of size n x 2, where bottomLeft[i] and topRight[i] represent the bottom-left and top-right coordinates of the ith rectangle respectively.

    +

    There exist n rectangles in a 2D plane with edges parallel to the x and y axis. You are given two 2D integer arrays bottomLeft and topRight where bottomLeft[i] = [a_i, b_i] and topRight[i] = [c_i, d_i] represent the bottom-left and top-right coordinates of the ith rectangle, respectively.

    -

    You can select a region formed from the intersection of two of the given rectangles. You need to find the largest area of a square that can fit inside this region if you select the region optimally.

    - -

    Return the largest possible area of a square, or 0 if there do not exist any intersecting regions between the rectangles.

    +

    You need to find the maximum area of a square that can fit inside the intersecting region of at least two rectangles. Return 0 if such a square does not exist.

     

    Example 1:

    -
    -Input: bottomLeft = [[1,1],[2,2],[3,1]], topRight = [[3,3],[4,4],[6,6]]
    -Output: 1
    -Explanation: A square with side length 1 can fit inside either the intersecting region of rectangle 0 and rectangle 1, or the intersecting region of rectangle 1 and rectangle 2. Hence the largest area is side * side which is 1 * 1 == 1.
    -It can be shown that a square with a greater side length can not fit inside any intersecting region.
    -
    +

    Input: bottomLeft = [[1,1],[2,2],[3,1]], topRight = [[3,3],[4,4],[6,6]]

    + +

    Output: 1

    + +

    Explanation:

    + +

    A square with side length 1 can fit inside either the intersecting region of rectangles 0 and 1 or the intersecting region of rectangles 1 and 2. Hence the maximum area is 1. It can be shown that a square with a greater side length can not fit inside any intersecting region of two rectangles.

    Example 2:

    - -
    -Input: bottomLeft = [[1,1],[2,2],[1,2]], topRight = [[3,3],[4,4],[3,4]]
    -Output: 1
    -Explanation: A square with side length 1 can fit inside either the intersecting region of rectangle 0 and rectangle 1, the intersecting region of rectangle 1 and rectangle 2, or the intersection region of all 3 rectangles. Hence the largest area is side * side which is 1 * 1 == 1.
    -It can be shown that a square with a greater side length can not fit inside any intersecting region.
    -Note that the region can be formed by the intersection of more than 2 rectangles.
    -
    + +

    Input: bottomLeft = [[1,1],[1,3],[1,5]], topRight = [[5,5],[5,7],[5,9]]

    + +

    Output: 4

    + +

    Explanation:

    + +

    A square with side length 2 can fit inside either the intersecting region of rectangles 0 and 1 or the intersecting region of rectangles 1 and 2. Hence the maximum area is 2 * 2 = 4. It can be shown that a square with a greater side length can not fit inside any intersecting region of two rectangles.

    Example 3:

    - -
    -Input: bottomLeft = [[1,1],[3,3],[3,1]], topRight = [[2,2],[4,4],[4,2]]
    -Output: 0
    -Explanation: No pair of rectangles intersect, hence, we return 0.
    -
    + + +

    Input: bottomLeft = [[1,1],[2,2],[1,2]], topRight = [[3,3],[4,4],[3,4]]

    + +

    Output: 1

    + +

    Explanation:

    + +

    A square with side length 1 can fit inside the intersecting region of any two rectangles. Also, no larger square can, so the maximum area is 1. Note that the region can be formed by the intersection of more than 2 rectangles.

    + +

    Example 4:

    + + +

    Input: bottomLeft = [[1,1],[3,3],[3,1]], topRight = [[2,2],[4,4],[4,2]]

    + +

    Output: 0

    + +

    Explanation:

    + +

    No pair of rectangles intersect, hence, the answer is 0.

     

    Constraints:

    diff --git a/solution/3000-3099/3047.Find the Largest Area of Square Inside Two Rectangles/images/diag.png b/solution/3000-3099/3047.Find the Largest Area of Square Inside Two Rectangles/images/diag.png new file mode 100644 index 000000000000..886694f3a8b0 Binary files /dev/null and b/solution/3000-3099/3047.Find the Largest Area of Square Inside Two Rectangles/images/diag.png differ diff --git a/solution/3000-3099/3052.Maximize Items/README.md b/solution/3000-3099/3052.Maximize Items/README.md index 1e131c3401b9..347a4ae8d4d0 100644 --- a/solution/3000-3099/3052.Maximize Items/README.md +++ b/solution/3000-3099/3052.Maximize Items/README.md @@ -89,7 +89,7 @@ Inventory 表: 我们先计算出所有 prime_eligible 类型的物品的总面积,记录在 `T` 表的 `s` 字段中。 -接下来,我们分别计算 prime_eligible 和 not_prime 类型的物品的数量。对于 prime_eligible 类型的物品,我们可以存储的份数是 $\lfloor \frac{500000}{s} \rfloor$,对于 not_prime 类型的物品,我们可以存储的份数是 $\lfloor \frac{500000 \mod s}{\sum \text{s1}} \rfloor$。其中 $\sum \text{s1}$ 是所有 not_prime 类型的物品的总面积。再分别乘上 prime_eligible 和 not_prime 类型的物品的数量,就是我们的结果。 +接下来,我们分别计算 prime_eligible 和 not_prime 类型的物品的数量。对于 prime_eligible 类型的物品,我们可以存储的份数是 $\lfloor \frac{500000}{s} \rfloor$,对于 not_prime 类型的物品,我们可以存储的份数是 $\lfloor \frac{500000 \mod s}{\sum \textit{s1}} \rfloor$。其中 $\sum \textit{s1}$ 是所有 not_prime 类型的物品的总面积。再分别乘上 prime_eligible 和 not_prime 类型的物品的数量,就是我们的结果。 diff --git a/solution/3000-3099/3052.Maximize Items/README_EN.md b/solution/3000-3099/3052.Maximize Items/README_EN.md index 6e0df2f90172..0bb755c893d5 100644 --- a/solution/3000-3099/3052.Maximize Items/README_EN.md +++ b/solution/3000-3099/3052.Maximize Items/README_EN.md @@ -88,7 +88,7 @@ Output table is ordered by item count in descending order.
    First, we calculate the total area of all items of type `prime_eligible` and record it in the `s` field of table `T`. -Next, we calculate the number of items of type `prime_eligible` and `not_prime` respectively. For items of type `prime_eligible`, the number of portions we can store is $\lfloor \frac{500000}{s} \rfloor$. For items of type `not_prime`, the number of portions we can store is $\lfloor \frac{500000 \mod s}{\sum \text{s1}} \rfloor$. Where $\sum \text{s1}$ is the total area of all items of type `not_prime`. Multiplying by the number of items of type `prime_eligible` and `not_prime` respectively gives us our result. +Next, we calculate the number of items of type `prime_eligible` and `not_prime` respectively. For items of type `prime_eligible`, the number of portions we can store is $\lfloor \frac{500000}{s} \rfloor$. For items of type `not_prime`, the number of portions we can store is $\lfloor \frac{500000 \mod s}{\sum \textit{s1}} \rfloor$. Where $\sum \textit{s1}$ is the total area of all items of type `not_prime`. Multiplying by the number of items of type `prime_eligible` and `not_prime` respectively gives us our result. diff --git a/solution/3000-3099/3062.Winner of the Linked List Game/README.md b/solution/3000-3099/3062.Winner of the Linked List Game/README.md index 16659edbae76..f8b8b75981e8 100644 --- a/solution/3000-3099/3062.Winner of the Linked List Game/README.md +++ b/solution/3000-3099/3062.Winner of the Linked List Game/README.md @@ -26,7 +26,7 @@ tags:
    • 如果奇数节点更大,"Odd" 队得一分。
    • -
    • 如果偶数节点更大,"Even" 队得一分。
    • +
    • 如果偶数节点更大,"Even" 队得一分。

    返回分数更 的队名,如果分数相同,返回 "Tie"

    diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README.md b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README.md index 83e99e58f23d..8484e5d17c3b 100644 --- a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README.md +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README.md @@ -98,20 +98,56 @@ tags: -### 方法一 +### 方法一:动态规划 + +对于任意一个数 $x$,与 $k$ 异或偶数次后,值不变。所以,对于一棵树的任意一条路径,我们将路径上所有的边都进行操作,那么该路径上除了起点和终点外,其他节点的值都不会改变。 + +另外,无论进行了多少次操作,总会有偶数个元素异或了 $k$,其余元素不变。 + +因此,问题转化为:对于数组 $\textit{nums}$,任选其中偶数个元素异或 $k$,使得和最大。 + +我们可以使用动态规划解决这个问题。设 $f_0$ 表示当前有偶数个元素异或了 $k$ 时的最大和,而 $f_1$ 表示当前有奇数个元素异或了 $k$ 时的最大和。那么状态转移方程为: + +$$ +\begin{aligned} +f_0 &= \max(f_0 + x, f_1 + (x \oplus k)) \\ +f_1 &= \max(f_1 + x, f_0 + (x \oplus k)) +\end{aligned} +$$ + +其中 $x$ 表示当前元素的值。 + +我们遍历数组 $\textit{nums}$,根据上述状态转移方程更新 $f_0$ 和 $f_1$,最后返回 $f_0$ 即可。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 #### Python3 ```python - +class Solution: + def maximumValueSum(self, nums: List[int], k: int, edges: List[List[int]]) -> int: + f0, f1 = 0, -inf + for x in nums: + f0, f1 = max(f0 + x, f1 + (x ^ k)), max(f1 + x, f0 + (x ^ k)) + return f0 ``` #### Java ```java - +class Solution { + public long maximumValueSum(int[] nums, int k, int[][] edges) { + long f0 = 0, f1 = -0x3f3f3f3f; + for (int x : nums) { + long tmp = f0; + f0 = Math.max(f0 + x, f1 + (x ^ k)); + f1 = Math.max(f1 + x, tmp + (x ^ k)); + } + return f0; + } +} ``` #### C++ @@ -120,29 +156,13 @@ tags: class Solution { public: long long maximumValueSum(vector& nums, int k, vector>& edges) { - long long totalSum = 0; - int count = 0; - int positiveMin = INT_MAX; - int negativeMax = INT_MIN; - - for (int nodeValue : nums) { - int nodeValAfterOperation = nodeValue ^ k; - totalSum += nodeValue; - int netChange = nodeValAfterOperation - nodeValue; - - if (netChange > 0) { - positiveMin = min(positiveMin, netChange); - totalSum += netChange; - count += 1; - } else { - negativeMax = max(negativeMax, netChange); - } - } - - if (count % 2 == 0) { - return totalSum; + long long f0 = 0, f1 = -0x3f3f3f3f; + for (int x : nums) { + long long tmp = f0; + f0 = max(f0 + x, f1 + (x ^ k)); + f1 = max(f1 + x, tmp + (x ^ k)); } - return max(totalSum - positiveMin, totalSum + negativeMax); + return f0; } }; ``` @@ -150,7 +170,60 @@ public: #### Go ```go +func maximumValueSum(nums []int, k int, edges [][]int) int64 { + f0, f1 := 0, -0x3f3f3f3f + for _, x := range nums { + f0, f1 = max(f0+x, f1+(x^k)), max(f1+x, f0+(x^k)) + } + return int64(f0) +} +``` + +#### TypeScript + +```ts +function maximumValueSum(nums: number[], k: number, edges: number[][]): number { + let [f0, f1] = [0, -Infinity]; + for (const x of nums) { + [f0, f1] = [Math.max(f0 + x, f1 + (x ^ k)), Math.max(f1 + x, f0 + (x ^ k))]; + } + return f0; +} +``` + +#### Rust +```rust +impl Solution { + pub fn maximum_value_sum(nums: Vec, k: i32, edges: Vec>) -> i64 { + let mut f0: i64 = 0; + let mut f1: i64 = i64::MIN; + + for &x in &nums { + let tmp = f0; + f0 = std::cmp::max(f0 + x as i64, f1 + (x ^ k) as i64); + f1 = std::cmp::max(f1 + x as i64, tmp + (x ^ k) as i64); + } + + f0 + } +} +``` + +#### C# + +```cs +public class Solution { + public long MaximumValueSum(int[] nums, int k, int[][] edges) { + long f0 = 0, f1 = -0x3f3f3f3f; + foreach (int x in nums) { + long tmp = f0; + f0 = Math.Max(f0 + x, f1 + (x ^ k)); + f1 = Math.Max(f1 + x, tmp + (x ^ k)); + } + return f0; + } +} ``` diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README_EN.md b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README_EN.md index 02f7391356a6..b31fcfbf22a6 100644 --- a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README_EN.md +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/README_EN.md @@ -90,20 +90,56 @@ It can be shown that 9 is the maximum achievable sum of values. -### Solution 1 +### Solution 1: Dynamic Programming + +For any number $x$, its value remains unchanged after being XORed with $k$ an even number of times. Therefore, for any path in a tree, if we perform the operation on all edges in the path, the values of all nodes on the path except the start and end nodes will not change. + +Additionally, no matter how many operations are performed, there will always be an even number of elements XORed with $k$, and the remaining elements will remain unchanged. + +Thus, the problem is transformed into: for the array $\textit{nums}$, select an even number of elements to XOR with $k$ to maximize the sum. + +We can use dynamic programming to solve this problem. Let $f_0$ represent the maximum sum when an even number of elements have been XORed with $k$, and $f_1$ represent the maximum sum when an odd number of elements have been XORed with $k$. The state transition equations are: + +$$ +\begin{aligned} +f_0 &= \max(f_0 + x, f_1 + (x \oplus k)) \\ +f_1 &= \max(f_1 + x, f_0 + (x \oplus k)) +\end{aligned} +$$ + +where $x$ represents the current element's value. + +We traverse the array $\textit{nums}$ and update $f_0$ and $f_1$ according to the above state transition equations. Finally, we return $f_0$. + +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. #### Python3 ```python - +class Solution: + def maximumValueSum(self, nums: List[int], k: int, edges: List[List[int]]) -> int: + f0, f1 = 0, -inf + for x in nums: + f0, f1 = max(f0 + x, f1 + (x ^ k)), max(f1 + x, f0 + (x ^ k)) + return f0 ``` #### Java ```java - +class Solution { + public long maximumValueSum(int[] nums, int k, int[][] edges) { + long f0 = 0, f1 = -0x3f3f3f3f; + for (int x : nums) { + long tmp = f0; + f0 = Math.max(f0 + x, f1 + (x ^ k)); + f1 = Math.max(f1 + x, tmp + (x ^ k)); + } + return f0; + } +} ``` #### C++ @@ -112,29 +148,13 @@ It can be shown that 9 is the maximum achievable sum of values. class Solution { public: long long maximumValueSum(vector& nums, int k, vector>& edges) { - long long totalSum = 0; - int count = 0; - int positiveMin = INT_MAX; - int negativeMax = INT_MIN; - - for (int nodeValue : nums) { - int nodeValAfterOperation = nodeValue ^ k; - totalSum += nodeValue; - int netChange = nodeValAfterOperation - nodeValue; - - if (netChange > 0) { - positiveMin = min(positiveMin, netChange); - totalSum += netChange; - count += 1; - } else { - negativeMax = max(negativeMax, netChange); - } - } - - if (count % 2 == 0) { - return totalSum; + long long f0 = 0, f1 = -0x3f3f3f3f; + for (int x : nums) { + long long tmp = f0; + f0 = max(f0 + x, f1 + (x ^ k)); + f1 = max(f1 + x, tmp + (x ^ k)); } - return max(totalSum - positiveMin, totalSum + negativeMax); + return f0; } }; ``` @@ -142,7 +162,60 @@ public: #### Go ```go +func maximumValueSum(nums []int, k int, edges [][]int) int64 { + f0, f1 := 0, -0x3f3f3f3f + for _, x := range nums { + f0, f1 = max(f0+x, f1+(x^k)), max(f1+x, f0+(x^k)) + } + return int64(f0) +} +``` + +#### TypeScript + +```ts +function maximumValueSum(nums: number[], k: number, edges: number[][]): number { + let [f0, f1] = [0, -Infinity]; + for (const x of nums) { + [f0, f1] = [Math.max(f0 + x, f1 + (x ^ k)), Math.max(f1 + x, f0 + (x ^ k))]; + } + return f0; +} +``` + +#### Rust +```rust +impl Solution { + pub fn maximum_value_sum(nums: Vec, k: i32, edges: Vec>) -> i64 { + let mut f0: i64 = 0; + let mut f1: i64 = i64::MIN; + + for &x in &nums { + let tmp = f0; + f0 = std::cmp::max(f0 + x as i64, f1 + (x ^ k) as i64); + f1 = std::cmp::max(f1 + x as i64, tmp + (x ^ k) as i64); + } + + f0 + } +} +``` + +#### C# + +```cs +public class Solution { + public long MaximumValueSum(int[] nums, int k, int[][] edges) { + long f0 = 0, f1 = -0x3f3f3f3f; + foreach (int x in nums) { + long tmp = f0; + f0 = Math.Max(f0 + x, f1 + (x ^ k)); + f1 = Math.Max(f1 + x, tmp + (x ^ k)); + } + return f0; + } +} ``` diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.cpp b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.cpp index 76da2b6d4488..c52e439a6bd6 100644 --- a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.cpp +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.cpp @@ -1,28 +1,12 @@ class Solution { public: long long maximumValueSum(vector& nums, int k, vector>& edges) { - long long totalSum = 0; - int count = 0; - int positiveMin = INT_MAX; - int negativeMax = INT_MIN; - - for (int nodeValue : nums) { - int nodeValAfterOperation = nodeValue ^ k; - totalSum += nodeValue; - int netChange = nodeValAfterOperation - nodeValue; - - if (netChange > 0) { - positiveMin = min(positiveMin, netChange); - totalSum += netChange; - count += 1; - } else { - negativeMax = max(negativeMax, netChange); - } + long long f0 = 0, f1 = -0x3f3f3f3f; + for (int x : nums) { + long long tmp = f0; + f0 = max(f0 + x, f1 + (x ^ k)); + f1 = max(f1 + x, tmp + (x ^ k)); } - - if (count % 2 == 0) { - return totalSum; - } - return max(totalSum - positiveMin, totalSum + negativeMax); + return f0; } }; diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.cs b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.cs new file mode 100644 index 000000000000..03fbb853e08e --- /dev/null +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.cs @@ -0,0 +1,11 @@ +public class Solution { + public long MaximumValueSum(int[] nums, int k, int[][] edges) { + long f0 = 0, f1 = -0x3f3f3f3f; + foreach (int x in nums) { + long tmp = f0; + f0 = Math.Max(f0 + x, f1 + (x ^ k)); + f1 = Math.Max(f1 + x, tmp + (x ^ k)); + } + return f0; + } +} diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.go b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.go new file mode 100644 index 000000000000..097c05f9dc1e --- /dev/null +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.go @@ -0,0 +1,7 @@ +func maximumValueSum(nums []int, k int, edges [][]int) int64 { + f0, f1 := 0, -0x3f3f3f3f + for _, x := range nums { + f0, f1 = max(f0+x, f1+(x^k)), max(f1+x, f0+(x^k)) + } + return int64(f0) +} diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.java b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.java new file mode 100644 index 000000000000..a5dbc45c9e13 --- /dev/null +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.java @@ -0,0 +1,11 @@ +class Solution { + public long maximumValueSum(int[] nums, int k, int[][] edges) { + long f0 = 0, f1 = -0x3f3f3f3f; + for (int x : nums) { + long tmp = f0; + f0 = Math.max(f0 + x, f1 + (x ^ k)); + f1 = Math.max(f1 + x, tmp + (x ^ k)); + } + return f0; + } +} diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.py b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.py new file mode 100644 index 000000000000..0e244763277c --- /dev/null +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.py @@ -0,0 +1,6 @@ +class Solution: + def maximumValueSum(self, nums: List[int], k: int, edges: List[List[int]]) -> int: + f0, f1 = 0, -inf + for x in nums: + f0, f1 = max(f0 + x, f1 + (x ^ k)), max(f1 + x, f0 + (x ^ k)) + return f0 diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.rs b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.rs new file mode 100644 index 000000000000..b8789ed10642 --- /dev/null +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.rs @@ -0,0 +1,14 @@ +impl Solution { + pub fn maximum_value_sum(nums: Vec, k: i32, edges: Vec>) -> i64 { + let mut f0: i64 = 0; + let mut f1: i64 = i64::MIN; + + for &x in &nums { + let tmp = f0; + f0 = std::cmp::max(f0 + x as i64, f1 + (x ^ k) as i64); + f1 = std::cmp::max(f1 + x as i64, tmp + (x ^ k) as i64); + } + + f0 + } +} diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.ts b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.ts new file mode 100644 index 000000000000..2769ab13f6ec --- /dev/null +++ b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/Solution.ts @@ -0,0 +1,7 @@ +function maximumValueSum(nums: number[], k: number, edges: number[][]): number { + let [f0, f1] = [0, -Infinity]; + for (const x of nums) { + [f0, f1] = [Math.max(f0 + x, f1 + (x ^ k)), Math.max(f1 + x, f0 + (x ^ k))]; + } + return f0; +} diff --git a/solution/3000-3099/3068.Find the Maximum Sum of Node Values/images/screenshot-2023-11-10-012641.png b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/images/screenshot-2023-11-10-012641.png new file mode 100644 index 000000000000..86f3ff4af05c Binary files /dev/null and b/solution/3000-3099/3068.Find the Maximum Sum of Node Values/images/screenshot-2023-11-10-012641.png differ diff --git a/solution/3000-3099/3076.Shortest Uncommon Substring in an Array/README.md b/solution/3000-3099/3076.Shortest Uncommon Substring in an Array/README.md index 09830e7e955d..f7e6a35d2048 100644 --- a/solution/3000-3099/3076.Shortest Uncommon Substring in an Array/README.md +++ b/solution/3000-3099/3076.Shortest Uncommon Substring in an Array/README.md @@ -23,7 +23,7 @@ tags:

    给你一个数组 arr ,数组中有 n 个 非空 字符串。

    -

    请你求出一个长度为 n 的字符串 answer ,满足:

    +

    请你求出一个长度为 n 的字符串数组 answer ,满足:

    • answer[i] 是 arr[i] 最短 的子字符串,且它不是 arr 中其他任何字符串的子字符串。如果有多个这样的子字符串存在,answer[i] 应该是它们中字典序最小的一个。如果不存在这样的子字符串,answer[i] 为空字符串。
    • diff --git a/solution/3000-3099/3077.Maximum Strength of K Disjoint Subarrays/README_EN.md b/solution/3000-3099/3077.Maximum Strength of K Disjoint Subarrays/README_EN.md index d8da4ba7f9d0..5e18c7ac20f5 100644 --- a/solution/3000-3099/3077.Maximum Strength of K Disjoint Subarrays/README_EN.md +++ b/solution/3000-3099/3077.Maximum Strength of K Disjoint Subarrays/README_EN.md @@ -20,40 +20,56 @@ tags: -

      You are given a 0-indexed array of integers nums of length n, and a positive odd integer k.

      +

      You are given an array of integers nums with length n, and a positive odd integer k.

      -

      The strength of x subarrays is defined as strength = sum[1] * x - sum[2] * (x - 1) + sum[3] * (x - 2) - sum[4] * (x - 3) + ... + sum[x] * 1 where sum[i] is the sum of the elements in the ith subarray. Formally, strength is sum of (-1)i+1 * sum[i] * (x - i + 1) over all i's such that 1 <= i <= x.

      +

      Select exactly k disjoint subarrays sub1, sub2, ..., subk from nums such that the last element of subi appears before the first element of sub{i+1} for all 1 <= i <= k-1. The goal is to maximize their combined strength.

      -

      You need to select k disjoint subarrays from nums, such that their strength is maximum.

      +

      The strength of the selected subarrays is defined as:

      -

      Return the maximum possible strength that can be obtained.

      +

      strength = k * sum(sub1)- (k - 1) * sum(sub2) + (k - 2) * sum(sub3) - ... - 2 * sum(sub{k-1}) + sum(subk)

      -

      Note that the selected subarrays don't need to cover the entire array.

      +

      where sum(subi) is the sum of the elements in the i-th subarray.

      + +

      Return the maximum possible strength that can be obtained from selecting exactly k disjoint subarrays from nums.

      + +

      Note that the chosen subarrays don't need to cover the entire array.

       

      Example 1:

      -
      -Input: nums = [1,2,3,-1,2], k = 3
      -Output: 22
      -Explanation: The best possible way to select 3 subarrays is: nums[0..2], nums[3..3], and nums[4..4]. The strength is (1 + 2 + 3) * 3 - (-1) * 2 + 2 * 1 = 22.
      -
      +

      Input: nums = [1,2,3,-1,2], k = 3

      + +

      Output: 22

      + +

      Explanation:

      + +

      The best possible way to select 3 subarrays is: nums[0..2], nums[3..3], and nums[4..4]. The strength is calculated as follows:

      + +

      strength = 3 * (1 + 2 + 3) - 2 * (-1) + 2 = 22

      + +

       

      Example 2:

      -
      -Input: nums = [12,-2,-2,-2,-2], k = 5
      -Output: 64
      -Explanation: The only possible way to select 5 disjoint subarrays is: nums[0..0], nums[1..1], nums[2..2], nums[3..3], and nums[4..4]. The strength is 12 * 5 - (-2) * 4 + (-2) * 3 - (-2) * 2 + (-2) * 1 = 64.
      -
      +

      Input: nums = [12,-2,-2,-2,-2], k = 5

      + +

      Output: 64

      + +

      Explanation:

      + +

      The only possible way to select 5 disjoint subarrays is: nums[0..0], nums[1..1], nums[2..2], nums[3..3], and nums[4..4]. The strength is calculated as follows:

      + +

      strength = 5 * 12 - 4 * (-2) + 3 * (-2) - 2 * (-2) + (-2) = 64

      Example 3:

      -
      -Input: nums = [-1,-2,-3], k = 1
      -Output: -1
      -Explanation: The best possible way to select 1 subarray is: nums[0..0]. The strength is -1.
      -
      +

      Input: nums = [-1,-2,-3], k = 1

      + +

      Output: -1

      + +

      Explanation:

      + +

      The best possible way to select 1 subarray is: nums[0..0]. The strength is -1.

       

      Constraints:

      diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README.md b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README.md index 54cdb0646eff..374b0ef58b28 100644 --- a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README.md +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README.md @@ -97,32 +97,237 @@ tags: -### 方法一 +### 方法一:动态规划 + +题目需要我们在给定数组 $\textit{nums}$ 中找到所有子序列 $\textit{S}$,然后计算每个 $\textit{S}$ 的每个子序列 $\textit{T}$ 的和等于 $\textit{k}$ 的方案数。 + +我们定义 $f[i][j]$ 表示前 $i$ 个数构成的若干个子序列中,每个子序列的子序列和等于 $j$ 的方案数。初始时 $f[0][0] = 1$,其余位置均为 $0$。 + +对于第 $i$ 个数 $x$,有以下三种情况: + +1. 不在子序列 $\textit{S}$ 中,此时 $f[i][j] = f[i-1][j]$; +1. 在子序列 $\textit{S}$,但不在子序列 $\textit{T}$ 中,此时 $f[i][j] = f[i-1][j]$; +1. 在子序列 $\textit{S}$,且在子序列 $\textit{T}$ 中,此时 $f[i][j] = f[i-1][j-x]$。 + +综上,状态转移方程为: + +$$ +f[i][j] = f[i-1][j] \times 2 + f[i-1][j-x] +$$ + +最终答案为 $f[n][k]$。 + +时间复杂度 $O(n \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $k$ 为给定的正整数。 #### Python3 ```python - +class Solution: + def sumOfPower(self, nums: List[int], k: int) -> int: + mod = 10**9 + 7 + n = len(nums) + f = [[0] * (k + 1) for _ in range(n + 1)] + f[0][0] = 1 + for i, x in enumerate(nums, 1): + for j in range(k + 1): + f[i][j] = f[i - 1][j] * 2 % mod + if j >= x: + f[i][j] = (f[i][j] + f[i - 1][j - x]) % mod + return f[n][k] ``` #### Java ```java - +class Solution { + public int sumOfPower(int[] nums, int k) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int[][] f = new int[n + 1][k + 1]; + f[0][0] = 1; + for (int i = 1; i <= n; ++i) { + for (int j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; + } +} ``` #### C++ ```cpp +class Solution { +public: + int sumOfPower(vector& nums, int k) { + const int mod = 1e9 + 7; + int n = nums.size(); + int f[n + 1][k + 1]; + memset(f, 0, sizeof(f)); + f[0][0] = 1; + for (int i = 1; i <= n; ++i) { + for (int j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; + } +}; +``` +#### Go + +```go +func sumOfPower(nums []int, k int) int { + const mod int = 1e9 + 7 + n := len(nums) + f := make([][]int, n+1) + for i := range f { + f[i] = make([]int, k+1) + } + f[0][0] = 1 + for i := 1; i <= n; i++ { + for j := 0; j <= k; j++ { + f[i][j] = (f[i-1][j] * 2) % mod + if j >= nums[i-1] { + f[i][j] = (f[i][j] + f[i-1][j-nums[i-1]]) % mod + } + } + } + return f[n][k] +} +``` + +#### TypeScript + +```ts +function sumOfPower(nums: number[], k: number): number { + const mod = 10 ** 9 + 7; + const n = nums.length; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0)); + f[0][0] = 1; + for (let i = 1; i <= n; ++i) { + for (let j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; +} +``` + + + + + + + +### 方法二:动态规划(优化) + +方法一中的状态转移方程中,$f[i][j]$ 的值只与 $f[i-1][j]$ 和 $f[i-1][j-x]$ 有关,因此我们可以优化第一维空间,从而将空间复杂度优化为 $O(k)$。 + +时间复杂度 $O(n \times k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $k$ 为给定的正整数。 + + + +#### Python3 + +```python +class Solution: + def sumOfPower(self, nums: List[int], k: int) -> int: + mod = 10**9 + 7 + f = [1] + [0] * k + for x in nums: + for j in range(k, -1, -1): + f[j] = (f[j] * 2 + (0 if j < x else f[j - x])) % mod + return f[k] +``` + +#### Java + +```java +class Solution { + public int sumOfPower(int[] nums, int k) { + final int mod = (int) 1e9 + 7; + int[] f = new int[k + 1]; + f[0] = 1; + for (int x : nums) { + for (int j = k; j >= 0; --j) { + f[j] = (f[j] * 2 % mod + (j >= x ? f[j - x] : 0)) % mod; + } + } + return f[k]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int sumOfPower(vector& nums, int k) { + const int mod = 1e9 + 7; + int f[k + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (int x : nums) { + for (int j = k; j >= 0; --j) { + f[j] = (f[j] * 2 % mod + (j >= x ? f[j - x] : 0)) % mod; + } + } + return f[k]; + } +}; ``` #### Go ```go +func sumOfPower(nums []int, k int) int { + const mod int = 1e9 + 7 + f := make([]int, k+1) + f[0] = 1 + for _, x := range nums { + for j := k; j >= 0; j-- { + f[j] = f[j] * 2 % mod + if j >= x { + f[j] = (f[j] + f[j-x]) % mod + } + } + } + return f[k] +} +``` +#### TypeScript + +```ts +function sumOfPower(nums: number[], k: number): number { + const mod = 10 ** 9 + 7; + const f: number[] = Array(k + 1).fill(0); + f[0] = 1; + for (const x of nums) { + for (let j = k; ~j; --j) { + f[j] = (f[j] * 2) % mod; + if (j >= x) { + f[j] = (f[j] + f[j - x]) % mod; + } + } + } + return f[k]; +} ``` diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README_EN.md b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README_EN.md index 0069c359275d..62d347cb5428 100644 --- a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README_EN.md +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/README_EN.md @@ -95,32 +95,237 @@ tags: -### Solution 1 +### Solution 1: Dynamic Programming + +The problem requires us to find all subsequences $\textit{S}$ in the given array $\textit{nums}$, and then calculate the number of ways for each subsequence $\textit{T}$ such that the sum of $\textit{T}$ equals $\textit{k}$. + +We define $f[i][j]$ to represent the number of ways to form subsequences with the first $i$ numbers such that the sum of each subsequence equals $j$. Initially, $f[0][0] = 1$, and all other positions are $0$. + +For the $i$-th number $x$, there are three cases: + +1. Not in the subsequence $\textit{S}$, in which case $f[i][j] = f[i-1][j]$; +2. In the subsequence $\textit{S}$, but not in the subsequence $\textit{T}$, in which case $f[i][j] = f[i-1][j]$; +3. In the subsequence $\textit{S}$, and in the subsequence $\textit{T}$, in which case $f[i][j] = f[i-1][j-x]$. + +In summary, the state transition equation is: + +$$ +f[i][j] = f[i-1][j] \times 2 + f[i-1][j-x] +$$ + +The final answer is $f[n][k]$. + +The time complexity is $O(n \times k)$, and the space complexity is $O(n \times k)$. Here, $n$ is the length of the array $\textit{nums}$, and $k$ is the given positive integer. #### Python3 ```python - +class Solution: + def sumOfPower(self, nums: List[int], k: int) -> int: + mod = 10**9 + 7 + n = len(nums) + f = [[0] * (k + 1) for _ in range(n + 1)] + f[0][0] = 1 + for i, x in enumerate(nums, 1): + for j in range(k + 1): + f[i][j] = f[i - 1][j] * 2 % mod + if j >= x: + f[i][j] = (f[i][j] + f[i - 1][j - x]) % mod + return f[n][k] ``` #### Java ```java - +class Solution { + public int sumOfPower(int[] nums, int k) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int[][] f = new int[n + 1][k + 1]; + f[0][0] = 1; + for (int i = 1; i <= n; ++i) { + for (int j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; + } +} ``` #### C++ ```cpp +class Solution { +public: + int sumOfPower(vector& nums, int k) { + const int mod = 1e9 + 7; + int n = nums.size(); + int f[n + 1][k + 1]; + memset(f, 0, sizeof(f)); + f[0][0] = 1; + for (int i = 1; i <= n; ++i) { + for (int j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; + } +}; +``` +#### Go + +```go +func sumOfPower(nums []int, k int) int { + const mod int = 1e9 + 7 + n := len(nums) + f := make([][]int, n+1) + for i := range f { + f[i] = make([]int, k+1) + } + f[0][0] = 1 + for i := 1; i <= n; i++ { + for j := 0; j <= k; j++ { + f[i][j] = (f[i-1][j] * 2) % mod + if j >= nums[i-1] { + f[i][j] = (f[i][j] + f[i-1][j-nums[i-1]]) % mod + } + } + } + return f[n][k] +} +``` + +#### TypeScript + +```ts +function sumOfPower(nums: number[], k: number): number { + const mod = 10 ** 9 + 7; + const n = nums.length; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0)); + f[0][0] = 1; + for (let i = 1; i <= n; ++i) { + for (let j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; +} +``` + + + + + + + +### Solution 2: Dynamic Programming (Optimization) + +In the state transition equation from Solution 1, the value of $f[i][j]$ only depends on $f[i-1][j]$ and $f[i-1][j-x]$. Therefore, we can optimize the first dimension of the space, reducing the space complexity to $O(k)$. + +Time complexity is $O(n \times k)$, and space complexity is $O(k)$. Here, $n$ is the length of the array $\textit{nums}$, and $k$ is the given positive integer. + + + +#### Python3 + +```python +class Solution: + def sumOfPower(self, nums: List[int], k: int) -> int: + mod = 10**9 + 7 + f = [1] + [0] * k + for x in nums: + for j in range(k, -1, -1): + f[j] = (f[j] * 2 + (0 if j < x else f[j - x])) % mod + return f[k] +``` + +#### Java + +```java +class Solution { + public int sumOfPower(int[] nums, int k) { + final int mod = (int) 1e9 + 7; + int[] f = new int[k + 1]; + f[0] = 1; + for (int x : nums) { + for (int j = k; j >= 0; --j) { + f[j] = (f[j] * 2 % mod + (j >= x ? f[j - x] : 0)) % mod; + } + } + return f[k]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int sumOfPower(vector& nums, int k) { + const int mod = 1e9 + 7; + int f[k + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (int x : nums) { + for (int j = k; j >= 0; --j) { + f[j] = (f[j] * 2 % mod + (j >= x ? f[j - x] : 0)) % mod; + } + } + return f[k]; + } +}; ``` #### Go ```go +func sumOfPower(nums []int, k int) int { + const mod int = 1e9 + 7 + f := make([]int, k+1) + f[0] = 1 + for _, x := range nums { + for j := k; j >= 0; j-- { + f[j] = f[j] * 2 % mod + if j >= x { + f[j] = (f[j] + f[j-x]) % mod + } + } + } + return f[k] +} +``` +#### TypeScript + +```ts +function sumOfPower(nums: number[], k: number): number { + const mod = 10 ** 9 + 7; + const f: number[] = Array(k + 1).fill(0); + f[0] = 1; + for (const x of nums) { + for (let j = k; ~j; --j) { + f[j] = (f[j] * 2) % mod; + if (j >= x) { + f[j] = (f[j] + f[j - x]) % mod; + } + } + } + return f[k]; +} ``` diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.cpp b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.cpp new file mode 100644 index 000000000000..2387620380a7 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + int sumOfPower(vector& nums, int k) { + const int mod = 1e9 + 7; + int n = nums.size(); + int f[n + 1][k + 1]; + memset(f, 0, sizeof(f)); + f[0][0] = 1; + for (int i = 1; i <= n; ++i) { + for (int j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; + } +}; diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.go b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.go new file mode 100644 index 000000000000..dfb0854e3bd0 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.go @@ -0,0 +1,18 @@ +func sumOfPower(nums []int, k int) int { + const mod int = 1e9 + 7 + n := len(nums) + f := make([][]int, n+1) + for i := range f { + f[i] = make([]int, k+1) + } + f[0][0] = 1 + for i := 1; i <= n; i++ { + for j := 0; j <= k; j++ { + f[i][j] = (f[i-1][j] * 2) % mod + if j >= nums[i-1] { + f[i][j] = (f[i][j] + f[i-1][j-nums[i-1]]) % mod + } + } + } + return f[n][k] +} diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.java b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.java new file mode 100644 index 000000000000..34bb4f773274 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.java @@ -0,0 +1,17 @@ +class Solution { + public int sumOfPower(int[] nums, int k) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int[][] f = new int[n + 1][k + 1]; + f[0][0] = 1; + for (int i = 1; i <= n; ++i) { + for (int j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; + } +} diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.py b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.py new file mode 100644 index 000000000000..51280aba941e --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.py @@ -0,0 +1,12 @@ +class Solution: + def sumOfPower(self, nums: List[int], k: int) -> int: + mod = 10**9 + 7 + n = len(nums) + f = [[0] * (k + 1) for _ in range(n + 1)] + f[0][0] = 1 + for i, x in enumerate(nums, 1): + for j in range(k + 1): + f[i][j] = f[i - 1][j] * 2 % mod + if j >= x: + f[i][j] = (f[i][j] + f[i - 1][j - x]) % mod + return f[n][k] diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.ts b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.ts new file mode 100644 index 000000000000..188f71ed2701 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution.ts @@ -0,0 +1,15 @@ +function sumOfPower(nums: number[], k: number): number { + const mod = 10 ** 9 + 7; + const n = nums.length; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0)); + f[0][0] = 1; + for (let i = 1; i <= n; ++i) { + for (let j = 0; j <= k; ++j) { + f[i][j] = (f[i - 1][j] * 2) % mod; + if (j >= nums[i - 1]) { + f[i][j] = (f[i][j] + f[i - 1][j - nums[i - 1]]) % mod; + } + } + } + return f[n][k]; +} diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.cpp b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.cpp new file mode 100644 index 000000000000..abe9d96057e6 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int sumOfPower(vector& nums, int k) { + const int mod = 1e9 + 7; + int f[k + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (int x : nums) { + for (int j = k; j >= 0; --j) { + f[j] = (f[j] * 2 % mod + (j >= x ? f[j - x] : 0)) % mod; + } + } + return f[k]; + } +}; diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.go b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.go new file mode 100644 index 000000000000..d93a8a02d7b2 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.go @@ -0,0 +1,14 @@ +func sumOfPower(nums []int, k int) int { + const mod int = 1e9 + 7 + f := make([]int, k+1) + f[0] = 1 + for _, x := range nums { + for j := k; j >= 0; j-- { + f[j] = f[j] * 2 % mod + if j >= x { + f[j] = (f[j] + f[j-x]) % mod + } + } + } + return f[k] +} diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.java b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.java new file mode 100644 index 000000000000..89ff2cf9c366 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.java @@ -0,0 +1,13 @@ +class Solution { + public int sumOfPower(int[] nums, int k) { + final int mod = (int) 1e9 + 7; + int[] f = new int[k + 1]; + f[0] = 1; + for (int x : nums) { + for (int j = k; j >= 0; --j) { + f[j] = (f[j] * 2 % mod + (j >= x ? f[j - x] : 0)) % mod; + } + } + return f[k]; + } +} diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.py b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.py new file mode 100644 index 000000000000..403c3d9ba247 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.py @@ -0,0 +1,8 @@ +class Solution: + def sumOfPower(self, nums: List[int], k: int) -> int: + mod = 10**9 + 7 + f = [1] + [0] * k + for x in nums: + for j in range(k, -1, -1): + f[j] = (f[j] * 2 + (0 if j < x else f[j - x])) % mod + return f[k] diff --git a/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.ts b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.ts new file mode 100644 index 000000000000..5fa89b2561f1 --- /dev/null +++ b/solution/3000-3099/3082.Find the Sum of the Power of All Subsequences/Solution2.ts @@ -0,0 +1,14 @@ +function sumOfPower(nums: number[], k: number): number { + const mod = 10 ** 9 + 7; + const f: number[] = Array(k + 1).fill(0); + f[0] = 1; + for (const x of nums) { + for (let j = k; ~j; --j) { + f[j] = (f[j] * 2) % mod; + if (j >= x) { + f[j] = (f[j] + f[j - x]) % mod; + } + } + } + return f[k]; +} diff --git a/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README.md b/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README.md index 6d9c6b2a4207..bf4c1bbf1404 100644 --- a/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README.md +++ b/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README.md @@ -94,10 +94,10 @@ tags: - 首先,如果位置 $i$ 的数字为 $1$,我们可以直接拾取一个 $1$,不需要行动次数。 - 然后,我们对 $i$ 的左右两侧位置的数字 $1$ 进行拾取,执行的是行动 $2$,即把位置 $i-1$ 的 $1$ 移到位置 $i$,然后拾取;把位置 $i+1$ 的 $1$ 移到位置 $i$,然后拾取。每拾取一个 $1$,需要 $1$ 次行动。 -- 接下来,我们最大限度地将 $i-1$ 或 $i+1$ 上的 $0$,利用行动 $1$,将其置为 $1$,然后利用行动 $2$,将其移动到位置 $i$,拾取。直到拾取的 $1$ 的数量达到 $k$ 或者行动 $1$ 的次数达到 $\text{maxChanges}$。我们假设行动 $1$ 的次数为 $c$,那么总共需要 $2c$ 次行动。 +- 接下来,我们最大限度地将 $i-1$ 或 $i+1$ 上的 $0$,利用行动 $1$,将其置为 $1$,然后利用行动 $2$,将其移动到位置 $i$,拾取。直到拾取的 $1$ 的数量达到 $k$ 或者行动 $1$ 的次数达到 $\textit{maxChanges}$。我们假设行动 $1$ 的次数为 $c$,那么总共需要 $2c$ 次行动。 - 利用完行动 $1$,如果拾取的 $1$ 的数量还没有达到 $k$,我们需要继续考虑在 $[1,..i-2]$ 和 $[i+2,..n]$ 的区间内,进行行动 $2$,将 $1$ 移动到位置 $i$,拾取。我们可以使用二分查找来确定这个区间的大小,使得拾取的 $1$ 的数量达到 $k$。具体地,我们二分枚举一个区间的大小 $d$,然后在区间 $[i-d,..i-2]$ 和 $[i+2,..i+d]$ 内,进行行动 $2$,将 $1$ 移动到位置 $i$,拾取。如果拾取的 $1$ 的数量达到 $k$,我们就更新答案。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $\textit{nums}$ 的长度。 diff --git a/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README_EN.md b/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README_EN.md index 6ce12dd2b913..98d8d0d29c85 100644 --- a/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README_EN.md +++ b/solution/3000-3099/3086.Minimum Moves to Pick K Ones/README_EN.md @@ -92,10 +92,10 @@ We consider enumerating Alice's standing position $i$. For each $i$, we follow t - First, if the number at position $i$ is $1$, we can directly pick up a $1$ without needing any moves. - Then, we pick up the number $1$ from both sides of position $i$, which is action $2$, i.e., move the $1$ from position $i-1$ to position $i$, then pick it up; move the $1$ from position $i+1$ to position $i$, then pick it up. Each pick up of a $1$ requires $1$ move. -- Next, we maximize the conversion of $0$s at positions $i-1$ or $i+1$ to $1$s using action $1$, then move them to position $i$ using action $2$ to pick them up. This continues until the number of $1$s picked up reaches $k$ or the number of times action $1$ is used reaches $\text{maxChanges}$. Assuming the number of times action $1$ is used is $c$, then a total of $2c$ moves are needed. +- Next, we maximize the conversion of $0$s at positions $i-1$ or $i+1$ to $1$s using action $1$, then move them to position $i$ using action $2$ to pick them up. This continues until the number of $1$s picked up reaches $k$ or the number of times action $1$ is used reaches $\textit{maxChanges}$. Assuming the number of times action $1$ is used is $c$, then a total of $2c$ moves are needed. - After utilizing action $1$, if the number of $1$s picked up has not reached $k$, we need to continue considering moving $1$s to position $i$ from the intervals $[1,..i-2]$ and $[i+2,..n]$ using action $2$ to pick them up. We can use binary search to determine the size of this interval so that the number of $1$s picked up reaches $k$. Specifically, we binary search for an interval size $d$, then within the intervals $[i-d,..i-2]$ and $[i+2,..i+d]$, we perform action $2$ to move $1$s to position $i$ for pickup. If the number of $1$s picked up reaches $k$, we update the answer. -The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\text{nums}$. +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. diff --git a/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README.md b/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README.md index 480e2c2e9090..a2bbdb2203b4 100644 --- a/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README.md +++ b/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README.md @@ -163,6 +163,22 @@ function minOperations(k: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn min_operations(k: i32) -> i32 { + let mut ans = k; + for a in 0..k { + let x = a + 1; + let b = (k + x - 1) / x - 1; + ans = ans.min(a + b); + } + ans + } +} +``` + diff --git a/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README_EN.md b/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README_EN.md index e770afb61bf0..aef9ff3dde83 100644 --- a/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README_EN.md +++ b/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/README_EN.md @@ -161,6 +161,22 @@ function minOperations(k: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn min_operations(k: i32) -> i32 { + let mut ans = k; + for a in 0..k { + let x = a + 1; + let b = (k + x - 1) / x - 1; + ans = ans.min(a + b); + } + ans + } +} +``` + diff --git a/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/Solution.rs b/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/Solution.rs new file mode 100644 index 000000000000..869990a5f085 --- /dev/null +++ b/solution/3000-3099/3091.Apply Operations to Make Sum of Array Greater Than or Equal to k/Solution.rs @@ -0,0 +1,11 @@ +impl Solution { + pub fn min_operations(k: i32) -> i32 { + let mut ans = k; + for a in 0..k { + let x = a + 1; + let b = (k + x - 1) / x - 1; + ans = ans.min(a + b); + } + ans + } +} diff --git a/solution/3000-3099/3096.Minimum Levels to Gain More Points/README.md b/solution/3000-3099/3096.Minimum Levels to Gain More Points/README.md index d8949a6889d8..c60ded6856cc 100644 --- a/solution/3000-3099/3096.Minimum Levels to Gain More Points/README.md +++ b/solution/3000-3099/3096.Minimum Levels to Gain More Points/README.md @@ -21,7 +21,7 @@ tags:

      给你一个长度为 n 的二进制数组 possible 。

      -

      Alice 和 Bob 正在玩一个有 n 个关卡的游戏,游戏中有一些关卡是 困难 模式,其他的关卡是 简单 模式。如果 possible[i] == 0 ,那么第 i 个关卡是 困难 模式。一个玩家通过一个简单模式的关卡可以获得 1 分,通过困难模式的关卡将失去 1 分。

      +

      Alice 和 Bob 正在玩一个有 n 个关卡的游戏,游戏中有一些关卡是 困难 模式,其他的关卡是 简单 模式。如果 possible[i] == 0 ,那么第 i 个关卡是 困难 模式,两个玩家 都不可能 通过。一个玩家通过一个简单模式的关卡可以获得 1 分,遇到困难模式的关卡将失去 1 分。

      游戏的一开始,Alice 将从第 0 级开始 按顺序 完成一些关卡,然后 Bob 会完成剩下的所有关卡。

      diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md index e4fac77acc8a..3ca9f25bb9fd 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md @@ -84,18 +84,21 @@ tags: ### 方法一:记忆化搜索 -我们设计一个函数 $dfs(i, j, k, mi)$,表示当前处理到第 $i$ 个元素,上一个选取的是第 $j$ 个元素,还需要选取 $k$ 个元素,当前的最小差值为 $mi$ 时,能量和的值。那么答案就是 $dfs(0, n, k, +\infty)$。 +由于题目涉及子序列元素的最小差值,我们不妨对数组 $\textit{nums}$ 进行排序,这样可以方便我们计算子序列元素的最小差值。 + +接下来,我们设计一个函数 $dfs(i, j, k, mi)$,表示当前处理到第 $i$ 个元素,上一个选取的是第 $j$ 个元素,还需要选取 $k$ 个元素,当前的最小差值为 $mi$ 时,能量和的值。那么答案就是 $dfs(0, n, k, +\infty)$。(若上一个选取的是第 $n$ 个元素,表示之前没有选取过元素) 函数 $dfs(i, j, k, mi)$ 的执行过程如下: - 如果 $i \geq n$,表示已经处理完了所有的元素,如果 $k = 0$,返回 $mi$,否则返回 $0$; +- 如果剩余的元素个数 $n - i$ 不足 $k$ 个,返回 $0$; - 否则,我们可以选择不选取第 $i$ 个元素,可以获得的能量和为 $dfs(i + 1, j, k, mi)$; -- 也可以选择选取第 $i$ 个元素。如果 $j = n$,表示之前没有选取过元素,那么可以获得的能量和为 $dfs(i + 1, i, k - 1, mi)$;否则,可以获得的能量和为 $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$。 +- 也可以选择选取第 $i$ 个元素。如果 $j = n$,表示之前没有选取过元素,那么可以获得的能量和为 $dfs(i + 1, i, k - 1, mi)$;否则,可以获得的能量和为 $dfs(i + 1, i, k - 1, \min(mi, \textit{nums}[i] - \textit{nums}[j]))$。 - 我们累加上述结果,并对 $10^9 + 7$ 取模后返回。 为了避免重复计算,我们可以使用记忆化搜索的方法,将已经计算过的结果保存起来。 -时间复杂度 $O(n^5)$,空间复杂度 $O(n^5)$。其中 $n$ 为数组的长度。 +时间复杂度 $O(n^4 \times k)$,空间复杂度 $O(n^4 \times k)$。其中 $n$ 为数组的长度。 @@ -108,6 +111,8 @@ class Solution: def dfs(i: int, j: int, k: int, mi: int) -> int: if i >= n: return mi if k == 0 else 0 + if n - i < k: + return 0 ans = dfs(i + 1, j, k, mi) if j == n: ans += dfs(i + 1, i, k - 1, mi) @@ -140,6 +145,9 @@ class Solution { if (i >= nums.length) { return k == 0 ? mi : 0; } + if (nums.length - i < k) { + return 0; + } long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k; if (f.containsKey(key)) { return f.get(key); @@ -167,25 +175,28 @@ public: const int mod = 1e9 + 7; int n = nums.size(); sort(nums.begin(), nums.end()); - function dfs = [&](int i, int j, int k, int mi) { + auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int { if (i >= n) { return k == 0 ? mi : 0; } + if (n - i < k) { + return 0; + } long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k; if (f.contains(key)) { return f[key]; } - long long ans = dfs(i + 1, j, k, mi); + long long ans = dfs(dfs, i + 1, j, k, mi); if (j == n) { - ans += dfs(i + 1, i, k - 1, mi); + ans += dfs(dfs, i + 1, i, k - 1, mi); } else { - ans += dfs(i + 1, i, k - 1, min(mi, nums[i] - nums[j])); + ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j])); } ans %= mod; f[key] = ans; return f[key]; }; - return dfs(0, n, k, INT_MAX); + return dfs(dfs, 0, n, k, INT_MAX); } }; ``` @@ -206,6 +217,9 @@ func sumOfPowers(nums []int, k int) int { } return 0 } + if n-i < k { + return 0 + } key := mi<<18 | (i << 12) | (j << 6) | k if v, ok := f[key]; ok { return v @@ -224,6 +238,47 @@ func sumOfPowers(nums []int, k int) int { } ``` +#### TypeScript + +```ts +function sumOfPowers(nums: number[], k: number): number { + const mod = BigInt(1e9 + 7); + nums.sort((a, b) => a - b); + const n = nums.length; + const f: Map = new Map(); + function dfs(i: number, j: number, k: number, mi: number): bigint { + if (i >= n) { + if (k === 0) { + return BigInt(mi); + } + return BigInt(0); + } + if (n - i < k) { + return BigInt(0); + } + const key = + (BigInt(mi) << BigInt(18)) | + (BigInt(i) << BigInt(12)) | + (BigInt(j) << BigInt(6)) | + BigInt(k); + if (f.has(key)) { + return f.get(key)!; + } + let ans = dfs(i + 1, j, k, mi); + if (j === n) { + ans += dfs(i + 1, i, k - 1, mi); + } else { + ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j])); + } + ans %= mod; + f.set(key, ans); + return ans; + } + + return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER)); +} +``` + diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md index 5b0cac31f3d1..db46b8a10d37 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md @@ -82,18 +82,21 @@ tags: ### Solution 1: Memoization Search -We design a function $dfs(i, j, k, mi)$, which represents the energy sum value when we are currently processing the $i$-th element, the last selected element is the $j$-th element, we still need to select $k$ elements, and the current minimum difference is $mi$. The answer is $dfs(0, n, k, +\infty)$. +Given the problem involves the minimum difference between elements of a subsequence, we might as well sort the array $\textit{nums}$, which facilitates the calculation of the minimum difference between subsequence elements. + +Next, we design a function $dfs(i, j, k, mi)$, representing the value of the energy sum when processing the $i$-th element, the last selected element is the $j$-th element, $k$ more elements need to be selected, and the current minimum difference is $mi$. Therefore, the answer is $dfs(0, n, k, +\infty)$ (If the last selected element is the $n$-th element, it indicates that no element has been selected before). The execution process of the function $dfs(i, j, k, mi)$ is as follows: -- If $i \geq n$, it means that all elements have been processed. If $k = 0$, return $mi$, otherwise return $0$; -- Otherwise, we can choose not to select the $i$-th element, and the energy sum obtained is $dfs(i + 1, j, k, mi)$; -- We can also choose to select the $i$-th element. If $j = n$, it means that no element has been selected before, and the energy sum obtained is $dfs(i + 1, i, k - 1, mi)$; otherwise, the energy sum obtained is $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$. -- We add up the above results, take the modulus of $10^9 + 7$, and return. +- If $i \geq n$, it means all elements have been processed. If $k = 0$, return $mi$; otherwise, return $0$. +- If the remaining number of elements $n - i$ is less than $k$, return $0$. +- Otherwise, we can choose not to select the $i$-th element, and the energy sum obtained is $dfs(i + 1, j, k, mi)$. +- We can also choose to select the $i$-th element. If $j = n$, it means no element has been selected before, then the energy sum obtained is $dfs(i + 1, i, k - 1, mi)$; otherwise, the energy sum obtained is $dfs(i + 1, i, k - 1, \min(mi, \textit{nums}[i] - \textit{nums}[j]))$. +- We add up the above results and return the result modulo $10^9 + 7$. -To avoid repeated calculations, we can use the method of memoization search to save the calculated results. +To avoid repeated calculations, we can use memoization, saving the results that have already been calculated. -The time complexity is $O(n^5)$, and the space complexity is $O(n^5)$. Where $n$ is the length of the array. +The time complexity is $O(n^4 \times k)$, and the space complexity is $O(n^4 \times k)$. Here, $n$ is the length of the array. @@ -106,6 +109,8 @@ class Solution: def dfs(i: int, j: int, k: int, mi: int) -> int: if i >= n: return mi if k == 0 else 0 + if n - i < k: + return 0 ans = dfs(i + 1, j, k, mi) if j == n: ans += dfs(i + 1, i, k - 1, mi) @@ -138,6 +143,9 @@ class Solution { if (i >= nums.length) { return k == 0 ? mi : 0; } + if (nums.length - i < k) { + return 0; + } long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k; if (f.containsKey(key)) { return f.get(key); @@ -165,25 +173,28 @@ public: const int mod = 1e9 + 7; int n = nums.size(); sort(nums.begin(), nums.end()); - function dfs = [&](int i, int j, int k, int mi) { + auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int { if (i >= n) { return k == 0 ? mi : 0; } + if (n - i < k) { + return 0; + } long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k; if (f.contains(key)) { return f[key]; } - long long ans = dfs(i + 1, j, k, mi); + long long ans = dfs(dfs, i + 1, j, k, mi); if (j == n) { - ans += dfs(i + 1, i, k - 1, mi); + ans += dfs(dfs, i + 1, i, k - 1, mi); } else { - ans += dfs(i + 1, i, k - 1, min(mi, nums[i] - nums[j])); + ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j])); } ans %= mod; f[key] = ans; return f[key]; }; - return dfs(0, n, k, INT_MAX); + return dfs(dfs, 0, n, k, INT_MAX); } }; ``` @@ -204,6 +215,9 @@ func sumOfPowers(nums []int, k int) int { } return 0 } + if n-i < k { + return 0 + } key := mi<<18 | (i << 12) | (j << 6) | k if v, ok := f[key]; ok { return v @@ -222,6 +236,47 @@ func sumOfPowers(nums []int, k int) int { } ``` +#### TypeScript + +```ts +function sumOfPowers(nums: number[], k: number): number { + const mod = BigInt(1e9 + 7); + nums.sort((a, b) => a - b); + const n = nums.length; + const f: Map = new Map(); + function dfs(i: number, j: number, k: number, mi: number): bigint { + if (i >= n) { + if (k === 0) { + return BigInt(mi); + } + return BigInt(0); + } + if (n - i < k) { + return BigInt(0); + } + const key = + (BigInt(mi) << BigInt(18)) | + (BigInt(i) << BigInt(12)) | + (BigInt(j) << BigInt(6)) | + BigInt(k); + if (f.has(key)) { + return f.get(key)!; + } + let ans = dfs(i + 1, j, k, mi); + if (j === n) { + ans += dfs(i + 1, i, k - 1, mi); + } else { + ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j])); + } + ans %= mod; + f.set(key, ans); + return ans; + } + + return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER)); +} +``` + diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp index 6b6e24b913e5..7e5407b6435b 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp @@ -5,24 +5,27 @@ class Solution { const int mod = 1e9 + 7; int n = nums.size(); sort(nums.begin(), nums.end()); - function dfs = [&](int i, int j, int k, int mi) { + auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int { if (i >= n) { return k == 0 ? mi : 0; } + if (n - i < k) { + return 0; + } long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k; if (f.contains(key)) { return f[key]; } - long long ans = dfs(i + 1, j, k, mi); + long long ans = dfs(dfs, i + 1, j, k, mi); if (j == n) { - ans += dfs(i + 1, i, k - 1, mi); + ans += dfs(dfs, i + 1, i, k - 1, mi); } else { - ans += dfs(i + 1, i, k - 1, min(mi, nums[i] - nums[j])); + ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j])); } ans %= mod; f[key] = ans; return f[key]; }; - return dfs(0, n, k, INT_MAX); + return dfs(dfs, 0, n, k, INT_MAX); } }; \ No newline at end of file diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go index 75b1528dde09..644ad8377e22 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go @@ -11,6 +11,9 @@ func sumOfPowers(nums []int, k int) int { } return 0 } + if n-i < k { + return 0 + } key := mi<<18 | (i << 12) | (j << 6) | k if v, ok := f[key]; ok { return v diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java index ee6e753cf1ad..ed981e0a2aba 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java @@ -13,6 +13,9 @@ private int dfs(int i, int j, int k, int mi) { if (i >= nums.length) { return k == 0 ? mi : 0; } + if (nums.length - i < k) { + return 0; + } long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k; if (f.containsKey(key)) { return f.get(key); diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py index 89d6cc5d3688..f570a54adb8d 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py @@ -4,6 +4,8 @@ def sumOfPowers(self, nums: List[int], k: int) -> int: def dfs(i: int, j: int, k: int, mi: int) -> int: if i >= n: return mi if k == 0 else 0 + if n - i < k: + return 0 ans = dfs(i + 1, j, k, mi) if j == n: ans += dfs(i + 1, i, k - 1, mi) diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.ts b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.ts new file mode 100644 index 000000000000..53b27d04f410 --- /dev/null +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.ts @@ -0,0 +1,36 @@ +function sumOfPowers(nums: number[], k: number): number { + const mod = BigInt(1e9 + 7); + nums.sort((a, b) => a - b); + const n = nums.length; + const f: Map = new Map(); + function dfs(i: number, j: number, k: number, mi: number): bigint { + if (i >= n) { + if (k === 0) { + return BigInt(mi); + } + return BigInt(0); + } + if (n - i < k) { + return BigInt(0); + } + const key = + (BigInt(mi) << BigInt(18)) | + (BigInt(i) << BigInt(12)) | + (BigInt(j) << BigInt(6)) | + BigInt(k); + if (f.has(key)) { + return f.get(key)!; + } + let ans = dfs(i + 1, j, k, mi); + if (j === n) { + ans += dfs(i + 1, i, k - 1, mi); + } else { + ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j])); + } + ans %= mod; + f.set(key, ans); + return ans; + } + + return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER)); +} diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README.md b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README.md index c51e9bb67edf..0204d8fcb395 100644 --- a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README.md +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README.md @@ -113,9 +113,11 @@ tags: 根据题目描述,我们不需要考虑矩形的高度,只需要考虑矩形的宽度。 -我们可以将所有的点按照横坐标进行排序,用一个变量 $x_1$ 记录当前矩形的左下角的横坐标。然后遍历所有的点,如果当前点的横坐标 $x$ 比 $x_1 + w$ 大,说明当前点不能被当前的矩形覆盖,我们就需要增加一个新的矩形,然后更新 $x_1$ 为当前点的横坐标。 +我们可以将所有的点按照横坐标进行排序,用一个变量 $x_1$ 记录当前矩形所能覆盖的最右边的横坐标,初始时 $x_1 = -1$。 -遍历完成后,我们就得到了最少需要多少个矩形。 +接下来我们遍历所有的点,如果当前点的横坐标 $x$ 大于 $x_1$,说明已有的矩形无法覆盖当前点,我们就需要增加一个矩形,答案加一,然后我们更新 $x_1 = x + w$。 + +遍历完成后,我们就得到了最少需要的矩形数目。 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是点的数量。 @@ -127,11 +129,11 @@ tags: class Solution: def minRectanglesToCoverPoints(self, points: List[List[int]], w: int) -> int: points.sort() - ans, x1 = 0, -inf + ans, x1 = 0, -1 for x, _ in points: - if x1 + w < x: - x1 = x + if x > x1: ans += 1 + x1 = x + w return ans ``` @@ -141,13 +143,12 @@ class Solution: class Solution { public int minRectanglesToCoverPoints(int[][] points, int w) { Arrays.sort(points, (a, b) -> a[0] - b[0]); - int ans = 0; - int x1 = -(1 << 30); + int ans = 0, x1 = -1; for (int[] p : points) { int x = p[0]; - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; @@ -162,12 +163,12 @@ class Solution { public: int minRectanglesToCoverPoints(vector>& points, int w) { sort(points.begin(), points.end()); - int ans = 0, x1 = -(1 << 30); - for (auto& p : points) { + int ans = 0, x1 = -1; + for (const auto& p : points) { int x = p[0]; - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; @@ -180,11 +181,11 @@ public: ```go func minRectanglesToCoverPoints(points [][]int, w int) (ans int) { sort.Slice(points, func(i, j int) bool { return points[i][0] < points[j][0] }) - x1 := -(1 << 30) + x1 := -1 for _, p := range points { - if x := p[0]; x1+w < x { - x1 = x + if x := p[0]; x > x1 { ans++ + x1 = x + w } } return @@ -196,18 +197,56 @@ func minRectanglesToCoverPoints(points [][]int, w int) (ans int) { ```ts function minRectanglesToCoverPoints(points: number[][], w: number): number { points.sort((a, b) => a[0] - b[0]); - let ans = 0; - let x1 = -Infinity; + let [ans, x1] = [0, -1]; for (const [x, _] of points) { - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; } ``` +#### Rust + +```rust +impl Solution { + pub fn min_rectangles_to_cover_points(mut points: Vec>, w: i32) -> i32 { + points.sort_by(|a, b| a[0].cmp(&b[0])); + let mut ans = 0; + let mut x1 = -1; + for p in points { + let x = p[0]; + if x > x1 { + ans += 1; + x1 = x + w; + } + } + ans + } +} +``` + +#### C# + +```cs +public class Solution { + public int MinRectanglesToCoverPoints(int[][] points, int w) { + Array.Sort(points, (a, b) => a[0] - b[0]); + int ans = 0, x1 = -1; + foreach (int[] p in points) { + int x = p[0]; + if (x > x1) { + ans++; + x1 = x + w; + } + } + return ans; + } +} +``` + diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README_EN.md b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README_EN.md index 75c8a95b32d0..e241e0556a29 100644 --- a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README_EN.md +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/README_EN.md @@ -154,13 +154,15 @@ tags: ### Solution 1: Greedy + Sorting -According to the problem description, we don't need to consider the height of the rectangle, only the width. +According to the problem description, we do not need to consider the height of the rectangles, only the width. -We can sort all the points according to the x-coordinate and use a variable $x_1$ to record the current x-coordinate of the lower left corner of the rectangle. Then we traverse all the points. If the x-coordinate $x$ of the current point is greater than $x_1 + w$, it means that the current point cannot be covered by the current rectangle. We need to add a new rectangle and update $x_1$ to the x-coordinate of the current point. +We can sort all the points by their x-coordinates and use a variable $x_1$ to record the rightmost x-coordinate that the current rectangle can cover. Initially, $x_1 = -1$. -After the traversal, we get the minimum number of rectangles needed. +Next, we iterate through all the points. If the current point's x-coordinate $x$ is greater than $x_1$, it means the existing rectangle cannot cover the current point. We need to add a new rectangle, increment the answer by one, and update $x_1 = x + w$. -The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$, where $n$ is the number of points. +After completing the iteration, we obtain the minimum number of rectangles needed. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the number of points. @@ -170,11 +172,11 @@ The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log class Solution: def minRectanglesToCoverPoints(self, points: List[List[int]], w: int) -> int: points.sort() - ans, x1 = 0, -inf + ans, x1 = 0, -1 for x, _ in points: - if x1 + w < x: - x1 = x + if x > x1: ans += 1 + x1 = x + w return ans ``` @@ -184,13 +186,12 @@ class Solution: class Solution { public int minRectanglesToCoverPoints(int[][] points, int w) { Arrays.sort(points, (a, b) -> a[0] - b[0]); - int ans = 0; - int x1 = -(1 << 30); + int ans = 0, x1 = -1; for (int[] p : points) { int x = p[0]; - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; @@ -205,12 +206,12 @@ class Solution { public: int minRectanglesToCoverPoints(vector>& points, int w) { sort(points.begin(), points.end()); - int ans = 0, x1 = -(1 << 30); - for (auto& p : points) { + int ans = 0, x1 = -1; + for (const auto& p : points) { int x = p[0]; - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; @@ -223,11 +224,11 @@ public: ```go func minRectanglesToCoverPoints(points [][]int, w int) (ans int) { sort.Slice(points, func(i, j int) bool { return points[i][0] < points[j][0] }) - x1 := -(1 << 30) + x1 := -1 for _, p := range points { - if x := p[0]; x1+w < x { - x1 = x + if x := p[0]; x > x1 { ans++ + x1 = x + w } } return @@ -239,18 +240,56 @@ func minRectanglesToCoverPoints(points [][]int, w int) (ans int) { ```ts function minRectanglesToCoverPoints(points: number[][], w: number): number { points.sort((a, b) => a[0] - b[0]); - let ans = 0; - let x1 = -Infinity; + let [ans, x1] = [0, -1]; for (const [x, _] of points) { - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; } ``` +#### Rust + +```rust +impl Solution { + pub fn min_rectangles_to_cover_points(mut points: Vec>, w: i32) -> i32 { + points.sort_by(|a, b| a[0].cmp(&b[0])); + let mut ans = 0; + let mut x1 = -1; + for p in points { + let x = p[0]; + if x > x1 { + ans += 1; + x1 = x + w; + } + } + ans + } +} +``` + +#### C# + +```cs +public class Solution { + public int MinRectanglesToCoverPoints(int[][] points, int w) { + Array.Sort(points, (a, b) => a[0] - b[0]); + int ans = 0, x1 = -1; + foreach (int[] p in points) { + int x = p[0]; + if (x > x1) { + ans++; + x1 = x + w; + } + } + return ans; + } +} +``` + diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.cpp b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.cpp index cb90fdb4e6c2..d20c6cb6b24f 100644 --- a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.cpp +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.cpp @@ -2,14 +2,14 @@ class Solution { public: int minRectanglesToCoverPoints(vector>& points, int w) { sort(points.begin(), points.end()); - int ans = 0, x1 = -(1 << 30); - for (auto& p : points) { + int ans = 0, x1 = -1; + for (const auto& p : points) { int x = p[0]; - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.cs b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.cs new file mode 100644 index 000000000000..6d8d1b4aaab5 --- /dev/null +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.cs @@ -0,0 +1,14 @@ +public class Solution { + public int MinRectanglesToCoverPoints(int[][] points, int w) { + Array.Sort(points, (a, b) => a[0] - b[0]); + int ans = 0, x1 = -1; + foreach (int[] p in points) { + int x = p[0]; + if (x > x1) { + ans++; + x1 = x + w; + } + } + return ans; + } +} diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.go b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.go index 576eb533bc39..7296c2289104 100644 --- a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.go +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.go @@ -1,11 +1,11 @@ func minRectanglesToCoverPoints(points [][]int, w int) (ans int) { sort.Slice(points, func(i, j int) bool { return points[i][0] < points[j][0] }) - x1 := -(1 << 30) + x1 := -1 for _, p := range points { - if x := p[0]; x1+w < x { - x1 = x + if x := p[0]; x > x1 { ans++ + x1 = x + w } } return -} \ No newline at end of file +} diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.java b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.java index 8f965d1e11c4..453d47b2bcf5 100644 --- a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.java +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.java @@ -1,15 +1,14 @@ class Solution { public int minRectanglesToCoverPoints(int[][] points, int w) { Arrays.sort(points, (a, b) -> a[0] - b[0]); - int ans = 0; - int x1 = -(1 << 30); + int ans = 0, x1 = -1; for (int[] p : points) { int x = p[0]; - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; } -} \ No newline at end of file +} diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.py b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.py index 8f7b702ffadf..6589281e1490 100644 --- a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.py +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.py @@ -1,9 +1,9 @@ class Solution: def minRectanglesToCoverPoints(self, points: List[List[int]], w: int) -> int: points.sort() - ans, x1 = 0, -inf + ans, x1 = 0, -1 for x, _ in points: - if x1 + w < x: - x1 = x + if x > x1: ans += 1 + x1 = x + w return ans diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.rs b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.rs new file mode 100644 index 000000000000..1a3220313c40 --- /dev/null +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.rs @@ -0,0 +1,15 @@ +impl Solution { + pub fn min_rectangles_to_cover_points(mut points: Vec>, w: i32) -> i32 { + points.sort_by(|a, b| a[0].cmp(&b[0])); + let mut ans = 0; + let mut x1 = -1; + for p in points { + let x = p[0]; + if x > x1 { + ans += 1; + x1 = x + w; + } + } + ans + } +} diff --git a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.ts b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.ts index e59de2938075..93859174a06c 100644 --- a/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.ts +++ b/solution/3100-3199/3111.Minimum Rectangles to Cover Points/Solution.ts @@ -1,11 +1,10 @@ function minRectanglesToCoverPoints(points: number[][], w: number): number { points.sort((a, b) => a[0] - b[0]); - let ans = 0; - let x1 = -Infinity; + let [ans, x1] = [0, -1]; for (const [x, _] of points) { - if (x1 + w < x) { - x1 = x; + if (x > x1) { ++ans; + x1 = x + w; } } return ans; diff --git a/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README.md b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README.md index 5f704610a9f1..c2df0346a623 100644 --- a/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README.md +++ b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README.md @@ -36,9 +36,9 @@ tags:

      -

      输入:n = 3, edges = [[0,1,2],[1,2,1],[0,2,4]], disappear = [1,1,5]

      +

      输入:n = 3, edges = [[0,1,2],[1,2,1],[0,2,4]], disappear = [1,1,5]

      -

      输出:[0,-1,4]

      +

      输出:[0,-1,4]

      解释:

      @@ -56,9 +56,9 @@ tags:

      -

      输入:n = 3, edges = [[0,1,2],[1,2,1],[0,2,4]], disappear = [1,3,5]

      +

      输入:n = 3, edges = [[0,1,2],[1,2,1],[0,2,4]], disappear = [1,3,5]

      -

      输出:[0,2,3]

      +

      输出:[0,2,3]

      解释:

      @@ -105,16 +105,16 @@ tags: ### 方法一:堆优化的 Dijkstra -我们先创建一个邻接表 $g$,用于存储图的边。然后创建一个数组 $dist$,用于存储从节点 $0$ 到其他节点的最短距离。初始化 $dist[0] = 0$,其余节点的距离初始化为无穷大。 +我们先创建一个邻接表 $\textit{g}$,用于存储图的边。然后创建一个数组 $\textit{dist}$,用于存储从节点 $0$ 到其他节点的最短距离。初始化 $\textit{dist}[0] = 0$,其余节点的距离初始化为无穷大。 然后,我们使用 Dijkstra 算法计算从节点 $0$ 到其他节点的最短距离。具体步骤如下: -1. 创建一个优先队列 $q$,用于存储节点的距离和节点编号,初始时将节点 $0$ 加入队列,距离为 $0$。 -2. 从队列中取出一个节点 $u$,如果 $u$ 的距离 $du$ 大于 $dist[u]$,说明 $u$ 已经被更新过了,直接跳过。 -3. 遍历节点 $u$ 的所有邻居节点 $v$,如果 $dist[v] > dist[u] + w$ 且 $dist[u] + w < disappear[v]$,则更新 $dist[v] = dist[u] + w$,并将节点 $v$ 加入队列。 +1. 创建一个优先队列 $\textit{pq}$,用于存储节点的距离和节点编号,初始时将节点 $0$ 加入队列,距离为 $0$。 +2. 从队列中取出一个节点 $u$,如果 $u$ 的距离 $du$ 大于 $\textit{dist}[u]$,说明 $u$ 已经被更新过了,直接跳过。 +3. 遍历节点 $u$ 的所有邻居节点 $v$,如果 $\textit{dist}[v] > \textit{dist}[u] + w$ 且 $\textit{dist}[u] + w < \textit{disappear}[v]$,则更新 $\textit{dist}[v] = \textit{dist}[u] + w$,并将节点 $v$ 加入队列。 4. 重复步骤 2 和步骤 3,直到队列为空。 -最后,我们遍历 $dist$ 数组,如果 $dist[i] < disappear[i]$,则 $answer[i] = dist[i]$,否则 $answer[i] = -1$。 +最后,我们遍历 $\textit{dist}$ 数组,如果 $\textit{dist}[i] < \textit{disappear}[i]$,则 $\textit{answer}[i] = \textit{dist}[i]$,否则 $\textit{answer}[i] = -1$。 时间复杂度 $O(m \times \log m)$,空间复杂度 $O(m)$。其中 $m$ 是边的数量。 @@ -133,15 +133,15 @@ class Solution: g[v].append((u, w)) dist = [inf] * n dist[0] = 0 - q = [(0, 0)] - while q: - du, u = heappop(q) + pq = [(0, 0)] + while pq: + du, u = heappop(pq) if du > dist[u]: continue for v, w in g[u]: if dist[v] > dist[u] + w and dist[u] + w < disappear[v]: dist[v] = dist[u] + w - heappush(q, (dist[v], v)) + heappush(pq, (dist[v], v)) return [a if a < b else -1 for a, b in zip(dist, disappear)] ``` @@ -289,6 +289,37 @@ func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } ``` +#### TypeScript + +```ts +function minimumTime(n: number, edges: number[][], disappear: number[]): number[] { + const g: [number, number][][] = Array.from({ length: n }, () => []); + for (const [u, v, w] of edges) { + g[u].push([v, w]); + g[v].push([u, w]); + } + const dist = Array.from({ length: n }, () => Infinity); + dist[0] = 0; + const pq = new PriorityQueue({ + compare: (a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]), + }); + pq.enqueue([0, 0]); + while (pq.size() > 0) { + const [du, u] = pq.dequeue()!; + if (du > dist[u]) { + continue; + } + for (const [v, w] of g[u]) { + if (dist[v] > dist[u] + w && dist[u] + w < disappear[v]) { + dist[v] = dist[u] + w; + pq.enqueue([dist[v], v]); + } + } + } + return dist.map((a, i) => (a < disappear[i] ? a : -1)); +} +``` + diff --git a/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README_EN.md b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README_EN.md index 9ba4b772101c..5d150f2fbba3 100644 --- a/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README_EN.md +++ b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/README_EN.md @@ -101,20 +101,20 @@ tags: -### Solution 1: Heap Optimized Dijkstra +### Solution 1: Heap-Optimized Dijkstra -First, we create an adjacency list $g$ to store the edges of the graph. Then we create an array $dist$ to store the shortest distance from node $0$ to other nodes. We initialize $dist[0] = 0$ and the distance of other nodes is initialized to infinity. +First, we create an adjacency list $\textit{g}$ to store the edges of the graph. Then, we create an array $\textit{dist}$ to store the shortest distances from node $0$ to other nodes. Initialize $\textit{dist}[0] = 0$, and the distances for the rest of the nodes are initialized to infinity. -Then, we use Dijkstra's algorithm to calculate the shortest distance from node $0$ to other nodes. The specific steps are as follows: +Next, we use the Dijkstra algorithm to calculate the shortest distances from node $0$ to other nodes. The specific steps are as follows: -1. Create a priority queue $q$ to store the distance and node number of nodes. Initially, add node $0$ to the queue with a distance of $0$. -2. Take out a node $u$ from the queue. If the distance $du$ of $u$ is greater than $dist[u]$, it means that $u$ has been updated, so skip it directly. -3. Traverse all neighbor nodes $v$ of node $u$. If $dist[v] > dist[u] + w$ and $dist[u] + w < disappear[v]$, then update $dist[v] = dist[u] + w$ and add node $v$ to the queue. +1. Create a priority queue $\textit{pq}$ to store the distances and node numbers. Initially, add node $0$ to the queue with a distance of $0$. +2. Remove a node $u$ from the queue. If the distance $du$ of $u$ is greater than $\textit{dist}[u]$, it means $u$ has already been updated, so we skip it directly. +3. Iterate through all neighbor nodes $v$ of node $u$. If $\textit{dist}[v] > \textit{dist}[u] + w$ and $\textit{dist}[u] + w < \textit{disappear}[v]$, then update $\textit{dist}[v] = \textit{dist}[u] + w$ and add node $v$ to the queue. 4. Repeat steps 2 and 3 until the queue is empty. -Finally, we traverse the $dist$ array. If $dist[i] < disappear[i]$, then $answer[i] = dist[i]$, otherwise $answer[i] = -1$. +Finally, we iterate through the $\textit{dist}$ array. If $\textit{dist}[i] < \textit{disappear}[i]$, then $\textit{answer}[i] = \textit{dist}[i]$; otherwise, $\textit{answer}[i] = -1$. -The time complexity is $O(m \times \log m)$, and the space complexity is $O(m)$, where $m$ is the number of edges. +The time complexity is $O(m \times \log m)$, and the space complexity is $O(m)$. Here, $m$ is the number of edges. @@ -131,15 +131,15 @@ class Solution: g[v].append((u, w)) dist = [inf] * n dist[0] = 0 - q = [(0, 0)] - while q: - du, u = heappop(q) + pq = [(0, 0)] + while pq: + du, u = heappop(pq) if du > dist[u]: continue for v, w in g[u]: if dist[v] > dist[u] + w and dist[u] + w < disappear[v]: dist[v] = dist[u] + w - heappush(q, (dist[v], v)) + heappush(pq, (dist[v], v)) return [a if a < b else -1 for a, b in zip(dist, disappear)] ``` @@ -287,6 +287,37 @@ func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } ``` +#### TypeScript + +```ts +function minimumTime(n: number, edges: number[][], disappear: number[]): number[] { + const g: [number, number][][] = Array.from({ length: n }, () => []); + for (const [u, v, w] of edges) { + g[u].push([v, w]); + g[v].push([u, w]); + } + const dist = Array.from({ length: n }, () => Infinity); + dist[0] = 0; + const pq = new PriorityQueue({ + compare: (a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]), + }); + pq.enqueue([0, 0]); + while (pq.size() > 0) { + const [du, u] = pq.dequeue()!; + if (du > dist[u]) { + continue; + } + for (const [v, w] of g[u]) { + if (dist[v] > dist[u] + w && dist[u] + w < disappear[v]) { + dist[v] = dist[u] + w; + pq.enqueue([dist[v], v]); + } + } + } + return dist.map((a, i) => (a < disappear[i] ? a : -1)); +} +``` + diff --git a/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/Solution.py b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/Solution.py index 8695ae255103..621600ee6e4c 100644 --- a/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/Solution.py +++ b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/Solution.py @@ -8,13 +8,13 @@ def minimumTime( g[v].append((u, w)) dist = [inf] * n dist[0] = 0 - q = [(0, 0)] - while q: - du, u = heappop(q) + pq = [(0, 0)] + while pq: + du, u = heappop(pq) if du > dist[u]: continue for v, w in g[u]: if dist[v] > dist[u] + w and dist[u] + w < disappear[v]: dist[v] = dist[u] + w - heappush(q, (dist[v], v)) + heappush(pq, (dist[v], v)) return [a if a < b else -1 for a, b in zip(dist, disappear)] diff --git a/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/Solution.ts b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/Solution.ts new file mode 100644 index 000000000000..4751f7f563ed --- /dev/null +++ b/solution/3100-3199/3112.Minimum Time to Visit Disappearing Nodes/Solution.ts @@ -0,0 +1,26 @@ +function minimumTime(n: number, edges: number[][], disappear: number[]): number[] { + const g: [number, number][][] = Array.from({ length: n }, () => []); + for (const [u, v, w] of edges) { + g[u].push([v, w]); + g[v].push([u, w]); + } + const dist = Array.from({ length: n }, () => Infinity); + dist[0] = 0; + const pq = new PriorityQueue({ + compare: (a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]), + }); + pq.enqueue([0, 0]); + while (pq.size() > 0) { + const [du, u] = pq.dequeue()!; + if (du > dist[u]) { + continue; + } + for (const [v, w] of g[u]) { + if (dist[v] > dist[u] + w && dist[u] + w < disappear[v]) { + dist[v] = dist[u] + w; + pq.enqueue([dist[v], v]); + } + } + } + return dist.map((a, i) => (a < disappear[i] ? a : -1)); +} diff --git a/solution/3100-3199/3117.Minimum Sum of Values by Dividing Array/README.md b/solution/3100-3199/3117.Minimum Sum of Values by Dividing Array/README.md index a70a1efd64bf..47dc3567e4e4 100644 --- a/solution/3100-3199/3117.Minimum Sum of Values by Dividing Array/README.md +++ b/solution/3100-3199/3117.Minimum Sum of Values by Dividing Array/README.md @@ -27,7 +27,7 @@ tags:

      数组的 等于该数组的 最后一个 元素。

      -

      你需要将 nums 划分为 m不相交的连续 子数组,对于第 ith 个子数组 [li, ri],子数组元素的按位AND运算结果等于 andValues[i],换句话说,对所有的 1 <= i <= mnums[li] & nums[li + 1] & ... & nums[ri] == andValues[i] ,其中 & 表示按位AND运算符。

      +

      你需要将 nums 划分为 m不相交的连续 子数组,对于第 ith 个子数组 [li, ri],子数组元素的按位 AND 运算结果等于 andValues[i],换句话说,对所有的 1 <= i <= mnums[li] & nums[li + 1] & ... & nums[ri] == andValues[i] ,其中 & 表示按位 AND 运算符。

      返回将 nums 划分为 m 个子数组所能得到的可能的 最小 子数组 之和。如果无法完成这样的划分,则返回 -1

      diff --git a/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README.md b/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README.md index 290a62ef8c63..84108cae8649 100644 --- a/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README.md +++ b/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README.md @@ -82,7 +82,7 @@ tags: 由于我们要尽可能多地修补坑洼,而对于长度为 $k$ 的连续坑洼,我们需要花费 $k + 1$ 的代价,应该优先修补长度较长的坑洼,这样可以使得代价最小。 -因此,我们从最长的坑洼开始修补,对于长度为 $k$ 的坑洼,我们最多可以修补的个数为 $t = \min(\text{budget} / (k + 1), \text{cnt}[k])$,我们将修补的个数乘以长度 $k$ 加到答案中,然后更新剩余的预算。对于长度为 $k$ 的其余 $cnt[k] - t$ 个坑洼,我们将它们合并到长度为 $k - 1$ 的坑洼中。继续这个过程,直到遍历完所有的坑洼。 +因此,我们从最长的坑洼开始修补,对于长度为 $k$ 的坑洼,我们最多可以修补的个数为 $t = \min(\textit{budget} / (k + 1), \textit{cnt}[k])$,我们将修补的个数乘以长度 $k$ 加到答案中,然后更新剩余的预算。对于长度为 $k$ 的其余 $cnt[k] - t$ 个坑洼,我们将它们合并到长度为 $k - 1$ 的坑洼中。继续这个过程,直到遍历完所有的坑洼。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $road$ 的长度。 diff --git a/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README_EN.md b/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README_EN.md index 8b937a829965..0ae2d4782d42 100644 --- a/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README_EN.md +++ b/solution/3100-3199/3119.Maximum Number of Potholes That Can Be Fixed/README_EN.md @@ -82,7 +82,7 @@ First, we count the number of each continuous pothole, recorded in the array $cn Since we want to repair as many potholes as possible, and for a continuous pothole of length $k$, we need to spend a cost of $k + 1$, we should prioritize repairing longer potholes to minimize the cost. -Therefore, we start repairing from the longest pothole. For a pothole of length $k$, the maximum number we can repair is $t = \min(\text{budget} / (k + 1), \text{cnt}[k])$. We add the number of repairs multiplied by the length $k$ to the answer, then update the remaining budget. For the remaining $cnt[k] - t$ potholes of length $k$, we merge them into the potholes of length $k - 1$. Continue this process until all potholes are traversed. +Therefore, we start repairing from the longest pothole. For a pothole of length $k$, the maximum number we can repair is $t = \min(\textit{budget} / (k + 1), \textit{cnt}[k])$. We add the number of repairs multiplied by the length $k$ to the answer, then update the remaining budget. For the remaining $cnt[k] - t$ potholes of length $k$, we merge them into the potholes of length $k - 1$. Continue this process until all potholes are traversed. The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $road$. diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md index f7451e714ecf..e1527b9e6a03 100644 --- a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README.md @@ -101,10 +101,10 @@ tags: 我们定义状态 $f[i][j]$ 表示前 $[0,..i]$ 列数字,且第 $i$ 列数字为 $j$ 的最小操作次数。那么我们可以得到状态转移方程: $$ -f[i][j] = \min_{k \neq j} f[i-1][k] + m - \text{cnt}[j] +f[i][j] = \min_{k \neq j} f[i-1][k] + m - \textit{cnt}[j] $$ -其中 $\text{cnt}[j]$ 表示第 $i$ 列数字为 $j$ 的个数。 +其中 $\textit{cnt}[j]$ 表示第 $i$ 列数字为 $j$ 的个数。 最后我们只需要求出 $f[n-1][j]$ 的最小值即可。 diff --git a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md index 08af516eed73..35f57b8c6f2a 100644 --- a/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md +++ b/solution/3100-3199/3122.Minimum Number of Operations to Satisfy Conditions/README_EN.md @@ -99,10 +99,10 @@ We notice that the values in the cells of the matrix only have 10 possibilities. We define the state $f[i][j]$ to represent the minimum number of operations for the numbers in the first $[0,..i]$ columns, and the number in the $i$-th column is $j$. Then we can get the state transition equation: $$ -f[i][j] = \min_{k \neq j} (f[i-1][k] + m - \text{cnt}[j]) +f[i][j] = \min_{k \neq j} (f[i-1][k] + m - \textit{cnt}[j]) $$ -Where $\text{cnt}[j]$ represents the number of cells in the $i$-th column that are $j$. +Where $\textit{cnt}[j]$ represents the number of cells in the $i$-th column that are $j$. Finally, we only need to find the minimum value of $f[n-1][j]$. diff --git a/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README.md b/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README.md index 8653f4aad4bd..42c153dae461 100644 --- a/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README.md +++ b/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README.md @@ -80,7 +80,7 @@ tags: ### 方法一:位运算 -我们可以找到 $n$ 的二进制表示中最高位的 $1$,那么最大的 $x$ 一定小于 $n$ 且该位为 $0$,其他低位均为 $1$,即 $x = 2^{\text{最高位的位数} - 1} - 1$。这是因为 $x \text{ and } (x + 1) = 0$ 一定成立。 +我们可以找到 $n$ 的二进制表示中最高位的 $1$,那么最大的 $x$ 一定小于 $n$ 且该位为 $0$,其他低位均为 $1$,即 $x = 2^{\textit{最高位的位数} - 1} - 1$。这是因为 $x \textit{ and } (x + 1) = 0$ 一定成立。 时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。 diff --git a/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README_EN.md b/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README_EN.md index e211a32d8909..0c40c9ba9b4a 100644 --- a/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README_EN.md +++ b/solution/3100-3199/3125.Maximum Number That Makes Result of Bitwise AND Zero/README_EN.md @@ -75,7 +75,7 @@ The bitwise AND of [3, 4, 5, 6, 7] is 0.

      ### Solution 1: Bit Manipulation -We can find the highest bit of $1$ in the binary representation of $n$. The maximum $x$ must be less than $n$ and this bit is $0$, and all other lower bits are $1$, i.e., $x = 2^{\text{number of the highest bit}} - 1$. This is because $x \text{ and } (x + 1) = 0$ must hold. +We can find the highest bit of $1$ in the binary representation of $n$. The maximum $x$ must be less than $n$ and this bit is $0$, and all other lower bits are $1$, i.e., $x = 2^{\textit{number of the highest bit}} - 1$. This is because $x \textit{ and } (x + 1) = 0$ must hold. The time complexity is $O(\log n)$, and the space complexity is $O(1)$. diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README.md b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README.md index 8d975b6c1078..c2b006949e5d 100644 --- a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README.md +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README.md @@ -94,10 +94,10 @@ tags: 函数 $dfs(i, j, k)$ 的计算过程如下: - 如果 $i \lt 0$ 或 $j \lt 0$,返回 $0$。 -- 如果 $i = 0$,那么当 $k = 1$ 且 $j \leq \text{limit}$ 时返回 $1$,否则返回 $0$。 -- 如果 $j = 0$,那么当 $k = 0$ 且 $i \leq \text{limit}$ 时返回 $1$,否则返回 $0$。 -- 如果 $k = 0$,我们考虑前一个数字是 $0$ 的情况 $dfs(i - 1, j, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i - 1, j, 1)$,如果前一个数是 $0$,那么有可能使得子数组中有超过 $\text{limit}$ 个 $0$,即不允许出现倒数第 $\text{limit} + 1$ 个数是 $1$ 的情况,所以我们要减去这种情况,即 $dfs(i - \text{limit} - 1, j, 1)$。 -- 如果 $k = 1$,我们考虑前一个数字是 $0$ 的情况 $dfs(i, j - 1, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i, j - 1, 1)$,如果前一个数是 $1$,那么有可能使得子数组中有超过 $\text{limit}$ 个 $1$,即不允许出现倒数第 $\text{limit} + 1$ 个数是 $0$ 的情况,所以我们要减去这种情况,即 $dfs(i, j - \text{limit} - 1, 0)$。 +- 如果 $i = 0$,那么当 $k = 1$ 且 $j \leq \textit{limit}$ 时返回 $1$,否则返回 $0$。 +- 如果 $j = 0$,那么当 $k = 0$ 且 $i \leq \textit{limit}$ 时返回 $1$,否则返回 $0$。 +- 如果 $k = 0$,我们考虑前一个数字是 $0$ 的情况 $dfs(i - 1, j, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i - 1, j, 1)$,如果前一个数是 $0$,那么有可能使得子数组中有超过 $\textit{limit}$ 个 $0$,即不允许出现倒数第 $\textit{limit} + 1$ 个数是 $1$ 的情况,所以我们要减去这种情况,即 $dfs(i - \textit{limit} - 1, j, 1)$。 +- 如果 $k = 1$,我们考虑前一个数字是 $0$ 的情况 $dfs(i, j - 1, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i, j - 1, 1)$,如果前一个数是 $1$,那么有可能使得子数组中有超过 $\textit{limit}$ 个 $1$,即不允许出现倒数第 $\textit{limit} + 1$ 个数是 $0$ 的情况,所以我们要减去这种情况,即 $dfs(i, j - \textit{limit} - 1, 0)$。 为了避免重复计算,我们使用记忆化搜索的方法。 @@ -176,41 +176,34 @@ class Solution { #### C++ ```cpp -using ll = long long; - class Solution { public: int numberOfStableArrays(int zero, int one, int limit) { - this->limit = limit; - f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); - return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; - } - -private: - const int mod = 1e9 + 7; - int limit; - vector>> f; - - ll dfs(int i, int j, int k) { - if (i < 0 || j < 0) { - return 0; - } - if (i == 0) { - return k == 1 && j <= limit; - } - if (j == 0) { - return k == 0 && i <= limit; - } - ll& res = f[i][j][k]; - if (res != -1) { + const int mod = 1e9 + 7; + using ll = long long; + vector>> f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); + auto dfs = [&](auto&& dfs, int i, int j, int k) -> ll { + if (i < 0 || j < 0) { + return 0; + } + if (i == 0) { + return k == 1 && j <= limit; + } + if (j == 0) { + return k == 0 && i <= limit; + } + ll& res = f[i][j][k]; + if (res != -1) { + return res; + } + if (k == 0) { + res = (dfs(dfs, i - 1, j, 0) + dfs(dfs, i - 1, j, 1) - dfs(dfs, i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(dfs, i, j - 1, 0) + dfs(dfs, i, j - 1, 1) - dfs(dfs, i, j - limit - 1, 0) + mod) % mod; + } return res; - } - if (k == 0) { - res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; - } else { - res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; - } - return res; + }; + return (dfs(dfs, zero, one, 0) + dfs(dfs, zero, one, 1)) % mod; } }; ``` @@ -259,6 +252,41 @@ func numberOfStableArrays(zero int, one int, limit int) int { } ``` +#### TypeScript + +```ts +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [-1, -1]), + ); + + const dfs = (i: number, j: number, k: number): number => { + if (i < 0 || j < 0) { + return 0; + } + if (i === 0) { + return k === 1 && j <= limit ? 1 : 0; + } + if (j === 0) { + return k === 0 && i <= limit ? 1 : 0; + } + let res = f[i][j][k]; + if (res !== -1) { + return res; + } + if (k === 0) { + res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; + } + return (f[i][j][k] = res); + }; + + return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; +} +``` + @@ -271,12 +299,12 @@ func numberOfStableArrays(zero int, one int, limit int) int { 我们定义 $f[i][j][k]$ 表示使用 $i$ 个 $0$ 和 $j$ 个 $1$ 且最后一个数字是 $k$ 的稳定二进制数组的个数。那么答案就是 $f[zero][one][0] + f[zero][one][1]$。 -初始时,我们有 $f[i][0][0] = 1$,其中 $1 \leq i \leq \min(\text{limit}, \text{zero})$;有 $f[0][j][1] = 1$,其中 $1 \leq j \leq \min(\text{limit}, \text{one})$。 +初始时,我们有 $f[i][0][0] = 1$,其中 $1 \leq i \leq \min(\textit{limit}, \textit{zero})$;有 $f[0][j][1] = 1$,其中 $1 \leq j \leq \min(\textit{limit}, \textit{one})$。 状态转移方程如下: -- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \text{limit} - 1][j][1]$。 -- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \text{limit} - 1][0]$。 +- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \textit{limit} - 1][j][1]$。 +- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \textit{limit} - 1][0]$。 时间复杂度 $O(zero \times one)$,空间复杂度 $O(zero \times one)$。 @@ -295,16 +323,10 @@ class Solution: f[0][j][1] = 1 for i in range(1, zero + 1): for j in range(1, one + 1): - f[i][j][0] = ( - f[i - 1][j][0] - + f[i - 1][j][1] - - (0 if i - limit - 1 < 0 else f[i - limit - 1][j][1]) - ) % mod - f[i][j][1] = ( - f[i][j - 1][0] - + f[i][j - 1][1] - - (0 if j - limit - 1 < 0 else f[i][j - limit - 1][0]) - ) % mod + x = 0 if i - limit - 1 < 0 else f[i - limit - 1][j][1] + y = 0 if j - limit - 1 < 0 else f[i][j - limit - 1][0] + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x) % mod + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y) % mod return sum(f[zero][one]) % mod ``` @@ -323,12 +345,10 @@ class Solution { } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + long x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + long y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (int) ((f[zero][one][0] + f[zero][one][1]) % mod); @@ -354,12 +374,10 @@ public: } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + ll x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + ll y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (f[zero][one][0] + f[zero][one][1]) % mod; @@ -398,6 +416,35 @@ func numberOfStableArrays(zero int, one int, limit int) int { } ``` +#### TypeScript + +```ts +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [0, 0]), + ); + + for (let i = 1; i <= Math.min(limit, zero); i++) { + f[i][0][0] = 1; + } + for (let j = 1; j <= Math.min(limit, one); j++) { + f[0][j][1] = 1; + } + + for (let i = 1; i <= zero; i++) { + for (let j = 1; j <= one; j++) { + const x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + const y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; + } + } + + return (f[zero][one][0] + f[zero][one][1]) % mod; +} +``` + diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README_EN.md b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README_EN.md index 35924ccabd7d..4888d0a98822 100644 --- a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README_EN.md +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/README_EN.md @@ -92,9 +92,9 @@ We design a function $dfs(i, j, k)$ to represent the number of stable binary arr The calculation process of the function $dfs(i, j, k)$ is as follows: - If $i < 0$ or $j < 0$, return $0$. -- If $i = 0$, return $1$ when $k = 1$ and $j \leq \text{limit}$, otherwise return $0$. -- If $j = 0$, return $1$ when $k = 0$ and $i \leq \text{limit}$, otherwise return $0$. -- If $k = 0$, we consider the case where the previous number is $0$, $dfs(i - 1, j, 0)$, and the case where the previous number is $1$, $dfs(i - 1, j, 1)$. If the previous number is $0$, it may cause more than $\text{limit}$ $0$s in the subarray, i.e., the situation where the $\text{limit} + 1$ +- If $i = 0$, return $1$ when $k = 1$ and $j \leq \textit{limit}$, otherwise return $0$. +- If $j = 0$, return $1$ when $k = 0$ and $i \leq \textit{limit}$, otherwise return $0$. +- If $k = 0$, we consider the case where the previous number is $0$, $dfs(i - 1, j, 0)$, and the case where the previous number is $1$, $dfs(i - 1, j, 1)$. If the previous number is $0$, it may cause more than $\textit{limit}$ $0$s in the subarray, i.e., the situation where the $\textit{limit} + 1$ @@ -167,41 +167,34 @@ class Solution { #### C++ ```cpp -using ll = long long; - class Solution { public: int numberOfStableArrays(int zero, int one, int limit) { - this->limit = limit; - f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); - return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; - } - -private: - const int mod = 1e9 + 7; - int limit; - vector>> f; - - ll dfs(int i, int j, int k) { - if (i < 0 || j < 0) { - return 0; - } - if (i == 0) { - return k == 1 && j <= limit; - } - if (j == 0) { - return k == 0 && i <= limit; - } - ll& res = f[i][j][k]; - if (res != -1) { + const int mod = 1e9 + 7; + using ll = long long; + vector>> f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); + auto dfs = [&](auto&& dfs, int i, int j, int k) -> ll { + if (i < 0 || j < 0) { + return 0; + } + if (i == 0) { + return k == 1 && j <= limit; + } + if (j == 0) { + return k == 0 && i <= limit; + } + ll& res = f[i][j][k]; + if (res != -1) { + return res; + } + if (k == 0) { + res = (dfs(dfs, i - 1, j, 0) + dfs(dfs, i - 1, j, 1) - dfs(dfs, i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(dfs, i, j - 1, 0) + dfs(dfs, i, j - 1, 1) - dfs(dfs, i, j - limit - 1, 0) + mod) % mod; + } return res; - } - if (k == 0) { - res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; - } else { - res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; - } - return res; + }; + return (dfs(dfs, zero, one, 0) + dfs(dfs, zero, one, 1)) % mod; } }; ``` @@ -250,6 +243,41 @@ func numberOfStableArrays(zero int, one int, limit int) int { } ``` +#### TypeScript + +```ts +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [-1, -1]), + ); + + const dfs = (i: number, j: number, k: number): number => { + if (i < 0 || j < 0) { + return 0; + } + if (i === 0) { + return k === 1 && j <= limit ? 1 : 0; + } + if (j === 0) { + return k === 0 && i <= limit ? 1 : 0; + } + let res = f[i][j][k]; + if (res !== -1) { + return res; + } + if (k === 0) { + res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; + } + return (f[i][j][k] = res); + }; + + return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; +} +``` + @@ -262,12 +290,12 @@ We can also convert the memoization search of Solution 1 into dynamic programmin We define $f[i][j][k]$ as the number of stable binary arrays using $i$ $0$s and $j$ $1$s, and the last number is $k$. So the answer is $f[zero][one][0] + f[zero][one][1]$. -Initially, we have $f[i][0][0] = 1$, where $1 \leq i \leq \min(\text{limit}, \text{zero})$; and $f[0][j][1] = 1$, where $1 \leq j \leq \min(\text{limit}, \text{one})$. +Initially, we have $f[i][0][0] = 1$, where $1 \leq i \leq \min(\textit{limit}, \textit{zero})$; and $f[0][j][1] = 1$, where $1 \leq j \leq \min(\textit{limit}, \textit{one})$. The state transition equation is as follows: -- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \text{limit} - 1][j][1]$. -- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \text{limit} - 1][0]$. +- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \textit{limit} - 1][j][1]$. +- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \textit{limit} - 1][0]$. The time complexity is $O(zero \times one)$, and the space complexity is $O(zero \times one)$. @@ -286,16 +314,10 @@ class Solution: f[0][j][1] = 1 for i in range(1, zero + 1): for j in range(1, one + 1): - f[i][j][0] = ( - f[i - 1][j][0] - + f[i - 1][j][1] - - (0 if i - limit - 1 < 0 else f[i - limit - 1][j][1]) - ) % mod - f[i][j][1] = ( - f[i][j - 1][0] - + f[i][j - 1][1] - - (0 if j - limit - 1 < 0 else f[i][j - limit - 1][0]) - ) % mod + x = 0 if i - limit - 1 < 0 else f[i - limit - 1][j][1] + y = 0 if j - limit - 1 < 0 else f[i][j - limit - 1][0] + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x) % mod + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y) % mod return sum(f[zero][one]) % mod ``` @@ -303,37 +325,24 @@ class Solution: ```java class Solution { - private final int mod = (int) 1e9 + 7; - private Long[][][] f; - private int limit; - public int numberOfStableArrays(int zero, int one, int limit) { - f = new Long[zero + 1][one + 1][2]; - this.limit = limit; - return (int) ((dfs(zero, one, 0) + dfs(zero, one, 1)) % mod); - } - - private long dfs(int i, int j, int k) { - if (i < 0 || j < 0) { - return 0; - } - if (i == 0) { - return k == 1 && j <= limit ? 1 : 0; - } - if (j == 0) { - return k == 0 && i <= limit ? 1 : 0; + final int mod = (int) 1e9 + 7; + long[][][] f = new long[zero + 1][one + 1][2]; + for (int i = 1; i <= Math.min(zero, limit); ++i) { + f[i][0][0] = 1; } - if (f[i][j][k] != null) { - return f[i][j][k]; + for (int j = 1; j <= Math.min(one, limit); ++j) { + f[0][j][1] = 1; } - if (k == 0) { - f[i][j][k] - = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; - } else { - f[i][j][k] - = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; + for (int i = 1; i <= zero; ++i) { + for (int j = 1; j <= one; ++j) { + long x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + long y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; + } } - return f[i][j][k]; + return (int) ((f[zero][one][0] + f[zero][one][1]) % mod); } } ``` @@ -356,12 +365,10 @@ public: } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + ll x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + ll y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (f[zero][one][0] + f[zero][one][1]) % mod; @@ -400,6 +407,35 @@ func numberOfStableArrays(zero int, one int, limit int) int { } ``` +#### TypeScript + +```ts +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [0, 0]), + ); + + for (let i = 1; i <= Math.min(limit, zero); i++) { + f[i][0][0] = 1; + } + for (let j = 1; j <= Math.min(limit, one); j++) { + f[0][j][1] = 1; + } + + for (let i = 1; i <= zero; i++) { + for (let j = 1; j <= one; j++) { + const x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + const y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; + } + } + + return (f[zero][one][0] + f[zero][one][1]) % mod; +} +``` + diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution.cpp b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution.cpp index 8f5ef0950d2a..dfee6678a0b5 100644 --- a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution.cpp +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution.cpp @@ -1,37 +1,30 @@ -using ll = long long; - class Solution { public: int numberOfStableArrays(int zero, int one, int limit) { - this->limit = limit; - f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); - return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; - } - -private: - const int mod = 1e9 + 7; - int limit; - vector>> f; - - ll dfs(int i, int j, int k) { - if (i < 0 || j < 0) { - return 0; - } - if (i == 0) { - return k == 1 && j <= limit; - } - if (j == 0) { - return k == 0 && i <= limit; - } - ll& res = f[i][j][k]; - if (res != -1) { + const int mod = 1e9 + 7; + using ll = long long; + vector>> f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); + auto dfs = [&](auto&& dfs, int i, int j, int k) -> ll { + if (i < 0 || j < 0) { + return 0; + } + if (i == 0) { + return k == 1 && j <= limit; + } + if (j == 0) { + return k == 0 && i <= limit; + } + ll& res = f[i][j][k]; + if (res != -1) { + return res; + } + if (k == 0) { + res = (dfs(dfs, i - 1, j, 0) + dfs(dfs, i - 1, j, 1) - dfs(dfs, i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(dfs, i, j - 1, 0) + dfs(dfs, i, j - 1, 1) - dfs(dfs, i, j - limit - 1, 0) + mod) % mod; + } return res; - } - if (k == 0) { - res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; - } else { - res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; - } - return res; + }; + return (dfs(dfs, zero, one, 0) + dfs(dfs, zero, one, 1)) % mod; } -}; \ No newline at end of file +}; diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution.ts b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution.ts new file mode 100644 index 000000000000..64a31af4327d --- /dev/null +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution.ts @@ -0,0 +1,30 @@ +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [-1, -1]), + ); + + const dfs = (i: number, j: number, k: number): number => { + if (i < 0 || j < 0) { + return 0; + } + if (i === 0) { + return k === 1 && j <= limit ? 1 : 0; + } + if (j === 0) { + return k === 0 && i <= limit ? 1 : 0; + } + let res = f[i][j][k]; + if (res !== -1) { + return res; + } + if (k === 0) { + res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; + } + return (f[i][j][k] = res); + }; + + return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; +} diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.cpp b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.cpp index 0d36a39c814d..be0cc582cb90 100644 --- a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.cpp +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.cpp @@ -13,14 +13,12 @@ class Solution { } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + ll x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + ll y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (f[zero][one][0] + f[zero][one][1]) % mod; } -}; \ No newline at end of file +}; diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.java b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.java index ee73b631325c..3aa871fd3244 100644 --- a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.java +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.java @@ -10,14 +10,12 @@ public int numberOfStableArrays(int zero, int one, int limit) { } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + long x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + long y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (int) ((f[zero][one][0] + f[zero][one][1]) % mod); } -} \ No newline at end of file +} diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.py b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.py index 643f1e05590f..861592a92cc1 100644 --- a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.py +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.py @@ -8,14 +8,8 @@ def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int: f[0][j][1] = 1 for i in range(1, zero + 1): for j in range(1, one + 1): - f[i][j][0] = ( - f[i - 1][j][0] - + f[i - 1][j][1] - - (0 if i - limit - 1 < 0 else f[i - limit - 1][j][1]) - ) % mod - f[i][j][1] = ( - f[i][j - 1][0] - + f[i][j - 1][1] - - (0 if j - limit - 1 < 0 else f[i][j - limit - 1][0]) - ) % mod + x = 0 if i - limit - 1 < 0 else f[i - limit - 1][j][1] + y = 0 if j - limit - 1 < 0 else f[i][j - limit - 1][0] + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x) % mod + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y) % mod return sum(f[zero][one]) % mod diff --git a/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.ts b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.ts new file mode 100644 index 000000000000..de481edc1913 --- /dev/null +++ b/solution/3100-3199/3129.Find All Possible Stable Binary Arrays I/Solution2.ts @@ -0,0 +1,24 @@ +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [0, 0]), + ); + + for (let i = 1; i <= Math.min(limit, zero); i++) { + f[i][0][0] = 1; + } + for (let j = 1; j <= Math.min(limit, one); j++) { + f[0][j][1] = 1; + } + + for (let i = 1; i <= zero; i++) { + for (let j = 1; j <= one; j++) { + const x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + const y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; + } + } + + return (f[zero][one][0] + f[zero][one][1]) % mod; +} diff --git a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README.md b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README.md index 992561be8437..7ec6dcc5a675 100644 --- a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README.md +++ b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README.md @@ -94,10 +94,10 @@ tags: 函数 $dfs(i, j, k)$ 的计算过程如下: - 如果 $i \lt 0$ 或 $j \lt 0$,返回 $0$。 -- 如果 $i = 0$,那么当 $k = 1$ 且 $j \leq \text{limit}$ 时返回 $1$,否则返回 $0$。 -- 如果 $j = 0$,那么当 $k = 0$ 且 $i \leq \text{limit}$ 时返回 $1$,否则返回 $0$。 -- 如果 $k = 0$,我们考虑前一个数字是 $0$ 的情况 $dfs(i - 1, j, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i - 1, j, 1)$,如果前一个数是 $0$,那么有可能使得子数组中有超过 $\text{limit}$ 个 $0$,即不允许出现倒数第 $\text{limit} + 1$ 个数是 $1$ 的情况,所以我们要减去这种情况,即 $dfs(i - \text{limit} - 1, j, 1)$。 -- 如果 $k = 1$,我们考虑前一个数字是 $0$ 的情况 $dfs(i, j - 1, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i, j - 1, 1)$,如果前一个数是 $1$,那么有可能使得子数组中有超过 $\text{limit}$ 个 $1$,即不允许出现倒数第 $\text{limit} + 1$ 个数是 $0$ 的情况,所以我们要减去这种情况,即 $dfs(i, j - \text{limit} - 1, 0)$。 +- 如果 $i = 0$,那么当 $k = 1$ 且 $j \leq \textit{limit}$ 时返回 $1$,否则返回 $0$。 +- 如果 $j = 0$,那么当 $k = 0$ 且 $i \leq \textit{limit}$ 时返回 $1$,否则返回 $0$。 +- 如果 $k = 0$,我们考虑前一个数字是 $0$ 的情况 $dfs(i - 1, j, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i - 1, j, 1)$,如果前一个数是 $0$,那么有可能使得子数组中有超过 $\textit{limit}$ 个 $0$,即不允许出现倒数第 $\textit{limit} + 1$ 个数是 $1$ 的情况,所以我们要减去这种情况,即 $dfs(i - \textit{limit} - 1, j, 1)$。 +- 如果 $k = 1$,我们考虑前一个数字是 $0$ 的情况 $dfs(i, j - 1, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i, j - 1, 1)$,如果前一个数是 $1$,那么有可能使得子数组中有超过 $\textit{limit}$ 个 $1$,即不允许出现倒数第 $\textit{limit} + 1$ 个数是 $0$ 的情况,所以我们要减去这种情况,即 $dfs(i, j - \textit{limit} - 1, 0)$。 为了避免重复计算,我们使用记忆化搜索的方法。 @@ -176,41 +176,34 @@ class Solution { #### C++ ```cpp -using ll = long long; - class Solution { public: int numberOfStableArrays(int zero, int one, int limit) { - this->limit = limit; - f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); - return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; - } - -private: - const int mod = 1e9 + 7; - int limit; - vector>> f; - - ll dfs(int i, int j, int k) { - if (i < 0 || j < 0) { - return 0; - } - if (i == 0) { - return k == 1 && j <= limit; - } - if (j == 0) { - return k == 0 && i <= limit; - } - ll& res = f[i][j][k]; - if (res != -1) { + const int mod = 1e9 + 7; + using ll = long long; + vector>> f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); + auto dfs = [&](auto&& dfs, int i, int j, int k) -> ll { + if (i < 0 || j < 0) { + return 0; + } + if (i == 0) { + return k == 1 && j <= limit; + } + if (j == 0) { + return k == 0 && i <= limit; + } + ll& res = f[i][j][k]; + if (res != -1) { + return res; + } + if (k == 0) { + res = (dfs(dfs, i - 1, j, 0) + dfs(dfs, i - 1, j, 1) - dfs(dfs, i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(dfs, i, j - 1, 0) + dfs(dfs, i, j - 1, 1) - dfs(dfs, i, j - limit - 1, 0) + mod) % mod; + } return res; - } - if (k == 0) { - res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; - } else { - res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; - } - return res; + }; + return (dfs(dfs, zero, one, 0) + dfs(dfs, zero, one, 1)) % mod; } }; ``` @@ -271,12 +264,12 @@ func numberOfStableArrays(zero int, one int, limit int) int { 我们定义 $f[i][j][k]$ 表示使用 $i$ 个 $0$ 和 $j$ 个 $1$ 且最后一个数字是 $k$ 的稳定二进制数组的个数。那么答案就是 $f[zero][one][0] + f[zero][one][1]$。 -初始时,我们有 $f[i][0][0] = 1$,其中 $1 \leq i \leq \min(\text{limit}, \text{zero})$;有 $f[0][j][1] = 1$,其中 $1 \leq j \leq \min(\text{limit}, \text{one})$。 +初始时,我们有 $f[i][0][0] = 1$,其中 $1 \leq i \leq \min(\textit{limit}, \textit{zero})$;有 $f[0][j][1] = 1$,其中 $1 \leq j \leq \min(\textit{limit}, \textit{one})$。 状态转移方程如下: -- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \text{limit} - 1][j][1]$。 -- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \text{limit} - 1][0]$。 +- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \textit{limit} - 1][j][1]$。 +- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \textit{limit} - 1][0]$。 时间复杂度 $O(zero \times one)$,空间复杂度 $O(zero \times one)$。 @@ -295,16 +288,10 @@ class Solution: f[0][j][1] = 1 for i in range(1, zero + 1): for j in range(1, one + 1): - f[i][j][0] = ( - f[i - 1][j][0] - + f[i - 1][j][1] - - (0 if i - limit - 1 < 0 else f[i - limit - 1][j][1]) - ) % mod - f[i][j][1] = ( - f[i][j - 1][0] - + f[i][j - 1][1] - - (0 if j - limit - 1 < 0 else f[i][j - limit - 1][0]) - ) % mod + x = 0 if i - limit - 1 < 0 else f[i - limit - 1][j][1] + y = 0 if j - limit - 1 < 0 else f[i][j - limit - 1][0] + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x) % mod + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y) % mod return sum(f[zero][one]) % mod ``` @@ -323,12 +310,10 @@ class Solution { } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + long x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + long y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (int) ((f[zero][one][0] + f[zero][one][1]) % mod); @@ -354,12 +339,10 @@ public: } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + ll x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + ll y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (f[zero][one][0] + f[zero][one][1]) % mod; @@ -398,6 +381,35 @@ func numberOfStableArrays(zero int, one int, limit int) int { } ``` +#### TypeScript + +```ts +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [0, 0]), + ); + + for (let i = 1; i <= Math.min(limit, zero); i++) { + f[i][0][0] = 1; + } + for (let j = 1; j <= Math.min(limit, one); j++) { + f[0][j][1] = 1; + } + + for (let i = 1; i <= zero; i++) { + for (let j = 1; j <= one; j++) { + const x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + const y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; + } + } + + return (f[zero][one][0] + f[zero][one][1]) % mod; +} +``` + diff --git a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README_EN.md b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README_EN.md index cfc043bbd5b4..db7a668d7cdc 100644 --- a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README_EN.md +++ b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/README_EN.md @@ -90,9 +90,9 @@ We design a function $dfs(i, j, k)$ to represent the number of stable binary arr The calculation process of the function $dfs(i, j, k)$ is as follows: - If $i < 0$ or $j < 0$, return $0$. -- If $i = 0$, return $1$ when $k = 1$ and $j \leq \text{limit}$, otherwise return $0$. -- If $j = 0$, return $1$ when $k = 0$ and $i \leq \text{limit}$, otherwise return $0$. -- If $k = 0$, we consider the case where the previous number is $0$, $dfs(i - 1, j, 0)$, and the case where the previous number is $1$, $dfs(i - 1, j, 1)$. If the previous number is $0$, it may cause more than $\text{limit}$ $0$s in the subarray, i.e., the situation where the $\text{limit} + 1$ +- If $i = 0$, return $1$ when $k = 1$ and $j \leq \textit{limit}$, otherwise return $0$. +- If $j = 0$, return $1$ when $k = 0$ and $i \leq \textit{limit}$, otherwise return $0$. +- If $k = 0$, we consider the case where the previous number is $0$, $dfs(i - 1, j, 0)$, and the case where the previous number is $1$, $dfs(i - 1, j, 1)$. If the previous number is $0$, it may cause more than $\textit{limit}$ $0$s in the subarray, i.e., the situation where the $\textit{limit} + 1$ @@ -167,41 +167,34 @@ class Solution { #### C++ ```cpp -using ll = long long; - class Solution { public: int numberOfStableArrays(int zero, int one, int limit) { - this->limit = limit; - f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); - return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; - } - -private: - const int mod = 1e9 + 7; - int limit; - vector>> f; - - ll dfs(int i, int j, int k) { - if (i < 0 || j < 0) { - return 0; - } - if (i == 0) { - return k == 1 && j <= limit; - } - if (j == 0) { - return k == 0 && i <= limit; - } - ll& res = f[i][j][k]; - if (res != -1) { + const int mod = 1e9 + 7; + using ll = long long; + vector>> f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); + auto dfs = [&](auto&& dfs, int i, int j, int k) -> ll { + if (i < 0 || j < 0) { + return 0; + } + if (i == 0) { + return k == 1 && j <= limit; + } + if (j == 0) { + return k == 0 && i <= limit; + } + ll& res = f[i][j][k]; + if (res != -1) { + return res; + } + if (k == 0) { + res = (dfs(dfs, i - 1, j, 0) + dfs(dfs, i - 1, j, 1) - dfs(dfs, i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(dfs, i, j - 1, 0) + dfs(dfs, i, j - 1, 1) - dfs(dfs, i, j - limit - 1, 0) + mod) % mod; + } return res; - } - if (k == 0) { - res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; - } else { - res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; - } - return res; + }; + return (dfs(dfs, zero, one, 0) + dfs(dfs, zero, one, 1)) % mod; } }; ``` @@ -262,12 +255,12 @@ We can also convert the memoization search of Solution 1 into dynamic programmin We define $f[i][j][k]$ as the number of stable binary arrays using $i$ $0$s and $j$ $1$s, and the last number is $k$. So the answer is $f[zero][one][0] + f[zero][one][1]$. -Initially, we have $f[i][0][0] = 1$, where $1 \leq i \leq \min(\text{limit}, \text{zero})$; and $f[0][j][1] = 1$, where $1 \leq j \leq \min(\text{limit}, \text{one})$. +Initially, we have $f[i][0][0] = 1$, where $1 \leq i \leq \min(\textit{limit}, \textit{zero})$; and $f[0][j][1] = 1$, where $1 \leq j \leq \min(\textit{limit}, \textit{one})$. The state transition equation is as follows: -- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \text{limit} - 1][j][1]$. -- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \text{limit} - 1][0]$. +- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \textit{limit} - 1][j][1]$. +- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \textit{limit} - 1][0]$. The time complexity is $O(zero \times one)$, and the space complexity is $O(zero \times one)$. @@ -286,16 +279,10 @@ class Solution: f[0][j][1] = 1 for i in range(1, zero + 1): for j in range(1, one + 1): - f[i][j][0] = ( - f[i - 1][j][0] - + f[i - 1][j][1] - - (0 if i - limit - 1 < 0 else f[i - limit - 1][j][1]) - ) % mod - f[i][j][1] = ( - f[i][j - 1][0] - + f[i][j - 1][1] - - (0 if j - limit - 1 < 0 else f[i][j - limit - 1][0]) - ) % mod + x = 0 if i - limit - 1 < 0 else f[i - limit - 1][j][1] + y = 0 if j - limit - 1 < 0 else f[i][j - limit - 1][0] + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x) % mod + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y) % mod return sum(f[zero][one]) % mod ``` @@ -314,12 +301,10 @@ class Solution { } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + long x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + long y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (int) ((f[zero][one][0] + f[zero][one][1]) % mod); @@ -345,12 +330,10 @@ public: } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + ll x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + ll y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (f[zero][one][0] + f[zero][one][1]) % mod; @@ -389,6 +372,35 @@ func numberOfStableArrays(zero int, one int, limit int) int { } ``` +#### TypeScript + +```ts +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [0, 0]), + ); + + for (let i = 1; i <= Math.min(limit, zero); i++) { + f[i][0][0] = 1; + } + for (let j = 1; j <= Math.min(limit, one); j++) { + f[0][j][1] = 1; + } + + for (let i = 1; i <= zero; i++) { + for (let j = 1; j <= one; j++) { + const x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + const y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; + } + } + + return (f[zero][one][0] + f[zero][one][1]) % mod; +} +``` + diff --git a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution.cpp b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution.cpp index 8f5ef0950d2a..dfee6678a0b5 100644 --- a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution.cpp +++ b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution.cpp @@ -1,37 +1,30 @@ -using ll = long long; - class Solution { public: int numberOfStableArrays(int zero, int one, int limit) { - this->limit = limit; - f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); - return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod; - } - -private: - const int mod = 1e9 + 7; - int limit; - vector>> f; - - ll dfs(int i, int j, int k) { - if (i < 0 || j < 0) { - return 0; - } - if (i == 0) { - return k == 1 && j <= limit; - } - if (j == 0) { - return k == 0 && i <= limit; - } - ll& res = f[i][j][k]; - if (res != -1) { + const int mod = 1e9 + 7; + using ll = long long; + vector>> f = vector>>(zero + 1, vector>(one + 1, {-1, -1})); + auto dfs = [&](auto&& dfs, int i, int j, int k) -> ll { + if (i < 0 || j < 0) { + return 0; + } + if (i == 0) { + return k == 1 && j <= limit; + } + if (j == 0) { + return k == 0 && i <= limit; + } + ll& res = f[i][j][k]; + if (res != -1) { + return res; + } + if (k == 0) { + res = (dfs(dfs, i - 1, j, 0) + dfs(dfs, i - 1, j, 1) - dfs(dfs, i - limit - 1, j, 1) + mod) % mod; + } else { + res = (dfs(dfs, i, j - 1, 0) + dfs(dfs, i, j - 1, 1) - dfs(dfs, i, j - limit - 1, 0) + mod) % mod; + } return res; - } - if (k == 0) { - res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod; - } else { - res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod; - } - return res; + }; + return (dfs(dfs, zero, one, 0) + dfs(dfs, zero, one, 1)) % mod; } -}; \ No newline at end of file +}; diff --git a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.cpp b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.cpp index 0d36a39c814d..be0cc582cb90 100644 --- a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.cpp +++ b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.cpp @@ -13,14 +13,12 @@ class Solution { } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + ll x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + ll y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (f[zero][one][0] + f[zero][one][1]) % mod; } -}; \ No newline at end of file +}; diff --git a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.java b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.java index ee73b631325c..3aa871fd3244 100644 --- a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.java +++ b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.java @@ -10,14 +10,12 @@ public int numberOfStableArrays(int zero, int one, int limit) { } for (int i = 1; i <= zero; ++i) { for (int j = 1; j <= one; ++j) { - f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod) - % mod; - f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod) - % mod; + long x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + long y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; } } return (int) ((f[zero][one][0] + f[zero][one][1]) % mod); } -} \ No newline at end of file +} diff --git a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.py b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.py index 643f1e05590f..861592a92cc1 100644 --- a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.py +++ b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.py @@ -8,14 +8,8 @@ def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int: f[0][j][1] = 1 for i in range(1, zero + 1): for j in range(1, one + 1): - f[i][j][0] = ( - f[i - 1][j][0] - + f[i - 1][j][1] - - (0 if i - limit - 1 < 0 else f[i - limit - 1][j][1]) - ) % mod - f[i][j][1] = ( - f[i][j - 1][0] - + f[i][j - 1][1] - - (0 if j - limit - 1 < 0 else f[i][j - limit - 1][0]) - ) % mod + x = 0 if i - limit - 1 < 0 else f[i - limit - 1][j][1] + y = 0 if j - limit - 1 < 0 else f[i][j - limit - 1][0] + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x) % mod + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y) % mod return sum(f[zero][one]) % mod diff --git a/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.ts b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.ts new file mode 100644 index 000000000000..de481edc1913 --- /dev/null +++ b/solution/3100-3199/3130.Find All Possible Stable Binary Arrays II/Solution2.ts @@ -0,0 +1,24 @@ +function numberOfStableArrays(zero: number, one: number, limit: number): number { + const mod = 1e9 + 7; + const f: number[][][] = Array.from({ length: zero + 1 }, () => + Array.from({ length: one + 1 }, () => [0, 0]), + ); + + for (let i = 1; i <= Math.min(limit, zero); i++) { + f[i][0][0] = 1; + } + for (let j = 1; j <= Math.min(limit, one); j++) { + f[0][j][1] = 1; + } + + for (let i = 1; i <= zero; i++) { + for (let j = 1; j <= one; j++) { + const x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]; + const y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]; + f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod; + f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod; + } + } + + return (f[zero][one][0] + f[zero][one][1]) % mod; +} diff --git a/solution/3100-3199/3132.Find the Integer Added to Array II/README.md b/solution/3100-3199/3132.Find the Integer Added to Array II/README.md index 5fa21531a300..228f5937fd5c 100644 --- a/solution/3100-3199/3132.Find the Integer Added to Array II/README.md +++ b/solution/3100-3199/3132.Find the Integer Added to Array II/README.md @@ -109,11 +109,12 @@ class Solution: nums1.sort() nums2.sort() - return min( - x - for x in (nums2[0] - nums1[0], nums2[0] - nums1[1], nums2[0] - nums1[2]) - if f(x) - ) + ans = inf + for i in range(3): + x = nums2[0] - nums1[i] + if f(x): + ans = min(ans, x) + return ans ``` #### Java diff --git a/solution/3100-3199/3132.Find the Integer Added to Array II/README_EN.md b/solution/3100-3199/3132.Find the Integer Added to Array II/README_EN.md index 14781b2a25c7..ce250b7c63e1 100644 --- a/solution/3100-3199/3132.Find the Integer Added to Array II/README_EN.md +++ b/solution/3100-3199/3132.Find the Integer Added to Array II/README_EN.md @@ -107,11 +107,12 @@ class Solution: nums1.sort() nums2.sort() - return min( - x - for x in (nums2[0] - nums1[0], nums2[0] - nums1[1], nums2[0] - nums1[2]) - if f(x) - ) + ans = inf + for i in range(3): + x = nums2[0] - nums1[i] + if f(x): + ans = min(ans, x) + return ans ``` #### Java diff --git a/solution/3100-3199/3132.Find the Integer Added to Array II/Solution.py b/solution/3100-3199/3132.Find the Integer Added to Array II/Solution.py index a4e5a4725964..5cdd11fd4051 100644 --- a/solution/3100-3199/3132.Find the Integer Added to Array II/Solution.py +++ b/solution/3100-3199/3132.Find the Integer Added to Array II/Solution.py @@ -12,8 +12,9 @@ def f(x: int) -> bool: nums1.sort() nums2.sort() - return min( - x - for x in (nums2[0] - nums1[0], nums2[0] - nums1[1], nums2[0] - nums1[2]) - if f(x) - ) + ans = inf + for i in range(3): + x = nums2[0] - nums1[i] + if f(x): + ans = min(ans, x) + return ans diff --git a/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README.md b/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README.md index 5922952b0aba..795b7f5f05de 100644 --- a/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README.md +++ b/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README.md @@ -120,8 +120,8 @@ tags: $$ f[i][j] = \begin{cases} -f[i - 1][j - 1] + 1, & \text{if } \text{initial}[i - 1] = \text{target}[j - 1], \\ -0, & \text{otherwise}. +f[i - 1][j - 1] + 1, & \textit{if } \textit{initial}[i - 1] = \textit{target}[j - 1], \\ +0, & \textit{otherwise}. \end{cases} $$ diff --git a/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README_EN.md b/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README_EN.md index 511240f056ad..d3d972bd89df 100644 --- a/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README_EN.md +++ b/solution/3100-3199/3135.Equalize Strings by Adding or Removing Characters at Ends/README_EN.md @@ -118,8 +118,8 @@ We can use dynamic programming to find the length $mx$ of the longest common sub $$ f[i][j] = \begin{cases} -f[i - 1][j - 1] + 1, & \text{if } \text{initial}[i - 1] = \text{target}[j - 1], \\ -0, & \text{otherwise}. +f[i - 1][j - 1] + 1, & \textit{if } \textit{initial}[i - 1] = \textit{target}[j - 1], \\ +0, & \textit{otherwise}. \end{cases} $$ diff --git a/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README.md b/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README.md index b2dc2f96bd8c..929398345127 100644 --- a/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README.md +++ b/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README.md @@ -69,13 +69,13 @@ tags: ### 方法一:枚举 -根据题目描述,字符串 $\text{t}$ 的长度一定是 $\text{s}$ 的长度的因子,我们可以从小到大枚举字符串 $\text{t}$ 的长度 $k$,然后检查是否满足题目要求,如果满足则返回。因此,问题转化为如何检查字符串 $\text{t}$ 的长度 $k$ 是否满足题目要求。 +根据题目描述,字符串 $\textit{t}$ 的长度一定是 $\textit{s}$ 的长度的因子,我们可以从小到大枚举字符串 $\textit{t}$ 的长度 $k$,然后检查是否满足题目要求,如果满足则返回。因此,问题转化为如何检查字符串 $\textit{t}$ 的长度 $k$ 是否满足题目要求。 -我们首先统计字符串 $\text{s}$ 中每个字符出现的次数,记录在数组或哈希表 $\text{cnt}$ 中。 +我们首先统计字符串 $\textit{s}$ 中每个字符出现的次数,记录在数组或哈希表 $\textit{cnt}$ 中。 -然后,我们定义一个函数 $\text{check}(k)$,用来检查字符串 $\text{t}$ 的长度 $k$ 是否满足题目要求。我们可以遍历字符串 $\text{s}$,每次取长度为 $k$ 的子串,然后统计每个字符出现的次数,如果每个字符出现的次数乘以 $\frac{n}{k}$ 不等于 $\text{cnt}$ 中的值,则返回 $\text{false}$。遍历结束,如果都满足,则返回 $\text{true}$。 +然后,我们定义一个函数 $\textit{check}(k)$,用来检查字符串 $\textit{t}$ 的长度 $k$ 是否满足题目要求。我们可以遍历字符串 $\textit{s}$,每次取长度为 $k$ 的子串,然后统计每个字符出现的次数,如果每个字符出现的次数乘以 $\frac{n}{k}$ 不等于 $\textit{cnt}$ 中的值,则返回 $\textit{false}$。遍历结束,如果都满足,则返回 $\textit{true}$。 -时间复杂度 $O(n \times A)$,其中 $n$ 是字符串 $\text{s}$ 的长度,而 $A$ 是 $n$ 的因子个数。空间复杂度 $O(|\Sigma|)$,其中 $\Sigma$ 是字符集,本题中为小写字母集合。 +时间复杂度 $O(n \times A)$,其中 $n$ 是字符串 $\textit{s}$ 的长度,而 $A$ 是 $n$ 的因子个数。空间复杂度 $O(|\Sigma|)$,其中 $\Sigma$ 是字符集,本题中为小写字母集合。 diff --git a/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README_EN.md b/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README_EN.md index 33c9ae074865..e602923c74d7 100644 --- a/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README_EN.md +++ b/solution/3100-3199/3138.Minimum Length of Anagram Concatenation/README_EN.md @@ -67,13 +67,13 @@ tags: ### Solution 1: Enumeration -Based on the problem description, the length of string $\text{t}$ must be a factor of the length of string $\text{s}$. We can enumerate the length $k$ of string $\text{t}$ from small to large, and then check if it meets the requirements of the problem. If it does, we return. Thus, the problem is transformed into how to check whether the length $k$ of string $\text{t}$ meets the requirements. +Based on the problem description, the length of string $\textit{t}$ must be a factor of the length of string $\textit{s}$. We can enumerate the length $k$ of string $\textit{t}$ from small to large, and then check if it meets the requirements of the problem. If it does, we return. Thus, the problem is transformed into how to check whether the length $k$ of string $\textit{t}$ meets the requirements. -First, we count the occurrence of each character in string $\text{s}$ and record it in an array or hash table $\text{cnt}$. +First, we count the occurrence of each character in string $\textit{s}$ and record it in an array or hash table $\textit{cnt}$. -Next, we define a function $\text{check}(k)$ to check whether the length $k$ of string $\text{t}$ meets the requirements. We can traverse string $\text{s}$, taking a substring of length $k$ each time, and then count the occurrence of each character. If the occurrence of each character multiplied by $\frac{n}{k}$ does not equal the value in $\text{cnt}$, then return $\text{false}$. If all checks pass by the end of the traversal, return $\text{true}$. +Next, we define a function $\textit{check}(k)$ to check whether the length $k$ of string $\textit{t}$ meets the requirements. We can traverse string $\textit{s}$, taking a substring of length $k$ each time, and then count the occurrence of each character. If the occurrence of each character multiplied by $\frac{n}{k}$ does not equal the value in $\textit{cnt}$, then return $\textit{false}$. If all checks pass by the end of the traversal, return $\textit{true}$. -The time complexity is $O(n \times A)$, where $n$ is the length of string $\text{s}$, and $A$ is the number of factors of $n$. The space complexity is $O(|\Sigma|)$, where $\Sigma$ is the character set, which in this case is the set of lowercase letters. +The time complexity is $O(n \times A)$, where $n$ is the length of string $\textit{s}$, and $A$ is the number of factors of $n$. The space complexity is $O(|\Sigma|)$, where $\Sigma$ is the character set, which in this case is the set of lowercase letters. diff --git a/solution/3100-3199/3141.Maximum Hamming Distances/README.md b/solution/3100-3199/3141.Maximum Hamming Distances/README.md index b36eda6f9c07..957087931a47 100644 --- a/solution/3100-3199/3141.Maximum Hamming Distances/README.md +++ b/solution/3100-3199/3141.Maximum Hamming Distances/README.md @@ -90,12 +90,12 @@ tags: 具体步骤如下: -1. 初始化一个数组 $\text{dist}$,数组长度为 $2^m$,用来记录每个取反后的元素到其他元素的最小海明距离,初始时全部置为 $-1$。 -2. 遍历数组 $\text{nums}$,将每个元素的取反值置为 $0$,并将其加入队列 $\text{q}$。 -3. 从 $k = 1$ 开始,不断遍历队列 $\text{q}$,每次遍历时,将队列中的元素取出,然后对其进行 $m$ 次取反操作,将取反后的元素加入队列 $\text{t}$,并将其到原元素的最小海明距离置为 $k$。 +1. 初始化一个数组 $\textit{dist}$,数组长度为 $2^m$,用来记录每个取反后的元素到其他元素的最小海明距离,初始时全部置为 $-1$。 +2. 遍历数组 $\textit{nums}$,将每个元素的取反值置为 $0$,并将其加入队列 $\textit{q}$。 +3. 从 $k = 1$ 开始,不断遍历队列 $\textit{q}$,每次遍历时,将队列中的元素取出,然后对其进行 $m$ 次取反操作,将取反后的元素加入队列 $\textit{t}$,并将其到原元素的最小海明距离置为 $k$。 4. 重复步骤 3,直到队列为空。 -最后,我们遍历数组 $\text{nums}$,将每个元素取反后的值作为下标,从 $\text{dist}$ 数组中取出对应的最小海明距离,然后用 $m$ 减去这个值,就是我们要求的最大海明距离。 +最后,我们遍历数组 $\textit{nums}$,将每个元素取反后的值作为下标,从 $\textit{dist}$ 数组中取出对应的最小海明距离,然后用 $m$ 减去这个值,就是我们要求的最大海明距离。 时间复杂度 $O(2^m)$,空间复杂度 $O(2^m)$。其中 $m$ 为题目给定的整数。 diff --git a/solution/3100-3199/3141.Maximum Hamming Distances/README_EN.md b/solution/3100-3199/3141.Maximum Hamming Distances/README_EN.md index 4978dba7eb1c..172be39cb2aa 100644 --- a/solution/3100-3199/3141.Maximum Hamming Distances/README_EN.md +++ b/solution/3100-3199/3141.Maximum Hamming Distances/README_EN.md @@ -88,12 +88,12 @@ We can use Breadth-First Search (BFS) to find the minimum Hamming distance from The specific steps are as follows: -1. Initialize an array $\text{dist}$ with a length of $2^m$ to record the minimum Hamming distance from each complemented element to other elements. Initially, all are set to $-1$. -2. Traverse the array $\text{nums}$, set the complement of each element to $0$, and add it to the queue $\text{q}$. -3. Starting from $k = 1$, continuously traverse the queue $\text{q}$. Each time, take out the elements in the queue, perform $m$ complement operations on them, add the complemented elements to the queue $\text{t}$, and set the minimum Hamming distance to the original element to $k$. +1. Initialize an array $\textit{dist}$ with a length of $2^m$ to record the minimum Hamming distance from each complemented element to other elements. Initially, all are set to $-1$. +2. Traverse the array $\textit{nums}$, set the complement of each element to $0$, and add it to the queue $\textit{q}$. +3. Starting from $k = 1$, continuously traverse the queue $\textit{q}$. Each time, take out the elements in the queue, perform $m$ complement operations on them, add the complemented elements to the queue $\textit{t}$, and set the minimum Hamming distance to the original element to $k$. 4. Repeat step 3 until the queue is empty. -Finally, we traverse the array $\text{nums}$, take the complement of each element as the index, and take out the corresponding minimum Hamming distance from the $\text{dist}$ array. Then, $m$ minus this value is the maximum Hamming distance we are looking for. +Finally, we traverse the array $\textit{nums}$, take the complement of each element as the index, and take out the corresponding minimum Hamming distance from the $\textit{dist}$ array. Then, $m$ minus this value is the maximum Hamming distance we are looking for. The time complexity is $O(2^m)$, and the space complexity is $O(2^m)$, where $m$ is the integer given in the problem. diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README.md b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README.md index a668078a1855..afce030b63e1 100644 --- a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README.md +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README.md @@ -70,19 +70,19 @@ tags: ### 方法一:记忆化搜索 + 哈希表 -我们设计一个函数 $\text{dfs}(i)$,表示从字符串 $s[i]$ 开始分割的最少子字符串数量。那么答案就是 $\text{dfs}(0)$。 +我们设计一个函数 $\textit{dfs}(i)$,表示从字符串 $s[i]$ 开始分割的最少子字符串数量。那么答案就是 $\textit{dfs}(0)$。 -函数 $\text{dfs}(i)$ 的计算过程如下: +函数 $\textit{dfs}(i)$ 的计算过程如下: 如果 $i \geq n$,表示已经处理完了所有字符,返回 $0$。 -否则,我们维护一个哈希表 $\text{cnt}$,表示当前子字符串中每个字符出现的次数。另外,我们还维护一个哈希表 $\text{freq}$,表示每个字符出现的次数的频率。 +否则,我们维护一个哈希表 $\textit{cnt}$,表示当前子字符串中每个字符出现的次数。另外,我们还维护一个哈希表 $\textit{freq}$,表示每个字符出现的次数的频率。 -然后我们枚举 $j$ 从 $i$ 到 $n-1$,表示当前子字符串的结束位置。对于每个 $j$,我们更新 $\text{cnt}$ 和 $\text{freq}$,然后判断 $\text{freq}$ 的大小是否为 $1$,如果是的话,我们可以从 $j+1$ 开始分割,此时答案为 $1 + \text{dfs}(j+1)$,我们取所有 $j$ 中答案的最小值作为函数的返回值。 +然后我们枚举 $j$ 从 $i$ 到 $n-1$,表示当前子字符串的结束位置。对于每个 $j$,我们更新 $\textit{cnt}$ 和 $\textit{freq}$,然后判断 $\textit{freq}$ 的大小是否为 $1$,如果是的话,我们可以从 $j+1$ 开始分割,此时答案为 $1 + \textit{dfs}(j+1)$,我们取所有 $j$ 中答案的最小值作为函数的返回值。 为了避免重复计算,我们使用记忆化搜索。 -时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。 +时间复杂度 $O(n^2)$,空间复杂度 $O(n \times |\Sigma|)$。其中 $n$ 为字符串 $s$ 的长度,而 $|\Sigma|$ 表示字符集的大小,本题中 $|\Sigma| = 26$。 @@ -165,7 +165,7 @@ public: int n = s.size(); int f[n]; memset(f, -1, sizeof(f)); - function dfs = [&](int i) { + auto dfs = [&](auto&& dfs, int i) -> int { if (i >= n) { return 0; } @@ -186,12 +186,12 @@ public: ++cnt[k]; ++freq[cnt[k]]; if (freq.size() == 1) { - f[i] = min(f[i], 1 + dfs(j + 1)); + f[i] = min(f[i], 1 + dfs(dfs, j + 1)); } } return f[i]; }; - return dfs(0); + return dfs(dfs, 0); } }; ``` @@ -276,4 +276,320 @@ function minimumSubstringsInPartition(s: string): number { + + +### 方法二:记忆化搜索(优化) + +我们可以对方法一进行优化,不需要维护 $\textit{freq}$ 哈希表,只需要维护一个哈希表 $\textit{cnt}$,表示当前子字符串中每个字符出现的次数。另外,维护两个变量 $k$ 和 $m$ 分别表示当前子字符串中的字符种类数和出现次数最多的字符的出现次数。对于一个子串 $s[i..j]$,如果 $j-i+1 = m \times k$,那么这个子串就是一个平衡子串。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n \times |\Sigma|)$。其中 $n$ 为字符串 $s$ 的长度,而 $|\Sigma|$ 表示字符集的大小,本题中 $|\Sigma| = 26$。 + + + +#### Python3 + +```python +class Solution: + def minimumSubstringsInPartition(self, s: str) -> int: + @cache + def dfs(i: int) -> int: + if i >= n: + return 0 + cnt = defaultdict(int) + m = 0 + ans = n - i + for j in range(i, n): + cnt[s[j]] += 1 + m = max(m, cnt[s[j]]) + if j - i + 1 == m * len(cnt): + ans = min(ans, 1 + dfs(j + 1)) + return ans + + n = len(s) + ans = dfs(0) + dfs.cache_clear() + return ans +``` + +#### Java + +```java +class Solution { + private int n; + private char[] s; + private Integer[] f; + + public int minimumSubstringsInPartition(String s) { + n = s.length(); + f = new Integer[n]; + this.s = s.toCharArray(); + return dfs(0); + } + + private int dfs(int i) { + if (i >= n) { + return 0; + } + if (f[i] != null) { + return f[i]; + } + int[] cnt = new int[26]; + int ans = n - i; + int k = 0, m = 0; + for (int j = i; j < n; ++j) { + k += ++cnt[s[j] - 'a'] == 1 ? 1 : 0; + m = Math.max(m, cnt[s[j] - 'a']); + if (j - i + 1 == k * m) { + ans = Math.min(ans, 1 + dfs(j + 1)); + } + } + return f[i] = ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumSubstringsInPartition(string s) { + int n = s.size(); + int f[n]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (i >= n) { + return 0; + } + if (f[i] != -1) { + return f[i]; + } + f[i] = n - i; + int cnt[26]{}; + int k = 0, m = 0; + for (int j = i; j < n; ++j) { + k += ++cnt[s[j] - 'a'] == 1 ? 1 : 0; + m = max(m, cnt[s[j] - 'a']); + if (j - i + 1 == k * m) { + f[i] = min(f[i], 1 + dfs(dfs, j + 1)); + } + } + return f[i]; + }; + return dfs(dfs, 0); + } +}; +``` + +#### Go + +```go +func minimumSubstringsInPartition(s string) int { + n := len(s) + f := make([]int, n) + for i := range f { + f[i] = -1 + } + var dfs func(int) int + dfs = func(i int) int { + if i >= n { + return 0 + } + if f[i] != -1 { + return f[i] + } + cnt := [26]int{} + f[i] = n - i + k, m := 0, 0 + for j := i; j < n; j++ { + x := int(s[j] - 'a') + cnt[x]++ + if cnt[x] == 1 { + k++ + } + m = max(m, cnt[x]) + if j-i+1 == k*m { + f[i] = min(f[i], 1+dfs(j+1)) + } + } + return f[i] + } + return dfs(0) +} +``` + +#### TypeScript + +```ts +function minimumSubstringsInPartition(s: string): number { + const n = s.length; + const f: number[] = Array(n).fill(-1); + const dfs = (i: number): number => { + if (i >= n) { + return 0; + } + if (f[i] !== -1) { + return f[i]; + } + const cnt: number[] = Array(26).fill(0); + f[i] = n - i; + let [k, m] = [0, 0]; + for (let j = i; j < n; ++j) { + const x = s.charCodeAt(j) - 97; + k += ++cnt[x] === 1 ? 1 : 0; + m = Math.max(m, cnt[x]); + if (j - i + 1 === k * m) { + f[i] = Math.min(f[i], 1 + dfs(j + 1)); + } + } + return f[i]; + }; + return dfs(0); +} +``` + + + + + + + +### 方法三:动态规划 + +我们可以将记忆化搜索转换为动态规划,定义状态 $f[i]$ 对前 $i$ 个字符进行分割的最少子字符串数量。初始时 $f[0] = 0$,其余 $f[i] = +\infty$ 或者 $f[i] = n$。 + +接下来我们枚举 $i$ 从 $0$ 到 $n-1$,对于每个 $i$,我们维护一个哈希表 $\textit{cnt}$,表示当前子字符串中每个字符出现的次数。另外,我们维护两个变量 $k$ 和 $m$ 分别表示当前子字符串中的字符种类数和出现次数最多的字符的出现次数。对于一个子串 $s[j..i]$,如果 $i-j+1 = m \times k$,那么这个子串就是一个平衡子串。此时我们可以从 $j$ 开始分割,那么 $f[i+1] = \min(f[i+1], f[j] + 1)$。 + +最终答案为 $f[n]$。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n + |\Sigma|)$。其中 $n$ 为字符串 $s$ 的长度,而 $|\Sigma|$ 表示字符集的大小,本题中 $|\Sigma| = 26$。 + + + +#### Python3 + +```python +class Solution: + def minimumSubstringsInPartition(self, s: str) -> int: + n = len(s) + f = [inf] * (n + 1) + f[0] = 0 + for i in range(n): + cnt = defaultdict(int) + m = 0 + for j in range(i, -1, -1): + cnt[s[j]] += 1 + m = max(m, cnt[s[j]]) + if i - j + 1 == len(cnt) * m: + f[i + 1] = min(f[i + 1], f[j] + 1) + return f[n] +``` + +#### Java + +```java +class Solution { + public int minimumSubstringsInPartition(String s) { + int n = s.length(); + char[] cs = s.toCharArray(); + int[] f = new int[n + 1]; + Arrays.fill(f, n); + f[0] = 0; + for (int i = 0; i < n; ++i) { + int[] cnt = new int[26]; + int k = 0, m = 0; + for (int j = i; j >= 0; --j) { + k += ++cnt[cs[j] - 'a'] == 1 ? 1 : 0; + m = Math.max(m, cnt[cs[j] - 'a']); + if (i - j + 1 == k * m) { + f[i + 1] = Math.min(f[i + 1], 1 + f[j]); + } + } + } + return f[n]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumSubstringsInPartition(string s) { + int n = s.size(); + vector f(n + 1, n); + f[0] = 0; + for (int i = 0; i < n; ++i) { + int cnt[26]{}; + int k = 0, m = 0; + for (int j = i; ~j; --j) { + k += ++cnt[s[j] - 'a'] == 1; + m = max(m, cnt[s[j] - 'a']); + if (i - j + 1 == k * m) { + f[i + 1] = min(f[i + 1], f[j] + 1); + } + } + } + return f[n]; + } +}; +``` + +#### Go + +```go +func minimumSubstringsInPartition(s string) int { + n := len(s) + f := make([]int, n+1) + for i := range f { + f[i] = n + } + f[0] = 0 + for i := 0; i < n; i++ { + cnt := [26]int{} + k, m := 0, 0 + for j := i; j >= 0; j-- { + x := int(s[j] - 'a') + cnt[x]++ + if cnt[x] == 1 { + k++ + } + m = max(m, cnt[x]) + if i-j+1 == k*m { + f[i+1] = min(f[i+1], 1+f[j]) + } + } + } + return f[n] +} +``` + +#### TypeScript + +```ts +function minimumSubstringsInPartition(s: string): number { + const n = s.length; + const f: number[] = Array(n + 1).fill(n); + f[0] = 0; + for (let i = 0; i < n; ++i) { + const cnt: number[] = Array(26).fill(0); + let [k, m] = [0, 0]; + for (let j = i; ~j; --j) { + const x = s.charCodeAt(j) - 97; + k += ++cnt[x] === 1 ? 1 : 0; + m = Math.max(m, cnt[x]); + if (i - j + 1 === k * m) { + f[i + 1] = Math.min(f[i + 1], 1 + f[j]); + } + } + } + return f[n]; +} +``` + + + + + diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README_EN.md b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README_EN.md index b719a3f5d289..0a1cae6cedec 100644 --- a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README_EN.md +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/README_EN.md @@ -66,21 +66,21 @@ tags: -### Solution 1: Memoization Search + Hash Table +### Solution 1: Memoized Search + Hash Table -We design a function $\text{dfs}(i)$, which represents the minimum number of substrings starting from the string $s[i]$. So the answer is $\text{dfs}(0)$. +We design a function $\textit{dfs}(i)$, which represents the minimum number of substrings starting from $s[i]$. The answer is $\textit{dfs}(0)$. -The calculation process of the function $\text{dfs}(i)$ is as follows: +The calculation process of the function $\textit{dfs}(i)$ is as follows: -If $i \geq n$, it means that all characters have been processed, return $0$. +If $i \geq n$, it means all characters have been processed, so return $0$. -Otherwise, we maintain a hash table $\text{cnt}$, which represents the number of occurrences of each character in the current substring. In addition, we also maintain a hash table $\text{freq}$, which represents the frequency of the number of occurrences of each character. +Otherwise, we maintain a hash table $\textit{cnt}$ to represent the frequency of each character in the current substring. Additionally, we maintain a hash table $\textit{freq}$ to represent the frequency of each character's occurrence count. -Then we enumerate $j$ from $i$ to $n-1$, which represents the end position of the current substring. For each $j$, we update $\text{cnt}$ and $\text{freq}$, then check whether the size of $\text{freq}$ is $1$. If so, we can start splitting from $j+1$, at this time the answer is $1 + \text{dfs}(j+1)$. We take the minimum value of the answer among all $j$ as the return value of the function. +Then we enumerate $j$ from $i$ to $n-1$, representing the end position of the current substring. For each $j$, we update $\textit{cnt}$ and $\textit{freq}$, then check if the size of $\textit{freq}$ is $1$. If it is, we can split from $j+1$, and the answer is $1 + \textit{dfs}(j+1)$. We take the minimum answer among all $j$ as the return value of the function. -To avoid repeated calculations, we use memoization search. +To avoid repeated calculations, we use memoized search. -The time complexity is $O(n^2)$, and the space complexity is $O(n)$. Where $n$ is the length of the string $s$. +The time complexity is $O(n^2)$, and the space complexity is $O(n \times |\Sigma|)$. Here, $n$ is the length of the string $s$, and $|\Sigma|$ represents the size of the character set, which is $26$ in this problem. @@ -163,7 +163,7 @@ public: int n = s.size(); int f[n]; memset(f, -1, sizeof(f)); - function dfs = [&](int i) { + auto dfs = [&](auto&& dfs, int i) -> int { if (i >= n) { return 0; } @@ -184,12 +184,12 @@ public: ++cnt[k]; ++freq[cnt[k]]; if (freq.size() == 1) { - f[i] = min(f[i], 1 + dfs(j + 1)); + f[i] = min(f[i], 1 + dfs(dfs, j + 1)); } } return f[i]; }; - return dfs(0); + return dfs(dfs, 0); } }; ``` @@ -274,4 +274,320 @@ function minimumSubstringsInPartition(s: string): number { + + +### Solution 2: Memoized Search (Optimization) + +We can optimize Solution 1 by not maintaining the $\textit{freq}$ hash table. Instead, we only need to maintain a hash table $\textit{cnt}$, which represents the frequency of each character in the current substring. Additionally, we maintain two variables $k$ and $m$ to represent the number of distinct characters in the current substring and the maximum frequency of any character, respectively. For a substring $s[i..j]$, if $j-i+1 = m \times k$, then this substring is a balanced substring. + +The time complexity is $O(n^2)$, and the space complexity is $O(n \times |\Sigma|)$. Here, $n$ is the length of the string $s$, and $|\Sigma|$ represents the size of the character set, which is $26$ in this problem. + + + +#### Python3 + +```python +class Solution: + def minimumSubstringsInPartition(self, s: str) -> int: + @cache + def dfs(i: int) -> int: + if i >= n: + return 0 + cnt = defaultdict(int) + m = 0 + ans = n - i + for j in range(i, n): + cnt[s[j]] += 1 + m = max(m, cnt[s[j]]) + if j - i + 1 == m * len(cnt): + ans = min(ans, 1 + dfs(j + 1)) + return ans + + n = len(s) + ans = dfs(0) + dfs.cache_clear() + return ans +``` + +#### Java + +```java +class Solution { + private int n; + private char[] s; + private Integer[] f; + + public int minimumSubstringsInPartition(String s) { + n = s.length(); + f = new Integer[n]; + this.s = s.toCharArray(); + return dfs(0); + } + + private int dfs(int i) { + if (i >= n) { + return 0; + } + if (f[i] != null) { + return f[i]; + } + int[] cnt = new int[26]; + int ans = n - i; + int k = 0, m = 0; + for (int j = i; j < n; ++j) { + k += ++cnt[s[j] - 'a'] == 1 ? 1 : 0; + m = Math.max(m, cnt[s[j] - 'a']); + if (j - i + 1 == k * m) { + ans = Math.min(ans, 1 + dfs(j + 1)); + } + } + return f[i] = ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumSubstringsInPartition(string s) { + int n = s.size(); + int f[n]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (i >= n) { + return 0; + } + if (f[i] != -1) { + return f[i]; + } + f[i] = n - i; + int cnt[26]{}; + int k = 0, m = 0; + for (int j = i; j < n; ++j) { + k += ++cnt[s[j] - 'a'] == 1 ? 1 : 0; + m = max(m, cnt[s[j] - 'a']); + if (j - i + 1 == k * m) { + f[i] = min(f[i], 1 + dfs(dfs, j + 1)); + } + } + return f[i]; + }; + return dfs(dfs, 0); + } +}; +``` + +#### Go + +```go +func minimumSubstringsInPartition(s string) int { + n := len(s) + f := make([]int, n) + for i := range f { + f[i] = -1 + } + var dfs func(int) int + dfs = func(i int) int { + if i >= n { + return 0 + } + if f[i] != -1 { + return f[i] + } + cnt := [26]int{} + f[i] = n - i + k, m := 0, 0 + for j := i; j < n; j++ { + x := int(s[j] - 'a') + cnt[x]++ + if cnt[x] == 1 { + k++ + } + m = max(m, cnt[x]) + if j-i+1 == k*m { + f[i] = min(f[i], 1+dfs(j+1)) + } + } + return f[i] + } + return dfs(0) +} +``` + +#### TypeScript + +```ts +function minimumSubstringsInPartition(s: string): number { + const n = s.length; + const f: number[] = Array(n).fill(-1); + const dfs = (i: number): number => { + if (i >= n) { + return 0; + } + if (f[i] !== -1) { + return f[i]; + } + const cnt: number[] = Array(26).fill(0); + f[i] = n - i; + let [k, m] = [0, 0]; + for (let j = i; j < n; ++j) { + const x = s.charCodeAt(j) - 97; + k += ++cnt[x] === 1 ? 1 : 0; + m = Math.max(m, cnt[x]); + if (j - i + 1 === k * m) { + f[i] = Math.min(f[i], 1 + dfs(j + 1)); + } + } + return f[i]; + }; + return dfs(0); +} +``` + + + + + + + +### Solution 3: Dynamic Programming + +We can convert the memoized search into dynamic programming. Define the state $f[i]$ as the minimum number of substrings required to partition the first $i$ characters. Initially, $f[0] = 0$, and the rest $f[i] = +\infty$ or $f[i] = n$. + +Next, we enumerate $i$ from $0$ to $n-1$. For each $i$, we maintain a hash table $\textit{cnt}$ to represent the frequency of each character in the current substring. Additionally, we maintain two variables $k$ and $m$ to represent the number of distinct characters in the current substring and the maximum frequency of any character, respectively. For a substring $s[j..i]$, if $i-j+1 = m \times k$, then this substring is a balanced substring. At this point, we can partition from $j$, so $f[i+1] = \min(f[i+1], f[j] + 1)$. + +The final answer is $f[n]$. + +The time complexity is $O(n^2)$, and the space complexity is $O(n + |\Sigma|)$. Here, $n$ is the length of the string $s$, and $|\Sigma|$ represents the size of the character set, which is $26$ in this problem. + + + +#### Python3 + +```python +class Solution: + def minimumSubstringsInPartition(self, s: str) -> int: + n = len(s) + f = [inf] * (n + 1) + f[0] = 0 + for i in range(n): + cnt = defaultdict(int) + m = 0 + for j in range(i, -1, -1): + cnt[s[j]] += 1 + m = max(m, cnt[s[j]]) + if i - j + 1 == len(cnt) * m: + f[i + 1] = min(f[i + 1], f[j] + 1) + return f[n] +``` + +#### Java + +```java +class Solution { + public int minimumSubstringsInPartition(String s) { + int n = s.length(); + char[] cs = s.toCharArray(); + int[] f = new int[n + 1]; + Arrays.fill(f, n); + f[0] = 0; + for (int i = 0; i < n; ++i) { + int[] cnt = new int[26]; + int k = 0, m = 0; + for (int j = i; j >= 0; --j) { + k += ++cnt[cs[j] - 'a'] == 1 ? 1 : 0; + m = Math.max(m, cnt[cs[j] - 'a']); + if (i - j + 1 == k * m) { + f[i + 1] = Math.min(f[i + 1], 1 + f[j]); + } + } + } + return f[n]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumSubstringsInPartition(string s) { + int n = s.size(); + vector f(n + 1, n); + f[0] = 0; + for (int i = 0; i < n; ++i) { + int cnt[26]{}; + int k = 0, m = 0; + for (int j = i; ~j; --j) { + k += ++cnt[s[j] - 'a'] == 1; + m = max(m, cnt[s[j] - 'a']); + if (i - j + 1 == k * m) { + f[i + 1] = min(f[i + 1], f[j] + 1); + } + } + } + return f[n]; + } +}; +``` + +#### Go + +```go +func minimumSubstringsInPartition(s string) int { + n := len(s) + f := make([]int, n+1) + for i := range f { + f[i] = n + } + f[0] = 0 + for i := 0; i < n; i++ { + cnt := [26]int{} + k, m := 0, 0 + for j := i; j >= 0; j-- { + x := int(s[j] - 'a') + cnt[x]++ + if cnt[x] == 1 { + k++ + } + m = max(m, cnt[x]) + if i-j+1 == k*m { + f[i+1] = min(f[i+1], 1+f[j]) + } + } + } + return f[n] +} +``` + +#### TypeScript + +```ts +function minimumSubstringsInPartition(s: string): number { + const n = s.length; + const f: number[] = Array(n + 1).fill(n); + f[0] = 0; + for (let i = 0; i < n; ++i) { + const cnt: number[] = Array(26).fill(0); + let [k, m] = [0, 0]; + for (let j = i; ~j; --j) { + const x = s.charCodeAt(j) - 97; + k += ++cnt[x] === 1 ? 1 : 0; + m = Math.max(m, cnt[x]); + if (i - j + 1 === k * m) { + f[i + 1] = Math.min(f[i + 1], 1 + f[j]); + } + } + } + return f[n]; +} +``` + + + + + diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution.cpp b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution.cpp index 24042931571a..6bdac4b97dc7 100644 --- a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution.cpp +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution.cpp @@ -4,7 +4,7 @@ class Solution { int n = s.size(); int f[n]; memset(f, -1, sizeof(f)); - function dfs = [&](int i) { + auto dfs = [&](auto&& dfs, int i) -> int { if (i >= n) { return 0; } @@ -25,11 +25,11 @@ class Solution { ++cnt[k]; ++freq[cnt[k]]; if (freq.size() == 1) { - f[i] = min(f[i], 1 + dfs(j + 1)); + f[i] = min(f[i], 1 + dfs(dfs, j + 1)); } } return f[i]; }; - return dfs(0); + return dfs(dfs, 0); } -}; \ No newline at end of file +}; diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.cpp b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.cpp new file mode 100644 index 000000000000..202c1223c947 --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int minimumSubstringsInPartition(string s) { + int n = s.size(); + int f[n]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (i >= n) { + return 0; + } + if (f[i] != -1) { + return f[i]; + } + f[i] = n - i; + int cnt[26]{}; + int k = 0, m = 0; + for (int j = i; j < n; ++j) { + k += ++cnt[s[j] - 'a'] == 1 ? 1 : 0; + m = max(m, cnt[s[j] - 'a']); + if (j - i + 1 == k * m) { + f[i] = min(f[i], 1 + dfs(dfs, j + 1)); + } + } + return f[i]; + }; + return dfs(dfs, 0); + } +}; diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.go b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.go new file mode 100644 index 000000000000..21915c15cfea --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.go @@ -0,0 +1,32 @@ +func minimumSubstringsInPartition(s string) int { + n := len(s) + f := make([]int, n) + for i := range f { + f[i] = -1 + } + var dfs func(int) int + dfs = func(i int) int { + if i >= n { + return 0 + } + if f[i] != -1 { + return f[i] + } + cnt := [26]int{} + f[i] = n - i + k, m := 0, 0 + for j := i; j < n; j++ { + x := int(s[j] - 'a') + cnt[x]++ + if cnt[x] == 1 { + k++ + } + m = max(m, cnt[x]) + if j-i+1 == k*m { + f[i] = min(f[i], 1+dfs(j+1)) + } + } + return f[i] + } + return dfs(0) +} diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.java b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.java new file mode 100644 index 000000000000..dbb93107fc6d --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.java @@ -0,0 +1,32 @@ +class Solution { + private int n; + private char[] s; + private Integer[] f; + + public int minimumSubstringsInPartition(String s) { + n = s.length(); + f = new Integer[n]; + this.s = s.toCharArray(); + return dfs(0); + } + + private int dfs(int i) { + if (i >= n) { + return 0; + } + if (f[i] != null) { + return f[i]; + } + int[] cnt = new int[26]; + int ans = n - i; + int k = 0, m = 0; + for (int j = i; j < n; ++j) { + k += ++cnt[s[j] - 'a'] == 1 ? 1 : 0; + m = Math.max(m, cnt[s[j] - 'a']); + if (j - i + 1 == k * m) { + ans = Math.min(ans, 1 + dfs(j + 1)); + } + } + return f[i] = ans; + } +} diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.py b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.py new file mode 100644 index 000000000000..fef371500aec --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.py @@ -0,0 +1,20 @@ +class Solution: + def minimumSubstringsInPartition(self, s: str) -> int: + @cache + def dfs(i: int) -> int: + if i >= n: + return 0 + cnt = defaultdict(int) + m = 0 + ans = n - i + for j in range(i, n): + cnt[s[j]] += 1 + m = max(m, cnt[s[j]]) + if j - i + 1 == m * len(cnt): + ans = min(ans, 1 + dfs(j + 1)) + return ans + + n = len(s) + ans = dfs(0) + dfs.cache_clear() + return ans diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.ts b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.ts new file mode 100644 index 000000000000..2a90143b8be7 --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution2.ts @@ -0,0 +1,25 @@ +function minimumSubstringsInPartition(s: string): number { + const n = s.length; + const f: number[] = Array(n).fill(-1); + const dfs = (i: number): number => { + if (i >= n) { + return 0; + } + if (f[i] !== -1) { + return f[i]; + } + const cnt: number[] = Array(26).fill(0); + f[i] = n - i; + let [k, m] = [0, 0]; + for (let j = i; j < n; ++j) { + const x = s.charCodeAt(j) - 97; + k += ++cnt[x] === 1 ? 1 : 0; + m = Math.max(m, cnt[x]); + if (j - i + 1 === k * m) { + f[i] = Math.min(f[i], 1 + dfs(j + 1)); + } + } + return f[i]; + }; + return dfs(0); +} diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.cpp b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.cpp new file mode 100644 index 000000000000..0d50a52227fa --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + int minimumSubstringsInPartition(string s) { + int n = s.size(); + vector f(n + 1, n); + f[0] = 0; + for (int i = 0; i < n; ++i) { + int cnt[26]{}; + int k = 0, m = 0; + for (int j = i; ~j; --j) { + k += ++cnt[s[j] - 'a'] == 1; + m = max(m, cnt[s[j] - 'a']); + if (i - j + 1 == k * m) { + f[i + 1] = min(f[i + 1], f[j] + 1); + } + } + } + return f[n]; + } +}; diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.go b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.go new file mode 100644 index 000000000000..081baa611aef --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.go @@ -0,0 +1,24 @@ +func minimumSubstringsInPartition(s string) int { + n := len(s) + f := make([]int, n+1) + for i := range f { + f[i] = n + } + f[0] = 0 + for i := 0; i < n; i++ { + cnt := [26]int{} + k, m := 0, 0 + for j := i; j >= 0; j-- { + x := int(s[j] - 'a') + cnt[x]++ + if cnt[x] == 1 { + k++ + } + m = max(m, cnt[x]) + if i-j+1 == k*m { + f[i+1] = min(f[i+1], 1+f[j]) + } + } + } + return f[n] +} diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.java b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.java new file mode 100644 index 000000000000..ba40cc56d9a8 --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.java @@ -0,0 +1,21 @@ +class Solution { + public int minimumSubstringsInPartition(String s) { + int n = s.length(); + char[] cs = s.toCharArray(); + int[] f = new int[n + 1]; + Arrays.fill(f, n); + f[0] = 0; + for (int i = 0; i < n; ++i) { + int[] cnt = new int[26]; + int k = 0, m = 0; + for (int j = i; j >= 0; --j) { + k += ++cnt[cs[j] - 'a'] == 1 ? 1 : 0; + m = Math.max(m, cnt[cs[j] - 'a']); + if (i - j + 1 == k * m) { + f[i + 1] = Math.min(f[i + 1], 1 + f[j]); + } + } + } + return f[n]; + } +} diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.py b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.py new file mode 100644 index 000000000000..75a7b31a981f --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.py @@ -0,0 +1,14 @@ +class Solution: + def minimumSubstringsInPartition(self, s: str) -> int: + n = len(s) + f = [inf] * (n + 1) + f[0] = 0 + for i in range(n): + cnt = defaultdict(int) + m = 0 + for j in range(i, -1, -1): + cnt[s[j]] += 1 + m = max(m, cnt[s[j]]) + if i - j + 1 == len(cnt) * m: + f[i + 1] = min(f[i + 1], f[j] + 1) + return f[n] diff --git a/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.ts b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.ts new file mode 100644 index 000000000000..eb40d5f552cd --- /dev/null +++ b/solution/3100-3199/3144.Minimum Substring Partition of Equal Character Frequency/Solution3.ts @@ -0,0 +1,18 @@ +function minimumSubstringsInPartition(s: string): number { + const n = s.length; + const f: number[] = Array(n + 1).fill(n); + f[0] = 0; + for (let i = 0; i < n; ++i) { + const cnt: number[] = Array(26).fill(0); + let [k, m] = [0, 0]; + for (let j = i; ~j; --j) { + const x = s.charCodeAt(j) - 97; + k += ++cnt[x] === 1 ? 1 : 0; + m = Math.max(m, cnt[x]); + if (i - j + 1 === k * m) { + f[i + 1] = Math.min(f[i + 1], 1 + f[j]); + } + } + } + return f[n]; +} diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md b/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md index e405d5ea3953..4d89e50ccc1d 100644 --- a/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md @@ -20,9 +20,46 @@ tags: -

      一个整数 x 的 强数组 指的是满足和为 x 的二的幂的最短有序数组。比方说,11 的强数组为 [1, 2, 8] 。

      +

      一个非负整数 x 的 强数组 指的是满足元素为 2 的幂且元素总和为 x 的最短有序数组。下表说明了如何确定 强数组 的示例。可以证明,x 对应的强数组是独一无二的。

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      数字二进制表示强数组
      100001[1]
      801000[8]
      1001010[2, 8]
      1301101[1, 4, 8]
      2310111[1, 2, 4, 16]
      -

      我们将每一个正整数 i (即1,2,3等等)的 强数组 连接得到数组 big_nums ,big_nums 开始部分为 [1, 2, 1, 2, 4, 1, 4, 2, 4, 1, 2, 4, 8, ...] 。

      +

       

      + +

      我们将每一个升序的正整数 i (即1,2,3等等)的 强数组 连接得到数组 big_nums ,big_nums 开始部分为 [1, 2, 1, 2, 4, 1, 4, 2, 4, 1, 2, 4, 8, ...] 。

      给你一个二维整数数组 queries ,其中 queries[i] = [fromi, toi, modi] ,你需要计算 (big_nums[fromi] * big_nums[fromi + 1] * ... * big_nums[toi]) % modi 。

      @@ -30,35 +67,31 @@ tags:

       

      -

      示例 1:

      +

      示例 1:

      -
      -

      输入:queries = [[1,3,7]]

      +

      输入:queries = [[1,3,7]]

      -

      输出:[4]

      +

      输出:[4]

      解释:

      只有一个查询。

      -

      big_nums[1..3] = [2,1,2] 。它们的乘积为 4 ,4 对 7 取余数得到 4 。

      -
      +

      big_nums[1..3] = [2,1,2] 。它们的乘积为 4。结果为 4 % 7 = 4

      -

      示例 2:

      +

      示例 2:

      -
      -

      输入:queries = [[2,5,3],[7,7,4]]

      +

      输入:queries = [[2,5,3],[7,7,4]]

      -

      输出:[2,2]

      +

      输出:[2,2]

      解释:

      有两个查询。

      -

      第一个查询:big_nums[2..5] = [1,2,4,1] 。它们的乘积为 8 ,8 对 3 取余数得到 2 。

      +

      第一个查询:big_nums[2..5] = [1,2,4,1] 。它们的乘积为 8 。结果为  8 % 3 = 2

      -

      第二个查询:big_nums[7] = 2 ,2 对 4 取余数得到 2 。

      -
      +

      第二个查询:big_nums[7] = 2 。结果为 2 % 4 = 2

       

      @@ -71,6 +104,8 @@ tags:
    • 1 <= queries[i][2] <= 105
    +

     

    + ## 解法 diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md b/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md index 381c10968c8a..381aec84bfd4 100644 --- a/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md @@ -20,9 +20,44 @@ tags: -

    A powerful array for an integer x is the shortest sorted array of powers of two that sum up to x. For example, the powerful array for 11 is [1, 2, 8].

    - -

    The array big_nums is created by concatenating the powerful arrays for every positive integer i in ascending order: 1, 2, 3, and so forth. Thus, big_nums starts as [1, 2, 1, 2, 4, 1, 4, 2, 4, 1, 2, 4, 8, ...].

    +

    The powerful array of a non-negative integer x is defined as the shortest sorted array of powers of two that sum up to x. The table below illustrates examples of how the powerful array is determined. It can be proven that the powerful array of x is unique.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    numBinary Representationpowerful array
    100001[1]
    801000[8]
    1001010[2, 8]
    1301101[1, 4, 8]
    2310111[1, 2, 4, 16]
    + +

    The array big_nums is created by concatenating the powerful arrays for every positive integer i in ascending order: 1, 2, 3, and so on. Thus, big_nums begins as [1, 2, 1, 2, 4, 1, 4, 2, 4, 1, 2, 4, 8, ...].

    You are given a 2D integer matrix queries, where for queries[i] = [fromi, toi, modi] you should calculate (big_nums[fromi] * big_nums[fromi + 1] * ... * big_nums[toi]) % modi.

    @@ -40,7 +75,7 @@ tags:

    There is one query.

    -

    big_nums[1..3] = [2,1,2]. The product of them is 4. The remainder of 4 under 7 is 4.

    +

    big_nums[1..3] = [2,1,2]. The product of them is 4. The result is 4 % 7 = 4.

    Example 2:

    @@ -54,9 +89,9 @@ tags:

    There are two queries.

    -

    First query: big_nums[2..5] = [1,2,4,1]. The product of them is 8. The remainder of 8 under 3 is 2.

    +

    First query: big_nums[2..5] = [1,2,4,1]. The product of them is 8. The result is 8 % 3 = 2.

    -

    Second query: big_nums[7] = 2. The remainder of 2 under 4 is 2.

    +

    Second query: big_nums[7] = 2. The result is 2 % 4 = 2.

     

    diff --git a/solution/3100-3199/3148.Maximum Difference Score in a Grid/README.md b/solution/3100-3199/3148.Maximum Difference Score in a Grid/README.md index a449b6239b2b..fbc6dd3be277 100644 --- a/solution/3100-3199/3148.Maximum Difference Score in a Grid/README.md +++ b/solution/3100-3199/3148.Maximum Difference Score in a Grid/README.md @@ -81,7 +81,7 @@ $$ f[i][j] = \min(f[i-1][j], f[i][j-1], grid[i][j]) $$ -那么答案为 $\text{grid}[i][j] - \min(f[i-1][j], f[i][j-1])$ 的最大值。 +那么答案为 $\textit{grid}[i][j] - \min(f[i-1][j], f[i][j-1])$ 的最大值。 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩阵的行数和列数。 diff --git a/solution/3100-3199/3148.Maximum Difference Score in a Grid/README_EN.md b/solution/3100-3199/3148.Maximum Difference Score in a Grid/README_EN.md index 8c361aec099e..59cc08214a3e 100644 --- a/solution/3100-3199/3148.Maximum Difference Score in a Grid/README_EN.md +++ b/solution/3100-3199/3148.Maximum Difference Score in a Grid/README_EN.md @@ -79,7 +79,7 @@ $$ f[i][j] = \min(f[i-1][j], f[i][j-1], grid[i][j]) $$ -So the answer is the maximum value of $\text{grid}[i][j] - \min(f[i-1][j], f[i][j-1])$. +So the answer is the maximum value of $\textit{grid}[i][j] - \min(f[i-1][j], f[i][j-1])$. The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows and columns of the matrix, respectively. diff --git a/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README.md b/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README.md index 3a807344e82b..11890636496d 100644 --- a/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README.md +++ b/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README.md @@ -74,20 +74,20 @@ tags: ### 方法一:记忆化搜索 -我们注意到,对于任意一个排列 $\text{perm}$,把它循环向左移动任意次,得到的排列分数依然是相同的。由于题目要求返回字典序最小的排列,因此我们可以确定排列的第一个元素一定是 $0$。 +我们注意到,对于任意一个排列 $\textit{perm}$,把它循环向左移动任意次,得到的排列分数依然是相同的。由于题目要求返回字典序最小的排列,因此我们可以确定排列的第一个元素一定是 $0$。 -另外,由于题目的数据范围不超过 $14$,我们可以考虑使用状态压缩的方法,来表示当前排列选取的数字集合。我们用一个长度为 $n$ 的二进制数 $\text{mask}$ 来表示当前排列选取的数字集合,其中 $\text{mask}$ 的第 $i$ 位为 $1$ 表示数字 $i$ 已经被选取,为 $0$ 表示数字 $i$ 还未被选取。 +另外,由于题目的数据范围不超过 $14$,我们可以考虑使用状态压缩的方法,来表示当前排列选取的数字集合。我们用一个长度为 $n$ 的二进制数 $\textit{mask}$ 来表示当前排列选取的数字集合,其中 $\textit{mask}$ 的第 $i$ 位为 $1$ 表示数字 $i$ 已经被选取,为 $0$ 表示数字 $i$ 还未被选取。 -我们设计一个函数 $\text{dfs}(\text{mask}, \text{pre})$,表示当前排列选取的数字集合为 $\text{mask}$,且最后一个选取的数字为 $\text{pre}$ 时,得到的排列的最小分数。初始时我们将数字 $0$ 加入到排列中。 +我们设计一个函数 $\textit{dfs}(\textit{mask}, \textit{pre})$,表示当前排列选取的数字集合为 $\textit{mask}$,且最后一个选取的数字为 $\textit{pre}$ 时,得到的排列的最小分数。初始时我们将数字 $0$ 加入到排列中。 -函数 $\text{dfs}(\text{mask}, \text{pre})$ 的计算过程如下: +函数 $\textit{dfs}(\textit{mask}, \textit{pre})$ 的计算过程如下: -- 如果 $\text{mask}$ 的二进制表示中 $1$ 的个数为 $n$,即 $\text{mask} = 2^n - 1$,表示所有数字都已经被选取,此时返回 $|\text{pre} - \text{nums}[0]|$; -- 否则,我们枚举下一个选取的数字 $\text{cur}$,如果数字 $\text{cur}$ 还未被选取,那么我们可以将数字 $\text{cur}$ 加入到排列中,此时排列的分数为 $|\text{pre} - \text{nums}[\text{cur}]| + \text{dfs}(\text{mask} \, | \, 1 << \text{cur}, \text{cur})$,我们需要取所有 $\text{cur}$ 中分数的最小值。 +- 如果 $\textit{mask}$ 的二进制表示中 $1$ 的个数为 $n$,即 $\textit{mask} = 2^n - 1$,表示所有数字都已经被选取,此时返回 $|\textit{pre} - \textit{nums}[0]|$; +- 否则,我们枚举下一个选取的数字 $\textit{cur}$,如果数字 $\textit{cur}$ 还未被选取,那么我们可以将数字 $\textit{cur}$ 加入到排列中,此时排列的分数为 $|\textit{pre} - \textit{nums}[\textit{cur}]| + \textit{dfs}(\textit{mask} \, | \, 1 << \textit{cur}, \textit{cur})$,我们需要取所有 $\textit{cur}$ 中分数的最小值。 -最后,我们利用一个函数 $\text{g}(\text{mask}, \text{pre})$ 来构造得到最小分数的排列。我们首先将数字 $\text{pre}$ 加入到排列中,然后枚举下一个选取的数字 $\text{cur}$,如果数字 $\text{cur}$ 还未被选取,且满足 $|\text{pre} - \text{nums}[\text{cur}]| + \text{dfs}(\text{mask} \, | \, 1 << \text{cur}, \text{cur})$ 的值等于 $\text{dfs}(\text{mask}, \text{pre})$,那么我们就可以将数字 $\text{cur}$ 加入到排列中。 +最后,我们利用一个函数 $\textit{g}(\textit{mask}, \textit{pre})$ 来构造得到最小分数的排列。我们首先将数字 $\textit{pre}$ 加入到排列中,然后枚举下一个选取的数字 $\textit{cur}$,如果数字 $\textit{cur}$ 还未被选取,且满足 $|\textit{pre} - \textit{nums}[\textit{cur}]| + \textit{dfs}(\textit{mask} \, | \, 1 << \textit{cur}, \textit{cur})$ 的值等于 $\textit{dfs}(\textit{mask}, \textit{pre})$,那么我们就可以将数字 $\textit{cur}$ 加入到排列中。 -时间复杂度 $(n^2 \times 2^n)$,空间复杂度 $O(n \times 2^n)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $(n^2 \times 2^n)$,空间复杂度 $O(n \times 2^n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 diff --git a/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README_EN.md b/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README_EN.md index 9c085d7a0667..b4c14ba1551a 100644 --- a/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README_EN.md +++ b/solution/3100-3199/3149.Find the Minimum Cost Array Permutation/README_EN.md @@ -72,20 +72,20 @@ tags: ### Solution 1: Memoization Search -We notice that for any permutation $\text{perm}$, if we cyclically shift it to the left any number of times, the score of the permutation remains the same. Since the problem requires returning the lexicographically smallest permutation, we can determine that the first element of the permutation must be $0$. +We notice that for any permutation $\textit{perm}$, if we cyclically shift it to the left any number of times, the score of the permutation remains the same. Since the problem requires returning the lexicographically smallest permutation, we can determine that the first element of the permutation must be $0$. -Also, since the data range of the problem does not exceed $14$, we can consider using the method of state compression to represent the set of numbers selected in the current permutation. We use a binary number $\text{mask}$ of length $n$ to represent the set of numbers selected in the current permutation, where the $i$-th bit of $\text{mask}$ is $1$ indicates that the number $i$ has been selected, and $0$ indicates that the number $i$ has not been selected yet. +Also, since the data range of the problem does not exceed $14$, we can consider using the method of state compression to represent the set of numbers selected in the current permutation. We use a binary number $\textit{mask}$ of length $n$ to represent the set of numbers selected in the current permutation, where the $i$-th bit of $\textit{mask}$ is $1$ indicates that the number $i$ has been selected, and $0$ indicates that the number $i$ has not been selected yet. -We design a function $\text{dfs}(\text{mask}, \text{pre})$, which represents the minimum score of the permutation obtained when the set of numbers selected in the current permutation is $\text{mask}$ and the last selected number is $\text{pre}$. Initially, we add the number $0$ to the permutation. +We design a function $\textit{dfs}(\textit{mask}, \textit{pre})$, which represents the minimum score of the permutation obtained when the set of numbers selected in the current permutation is $\textit{mask}$ and the last selected number is $\textit{pre}$. Initially, we add the number $0$ to the permutation. -The calculation process of the function $\text{dfs}(\text{mask}, \text{pre})$ is as follows: +The calculation process of the function $\textit{dfs}(\textit{mask}, \textit{pre})$ is as follows: -- If the number of $1$s in the binary representation of $\text{mask}$ is $n$, that is, $\text{mask} = 2^n - 1$, it means that all numbers have been selected, then return $|\text{pre} - \text{nums}[0]|$; -- Otherwise, we enumerate the next selected number $\text{cur}$. If the number $\text{cur}$ has not been selected yet, then we can add the number $\text{cur}$ to the permutation. At this time, the score of the permutation is $|\text{pre} - \text{nums}[\text{cur}]| + \text{dfs}(\text{mask} \, | \, 1 << \text{cur}, \text{cur})$. We need to take the minimum score among all $\text{cur}$. +- If the number of $1$s in the binary representation of $\textit{mask}$ is $n$, that is, $\textit{mask} = 2^n - 1$, it means that all numbers have been selected, then return $|\textit{pre} - \textit{nums}[0]|$; +- Otherwise, we enumerate the next selected number $\textit{cur}$. If the number $\textit{cur}$ has not been selected yet, then we can add the number $\textit{cur}$ to the permutation. At this time, the score of the permutation is $|\textit{pre} - \textit{nums}[\textit{cur}]| + \textit{dfs}(\textit{mask} \, | \, 1 << \textit{cur}, \textit{cur})$. We need to take the minimum score among all $\textit{cur}$. -Finally, we use a function $\text{g}(\text{mask}, \text{pre})$ to construct the permutation that gets the minimum score. We first add the number $\text{pre}$ to the permutation, and then enumerate the next selected number $\text{cur}$. If the number $\text{cur}$ has not been selected yet, and it satisfies that the value of $|\text{pre} - \text{nums}[\text{cur}]| + \text{dfs}(\text{mask} \, | \, 1 << \text{cur}, \text{cur})$ is equal to $\text{dfs}(\text{mask}, \text{pre})$, then we can add the number $\text{cur}$ to the permutation. +Finally, we use a function $\textit{g}(\textit{mask}, \textit{pre})$ to construct the permutation that gets the minimum score. We first add the number $\textit{pre}$ to the permutation, and then enumerate the next selected number $\textit{cur}$. If the number $\textit{cur}$ has not been selected yet, and it satisfies that the value of $|\textit{pre} - \textit{nums}[\textit{cur}]| + \textit{dfs}(\textit{mask} \, | \, 1 << \textit{cur}, \textit{cur})$ is equal to $\textit{dfs}(\textit{mask}, \textit{pre})$, then we can add the number $\textit{cur}$ to the permutation. -The time complexity is $(n^2 \times 2^n)$, and the space complexity is $O(n \times 2^n)$. Where $n$ is the length of the array $\text{nums}$. +The time complexity is $(n^2 \times 2^n)$, and the space complexity is $O(n \times 2^n)$. Where $n$ is the length of the array $\textit{nums}$. diff --git a/solution/3100-3199/3151.Special Array I/README.md b/solution/3100-3199/3151.Special Array I/README.md index dfcb793d3cbb..d6264ba41dd3 100644 --- a/solution/3100-3199/3151.Special Array I/README.md +++ b/solution/3100-3199/3151.Special Array I/README.md @@ -20,7 +20,7 @@ tags:

    如果数组的每一对相邻元素都是两个奇偶性不同的数字,则该数组被认为是一个 特殊数组

    -

    Aging 有一个整数数组 nums。如果 nums 是一个 特殊数组 ,返回 true,否则返回 false

    +

    你有一个整数数组 nums。如果 nums 是一个 特殊数组 ,返回 true,否则返回 false

     

    diff --git a/solution/3100-3199/3152.Special Array II/README.md b/solution/3100-3199/3152.Special Array II/README.md index 7c4f7a32ca35..526fd8c912d5 100644 --- a/solution/3100-3199/3152.Special Array II/README.md +++ b/solution/3100-3199/3152.Special Array II/README.md @@ -22,7 +22,7 @@ tags:

    如果数组的每一对相邻元素都是两个奇偶性不同的数字,则该数组被认为是一个 特殊数组

    -

    周洋哥有一个整数数组 nums 和一个二维整数矩阵 queries,对于 queries[i] = [fromi, toi],请你帮助周洋哥检查子数组 nums[fromi..toi] 是不是一个 特殊数组

    +

    你有一个整数数组 nums 和一个二维整数矩阵 queries,对于 queries[i] = [fromi, toi],请你帮助你检查 子数组 nums[fromi..toi] 是不是一个 特殊数组

    返回布尔数组 answer,如果 nums[fromi..toi] 是特殊数组,则 answer[i]true ,否则,answer[i]false

    diff --git a/solution/3100-3199/3153.Sum of Digit Differences of All Pairs/README.md b/solution/3100-3199/3153.Sum of Digit Differences of All Pairs/README.md index ec1940c577ad..eb8b072ee284 100644 --- a/solution/3100-3199/3153.Sum of Digit Differences of All Pairs/README.md +++ b/solution/3100-3199/3153.Sum of Digit Differences of All Pairs/README.md @@ -21,11 +21,11 @@ tags: -

    车尔尼有一个数组 nums ,它只包含  整数,所有正整数的数位长度都 相同 。

    +

    你有一个数组 nums ,它只包含  整数,所有正整数的数位长度都 相同 。

    两个整数的 数位不同 指的是两个整数 相同 位置上不同数字的数目。

    -

    请车尔尼返回 nums 中 所有 整数对里,数位不同之和。

    +

    请你返回 nums 中 所有 整数对里,数位不同之和。

     

    diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md index 857b6a73d2c6..702b20e09c08 100644 --- a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md @@ -24,16 +24,16 @@ tags:

    给你有一个 非负 整数 k 。有一个无限长度的台阶,最低 一层编号为 0 。

    -

    虎老师有一个整数 jump ,一开始值为 0 。虎老师从台阶 1 开始,虎老师可以使用 任意 次操作,目标是到达第 k 级台阶。假设虎老师位于台阶 i ,一次 操作 中,虎老师可以:

    +

    Alice 有一个整数 jump ,一开始值为 0 。Alice 从台阶 1 开始,可以使用 任意 次操作,目标是到达第 k 级台阶。假设 Alice 位于台阶 i ,一次 操作 中,Alice 可以:

    • 向下走一级到 i - 1 ,但该操作 不能 连续使用,如果在台阶第 0 级也不能使用。
    • 向上走到台阶 i + 2jump 处,然后 jump 变为 jump + 1 。
    -

    请你返回虎老师到达台阶 k 处的总方案数。

    +

    请你返回 Alice 到达台阶 k 处的总方案数。

    -

    注意 ,虎老师可能到达台阶 k 处后,通过一些操作重新回到台阶 k 处,这视为不同的方案。

    +

    注意,Alice 可能到达台阶 k 处后,通过一些操作重新回到台阶 k 处,这视为不同的方案。

     

    @@ -49,12 +49,12 @@ tags:

    2 种到达台阶 0 的方案为:

      -
    • 虎老师从台阶 1 开始。 +
    • Alice 从台阶 1 开始。
      • 执行第一种操作,从台阶 1 向下走到台阶 0 。
    • -
    • 虎老师从台阶 1 开始。 +
    • Alice 从台阶 1 开始。
      • 执行第一种操作,从台阶 1 向下走到台阶 0 。
      • 执行第二种操作,向上走 20 级台阶到台阶 1 。
      • @@ -76,20 +76,20 @@ tags:

        4 种到达台阶 1 的方案为:

          -
        • 虎老师从台阶 1 开始,已经到达台阶 1 。
        • -
        • 虎老师从台阶 1 开始。 +
        • Alice 从台阶 1 开始,已经到达台阶 1 。
        • +
        • Alice 从台阶 1 开始。
          • 执行第一种操作,从台阶 1 向下走到台阶 0 。
          • 执行第二种操作,向上走 20 级台阶到台阶 1 。
        • -
        • 虎老师从台阶 1 开始。 +
        • Alice 从台阶 1 开始。
          • 执行第二种操作,向上走 20 级台阶到台阶 2 。
          • 执行第一种操作,向下走 1 级台阶到台阶 1 。
        • -
        • 虎老师从台阶 1 开始。 +
        • Alice 从台阶 1 开始。
          • 执行第一种操作,从台阶 1 向下走到台阶 0 。
          • 执行第二种操作,向上走 20 级台阶到台阶 1 。
          • @@ -117,14 +117,14 @@ tags: ### 方法一:记忆化搜索 -我们设计一个函数 $\text{dfs}(i, j, \text{jump})$,表示当前位于第 $i$ 级台阶,且进行了 $j$ 次操作 $1$ 和 $\text{jump}$ 次操作 $2$,到达第 $k$ 级台阶的方案数。那么答案就是 $\text{dfs}(1, 0, 0)$。 +我们设计一个函数 $\textit{dfs}(i, j, \textit{jump})$,表示当前位于第 $i$ 级台阶,且进行了 $j$ 次操作 $1$ 和 $\textit{jump}$ 次操作 $2$,到达第 $k$ 级台阶的方案数。那么答案就是 $\textit{dfs}(1, 0, 0)$。 -函数 $\text{dfs}(i, j, \text{jump})$ 的计算过程如下: +函数 $\textit{dfs}(i, j, \textit{jump})$ 的计算过程如下: - 如果 $i > k + 1$,由于无法连续两次向下走,所以无法再到达第 $k$ 级台阶,返回 $0$; - 如果 $i = k$,表示已经到达第 $k$ 级台阶,答案初始化为 $1$,然后继续计算; -- 如果 $i > 0$ 且 $j = 0$,表示可以向下走,递归计算 $\text{dfs}(i - 1, 1, \text{jump})$; -- 递归计算 $\text{dfs}(i + 2^{\text{jump}}, 0, \text{jump} + 1)$,累加到答案中。 +- 如果 $i > 0$ 且 $j = 0$,表示可以向下走,递归计算 $\textit{dfs}(i - 1, 1, \textit{jump})$; +- 递归计算 $\textit{dfs}(i + 2^{\textit{jump}}, 0, \textit{jump} + 1)$,累加到答案中。 为了避免重复计算,我们使用记忆化搜索,将已经计算过的状态保存起来。 @@ -187,29 +187,24 @@ class Solution { class Solution { public: int waysToReachStair(int k) { - this->k = k; - return dfs(1, 0, 0); - } - -private: - unordered_map f; - int k; - - int dfs(int i, int j, int jump) { - if (i > k + 1) { - return 0; - } - long long key = ((long long) i << 32) | jump << 1 | j; - if (f.contains(key)) { - return f[key]; - } - int ans = i == k ? 1 : 0; - if (i > 0 && j == 0) { - ans += dfs(i - 1, 1, jump); - } - ans += dfs(i + (1 << jump), 0, jump + 1); - f[key] = ans; - return ans; + unordered_map f; + auto dfs = [&](auto&& dfs, int i, int j, int jump) -> int { + if (i > k + 1) { + return 0; + } + long long key = ((long long) i << 32) | jump << 1 | j; + if (f.contains(key)) { + return f[key]; + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(dfs, i - 1, 1, jump); + } + ans += dfs(dfs, i + (1 << jump), 0, jump + 1); + f[key] = ans; + return ans; + }; + return dfs(dfs, 1, 0, 0); } }; ``` diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md index a63401fef683..2f1f308b8184 100644 --- a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md @@ -185,29 +185,24 @@ class Solution { class Solution { public: int waysToReachStair(int k) { - this->k = k; - return dfs(1, 0, 0); - } - -private: - unordered_map f; - int k; - - int dfs(int i, int j, int jump) { - if (i > k + 1) { - return 0; - } - long long key = ((long long) i << 32) | jump << 1 | j; - if (f.contains(key)) { - return f[key]; - } - int ans = i == k ? 1 : 0; - if (i > 0 && j == 0) { - ans += dfs(i - 1, 1, jump); - } - ans += dfs(i + (1 << jump), 0, jump + 1); - f[key] = ans; - return ans; + unordered_map f; + auto dfs = [&](auto&& dfs, int i, int j, int jump) -> int { + if (i > k + 1) { + return 0; + } + long long key = ((long long) i << 32) | jump << 1 | j; + if (f.contains(key)) { + return f[key]; + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(dfs, i - 1, 1, jump); + } + ans += dfs(dfs, i + (1 << jump), 0, jump + 1); + f[key] = ans; + return ans; + }; + return dfs(dfs, 1, 0, 0); } }; ``` diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.cpp b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.cpp index bac94a2f6d75..484ee9cb8677 100644 --- a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.cpp +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.cpp @@ -1,28 +1,23 @@ class Solution { public: int waysToReachStair(int k) { - this->k = k; - return dfs(1, 0, 0); + unordered_map f; + auto dfs = [&](auto&& dfs, int i, int j, int jump) -> int { + if (i > k + 1) { + return 0; + } + long long key = ((long long) i << 32) | jump << 1 | j; + if (f.contains(key)) { + return f[key]; + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(dfs, i - 1, 1, jump); + } + ans += dfs(dfs, i + (1 << jump), 0, jump + 1); + f[key] = ans; + return ans; + }; + return dfs(dfs, 1, 0, 0); } - -private: - unordered_map f; - int k; - - int dfs(int i, int j, int jump) { - if (i > k + 1) { - return 0; - } - long long key = ((long long) i << 32) | jump << 1 | j; - if (f.contains(key)) { - return f[key]; - } - int ans = i == k ? 1 : 0; - if (i > 0 && j == 0) { - ans += dfs(i - 1, 1, jump); - } - ans += dfs(i + (1 << jump), 0, jump + 1); - f[key] = ans; - return ans; - } -}; \ No newline at end of file +}; diff --git a/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README.md b/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README.md index 6a59554da214..72e0934490fc 100644 --- a/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README.md +++ b/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README.md @@ -74,7 +74,7 @@ tags: ### 方法一:数学 -对于每个数据中心,我们假设可以升级 $\text{x}$ 台服务器,那么 $\text{x} \times \text{upgrade[i]} \leq \text{count[i]} \times \text{sell[i]} + \text{money[i]}$。即 $\text{x} \leq \frac{\text{count[i]} \times \text{sell[i]} + \text{money[i]}}{\text{upgrade[i]} + \text{sell[i]}}$。又因为 $\text{x} \leq \text{count[i]}$,所以我们取两者的最小值即可。 +对于每个数据中心,我们假设可以升级 $\textit{x}$ 台服务器,那么 $\textit{x} \times \textit{upgrade[i]} \leq \textit{count[i]} \times \textit{sell[i]} + \textit{money[i]}$。即 $\textit{x} \leq \frac{\textit{count[i]} \times \textit{sell[i]} + \textit{money[i]}}{\textit{upgrade[i]} + \textit{sell[i]}}$。又因为 $\textit{x} \leq \textit{count[i]}$,所以我们取两者的最小值即可。 时间复杂度 $O(n)$,其中 $n$ 为数组的长度。忽略答案数组的空间消耗,空间复杂度 $O(1)$。 diff --git a/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README_EN.md b/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README_EN.md index 7272531b497c..8fa54e1696ac 100644 --- a/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README_EN.md +++ b/solution/3100-3199/3155.Maximum Number of Upgradable Servers/README_EN.md @@ -74,7 +74,7 @@ tags: ### Solution 1: Mathematics -For each data center, we assume that we can upgrade $x$ servers, then $x \times \text{upgrade[i]} \leq \text{count[i]} \times \text{sell[i]} + \text{money[i]}$. That is, $x \leq \frac{\text{count[i]} \times \text{sell[i]} + \text{money[i]}}{\text{upgrade[i]} + \text{sell[i]}}$. Also, $x \leq \text{count[i]}$, so we can take the minimum of the two. +For each data center, we assume that we can upgrade $x$ servers, then $x \times \textit{upgrade[i]} \leq \textit{count[i]} \times \textit{sell[i]} + \textit{money[i]}$. That is, $x \leq \frac{\textit{count[i]} \times \textit{sell[i]} + \textit{money[i]}}{\textit{upgrade[i]} + \textit{sell[i]}}$. Also, $x \leq \textit{count[i]}$, so we can take the minimum of the two. The time complexity is $O(n)$, where $n$ is the length of the array. Ignoring the space consumption of the answer array, the space complexity is $O(1)$. diff --git a/solution/3100-3199/3158.Find the XOR of Numbers Which Appear Twice/README.md b/solution/3100-3199/3158.Find the XOR of Numbers Which Appear Twice/README.md index 54e3498390cf..ee517afe32fe 100644 --- a/solution/3100-3199/3158.Find the XOR of Numbers Which Appear Twice/README.md +++ b/solution/3100-3199/3158.Find the XOR of Numbers Which Appear Twice/README.md @@ -80,13 +80,13 @@ tags: ### 方法一:计数 -我们定义一个数组或哈希表 $\text{cnt}$ 记录每个数字出现的次数。 +我们定义一个数组或哈希表 $\textit{cnt}$ 记录每个数字出现的次数。 -接下来,遍历数组 $\text{nums}$,当某个数字出现两次时,我们将其与答案进行异或运算。 +接下来,遍历数组 $\textit{nums}$,当某个数字出现两次时,我们将其与答案进行异或运算。 最后返回答案即可。 -时间复杂度 $O(n)$,空间复杂度 $O(M)$。其中 $n$ 是数组 $\text{nums}$ 的长度,而 $M$ 是数组 $\text{nums}$ 中的最大值或数组 $\text{nums}$ 不同数字的个数。 +时间复杂度 $O(n)$,空间复杂度 $O(M)$。其中 $n$ 是数组 $\textit{nums}$ 的长度,而 $M$ 是数组 $\textit{nums}$ 中的最大值或数组 $\textit{nums}$ 不同数字的个数。 diff --git a/solution/3100-3199/3159.Find Occurrences of an Element in an Array/README.md b/solution/3100-3199/3159.Find Occurrences of an Element in an Array/README.md index e40f0c105fb2..8c0901f51d4e 100644 --- a/solution/3100-3199/3159.Find Occurrences of an Element in an Array/README.md +++ b/solution/3100-3199/3159.Find Occurrences of an Element in an Array/README.md @@ -76,11 +76,11 @@ tags: ### 方法一:模拟 -根据题目描述,我们可以先遍历一遍数组 $\text{nums}$,找出所有值为 $x$ 的元素的下标,记录在数组 $\text{ids}$ 中。 +根据题目描述,我们可以先遍历一遍数组 $\textit{nums}$,找出所有值为 $x$ 的元素的下标,记录在数组 $\textit{ids}$ 中。 -接着遍历数组 $\text{queries}$,对于每个查询 $i$,如果 $i - 1$ 小于 $\text{ids}$ 的长度,那么答案就是 $\text{ids}[i - 1]$,否则答案就是 $-1$。 +接着遍历数组 $\textit{queries}$,对于每个查询 $i$,如果 $i - 1$ 小于 $\textit{ids}$ 的长度,那么答案就是 $\textit{ids}[i - 1]$,否则答案就是 $-1$。 -时间复杂度 $O(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是数组 $\text{nums}$ 和数组 $\text{queries}$ 的长度。 +时间复杂度 $O(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是数组 $\textit{nums}$ 和数组 $\textit{queries}$ 的长度。 diff --git a/solution/3100-3199/3160.Find the Number of Distinct Colors Among the Balls/README.md b/solution/3100-3199/3160.Find the Number of Distinct Colors Among the Balls/README.md index f67d5d4a3f5c..7c2a9221b261 100644 --- a/solution/3100-3199/3160.Find the Number of Distinct Colors Among the Balls/README.md +++ b/solution/3100-3199/3160.Find the Number of Distinct Colors Among the Balls/README.md @@ -89,13 +89,13 @@ tags: ### 方法一:双哈希表 -我们使用一个哈希表 $\text{g}$ 记录每个球的颜色,使用一个哈希表 $\text{cnt}$ 记录每种颜色的球的个数。 +我们使用一个哈希表 $\textit{g}$ 记录每个球的颜色,使用一个哈希表 $\textit{cnt}$ 记录每种颜色的球的个数。 -接下来,遍历数组 $\text{queries}$,对于每个查询 $(x, y)$,我们将颜色 $y$ 的球的个数加 $1$,然后判断球 $x$ 是否已经染色,如果已经染色,我们将球 $x$ 的颜色的球的个数减 $1$,如果减到 $0$,我们将其从哈希表 $\text{cnt}$ 中移除。接下来,我们将球 $x$ 的颜色更新为 $y$,并将当前哈希表 $\text{cnt}$ 的大小加入答案数组。 +接下来,遍历数组 $\textit{queries}$,对于每个查询 $(x, y)$,我们将颜色 $y$ 的球的个数加 $1$,然后判断球 $x$ 是否已经染色,如果已经染色,我们将球 $x$ 的颜色的球的个数减 $1$,如果减到 $0$,我们将其从哈希表 $\textit{cnt}$ 中移除。接下来,我们将球 $x$ 的颜色更新为 $y$,并将当前哈希表 $\textit{cnt}$ 的大小加入答案数组。 遍历结束后,返回答案数组即可。 -时间复杂度 $O(m)$,空间复杂度 $O(m)$,其中 $m$ 为数组 $\text{queries}$ 的长度。 +时间复杂度 $O(m)$,空间复杂度 $O(m)$,其中 $m$ 为数组 $\textit{queries}$ 的长度。 diff --git a/solution/3100-3199/3162.Find the Number of Good Pairs I/README.md b/solution/3100-3199/3162.Find the Number of Good Pairs I/README.md index a99efdfd8a83..bf962a213512 100644 --- a/solution/3100-3199/3162.Find the Number of Good Pairs I/README.md +++ b/solution/3100-3199/3162.Find the Number of Good Pairs I/README.md @@ -161,11 +161,11 @@ function numberOfPairs(nums1: number[], nums2: number[], k: number): number { ### 方法二:哈希表 + 枚举倍数 -我们用一个哈希表 $\text{cnt1}$ 记录数组 $\text{nums1}$ 中每个数除以 $k$ 的商的出现次数,用一个哈希表 $\text{cnt2}$ 记录数组 $\text{nums2}$ 中每个数的出现次数。 +我们用一个哈希表 $\textit{cnt1}$ 记录数组 $\textit{nums1}$ 中每个数除以 $k$ 的商的出现次数,用一个哈希表 $\textit{cnt2}$ 记录数组 $\textit{nums2}$ 中每个数的出现次数。 -接下来,我们枚举数组 $\text{nums2}$ 中的每个数 $x$,对于每个数 $x$,我们枚举 $x$ 的倍数 $y$,其中 $y$ 的范围是 $[x, \text{mx}]$,其中 $\text{mx}$ 是 $\text{cnt1}$ 中的最大键值,然后我们统计 $\text{cnt1}[y]$ 的和,记为 $s$,最后我们将 $s \times v$ 累加到答案中,其中 $v$ 是 $\text{cnt2}[x]$。 +接下来,我们枚举数组 $\textit{nums2}$ 中的每个数 $x$,对于每个数 $x$,我们枚举 $x$ 的倍数 $y$,其中 $y$ 的范围是 $[x, \textit{mx}]$,其中 $\textit{mx}$ 是 $\textit{cnt1}$ 中的最大键值,然后我们统计 $\textit{cnt1}[y]$ 的和,记为 $s$,最后我们将 $s \times v$ 累加到答案中,其中 $v$ 是 $\textit{cnt2}[x]$。 -时间复杂度 $O(n + m + (M / k) \times \log m)$,空间复杂度 $O(n + m)$,其中 $n$ 和 $m$ 分别是数组 $\text{nums1}$ 和 $\text{nums2}$ 的长度,而 $M$ 是数组 $\text{nums1}$ 中的最大值。 +时间复杂度 $O(n + m + (M / k) \times \log m)$,空间复杂度 $O(n + m)$,其中 $n$ 和 $m$ 分别是数组 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度,而 $M$ 是数组 $\textit{nums1}$ 中的最大值。 diff --git a/solution/3100-3199/3162.Find the Number of Good Pairs I/README_EN.md b/solution/3100-3199/3162.Find the Number of Good Pairs I/README_EN.md index 194216adbaa3..c7da5c2e19a7 100644 --- a/solution/3100-3199/3162.Find the Number of Good Pairs I/README_EN.md +++ b/solution/3100-3199/3162.Find the Number of Good Pairs I/README_EN.md @@ -159,7 +159,7 @@ function numberOfPairs(nums1: number[], nums2: number[], k: number): number { We use a hash table `cnt1` to record the occurrence times of each number divided by $k$ in array `nums1`, and a hash table `cnt2` to record the occurrence times of each number in array `nums2`. -Next, we enumerate each number $x$ in array `nums2`. For each number $x$, we enumerate its multiples $y$, where the range of $y$ is $[x, \text{mx}]$, where `mx` is the maximum key value in `cnt1`. Then we count the sum of `cnt1[y]`, denoted as $s$. Finally, we add $s \times v$ to the answer, where $v$ is `cnt2[x]`. +Next, we enumerate each number $x$ in array `nums2`. For each number $x$, we enumerate its multiples $y$, where the range of $y$ is $[x, \textit{mx}]$, where `mx` is the maximum key value in `cnt1`. Then we count the sum of `cnt1[y]`, denoted as $s$. Finally, we add $s \times v$ to the answer, where $v$ is `cnt2[x]`. The time complexity is $O(n + m + (M / k) \times \log m)$, and the space complexity is $O(n + m)$. Where $n$ and $m$ are the lengths of arrays `nums1` and `nums2` respectively, and $M$ is the maximum value in array `nums1`. diff --git a/solution/3100-3199/3164.Find the Number of Good Pairs II/README.md b/solution/3100-3199/3164.Find the Number of Good Pairs II/README.md index 8fd39fac99c3..0dbd980e14d3 100644 --- a/solution/3100-3199/3164.Find the Number of Good Pairs II/README.md +++ b/solution/3100-3199/3164.Find the Number of Good Pairs II/README.md @@ -69,11 +69,11 @@ tags: ### 方法一:哈希表 + 枚举倍数 -我们用一个哈希表 $\text{cnt1}$ 记录数组 $\text{nums1}$ 中每个数除以 $k$ 的商的出现次数,用一个哈希表 $\text{cnt2}$ 记录数组 $\text{nums2}$ 中每个数的出现次数。 +我们用一个哈希表 $\textit{cnt1}$ 记录数组 $\textit{nums1}$ 中每个数除以 $k$ 的商的出现次数,用一个哈希表 $\textit{cnt2}$ 记录数组 $\textit{nums2}$ 中每个数的出现次数。 -接下来,我们枚举数组 $\text{nums2}$ 中的每个数 $x$,对于每个数 $x$,我们枚举 $x$ 的倍数 $y$,其中 $y$ 的范围是 $[x, \text{mx}]$,其中 $\text{mx}$ 是 $\text{cnt1}$ 中的最大键值,然后我们统计 $\text{cnt1}[y]$ 的和,记为 $s$,最后我们将 $s \times v$ 累加到答案中,其中 $v$ 是 $\text{cnt2}[x]$。 +接下来,我们枚举数组 $\textit{nums2}$ 中的每个数 $x$,对于每个数 $x$,我们枚举 $x$ 的倍数 $y$,其中 $y$ 的范围是 $[x, \textit{mx}]$,其中 $\textit{mx}$ 是 $\textit{cnt1}$ 中的最大键值,然后我们统计 $\textit{cnt1}[y]$ 的和,记为 $s$,最后我们将 $s \times v$ 累加到答案中,其中 $v$ 是 $\textit{cnt2}[x]$。 -时间复杂度 $O(n + m + (M / k) \times \log m)$,空间复杂度 $O(n + m)$,其中 $n$ 和 $m$ 分别是数组 $\text{nums1}$ 和 $\text{nums2}$ 的长度,而 $M$ 是数组 $\text{nums1}$ 中的最大值。 +时间复杂度 $O(n + m + (M / k) \times \log m)$,空间复杂度 $O(n + m)$,其中 $n$ 和 $m$ 分别是数组 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度,而 $M$ 是数组 $\textit{nums1}$ 中的最大值。 diff --git a/solution/3100-3199/3164.Find the Number of Good Pairs II/README_EN.md b/solution/3100-3199/3164.Find the Number of Good Pairs II/README_EN.md index b15407f7cdf8..1a798ecde7d0 100644 --- a/solution/3100-3199/3164.Find the Number of Good Pairs II/README_EN.md +++ b/solution/3100-3199/3164.Find the Number of Good Pairs II/README_EN.md @@ -67,7 +67,7 @@ The 5 good pairs are (0, 0), (1, 0), (1, 1) diff --git a/solution/3100-3199/3169.Count Days Without Meetings/README.md b/solution/3100-3199/3169.Count Days Without Meetings/README.md index bb0e8d21cc9b..62d0f4d43c51 100644 --- a/solution/3100-3199/3169.Count Days Without Meetings/README.md +++ b/solution/3100-3199/3169.Count Days Without Meetings/README.md @@ -82,11 +82,11 @@ tags: ### 方法一:排序 -我们不妨将所有会议按照开始时间排序,用一个变量 $\text{last}$ 记录此前会议的最晚结束时间。 +我们不妨将所有会议按照开始时间排序,用一个变量 $\textit{last}$ 记录此前会议的最晚结束时间。 -然后我们遍历所有会议,对于每一个会议 $(\text{st}, \text{ed})$,如果 $\text{last} < \text{st}$,说明 $\text{last}$ 到 $\text{st}$ 之间的时间段是员工可以工作且没有安排会议的时间,我们将这段时间加入答案。然后我们更新 $\text{last} = \max(\text{last}, \text{ed})$。 +然后我们遍历所有会议,对于每一个会议 $(\textit{st}, \textit{ed})$,如果 $\textit{last} < \textit{st}$,说明 $\textit{last}$ 到 $\textit{st}$ 之间的时间段是员工可以工作且没有安排会议的时间,我们将这段时间加入答案。然后我们更新 $\textit{last} = \max(\textit{last}, \textit{ed})$。 -最后,如果 $\text{last} < \text{days}$,说明最后一次会议结束后还有时间段是员工可以工作且没有安排会议的时间,我们将这段时间加入答案。 +最后,如果 $\textit{last} < \textit{days}$,说明最后一次会议结束后还有时间段是员工可以工作且没有安排会议的时间,我们将这段时间加入答案。 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为会议的数量。 diff --git a/solution/3100-3199/3174.Clear Digits/README.md b/solution/3100-3199/3174.Clear Digits/README.md index 16bbb3258f58..a39c09569d16 100644 --- a/solution/3100-3199/3174.Clear Digits/README.md +++ b/solution/3100-3199/3174.Clear Digits/README.md @@ -5,7 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3174.Cl rating: 1255 source: 第 132 场双周赛 Q1 tags: - - 哈希表 + - 栈 - 字符串 - 模拟 --- diff --git a/solution/3100-3199/3174.Clear Digits/README_EN.md b/solution/3100-3199/3174.Clear Digits/README_EN.md index 77870d76bc43..a26fe13430ef 100644 --- a/solution/3100-3199/3174.Clear Digits/README_EN.md +++ b/solution/3100-3199/3174.Clear Digits/README_EN.md @@ -5,7 +5,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3174.Cl rating: 1255 source: Biweekly Contest 132 Q1 tags: - - Hash Table + - Stack - String - Simulation --- diff --git a/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README.md b/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README.md index 40158e36eba5..ae6054d888a2 100644 --- a/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README.md +++ b/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README.md @@ -75,8 +75,8 @@ tags: $$ f[i][h]= \begin{cases} -\max(f[i][h], f[j][h] + 1), & \text{if } nums[i] = nums[j], \\ -\max(f[i][h], f[j][h - 1] + 1), & \text{if } h > 0. +\max(f[i][h], f[j][h] + 1), & \textit{if } nums[i] = nums[j], \\ +\max(f[i][h], f[j][h - 1] + 1), & \textit{if } h > 0. \end{cases} $$ diff --git a/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README_EN.md b/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README_EN.md index 3f9a6db90957..e153a19dd2df 100644 --- a/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README_EN.md +++ b/solution/3100-3199/3176.Find the Maximum Length of a Good Subsequence I/README_EN.md @@ -73,8 +73,8 @@ We consider how to calculate $f[i][h]$. We can enumerate $0 \le j < i$, if $nums $$ f[i][h]= \begin{cases} -\max(f[i][h], f[j][h] + 1), & \text{if } nums[i] = nums[j], \\ -\max(f[i][h], f[j][h - 1] + 1), & \text{if } h > 0. +\max(f[i][h], f[j][h] + 1), & \textit{if } nums[i] = nums[j], \\ +\max(f[i][h], f[j][h - 1] + 1), & \textit{if } h > 0. \end{cases} $$ diff --git a/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README.md b/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README.md index 161d08460dd5..6d4f6f32254c 100644 --- a/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README.md +++ b/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README.md @@ -75,8 +75,8 @@ tags: $$ f[i][h]= \begin{cases} -\max(f[i][h], f[j][h] + 1), & \text{if } nums[i] = nums[j], \\ -\max(f[i][h], f[j][h - 1] + 1), & \text{if } h > 0. +\max(f[i][h], f[j][h] + 1), & \textit{if } nums[i] = nums[j], \\ +\max(f[i][h], f[j][h - 1] + 1), & \textit{if } h > 0. \end{cases} $$ diff --git a/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README_EN.md b/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README_EN.md index 62f0620bbece..da52faadc556 100644 --- a/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README_EN.md +++ b/solution/3100-3199/3177.Find the Maximum Length of a Good Subsequence II/README_EN.md @@ -73,8 +73,8 @@ We consider how to calculate $f[i][h]$. We can enumerate $0 \le j < i$, if $nums $$ f[i][h]= \begin{cases} -\max(f[i][h], f[j][h] + 1), & \text{if } nums[i] = nums[j], \\ -\max(f[i][h], f[j][h - 1] + 1), & \text{if } h > 0. +\max(f[i][h], f[j][h] + 1), & \textit{if } nums[i] = nums[j], \\ +\max(f[i][h], f[j][h - 1] + 1), & \textit{if } h > 0. \end{cases} $$ diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md index 5f8735a3c308..059ddcce253d 100644 --- a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README.md @@ -75,12 +75,12 @@ tags: 我们可以对奖励值数组 `rewardValues` 进行排序,然后使用记忆化搜索的方法求解最大总奖励。 -我们定义一个函数 $\text{dfs}(x)$,表示当前总奖励为 $x$ 时,能够获得的最大总奖励。那么答案为 $\text{dfs}(0)$。 +我们定义一个函数 $\textit{dfs}(x)$,表示当前总奖励为 $x$ 时,能够获得的最大总奖励。那么答案为 $\textit{dfs}(0)$。 -函数 $\text{dfs}(x)$ 的执行过程如下: +函数 $\textit{dfs}(x)$ 的执行过程如下: 1. 二分查找数组 `rewardValues` 中第一个大于 $x$ 的元素的下标 $i$; -2. 遍历数组 `rewardValues` 中从下标 $i$ 开始的元素,对于每个元素 $v$,计算 $v + \text{dfs}(x + v)$ 的最大值。 +2. 遍历数组 `rewardValues` 中从下标 $i$ 开始的元素,对于每个元素 $v$,计算 $v + \textit{dfs}(x + v)$ 的最大值。 3. 将结果返回。 为了避免重复计算,我们使用记忆化数组 `f` 记录已经计算过的结果。 @@ -228,7 +228,7 @@ function maxTotalReward(rewardValues: number[]): number { ### 方法二:动态规划 -我们定义 $f[i][j]$ 表示用前 $i$ 个奖励值,能否得到总奖励 $j$。初始时 $f[0][0] = \text{True}$,其余值均为 $\text{False}$。 +我们定义 $f[i][j]$ 表示用前 $i$ 个奖励值,能否得到总奖励 $j$。初始时 $f[0][0] = \textit{True}$,其余值均为 $\textit{False}$。 我们考虑第 $i$ 个奖励值 $v$,如果我们不选择它,那么 $f[i][j] = f[i - 1][j]$;如果我们选择它,那么 $f[i][j] = f[i - 1][j - v]$,其中 $0 \leq j - v \lt v$。即状态转移方程为: @@ -236,7 +236,7 @@ $$ f[i][j] = f[i - 1][j] \vee f[i - 1][j - v] $$ -最终答案为 $\max\{j \mid f[n][j] = \text{True}\}$。 +最终答案为 $\max\{j \mid f[n][j] = \textit{True}\}$。 由于 $f[i][j]$ 只与 $f[i - 1][j]$ 和 $f[i - 1][j - v]$ 有关,我们可以优化掉第一维,只使用一个一维数组进行状态转移。 diff --git a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md index 10cd748978f9..8a39b4d1a95b 100644 --- a/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md +++ b/solution/3100-3199/3180.Maximum Total Reward Using Operations I/README_EN.md @@ -73,12 +73,12 @@ tags: We can sort the `rewardValues` array and then use memoization to solve for the maximum total reward. -We define a function $\text{dfs}(x)$, representing the maximum total reward that can be obtained when the current total reward is $x$. Thus, the answer is $\text{dfs}(0)$. +We define a function $\textit{dfs}(x)$, representing the maximum total reward that can be obtained when the current total reward is $x$. Thus, the answer is $\textit{dfs}(0)$. -The execution process of the function $\text{dfs}(x)$ is as follows: +The execution process of the function $\textit{dfs}(x)$ is as follows: 1. Perform a binary search in the `rewardValues` array for the index $i$ of the first element greater than $x$; -2. Iterate over the elements in the `rewardValues` array starting from index $i$, and for each element $v$, calculate the maximum value of $v + \text{dfs}(x + v)$. +2. Iterate over the elements in the `rewardValues` array starting from index $i$, and for each element $v$, calculate the maximum value of $v + \textit{dfs}(x + v)$. 3. Return the result. To avoid repeated calculations, we use a memoization array `f` to record the results that have already been computed. @@ -226,7 +226,7 @@ function maxTotalReward(rewardValues: number[]): number { ### Solution 2: Dynamic Programming -We define $f[i][j]$ as whether it is possible to obtain a total reward of $j$ using the first $i$ reward values. Initially, $f[0][0] = \text{True}$, and all other values are $\text{False}$. +We define $f[i][j]$ as whether it is possible to obtain a total reward of $j$ using the first $i$ reward values. Initially, $f[0][0] = \textit{True}$, and all other values are $\textit{False}$. We consider the $i$-th reward value $v$. If we do not choose it, then $f[i][j] = f[i - 1][j]$. If we choose it, then $f[i][j] = f[i - 1][j - v]$, where $0 \leq j - v < v$. Thus, the state transition equation is: @@ -234,7 +234,7 @@ $$ f[i][j] = f[i - 1][j] \vee f[i - 1][j - v] $$ -The final answer is $\max\{j \mid f[n][j] = \text{True}\}$. +The final answer is $\max\{j \mid f[n][j] = \textit{True}\}$. Since $f[i][j]$ only depends on $f[i - 1][j]$ and $f[i - 1][j - v]$, we can optimize away the first dimension and use only a one-dimensional array for state transitions. diff --git a/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README.md b/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README.md index be8aeacc8e60..94676efc4b91 100644 --- a/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README.md +++ b/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README.md @@ -74,7 +74,7 @@ tags: ### 方法一:动态规划 + 位运算 -我们定义 $f[i][j]$ 表示用前 $i$ 个奖励值,能否得到总奖励 $j$。初始时 $f[0][0] = \text{True}$,其余值均为 $\text{False}$。 +我们定义 $f[i][j]$ 表示用前 $i$ 个奖励值,能否得到总奖励 $j$。初始时 $f[0][0] = \textit{True}$,其余值均为 $\textit{False}$。 我们考虑第 $i$ 个奖励值 $v$,如果我们不选择它,那么 $f[i][j] = f[i - 1][j]$;如果我们选择它,那么 $f[i][j] = f[i - 1][j - v]$,其中 $0 \leq j - v \lt v$。即状态转移方程为: @@ -82,7 +82,7 @@ $$ f[i][j] = f[i - 1][j] \vee f[i - 1][j - v] $$ -最终答案为 $\max\{j \mid f[n][j] = \text{True}\}$。 +最终答案为 $\max\{j \mid f[n][j] = \textit{True}\}$。 由于 $f[i][j]$ 只与 $f[i - 1][j]$ 和 $f[i - 1][j - v]$ 有关,我们可以优化掉第一维,只使用一个一维数组进行状态转移。另外,由于本题数据范围较大,我们需要使用位运算来优化状态转移的效率。 diff --git a/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README_EN.md b/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README_EN.md index f745d0c947de..358708a1eff5 100644 --- a/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README_EN.md +++ b/solution/3100-3199/3181.Maximum Total Reward Using Operations II/README_EN.md @@ -72,7 +72,7 @@ tags: ### Solution 1: Dynamic Programming + Bit Manipulation -We define $f[i][j]$ as whether it is possible to obtain a total reward of $j$ using the first $i$ reward values. Initially, $f[0][0] = \text{True}$, and all other values are $\text{False}$. +We define $f[i][j]$ as whether it is possible to obtain a total reward of $j$ using the first $i$ reward values. Initially, $f[0][0] = \textit{True}$, and all other values are $\textit{False}$. We consider the $i$-th reward value $v$. If we do not choose it, then $f[i][j] = f[i - 1][j]$; if we choose it, then $f[i][j] = f[i - 1][j - v]$, where $0 \leq j - v < v$. Thus, the state transition equation is: @@ -80,7 +80,7 @@ $$ f[i][j] = f[i - 1][j] \vee f[i - 1][j - v] $$ -The final answer is $\max\{j \mid f[n][j] = \text{True}\}$. +The final answer is $\max\{j \mid f[n][j] = \textit{True}\}$. Since $f[i][j]$ only depends on $f[i - 1][j]$ and $f[i - 1][j - v]$, we can optimize away the first dimension and use only a one-dimensional array for state transitions. Additionally, due to the large data range of this problem, we need to use bit manipulation to optimize the efficiency of state transitions. diff --git a/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README.md b/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README.md index c111e5a4b60e..c930628bc2e2 100644 --- a/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README.md +++ b/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3184.Count%20Pairs%20That%20Form%20a%20Complete%20Day%20I/README.md +rating: 1149 +source: 第 402 场周赛 Q1 tags: - 数组 - 哈希表 @@ -67,13 +69,13 @@ tags: ### 方法一:计数 -我们可以用一个哈希表或者一个长度为 $24$ 的数组 $\text{cnt}$ 来记录每个小时数模 $24$ 的出现次数。 +我们可以用一个哈希表或者一个长度为 $24$ 的数组 $\textit{cnt}$ 来记录每个小时数模 $24$ 的出现次数。 -遍历数组 $\text{hours}$,对于每个小时数 $x$,我们可以得出与 $x$ 相加为 $24$ 的倍数,且模 $24$ 之后的数为 $(24 - x \bmod 24) \bmod 24$。累加这个数在哈希表或者数组中的出现次数即可。然后我们将 $x$ 的模 $24$ 的出现次数加一。 +遍历数组 $\textit{hours}$,对于每个小时数 $x$,我们可以得出与 $x$ 相加为 $24$ 的倍数,且模 $24$ 之后的数为 $(24 - x \bmod 24) \bmod 24$。累加这个数在哈希表或者数组中的出现次数即可。然后我们将 $x$ 的模 $24$ 的出现次数加一。 -遍历完数组 $\text{hours}$ 后,我们就可以得到满足题意的下标对数目。 +遍历完数组 $\textit{hours}$ 后,我们就可以得到满足题意的下标对数目。 -时间复杂度 $O(n)$,其中 $n$ 为数组 $\text{hours}$ 的长度。空间复杂度 $O(C)$,其中 $C=24$。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{hours}$ 的长度。空间复杂度 $O(C)$,其中 $C=24$。 diff --git a/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README_EN.md b/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README_EN.md index 7637e71618ea..c40c413ca542 100644 --- a/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README_EN.md +++ b/solution/3100-3199/3184.Count Pairs That Form a Complete Day I/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3184.Count%20Pairs%20That%20Form%20a%20Complete%20Day%20I/README_EN.md +rating: 1149 +source: Weekly Contest 402 Q1 tags: - Array - Hash Table @@ -65,13 +67,13 @@ tags: ### Solution 1: Counting -We can use a hash table or an array $\text{cnt}$ of length $24$ to record the occurrence count of each hour modulo $24$. +We can use a hash table or an array $\textit{cnt}$ of length $24$ to record the occurrence count of each hour modulo $24$. -Iterate through the array $\text{hours}$. For each hour $x$, we can find the number that, when added to $x$, results in a multiple of $24$, and after modulo $24$, this number is $(24 - x \bmod 24) \bmod 24$. We then accumulate the occurrence count of this number from the hash table or array. After that, we increment the occurrence count of $x$ modulo $24$ by one. +Iterate through the array $\textit{hours}$. For each hour $x$, we can find the number that, when added to $x$, results in a multiple of $24$, and after modulo $24$, this number is $(24 - x \bmod 24) \bmod 24$. We then accumulate the occurrence count of this number from the hash table or array. After that, we increment the occurrence count of $x$ modulo $24$ by one. -After iterating through the array $\text{hours}$, we can obtain the number of index pairs that meet the problem requirements. +After iterating through the array $\textit{hours}$, we can obtain the number of index pairs that meet the problem requirements. -The time complexity is $O(n)$, where $n$ is the length of the array $\text{hours}$. The space complexity is $O(C)$, where $C=24$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{hours}$. The space complexity is $O(C)$, where $C=24$. diff --git a/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README.md b/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README.md index 9435a4716364..61dcd201bce1 100644 --- a/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README.md +++ b/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3185.Count%20Pairs%20That%20Form%20a%20Complete%20Day%20II/README.md +rating: 1385 +source: 第 402 场周赛 Q2 tags: - 数组 - 哈希表 @@ -67,13 +69,13 @@ tags: ### 方法一:计数 -我们可以用一个哈希表或者一个长度为 $24$ 的数组 $\text{cnt}$ 来记录每个小时数模 $24$ 的出现次数。 +我们可以用一个哈希表或者一个长度为 $24$ 的数组 $\textit{cnt}$ 来记录每个小时数模 $24$ 的出现次数。 -遍历数组 $\text{hours}$,对于每个小时数 $x$,我们可以得出与 $x$ 相加为 $24$ 的倍数,且模 $24$ 之后的数为 $(24 - x \bmod 24) \bmod 24$。累加这个数在哈希表或者数组中的出现次数即可。然后我们将 $x$ 的模 $24$ 的出现次数加一。 +遍历数组 $\textit{hours}$,对于每个小时数 $x$,我们可以得出与 $x$ 相加为 $24$ 的倍数,且模 $24$ 之后的数为 $(24 - x \bmod 24) \bmod 24$。累加这个数在哈希表或者数组中的出现次数即可。然后我们将 $x$ 的模 $24$ 的出现次数加一。 -遍历完数组 $\text{hours}$ 后,我们就可以得到满足题意的下标对数目。 +遍历完数组 $\textit{hours}$ 后,我们就可以得到满足题意的下标对数目。 -时间复杂度 $O(n)$,其中 $n$ 为数组 $\text{hours}$ 的长度。空间复杂度 $O(C)$,其中 $C=24$。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{hours}$ 的长度。空间复杂度 $O(C)$,其中 $C=24$。 diff --git a/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README_EN.md b/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README_EN.md index f71fad7669f2..ea322133fd68 100644 --- a/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README_EN.md +++ b/solution/3100-3199/3185.Count Pairs That Form a Complete Day II/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3185.Count%20Pairs%20That%20Form%20a%20Complete%20Day%20II/README_EN.md +rating: 1385 +source: Weekly Contest 402 Q2 tags: - Array - Hash Table @@ -61,13 +63,13 @@ tags: ### Solution 1: Counting -We can use a hash table or an array $\text{cnt}$ of length $24$ to record the occurrence count of each hour modulo $24$. +We can use a hash table or an array $\textit{cnt}$ of length $24$ to record the occurrence count of each hour modulo $24$. -Iterate through the array $\text{hours}$. For each hour $x$, we can find the number that, when added to $x$, results in a multiple of $24$, and after modulo $24$, this number is $(24 - x \bmod 24) \bmod 24$. We then accumulate the occurrence count of this number from the hash table or array. After that, we increment the occurrence count of $x$ modulo $24$ by one. +Iterate through the array $\textit{hours}$. For each hour $x$, we can find the number that, when added to $x$, results in a multiple of $24$, and after modulo $24$, this number is $(24 - x \bmod 24) \bmod 24$. We then accumulate the occurrence count of this number from the hash table or array. After that, we increment the occurrence count of $x$ modulo $24$ by one. -After iterating through the array $\text{hours}$, we can obtain the number of index pairs that meet the problem requirements. +After iterating through the array $\textit{hours}$, we can obtain the number of index pairs that meet the problem requirements. -The time complexity is $O(n)$, where $n$ is the length of the array $\text{hours}$. The space complexity is $O(C)$, where $C=24$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{hours}$. The space complexity is $O(C)$, where $C=24$. diff --git a/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README.md b/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README.md index b539d6b97083..0f90dde7130b 100644 --- a/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README.md +++ b/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3186.Maximum%20Total%20Damage%20With%20Spell%20Casting/README.md +rating: 1840 +source: 第 402 场周赛 Q3 tags: - 数组 - 哈希表 @@ -75,17 +77,17 @@ tags: ### 方法一:二分查找 + 记忆化搜索 -我们可以先对数组 $\text{power}$ 进行排序,用一个哈希表 $\text{cnt}$ 来记录每个伤害值的出现次数,然后遍历数组 $\text{power}$,对于每个伤害值 $x$,我们可以得出使用伤害值为 $x$ 的咒语时,可以使用的下一个伤害值的索引,即第一个大于 $x + 2$ 的伤害值的索引,我们可以使用二分查找来找到这个索引,记录在数组 $\text{nxt}$ 中。 +我们可以先对数组 $\textit{power}$ 进行排序,用一个哈希表 $\textit{cnt}$ 来记录每个伤害值的出现次数,然后遍历数组 $\textit{power}$,对于每个伤害值 $x$,我们可以得出使用伤害值为 $x$ 的咒语时,可以使用的下一个伤害值的索引,即第一个大于 $x + 2$ 的伤害值的索引,我们可以使用二分查找来找到这个索引,记录在数组 $\textit{nxt}$ 中。 -接下来,我们定义一个函数 $\text{dfs}$,用来计算从第 $i$ 个伤害值开始,可以获得的最大伤害值。 +接下来,我们定义一个函数 $\textit{dfs}$,用来计算从第 $i$ 个伤害值开始,可以获得的最大伤害值。 -在 $\text{dfs}$ 函数中,我们可以选择跳过当前伤害值,那么我们可以跳过当前伤害值的所有相同伤害值,直接跳到 $i + \text{cnt}[x]$,可以获得的伤害值为 $\text{dfs}(i + \text{cnt}[x])$;或者我们可以选择使用当前伤害值,那么我们可以使用当前伤害值的所有相同伤害值,然后跳到下一个伤害值的索引,可以获得的伤害值为 $x \times \text{cnt}[x] + \text{dfs}(\text{nxt}[i])$,其中 $\text{nxt}[i]$ 表示第一个大于 $x + 2$ 的伤害值的索引。我们取这两种情况的最大值作为函数的返回值。 +在 $\textit{dfs}$ 函数中,我们可以选择跳过当前伤害值,那么我们可以跳过当前伤害值的所有相同伤害值,直接跳到 $i + \textit{cnt}[x]$,可以获得的伤害值为 $\textit{dfs}(i + \textit{cnt}[x])$;或者我们可以选择使用当前伤害值,那么我们可以使用当前伤害值的所有相同伤害值,然后跳到下一个伤害值的索引,可以获得的伤害值为 $x \times \textit{cnt}[x] + \textit{dfs}(\textit{nxt}[i])$,其中 $\textit{nxt}[i]$ 表示第一个大于 $x + 2$ 的伤害值的索引。我们取这两种情况的最大值作为函数的返回值。 -为了避免重复计算,我们可以使用记忆化搜索,将已经计算过的结果保存在数组 $\text{f}$ 中,这样在计算 $\text{dfs}(i)$ 时,如果 $\text{f}[i]$ 不为 $0$,则直接返回 $\text{f}[i]$。 +为了避免重复计算,我们可以使用记忆化搜索,将已经计算过的结果保存在数组 $\textit{f}$ 中,这样在计算 $\textit{dfs}(i)$ 时,如果 $\textit{f}[i]$ 不为 $0$,则直接返回 $\textit{f}[i]$。 -答案即为 $\text{dfs}(0)$。 +答案即为 $\textit{dfs}(0)$。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{power}$ 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{power}$ 的长度。 diff --git a/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README_EN.md b/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README_EN.md index 4491af4e9a56..ba65c0307dfa 100644 --- a/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README_EN.md +++ b/solution/3100-3199/3186.Maximum Total Damage With Spell Casting/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3186.Maximum%20Total%20Damage%20With%20Spell%20Casting/README_EN.md +rating: 1840 +source: Weekly Contest 402 Q3 tags: - Array - Hash Table @@ -73,17 +75,17 @@ tags: ### Solution 1: Binary Search + Memoization -We can first sort the array $\text{power}$, use a hash table $\text{cnt}$ to record the occurrence count of each damage value, and then iterate through the array $\text{power}$. For each damage value $x$, we can determine the index of the next damage value that can be used when using a spell with damage value $x$, which is the index of the first damage value greater than $x + 2$. We can use binary search to find this index and record it in the array $\text{nxt}$. +We can first sort the array $\textit{power}$, use a hash table $\textit{cnt}$ to record the occurrence count of each damage value, and then iterate through the array $\textit{power}$. For each damage value $x$, we can determine the index of the next damage value that can be used when using a spell with damage value $x$, which is the index of the first damage value greater than $x + 2$. We can use binary search to find this index and record it in the array $\textit{nxt}$. -Next, we define a function $\text{dfs}$ to calculate the maximum damage value that can be obtained starting from the $i$-th damage value. +Next, we define a function $\textit{dfs}$ to calculate the maximum damage value that can be obtained starting from the $i$-th damage value. -In the $\text{dfs}$ function, we can choose to skip the current damage value, so we can skip all the same damage values of the current one and directly jump to $i + \text{cnt}[x]$, obtaining a damage value of $\text{dfs}(i + \text{cnt}[x])$; or we can choose to use the current damage value, so we can use all the same damage values of the current one and then jump to the index of the next damage value, obtaining a damage value of $x \times \text{cnt}[x] + \text{dfs}(\text{nxt}[i])$, where $\text{nxt}[i]$ represents the index of the first damage value greater than $x + 2$. We take the maximum of these two cases as the return value of the function. +In the $\textit{dfs}$ function, we can choose to skip the current damage value, so we can skip all the same damage values of the current one and directly jump to $i + \textit{cnt}[x]$, obtaining a damage value of $\textit{dfs}(i + \textit{cnt}[x])$; or we can choose to use the current damage value, so we can use all the same damage values of the current one and then jump to the index of the next damage value, obtaining a damage value of $x \times \textit{cnt}[x] + \textit{dfs}(\textit{nxt}[i])$, where $\textit{nxt}[i]$ represents the index of the first damage value greater than $x + 2$. We take the maximum of these two cases as the return value of the function. -To avoid repeated calculations, we can use memoization, storing the results that have already been calculated in an array $\text{f}$. Thus, when calculating $\text{dfs}(i)$, if $\text{f}[i]$ is not $0$, we directly return $\text{f}[i]$. +To avoid repeated calculations, we can use memoization, storing the results that have already been calculated in an array $\textit{f}$. Thus, when calculating $\textit{dfs}(i)$, if $\textit{f}[i]$ is not $0$, we directly return $\textit{f}[i]$. -The answer is $\text{dfs}(0)$. +The answer is $\textit{dfs}(0)$. -The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\text{power}$. +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{power}$. diff --git a/solution/3100-3199/3187.Peaks in Array/README.md b/solution/3100-3199/3187.Peaks in Array/README.md index 761d9c055519..0718b4193200 100644 --- a/solution/3100-3199/3187.Peaks in Array/README.md +++ b/solution/3100-3199/3187.Peaks in Array/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3187.Peaks%20in%20Array/README.md +rating: 2154 +source: 第 402 场周赛 Q4 tags: - 树状数组 - 线段树 diff --git a/solution/3100-3199/3187.Peaks in Array/README_EN.md b/solution/3100-3199/3187.Peaks in Array/README_EN.md index eadb9d60bf3e..93986448235f 100644 --- a/solution/3100-3199/3187.Peaks in Array/README_EN.md +++ b/solution/3100-3199/3187.Peaks in Array/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3187.Peaks%20in%20Array/README_EN.md +rating: 2154 +source: Weekly Contest 402 Q4 tags: - Binary Indexed Tree - Segment Tree diff --git a/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README.md b/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README.md index a0f8fd3a4492..68fe4c358ac7 100644 --- a/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README.md +++ b/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3190.Find%20Minimum%20Operations%20to%20Make%20All%20Elements%20Divisible%20by%20Three/README.md +rating: 1139 +source: 第 133 场双周赛 Q1 tags: - 数组 - 数学 @@ -66,9 +68,9 @@ tags: ### 方法一:数学 -我们直接遍历数组 $\text{nums}$,对于每个元素 $x$,我们计算 $x$ 除以 3 的余数 $x \bmod 3$,如果余数不为 0,我们需要将 $x$ 变为能被 3 整除且操作次数最少,那么我们可以选择将 $x$ 减少 $x \bmod 3$ 或者增加 $3 - x \bmod 3$,取两者的最小值累加到答案中。 +我们直接遍历数组 $\textit{nums}$,对于每个元素 $x$,我们计算 $x$ 除以 3 的余数 $x \bmod 3$,如果余数不为 0,我们需要将 $x$ 变为能被 3 整除且操作次数最少,那么我们可以选择将 $x$ 减少 $x \bmod 3$ 或者增加 $3 - x \bmod 3$,取两者的最小值累加到答案中。 -时间复杂度 $O(n)$,其中 $n$ 为数组 $\text{nums}$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README_EN.md b/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README_EN.md index 2070d7a636b0..95003efe76f8 100644 --- a/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README_EN.md +++ b/solution/3100-3199/3190.Find Minimum Operations to Make All Elements Divisible by Three/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3190.Find%20Minimum%20Operations%20to%20Make%20All%20Elements%20Divisible%20by%20Three/README_EN.md +rating: 1139 +source: Biweekly Contest 133 Q1 tags: - Array - Math @@ -64,9 +66,9 @@ tags: ### Solution 1: Mathematics -We directly iterate through the array $\text{nums}$. For each element $x$, we calculate the remainder of $x$ divided by 3, $x \bmod 3$. If the remainder is not 0, we need to make $x$ divisible by 3 with the minimum number of operations. Therefore, we can choose to either decrease $x$ by $x \bmod 3$ or increase $x$ by $3 - x \bmod 3$, and we accumulate the minimum of these two values to the answer. +We directly iterate through the array $\textit{nums}$. For each element $x$, we calculate the remainder of $x$ divided by 3, $x \bmod 3$. If the remainder is not 0, we need to make $x$ divisible by 3 with the minimum number of operations. Therefore, we can choose to either decrease $x$ by $x \bmod 3$ or increase $x$ by $3 - x \bmod 3$, and we accumulate the minimum of these two values to the answer. -The time complexity is $O(n)$, where $n$ is the length of the array $\text{nums}$. The space complexity is $O(1)$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. diff --git a/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README.md b/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README.md index 649c317d41b0..1e2917435d4b 100644 --- a/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README.md +++ b/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3191.Minimum%20Operations%20to%20Make%20Binary%20Array%20Elements%20Equal%20to%20One%20I/README.md +rating: 1311 +source: 第 133 场双周赛 Q2 tags: - 位运算 - 队列 @@ -83,7 +85,7 @@ tags: 遍历结束后,返回答案即可。 -时间复杂度 $O(n)$,其中 $n$ 为数组 $\text{nums}$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README_EN.md b/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README_EN.md index 5e883bbb0f06..24960403e2ff 100644 --- a/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README_EN.md +++ b/solution/3100-3199/3191.Minimum Operations to Make Binary Array Elements Equal to One I/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3191.Minimum%20Operations%20to%20Make%20Binary%20Array%20Elements%20Equal%20to%20One%20I/README_EN.md +rating: 1311 +source: Biweekly Contest 133 Q2 tags: - Bit Manipulation - Queue @@ -81,7 +83,7 @@ We notice that the first position in the array that is $0$ must undergo a flip o After the traversal, we return the answer. -The time complexity is $O(n)$, where $n$ is the length of the array $\text{nums}$. The space complexity is $O(1)$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. diff --git a/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README.md b/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README.md index db4a7f96d87e..aa576122e8ec 100644 --- a/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README.md +++ b/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3192.Minimum%20Operations%20to%20Make%20Binary%20Array%20Elements%20Equal%20to%20One%20II/README.md +rating: 1432 +source: 第 133 场双周赛 Q3 tags: - 贪心 - 数组 @@ -84,11 +86,11 @@ tags: 我们注意到,每当我们将某个位置的元素变为 1 时,它的右侧的所有元素都会被反转。因此,我们可以用一个变量 $v$ 来记录当前位置及其右侧的元素是否被反转,如果被反转,那么 $v$ 的值为 1,否则为 0。 -我们遍历数组 $\text{nums}$,对于每个元素 $x$,我们将 $x$ 与 $v$ 进行异或运算,如果 $x$ 为 0,那么我们需要将 $x$ 变为 1,我们需要进行反转操作,我们将答案加一,并将 $v$ 取反。 +我们遍历数组 $\textit{nums}$,对于每个元素 $x$,我们将 $x$ 与 $v$ 进行异或运算,如果 $x$ 为 0,那么我们需要将 $x$ 变为 1,我们需要进行反转操作,我们将答案加一,并将 $v$ 取反。 遍历结束后,我们就可以得到最少操作次数。 -时间复杂度 $O(n)$,其中 $n$ 为数组 $\text{nums}$ 的长度。空间复杂度 $O(1)$。 +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 diff --git a/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README_EN.md b/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README_EN.md index d688ec1879a5..0342e644a6bc 100644 --- a/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README_EN.md +++ b/solution/3100-3199/3192.Minimum Operations to Make Binary Array Elements Equal to One II/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3192.Minimum%20Operations%20to%20Make%20Binary%20Array%20Elements%20Equal%20to%20One%20II/README_EN.md +rating: 1432 +source: Biweekly Contest 133 Q3 tags: - Greedy - Array @@ -82,11 +84,11 @@ We can do the following operation:

            We notice that whenever we change an element at a certain position to 1, all the elements to its right are flipped. Therefore, we can use a variable $v$ to record whether the current position and all elements to its right have been flipped. If flipped, the value of $v$ is 1, otherwise, it is 0. -We iterate through the array $\text{nums}$. For each element $x$, we perform an XOR operation between $x$ and $v$. If $x$ is 0, then we need to change $x$ to 1, which requires a flip operation. We increment the answer by one and flip the value of $v$. +We iterate through the array $\textit{nums}$. For each element $x$, we perform an XOR operation between $x$ and $v$. If $x$ is 0, then we need to change $x$ to 1, which requires a flip operation. We increment the answer by one and flip the value of $v$. After the iteration, we can obtain the minimum number of operations. -The time complexity is $O(n)$, where $n$ is the length of the array $\text{nums}$. The space complexity is $O(1)$. +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. diff --git a/solution/3100-3199/3193.Count the Number of Inversions/README.md b/solution/3100-3199/3193.Count the Number of Inversions/README.md index facd193e0f20..8d939c1912e3 100644 --- a/solution/3100-3199/3193.Count the Number of Inversions/README.md +++ b/solution/3100-3199/3193.Count the Number of Inversions/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3193.Count%20the%20Number%20of%20Inversions/README.md +rating: 2266 +source: 第 133 场双周赛 Q4 tags: - 数组 - 动态规划 @@ -127,7 +129,7 @@ $$ f[i][j] = \sum_{k=0}^{\min(i, j)} f[i-1][j-k] $$ -由于题目要求 $[0..\text{end}_i]$ 的逆序对数量为 $\text{cnt}_i$,因此,当我们计算 $i = \text{end}_i$ 时,我们只需要计算 $f[i][\text{cnt}_i]$ 即可。其余的 $f[i][..]$ 都为 $0$。 +由于题目要求 $[0..\textit{end}_i]$ 的逆序对数量为 $\textit{cnt}_i$,因此,当我们计算 $i = \textit{end}_i$ 时,我们只需要计算 $f[i][\textit{cnt}_i]$ 即可。其余的 $f[i][..]$ 都为 $0$。 时间复杂度 $O(n \times m \times \min(n, m))$,空间复杂度 $O(n \times m)$。其中 $m$ 是逆序对数量的最大值。本题中 $m \le 400$。 diff --git a/solution/3100-3199/3193.Count the Number of Inversions/README_EN.md b/solution/3100-3199/3193.Count the Number of Inversions/README_EN.md index 89739bbfbe15..1f423e476ea9 100644 --- a/solution/3100-3199/3193.Count the Number of Inversions/README_EN.md +++ b/solution/3100-3199/3193.Count the Number of Inversions/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3193.Count%20the%20Number%20of%20Inversions/README_EN.md +rating: 2266 +source: Biweekly Contest 133 Q4 tags: - Array - Dynamic Programming @@ -121,7 +123,7 @@ $$ f[i][j] = \sum_{k=0}^{\min(i, j)} f[i-1][j-k] $$ -Since the problem requires the number of inversions in $[0..\text{end}_i]$ to be $\text{cnt}_i$, when we calculate for $i = \text{end}_i$, we only need to compute $f[i][\text{cnt}_i]$. The rest of $f[i][..]$ will be $0$. +Since the problem requires the number of inversions in $[0..\textit{end}_i]$ to be $\textit{cnt}_i$, when we calculate for $i = \textit{end}_i$, we only need to compute $f[i][\textit{cnt}_i]$. The rest of $f[i][..]$ will be $0$. The time complexity is $O(n \times m \times \min(n, m))$, and the space complexity is $O(n \times m)$. Here, $m$ is the maximum number of inversions, and in this problem, $m \le 400$. diff --git a/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README.md b/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README.md index b013c5378d84..77387f14b8b5 100644 --- a/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README.md +++ b/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3194.Minimum%20Average%20of%20Smallest%20and%20Largest%20Elements/README.md +rating: 1194 +source: 第 403 场周赛 Q1 tags: - 数组 - 双指针 @@ -174,9 +176,9 @@ tags: ### 方法一:排序 -我们首先对数组 $\text{nums}$ 进行排序,然后从数组的两端开始取元素,分别计算两个元素的和,取最小值。最后将最小值除以 2 作为答案返回即可。 +我们首先对数组 $\textit{nums}$ 进行排序,然后从数组的两端开始取元素,分别计算两个元素的和,取最小值。最后将最小值除以 2 作为答案返回即可。 -时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 diff --git a/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README_EN.md b/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README_EN.md index 80e412dd5c12..98cb91d17c98 100644 --- a/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README_EN.md +++ b/solution/3100-3199/3194.Minimum Average of Smallest and Largest Elements/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3194.Minimum%20Average%20of%20Smallest%20and%20Largest%20Elements/README_EN.md +rating: 1194 +source: Weekly Contest 403 Q1 tags: - Array - Two Pointers @@ -172,9 +174,9 @@ The smallest element of averages, 5.5, is returned. ### Solution 1: Sorting -First, we sort the array $\text{nums}$. Then, we start taking elements from both ends of the array, calculating the sum of the two elements, and taking the minimum value. Finally, we return the minimum value divided by 2 as the answer. +First, we sort the array $\textit{nums}$. Then, we start taking elements from both ends of the array, calculating the sum of the two elements, and taking the minimum value. Finally, we return the minimum value divided by 2 as the answer. -The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$, where $n$ is the length of the array $\text{nums}$. +The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$, where $n$ is the length of the array $\textit{nums}$. diff --git a/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README.md b/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README.md index 9aabb18bdbdd..20653b5e553e 100644 --- a/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README.md +++ b/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3195.Find%20the%20Minimum%20Area%20to%20Cover%20All%20Ones%20I/README.md +rating: 1348 +source: 第 403 场周赛 Q2 tags: - 数组 - 矩阵 diff --git a/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README_EN.md b/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README_EN.md index dc73bfd04795..05fe44572fda 100644 --- a/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README_EN.md +++ b/solution/3100-3199/3195.Find the Minimum Area to Cover All Ones I/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3195.Find%20the%20Minimum%20Area%20to%20Cover%20All%20Ones%20I/README_EN.md +rating: 1348 +source: Weekly Contest 403 Q2 tags: - Array - Matrix diff --git a/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README.md b/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README.md index 70c2367cf694..3670c65248a3 100644 --- a/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README.md +++ b/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3196.Maximize%20Total%20Cost%20of%20Alternating%20Subarrays/README.md +rating: 1846 +source: 第 403 场周赛 Q3 tags: - 数组 - 动态规划 @@ -102,12 +104,12 @@ tags: 根据题目描述,如果当前数没取反,那么下一个可以取反,也可以不取反;如果当前数取反了,那么下一个只能不取反。 -因此,我们定义一个函数 $\text{dfs}(i, j)$,表示从第 $i$ 个数开始,第 $i$ 个数是否能取反,其中 $j$ 表示第 $i$ 个数是否取反。如果 $j = 0$,表示第 $i$ 个数不能取反,否则可以取反。答案为 $\text{dfs}(0, 0)$。 +因此,我们定义一个函数 $\textit{dfs}(i, j)$,表示从第 $i$ 个数开始,第 $i$ 个数是否能取反,其中 $j$ 表示第 $i$ 个数是否取反。如果 $j = 0$,表示第 $i$ 个数不能取反,否则可以取反。答案为 $\textit{dfs}(0, 0)$。 函数 $dfs(i, j)$ 的执行过程如下: -- 如果 $i \geq \text{len}(nums)$,表示已经遍历完了数组,返回 $0$; -- 否则,第 $i$ 个数可以不取反,此时答案为 $nums[i] + \text{dfs}(i + 1, 1)$;如果 $j = 1$,表示第 $i$ 个数可以取反,此时答案为 $\max(\text{dfs}(i + 1, 0) - nums[i])$。我们取两者的最大值即可。 +- 如果 $i \geq \textit{len}(nums)$,表示已经遍历完了数组,返回 $0$; +- 否则,第 $i$ 个数可以不取反,此时答案为 $nums[i] + \textit{dfs}(i + 1, 1)$;如果 $j = 1$,表示第 $i$ 个数可以取反,此时答案为 $\max(\textit{dfs}(i + 1, 0) - nums[i])$。我们取两者的最大值即可。 为了避免重复计算,我们可以使用记忆化搜索,将已经计算过的结果保存起来。 diff --git a/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README_EN.md b/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README_EN.md index 9c71740b95a0..17ac12706d72 100644 --- a/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README_EN.md +++ b/solution/3100-3199/3196.Maximize Total Cost of Alternating Subarrays/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3196.Maximize%20Total%20Cost%20of%20Alternating%20Subarrays/README_EN.md +rating: 1846 +source: Weekly Contest 403 Q3 tags: - Array - Dynamic Programming @@ -100,12 +102,12 @@ tags: Based on the problem description, if the current number has not been flipped, then the next one can either be flipped or not flipped; if the current number has been flipped, then the next one can only remain unflipped. -Therefore, we define a function $\text{dfs}(i, j)$, which represents starting from the $i$-th number, whether the $i$-th number can be flipped, where $j$ indicates whether the $i$-th number is flipped. If $j = 0$, it means the $i$-th number cannot be flipped, otherwise, it can be flipped. The answer is $\text{dfs}(0, 0)$. +Therefore, we define a function $\textit{dfs}(i, j)$, which represents starting from the $i$-th number, whether the $i$-th number can be flipped, where $j$ indicates whether the $i$-th number is flipped. If $j = 0$, it means the $i$-th number cannot be flipped, otherwise, it can be flipped. The answer is $\textit{dfs}(0, 0)$. The execution process of the function $dfs(i, j)$ is as follows: -- If $i \geq \text{len}(nums)$, it means the array has been fully traversed, return $0$; -- Otherwise, the $i$-th number can remain unflipped, in which case the answer is $nums[i] + \text{dfs}(i + 1, 1)$; if $j = 1$, it means the $i$-th number can be flipped, in which case the answer is $\max(\text{dfs}(i + 1, 0) - nums[i])$. We take the maximum of the two. +- If $i \geq \textit{len}(nums)$, it means the array has been fully traversed, return $0$; +- Otherwise, the $i$-th number can remain unflipped, in which case the answer is $nums[i] + \textit{dfs}(i + 1, 1)$; if $j = 1$, it means the $i$-th number can be flipped, in which case the answer is $\max(\textit{dfs}(i + 1, 0) - nums[i])$. We take the maximum of the two. To avoid repeated calculations, we can use memoization to save the results that have already been computed. diff --git a/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README.md b/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README.md index 74416885c359..acce2c72fabd 100644 --- a/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README.md +++ b/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3197.Find%20the%20Minimum%20Area%20to%20Cover%20All%20Ones%20II/README.md +rating: 2540 +source: 第 403 场周赛 Q4 tags: - 数组 - 枚举 @@ -91,7 +93,7 @@ tags: 1. 先进行一次纵向分割,再对左部分进行一次横向分割 1. 先进行一次纵向分割,再对右部分进行一次横向分割 -我们可以用一个函数 $\text{f}(i_1, j_1, i_2, j_2)$ 来计算矩形 $(i_1, j_1)$ 到 $(i_2, j_2)$ 包含所有 $1$ 的最小矩形面积。 +我们可以用一个函数 $\textit{f}(i_1, j_1, i_2, j_2)$ 来计算矩形 $(i_1, j_1)$ 到 $(i_2, j_2)$ 包含所有 $1$ 的最小矩形面积。 时间复杂度 $O(m^2 \times n^2)$,其中 $m$ 和 $n$ 分别是矩形的行数和列数。空间复杂度 $O(1)$。 diff --git a/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README_EN.md b/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README_EN.md index 90a5703fc160..8ca1f29792f5 100644 --- a/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README_EN.md +++ b/solution/3100-3199/3197.Find the Minimum Area to Cover All Ones II/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3197.Find%20the%20Minimum%20Area%20to%20Cover%20All%20Ones%20II/README_EN.md +rating: 2540 +source: Weekly Contest 403 Q4 tags: - Array - Enumeration @@ -89,7 +91,7 @@ We can enumerate the positions of the two dividing lines, which have $6$ possibi 5. First perform a vertical split, then a horizontal split on the left part 6. First perform a vertical split, then a horizontal split on the right part -We can use a function $\text{f}(i_1, j_1, i_2, j_2)$ to calculate the minimum rectangular area containing all $1$s from $(i_1, j_1)$ to $(i_2, j_2)$. +We can use a function $\textit{f}(i_1, j_1, i_2, j_2)$ to calculate the minimum rectangular area containing all $1$s from $(i_1, j_1)$ to $(i_2, j_2)$. The time complexity is $O(m^2 \times n^2)$, where $m$ and $n$ are the number of rows and columns of the rectangle, respectively. The space complexity is $O(1)$. diff --git a/solution/3200-3299/3200.Maximum Height of a Triangle/README.md b/solution/3200-3299/3200.Maximum Height of a Triangle/README.md index a2d75a955a96..539e1a35d13c 100644 --- a/solution/3200-3299/3200.Maximum Height of a Triangle/README.md +++ b/solution/3200-3299/3200.Maximum Height of a Triangle/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3200.Maximum%20Height%20of%20a%20Triangle/README.md +rating: 1451 +source: 第 404 场周赛 Q1 tags: - 数组 - 枚举 diff --git a/solution/3200-3299/3200.Maximum Height of a Triangle/README_EN.md b/solution/3200-3299/3200.Maximum Height of a Triangle/README_EN.md index de3101a17171..4ab6bea1319b 100644 --- a/solution/3200-3299/3200.Maximum Height of a Triangle/README_EN.md +++ b/solution/3200-3299/3200.Maximum Height of a Triangle/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3200.Maximum%20Height%20of%20a%20Triangle/README_EN.md +rating: 1451 +source: Weekly Contest 404 Q1 tags: - Array - Enumeration diff --git a/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README.md b/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README.md index 1cadd23dd13e..e13927dcf72a 100644 --- a/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README.md +++ b/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3201.Find%20the%20Maximum%20Length%20of%20Valid%20Subsequence%20I/README.md +rating: 1663 +source: 第 404 场周赛 Q2 tags: - 数组 - 动态规划 @@ -94,7 +96,7 @@ tags: 答案为所有 $f[x][y]$ 中的最大值。 -时间复杂度 $O(n \times k)$,空间复杂度 $O(k^2)$。其中 $n$ 为数组 $\text{nums}$ 的长度,而 $k=2$。 +时间复杂度 $O(n \times k)$,空间复杂度 $O(k^2)$。其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $k=2$。 diff --git a/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README_EN.md b/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README_EN.md index 64aa506195bd..44454ee1cdb7 100644 --- a/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README_EN.md +++ b/solution/3200-3299/3201.Find the Maximum Length of Valid Subsequence I/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3201.Find%20the%20Maximum%20Length%20of%20Valid%20Subsequence%20I/README_EN.md +rating: 1663 +source: Weekly Contest 404 Q2 tags: - Array - Dynamic Programming @@ -92,7 +94,7 @@ Iterate through the array $nums$, and for each number $x$, we get $x = x \bmod k The answer is the maximum value among all $f[x][y]$. -The time complexity is $O(n \times k)$, and the space complexity is $O(k^2)$. Here, $n$ is the length of the array $\text{nums}$, and $k=2$. +The time complexity is $O(n \times k)$, and the space complexity is $O(k^2)$. Here, $n$ is the length of the array $\textit{nums}$, and $k=2$. diff --git a/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README.md b/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README.md index 6b6d8c5488a0..46d2c442bb8f 100644 --- a/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README.md +++ b/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3202.Find%20the%20Maximum%20Length%20of%20Valid%20Subsequence%20II/README.md +rating: 1973 +source: 第 404 场周赛 Q3 tags: - 数组 - 动态规划 @@ -78,7 +80,7 @@ tags: 答案为所有 $f[x][y]$ 中的最大值。 -时间复杂度 $O(n \times k)$,空间复杂度 $O(k^2)$。其中 $n$ 为数组 $\text{nums}$ 的长度,而 $k$ 为给定的正整数。 +时间复杂度 $O(n \times k)$,空间复杂度 $O(k^2)$。其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $k$ 为给定的正整数。 #### Python3 diff --git a/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README_EN.md b/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README_EN.md index 74cad2e6c6e8..d95fb4e4de20 100644 --- a/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README_EN.md +++ b/solution/3200-3299/3202.Find the Maximum Length of Valid Subsequence II/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3202.Find%20the%20Maximum%20Length%20of%20Valid%20Subsequence%20II/README_EN.md +rating: 1973 +source: Weekly Contest 404 Q3 tags: - Array - Dynamic Programming @@ -75,7 +77,7 @@ Iterate through the array $nums$, and for each number $x$, we get $x = x \bmod k The answer is the maximum value among all $f[x][y]$. -The time complexity is $O(n \times k)$, and the space complexity is $O(k^2)$. Here, $n$ is the length of the array $\text{nums}$, and $k$ is the given positive integer. +The time complexity is $O(n \times k)$, and the space complexity is $O(k^2)$. Here, $n$ is the length of the array $\textit{nums}$, and $k$ is the given positive integer. diff --git a/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README.md b/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README.md index 6d9a65a21b59..39c06608c846 100644 --- a/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README.md +++ b/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3203.Find%20Minimum%20Diameter%20After%20Merging%20Two%20Trees/README.md +rating: 2266 +source: 第 404 场周赛 Q4 tags: - 树 - 深度优先搜索 diff --git a/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README_EN.md b/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README_EN.md index 9eae9c17028f..8664c3b7cd42 100644 --- a/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README_EN.md +++ b/solution/3200-3299/3203.Find Minimum Diameter After Merging Two Trees/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3203.Find%20Minimum%20Diameter%20After%20Merging%20Two%20Trees/README_EN.md +rating: 2266 +source: Weekly Contest 404 Q4 tags: - Tree - Depth-First Search diff --git a/solution/3200-3299/3205.Maximum Array Hopping Score I/README.md b/solution/3200-3299/3205.Maximum Array Hopping Score I/README.md index 2eb2746a9c65..c37847f6587b 100644 --- a/solution/3200-3299/3205.Maximum Array Hopping Score I/README.md +++ b/solution/3200-3299/3205.Maximum Array Hopping Score I/README.md @@ -4,6 +4,7 @@ difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README.md tags: - 栈 + - 贪心 - 数组 - 动态规划 - 单调栈 @@ -73,13 +74,13 @@ tags: ### 方法一:记忆化搜索 -我们设计一个函数 $\text{dfs}(i)$,表示从下标 $i$ 出发,能够获得的最大分数。那么答案就是 $\text{dfs}(0)$。 +我们设计一个函数 $\textit{dfs}(i)$,表示从下标 $i$ 出发,能够获得的最大分数。那么答案就是 $\textit{dfs}(0)$。 -函数 $\text{dfs}(i)$ 的执行过程如下: +函数 $\textit{dfs}(i)$ 的执行过程如下: -我们枚举下一个跳跃的位置 $j$,那么从下标 $i$ 出发,能够获得的分数就是 $(j - i) \times \text{nums}[j]$,加上从下标 $j$ 出发,能够获得的最大分数,总分数就是 $(j - i) \times \text{nums}[j] + \text{dfs}(j)$。我们枚举所有的 $j$,取分数的最大值即可。 +我们枚举下一个跳跃的位置 $j$,那么从下标 $i$ 出发,能够获得的分数就是 $(j - i) \times \textit{nums}[j]$,加上从下标 $j$ 出发,能够获得的最大分数,总分数就是 $(j - i) \times \textit{nums}[j] + \textit{dfs}(j)$。我们枚举所有的 $j$,取分数的最大值即可。 -为了避免重复计算,我们使用记忆化搜索的方法,将已经计算过的 $\text{dfs}(i)$ 的值保存起来,下次直接返回即可。 +为了避免重复计算,我们使用记忆化搜索的方法,将已经计算过的 $\textit{dfs}(i)$ 的值保存起来,下次直接返回即可。 时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。 @@ -203,7 +204,7 @@ function maxScore(nums: number[]): number { 状态转移方程为: $$ -f[j] = \max_{0 \leq i < j} \{ f[i] + (j - i) \times \text{nums}[j] \} +f[j] = \max_{0 \leq i < j} \{ f[i] + (j - i) \times \textit{nums}[j] \} $$ 时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。 @@ -298,11 +299,11 @@ function maxScore(nums: number[]): number { 我们观察发现,对于当前位置 $i$,我们应该跳到下一个值最大的位置 $j$,这样才能获得最大的分数。 -因此,我们遍历数组 $\text{nums}$,维护一个从栈底到栈顶单调递减的栈 $\text{stk}$。对于当前遍历到的位置 $i$,如果栈顶元素对应的值小于等于 $\text{nums}[i]$,我们就不断地弹出栈顶元素,直到栈为空或者栈顶元素对应的值大于 $\text{nums}[i]$,然后将 $i$ 入栈。 +因此,我们遍历数组 $\textit{nums}$,维护一个从栈底到栈顶单调递减的栈 $\textit{stk}$。对于当前遍历到的位置 $i$,如果栈顶元素对应的值小于等于 $\textit{nums}[i]$,我们就不断地弹出栈顶元素,直到栈为空或者栈顶元素对应的值大于 $\textit{nums}[i]$,然后将 $i$ 入栈。 -然后,我们初始化答案 $\text{ans}$ 和当前位置 $i = 0$,遍历栈中的元素,每次取出栈顶元素 $j$,更新答案 $\text{ans} += \text{nums}[j] \times (j - i)$,然后更新 $i = j$。 +然后,我们初始化答案 $\textit{ans}$ 和当前位置 $i = 0$,遍历栈中的元素,每次取出栈顶元素 $j$,更新答案 $\textit{ans} += \textit{nums}[j] \times (j - i)$,然后更新 $i = j$。 -最后返回答案 $\text{ans}$。 +最后返回答案 $\textit{ans}$。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。 diff --git a/solution/3200-3299/3205.Maximum Array Hopping Score I/README_EN.md b/solution/3200-3299/3205.Maximum Array Hopping Score I/README_EN.md index b944e0d127bb..1ce14013d7b5 100644 --- a/solution/3200-3299/3205.Maximum Array Hopping Score I/README_EN.md +++ b/solution/3200-3299/3205.Maximum Array Hopping Score I/README_EN.md @@ -4,6 +4,7 @@ difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README_EN.md tags: - Stack + - Greedy - Array - Dynamic Programming - Monotonic Stack @@ -71,13 +72,13 @@ tags: ### Solution 1: Memoization Search -We design a function $\text{dfs}(i)$, which represents the maximum score that can be obtained starting from index $i$. Therefore, the answer is $\text{dfs}(0)$. +We design a function $\textit{dfs}(i)$, which represents the maximum score that can be obtained starting from index $i$. Therefore, the answer is $\textit{dfs}(0)$. -The execution process of the function $\text{dfs}(i)$ is as follows: +The execution process of the function $\textit{dfs}(i)$ is as follows: -We enumerate the next jump position $j$. Thus, the score that can be obtained starting from index $i$ is $(j - i) \times \text{nums}[j]$, plus the maximum score that can be obtained starting from index $j$, making the total score $(j - i) \times \text{nums}[j] + \text{dfs}(j)$. We enumerate all possible $j$ and take the maximum score. +We enumerate the next jump position $j$. Thus, the score that can be obtained starting from index $i$ is $(j - i) \times \textit{nums}[j]$, plus the maximum score that can be obtained starting from index $j$, making the total score $(j - i) \times \textit{nums}[j] + \textit{dfs}(j)$. We enumerate all possible $j$ and take the maximum score. -To avoid redundant calculations, we use memoization search. We save the calculated value of $\text{dfs}(i)$, so it can be directly returned next time. +To avoid redundant calculations, we use memoization search. We save the calculated value of $\textit{dfs}(i)$, so it can be directly returned next time. The time complexity is $O(n^2)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array. @@ -201,7 +202,7 @@ Define $f[j]$ as the maximum score that can be obtained starting from index $0$ The state transition equation is: $$ -f[j] = \max_{0 \leq i < j} \{ f[i] + (j - i) \times \text{nums}[j] \} +f[j] = \max_{0 \leq i < j} \{ f[i] + (j - i) \times \textit{nums}[j] \} $$ The time complexity is $O(n^2)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array. @@ -296,11 +297,11 @@ function maxScore(nums: number[]): number { We observe that for the current position $i$, we should jump to the next position $j$ with the maximum value to obtain the maximum score. -Therefore, we traverse the array $\text{nums}$, maintaining a stack $\text{stk}$ that is monotonically decreasing from the bottom to the top of the stack. For the current position $i$ being traversed, if the value corresponding to the top element of the stack is less than or equal to $\text{nums}[i]$, we continuously pop the top element of the stack until the stack is empty or the value corresponding to the top element of the stack is greater than $\text{nums}[i]$, and then push $i$ into the stack. +Therefore, we traverse the array $\textit{nums}$, maintaining a stack $\textit{stk}$ that is monotonically decreasing from the bottom to the top of the stack. For the current position $i$ being traversed, if the value corresponding to the top element of the stack is less than or equal to $\textit{nums}[i]$, we continuously pop the top element of the stack until the stack is empty or the value corresponding to the top element of the stack is greater than $\textit{nums}[i]$, and then push $i$ into the stack. -Next, we initialize the answer $\text{ans}$ and the current position $i = 0$, traverse the elements in the stack, each time taking out the top element $j$, updating the answer $\text{ans} += \text{nums}[j] \times (j - i)$, and then updating $i = j$. +Next, we initialize the answer $\textit{ans}$ and the current position $i = 0$, traverse the elements in the stack, each time taking out the top element $j$, updating the answer $\textit{ans} += \textit{nums}[j] \times (j - i)$, and then updating $i = j$. -Finally, return the answer $\text{ans}$. +Finally, return the answer $\textit{ans}$. The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array. diff --git a/solution/3200-3299/3206.Alternating Groups I/README.md b/solution/3200-3299/3206.Alternating Groups I/README.md index 13e5f8ae452d..4222dac247b6 100644 --- a/solution/3200-3299/3206.Alternating Groups I/README.md +++ b/solution/3200-3299/3206.Alternating Groups I/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3206.Alternating%20Groups%20I/README.md +rating: 1223 +source: 第 134 场双周赛 Q1 tags: - 数组 - 滑动窗口 diff --git a/solution/3200-3299/3206.Alternating Groups I/README_EN.md b/solution/3200-3299/3206.Alternating Groups I/README_EN.md index f95540432521..92c5e1fecdfd 100644 --- a/solution/3200-3299/3206.Alternating Groups I/README_EN.md +++ b/solution/3200-3299/3206.Alternating Groups I/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3206.Alternating%20Groups%20I/README_EN.md +rating: 1223 +source: Biweekly Contest 134 Q1 tags: - Array - Sliding Window diff --git a/solution/3200-3299/3207.Maximum Points After Enemy Battles/README.md b/solution/3200-3299/3207.Maximum Points After Enemy Battles/README.md index 7b186e1d37b5..122f272003f8 100644 --- a/solution/3200-3299/3207.Maximum Points After Enemy Battles/README.md +++ b/solution/3200-3299/3207.Maximum Points After Enemy Battles/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3207.Maximum%20Points%20After%20Enemy%20Battles/README.md +rating: 1591 +source: 第 134 场双周赛 Q2 tags: - 贪心 - 数组 diff --git a/solution/3200-3299/3207.Maximum Points After Enemy Battles/README_EN.md b/solution/3200-3299/3207.Maximum Points After Enemy Battles/README_EN.md index ca3f5e671014..28741c8708b1 100644 --- a/solution/3200-3299/3207.Maximum Points After Enemy Battles/README_EN.md +++ b/solution/3200-3299/3207.Maximum Points After Enemy Battles/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3207.Maximum%20Points%20After%20Enemy%20Battles/README_EN.md +rating: 1591 +source: Biweekly Contest 134 Q2 tags: - Greedy - Array diff --git a/solution/3200-3299/3208.Alternating Groups II/README.md b/solution/3200-3299/3208.Alternating Groups II/README.md index a2a42683fd46..8b2dc2eba5ee 100644 --- a/solution/3200-3299/3208.Alternating Groups II/README.md +++ b/solution/3200-3299/3208.Alternating Groups II/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3208.Alternating%20Groups%20II/README.md +rating: 1721 +source: 第 134 场双周赛 Q3 tags: - 数组 - 滑动窗口 diff --git a/solution/3200-3299/3208.Alternating Groups II/README_EN.md b/solution/3200-3299/3208.Alternating Groups II/README_EN.md index 70a06159d6e2..a8811e709e9c 100644 --- a/solution/3200-3299/3208.Alternating Groups II/README_EN.md +++ b/solution/3200-3299/3208.Alternating Groups II/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3208.Alternating%20Groups%20II/README_EN.md +rating: 1721 +source: Biweekly Contest 134 Q3 tags: - Array - Sliding Window diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md index b4e01a11e8e7..96be0735405d 100644 --- a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3209.Number%20of%20Subarrays%20With%20AND%20Value%20of%20K/README.md +rating: 2050 +source: 第 134 场双周赛 Q4 tags: - 位运算 - 线段树 diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md index e3fcea5a71fe..9cf3a0099105 100644 --- a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3209.Number%20of%20Subarrays%20With%20AND%20Value%20of%20K/README_EN.md +rating: 2050 +source: Biweekly Contest 134 Q4 tags: - Bit Manipulation - Segment Tree diff --git a/solution/3200-3299/3210.Find the Encrypted String/README.md b/solution/3200-3299/3210.Find the Encrypted String/README.md index 7d494a649f79..5eda6583473a 100644 --- a/solution/3200-3299/3210.Find the Encrypted String/README.md +++ b/solution/3200-3299/3210.Find the Encrypted String/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3210.Find%20the%20Encrypted%20String/README.md +rating: 1179 +source: 第 405 场周赛 Q1 tags: - 字符串 --- diff --git a/solution/3200-3299/3210.Find the Encrypted String/README_EN.md b/solution/3200-3299/3210.Find the Encrypted String/README_EN.md index 19a55052eace..55d01cf9d8cc 100644 --- a/solution/3200-3299/3210.Find the Encrypted String/README_EN.md +++ b/solution/3200-3299/3210.Find the Encrypted String/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Easy edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3210.Find%20the%20Encrypted%20String/README_EN.md +rating: 1179 +source: Weekly Contest 405 Q1 tags: - String --- diff --git a/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README.md b/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README.md index d1169b1cf7f3..9adda151ba2e 100644 --- a/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README.md +++ b/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3211.Generate%20Binary%20Strings%20Without%20Adjacent%20Zeros/README.md +rating: 1352 +source: 第 405 场周赛 Q2 tags: - 位运算 - 递归 diff --git a/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README_EN.md b/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README_EN.md index 14dc2ab98e42..6b1ac72f6b51 100644 --- a/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README_EN.md +++ b/solution/3200-3299/3211.Generate Binary Strings Without Adjacent Zeros/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3211.Generate%20Binary%20Strings%20Without%20Adjacent%20Zeros/README_EN.md +rating: 1352 +source: Weekly Contest 405 Q2 tags: - Bit Manipulation - Recursion diff --git a/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README.md b/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README.md index 8a55c146733c..e3c42831e9a7 100644 --- a/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README.md +++ b/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3212.Count%20Submatrices%20With%20Equal%20Frequency%20of%20X%20and%20Y/README.md +rating: 1672 +source: 第 405 场周赛 Q3 tags: - 数组 - 矩阵 diff --git a/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README_EN.md b/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README_EN.md index 466cb50630e6..d8280dcef2bd 100644 --- a/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README_EN.md +++ b/solution/3200-3299/3212.Count Submatrices With Equal Frequency of X and Y/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3212.Count%20Submatrices%20With%20Equal%20Frequency%20of%20X%20and%20Y/README_EN.md +rating: 1672 +source: Weekly Contest 405 Q3 tags: - Array - Matrix diff --git a/solution/3200-3299/3213.Construct String with Minimum Cost/README.md b/solution/3200-3299/3213.Construct String with Minimum Cost/README.md index c2b9f03bdfdf..c32e43fe2fe8 100644 --- a/solution/3200-3299/3213.Construct String with Minimum Cost/README.md +++ b/solution/3200-3299/3213.Construct String with Minimum Cost/README.md @@ -2,6 +2,8 @@ comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3213.Construct%20String%20with%20Minimum%20Cost/README.md +rating: 2170 +source: 第 405 场周赛 Q4 tags: - 数组 - 字符串 diff --git a/solution/3200-3299/3213.Construct String with Minimum Cost/README_EN.md b/solution/3200-3299/3213.Construct String with Minimum Cost/README_EN.md index c9c9d354943b..b9403c42dccf 100644 --- a/solution/3200-3299/3213.Construct String with Minimum Cost/README_EN.md +++ b/solution/3200-3299/3213.Construct String with Minimum Cost/README_EN.md @@ -2,6 +2,8 @@ comments: true difficulty: Hard edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3213.Construct%20String%20with%20Minimum%20Cost/README_EN.md +rating: 2170 +source: Weekly Contest 405 Q4 tags: - Array - String diff --git a/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README.md b/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README.md index 48f26df72f9e..86aba739b80c 100644 --- a/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README.md +++ b/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README.md @@ -2,6 +2,9 @@ comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3215.Count%20Triplets%20with%20Even%20XOR%20Set%20Bits%20II/README.md +tags: + - 位运算 + - 数组 --- diff --git a/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README_EN.md b/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README_EN.md index ad7e28c68dbb..f69e8b398895 100644 --- a/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README_EN.md +++ b/solution/3200-3299/3215.Count Triplets with Even XOR Set Bits II/README_EN.md @@ -2,6 +2,9 @@ comments: true difficulty: Medium edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3215.Count%20Triplets%20with%20Even%20XOR%20Set%20Bits%20II/README_EN.md +tags: + - Bit Manipulation + - Array --- diff --git a/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/README.md b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/README.md new file mode 100644 index 000000000000..b7bd3ad19f6d --- /dev/null +++ b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/README.md @@ -0,0 +1,168 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README.md +rating: 1242 +source: 第 406 场周赛 Q1 +tags: + - 贪心 + - 字符串 +--- + + + +# [3216. 交换后字典序最小的字符串](https://leetcode.cn/problems/lexicographically-smallest-string-after-a-swap) + +[English Version](/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README_EN.md) + +## 题目描述 + + + +

            给你一个仅由数字组成的字符串 s,在最多交换一次 相邻 且具有相同 奇偶性 的数字后,返回可以得到的字典序最小的字符串

            + +

            如果两个数字都是奇数或都是偶数,则它们具有相同的奇偶性。例如,5 和 9、2 和 4 奇偶性相同,而 6 和 9 奇偶性不同。

            + +

             

            + +

            示例 1:

            + +
            +

            输入: s = "45320"

            + +

            输出: "43520"

            + +

            解释:

            + +

            s[1] == '5's[2] == '3' 都具有相同的奇偶性,交换它们可以得到字典序最小的字符串。

            +
            + +

            示例 2:

            + +
            +

            输入: s = "001"

            + +

            输出: "001"

            + +

            解释:

            + +

            无需进行交换,因为 s 已经是字典序最小的。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 2 <= s.length <= 100
            • +
            • s 仅由数字组成。
            • +
            + + + +## 解法 + + + +### 方法一:贪心 + 模拟 + +我们可以从左到右遍历字符串 $\textit{s}$,对于每一对相邻的数字,如果它们具有相同的奇偶性且前一个数字大于后一个数字,那么我们就交换这两个数字,使得字符串 $\textit{s}$ 的字典序变小,然后返回交换后的字符串。 + +遍历结束后,如果没有找到可以交换的数字对,说明字符串 $\textit{s}$ 已经是字典序最小的,直接返回即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $\textit{s}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def getSmallestString(self, s: str) -> str: + for i, (a, b) in enumerate(pairwise(map(ord, s))): + if (a + b) % 2 == 0 and a > b: + return s[:i] + s[i + 1] + s[i] + s[i + 2 :] + return s +``` + +#### Java + +```java +class Solution { + public String getSmallestString(String s) { + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 1; i < n; ++i) { + char a = cs[i - 1], b = cs[i]; + if (a > b && a % 2 == b % 2) { + cs[i] = a; + cs[i - 1] = b; + return new String(cs); + } + } + return s; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string getSmallestString(string s) { + int n = s.length(); + for (int i = 1; i < n; ++i) { + char a = s[i - 1], b = s[i]; + if (a > b && a % 2 == b % 2) { + s[i - 1] = b; + s[i] = a; + break; + } + } + return s; + } +}; +``` + +#### Go + +```go +func getSmallestString(s string) string { + cs := []byte(s) + n := len(cs) + for i := 1; i < n; i++ { + a, b := cs[i-1], cs[i] + if a > b && a%2 == b%2 { + cs[i-1], cs[i] = b, a + return string(cs) + } + } + return s +} +``` + +#### TypeScript + +```ts +function getSmallestString(s: string): string { + const n = s.length; + const cs: string[] = s.split(''); + for (let i = 1; i < n; ++i) { + const a = cs[i - 1]; + const b = cs[i]; + if (a > b && +a % 2 === +b % 2) { + cs[i - 1] = b; + cs[i] = a; + return cs.join(''); + } + } + return s; +} +``` + + + + + + diff --git a/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/README_EN.md b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/README_EN.md new file mode 100644 index 000000000000..de9488609865 --- /dev/null +++ b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/README_EN.md @@ -0,0 +1,166 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README_EN.md +rating: 1242 +source: Weekly Contest 406 Q1 +tags: + - Greedy + - String +--- + + + +# [3216. Lexicographically Smallest String After a Swap](https://leetcode.com/problems/lexicographically-smallest-string-after-a-swap) + +[中文文档](/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README.md) + +## Description + + + +

            Given a string s containing only digits, return the lexicographically smallest string that can be obtained after swapping adjacent digits in s with the same parity at most once.

            + +

            Digits have the same parity if both are odd or both are even. For example, 5 and 9, as well as 2 and 4, have the same parity, while 6 and 9 do not.

            + +

             

            +

            Example 1:

            + +
            +

            Input: s = "45320"

            + +

            Output: "43520"

            + +

            Explanation:

            + +

            s[1] == '5' and s[2] == '3' both have the same parity, and swapping them results in the lexicographically smallest string.

            +
            + +

            Example 2:

            + +
            +

            Input: s = "001"

            + +

            Output: "001"

            + +

            Explanation:

            + +

            There is no need to perform a swap because s is already the lexicographically smallest.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 2 <= s.length <= 100
            • +
            • s consists only of digits.
            • +
            + + + +## Solutions + + + +### Solution 1: Greedy + Simulation + +We can traverse the string $\textit{s}$ from left to right. For each pair of adjacent digits, if they have the same parity and the previous digit is greater than the next digit, then we swap these two digits to make the lexicographical order of the string $\textit{s}$ smaller, and then return the swapped string. + +After the traversal, if no swappable pair of digits is found, it means the string $\textit{s}$ is already in its smallest lexicographical order, and we can return it directly. + +The time complexity is $O(n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $\textit{s}$. + + + +#### Python3 + +```python +class Solution: + def getSmallestString(self, s: str) -> str: + for i, (a, b) in enumerate(pairwise(map(ord, s))): + if (a + b) % 2 == 0 and a > b: + return s[:i] + s[i + 1] + s[i] + s[i + 2 :] + return s +``` + +#### Java + +```java +class Solution { + public String getSmallestString(String s) { + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 1; i < n; ++i) { + char a = cs[i - 1], b = cs[i]; + if (a > b && a % 2 == b % 2) { + cs[i] = a; + cs[i - 1] = b; + return new String(cs); + } + } + return s; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string getSmallestString(string s) { + int n = s.length(); + for (int i = 1; i < n; ++i) { + char a = s[i - 1], b = s[i]; + if (a > b && a % 2 == b % 2) { + s[i - 1] = b; + s[i] = a; + break; + } + } + return s; + } +}; +``` + +#### Go + +```go +func getSmallestString(s string) string { + cs := []byte(s) + n := len(cs) + for i := 1; i < n; i++ { + a, b := cs[i-1], cs[i] + if a > b && a%2 == b%2 { + cs[i-1], cs[i] = b, a + return string(cs) + } + } + return s +} +``` + +#### TypeScript + +```ts +function getSmallestString(s: string): string { + const n = s.length; + const cs: string[] = s.split(''); + for (let i = 1; i < n; ++i) { + const a = cs[i - 1]; + const b = cs[i]; + if (a > b && +a % 2 === +b % 2) { + cs[i - 1] = b; + cs[i] = a; + return cs.join(''); + } + } + return s; +} +``` + + + + + + diff --git a/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.cpp b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.cpp new file mode 100644 index 000000000000..398011a423db --- /dev/null +++ b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + string getSmallestString(string s) { + int n = s.length(); + for (int i = 1; i < n; ++i) { + char a = s[i - 1], b = s[i]; + if (a > b && a % 2 == b % 2) { + s[i - 1] = b; + s[i] = a; + break; + } + } + return s; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.go b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.go new file mode 100644 index 000000000000..49f0ae97226e --- /dev/null +++ b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.go @@ -0,0 +1,12 @@ +func getSmallestString(s string) string { + cs := []byte(s) + n := len(cs) + for i := 1; i < n; i++ { + a, b := cs[i-1], cs[i] + if a > b && a%2 == b%2 { + cs[i-1], cs[i] = b, a + return string(cs) + } + } + return s +} \ No newline at end of file diff --git a/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.java b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.java new file mode 100644 index 000000000000..92c26f742abf --- /dev/null +++ b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.java @@ -0,0 +1,15 @@ +class Solution { + public String getSmallestString(String s) { + char[] cs = s.toCharArray(); + int n = cs.length; + for (int i = 1; i < n; ++i) { + char a = cs[i - 1], b = cs[i]; + if (a > b && a % 2 == b % 2) { + cs[i] = a; + cs[i - 1] = b; + return new String(cs); + } + } + return s; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.py b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.py new file mode 100644 index 000000000000..9f75d824bc01 --- /dev/null +++ b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.py @@ -0,0 +1,6 @@ +class Solution: + def getSmallestString(self, s: str) -> str: + for i, (a, b) in enumerate(pairwise(map(ord, s))): + if (a + b) % 2 == 0 and a > b: + return s[:i] + s[i + 1] + s[i] + s[i + 2 :] + return s diff --git a/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.ts b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.ts new file mode 100644 index 000000000000..c3d04e79b680 --- /dev/null +++ b/solution/3200-3299/3216.Lexicographically Smallest String After a Swap/Solution.ts @@ -0,0 +1,14 @@ +function getSmallestString(s: string): string { + const n = s.length; + const cs: string[] = s.split(''); + for (let i = 1; i < n; ++i) { + const a = cs[i - 1]; + const b = cs[i]; + if (a > b && +a % 2 === +b % 2) { + cs[i - 1] = b; + cs[i] = a; + return cs.join(''); + } + } + return s; +} diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/README.md b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/README.md new file mode 100644 index 000000000000..d999985a5ca7 --- /dev/null +++ b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/README.md @@ -0,0 +1,244 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README.md +rating: 1341 +source: 第 406 场周赛 Q2 +tags: + - 数组 + - 哈希表 + - 链表 +--- + + + +# [3217. 从链表中移除在数组中存在的节点](https://leetcode.cn/problems/delete-nodes-from-linked-list-present-in-array) + +[English Version](/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README_EN.md) + +## 题目描述 + + + +

            给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后,返回修改后的链表的头节点。

            + +

             

            + +

            示例 1:

            + +
            +

            输入: nums = [1,2,3], head = [1,2,3,4,5]

            + +

            输出: [4,5]

            + +

            解释:

            + +

            + +

            移除数值为 1, 2 和 3 的节点。

            +
            + +

            示例 2:

            + +
            +

            输入: nums = [1], head = [1,2,1,2,1,2]

            + +

            输出: [2,2,2]

            + +

            解释:

            + +

            + +

            移除数值为 1 的节点。

            +
            + +

            示例 3:

            + +
            +

            输入: nums = [5], head = [1,2,3,4]

            + +

            输出: [1,2,3,4]

            + +

            解释:

            + +

            + +

            链表中不存在值为 5 的节点。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 105
            • +
            • nums 中的所有元素都是唯一的。
            • +
            • 链表中的节点数在 [1, 105] 的范围内。
            • +
            • 1 <= Node.val <= 105
            • +
            • 输入保证链表中至少有一个值没有在 nums 中出现过。
            • +
            + + + +## 解法 + + + +### 方法一:哈希表 + +我们可以使用一个哈希表 $\textit{s}$ 来存储数组 $\textit{nums}$ 中的所有元素,然后定义一个虚拟节点 $\textit{dummy}$,将其指向链表的头节点 $\textit{head}$。 + +接下来,我们遍历从虚拟节点 $\textit{dummy}$ 开始的链表,如果当前节点的下一个节点的值在哈希表 $\textit{s}$ 中,我们就将当前节点的指针指向下下个节点,否则我们就将当前节点指针指向下一个节点。 + +最后,我们返回虚拟节点 $\textit{dummy}$ 的下一个节点。 + +时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度,而 $m$ 为链表 $\textit{head}$ 的长度。 + + + +#### Python3 + +```python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def modifiedList( + self, nums: List[int], head: Optional[ListNode] + ) -> Optional[ListNode]: + s = set(nums) + pre = dummy = ListNode(next=head) + while pre.next: + if pre.next.val in s: + pre.next = pre.next.next + else: + pre = pre.next + return dummy.next +``` + +#### Java + +```java +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode modifiedList(int[] nums, ListNode head) { + Set s = new HashSet<>(); + for (int x : nums) { + s.add(x); + } + ListNode dummy = new ListNode(0, head); + for (ListNode pre = dummy; pre.next != null;) { + if (s.contains(pre.next.val)) { + pre.next = pre.next.next; + } else { + pre = pre.next; + } + } + return dummy.next; + } +} +``` + +#### C++ + +```cpp +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* modifiedList(vector& nums, ListNode* head) { + unordered_set s(nums.begin(), nums.end()); + ListNode* dummy = new ListNode(0, head); + for (ListNode* pre = dummy; pre->next;) { + if (s.count(pre->next->val)) { + pre->next = pre->next->next; + } else { + pre = pre->next; + } + } + return dummy->next; + } +}; +``` + +#### Go + +```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func modifiedList(nums []int, head *ListNode) *ListNode { + s := map[int]bool{} + for _, x := range nums { + s[x] = true + } + dummy := &ListNode{Next: head} + for pre := dummy; pre.Next != nil; { + if s[pre.Next.Val] { + pre.Next = pre.Next.Next + } else { + pre = pre.Next + } + } + return dummy.Next +} +``` + +#### TypeScript + +```ts +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +function modifiedList(nums: number[], head: ListNode | null): ListNode | null { + const s: Set = new Set(nums); + const dummy = new ListNode(0, head); + for (let pre = dummy; pre.next; ) { + if (s.has(pre.next.val)) { + pre.next = pre.next.next; + } else { + pre = pre.next; + } + } + return dummy.next; +} +``` + + + + + + diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/README_EN.md b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/README_EN.md new file mode 100644 index 000000000000..25635df4cc7e --- /dev/null +++ b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/README_EN.md @@ -0,0 +1,242 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README_EN.md +rating: 1341 +source: Weekly Contest 406 Q2 +tags: + - Array + - Hash Table + - Linked List +--- + + + +# [3217. Delete Nodes From Linked List Present in Array](https://leetcode.com/problems/delete-nodes-from-linked-list-present-in-array) + +[中文文档](/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README.md) + +## Description + + + +

            You are given an array of integers nums and the head of a linked list. Return the head of the modified linked list after removing all nodes from the linked list that have a value that exists in nums.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [1,2,3], head = [1,2,3,4,5]

            + +

            Output: [4,5]

            + +

            Explanation:

            + +

            + +

            Remove the nodes with values 1, 2, and 3.

            +
            + +

            Example 2:

            + +
            +

            Input: nums = [1], head = [1,2,1,2,1,2]

            + +

            Output: [2,2,2]

            + +

            Explanation:

            + +

            + +

            Remove the nodes with value 1.

            +
            + +

            Example 3:

            + +
            +

            Input: nums = [5], head = [1,2,3,4]

            + +

            Output: [1,2,3,4]

            + +

            Explanation:

            + +

            + +

            No node has value 5.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 105
            • +
            • All elements in nums are unique.
            • +
            • The number of nodes in the given list is in the range [1, 105].
            • +
            • 1 <= Node.val <= 105
            • +
            • The input is generated such that there is at least one node in the linked list that has a value not present in nums.
            • +
            + + + +## Solutions + + + +### Solution 1: Hash Table + +We can use a hash table $\textit{s}$ to store all the elements in the array $\textit{nums}$. Then, we define a dummy node $\textit{dummy}$ and point it to the head node of the list $\textit{head}$. + +Next, we traverse the list starting from the dummy node $\textit{dummy}$. If the value of the next node of the current node is in the hash table $\textit{s}$, we make the current node point to the next next node; otherwise, we move the current node pointer to the next node. + +Finally, we return the next node of the dummy node $\textit{dummy}$. + +The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$, and $m$ is the length of the list $\textit{head}$. + + + +#### Python3 + +```python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def modifiedList( + self, nums: List[int], head: Optional[ListNode] + ) -> Optional[ListNode]: + s = set(nums) + pre = dummy = ListNode(next=head) + while pre.next: + if pre.next.val in s: + pre.next = pre.next.next + else: + pre = pre.next + return dummy.next +``` + +#### Java + +```java +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode modifiedList(int[] nums, ListNode head) { + Set s = new HashSet<>(); + for (int x : nums) { + s.add(x); + } + ListNode dummy = new ListNode(0, head); + for (ListNode pre = dummy; pre.next != null;) { + if (s.contains(pre.next.val)) { + pre.next = pre.next.next; + } else { + pre = pre.next; + } + } + return dummy.next; + } +} +``` + +#### C++ + +```cpp +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* modifiedList(vector& nums, ListNode* head) { + unordered_set s(nums.begin(), nums.end()); + ListNode* dummy = new ListNode(0, head); + for (ListNode* pre = dummy; pre->next;) { + if (s.count(pre->next->val)) { + pre->next = pre->next->next; + } else { + pre = pre->next; + } + } + return dummy->next; + } +}; +``` + +#### Go + +```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func modifiedList(nums []int, head *ListNode) *ListNode { + s := map[int]bool{} + for _, x := range nums { + s[x] = true + } + dummy := &ListNode{Next: head} + for pre := dummy; pre.Next != nil; { + if s[pre.Next.Val] { + pre.Next = pre.Next.Next + } else { + pre = pre.Next + } + } + return dummy.Next +} +``` + +#### TypeScript + +```ts +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +function modifiedList(nums: number[], head: ListNode | null): ListNode | null { + const s: Set = new Set(nums); + const dummy = new ListNode(0, head); + for (let pre = dummy; pre.next; ) { + if (s.has(pre.next.val)) { + pre.next = pre.next.next; + } else { + pre = pre.next; + } + } + return dummy.next; +} +``` + + + + + + diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.cpp b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.cpp new file mode 100644 index 000000000000..41b9361edf0b --- /dev/null +++ b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.cpp @@ -0,0 +1,25 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* modifiedList(vector& nums, ListNode* head) { + unordered_set s(nums.begin(), nums.end()); + ListNode* dummy = new ListNode(0, head); + for (ListNode* pre = dummy; pre->next;) { + if (s.count(pre->next->val)) { + pre->next = pre->next->next; + } else { + pre = pre->next; + } + } + return dummy->next; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.go b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.go new file mode 100644 index 000000000000..6e1e31d9e19c --- /dev/null +++ b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.go @@ -0,0 +1,22 @@ +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func modifiedList(nums []int, head *ListNode) *ListNode { + s := map[int]bool{} + for _, x := range nums { + s[x] = true + } + dummy := &ListNode{Next: head} + for pre := dummy; pre.Next != nil; { + if s[pre.Next.Val] { + pre.Next = pre.Next.Next + } else { + pre = pre.Next + } + } + return dummy.Next +} \ No newline at end of file diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.java b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.java new file mode 100644 index 000000000000..a4754a75ceea --- /dev/null +++ b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.java @@ -0,0 +1,27 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode modifiedList(int[] nums, ListNode head) { + Set s = new HashSet<>(); + for (int x : nums) { + s.add(x); + } + ListNode dummy = new ListNode(0, head); + for (ListNode pre = dummy; pre.next != null;) { + if (s.contains(pre.next.val)) { + pre.next = pre.next.next; + } else { + pre = pre.next; + } + } + return dummy.next; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.py b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.py new file mode 100644 index 000000000000..82b67d3f6f4e --- /dev/null +++ b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.py @@ -0,0 +1,17 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def modifiedList( + self, nums: List[int], head: Optional[ListNode] + ) -> Optional[ListNode]: + s = set(nums) + pre = dummy = ListNode(next=head) + while pre.next: + if pre.next.val in s: + pre.next = pre.next.next + else: + pre = pre.next + return dummy.next diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.ts b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.ts new file mode 100644 index 000000000000..4d499ab5049b --- /dev/null +++ b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/Solution.ts @@ -0,0 +1,24 @@ +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +function modifiedList(nums: number[], head: ListNode | null): ListNode | null { + const s: Set = new Set(nums); + const dummy = new ListNode(0, head); + for (let pre = dummy; pre.next; ) { + if (s.has(pre.next.val)) { + pre.next = pre.next.next; + } else { + pre = pre.next; + } + } + return dummy.next; +} diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample0.png b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample0.png new file mode 100644 index 000000000000..959f64e61dd0 Binary files /dev/null and b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample0.png differ diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample1.png b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample1.png new file mode 100644 index 000000000000..6946829c5499 Binary files /dev/null and b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample1.png differ diff --git a/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample2.png b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample2.png new file mode 100644 index 000000000000..4a03c7e48378 Binary files /dev/null and b/solution/3200-3299/3217.Delete Nodes From Linked List Present in Array/images/linkedlistexample2.png differ diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/README.md b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/README.md new file mode 100644 index 000000000000..0be2d066422a --- /dev/null +++ b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/README.md @@ -0,0 +1,240 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README.md +rating: 1654 +source: 第 406 场周赛 Q3 +tags: + - 贪心 + - 数组 + - 动态规划 + - 排序 +--- + + + +# [3218. 切蛋糕的最小总开销 I](https://leetcode.cn/problems/minimum-cost-for-cutting-cake-i) + +[English Version](/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README_EN.md) + +## 题目描述 + + + +

            有一个 m x n 大小的矩形蛋糕,需要切成 1 x 1 的小块。

            + +

            给你整数 m ,n 和两个数组:

            + +
              +
            • horizontalCut 的大小为 m - 1 ,其中 horizontalCut[i] 表示沿着水平线 i 切蛋糕的开销。
            • +
            • verticalCut 的大小为 n - 1 ,其中 verticalCut[j] 表示沿着垂直线 j 切蛋糕的开销。
            • +
            + +

            一次操作中,你可以选择任意不是 1 x 1 大小的矩形蛋糕并执行以下操作之一:

            + +
              +
            1. 沿着水平线 i 切开蛋糕,开销为 horizontalCut[i] 。
            2. +
            3. 沿着垂直线 j 切开蛋糕,开销为 verticalCut[j] 。
            4. +
            + +

            每次操作后,这块蛋糕都被切成两个独立的小蛋糕。

            + +

            每次操作的开销都为最开始对应切割线的开销,并且不会改变。

            + +

            请你返回将蛋糕全部切成 1 x 1 的蛋糕块的 最小 总开销。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:m = 3, n = 2, horizontalCut = [1,3], verticalCut = [5]

            + +

            输出:13

            + +

            解释:

            + +

            + +
              +
            • 沿着垂直线 0 切开蛋糕,开销为 5 。
            • +
            • 沿着水平线 0 切开 3 x 1 的蛋糕块,开销为 1 。
            • +
            • 沿着水平线 0 切开 3 x 1 的蛋糕块,开销为 1 。
            • +
            • 沿着水平线 1 切开 2 x 1 的蛋糕块,开销为 3 。
            • +
            • 沿着水平线 1 切开 2 x 1 的蛋糕块,开销为 3 。
            • +
            + +

            总开销为 5 + 1 + 1 + 3 + 3 = 13 。

            +
            + +

            示例 2:

            + +
            +

            输入:m = 2, n = 2, horizontalCut = [7], verticalCut = [4]

            + +

            输出:15

            + +

            解释:

            + +
              +
            • 沿着水平线 0 切开蛋糕,开销为 7 。
            • +
            • 沿着垂直线 0 切开 1 x 2 的蛋糕块,开销为 4 。
            • +
            • 沿着垂直线 0 切开 1 x 2 的蛋糕块,开销为 4 。
            • +
            + +

            总开销为 7 + 4 + 4 = 15 。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= m, n <= 20
            • +
            • horizontalCut.length == m - 1
            • +
            • verticalCut.length == n - 1
            • +
            • 1 <= horizontalCut[i], verticalCut[i] <= 103
            • +
            + + + +## 解法 + + + +### 方法一:贪心 + 双指针 + +对于一个位置,越早切,所需要切的次数越少,因此,显然是开销越大的位置越早切。 + +所以,我们可以对数组 $\textit{horizontalCut}$ 和 $\textit{verticalCut}$ 按照从大到小的顺序排序,然后使用两个指针 $i$ 和 $j$ 分别指向 $\textit{horizontalCut}$ 和 $\textit{verticalCut}$ 的开销,每次选择开销较大的位置进行切割,同时更新对应的行数和列数。 + +每次在水平方向上切割时,如果此前列数为 $v$,那么此次的开销为 $\textit{horizontalCut}[i] \times v$,然后行数 $h$ 加一;同理,每次在垂直方向上切割时,如果此前行数为 $h$,那么此次的开销为 $\textit{verticalCut}[j] \times h$,然后列数 $v$ 加一。 + +最后,当 $i$ 和 $j$ 都到达末尾时,返回总开销即可。 + +时间复杂度 $O(m \times \log m + n \times \log n)$,空间复杂度 $O(\log m + \log n)$。其中 $m$ 和 $n$ 分别为 $\textit{horizontalCut}$ 和 $\textit{verticalCut}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def minimumCost( + self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int] + ) -> int: + horizontalCut.sort(reverse=True) + verticalCut.sort(reverse=True) + ans = i = j = 0 + h = v = 1 + while i < m - 1 or j < n - 1: + if j == n - 1 or (i < m - 1 and horizontalCut[i] > verticalCut[j]): + ans += horizontalCut[i] * v + h, i = h + 1, i + 1 + else: + ans += verticalCut[j] * h + v, j = v + 1, j + 1 + return ans +``` + +#### Java + +```java +class Solution { + public int minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { + Arrays.sort(horizontalCut); + Arrays.sort(verticalCut); + int ans = 0; + int i = m - 2, j = n - 2; + int h = 1, v = 1; + while (i >= 0 || j >= 0) { + if (j < 0 || (i >= 0 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i--] * v; + ++h; + } else { + ans += verticalCut[j--] * h; + ++v; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumCost(int m, int n, vector& horizontalCut, vector& verticalCut) { + sort(horizontalCut.rbegin(), horizontalCut.rend()); + sort(verticalCut.rbegin(), verticalCut.rend()); + int ans = 0; + int i = 0, j = 0; + int h = 1, v = 1; + while (i < m - 1 || j < n - 1) { + if (j == n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i++] * v; + h++; + } else { + ans += verticalCut[j++] * h; + v++; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func minimumCost(m int, n int, horizontalCut []int, verticalCut []int) (ans int) { + sort.Sort(sort.Reverse(sort.IntSlice(horizontalCut))) + sort.Sort(sort.Reverse(sort.IntSlice(verticalCut))) + i, j := 0, 0 + h, v := 1, 1 + for i < m-1 || j < n-1 { + if j == n-1 || (i < m-1 && horizontalCut[i] > verticalCut[j]) { + ans += horizontalCut[i] * v + h++ + i++ + } else { + ans += verticalCut[j] * h + v++ + j++ + } + } + return +} +``` + +#### TypeScript + +```ts +function minimumCost(m: number, n: number, horizontalCut: number[], verticalCut: number[]): number { + horizontalCut.sort((a, b) => b - a); + verticalCut.sort((a, b) => b - a); + let ans = 0; + let [i, j] = [0, 0]; + let [h, v] = [1, 1]; + while (i < m - 1 || j < n - 1) { + if (j === n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i] * v; + h++; + i++; + } else { + ans += verticalCut[j] * h; + v++; + j++; + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/README_EN.md b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/README_EN.md new file mode 100644 index 000000000000..9d77bdd99146 --- /dev/null +++ b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/README_EN.md @@ -0,0 +1,238 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README_EN.md +rating: 1654 +source: Weekly Contest 406 Q3 +tags: + - Greedy + - Array + - Dynamic Programming + - Sorting +--- + + + +# [3218. Minimum Cost for Cutting Cake I](https://leetcode.com/problems/minimum-cost-for-cutting-cake-i) + +[中文文档](/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README.md) + +## Description + + + +

            There is an m x n cake that needs to be cut into 1 x 1 pieces.

            + +

            You are given integers m, n, and two arrays:

            + +
              +
            • horizontalCut of size m - 1, where horizontalCut[i] represents the cost to cut along the horizontal line i.
            • +
            • verticalCut of size n - 1, where verticalCut[j] represents the cost to cut along the vertical line j.
            • +
            + +

            In one operation, you can choose any piece of cake that is not yet a 1 x 1 square and perform one of the following cuts:

            + +
              +
            1. Cut along a horizontal line i at a cost of horizontalCut[i].
            2. +
            3. Cut along a vertical line j at a cost of verticalCut[j].
            4. +
            + +

            After the cut, the piece of cake is divided into two distinct pieces.

            + +

            The cost of a cut depends only on the initial cost of the line and does not change.

            + +

            Return the minimum total cost to cut the entire cake into 1 x 1 pieces.

            + +

             

            +

            Example 1:

            + +
            +

            Input: m = 3, n = 2, horizontalCut = [1,3], verticalCut = [5]

            + +

            Output: 13

            + +

            Explanation:

            + +

            + +
              +
            • Perform a cut on the vertical line 0 with cost 5, current total cost is 5.
            • +
            • Perform a cut on the horizontal line 0 on 3 x 1 subgrid with cost 1.
            • +
            • Perform a cut on the horizontal line 0 on 3 x 1 subgrid with cost 1.
            • +
            • Perform a cut on the horizontal line 1 on 2 x 1 subgrid with cost 3.
            • +
            • Perform a cut on the horizontal line 1 on 2 x 1 subgrid with cost 3.
            • +
            + +

            The total cost is 5 + 1 + 1 + 3 + 3 = 13.

            +
            + +

            Example 2:

            + +
            +

            Input: m = 2, n = 2, horizontalCut = [7], verticalCut = [4]

            + +

            Output: 15

            + +

            Explanation:

            + +
              +
            • Perform a cut on the horizontal line 0 with cost 7.
            • +
            • Perform a cut on the vertical line 0 on 1 x 2 subgrid with cost 4.
            • +
            • Perform a cut on the vertical line 0 on 1 x 2 subgrid with cost 4.
            • +
            + +

            The total cost is 7 + 4 + 4 = 15.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= m, n <= 20
            • +
            • horizontalCut.length == m - 1
            • +
            • verticalCut.length == n - 1
            • +
            • 1 <= horizontalCut[i], verticalCut[i] <= 103
            • +
            + + + +## Solutions + + + +### Solution 1: Greedy + Two Pointers + +For a given position, the earlier you cut, the fewer cuts are needed, so it is clear that positions with higher costs should be cut earlier. + +Therefore, we can sort the arrays $\textit{horizontalCut}$ and $\textit{verticalCut}$ in descending order, and then use two pointers $i$ and $j$ to point to the costs in $\textit{horizontalCut}$ and $\textit{verticalCut}$, respectively. Each time, we choose the position with the larger cost to cut, while updating the corresponding number of rows and columns. + +Each time a horizontal cut is made, if the number of columns before the cut was $v$, then the cost of this cut is $\textit{horizontalCut}[i] \times v$, and then the number of rows $h$ is incremented by one; similarly, each time a vertical cut is made, if the number of rows before the cut was $h$, then the cost of this cut is $\textit{verticalCut}[j] \times h$, and then the number of columns $v$ is incremented by one. + +Finally, when both $i$ and $j$ reach the end, return the total cost. + +The time complexity is $O(m \times \log m + n \times \log n)$, and the space complexity is $O(\log m + \log n)$. Here, $m$ and $n$ are the lengths of $\textit{horizontalCut}$ and $\textit{verticalCut}$, respectively. + + + +#### Python3 + +```python +class Solution: + def minimumCost( + self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int] + ) -> int: + horizontalCut.sort(reverse=True) + verticalCut.sort(reverse=True) + ans = i = j = 0 + h = v = 1 + while i < m - 1 or j < n - 1: + if j == n - 1 or (i < m - 1 and horizontalCut[i] > verticalCut[j]): + ans += horizontalCut[i] * v + h, i = h + 1, i + 1 + else: + ans += verticalCut[j] * h + v, j = v + 1, j + 1 + return ans +``` + +#### Java + +```java +class Solution { + public int minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { + Arrays.sort(horizontalCut); + Arrays.sort(verticalCut); + int ans = 0; + int i = m - 2, j = n - 2; + int h = 1, v = 1; + while (i >= 0 || j >= 0) { + if (j < 0 || (i >= 0 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i--] * v; + ++h; + } else { + ans += verticalCut[j--] * h; + ++v; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumCost(int m, int n, vector& horizontalCut, vector& verticalCut) { + sort(horizontalCut.rbegin(), horizontalCut.rend()); + sort(verticalCut.rbegin(), verticalCut.rend()); + int ans = 0; + int i = 0, j = 0; + int h = 1, v = 1; + while (i < m - 1 || j < n - 1) { + if (j == n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i++] * v; + h++; + } else { + ans += verticalCut[j++] * h; + v++; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func minimumCost(m int, n int, horizontalCut []int, verticalCut []int) (ans int) { + sort.Sort(sort.Reverse(sort.IntSlice(horizontalCut))) + sort.Sort(sort.Reverse(sort.IntSlice(verticalCut))) + i, j := 0, 0 + h, v := 1, 1 + for i < m-1 || j < n-1 { + if j == n-1 || (i < m-1 && horizontalCut[i] > verticalCut[j]) { + ans += horizontalCut[i] * v + h++ + i++ + } else { + ans += verticalCut[j] * h + v++ + j++ + } + } + return +} +``` + +#### TypeScript + +```ts +function minimumCost(m: number, n: number, horizontalCut: number[], verticalCut: number[]): number { + horizontalCut.sort((a, b) => b - a); + verticalCut.sort((a, b) => b - a); + let ans = 0; + let [i, j] = [0, 0]; + let [h, v] = [1, 1]; + while (i < m - 1 || j < n - 1) { + if (j === n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i] * v; + h++; + i++; + } else { + ans += verticalCut[j] * h; + v++; + j++; + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.cpp b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.cpp new file mode 100644 index 000000000000..b42c71b565b2 --- /dev/null +++ b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + int minimumCost(int m, int n, vector& horizontalCut, vector& verticalCut) { + sort(horizontalCut.rbegin(), horizontalCut.rend()); + sort(verticalCut.rbegin(), verticalCut.rend()); + int ans = 0; + int i = 0, j = 0; + int h = 1, v = 1; + while (i < m - 1 || j < n - 1) { + if (j == n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i++] * v; + h++; + } else { + ans += verticalCut[j++] * h; + v++; + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.go b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.go new file mode 100644 index 000000000000..51ccff2c94e7 --- /dev/null +++ b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.go @@ -0,0 +1,18 @@ +func minimumCost(m int, n int, horizontalCut []int, verticalCut []int) (ans int) { + sort.Sort(sort.Reverse(sort.IntSlice(horizontalCut))) + sort.Sort(sort.Reverse(sort.IntSlice(verticalCut))) + i, j := 0, 0 + h, v := 1, 1 + for i < m-1 || j < n-1 { + if j == n-1 || (i < m-1 && horizontalCut[i] > verticalCut[j]) { + ans += horizontalCut[i] * v + h++ + i++ + } else { + ans += verticalCut[j] * h + v++ + j++ + } + } + return +} \ No newline at end of file diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.java b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.java new file mode 100644 index 000000000000..2ea101401c9f --- /dev/null +++ b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.java @@ -0,0 +1,19 @@ +class Solution { + public int minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { + Arrays.sort(horizontalCut); + Arrays.sort(verticalCut); + int ans = 0; + int i = m - 2, j = n - 2; + int h = 1, v = 1; + while (i >= 0 || j >= 0) { + if (j < 0 || (i >= 0 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i--] * v; + ++h; + } else { + ans += verticalCut[j--] * h; + ++v; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.py b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.py new file mode 100644 index 000000000000..d87eb0723831 --- /dev/null +++ b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.py @@ -0,0 +1,16 @@ +class Solution: + def minimumCost( + self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int] + ) -> int: + horizontalCut.sort(reverse=True) + verticalCut.sort(reverse=True) + ans = i = j = 0 + h = v = 1 + while i < m - 1 or j < n - 1: + if j == n - 1 or (i < m - 1 and horizontalCut[i] > verticalCut[j]): + ans += horizontalCut[i] * v + h, i = h + 1, i + 1 + else: + ans += verticalCut[j] * h + v, j = v + 1, j + 1 + return ans diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.ts b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.ts new file mode 100644 index 000000000000..5069d7b85c34 --- /dev/null +++ b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/Solution.ts @@ -0,0 +1,19 @@ +function minimumCost(m: number, n: number, horizontalCut: number[], verticalCut: number[]): number { + horizontalCut.sort((a, b) => b - a); + verticalCut.sort((a, b) => b - a); + let ans = 0; + let [i, j] = [0, 0]; + let [h, v] = [1, 1]; + while (i < m - 1 || j < n - 1) { + if (j === n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i] * v; + h++; + i++; + } else { + ans += verticalCut[j] * h; + v++; + j++; + } + } + return ans; +} diff --git a/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/images/ezgifcom-animated-gif-maker-1.gif b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/images/ezgifcom-animated-gif-maker-1.gif new file mode 100644 index 000000000000..6f53ef8b8f9f Binary files /dev/null and b/solution/3200-3299/3218.Minimum Cost for Cutting Cake I/images/ezgifcom-animated-gif-maker-1.gif differ diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/README.md b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/README.md new file mode 100644 index 000000000000..14d3bfb3b2c6 --- /dev/null +++ b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/README.md @@ -0,0 +1,239 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README.md +rating: 1789 +source: 第 406 场周赛 Q4 +tags: + - 贪心 + - 数组 + - 排序 +--- + + + +# [3219. 切蛋糕的最小总开销 II](https://leetcode.cn/problems/minimum-cost-for-cutting-cake-ii) + +[English Version](/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README_EN.md) + +## 题目描述 + + + +

            有一个 m x n 大小的矩形蛋糕,需要切成 1 x 1 的小块。

            + +

            给你整数 m ,n 和两个数组:

            + +
              +
            • horizontalCut 的大小为 m - 1 ,其中 horizontalCut[i] 表示沿着水平线 i 切蛋糕的开销。
            • +
            • verticalCut 的大小为 n - 1 ,其中 verticalCut[j] 表示沿着垂直线 j 切蛋糕的开销。
            • +
            + +

            一次操作中,你可以选择任意不是 1 x 1 大小的矩形蛋糕并执行以下操作之一:

            + +
              +
            1. 沿着水平线 i 切开蛋糕,开销为 horizontalCut[i] 。
            2. +
            3. 沿着垂直线 j 切开蛋糕,开销为 verticalCut[j] 。
            4. +
            + +

            每次操作后,这块蛋糕都被切成两个独立的小蛋糕。

            + +

            每次操作的开销都为最开始对应切割线的开销,并且不会改变。

            + +

            请你返回将蛋糕全部切成 1 x 1 的蛋糕块的 最小 总开销。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:m = 3, n = 2, horizontalCut = [1,3], verticalCut = [5]

            + +

            输出:13

            + +

            解释:

            + +

            + +
              +
            • 沿着垂直线 0 切开蛋糕,开销为 5 。
            • +
            • 沿着水平线 0 切开 3 x 1 的蛋糕块,开销为 1 。
            • +
            • 沿着水平线 0 切开 3 x 1 的蛋糕块,开销为 1 。
            • +
            • 沿着水平线 1 切开 2 x 1 的蛋糕块,开销为 3 。
            • +
            • 沿着水平线 1 切开 2 x 1 的蛋糕块,开销为 3 。
            • +
            + +

            总开销为 5 + 1 + 1 + 3 + 3 = 13 。

            +
            + +

            示例 2:

            + +
            +

            输入:m = 2, n = 2, horizontalCut = [7], verticalCut = [4]

            + +

            输出:15

            + +

            解释:

            + +
              +
            • 沿着水平线 0 切开蛋糕,开销为 7 。
            • +
            • 沿着垂直线 0 切开 1 x 2 的蛋糕块,开销为 4 。
            • +
            • 沿着垂直线 0 切开 1 x 2 的蛋糕块,开销为 4 。
            • +
            + +

            总开销为 7 + 4 + 4 = 15 。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= m, n <= 105
            • +
            • horizontalCut.length == m - 1
            • +
            • verticalCut.length == n - 1
            • +
            • 1 <= horizontalCut[i], verticalCut[i] <= 103
            • +
            + + + +## 解法 + + + +### 方法一:贪心 + 双指针 + +对于一个位置,越早切,所需要切的次数越少,因此,显然是开销越大的位置越早切。 + +所以,我们可以对数组 $\textit{horizontalCut}$ 和 $\textit{verticalCut}$ 按照从大到小的顺序排序,然后使用两个指针 $i$ 和 $j$ 分别指向 $\textit{horizontalCut}$ 和 $\textit{verticalCut}$ 的开销,每次选择开销较大的位置进行切割,同时更新对应的行数和列数。 + +每次在水平方向上切割时,如果此前列数为 $v$,那么此次的开销为 $\textit{horizontalCut}[i] \times v$,然后行数 $h$ 加一;同理,每次在垂直方向上切割时,如果此前行数为 $h$,那么此次的开销为 $\textit{verticalCut}[j] \times h$,然后列数 $v$ 加一。 + +最后,当 $i$ 和 $j$ 都到达末尾时,返回总开销即可。 + +时间复杂度 $O(m \times \log m + n \times \log n)$,空间复杂度 $O(\log m + \log n)$。其中 $m$ 和 $n$ 分别为 $\textit{horizontalCut}$ 和 $\textit{verticalCut}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def minimumCost( + self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int] + ) -> int: + horizontalCut.sort(reverse=True) + verticalCut.sort(reverse=True) + ans = i = j = 0 + h = v = 1 + while i < m - 1 or j < n - 1: + if j == n - 1 or (i < m - 1 and horizontalCut[i] > verticalCut[j]): + ans += horizontalCut[i] * v + h, i = h + 1, i + 1 + else: + ans += verticalCut[j] * h + v, j = v + 1, j + 1 + return ans +``` + +#### Java + +```java +class Solution { + public long minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { + Arrays.sort(horizontalCut); + Arrays.sort(verticalCut); + long ans = 0; + int i = m - 2, j = n - 2; + int h = 1, v = 1; + while (i >= 0 || j >= 0) { + if (j < 0 || (i >= 0 && horizontalCut[i] > verticalCut[j])) { + ans += 1L * horizontalCut[i--] * v; + ++h; + } else { + ans += 1L * verticalCut[j--] * h; + ++v; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long minimumCost(int m, int n, vector& horizontalCut, vector& verticalCut) { + sort(horizontalCut.rbegin(), horizontalCut.rend()); + sort(verticalCut.rbegin(), verticalCut.rend()); + long long ans = 0; + int i = 0, j = 0; + int h = 1, v = 1; + while (i < m - 1 || j < n - 1) { + if (j == n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += 1LL * horizontalCut[i++] * v; + h++; + } else { + ans += 1LL * verticalCut[j++] * h; + v++; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func minimumCost(m int, n int, horizontalCut []int, verticalCut []int) (ans int64) { + sort.Sort(sort.Reverse(sort.IntSlice(horizontalCut))) + sort.Sort(sort.Reverse(sort.IntSlice(verticalCut))) + i, j := 0, 0 + h, v := 1, 1 + for i < m-1 || j < n-1 { + if j == n-1 || (i < m-1 && horizontalCut[i] > verticalCut[j]) { + ans += int64(horizontalCut[i] * v) + h++ + i++ + } else { + ans += int64(verticalCut[j] * h) + v++ + j++ + } + } + return +} +``` + +#### TypeScript + +```ts +function minimumCost(m: number, n: number, horizontalCut: number[], verticalCut: number[]): number { + horizontalCut.sort((a, b) => b - a); + verticalCut.sort((a, b) => b - a); + let ans = 0; + let [i, j] = [0, 0]; + let [h, v] = [1, 1]; + while (i < m - 1 || j < n - 1) { + if (j === n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i] * v; + h++; + i++; + } else { + ans += verticalCut[j] * h; + v++; + j++; + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/README_EN.md b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/README_EN.md new file mode 100644 index 000000000000..502af18615bb --- /dev/null +++ b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/README_EN.md @@ -0,0 +1,237 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README_EN.md +rating: 1789 +source: Weekly Contest 406 Q4 +tags: + - Greedy + - Array + - Sorting +--- + + + +# [3219. Minimum Cost for Cutting Cake II](https://leetcode.com/problems/minimum-cost-for-cutting-cake-ii) + +[中文文档](/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README.md) + +## Description + + + +

            There is an m x n cake that needs to be cut into 1 x 1 pieces.

            + +

            You are given integers m, n, and two arrays:

            + +
              +
            • horizontalCut of size m - 1, where horizontalCut[i] represents the cost to cut along the horizontal line i.
            • +
            • verticalCut of size n - 1, where verticalCut[j] represents the cost to cut along the vertical line j.
            • +
            + +

            In one operation, you can choose any piece of cake that is not yet a 1 x 1 square and perform one of the following cuts:

            + +
              +
            1. Cut along a horizontal line i at a cost of horizontalCut[i].
            2. +
            3. Cut along a vertical line j at a cost of verticalCut[j].
            4. +
            + +

            After the cut, the piece of cake is divided into two distinct pieces.

            + +

            The cost of a cut depends only on the initial cost of the line and does not change.

            + +

            Return the minimum total cost to cut the entire cake into 1 x 1 pieces.

            + +

             

            +

            Example 1:

            + +
            +

            Input: m = 3, n = 2, horizontalCut = [1,3], verticalCut = [5]

            + +

            Output: 13

            + +

            Explanation:

            + +

            + +
              +
            • Perform a cut on the vertical line 0 with cost 5, current total cost is 5.
            • +
            • Perform a cut on the horizontal line 0 on 3 x 1 subgrid with cost 1.
            • +
            • Perform a cut on the horizontal line 0 on 3 x 1 subgrid with cost 1.
            • +
            • Perform a cut on the horizontal line 1 on 2 x 1 subgrid with cost 3.
            • +
            • Perform a cut on the horizontal line 1 on 2 x 1 subgrid with cost 3.
            • +
            + +

            The total cost is 5 + 1 + 1 + 3 + 3 = 13.

            +
            + +

            Example 2:

            + +
            +

            Input: m = 2, n = 2, horizontalCut = [7], verticalCut = [4]

            + +

            Output: 15

            + +

            Explanation:

            + +
              +
            • Perform a cut on the horizontal line 0 with cost 7.
            • +
            • Perform a cut on the vertical line 0 on 1 x 2 subgrid with cost 4.
            • +
            • Perform a cut on the vertical line 0 on 1 x 2 subgrid with cost 4.
            • +
            + +

            The total cost is 7 + 4 + 4 = 15.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= m, n <= 105
            • +
            • horizontalCut.length == m - 1
            • +
            • verticalCut.length == n - 1
            • +
            • 1 <= horizontalCut[i], verticalCut[i] <= 103
            • +
            + + + +## Solutions + + + +### Solution 1: Greedy + Two Pointers + +For a given position, the earlier you cut, the fewer cuts are needed, so it is clear that positions with higher costs should be cut earlier. + +Therefore, we can sort the arrays $\textit{horizontalCut}$ and $\textit{verticalCut}$ in descending order, and then use two pointers $i$ and $j$ to point to the costs in $\textit{horizontalCut}$ and $\textit{verticalCut}$, respectively. Each time, we choose the position with the larger cost to cut, while updating the corresponding number of rows and columns. + +Each time a horizontal cut is made, if the number of columns before the cut was $v$, then the cost of this cut is $\textit{horizontalCut}[i] \times v$, and then the number of rows $h$ is incremented by one; similarly, each time a vertical cut is made, if the number of rows before the cut was $h$, then the cost of this cut is $\textit{verticalCut}[j] \times h$, and then the number of columns $v$ is incremented by one. + +Finally, when both $i$ and $j$ reach the end, return the total cost. + +The time complexity is $O(m \times \log m + n \times \log n)$, and the space complexity is $O(\log m + \log n)$. Here, $m$ and $n$ are the lengths of $\textit{horizontalCut}$ and $\textit{verticalCut}$, respectively. + + + +#### Python3 + +```python +class Solution: + def minimumCost( + self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int] + ) -> int: + horizontalCut.sort(reverse=True) + verticalCut.sort(reverse=True) + ans = i = j = 0 + h = v = 1 + while i < m - 1 or j < n - 1: + if j == n - 1 or (i < m - 1 and horizontalCut[i] > verticalCut[j]): + ans += horizontalCut[i] * v + h, i = h + 1, i + 1 + else: + ans += verticalCut[j] * h + v, j = v + 1, j + 1 + return ans +``` + +#### Java + +```java +class Solution { + public long minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { + Arrays.sort(horizontalCut); + Arrays.sort(verticalCut); + long ans = 0; + int i = m - 2, j = n - 2; + int h = 1, v = 1; + while (i >= 0 || j >= 0) { + if (j < 0 || (i >= 0 && horizontalCut[i] > verticalCut[j])) { + ans += 1L * horizontalCut[i--] * v; + ++h; + } else { + ans += 1L * verticalCut[j--] * h; + ++v; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long minimumCost(int m, int n, vector& horizontalCut, vector& verticalCut) { + sort(horizontalCut.rbegin(), horizontalCut.rend()); + sort(verticalCut.rbegin(), verticalCut.rend()); + long long ans = 0; + int i = 0, j = 0; + int h = 1, v = 1; + while (i < m - 1 || j < n - 1) { + if (j == n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += 1LL * horizontalCut[i++] * v; + h++; + } else { + ans += 1LL * verticalCut[j++] * h; + v++; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func minimumCost(m int, n int, horizontalCut []int, verticalCut []int) (ans int64) { + sort.Sort(sort.Reverse(sort.IntSlice(horizontalCut))) + sort.Sort(sort.Reverse(sort.IntSlice(verticalCut))) + i, j := 0, 0 + h, v := 1, 1 + for i < m-1 || j < n-1 { + if j == n-1 || (i < m-1 && horizontalCut[i] > verticalCut[j]) { + ans += int64(horizontalCut[i] * v) + h++ + i++ + } else { + ans += int64(verticalCut[j] * h) + v++ + j++ + } + } + return +} +``` + +#### TypeScript + +```ts +function minimumCost(m: number, n: number, horizontalCut: number[], verticalCut: number[]): number { + horizontalCut.sort((a, b) => b - a); + verticalCut.sort((a, b) => b - a); + let ans = 0; + let [i, j] = [0, 0]; + let [h, v] = [1, 1]; + while (i < m - 1 || j < n - 1) { + if (j === n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i] * v; + h++; + i++; + } else { + ans += verticalCut[j] * h; + v++; + j++; + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.cpp b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.cpp new file mode 100644 index 000000000000..b3e0a8b0b71e --- /dev/null +++ b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + long long minimumCost(int m, int n, vector& horizontalCut, vector& verticalCut) { + sort(horizontalCut.rbegin(), horizontalCut.rend()); + sort(verticalCut.rbegin(), verticalCut.rend()); + long long ans = 0; + int i = 0, j = 0; + int h = 1, v = 1; + while (i < m - 1 || j < n - 1) { + if (j == n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += 1LL * horizontalCut[i++] * v; + h++; + } else { + ans += 1LL * verticalCut[j++] * h; + v++; + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.go b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.go new file mode 100644 index 000000000000..2db1df5d2b30 --- /dev/null +++ b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.go @@ -0,0 +1,18 @@ +func minimumCost(m int, n int, horizontalCut []int, verticalCut []int) (ans int64) { + sort.Sort(sort.Reverse(sort.IntSlice(horizontalCut))) + sort.Sort(sort.Reverse(sort.IntSlice(verticalCut))) + i, j := 0, 0 + h, v := 1, 1 + for i < m-1 || j < n-1 { + if j == n-1 || (i < m-1 && horizontalCut[i] > verticalCut[j]) { + ans += int64(horizontalCut[i] * v) + h++ + i++ + } else { + ans += int64(verticalCut[j] * h) + v++ + j++ + } + } + return +} \ No newline at end of file diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.java b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.java new file mode 100644 index 000000000000..20e2ad7f52c5 --- /dev/null +++ b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.java @@ -0,0 +1,19 @@ +class Solution { + public long minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { + Arrays.sort(horizontalCut); + Arrays.sort(verticalCut); + long ans = 0; + int i = m - 2, j = n - 2; + int h = 1, v = 1; + while (i >= 0 || j >= 0) { + if (j < 0 || (i >= 0 && horizontalCut[i] > verticalCut[j])) { + ans += 1L * horizontalCut[i--] * v; + ++h; + } else { + ans += 1L * verticalCut[j--] * h; + ++v; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.py b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.py new file mode 100644 index 000000000000..d87eb0723831 --- /dev/null +++ b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.py @@ -0,0 +1,16 @@ +class Solution: + def minimumCost( + self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int] + ) -> int: + horizontalCut.sort(reverse=True) + verticalCut.sort(reverse=True) + ans = i = j = 0 + h = v = 1 + while i < m - 1 or j < n - 1: + if j == n - 1 or (i < m - 1 and horizontalCut[i] > verticalCut[j]): + ans += horizontalCut[i] * v + h, i = h + 1, i + 1 + else: + ans += verticalCut[j] * h + v, j = v + 1, j + 1 + return ans diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.ts b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.ts new file mode 100644 index 000000000000..5069d7b85c34 --- /dev/null +++ b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/Solution.ts @@ -0,0 +1,19 @@ +function minimumCost(m: number, n: number, horizontalCut: number[], verticalCut: number[]): number { + horizontalCut.sort((a, b) => b - a); + verticalCut.sort((a, b) => b - a); + let ans = 0; + let [i, j] = [0, 0]; + let [h, v] = [1, 1]; + while (i < m - 1 || j < n - 1) { + if (j === n - 1 || (i < m - 1 && horizontalCut[i] > verticalCut[j])) { + ans += horizontalCut[i] * v; + h++; + i++; + } else { + ans += verticalCut[j] * h; + v++; + j++; + } + } + return ans; +} diff --git a/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/images/ezgifcom-animated-gif-maker-1.gif b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/images/ezgifcom-animated-gif-maker-1.gif new file mode 100644 index 000000000000..6f53ef8b8f9f Binary files /dev/null and b/solution/3200-3299/3219.Minimum Cost for Cutting Cake II/images/ezgifcom-animated-gif-maker-1.gif differ diff --git a/solution/3200-3299/3220.Odd and Even Transactions/README.md b/solution/3200-3299/3220.Odd and Even Transactions/README.md new file mode 100644 index 000000000000..1c589de1e5f8 --- /dev/null +++ b/solution/3200-3299/3220.Odd and Even Transactions/README.md @@ -0,0 +1,157 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README.md +tags: + - 数据库 +--- + + + +# [3220. 奇数和偶数交易](https://leetcode.cn/problems/odd-and-even-transactions) + +[English Version](/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README_EN.md) + +## 题目描述 + + + +

            表:transactions

            + +
            ++------------------+------+
            +| Column Name      | Type | 
            ++------------------+------+
            +| transaction_id   | int  |
            +| amount           | int  |
            +| transaction_date | date |
            ++------------------+------+
            +transactions_id 列唯一标识了表中的每一行。
            +这张表的每一行包含交易 id,金额总和和交易日期。
            +
            + +

            编写一个解决方案来查找每天 奇数 交易金额和 偶数 交易金额的 总和。如果某天没有奇数或偶数交易,显示为 0

            + +

            返回结果表以 transaction_date 升序 排序。

            + +

            结果格式如下所示。

            + +

             

            + +

            示例:

            + +
            +

            输入:

            + +

            transactions 表:

            + +
            ++----------------+--------+------------------+
            +| transaction_id | amount | transaction_date |
            ++----------------+--------+------------------+
            +| 1              | 150    | 2024-07-01       |
            +| 2              | 200    | 2024-07-01       |
            +| 3              | 75     | 2024-07-01       |
            +| 4              | 300    | 2024-07-02       |
            +| 5              | 50     | 2024-07-02       |
            +| 6              | 120    | 2024-07-03       |
            ++----------------+--------+------------------+
            +  
            + +

            输出:

            + +
            ++------------------+---------+----------+
            +| transaction_date | odd_sum | even_sum |
            ++------------------+---------+----------+
            +| 2024-07-01       | 75      | 350      |
            +| 2024-07-02       | 0       | 350      |
            +| 2024-07-03       | 0       | 120      |
            ++------------------+---------+----------+
            +  
            + +

            解释:

            + +
              +
            • 对于交易日期: +
                +
              • 2024-07-01: +
                  +
                • 奇数交易金额总和:75
                • +
                • 偶数交易金额总和:150 + 200 = 350
                • +
                +
              • +
              • 2024-07-02: +
                  +
                • 奇数交易金额总和:0
                • +
                • 偶数交易金额总和:300 + 50 = 350
                • +
                +
              • +
              • 2024-07-03: +
                  +
                • 奇数交易金额总和:0
                • +
                • 偶数交易金额总和:120
                • +
                +
              • +
              +
            • +
            + +

            注意:输出表以 transaction_date 升序排序。

            +
            + + + +## 解法 + + + +### 方法一:分组求和 + +我们可以将数据按照 `transaction_date` 进行分组,然后分别计算奇数和偶数的交易金额之和。最后按照 `transaction_date` 升序排序。 + + + +#### MySQL + +```sql +# Write your MySQL query statement below +SELECT + transaction_date, + SUM(IF(amount % 2 = 1, amount, 0)) AS odd_sum, + SUM(IF(amount % 2 = 0, amount, 0)) AS even_sum +FROM transactions +GROUP BY 1 +ORDER BY 1; +``` + +#### Pandas + +```python +import pandas as pd + + +def sum_daily_odd_even(transactions: pd.DataFrame) -> pd.DataFrame: + transactions["odd_sum"] = transactions["amount"].where( + transactions["amount"] % 2 == 1, 0 + ) + transactions["even_sum"] = transactions["amount"].where( + transactions["amount"] % 2 == 0, 0 + ) + + result = ( + transactions.groupby("transaction_date") + .agg(odd_sum=("odd_sum", "sum"), even_sum=("even_sum", "sum")) + .reset_index() + ) + + result = result.sort_values("transaction_date") + + return result +``` + + + + + + diff --git a/solution/3200-3299/3220.Odd and Even Transactions/README_EN.md b/solution/3200-3299/3220.Odd and Even Transactions/README_EN.md new file mode 100644 index 000000000000..6df1b8b12509 --- /dev/null +++ b/solution/3200-3299/3220.Odd and Even Transactions/README_EN.md @@ -0,0 +1,156 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README_EN.md +tags: + - Database +--- + + + +# [3220. Odd and Even Transactions](https://leetcode.com/problems/odd-and-even-transactions) + +[中文文档](/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README.md) + +## Description + + + +

            Table: transactions

            + +
            ++------------------+------+
            +| Column Name      | Type | 
            ++------------------+------+
            +| transaction_id   | int  |
            +| amount           | int  |
            +| transaction_date | date |
            ++------------------+------+
            +The transactions_id column uniquely identifies each row in this table.
            +Each row of this table contains the transaction id, amount and transaction date.
            +
            + +

            Write a solution to find the sum of amounts for odd and even transactions for each day. If there are no odd or even transactions for a specific date, display as 0.

            + +

            Return the result table ordered by transaction_date in ascending order.

            + +

            The result format is in the following example.

            + +

             

            +

            Example:

            + +
            +

            Input:

            + +

            transactions table:

            + +
            ++----------------+--------+------------------+
            +| transaction_id | amount | transaction_date |
            ++----------------+--------+------------------+
            +| 1              | 150    | 2024-07-01       |
            +| 2              | 200    | 2024-07-01       |
            +| 3              | 75     | 2024-07-01       |
            +| 4              | 300    | 2024-07-02       |
            +| 5              | 50     | 2024-07-02       |
            +| 6              | 120    | 2024-07-03       |
            ++----------------+--------+------------------+
            +  
            + +

            Output:

            + +
            ++------------------+---------+----------+
            +| transaction_date | odd_sum | even_sum |
            ++------------------+---------+----------+
            +| 2024-07-01       | 75      | 350      |
            +| 2024-07-02       | 0       | 350      |
            +| 2024-07-03       | 0       | 120      |
            ++------------------+---------+----------+
            +  
            + +

            Explanation:

            + +
              +
            • For transaction dates: +
                +
              • 2024-07-01: +
                  +
                • Sum of amounts for odd transactions: 75
                • +
                • Sum of amounts for even transactions: 150 + 200 = 350
                • +
                +
              • +
              • 2024-07-02: +
                  +
                • Sum of amounts for odd transactions: 0
                • +
                • Sum of amounts for even transactions: 300 + 50 = 350
                • +
                +
              • +
              • 2024-07-03: +
                  +
                • Sum of amounts for odd transactions: 0
                • +
                • Sum of amounts for even transactions: 120
                • +
                +
              • +
              +
            • +
            + +

            Note: The output table is ordered by transaction_date in ascending order.

            +
            + + + +## Solutions + + + +### Solution 1: Grouping and Summing + +We can group the data by `transaction_date`, and then calculate the sum of transaction amounts for odd and even dates separately. Finally, sort by `transaction_date` in ascending order. + + + +#### MySQL + +```sql +# Write your MySQL query statement below +SELECT + transaction_date, + SUM(IF(amount % 2 = 1, amount, 0)) AS odd_sum, + SUM(IF(amount % 2 = 0, amount, 0)) AS even_sum +FROM transactions +GROUP BY 1 +ORDER BY 1; +``` + +#### Pandas + +```python +import pandas as pd + + +def sum_daily_odd_even(transactions: pd.DataFrame) -> pd.DataFrame: + transactions["odd_sum"] = transactions["amount"].where( + transactions["amount"] % 2 == 1, 0 + ) + transactions["even_sum"] = transactions["amount"].where( + transactions["amount"] % 2 == 0, 0 + ) + + result = ( + transactions.groupby("transaction_date") + .agg(odd_sum=("odd_sum", "sum"), even_sum=("even_sum", "sum")) + .reset_index() + ) + + result = result.sort_values("transaction_date") + + return result +``` + + + + + + diff --git a/solution/3200-3299/3220.Odd and Even Transactions/Solution.py b/solution/3200-3299/3220.Odd and Even Transactions/Solution.py new file mode 100644 index 000000000000..1b9e097b06ce --- /dev/null +++ b/solution/3200-3299/3220.Odd and Even Transactions/Solution.py @@ -0,0 +1,20 @@ +import pandas as pd + + +def sum_daily_odd_even(transactions: pd.DataFrame) -> pd.DataFrame: + transactions["odd_sum"] = transactions["amount"].where( + transactions["amount"] % 2 == 1, 0 + ) + transactions["even_sum"] = transactions["amount"].where( + transactions["amount"] % 2 == 0, 0 + ) + + result = ( + transactions.groupby("transaction_date") + .agg(odd_sum=("odd_sum", "sum"), even_sum=("even_sum", "sum")) + .reset_index() + ) + + result = result.sort_values("transaction_date") + + return result diff --git a/solution/3200-3299/3220.Odd and Even Transactions/Solution.sql b/solution/3200-3299/3220.Odd and Even Transactions/Solution.sql new file mode 100644 index 000000000000..9d454f9b3c34 --- /dev/null +++ b/solution/3200-3299/3220.Odd and Even Transactions/Solution.sql @@ -0,0 +1,8 @@ +# Write your MySQL query statement below +SELECT + transaction_date, + SUM(IF(amount % 2 = 1, amount, 0)) AS odd_sum, + SUM(IF(amount % 2 = 0, amount, 0)) AS even_sum +FROM transactions +GROUP BY 1 +ORDER BY 1; diff --git a/solution/3200-3299/3221.Maximum Array Hopping Score II/README.md b/solution/3200-3299/3221.Maximum Array Hopping Score II/README.md new file mode 100644 index 000000000000..d56e71f12be2 --- /dev/null +++ b/solution/3200-3299/3221.Maximum Array Hopping Score II/README.md @@ -0,0 +1,192 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3221.Maximum%20Array%20Hopping%20Score%20II/README.md +tags: + - 栈 + - 贪心 + - 数组 + - 单调栈 +--- + + + +# [3221. 最大数组跳跃得分 II 🔒](https://leetcode.cn/problems/maximum-array-hopping-score-ii) + +[English Version](/solution/3200-3299/3221.Maximum%20Array%20Hopping%20Score%20II/README_EN.md) + +## 题目描述 + + + +

            给定一个数组 nums,你必须从索引 0 开始跳跃,直到到达数组的最后一个元素,使得获取 最大 分数。

            + +

            每一次 跳跃 中,你可以从下标 i 跳到一个 j > i 的下标,并且可以得到 (j - i) * nums[j] 的分数。

            + +

            返回你能够取得的最大分数。

            + +

             

            + +

            示例 1:

            + +

            输入:nums = [1,5,8]

            + +

            输出:16

            + +

            解释:

            + +

            有两种可能的方法可以到达最后一个元素:

            + +
              +
            • 0 -> 1 -> 2 得分为 (1 - 0) * 5 + (2 - 1) * 8 = 13
            • +
            • 0 -> 2 得分为 (2 - 0) * 8 = 16
            • +
            + +

            示例 2:

            + +

            输入:nums = [4,5,2,8,9,1,3]

            + +

            输出:42

            + +

            解释:

            + +

            我们可以按 0 -> 4 -> 6 进行跳跃,得分为 (4 - 0) * 9 + (6 - 4) * 3 = 42

            + +

             

            + +

            提示:

            + +
              +
            • 2 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 105
            • +
            + + + +## 解法 + + + +### 方法一:单调栈 + +我们观察发现,对于当前位置 $i$,我们应该跳到下一个值最大的位置 $j$,这样才能获得最大的分数。 + +因此,我们遍历数组 $\textit{nums}$,维护一个从栈底到栈顶单调递减的栈 $\textit{stk}$。对于当前遍历到的位置 $i$,如果栈顶元素对应的值小于等于 $\textit{nums}[i]$,我们就不断地弹出栈顶元素,直到栈为空或者栈顶元素对应的值大于 $\textit{nums}[i]$,然后将 $i$ 入栈。 + +然后,我们初始化答案 $\textit{ans}$ 和当前位置 $i = 0$,遍历栈中的元素,每次取出栈顶元素 $j$,更新答案 $\textit{ans} += \textit{nums}[j] \times (j - i)$,然后更新 $i = j$。 + +最后返回答案 $\textit{ans}$。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。 + + + +#### Python3 + +```python +class Solution: + def maxScore(self, nums: List[int]) -> int: + stk = [] + for i, x in enumerate(nums): + while stk and nums[stk[-1]] <= x: + stk.pop() + stk.append(i) + ans = i = 0 + for j in stk: + ans += nums[j] * (j - i) + i = j + return ans +``` + +#### Java + +```java +class Solution { + public long maxScore(int[] nums) { + Deque stk = new ArrayDeque<>(); + for (int i = 0; i < nums.length; ++i) { + while (!stk.isEmpty() && nums[stk.peek()] <= nums[i]) { + stk.pop(); + } + stk.push(i); + } + long ans = 0, i = 0; + while (!stk.isEmpty()) { + int j = stk.pollLast(); + ans += (j - i) * nums[j]; + i = j; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long maxScore(vector& nums) { + vector stk; + for (int i = 0; i < nums.size(); ++i) { + while (stk.size() && nums[stk.back()] <= nums[i]) { + stk.pop_back(); + } + stk.push_back(i); + } + long long ans = 0, i = 0; + for (int j : stk) { + ans += (j - i) * nums[j]; + i = j; + } + return ans; + } +}; +``` + +#### Go + +```go +func maxScore(nums []int) (ans int64) { + stk := []int{} + for i, x := range nums { + for len(stk) > 0 && nums[stk[len(stk)-1]] <= x { + stk = stk[:len(stk)-1] + } + stk = append(stk, i) + } + i := 0 + for _, j := range stk { + ans += int64((j - i) * nums[j]) + i = j + } + return +} +``` + +#### TypeScript + +```ts +function maxScore(nums: number[]): number { + const stk: number[] = []; + for (let i = 0; i < nums.length; ++i) { + while (stk.length && nums[stk.at(-1)!] <= nums[i]) { + stk.pop(); + } + stk.push(i); + } + let ans = 0; + let i = 0; + for (const j of stk) { + ans += (j - i) * nums[j]; + i = j; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3221.Maximum Array Hopping Score II/README_EN.md b/solution/3200-3299/3221.Maximum Array Hopping Score II/README_EN.md new file mode 100644 index 000000000000..6fa27a469649 --- /dev/null +++ b/solution/3200-3299/3221.Maximum Array Hopping Score II/README_EN.md @@ -0,0 +1,190 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3221.Maximum%20Array%20Hopping%20Score%20II/README_EN.md +tags: + - Stack + - Greedy + - Array + - Monotonic Stack +--- + + + +# [3221. Maximum Array Hopping Score II 🔒](https://leetcode.com/problems/maximum-array-hopping-score-ii) + +[中文文档](/solution/3200-3299/3221.Maximum%20Array%20Hopping%20Score%20II/README.md) + +## Description + + + +

            Given an array nums, you have to get the maximum score starting from index 0 and hopping until you reach the last element of the array.

            + +

            In each hop, you can jump from index i to an index j > i, and you get a score of (j - i) * nums[j].

            + +

            Return the maximum score you can get.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [1,5,8]

            + +

            Output: 16

            + +

            Explanation:

            + +

            There are two possible ways to reach the last element:

            + +
              +
            • 0 -> 1 -> 2 with a score of (1 - 0) * 5 + (2 - 1) * 8 = 13.
            • +
            • 0 -> 2 with a score of (2 - 0) * 8 = 16.
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: nums = [4,5,2,8,9,1,3]

            + +

            Output: 42

            + +

            Explanation:

            + +

            We can do the hopping 0 -> 4 -> 6 with a score of (4 - 0) * 9 + (6 - 4) * 3 = 42.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 2 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 105
            • +
            + + + +## Solutions + + + +### Solution 1: Monotonic Stack + +We observe that for the current position $i$, we should jump to the next position $j$ with the maximum value to obtain the maximum score. + +Therefore, we traverse the array $\textit{nums}$, maintaining a stack $\textit{stk}$ that is monotonically decreasing from the bottom to the top of the stack. For the current position $i$ being traversed, if the value corresponding to the top element of the stack is less than or equal to $\textit{nums}[i]$, we continuously pop the top element of the stack until the stack is empty or the value corresponding to the top element of the stack is greater than $\textit{nums}[i]$, and then push $i$ into the stack. + +Next, we initialize the answer $\textit{ans}$ and the current position $i = 0$, traverse the elements in the stack, each time taking out the top element $j$, updating the answer $\textit{ans} += \textit{nums}[j] \times (j - i)$, and then updating $i = j$. + + + +#### Python3 + +```python +class Solution: + def maxScore(self, nums: List[int]) -> int: + stk = [] + for i, x in enumerate(nums): + while stk and nums[stk[-1]] <= x: + stk.pop() + stk.append(i) + ans = i = 0 + for j in stk: + ans += nums[j] * (j - i) + i = j + return ans +``` + +#### Java + +```java +class Solution { + public long maxScore(int[] nums) { + Deque stk = new ArrayDeque<>(); + for (int i = 0; i < nums.length; ++i) { + while (!stk.isEmpty() && nums[stk.peek()] <= nums[i]) { + stk.pop(); + } + stk.push(i); + } + long ans = 0, i = 0; + while (!stk.isEmpty()) { + int j = stk.pollLast(); + ans += (j - i) * nums[j]; + i = j; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long maxScore(vector& nums) { + vector stk; + for (int i = 0; i < nums.size(); ++i) { + while (stk.size() && nums[stk.back()] <= nums[i]) { + stk.pop_back(); + } + stk.push_back(i); + } + long long ans = 0, i = 0; + for (int j : stk) { + ans += (j - i) * nums[j]; + i = j; + } + return ans; + } +}; +``` + +#### Go + +```go +func maxScore(nums []int) (ans int64) { + stk := []int{} + for i, x := range nums { + for len(stk) > 0 && nums[stk[len(stk)-1]] <= x { + stk = stk[:len(stk)-1] + } + stk = append(stk, i) + } + i := 0 + for _, j := range stk { + ans += int64((j - i) * nums[j]) + i = j + } + return +} +``` + +#### TypeScript + +```ts +function maxScore(nums: number[]): number { + const stk: number[] = []; + for (let i = 0; i < nums.length; ++i) { + while (stk.length && nums[stk.at(-1)!] <= nums[i]) { + stk.pop(); + } + stk.push(i); + } + let ans = 0; + let i = 0; + for (const j of stk) { + ans += (j - i) * nums[j]; + i = j; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.cpp b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.cpp new file mode 100644 index 000000000000..7365af25c1e7 --- /dev/null +++ b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.cpp @@ -0,0 +1,18 @@ +class Solution { +public: + long long maxScore(vector& nums) { + vector stk; + for (int i = 0; i < nums.size(); ++i) { + while (stk.size() && nums[stk.back()] <= nums[i]) { + stk.pop_back(); + } + stk.push_back(i); + } + long long ans = 0, i = 0; + for (int j : stk) { + ans += (j - i) * nums[j]; + i = j; + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.go b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.go new file mode 100644 index 000000000000..34ecd330347d --- /dev/null +++ b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.go @@ -0,0 +1,15 @@ +func maxScore(nums []int) (ans int64) { + stk := []int{} + for i, x := range nums { + for len(stk) > 0 && nums[stk[len(stk)-1]] <= x { + stk = stk[:len(stk)-1] + } + stk = append(stk, i) + } + i := 0 + for _, j := range stk { + ans += int64((j - i) * nums[j]) + i = j + } + return +} \ No newline at end of file diff --git a/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.java b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.java new file mode 100644 index 000000000000..a862b3028d4f --- /dev/null +++ b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.java @@ -0,0 +1,18 @@ +class Solution { + public long maxScore(int[] nums) { + Deque stk = new ArrayDeque<>(); + for (int i = 0; i < nums.length; ++i) { + while (!stk.isEmpty() && nums[stk.peek()] <= nums[i]) { + stk.pop(); + } + stk.push(i); + } + long ans = 0, i = 0; + while (!stk.isEmpty()) { + int j = stk.pollLast(); + ans += (j - i) * nums[j]; + i = j; + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.py b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.py new file mode 100644 index 000000000000..02a773ddd21f --- /dev/null +++ b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.py @@ -0,0 +1,12 @@ +class Solution: + def maxScore(self, nums: List[int]) -> int: + stk = [] + for i, x in enumerate(nums): + while stk and nums[stk[-1]] <= x: + stk.pop() + stk.append(i) + ans = i = 0 + for j in stk: + ans += nums[j] * (j - i) + i = j + return ans diff --git a/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.ts b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.ts new file mode 100644 index 000000000000..a5411d1b49c0 --- /dev/null +++ b/solution/3200-3299/3221.Maximum Array Hopping Score II/Solution.ts @@ -0,0 +1,16 @@ +function maxScore(nums: number[]): number { + const stk: number[] = []; + for (let i = 0; i < nums.length; ++i) { + while (stk.length && nums[stk.at(-1)!] <= nums[i]) { + stk.pop(); + } + stk.push(i); + } + let ans = 0; + let i = 0; + for (const j of stk) { + ans += (j - i) * nums[j]; + i = j; + } + return ans; +} diff --git a/solution/3200-3299/3222.Find the Winning Player in Coin Game/README.md b/solution/3200-3299/3222.Find the Winning Player in Coin Game/README.md new file mode 100644 index 000000000000..7677d66714fe --- /dev/null +++ b/solution/3200-3299/3222.Find the Winning Player in Coin Game/README.md @@ -0,0 +1,153 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README.md +tags: + - 数学 + - 博弈 + - 模拟 +--- + + + +# [3222. 求出硬币游戏的赢家](https://leetcode.cn/problems/find-the-winning-player-in-coin-game) + +[English Version](/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README_EN.md) + +## 题目描述 + + + +

            给你两个  整数 x 和 y ,分别表示价值为 75 和 10 的硬币的数目。

            + +

            Alice 和 Bob 正在玩一个游戏。每一轮中,Alice 先进行操作,Bob 后操作。每次操作中,玩家需要拿出价值 总和 为 115 的硬币。如果一名玩家无法执行此操作,那么这名玩家 输掉 游戏。

            + +

            两名玩家都采取 最优 策略,请你返回游戏的赢家。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:x = 2, y = 7

            + +

            输出:"Alice"

            + +

            解释:

            + +

            游戏一次操作后结束:

            + +
              +
            • Alice 拿走 1 枚价值为 75 的硬币和 4 枚价值为 10 的硬币。
            • +
            +
            + +

            示例 2:

            + +
            +

            输入:x = 4, y = 11

            + +

            输出:"Bob"

            + +

            解释:

            + +

            游戏 2 次操作后结束:

            + +
              +
            • Alice 拿走 1 枚价值为 75 的硬币和 4 枚价值为 10 的硬币。
            • +
            • Bob 拿走 1 枚价值为 75 的硬币和 4 枚价值为 10 的硬币。
            • +
            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= x, y <= 100
            • +
            + + + +## 解法 + + + +### 方法一:数学 + +由于每一轮的操作,会消耗 $2$ 枚价值为 $75$ 的硬币和 $8$ 枚价值为 $10$ 的硬币,因此,我们可以计算得到操作的轮数 $k = \min(x / 2, y / 8)$,然后更新 $x$ 和 $y$ 的值,此时 $x$ 和 $y$ 就是经过 $k$ 轮操作后剩余的硬币数目。 + +如果 $x > 0$ 且 $y \geq 4$,那么 Alice 还可以继续操作,此时 Bob 就输了,返回 "Alice";否则,返回 "Bob"。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def losingPlayer(self, x: int, y: int) -> str: + k = min(x // 2, y // 8) + x -= k * 2 + y -= k * 8 + return "Alice" if x and y >= 4 else "Bob" +``` + +#### Java + +```java +class Solution { + public String losingPlayer(int x, int y) { + int k = Math.min(x / 2, y / 8); + x -= k * 2; + y -= k * 8; + return x > 0 && y >= 4 ? "Alice" : "Bob"; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string losingPlayer(int x, int y) { + int k = min(x / 2, y / 8); + x -= k * 2; + y -= k * 8; + return x && y >= 4 ? "Alice" : "Bob"; + } +}; +``` + +#### Go + +```go +func losingPlayer(x int, y int) string { + k := min(x/2, y/8) + x -= 2 * k + y -= 8 * k + if x > 0 && y >= 4 { + return "Alice" + } + return "Bob" +} +``` + +#### TypeScript + +```ts +function losingPlayer(x: number, y: number): string { + const k = Math.min((x / 2) | 0, (y / 8) | 0); + x -= k * 2; + y -= k * 8; + return x && y >= 4 ? 'Alice' : 'Bob'; +} +``` + + + + + + diff --git a/solution/3200-3299/3222.Find the Winning Player in Coin Game/README_EN.md b/solution/3200-3299/3222.Find the Winning Player in Coin Game/README_EN.md new file mode 100644 index 000000000000..81e55b55eca3 --- /dev/null +++ b/solution/3200-3299/3222.Find the Winning Player in Coin Game/README_EN.md @@ -0,0 +1,151 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README_EN.md +tags: + - Math + - Game Theory + - Simulation +--- + + + +# [3222. Find the Winning Player in Coin Game](https://leetcode.com/problems/find-the-winning-player-in-coin-game) + +[中文文档](/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README.md) + +## Description + + + +

            You are given two positive integers x and y, denoting the number of coins with values 75 and 10 respectively.

            + +

            Alice and Bob are playing a game. Each turn, starting with Alice, the player must pick up coins with a total value 115. If the player is unable to do so, they lose the game.

            + +

            Return the name of the player who wins the game if both players play optimally.

            + +

             

            +

            Example 1:

            + +
            +

            Input: x = 2, y = 7

            + +

            Output: "Alice"

            + +

            Explanation:

            + +

            The game ends in a single turn:

            + +
              +
            • Alice picks 1 coin with a value of 75 and 4 coins with a value of 10.
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: x = 4, y = 11

            + +

            Output: "Bob"

            + +

            Explanation:

            + +

            The game ends in 2 turns:

            + +
              +
            • Alice picks 1 coin with a value of 75 and 4 coins with a value of 10.
            • +
            • Bob picks 1 coin with a value of 75 and 4 coins with a value of 10.
            • +
            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= x, y <= 100
            • +
            + + + +## Solutions + + + +### Solution 1: Mathematics + +Since each round of operation consumes $2$ coins valued at $75$ and $8$ coins valued at $10$, we can calculate the number of rounds $k = \min(x / 2, y / 8)$, and then update the values of $x$ and $y$, where $x$ and $y$ are the remaining number of coins after $k$ rounds of operations. + +If $x > 0$ and $y \geq 4$, then Alice can continue the operation, and Bob loses, return "Alice"; otherwise, return "Bob". + +The time complexity is $O(1)$, and the space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def losingPlayer(self, x: int, y: int) -> str: + k = min(x // 2, y // 8) + x -= k * 2 + y -= k * 8 + return "Alice" if x and y >= 4 else "Bob" +``` + +#### Java + +```java +class Solution { + public String losingPlayer(int x, int y) { + int k = Math.min(x / 2, y / 8); + x -= k * 2; + y -= k * 8; + return x > 0 && y >= 4 ? "Alice" : "Bob"; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + string losingPlayer(int x, int y) { + int k = min(x / 2, y / 8); + x -= k * 2; + y -= k * 8; + return x && y >= 4 ? "Alice" : "Bob"; + } +}; +``` + +#### Go + +```go +func losingPlayer(x int, y int) string { + k := min(x/2, y/8) + x -= 2 * k + y -= 8 * k + if x > 0 && y >= 4 { + return "Alice" + } + return "Bob" +} +``` + +#### TypeScript + +```ts +function losingPlayer(x: number, y: number): string { + const k = Math.min((x / 2) | 0, (y / 8) | 0); + x -= k * 2; + y -= k * 8; + return x && y >= 4 ? 'Alice' : 'Bob'; +} +``` + + + + + + diff --git a/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.cpp b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.cpp new file mode 100644 index 000000000000..51bcd56b2c6c --- /dev/null +++ b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.cpp @@ -0,0 +1,9 @@ +class Solution { +public: + string losingPlayer(int x, int y) { + int k = min(x / 2, y / 8); + x -= k * 2; + y -= k * 8; + return x && y >= 4 ? "Alice" : "Bob"; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.go b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.go new file mode 100644 index 000000000000..6672207651cc --- /dev/null +++ b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.go @@ -0,0 +1,9 @@ +func losingPlayer(x int, y int) string { + k := min(x/2, y/8) + x -= 2 * k + y -= 8 * k + if x > 0 && y >= 4 { + return "Alice" + } + return "Bob" +} \ No newline at end of file diff --git a/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.java b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.java new file mode 100644 index 000000000000..3001c3178b57 --- /dev/null +++ b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.java @@ -0,0 +1,8 @@ +class Solution { + public String losingPlayer(int x, int y) { + int k = Math.min(x / 2, y / 8); + x -= k * 2; + y -= k * 8; + return x > 0 && y >= 4 ? "Alice" : "Bob"; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.py b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.py new file mode 100644 index 000000000000..a64879da9545 --- /dev/null +++ b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.py @@ -0,0 +1,6 @@ +class Solution: + def losingPlayer(self, x: int, y: int) -> str: + k = min(x // 2, y // 8) + x -= k * 2 + y -= k * 8 + return "Alice" if x and y >= 4 else "Bob" diff --git a/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.ts b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.ts new file mode 100644 index 000000000000..54630287e66b --- /dev/null +++ b/solution/3200-3299/3222.Find the Winning Player in Coin Game/Solution.ts @@ -0,0 +1,6 @@ +function losingPlayer(x: number, y: number): string { + const k = Math.min((x / 2) | 0, (y / 8) | 0); + x -= k * 2; + y -= k * 8; + return x && y >= 4 ? 'Alice' : 'Bob'; +} diff --git a/solution/3200-3299/3223.Minimum Length of String After Operations/README.md b/solution/3200-3299/3223.Minimum Length of String After Operations/README.md new file mode 100644 index 000000000000..c2124a46f956 --- /dev/null +++ b/solution/3200-3299/3223.Minimum Length of String After Operations/README.md @@ -0,0 +1,176 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README.md +tags: + - 哈希表 + - 字符串 + - 计数 +--- + + + +# [3223. 操作后字符串的最短长度](https://leetcode.cn/problems/minimum-length-of-string-after-operations) + +[English Version](/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README_EN.md) + +## 题目描述 + + + +

            给你一个字符串 s 。

            + +

            你需要对 s 执行以下操作 任意 次:

            + +
              +
            • 选择一个下标 i ,满足 s[i] 左边和右边都 至少 有一个字符与它相同。
            • +
            • 删除 s[i] 左边 离它 最近 且相同的字符。
            • +
            • 删除 s[i] 右边 离它 最近 且相同的字符。
            • +
            + +

            请你返回执行完所有操作后, s 的 最短 长度。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:s = "abaacbcbb"

            + +

            输出:5

            + +

            解释:
            +我们执行以下操作:

            + +
              +
            • 选择下标 2 ,然后删除下标 0 和 3 处的字符,得到 s = "bacbcbb" 。
            • +
            • 选择下标 3 ,然后删除下标 0 和 5 处的字符,得到 s = "acbcb" 。
            • +
            +
            + +

            示例 2:

            + +
            +

            输入:s = "aa"

            + +

            输出:2

            + +

            解释:
            +无法对字符串进行任何操作,所以返回初始字符串的长度。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= s.length <= 2 * 105
            • +
            • s 只包含小写英文字母。
            • +
            + + + +## 解法 + + + +### 方法一:计数 + +我们可以统计字符串中每个字符出现的次数,然后遍历计数数组,如果字符出现的次数为奇数,则最后该字符剩余 $1$ 个,如果字符出现的次数为偶数,则最后该字符剩余 $2$ 个。我们可以将所有字符的剩余个数相加,即为最终字符串的长度。 + +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(|\Sigma|)$,其中 $|\Sigma|$ 为字符集的大小,本题中 $|\Sigma| = 26$。 + + + +#### Python3 + +```python +class Solution: + def minimumLength(self, s: str) -> int: + cnt = Counter(s) + return sum(1 if x & 1 else 2 for x in cnt.values()) +``` + +#### Java + +```java +class Solution { + public int minimumLength(String s) { + int[] cnt = new int[26]; + for (int i = 0; i < s.length(); ++i) { + ++cnt[s.charAt(i) - 'a']; + } + int ans = 0; + for (int x : cnt) { + if (x > 0) { + ans += x % 2 == 1 ? 1 : 2; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumLength(string s) { + int cnt[26]{}; + for (char& c : s) { + ++cnt[c - 'a']; + } + int ans = 0; + for (int x : cnt) { + if (x) { + ans += x % 2 ? 1 : 2; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func minimumLength(s string) (ans int) { + cnt := [26]int{} + for _, c := range s { + cnt[c-'a']++ + } + for _, x := range cnt { + if x > 0 { + if x&1 == 1 { + ans += 1 + } else { + ans += 2 + } + } + } + return +} +``` + +#### TypeScript + +```ts +function minimumLength(s: string): number { + const cnt = new Map(); + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) + 1); + } + let ans = 0; + for (const x of cnt.values()) { + ans += x & 1 ? 1 : 2; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3223.Minimum Length of String After Operations/README_EN.md b/solution/3200-3299/3223.Minimum Length of String After Operations/README_EN.md new file mode 100644 index 000000000000..39c068822b53 --- /dev/null +++ b/solution/3200-3299/3223.Minimum Length of String After Operations/README_EN.md @@ -0,0 +1,174 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README_EN.md +tags: + - Hash Table + - String + - Counting +--- + + + +# [3223. Minimum Length of String After Operations](https://leetcode.com/problems/minimum-length-of-string-after-operations) + +[中文文档](/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README.md) + +## Description + + + +

            You are given a string s.

            + +

            You can perform the following process on s any number of times:

            + +
              +
            • Choose an index i in the string such that there is at least one character to the left of index i that is equal to s[i], and at least one character to the right that is also equal to s[i].
            • +
            • Delete the closest character to the left of index i that is equal to s[i].
            • +
            • Delete the closest character to the right of index i that is equal to s[i].
            • +
            + +

            Return the minimum length of the final string s that you can achieve.

            + +

             

            +

            Example 1:

            + +
            +

            Input: s = "abaacbcbb"

            + +

            Output: 5

            + +

            Explanation:
            +We do the following operations:

            + +
              +
            • Choose index 2, then remove the characters at indices 0 and 3. The resulting string is s = "bacbcbb".
            • +
            • Choose index 3, then remove the characters at indices 0 and 5. The resulting string is s = "acbcb".
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: s = "aa"

            + +

            Output: 2

            + +

            Explanation:
            +We cannot perform any operations, so we return the length of the original string.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= s.length <= 2 * 105
            • +
            • s consists only of lowercase English letters.
            • +
            + + + +## Solutions + + + +### Solution 1: Counting + +We can count the occurrences of each character in the string, and then iterate through the count array. If a character appears an odd number of times, then $1$ of that character remains in the end; if a character appears an even number of times, then $2$ of that character remain. We can sum the remaining counts of all characters to get the final length of the string. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(|\Sigma|)$, where $|\Sigma|$ is the size of the character set, which is $26$ in this problem. + + + +#### Python3 + +```python +class Solution: + def minimumLength(self, s: str) -> int: + cnt = Counter(s) + return sum(1 if x & 1 else 2 for x in cnt.values()) +``` + +#### Java + +```java +class Solution { + public int minimumLength(String s) { + int[] cnt = new int[26]; + for (int i = 0; i < s.length(); ++i) { + ++cnt[s.charAt(i) - 'a']; + } + int ans = 0; + for (int x : cnt) { + if (x > 0) { + ans += x % 2 == 1 ? 1 : 2; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minimumLength(string s) { + int cnt[26]{}; + for (char& c : s) { + ++cnt[c - 'a']; + } + int ans = 0; + for (int x : cnt) { + if (x) { + ans += x % 2 ? 1 : 2; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func minimumLength(s string) (ans int) { + cnt := [26]int{} + for _, c := range s { + cnt[c-'a']++ + } + for _, x := range cnt { + if x > 0 { + if x&1 == 1 { + ans += 1 + } else { + ans += 2 + } + } + } + return +} +``` + +#### TypeScript + +```ts +function minimumLength(s: string): number { + const cnt = new Map(); + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) + 1); + } + let ans = 0; + for (const x of cnt.values()) { + ans += x & 1 ? 1 : 2; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.cpp b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.cpp new file mode 100644 index 000000000000..45705e80f0a1 --- /dev/null +++ b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.cpp @@ -0,0 +1,16 @@ +class Solution { +public: + int minimumLength(string s) { + int cnt[26]{}; + for (char& c : s) { + ++cnt[c - 'a']; + } + int ans = 0; + for (int x : cnt) { + if (x) { + ans += x % 2 ? 1 : 2; + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.go b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.go new file mode 100644 index 000000000000..d3086856e20a --- /dev/null +++ b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.go @@ -0,0 +1,16 @@ +func minimumLength(s string) (ans int) { + cnt := [26]int{} + for _, c := range s { + cnt[c-'a']++ + } + for _, x := range cnt { + if x > 0 { + if x&1 == 1 { + ans += 1 + } else { + ans += 2 + } + } + } + return +} \ No newline at end of file diff --git a/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.java b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.java new file mode 100644 index 000000000000..9ca52c160546 --- /dev/null +++ b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.java @@ -0,0 +1,15 @@ +class Solution { + public int minimumLength(String s) { + int[] cnt = new int[26]; + for (int i = 0; i < s.length(); ++i) { + ++cnt[s.charAt(i) - 'a']; + } + int ans = 0; + for (int x : cnt) { + if (x > 0) { + ans += x % 2 == 1 ? 1 : 2; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.py b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.py new file mode 100644 index 000000000000..775fea34f1a4 --- /dev/null +++ b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.py @@ -0,0 +1,4 @@ +class Solution: + def minimumLength(self, s: str) -> int: + cnt = Counter(s) + return sum(1 if x & 1 else 2 for x in cnt.values()) diff --git a/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.ts b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.ts new file mode 100644 index 000000000000..3765ed123c2d --- /dev/null +++ b/solution/3200-3299/3223.Minimum Length of String After Operations/Solution.ts @@ -0,0 +1,11 @@ +function minimumLength(s: string): number { + const cnt = new Map(); + for (const c of s) { + cnt.set(c, (cnt.get(c) || 0) + 1); + } + let ans = 0; + for (const x of cnt.values()) { + ans += x & 1 ? 1 : 2; + } + return ans; +} diff --git a/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/README.md b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/README.md new file mode 100644 index 000000000000..82cb851a642a --- /dev/null +++ b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/README.md @@ -0,0 +1,245 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README.md +tags: + - 数组 + - 哈希表 + - 前缀和 +--- + + + +# [3224. 使差值相等的最少数组改动次数](https://leetcode.cn/problems/minimum-array-changes-to-make-differences-equal) + +[English Version](/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README_EN.md) + +## 题目描述 + + + +

            给你一个长度为 n 的整数数组 nums ,n 是 偶数 ,同时给你一个整数 k 。

            + +

            你可以对数组进行一些操作。每次操作中,你可以将数组中 任一 元素替换为 0 到 k 之间的 任一 整数。

            + +

            执行完所有操作以后,你需要确保最后得到的数组满足以下条件:

            + +
              +
            • 存在一个整数 X ,满足对于所有的 (0 <= i < n) 都有 abs(a[i] - a[n - i - 1]) = X 。
            • +
            + +

            请你返回满足以上条件 最少 修改次数。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [1,0,1,2,4,3], k = 4

            + +

            输出:2

            + +

            解释:
            +我们可以执行以下操作:

            + +
              +
            • 将 nums[1] 变为 2 ,结果数组为 nums = [1,2,1,2,4,3] 。
            • +
            • 将 nums[3] 变为 3 ,结果数组为 nums = [1,2,1,3,4,3] 。
            • +
            + +

            整数 X 为 2 。

            +
            + +

            示例 2:

            + +
            +

            输入:nums = [0,1,2,3,3,6,5,4], k = 6

            + +

            输出:2

            + +

            解释:
            +我们可以执行以下操作:

            + +
              +
            • 将 nums[3] 变为 0 ,结果数组为 nums = [0,1,2,0,3,6,5,4] 。
            • +
            • 将 nums[4] 变为 4 ,结果数组为 nums = [0,1,2,0,4,6,5,4] 。
            • +
            + +

            整数 X 为 4 。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 2 <= n == nums.length <= 105
            • +
            • n 是偶数。
            • +
            • 0 <= nums[i] <= k <= 105
            • +
            + + + +## 解法 + + + +### 方法一:差分数组 + +假设最终的数组中,数对 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的差值为 $s$。 + +我们不妨设 $x$ 为 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的较小值,设 $y$ 为 $\textit{nums}[i]$ 和 $\textit{nums}[n-i-1]$ 的较大值。 + +对于每一对数,我们有以下几种情况: + +- 如果不需要改动,那么 $y - x = s$。 +- 如果改动一次,那么 $s \le \max(y, k - x)$,最大值就是把 $x$ 变为 $0$,或者把 $y$ 变为 $k$。 +- 如果改动两次,那么 $s \gt \max(y, k - x)$。 + +即: + +- 在 $[0,y-x-1]$ 范围内,需要改动 $1$ 次。 +- 在 $[y-x]$ 时,不需要改动。 +- 在 $[y-x+1, \max(y, k-x)]$ 范围内,需要改动 $1$ 次。 +- 在 $[\max(y, k-x)+1, k]$ 范围内,需要改动 $2$ 次。 + +我们枚举每一个数对,利用差分数组,更新每个数对在不同区间范围内的改动次数。 + +最后,我们求出差分数组的前缀和中的最小值,即为最少的改动次数。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 + +相似题目: + +- [1674. 使数组互补的最少操作次数](https://github.com/doocs/leetcode/tree/main/solution/1600-1699/1674.Minimum%20Moves%20to%20Make%20Array%20Complementary/README.md) + + + +#### Python3 + +```python +class Solution: + def minChanges(self, nums: List[int], k: int) -> int: + d = [0] * (k + 2) + n = len(nums) + for i in range(n // 2): + x, y = nums[i], nums[-i - 1] + if x > y: + x, y = y, x + d[0] += 1 + d[y - x] -= 1 + d[y - x + 1] += 1 + d[max(y, k - x) + 1] -= 1 + d[max(y, k - x) + 1] += 2 + return min(accumulate(d)) +``` + +#### Java + +```java +class Solution { + public int minChanges(int[] nums, int k) { + int[] d = new int[k + 2]; + int n = nums.length; + for (int i = 0; i < n / 2; ++i) { + int x = Math.min(nums[i], nums[n - i - 1]); + int y = Math.max(nums[i], nums[n - i - 1]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[Math.max(y, k - x) + 1] -= 1; + d[Math.max(y, k - x) + 1] += 2; + } + int ans = n, s = 0; + for (int x : d) { + s += x; + ans = Math.min(ans, s); + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minChanges(vector& nums, int k) { + int d[k + 2]; + memset(d, 0, sizeof(d)); + int n = nums.size(); + for (int i = 0; i < n / 2; ++i) { + int x = min(nums[i], nums[n - i - 1]); + int y = max(nums[i], nums[n - i - 1]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[max(y, k - x) + 1] -= 1; + d[max(y, k - x) + 1] += 2; + } + int ans = n, s = 0; + for (int x : d) { + s += x; + ans = min(ans, s); + } + return ans; + } +}; +``` + +#### Go + +```go +func minChanges(nums []int, k int) int { + d := make([]int, k+2) + n := len(nums) + for i := 0; i < n/2; i++ { + x, y := nums[i], nums[n-1-i] + if x > y { + x, y = y, x + } + d[0] += 1 + d[y-x] -= 1 + d[y-x+1] += 1 + d[max(y, k-x)+1] -= 1 + d[max(y, k-x)+1] += 2 + } + ans, s := n, 0 + for _, x := range d { + s += x + ans = min(ans, s) + } + return ans +} +``` + +#### TypeScript + +```ts +function minChanges(nums: number[], k: number): number { + const d: number[] = Array(k + 2).fill(0); + const n = nums.length; + for (let i = 0; i < n >> 1; ++i) { + const x = Math.min(nums[i], nums[n - 1 - i]); + const y = Math.max(nums[i], nums[n - 1 - i]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[Math.max(y, k - x) + 1] -= 1; + d[Math.max(y, k - x) + 1] += 2; + } + let [ans, s] = [n, 0]; + for (const x of d) { + s += x; + ans = Math.min(ans, s); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/README_EN.md b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/README_EN.md new file mode 100644 index 000000000000..2b232818621b --- /dev/null +++ b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/README_EN.md @@ -0,0 +1,243 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README_EN.md +tags: + - Array + - Hash Table + - Prefix Sum +--- + + + +# [3224. Minimum Array Changes to Make Differences Equal](https://leetcode.com/problems/minimum-array-changes-to-make-differences-equal) + +[中文文档](/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README.md) + +## Description + + + +

            You are given an integer array nums of size n where n is even, and an integer k.

            + +

            You can perform some changes on the array, where in one change you can replace any element in the array with any integer in the range from 0 to k.

            + +

            You need to perform some changes (possibly none) such that the final array satisfies the following condition:

            + +
              +
            • There exists an integer X such that abs(a[i] - a[n - i - 1]) = X for all (0 <= i < n).
            • +
            + +

            Return the minimum number of changes required to satisfy the above condition.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [1,0,1,2,4,3], k = 4

            + +

            Output: 2

            + +

            Explanation:
            +We can perform the following changes:

            + +
              +
            • Replace nums[1] by 2. The resulting array is nums = [1,2,1,2,4,3].
            • +
            • Replace nums[3] by 3. The resulting array is nums = [1,2,1,3,4,3].
            • +
            + +

            The integer X will be 2.

            +
            + +

            Example 2:

            + +
            +

            Input: nums = [0,1,2,3,3,6,5,4], k = 6

            + +

            Output: 2

            + +

            Explanation:
            +We can perform the following operations:

            + +
              +
            • Replace nums[3] by 0. The resulting array is nums = [0,1,2,0,3,6,5,4].
            • +
            • Replace nums[4] by 4. The resulting array is nums = [0,1,2,0,4,6,5,4].
            • +
            + +

            The integer X will be 4.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 2 <= n == nums.length <= 105
            • +
            • n is even.
            • +
            • 0 <= nums[i] <= k <= 105
            • +
            + + + +## Solutions + + + +### Solution 1: Difference Array + +Assume that in the final array, the difference between the pair $\textit{nums}[i]$ and $\textit{nums}[n-i-1]$ is $s$. + +Let's denote $x$ as the smaller value between $\textit{nums}[i]$ and $\textit{nums}[n-i-1]$, and $y$ as the larger value. + +For each pair of numbers, we have the following scenarios: + +- If no change is needed, then $y - x = s$. +- If one change is made, then $s \le \max(y, k - x)$, where the maximum value is achieved by changing $x$ to $0$, or changing $y$ to $k$. +- If two changes are made, then $s > \max(y, k - x)$. + +That is: + +- In the range $[0, y-x-1]$, $1$ change is needed. +- At $[y-x]$, no change is needed. +- In the range $[y-x+1, \max(y, k-x)]$, $1$ change is needed. +- In the range $[\max(y, k-x)+1, k]$, $2$ changes are needed. + +We enumerate each pair of numbers and use a difference array to update the number of changes needed in different ranges for each pair. + +Finally, we find the minimum value among the prefix sums from the difference array, which is the minimum number of changes needed. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. + +Similar problems: + +- [1674. Minimum Moves to Make Array Complementary](https://github.com/doocs/leetcode/tree/main/solution/1600-1699/1674.Minimum%20Moves%20to%20Make%20Array%20Complementary/README_EN.md) + + + +#### Python3 + +```python +class Solution: + def minChanges(self, nums: List[int], k: int) -> int: + d = [0] * (k + 2) + n = len(nums) + for i in range(n // 2): + x, y = nums[i], nums[-i - 1] + if x > y: + x, y = y, x + d[0] += 1 + d[y - x] -= 1 + d[y - x + 1] += 1 + d[max(y, k - x) + 1] -= 1 + d[max(y, k - x) + 1] += 2 + return min(accumulate(d)) +``` + +#### Java + +```java +class Solution { + public int minChanges(int[] nums, int k) { + int[] d = new int[k + 2]; + int n = nums.length; + for (int i = 0; i < n / 2; ++i) { + int x = Math.min(nums[i], nums[n - i - 1]); + int y = Math.max(nums[i], nums[n - i - 1]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[Math.max(y, k - x) + 1] -= 1; + d[Math.max(y, k - x) + 1] += 2; + } + int ans = n, s = 0; + for (int x : d) { + s += x; + ans = Math.min(ans, s); + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minChanges(vector& nums, int k) { + int d[k + 2]; + memset(d, 0, sizeof(d)); + int n = nums.size(); + for (int i = 0; i < n / 2; ++i) { + int x = min(nums[i], nums[n - i - 1]); + int y = max(nums[i], nums[n - i - 1]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[max(y, k - x) + 1] -= 1; + d[max(y, k - x) + 1] += 2; + } + int ans = n, s = 0; + for (int x : d) { + s += x; + ans = min(ans, s); + } + return ans; + } +}; +``` + +#### Go + +```go +func minChanges(nums []int, k int) int { + d := make([]int, k+2) + n := len(nums) + for i := 0; i < n/2; i++ { + x, y := nums[i], nums[n-1-i] + if x > y { + x, y = y, x + } + d[0] += 1 + d[y-x] -= 1 + d[y-x+1] += 1 + d[max(y, k-x)+1] -= 1 + d[max(y, k-x)+1] += 2 + } + ans, s := n, 0 + for _, x := range d { + s += x + ans = min(ans, s) + } + return ans +} +``` + +#### TypeScript + +```ts +function minChanges(nums: number[], k: number): number { + const d: number[] = Array(k + 2).fill(0); + const n = nums.length; + for (let i = 0; i < n >> 1; ++i) { + const x = Math.min(nums[i], nums[n - 1 - i]); + const y = Math.max(nums[i], nums[n - 1 - i]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[Math.max(y, k - x) + 1] -= 1; + d[Math.max(y, k - x) + 1] += 2; + } + let [ans, s] = [n, 0]; + for (const x of d) { + s += x; + ans = Math.min(ans, s); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.cpp b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.cpp new file mode 100644 index 000000000000..696bfb8b7de5 --- /dev/null +++ b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.cpp @@ -0,0 +1,23 @@ +class Solution { +public: + int minChanges(vector& nums, int k) { + int d[k + 2]; + memset(d, 0, sizeof(d)); + int n = nums.size(); + for (int i = 0; i < n / 2; ++i) { + int x = min(nums[i], nums[n - i - 1]); + int y = max(nums[i], nums[n - i - 1]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[max(y, k - x) + 1] -= 1; + d[max(y, k - x) + 1] += 2; + } + int ans = n, s = 0; + for (int x : d) { + s += x; + ans = min(ans, s); + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.go b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.go new file mode 100644 index 000000000000..957b8167e1e1 --- /dev/null +++ b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.go @@ -0,0 +1,21 @@ +func minChanges(nums []int, k int) int { + d := make([]int, k+2) + n := len(nums) + for i := 0; i < n/2; i++ { + x, y := nums[i], nums[n-1-i] + if x > y { + x, y = y, x + } + d[0] += 1 + d[y-x] -= 1 + d[y-x+1] += 1 + d[max(y, k-x)+1] -= 1 + d[max(y, k-x)+1] += 2 + } + ans, s := n, 0 + for _, x := range d { + s += x + ans = min(ans, s) + } + return ans +} \ No newline at end of file diff --git a/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.java b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.java new file mode 100644 index 000000000000..70e0610c73c2 --- /dev/null +++ b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.java @@ -0,0 +1,21 @@ +class Solution { + public int minChanges(int[] nums, int k) { + int[] d = new int[k + 2]; + int n = nums.length; + for (int i = 0; i < n / 2; ++i) { + int x = Math.min(nums[i], nums[n - i - 1]); + int y = Math.max(nums[i], nums[n - i - 1]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[Math.max(y, k - x) + 1] -= 1; + d[Math.max(y, k - x) + 1] += 2; + } + int ans = n, s = 0; + for (int x : d) { + s += x; + ans = Math.min(ans, s); + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.py b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.py new file mode 100644 index 000000000000..a310c37ee734 --- /dev/null +++ b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.py @@ -0,0 +1,14 @@ +class Solution: + def minChanges(self, nums: List[int], k: int) -> int: + d = [0] * (k + 2) + n = len(nums) + for i in range(n // 2): + x, y = nums[i], nums[-i - 1] + if x > y: + x, y = y, x + d[0] += 1 + d[y - x] -= 1 + d[y - x + 1] += 1 + d[max(y, k - x) + 1] -= 1 + d[max(y, k - x) + 1] += 2 + return min(accumulate(d)) diff --git a/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.ts b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.ts new file mode 100644 index 000000000000..2817d3baae1a --- /dev/null +++ b/solution/3200-3299/3224.Minimum Array Changes to Make Differences Equal/Solution.ts @@ -0,0 +1,19 @@ +function minChanges(nums: number[], k: number): number { + const d: number[] = Array(k + 2).fill(0); + const n = nums.length; + for (let i = 0; i < n >> 1; ++i) { + const x = Math.min(nums[i], nums[n - 1 - i]); + const y = Math.max(nums[i], nums[n - 1 - i]); + d[0] += 1; + d[y - x] -= 1; + d[y - x + 1] += 1; + d[Math.max(y, k - x) + 1] -= 1; + d[Math.max(y, k - x) + 1] += 2; + } + let [ans, s] = [n, 0]; + for (const x of d) { + s += x; + ans = Math.min(ans, s); + } + return ans; +} diff --git a/solution/3200-3299/3225.Maximum Score From Grid Operations/README.md b/solution/3200-3299/3225.Maximum Score From Grid Operations/README.md new file mode 100644 index 000000000000..cae9e276ea6a --- /dev/null +++ b/solution/3200-3299/3225.Maximum Score From Grid Operations/README.md @@ -0,0 +1,102 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README.md +tags: + - 数组 + - 动态规划 + - 矩阵 + - 前缀和 +--- + + + +# [3225. 网格图操作后的最大分数](https://leetcode.cn/problems/maximum-score-from-grid-operations) + +[English Version](/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README_EN.md) + +## 题目描述 + + + +

            给你一个大小为 n x n 的二维矩阵 grid ,一开始所有格子都是白色的。一次操作中,你可以选择任意下标为 (i, j) 的格子,并将第 j 列中从最上面到第 i 行所有格子改成黑色。

            + +

            如果格子 (i, j) 为白色,且左边或者右边的格子至少一个格子为黑色,那么我们将 grid[i][j] 加到最后网格图的总分中去。

            + +

            请你返回执行任意次操作以后,最终网格图的 最大 总分数。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:grid = [[0,0,0,0,0],[0,0,3,0,0],[0,1,0,0,0],[5,0,0,3,0],[0,0,0,0,2]]

            + +

            输出:11

            + +

            解释:

            + +

            第一次操作中,我们将第 1 列中,最上面的格子到第 3 行的格子染成黑色。第二次操作中,我们将第 4 列中,最上面的格子到最后一行的格子染成黑色。最后网格图总分为 grid[3][0] + grid[1][2] + grid[3][3] 等于 11 。

            +
            + +

            示例 2:

            + +
            +

            输入:grid = [[10,9,0,0,15],[7,1,0,8,0],[5,20,0,11,0],[0,0,0,1,2],[8,12,1,10,3]]

            + +

            输出:94

            + +

            解释:

            + +

            我们对第 1 ,2 ,3 列分别从上往下染黑色到第 1 ,4, 0 行。最后网格图总分为 grid[0][0] + grid[1][0] + grid[2][1] + grid[4][1] + grid[1][3] + grid[2][3] + grid[3][3] + grid[4][3] + grid[0][4] 等于 94 。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n == grid.length <= 100
            • +
            • n == grid[i].length
            • +
            • 0 <= grid[i][j] <= 109
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3225.Maximum Score From Grid Operations/README_EN.md b/solution/3200-3299/3225.Maximum Score From Grid Operations/README_EN.md new file mode 100644 index 000000000000..69a71198c1ab --- /dev/null +++ b/solution/3200-3299/3225.Maximum Score From Grid Operations/README_EN.md @@ -0,0 +1,100 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README_EN.md +tags: + - Array + - Dynamic Programming + - Matrix + - Prefix Sum +--- + + + +# [3225. Maximum Score From Grid Operations](https://leetcode.com/problems/maximum-score-from-grid-operations) + +[中文文档](/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README.md) + +## Description + + + +

            You are given a 2D matrix grid of size n x n. Initially, all cells of the grid are colored white. In one operation, you can select any cell of indices (i, j), and color black all the cells of the jth column starting from the top row down to the ith row.

            + +

            The grid score is the sum of all grid[i][j] such that cell (i, j) is white and it has a horizontally adjacent black cell.

            + +

            Return the maximum score that can be achieved after some number of operations.

            + +

             

            +

            Example 1:

            + +
            +

            Input: grid = [[0,0,0,0,0],[0,0,3,0,0],[0,1,0,0,0],[5,0,0,3,0],[0,0,0,0,2]]

            + +

            Output: 11

            + +

            Explanation:

            + +

            In the first operation, we color all cells in column 1 down to row 3, and in the second operation, we color all cells in column 4 down to the last row. The score of the resulting grid is grid[3][0] + grid[1][2] + grid[3][3] which is equal to 11.

            +
            + +

            Example 2:

            + +
            +

            Input: grid = [[10,9,0,0,15],[7,1,0,8,0],[5,20,0,11,0],[0,0,0,1,2],[8,12,1,10,3]]

            + +

            Output: 94

            + +

            Explanation:

            + +

            We perform operations on 1, 2, and 3 down to rows 1, 4, and 0, respectively. The score of the resulting grid is grid[0][0] + grid[1][0] + grid[2][1] + grid[4][1] + grid[1][3] + grid[2][3] + grid[3][3] + grid[4][3] + grid[0][4] which is equal to 94.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n == grid.length <= 100
            • +
            • n == grid[i].length
            • +
            • 0 <= grid[i][j] <= 109
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3225.Maximum Score From Grid Operations/images/one.png b/solution/3200-3299/3225.Maximum Score From Grid Operations/images/one.png new file mode 100644 index 000000000000..355126667c8d Binary files /dev/null and b/solution/3200-3299/3225.Maximum Score From Grid Operations/images/one.png differ diff --git a/solution/3200-3299/3225.Maximum Score From Grid Operations/images/rectangles.png b/solution/3200-3299/3225.Maximum Score From Grid Operations/images/rectangles.png new file mode 100644 index 000000000000..ceb0f1831ab6 Binary files /dev/null and b/solution/3200-3299/3225.Maximum Score From Grid Operations/images/rectangles.png differ diff --git a/solution/3200-3299/3225.Maximum Score From Grid Operations/images/two-1.png b/solution/3200-3299/3225.Maximum Score From Grid Operations/images/two-1.png new file mode 100644 index 000000000000..a324a27670de Binary files /dev/null and b/solution/3200-3299/3225.Maximum Score From Grid Operations/images/two-1.png differ diff --git a/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/README.md b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/README.md new file mode 100644 index 000000000000..68da25abe825 --- /dev/null +++ b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/README.md @@ -0,0 +1,145 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README.md +tags: + - 位运算 +--- + + + +# [3226. 使两个整数相等的位更改次数](https://leetcode.cn/problems/number-of-bit-changes-to-make-two-integers-equal) + +[English Version](/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README_EN.md) + +## 题目描述 + + + +

            给你两个正整数 nk

            + +

            你可以选择 n二进制表示 中任意一个值为 1 的位,并将其改为 0。

            + +

            返回使得 n 等于 k 所需要的更改次数。如果无法实现,返回 -1。

            + +

             

            + +

            示例 1:

            + +
            +

            输入: n = 13, k = 4

            + +

            输出: 2

            + +

            解释:
            +最初,nk 的二进制表示分别为 n = (1101)2k = (0100)2

            + +

            我们可以改变 n 的第一位和第四位。结果整数为 n = (0100)2 = k

            +
            + +

            示例 2:

            + +
            +

            输入: n = 21, k = 21

            + +

            输出: 0

            + +

            解释:
            +nk 已经相等,因此不需要更改。

            +
            + +

            示例 3:

            + +
            +

            输入: n = 14, k = 13

            + +

            输出: -1

            + +

            解释:
            +无法使 n 等于 k

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n, k <= 106
            • +
            + + + +## 解法 + + + +### 方法一:位运算 + +如果 $n$ 和 $k$ 的按位与结果不等于 $k$,说明 $k$ 存在某一位为 $1$,而 $n$ 对应的位为 $0$,此时无法通过改变 $n$ 的某一位使得 $n$ 等于 $k$,返回 $-1$;否则,我们统计 $n \oplus k$ 的二进制表示中 $1$ 的个数即可。 + +时间复杂度 $O(\log n)$,空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def minChanges(self, n: int, k: int) -> int: + return -1 if n & k != k else (n ^ k).bit_count() +``` + +#### Java + +```java +class Solution { + public int minChanges(int n, int k) { + return (n & k) != k ? -1 : Integer.bitCount(n ^ k); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minChanges(int n, int k) { + return (n & k) != k ? -1 : __builtin_popcount(n ^ k); + } +}; +``` + +#### Go + +```go +func minChanges(n int, k int) int { + if n&k != k { + return -1 + } + return bits.OnesCount(uint(n ^ k)) +} +``` + +#### TypeScript + +```ts +function minChanges(n: number, k: number): number { + return (n & k) !== k ? -1 : bitCount(n ^ k); +} + +function bitCount(i: number): number { + i = i - ((i >>> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); + i = (i + (i >>> 4)) & 0x0f0f0f0f; + i = i + (i >>> 8); + i = i + (i >>> 16); + return i & 0x3f; +} +``` + + + + + + diff --git a/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/README_EN.md b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/README_EN.md new file mode 100644 index 000000000000..bbf7790d9636 --- /dev/null +++ b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/README_EN.md @@ -0,0 +1,142 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README_EN.md +tags: + - Bit Manipulation +--- + + + +# [3226. Number of Bit Changes to Make Two Integers Equal](https://leetcode.com/problems/number-of-bit-changes-to-make-two-integers-equal) + +[中文文档](/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README.md) + +## Description + + + +

            You are given two positive integers n and k.

            + +

            You can choose any bit in the binary representation of n that is equal to 1 and change it to 0.

            + +

            Return the number of changes needed to make n equal to k. If it is impossible, return -1.

            + +

             

            +

            Example 1:

            + +
            +

            Input: n = 13, k = 4

            + +

            Output: 2

            + +

            Explanation:
            +Initially, the binary representations of n and k are n = (1101)2 and k = (0100)2.
            +We can change the first and fourth bits of n. The resulting integer is n = (0100)2 = k.

            +
            + +

            Example 2:

            + +
            +

            Input: n = 21, k = 21

            + +

            Output: 0

            + +

            Explanation:
            +n and k are already equal, so no changes are needed.

            +
            + +

            Example 3:

            + +
            +

            Input: n = 14, k = 13

            + +

            Output: -1

            + +

            Explanation:
            +It is not possible to make n equal to k.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n, k <= 106
            • +
            + + + +## Solutions + + + +### Solution 1: Bit Manipulation + +If the bitwise AND result of $n$ and $k$ is not equal to $k$, it indicates that there exists at least one bit where $k$ is $1$ and the corresponding bit in $n$ is $0$. In this case, it is impossible to modify a bit in $n$ to make $n$ equal to $k$, and we return $-1$. Otherwise, we count the number of $1$s in the binary representation of $n \oplus k$. + +The time complexity is $O(\log n)$, and the space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def minChanges(self, n: int, k: int) -> int: + return -1 if n & k != k else (n ^ k).bit_count() +``` + +#### Java + +```java +class Solution { + public int minChanges(int n, int k) { + return (n & k) != k ? -1 : Integer.bitCount(n ^ k); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minChanges(int n, int k) { + return (n & k) != k ? -1 : __builtin_popcount(n ^ k); + } +}; +``` + +#### Go + +```go +func minChanges(n int, k int) int { + if n&k != k { + return -1 + } + return bits.OnesCount(uint(n ^ k)) +} +``` + +#### TypeScript + +```ts +function minChanges(n: number, k: number): number { + return (n & k) !== k ? -1 : bitCount(n ^ k); +} + +function bitCount(i: number): number { + i = i - ((i >>> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); + i = (i + (i >>> 4)) & 0x0f0f0f0f; + i = i + (i >>> 8); + i = i + (i >>> 16); + return i & 0x3f; +} +``` + + + + + + diff --git a/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.cpp b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.cpp new file mode 100644 index 000000000000..9443e7b448da --- /dev/null +++ b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.cpp @@ -0,0 +1,6 @@ +class Solution { +public: + int minChanges(int n, int k) { + return (n & k) != k ? -1 : __builtin_popcount(n ^ k); + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.go b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.go new file mode 100644 index 000000000000..3415816b54b0 --- /dev/null +++ b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.go @@ -0,0 +1,6 @@ +func minChanges(n int, k int) int { + if n&k != k { + return -1 + } + return bits.OnesCount(uint(n ^ k)) +} \ No newline at end of file diff --git a/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.java b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.java new file mode 100644 index 000000000000..04157dcaf50a --- /dev/null +++ b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.java @@ -0,0 +1,5 @@ +class Solution { + public int minChanges(int n, int k) { + return (n & k) != k ? -1 : Integer.bitCount(n ^ k); + } +} \ No newline at end of file diff --git a/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.py b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.py new file mode 100644 index 000000000000..5c707555daea --- /dev/null +++ b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.py @@ -0,0 +1,3 @@ +class Solution: + def minChanges(self, n: int, k: int) -> int: + return -1 if n & k != k else (n ^ k).bit_count() diff --git a/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.ts b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.ts new file mode 100644 index 000000000000..3833d04359b5 --- /dev/null +++ b/solution/3200-3299/3226.Number of Bit Changes to Make Two Integers Equal/Solution.ts @@ -0,0 +1,12 @@ +function minChanges(n: number, k: number): number { + return (n & k) !== k ? -1 : bitCount(n ^ k); +} + +function bitCount(i: number): number { + i = i - ((i >>> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); + i = (i + (i >>> 4)) & 0x0f0f0f0f; + i = i + (i >>> 8); + i = i + (i >>> 16); + return i & 0x3f; +} diff --git a/solution/3200-3299/3227.Vowels Game in a String/README.md b/solution/3200-3299/3227.Vowels Game in a String/README.md new file mode 100644 index 000000000000..7e67af7f5dcd --- /dev/null +++ b/solution/3200-3299/3227.Vowels Game in a String/README.md @@ -0,0 +1,172 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README.md +tags: + - 脑筋急转弯 + - 数学 + - 字符串 + - 博弈 +--- + + + +# [3227. 字符串元音游戏](https://leetcode.cn/problems/vowels-game-in-a-string) + +[English Version](/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README_EN.md) + +## 题目描述 + + + +

            小红和小明在玩一个字符串元音游戏。

            + +

            给你一个字符串 s,小红和小明将轮流参与游戏,小红开始:

            + +
              +
            • 在小红的回合,她必须移除 s 中包含 奇数 个元音的任意 非空 子字符串
            • +
            • 在小明的回合,他必须移除 s 中包含 偶数 个元音的任意 非空 子字符串
            • +
            + +

            第一个无法在其回合内进行移除操作的玩家输掉游戏。假设小红和小明都采取 最优策略

            + +

            如果小红赢得游戏,返回 true,否则返回 false

            + +

            英文元音字母包括:a, e, i, o, 和 u

            + +

             

            + +

            示例 1:

            + +
            +

            输入: s = "leetcoder"

            + +

            输出: true

            + +

            解释:
            +小红可以执行如下移除操作来赢得游戏:

            + +
              +
            • 小红先手,她可以移除加下划线的子字符串 s = "leetcoder",其中包含 3 个元音。结果字符串为 s = "der"
            • +
            • 小明接着,他可以移除加下划线的子字符串 s = "der",其中包含 0 个元音。结果字符串为 s = "er"
            • +
            • 小红再次操作,她可以移除整个字符串 s = "er",其中包含 1 个元音。
            • +
            • 又轮到小明,由于字符串为空,无法执行移除操作,因此小红赢得游戏。
            • +
            +
            + +

            示例 2:

            + +
            +

            输入: s = "bbcd"

            + +

            输出: false

            + +

            解释:
            +小红在她的第一回合无法执行移除操作,因此小红输掉了游戏。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= s.length <= 105
            • +
            • s 仅由小写英文字母组成。
            • +
            + + + +## 解法 + + + +### 方法一:脑筋急转弯 + +我们不妨记字符串中元音字母的个数为 $k$。 + +如果 $k = 0$,即字符串中没有元音字母,那么小红无法移除任何子字符串,小明直接获胜。 + +如果 $k$ 为奇数,那么小红可以移除整个字符串,小红直接获胜。 + +如果 $k$ 为偶数,那么小红可以移除 $k - 1$ 个元音字母,此时剩下一个元音字母,小明无法移除任何子字符串,小红直接获胜。 + +综上所述,如果字符串中包含元音字母,那么小红获胜,否则小明获胜。 + +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def doesAliceWin(self, s: str) -> bool: + vowels = set("aeiou") + return any(c in vowels for c in s) +``` + +#### Java + +```java +class Solution { + public boolean doesAliceWin(String s) { + for (int i = 0; i < s.length(); ++i) { + if ("aeiou".indexOf(s.charAt(i)) != -1) { + return true; + } + } + return false; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + bool doesAliceWin(string s) { + string vowels = "aeiou"; + for (char c : s) { + if (vowels.find(c) != string::npos) { + return true; + } + } + return false; + } +}; +``` + +#### Go + +```go +func doesAliceWin(s string) bool { + vowels := "aeiou" + for _, c := range s { + if strings.ContainsRune(vowels, c) { + return true + } + } + return false +} +``` + +#### TypeScript + +```ts +function doesAliceWin(s: string): boolean { + const vowels = 'aeiou'; + for (const c of s) { + if (vowels.includes(c)) { + return true; + } + } + return false; +} +``` + + + + + + diff --git a/solution/3200-3299/3227.Vowels Game in a String/README_EN.md b/solution/3200-3299/3227.Vowels Game in a String/README_EN.md new file mode 100644 index 000000000000..db43ca010d72 --- /dev/null +++ b/solution/3200-3299/3227.Vowels Game in a String/README_EN.md @@ -0,0 +1,170 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README_EN.md +tags: + - Brainteaser + - Math + - String + - Game Theory +--- + + + +# [3227. Vowels Game in a String](https://leetcode.com/problems/vowels-game-in-a-string) + +[中文文档](/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README.md) + +## Description + + + +

            Alice and Bob are playing a game on a string.

            + +

            You are given a string s, Alice and Bob will take turns playing the following game where Alice starts first:

            + +
              +
            • On Alice's turn, she has to remove any non-empty substring from s that contains an odd number of vowels.
            • +
            • On Bob's turn, he has to remove any non-empty substring from s that contains an even number of vowels.
            • +
            + +

            The first player who cannot make a move on their turn loses the game. We assume that both Alice and Bob play optimally.

            + +

            Return true if Alice wins the game, and false otherwise.

            + +

            The English vowels are: a, e, i, o, and u.

            + +

             

            +

            Example 1:

            + +
            +

            Input: s = "leetcoder"

            + +

            Output: true

            + +

            Explanation:
            +Alice can win the game as follows:

            + +
              +
            • Alice plays first, she can delete the underlined substring in s = "leetcoder" which contains 3 vowels. The resulting string is s = "der".
            • +
            • Bob plays second, he can delete the underlined substring in s = "der" which contains 0 vowels. The resulting string is s = "er".
            • +
            • Alice plays third, she can delete the whole string s = "er" which contains 1 vowel.
            • +
            • Bob plays fourth, since the string is empty, there is no valid play for Bob. So Alice wins the game.
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: s = "bbcd"

            + +

            Output: false

            + +

            Explanation:
            +There is no valid play for Alice in her first turn, so Alice loses the game.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= s.length <= 105
            • +
            • s consists only of lowercase English letters.
            • +
            + + + +## Solutions + + + +### Solution 1: Brain Teaser + +Let's denote the number of vowels in the string as $k$. + +If $k = 0$, meaning there are no vowels in the string, then Little Red cannot remove any substring, and Little Ming wins directly. + +If $k$ is odd, then Little Red can remove the entire string, resulting in a direct win for Little Red. + +If $k$ is even, then Little Red can remove $k - 1$ vowels, leaving one vowel in the string. In this case, Little Ming cannot remove any substring, leading to a direct win for Little Red. + +In conclusion, if the string contains vowels, then Little Red wins; otherwise, Little Ming wins. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def doesAliceWin(self, s: str) -> bool: + vowels = set("aeiou") + return any(c in vowels for c in s) +``` + +#### Java + +```java +class Solution { + public boolean doesAliceWin(String s) { + for (int i = 0; i < s.length(); ++i) { + if ("aeiou".indexOf(s.charAt(i)) != -1) { + return true; + } + } + return false; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + bool doesAliceWin(string s) { + string vowels = "aeiou"; + for (char c : s) { + if (vowels.find(c) != string::npos) { + return true; + } + } + return false; + } +}; +``` + +#### Go + +```go +func doesAliceWin(s string) bool { + vowels := "aeiou" + for _, c := range s { + if strings.ContainsRune(vowels, c) { + return true + } + } + return false +} +``` + +#### TypeScript + +```ts +function doesAliceWin(s: string): boolean { + const vowels = 'aeiou'; + for (const c of s) { + if (vowels.includes(c)) { + return true; + } + } + return false; +} +``` + + + + + + diff --git a/solution/3200-3299/3227.Vowels Game in a String/Solution.cpp b/solution/3200-3299/3227.Vowels Game in a String/Solution.cpp new file mode 100644 index 000000000000..d6f1ed3c761e --- /dev/null +++ b/solution/3200-3299/3227.Vowels Game in a String/Solution.cpp @@ -0,0 +1,12 @@ +class Solution { +public: + bool doesAliceWin(string s) { + string vowels = "aeiou"; + for (char c : s) { + if (vowels.find(c) != string::npos) { + return true; + } + } + return false; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3227.Vowels Game in a String/Solution.go b/solution/3200-3299/3227.Vowels Game in a String/Solution.go new file mode 100644 index 000000000000..fd0d441936b5 --- /dev/null +++ b/solution/3200-3299/3227.Vowels Game in a String/Solution.go @@ -0,0 +1,9 @@ +func doesAliceWin(s string) bool { + vowels := "aeiou" + for _, c := range s { + if strings.ContainsRune(vowels, c) { + return true + } + } + return false +} \ No newline at end of file diff --git a/solution/3200-3299/3227.Vowels Game in a String/Solution.java b/solution/3200-3299/3227.Vowels Game in a String/Solution.java new file mode 100644 index 000000000000..96d204480b6a --- /dev/null +++ b/solution/3200-3299/3227.Vowels Game in a String/Solution.java @@ -0,0 +1,10 @@ +class Solution { + public boolean doesAliceWin(String s) { + for (int i = 0; i < s.length(); ++i) { + if ("aeiou".indexOf(s.charAt(i)) != -1) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3227.Vowels Game in a String/Solution.py b/solution/3200-3299/3227.Vowels Game in a String/Solution.py new file mode 100644 index 000000000000..0f2ca25232ce --- /dev/null +++ b/solution/3200-3299/3227.Vowels Game in a String/Solution.py @@ -0,0 +1,4 @@ +class Solution: + def doesAliceWin(self, s: str) -> bool: + vowels = set("aeiou") + return any(c in vowels for c in s) diff --git a/solution/3200-3299/3227.Vowels Game in a String/Solution.ts b/solution/3200-3299/3227.Vowels Game in a String/Solution.ts new file mode 100644 index 000000000000..78295149c93a --- /dev/null +++ b/solution/3200-3299/3227.Vowels Game in a String/Solution.ts @@ -0,0 +1,9 @@ +function doesAliceWin(s: string): boolean { + const vowels = 'aeiou'; + for (const c of s) { + if (vowels.includes(c)) { + return true; + } + } + return false; +} diff --git a/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/README.md b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/README.md new file mode 100644 index 000000000000..cdc31cc1f0b1 --- /dev/null +++ b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/README.md @@ -0,0 +1,178 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README.md +tags: + - 贪心 + - 字符串 + - 计数 +--- + + + +# [3228. 将 1 移动到末尾的最大操作次数](https://leetcode.cn/problems/maximum-number-of-operations-to-move-ones-to-the-end) + +[English Version](/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README_EN.md) + +## 题目描述 + + + +

            给你一个 二进制字符串 s

            + +

            你可以对这个字符串执行 任意次 下述操作:

            + +
              +
            • 选择字符串中的任一下标 ii + 1 < s.length ),该下标满足 s[i] == '1's[i + 1] == '0'
            • +
            • 将字符 s[i]右移 直到它到达字符串的末端或另一个 '1'。例如,对于 s = "010010",如果我们选择 i = 1,结果字符串将会是 s = "000110"
            • +
            + +

            返回你能执行的 最大 操作次数。

            + +

             

            + +

            示例 1:

            + +
            +

            输入: s = "1001101"

            + +

            输出: 4

            + +

            解释:

            + +

            可以执行以下操作:

            + +
              +
            • 选择下标 i = 0。结果字符串为 s = "0011101"
            • +
            • 选择下标 i = 4。结果字符串为 s = "0011011"
            • +
            • 选择下标 i = 3。结果字符串为 s = "0010111"
            • +
            • 选择下标 i = 2。结果字符串为 s = "0001111"
            • +
            +
            + +

            示例 2:

            + +
            +

            输入: s = "00111"

            + +

            输出: 0

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= s.length <= 105
            • +
            • s[i]'0''1'
            • +
            + + + +## 解法 + + + +### 方法一:贪心 + +我们用一个变量 $\textit{ans}$ 记录答案,用一个变量 $\textit{cnt}$ 记录当前的 $1$ 的个数。 + +然后我们遍历字符串 $s$,如果当前字符是 $1$,则 $\textit{cnt}$ 加一,否则如果存在前一个字符,且前一个字符是 $1$,那么前面的 $\textit{cnt}$ 个 $1$ 可以往后移动,答案加上 $\textit{cnt}$。 + +最后返回答案即可。 + +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def maxOperations(self, s: str) -> int: + ans = cnt = 0 + for i, c in enumerate(s): + if c == "1": + cnt += 1 + elif i and s[i - 1] == "1": + ans += cnt + return ans +``` + +#### Java + +```java +class Solution { + public int maxOperations(String s) { + int ans = 0, cnt = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++cnt; + } else if (i > 0 && s.charAt(i - 1) == '1') { + ans += cnt; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int maxOperations(string s) { + int ans = 0, cnt = 0; + int n = s.size(); + for (int i = 0; i < n; ++i) { + if (s[i] == '1') { + ++cnt; + } else if (i && s[i - 1] == '1') { + ans += cnt; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func maxOperations(s string) (ans int) { + cnt := 0 + for i, c := range s { + if c == '1' { + cnt++ + } else if i > 0 && s[i-1] == '1' { + ans += cnt + } + } + return +} +``` + +#### TypeScript + +```ts +function maxOperations(s: string): number { + let [ans, cnt] = [0, 0]; + const n = s.length; + for (let i = 0; i < n; ++i) { + if (s[i] === '1') { + ++cnt; + } else if (i && s[i - 1] === '1') { + ans += cnt; + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/README_EN.md b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/README_EN.md new file mode 100644 index 000000000000..614bd3ab469a --- /dev/null +++ b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/README_EN.md @@ -0,0 +1,176 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README_EN.md +tags: + - Greedy + - String + - Counting +--- + + + +# [3228. Maximum Number of Operations to Move Ones to the End](https://leetcode.com/problems/maximum-number-of-operations-to-move-ones-to-the-end) + +[中文文档](/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README.md) + +## Description + + + +

            You are given a binary string s.

            + +

            You can perform the following operation on the string any number of times:

            + +
              +
            • Choose any index i from the string where i + 1 < s.length such that s[i] == '1' and s[i + 1] == '0'.
            • +
            • Move the character s[i] to the right until it reaches the end of the string or another '1'. For example, for s = "010010", if we choose i = 1, the resulting string will be s = "000110".
            • +
            + +

            Return the maximum number of operations that you can perform.

            + +

             

            +

            Example 1:

            + +
            +

            Input: s = "1001101"

            + +

            Output: 4

            + +

            Explanation:

            + +

            We can perform the following operations:

            + +
              +
            • Choose index i = 0. The resulting string is s = "0011101".
            • +
            • Choose index i = 4. The resulting string is s = "0011011".
            • +
            • Choose index i = 3. The resulting string is s = "0010111".
            • +
            • Choose index i = 2. The resulting string is s = "0001111".
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: s = "00111"

            + +

            Output: 0

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= s.length <= 105
            • +
            • s[i] is either '0' or '1'.
            • +
            + + + +## Solutions + + + +### Solution 1: Greedy + +We use a variable $\textit{ans}$ to record the answer and another variable $\textit{cnt}$ to count the current number of $1$s. + +Then, we iterate through the string $s$. If the current character is $1$, then we increment $\textit{cnt}$. Otherwise, if there is a previous character and the previous character is $1$, then the previous $\textit{cnt}$ number of $1$s can be moved backward, and we add $\textit{cnt}$ to the answer. + +Finally, we return the answer. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def maxOperations(self, s: str) -> int: + ans = cnt = 0 + for i, c in enumerate(s): + if c == "1": + cnt += 1 + elif i and s[i - 1] == "1": + ans += cnt + return ans +``` + +#### Java + +```java +class Solution { + public int maxOperations(String s) { + int ans = 0, cnt = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++cnt; + } else if (i > 0 && s.charAt(i - 1) == '1') { + ans += cnt; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int maxOperations(string s) { + int ans = 0, cnt = 0; + int n = s.size(); + for (int i = 0; i < n; ++i) { + if (s[i] == '1') { + ++cnt; + } else if (i && s[i - 1] == '1') { + ans += cnt; + } + } + return ans; + } +}; +``` + +#### Go + +```go +func maxOperations(s string) (ans int) { + cnt := 0 + for i, c := range s { + if c == '1' { + cnt++ + } else if i > 0 && s[i-1] == '1' { + ans += cnt + } + } + return +} +``` + +#### TypeScript + +```ts +function maxOperations(s: string): number { + let [ans, cnt] = [0, 0]; + const n = s.length; + for (let i = 0; i < n; ++i) { + if (s[i] === '1') { + ++cnt; + } else if (i && s[i - 1] === '1') { + ans += cnt; + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.cpp b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.cpp new file mode 100644 index 000000000000..e76afa9f8ddf --- /dev/null +++ b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int maxOperations(string s) { + int ans = 0, cnt = 0; + int n = s.size(); + for (int i = 0; i < n; ++i) { + if (s[i] == '1') { + ++cnt; + } else if (i && s[i - 1] == '1') { + ans += cnt; + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.go b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.go new file mode 100644 index 000000000000..c30a2c1ab40e --- /dev/null +++ b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.go @@ -0,0 +1,11 @@ +func maxOperations(s string) (ans int) { + cnt := 0 + for i, c := range s { + if c == '1' { + cnt++ + } else if i > 0 && s[i-1] == '1' { + ans += cnt + } + } + return +} \ No newline at end of file diff --git a/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.java b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.java new file mode 100644 index 000000000000..0b95971b06c5 --- /dev/null +++ b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.java @@ -0,0 +1,14 @@ +class Solution { + public int maxOperations(String s) { + int ans = 0, cnt = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++cnt; + } else if (i > 0 && s.charAt(i - 1) == '1') { + ans += cnt; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.py b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.py new file mode 100644 index 000000000000..63098db43f63 --- /dev/null +++ b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.py @@ -0,0 +1,9 @@ +class Solution: + def maxOperations(self, s: str) -> int: + ans = cnt = 0 + for i, c in enumerate(s): + if c == "1": + cnt += 1 + elif i and s[i - 1] == "1": + ans += cnt + return ans diff --git a/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.ts b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.ts new file mode 100644 index 000000000000..1e294a779a33 --- /dev/null +++ b/solution/3200-3299/3228.Maximum Number of Operations to Move Ones to the End/Solution.ts @@ -0,0 +1,12 @@ +function maxOperations(s: string): number { + let [ans, cnt] = [0, 0]; + const n = s.length; + for (let i = 0; i < n; ++i) { + if (s[i] === '1') { + ++cnt; + } else if (i && s[i - 1] === '1') { + ans += cnt; + } + } + return ans; +} diff --git a/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/README.md b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/README.md new file mode 100644 index 000000000000..b6254c4de823 --- /dev/null +++ b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/README.md @@ -0,0 +1,209 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README.md +tags: + - 栈 + - 贪心 + - 数组 + - 动态规划 + - 单调栈 +--- + + + +# [3229. 使数组等于目标数组所需的最少操作次数](https://leetcode.cn/problems/minimum-operations-to-make-array-equal-to-target) + +[English Version](/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README_EN.md) + +## 题目描述 + + + +

            给你两个长度相同的正整数数组 numstarget

            + +

            在一次操作中,你可以选择 nums 的任何子数组,并将该子数组内的每个元素的值增加或减少 1。

            + +

            返回使 nums 数组变为 target 数组所需的 最少 操作次数。

            + +

             

            + +

            示例 1:

            + +
            +

            输入: nums = [3,5,1,2], target = [4,6,2,4]

            + +

            输出: 2

            + +

            解释:

            + +

            执行以下操作可以使 nums 等于 target
            +- nums[0..3] 增加 1,nums = [4,6,2,3]
            +- nums[3..3] 增加 1,nums = [4,6,2,4]

            +
            + +

            示例 2:

            + +
            +

            输入: nums = [1,3,2], target = [2,1,4]

            + +

            输出: 5

            + +

            解释:

            + +

            执行以下操作可以使 nums 等于 target
            +- nums[0..0] 增加 1,nums = [2,3,2]
            +- nums[1..1] 减少 1,nums = [2,2,2]
            +- nums[1..1] 减少 1,nums = [2,1,2]
            +- nums[2..2] 增加 1,nums = [2,1,3]
            +- nums[2..2] 增加 1,nums = [2,1,4]

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= nums.length == target.length <= 105
            • +
            • 1 <= nums[i], target[i] <= 108
            • +
            + + + +## 解法 + + + +### 方法一:动态规划 + +我们可以先计算出 $\textit{nums}$ 和 $\textit{target}$ 两个数组的差值,然后对于一个差值数组,我们找出连续的差值符号相同的区间,然后对于每个区间,我们将第一个元素的绝对值加到结果中,然后对于后面的元素,如果差值的绝对值比前一个差值的绝对值大,那么我们将绝对值的差值加到结果中。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 + +相似题目: + +- [1526. 形成目标数组的子数组最少增加次数](https://github.com/doocs/leetcode/tree/main/solution/1500-1599/1526.Minimum%20Number%20of%20Increments%20on%20Subarrays%20to%20Form%20a%20Target%20Array/README.md) + + + +#### Python3 + +```python +class Solution: + def minimumOperations(self, nums: List[int], target: List[int]) -> int: + n = len(nums) + f = abs(target[0] - nums[0]) + for i in range(1, n): + x = target[i] - nums[i] + y = target[i - 1] - nums[i - 1] + if x * y > 0: + d = abs(x) - abs(y) + if d > 0: + f += d + else: + f += abs(x) + return f +``` + +#### Java + +```java +class Solution { + public long minimumOperations(int[] nums, int[] target) { + long f = Math.abs(target[0] - nums[0]); + for (int i = 1; i < nums.length; ++i) { + long x = target[i] - nums[i]; + long y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + long d = Math.abs(x) - Math.abs(y); + if (d > 0) { + f += d; + } + } else { + f += Math.abs(x); + } + } + return f; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long minimumOperations(vector& nums, vector& target) { + using ll = long long; + ll f = abs(target[0] - nums[0]); + for (int i = 1; i < nums.size(); ++i) { + long x = target[i] - nums[i]; + long y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + ll d = abs(x) - abs(y); + if (d > 0) { + f += d; + } + } else { + f += abs(x); + } + } + return f; + } +}; +``` + +#### Go + +```go +func minimumOperations(nums []int, target []int) int64 { + f := abs(target[0] - nums[0]) + for i := 1; i < len(target); i++ { + x := target[i] - nums[i] + y := target[i-1] - nums[i-1] + if x*y > 0 { + if d := abs(x) - abs(y); d > 0 { + f += d + } + } else { + f += abs(x) + } + } + return int64(f) +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} +``` + +#### TypeScript + +```ts +function minimumOperations(nums: number[], target: number[]): number { + const n = nums.length; + let f = Math.abs(target[0] - nums[0]); + for (let i = 1; i < n; ++i) { + const x = target[i] - nums[i]; + const y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + const d = Math.abs(x) - Math.abs(y); + if (d > 0) { + f += d; + } + } else { + f += Math.abs(x); + } + } + return f; +} +``` + + + + + + diff --git a/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/README_EN.md b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/README_EN.md new file mode 100644 index 000000000000..a1c1204b2f0c --- /dev/null +++ b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/README_EN.md @@ -0,0 +1,207 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README_EN.md +tags: + - Stack + - Greedy + - Array + - Dynamic Programming + - Monotonic Stack +--- + + + +# [3229. Minimum Operations to Make Array Equal to Target](https://leetcode.com/problems/minimum-operations-to-make-array-equal-to-target) + +[中文文档](/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README.md) + +## Description + + + +

            You are given two positive integer arrays nums and target, of the same length.

            + +

            In a single operation, you can select any subarray of nums and increment each element within that subarray by 1 or decrement each element within that subarray by 1.

            + +

            Return the minimum number of operations required to make nums equal to the array target.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [3,5,1,2], target = [4,6,2,4]

            + +

            Output: 2

            + +

            Explanation:

            + +

            We will perform the following operations to make nums equal to target:
            +- Increment nums[0..3] by 1, nums = [4,6,2,3].
            +- Increment nums[3..3] by 1, nums = [4,6,2,4].

            +
            + +

            Example 2:

            + +
            +

            Input: nums = [1,3,2], target = [2,1,4]

            + +

            Output: 5

            + +

            Explanation:

            + +

            We will perform the following operations to make nums equal to target:
            +- Increment nums[0..0] by 1, nums = [2,3,2].
            +- Decrement nums[1..1] by 1, nums = [2,2,2].
            +- Decrement nums[1..1] by 1, nums = [2,1,2].
            +- Increment nums[2..2] by 1, nums = [2,1,3].
            +- Increment nums[2..2] by 1, nums = [2,1,4].

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= nums.length == target.length <= 105
            • +
            • 1 <= nums[i], target[i] <= 108
            • +
            + + + +## Solutions + + + +### Solution 1: Dynamic Programming + +We can first calculate the difference between the arrays $\textit{nums}$ and $\textit{target}$. For a difference array, we find continuous intervals where the signs of the differences are the same. For each interval, we add the absolute value of the first element to the result. For the subsequent elements, if the absolute value of the difference is greater than the absolute value of the previous difference, we add the difference of the absolute values to the result. + +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. + +Similar problems: + +- [1526. Minimum Number of Increments on Subarrays to Form a Target Array](https://github.com/doocs/leetcode/tree/main/solution/1500-1599/1526.Minimum%20Number%20of%20Increments%20on%20Subarrays%20to%20Form%20a%20Target%20Array/README_EN.md) + + + +#### Python3 + +```python +class Solution: + def minimumOperations(self, nums: List[int], target: List[int]) -> int: + n = len(nums) + f = abs(target[0] - nums[0]) + for i in range(1, n): + x = target[i] - nums[i] + y = target[i - 1] - nums[i - 1] + if x * y > 0: + d = abs(x) - abs(y) + if d > 0: + f += d + else: + f += abs(x) + return f +``` + +#### Java + +```java +class Solution { + public long minimumOperations(int[] nums, int[] target) { + long f = Math.abs(target[0] - nums[0]); + for (int i = 1; i < nums.length; ++i) { + long x = target[i] - nums[i]; + long y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + long d = Math.abs(x) - Math.abs(y); + if (d > 0) { + f += d; + } + } else { + f += Math.abs(x); + } + } + return f; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long minimumOperations(vector& nums, vector& target) { + using ll = long long; + ll f = abs(target[0] - nums[0]); + for (int i = 1; i < nums.size(); ++i) { + long x = target[i] - nums[i]; + long y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + ll d = abs(x) - abs(y); + if (d > 0) { + f += d; + } + } else { + f += abs(x); + } + } + return f; + } +}; +``` + +#### Go + +```go +func minimumOperations(nums []int, target []int) int64 { + f := abs(target[0] - nums[0]) + for i := 1; i < len(target); i++ { + x := target[i] - nums[i] + y := target[i-1] - nums[i-1] + if x*y > 0 { + if d := abs(x) - abs(y); d > 0 { + f += d + } + } else { + f += abs(x) + } + } + return int64(f) +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} +``` + +#### TypeScript + +```ts +function minimumOperations(nums: number[], target: number[]): number { + const n = nums.length; + let f = Math.abs(target[0] - nums[0]); + for (let i = 1; i < n; ++i) { + const x = target[i] - nums[i]; + const y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + const d = Math.abs(x) - Math.abs(y); + if (d > 0) { + f += d; + } + } else { + f += Math.abs(x); + } + } + return f; +} +``` + + + + + + diff --git a/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.cpp b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.cpp new file mode 100644 index 000000000000..7709e5c6369e --- /dev/null +++ b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + long long minimumOperations(vector& nums, vector& target) { + using ll = long long; + ll f = abs(target[0] - nums[0]); + for (int i = 1; i < nums.size(); ++i) { + long x = target[i] - nums[i]; + long y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + ll d = abs(x) - abs(y); + if (d > 0) { + f += d; + } + } else { + f += abs(x); + } + } + return f; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.go b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.go new file mode 100644 index 000000000000..c80b89e43282 --- /dev/null +++ b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.go @@ -0,0 +1,22 @@ +func minimumOperations(nums []int, target []int) int64 { + f := abs(target[0] - nums[0]) + for i := 1; i < len(target); i++ { + x := target[i] - nums[i] + y := target[i-1] - nums[i-1] + if x*y > 0 { + if d := abs(x) - abs(y); d > 0 { + f += d + } + } else { + f += abs(x) + } + } + return int64(f) +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} \ No newline at end of file diff --git a/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.java b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.java new file mode 100644 index 000000000000..0e5ec9103486 --- /dev/null +++ b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.java @@ -0,0 +1,18 @@ +class Solution { + public long minimumOperations(int[] nums, int[] target) { + long f = Math.abs(target[0] - nums[0]); + for (int i = 1; i < nums.length; ++i) { + long x = target[i] - nums[i]; + long y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + long d = Math.abs(x) - Math.abs(y); + if (d > 0) { + f += d; + } + } else { + f += Math.abs(x); + } + } + return f; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.py b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.py new file mode 100644 index 000000000000..4428f92a99d5 --- /dev/null +++ b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.py @@ -0,0 +1,14 @@ +class Solution: + def minimumOperations(self, nums: List[int], target: List[int]) -> int: + n = len(nums) + f = abs(target[0] - nums[0]) + for i in range(1, n): + x = target[i] - nums[i] + y = target[i - 1] - nums[i - 1] + if x * y > 0: + d = abs(x) - abs(y) + if d > 0: + f += d + else: + f += abs(x) + return f diff --git a/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.ts b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.ts new file mode 100644 index 000000000000..0f704df02482 --- /dev/null +++ b/solution/3200-3299/3229.Minimum Operations to Make Array Equal to Target/Solution.ts @@ -0,0 +1,17 @@ +function minimumOperations(nums: number[], target: number[]): number { + const n = nums.length; + let f = Math.abs(target[0] - nums[0]); + for (let i = 1; i < n; ++i) { + const x = target[i] - nums[i]; + const y = target[i - 1] - nums[i - 1]; + if (x * y > 0) { + const d = Math.abs(x) - Math.abs(y); + if (d > 0) { + f += d; + } + } else { + f += Math.abs(x); + } + } + return f; +} diff --git a/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/README.md b/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/README.md new file mode 100644 index 000000000000..847d5c0de042 --- /dev/null +++ b/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/README.md @@ -0,0 +1,205 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README.md +tags: + - 数据库 +--- + + + +# [3230. 客户购买行为分析 🔒](https://leetcode.cn/problems/customer-purchasing-behavior-analysis) + +[English Version](/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README_EN.md) + +## 题目描述 + + + +

            表:Transactions

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| transaction_id   | int     |
            +| customer_id      | int     |
            +| product_id       | int     |
            +| transaction_date | date    |
            +| amount           | decimal |
            ++------------------+---------+
            +transaction_id 是这张表的唯一标识符。
            +这张表的每一行包含一次交易的信息,包括客户 ID,产品 ID,日期和总花费。
            +
            + +

            表:Products

            + +
            ++-------------+---------+
            +| Column Name | Type    |
            ++-------------+---------+
            +| product_id  | int     |
            +| category    | varchar |
            +| price       | decimal |
            ++-------------+---------+
            +product_id 是这张表的唯一标识符。
            +这张表的每一行包含一个产品的信息,包括它的分类和价格。
            +
            + +

            编写一个解决方案来分析用户购买行为。对于 每个消费者,计算:

            + +
              +
            • 总消费额
            • +
            • 交易数量
            • +
            • 购买的 不同 产品类别的数量。
            • +
            • 平均消费金额。
            • +
            • 最常购买 的产品类别(如果相同,选择最近交易的那个)
            • +
            • 忠诚度分数 定义为:(交易数量 * 10) + (总消费 / 100)。
            • +
            + +

            将 total_amount, avg_transaction_amount 和 loyalty_score 舍入到 2 位小数。

            + +

            返回结果表以 loyalty_score 降序 排序,然后以 customer_id 升序 排序。

            + +

            查询结果格式如下所示。

            + +

             

            + +

            示例:

            + +
            +

            输入:

            + +

            Transactions 表:

            + +
            ++----------------+-------------+------------+------------------+--------+
            +| transaction_id | customer_id | product_id | transaction_date | amount |
            ++----------------+-------------+------------+------------------+--------+
            +| 1              | 101         | 1          | 2023-01-01       | 100.00 |
            +| 2              | 101         | 2          | 2023-01-15       | 150.00 |
            +| 3              | 102         | 1          | 2023-01-01       | 100.00 |
            +| 4              | 102         | 3          | 2023-01-22       | 200.00 |
            +| 5              | 101         | 3          | 2023-02-10       | 200.00 |
            ++----------------+-------------+------------+------------------+--------+
            +
            + +

            Products 表:

            + +
            ++------------+----------+--------+
            +| product_id | category | price  |
            ++------------+----------+--------+
            +| 1          | A        | 100.00 |
            +| 2          | B        | 150.00 |
            +| 3          | C        | 200.00 |
            ++------------+----------+--------+
            +
            + +

            输出:

            + +
            ++-------------+--------------+-------------------+-------------------+------------------------+--------------+---------------+
            +| customer_id | total_amount | transaction_count | unique_categories | avg_transaction_amount | top_category | loyalty_score |
            ++-------------+--------------+-------------------+-------------------+------------------------+--------------+---------------+
            +| 101         | 450.00       | 3                 | 3                 | 150.00                 | C            | 34.50         |
            +| 102         | 300.00       | 2                 | 2                 | 150.00                 | C            | 23.00         |
            ++-------------+--------------+-------------------+-------------------+------------------------+--------------+---------------+
            +
            + +

            解释:

            + +
              +
            • 对于消费者 101: +
                +
              • 总消费额:100.00 + 150.00 + 200.00 = 450.00
              • +
              • 交易次数:3
              • +
              • 不同分类:A, B, C (3 个分类)
              • +
              • 平均交易金额:450.00 / 3 = 150.00
              • +
              • 最高分类:C (消费者 101 在分类 A,B,C 分别进行了一次交易。因为所有分类的数量都一样,我们选择最近的那次交易,即在 2023-02-10 的分类 C)
              • +
              • 忠诚度分数:(3 * 10) + (450.00 / 100) = 34.50
              • +
              +
            • +
            • 对于消费者 102: +
                +
              • 总消费额:100.00 + 200.00 = 300.00
              • +
              • 交易次数:2
              • +
              • 不同分类:A, C(2 个分类)
              • +
              • 平均交易金额:300.00 / 2 = 150.00
              • +
              • 最高分类:C (消费者 102 在分类 A 和 C 分别进行了一次交易。因为所有分类的数量都一样,我们选择最近的那次交易,即在 2023-01-22 的分类 C)
              • +
              • 忠诚度分数:(2 * 10) + (300.00 / 100) = 23.00
              • +
              +
            • +
            + +

            注意:输出表以 loyalty_score 降序排序,然后以 customer_id 升序排序。

            +
            + + + +## 解法 + + + +### 方法一:分组 + 窗口函数 + 连接 + +我们首先将 `Transactions` 表和 `Products` 表连接起来,记录在临时表 `T` 中。 + +然后,我们使用 `T` 表计算每个用户在每个类别下的交易次数以及最近的交易日期,将结果保存在临时表 `P` 中。 + +接着,我们使用 `P` 表计算每个用户在每个类别下的交易次数的排名,将结果保存在临时表 `R` 中。 + +最后,我们使用 `T` 表和 `R` 表计算每个用户的总交易金额、交易次数、唯一类别数、平均交易金额、最常购买的类别、忠诚度分数,并按照忠诚度分数降序、用户 ID 升序的顺序返回结果。 + + + +#### MySQL + +```sql +# Write your MySQL query statement below +WITH + T AS ( + SELECT * + FROM + Transactions + JOIN Products USING (product_id) + ), + P AS ( + SELECT + customer_id, + category, + COUNT(1) cnt, + MAX(transaction_date) max_date + FROM T + GROUP BY 1, 2 + ), + R AS ( + SELECT + customer_id, + category, + RANK() OVER ( + PARTITION BY customer_id + ORDER BY cnt DESC, max_date DESC + ) rk + FROM P + ) +SELECT + t.customer_id, + ROUND(SUM(amount), 2) total_amount, + COUNT(1) transaction_count, + COUNT(DISTINCT t.category) unique_categories, + ROUND(AVG(amount), 2) avg_transaction_amount, + r.category top_category, + ROUND(COUNT(1) * 10 + SUM(amount) / 100, 2) loyalty_score +FROM + T t + JOIN R r ON t.customer_id = r.customer_id AND r.rk = 1 +GROUP BY 1 +ORDER BY 7 DESC, 1; +``` + + + + + + diff --git a/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/README_EN.md b/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/README_EN.md new file mode 100644 index 000000000000..8c4ee55a8234 --- /dev/null +++ b/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/README_EN.md @@ -0,0 +1,204 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README_EN.md +tags: + - Database +--- + + + +# [3230. Customer Purchasing Behavior Analysis 🔒](https://leetcode.com/problems/customer-purchasing-behavior-analysis) + +[中文文档](/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README.md) + +## Description + + + +

            Table: Transactions

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| transaction_id   | int     |
            +| customer_id      | int     |
            +| product_id       | int     |
            +| transaction_date | date    |
            +| amount           | decimal |
            ++------------------+---------+
            +transaction_id is the unique identifier for this table.
            +Each row of this table contains information about a transaction, including the customer ID, product ID, date, and amount spent.
            +
            + +

            Table: Products

            + +
            ++-------------+---------+
            +| Column Name | Type    |
            ++-------------+---------+
            +| product_id  | int     |
            +| category    | varchar |
            +| price       | decimal |
            ++-------------+---------+
            +product_id is the unique identifier for this table.
            +Each row of this table contains information about a product, including its category and price.
            +
            + +

            Write a solution to analyze customer purchasing behavior. For each customer, calculate:

            + +
              +
            • The total amount spent.
            • +
            • The number of transactions.
            • +
            • The number of unique product categories purchased.
            • +
            • The average amount spent. 
            • +
            • The most frequently purchased product category (if there is a tie, choose the one with the most recent transaction).
            • +
            • A loyalty score defined as: (Number of transactions * 10) + (Total amount spent / 100).
            • +
            + +

            Round total_amount, avg_transaction_amount, and loyalty_score to 2 decimal places.

            + +

            Return the result table ordered by loyalty_score in descending order, then by customer_id in ascending order.

            + +

            The query result format is in the following example.

            + +

             

            +

            Example:

            + +
            +

            Input:

            + +

            Transactions table:

            + +
            ++----------------+-------------+------------+------------------+--------+
            +| transaction_id | customer_id | product_id | transaction_date | amount |
            ++----------------+-------------+------------+------------------+--------+
            +| 1              | 101         | 1          | 2023-01-01       | 100.00 |
            +| 2              | 101         | 2          | 2023-01-15       | 150.00 |
            +| 3              | 102         | 1          | 2023-01-01       | 100.00 |
            +| 4              | 102         | 3          | 2023-01-22       | 200.00 |
            +| 5              | 101         | 3          | 2023-02-10       | 200.00 |
            ++----------------+-------------+------------+------------------+--------+
            +
            + +

            Products table:

            + +
            ++------------+----------+--------+
            +| product_id | category | price  |
            ++------------+----------+--------+
            +| 1          | A        | 100.00 |
            +| 2          | B        | 150.00 |
            +| 3          | C        | 200.00 |
            ++------------+----------+--------+
            +
            + +

            Output:

            + +
            ++-------------+--------------+-------------------+-------------------+------------------------+--------------+---------------+
            +| customer_id | total_amount | transaction_count | unique_categories | avg_transaction_amount | top_category | loyalty_score |
            ++-------------+--------------+-------------------+-------------------+------------------------+--------------+---------------+
            +| 101         | 450.00       | 3                 | 3                 | 150.00                 | C            | 34.50         |
            +| 102         | 300.00       | 2                 | 2                 | 150.00                 | C            | 23.00         |
            ++-------------+--------------+-------------------+-------------------+------------------------+--------------+---------------+
            +
            + +

            Explanation:

            + +
              +
            • For customer 101: +
                +
              • Total amount spent: 100.00 + 150.00 + 200.00 = 450.00
              • +
              • Number of transactions: 3
              • +
              • Unique categories: A, B, C (3 categories)
              • +
              • Average transaction amount: 450.00 / 3 = 150.00
              • +
              • Top category: C (Customer 101 made 1 purchase each in categories A, B, and C. Since the count is the same for all categories, we choose the most recent transaction, which is category C on 2023-02-10)
              • +
              • Loyalty score: (3 * 10) + (450.00 / 100) = 34.50
              • +
              +
            • +
            • For customer 102: +
                +
              • Total amount spent: 100.00 + 200.00 = 300.00
              • +
              • Number of transactions: 2
              • +
              • Unique categories: A, C (2 categories)
              • +
              • Average transaction amount: 300.00 / 2 = 150.00
              • +
              • Top category: C (Customer 102 made 1 purchase each in categories A and C. Since the count is the same for both categories, we choose the most recent transaction, which is category C on 2023-01-22)
              • +
              • Loyalty score: (2 * 10) + (300.00 / 100) = 23.00
              • +
              +
            • +
            + +

            Note: The output is ordered by loyalty_score in descending order, then by customer_id in ascending order.

            +
            + + + +## Solutions + + + +### Solution 1: Grouping + Window Functions + Join + +First, we join the `Transactions` table with the `Products` table, recording the result in a temporary table `T`. + +Next, we use the `T` table to calculate the transaction count and the most recent transaction date for each user in each category, saving the results in a temporary table `P`. + +Then, we use the `P` table to calculate the ranking of transaction counts for each user in each category, saving the results in a temporary table `R`. + +Finally, we use the `T` and `R` tables to calculate the total transaction amount, transaction count, unique category count, average transaction amount, most frequently purchased category, and loyalty score for each user, and return the results in descending order of loyalty score and ascending order of user ID. + + + +#### MySQL + +```sql +# Write your MySQL query statement below +WITH + T AS ( + SELECT * + FROM + Transactions + JOIN Products USING (product_id) + ), + P AS ( + SELECT + customer_id, + category, + COUNT(1) cnt, + MAX(transaction_date) max_date + FROM T + GROUP BY 1, 2 + ), + R AS ( + SELECT + customer_id, + category, + RANK() OVER ( + PARTITION BY customer_id + ORDER BY cnt DESC, max_date DESC + ) rk + FROM P + ) +SELECT + t.customer_id, + ROUND(SUM(amount), 2) total_amount, + COUNT(1) transaction_count, + COUNT(DISTINCT t.category) unique_categories, + ROUND(AVG(amount), 2) avg_transaction_amount, + r.category top_category, + ROUND(COUNT(1) * 10 + SUM(amount) / 100, 2) loyalty_score +FROM + T t + JOIN R r ON t.customer_id = r.customer_id AND r.rk = 1 +GROUP BY 1 +ORDER BY 7 DESC, 1; +``` + + + + + + diff --git a/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/Solution.sql b/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/Solution.sql new file mode 100644 index 000000000000..0b4b216327dd --- /dev/null +++ b/solution/3200-3299/3230.Customer Purchasing Behavior Analysis/Solution.sql @@ -0,0 +1,40 @@ +# Write your MySQL query statement below +WITH + T AS ( + SELECT * + FROM + Transactions + JOIN Products USING (product_id) + ), + P AS ( + SELECT + customer_id, + category, + COUNT(1) cnt, + MAX(transaction_date) max_date + FROM T + GROUP BY 1, 2 + ), + R AS ( + SELECT + customer_id, + category, + RANK() OVER ( + PARTITION BY customer_id + ORDER BY cnt DESC, max_date DESC + ) rk + FROM P + ) +SELECT + t.customer_id, + ROUND(SUM(amount), 2) total_amount, + COUNT(1) transaction_count, + COUNT(DISTINCT t.category) unique_categories, + ROUND(AVG(amount), 2) avg_transaction_amount, + r.category top_category, + ROUND(COUNT(1) * 10 + SUM(amount) / 100, 2) loyalty_score +FROM + T t + JOIN R r ON t.customer_id = r.customer_id AND r.rk = 1 +GROUP BY 1 +ORDER BY 7 DESC, 1; diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/README.md b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/README.md new file mode 100644 index 000000000000..38de826757ba --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/README.md @@ -0,0 +1,243 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3231.Minimum%20Number%20of%20Increasing%20Subsequence%20to%20Be%20Removed/README.md +tags: + - 数组 + - 二分查找 +--- + + + +# [3231. 要删除的递增子序列的最小数量 🔒](https://leetcode.cn/problems/minimum-number-of-increasing-subsequence-to-be-removed) + +[English Version](/solution/3200-3299/3231.Minimum%20Number%20of%20Increasing%20Subsequence%20to%20Be%20Removed/README_EN.md) + +## 题目描述 + + + +

            给定一个整数数组 nums,你可以执行任意次下面的操作:

            + +
              +
            • 从数组删除一个 严格递增子序列
            • +
            + +

            您的任务是找到使数组为 所需的 最小 操作数。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [5,3,1,4,2]

            + +

            输出:3

            + +

            解释:

            + +

            我们删除子序列 [1, 2][3, 4][5]

            +
            + +

            示例 2:

            + +
            +

            输入:nums = [1,2,3,4,5]

            + +

            输出:1

            +
            + +

            示例 3:

            + +
            +

            输入:nums = [5,4,3,2,1]

            + +

            输出:5

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 105
            • +
            + + + +## 解法 + + + +### 方法一:贪心 + 二分查找 + +我们从左到右遍历数组 $\textit{nums}$,对于每个元素 $x$,我们需要贪心地将其追加到前面序列中最后一个元素小于 $x$ 的最大值后面。如果找不到这样的元素,则说明当前元素 $x$ 比前面序列中的所有元素都小,我们需要新开辟一个序列,将 $x$ 放入其中。 + +这样分析下来,我们可以发现,前面序列中的最后一个元素呈单调递减的状态。因此,我们可以使用二分查找来找到前面序列中最后一个元素小于 $x$ 的第一个元素位置,然后将 $x$ 放入该位置。 + +最终,我们返回序列的个数即可。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def minOperations(self, nums: List[int]) -> int: + g = [] + for x in nums: + l, r = 0, len(g) + while l < r: + mid = (l + r) >> 1 + if g[mid] < x: + r = mid + else: + l = mid + 1 + if l == len(g): + g.append(x) + else: + g[l] = x + return len(g) +``` + +#### Java + +```java +class Solution { + public int minOperations(int[] nums) { + List g = new ArrayList<>(); + for (int x : nums) { + int l = 0, r = g.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (g.get(mid) < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l == g.size()) { + g.add(x); + } else { + g.set(l, x); + } + } + return g.size(); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minOperations(vector& nums) { + vector g; + for (int x : nums) { + int l = 0, r = g.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (g[mid] < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l == g.size()) { + g.push_back(x); + } else { + g[l] = x; + } + } + return g.size(); + } +}; +``` + +#### Go + +```go +func minOperations(nums []int) int { + g := []int{} + for _, x := range nums { + l, r := 0, len(g) + for l < r { + mid := (l + r) >> 1 + if g[mid] < x { + r = mid + } else { + l = mid + 1 + } + } + if l == len(g) { + g = append(g, x) + } else { + g[l] = x + } + } + return len(g) +} +``` + +#### TypeScript + +```ts +function minOperations(nums: number[]): number { + const g: number[] = []; + for (const x of nums) { + let [l, r] = [0, g.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (g[mid] < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l === g.length) { + g.push(x); + } else { + g[l] = x; + } + } + return g.length; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn min_operations(nums: Vec) -> i32 { + let mut g = Vec::new(); + for &x in nums.iter() { + let mut l = 0; + let mut r = g.len(); + while l < r { + let mid = (l + r) / 2; + if g[mid] < x { + r = mid; + } else { + l = mid + 1; + } + } + if l == g.len() { + g.push(x); + } else { + g[l] = x; + } + } + g.len() as i32 + } +} +``` + + + + + + diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/README_EN.md b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/README_EN.md new file mode 100644 index 000000000000..14f3265d9c8e --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/README_EN.md @@ -0,0 +1,241 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3231.Minimum%20Number%20of%20Increasing%20Subsequence%20to%20Be%20Removed/README_EN.md +tags: + - Array + - Binary Search +--- + + + +# [3231. Minimum Number of Increasing Subsequence to Be Removed 🔒](https://leetcode.com/problems/minimum-number-of-increasing-subsequence-to-be-removed) + +[中文文档](/solution/3200-3299/3231.Minimum%20Number%20of%20Increasing%20Subsequence%20to%20Be%20Removed/README.md) + +## Description + + + +

            Given an array of integers nums, you are allowed to perform the following operation any number of times:

            + +
              +
            • Remove a strictly increasing subsequence from the array.
            • +
            + +

            Your task is to find the minimum number of operations required to make the array empty.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [5,3,1,4,2]

            + +

            Output: 3

            + +

            Explanation:

            + +

            We remove subsequences [1, 2], [3, 4], [5].

            +
            + +

            Example 2:

            + +
            +

            Input: nums = [1,2,3,4,5]

            + +

            Output: 1

            +
            + +

            Example 3:

            + +
            +

            Input: nums = [5,4,3,2,1]

            + +

            Output: 5

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 105
            • +
            + + + +## Solutions + + + +### Solution 1: Greedy + Binary Search + +We traverse the array $\textit{nums}$ from left to right. For each element $x$, we need to greedily append it after the last element of the preceding sequence that is smaller than $x$. If no such element is found, it means the current element $x$ is smaller than all elements in the preceding sequences, and we need to start a new sequence with $x$. + +From this analysis, we can observe that the last elements of the preceding sequences are in a monotonically decreasing order. Therefore, we can use binary search to find the position of the first element in the preceding sequences that is smaller than $x$, and then place $x$ in that position. + +Finally, we return the number of sequences. + +The time complexity is $O(n \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. + + + +#### Python3 + +```python +class Solution: + def minOperations(self, nums: List[int]) -> int: + g = [] + for x in nums: + l, r = 0, len(g) + while l < r: + mid = (l + r) >> 1 + if g[mid] < x: + r = mid + else: + l = mid + 1 + if l == len(g): + g.append(x) + else: + g[l] = x + return len(g) +``` + +#### Java + +```java +class Solution { + public int minOperations(int[] nums) { + List g = new ArrayList<>(); + for (int x : nums) { + int l = 0, r = g.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (g.get(mid) < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l == g.size()) { + g.add(x); + } else { + g.set(l, x); + } + } + return g.size(); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minOperations(vector& nums) { + vector g; + for (int x : nums) { + int l = 0, r = g.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (g[mid] < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l == g.size()) { + g.push_back(x); + } else { + g[l] = x; + } + } + return g.size(); + } +}; +``` + +#### Go + +```go +func minOperations(nums []int) int { + g := []int{} + for _, x := range nums { + l, r := 0, len(g) + for l < r { + mid := (l + r) >> 1 + if g[mid] < x { + r = mid + } else { + l = mid + 1 + } + } + if l == len(g) { + g = append(g, x) + } else { + g[l] = x + } + } + return len(g) +} +``` + +#### TypeScript + +```ts +function minOperations(nums: number[]): number { + const g: number[] = []; + for (const x of nums) { + let [l, r] = [0, g.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (g[mid] < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l === g.length) { + g.push(x); + } else { + g[l] = x; + } + } + return g.length; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn min_operations(nums: Vec) -> i32 { + let mut g = Vec::new(); + for &x in nums.iter() { + let mut l = 0; + let mut r = g.len(); + while l < r { + let mid = (l + r) / 2; + if g[mid] < x { + r = mid; + } else { + l = mid + 1; + } + } + if l == g.len() { + g.push(x); + } else { + g[l] = x; + } + } + g.len() as i32 + } +} +``` + + + + + + diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.cpp b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.cpp new file mode 100644 index 000000000000..75c5d4a2c4dd --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.cpp @@ -0,0 +1,23 @@ +class Solution { +public: + int minOperations(vector& nums) { + vector g; + for (int x : nums) { + int l = 0, r = g.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (g[mid] < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l == g.size()) { + g.push_back(x); + } else { + g[l] = x; + } + } + return g.size(); + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.go b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.go new file mode 100644 index 000000000000..26c6c62dbf43 --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.go @@ -0,0 +1,20 @@ +func minOperations(nums []int) int { + g := []int{} + for _, x := range nums { + l, r := 0, len(g) + for l < r { + mid := (l + r) >> 1 + if g[mid] < x { + r = mid + } else { + l = mid + 1 + } + } + if l == len(g) { + g = append(g, x) + } else { + g[l] = x + } + } + return len(g) +} \ No newline at end of file diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.java b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.java new file mode 100644 index 000000000000..61d01228fba5 --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.java @@ -0,0 +1,22 @@ +class Solution { + public int minOperations(int[] nums) { + List g = new ArrayList<>(); + for (int x : nums) { + int l = 0, r = g.size(); + while (l < r) { + int mid = (l + r) >> 1; + if (g.get(mid) < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l == g.size()) { + g.add(x); + } else { + g.set(l, x); + } + } + return g.size(); + } +} \ No newline at end of file diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.py b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.py new file mode 100644 index 000000000000..a936fc96e681 --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.py @@ -0,0 +1,16 @@ +class Solution: + def minOperations(self, nums: List[int]) -> int: + g = [] + for x in nums: + l, r = 0, len(g) + while l < r: + mid = (l + r) >> 1 + if g[mid] < x: + r = mid + else: + l = mid + 1 + if l == len(g): + g.append(x) + else: + g[l] = x + return len(g) diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.rs b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.rs new file mode 100644 index 000000000000..43e93ae2b2b6 --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.rs @@ -0,0 +1,23 @@ +impl Solution { + pub fn min_operations(nums: Vec) -> i32 { + let mut g = Vec::new(); + for &x in nums.iter() { + let mut l = 0; + let mut r = g.len(); + while l < r { + let mid = (l + r) / 2; + if g[mid] < x { + r = mid; + } else { + l = mid + 1; + } + } + if l == g.len() { + g.push(x); + } else { + g[l] = x; + } + } + g.len() as i32 + } +} diff --git a/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.ts b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.ts new file mode 100644 index 000000000000..56f6151197aa --- /dev/null +++ b/solution/3200-3299/3231.Minimum Number of Increasing Subsequence to Be Removed/Solution.ts @@ -0,0 +1,20 @@ +function minOperations(nums: number[]): number { + const g: number[] = []; + for (const x of nums) { + let [l, r] = [0, g.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (g[mid] < x) { + r = mid; + } else { + l = mid + 1; + } + } + if (l === g.length) { + g.push(x); + } else { + g[l] = x; + } + } + return g.length; +} diff --git a/solution/3200-3299/3232.Find if Digit Game Can Be Won/README.md b/solution/3200-3299/3232.Find if Digit Game Can Be Won/README.md new file mode 100644 index 000000000000..2171348a81ef --- /dev/null +++ b/solution/3200-3299/3232.Find if Digit Game Can Be Won/README.md @@ -0,0 +1,170 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README.md +tags: + - 数组 + - 数学 +--- + + + +# [3232. 判断是否可以赢得数字游戏](https://leetcode.cn/problems/find-if-digit-game-can-be-won) + +[English Version](/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README_EN.md) + +## 题目描述 + + + +

            给你一个 正整数 数组 nums

            + +

            Alice 和 Bob 正在玩游戏。在游戏中,Alice 可以从 nums 中选择所有个位数 所有两位数,剩余的数字归 Bob 所有。如果 Alice 所选数字之和 严格大于 Bob 的数字之和,则 Alice 获胜。

            + +

            如果 Alice 能赢得这场游戏,返回 true;否则,返回 false

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [1,2,3,4,10]

            + +

            输出:false

            + +

            解释:

            + +

            Alice 不管选个位数还是两位数都无法赢得比赛。

            +
            + +

            示例 2:

            + +
            +

            输入:nums = [1,2,3,4,5,14]

            + +

            输出:true

            + +

            解释:

            + +

            Alice 选择个位数可以赢得比赛,所选数字之和为 15。

            +
            + +

            示例 3:

            + +
            +

            输入:nums = [5,5,5,25]

            + +

            输出:true

            + +

            解释:

            + +

            Alice 选择两位数可以赢得比赛,所选数字之和为 25。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= nums.length <= 100
            • +
            • 1 <= nums[i] <= 99
            • +
            + + + +## 解法 + + + +### 方法一:求和 + +根据题目描述,只要个位数之和不等于两位数之和,那么小红一定可以选择一个较大的和来获胜。 + +时间复杂度 $O(n)$,其中 $n$ 是数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def canAliceWin(self, nums: List[int]) -> bool: + a = sum(x for x in nums if x < 10) + b = sum(x for x in nums if x > 9) + return a != b +``` + +#### Java + +```java +class Solution { + public boolean canAliceWin(int[] nums) { + int a = 0, b = 0; + for (int x : nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a != b; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + bool canAliceWin(vector& nums) { + int a = 0, b = 0; + for (int x : nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a != b; + } +}; +``` + +#### Go + +```go +func canAliceWin(nums []int) bool { + a, b := 0, 0 + for _, x := range nums { + if x < 10 { + a += x + } else { + b += x + } + } + return a != b +} +``` + +#### TypeScript + +```ts +function canAliceWin(nums: number[]): boolean { + let [a, b] = [0, 0]; + for (const x of nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a !== b; +} +``` + + + + + + diff --git a/solution/3200-3299/3232.Find if Digit Game Can Be Won/README_EN.md b/solution/3200-3299/3232.Find if Digit Game Can Be Won/README_EN.md new file mode 100644 index 000000000000..1c5ae8a16707 --- /dev/null +++ b/solution/3200-3299/3232.Find if Digit Game Can Be Won/README_EN.md @@ -0,0 +1,168 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README_EN.md +tags: + - Array + - Math +--- + + + +# [3232. Find if Digit Game Can Be Won](https://leetcode.com/problems/find-if-digit-game-can-be-won) + +[中文文档](/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README.md) + +## Description + + + +

            You are given an array of positive integers nums.

            + +

            Alice and Bob are playing a game. In the game, Alice can choose either all single-digit numbers or all double-digit numbers from nums, and the rest of the numbers are given to Bob. Alice wins if the sum of her numbers is strictly greater than the sum of Bob's numbers.

            + +

            Return true if Alice can win this game, otherwise, return false.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [1,2,3,4,10]

            + +

            Output: false

            + +

            Explanation:

            + +

            Alice cannot win by choosing either single-digit or double-digit numbers.

            +
            + +

            Example 2:

            + +
            +

            Input: nums = [1,2,3,4,5,14]

            + +

            Output: true

            + +

            Explanation:

            + +

            Alice can win by choosing single-digit numbers which have a sum equal to 15.

            +
            + +

            Example 3:

            + +
            +

            Input: nums = [5,5,5,25]

            + +

            Output: true

            + +

            Explanation:

            + +

            Alice can win by choosing double-digit numbers which have a sum equal to 25.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= nums.length <= 100
            • +
            • 1 <= nums[i] <= 99
            • +
            + + + +## Solutions + + + +### Solution 1: Summation + +According to the problem description, as long as the sum of the units digits is not equal to the sum of the tens digits, Xiaohong can always choose a larger sum to win. + +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def canAliceWin(self, nums: List[int]) -> bool: + a = sum(x for x in nums if x < 10) + b = sum(x for x in nums if x > 9) + return a != b +``` + +#### Java + +```java +class Solution { + public boolean canAliceWin(int[] nums) { + int a = 0, b = 0; + for (int x : nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a != b; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + bool canAliceWin(vector& nums) { + int a = 0, b = 0; + for (int x : nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a != b; + } +}; +``` + +#### Go + +```go +func canAliceWin(nums []int) bool { + a, b := 0, 0 + for _, x := range nums { + if x < 10 { + a += x + } else { + b += x + } + } + return a != b +} +``` + +#### TypeScript + +```ts +function canAliceWin(nums: number[]): boolean { + let [a, b] = [0, 0]; + for (const x of nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a !== b; +} +``` + + + + + + diff --git a/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.cpp b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.cpp new file mode 100644 index 000000000000..ef269d390a80 --- /dev/null +++ b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + bool canAliceWin(vector& nums) { + int a = 0, b = 0; + for (int x : nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a != b; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.go b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.go new file mode 100644 index 000000000000..14f7782437a1 --- /dev/null +++ b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.go @@ -0,0 +1,11 @@ +func canAliceWin(nums []int) bool { + a, b := 0, 0 + for _, x := range nums { + if x < 10 { + a += x + } else { + b += x + } + } + return a != b +} \ No newline at end of file diff --git a/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.java b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.java new file mode 100644 index 000000000000..34b98eda2046 --- /dev/null +++ b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.java @@ -0,0 +1,13 @@ +class Solution { + public boolean canAliceWin(int[] nums) { + int a = 0, b = 0; + for (int x : nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a != b; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.py b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.py new file mode 100644 index 000000000000..262ac3f5a8d8 --- /dev/null +++ b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.py @@ -0,0 +1,5 @@ +class Solution: + def canAliceWin(self, nums: List[int]) -> bool: + a = sum(x for x in nums if x < 10) + b = sum(x for x in nums if x > 9) + return a != b diff --git a/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.ts b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.ts new file mode 100644 index 000000000000..c63e46fb84ce --- /dev/null +++ b/solution/3200-3299/3232.Find if Digit Game Can Be Won/Solution.ts @@ -0,0 +1,11 @@ +function canAliceWin(nums: number[]): boolean { + let [a, b] = [0, 0]; + for (const x of nums) { + if (x < 10) { + a += x; + } else { + b += x; + } + } + return a !== b; +} diff --git a/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/README.md b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/README.md new file mode 100644 index 000000000000..8cd65f830fd7 --- /dev/null +++ b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/README.md @@ -0,0 +1,237 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README.md +tags: + - 数组 + - 数学 + - 数论 +--- + + + +# [3233. 统计不是特殊数字的数字数量](https://leetcode.cn/problems/find-the-count-of-numbers-which-are-not-special) + +[English Version](/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README_EN.md) + +## 题目描述 + + + +

            给你两个 正整数 lr。对于任何数字 xx 的所有正因数(除了 x 本身)被称为 x真因数

            + +

            如果一个数字恰好仅有两个 真因数,则称该数字为 特殊数字。例如:

            + +
              +
            • 数字 4 是 特殊数字,因为它的真因数为 1 和 2。
            • +
            • 数字 6 不是 特殊数字,因为它的真因数为 1、2 和 3。
            • +
            + +

            返回区间 [l, r] 不是 特殊数字 的数字数量。

            + +

             

            + +

            示例 1:

            + +
            +

            输入: l = 5, r = 7

            + +

            输出: 3

            + +

            解释:

            + +

            区间 [5, 7] 内不存在特殊数字。

            +
            + +

            示例 2:

            + +
            +

            输入: l = 4, r = 16

            + +

            输出: 11

            + +

            解释:

            + +

            区间 [4, 16] 内的特殊数字为 4 和 9。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= l <= r <= 109
            • +
            + + + +## 解法 + + + +### 方法一:数学 + +根据题目描述,我们可以发现,只有质数的平方才是特殊数字。因此,我们可以先预处理出小于等于 $\sqrt{10^9}$ 的所有质数,然后遍历区间 $[\lceil\sqrt{l}\rceil, \lfloor\sqrt{r}\rfloor]$,统计出区间内的质数个数 $\textit{cnt}$,最后返回 $r - l + 1 - \textit{cnt}$ 即可。 + +时间复杂度 $O(\sqrt{m})$,空间复杂度 $O(\sqrt{m})$。其中 $m = 10^9$。 + + + +#### Python3 + +```python +m = 31623 +primes = [True] * (m + 1) +primes[0] = primes[1] = False +for i in range(2, m + 1): + if primes[i]: + for j in range(i + i, m + 1, i): + primes[j] = False + + +class Solution: + def nonSpecialCount(self, l: int, r: int) -> int: + lo = ceil(sqrt(l)) + hi = floor(sqrt(r)) + cnt = sum(primes[i] for i in range(lo, hi + 1)) + return r - l + 1 - cnt +``` + +#### Java + +```java +class Solution { + static int m = 31623; + static boolean[] primes = new boolean[m + 1]; + + static { + Arrays.fill(primes, true); + primes[0] = primes[1] = false; + for (int i = 2; i <= m; i++) { + if (primes[i]) { + for (int j = i + i; j <= m; j += i) { + primes[j] = false; + } + } + } + } + + public int nonSpecialCount(int l, int r) { + int lo = (int) Math.ceil(Math.sqrt(l)); + int hi = (int) Math.floor(Math.sqrt(r)); + int cnt = 0; + for (int i = lo; i <= hi; i++) { + if (primes[i]) { + cnt++; + } + } + return r - l + 1 - cnt; + } +} +``` + +#### C++ + +```cpp +const int m = 31623; +bool primes[m + 1]; + +auto init = [] { + memset(primes, true, sizeof(primes)); + primes[0] = primes[1] = false; + for (int i = 2; i <= m; ++i) { + if (primes[i]) { + for (int j = i * 2; j <= m; j += i) { + primes[j] = false; + } + } + } + return 0; +}(); + +class Solution { +public: + int nonSpecialCount(int l, int r) { + int lo = ceil(sqrt(l)); + int hi = floor(sqrt(r)); + int cnt = 0; + for (int i = lo; i <= hi; ++i) { + if (primes[i]) { + ++cnt; + } + } + return r - l + 1 - cnt; + } +}; +``` + +#### Go + +```go +const m = 31623 + +var primes [m + 1]bool + +func init() { + for i := range primes { + primes[i] = true + } + primes[0] = false + primes[1] = false + for i := 2; i <= m; i++ { + if primes[i] { + for j := i * 2; j <= m; j += i { + primes[j] = false + } + } + } +} + +func nonSpecialCount(l int, r int) int { + lo := int(math.Ceil(math.Sqrt(float64(l)))) + hi := int(math.Floor(math.Sqrt(float64(r)))) + cnt := 0 + for i := lo; i <= hi; i++ { + if primes[i] { + cnt++ + } + } + return r - l + 1 - cnt +} +``` + +#### TypeScript + +```ts +const m = 31623; +const primes: boolean[] = Array(m + 1).fill(true); + +(() => { + primes[0] = primes[1] = false; + for (let i = 2; i <= m; ++i) { + if (primes[i]) { + for (let j = i * 2; j <= m; j += i) { + primes[j] = false; + } + } + } +})(); + +function nonSpecialCount(l: number, r: number): number { + const lo = Math.ceil(Math.sqrt(l)); + const hi = Math.floor(Math.sqrt(r)); + let cnt = 0; + for (let i = lo; i <= hi; ++i) { + if (primes[i]) { + ++cnt; + } + } + return r - l + 1 - cnt; +} +``` + + + + + + diff --git a/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/README_EN.md b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/README_EN.md new file mode 100644 index 000000000000..177d370511b8 --- /dev/null +++ b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/README_EN.md @@ -0,0 +1,235 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README_EN.md +tags: + - Array + - Math + - Number Theory +--- + + + +# [3233. Find the Count of Numbers Which Are Not Special](https://leetcode.com/problems/find-the-count-of-numbers-which-are-not-special) + +[中文文档](/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README.md) + +## Description + + + +

            You are given 2 positive integers l and r. For any number x, all positive divisors of x except x are called the proper divisors of x.

            + +

            A number is called special if it has exactly 2 proper divisors. For example:

            + +
              +
            • The number 4 is special because it has proper divisors 1 and 2.
            • +
            • The number 6 is not special because it has proper divisors 1, 2, and 3.
            • +
            + +

            Return the count of numbers in the range [l, r] that are not special.

            + +

             

            +

            Example 1:

            + +
            +

            Input: l = 5, r = 7

            + +

            Output: 3

            + +

            Explanation:

            + +

            There are no special numbers in the range [5, 7].

            +
            + +

            Example 2:

            + +
            +

            Input: l = 4, r = 16

            + +

            Output: 11

            + +

            Explanation:

            + +

            The special numbers in the range [4, 16] are 4 and 9.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= l <= r <= 109
            • +
            + + + +## Solutions + + + +### Solution 1: Mathematics + +According to the problem description, we can observe that only the squares of prime numbers are special numbers. Therefore, we can first preprocess all prime numbers less than or equal to $\sqrt{10^9}$, and then iterate through the interval $[\lceil\sqrt{l}\rceil, \lfloor\sqrt{r}\rfloor]$, counting the number of primes $\textit{cnt}$ in the interval. Finally, we return $r - l + 1 - \textit{cnt}$. + +The time complexity is $O(\sqrt{m})$, and the space complexity is $O(\sqrt{m})$, where $m = 10^9$. + + + +#### Python3 + +```python +m = 31623 +primes = [True] * (m + 1) +primes[0] = primes[1] = False +for i in range(2, m + 1): + if primes[i]: + for j in range(i + i, m + 1, i): + primes[j] = False + + +class Solution: + def nonSpecialCount(self, l: int, r: int) -> int: + lo = ceil(sqrt(l)) + hi = floor(sqrt(r)) + cnt = sum(primes[i] for i in range(lo, hi + 1)) + return r - l + 1 - cnt +``` + +#### Java + +```java +class Solution { + static int m = 31623; + static boolean[] primes = new boolean[m + 1]; + + static { + Arrays.fill(primes, true); + primes[0] = primes[1] = false; + for (int i = 2; i <= m; i++) { + if (primes[i]) { + for (int j = i + i; j <= m; j += i) { + primes[j] = false; + } + } + } + } + + public int nonSpecialCount(int l, int r) { + int lo = (int) Math.ceil(Math.sqrt(l)); + int hi = (int) Math.floor(Math.sqrt(r)); + int cnt = 0; + for (int i = lo; i <= hi; i++) { + if (primes[i]) { + cnt++; + } + } + return r - l + 1 - cnt; + } +} +``` + +#### C++ + +```cpp +const int m = 31623; +bool primes[m + 1]; + +auto init = [] { + memset(primes, true, sizeof(primes)); + primes[0] = primes[1] = false; + for (int i = 2; i <= m; ++i) { + if (primes[i]) { + for (int j = i * 2; j <= m; j += i) { + primes[j] = false; + } + } + } + return 0; +}(); + +class Solution { +public: + int nonSpecialCount(int l, int r) { + int lo = ceil(sqrt(l)); + int hi = floor(sqrt(r)); + int cnt = 0; + for (int i = lo; i <= hi; ++i) { + if (primes[i]) { + ++cnt; + } + } + return r - l + 1 - cnt; + } +}; +``` + +#### Go + +```go +const m = 31623 + +var primes [m + 1]bool + +func init() { + for i := range primes { + primes[i] = true + } + primes[0] = false + primes[1] = false + for i := 2; i <= m; i++ { + if primes[i] { + for j := i * 2; j <= m; j += i { + primes[j] = false + } + } + } +} + +func nonSpecialCount(l int, r int) int { + lo := int(math.Ceil(math.Sqrt(float64(l)))) + hi := int(math.Floor(math.Sqrt(float64(r)))) + cnt := 0 + for i := lo; i <= hi; i++ { + if primes[i] { + cnt++ + } + } + return r - l + 1 - cnt +} +``` + +#### TypeScript + +```ts +const m = 31623; +const primes: boolean[] = Array(m + 1).fill(true); + +(() => { + primes[0] = primes[1] = false; + for (let i = 2; i <= m; ++i) { + if (primes[i]) { + for (let j = i * 2; j <= m; j += i) { + primes[j] = false; + } + } + } +})(); + +function nonSpecialCount(l: number, r: number): number { + const lo = Math.ceil(Math.sqrt(l)); + const hi = Math.floor(Math.sqrt(r)); + let cnt = 0; + for (let i = lo; i <= hi; ++i) { + if (primes[i]) { + ++cnt; + } + } + return r - l + 1 - cnt; +} +``` + + + + + + diff --git a/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.cpp b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.cpp new file mode 100644 index 000000000000..d06a5cf7261b --- /dev/null +++ b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.cpp @@ -0,0 +1,30 @@ +const int m = 31623; +bool primes[m + 1]; + +auto init = [] { + memset(primes, true, sizeof(primes)); + primes[0] = primes[1] = false; + for (int i = 2; i <= m; ++i) { + if (primes[i]) { + for (int j = i * 2; j <= m; j += i) { + primes[j] = false; + } + } + } + return 0; +}(); + +class Solution { +public: + int nonSpecialCount(int l, int r) { + int lo = ceil(sqrt(l)); + int hi = floor(sqrt(r)); + int cnt = 0; + for (int i = lo; i <= hi; ++i) { + if (primes[i]) { + ++cnt; + } + } + return r - l + 1 - cnt; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.go b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.go new file mode 100644 index 000000000000..b8afdf706d79 --- /dev/null +++ b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.go @@ -0,0 +1,30 @@ +const m = 31623 + +var primes [m + 1]bool + +func init() { + for i := range primes { + primes[i] = true + } + primes[0] = false + primes[1] = false + for i := 2; i <= m; i++ { + if primes[i] { + for j := i * 2; j <= m; j += i { + primes[j] = false + } + } + } +} + +func nonSpecialCount(l int, r int) int { + lo := int(math.Ceil(math.Sqrt(float64(l)))) + hi := int(math.Floor(math.Sqrt(float64(r)))) + cnt := 0 + for i := lo; i <= hi; i++ { + if primes[i] { + cnt++ + } + } + return r - l + 1 - cnt +} \ No newline at end of file diff --git a/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.java b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.java new file mode 100644 index 000000000000..0745c5560e1a --- /dev/null +++ b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.java @@ -0,0 +1,28 @@ +class Solution { + static int m = 31623; + static boolean[] primes = new boolean[m + 1]; + + static { + Arrays.fill(primes, true); + primes[0] = primes[1] = false; + for (int i = 2; i <= m; i++) { + if (primes[i]) { + for (int j = i + i; j <= m; j += i) { + primes[j] = false; + } + } + } + } + + public int nonSpecialCount(int l, int r) { + int lo = (int) Math.ceil(Math.sqrt(l)); + int hi = (int) Math.floor(Math.sqrt(r)); + int cnt = 0; + for (int i = lo; i <= hi; i++) { + if (primes[i]) { + cnt++; + } + } + return r - l + 1 - cnt; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.py b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.py new file mode 100644 index 000000000000..f1e74378ad57 --- /dev/null +++ b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.py @@ -0,0 +1,15 @@ +m = 31623 +primes = [True] * (m + 1) +primes[0] = primes[1] = False +for i in range(2, m + 1): + if primes[i]: + for j in range(i + i, m + 1, i): + primes[j] = False + + +class Solution: + def nonSpecialCount(self, l: int, r: int) -> int: + lo = ceil(sqrt(l)) + hi = floor(sqrt(r)) + cnt = sum(primes[i] for i in range(lo, hi + 1)) + return r - l + 1 - cnt diff --git a/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.ts b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.ts new file mode 100644 index 000000000000..28968a039460 --- /dev/null +++ b/solution/3200-3299/3233.Find the Count of Numbers Which Are Not Special/Solution.ts @@ -0,0 +1,25 @@ +const m = 31623; +const primes: boolean[] = Array(m + 1).fill(true); + +(() => { + primes[0] = primes[1] = false; + for (let i = 2; i <= m; ++i) { + if (primes[i]) { + for (let j = i * 2; j <= m; j += i) { + primes[j] = false; + } + } + } +})(); + +function nonSpecialCount(l: number, r: number): number { + const lo = Math.ceil(Math.sqrt(l)); + const hi = Math.floor(Math.sqrt(r)); + let cnt = 0; + for (let i = lo; i <= hi; ++i) { + if (primes[i]) { + ++cnt; + } + } + return r - l + 1 - cnt; +} diff --git a/solution/3200-3299/3234.Count the Number of Substrings With Dominant Ones/README.md b/solution/3200-3299/3234.Count the Number of Substrings With Dominant Ones/README.md new file mode 100644 index 000000000000..b10e2e00877e --- /dev/null +++ b/solution/3200-3299/3234.Count the Number of Substrings With Dominant Ones/README.md @@ -0,0 +1,200 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README.md +tags: + - 字符串 + - 枚举 + - 滑动窗口 +--- + + + +# [3234. 统计 1 显著的字符串的数量](https://leetcode.cn/problems/count-the-number-of-substrings-with-dominant-ones) + +[English Version](/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README_EN.md) + +## 题目描述 + + + +

            给你一个二进制字符串 s

            + +

            请你统计并返回其中 1 显著 子字符串 的数量。

            + +

            如果字符串中 1 的数量 大于或等于 0 的数量的 平方,则认为该字符串是一个 1 显著 的字符串 。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:s = "00011"

            + +

            输出:5

            + +

            解释:

            + +

            1 显著的子字符串如下表所示。

            +
            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            ijs[i..j]0 的数量1 的数量
            33101
            44101
            230111
            341102
            2401112
            + +

            示例 2:

            + +
            +

            输入:s = "101101"

            + +

            输出:16

            + +

            解释:

            + +

            1 不显著的子字符串如下表所示。

            + +

            总共有 21 个子字符串,其中 5 个是 1 不显著字符串,因此有 16 个 1 显著子字符串。

            +
            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            ijs[i..j]0 的数量1 的数量
            11010
            44010
            14011022
            041011023
            150110123
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= s.length <= 4 * 104
            • +
            • s 仅包含字符 '0''1'
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3234.Count the Number of Substrings With Dominant Ones/README_EN.md b/solution/3200-3299/3234.Count the Number of Substrings With Dominant Ones/README_EN.md new file mode 100644 index 000000000000..151fb87789c1 --- /dev/null +++ b/solution/3200-3299/3234.Count the Number of Substrings With Dominant Ones/README_EN.md @@ -0,0 +1,198 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README_EN.md +tags: + - String + - Enumeration + - Sliding Window +--- + + + +# [3234. Count the Number of Substrings With Dominant Ones](https://leetcode.com/problems/count-the-number-of-substrings-with-dominant-ones) + +[中文文档](/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README.md) + +## Description + + + +

            You are given a binary string s.

            + +

            Return the number of substrings with dominant ones.

            + +

            A string has dominant ones if the number of ones in the string is greater than or equal to the square of the number of zeros in the string.

            + +

             

            +

            Example 1:

            + +
            +

            Input: s = "00011"

            + +

            Output: 5

            + +

            Explanation:

            + +

            The substrings with dominant ones are shown in the table below.

            +
            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            ijs[i..j]Number of ZerosNumber of Ones
            33101
            44101
            230111
            341102
            2401112
            + +

            Example 2:

            + +
            +

            Input: s = "101101"

            + +

            Output: 16

            + +

            Explanation:

            + +

            The substrings with non-dominant ones are shown in the table below.

            + +

            Since there are 21 substrings total and 5 of them have non-dominant ones, it follows that there are 16 substrings with dominant ones.

            +
            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            ijs[i..j]Number of ZerosNumber of Ones
            11010
            44010
            14011022
            041011023
            150110123
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= s.length <= 4 * 104
            • +
            • s consists only of characters '0' and '1'.
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/README.md b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/README.md new file mode 100644 index 000000000000..1e5e11ea2294 --- /dev/null +++ b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/README.md @@ -0,0 +1,135 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README.md +tags: + - 深度优先搜索 + - 广度优先搜索 + - 并查集 + - 几何 + - 数组 + - 数学 +--- + + + +# [3235. 判断矩形的两个角落是否可达](https://leetcode.cn/problems/check-if-the-rectangle-corner-is-reachable) + +[English Version](/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README_EN.md) + +## 题目描述 + + + +

            给你两个正整数 xCorner 和 yCorner 和一个二维整数数组 circles ,其中 circles[i] = [xi, yi, ri] 表示一个圆心在 (xi, yi) 半径为 ri 的圆。

            + +

            坐标平面内有一个左下角在原点,右上角在 (xCorner, yCorner) 的矩形。你需要判断是否存在一条从左下角到右上角的路径满足:路径 完全 在矩形内部,不会 触碰或者经过 任何 圆的内部和边界,同时  在起点和终点接触到矩形。

            + +

            如果存在这样的路径,请你返回 true ,否则返回 false 。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:X = 3, Y = 4, circles = [[2,1,1]]

            + +

            输出:true

            + +

            解释:

            + +

            + +

            黑色曲线表示一条从 (0, 0) 到 (3, 4) 的路径。

            +
            + +

            示例 2:

            + +
            +

            输入:X = 3, Y = 3, circles = [[1,1,2]]

            + +

            输出:false

            + +

            解释:

            + +

            + +

            不存在从 (0, 0) 到 (3, 3) 的路径。

            +
            + +

            示例 3:

            + +
            +

            输入:X = 3, Y = 3, circles = [[2,1,1],[1,2,1]]

            + +

            输出:false

            + +

            解释:

            + +

            + +

            不存在从 (0, 0) 到 (3, 3) 的路径。

            +
            + +

            示例 4:

            + +
            +

            输入:X = 4, Y = 4, circles = [[5,5,1]]

            + +

            输出:true

            + +

            解释:

            + +

            +
            + +

             

            + +

            提示:

            + +
              +
            • 3 <= xCorner, yCorner <= 109
            • +
            • 1 <= circles.length <= 1000
            • +
            • circles[i].length == 3
            • +
            • 1 <= xi, yi, ri <= 109
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/README_EN.md b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/README_EN.md new file mode 100644 index 000000000000..0df33207445b --- /dev/null +++ b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/README_EN.md @@ -0,0 +1,133 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README_EN.md +tags: + - Depth-First Search + - Breadth-First Search + - Union Find + - Geometry + - Array + - Math +--- + + + +# [3235. Check if the Rectangle Corner Is Reachable](https://leetcode.com/problems/check-if-the-rectangle-corner-is-reachable) + +[中文文档](/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README.md) + +## Description + + + +

            You are given two positive integers xCorner and yCorner, and a 2D array circles, where circles[i] = [xi, yi, ri] denotes a circle with center at (xi, yi) and radius ri.

            + +

            There is a rectangle in the coordinate plane with its bottom left corner at the origin and top right corner at the coordinate (xCorner, yCorner). You need to check whether there is a path from the bottom left corner to the top right corner such that the entire path lies inside the rectangle, does not touch or lie inside any circle, and touches the rectangle only at the two corners.

            + +

            Return true if such a path exists, and false otherwise.

            + +

             

            +

            Example 1:

            + +
            +

            Input: xCorner = 3, yCorner = 4, circles = [[2,1,1]]

            + +

            Output: true

            + +

            Explanation:

            + +

            + +

            The black curve shows a possible path between (0, 0) and (3, 4).

            +
            + +

            Example 2:

            + +
            +

            Input: xCorner = 3, yCorner = 3, circles = [[1,1,2]]

            + +

            Output: false

            + +

            Explanation:

            + +

            + +

            No path exists from (0, 0) to (3, 3).

            +
            + +

            Example 3:

            + +
            +

            Input: xCorner = 3, yCorner = 3, circles = [[2,1,1],[1,2,1]]

            + +

            Output: false

            + +

            Explanation:

            + +

            + +

            No path exists from (0, 0) to (3, 3).

            +
            + +

            Example 4:

            + +
            +

            Input: xCorner = 4, yCorner = 4, circles = [[5,5,1]]

            + +

            Output: true

            + +

            Explanation:

            + +

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 3 <= xCorner, yCorner <= 109
            • +
            • 1 <= circles.length <= 1000
            • +
            • circles[i].length == 3
            • +
            • 1 <= xi, yi, ri <= 109
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example0circle.png b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example0circle.png new file mode 100644 index 000000000000..4a5b9ece9871 Binary files /dev/null and b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example0circle.png differ diff --git a/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example1circle.png b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example1circle.png new file mode 100644 index 000000000000..33d23ea8cafb Binary files /dev/null and b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example1circle.png differ diff --git a/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example2circle1.png b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example2circle1.png new file mode 100644 index 000000000000..ae08da9f8e29 Binary files /dev/null and b/solution/3200-3299/3235.Check if the Rectangle Corner Is Reachable/images/example2circle1.png differ diff --git a/solution/3200-3299/3236.CEO Subordinate Hierarchy/README.md b/solution/3200-3299/3236.CEO Subordinate Hierarchy/README.md new file mode 100644 index 000000000000..051e12d53965 --- /dev/null +++ b/solution/3200-3299/3236.CEO Subordinate Hierarchy/README.md @@ -0,0 +1,164 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README.md +tags: + - 数据库 +--- + + + +# [3236. 首席执行官下属层级 🔒](https://leetcode.cn/problems/ceo-subordinate-hierarchy) + +[English Version](/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README_EN.md) + +## 题目描述 + + + +

            表:Employees

            + +
            ++---------------+---------+
            +| Column Name   | Type    |
            ++---------------+---------+
            +| employee_id   | int     |
            +| employee_name | varchar |
            +| manager_id    | int     |
            +| salary        | int     |
            ++---------------+---------+
            +employee_id 是这张表的唯一标识符。
            +manager_id 是 employee_id 对应员工的经理。首席执行官的 manager_id 为 NULL。
            +
            + +

            编写一个解决方案来找到首席执行官的下属(直接 和 非直接),以及他们在 等级制度中的级别 以及与首席执行官的 薪资差异。结果应该包含下面的列:

            + +

            查询结果格式如下所示。

            + +
              +
            • subordinate_id:下属的 employee_id。
            • +
            • subordinate_name:下属的名字。
            • +
            • hierarchy_level:下属在等级制度中的级别(1 表示直接下属,2 表示 他们的直接下属以此类推。)
            • +
            • salary_difference:下属与首席执行官的薪资差异。
            • +
            + +

            返回结果表以 hierarchy_level 升序排序,然后按 subordinate_id 升序排序

            + +

            查询格式如下所示。

            + +

             

            + +

            示例:

            + +
            +

            输入:

            + +

            Employees 表:

            + +
            ++-------------+----------------+------------+---------+
            +| employee_id | employee_name  | manager_id | salary  |
            ++-------------+----------------+------------+---------+
            +| 1           | Alice          | NULL       | 150000  |
            +| 2           | Bob            | 1          | 120000  |
            +| 3           | Charlie        | 1          | 110000  |
            +| 4           | David          | 2          | 105000  |
            +| 5           | Eve            | 2          | 100000  |
            +| 6           | Frank          | 3          | 95000   |
            +| 7           | Grace          | 3          | 98000   |
            +| 8           | Helen          | 5          | 90000   |
            ++-------------+----------------+------------+---------+
            +
            + +

            输出:

            + +
            ++----------------+------------------+------------------+-------------------+
            +| subordinate_id | subordinate_name | hierarchy_level  | salary_difference |
            ++----------------+------------------+------------------+-------------------+
            +| 2              | Bob              | 1                | -30000            |
            +| 3              | Charlie          | 1                | -40000            |
            +| 4              | David            | 2                | -45000            |
            +| 5              | Eve              | 2                | -50000            |
            +| 6              | Frank            | 2                | -55000            |
            +| 7              | Grace            | 2                | -52000            |
            +| 8              | Helen            | 3                | -60000            |
            ++----------------+------------------+------------------+-------------------+
            +
            + +

            解释:

            + +
              +
            • Bob 和 Charlie 是 Alice 的直接下属(首席执行官)因此,hierarchy_level 为 1。
            • +
            • David 和 Eve 下属于 Bob,而 Frank 和 Grace 下属于 Charlie,因此他们是二级下属(hierarchy_level 为 2)。
            • +
            • Helen 下属于 Eve,因此 Helen 为三级下属(hierarchy_level 为 3)。
            • +
            • 薪资差异是相对于 Alice 的薪资 150000 计算的。
            • +
            • 结果先以 hierarchy_level 升序排序,然后以 subordinate_id 升序排序。
            • +
            + +

            注意:输出表先以 hierarchy_level 升序排序,然后以 subordinate_id 升序排序。

            +
            + + + +## 解法 + + + +### 方法一:递归 CTE + 连接 + +首先,我们使用递归 CTE 计算出每个员工的层级,其中 CEO 的层级为 0,将 `employee_id`、`employee_name`、`hierarchy_level`、`manager_id` 和 `salary` 保存到临时表 `T` 中。 + +然后,我们查询出 CEO 的薪资,将其保存到临时表 `P` 中。 + +最后,我们连接 `T` 和 `P` 表,计算出每个下属的薪资差异,并按照 `hierarchy_level` 和 `subordinate_id` 进行排序。 + + + +#### MySQL + +```sql +# Write your MySQL query statement below +WITH RECURSIVE + T AS ( + SELECT + employee_id, + employee_name, + 0 AS hierarchy_level, + manager_id, + salary + FROM Employees + WHERE manager_id IS NULL + UNION ALL + SELECT + e.employee_id, + e.employee_name, + hierarchy_level + 1 AS hierarchy_level, + e.manager_id, + e.salary + FROM + T t + JOIN Employees e ON t.employee_id = e.manager_id + ), + P AS ( + SELECT salary + FROM Employees + WHERE manager_id IS NULL + ) +SELECT + employee_id subordinate_id, + employee_name subordinate_name, + hierarchy_level, + t.salary - p.salary salary_difference +FROM + T t + JOIN P p +WHERE hierarchy_level != 0 +ORDER BY 3, 1; +``` + + + + + + diff --git a/solution/3200-3299/3236.CEO Subordinate Hierarchy/README_EN.md b/solution/3200-3299/3236.CEO Subordinate Hierarchy/README_EN.md new file mode 100644 index 000000000000..cef9919f8554 --- /dev/null +++ b/solution/3200-3299/3236.CEO Subordinate Hierarchy/README_EN.md @@ -0,0 +1,165 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README_EN.md +tags: + - Database +--- + + + +# [3236. CEO Subordinate Hierarchy 🔒](https://leetcode.com/problems/ceo-subordinate-hierarchy) + +[中文文档](/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README.md) + +## Description + + + +

            Table: Employees

            + +
            ++---------------+---------+
            +| Column Name   | Type    |
            ++---------------+---------+
            +| employee_id   | int     |
            +| employee_name | varchar |
            +| manager_id    | int     |
            +| salary        | int     |
            ++---------------+---------+
            +employee_id is the unique identifier for this table.
            +manager_id is the employee_id of the employee's manager. The CEO has a NULL manager_id.
            +
            + +

            Write a solution to find subordinates of the CEO (both direct and indirect), along with their level in the hierarchy and their salary difference from the CEO.

            + +

            The result should have the following columns:

            + +

            The query result format is in the following example.

            + +
              +
            • subordinate_id: The employee_id of the subordinate
            • +
            • subordinate_name: The name of the subordinate
            • +
            • hierarchy_level: The level of the subordinate in the hierarchy (1 for direct reports, 2 for their direct reports, and so on)
            • +
            • salary_difference: The difference between the subordinate's salary and the CEO's salary
            • +
            + +

            Return the result table ordered by hierarchy_level ascending, and then by subordinate_id ascending.

            + +

            The query result format is in the following example.

            + +

             

            +

            Example:

            + +
            +

            Input:

            + +

            Employees table:

            + +
            ++-------------+----------------+------------+---------+
            +| employee_id | employee_name  | manager_id | salary  |
            ++-------------+----------------+------------+---------+
            +| 1           | Alice          | NULL       | 150000  |
            +| 2           | Bob            | 1          | 120000  |
            +| 3           | Charlie        | 1          | 110000  |
            +| 4           | David          | 2          | 105000  |
            +| 5           | Eve            | 2          | 100000  |
            +| 6           | Frank          | 3          | 95000   |
            +| 7           | Grace          | 3          | 98000   |
            +| 8           | Helen          | 5          | 90000   |
            ++-------------+----------------+------------+---------+
            +
            + +

            Output:

            + +
            ++----------------+------------------+------------------+-------------------+
            +| subordinate_id | subordinate_name | hierarchy_level  | salary_difference |
            ++----------------+------------------+------------------+-------------------+
            +| 2              | Bob              | 1                | -30000            |
            +| 3              | Charlie          | 1                | -40000            |
            +| 4              | David            | 2                | -45000            |
            +| 5              | Eve              | 2                | -50000            |
            +| 6              | Frank            | 2                | -55000            |
            +| 7              | Grace            | 2                | -52000            |
            +| 8              | Helen            | 3                | -60000            |
            ++----------------+------------------+------------------+-------------------+
            +
            + +

            Explanation:

            + +
              +
            • Bob and Charlie are direct subordinates of Alice (CEO) and thus have a hierarchy_level of 1.
            • +
            • David and Eve report to Bob, while Frank and Grace report to Charlie, making them second-level subordinates (hierarchy_level 2).
            • +
            • Helen reports to Eve, making Helen a third-level subordinate (hierarchy_level 3).
            • +
            • Salary differences are calculated relative to Alice's salary of 150000.
            • +
            • The result is ordered by hierarchy_level ascending, and then by subordinate_id ascending.
            • +
            + +

            Note: The output is ordered first by hierarchy_level in ascending order, then by subordinate_id in ascending order.

            +
            + + + +## Solutions + + + +### Solution 1: Recursive CTE + Join + +First, we use a recursive CTE to calculate the hierarchy level of each employee, where the CEO's level is $0$. We save `employee_id`, `employee_name`, `hierarchy_level`, `manager_id`, and `salary` into a temporary table `T`. + +Then, we query the CEO's salary and save it into a temporary table `P`. + +Finally, we join tables `T` and `P` to calculate the salary difference for each subordinate, and sort by `hierarchy_level` and `subordinate_id`. + + + +#### MySQL + +```sql +# Write your MySQL query statement below +WITH RECURSIVE + T AS ( + SELECT + employee_id, + employee_name, + 0 AS hierarchy_level, + manager_id, + salary + FROM Employees + WHERE manager_id IS NULL + UNION ALL + SELECT + e.employee_id, + e.employee_name, + hierarchy_level + 1 AS hierarchy_level, + e.manager_id, + e.salary + FROM + T t + JOIN Employees e ON t.employee_id = e.manager_id + ), + P AS ( + SELECT salary + FROM Employees + WHERE manager_id IS NULL + ) +SELECT + employee_id subordinate_id, + employee_name subordinate_name, + hierarchy_level, + t.salary - p.salary salary_difference +FROM + T t + JOIN P p +WHERE hierarchy_level != 0 +ORDER BY 3, 1; +``` + + + + + + diff --git a/solution/3200-3299/3236.CEO Subordinate Hierarchy/Solution.sql b/solution/3200-3299/3236.CEO Subordinate Hierarchy/Solution.sql new file mode 100644 index 000000000000..7c91b6608841 --- /dev/null +++ b/solution/3200-3299/3236.CEO Subordinate Hierarchy/Solution.sql @@ -0,0 +1,37 @@ +# Write your MySQL query statement below +WITH RECURSIVE + T AS ( + SELECT + employee_id, + employee_name, + 0 AS hierarchy_level, + manager_id, + salary + FROM Employees + WHERE manager_id IS NULL + UNION ALL + SELECT + e.employee_id, + e.employee_name, + hierarchy_level + 1 AS hierarchy_level, + e.manager_id, + e.salary + FROM + T t + JOIN Employees e ON t.employee_id = e.manager_id + ), + P AS ( + SELECT salary + FROM Employees + WHERE manager_id IS NULL + ) +SELECT + employee_id subordinate_id, + employee_name subordinate_name, + hierarchy_level, + t.salary - p.salary salary_difference +FROM + T t + JOIN P p +WHERE hierarchy_level != 0 +ORDER BY 3, 1; diff --git a/solution/3200-3299/3237.Alt and Tab Simulation/README.md b/solution/3200-3299/3237.Alt and Tab Simulation/README.md new file mode 100644 index 000000000000..6f3581ae4ecf --- /dev/null +++ b/solution/3200-3299/3237.Alt and Tab Simulation/README.md @@ -0,0 +1,212 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3237.Alt%20and%20Tab%20Simulation/README.md +tags: + - 数组 + - 哈希表 + - 模拟 +--- + + + +# [3237. Alt 和 Tab 模拟 🔒](https://leetcode.cn/problems/alt-and-tab-simulation) + +[English Version](/solution/3200-3299/3237.Alt%20and%20Tab%20Simulation/README_EN.md) + +## 题目描述 + + + +

            有 n 个编号从  1 到 n 的打开的窗口,我们想要模拟使用 alt + tab 键在窗口之间导航。

            + +

            给定数组 windows 包含窗口的初始顺序(第一个元素在最前面,最后一个元素在最后面)。

            + +

            同时给定数组 queries 表示每一次查询中,编号为 queries[i] 的窗口被切换到最前面。

            + +

            返回 windows 数组的最后状态。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:windows = [1,2,3], queries = [3,3,2]

            + +

            输出:[2,3,1]

            + +

            解释:

            + +

            以下是每次查询后的 windows 数组:

            + +
              +
            • 初始顺序:[1,2,3]
            • +
            • 第一次查询后:[3,1,2]
            • +
            • 第二次查询后:[3,1,2]
            • +
            • 最后一次查询后:[2,3,1]
            • +
            +
            + +

            示例 2:

            + +
            +

            输入:windows = [1,4,2,3], queries = [4,1,3]

            + +

            输出:[3,1,4,2]

            + +

            解释:

            + +

            以下是每次查询后的 windows 数组:

            + +
              +
            • 初始顺序:[1,4,2,3]
            • +
            • 第一次查询后:[4,1,2,3]
            • +
            • 第二次查询后:[1,4,2,3]
            • +
            • 最后一次查询后:[3,1,4,2]
            • +
            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n == windows.length <= 105
            • +
            • windows 是 [1, n] 的一个排列。
            • +
            • 1 <= queries.length <= 105
            • +
            • 1 <= queries[i] <= n
            • +
            + + + +## 解法 + + + +### 方法一:哈希表 + 逆序遍历 + +根据题目描述,越是后面的查询,越是出现在最前面的位置。因此,我们可以逆序遍历 $\textit{queries}$ 数组,用一个哈希表 $\textit{s}$ 记录已经出现过的窗口。对于每一个查询,如果当前窗口不在哈希表中,我们将其加入答案数组,并将其加入哈希表中。最后,我们再次遍历 $\textit{windows}$ 数组,将不在哈希表中的窗口加入答案数组。 + +时间复杂度 $O(n + m)$,空间复杂度 $O(m)$。其中 $n$ 和 $m$ 分别为 $\textit{windows}$ 和 $\textit{queries}$ 数组的长度。 + + + +#### Python3 + +```python +class Solution: + def simulationResult(self, windows: List[int], queries: List[int]) -> List[int]: + s = set() + ans = [] + for q in queries[::-1]: + if q not in s: + ans.append(q) + s.add(q) + for w in windows: + if w not in s: + ans.append(w) + return ans +``` + +#### Java + +```java +class Solution { + public int[] simulationResult(int[] windows, int[] queries) { + int n = windows.length; + boolean[] s = new boolean[n + 1]; + int[] ans = new int[n]; + int k = 0; + for (int i = queries.length - 1; i >= 0; --i) { + int q = queries[i]; + if (!s[q]) { + ans[k++] = q; + s[q] = true; + } + } + for (int w : windows) { + if (!s[w]) { + ans[k++] = w; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector simulationResult(vector& windows, vector& queries) { + int n = windows.size(); + vector s(n + 1); + vector ans; + for (int i = queries.size() - 1; ~i; --i) { + int q = queries[i]; + if (!s[q]) { + s[q] = true; + ans.push_back(q); + } + } + for (int w : windows) { + if (!s[w]) { + ans.push_back(w); + } + } + return ans; + } +}; +``` + +#### Go + +```go +func simulationResult(windows []int, queries []int) (ans []int) { + n := len(windows) + s := make([]bool, n+1) + for i := len(queries) - 1; i >= 0; i-- { + q := queries[i] + if !s[q] { + s[q] = true + ans = append(ans, q) + } + } + for _, w := range windows { + if !s[w] { + ans = append(ans, w) + } + } + return +} +``` + +#### TypeScript + +```ts +function simulationResult(windows: number[], queries: number[]): number[] { + const n = windows.length; + const s: boolean[] = Array(n + 1).fill(false); + const ans: number[] = []; + for (let i = queries.length - 1; i >= 0; i--) { + const q = queries[i]; + if (!s[q]) { + s[q] = true; + ans.push(q); + } + } + for (const w of windows) { + if (!s[w]) { + ans.push(w); + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3237.Alt and Tab Simulation/README_EN.md b/solution/3200-3299/3237.Alt and Tab Simulation/README_EN.md new file mode 100644 index 000000000000..e0d8df3519a4 --- /dev/null +++ b/solution/3200-3299/3237.Alt and Tab Simulation/README_EN.md @@ -0,0 +1,210 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3237.Alt%20and%20Tab%20Simulation/README_EN.md +tags: + - Array + - Hash Table + - Simulation +--- + + + +# [3237. Alt and Tab Simulation 🔒](https://leetcode.com/problems/alt-and-tab-simulation) + +[中文文档](/solution/3200-3299/3237.Alt%20and%20Tab%20Simulation/README.md) + +## Description + + + +

            There are n windows open numbered from 1 to n, we want to simulate using alt + tab to navigate between the windows.

            + +

            You are given an array windows which contains the initial order of the windows (the first element is at the top and the last one is at the bottom).

            + +

            You are also given an array queries where for each query, the window queries[i] is brought to the top.

            + +

            Return the final state of the array windows.

            + +

             

            +

            Example 1:

            + +
            +

            Input: windows = [1,2,3], queries = [3,3,2]

            + +

            Output: [2,3,1]

            + +

            Explanation:

            + +

            Here is the window array after each query:

            + +
              +
            • Initial order: [1,2,3]
            • +
            • After the first query: [3,1,2]
            • +
            • After the second query: [3,1,2]
            • +
            • After the last query: [2,3,1]
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: windows = [1,4,2,3], queries = [4,1,3]

            + +

            Output: [3,1,4,2]

            + +

            Explanation:

            + +

            Here is the window array after each query:

            + +
              +
            • Initial order: [1,4,2,3]
            • +
            • After the first query: [4,1,2,3]
            • +
            • After the second query: [1,4,2,3]
            • +
            • After the last query: [3,1,4,2]
            • +
            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n == windows.length <= 105
            • +
            • windows is a permutation of [1, n].
            • +
            • 1 <= queries.length <= 105
            • +
            • 1 <= queries[i] <= n
            • +
            + + + +## Solutions + + + +### Solution 1: Hash Table + Reverse Traversal + +According to the problem description, the later the query, the earlier it appears in the result. Therefore, we can traverse the $\textit{queries}$ array in reverse order, using a hash table $\textit{s}$ to record the windows that have already appeared. For each query, if the current window is not in the hash table, we add it to the answer array and also add it to the hash table. Finally, we traverse the $\textit{windows}$ array again, adding the windows that are not in the hash table to the answer array. + +The time complexity is $O(n + m)$, and the space complexity is $O(m)$. Here, $n$ and $m$ are the lengths of the $\textit{windows}$ and $\textit{queries}$ arrays, respectively. + + + +#### Python3 + +```python +class Solution: + def simulationResult(self, windows: List[int], queries: List[int]) -> List[int]: + s = set() + ans = [] + for q in queries[::-1]: + if q not in s: + ans.append(q) + s.add(q) + for w in windows: + if w not in s: + ans.append(w) + return ans +``` + +#### Java + +```java +class Solution { + public int[] simulationResult(int[] windows, int[] queries) { + int n = windows.length; + boolean[] s = new boolean[n + 1]; + int[] ans = new int[n]; + int k = 0; + for (int i = queries.length - 1; i >= 0; --i) { + int q = queries[i]; + if (!s[q]) { + ans[k++] = q; + s[q] = true; + } + } + for (int w : windows) { + if (!s[w]) { + ans[k++] = w; + } + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector simulationResult(vector& windows, vector& queries) { + int n = windows.size(); + vector s(n + 1); + vector ans; + for (int i = queries.size() - 1; ~i; --i) { + int q = queries[i]; + if (!s[q]) { + s[q] = true; + ans.push_back(q); + } + } + for (int w : windows) { + if (!s[w]) { + ans.push_back(w); + } + } + return ans; + } +}; +``` + +#### Go + +```go +func simulationResult(windows []int, queries []int) (ans []int) { + n := len(windows) + s := make([]bool, n+1) + for i := len(queries) - 1; i >= 0; i-- { + q := queries[i] + if !s[q] { + s[q] = true + ans = append(ans, q) + } + } + for _, w := range windows { + if !s[w] { + ans = append(ans, w) + } + } + return +} +``` + +#### TypeScript + +```ts +function simulationResult(windows: number[], queries: number[]): number[] { + const n = windows.length; + const s: boolean[] = Array(n + 1).fill(false); + const ans: number[] = []; + for (let i = queries.length - 1; i >= 0; i--) { + const q = queries[i]; + if (!s[q]) { + s[q] = true; + ans.push(q); + } + } + for (const w of windows) { + if (!s[w]) { + ans.push(w); + } + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3237.Alt and Tab Simulation/Solution.cpp b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.cpp new file mode 100644 index 000000000000..514d3f2af7b2 --- /dev/null +++ b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.cpp @@ -0,0 +1,21 @@ +class Solution { +public: + vector simulationResult(vector& windows, vector& queries) { + int n = windows.size(); + vector s(n + 1); + vector ans; + for (int i = queries.size() - 1; ~i; --i) { + int q = queries[i]; + if (!s[q]) { + s[q] = true; + ans.push_back(q); + } + } + for (int w : windows) { + if (!s[w]) { + ans.push_back(w); + } + } + return ans; + } +}; diff --git a/solution/3200-3299/3237.Alt and Tab Simulation/Solution.go b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.go new file mode 100644 index 000000000000..ee25d0095980 --- /dev/null +++ b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.go @@ -0,0 +1,17 @@ +func simulationResult(windows []int, queries []int) (ans []int) { + n := len(windows) + s := make([]bool, n+1) + for i := len(queries) - 1; i >= 0; i-- { + q := queries[i] + if !s[q] { + s[q] = true + ans = append(ans, q) + } + } + for _, w := range windows { + if !s[w] { + ans = append(ans, w) + } + } + return +} diff --git a/solution/3200-3299/3237.Alt and Tab Simulation/Solution.java b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.java new file mode 100644 index 000000000000..e40e3edac837 --- /dev/null +++ b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.java @@ -0,0 +1,21 @@ +class Solution { + public int[] simulationResult(int[] windows, int[] queries) { + int n = windows.length; + boolean[] s = new boolean[n + 1]; + int[] ans = new int[n]; + int k = 0; + for (int i = queries.length - 1; i >= 0; --i) { + int q = queries[i]; + if (!s[q]) { + ans[k++] = q; + s[q] = true; + } + } + for (int w : windows) { + if (!s[w]) { + ans[k++] = w; + } + } + return ans; + } +} diff --git a/solution/3200-3299/3237.Alt and Tab Simulation/Solution.py b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.py new file mode 100644 index 000000000000..a04a70ff8d8f --- /dev/null +++ b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.py @@ -0,0 +1,12 @@ +class Solution: + def simulationResult(self, windows: List[int], queries: List[int]) -> List[int]: + s = set() + ans = [] + for q in queries[::-1]: + if q not in s: + ans.append(q) + s.add(q) + for w in windows: + if w not in s: + ans.append(w) + return ans diff --git a/solution/3200-3299/3237.Alt and Tab Simulation/Solution.ts b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.ts new file mode 100644 index 000000000000..b9cc684a6b0d --- /dev/null +++ b/solution/3200-3299/3237.Alt and Tab Simulation/Solution.ts @@ -0,0 +1,18 @@ +function simulationResult(windows: number[], queries: number[]): number[] { + const n = windows.length; + const s: boolean[] = Array(n + 1).fill(false); + const ans: number[] = []; + for (let i = queries.length - 1; i >= 0; i--) { + const q = queries[i]; + if (!s[q]) { + s[q] = true; + ans.push(q); + } + } + for (const w of windows) { + if (!s[w]) { + ans.push(w); + } + } + return ans; +} diff --git a/solution/3200-3299/3238.Find the Number of Winning Players/README.md b/solution/3200-3299/3238.Find the Number of Winning Players/README.md new file mode 100644 index 000000000000..bae3d97464d2 --- /dev/null +++ b/solution/3200-3299/3238.Find the Number of Winning Players/README.md @@ -0,0 +1,191 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README.md +tags: + - 数组 + - 哈希表 + - 计数 +--- + + + +# [3238. 求出胜利玩家的数目](https://leetcode.cn/problems/find-the-number-of-winning-players) + +[English Version](/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README_EN.md) + +## 题目描述 + + + +

            给你一个整数 n ,表示在一个游戏中的玩家数目。同时给你一个二维整数数组 pick ,其中 pick[i] = [xi, yi] 表示玩家 xi 获得了一个颜色为 yi 的球。

            + +

            如果玩家 i 获得的球中任何一种颜色球的数目 严格大于 i 个,那么我们说玩家 i 是胜利玩家。换句话说:

            + +
              +
            • 如果玩家 0 获得了任何的球,那么玩家 0 是胜利玩家。
            • +
            • 如果玩家 1 获得了至少 2 个相同颜色的球,那么玩家 1 是胜利玩家。
            • +
            • ...
            • +
            • 如果玩家 i 获得了至少 i + 1 个相同颜色的球,那么玩家 i 是胜利玩家。
            • +
            + +

            请你返回游戏中 胜利玩家 的数目。

            + +

            注意,可能有多个玩家是胜利玩家。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:n = 4, pick = [[0,0],[1,0],[1,0],[2,1],[2,1],[2,0]]

            + +

            输出:2

            + +

            解释:

            + +

            玩家 0 和玩家 1 是胜利玩家,玩家 2 和玩家 3 不是胜利玩家。

            +
            + +

            示例 2:

            + +
            +

            输入:n = 5, pick = [[1,1],[1,2],[1,3],[1,4]]

            + +

            输出:0

            + +

            解释:

            + +

            没有胜利玩家。

            +
            + +

            示例 3:

            + +
            +

            输入:n = 5, pick = [[1,1],[2,4],[2,4],[2,4]]

            + +

            输出:1

            + +

            解释:

            + +

            玩家 2 是胜利玩家,因为玩家 2 获得了 3 个颜色为 4 的球。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 2 <= n <= 10
            • +
            • 1 <= pick.length <= 100
            • +
            • pick[i].length == 2
            • +
            • 0 <= xi <= n - 1
            • +
            • 0 <= yi <= 10
            • +
            + + + +## 解法 + + + +### 方法一:计数 + +我们可以用一个二维数组 $\textit{cnt}$ 记录每个玩家获得的每种颜色球的数量,用一个哈希表 $\textit{s}$ 记录胜利玩家的编号。 + +遍历 $\textit{pick}$ 数组,对于每个元素 $[x, y]$,我们将 $\textit{cnt}[x][y]$ 加一,如果 $\textit{cnt}[x][y]$ 大于 $x$,则将 $x$ 加入哈希表 $\textit{s}$。 + +最后返回哈希表 $\textit{s}$ 的大小即可。 + +时间复杂度 $O(m + n \times M)$,空间复杂度 $O(n \times M)$。其中 $m$ 为 $\textit{pick}$ 数组的长度,而 $n$ 和 $M$ 分别为玩家数目和颜色数目。 + + + +#### Python3 + +```python +class Solution: + def winningPlayerCount(self, n: int, pick: List[List[int]]) -> int: + cnt = [[0] * 11 for _ in range(n)] + s = set() + for x, y in pick: + cnt[x][y] += 1 + if cnt[x][y] > x: + s.add(x) + return len(s) +``` + +#### Java + +```java +class Solution { + public int winningPlayerCount(int n, int[][] pick) { + int[][] cnt = new int[n][11]; + Set s = new HashSet<>(); + for (var p : pick) { + int x = p[0], y = p[1]; + if (++cnt[x][y] > x) { + s.add(x); + } + } + return s.size(); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int winningPlayerCount(int n, vector>& pick) { + int cnt[10][11]{}; + unordered_set s; + for (const auto& p : pick) { + int x = p[0], y = p[1]; + if (++cnt[x][y] > x) { + s.insert(x); + } + } + return s.size(); + } +}; +``` + +#### Go + +```go +func winningPlayerCount(n int, pick [][]int) int { + cnt := make([][11]int, n) + s := map[int]struct{}{} + for _, p := range pick { + x, y := p[0], p[1] + cnt[x][y]++ + if cnt[x][y] > x { + s[x] = struct{}{} + } + } + return len(s) +} +``` + +#### TypeScript + +```ts +function winningPlayerCount(n: number, pick: number[][]): number { + const cnt: number[][] = Array.from({ length: n }, () => Array(11).fill(0)); + const s = new Set(); + for (const [x, y] of pick) { + if (++cnt[x][y] > x) { + s.add(x); + } + } + return s.size; +} +``` + + + + + + diff --git a/solution/3200-3299/3238.Find the Number of Winning Players/README_EN.md b/solution/3200-3299/3238.Find the Number of Winning Players/README_EN.md new file mode 100644 index 000000000000..19b2f73e562a --- /dev/null +++ b/solution/3200-3299/3238.Find the Number of Winning Players/README_EN.md @@ -0,0 +1,189 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README_EN.md +tags: + - Array + - Hash Table + - Counting +--- + + + +# [3238. Find the Number of Winning Players](https://leetcode.com/problems/find-the-number-of-winning-players) + +[中文文档](/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README.md) + +## Description + + + +

            You are given an integer n representing the number of players in a game and a 2D array pick where pick[i] = [xi, yi] represents that the player xi picked a ball of color yi.

            + +

            Player i wins the game if they pick strictly more than i balls of the same color. In other words,

            + +
              +
            • Player 0 wins if they pick any ball.
            • +
            • Player 1 wins if they pick at least two balls of the same color.
            • +
            • ...
            • +
            • Player i wins if they pick at leasti + 1 balls of the same color.
            • +
            + +

            Return the number of players who win the game.

            + +

            Note that multiple players can win the game.

            + +

             

            +

            Example 1:

            + +
            +

            Input: n = 4, pick = [[0,0],[1,0],[1,0],[2,1],[2,1],[2,0]]

            + +

            Output: 2

            + +

            Explanation:

            + +

            Player 0 and player 1 win the game, while players 2 and 3 do not win.

            +
            + +

            Example 2:

            + +
            +

            Input: n = 5, pick = [[1,1],[1,2],[1,3],[1,4]]

            + +

            Output: 0

            + +

            Explanation:

            + +

            No player wins the game.

            +
            + +

            Example 3:

            + +
            +

            Input: n = 5, pick = [[1,1],[2,4],[2,4],[2,4]]

            + +

            Output: 1

            + +

            Explanation:

            + +

            Player 2 wins the game by picking 3 balls with color 4.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 2 <= n <= 10
            • +
            • 1 <= pick.length <= 100
            • +
            • pick[i].length == 2
            • +
            • 0 <= xi <= n - 1
            • +
            • 0 <= yi <= 10
            • +
            + + + +## Solutions + + + +### Solution 1: Counting + +We can use a 2D array $\textit{cnt}$ to record the number of balls of each color obtained by each player, and a hash table $\textit{s}$ to record the IDs of the winning players. + +Traverse the $\textit{pick}$ array, for each element $[x, y]$, we increment $\textit{cnt}[x][y]$ by one. If $\textit{cnt}[x][y]$ is greater than $x$, we add $x$ to the hash table $\textit{s}$. + +Finally, return the size of the hash table $\textit{s}$. + +The time complexity is $O(m + n \times M)$, and the space complexity is $O(n \times M)$. Here, $m$ is the length of the $\textit{pick}$ array, and $n$ and $M$ are the number of players and the number of colors, respectively. + + + +#### Python3 + +```python +class Solution: + def winningPlayerCount(self, n: int, pick: List[List[int]]) -> int: + cnt = [[0] * 11 for _ in range(n)] + s = set() + for x, y in pick: + cnt[x][y] += 1 + if cnt[x][y] > x: + s.add(x) + return len(s) +``` + +#### Java + +```java +class Solution { + public int winningPlayerCount(int n, int[][] pick) { + int[][] cnt = new int[n][11]; + Set s = new HashSet<>(); + for (var p : pick) { + int x = p[0], y = p[1]; + if (++cnt[x][y] > x) { + s.add(x); + } + } + return s.size(); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int winningPlayerCount(int n, vector>& pick) { + int cnt[10][11]{}; + unordered_set s; + for (const auto& p : pick) { + int x = p[0], y = p[1]; + if (++cnt[x][y] > x) { + s.insert(x); + } + } + return s.size(); + } +}; +``` + +#### Go + +```go +func winningPlayerCount(n int, pick [][]int) int { + cnt := make([][11]int, n) + s := map[int]struct{}{} + for _, p := range pick { + x, y := p[0], p[1] + cnt[x][y]++ + if cnt[x][y] > x { + s[x] = struct{}{} + } + } + return len(s) +} +``` + +#### TypeScript + +```ts +function winningPlayerCount(n: number, pick: number[][]): number { + const cnt: number[][] = Array.from({ length: n }, () => Array(11).fill(0)); + const s = new Set(); + for (const [x, y] of pick) { + if (++cnt[x][y] > x) { + s.add(x); + } + } + return s.size; +} +``` + + + + + + diff --git a/solution/3200-3299/3238.Find the Number of Winning Players/Solution.cpp b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.cpp new file mode 100644 index 000000000000..48375dca9c15 --- /dev/null +++ b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + int winningPlayerCount(int n, vector>& pick) { + int cnt[10][11]{}; + unordered_set s; + for (const auto& p : pick) { + int x = p[0], y = p[1]; + if (++cnt[x][y] > x) { + s.insert(x); + } + } + return s.size(); + } +}; diff --git a/solution/3200-3299/3238.Find the Number of Winning Players/Solution.go b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.go new file mode 100644 index 000000000000..b45604ea2ccc --- /dev/null +++ b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.go @@ -0,0 +1,12 @@ +func winningPlayerCount(n int, pick [][]int) int { + cnt := make([][11]int, n) + s := map[int]struct{}{} + for _, p := range pick { + x, y := p[0], p[1] + cnt[x][y]++ + if cnt[x][y] > x { + s[x] = struct{}{} + } + } + return len(s) +} diff --git a/solution/3200-3299/3238.Find the Number of Winning Players/Solution.java b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.java new file mode 100644 index 000000000000..33814f49dc87 --- /dev/null +++ b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.java @@ -0,0 +1,13 @@ +class Solution { + public int winningPlayerCount(int n, int[][] pick) { + int[][] cnt = new int[n][11]; + Set s = new HashSet<>(); + for (var p : pick) { + int x = p[0], y = p[1]; + if (++cnt[x][y] > x) { + s.add(x); + } + } + return s.size(); + } +} diff --git a/solution/3200-3299/3238.Find the Number of Winning Players/Solution.py b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.py new file mode 100644 index 000000000000..db936dbdb0c9 --- /dev/null +++ b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.py @@ -0,0 +1,9 @@ +class Solution: + def winningPlayerCount(self, n: int, pick: List[List[int]]) -> int: + cnt = [[0] * 11 for _ in range(n)] + s = set() + for x, y in pick: + cnt[x][y] += 1 + if cnt[x][y] > x: + s.add(x) + return len(s) diff --git a/solution/3200-3299/3238.Find the Number of Winning Players/Solution.ts b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.ts new file mode 100644 index 000000000000..2d81f3042db8 --- /dev/null +++ b/solution/3200-3299/3238.Find the Number of Winning Players/Solution.ts @@ -0,0 +1,10 @@ +function winningPlayerCount(n: number, pick: number[][]): number { + const cnt: number[][] = Array.from({ length: n }, () => Array(11).fill(0)); + const s = new Set(); + for (const [x, y] of pick) { + if (++cnt[x][y] > x) { + s.add(x); + } + } + return s.size; +} diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/README.md b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/README.md new file mode 100644 index 000000000000..f8d540b9b68a --- /dev/null +++ b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/README.md @@ -0,0 +1,219 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README.md +tags: + - 数组 + - 双指针 + - 矩阵 +--- + + + +# [3239. 最少翻转次数使二进制矩阵回文 I](https://leetcode.cn/problems/minimum-number-of-flips-to-make-binary-grid-palindromic-i) + +[English Version](/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README_EN.md) + +## 题目描述 + + + +

            给你一个 m x n 的二进制矩阵 grid 。

            + +

            如果矩阵中一行或者一列从前往后与从后往前读是一样的,那么我们称这一行或者这一列是 回文 的。

            + +

            你可以将 grid 中任意格子的值 翻转 ,也就是将格子里的值从 0 变成 1 ,或者从 1 变成 0 。

            + +

            请你返回 最少 翻转次数,使得矩阵 要么 所有行是 回文的 ,要么所有列是 回文的 。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:grid = [[1,0,0],[0,0,0],[0,0,1]]

            + +

            输出:2

            + +

            解释:

            + +

            + +

            将高亮的格子翻转,得到所有行都是回文的。

            +
            + +

            示例 2:

            + +
            +

            输入:grid = [[0,1],[0,1],[0,0]]

            + +

            输出:1

            + +

            解释:

            + +

            + +

            将高亮的格子翻转,得到所有列都是回文的。

            +
            + +

            示例 3:

            + +
            +

            输入:grid = [[1],[0]]

            + +

            输出:0

            + +

            解释:

            + +

            所有行已经是回文的。

            +
            + +

             

            + +

            提示:

            + +
              +
            • m == grid.length
            • +
            • n == grid[i].length
            • +
            • 1 <= m * n <= 2 * 105
            • +
            • 0 <= grid[i][j] <= 1
            • +
            + + + +## 解法 + + + +### 方法一:计数 + +我们分别计算行和列的翻转次数,记为 $\textit{cnt1}$ 和 $\textit{cnt2}$,最后取二者的最小值即可。 + +时间复杂度 $O(m \times n)$,其中 $m$ 和 $n$ 分别是矩阵 $\textit{grid}$ 的行数和列数。 + + + +#### Python3 + +```python +class Solution: + def minFlips(self, grid: List[List[int]]) -> int: + m, n = len(grid), len(grid[0]) + cnt1 = cnt2 = 0 + for row in grid: + for j in range(n // 2): + if row[j] != row[n - j - 1]: + cnt1 += 1 + for j in range(n): + for i in range(m // 2): + if grid[i][j] != grid[m - i - 1][j]: + cnt2 += 1 + return min(cnt1, cnt2) +``` + +#### Java + +```java +class Solution { + public int minFlips(int[][] grid) { + int m = grid.length, n = grid[0].length; + int cnt1 = 0, cnt2 = 0; + for (var row : grid) { + for (int j = 0; j < n / 2; ++j) { + if (row[j] != row[n - j - 1]) { + ++cnt1; + } + } + } + for (int j = 0; j < n; ++j) { + for (int i = 0; i < m / 2; ++i) { + if (grid[i][j] != grid[m - i - 1][j]) { + ++cnt2; + } + } + } + return Math.min(cnt1, cnt2); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minFlips(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + int cnt1 = 0, cnt2 = 0; + for (const auto& row : grid) { + for (int j = 0; j < n / 2; ++j) { + if (row[j] != row[n - j - 1]) { + ++cnt1; + } + } + } + for (int j = 0; j < n; ++j) { + for (int i = 0; i < m / 2; ++i) { + if (grid[i][j] != grid[m - i - 1][j]) { + ++cnt2; + } + } + } + return min(cnt1, cnt2); + } +}; +``` + +#### Go + +```go +func minFlips(grid [][]int) int { + m, n := len(grid), len(grid[0]) + cnt1, cnt2 := 0, 0 + for _, row := range grid { + for j := 0; j < n/2; j++ { + if row[j] != row[n-j-1] { + cnt1++ + } + } + } + for j := 0; j < n; j++ { + for i := 0; i < m/2; i++ { + if grid[i][j] != grid[m-i-1][j] { + cnt2++ + } + } + } + return min(cnt1, cnt2) +} +``` + +#### TypeScript + +```ts +function minFlips(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + let [cnt1, cnt2] = [0, 0]; + for (const row of grid) { + for (let j = 0; j < n / 2; ++j) { + if (row[j] !== row[n - 1 - j]) { + ++cnt1; + } + } + } + for (let j = 0; j < n; ++j) { + for (let i = 0; i < m / 2; ++i) { + if (grid[i][j] !== grid[m - 1 - i][j]) { + ++cnt2; + } + } + } + return Math.min(cnt1, cnt2); +} +``` + + + + + + diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/README_EN.md b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/README_EN.md new file mode 100644 index 000000000000..0ead14996500 --- /dev/null +++ b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/README_EN.md @@ -0,0 +1,217 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README_EN.md +tags: + - Array + - Two Pointers + - Matrix +--- + + + +# [3239. Minimum Number of Flips to Make Binary Grid Palindromic I](https://leetcode.com/problems/minimum-number-of-flips-to-make-binary-grid-palindromic-i) + +[中文文档](/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README.md) + +## Description + + + +

            You are given an m x n binary matrix grid.

            + +

            A row or column is considered palindromic if its values read the same forward and backward.

            + +

            You can flip any number of cells in grid from 0 to 1, or from 1 to 0.

            + +

            Return the minimum number of cells that need to be flipped to make either all rows palindromic or all columns palindromic.

            + +

             

            +

            Example 1:

            + +
            +

            Input: grid = [[1,0,0],[0,0,0],[0,0,1]]

            + +

            Output: 2

            + +

            Explanation:

            + +

            + +

            Flipping the highlighted cells makes all the rows palindromic.

            +
            + +

            Example 2:

            + +
            +

            Input: grid = [[0,1],[0,1],[0,0]]

            + +

            Output: 1

            + +

            Explanation:

            + +

            + +

            Flipping the highlighted cell makes all the columns palindromic.

            +
            + +

            Example 3:

            + +
            +

            Input: grid = [[1],[0]]

            + +

            Output: 0

            + +

            Explanation:

            + +

            All rows are already palindromic.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • m == grid.length
            • +
            • n == grid[i].length
            • +
            • 1 <= m * n <= 2 * 105
            • +
            • 0 <= grid[i][j] <= 1
            • +
            + + + +## Solutions + + + +### Solution 1: Counting + +We separately count the number of flips for rows and columns, denoted as $\textit{cnt1}$ and $\textit{cnt2}$, respectively. Finally, we take the minimum of the two. + +The time complexity is $O(m \times n)$, where $m$ and $n$ are the number of rows and columns of the matrix $\textit{grid}$, respectively. + + + +#### Python3 + +```python +class Solution: + def minFlips(self, grid: List[List[int]]) -> int: + m, n = len(grid), len(grid[0]) + cnt1 = cnt2 = 0 + for row in grid: + for j in range(n // 2): + if row[j] != row[n - j - 1]: + cnt1 += 1 + for j in range(n): + for i in range(m // 2): + if grid[i][j] != grid[m - i - 1][j]: + cnt2 += 1 + return min(cnt1, cnt2) +``` + +#### Java + +```java +class Solution { + public int minFlips(int[][] grid) { + int m = grid.length, n = grid[0].length; + int cnt1 = 0, cnt2 = 0; + for (var row : grid) { + for (int j = 0; j < n / 2; ++j) { + if (row[j] != row[n - j - 1]) { + ++cnt1; + } + } + } + for (int j = 0; j < n; ++j) { + for (int i = 0; i < m / 2; ++i) { + if (grid[i][j] != grid[m - i - 1][j]) { + ++cnt2; + } + } + } + return Math.min(cnt1, cnt2); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int minFlips(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + int cnt1 = 0, cnt2 = 0; + for (const auto& row : grid) { + for (int j = 0; j < n / 2; ++j) { + if (row[j] != row[n - j - 1]) { + ++cnt1; + } + } + } + for (int j = 0; j < n; ++j) { + for (int i = 0; i < m / 2; ++i) { + if (grid[i][j] != grid[m - i - 1][j]) { + ++cnt2; + } + } + } + return min(cnt1, cnt2); + } +}; +``` + +#### Go + +```go +func minFlips(grid [][]int) int { + m, n := len(grid), len(grid[0]) + cnt1, cnt2 := 0, 0 + for _, row := range grid { + for j := 0; j < n/2; j++ { + if row[j] != row[n-j-1] { + cnt1++ + } + } + } + for j := 0; j < n; j++ { + for i := 0; i < m/2; i++ { + if grid[i][j] != grid[m-i-1][j] { + cnt2++ + } + } + } + return min(cnt1, cnt2) +} +``` + +#### TypeScript + +```ts +function minFlips(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + let [cnt1, cnt2] = [0, 0]; + for (const row of grid) { + for (let j = 0; j < n / 2; ++j) { + if (row[j] !== row[n - 1 - j]) { + ++cnt1; + } + } + } + for (let j = 0; j < n; ++j) { + for (let i = 0; i < m / 2; ++i) { + if (grid[i][j] !== grid[m - 1 - i][j]) { + ++cnt2; + } + } + } + return Math.min(cnt1, cnt2); +} +``` + + + + + + diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.cpp b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.cpp new file mode 100644 index 000000000000..426991d95278 --- /dev/null +++ b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.cpp @@ -0,0 +1,22 @@ +class Solution { +public: + int minFlips(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + int cnt1 = 0, cnt2 = 0; + for (const auto& row : grid) { + for (int j = 0; j < n / 2; ++j) { + if (row[j] != row[n - j - 1]) { + ++cnt1; + } + } + } + for (int j = 0; j < n; ++j) { + for (int i = 0; i < m / 2; ++i) { + if (grid[i][j] != grid[m - i - 1][j]) { + ++cnt2; + } + } + } + return min(cnt1, cnt2); + } +}; diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.go b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.go new file mode 100644 index 000000000000..8d6a4cf7583b --- /dev/null +++ b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.go @@ -0,0 +1,19 @@ +func minFlips(grid [][]int) int { + m, n := len(grid), len(grid[0]) + cnt1, cnt2 := 0, 0 + for _, row := range grid { + for j := 0; j < n/2; j++ { + if row[j] != row[n-j-1] { + cnt1++ + } + } + } + for j := 0; j < n; j++ { + for i := 0; i < m/2; i++ { + if grid[i][j] != grid[m-i-1][j] { + cnt2++ + } + } + } + return min(cnt1, cnt2) +} diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.java b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.java new file mode 100644 index 000000000000..0b290d2e8959 --- /dev/null +++ b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.java @@ -0,0 +1,21 @@ +class Solution { + public int minFlips(int[][] grid) { + int m = grid.length, n = grid[0].length; + int cnt1 = 0, cnt2 = 0; + for (var row : grid) { + for (int j = 0; j < n / 2; ++j) { + if (row[j] != row[n - j - 1]) { + ++cnt1; + } + } + } + for (int j = 0; j < n; ++j) { + for (int i = 0; i < m / 2; ++i) { + if (grid[i][j] != grid[m - i - 1][j]) { + ++cnt2; + } + } + } + return Math.min(cnt1, cnt2); + } +} diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.py b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.py new file mode 100644 index 000000000000..a179dd9e9e88 --- /dev/null +++ b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.py @@ -0,0 +1,13 @@ +class Solution: + def minFlips(self, grid: List[List[int]]) -> int: + m, n = len(grid), len(grid[0]) + cnt1 = cnt2 = 0 + for row in grid: + for j in range(n // 2): + if row[j] != row[n - j - 1]: + cnt1 += 1 + for j in range(n): + for i in range(m // 2): + if grid[i][j] != grid[m - i - 1][j]: + cnt2 += 1 + return min(cnt1, cnt2) diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.ts b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.ts new file mode 100644 index 000000000000..918fbc2585e0 --- /dev/null +++ b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/Solution.ts @@ -0,0 +1,19 @@ +function minFlips(grid: number[][]): number { + const [m, n] = [grid.length, grid[0].length]; + let [cnt1, cnt2] = [0, 0]; + for (const row of grid) { + for (let j = 0; j < n / 2; ++j) { + if (row[j] !== row[n - 1 - j]) { + ++cnt1; + } + } + } + for (let j = 0; j < n; ++j) { + for (let i = 0; i < m / 2; ++i) { + if (grid[i][j] !== grid[m - 1 - i][j]) { + ++cnt2; + } + } + } + return Math.min(cnt1, cnt2); +} diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/images/screenshot-from-2024-07-08-00-20-10.png b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/images/screenshot-from-2024-07-08-00-20-10.png new file mode 100644 index 000000000000..095d57eba60c Binary files /dev/null and b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/images/screenshot-from-2024-07-08-00-20-10.png differ diff --git a/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/images/screenshot-from-2024-07-08-00-31-23.png b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/images/screenshot-from-2024-07-08-00-31-23.png new file mode 100644 index 000000000000..7b2e66d28ba4 Binary files /dev/null and b/solution/3200-3299/3239.Minimum Number of Flips to Make Binary Grid Palindromic I/images/screenshot-from-2024-07-08-00-31-23.png differ diff --git a/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/README.md b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/README.md new file mode 100644 index 000000000000..c4e6ae769cf2 --- /dev/null +++ b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/README.md @@ -0,0 +1,116 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README.md +tags: + - 数组 + - 双指针 + - 矩阵 +--- + + + +# [3240. 最少翻转次数使二进制矩阵回文 II](https://leetcode.cn/problems/minimum-number-of-flips-to-make-binary-grid-palindromic-ii) + +[English Version](/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README_EN.md) + +## 题目描述 + + + +

            给你一个 m x n 的二进制矩阵 grid 。

            + +

            如果矩阵中一行或者一列从前往后与从后往前读是一样的,那么我们称这一行或者这一列是 回文 的。

            + +

            你可以将 grid 中任意格子的值 翻转 ,也就是将格子里的值从 0 变成 1 ,或者从 1 变成 0 。

            + +

            请你返回 最少 翻转次数,使得矩阵中 所有 行和列都是 回文的 ,且矩阵中 1 的数目可以被 4 整除 。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:grid = [[1,0,0],[0,1,0],[0,0,1]]

            + +

            输出:3

            + +

            解释:

            + +

            +
            + +

            示例 2:

            + +
            +

            输入:grid = [[0,1],[0,1],[0,0]]

            + +

            输出:2

            + +

            解释:

            + +

            +
            + +

            示例 3:

            + +
            +

            输入:grid = [[1],[1]]

            + +

            输出:2

            + +

            解释:

            + +

            +
            + +

             

            + +

            提示:

            + +
              +
            • m == grid.length
            • +
            • n == grid[i].length
            • +
            • 1 <= m * n <= 2 * 105
            • +
            • 0 <= grid[i][j] <= 1
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/README_EN.md b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/README_EN.md new file mode 100644 index 000000000000..970aa51e0bae --- /dev/null +++ b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/README_EN.md @@ -0,0 +1,114 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README_EN.md +tags: + - Array + - Two Pointers + - Matrix +--- + + + +# [3240. Minimum Number of Flips to Make Binary Grid Palindromic II](https://leetcode.com/problems/minimum-number-of-flips-to-make-binary-grid-palindromic-ii) + +[中文文档](/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README.md) + +## Description + + + +

            You are given an m x n binary matrix grid.

            + +

            A row or column is considered palindromic if its values read the same forward and backward.

            + +

            You can flip any number of cells in grid from 0 to 1, or from 1 to 0.

            + +

            Return the minimum number of cells that need to be flipped to make all rows and columns palindromic, and the total number of 1's in grid divisible by 4.

            + +

             

            +

            Example 1:

            + +
            +

            Input: grid = [[1,0,0],[0,1,0],[0,0,1]]

            + +

            Output: 3

            + +

            Explanation:

            + +

            +
            + +

            Example 2:

            + +
            +

            Input: grid = [[0,1],[0,1],[0,0]]

            + +

            Output: 2

            + +

            Explanation:

            + +

            +
            + +

            Example 3:

            + +
            +

            Input: grid = [[1],[1]]

            + +

            Output: 2

            + +

            Explanation:

            + +

            +
            + +

             

            +

            Constraints:

            + +
              +
            • m == grid.length
            • +
            • n == grid[i].length
            • +
            • 1 <= m * n <= 2 * 105
            • +
            • 0 <= grid[i][j] <= 1
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/image.png b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/image.png new file mode 100644 index 000000000000..d4e3d5f2f5a3 Binary files /dev/null and b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/image.png differ diff --git a/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/screenshot-from-2024-07-09-01-37-48.png b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/screenshot-from-2024-07-09-01-37-48.png new file mode 100644 index 000000000000..0f58d7834fbd Binary files /dev/null and b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/screenshot-from-2024-07-09-01-37-48.png differ diff --git a/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/screenshot-from-2024-08-01-23-05-26.png b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/screenshot-from-2024-08-01-23-05-26.png new file mode 100644 index 000000000000..d3dae53b17dc Binary files /dev/null and b/solution/3200-3299/3240.Minimum Number of Flips to Make Binary Grid Palindromic II/images/screenshot-from-2024-08-01-23-05-26.png differ diff --git a/solution/3200-3299/3241.Time Taken to Mark All Nodes/README.md b/solution/3200-3299/3241.Time Taken to Mark All Nodes/README.md new file mode 100644 index 000000000000..211aa877c13a --- /dev/null +++ b/solution/3200-3299/3241.Time Taken to Mark All Nodes/README.md @@ -0,0 +1,158 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README.md +tags: + - 树 + - 深度优先搜索 + - 图 + - 动态规划 +--- + + + +# [3241. 标记所有节点需要的时间](https://leetcode.cn/problems/time-taken-to-mark-all-nodes) + +[English Version](/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README_EN.md) + +## 题目描述 + + + +

            给你一棵 无向 树,树中节点从 0 到 n - 1 编号。同时给你一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ui, vi] 表示节点 ui 和 vi 在树中有一条边。

            + +

            一开始,所有 节点都 未标记 。对于节点 i :

            + +
              +
            • 当 i 是奇数时,如果时刻 x - 1 该节点有 至少 一个相邻节点已经被标记了,那么节点 i 会在时刻 x 被标记。
            • +
            • 当 i 是偶数时,如果时刻 x - 2 该节点有 至少 一个相邻节点已经被标记了,那么节点 i 会在时刻 x 被标记。
            • +
            + +

            请你返回一个数组 times ,表示如果你在时刻 t = 0 标记节点 i ,那么时刻 times[i] 时,树中所有节点都会被标记。

            + +

            请注意,每个 times[i] 的答案都是独立的,即当你标记节点 i 时,所有其他节点都未标记。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:edges = [[0,1],[0,2]]

            + +

            输出:[2,4,3]

            + +

            解释:

            + +

            + +
              +
            • 对于 i = 0 : + +
                +
              • 节点 1 在时刻 t = 1 被标记,节点 2 在时刻 t = 2 被标记。
              • +
              +
            • +
            • 对于 i = 1 : +
                +
              • 节点 0 在时刻 t = 2 被标记,节点 2 在时刻 t = 4 被标记。
              • +
              +
            • +
            • 对于 i = 2 : +
                +
              • 节点 0 在时刻 t = 2 被标记,节点 1 在时刻 t = 3 被标记。
              • +
              +
            • + +
            +
            + +

            示例 2:

            + +
            +

            输入:edges = [[0,1]]

            + +

            输出:[1,2]

            + +

            解释:

            + +

            + +
              +
            • 对于 i = 0 : + +
                +
              • 节点 1 在时刻 t = 1 被标记。
              • +
              +
            • +
            • 对于 i = 1 : +
                +
              • 节点 0 在时刻 t = 2 被标记。
              • +
              +
            • + +
            +
            + +

            示例 3:

            + +
            +

            输入:edges = [[2,4],[0,1],[2,3],[0,2]]

            + +

            输出:[4,6,3,5,5]

            + +

            解释:

            + +

            +
            + +

             

            + +

            提示:

            + +
              +
            • 2 <= n <= 105
            • +
            • edges.length == n - 1
            • +
            • edges[i].length == 2
            • +
            • 0 <= edges[i][0], edges[i][1] <= n - 1
            • +
            • 输入保证 edges 表示一棵合法的树。
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3241.Time Taken to Mark All Nodes/README_EN.md b/solution/3200-3299/3241.Time Taken to Mark All Nodes/README_EN.md new file mode 100644 index 000000000000..a955b1cedcc1 --- /dev/null +++ b/solution/3200-3299/3241.Time Taken to Mark All Nodes/README_EN.md @@ -0,0 +1,156 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README_EN.md +tags: + - Tree + - Depth-First Search + - Graph + - Dynamic Programming +--- + + + +# [3241. Time Taken to Mark All Nodes](https://leetcode.com/problems/time-taken-to-mark-all-nodes) + +[中文文档](/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README.md) + +## Description + + + +

            There exists an undirected tree with n nodes numbered 0 to n - 1. You are given a 2D integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the tree.

            + +

            Initially, all nodes are unmarked. For each node i:

            + +
              +
            • If i is odd, the node will get marked at time x if there is at least one node adjacent to it which was marked at time x - 1.
            • +
            • If i is even, the node will get marked at time x if there is at least one node adjacent to it which was marked at time x - 2.
            • +
            + +

            Return an array times where times[i] is the time when all nodes get marked in the tree, if you mark node i at time t = 0.

            + +

            Note that the answer for each times[i] is independent, i.e. when you mark node i all other nodes are unmarked.

            + +

             

            +

            Example 1:

            + +
            +

            Input: edges = [[0,1],[0,2]]

            + +

            Output: [2,4,3]

            + +

            Explanation:

            + +

            + +
              +
            • For i = 0: + +
                +
              • Node 1 is marked at t = 1, and Node 2 at t = 2.
              • +
              +
            • +
            • For i = 1: +
                +
              • Node 0 is marked at t = 2, and Node 2 at t = 4.
              • +
              +
            • +
            • For i = 2: +
                +
              • Node 0 is marked at t = 2, and Node 1 at t = 3.
              • +
              +
            • + +
            +
            + +

            Example 2:

            + +
            +

            Input: edges = [[0,1]]

            + +

            Output: [1,2]

            + +

            Explanation:

            + +

            + +
              +
            • For i = 0: + +
                +
              • Node 1 is marked at t = 1.
              • +
              +
            • +
            • For i = 1: +
                +
              • Node 0 is marked at t = 2.
              • +
              +
            • + +
            +
            + +

            Example 3:

            + +
            +

            Input: edges = [[2,4],[0,1],[2,3],[0,2]]

            + +

            Output: [4,6,3,5,5]

            + +

            Explanation:

            + +

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 2 <= n <= 105
            • +
            • edges.length == n - 1
            • +
            • edges[i].length == 2
            • +
            • 0 <= edges[i][0], edges[i][1] <= n - 1
            • +
            • The input is generated such that edges represents a valid tree.
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3241.Time Taken to Mark All Nodes/images/screenshot-2024-06-02-122236.png b/solution/3200-3299/3241.Time Taken to Mark All Nodes/images/screenshot-2024-06-02-122236.png new file mode 100644 index 000000000000..99c2faa939bd Binary files /dev/null and b/solution/3200-3299/3241.Time Taken to Mark All Nodes/images/screenshot-2024-06-02-122236.png differ diff --git a/solution/3200-3299/3241.Time Taken to Mark All Nodes/images/screenshot-2024-06-02-122249.png b/solution/3200-3299/3241.Time Taken to Mark All Nodes/images/screenshot-2024-06-02-122249.png new file mode 100644 index 000000000000..a1c69f9e571f Binary files /dev/null and b/solution/3200-3299/3241.Time Taken to Mark All Nodes/images/screenshot-2024-06-02-122249.png differ diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/README.md b/solution/3200-3299/3242.Design Neighbor Sum Service/README.md new file mode 100644 index 000000000000..1980ce10be30 --- /dev/null +++ b/solution/3200-3299/3242.Design Neighbor Sum Service/README.md @@ -0,0 +1,338 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README.md +tags: + - 设计 + - 数组 + - 哈希表 + - 矩阵 + - 模拟 +--- + + + +# [3242. 设计相邻元素求和服务](https://leetcode.cn/problems/design-neighbor-sum-service) + +[English Version](/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README_EN.md) + +## 题目描述 + + + +

            给你一个 n x n 的二维数组 grid,它包含范围 [0, n2 - 1] 内的不重复元素。

            + +

            实现 neighborSum 类:

            + +
              +
            • neighborSum(int [][]grid) 初始化对象。
            • +
            • int adjacentSum(int value) 返回在 grid 中与 value 相邻的元素之,相邻指的是与 value 在上、左、右或下的元素。
            • +
            • int diagonalSum(int value) 返回在 grid 中与 value 对角线相邻的元素之,对角线相邻指的是与 value 在左上、右上、左下或右下的元素。
            • +
            + +

            + +

             

            + +

            示例 1:

            + +
            +

            输入:

            + +

            ["neighborSum", "adjacentSum", "adjacentSum", "diagonalSum", "diagonalSum"]

            + +

            [[[[0, 1, 2], [3, 4, 5], [6, 7, 8]]], [1], [4], [4], [8]]

            + +

            输出: [null, 6, 16, 16, 4]

            + +

            解释:

            + +

            + +
              +
            • 1 的相邻元素是 0、2 和 4。
            • +
            • 4 的相邻元素是 1、3、5 和 7。
            • +
            • 4 的对角线相邻元素是 0、2、6 和 8。
            • +
            • 8 的对角线相邻元素是 4。
            • +
            +
            + +

            示例 2:

            + +
            +

            输入:

            + +

            ["neighborSum", "adjacentSum", "diagonalSum"]

            + +

            [[[[1, 2, 0, 3], [4, 7, 15, 6], [8, 9, 10, 11], [12, 13, 14, 5]]], [15], [9]]

            + +

            输出: [null, 23, 45]

            + +

            解释:

            + +

            + +
              +
            • 15 的相邻元素是 0、10、7 和 6。
            • +
            • 9 的对角线相邻元素是 4、12、14 和 15。
            • +
            +
            + +

             

            + +

            提示:

            + +
              +
            • 3 <= n == grid.length == grid[0].length <= 10
            • +
            • 0 <= grid[i][j] <= n2 - 1
            • +
            • 所有 grid[i][j] 值均不重复。
            • +
            • adjacentSumdiagonalSum 中的 value 均在范围 [0, n2 - 1] 内。
            • +
            • 最多会调用 adjacentSumdiagonalSum 总共 2 * n2 次。
            • +
            + + + +## 解法 + + + +### 方法一:哈希表 + +我们可以用一个哈希表 $\textit{d}$ 来存储每个元素的坐标,然后根据题意,分别计算相邻元素和对角线相邻元素的和。 + +时间复杂度方面,初始化哈希表的时间复杂度为 $O(m \times n)$,计算相邻元素和对角线相邻元素的和的时间复杂度为 $O(1)$。空间复杂度为 $O(m \times n)$。 + + + +#### Python3 + +```python +class neighborSum: + + def __init__(self, grid: List[List[int]]): + self.grid = grid + self.d = {} + self.dirs = ((-1, 0, 1, 0, -1), (-1, 1, 1, -1, -1)) + for i, row in enumerate(grid): + for j, x in enumerate(row): + self.d[x] = (i, j) + + def adjacentSum(self, value: int) -> int: + return self.cal(value, 0) + + def cal(self, value: int, k: int): + i, j = self.d[value] + s = 0 + for a, b in pairwise(self.dirs[k]): + x, y = i + a, j + b + if 0 <= x < len(self.grid) and 0 <= y < len(self.grid[0]): + s += self.grid[x][y] + return s + + def diagonalSum(self, value: int) -> int: + return self.cal(value, 1) + + +# Your neighborSum object will be instantiated and called as such: +# obj = neighborSum(grid) +# param_1 = obj.adjacentSum(value) +# param_2 = obj.diagonalSum(value) +``` + +#### Java + +```java +class neighborSum { + private int[][] grid; + private final Map d = new HashMap<>(); + private final int[][] dirs = {{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}}; + + public neighborSum(int[][] grid) { + this.grid = grid; + int m = grid.length, n = grid[0].length; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + d.put(grid[i][j], new int[] {i, j}); + } + } + } + + public int adjacentSum(int value) { + return cal(value, 0); + } + + public int diagonalSum(int value) { + return cal(value, 1); + } + + private int cal(int value, int k) { + int[] p = d.get(value); + int s = 0; + for (int q = 0; q < 4; ++q) { + int x = p[0] + dirs[k][q], y = p[1] + dirs[k][q + 1]; + if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length) { + s += grid[x][y]; + } + } + return s; + } +} + +/** + * Your neighborSum object will be instantiated and called as such: + * neighborSum obj = new neighborSum(grid); + * int param_1 = obj.adjacentSum(value); + * int param_2 = obj.diagonalSum(value); + */ +``` + +#### C++ + +```cpp +class neighborSum { +public: + neighborSum(vector>& grid) { + this->grid = grid; + int m = grid.size(), n = grid[0].size(); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + d[grid[i][j]] = {i, j}; + } + } + } + + int adjacentSum(int value) { + return cal(value, 0); + } + + int diagonalSum(int value) { + return cal(value, 1); + } + +private: + vector> grid; + unordered_map> d; + int dirs[2][5] = {{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}}; + + int cal(int value, int k) { + auto [i, j] = d[value]; + int s = 0; + for (int q = 0; q < 4; ++q) { + int x = i + dirs[k][q], y = j + dirs[k][q + 1]; + if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size()) { + s += grid[x][y]; + } + } + return s; + } +}; + +/** + * Your neighborSum object will be instantiated and called as such: + * neighborSum* obj = new neighborSum(grid); + * int param_1 = obj->adjacentSum(value); + * int param_2 = obj->diagonalSum(value); + */ +``` + +#### Go + +```go +type neighborSum struct { + grid [][]int + d map[int][2]int + dirs [2][5]int +} + +func Constructor(grid [][]int) neighborSum { + d := map[int][2]int{} + for i, row := range grid { + for j, x := range row { + d[x] = [2]int{i, j} + } + } + dirs := [2][5]int{{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}} + return neighborSum{grid, d, dirs} +} + +func (this *neighborSum) AdjacentSum(value int) int { + return this.cal(value, 0) +} + +func (this *neighborSum) DiagonalSum(value int) int { + return this.cal(value, 1) +} + +func (this *neighborSum) cal(value, k int) int { + p := this.d[value] + s := 0 + for q := 0; q < 4; q++ { + x, y := p[0]+this.dirs[k][q], p[1]+this.dirs[k][q+1] + if x >= 0 && x < len(this.grid) && y >= 0 && y < len(this.grid[0]) { + s += this.grid[x][y] + } + } + return s +} + +/** + * Your neighborSum object will be instantiated and called as such: + * obj := Constructor(grid); + * param_1 := obj.AdjacentSum(value); + * param_2 := obj.DiagonalSum(value); + */ +``` + +#### TypeScript + +```ts +class neighborSum { + private grid: number[][]; + private d: Map = new Map(); + private dirs: number[][] = [ + [-1, 0, 1, 0, -1], + [-1, 1, 1, -1, -1], + ]; + constructor(grid: number[][]) { + for (let i = 0; i < grid.length; ++i) { + for (let j = 0; j < grid[0].length; ++j) { + this.d.set(grid[i][j], [i, j]); + } + } + this.grid = grid; + } + + adjacentSum(value: number): number { + return this.cal(value, 0); + } + + diagonalSum(value: number): number { + return this.cal(value, 1); + } + + cal(value: number, k: number): number { + const [i, j] = this.d.get(value)!; + let s = 0; + for (let q = 0; q < 4; ++q) { + const [x, y] = [i + this.dirs[k][q], j + this.dirs[k][q + 1]]; + if (x >= 0 && x < this.grid.length && y >= 0 && y < this.grid[0].length) { + s += this.grid[x][y]; + } + } + return s; + } +} + +/** + * Your neighborSum object will be instantiated and called as such: + * var obj = new neighborSum(grid) + * var param_1 = obj.adjacentSum(value) + * var param_2 = obj.diagonalSum(value) + */ +``` + + + + + + diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/README_EN.md b/solution/3200-3299/3242.Design Neighbor Sum Service/README_EN.md new file mode 100644 index 000000000000..e04c93c92bc1 --- /dev/null +++ b/solution/3200-3299/3242.Design Neighbor Sum Service/README_EN.md @@ -0,0 +1,336 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README_EN.md +tags: + - Design + - Array + - Hash Table + - Matrix + - Simulation +--- + + + +# [3242. Design Neighbor Sum Service](https://leetcode.com/problems/design-neighbor-sum-service) + +[中文文档](/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README.md) + +## Description + + + +

            You are given a n x n 2D array grid containing distinct elements in the range [0, n2 - 1].

            + +

            Implement the NeighborSum class:

            + +
              +
            • NeighborSum(int [][]grid) initializes the object.
            • +
            • int adjacentSum(int value) returns the sum of elements which are adjacent neighbors of value, that is either to the top, left, right, or bottom of value in grid.
            • +
            • int diagonalSum(int value) returns the sum of elements which are diagonal neighbors of value, that is either to the top-left, top-right, bottom-left, or bottom-right of value in grid.
            • +
            + +

            + +

             

            +

            Example 1:

            + +
            +

            Input:

            + +

            ["NeighborSum", "adjacentSum", "adjacentSum", "diagonalSum", "diagonalSum"]

            + +

            [[[[0, 1, 2], [3, 4, 5], [6, 7, 8]]], [1], [4], [4], [8]]

            + +

            Output: [null, 6, 16, 16, 4]

            + +

            Explanation:

            + +

            + +
              +
            • The adjacent neighbors of 1 are 0, 2, and 4.
            • +
            • The adjacent neighbors of 4 are 1, 3, 5, and 7.
            • +
            • The diagonal neighbors of 4 are 0, 2, 6, and 8.
            • +
            • The diagonal neighbor of 8 is 4.
            • +
            +
            + +

            Example 2:

            + +
            +

            Input:

            + +

            ["NeighborSum", "adjacentSum", "diagonalSum"]

            + +

            [[[[1, 2, 0, 3], [4, 7, 15, 6], [8, 9, 10, 11], [12, 13, 14, 5]]], [15], [9]]

            + +

            Output: [null, 23, 45]

            + +

            Explanation:

            + +

            + +
              +
            • The adjacent neighbors of 15 are 0, 10, 7, and 6.
            • +
            • The diagonal neighbors of 9 are 4, 12, 14, and 15.
            • +
            +
            + +

             

            +

            Constraints:

            + +
              +
            • 3 <= n == grid.length == grid[0].length <= 10
            • +
            • 0 <= grid[i][j] <= n2 - 1
            • +
            • All grid[i][j] are distinct.
            • +
            • value in adjacentSum and diagonalSum will be in the range [0, n2 - 1].
            • +
            • At most 2 * n2 calls will be made to adjacentSum and diagonalSum.
            • +
            + + + +## Solutions + + + +### Solution 1: Hash Table + +We can use a hash table $\textit{d}$ to store the coordinates of each element. Then, according to the problem description, we separately calculate the sum of adjacent elements and diagonally adjacent elements. + +In terms of time complexity, initializing the hash table has a time complexity of $O(m \times n)$, and calculating the sum of adjacent elements and diagonally adjacent elements has a time complexity of $O(1)$. The space complexity is $O(m \times n)$. + + + +#### Python3 + +```python +class neighborSum: + + def __init__(self, grid: List[List[int]]): + self.grid = grid + self.d = {} + self.dirs = ((-1, 0, 1, 0, -1), (-1, 1, 1, -1, -1)) + for i, row in enumerate(grid): + for j, x in enumerate(row): + self.d[x] = (i, j) + + def adjacentSum(self, value: int) -> int: + return self.cal(value, 0) + + def cal(self, value: int, k: int): + i, j = self.d[value] + s = 0 + for a, b in pairwise(self.dirs[k]): + x, y = i + a, j + b + if 0 <= x < len(self.grid) and 0 <= y < len(self.grid[0]): + s += self.grid[x][y] + return s + + def diagonalSum(self, value: int) -> int: + return self.cal(value, 1) + + +# Your neighborSum object will be instantiated and called as such: +# obj = neighborSum(grid) +# param_1 = obj.adjacentSum(value) +# param_2 = obj.diagonalSum(value) +``` + +#### Java + +```java +class neighborSum { + private int[][] grid; + private final Map d = new HashMap<>(); + private final int[][] dirs = {{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}}; + + public neighborSum(int[][] grid) { + this.grid = grid; + int m = grid.length, n = grid[0].length; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + d.put(grid[i][j], new int[] {i, j}); + } + } + } + + public int adjacentSum(int value) { + return cal(value, 0); + } + + public int diagonalSum(int value) { + return cal(value, 1); + } + + private int cal(int value, int k) { + int[] p = d.get(value); + int s = 0; + for (int q = 0; q < 4; ++q) { + int x = p[0] + dirs[k][q], y = p[1] + dirs[k][q + 1]; + if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length) { + s += grid[x][y]; + } + } + return s; + } +} + +/** + * Your neighborSum object will be instantiated and called as such: + * neighborSum obj = new neighborSum(grid); + * int param_1 = obj.adjacentSum(value); + * int param_2 = obj.diagonalSum(value); + */ +``` + +#### C++ + +```cpp +class neighborSum { +public: + neighborSum(vector>& grid) { + this->grid = grid; + int m = grid.size(), n = grid[0].size(); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + d[grid[i][j]] = {i, j}; + } + } + } + + int adjacentSum(int value) { + return cal(value, 0); + } + + int diagonalSum(int value) { + return cal(value, 1); + } + +private: + vector> grid; + unordered_map> d; + int dirs[2][5] = {{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}}; + + int cal(int value, int k) { + auto [i, j] = d[value]; + int s = 0; + for (int q = 0; q < 4; ++q) { + int x = i + dirs[k][q], y = j + dirs[k][q + 1]; + if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size()) { + s += grid[x][y]; + } + } + return s; + } +}; + +/** + * Your neighborSum object will be instantiated and called as such: + * neighborSum* obj = new neighborSum(grid); + * int param_1 = obj->adjacentSum(value); + * int param_2 = obj->diagonalSum(value); + */ +``` + +#### Go + +```go +type neighborSum struct { + grid [][]int + d map[int][2]int + dirs [2][5]int +} + +func Constructor(grid [][]int) neighborSum { + d := map[int][2]int{} + for i, row := range grid { + for j, x := range row { + d[x] = [2]int{i, j} + } + } + dirs := [2][5]int{{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}} + return neighborSum{grid, d, dirs} +} + +func (this *neighborSum) AdjacentSum(value int) int { + return this.cal(value, 0) +} + +func (this *neighborSum) DiagonalSum(value int) int { + return this.cal(value, 1) +} + +func (this *neighborSum) cal(value, k int) int { + p := this.d[value] + s := 0 + for q := 0; q < 4; q++ { + x, y := p[0]+this.dirs[k][q], p[1]+this.dirs[k][q+1] + if x >= 0 && x < len(this.grid) && y >= 0 && y < len(this.grid[0]) { + s += this.grid[x][y] + } + } + return s +} + +/** + * Your neighborSum object will be instantiated and called as such: + * obj := Constructor(grid); + * param_1 := obj.AdjacentSum(value); + * param_2 := obj.DiagonalSum(value); + */ +``` + +#### TypeScript + +```ts +class neighborSum { + private grid: number[][]; + private d: Map = new Map(); + private dirs: number[][] = [ + [-1, 0, 1, 0, -1], + [-1, 1, 1, -1, -1], + ]; + constructor(grid: number[][]) { + for (let i = 0; i < grid.length; ++i) { + for (let j = 0; j < grid[0].length; ++j) { + this.d.set(grid[i][j], [i, j]); + } + } + this.grid = grid; + } + + adjacentSum(value: number): number { + return this.cal(value, 0); + } + + diagonalSum(value: number): number { + return this.cal(value, 1); + } + + cal(value: number, k: number): number { + const [i, j] = this.d.get(value)!; + let s = 0; + for (let q = 0; q < 4; ++q) { + const [x, y] = [i + this.dirs[k][q], j + this.dirs[k][q + 1]]; + if (x >= 0 && x < this.grid.length && y >= 0 && y < this.grid[0].length) { + s += this.grid[x][y]; + } + } + return s; + } +} + +/** + * Your neighborSum object will be instantiated and called as such: + * var obj = new neighborSum(grid) + * var param_1 = obj.adjacentSum(value) + * var param_2 = obj.diagonalSum(value) + */ +``` + + + + + + diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.cpp b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.cpp new file mode 100644 index 000000000000..dd12e65e3d6c --- /dev/null +++ b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.cpp @@ -0,0 +1,44 @@ +class neighborSum { +public: + neighborSum(vector>& grid) { + this->grid = grid; + int m = grid.size(), n = grid[0].size(); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + d[grid[i][j]] = {i, j}; + } + } + } + + int adjacentSum(int value) { + return cal(value, 0); + } + + int diagonalSum(int value) { + return cal(value, 1); + } + +private: + vector> grid; + unordered_map> d; + int dirs[2][5] = {{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}}; + + int cal(int value, int k) { + auto [i, j] = d[value]; + int s = 0; + for (int q = 0; q < 4; ++q) { + int x = i + dirs[k][q], y = j + dirs[k][q + 1]; + if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size()) { + s += grid[x][y]; + } + } + return s; + } +}; + +/** + * Your neighborSum object will be instantiated and called as such: + * neighborSum* obj = new neighborSum(grid); + * int param_1 = obj->adjacentSum(value); + * int param_2 = obj->diagonalSum(value); + */ diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.go b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.go new file mode 100644 index 000000000000..2e41dd0d3d67 --- /dev/null +++ b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.go @@ -0,0 +1,43 @@ +type neighborSum struct { + grid [][]int + d map[int][2]int + dirs [2][5]int +} + +func Constructor(grid [][]int) neighborSum { + d := map[int][2]int{} + for i, row := range grid { + for j, x := range row { + d[x] = [2]int{i, j} + } + } + dirs := [2][5]int{{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}} + return neighborSum{grid, d, dirs} +} + +func (this *neighborSum) AdjacentSum(value int) int { + return this.cal(value, 0) +} + +func (this *neighborSum) DiagonalSum(value int) int { + return this.cal(value, 1) +} + +func (this *neighborSum) cal(value, k int) int { + p := this.d[value] + s := 0 + for q := 0; q < 4; q++ { + x, y := p[0]+this.dirs[k][q], p[1]+this.dirs[k][q+1] + if x >= 0 && x < len(this.grid) && y >= 0 && y < len(this.grid[0]) { + s += this.grid[x][y] + } + } + return s +} + +/** + * Your neighborSum object will be instantiated and called as such: + * obj := Constructor(grid); + * param_1 := obj.AdjacentSum(value); + * param_2 := obj.DiagonalSum(value); + */ diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.java b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.java new file mode 100644 index 000000000000..2e806cce0021 --- /dev/null +++ b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.java @@ -0,0 +1,42 @@ +class neighborSum { + private int[][] grid; + private final Map d = new HashMap<>(); + private final int[][] dirs = {{-1, 0, 1, 0, -1}, {-1, 1, 1, -1, -1}}; + + public neighborSum(int[][] grid) { + this.grid = grid; + int m = grid.length, n = grid[0].length; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + d.put(grid[i][j], new int[] {i, j}); + } + } + } + + public int adjacentSum(int value) { + return cal(value, 0); + } + + public int diagonalSum(int value) { + return cal(value, 1); + } + + private int cal(int value, int k) { + int[] p = d.get(value); + int s = 0; + for (int q = 0; q < 4; ++q) { + int x = p[0] + dirs[k][q], y = p[1] + dirs[k][q + 1]; + if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length) { + s += grid[x][y]; + } + } + return s; + } +} + +/** + * Your neighborSum object will be instantiated and called as such: + * neighborSum obj = new neighborSum(grid); + * int param_1 = obj.adjacentSum(value); + * int param_2 = obj.diagonalSum(value); + */ diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.py b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.py new file mode 100644 index 000000000000..cbf13d7925e0 --- /dev/null +++ b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.py @@ -0,0 +1,30 @@ +class neighborSum: + + def __init__(self, grid: List[List[int]]): + self.grid = grid + self.d = {} + self.dirs = ((-1, 0, 1, 0, -1), (-1, 1, 1, -1, -1)) + for i, row in enumerate(grid): + for j, x in enumerate(row): + self.d[x] = (i, j) + + def adjacentSum(self, value: int) -> int: + return self.cal(value, 0) + + def cal(self, value: int, k: int): + i, j = self.d[value] + s = 0 + for a, b in pairwise(self.dirs[k]): + x, y = i + a, j + b + if 0 <= x < len(self.grid) and 0 <= y < len(self.grid[0]): + s += self.grid[x][y] + return s + + def diagonalSum(self, value: int) -> int: + return self.cal(value, 1) + + +# Your neighborSum object will be instantiated and called as such: +# obj = neighborSum(grid) +# param_1 = obj.adjacentSum(value) +# param_2 = obj.diagonalSum(value) diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.ts b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.ts new file mode 100644 index 000000000000..858e16f3de97 --- /dev/null +++ b/solution/3200-3299/3242.Design Neighbor Sum Service/Solution.ts @@ -0,0 +1,43 @@ +class neighborSum { + private grid: number[][]; + private d: Map = new Map(); + private dirs: number[][] = [ + [-1, 0, 1, 0, -1], + [-1, 1, 1, -1, -1], + ]; + constructor(grid: number[][]) { + for (let i = 0; i < grid.length; ++i) { + for (let j = 0; j < grid[0].length; ++j) { + this.d.set(grid[i][j], [i, j]); + } + } + this.grid = grid; + } + + adjacentSum(value: number): number { + return this.cal(value, 0); + } + + diagonalSum(value: number): number { + return this.cal(value, 1); + } + + cal(value: number, k: number): number { + const [i, j] = this.d.get(value)!; + let s = 0; + for (let q = 0; q < 4; ++q) { + const [x, y] = [i + this.dirs[k][q], j + this.dirs[k][q + 1]]; + if (x >= 0 && x < this.grid.length && y >= 0 && y < this.grid[0].length) { + s += this.grid[x][y]; + } + } + return s; + } +} + +/** + * Your neighborSum object will be instantiated and called as such: + * var obj = new neighborSum(grid) + * var param_1 = obj.adjacentSum(value) + * var param_2 = obj.diagonalSum(value) + */ diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/images/design.png b/solution/3200-3299/3242.Design Neighbor Sum Service/images/design.png new file mode 100644 index 000000000000..18f15165195c Binary files /dev/null and b/solution/3200-3299/3242.Design Neighbor Sum Service/images/design.png differ diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/images/designexample0.png b/solution/3200-3299/3242.Design Neighbor Sum Service/images/designexample0.png new file mode 100644 index 000000000000..4b3cd4dabbdc Binary files /dev/null and b/solution/3200-3299/3242.Design Neighbor Sum Service/images/designexample0.png differ diff --git a/solution/3200-3299/3242.Design Neighbor Sum Service/images/designexample2.png b/solution/3200-3299/3242.Design Neighbor Sum Service/images/designexample2.png new file mode 100644 index 000000000000..55bd815d0cd1 Binary files /dev/null and b/solution/3200-3299/3242.Design Neighbor Sum Service/images/designexample2.png differ diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/README.md b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/README.md new file mode 100644 index 000000000000..15c34a23cfd1 --- /dev/null +++ b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/README.md @@ -0,0 +1,298 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README.md +tags: + - 广度优先搜索 + - 图 + - 数组 +--- + + + +# [3243. 新增道路查询后的最短距离 I](https://leetcode.cn/problems/shortest-distance-after-road-addition-queries-i) + +[English Version](/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README_EN.md) + +## 题目描述 + + + +

            给你一个整数 n 和一个二维整数数组 queries

            + +

            n 个城市,编号从 0n - 1。初始时,每个城市 i 都有一条单向道路通往城市 i + 10 <= i < n - 1)。

            + +

            queries[i] = [ui, vi] 表示新建一条从城市 ui 到城市 vi单向道路。每次查询后,你需要找到从城市 0 到城市 n - 1最短路径长度

            + +

            返回一个数组 answer,对于范围 [0, queries.length - 1] 中的每个 ianswer[i] 是处理完 i + 1 个查询后,从城市 0 到城市 n - 1 的最短路径的长度

            + +

             

            + +

            示例 1:

            + +
            +

            输入: n = 5, queries = [[2, 4], [0, 2], [0, 4]]

            + +

            输出: [3, 2, 1]

            + +

            解释:

            + +

            + +

            新增一条从 2 到 4 的道路后,从 0 到 4 的最短路径长度为 3。

            + +

            + +

            新增一条从 0 到 2 的道路后,从 0 到 4 的最短路径长度为 2。

            + +

            + +

            新增一条从 0 到 4 的道路后,从 0 到 4 的最短路径长度为 1。

            +
            + +

            示例 2:

            + +
            +

            输入: n = 4, queries = [[0, 3], [0, 2]]

            + +

            输出: [1, 1]

            + +

            解释:

            + +

            + +

            新增一条从 0 到 3 的道路后,从 0 到 3 的最短路径长度为 1。

            + +

            + +

            新增一条从 0 到 2 的道路后,从 0 到 3 的最短路径长度仍为 1。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 3 <= n <= 500
            • +
            • 1 <= queries.length <= 500
            • +
            • queries[i].length == 2
            • +
            • 0 <= queries[i][0] < queries[i][1] < n
            • +
            • 1 < queries[i][1] - queries[i][0]
            • +
            • 查询中没有重复的道路。
            • +
            + + + +## 解法 + + + +### 方法一:BFS + +我们先建立一个有向图 $\textit{g}$,其中 $\textit{g}[i]$ 表示从城市 $i$ 出发可以到达的城市列表,初始时,每个城市 $i$ 都有一条单向道路通往城市 $i + 1$。 + +然后,我们对每个查询 $[u, v]$,将 $u$ 添加到 $v$ 的出发城市列表中,然后使用 BFS 求出从城市 $0$ 到城市 $n - 1$ 的最短路径长度,将结果添加到答案数组中。 + +最后返回答案数组即可。 + +时间复杂度 $O(q \times (n + q))$,空间复杂度 $O(n + q)$。其中 $n$ 和 $q$ 分别为城市数量和查询数量。 + + + +#### Python3 + +```python +class Solution: + def shortestDistanceAfterQueries( + self, n: int, queries: List[List[int]] + ) -> List[int]: + def bfs(i: int) -> int: + q = deque([i]) + vis = [False] * n + vis[i] = True + d = 0 + while 1: + for _ in range(len(q)): + u = q.popleft() + if u == n - 1: + return d + for v in g[u]: + if not vis[v]: + vis[v] = True + q.append(v) + d += 1 + + g = [[i + 1] for i in range(n - 1)] + ans = [] + for u, v in queries: + g[u].append(v) + ans.append(bfs(0)) + return ans +``` + +#### Java + +```java +class Solution { + private List[] g; + private int n; + + public int[] shortestDistanceAfterQueries(int n, int[][] queries) { + this.n = n; + g = new List[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + for (int i = 0; i < n - 1; ++i) { + g[i].add(i + 1); + } + int m = queries.length; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int u = queries[i][0], v = queries[i][1]; + g[u].add(v); + ans[i] = bfs(0); + } + return ans; + } + + private int bfs(int i) { + Deque q = new ArrayDeque<>(); + q.offer(i); + boolean[] vis = new boolean[n]; + vis[i] = true; + for (int d = 0;; ++d) { + for (int k = q.size(); k > 0; --k) { + int u = q.poll(); + if (u == n - 1) { + return d; + } + for (int v : g[u]) { + if (!vis[v]) { + vis[v] = true; + q.offer(v); + } + } + } + } + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector shortestDistanceAfterQueries(int n, vector>& queries) { + vector g[n]; + for (int i = 0; i < n - 1; ++i) { + g[i].push_back(i + 1); + } + auto bfs = [&](int i) -> int { + queue q{{i}}; + vector vis(n); + vis[i] = true; + for (int d = 0;; ++d) { + for (int k = q.size(); k; --k) { + int u = q.front(); + q.pop(); + if (u == n - 1) { + return d; + } + for (int v : g[u]) { + if (!vis[v]) { + vis[v] = true; + q.push(v); + } + } + } + } + }; + vector ans; + for (const auto& q : queries) { + g[q[0]].push_back(q[1]); + ans.push_back(bfs(0)); + } + return ans; + } +}; +``` + +#### Go + +```go +func shortestDistanceAfterQueries(n int, queries [][]int) []int { + g := make([][]int, n) + for i := range g { + g[i] = append(g[i], i+1) + } + bfs := func(i int) int { + q := []int{i} + vis := make([]bool, n) + vis[i] = true + for d := 0; ; d++ { + for k := len(q); k > 0; k-- { + u := q[0] + if u == n-1 { + return d + } + q = q[1:] + for _, v := range g[u] { + if !vis[v] { + vis[v] = true + q = append(q, v) + } + } + } + } + } + ans := make([]int, len(queries)) + for i, q := range queries { + g[q[0]] = append(g[q[0]], q[1]) + ans[i] = bfs(0) + } + return ans +} +``` + +#### TypeScript + +```ts +function shortestDistanceAfterQueries(n: number, queries: number[][]): number[] { + const g: number[][] = Array.from({ length: n }, () => []); + for (let i = 0; i < n - 1; ++i) { + g[i].push(i + 1); + } + const bfs = (i: number): number => { + const q: number[] = [i]; + const vis: boolean[] = Array(n).fill(false); + vis[i] = true; + for (let d = 0; ; ++d) { + const nq: number[] = []; + for (const u of q) { + if (u === n - 1) { + return d; + } + for (const v of g[u]) { + if (!vis[v]) { + vis[v] = true; + nq.push(v); + } + } + } + q.splice(0, q.length, ...nq); + } + }; + const ans: number[] = []; + for (const [u, v] of queries) { + g[u].push(v); + ans.push(bfs(0)); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/README_EN.md b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/README_EN.md new file mode 100644 index 000000000000..4ce3df8a9553 --- /dev/null +++ b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/README_EN.md @@ -0,0 +1,296 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README_EN.md +tags: + - Breadth-First Search + - Graph + - Array +--- + + + +# [3243. Shortest Distance After Road Addition Queries I](https://leetcode.com/problems/shortest-distance-after-road-addition-queries-i) + +[中文文档](/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README.md) + +## Description + + + +

            You are given an integer n and a 2D integer array queries.

            + +

            There are n cities numbered from 0 to n - 1. Initially, there is a unidirectional road from city i to city i + 1 for all 0 <= i < n - 1.

            + +

            queries[i] = [ui, vi] represents the addition of a new unidirectional road from city ui to city vi. After each query, you need to find the length of the shortest path from city 0 to city n - 1.

            + +

            Return an array answer where for each i in the range [0, queries.length - 1], answer[i] is the length of the shortest path from city 0 to city n - 1 after processing the first i + 1 queries.

            + +

             

            +

            Example 1:

            + +
            +

            Input: n = 5, queries = [[2,4],[0,2],[0,4]]

            + +

            Output: [3,2,1]

            + +

            Explanation:

            + +

            + +

            After the addition of the road from 2 to 4, the length of the shortest path from 0 to 4 is 3.

            + +

            + +

            After the addition of the road from 0 to 2, the length of the shortest path from 0 to 4 is 2.

            + +

            + +

            After the addition of the road from 0 to 4, the length of the shortest path from 0 to 4 is 1.

            +
            + +

            Example 2:

            + +
            +

            Input: n = 4, queries = [[0,3],[0,2]]

            + +

            Output: [1,1]

            + +

            Explanation:

            + +

            + +

            After the addition of the road from 0 to 3, the length of the shortest path from 0 to 3 is 1.

            + +

            + +

            After the addition of the road from 0 to 2, the length of the shortest path remains 1.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 3 <= n <= 500
            • +
            • 1 <= queries.length <= 500
            • +
            • queries[i].length == 2
            • +
            • 0 <= queries[i][0] < queries[i][1] < n
            • +
            • 1 < queries[i][1] - queries[i][0]
            • +
            • There are no repeated roads among the queries.
            • +
            + + + +## Solutions + + + +### Solution 1: BFS + +First, we establish a directed graph $\textit{g}$, where $\textit{g}[i]$ represents the list of cities that can be reached from city $i$. Initially, each city $i$ has a one-way road leading to city $i + 1$. + +Then, for each query $[u, v]$, we add $u$ to the departure city list of $v$, and then use BFS to find the shortest path length from city $0$ to city $n - 1$, adding the result to the answer array. + +Finally, we return the answer array. + +Time complexity is $O(q \times (n + q))$, and space complexity is $O(n + q)$. Here, $n$ and $q$ are the number of cities and the number of queries, respectively. + + + +#### Python3 + +```python +class Solution: + def shortestDistanceAfterQueries( + self, n: int, queries: List[List[int]] + ) -> List[int]: + def bfs(i: int) -> int: + q = deque([i]) + vis = [False] * n + vis[i] = True + d = 0 + while 1: + for _ in range(len(q)): + u = q.popleft() + if u == n - 1: + return d + for v in g[u]: + if not vis[v]: + vis[v] = True + q.append(v) + d += 1 + + g = [[i + 1] for i in range(n - 1)] + ans = [] + for u, v in queries: + g[u].append(v) + ans.append(bfs(0)) + return ans +``` + +#### Java + +```java +class Solution { + private List[] g; + private int n; + + public int[] shortestDistanceAfterQueries(int n, int[][] queries) { + this.n = n; + g = new List[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + for (int i = 0; i < n - 1; ++i) { + g[i].add(i + 1); + } + int m = queries.length; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int u = queries[i][0], v = queries[i][1]; + g[u].add(v); + ans[i] = bfs(0); + } + return ans; + } + + private int bfs(int i) { + Deque q = new ArrayDeque<>(); + q.offer(i); + boolean[] vis = new boolean[n]; + vis[i] = true; + for (int d = 0;; ++d) { + for (int k = q.size(); k > 0; --k) { + int u = q.poll(); + if (u == n - 1) { + return d; + } + for (int v : g[u]) { + if (!vis[v]) { + vis[v] = true; + q.offer(v); + } + } + } + } + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector shortestDistanceAfterQueries(int n, vector>& queries) { + vector g[n]; + for (int i = 0; i < n - 1; ++i) { + g[i].push_back(i + 1); + } + auto bfs = [&](int i) -> int { + queue q{{i}}; + vector vis(n); + vis[i] = true; + for (int d = 0;; ++d) { + for (int k = q.size(); k; --k) { + int u = q.front(); + q.pop(); + if (u == n - 1) { + return d; + } + for (int v : g[u]) { + if (!vis[v]) { + vis[v] = true; + q.push(v); + } + } + } + } + }; + vector ans; + for (const auto& q : queries) { + g[q[0]].push_back(q[1]); + ans.push_back(bfs(0)); + } + return ans; + } +}; +``` + +#### Go + +```go +func shortestDistanceAfterQueries(n int, queries [][]int) []int { + g := make([][]int, n) + for i := range g { + g[i] = append(g[i], i+1) + } + bfs := func(i int) int { + q := []int{i} + vis := make([]bool, n) + vis[i] = true + for d := 0; ; d++ { + for k := len(q); k > 0; k-- { + u := q[0] + if u == n-1 { + return d + } + q = q[1:] + for _, v := range g[u] { + if !vis[v] { + vis[v] = true + q = append(q, v) + } + } + } + } + } + ans := make([]int, len(queries)) + for i, q := range queries { + g[q[0]] = append(g[q[0]], q[1]) + ans[i] = bfs(0) + } + return ans +} +``` + +#### TypeScript + +```ts +function shortestDistanceAfterQueries(n: number, queries: number[][]): number[] { + const g: number[][] = Array.from({ length: n }, () => []); + for (let i = 0; i < n - 1; ++i) { + g[i].push(i + 1); + } + const bfs = (i: number): number => { + const q: number[] = [i]; + const vis: boolean[] = Array(n).fill(false); + vis[i] = true; + for (let d = 0; ; ++d) { + const nq: number[] = []; + for (const u of q) { + if (u === n - 1) { + return d; + } + for (const v of g[u]) { + if (!vis[v]) { + vis[v] = true; + nq.push(v); + } + } + } + q.splice(0, q.length, ...nq); + } + }; + const ans: number[] = []; + for (const [u, v] of queries) { + g[u].push(v); + ans.push(bfs(0)); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.cpp b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.cpp new file mode 100644 index 000000000000..08fcc2701abd --- /dev/null +++ b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.cpp @@ -0,0 +1,35 @@ +class Solution { +public: + vector shortestDistanceAfterQueries(int n, vector>& queries) { + vector g[n]; + for (int i = 0; i < n - 1; ++i) { + g[i].push_back(i + 1); + } + auto bfs = [&](int i) -> int { + queue q{{i}}; + vector vis(n); + vis[i] = true; + for (int d = 0;; ++d) { + for (int k = q.size(); k; --k) { + int u = q.front(); + q.pop(); + if (u == n - 1) { + return d; + } + for (int v : g[u]) { + if (!vis[v]) { + vis[v] = true; + q.push(v); + } + } + } + } + }; + vector ans; + for (const auto& q : queries) { + g[q[0]].push_back(q[1]); + ans.push_back(bfs(0)); + } + return ans; + } +}; diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.go b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.go new file mode 100644 index 000000000000..f10249338f86 --- /dev/null +++ b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.go @@ -0,0 +1,32 @@ +func shortestDistanceAfterQueries(n int, queries [][]int) []int { + g := make([][]int, n) + for i := range g { + g[i] = append(g[i], i+1) + } + bfs := func(i int) int { + q := []int{i} + vis := make([]bool, n) + vis[i] = true + for d := 0; ; d++ { + for k := len(q); k > 0; k-- { + u := q[0] + if u == n-1 { + return d + } + q = q[1:] + for _, v := range g[u] { + if !vis[v] { + vis[v] = true + q = append(q, v) + } + } + } + } + } + ans := make([]int, len(queries)) + for i, q := range queries { + g[q[0]] = append(g[q[0]], q[1]) + ans[i] = bfs(0) + } + return ans +} diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.java b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.java new file mode 100644 index 000000000000..b972291097f1 --- /dev/null +++ b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.java @@ -0,0 +1,42 @@ +class Solution { + private List[] g; + private int n; + + public int[] shortestDistanceAfterQueries(int n, int[][] queries) { + this.n = n; + g = new List[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + for (int i = 0; i < n - 1; ++i) { + g[i].add(i + 1); + } + int m = queries.length; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int u = queries[i][0], v = queries[i][1]; + g[u].add(v); + ans[i] = bfs(0); + } + return ans; + } + + private int bfs(int i) { + Deque q = new ArrayDeque<>(); + q.offer(i); + boolean[] vis = new boolean[n]; + vis[i] = true; + for (int d = 0;; ++d) { + for (int k = q.size(); k > 0; --k) { + int u = q.poll(); + if (u == n - 1) { + return d; + } + for (int v : g[u]) { + if (!vis[v]) { + vis[v] = true; + q.offer(v); + } + } + } + } + } +} diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.py b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.py new file mode 100644 index 000000000000..1bfb259d4d3b --- /dev/null +++ b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.py @@ -0,0 +1,26 @@ +class Solution: + def shortestDistanceAfterQueries( + self, n: int, queries: List[List[int]] + ) -> List[int]: + def bfs(i: int) -> int: + q = deque([i]) + vis = [False] * n + vis[i] = True + d = 0 + while 1: + for _ in range(len(q)): + u = q.popleft() + if u == n - 1: + return d + for v in g[u]: + if not vis[v]: + vis[v] = True + q.append(v) + d += 1 + + g = [[i + 1] for i in range(n - 1)] + ans = [] + for u, v in queries: + g[u].append(v) + ans.append(bfs(0)) + return ans diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.ts b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.ts new file mode 100644 index 000000000000..e069953606aa --- /dev/null +++ b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/Solution.ts @@ -0,0 +1,32 @@ +function shortestDistanceAfterQueries(n: number, queries: number[][]): number[] { + const g: number[][] = Array.from({ length: n }, () => []); + for (let i = 0; i < n - 1; ++i) { + g[i].push(i + 1); + } + const bfs = (i: number): number => { + const q: number[] = [i]; + const vis: boolean[] = Array(n).fill(false); + vis[i] = true; + for (let d = 0; ; ++d) { + const nq: number[] = []; + for (const u of q) { + if (u === n - 1) { + return d; + } + for (const v of g[u]) { + if (!vis[v]) { + vis[v] = true; + nq.push(v); + } + } + } + q.splice(0, q.length, ...nq); + } + }; + const ans: number[] = []; + for (const [u, v] of queries) { + g[u].push(v); + ans.push(bfs(0)); + } + return ans; +} diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image10.jpg b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image10.jpg new file mode 100644 index 000000000000..a6f2c00fc395 Binary files /dev/null and b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image10.jpg differ diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image11.jpg b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image11.jpg new file mode 100644 index 000000000000..2a3638c72021 Binary files /dev/null and b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image11.jpg differ diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image12.jpg b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image12.jpg new file mode 100644 index 000000000000..45873f6498f3 Binary files /dev/null and b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image12.jpg differ diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image8.jpg b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image8.jpg new file mode 100644 index 000000000000..7b418663473d Binary files /dev/null and b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image8.jpg differ diff --git a/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image9.jpg b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image9.jpg new file mode 100644 index 000000000000..cb2c4076c521 Binary files /dev/null and b/solution/3200-3299/3243.Shortest Distance After Road Addition Queries I/images/image9.jpg differ diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/README.md b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/README.md new file mode 100644 index 000000000000..0ab7ceb21c87 --- /dev/null +++ b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/README.md @@ -0,0 +1,238 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README.md +tags: + - 贪心 + - 图 + - 数组 + - 有序集合 +--- + + + +# [3244. 新增道路查询后的最短距离 II](https://leetcode.cn/problems/shortest-distance-after-road-addition-queries-ii) + +[English Version](/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README_EN.md) + +## 题目描述 + + + +

            给你一个整数 n 和一个二维整数数组 queries

            + +

            n 个城市,编号从 0n - 1。初始时,每个城市 i 都有一条单向道路通往城市 i + 10 <= i < n - 1)。

            + +

            queries[i] = [ui, vi] 表示新建一条从城市 ui 到城市 vi单向道路。每次查询后,你需要找到从城市 0 到城市 n - 1最短路径长度

            + +

            所有查询中不会存在两个查询都满足 queries[i][0] < queries[j][0] < queries[i][1] < queries[j][1]

            + +

            返回一个数组 answer,对于范围 [0, queries.length - 1] 中的每个 ianswer[i] 是处理完 i + 1 个查询后,从城市 0 到城市 n - 1 的最短路径的长度

            + +

             

            + +

            示例 1:

            + +
            +

            输入: n = 5, queries = [[2, 4], [0, 2], [0, 4]]

            + +

            输出: [3, 2, 1]

            + +

            解释:

            + +

            + +

            新增一条从 2 到 4 的道路后,从 0 到 4 的最短路径长度为 3。

            + +

            + +

            新增一条从 0 到 2 的道路后,从 0 到 4 的最短路径长度为 2。

            + +

            + +

            新增一条从 0 到 4 的道路后,从 0 到 4 的最短路径长度为 1。

            +
            + +

            示例 2:

            + +
            +

            输入: n = 4, queries = [[0, 3], [0, 2]]

            + +

            输出: [1, 1]

            + +

            解释:

            + +

            + +

            新增一条从 0 到 3 的道路后,从 0 到 3 的最短路径长度为 1。

            + +

            + +

            新增一条从 0 到 2 的道路后,从 0 到 3 的最短路径长度仍为 1。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 3 <= n <= 105
            • +
            • 1 <= queries.length <= 105
            • +
            • queries[i].length == 2
            • +
            • 0 <= queries[i][0] < queries[i][1] < n
            • +
            • 1 < queries[i][1] - queries[i][0]
            • +
            • 查询中不存在重复的道路。
            • +
            • 不存在两个查询都满足 i != jqueries[i][0] < queries[j][0] < queries[i][1] < queries[j][1]
            • +
            + + + +## 解法 + + + +### 方法一:贪心 + 记录跳转位置 + +我们定义一个长度为 $n - 1$ 的数组 $\textit{nxt}$,其中 $\textit{nxt}[i]$ 表示从城市 $i$ 可以到达的下一个城市的编号。初始时 $\textit{nxt}[i] = i + 1$。 + +对于每次查询 $[u, v]$,如果此前已经连通了 $u'$ 和 $v'$,且 $u' <= u < v <= v'$,那么我们可以跳过这次查询。否则,我们需要将 $nxt[u]$ 到 $nxt[v - 1]$ 这些城市的下一个城市编号设置为 $0$,并将 $nxt[u]$ 设置为 $v$。 + +在这个过程中,我们维护一个变量 $\textit{cnt}$,表示从城市 $0$ 到城市 $n - 1$ 的最短路径的长度。初始时 $\textit{cnt} = n - 1$。每一次,如果我们将 $[\textit{nxt}[u], \textit{v})$ 这些城市的下一个城市编号设置为 $0$,那么 $\textit{cnt}$ 就会减少 $1$。 + +时间复杂度 $O(n + q)$,空间复杂度 $O(n)$。其中 $n$ 和 $q$ 分别是城市数量和查询数量。 + + + +#### Python3 + +```python +class Solution: + def shortestDistanceAfterQueries( + self, n: int, queries: List[List[int]] + ) -> List[int]: + nxt = list(range(1, n)) + ans = [] + cnt = n - 1 + for u, v in queries: + if 0 < nxt[u] < v: + i = nxt[u] + while i < v: + cnt -= 1 + nxt[i], i = 0, nxt[i] + nxt[u] = v + ans.append(cnt) + return ans +``` + +#### Java + +```java +class Solution { + public int[] shortestDistanceAfterQueries(int n, int[][] queries) { + int[] nxt = new int[n - 1]; + for (int i = 1; i < n; ++i) { + nxt[i - 1] = i; + } + int m = queries.length; + int cnt = n - 1; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int u = queries[i][0], v = queries[i][1]; + if (nxt[u] > 0 && nxt[u] < v) { + int j = nxt[u]; + while (j < v) { + --cnt; + int t = nxt[j]; + nxt[j] = 0; + j = t; + } + nxt[u] = v; + } + ans[i] = cnt; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector shortestDistanceAfterQueries(int n, vector>& queries) { + vector nxt(n - 1); + iota(nxt.begin(), nxt.end(), 1); + int cnt = n - 1; + vector ans; + for (const auto& q : queries) { + int u = q[0], v = q[1]; + if (nxt[u] && nxt[u] < v) { + int i = nxt[u]; + while (i < v) { + --cnt; + int t = nxt[i]; + nxt[i] = 0; + i = t; + } + nxt[u] = v; + } + ans.push_back(cnt); + } + return ans; + } +}; +``` + +#### Go + +```go +func shortestDistanceAfterQueries(n int, queries [][]int) (ans []int) { + nxt := make([]int, n-1) + for i := range nxt { + nxt[i] = i + 1 + } + cnt := n - 1 + for _, q := range queries { + u, v := q[0], q[1] + if nxt[u] > 0 && nxt[u] < v { + i := nxt[u] + for i < v { + cnt-- + nxt[i], i = 0, nxt[i] + } + nxt[u] = v + } + ans = append(ans, cnt) + } + return +} +``` + +#### TypeScript + +```ts +function shortestDistanceAfterQueries(n: number, queries: number[][]): number[] { + const nxt: number[] = Array.from({ length: n - 1 }, (_, i) => i + 1); + const ans: number[] = []; + let cnt = n - 1; + for (const [u, v] of queries) { + if (nxt[u] && nxt[u] < v) { + let i = nxt[u]; + while (i < v) { + --cnt; + [nxt[i], i] = [0, nxt[i]]; + } + nxt[u] = v; + } + ans.push(cnt); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/README_EN.md b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/README_EN.md new file mode 100644 index 000000000000..ff4e704f5952 --- /dev/null +++ b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/README_EN.md @@ -0,0 +1,236 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README_EN.md +tags: + - Greedy + - Graph + - Array + - Ordered Set +--- + + + +# [3244. Shortest Distance After Road Addition Queries II](https://leetcode.com/problems/shortest-distance-after-road-addition-queries-ii) + +[中文文档](/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README.md) + +## Description + + + +

            You are given an integer n and a 2D integer array queries.

            + +

            There are n cities numbered from 0 to n - 1. Initially, there is a unidirectional road from city i to city i + 1 for all 0 <= i < n - 1.

            + +

            queries[i] = [ui, vi] represents the addition of a new unidirectional road from city ui to city vi. After each query, you need to find the length of the shortest path from city 0 to city n - 1.

            + +

            There are no two queries such that queries[i][0] < queries[j][0] < queries[i][1] < queries[j][1].

            + +

            Return an array answer where for each i in the range [0, queries.length - 1], answer[i] is the length of the shortest path from city 0 to city n - 1 after processing the first i + 1 queries.

            + +

             

            +

            Example 1:

            + +
            +

            Input: n = 5, queries = [[2,4],[0,2],[0,4]]

            + +

            Output: [3,2,1]

            + +

            Explanation:

            + +

            + +

            After the addition of the road from 2 to 4, the length of the shortest path from 0 to 4 is 3.

            + +

            + +

            After the addition of the road from 0 to 2, the length of the shortest path from 0 to 4 is 2.

            + +

            + +

            After the addition of the road from 0 to 4, the length of the shortest path from 0 to 4 is 1.

            +
            + +

            Example 2:

            + +
            +

            Input: n = 4, queries = [[0,3],[0,2]]

            + +

            Output: [1,1]

            + +

            Explanation:

            + +

            + +

            After the addition of the road from 0 to 3, the length of the shortest path from 0 to 3 is 1.

            + +

            + +

            After the addition of the road from 0 to 2, the length of the shortest path remains 1.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 3 <= n <= 105
            • +
            • 1 <= queries.length <= 105
            • +
            • queries[i].length == 2
            • +
            • 0 <= queries[i][0] < queries[i][1] < n
            • +
            • 1 < queries[i][1] - queries[i][0]
            • +
            • There are no repeated roads among the queries.
            • +
            • There are no two queries such that i != j and queries[i][0] < queries[j][0] < queries[i][1] < queries[j][1].
            • +
            + + + +## Solutions + + + +### Solution 1: Greedy + Recording Jump Positions + +We define an array $\textit{nxt}$ of length $n - 1$, where $\textit{nxt}[i]$ represents the next city that can be reached from city $i$. Initially, $\textit{nxt}[i] = i + 1$. + +For each query $[u, v]$, if $u'$ and $v'$ have already been connected before, and $u' \leq u < v \leq v'$, then we can skip this query. Otherwise, we need to set the next city number for cities from $\textit{nxt}[u]$ to $\textit{nxt}[v - 1]$ to $0$, and set $\textit{nxt}[u]$ to $v$. + +During this process, we maintain a variable $\textit{cnt}$, which represents the length of the shortest path from city $0$ to city $n - 1$. Initially, $\textit{cnt} = n - 1$. Each time we set the next city number for cities in $[\textit{nxt}[u], \textit{v})$ to $0$, $\textit{cnt}$ decreases by $1$. + +Time complexity is $O(n + q)$, and space complexity is $O(n)$. Here, $n$ and $q$ are the number of cities and the number of queries, respectively. + + + +#### Python3 + +```python +class Solution: + def shortestDistanceAfterQueries( + self, n: int, queries: List[List[int]] + ) -> List[int]: + nxt = list(range(1, n)) + ans = [] + cnt = n - 1 + for u, v in queries: + if 0 < nxt[u] < v: + i = nxt[u] + while i < v: + cnt -= 1 + nxt[i], i = 0, nxt[i] + nxt[u] = v + ans.append(cnt) + return ans +``` + +#### Java + +```java +class Solution { + public int[] shortestDistanceAfterQueries(int n, int[][] queries) { + int[] nxt = new int[n - 1]; + for (int i = 1; i < n; ++i) { + nxt[i - 1] = i; + } + int m = queries.length; + int cnt = n - 1; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int u = queries[i][0], v = queries[i][1]; + if (nxt[u] > 0 && nxt[u] < v) { + int j = nxt[u]; + while (j < v) { + --cnt; + int t = nxt[j]; + nxt[j] = 0; + j = t; + } + nxt[u] = v; + } + ans[i] = cnt; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector shortestDistanceAfterQueries(int n, vector>& queries) { + vector nxt(n - 1); + iota(nxt.begin(), nxt.end(), 1); + int cnt = n - 1; + vector ans; + for (const auto& q : queries) { + int u = q[0], v = q[1]; + if (nxt[u] && nxt[u] < v) { + int i = nxt[u]; + while (i < v) { + --cnt; + int t = nxt[i]; + nxt[i] = 0; + i = t; + } + nxt[u] = v; + } + ans.push_back(cnt); + } + return ans; + } +}; +``` + +#### Go + +```go +func shortestDistanceAfterQueries(n int, queries [][]int) (ans []int) { + nxt := make([]int, n-1) + for i := range nxt { + nxt[i] = i + 1 + } + cnt := n - 1 + for _, q := range queries { + u, v := q[0], q[1] + if nxt[u] > 0 && nxt[u] < v { + i := nxt[u] + for i < v { + cnt-- + nxt[i], i = 0, nxt[i] + } + nxt[u] = v + } + ans = append(ans, cnt) + } + return +} +``` + +#### TypeScript + +```ts +function shortestDistanceAfterQueries(n: number, queries: number[][]): number[] { + const nxt: number[] = Array.from({ length: n - 1 }, (_, i) => i + 1); + const ans: number[] = []; + let cnt = n - 1; + for (const [u, v] of queries) { + if (nxt[u] && nxt[u] < v) { + let i = nxt[u]; + while (i < v) { + --cnt; + [nxt[i], i] = [0, nxt[i]]; + } + nxt[u] = v; + } + ans.push(cnt); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.cpp b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.cpp new file mode 100644 index 000000000000..e73154187daa --- /dev/null +++ b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.cpp @@ -0,0 +1,24 @@ +class Solution { +public: + vector shortestDistanceAfterQueries(int n, vector>& queries) { + vector nxt(n - 1); + iota(nxt.begin(), nxt.end(), 1); + int cnt = n - 1; + vector ans; + for (const auto& q : queries) { + int u = q[0], v = q[1]; + if (nxt[u] && nxt[u] < v) { + int i = nxt[u]; + while (i < v) { + --cnt; + int t = nxt[i]; + nxt[i] = 0; + i = t; + } + nxt[u] = v; + } + ans.push_back(cnt); + } + return ans; + } +}; diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.go b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.go new file mode 100644 index 000000000000..b3c3be50b9d9 --- /dev/null +++ b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.go @@ -0,0 +1,20 @@ +func shortestDistanceAfterQueries(n int, queries [][]int) (ans []int) { + nxt := make([]int, n-1) + for i := range nxt { + nxt[i] = i + 1 + } + cnt := n - 1 + for _, q := range queries { + u, v := q[0], q[1] + if nxt[u] > 0 && nxt[u] < v { + i := nxt[u] + for i < v { + cnt-- + nxt[i], i = 0, nxt[i] + } + nxt[u] = v + } + ans = append(ans, cnt) + } + return +} diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.java b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.java new file mode 100644 index 000000000000..ec5ff2e6127c --- /dev/null +++ b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.java @@ -0,0 +1,26 @@ +class Solution { + public int[] shortestDistanceAfterQueries(int n, int[][] queries) { + int[] nxt = new int[n - 1]; + for (int i = 1; i < n; ++i) { + nxt[i - 1] = i; + } + int m = queries.length; + int cnt = n - 1; + int[] ans = new int[m]; + for (int i = 0; i < m; ++i) { + int u = queries[i][0], v = queries[i][1]; + if (nxt[u] > 0 && nxt[u] < v) { + int j = nxt[u]; + while (j < v) { + --cnt; + int t = nxt[j]; + nxt[j] = 0; + j = t; + } + nxt[u] = v; + } + ans[i] = cnt; + } + return ans; + } +} diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.py b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.py new file mode 100644 index 000000000000..6182b7f8214d --- /dev/null +++ b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.py @@ -0,0 +1,16 @@ +class Solution: + def shortestDistanceAfterQueries( + self, n: int, queries: List[List[int]] + ) -> List[int]: + nxt = list(range(1, n)) + ans = [] + cnt = n - 1 + for u, v in queries: + if 0 < nxt[u] < v: + i = nxt[u] + while i < v: + cnt -= 1 + nxt[i], i = 0, nxt[i] + nxt[u] = v + ans.append(cnt) + return ans diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.ts b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.ts new file mode 100644 index 000000000000..6b5cad8cf920 --- /dev/null +++ b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/Solution.ts @@ -0,0 +1,17 @@ +function shortestDistanceAfterQueries(n: number, queries: number[][]): number[] { + const nxt: number[] = Array.from({ length: n - 1 }, (_, i) => i + 1); + const ans: number[] = []; + let cnt = n - 1; + for (const [u, v] of queries) { + if (nxt[u] && nxt[u] < v) { + let i = nxt[u]; + while (i < v) { + --cnt; + [nxt[i], i] = [0, nxt[i]]; + } + nxt[u] = v; + } + ans.push(cnt); + } + return ans; +} diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image10.jpg b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image10.jpg new file mode 100644 index 000000000000..a6f2c00fc395 Binary files /dev/null and b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image10.jpg differ diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image11.jpg b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image11.jpg new file mode 100644 index 000000000000..2a3638c72021 Binary files /dev/null and b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image11.jpg differ diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image12.jpg b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image12.jpg new file mode 100644 index 000000000000..45873f6498f3 Binary files /dev/null and b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image12.jpg differ diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image8.jpg b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image8.jpg new file mode 100644 index 000000000000..7b418663473d Binary files /dev/null and b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image8.jpg differ diff --git a/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image9.jpg b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image9.jpg new file mode 100644 index 000000000000..cb2c4076c521 Binary files /dev/null and b/solution/3200-3299/3244.Shortest Distance After Road Addition Queries II/images/image9.jpg differ diff --git a/solution/3200-3299/3245.Alternating Groups III/README.md b/solution/3200-3299/3245.Alternating Groups III/README.md new file mode 100644 index 000000000000..3ba6d8cbb92e --- /dev/null +++ b/solution/3200-3299/3245.Alternating Groups III/README.md @@ -0,0 +1,141 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3245.Alternating%20Groups%20III/README.md +tags: + - 树状数组 + - 数组 +--- + + + +# [3245. 交替组 III](https://leetcode.cn/problems/alternating-groups-iii) + +[English Version](/solution/3200-3299/3245.Alternating%20Groups%20III/README_EN.md) + +## 题目描述 + + + +

            给你一个整数数组 colors 和一个二维整数数组 queriescolors表示一个由红色和蓝色瓷砖组成的环,第 i 块瓷砖的颜色为 colors[i] :

            + +
              +
            • colors[i] == 0 表示第 i 块瓷砖的颜色是 红色 。
            • +
            • colors[i] == 1 表示第 i 块瓷砖的颜色是 蓝色 。
            • +
            + +

            环中连续若干块瓷砖的颜色如果是 交替 颜色(也就是说这组瓷砖中除了第一块和最后一块瓷砖以外,中间瓷砖的颜色与它 左边 和 右边 的颜色都不同),那么它被称为一个 交替组

            + +

            你需要处理两种类型的查询:

            + +
              +
            • queries[i] = [1, sizei],确定大小为sizei 交替组 的数量。
            • +
            • queries[i] = [2, indexi, colori],将colors[indexi]更改为colori
            • +
            + +

            返回数组 answer,数组中按顺序包含第一种类型查询的结果。

            + +

            注意 ,由于 colors 表示一个  ,第一块 瓷砖和 最后一块 瓷砖是相邻的。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:colors = [0,1,1,0,1], queries = [[2,1,0],[1,4]]

            + +

            输出:[2]

            + +

            解释:

            + +

            第一次查询:

            + +

            colors[1] 改为 0。

            + +

            + +

            第二次查询:

            + +

            统计大小为 4 的交替组的数量:

            + +

            +
            + +

            示例 2:

            + +
            +

            输入:colors = [0,0,1,0,1,1], queries = [[1,3],[2,3,0],[1,5]]

            + +

            输出:[2,0]

            + +

            解释:

            + +

            + +

            第一次查询:

            + +

            统计大小为 3 的交替组的数量。

            + +

            + +

            第二次查询:colors不变。

            + +

            第三次查询:不存在大小为 5 的交替组。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 4 <= colors.length <= 5 * 104
            • +
            • 0 <= colors[i] <= 1
            • +
            • 1 <= queries.length <= 5 * 104
            • +
            • queries[i][0] == 1queries[i][0] == 2
            • +
            • 对于所有的i: +
                +
              • queries[i][0] == 1queries[i].length == 2, 3 <= queries[i][1] <= colors.length - 1
              • +
              • queries[i][0] == 2queries[i].length == 3, 0 <= queries[i][1] <= colors.length - 1, 0 <= queries[i][2] <= 1
              • +
              +
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3245.Alternating Groups III/README_EN.md b/solution/3200-3299/3245.Alternating Groups III/README_EN.md new file mode 100644 index 000000000000..b9e86ef79752 --- /dev/null +++ b/solution/3200-3299/3245.Alternating Groups III/README_EN.md @@ -0,0 +1,143 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3245.Alternating%20Groups%20III/README_EN.md +tags: + - Binary Indexed Tree + - Array +--- + + + +# [3245. Alternating Groups III](https://leetcode.com/problems/alternating-groups-iii) + +[中文文档](/solution/3200-3299/3245.Alternating%20Groups%20III/README.md) + +## Description + + + +

            There are some red and blue tiles arranged circularly. You are given an array of integers colors and a 2D integers array queries.

            + +

            The color of tile i is represented by colors[i]:

            + +
              +
            • colors[i] == 0 means that tile i is red.
            • +
            • colors[i] == 1 means that tile i is blue.
            • +
            + +

            An alternating group is a contiguous subset of tiles in the circle with alternating colors (each tile in the group except the first and last one has a different color from its adjacent tiles in the group).

            + +

            You have to process queries of two types:

            + +
              +
            • queries[i] = [1, sizei], determine the count of alternating groups with size sizei.
            • +
            • queries[i] = [2, indexi, colori], change colors[indexi] to colori.
            • +
            + +

            Return an array answer containing the results of the queries of the first type in order.

            + +

            Note that since colors represents a circle, the first and the last tiles are considered to be next to each other.

            + +

             

            +

            Example 1:

            + +
            +

            Input: colors = [0,1,1,0,1], queries = [[2,1,0],[1,4]]

            + +

            Output: [2]

            + +

            Explanation:

            + +

            + +

            First query:

            + +

            Change colors[1] to 0.

            + +

            + +

            Second query:

            + +

            Count of the alternating groups with size 4:

            + +

            +
            + +

            Example 2:

            + +
            +

            Input: colors = [0,0,1,0,1,1], queries = [[1,3],[2,3,0],[1,5]]

            + +

            Output: [2,0]

            + +

            Explanation:

            + +

            + +

            First query:

            + +

            Count of the alternating groups with size 3:

            + +

            + +

            Second query: colors will not change.

            + +

            Third query: There is no alternating group with size 5.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 4 <= colors.length <= 5 * 104
            • +
            • 0 <= colors[i] <= 1
            • +
            • 1 <= queries.length <= 5 * 104
            • +
            • queries[i][0] == 1 or queries[i][0] == 2
            • +
            • For all i that: +
                +
              • queries[i][0] == 1: queries[i].length == 2, 3 <= queries[i][1] <= colors.length - 1
              • +
              • queries[i][0] == 2: queries[i].length == 3, 0 <= queries[i][1] <= colors.length - 1, 0 <= queries[i][2] <= 1
              • +
              +
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-20-25.png b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-20-25.png new file mode 100644 index 000000000000..302718e3dd07 Binary files /dev/null and b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-20-25.png differ diff --git a/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-24-12.png b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-24-12.png new file mode 100644 index 000000000000..e45dc0927357 Binary files /dev/null and b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-24-12.png differ diff --git a/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-25-02-2.png b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-25-02-2.png new file mode 100644 index 000000000000..269cae962a86 Binary files /dev/null and b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-25-02-2.png differ diff --git a/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-35-50.png b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-35-50.png new file mode 100644 index 000000000000..1b0e58fb5804 Binary files /dev/null and b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-35-50.png differ diff --git a/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-36-40.png b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-36-40.png new file mode 100644 index 000000000000..1bab7e92b50c Binary files /dev/null and b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-36-40.png differ diff --git a/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-37-13.png b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-37-13.png new file mode 100644 index 000000000000..099bb3d36a95 Binary files /dev/null and b/solution/3200-3299/3245.Alternating Groups III/images/screenshot-from-2024-06-03-20-37-13.png differ diff --git a/solution/3200-3299/3246.Premier League Table Ranking/README.md b/solution/3200-3299/3246.Premier League Table Ranking/README.md new file mode 100644 index 000000000000..5d3e6ec2c5ab --- /dev/null +++ b/solution/3200-3299/3246.Premier League Table Ranking/README.md @@ -0,0 +1,141 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README.md +tags: + - 数据库 +--- + + + +# [3246. 英超积分榜排名 🔒](https://leetcode.cn/problems/premier-league-table-ranking) + +[English Version](/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README_EN.md) + +## 题目描述 + + + +

            表:TeamStats

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| team_id          | int     |
            +| team_name        | varchar |
            +| matches_played   | int     |
            +| wins             | int     |
            +| draws            | int     |
            +| losses           | int     |
            ++------------------+---------+
            +team_id 是这张表的唯一主键。
            +这张表包含队伍 id,队伍名,场次,赢局,平局和输局。
            +
            + +

            编写一个解决方案来计算联盟中每支球队的 得分排名。积分计算方式如下:

            + +
              +
            • 赢局 有 3 点得分
            • +
            • 平局 有 1 点得分
            • +
            • 输局 有 0 点得分
            • +
            + +

            注意:积分相同的球队必须分配相同的排名。

            + +

            返回结果表以 points 降序 排序,然后以 team_name 升序 排序。

            + +

            结果格式如下所示。

            + +

             

            + +

            示例:

            + +
            +

            输入:

            + +

            TeamStats 表:

            + +
            ++---------+-----------------+----------------+------+-------+--------+
            +| team_id | team_name       | matches_played | wins | draws | losses |
            ++---------+-----------------+----------------+------+-------+--------+
            +| 1       | Manchester City | 10             | 6    | 2     | 2      |
            +| 2       | Liverpool       | 10             | 6    | 2     | 2      |
            +| 3       | Chelsea         | 10             | 5    | 3     | 2      |
            +| 4       | Arsenal         | 10             | 4    | 4     | 2      |
            +| 5       | Tottenham       | 10             | 3    | 5     | 2      |
            ++---------+-----------------+----------------+------+-------+--------+
            +
            + +

            输出:

            + +
            ++---------+-----------------+--------+----------+
            +| team_id | team_name       | points | position |
            ++---------+-----------------+--------+----------+
            +| 2       | Liverpool       | 20     | 1        |
            +| 1       | Manchester City | 20     | 1        |
            +| 3       | Chelsea         | 18     | 3        |
            +| 4       | Arsenal         | 16     | 4        |
            +| 5       | Tottenham       | 14     | 5        |
            ++---------+-----------------+--------+----------+
            +
            + +

            解释:

            + +
              +
            • 曼城和利物浦均拿下 20 分(6 赢 * 3 分 + 2 平 * 1 分),所以他们并列第一。
            • +
            • 切尔西拿下 18 分(5 赢 * 3 分 + 3 平 * 1 分)所以位列第三。
            • +
            • 阿森纳拿下 16 分(4 赢 * 3 分 + 4 平 * 1 分)位列第四。
            • +
            • 托特纳姆热刺队拿下 14 分(3 赢 * 3 分 + 5 平 * 1 分)位列第五。
            • +
            + +

            输出表以得分降序排序,然后以 team_name 升序排序。

            +
            + + + +## 解法 + + + +### 方法一:窗口函数 + +我们可以使用 `RANK()` 窗口函数来计算球队的排名,然后按照得分和球队名进行排序。 + + + +#### MySQL + +```sql +# Write your MySQL query statement below +SELECT + team_id, + team_name, + wins * 3 + draws points, + RANK() OVER (ORDER BY (wins * 3 + draws) DESC) position +FROM TeamStats +ORDER BY 3 DESC, 2; +``` + +#### Pandas + +```python +import pandas as pd + + +def calculate_team_standings(team_stats: pd.DataFrame) -> pd.DataFrame: + team_stats["points"] = team_stats["wins"] * 3 + team_stats["draws"] + team_stats["position"] = team_stats["points"].rank(method="min", ascending=False) + team_stats = team_stats.sort_values( + by=["points", "team_name"], ascending=[False, True] + ) + return team_stats[["team_id", "team_name", "points", "position"]] +``` + + + + + + diff --git a/solution/3200-3299/3246.Premier League Table Ranking/README_EN.md b/solution/3200-3299/3246.Premier League Table Ranking/README_EN.md new file mode 100644 index 000000000000..1aa5a30d3c43 --- /dev/null +++ b/solution/3200-3299/3246.Premier League Table Ranking/README_EN.md @@ -0,0 +1,140 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README_EN.md +tags: + - Database +--- + + + +# [3246. Premier League Table Ranking 🔒](https://leetcode.com/problems/premier-league-table-ranking) + +[中文文档](/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README.md) + +## Description + + + +

            Table: TeamStats

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| team_id          | int     |
            +| team_name        | varchar |
            +| matches_played   | int     |
            +| wins             | int     |
            +| draws            | int     |
            +| losses           | int     |
            ++------------------+---------+
            +team_id is the unique key for this table.
            +This table contains team id, team name, matches_played, wins, draws, and losses.
            +
            + +

            Write a solution to calculate the points and rank for each team in the league. Points are calculated as follows:

            + +
              +
            • 3 points for a win
            • +
            • 1 point for a draw
            • +
            • 0 points for a loss
            • +
            + +

            Note: Teams with the same points must be assigned the same rank.

            + +

            Return the result table ordered by points in descending, and then by team_name in ascending order.

            + +

            The query result format is in the following example.

            + +

             

            +

            Example:

            + +
            +

            Input:

            + +

            TeamStats table:

            + +
            ++---------+-----------------+----------------+------+-------+--------+
            +| team_id | team_name       | matches_played | wins | draws | losses |
            ++---------+-----------------+----------------+------+-------+--------+
            +| 1       | Manchester City | 10             | 6    | 2     | 2      |
            +| 2       | Liverpool       | 10             | 6    | 2     | 2      |
            +| 3       | Chelsea         | 10             | 5    | 3     | 2      |
            +| 4       | Arsenal         | 10             | 4    | 4     | 2      |
            +| 5       | Tottenham       | 10             | 3    | 5     | 2      |
            ++---------+-----------------+----------------+------+-------+--------+
            +
            + +

            Output:

            + +
            ++---------+-----------------+--------+----------+
            +| team_id | team_name       | points | position |
            ++---------+-----------------+--------+----------+
            +| 2       | Liverpool       | 20     | 1        |
            +| 1       | Manchester City | 20     | 1        |
            +| 3       | Chelsea         | 18     | 3        |
            +| 4       | Arsenal         | 16     | 4        |
            +| 5       | Tottenham       | 14     | 5        |
            ++---------+-----------------+--------+----------+
            +
            + +

            Explanation:

            + +
              +
            • Manchester City and Liverpool both have 20 points (6 wins * 3 points + 2 draws * 1 point), so they share position 1.
            • +
            • Chelsea has 18 points (5 wins * 3 points + 3 draws * 1 point) and is position 3rd.
            • +
            • Arsenal has 16 points (4 wins * 3 points + 4 draws * 1 point) and is position 4th.
            • +
            • Tottenham has 14 points (3 wins * 3 points + 5 draws * 1 point) and is position 5th.
            • +
            + +

            The output table is ordered by points in descending order, then by team_name in ascending order.

            +
            + + + +## Solutions + + + +### Solution 1: Window Function + +We can use the `RANK()` window function to calculate the ranking of the teams, and then sort by score and team name. + + + +#### MySQL + +```sql +# Write your MySQL query statement below +SELECT + team_id, + team_name, + wins * 3 + draws points, + RANK() OVER (ORDER BY (wins * 3 + draws) DESC) position +FROM TeamStats +ORDER BY 3 DESC, 2; +``` + +#### Pandas + +```python +import pandas as pd + + +def calculate_team_standings(team_stats: pd.DataFrame) -> pd.DataFrame: + team_stats["points"] = team_stats["wins"] * 3 + team_stats["draws"] + team_stats["position"] = team_stats["points"].rank(method="min", ascending=False) + team_stats = team_stats.sort_values( + by=["points", "team_name"], ascending=[False, True] + ) + return team_stats[["team_id", "team_name", "points", "position"]] +``` + + + + + + diff --git a/solution/3200-3299/3246.Premier League Table Ranking/Solution.py b/solution/3200-3299/3246.Premier League Table Ranking/Solution.py new file mode 100644 index 000000000000..361bfe1ed984 --- /dev/null +++ b/solution/3200-3299/3246.Premier League Table Ranking/Solution.py @@ -0,0 +1,10 @@ +import pandas as pd + + +def calculate_team_standings(team_stats: pd.DataFrame) -> pd.DataFrame: + team_stats["points"] = team_stats["wins"] * 3 + team_stats["draws"] + team_stats["position"] = team_stats["points"].rank(method="min", ascending=False) + team_stats = team_stats.sort_values( + by=["points", "team_name"], ascending=[False, True] + ) + return team_stats[["team_id", "team_name", "points", "position"]] diff --git a/solution/3200-3299/3246.Premier League Table Ranking/Solution.sql b/solution/3200-3299/3246.Premier League Table Ranking/Solution.sql new file mode 100644 index 000000000000..59ed88014252 --- /dev/null +++ b/solution/3200-3299/3246.Premier League Table Ranking/Solution.sql @@ -0,0 +1,8 @@ +# Write your MySQL query statement below +SELECT + team_id, + team_name, + wins * 3 + draws points, + RANK() OVER (ORDER BY (wins * 3 + draws) DESC) position +FROM TeamStats +ORDER BY 3 DESC, 2; diff --git a/solution/3200-3299/3247.Number of Subsequences with Odd Sum/README.md b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/README.md new file mode 100644 index 000000000000..a601420ffda1 --- /dev/null +++ b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/README.md @@ -0,0 +1,209 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3247.Number%20of%20Subsequences%20with%20Odd%20Sum/README.md +tags: + - 数组 + - 数学 + - 动态规划 + - 组合数学 +--- + + + +# [3247. 奇数和子序列的数量 🔒](https://leetcode.cn/problems/number-of-subsequences-with-odd-sum) + +[English Version](/solution/3200-3299/3247.Number%20of%20Subsequences%20with%20Odd%20Sum/README_EN.md) + +## 题目描述 + + + +

            给定一个数组 nums,返回元素和为奇数的 子序列 的数量。

            + +

            由于答案可能很大,返回答案对 109 + 7 取模

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [1,1,1]

            + +

            输出:4

            + +

            解释:

            + +

            奇数和子序列为:[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1].

            +
            + +

            示例 2:

            + +
            +

            输入:nums = [1,2,2]

            + +

            输出:4

            + +

            解释:

            + +

            奇数和子序列为:[1, 2, 2], [1, 2, 2], [1, 2, 2], [1, 2, 2].

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 109
            • +
            + + + +## 解法 + + + +### 方法一:动态规划 + +我们定义 $f[0]$ 表示目前为止的子序列中,和为偶数的子序列个数,而 $f[1]$ 表示目前为止的子序列中,和为奇数的子序列个数。初始时 $f[0] = 0$, $f[1] = 0$。 + +遍历数组 $\textit{nums}$,对于每个数 $x$: + +如果 $x$ 为奇数,那么 $f[0]$ 和 $f[1]$ 的更新方式为: + +$$ +\begin{aligned} +f[0] & = (f[0] + f[1]) \bmod 10^9 + 7, \\ +f[1] & = (f[0] + f[1] + 1) \bmod 10^9 + 7. +\end{aligned} +$$ + +即,当前的和为偶数的子序列个数等于之前的和为偶数的子序列个数,加上之前的和为奇数的子序列拼上当前数 $x$ 的子序列个数;当前的和为奇数的子序列个数等于之前的和为偶数的子序列拼上当前数 $x$ 的子序列个数,加上之前的和为奇数的子序列个数,再加上一个只包含当前数 $x$ 的子序列。 + +如果 $x$ 为偶数,那么 $f[0]$ 和 $f[1]$ 的更新方式为: + +$$ +\begin{aligned} +f[0] & = (f[0] + f[0] + 1) \bmod 10^9 + 7, \\ +f[1] & = (f[1] + f[1]) \bmod 10^9 + 7. +\end{aligned} +$$ + +即,当前的和为偶数的子序列个数等于之前的和为偶数的子序列个数,加上之前的和为偶数的子序列拼上当前数 $x$ 的子序列个数,再加上一个只包含当前数 $x$ 的子序列;当前的和为奇数的子序列个数等于之前的和为奇数的子序列拼上当前数 $x$ 的子序列个数,加上之前的和为奇数的子序列个数。 + +最终,返回 $f[1]$ 即可。 + +时间复杂度 $O(n)$,其中 $n$ 为数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def subsequenceCount(self, nums: List[int]) -> int: + mod = 10**9 + 7 + f = [0] * 2 + for x in nums: + if x % 2: + f[0], f[1] = (f[0] + f[1]) % mod, (f[0] + f[1] + 1) % mod + else: + f[0], f[1] = (f[0] + f[0] + 1) % mod, (f[1] + f[1]) % mod + return f[1] +``` + +#### Java + +```java +class Solution { + public int subsequenceCount(int[] nums) { + final int mod = (int) 1e9 + 7; + int[] f = new int[2]; + for (int x : nums) { + int[] g = new int[2]; + if (x % 2 == 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int subsequenceCount(vector& nums) { + const int mod = 1e9 + 7; + vector f(2); + for (int x : nums) { + vector g(2); + if (x % 2 == 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; + } +}; +``` + +#### Go + +```go +func subsequenceCount(nums []int) int { + mod := int(1e9 + 7) + f := [2]int{} + for _, x := range nums { + g := [2]int{} + if x%2 == 1 { + g[0] = (f[0] + f[1]) % mod + g[1] = (f[0] + f[1] + 1) % mod + } else { + g[0] = (f[0] + f[0] + 1) % mod + g[1] = (f[1] + f[1]) % mod + } + f = g + } + return f[1] +} +``` + +#### TypeScript + +```ts +function subsequenceCount(nums: number[]): number { + const mod = 1e9 + 7; + let f = [0, 0]; + for (const x of nums) { + const g = [0, 0]; + if (x % 2 === 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; +} +``` + + + + + + diff --git a/solution/3200-3299/3247.Number of Subsequences with Odd Sum/README_EN.md b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/README_EN.md new file mode 100644 index 000000000000..f294a17bc290 --- /dev/null +++ b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/README_EN.md @@ -0,0 +1,207 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3247.Number%20of%20Subsequences%20with%20Odd%20Sum/README_EN.md +tags: + - Array + - Math + - Dynamic Programming + - Combinatorics +--- + + + +# [3247. Number of Subsequences with Odd Sum 🔒](https://leetcode.com/problems/number-of-subsequences-with-odd-sum) + +[中文文档](/solution/3200-3299/3247.Number%20of%20Subsequences%20with%20Odd%20Sum/README.md) + +## Description + + + +

            Given an array nums, return the number of subsequences with an odd sum of elements.

            + +

            Since the answer may be very large, return it modulo 109 + 7.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [1,1,1]

            + +

            Output: 4

            + +

            Explanation:

            + +

            The odd-sum subsequences are: [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1].

            +
            + +

            Example 2:

            + +
            +

            Input: nums = [1,2,2]

            + +

            Output: 4

            + +

            Explanation:

            + +

            The odd-sum subsequences are: [1, 2, 2], [1, 2, 2], [1, 2, 2], [1, 2, 2].

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= nums.length <= 105
            • +
            • 1 <= nums[i] <= 109
            • +
            + + + +## Solutions + + + +### Solution 1: Dynamic Programming + +We define $f[0]$ to represent the number of subsequences with an even sum so far, and $f[1]$ to represent the number of subsequences with an odd sum so far. Initially, $f[0] = 0$ and $f[1] = 0$. + +Traverse the array $\textit{nums}$, for each number $x$: + +If $x$ is odd, the update rules for $f[0]$ and $f[1]$ are: + +$$ +\begin{aligned} +f[0] & = (f[0] + f[1]) \bmod 10^9 + 7, \\ +f[1] & = (f[0] + f[1] + 1) \bmod 10^9 + 7. +\end{aligned} +$$ + +That is, the current number of subsequences with an even sum is equal to the previous number of subsequences with an even sum plus the number of subsequences with an odd sum concatenated with the current number $x$; the current number of subsequences with an odd sum is equal to the previous number of subsequences with an even sum concatenated with the current number $x$ plus the previous number of subsequences with an odd sum, plus one subsequence containing only the current number $x$. + +If $x$ is even, the update rules for $f[0]$ and $f[1]$ are: + +$$ +\begin{aligned} +f[0] & = (f[0] + f[0] + 1) \bmod 10^9 + 7, \\ +f[1] & = (f[1] + f[1]) \bmod 10^9 + 7. +\end{aligned} +$$ + +That is, the current number of subsequences with an even sum is equal to the previous number of subsequences with an even sum plus the number of subsequences with an even sum concatenated with the current number $x$, plus one subsequence containing only the current number $x$; the current number of subsequences with an odd sum is equal to the previous number of subsequences with an odd sum concatenated with the current number $x$ plus the previous number of subsequences with an odd sum. + +Finally, return $f[1]$. + +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{nums}$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def subsequenceCount(self, nums: List[int]) -> int: + mod = 10**9 + 7 + f = [0] * 2 + for x in nums: + if x % 2: + f[0], f[1] = (f[0] + f[1]) % mod, (f[0] + f[1] + 1) % mod + else: + f[0], f[1] = (f[0] + f[0] + 1) % mod, (f[1] + f[1]) % mod + return f[1] +``` + +#### Java + +```java +class Solution { + public int subsequenceCount(int[] nums) { + final int mod = (int) 1e9 + 7; + int[] f = new int[2]; + for (int x : nums) { + int[] g = new int[2]; + if (x % 2 == 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int subsequenceCount(vector& nums) { + const int mod = 1e9 + 7; + vector f(2); + for (int x : nums) { + vector g(2); + if (x % 2 == 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; + } +}; +``` + +#### Go + +```go +func subsequenceCount(nums []int) int { + mod := int(1e9 + 7) + f := [2]int{} + for _, x := range nums { + g := [2]int{} + if x%2 == 1 { + g[0] = (f[0] + f[1]) % mod + g[1] = (f[0] + f[1] + 1) % mod + } else { + g[0] = (f[0] + f[0] + 1) % mod + g[1] = (f[1] + f[1]) % mod + } + f = g + } + return f[1] +} +``` + +#### TypeScript + +```ts +function subsequenceCount(nums: number[]): number { + const mod = 1e9 + 7; + let f = [0, 0]; + for (const x of nums) { + const g = [0, 0]; + if (x % 2 === 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; +} +``` + + + + + + diff --git a/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.cpp b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.cpp new file mode 100644 index 000000000000..c2a88c814b99 --- /dev/null +++ b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + int subsequenceCount(vector& nums) { + const int mod = 1e9 + 7; + vector f(2); + for (int x : nums) { + vector g(2); + if (x % 2 == 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; + } +}; diff --git a/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.go b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.go new file mode 100644 index 000000000000..0ddb57c6aca8 --- /dev/null +++ b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.go @@ -0,0 +1,16 @@ +func subsequenceCount(nums []int) int { + mod := int(1e9 + 7) + f := [2]int{} + for _, x := range nums { + g := [2]int{} + if x%2 == 1 { + g[0] = (f[0] + f[1]) % mod + g[1] = (f[0] + f[1] + 1) % mod + } else { + g[0] = (f[0] + f[0] + 1) % mod + g[1] = (f[1] + f[1]) % mod + } + f = g + } + return f[1] +} diff --git a/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.java b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.java new file mode 100644 index 000000000000..f9312a8a8267 --- /dev/null +++ b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.java @@ -0,0 +1,18 @@ +class Solution { + public int subsequenceCount(int[] nums) { + final int mod = (int) 1e9 + 7; + int[] f = new int[2]; + for (int x : nums) { + int[] g = new int[2]; + if (x % 2 == 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; + } +} diff --git a/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.py b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.py new file mode 100644 index 000000000000..421f8d00986b --- /dev/null +++ b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.py @@ -0,0 +1,10 @@ +class Solution: + def subsequenceCount(self, nums: List[int]) -> int: + mod = 10**9 + 7 + f = [0] * 2 + for x in nums: + if x % 2: + f[0], f[1] = (f[0] + f[1]) % mod, (f[0] + f[1] + 1) % mod + else: + f[0], f[1] = (f[0] + f[0] + 1) % mod, (f[1] + f[1]) % mod + return f[1] diff --git a/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.ts b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.ts new file mode 100644 index 000000000000..3aa3745777cf --- /dev/null +++ b/solution/3200-3299/3247.Number of Subsequences with Odd Sum/Solution.ts @@ -0,0 +1,16 @@ +function subsequenceCount(nums: number[]): number { + const mod = 1e9 + 7; + let f = [0, 0]; + for (const x of nums) { + const g = [0, 0]; + if (x % 2 === 1) { + g[0] = (f[0] + f[1]) % mod; + g[1] = (f[0] + f[1] + 1) % mod; + } else { + g[0] = (f[0] + f[0] + 1) % mod; + g[1] = (f[1] + f[1]) % mod; + } + f = g; + } + return f[1]; +} diff --git a/solution/3200-3299/3248.Snake in Matrix/README.md b/solution/3200-3299/3248.Snake in Matrix/README.md new file mode 100644 index 000000000000..321f12e83856 --- /dev/null +++ b/solution/3200-3299/3248.Snake in Matrix/README.md @@ -0,0 +1,297 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3248.Snake%20in%20Matrix/README.md +tags: + - 数组 + - 字符串 + - 模拟 +--- + + + +# [3248. 矩阵中的蛇](https://leetcode.cn/problems/snake-in-matrix) + +[English Version](/solution/3200-3299/3248.Snake%20in%20Matrix/README_EN.md) + +## 题目描述 + + + +

            大小为 n x n 的矩阵 grid 中有一条蛇。蛇可以朝 四个可能的方向 移动。矩阵中的每个单元格都使用位置进行标识: grid[i][j] = (i * n) + j

            + +

            蛇从单元格 0 开始,并遵循一系列命令移动。

            + +

            给你一个整数 n 表示 grid 的大小,另给你一个字符串数组 commands,其中包括 "UP""RIGHT""DOWN""LEFT"。题目测评数据保证蛇在整个移动过程中将始终位于 grid 边界内。

            + +

            返回执行 commands 后蛇所停留的最终单元格的位置。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:n = 2, commands = ["RIGHT","DOWN"]

            + +

            输出:3

            + +

            解释:

            + +
            + + + + + + + + + + + +
            01
            23
            + + + + + + + + + + + + +
            01
            23
            + + + + + + + + + + + + +
            01
            23
            +
            +
            + +

            示例 2:

            + +
            +

            输入:n = 3, commands = ["DOWN","RIGHT","UP"]

            + +

            输出:1

            + +

            解释:

            + +
            + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            + + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            + + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            + + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            +
            +
            + +

             

            + +

            提示:

            + +
              +
            • 2 <= n <= 10
            • +
            • 1 <= commands.length <= 100
            • +
            • commands 仅由 "UP""RIGHT""DOWN""LEFT" 组成。
            • +
            • 生成的测评数据确保蛇不会移动到矩阵的边界外。
            • +
            + + + +## 解法 + + + +### 方法一:模拟 + +我们可以用两个变量 $x$ 和 $y$ 来表示蛇的位置,初始时 $x = y = 0$,然后遍历 $\textit{commands}$,根据当前的命令更新 $x$ 和 $y$ 的值,最后返回 $x \times n + y$ 即可。 + +时间复杂度 $O(n)$,其中 $n$ 是数组 $\textit{commands}$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def finalPositionOfSnake(self, n: int, commands: List[str]) -> int: + x = y = 0 + for c in commands: + match c[0]: + case "U": + x -= 1 + case "D": + x += 1 + case "L": + y -= 1 + case "R": + y += 1 + return x * n + y +``` + +#### Java + +```java +class Solution { + public int finalPositionOfSnake(int n, List commands) { + int x = 0, y = 0; + for (var c : commands) { + switch (c.charAt(0)) { + case 'U' -> x--; + case 'D' -> x++; + case 'L' -> y--; + case 'R' -> y++; + } + } + return x * n + y; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int finalPositionOfSnake(int n, vector& commands) { + int x = 0, y = 0; + for (const auto& c : commands) { + switch (c[0]) { + case 'U': x--; break; + case 'D': x++; break; + case 'L': y--; break; + case 'R': y++; break; + } + } + return x * n + y; + } +}; +``` + +#### Go + +```go +func finalPositionOfSnake(n int, commands []string) int { + x, y := 0, 0 + for _, c := range commands { + switch c[0] { + case 'U': + x-- + case 'D': + x++ + case 'L': + y-- + case 'R': + y++ + } + } + return x*n + y +} +``` + +#### TypeScript + +```ts +function finalPositionOfSnake(n: number, commands: string[]): number { + let [x, y] = [0, 0]; + for (const c of commands) { + c[0] === 'U' && x--; + c[0] === 'D' && x++; + c[0] === 'L' && y--; + c[0] === 'R' && y++; + } + return x * n + y; +} +``` + + + + + + diff --git a/solution/3200-3299/3248.Snake in Matrix/README_EN.md b/solution/3200-3299/3248.Snake in Matrix/README_EN.md new file mode 100644 index 000000000000..4973a21485aa --- /dev/null +++ b/solution/3200-3299/3248.Snake in Matrix/README_EN.md @@ -0,0 +1,295 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3248.Snake%20in%20Matrix/README_EN.md +tags: + - Array + - String + - Simulation +--- + + + +# [3248. Snake in Matrix](https://leetcode.com/problems/snake-in-matrix) + +[中文文档](/solution/3200-3299/3248.Snake%20in%20Matrix/README.md) + +## Description + + + +

            There is a snake in an n x n matrix grid and can move in four possible directions. Each cell in the grid is identified by the position: grid[i][j] = (i * n) + j.

            + +

            The snake starts at cell 0 and follows a sequence of commands.

            + +

            You are given an integer n representing the size of the grid and an array of strings commands where each command[i] is either "UP", "RIGHT", "DOWN", and "LEFT". It's guaranteed that the snake will remain within the grid boundaries throughout its movement.

            + +

            Return the position of the final cell where the snake ends up after executing commands.

            + +

             

            +

            Example 1:

            + +
            +

            Input: n = 2, commands = ["RIGHT","DOWN"]

            + +

            Output: 3

            + +

            Explanation:

            + +
            + + + + + + + + + + + +
            01
            23
            + + + + + + + + + + + + +
            01
            23
            + + + + + + + + + + + + +
            01
            23
            +
            +
            + +

            Example 2:

            + +
            +

            Input: n = 3, commands = ["DOWN","RIGHT","UP"]

            + +

            Output: 1

            + +

            Explanation:

            + +
            + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            + + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            + + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            + + + + + + + + + + + + + + + + + + + +
            012
            345
            678
            +
            +
            + +

             

            +

            Constraints:

            + +
              +
            • 2 <= n <= 10
            • +
            • 1 <= commands.length <= 100
            • +
            • commands consists only of "UP", "RIGHT", "DOWN", and "LEFT".
            • +
            • The input is generated such the snake will not move outside of the boundaries.
            • +
            + + + +## Solutions + + + +### Solution 1: Simulation + +We can use two variables $x$ and $y$ to represent the position of the snake. Initially, $x = y = 0$. Then, we traverse $\textit{commands}$ and update the values of $x$ and $y$ based on the current command. Finally, we return $x \times n + y$. + +The time complexity is $O(n)$, where $n$ is the length of the array $\textit{commands}$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def finalPositionOfSnake(self, n: int, commands: List[str]) -> int: + x = y = 0 + for c in commands: + match c[0]: + case "U": + x -= 1 + case "D": + x += 1 + case "L": + y -= 1 + case "R": + y += 1 + return x * n + y +``` + +#### Java + +```java +class Solution { + public int finalPositionOfSnake(int n, List commands) { + int x = 0, y = 0; + for (var c : commands) { + switch (c.charAt(0)) { + case 'U' -> x--; + case 'D' -> x++; + case 'L' -> y--; + case 'R' -> y++; + } + } + return x * n + y; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int finalPositionOfSnake(int n, vector& commands) { + int x = 0, y = 0; + for (const auto& c : commands) { + switch (c[0]) { + case 'U': x--; break; + case 'D': x++; break; + case 'L': y--; break; + case 'R': y++; break; + } + } + return x * n + y; + } +}; +``` + +#### Go + +```go +func finalPositionOfSnake(n int, commands []string) int { + x, y := 0, 0 + for _, c := range commands { + switch c[0] { + case 'U': + x-- + case 'D': + x++ + case 'L': + y-- + case 'R': + y++ + } + } + return x*n + y +} +``` + +#### TypeScript + +```ts +function finalPositionOfSnake(n: number, commands: string[]): number { + let [x, y] = [0, 0]; + for (const c of commands) { + c[0] === 'U' && x--; + c[0] === 'D' && x++; + c[0] === 'L' && y--; + c[0] === 'R' && y++; + } + return x * n + y; +} +``` + + + + + + diff --git a/solution/3200-3299/3248.Snake in Matrix/Solution.cpp b/solution/3200-3299/3248.Snake in Matrix/Solution.cpp new file mode 100644 index 000000000000..76bf76325ff9 --- /dev/null +++ b/solution/3200-3299/3248.Snake in Matrix/Solution.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int finalPositionOfSnake(int n, vector& commands) { + int x = 0, y = 0; + for (const auto& c : commands) { + switch (c[0]) { + case 'U': x--; break; + case 'D': x++; break; + case 'L': y--; break; + case 'R': y++; break; + } + } + return x * n + y; + } +}; diff --git a/solution/3200-3299/3248.Snake in Matrix/Solution.go b/solution/3200-3299/3248.Snake in Matrix/Solution.go new file mode 100644 index 000000000000..14125f00d9be --- /dev/null +++ b/solution/3200-3299/3248.Snake in Matrix/Solution.go @@ -0,0 +1,16 @@ +func finalPositionOfSnake(n int, commands []string) int { + x, y := 0, 0 + for _, c := range commands { + switch c[0] { + case 'U': + x-- + case 'D': + x++ + case 'L': + y-- + case 'R': + y++ + } + } + return x*n + y +} diff --git a/solution/3200-3299/3248.Snake in Matrix/Solution.java b/solution/3200-3299/3248.Snake in Matrix/Solution.java new file mode 100644 index 000000000000..52f6251492a6 --- /dev/null +++ b/solution/3200-3299/3248.Snake in Matrix/Solution.java @@ -0,0 +1,14 @@ +class Solution { + public int finalPositionOfSnake(int n, List commands) { + int x = 0, y = 0; + for (var c : commands) { + switch (c.charAt(0)) { + case 'U' -> x--; + case 'D' -> x++; + case 'L' -> y--; + case 'R' -> y++; + } + } + return x * n + y; + } +} diff --git a/solution/3200-3299/3248.Snake in Matrix/Solution.py b/solution/3200-3299/3248.Snake in Matrix/Solution.py new file mode 100644 index 000000000000..2063c455b24d --- /dev/null +++ b/solution/3200-3299/3248.Snake in Matrix/Solution.py @@ -0,0 +1,14 @@ +class Solution: + def finalPositionOfSnake(self, n: int, commands: List[str]) -> int: + x = y = 0 + for c in commands: + match c[0]: + case "U": + x -= 1 + case "D": + x += 1 + case "L": + y -= 1 + case "R": + y += 1 + return x * n + y diff --git a/solution/3200-3299/3248.Snake in Matrix/Solution.ts b/solution/3200-3299/3248.Snake in Matrix/Solution.ts new file mode 100644 index 000000000000..26c4b7e17792 --- /dev/null +++ b/solution/3200-3299/3248.Snake in Matrix/Solution.ts @@ -0,0 +1,10 @@ +function finalPositionOfSnake(n: number, commands: string[]): number { + let [x, y] = [0, 0]; + for (const c of commands) { + c[0] === 'U' && x--; + c[0] === 'D' && x++; + c[0] === 'L' && y--; + c[0] === 'R' && y++; + } + return x * n + y; +} diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/README.md b/solution/3200-3299/3249.Count the Number of Good Nodes/README.md new file mode 100644 index 000000000000..ec3b3f0a8b8c --- /dev/null +++ b/solution/3200-3299/3249.Count the Number of Good Nodes/README.md @@ -0,0 +1,277 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README.md +tags: + - 树 + - 深度优先搜索 +--- + + + +# [3249. 统计好节点的数目](https://leetcode.cn/problems/count-the-number-of-good-nodes) + +[English Version](/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README_EN.md) + +## 题目描述 + + + +

            现有一棵 无向 树,树中包含 n 个节点,按从 0n - 1 标记。树的根节点是节点 0 。给你一个长度为 n - 1 的二维整数数组 edges,其中 edges[i] = [ai, bi] 表示树中节点 ai 与节点 bi 之间存在一条边。

            + +

            如果一个节点的所有子节点为根的 子树 包含的节点数相同,则认为该节点是一个 好节点

            + +

            返回给定树中 好节点 的数量。

            + +

            子树 指的是一个节点以及它所有后代节点构成的一棵树。

            + +

             

            + +

             

            + +

            示例 1:

            + +
            +

            输入:edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6]]

            + +

            输出:7

            + +

            说明:

            + +

            树的所有节点都是好节点。

            +
            + +

            示例 2:

            + +
            +

            输入:edges = [[0,1],[1,2],[2,3],[3,4],[0,5],[1,6],[2,7],[3,8]]

            + +

            输出:6

            + +

            说明:

            + +

            树中有 6 个好节点。上图中已将这些节点着色。

            +
            + +

            示例 3:

            + +
            +

            输入:edges = [[0,1],[1,2],[1,3],[1,4],[0,5],[5,6],[6,7],[7,8],[0,9],[9,10],[9,12],[10,11]]

            + +

            输出:12

            + +

            解释:

            + +

            除了节点 9 以外其他所有节点都是好节点。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 2 <= n <= 105
            • +
            • edges.length == n - 1
            • +
            • edges[i].length == 2
            • +
            • 0 <= ai, bi < n
            • +
            • 输入确保 edges 总表示一棵有效的树。
            • +
            + + + +## 解法 + + + +### 方法一:DFS + +我们先根据题目给定的边 $\textit{edges}$ 构建出树的邻接表 $\textit{g}$,其中 $\textit{g}[a]$ 表示节点 $a$ 的所有邻居节点。 + +然后,我们设计一个函数 $\textit{dfs}(a, \textit{fa})$,表示计算以节点 $a$ 为根的子树中的节点数,并累计好节点的数量。其中 $\textit{fa}$ 表示节点 $a$ 的父节点。 + +函数 $\textit{dfs}(a, \textit{fa})$ 的执行过程如下: + +1. 初始化变量 $\textit{pre} = -1$, $\textit{cnt} = 1$, $\textit{ok} = 1$,分别表示节点 $a$ 的某个子树的节点数、节点 $a$ 的所有子树的节点数、以及节点 $a$ 是否为好节点。 +2. 遍历节点 $a$ 的所有邻居节点 $b$,如果 $b$ 不等于 $\textit{fa}$,则递归调用 $\textit{dfs}(b, a)$,返回值为 $\textit{cur}$,并累加到 $\textit{cnt}$ 中。如果 $\textit{pre} < 0$,则将 $\textit{cur}$ 赋值给 $\textit{pre}$;否则,如果 $\textit{pre}$ 不等于 $\textit{cur}$,说明节点 $a$ 的不同子树的节点数不同,将 $\textit{ok}$ 置为 $0$。 +3. 最后,累加 $\textit{ok}$ 到答案中,并返回 $\textit{cnt}$。 + +在主函数中,我们调用 $\textit{dfs}(0, -1)$,最后返回答案。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 表示节点的数量。 + + + +#### Python3 + +```python +class Solution: + def countGoodNodes(self, edges: List[List[int]]) -> int: + def dfs(a: int, fa: int) -> int: + pre = -1 + cnt = ok = 1 + for b in g[a]: + if b != fa: + cur = dfs(b, a) + cnt += cur + if pre < 0: + pre = cur + elif pre != cur: + ok = 0 + nonlocal ans + ans += ok + return cnt + + g = defaultdict(list) + for a, b in edges: + g[a].append(b) + g[b].append(a) + ans = 0 + dfs(0, -1) + return ans +``` + +#### Java + +```java +class Solution { + private int ans; + private List[] g; + + public int countGoodNodes(int[][] edges) { + int n = edges.length + 1; + g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + for (var e : edges) { + int a = e[0], b = e[1]; + g[a].add(b); + g[b].add(a); + } + dfs(0, -1); + return ans; + } + + private int dfs(int a, int fa) { + int pre = -1, cnt = 1, ok = 1; + for (int b : g[a]) { + if (b != fa) { + int cur = dfs(b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre != cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countGoodNodes(vector>& edges) { + int n = edges.size() + 1; + vector g[n]; + for (const auto& e : edges) { + int a = e[0], b = e[1]; + g[a].push_back(b); + g[b].push_back(a); + } + int ans = 0; + auto dfs = [&](auto&& dfs, int a, int fa) -> int { + int pre = -1, cnt = 1, ok = 1; + for (int b : g[a]) { + if (b != fa) { + int cur = dfs(dfs, b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre != cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + }; + dfs(dfs, 0, -1); + return ans; + } +}; +``` + +#### Go + +```go +func countGoodNodes(edges [][]int) (ans int) { + n := len(edges) + 1 + g := make([][]int, n) + for _, e := range edges { + a, b := e[0], e[1] + g[a] = append(g[a], b) + g[b] = append(g[b], a) + } + var dfs func(int, int) int + dfs = func(a, fa int) int { + pre, cnt, ok := -1, 1, 1 + for _, b := range g[a] { + if b != fa { + cur := dfs(b, a) + cnt += cur + if pre < 0 { + pre = cur + } else if pre != cur { + ok = 0 + } + } + } + ans += ok + return cnt + } + dfs(0, -1) + return +} +``` + +#### TypeScript + +```ts +function countGoodNodes(edges: number[][]): number { + const n = edges.length + 1; + const g: number[][] = Array.from({ length: n }, () => []); + for (const [a, b] of edges) { + g[a].push(b); + g[b].push(a); + } + let ans = 0; + const dfs = (a: number, fa: number): number => { + let [pre, cnt, ok] = [-1, 1, 1]; + for (const b of g[a]) { + if (b !== fa) { + const cur = dfs(b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre !== cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + }; + dfs(0, -1); + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/README_EN.md b/solution/3200-3299/3249.Count the Number of Good Nodes/README_EN.md new file mode 100644 index 000000000000..c2a8453e40fe --- /dev/null +++ b/solution/3200-3299/3249.Count the Number of Good Nodes/README_EN.md @@ -0,0 +1,273 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README_EN.md +tags: + - Tree + - Depth-First Search +--- + + + +# [3249. Count the Number of Good Nodes](https://leetcode.com/problems/count-the-number-of-good-nodes) + +[中文文档](/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README.md) + +## Description + + + +

            There is an undirected tree with n nodes labeled from 0 to n - 1, and rooted at node 0. You are given a 2D integer array edges of length n - 1, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the tree.

            + +

            A node is good if all the subtrees rooted at its children have the same size.

            + +

            Return the number of good nodes in the given tree.

            + +

            A subtree of treeName is a tree consisting of a node in treeName and all of its descendants.

            + +

             

            +

            Example 1:

            + +
            +

            Input: edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6]]

            + +

            Output: 7

            + +

            Explanation:

            + +

            All of the nodes of the given tree are good.

            +
            + +

            Example 2:

            + +
            +

            Input: edges = [[0,1],[1,2],[2,3],[3,4],[0,5],[1,6],[2,7],[3,8]]

            + +

            Output: 6

            + +

            Explanation:

            + +

            There are 6 good nodes in the given tree. They are colored in the image above.

            + +

            Example 3:

            + +
            +

            Input: edges = [[0,1],[1,2],[1,3],[1,4],[0,5],[5,6],[6,7],[7,8],[0,9],[9,10],[9,12],[10,11]]

            + +

            Output: 12

            + +

            Explanation:

            + +

            All nodes except node 9 are good.

            +
            +
            + +

             

            +

            Constraints:

            + +
              +
            • 2 <= n <= 105
            • +
            • edges.length == n - 1
            • +
            • edges[i].length == 2
            • +
            • 0 <= ai, bi < n
            • +
            • The input is generated such that edges represents a valid tree.
            • +
            + + + +## Solutions + + + +### Solution 1: DFS + +First, we construct the adjacency list $\textit{g}$ of the tree based on the given edges $\textit{edges}$, where $\textit{g}[a]$ represents all the neighboring nodes of node $a$. + +Next, we design a function $\textit{dfs}(a, \textit{fa})$ to calculate the number of nodes in the subtree rooted at node $a$ and to accumulate the count of good nodes. Here, $\textit{fa}$ represents the parent node of node $a$. + +The execution process of the function $\textit{dfs}(a, \textit{fa})$ is as follows: + +1. Initialize variables $\textit{pre} = -1$, $\textit{cnt} = 1$, $\textit{ok} = 1$, representing the number of nodes in a subtree of node $a$, the total number of nodes in all subtrees of node $a$, and whether node $a$ is a good node, respectively. +2. Traverse all neighboring nodes $b$ of node $a$. If $b$ is not equal to $\textit{fa}$, recursively call $\textit{dfs}(b, a)$, with the return value being $\textit{cur}$, and add $\textit{cur}$ to $\textit{cnt}$. If $\textit{pre} < 0$, assign $\textit{cur}$ to $\textit{pre}$; otherwise, if $\textit{pre}$ is not equal to $\textit{cur}$, it means the number of nodes in different subtrees of node $a$ is different, and set $\textit{ok}$ to $0$. +3. Finally, add $\textit{ok}$ to the answer and return $\textit{cnt}$. + +In the main function, we call $\textit{dfs}(0, -1)$ and return the final answer. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ represents the number of nodes. + + + +#### Python3 + +```python +class Solution: + def countGoodNodes(self, edges: List[List[int]]) -> int: + def dfs(a: int, fa: int) -> int: + pre = -1 + cnt = ok = 1 + for b in g[a]: + if b != fa: + cur = dfs(b, a) + cnt += cur + if pre < 0: + pre = cur + elif pre != cur: + ok = 0 + nonlocal ans + ans += ok + return cnt + + g = defaultdict(list) + for a, b in edges: + g[a].append(b) + g[b].append(a) + ans = 0 + dfs(0, -1) + return ans +``` + +#### Java + +```java +class Solution { + private int ans; + private List[] g; + + public int countGoodNodes(int[][] edges) { + int n = edges.length + 1; + g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + for (var e : edges) { + int a = e[0], b = e[1]; + g[a].add(b); + g[b].add(a); + } + dfs(0, -1); + return ans; + } + + private int dfs(int a, int fa) { + int pre = -1, cnt = 1, ok = 1; + for (int b : g[a]) { + if (b != fa) { + int cur = dfs(b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre != cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countGoodNodes(vector>& edges) { + int n = edges.size() + 1; + vector g[n]; + for (const auto& e : edges) { + int a = e[0], b = e[1]; + g[a].push_back(b); + g[b].push_back(a); + } + int ans = 0; + auto dfs = [&](auto&& dfs, int a, int fa) -> int { + int pre = -1, cnt = 1, ok = 1; + for (int b : g[a]) { + if (b != fa) { + int cur = dfs(dfs, b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre != cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + }; + dfs(dfs, 0, -1); + return ans; + } +}; +``` + +#### Go + +```go +func countGoodNodes(edges [][]int) (ans int) { + n := len(edges) + 1 + g := make([][]int, n) + for _, e := range edges { + a, b := e[0], e[1] + g[a] = append(g[a], b) + g[b] = append(g[b], a) + } + var dfs func(int, int) int + dfs = func(a, fa int) int { + pre, cnt, ok := -1, 1, 1 + for _, b := range g[a] { + if b != fa { + cur := dfs(b, a) + cnt += cur + if pre < 0 { + pre = cur + } else if pre != cur { + ok = 0 + } + } + } + ans += ok + return cnt + } + dfs(0, -1) + return +} +``` + +#### TypeScript + +```ts +function countGoodNodes(edges: number[][]): number { + const n = edges.length + 1; + const g: number[][] = Array.from({ length: n }, () => []); + for (const [a, b] of edges) { + g[a].push(b); + g[b].push(a); + } + let ans = 0; + const dfs = (a: number, fa: number): number => { + let [pre, cnt, ok] = [-1, 1, 1]; + for (const b of g[a]) { + if (b !== fa) { + const cur = dfs(b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre !== cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + }; + dfs(0, -1); + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.cpp b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.cpp new file mode 100644 index 000000000000..73189db59949 --- /dev/null +++ b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.cpp @@ -0,0 +1,31 @@ +class Solution { +public: + int countGoodNodes(vector>& edges) { + int n = edges.size() + 1; + vector g[n]; + for (const auto& e : edges) { + int a = e[0], b = e[1]; + g[a].push_back(b); + g[b].push_back(a); + } + int ans = 0; + auto dfs = [&](auto&& dfs, int a, int fa) -> int { + int pre = -1, cnt = 1, ok = 1; + for (int b : g[a]) { + if (b != fa) { + int cur = dfs(dfs, b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre != cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + }; + dfs(dfs, 0, -1); + return ans; + } +}; diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.go b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.go new file mode 100644 index 000000000000..fe5bc40195bd --- /dev/null +++ b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.go @@ -0,0 +1,28 @@ +func countGoodNodes(edges [][]int) (ans int) { + n := len(edges) + 1 + g := make([][]int, n) + for _, e := range edges { + a, b := e[0], e[1] + g[a] = append(g[a], b) + g[b] = append(g[b], a) + } + var dfs func(int, int) int + dfs = func(a, fa int) int { + pre, cnt, ok := -1, 1, 1 + for _, b := range g[a] { + if b != fa { + cur := dfs(b, a) + cnt += cur + if pre < 0 { + pre = cur + } else if pre != cur { + ok = 0 + } + } + } + ans += ok + return cnt + } + dfs(0, -1) + return +} diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.java b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.java new file mode 100644 index 000000000000..3917be07c689 --- /dev/null +++ b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.java @@ -0,0 +1,34 @@ +class Solution { + private int ans; + private List[] g; + + public int countGoodNodes(int[][] edges) { + int n = edges.length + 1; + g = new List[n]; + Arrays.setAll(g, k -> new ArrayList<>()); + for (var e : edges) { + int a = e[0], b = e[1]; + g[a].add(b); + g[b].add(a); + } + dfs(0, -1); + return ans; + } + + private int dfs(int a, int fa) { + int pre = -1, cnt = 1, ok = 1; + for (int b : g[a]) { + if (b != fa) { + int cur = dfs(b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre != cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + } +} diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.py b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.py new file mode 100644 index 000000000000..035ca6e74663 --- /dev/null +++ b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.py @@ -0,0 +1,24 @@ +class Solution: + def countGoodNodes(self, edges: List[List[int]]) -> int: + def dfs(a: int, fa: int) -> int: + pre = -1 + cnt = ok = 1 + for b in g[a]: + if b != fa: + cur = dfs(b, a) + cnt += cur + if pre < 0: + pre = cur + elif pre != cur: + ok = 0 + nonlocal ans + ans += ok + return cnt + + g = defaultdict(list) + for a, b in edges: + g[a].append(b) + g[b].append(a) + ans = 0 + dfs(0, -1) + return ans diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.ts b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.ts new file mode 100644 index 000000000000..adfc1f2b20d3 --- /dev/null +++ b/solution/3200-3299/3249.Count the Number of Good Nodes/Solution.ts @@ -0,0 +1,27 @@ +function countGoodNodes(edges: number[][]): number { + const n = edges.length + 1; + const g: number[][] = Array.from({ length: n }, () => []); + for (const [a, b] of edges) { + g[a].push(b); + g[b].push(a); + } + let ans = 0; + const dfs = (a: number, fa: number): number => { + let [pre, cnt, ok] = [-1, 1, 1]; + for (const b of g[a]) { + if (b !== fa) { + const cur = dfs(b, a); + cnt += cur; + if (pre < 0) { + pre = cur; + } else if (pre !== cur) { + ok = 0; + } + } + } + ans += ok; + return cnt; + }; + dfs(0, -1); + return ans; +} diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/images/rob.jpg b/solution/3200-3299/3249.Count the Number of Good Nodes/images/rob.jpg new file mode 100644 index 000000000000..78cf21ae7bac Binary files /dev/null and b/solution/3200-3299/3249.Count the Number of Good Nodes/images/rob.jpg differ diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/images/screenshot-2024-06-03-193552.png b/solution/3200-3299/3249.Count the Number of Good Nodes/images/screenshot-2024-06-03-193552.png new file mode 100644 index 000000000000..1a4674f03a9f Binary files /dev/null and b/solution/3200-3299/3249.Count the Number of Good Nodes/images/screenshot-2024-06-03-193552.png differ diff --git a/solution/3200-3299/3249.Count the Number of Good Nodes/images/tree1.png b/solution/3200-3299/3249.Count the Number of Good Nodes/images/tree1.png new file mode 100644 index 000000000000..aa41918f8081 Binary files /dev/null and b/solution/3200-3299/3249.Count the Number of Good Nodes/images/tree1.png differ diff --git a/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/README.md b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/README.md new file mode 100644 index 000000000000..64fc72f3f477 --- /dev/null +++ b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/README.md @@ -0,0 +1,254 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README.md +tags: + - 数组 + - 数学 + - 动态规划 + - 组合数学 + - 前缀和 +--- + + + +# [3250. 单调数组对的数目 I](https://leetcode.cn/problems/find-the-count-of-monotonic-pairs-i) + +[English Version](/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README_EN.md) + +## 题目描述 + + + +

            给你一个长度为 n 的  整数数组 nums 。

            + +

            如果两个 非负 整数数组 (arr1, arr2) 满足以下条件,我们称它们是 单调 数组对:

            + +
              +
            • 两个数组的长度都是 n 。
            • +
            • arr1 是单调 非递减 的,换句话说 arr1[0] <= arr1[1] <= ... <= arr1[n - 1] 。
            • +
            • arr2 是单调 非递增 的,换句话说 arr2[0] >= arr2[1] >= ... >= arr2[n - 1] 。
            • +
            • 对于所有的 0 <= i <= n - 1 都有 arr1[i] + arr2[i] == nums[i] 。
            • +
            + +

            请你返回所有 单调 数组对的数目。

            + +

            由于答案可能很大,请你将它对 109 + 7 取余 后返回。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [2,3,2]

            + +

            输出:4

            + +

            解释:

            + +

            单调数组对包括:

            + +
              +
            1. ([0, 1, 1], [2, 2, 1])
            2. +
            3. ([0, 1, 2], [2, 2, 0])
            4. +
            5. ([0, 2, 2], [2, 1, 0])
            6. +
            7. ([1, 2, 2], [1, 1, 0])
            8. +
            +
            + +

            示例 2:

            + +
            +

            输入:nums = [5,5,5,5]

            + +

            输出:126

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n == nums.length <= 2000
            • +
            • 1 <= nums[i] <= 50
            • +
            + + + +## 解法 + + + +### 方法一:动态规划 + 前缀和优化 + +我们定义 $f[i][j]$ 表示下标 $[0,..i]$ 的单调数组对的数目,且 $arr1[i] = j$。初始时 $[i][j] = 0$,答案为 $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$。 + +当 $i = 0$ 时,有 $[0][j] = 1$,其中 $0 \leq j \leq \textit{nums}[0]$。 + +当 $i > 0$ 时,我们可以根据 $f[i-1][j']$ 计算 $f[i][j]$。由于 $\textit{arr1}$ 是单调非递减的,因此 $j' \leq j$。又由于 $\textit{arr2}$ 是单调非递增的,因此 $\textit{nums}[i] - j \leq \textit{nums}[i - 1] - j'$。即 $j' \leq \min(j, j + \textit{nums}[i - 1] - \textit{nums}[i])$。 + +答案为 $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$。 + +时间复杂度 $O(n \times m)$,空间复杂度 $O(n \times m)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度,而 $m$ 表示数组 $\textit{nums}$ 中的最大值。 + + + +#### Python3 + +```python +class Solution: + def countOfPairs(self, nums: List[int]) -> int: + mod = 10**9 + 7 + n, m = len(nums), max(nums) + f = [[0] * (m + 1) for _ in range(n)] + for j in range(nums[0] + 1): + f[0][j] = 1 + for i in range(1, n): + s = list(accumulate(f[i - 1])) + for j in range(nums[i] + 1): + k = min(j, j + nums[i - 1] - nums[i]) + if k >= 0: + f[i][j] = s[k] % mod + return sum(f[-1][: nums[-1] + 1]) % mod +``` + +#### Java + +```java +class Solution { + public int countOfPairs(int[] nums) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int m = Arrays.stream(nums).max().getAsInt(); + int[][] f = new int[n][m + 1]; + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + int[] g = new int[m + 1]; + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countOfPairs(vector& nums) { + const int mod = 1e9 + 7; + int n = nums.size(); + int m = *max_element(nums.begin(), nums.end()); + vector> f(n, vector(m + 1)); + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + vector g(m + 1); + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +}; +``` + +#### Go + +```go +func countOfPairs(nums []int) (ans int) { + const mod int = 1e9 + 7 + n := len(nums) + m := slices.Max(nums) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m+1) + } + for j := 0; j <= nums[0]; j++ { + f[0][j] = 1 + } + g := make([]int, m+1) + for i := 1; i < n; i++ { + g[0] = f[i-1][0] + for j := 1; j <= m; j++ { + g[j] = (g[j-1] + f[i-1][j]) % mod + } + for j := 0; j <= nums[i]; j++ { + k := min(j, j+nums[i-1]-nums[i]) + if k >= 0 { + f[i][j] = g[k] + } + } + } + for j := 0; j <= nums[n-1]; j++ { + ans = (ans + f[n-1][j]) % mod + } + return +} +``` + +#### TypeScript + +```ts +function countOfPairs(nums: number[]): number { + const mod = 1e9 + 7; + const n = nums.length; + const m = Math.max(...nums); + const f: number[][] = Array.from({ length: n }, () => Array(m + 1).fill(0)); + for (let j = 0; j <= nums[0]; j++) { + f[0][j] = 1; + } + const g: number[] = Array(m + 1).fill(0); + for (let i = 1; i < n; i++) { + g[0] = f[i - 1][0]; + for (let j = 1; j <= m; j++) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (let j = 0; j <= nums[i]; j++) { + const k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + let ans = 0; + for (let j = 0; j <= nums[n - 1]; j++) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/README_EN.md b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/README_EN.md new file mode 100644 index 000000000000..b0bdb02e099a --- /dev/null +++ b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/README_EN.md @@ -0,0 +1,252 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README_EN.md +tags: + - Array + - Math + - Dynamic Programming + - Combinatorics + - Prefix Sum +--- + + + +# [3250. Find the Count of Monotonic Pairs I](https://leetcode.com/problems/find-the-count-of-monotonic-pairs-i) + +[中文文档](/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README.md) + +## Description + + + +

            You are given an array of positive integers nums of length n.

            + +

            We call a pair of non-negative integer arrays (arr1, arr2) monotonic if:

            + +
              +
            • The lengths of both arrays are n.
            • +
            • arr1 is monotonically non-decreasing, in other words, arr1[0] <= arr1[1] <= ... <= arr1[n - 1].
            • +
            • arr2 is monotonically non-increasing, in other words, arr2[0] >= arr2[1] >= ... >= arr2[n - 1].
            • +
            • arr1[i] + arr2[i] == nums[i] for all 0 <= i <= n - 1.
            • +
            + +

            Return the count of monotonic pairs.

            + +

            Since the answer may be very large, return it modulo 109 + 7.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [2,3,2]

            + +

            Output: 4

            + +

            Explanation:

            + +

            The good pairs are:

            + +
              +
            1. ([0, 1, 1], [2, 2, 1])
            2. +
            3. ([0, 1, 2], [2, 2, 0])
            4. +
            5. ([0, 2, 2], [2, 1, 0])
            6. +
            7. ([1, 2, 2], [1, 1, 0])
            8. +
            +
            + +

            Example 2:

            + +
            +

            Input: nums = [5,5,5,5]

            + +

            Output: 126

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n == nums.length <= 2000
            • +
            • 1 <= nums[i] <= 50
            • +
            + + + +## Solutions + + + +### Solution 1: Dynamic Programming + Prefix Sum Optimization + +We define $f[i][j]$ to represent the number of monotonic array pairs for the subarray $[0, \ldots, i]$ where $arr1[i] = j$. Initially, $f[i][j] = 0$, and the answer is $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$. + +When $i = 0$, we have $f[0][j] = 1$ for $0 \leq j \leq \textit{nums}[0]$. + +When $i > 0$, we can calculate $f[i][j]$ based on $f[i-1][j']$. Since $\textit{arr1}$ is non-decreasing, $j' \leq j$. Additionally, since $\textit{arr2}$ is non-increasing, $\textit{nums}[i] - j \leq \textit{nums}[i - 1] - j'$. Thus, $j' \leq \min(j, j + \textit{nums}[i - 1] - \textit{nums}[i])$. + +The answer is $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$. + +The time complexity is $O(n \times m)$, and the space complexity is $O(n \times m)$. Here, $n$ represents the length of the array $\textit{nums}$, and $m$ represents the maximum value in the array $\textit{nums}$. + + + +#### Python3 + +```python +class Solution: + def countOfPairs(self, nums: List[int]) -> int: + mod = 10**9 + 7 + n, m = len(nums), max(nums) + f = [[0] * (m + 1) for _ in range(n)] + for j in range(nums[0] + 1): + f[0][j] = 1 + for i in range(1, n): + s = list(accumulate(f[i - 1])) + for j in range(nums[i] + 1): + k = min(j, j + nums[i - 1] - nums[i]) + if k >= 0: + f[i][j] = s[k] % mod + return sum(f[-1][: nums[-1] + 1]) % mod +``` + +#### Java + +```java +class Solution { + public int countOfPairs(int[] nums) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int m = Arrays.stream(nums).max().getAsInt(); + int[][] f = new int[n][m + 1]; + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + int[] g = new int[m + 1]; + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countOfPairs(vector& nums) { + const int mod = 1e9 + 7; + int n = nums.size(); + int m = *max_element(nums.begin(), nums.end()); + vector> f(n, vector(m + 1)); + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + vector g(m + 1); + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +}; +``` + +#### Go + +```go +func countOfPairs(nums []int) (ans int) { + const mod int = 1e9 + 7 + n := len(nums) + m := slices.Max(nums) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m+1) + } + for j := 0; j <= nums[0]; j++ { + f[0][j] = 1 + } + g := make([]int, m+1) + for i := 1; i < n; i++ { + g[0] = f[i-1][0] + for j := 1; j <= m; j++ { + g[j] = (g[j-1] + f[i-1][j]) % mod + } + for j := 0; j <= nums[i]; j++ { + k := min(j, j+nums[i-1]-nums[i]) + if k >= 0 { + f[i][j] = g[k] + } + } + } + for j := 0; j <= nums[n-1]; j++ { + ans = (ans + f[n-1][j]) % mod + } + return +} +``` + +#### TypeScript + +```ts +function countOfPairs(nums: number[]): number { + const mod = 1e9 + 7; + const n = nums.length; + const m = Math.max(...nums); + const f: number[][] = Array.from({ length: n }, () => Array(m + 1).fill(0)); + for (let j = 0; j <= nums[0]; j++) { + f[0][j] = 1; + } + const g: number[] = Array(m + 1).fill(0); + for (let i = 1; i < n; i++) { + g[0] = f[i - 1][0]; + for (let j = 1; j <= m; j++) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (let j = 0; j <= nums[i]; j++) { + const k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + let ans = 0; + for (let j = 0; j <= nums[n - 1]; j++) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.cpp b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.cpp new file mode 100644 index 000000000000..835f1154a7ad --- /dev/null +++ b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.cpp @@ -0,0 +1,30 @@ +class Solution { +public: + int countOfPairs(vector& nums) { + const int mod = 1e9 + 7; + int n = nums.size(); + int m = *max_element(nums.begin(), nums.end()); + vector> f(n, vector(m + 1)); + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + vector g(m + 1); + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +}; diff --git a/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.go b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.go new file mode 100644 index 000000000000..72ed9c30e80f --- /dev/null +++ b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.go @@ -0,0 +1,29 @@ +func countOfPairs(nums []int) (ans int) { + const mod int = 1e9 + 7 + n := len(nums) + m := slices.Max(nums) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m+1) + } + for j := 0; j <= nums[0]; j++ { + f[0][j] = 1 + } + g := make([]int, m+1) + for i := 1; i < n; i++ { + g[0] = f[i-1][0] + for j := 1; j <= m; j++ { + g[j] = (g[j-1] + f[i-1][j]) % mod + } + for j := 0; j <= nums[i]; j++ { + k := min(j, j+nums[i-1]-nums[i]) + if k >= 0 { + f[i][j] = g[k] + } + } + } + for j := 0; j <= nums[n-1]; j++ { + ans = (ans + f[n-1][j]) % mod + } + return +} diff --git a/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.java b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.java new file mode 100644 index 000000000000..6391ae1136ff --- /dev/null +++ b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.java @@ -0,0 +1,29 @@ +class Solution { + public int countOfPairs(int[] nums) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int m = Arrays.stream(nums).max().getAsInt(); + int[][] f = new int[n][m + 1]; + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + int[] g = new int[m + 1]; + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +} diff --git a/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.py b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.py new file mode 100644 index 000000000000..cf4957154bf6 --- /dev/null +++ b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.py @@ -0,0 +1,14 @@ +class Solution: + def countOfPairs(self, nums: List[int]) -> int: + mod = 10**9 + 7 + n, m = len(nums), max(nums) + f = [[0] * (m + 1) for _ in range(n)] + for j in range(nums[0] + 1): + f[0][j] = 1 + for i in range(1, n): + s = list(accumulate(f[i - 1])) + for j in range(nums[i] + 1): + k = min(j, j + nums[i - 1] - nums[i]) + if k >= 0: + f[i][j] = s[k] % mod + return sum(f[-1][: nums[-1] + 1]) % mod diff --git a/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.ts b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.ts new file mode 100644 index 000000000000..94b14790bc2e --- /dev/null +++ b/solution/3200-3299/3250.Find the Count of Monotonic Pairs I/Solution.ts @@ -0,0 +1,27 @@ +function countOfPairs(nums: number[]): number { + const mod = 1e9 + 7; + const n = nums.length; + const m = Math.max(...nums); + const f: number[][] = Array.from({ length: n }, () => Array(m + 1).fill(0)); + for (let j = 0; j <= nums[0]; j++) { + f[0][j] = 1; + } + const g: number[] = Array(m + 1).fill(0); + for (let i = 1; i < n; i++) { + g[0] = f[i - 1][0]; + for (let j = 1; j <= m; j++) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (let j = 0; j <= nums[i]; j++) { + const k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + let ans = 0; + for (let j = 0; j <= nums[n - 1]; j++) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; +} diff --git a/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/README.md b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/README.md new file mode 100644 index 000000000000..75da825a398e --- /dev/null +++ b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/README.md @@ -0,0 +1,254 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README.md +tags: + - 数组 + - 数学 + - 动态规划 + - 组合数学 + - 前缀和 +--- + + + +# [3251. 单调数组对的数目 II](https://leetcode.cn/problems/find-the-count-of-monotonic-pairs-ii) + +[English Version](/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README_EN.md) + +## 题目描述 + + + +

            给你一个长度为 n 的  整数数组 nums 。

            + +

            如果两个 非负 整数数组 (arr1, arr2) 满足以下条件,我们称它们是 单调 数组对:

            + +
              +
            • 两个数组的长度都是 n 。
            • +
            • arr1 是单调 非递减 的,换句话说 arr1[0] <= arr1[1] <= ... <= arr1[n - 1] 。
            • +
            • arr2 是单调 非递增 的,换句话说 arr2[0] >= arr2[1] >= ... >= arr2[n - 1] 。
            • +
            • 对于所有的 0 <= i <= n - 1 都有 arr1[i] + arr2[i] == nums[i] 。
            • +
            + +

            请你返回所有 单调 数组对的数目。

            + +

            由于答案可能很大,请你将它对 109 + 7 取余 后返回。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [2,3,2]

            + +

            输出:4

            + +

            解释:

            + +

            单调数组对包括:

            + +
              +
            1. ([0, 1, 1], [2, 2, 1])
            2. +
            3. ([0, 1, 2], [2, 2, 0])
            4. +
            5. ([0, 2, 2], [2, 1, 0])
            6. +
            7. ([1, 2, 2], [1, 1, 0])
            8. +
            +
            + +

            示例 2:

            + +
            +

            输入:nums = [5,5,5,5]

            + +

            输出:126

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n == nums.length <= 2000
            • +
            • 1 <= nums[i] <= 1000
            • +
            + + + +## 解法 + + + +### 方法一:动态规划 + 前缀和优化 + +我们定义 $f[i][j]$ 表示下标 $[0,..i]$ 的单调数组对的数目,且 $arr1[i] = j$。初始时 $[i][j] = 0$,答案为 $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$。 + +当 $i = 0$ 时,有 $[0][j] = 1$,其中 $0 \leq j \leq \textit{nums}[0]$。 + +当 $i > 0$ 时,我们可以根据 $f[i-1][j']$ 计算 $f[i][j]$。由于 $\textit{arr1}$ 是单调非递减的,因此 $j' \leq j$。又由于 $\textit{arr2}$ 是单调非递增的,因此 $\textit{nums}[i] - j \leq \textit{nums}[i - 1] - j'$。即 $j' \leq \min(j, j + \textit{nums}[i - 1] - \textit{nums}[i])$。 + +答案为 $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$。 + +时间复杂度 $O(n \times m)$,空间复杂度 $O(n \times m)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度,而 $m$ 表示数组 $\textit{nums}$ 中的最大值。 + + + +#### Python3 + +```python +class Solution: + def countOfPairs(self, nums: List[int]) -> int: + mod = 10**9 + 7 + n, m = len(nums), max(nums) + f = [[0] * (m + 1) for _ in range(n)] + for j in range(nums[0] + 1): + f[0][j] = 1 + for i in range(1, n): + s = list(accumulate(f[i - 1])) + for j in range(nums[i] + 1): + k = min(j, j + nums[i - 1] - nums[i]) + if k >= 0: + f[i][j] = s[k] % mod + return sum(f[-1][: nums[-1] + 1]) % mod +``` + +#### Java + +```java +class Solution { + public int countOfPairs(int[] nums) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int m = Arrays.stream(nums).max().getAsInt(); + int[][] f = new int[n][m + 1]; + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + int[] g = new int[m + 1]; + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countOfPairs(vector& nums) { + const int mod = 1e9 + 7; + int n = nums.size(); + int m = *max_element(nums.begin(), nums.end()); + vector> f(n, vector(m + 1)); + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + vector g(m + 1); + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +}; +``` + +#### Go + +```go +func countOfPairs(nums []int) (ans int) { + const mod int = 1e9 + 7 + n := len(nums) + m := slices.Max(nums) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m+1) + } + for j := 0; j <= nums[0]; j++ { + f[0][j] = 1 + } + g := make([]int, m+1) + for i := 1; i < n; i++ { + g[0] = f[i-1][0] + for j := 1; j <= m; j++ { + g[j] = (g[j-1] + f[i-1][j]) % mod + } + for j := 0; j <= nums[i]; j++ { + k := min(j, j+nums[i-1]-nums[i]) + if k >= 0 { + f[i][j] = g[k] + } + } + } + for j := 0; j <= nums[n-1]; j++ { + ans = (ans + f[n-1][j]) % mod + } + return +} +``` + +#### TypeScript + +```ts +function countOfPairs(nums: number[]): number { + const mod = 1e9 + 7; + const n = nums.length; + const m = Math.max(...nums); + const f: number[][] = Array.from({ length: n }, () => Array(m + 1).fill(0)); + for (let j = 0; j <= nums[0]; j++) { + f[0][j] = 1; + } + const g: number[] = Array(m + 1).fill(0); + for (let i = 1; i < n; i++) { + g[0] = f[i - 1][0]; + for (let j = 1; j <= m; j++) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (let j = 0; j <= nums[i]; j++) { + const k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + let ans = 0; + for (let j = 0; j <= nums[n - 1]; j++) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/README_EN.md b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/README_EN.md new file mode 100644 index 000000000000..9eed6d2d9fb0 --- /dev/null +++ b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/README_EN.md @@ -0,0 +1,252 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README_EN.md +tags: + - Array + - Math + - Dynamic Programming + - Combinatorics + - Prefix Sum +--- + + + +# [3251. Find the Count of Monotonic Pairs II](https://leetcode.com/problems/find-the-count-of-monotonic-pairs-ii) + +[中文文档](/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README.md) + +## Description + + + +

            You are given an array of positive integers nums of length n.

            + +

            We call a pair of non-negative integer arrays (arr1, arr2) monotonic if:

            + +
              +
            • The lengths of both arrays are n.
            • +
            • arr1 is monotonically non-decreasing, in other words, arr1[0] <= arr1[1] <= ... <= arr1[n - 1].
            • +
            • arr2 is monotonically non-increasing, in other words, arr2[0] >= arr2[1] >= ... >= arr2[n - 1].
            • +
            • arr1[i] + arr2[i] == nums[i] for all 0 <= i <= n - 1.
            • +
            + +

            Return the count of monotonic pairs.

            + +

            Since the answer may be very large, return it modulo 109 + 7.

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [2,3,2]

            + +

            Output: 4

            + +

            Explanation:

            + +

            The good pairs are:

            + +
              +
            1. ([0, 1, 1], [2, 2, 1])
            2. +
            3. ([0, 1, 2], [2, 2, 0])
            4. +
            5. ([0, 2, 2], [2, 1, 0])
            6. +
            7. ([1, 2, 2], [1, 1, 0])
            8. +
            +
            + +

            Example 2:

            + +
            +

            Input: nums = [5,5,5,5]

            + +

            Output: 126

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n == nums.length <= 2000
            • +
            • 1 <= nums[i] <= 1000
            • +
            + + + +## Solutions + + + +### Solution 1: Dynamic Programming + Prefix Sum Optimization + +We define $f[i][j]$ to represent the number of monotonic array pairs for the subarray $[0, \ldots, i]$ where $arr1[i] = j$. Initially, $f[i][j] = 0$, and the answer is $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$. + +When $i = 0$, we have $f[0][j] = 1$ for $0 \leq j \leq \textit{nums}[0]$. + +When $i > 0$, we can calculate $f[i][j]$ based on $f[i-1][j']$. Since $\textit{arr1}$ is non-decreasing, $j' \leq j$. Additionally, since $\textit{arr2}$ is non-increasing, $\textit{nums}[i] - j \leq \textit{nums}[i - 1] - j'$. Thus, $j' \leq \min(j, j + \textit{nums}[i - 1] - \textit{nums}[i])$. + +The answer is $\sum_{j=0}^{\textit{nums}[n-1]} f[n-1][j]$. + +The time complexity is $O(n \times m)$, and the space complexity is $O(n \times m)$. Here, $n$ represents the length of the array $\textit{nums}$, and $m$ represents the maximum value in the array $\textit{nums}$. + + + +#### Python3 + +```python +class Solution: + def countOfPairs(self, nums: List[int]) -> int: + mod = 10**9 + 7 + n, m = len(nums), max(nums) + f = [[0] * (m + 1) for _ in range(n)] + for j in range(nums[0] + 1): + f[0][j] = 1 + for i in range(1, n): + s = list(accumulate(f[i - 1])) + for j in range(nums[i] + 1): + k = min(j, j + nums[i - 1] - nums[i]) + if k >= 0: + f[i][j] = s[k] % mod + return sum(f[-1][: nums[-1] + 1]) % mod +``` + +#### Java + +```java +class Solution { + public int countOfPairs(int[] nums) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int m = Arrays.stream(nums).max().getAsInt(); + int[][] f = new int[n][m + 1]; + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + int[] g = new int[m + 1]; + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countOfPairs(vector& nums) { + const int mod = 1e9 + 7; + int n = nums.size(); + int m = *max_element(nums.begin(), nums.end()); + vector> f(n, vector(m + 1)); + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + vector g(m + 1); + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +}; +``` + +#### Go + +```go +func countOfPairs(nums []int) (ans int) { + const mod int = 1e9 + 7 + n := len(nums) + m := slices.Max(nums) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m+1) + } + for j := 0; j <= nums[0]; j++ { + f[0][j] = 1 + } + g := make([]int, m+1) + for i := 1; i < n; i++ { + g[0] = f[i-1][0] + for j := 1; j <= m; j++ { + g[j] = (g[j-1] + f[i-1][j]) % mod + } + for j := 0; j <= nums[i]; j++ { + k := min(j, j+nums[i-1]-nums[i]) + if k >= 0 { + f[i][j] = g[k] + } + } + } + for j := 0; j <= nums[n-1]; j++ { + ans = (ans + f[n-1][j]) % mod + } + return +} +``` + +#### TypeScript + +```ts +function countOfPairs(nums: number[]): number { + const mod = 1e9 + 7; + const n = nums.length; + const m = Math.max(...nums); + const f: number[][] = Array.from({ length: n }, () => Array(m + 1).fill(0)); + for (let j = 0; j <= nums[0]; j++) { + f[0][j] = 1; + } + const g: number[] = Array(m + 1).fill(0); + for (let i = 1; i < n; i++) { + g[0] = f[i - 1][0]; + for (let j = 1; j <= m; j++) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (let j = 0; j <= nums[i]; j++) { + const k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + let ans = 0; + for (let j = 0; j <= nums[n - 1]; j++) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.cpp b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.cpp new file mode 100644 index 000000000000..835f1154a7ad --- /dev/null +++ b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.cpp @@ -0,0 +1,30 @@ +class Solution { +public: + int countOfPairs(vector& nums) { + const int mod = 1e9 + 7; + int n = nums.size(); + int m = *max_element(nums.begin(), nums.end()); + vector> f(n, vector(m + 1)); + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + vector g(m + 1); + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +}; diff --git a/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.go b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.go new file mode 100644 index 000000000000..72ed9c30e80f --- /dev/null +++ b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.go @@ -0,0 +1,29 @@ +func countOfPairs(nums []int) (ans int) { + const mod int = 1e9 + 7 + n := len(nums) + m := slices.Max(nums) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m+1) + } + for j := 0; j <= nums[0]; j++ { + f[0][j] = 1 + } + g := make([]int, m+1) + for i := 1; i < n; i++ { + g[0] = f[i-1][0] + for j := 1; j <= m; j++ { + g[j] = (g[j-1] + f[i-1][j]) % mod + } + for j := 0; j <= nums[i]; j++ { + k := min(j, j+nums[i-1]-nums[i]) + if k >= 0 { + f[i][j] = g[k] + } + } + } + for j := 0; j <= nums[n-1]; j++ { + ans = (ans + f[n-1][j]) % mod + } + return +} diff --git a/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.java b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.java new file mode 100644 index 000000000000..6391ae1136ff --- /dev/null +++ b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.java @@ -0,0 +1,29 @@ +class Solution { + public int countOfPairs(int[] nums) { + final int mod = (int) 1e9 + 7; + int n = nums.length; + int m = Arrays.stream(nums).max().getAsInt(); + int[][] f = new int[n][m + 1]; + for (int j = 0; j <= nums[0]; ++j) { + f[0][j] = 1; + } + int[] g = new int[m + 1]; + for (int i = 1; i < n; ++i) { + g[0] = f[i - 1][0]; + for (int j = 1; j <= m; ++j) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (int j = 0; j <= nums[i]; ++j) { + int k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + int ans = 0; + for (int j = 0; j <= nums[n - 1]; ++j) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; + } +} diff --git a/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.py b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.py new file mode 100644 index 000000000000..cf4957154bf6 --- /dev/null +++ b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.py @@ -0,0 +1,14 @@ +class Solution: + def countOfPairs(self, nums: List[int]) -> int: + mod = 10**9 + 7 + n, m = len(nums), max(nums) + f = [[0] * (m + 1) for _ in range(n)] + for j in range(nums[0] + 1): + f[0][j] = 1 + for i in range(1, n): + s = list(accumulate(f[i - 1])) + for j in range(nums[i] + 1): + k = min(j, j + nums[i - 1] - nums[i]) + if k >= 0: + f[i][j] = s[k] % mod + return sum(f[-1][: nums[-1] + 1]) % mod diff --git a/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.ts b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.ts new file mode 100644 index 000000000000..94b14790bc2e --- /dev/null +++ b/solution/3200-3299/3251.Find the Count of Monotonic Pairs II/Solution.ts @@ -0,0 +1,27 @@ +function countOfPairs(nums: number[]): number { + const mod = 1e9 + 7; + const n = nums.length; + const m = Math.max(...nums); + const f: number[][] = Array.from({ length: n }, () => Array(m + 1).fill(0)); + for (let j = 0; j <= nums[0]; j++) { + f[0][j] = 1; + } + const g: number[] = Array(m + 1).fill(0); + for (let i = 1; i < n; i++) { + g[0] = f[i - 1][0]; + for (let j = 1; j <= m; j++) { + g[j] = (g[j - 1] + f[i - 1][j]) % mod; + } + for (let j = 0; j <= nums[i]; j++) { + const k = Math.min(j, j + nums[i - 1] - nums[i]); + if (k >= 0) { + f[i][j] = g[k]; + } + } + } + let ans = 0; + for (let j = 0; j <= nums[n - 1]; j++) { + ans = (ans + f[n - 1][j]) % mod; + } + return ans; +} diff --git a/solution/3200-3299/3252.Premier League Table Ranking II/README.md b/solution/3200-3299/3252.Premier League Table Ranking II/README.md new file mode 100644 index 000000000000..73d28c3a7a83 --- /dev/null +++ b/solution/3200-3299/3252.Premier League Table Ranking II/README.md @@ -0,0 +1,194 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README.md +tags: + - 数据库 +--- + + + +# [3252. 英超积分榜排名 II 🔒](https://leetcode.cn/problems/premier-league-table-ranking-ii) + +[English Version](/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README_EN.md) + +## 题目描述 + + + +

            表:TeamStats

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| team_id          | int     |
            +| team_name        | varchar |
            +| matches_played   | int     |
            +| wins             | int     |
            +| draws            | int     |
            +| losses           | int     |
            ++------------------+---------+
            +team_id 是这张表的唯一主键。
            +这张表包含队伍 id,队伍名,场次,赢局,平局和输局。
            +
            + +

            编写一个解决方案来计算联盟中每支球队的 得分排名 等级。积分计算方式如下:

            + +
              +
            • 赢局 有 3 点得分
            • +
            • 平局 有 1 点得分
            • +
            • 输局 有 0 点得分
            • +
            + +

            注意:积分相同的球队必须分配相同的排名。

            + +

            等级评级:

            + +
              +
            • 根据积分将联盟分为 3 个等级:
            • +
            • 等级 1:前 33% 的队伍
            • +
            • 等级 2:中间 33% 的队伍
            • +
            • 等级 3:最后 34% 的队伍
            • +
            • 如果等级边界出现平局,平局的队伍分配到更高的等级。
            • +
            + +

            返回结果表以 points 降序 排序,然后以 team_name 升序 排序。

            + +

            结果格式如下所示。

            + +

             

            + +

            示例:

            + +
            +

            输入:

            + +

            TeamStats 表:

            + +
            ++---------+-------------------+----------------+------+-------+--------+
            +| team_id | team_name         | matches_played | wins | draws | losses |
            ++---------+-------------------+----------------+------+-------+--------+
            +| 1       | Chelsea           | 22             | 13   | 2     | 7      |
            +| 2       | Nottingham Forest | 27             | 6    | 6     | 15     |
            +| 3       | Liverpool         | 17             | 1    | 8     | 8      |
            +| 4       | Aston Villa       | 20             | 1    | 6     | 13     |
            +| 5       | Fulham            | 31             | 18   | 1     | 12     |
            +| 6       | Burnley           | 26             | 6    | 9     | 11     |
            +| 7       | Newcastle United  | 33             | 11   | 10    | 12     |
            +| 8       | Sheffield United  | 20             | 18   | 2     | 0      |
            +| 9       | Luton Town        | 5              | 4    | 0     | 1      |
            +| 10      | Everton           | 14             | 2    | 6     | 6      |
            ++---------+-------------------+----------------+------+-------+--------+
            +
            + +

            输出:

            + +
            ++-------------------+--------+----------+---------+
            +| team_name         | points | position | tier    |
            ++-------------------+--------+----------+---------+
            +| Sheffield United  | 56     | 1        | Tier 1  |
            +| Fulham            | 55     | 2        | Tier 1  |
            +| Newcastle United  | 43     | 3        | Tier 1  |
            +| Chelsea           | 41     | 4        | Tier 1  |
            +| Burnley           | 27     | 5        | Tier 2  |
            +| Nottingham Forest | 24     | 6        | Tier 2  |
            +| Everton           | 12     | 7        | Tier 2  |
            +| Luton Town        | 12     | 7        | Tier 2  |
            +| Liverpool         | 11     | 9        | Tier 3  |
            +| Aston Villa       | 9      | 10       | Tier 3  |
            ++-------------------+--------+----------+---------+
            +
            + +

            解释:

            + +
              +
            • 谢菲尔德联队拿下 56 分(18 胜 * 3 分 + 2 平 * 1 分)位列第 1。
            • +
            • 富勒姆拿下 55 分(18 胜 * 3 分 + 1 平 * 1 分)位列第 2。
            • +
            • 纽卡斯尔联队拿下 43 分(11 胜 * 3 分 + 10 平 * 1 分)位列第 3。
            • +
            • 切尔西拿下 41 分(13 胜 * 3 分 + 2 平 * 1 分)位列第 4。
            • +
            • 伯恩利拿下 27 分(6 胜 * 3 分 + 9 平 * 1 分)位列第 5。
            • +
            • 诺丁汉森林拿下 24 分(6 胜 * 3 分 + 6 平 * 1 分)位列第 6。
            • +
            • 埃弗顿和卢顿镇均拿下 12 分,埃弗顿 2 胜 * 3 分 + 6 平 * 1 分,卢顿镇 4 胜 * 3 分。两支队伍并列位列第 7。
            • +
            • 利物浦拿下 11 分(1 胜 * 3 分 + 8 平 * 1 分)位列第 9。
            • +
            • 阿斯顿维拉拿下 9 分(1 胜 * 3 分 + 6 平 * 1 分)位列第 10。
            • +
            + +

            等级计算:

            + +
              +
            • 等级 1:根据积分排名前 33% 的球队。谢菲尔德联队、富勒姆、纽卡斯尔联队和切尔西属于等级 1。
            • +
            • 等级 2:中间 33% 的球队。伯恩利、诺丁汉森林、埃弗顿和卢顿镇属于等级 2。
            • +
            • 等级 3:垫底 34% 的球队。利物浦和阿斯顿维拉落入等级 3。
            • +
            +
            + + + +## 解法 + + + +### 方法一:窗口函数 + CASE WHEN + +我们可以使用窗口函数 `RANK()` 来计算每支球队的积分、排名,并计算总球队数。然后,我们可以使用 `CASE WHEN` 语句来确定每支球队的等级。 + + + +#### MySQL + +```sql +WITH + T AS ( + SELECT + team_name, + wins * 3 + draws AS points, + RANK() OVER (ORDER BY wins * 3 + draws DESC) AS position, + COUNT(1) OVER () AS total_teams + FROM TeamStats + ) +SELECT + team_name, + points, + position, + CASE + WHEN position <= CEIL(total_teams / 3.0) THEN 'Tier 1' + WHEN position <= CEIL(2 * total_teams / 3.0) THEN 'Tier 2' + ELSE 'Tier 3' + END tier +FROM T +ORDER BY 2 DESC, 1; +``` + +#### Pandas + +```python +import pandas as pd + + +def calculate_team_tiers(team_stats: pd.DataFrame) -> pd.DataFrame: + team_stats["points"] = team_stats["wins"] * 3 + team_stats["draws"] + team_stats["position"] = ( + team_stats["points"].rank(method="min", ascending=False).astype(int) + ) + total_teams = len(team_stats) + team_stats["tier"] = np.where( + team_stats["position"] <= np.ceil(total_teams / 3.0), + "Tier 1", + np.where( + team_stats["position"] <= np.ceil(2 * total_teams / 3.0), "Tier 2", "Tier 3" + ), + ) + team_stats = team_stats.sort_values( + by=["points", "team_name"], ascending=[False, True] + ) + return team_stats[["team_name", "points", "position", "tier"]] +``` + + + + + + diff --git a/solution/3200-3299/3252.Premier League Table Ranking II/README_EN.md b/solution/3200-3299/3252.Premier League Table Ranking II/README_EN.md new file mode 100644 index 000000000000..04dad832e34f --- /dev/null +++ b/solution/3200-3299/3252.Premier League Table Ranking II/README_EN.md @@ -0,0 +1,193 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README_EN.md +tags: + - Database +--- + + + +# [3252. Premier League Table Ranking II 🔒](https://leetcode.com/problems/premier-league-table-ranking-ii) + +[中文文档](/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README.md) + +## Description + + + +

            Table: TeamStats

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| team_id          | int     |
            +| team_name        | varchar |
            +| matches_played   | int     |
            +| wins             | int     |
            +| draws            | int     |
            +| losses           | int     |
            ++------------------+---------+
            +team_id is the unique key for this table.
            +This table contains team id, team name, matches_played, wins, draws, and losses.
            +
            + +

            Write a solution to calculate the points, position, and tier for each team in the league. Points are calculated as follows:

            + +
              +
            • 3 points for a win
            • +
            • 1 point for a draw
            • +
            • 0 points for a loss
            • +
            + +

            Note: Teams with the same points must be assigned the same position.

            + +

            Tier ranking:

            + +
              +
            • Divide the league into 3 tiers based on points:
            • +
            • Tier 1: Top 33% of teams
            • +
            • Tier 2: Middle 33% of teams
            • +
            • Tier 3: Bottom 34% of teams
            • +
            • In case of ties at tier boundaries, place tied teams in the higher tier.
            • +
            + +

            Return the result table ordered by points in descending, and then by team_name in ascending order.

            + +

            The query result format is in the following example.

            + +

             

            +

            Example:

            + +
            +

            Input:

            + +

            TeamStats table:

            + +
            ++---------+-------------------+----------------+------+-------+--------+
            +| team_id | team_name         | matches_played | wins | draws | losses |
            ++---------+-------------------+----------------+------+-------+--------+
            +| 1       | Chelsea           | 22             | 13   | 2     | 7      |
            +| 2       | Nottingham Forest | 27             | 6    | 6     | 15     |
            +| 3       | Liverpool         | 17             | 1    | 8     | 8      |
            +| 4       | Aston Villa       | 20             | 1    | 6     | 13     |
            +| 5       | Fulham            | 31             | 18   | 1     | 12     |
            +| 6       | Burnley           | 26             | 6    | 9     | 11     |
            +| 7       | Newcastle United  | 33             | 11   | 10    | 12     |
            +| 8       | Sheffield United  | 20             | 18   | 2     | 0      |
            +| 9       | Luton Town        | 5              | 4    | 0     | 1      |
            +| 10      | Everton           | 14             | 2    | 6     | 6      |
            ++---------+-------------------+----------------+------+-------+--------+
            +
            + +

            Output:

            + +
            ++-------------------+--------+----------+---------+
            +| team_name         | points | position | tier    |
            ++-------------------+--------+----------+---------+
            +| Sheffield United  | 56     | 1        | Tier 1  |
            +| Fulham            | 55     | 2        | Tier 1  |
            +| Newcastle United  | 43     | 3        | Tier 1  |
            +| Chelsea           | 41     | 4        | Tier 1  |
            +| Burnley           | 27     | 5        | Tier 2  |
            +| Nottingham Forest | 24     | 6        | Tier 2  |
            +| Everton           | 12     | 7        | Tier 2  |
            +| Luton Town        | 12     | 7        | Tier 2  |
            +| Liverpool         | 11     | 9        | Tier 3  |
            +| Aston Villa       | 9      | 10       | Tier 3  |
            ++-------------------+--------+----------+---------+
            +
            + +

            Explanation:

            + +
              +
            • Sheffield United has 56 points (18 wins * 3 points + 2 draws * 1 point) and is in position 1.
            • +
            • Fulham has 55 points (18 wins * 3 points + 1 draw * 1 point) and is in position 2.
            • +
            • Newcastle United has 43 points (11 wins * 3 points + 10 draws * 1 point) and is in position 3.
            • +
            • Chelsea has 41 points (13 wins * 3 points + 2 draws * 1 point) and is in position 4.
            • +
            • Burnley has 27 points (6 wins * 3 points + 9 draws * 1 point) and is in position 5.
            • +
            • Nottingham Forest has 24 points (6 wins * 3 points + 6 draws * 1 point) and is in position 6.
            • +
            • Everton and Luton Town both have 12 points, with Everton having 2 wins * 3 points + 6 draws * 1 point, and Luton Town having 4 wins * 3 points. Both teams share position 7.
            • +
            • Liverpool has 11 points (1 win * 3 points + 8 draws * 1 point) and is in position 9.
            • +
            • Aston Villa has 9 points (1 win * 3 points + 6 draws * 1 point) and is in position 10.
            • +
            + +

            Tier Calculation:

            + +
              +
            • Tier 1: The top 33% of teams based on points. Sheffield United, Fulham, Newcastle United, and Chelsea fall into Tier 1.
            • +
            • Tier 2: The middle 33% of teams. Burnley, Nottingham Forest, Everton, and Luton Town fall into Tier 2.
            • +
            • Tier 3: The bottom 34% of teams. Liverpool and Aston Villa fall into Tier 3.
            • +
            +
            + + + +## Solutions + + + +### Solution 1: Window Function + CASE WHEN + +We can use the window function `RANK()` to calculate each team's points, ranking, and the total number of teams. Then, we can use the `CASE WHEN` statement to determine the grade of each team. + + + +#### MySQL + +```sql +WITH + T AS ( + SELECT + team_name, + wins * 3 + draws AS points, + RANK() OVER (ORDER BY wins * 3 + draws DESC) AS position, + COUNT(1) OVER () AS total_teams + FROM TeamStats + ) +SELECT + team_name, + points, + position, + CASE + WHEN position <= CEIL(total_teams / 3.0) THEN 'Tier 1' + WHEN position <= CEIL(2 * total_teams / 3.0) THEN 'Tier 2' + ELSE 'Tier 3' + END tier +FROM T +ORDER BY 2 DESC, 1; +``` + +#### Pandas + +```python +import pandas as pd + + +def calculate_team_tiers(team_stats: pd.DataFrame) -> pd.DataFrame: + team_stats["points"] = team_stats["wins"] * 3 + team_stats["draws"] + team_stats["position"] = ( + team_stats["points"].rank(method="min", ascending=False).astype(int) + ) + total_teams = len(team_stats) + team_stats["tier"] = np.where( + team_stats["position"] <= np.ceil(total_teams / 3.0), + "Tier 1", + np.where( + team_stats["position"] <= np.ceil(2 * total_teams / 3.0), "Tier 2", "Tier 3" + ), + ) + team_stats = team_stats.sort_values( + by=["points", "team_name"], ascending=[False, True] + ) + return team_stats[["team_name", "points", "position", "tier"]] +``` + + + + + + diff --git a/solution/3200-3299/3252.Premier League Table Ranking II/Solution.py b/solution/3200-3299/3252.Premier League Table Ranking II/Solution.py new file mode 100644 index 000000000000..944891ab9765 --- /dev/null +++ b/solution/3200-3299/3252.Premier League Table Ranking II/Solution.py @@ -0,0 +1,20 @@ +import pandas as pd + + +def calculate_team_tiers(team_stats: pd.DataFrame) -> pd.DataFrame: + team_stats["points"] = team_stats["wins"] * 3 + team_stats["draws"] + team_stats["position"] = ( + team_stats["points"].rank(method="min", ascending=False).astype(int) + ) + total_teams = len(team_stats) + team_stats["tier"] = np.where( + team_stats["position"] <= np.ceil(total_teams / 3.0), + "Tier 1", + np.where( + team_stats["position"] <= np.ceil(2 * total_teams / 3.0), "Tier 2", "Tier 3" + ), + ) + team_stats = team_stats.sort_values( + by=["points", "team_name"], ascending=[False, True] + ) + return team_stats[["team_name", "points", "position", "tier"]] diff --git a/solution/3200-3299/3252.Premier League Table Ranking II/Solution.sql b/solution/3200-3299/3252.Premier League Table Ranking II/Solution.sql new file mode 100644 index 000000000000..fcceb212af90 --- /dev/null +++ b/solution/3200-3299/3252.Premier League Table Ranking II/Solution.sql @@ -0,0 +1,20 @@ +WITH + T AS ( + SELECT + team_name, + wins * 3 + draws AS points, + RANK() OVER (ORDER BY wins * 3 + draws DESC) AS position, + COUNT(1) OVER () AS total_teams + FROM TeamStats + ) +SELECT + team_name, + points, + position, + CASE + WHEN position <= CEIL(total_teams / 3.0) THEN 'Tier 1' + WHEN position <= CEIL(2 * total_teams / 3.0) THEN 'Tier 2' + ELSE 'Tier 3' + END tier +FROM T +ORDER BY 2 DESC, 1; diff --git a/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/README.md b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/README.md new file mode 100644 index 000000000000..fc855a4c5b4f --- /dev/null +++ b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/README.md @@ -0,0 +1,382 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3253.Construct%20String%20with%20Minimum%20Cost%20%28Easy%29/README.md +--- + + + +# [3253. 以最低成本构建字符串(简单) 🔒](https://leetcode.cn/problems/construct-string-with-minimum-cost-easy) + +[English Version](/solution/3200-3299/3253.Construct%20String%20with%20Minimum%20Cost%20%28Easy%29/README_EN.md) + +## 题目描述 + + + +

            给定字符串 target,一个字符串数组 words 以及一个整数数组 costs,两个数组长度相同。

            + +

            想象一个空字符串 s

            + +

            您可以执行以下操作任意次数(包括 ):

            + +
              +
            • 从范围 [0, words.length - 1] 中选择一个下标 i
            • +
            • 将 words[i] 添加到 s
            • +
            • 操作的开销为 costs[i]
            • +
            + +

            返回使 s 与 target 相等的 最小 开销。如果不可能做到,返回 -1。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:target = "abcdef", words = ["abdef","abc","d","def","ef"], costs = [100,1,1,10,5]

            + +

            输出:7

            + +

            解释:

            + +

            通过执行以下操作可以实现最低开销:

            + +
              +
            • 选择下标 1 然后以 1 的开销将 "abc" 添加到 s,得到 s = "abc"
            • +
            • 选择下标 2 然后以 1 的开销将 "d" 添加到 s,得到 s = "abcd"
            • +
            • 选择下标 4 然后以 5 的开销将 "ef" 添加到 s,得到 s = "abcdef"
            • +
            +
            + +

            示例 2:

            + +
            +

            输入:target = "aaaa", words = ["z","zz","zzz"], costs = [1,10,100]

            + +

            输出:-1

            + +

            解释:

            + +

            不可能使 s 与 target 相等,所以我们返回 -1。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= target.length <= 2000
            • +
            • 1 <= words.length == costs.length <= 50
            • +
            • 1 <= words[i].length <= target.length
            • +
            • target 和 words[i] 只包含小写英语字母。
            • +
            • 1 <= costs[i] <= 105
            • +
            + + + +## 解法 + + + +### 方法一:字典树 + 记忆化搜索 + +我们首先创建一个字典树 $\textit{trie}$,字典树的每个节点包含一个长度为 $26$ 的数组 $\textit{children}$,数组中的每个元素都是一个指向下一个节点的指针。字典树的每个节点还包含一个 $\textit{cost}$ 变量,表示从根节点到当前节点的最小花费。 + +我们遍历 $\textit{words}$ 数组,将每个单词插入到字典树中,同时更新每个节点的 $\textit{cost}$ 变量。 + +接下来,我们定义一个记忆化搜索函数 $\textit{dfs}(i)$,表示从 $\textit{target}[i]$ 开始构造字符串的最小花费。那么答案就是 $\textit{dfs}(0)$。 + +函数 $\textit{dfs}(i)$ 的计算过程如下: + +- 如果 $i \geq \textit{len}(\textit{target})$,表示已经构造完整个字符串,返回 $0$。 +- 否则,我们从 $\textit{trie}$ 的根节点开始,遍历 $\textit{target}[i]$ 开始的所有后缀,找到最小花费,即 $\textit{trie}$ 中的 $\textit{cost}$ 变量,加上 $\textit{dfs}(j+1)$ 的结果,其中 $j$ 是 $\textit{target}[i]$ 开始的后缀的结束位置。 + +最后,如果 $\textit{dfs}(0) < \textit{inf}$,返回 $\textit{dfs}(0)$,否则返回 $-1$。 + +时间复杂度 $O(n^2 + L)$,空间复杂度 $O(n + L)$。其中 $n$ 是 $\textit{target}$ 的长度,而 $L$ 是 $\textit{words}$ 数组中所有单词的长度之和。 + + + +#### Python3 + +```python +class Trie: + def __init__(self): + self.children: List[Optional[Trie]] = [None] * 26 + self.cost = inf + + def insert(self, word: str, cost: int): + node = self + for c in word: + idx = ord(c) - ord("a") + if node.children[idx] is None: + node.children[idx] = Trie() + node = node.children[idx] + node.cost = min(node.cost, cost) + + +class Solution: + def minimumCost(self, target: str, words: List[str], costs: List[int]) -> int: + @cache + def dfs(i: int) -> int: + if i >= len(target): + return 0 + ans = inf + node = trie + for j in range(i, len(target)): + idx = ord(target[j]) - ord("a") + if node.children[idx] is None: + return ans + node = node.children[idx] + ans = min(ans, node.cost + dfs(j + 1)) + return ans + + trie = Trie() + for word, cost in zip(words, costs): + trie.insert(word, cost) + ans = dfs(0) + return ans if ans < inf else -1 +``` + +#### Java + +```java +class Trie { + public final int inf = 1 << 29; + public Trie[] children = new Trie[26]; + public int cost = inf; + + public void insert(String word, int cost) { + Trie node = this; + for (char c : word.toCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.cost = Math.min(node.cost, cost); + } +} + +class Solution { + private Trie trie = new Trie(); + private char[] target; + private Integer[] f; + + public int minimumCost(String target, String[] words, int[] costs) { + for (int i = 0; i < words.length; ++i) { + trie.insert(words[i], costs[i]); + } + this.target = target.toCharArray(); + f = new Integer[target.length()]; + int ans = dfs(0); + return ans < trie.inf ? ans : -1; + } + + private int dfs(int i) { + if (i >= target.length) { + return 0; + } + if (f[i] != null) { + return f[i]; + } + f[i] = trie.inf; + Trie node = trie; + for (int j = i; j < target.length; ++j) { + int idx = target[j] - 'a'; + if (node.children[idx] == null) { + return f[i]; + } + node = node.children[idx]; + f[i] = Math.min(f[i], node.cost + dfs(j + 1)); + } + return f[i]; + } +} +``` + +#### C++ + +```cpp +const int inf = 1 << 29; + +class Trie { +public: + Trie* children[26]{}; + int cost = inf; + + void insert(string& word, int cost) { + Trie* node = this; + for (char c : word) { + int idx = c - 'a'; + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } + node = node->children[idx]; + } + node->cost = min(node->cost, cost); + } +}; + +class Solution { +public: + int minimumCost(string target, vector& words, vector& costs) { + Trie* trie = new Trie(); + for (int i = 0; i < words.size(); ++i) { + trie->insert(words[i], costs[i]); + } + int n = target.length(); + int f[n]; + memset(f, 0, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (i >= n) { + return 0; + } + if (f[i]) { + return f[i]; + } + f[i] = inf; + Trie* node = trie; + for (int j = i; j < n; ++j) { + int idx = target[j] - 'a'; + if (!node->children[idx]) { + return f[i]; + } + node = node->children[idx]; + f[i] = min(f[i], node->cost + dfs(dfs, j + 1)); + } + return f[i]; + }; + int ans = dfs(dfs, 0); + return ans < inf ? ans : -1; + } +}; +``` + +#### Go + +```go +const inf = 1 << 29 + +type Trie struct { + children [26]*Trie + cost int +} + +func NewTrie() *Trie { + return &Trie{cost: inf} +} + +func (t *Trie) insert(word string, cost int) { + node := t + for _, c := range word { + idx := c - 'a' + if node.children[idx] == nil { + node.children[idx] = NewTrie() + } + node = node.children[idx] + } + node.cost = min(node.cost, cost) +} + +func minimumCost(target string, words []string, costs []int) int { + trie := NewTrie() + for i, word := range words { + trie.insert(word, costs[i]) + } + + n := len(target) + f := make([]int, n) + var dfs func(int) int + dfs = func(i int) int { + if i >= n { + return 0 + } + if f[i] != 0 { + return f[i] + } + f[i] = inf + node := trie + for j := i; j < n; j++ { + idx := target[j] - 'a' + if node.children[idx] == nil { + return f[i] + } + node = node.children[idx] + f[i] = min(f[i], node.cost+dfs(j+1)) + } + return f[i] + } + if ans := dfs(0); ans < inf { + return ans + } + return -1 +} +``` + +#### TypeScript + +```ts +const inf = 1 << 29; + +class Trie { + children: (Trie | null)[]; + cost: number; + + constructor() { + this.children = Array(26).fill(null); + this.cost = inf; + } + + insert(word: string, cost: number): void { + let node: Trie = this; + for (const c of word) { + const idx = c.charCodeAt(0) - 97; + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx]!; + } + node.cost = Math.min(node.cost, cost); + } +} + +function minimumCost(target: string, words: string[], costs: number[]): number { + const trie = new Trie(); + for (let i = 0; i < words.length; ++i) { + trie.insert(words[i], costs[i]); + } + + const n = target.length; + const f: number[] = Array(n).fill(0); + const dfs = (i: number): number => { + if (i >= n) { + return 0; + } + if (f[i]) { + return f[i]; + } + f[i] = inf; + let node: Trie | null = trie; + for (let j = i; j < n; ++j) { + const idx = target.charCodeAt(j) - 97; + if (!node?.children[idx]) { + return f[i]; + } + node = node.children[idx]; + f[i] = Math.min(f[i], node!.cost + dfs(j + 1)); + } + return f[i]; + }; + + const ans = dfs(0); + return ans < inf ? ans : -1; +} +``` + + + + + + diff --git a/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/README_EN.md b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/README_EN.md new file mode 100644 index 000000000000..b5af739ba1c6 --- /dev/null +++ b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/README_EN.md @@ -0,0 +1,380 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3253.Construct%20String%20with%20Minimum%20Cost%20%28Easy%29/README_EN.md +--- + + + +# [3253. Construct String with Minimum Cost (Easy) 🔒](https://leetcode.com/problems/construct-string-with-minimum-cost-easy) + +[中文文档](/solution/3200-3299/3253.Construct%20String%20with%20Minimum%20Cost%20%28Easy%29/README.md) + +## Description + + + +

            You are given a string target, an array of strings words, and an integer array costs, both arrays of the same length.

            + +

            Imagine an empty string s.

            + +

            You can perform the following operation any number of times (including zero):

            + +
              +
            • Choose an index i in the range [0, words.length - 1].
            • +
            • Append words[i] to s.
            • +
            • The cost of operation is costs[i].
            • +
            + +

            Return the minimum cost to make s equal to target. If it's not possible, return -1.

            + +

             

            +

            Example 1:

            + +
            +

            Input: target = "abcdef", words = ["abdef","abc","d","def","ef"], costs = [100,1,1,10,5]

            + +

            Output: 7

            + +

            Explanation:

            + +

            The minimum cost can be achieved by performing the following operations:

            + +
              +
            • Select index 1 and append "abc" to s at a cost of 1, resulting in s = "abc".
            • +
            • Select index 2 and append "d" to s at a cost of 1, resulting in s = "abcd".
            • +
            • Select index 4 and append "ef" to s at a cost of 5, resulting in s = "abcdef".
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: target = "aaaa", words = ["z","zz","zzz"], costs = [1,10,100]

            + +

            Output: -1

            + +

            Explanation:

            + +

            It is impossible to make s equal to target, so we return -1.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= target.length <= 2000
            • +
            • 1 <= words.length == costs.length <= 50
            • +
            • 1 <= words[i].length <= target.length
            • +
            • target and words[i] consist only of lowercase English letters.
            • +
            • 1 <= costs[i] <= 105
            • +
            + + + +## Solutions + + + +### Solution 1: Trie + Memoized Search + +We first create a Trie $\textit{trie}$, where each node in the Trie contains an array $\textit{children}$ of length $26$, and each element in the array is a pointer to the next node. Each node in the Trie also contains a $\textit{cost}$ variable, which represents the minimum cost from the root node to the current node. + +We traverse the $\textit{words}$ array, inserting each word into the Trie while updating the $\textit{cost}$ variable for each node. + +Next, we define a memoized search function $\textit{dfs}(i)$, which represents the minimum cost to construct the string starting from $\textit{target}[i]$. The answer is $\textit{dfs}(0)$. + +The calculation process of the function $\textit{dfs}(i)$ is as follows: + +- If $i \geq \textit{len}(\textit{target})$, it means the entire string has been constructed, so return $0$. +- Otherwise, we start from the root node of the $\textit{trie}$ and traverse all suffixes starting from $\textit{target}[i]$, finding the minimum cost, which is the $\textit{cost}$ variable in the $\textit{trie}$, plus the result of $\textit{dfs}(j+1)$, where $j$ is the ending position of the suffix starting from $\textit{target}[i]$. + +Finally, if $\textit{dfs}(0) < \textit{inf}$, return $\textit{dfs}(0)$; otherwise, return $-1$. + +The time complexity is $O(n^2 + L)$, and the space complexity is $O(n + L)$. Here, $n$ is the length of $\textit{target}$, and $L$ is the sum of the lengths of all words in the $\textit{words}$ array. + + + +#### Python3 + +```python +class Trie: + def __init__(self): + self.children: List[Optional[Trie]] = [None] * 26 + self.cost = inf + + def insert(self, word: str, cost: int): + node = self + for c in word: + idx = ord(c) - ord("a") + if node.children[idx] is None: + node.children[idx] = Trie() + node = node.children[idx] + node.cost = min(node.cost, cost) + + +class Solution: + def minimumCost(self, target: str, words: List[str], costs: List[int]) -> int: + @cache + def dfs(i: int) -> int: + if i >= len(target): + return 0 + ans = inf + node = trie + for j in range(i, len(target)): + idx = ord(target[j]) - ord("a") + if node.children[idx] is None: + return ans + node = node.children[idx] + ans = min(ans, node.cost + dfs(j + 1)) + return ans + + trie = Trie() + for word, cost in zip(words, costs): + trie.insert(word, cost) + ans = dfs(0) + return ans if ans < inf else -1 +``` + +#### Java + +```java +class Trie { + public final int inf = 1 << 29; + public Trie[] children = new Trie[26]; + public int cost = inf; + + public void insert(String word, int cost) { + Trie node = this; + for (char c : word.toCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.cost = Math.min(node.cost, cost); + } +} + +class Solution { + private Trie trie = new Trie(); + private char[] target; + private Integer[] f; + + public int minimumCost(String target, String[] words, int[] costs) { + for (int i = 0; i < words.length; ++i) { + trie.insert(words[i], costs[i]); + } + this.target = target.toCharArray(); + f = new Integer[target.length()]; + int ans = dfs(0); + return ans < trie.inf ? ans : -1; + } + + private int dfs(int i) { + if (i >= target.length) { + return 0; + } + if (f[i] != null) { + return f[i]; + } + f[i] = trie.inf; + Trie node = trie; + for (int j = i; j < target.length; ++j) { + int idx = target[j] - 'a'; + if (node.children[idx] == null) { + return f[i]; + } + node = node.children[idx]; + f[i] = Math.min(f[i], node.cost + dfs(j + 1)); + } + return f[i]; + } +} +``` + +#### C++ + +```cpp +const int inf = 1 << 29; + +class Trie { +public: + Trie* children[26]{}; + int cost = inf; + + void insert(string& word, int cost) { + Trie* node = this; + for (char c : word) { + int idx = c - 'a'; + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } + node = node->children[idx]; + } + node->cost = min(node->cost, cost); + } +}; + +class Solution { +public: + int minimumCost(string target, vector& words, vector& costs) { + Trie* trie = new Trie(); + for (int i = 0; i < words.size(); ++i) { + trie->insert(words[i], costs[i]); + } + int n = target.length(); + int f[n]; + memset(f, 0, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (i >= n) { + return 0; + } + if (f[i]) { + return f[i]; + } + f[i] = inf; + Trie* node = trie; + for (int j = i; j < n; ++j) { + int idx = target[j] - 'a'; + if (!node->children[idx]) { + return f[i]; + } + node = node->children[idx]; + f[i] = min(f[i], node->cost + dfs(dfs, j + 1)); + } + return f[i]; + }; + int ans = dfs(dfs, 0); + return ans < inf ? ans : -1; + } +}; +``` + +#### Go + +```go +const inf = 1 << 29 + +type Trie struct { + children [26]*Trie + cost int +} + +func NewTrie() *Trie { + return &Trie{cost: inf} +} + +func (t *Trie) insert(word string, cost int) { + node := t + for _, c := range word { + idx := c - 'a' + if node.children[idx] == nil { + node.children[idx] = NewTrie() + } + node = node.children[idx] + } + node.cost = min(node.cost, cost) +} + +func minimumCost(target string, words []string, costs []int) int { + trie := NewTrie() + for i, word := range words { + trie.insert(word, costs[i]) + } + + n := len(target) + f := make([]int, n) + var dfs func(int) int + dfs = func(i int) int { + if i >= n { + return 0 + } + if f[i] != 0 { + return f[i] + } + f[i] = inf + node := trie + for j := i; j < n; j++ { + idx := target[j] - 'a' + if node.children[idx] == nil { + return f[i] + } + node = node.children[idx] + f[i] = min(f[i], node.cost+dfs(j+1)) + } + return f[i] + } + if ans := dfs(0); ans < inf { + return ans + } + return -1 +} +``` + +#### TypeScript + +```ts +const inf = 1 << 29; + +class Trie { + children: (Trie | null)[]; + cost: number; + + constructor() { + this.children = Array(26).fill(null); + this.cost = inf; + } + + insert(word: string, cost: number): void { + let node: Trie = this; + for (const c of word) { + const idx = c.charCodeAt(0) - 97; + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx]!; + } + node.cost = Math.min(node.cost, cost); + } +} + +function minimumCost(target: string, words: string[], costs: number[]): number { + const trie = new Trie(); + for (let i = 0; i < words.length; ++i) { + trie.insert(words[i], costs[i]); + } + + const n = target.length; + const f: number[] = Array(n).fill(0); + const dfs = (i: number): number => { + if (i >= n) { + return 0; + } + if (f[i]) { + return f[i]; + } + f[i] = inf; + let node: Trie | null = trie; + for (let j = i; j < n; ++j) { + const idx = target.charCodeAt(j) - 97; + if (!node?.children[idx]) { + return f[i]; + } + node = node.children[idx]; + f[i] = Math.min(f[i], node!.cost + dfs(j + 1)); + } + return f[i]; + }; + + const ans = dfs(0); + return ans < inf ? ans : -1; +} +``` + + + + + + diff --git a/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.cpp b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.cpp new file mode 100644 index 000000000000..66e33c7b7856 --- /dev/null +++ b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.cpp @@ -0,0 +1,53 @@ +const int inf = 1 << 29; + +class Trie { +public: + Trie* children[26]{}; + int cost = inf; + + void insert(string& word, int cost) { + Trie* node = this; + for (char c : word) { + int idx = c - 'a'; + if (!node->children[idx]) { + node->children[idx] = new Trie(); + } + node = node->children[idx]; + } + node->cost = min(node->cost, cost); + } +}; + +class Solution { +public: + int minimumCost(string target, vector& words, vector& costs) { + Trie* trie = new Trie(); + for (int i = 0; i < words.size(); ++i) { + trie->insert(words[i], costs[i]); + } + int n = target.length(); + int f[n]; + memset(f, 0, sizeof(f)); + auto dfs = [&](auto&& dfs, int i) -> int { + if (i >= n) { + return 0; + } + if (f[i]) { + return f[i]; + } + f[i] = inf; + Trie* node = trie; + for (int j = i; j < n; ++j) { + int idx = target[j] - 'a'; + if (!node->children[idx]) { + return f[i]; + } + node = node->children[idx]; + f[i] = min(f[i], node->cost + dfs(dfs, j + 1)); + } + return f[i]; + }; + int ans = dfs(dfs, 0); + return ans < inf ? ans : -1; + } +}; diff --git a/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.go b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.go new file mode 100644 index 000000000000..6639a6b37671 --- /dev/null +++ b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.go @@ -0,0 +1,56 @@ +const inf = 1 << 29 + +type Trie struct { + children [26]*Trie + cost int +} + +func NewTrie() *Trie { + return &Trie{cost: inf} +} + +func (t *Trie) insert(word string, cost int) { + node := t + for _, c := range word { + idx := c - 'a' + if node.children[idx] == nil { + node.children[idx] = NewTrie() + } + node = node.children[idx] + } + node.cost = min(node.cost, cost) +} + +func minimumCost(target string, words []string, costs []int) int { + trie := NewTrie() + for i, word := range words { + trie.insert(word, costs[i]) + } + + n := len(target) + f := make([]int, n) + var dfs func(int) int + dfs = func(i int) int { + if i >= n { + return 0 + } + if f[i] != 0 { + return f[i] + } + f[i] = inf + node := trie + for j := i; j < n; j++ { + idx := target[j] - 'a' + if node.children[idx] == nil { + return f[i] + } + node = node.children[idx] + f[i] = min(f[i], node.cost+dfs(j+1)) + } + return f[i] + } + if ans := dfs(0); ans < inf { + return ans + } + return -1 +} diff --git a/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.java b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.java new file mode 100644 index 000000000000..9f02d21f1c56 --- /dev/null +++ b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.java @@ -0,0 +1,53 @@ +class Trie { + public final int inf = 1 << 29; + public Trie[] children = new Trie[26]; + public int cost = inf; + + public void insert(String word, int cost) { + Trie node = this; + for (char c : word.toCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.cost = Math.min(node.cost, cost); + } +} + +class Solution { + private Trie trie = new Trie(); + private char[] target; + private Integer[] f; + + public int minimumCost(String target, String[] words, int[] costs) { + for (int i = 0; i < words.length; ++i) { + trie.insert(words[i], costs[i]); + } + this.target = target.toCharArray(); + f = new Integer[target.length()]; + int ans = dfs(0); + return ans < trie.inf ? ans : -1; + } + + private int dfs(int i) { + if (i >= target.length) { + return 0; + } + if (f[i] != null) { + return f[i]; + } + f[i] = trie.inf; + Trie node = trie; + for (int j = i; j < target.length; ++j) { + int idx = target[j] - 'a'; + if (node.children[idx] == null) { + return f[i]; + } + node = node.children[idx]; + f[i] = Math.min(f[i], node.cost + dfs(j + 1)); + } + return f[i]; + } +} diff --git a/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.py b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.py new file mode 100644 index 000000000000..2619866316b7 --- /dev/null +++ b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.py @@ -0,0 +1,36 @@ +class Trie: + def __init__(self): + self.children: List[Optional[Trie]] = [None] * 26 + self.cost = inf + + def insert(self, word: str, cost: int): + node = self + for c in word: + idx = ord(c) - ord("a") + if node.children[idx] is None: + node.children[idx] = Trie() + node = node.children[idx] + node.cost = min(node.cost, cost) + + +class Solution: + def minimumCost(self, target: str, words: List[str], costs: List[int]) -> int: + @cache + def dfs(i: int) -> int: + if i >= len(target): + return 0 + ans = inf + node = trie + for j in range(i, len(target)): + idx = ord(target[j]) - ord("a") + if node.children[idx] is None: + return ans + node = node.children[idx] + ans = min(ans, node.cost + dfs(j + 1)) + return ans + + trie = Trie() + for word, cost in zip(words, costs): + trie.insert(word, cost) + ans = dfs(0) + return ans if ans < inf else -1 diff --git a/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.ts b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.ts new file mode 100644 index 000000000000..a0d76bdaa0d2 --- /dev/null +++ b/solution/3200-3299/3253.Construct String with Minimum Cost (Easy)/Solution.ts @@ -0,0 +1,55 @@ +const inf = 1 << 29; + +class Trie { + children: (Trie | null)[]; + cost: number; + + constructor() { + this.children = Array(26).fill(null); + this.cost = inf; + } + + insert(word: string, cost: number): void { + let node: Trie = this; + for (const c of word) { + const idx = c.charCodeAt(0) - 97; + if (!node.children[idx]) { + node.children[idx] = new Trie(); + } + node = node.children[idx]!; + } + node.cost = Math.min(node.cost, cost); + } +} + +function minimumCost(target: string, words: string[], costs: number[]): number { + const trie = new Trie(); + for (let i = 0; i < words.length; ++i) { + trie.insert(words[i], costs[i]); + } + + const n = target.length; + const f: number[] = Array(n).fill(0); + const dfs = (i: number): number => { + if (i >= n) { + return 0; + } + if (f[i]) { + return f[i]; + } + f[i] = inf; + let node: Trie | null = trie; + for (let j = i; j < n; ++j) { + const idx = target.charCodeAt(j) - 97; + if (!node?.children[idx]) { + return f[i]; + } + node = node.children[idx]; + f[i] = Math.min(f[i], node!.cost + dfs(j + 1)); + } + return f[i]; + }; + + const ans = dfs(0); + return ans < inf ? ans : -1; +} diff --git a/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/README.md b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/README.md new file mode 100644 index 000000000000..5e0ed741c966 --- /dev/null +++ b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/README.md @@ -0,0 +1,205 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README.md +tags: + - 数组 + - 滑动窗口 +--- + + + +# [3254. 长度为 K 的子数组的能量值 I](https://leetcode.cn/problems/find-the-power-of-k-size-subarrays-i) + +[English Version](/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README_EN.md) + +## 题目描述 + + + +

            给你一个长度为 n 的整数数组 nums 和一个正整数 k 。

            + +

            一个数组的 能量值 定义为:

            + +
              +
            • 如果 所有 元素都是依次 连续上升 的,那么能量值为 最大 的元素。
            • +
            • 否则为 -1 。
            • +
            + +

            你需要求出 nums 中所有长度为 k 的 子数组 的能量值。

            + +

            请你返回一个长度为 n - k + 1 的整数数组 results ,其中 results[i] 是子数组 nums[i..(i + k - 1)] 的能量值。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [1,2,3,4,3,2,5], k = 3

            + +

            输出:[3,4,-1,-1,-1]

            + +

            解释:

            + +

            nums 中总共有 5 个长度为 3 的子数组:

            + +
              +
            • [1, 2, 3] 中最大元素为 3 。
            • +
            • [2, 3, 4] 中最大元素为 4 。
            • +
            • [3, 4, 3] 中元素 不是 连续的。
            • +
            • [4, 3, 2] 中元素 不是 上升的。
            • +
            • [3, 2, 5] 中元素 不是 连续的。
            • +
            +
            + +

            示例 2:

            + +
            +

            输入:nums = [2,2,2,2,2], k = 4

            + +

            输出:[-1,-1]

            +
            + +

            示例 3:

            + +
            +

            输入:nums = [3,2,3,2,3,2], k = 2

            + +

            输出:[-1,3,-1,3,-1]

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n == nums.length <= 500
            • +
            • 1 <= nums[i] <= 105
            • +
            • 1 <= k <= n
            • +
            + + + +## 解法 + + + +### 方法一:递推 + +我们定义一个数组 $f$,其中 $f[i]$ 表示以第 $i$ 个元素结尾的连续上升子序列的长度。初始时 $f[i] = 1$。 + +接下来,我们遍历数组 $\textit{nums}$,计算数组 $f$ 的值。如果 $nums[i] = nums[i - 1] + 1$,则 $f[i] = f[i - 1] + 1$;否则 $f[i] = 1$。 + +然后,我们在 $[k - 1, n)$ 的范围内遍历数组 $f$,如果 $f[i] \ge k$,那么答案数组添加 $\textit{nums}$,否则添加 $-1$。 + +遍历结束后,返回答案数组。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def resultsArray(self, nums: List[int], k: int) -> List[int]: + n = len(nums) + f = [1] * n + for i in range(1, n): + if nums[i] == nums[i - 1] + 1: + f[i] = f[i - 1] + 1 + return [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)] +``` + +#### Java + +```java +class Solution { + public int[] resultsArray(int[] nums, int k) { + int n = nums.length; + int[] f = new int[n]; + Arrays.fill(f, 1); + for (int i = 1; i < n; ++i) { + if (nums[i] == nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + int[] ans = new int[n - k + 1]; + for (int i = k - 1; i < n; ++i) { + ans[i - k + 1] = f[i] >= k ? nums[i] : -1; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector resultsArray(vector& nums, int k) { + int n = nums.size(); + int f[n]; + f[0] = 1; + for (int i = 1; i < n; ++i) { + f[i] = nums[i] == nums[i - 1] + 1 ? f[i - 1] + 1 : 1; + } + vector ans; + for (int i = k - 1; i < n; ++i) { + ans.push_back(f[i] >= k ? nums[i] : -1); + } + return ans; + } +}; +``` + +#### Go + +```go +func resultsArray(nums []int, k int) (ans []int) { + n := len(nums) + f := make([]int, n) + f[0] = 1 + for i := 1; i < n; i++ { + if nums[i] == nums[i-1]+1 { + f[i] = f[i-1] + 1 + } else { + f[i] = 1 + } + } + for i := k - 1; i < n; i++ { + if f[i] >= k { + ans = append(ans, nums[i]) + } else { + ans = append(ans, -1) + } + } + return +} +``` + +#### TypeScript + +```ts +function resultsArray(nums: number[], k: number): number[] { + const n = nums.length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; ++i) { + if (nums[i] === nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + const ans: number[] = []; + for (let i = k - 1; i < n; ++i) { + ans.push(f[i] >= k ? nums[i] : -1); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/README_EN.md b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/README_EN.md new file mode 100644 index 000000000000..d14f9690c067 --- /dev/null +++ b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/README_EN.md @@ -0,0 +1,203 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README_EN.md +tags: + - Array + - Sliding Window +--- + + + +# [3254. Find the Power of K-Size Subarrays I](https://leetcode.com/problems/find-the-power-of-k-size-subarrays-i) + +[中文文档](/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README.md) + +## Description + + + +

            You are given an array of integers nums of length n and a positive integer k.

            + +

            The power of an array is defined as:

            + +
              +
            • Its maximum element if all of its elements are consecutive and sorted in ascending order.
            • +
            • -1 otherwise.
            • +
            + +

            You need to find the power of all subarrays of nums of size k.

            + +

            Return an integer array results of size n - k + 1, where results[i] is the power of nums[i..(i + k - 1)].

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [1,2,3,4,3,2,5], k = 3

            + +

            Output: [3,4,-1,-1,-1]

            + +

            Explanation:

            + +

            There are 5 subarrays of nums of size 3:

            + +
              +
            • [1, 2, 3] with the maximum element 3.
            • +
            • [2, 3, 4] with the maximum element 4.
            • +
            • [3, 4, 3] whose elements are not consecutive.
            • +
            • [4, 3, 2] whose elements are not sorted.
            • +
            • [3, 2, 5] whose elements are not consecutive.
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: nums = [2,2,2,2,2], k = 4

            + +

            Output: [-1,-1]

            +
            + +

            Example 3:

            + +
            +

            Input: nums = [3,2,3,2,3,2], k = 2

            + +

            Output: [-1,3,-1,3,-1]

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n == nums.length <= 500
            • +
            • 1 <= nums[i] <= 105
            • +
            • 1 <= k <= n
            • +
            + + + +## Solutions + + + +### Solution 1: Recursion + +We define an array $f$, where $f[i]$ represents the length of the continuous increasing subsequence ending at the $i$-th element. Initially, $f[i] = 1$. + +Next, we traverse the array $\textit{nums}$ to calculate the values of the array $f$. If $nums[i] = nums[i - 1] + 1$, then $f[i] = f[i - 1] + 1$; otherwise, $f[i] = 1$. + +Then, we traverse the array $f$ in the range $[k - 1, n)$. If $f[i] \ge k$, we add $\textit{nums}[i]$ to the answer array; otherwise, we add $-1$. + +After the traversal, we return the answer array. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ represents the length of the array $\textit{nums}$. + + + +#### Python3 + +```python +class Solution: + def resultsArray(self, nums: List[int], k: int) -> List[int]: + n = len(nums) + f = [1] * n + for i in range(1, n): + if nums[i] == nums[i - 1] + 1: + f[i] = f[i - 1] + 1 + return [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)] +``` + +#### Java + +```java +class Solution { + public int[] resultsArray(int[] nums, int k) { + int n = nums.length; + int[] f = new int[n]; + Arrays.fill(f, 1); + for (int i = 1; i < n; ++i) { + if (nums[i] == nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + int[] ans = new int[n - k + 1]; + for (int i = k - 1; i < n; ++i) { + ans[i - k + 1] = f[i] >= k ? nums[i] : -1; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector resultsArray(vector& nums, int k) { + int n = nums.size(); + int f[n]; + f[0] = 1; + for (int i = 1; i < n; ++i) { + f[i] = nums[i] == nums[i - 1] + 1 ? f[i - 1] + 1 : 1; + } + vector ans; + for (int i = k - 1; i < n; ++i) { + ans.push_back(f[i] >= k ? nums[i] : -1); + } + return ans; + } +}; +``` + +#### Go + +```go +func resultsArray(nums []int, k int) (ans []int) { + n := len(nums) + f := make([]int, n) + f[0] = 1 + for i := 1; i < n; i++ { + if nums[i] == nums[i-1]+1 { + f[i] = f[i-1] + 1 + } else { + f[i] = 1 + } + } + for i := k - 1; i < n; i++ { + if f[i] >= k { + ans = append(ans, nums[i]) + } else { + ans = append(ans, -1) + } + } + return +} +``` + +#### TypeScript + +```ts +function resultsArray(nums: number[], k: number): number[] { + const n = nums.length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; ++i) { + if (nums[i] === nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + const ans: number[] = []; + for (let i = k - 1; i < n; ++i) { + ans.push(f[i] >= k ? nums[i] : -1); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.cpp b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.cpp new file mode 100644 index 000000000000..629fdcb4ae7c --- /dev/null +++ b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.cpp @@ -0,0 +1,16 @@ +class Solution { +public: + vector resultsArray(vector& nums, int k) { + int n = nums.size(); + int f[n]; + f[0] = 1; + for (int i = 1; i < n; ++i) { + f[i] = nums[i] == nums[i - 1] + 1 ? f[i - 1] + 1 : 1; + } + vector ans; + for (int i = k - 1; i < n; ++i) { + ans.push_back(f[i] >= k ? nums[i] : -1); + } + return ans; + } +}; diff --git a/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.go b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.go new file mode 100644 index 000000000000..a13924f381d1 --- /dev/null +++ b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.go @@ -0,0 +1,20 @@ +func resultsArray(nums []int, k int) (ans []int) { + n := len(nums) + f := make([]int, n) + f[0] = 1 + for i := 1; i < n; i++ { + if nums[i] == nums[i-1]+1 { + f[i] = f[i-1] + 1 + } else { + f[i] = 1 + } + } + for i := k - 1; i < n; i++ { + if f[i] >= k { + ans = append(ans, nums[i]) + } else { + ans = append(ans, -1) + } + } + return +} diff --git a/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.java b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.java new file mode 100644 index 000000000000..1743d7c627b6 --- /dev/null +++ b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.java @@ -0,0 +1,17 @@ +class Solution { + public int[] resultsArray(int[] nums, int k) { + int n = nums.length; + int[] f = new int[n]; + Arrays.fill(f, 1); + for (int i = 1; i < n; ++i) { + if (nums[i] == nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + int[] ans = new int[n - k + 1]; + for (int i = k - 1; i < n; ++i) { + ans[i - k + 1] = f[i] >= k ? nums[i] : -1; + } + return ans; + } +} diff --git a/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.py b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.py new file mode 100644 index 000000000000..ff54f3b896d1 --- /dev/null +++ b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.py @@ -0,0 +1,8 @@ +class Solution: + def resultsArray(self, nums: List[int], k: int) -> List[int]: + n = len(nums) + f = [1] * n + for i in range(1, n): + if nums[i] == nums[i - 1] + 1: + f[i] = f[i - 1] + 1 + return [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)] diff --git a/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.ts b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.ts new file mode 100644 index 000000000000..382d63095f3a --- /dev/null +++ b/solution/3200-3299/3254.Find the Power of K-Size Subarrays I/Solution.ts @@ -0,0 +1,14 @@ +function resultsArray(nums: number[], k: number): number[] { + const n = nums.length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; ++i) { + if (nums[i] === nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + const ans: number[] = []; + for (let i = k - 1; i < n; ++i) { + ans.push(f[i] >= k ? nums[i] : -1); + } + return ans; +} diff --git a/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/README.md b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/README.md new file mode 100644 index 000000000000..422c9cc3b87b --- /dev/null +++ b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/README.md @@ -0,0 +1,205 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README.md +tags: + - 数组 + - 滑动窗口 +--- + + + +# [3255. 长度为 K 的子数组的能量值 II](https://leetcode.cn/problems/find-the-power-of-k-size-subarrays-ii) + +[English Version](/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README_EN.md) + +## 题目描述 + + + +

            给你一个长度为 n 的整数数组 nums 和一个正整数 k 。

            + +

            一个数组的 能量值 定义为:

            + +
              +
            • 如果 所有 元素都是依次 连续上升 的,那么能量值为 最大 的元素。
            • +
            • 否则为 -1 。
            • +
            + +

            你需要求出 nums 中所有长度为 k 的 子数组 的能量值。

            + +

            请你返回一个长度为 n - k + 1 的整数数组 results ,其中 results[i] 是子数组 nums[i..(i + k - 1)] 的能量值。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:nums = [1,2,3,4,3,2,5], k = 3

            + +

            输出:[3,4,-1,-1,-1]

            + +

            解释:

            + +

            nums 中总共有 5 个长度为 3 的子数组:

            + +
              +
            • [1, 2, 3] 中最大元素为 3 。
            • +
            • [2, 3, 4] 中最大元素为 4 。
            • +
            • [3, 4, 3] 中元素 不是 连续的。
            • +
            • [4, 3, 2] 中元素 不是 上升的。
            • +
            • [3, 2, 5] 中元素 不是 连续的。
            • +
            +
            + +

            示例 2:

            + +
            +

            输入:nums = [2,2,2,2,2], k = 4

            + +

            输出:[-1,-1]

            +
            + +

            示例 3:

            + +
            +

            输入:nums = [3,2,3,2,3,2], k = 2

            + +

            输出:[-1,3,-1,3,-1]

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n == nums.length <= 105
            • +
            • 1 <= nums[i] <= 106
            • +
            • 1 <= k <= n
            • +
            + + + +## 解法 + + + +### 方法一:递推 + +我们定义一个数组 $f$,其中 $f[i]$ 表示以第 $i$ 个元素结尾的连续上升子序列的长度。初始时 $f[i] = 1$。 + +接下来,我们遍历数组 $\textit{nums}$,计算数组 $f$ 的值。如果 $nums[i] = nums[i - 1] + 1$,则 $f[i] = f[i - 1] + 1$;否则 $f[i] = 1$。 + +然后,我们在 $[k - 1, n)$ 的范围内遍历数组 $f$,如果 $f[i] \ge k$,那么答案数组添加 $\textit{nums}$,否则添加 $-1$。 + +遍历结束后,返回答案数组。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def resultsArray(self, nums: List[int], k: int) -> List[int]: + n = len(nums) + f = [1] * n + for i in range(1, n): + if nums[i] == nums[i - 1] + 1: + f[i] = f[i - 1] + 1 + return [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)] +``` + +#### Java + +```java +class Solution { + public int[] resultsArray(int[] nums, int k) { + int n = nums.length; + int[] f = new int[n]; + Arrays.fill(f, 1); + for (int i = 1; i < n; ++i) { + if (nums[i] == nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + int[] ans = new int[n - k + 1]; + for (int i = k - 1; i < n; ++i) { + ans[i - k + 1] = f[i] >= k ? nums[i] : -1; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector resultsArray(vector& nums, int k) { + int n = nums.size(); + int f[n]; + f[0] = 1; + for (int i = 1; i < n; ++i) { + f[i] = nums[i] == nums[i - 1] + 1 ? f[i - 1] + 1 : 1; + } + vector ans; + for (int i = k - 1; i < n; ++i) { + ans.push_back(f[i] >= k ? nums[i] : -1); + } + return ans; + } +}; +``` + +#### Go + +```go +func resultsArray(nums []int, k int) (ans []int) { + n := len(nums) + f := make([]int, n) + f[0] = 1 + for i := 1; i < n; i++ { + if nums[i] == nums[i-1]+1 { + f[i] = f[i-1] + 1 + } else { + f[i] = 1 + } + } + for i := k - 1; i < n; i++ { + if f[i] >= k { + ans = append(ans, nums[i]) + } else { + ans = append(ans, -1) + } + } + return +} +``` + +#### TypeScript + +```ts +function resultsArray(nums: number[], k: number): number[] { + const n = nums.length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; ++i) { + if (nums[i] === nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + const ans: number[] = []; + for (let i = k - 1; i < n; ++i) { + ans.push(f[i] >= k ? nums[i] : -1); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/README_EN.md b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/README_EN.md new file mode 100644 index 000000000000..88568b364faf --- /dev/null +++ b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/README_EN.md @@ -0,0 +1,203 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README_EN.md +tags: + - Array + - Sliding Window +--- + + + +# [3255. Find the Power of K-Size Subarrays II](https://leetcode.com/problems/find-the-power-of-k-size-subarrays-ii) + +[中文文档](/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README.md) + +## Description + + + +

            You are given an array of integers nums of length n and a positive integer k.

            + +

            The power of an array is defined as:

            + +
              +
            • Its maximum element if all of its elements are consecutive and sorted in ascending order.
            • +
            • -1 otherwise.
            • +
            + +

            You need to find the power of all subarrays of nums of size k.

            + +

            Return an integer array results of size n - k + 1, where results[i] is the power of nums[i..(i + k - 1)].

            + +

             

            +

            Example 1:

            + +
            +

            Input: nums = [1,2,3,4,3,2,5], k = 3

            + +

            Output: [3,4,-1,-1,-1]

            + +

            Explanation:

            + +

            There are 5 subarrays of nums of size 3:

            + +
              +
            • [1, 2, 3] with the maximum element 3.
            • +
            • [2, 3, 4] with the maximum element 4.
            • +
            • [3, 4, 3] whose elements are not consecutive.
            • +
            • [4, 3, 2] whose elements are not sorted.
            • +
            • [3, 2, 5] whose elements are not consecutive.
            • +
            +
            + +

            Example 2:

            + +
            +

            Input: nums = [2,2,2,2,2], k = 4

            + +

            Output: [-1,-1]

            +
            + +

            Example 3:

            + +
            +

            Input: nums = [3,2,3,2,3,2], k = 2

            + +

            Output: [-1,3,-1,3,-1]

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n == nums.length <= 105
            • +
            • 1 <= nums[i] <= 106
            • +
            • 1 <= k <= n
            • +
            + + + +## Solutions + + + +### Solution 1: Recursion + +We define an array $f$, where $f[i]$ represents the length of the continuous increasing subsequence ending at the $i$-th element. Initially, $f[i] = 1$. + +Next, we traverse the array $\textit{nums}$ to calculate the values of the array $f$. If $nums[i] = nums[i - 1] + 1$, then $f[i] = f[i - 1] + 1$; otherwise, $f[i] = 1$. + +Then, we traverse the array $f$ in the range $[k - 1, n)$. If $f[i] \ge k$, we add $\textit{nums}[i]$ to the answer array; otherwise, we add $-1$. + +After the traversal, we return the answer array. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ represents the length of the array $\textit{nums}$. + + + +#### Python3 + +```python +class Solution: + def resultsArray(self, nums: List[int], k: int) -> List[int]: + n = len(nums) + f = [1] * n + for i in range(1, n): + if nums[i] == nums[i - 1] + 1: + f[i] = f[i - 1] + 1 + return [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)] +``` + +#### Java + +```java +class Solution { + public int[] resultsArray(int[] nums, int k) { + int n = nums.length; + int[] f = new int[n]; + Arrays.fill(f, 1); + for (int i = 1; i < n; ++i) { + if (nums[i] == nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + int[] ans = new int[n - k + 1]; + for (int i = k - 1; i < n; ++i) { + ans[i - k + 1] = f[i] >= k ? nums[i] : -1; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + vector resultsArray(vector& nums, int k) { + int n = nums.size(); + int f[n]; + f[0] = 1; + for (int i = 1; i < n; ++i) { + f[i] = nums[i] == nums[i - 1] + 1 ? f[i - 1] + 1 : 1; + } + vector ans; + for (int i = k - 1; i < n; ++i) { + ans.push_back(f[i] >= k ? nums[i] : -1); + } + return ans; + } +}; +``` + +#### Go + +```go +func resultsArray(nums []int, k int) (ans []int) { + n := len(nums) + f := make([]int, n) + f[0] = 1 + for i := 1; i < n; i++ { + if nums[i] == nums[i-1]+1 { + f[i] = f[i-1] + 1 + } else { + f[i] = 1 + } + } + for i := k - 1; i < n; i++ { + if f[i] >= k { + ans = append(ans, nums[i]) + } else { + ans = append(ans, -1) + } + } + return +} +``` + +#### TypeScript + +```ts +function resultsArray(nums: number[], k: number): number[] { + const n = nums.length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; ++i) { + if (nums[i] === nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + const ans: number[] = []; + for (let i = k - 1; i < n; ++i) { + ans.push(f[i] >= k ? nums[i] : -1); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.cpp b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.cpp new file mode 100644 index 000000000000..629fdcb4ae7c --- /dev/null +++ b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.cpp @@ -0,0 +1,16 @@ +class Solution { +public: + vector resultsArray(vector& nums, int k) { + int n = nums.size(); + int f[n]; + f[0] = 1; + for (int i = 1; i < n; ++i) { + f[i] = nums[i] == nums[i - 1] + 1 ? f[i - 1] + 1 : 1; + } + vector ans; + for (int i = k - 1; i < n; ++i) { + ans.push_back(f[i] >= k ? nums[i] : -1); + } + return ans; + } +}; diff --git a/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.go b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.go new file mode 100644 index 000000000000..a13924f381d1 --- /dev/null +++ b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.go @@ -0,0 +1,20 @@ +func resultsArray(nums []int, k int) (ans []int) { + n := len(nums) + f := make([]int, n) + f[0] = 1 + for i := 1; i < n; i++ { + if nums[i] == nums[i-1]+1 { + f[i] = f[i-1] + 1 + } else { + f[i] = 1 + } + } + for i := k - 1; i < n; i++ { + if f[i] >= k { + ans = append(ans, nums[i]) + } else { + ans = append(ans, -1) + } + } + return +} diff --git a/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.java b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.java new file mode 100644 index 000000000000..1743d7c627b6 --- /dev/null +++ b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.java @@ -0,0 +1,17 @@ +class Solution { + public int[] resultsArray(int[] nums, int k) { + int n = nums.length; + int[] f = new int[n]; + Arrays.fill(f, 1); + for (int i = 1; i < n; ++i) { + if (nums[i] == nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + int[] ans = new int[n - k + 1]; + for (int i = k - 1; i < n; ++i) { + ans[i - k + 1] = f[i] >= k ? nums[i] : -1; + } + return ans; + } +} diff --git a/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.py b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.py new file mode 100644 index 000000000000..ff54f3b896d1 --- /dev/null +++ b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.py @@ -0,0 +1,8 @@ +class Solution: + def resultsArray(self, nums: List[int], k: int) -> List[int]: + n = len(nums) + f = [1] * n + for i in range(1, n): + if nums[i] == nums[i - 1] + 1: + f[i] = f[i - 1] + 1 + return [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)] diff --git a/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.ts b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.ts new file mode 100644 index 000000000000..382d63095f3a --- /dev/null +++ b/solution/3200-3299/3255.Find the Power of K-Size Subarrays II/Solution.ts @@ -0,0 +1,14 @@ +function resultsArray(nums: number[], k: number): number[] { + const n = nums.length; + const f: number[] = Array(n).fill(1); + for (let i = 1; i < n; ++i) { + if (nums[i] === nums[i - 1] + 1) { + f[i] = f[i - 1] + 1; + } + } + const ans: number[] = []; + for (let i = k - 1; i < n; ++i) { + ans.push(f[i] >= k ? nums[i] : -1); + } + return ans; +} diff --git a/solution/3200-3299/3256.Maximum Value Sum by Placing Three Rooks I/README.md b/solution/3200-3299/3256.Maximum Value Sum by Placing Three Rooks I/README.md new file mode 100644 index 000000000000..f6cfac2c53dd --- /dev/null +++ b/solution/3200-3299/3256.Maximum Value Sum by Placing Three Rooks I/README.md @@ -0,0 +1,116 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README.md +tags: + - 数组 + - 动态规划 + - 枚举 + - 矩阵 +--- + + + +# [3256. 放三个车的价值之和最大 I](https://leetcode.cn/problems/maximum-value-sum-by-placing-three-rooks-i) + +[English Version](/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README_EN.md) + +## 题目描述 + + + +

            给你一个 m x n 的二维整数数组 board ,它表示一个国际象棋棋盘,其中 board[i][j] 表示格子 (i, j) 的 价值 。

            + +

            处于 同一行 或者 同一列 车会互相 攻击 。你需要在棋盘上放三个车,确保它们两两之间都 无法互相攻击 。

            + +

            请你返回满足上述条件下,三个车所在格子  之和 最大 为多少。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:board = [[-3,1,1,1],[-3,1,-3,1],[-3,2,1,1]]

            + +

            输出:4

            + +

            解释:

            + +

            + +

            我们可以将车分别放在格子 (0, 2) ,(1, 3) 和 (2, 1) 处,价值之和为 1 + 1 + 2 = 4 。

            +
            + +

            示例 2:

            + +
            +

            输入:board = [[1,2,3],[4,5,6],[7,8,9]]

            + +

            输出:15

            + +

            解释:

            + +

            我们可以将车分别放在格子 (0, 0) ,(1, 1) 和 (2, 2) 处,价值之和为 1 + 5 + 9 = 15 。

            +
            + +

            示例 3:

            + +
            +

            输入:board = [[1,1,1],[1,1,1],[1,1,1]]

            + +

            输出:3

            + +

            解释:

            + +

            我们可以将车分别放在格子 (0, 2) ,(1, 1) 和 (2, 0) 处,价值之和为 1 + 1 + 1 = 3 。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 3 <= m == board.length <= 100
            • +
            • 3 <= n == board[i].length <= 100
            • +
            • -109 <= board[i][j] <= 109
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3256.Maximum Value Sum by Placing Three Rooks I/README_EN.md b/solution/3200-3299/3256.Maximum Value Sum by Placing Three Rooks I/README_EN.md new file mode 100644 index 000000000000..019630a4cf3c --- /dev/null +++ b/solution/3200-3299/3256.Maximum Value Sum by Placing Three Rooks I/README_EN.md @@ -0,0 +1,114 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README_EN.md +tags: + - Array + - Dynamic Programming + - Enumeration + - Matrix +--- + + + +# [3256. Maximum Value Sum by Placing Three Rooks I](https://leetcode.com/problems/maximum-value-sum-by-placing-three-rooks-i) + +[中文文档](/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README.md) + +## Description + + + +

            You are given a m x n 2D array board representing a chessboard, where board[i][j] represents the value of the cell (i, j).

            + +

            Rooks in the same row or column attack each other. You need to place three rooks on the chessboard such that the rooks do not attack each other.

            + +

            Return the maximum sum of the cell values on which the rooks are placed.

            + +

             

            +

            Example 1:

            + +
            +

            Input: board = [[-3,1,1,1],[-3,1,-3,1],[-3,2,1,1]]

            + +

            Output: 4

            + +

            Explanation:

            + +

            + +

            We can place the rooks in the cells (0, 2), (1, 3), and (2, 1) for a sum of 1 + 1 + 2 = 4.

            +
            + +

            Example 2:

            + +
            +

            Input: board = [[1,2,3],[4,5,6],[7,8,9]]

            + +

            Output: 15

            + +

            Explanation:

            + +

            We can place the rooks in the cells (0, 0), (1, 1), and (2, 2) for a sum of 1 + 5 + 9 = 15.

            +
            + +

            Example 3:

            + +
            +

            Input: board = [[1,1,1],[1,1,1],[1,1,1]]

            + +

            Output: 3

            + +

            Explanation:

            + +

            We can place the rooks in the cells (0, 2), (1, 1), and (2, 0) for a sum of 1 + 1 + 1 = 3.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 3 <= m == board.length <= 100
            • +
            • 3 <= n == board[i].length <= 100
            • +
            • -109 <= board[i][j] <= 109
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3257.Maximum Value Sum by Placing Three Rooks II/README.md b/solution/3200-3299/3257.Maximum Value Sum by Placing Three Rooks II/README.md new file mode 100644 index 000000000000..7085075b244d --- /dev/null +++ b/solution/3200-3299/3257.Maximum Value Sum by Placing Three Rooks II/README.md @@ -0,0 +1,116 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README.md +tags: + - 数组 + - 动态规划 + - 枚举 + - 矩阵 +--- + + + +# [3257. 放三个车的价值之和最大 II](https://leetcode.cn/problems/maximum-value-sum-by-placing-three-rooks-ii) + +[English Version](/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README_EN.md) + +## 题目描述 + + + +

            给你一个 m x n 的二维整数数组 board ,它表示一个国际象棋棋盘,其中 board[i][j] 表示格子 (i, j) 的 价值 。

            + +

            处于 同一行 或者 同一列 车会互相 攻击 。你需要在棋盘上放三个车,确保它们两两之间都 无法互相攻击 。

            + +

            请你返回满足上述条件下,三个车所在格子  之和 最大 为多少。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:board = [[-3,1,1,1],[-3,1,-3,1],[-3,2,1,1]]

            + +

            输出:4

            + +

            解释:

            + +

            + +

            我们可以将车分别放在格子 (0, 2) ,(1, 3) 和 (2, 1) 处,价值之和为 1 + 1 + 2 = 4 。

            +
            + +

            示例 2:

            + +
            +

            输入:board = [[1,2,3],[4,5,6],[7,8,9]]

            + +

            输出:15

            + +

            解释:

            + +

            我们可以将车分别放在格子 (0, 0) ,(1, 1) 和 (2, 2) 处,价值之和为 1 + 5 + 9 = 15 。

            +
            + +

            示例 3:

            + +
            +

            输入:board = [[1,1,1],[1,1,1],[1,1,1]]

            + +

            输出:3

            + +

            解释:

            + +

            我们可以将车分别放在格子 (0, 2) ,(1, 1) 和 (2, 0) 处,价值之和为 1 + 1 + 1 = 3 。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 3 <= m == board.length <= 500
            • +
            • 3 <= n == board[i].length <= 500
            • +
            • -109 <= board[i][j] <= 109
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3257.Maximum Value Sum by Placing Three Rooks II/README_EN.md b/solution/3200-3299/3257.Maximum Value Sum by Placing Three Rooks II/README_EN.md new file mode 100644 index 000000000000..8df098939619 --- /dev/null +++ b/solution/3200-3299/3257.Maximum Value Sum by Placing Three Rooks II/README_EN.md @@ -0,0 +1,114 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README_EN.md +tags: + - Array + - Dynamic Programming + - Enumeration + - Matrix +--- + + + +# [3257. Maximum Value Sum by Placing Three Rooks II](https://leetcode.com/problems/maximum-value-sum-by-placing-three-rooks-ii) + +[中文文档](/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README.md) + +## Description + + + +

            You are given a m x n 2D array board representing a chessboard, where board[i][j] represents the value of the cell (i, j).

            + +

            Rooks in the same row or column attack each other. You need to place three rooks on the chessboard such that the rooks do not attack each other.

            + +

            Return the maximum sum of the cell values on which the rooks are placed.

            + +

             

            +

            Example 1:

            + +
            +

            Input: board = [[-3,1,1,1],[-3,1,-3,1],[-3,2,1,1]]

            + +

            Output: 4

            + +

            Explanation:

            + +

            + +

            We can place the rooks in the cells (0, 2), (1, 3), and (2, 1) for a sum of 1 + 1 + 2 = 4.

            +
            + +

            Example 2:

            + +
            +

            Input: board = [[1,2,3],[4,5,6],[7,8,9]]

            + +

            Output: 15

            + +

            Explanation:

            + +

            We can place the rooks in the cells (0, 0), (1, 1), and (2, 2) for a sum of 1 + 5 + 9 = 15.

            +
            + +

            Example 3:

            + +
            +

            Input: board = [[1,1,1],[1,1,1],[1,1,1]]

            + +

            Output: 3

            + +

            Explanation:

            + +

            We can place the rooks in the cells (0, 2), (1, 1), and (2, 0) for a sum of 1 + 1 + 1 = 3.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 3 <= m == board.length <= 500
            • +
            • 3 <= n == board[i].length <= 500
            • +
            • -109 <= board[i][j] <= 109
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README.md b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README.md new file mode 100644 index 000000000000..23858ac32a0a --- /dev/null +++ b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README.md @@ -0,0 +1,207 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README.md +tags: + - 字符串 + - 滑动窗口 +--- + + + +# [3258. 统计满足 K 约束的子字符串数量 I](https://leetcode.cn/problems/count-substrings-that-satisfy-k-constraint-i) + +[English Version](/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README_EN.md) + +## 题目描述 + + + +

            给你一个 二进制 字符串 s 和一个整数 k

            + +

            如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束

            + +
              +
            • 字符串中 0 的数量最多为 k
            • +
            • 字符串中 1 的数量最多为 k
            • +
            + +

            返回一个整数,表示 s 的所有满足 k 约束 子字符串的数量。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:s = "10101", k = 1

            + +

            输出:12

            + +

            解释:

            + +

            s 的所有子字符串中,除了 "1010""10101""0101" 外,其余子字符串都满足 k 约束。

            +
            + +

            示例 2:

            + +
            +

            输入:s = "1010101", k = 2

            + +

            输出:25

            + +

            解释:

            + +

            s 的所有子字符串中,除了长度大于 5 的子字符串外,其余子字符串都满足 k 约束。

            +
            + +

            示例 3:

            + +
            +

            输入:s = "11111", k = 1

            + +

            输出:15

            + +

            解释:

            + +

            s 的所有子字符串都满足 k 约束。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= s.length <= 50
            • +
            • 1 <= k <= s.length
            • +
            • s[i]'0''1'
            • +
            + + + +## 解法 + + + +### 方法一:滑动窗口 + +我们用两个变量 $\textit{cnt0}$ 和 $\textit{cnt1}$ 分别记录当前窗口内的 $0$ 和 $1$ 的个数,用 $\textit{ans}$ 记录满足 $k$ 约束的子字符串的个数,用 $l$ 记录窗口的左边界。 + +当我们右移窗口时,如果窗口内的 $0$ 和 $1$ 的个数都大于 $k$,我们就需要左移窗口,直到窗口内的 $0$ 和 $1$ 的个数都不大于 $k$。此时,窗口内的所有子字符串都满足 $k$ 约束,个数为 $r - l + 1$,其中 $r$ 是窗口的右边界。我们将这个个数累加到 $\textit{ans}$ 中。 + +最后,我们返回 $\textit{ans}$ 即可。 + +时间复杂度 $O(n)$,其中 $n$ 是字符串 $s$ 的长度。空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +class Solution: + def countKConstraintSubstrings(self, s: str, k: int) -> int: + cnt0 = cnt1 = 0 + ans = l = 0 + for r, c in enumerate(s): + cnt0 += int(c) ^ 1 + cnt1 += int(c) + while cnt0 > k and cnt1 > k: + cnt0 -= int(s[l]) ^ 1 + cnt1 -= int(s[l]) + l += 1 + ans += r - l + 1 + return ans +``` + +#### Java + +```java +class Solution { + public int countKConstraintSubstrings(String s, int k) { + int cnt0 = 0, cnt1 = 0; + int ans = 0, l = 0; + for (int r = 0; r < s.length(); ++r) { + int x = s.charAt(r) - '0'; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + int y = s.charAt(l++) - '0'; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countKConstraintSubstrings(string s, int k) { + int cnt0 = 0, cnt1 = 0; + int ans = 0, l = 0; + for (int r = 0; r < s.length(); ++r) { + int x = s[r] - '0'; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + int y = s[l++] - '0'; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; + } +}; +``` + +#### Go + +```go +func countKConstraintSubstrings(s string, k int) (ans int) { + cnt0, cnt1, l := 0, 0, 0 + for r, c := range s { + x := int(c - '0') + cnt0 += x ^ 1 + cnt1 += x + for cnt0 > k && cnt1 > k { + y := int(s[l] - '0') + cnt0 -= y ^ 1 + cnt1 -= y + l++ + } + ans += r - l + 1 + } + return +} +``` + +#### TypeScript + +```ts +function countKConstraintSubstrings(s: string, k: number): number { + let [cnt0, cnt1, ans, l] = [0, 0, 0, 0]; + for (let r = 0; r < s.length; ++r) { + const x = s[r] === '1' ? 1 : 0; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + const y = s[l++] === '1' ? 1 : 0; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README_EN.md b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README_EN.md new file mode 100644 index 000000000000..b307a649978f --- /dev/null +++ b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/README_EN.md @@ -0,0 +1,205 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README_EN.md +tags: + - String + - Sliding Window +--- + + + +# [3258. Count Substrings That Satisfy K-Constraint I](https://leetcode.com/problems/count-substrings-that-satisfy-k-constraint-i) + +[中文文档](/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README.md) + +## Description + + + +

            You are given a binary string s and an integer k.

            + +

            A binary string satisfies the k-constraint if either of the following conditions holds:

            + +
              +
            • The number of 0's in the string is at most k.
            • +
            • The number of 1's in the string is at most k.
            • +
            + +

            Return an integer denoting the number of substrings of s that satisfy the k-constraint.

            + +

             

            +

            Example 1:

            + +
            +

            Input: s = "10101", k = 1

            + +

            Output: 12

            + +

            Explanation:

            + +

            Every substring of s except the substrings "1010", "10101", and "0101" satisfies the k-constraint.

            +
            + +

            Example 2:

            + +
            +

            Input: s = "1010101", k = 2

            + +

            Output: 25

            + +

            Explanation:

            + +

            Every substring of s except the substrings with a length greater than 5 satisfies the k-constraint.

            +
            + +

            Example 3:

            + +
            +

            Input: s = "11111", k = 1

            + +

            Output: 15

            + +

            Explanation:

            + +

            All substrings of s satisfy the k-constraint.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= s.length <= 50
            • +
            • 1 <= k <= s.length
            • +
            • s[i] is either '0' or '1'.
            • +
            + + + +## Solutions + + + +### Solution 1: Sliding Window + +We use two variables $\textit{cnt0}$ and $\textit{cnt1}$ to record the number of $0$s and $1$s in the current window, respectively. We use $\textit{ans}$ to record the number of substrings that satisfy the $k$ constraint, and $l$ to record the left boundary of the window. + +When we move the window to the right, if the number of $0$s and $1$s in the window both exceed $k$, we need to move the window to the left until the number of $0$s and $1$s in the window are both no greater than $k$. At this point, all substrings in the window satisfy the $k$ constraint, and the number of such substrings is $r - l + 1$, where $r$ is the right boundary of the window. We add this count to $\textit{ans}$. + +Finally, we return $\textit{ans}$. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. + + + +#### Python3 + +```python +class Solution: + def countKConstraintSubstrings(self, s: str, k: int) -> int: + cnt0 = cnt1 = 0 + ans = l = 0 + for r, c in enumerate(s): + cnt0 += int(c) ^ 1 + cnt1 += int(c) + while cnt0 > k and cnt1 > k: + cnt0 -= int(s[l]) ^ 1 + cnt1 -= int(s[l]) + l += 1 + ans += r - l + 1 + return ans +``` + +#### Java + +```java +class Solution { + public int countKConstraintSubstrings(String s, int k) { + int cnt0 = 0, cnt1 = 0; + int ans = 0, l = 0; + for (int r = 0; r < s.length(); ++r) { + int x = s.charAt(r) - '0'; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + int y = s.charAt(l++) - '0'; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int countKConstraintSubstrings(string s, int k) { + int cnt0 = 0, cnt1 = 0; + int ans = 0, l = 0; + for (int r = 0; r < s.length(); ++r) { + int x = s[r] - '0'; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + int y = s[l++] - '0'; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; + } +}; +``` + +#### Go + +```go +func countKConstraintSubstrings(s string, k int) (ans int) { + cnt0, cnt1, l := 0, 0, 0 + for r, c := range s { + x := int(c - '0') + cnt0 += x ^ 1 + cnt1 += x + for cnt0 > k && cnt1 > k { + y := int(s[l] - '0') + cnt0 -= y ^ 1 + cnt1 -= y + l++ + } + ans += r - l + 1 + } + return +} +``` + +#### TypeScript + +```ts +function countKConstraintSubstrings(s: string, k: number): number { + let [cnt0, cnt1, ans, l] = [0, 0, 0, 0]; + for (let r = 0; r < s.length; ++r) { + const x = s[r] === '1' ? 1 : 0; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + const y = s[l++] === '1' ? 1 : 0; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.cpp b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.cpp new file mode 100644 index 000000000000..0b90f0c7816b --- /dev/null +++ b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + int countKConstraintSubstrings(string s, int k) { + int cnt0 = 0, cnt1 = 0; + int ans = 0, l = 0; + for (int r = 0; r < s.length(); ++r) { + int x = s[r] - '0'; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + int y = s[l++] - '0'; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; + } +}; diff --git a/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.go b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.go new file mode 100644 index 000000000000..fa3e015156a1 --- /dev/null +++ b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.go @@ -0,0 +1,16 @@ +func countKConstraintSubstrings(s string, k int) (ans int) { + cnt0, cnt1, l := 0, 0, 0 + for r, c := range s { + x := int(c - '0') + cnt0 += x ^ 1 + cnt1 += x + for cnt0 > k && cnt1 > k { + y := int(s[l] - '0') + cnt0 -= y ^ 1 + cnt1 -= y + l++ + } + ans += r - l + 1 + } + return +} diff --git a/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.java b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.java new file mode 100644 index 000000000000..e5a6fe9aef08 --- /dev/null +++ b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.java @@ -0,0 +1,18 @@ +class Solution { + public int countKConstraintSubstrings(String s, int k) { + int cnt0 = 0, cnt1 = 0; + int ans = 0, l = 0; + for (int r = 0; r < s.length(); ++r) { + int x = s.charAt(r) - '0'; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + int y = s.charAt(l++) - '0'; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; + } +} diff --git a/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.py b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.py new file mode 100644 index 000000000000..94dd71f835f6 --- /dev/null +++ b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.py @@ -0,0 +1,13 @@ +class Solution: + def countKConstraintSubstrings(self, s: str, k: int) -> int: + cnt0 = cnt1 = 0 + ans = l = 0 + for r, c in enumerate(s): + cnt0 += int(c) ^ 1 + cnt1 += int(c) + while cnt0 > k and cnt1 > k: + cnt0 -= int(s[l]) ^ 1 + cnt1 -= int(s[l]) + l += 1 + ans += r - l + 1 + return ans diff --git a/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.ts b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.ts new file mode 100644 index 000000000000..b888e706cd96 --- /dev/null +++ b/solution/3200-3299/3258.Count Substrings That Satisfy K-Constraint I/Solution.ts @@ -0,0 +1,15 @@ +function countKConstraintSubstrings(s: string, k: number): number { + let [cnt0, cnt1, ans, l] = [0, 0, 0, 0]; + for (let r = 0; r < s.length; ++r) { + const x = s[r] === '1' ? 1 : 0; + cnt0 += x ^ 1; + cnt1 += x; + while (cnt0 > k && cnt1 > k) { + const y = s[l++] === '1' ? 1 : 0; + cnt0 -= y ^ 1; + cnt1 -= y; + } + ans += r - l + 1; + } + return ans; +} diff --git a/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/README.md b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/README.md new file mode 100644 index 000000000000..f3dd8d9e8023 --- /dev/null +++ b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/README.md @@ -0,0 +1,181 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README.md +tags: + - 数组 + - 动态规划 +--- + + + +# [3259. 超级饮料的最大强化能量](https://leetcode.cn/problems/maximum-energy-boost-from-two-drinks) + +[English Version](/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README_EN.md) + +## 题目描述 + + + +

            来自未来的体育科学家给你两个整数数组 energyDrinkAenergyDrinkB,数组长度都等于 n。这两个数组分别代表 A、B 两种不同能量饮料每小时所能提供的强化能量。

            + +

            你需要每小时饮用一种能量饮料来 最大化 你的总强化能量。然而,如果从一种能量饮料切换到另一种,你需要等待一小时来梳理身体的能量体系(在那个小时里你将不会获得任何强化能量)。

            + +

            返回在接下来的 n 小时内你能获得的 最大 总强化能量。

            + +

            注意 你可以选择从饮用任意一种能量饮料开始。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:energyDrinkA = [1,3,1], energyDrinkB = [3,1,1]

            + +

            输出:5

            + +

            解释:

            + +

            要想获得 5 点强化能量,需要选择只饮用能量饮料 A(或者只饮用 B)。

            +
            + +

            示例 2:

            + +
            +

            输入:energyDrinkA = [4,1,1], energyDrinkB = [1,1,3]

            + +

            输出:7

            + +

            解释:

            + +
              +
            • 第一个小时饮用能量饮料 A。
            • +
            • 切换到能量饮料 B ,在第二个小时无法获得强化能量。
            • +
            • 第三个小时饮用能量饮料 B ,并获得强化能量。
            • +
            +
            + +

             

            + +

            提示:

            + +
              +
            • n == energyDrinkA.length == energyDrinkB.length
            • +
            • 3 <= n <= 105
            • +
            • 1 <= energyDrinkA[i], energyDrinkB[i] <= 105
            • +
            + + + +## 解法 + + + +### 方法一:动态规划 + +我们定义 $f[i][0]$ 表示在第 $i$ 小时选择能量饮料 A 获得的最大强化能量,定义 $f[i][1]$ 表示在第 $i$ 小时选择能量饮料 B 获得的最大强化能量。初始时 $f[0][0] = \textit{energyDrinkA}[0]$, $f[0][1] = \textit{energyDrinkB}[0]$。答案为 $\max(f[n - 1][0], f[n - 1][1])$。 + +对于 $i > 0$,我们有以下状态转移方程: + +$$ +\begin{aligned} +f[i][0] & = \max(f[i - 1][0] + \textit{energyDrinkA}[i], f[i - 1][1]) \\ +f[i][1] & = \max(f[i - 1][1] + \textit{energyDrinkB}[i], f[i - 1][0]) +\end{aligned} +$$ + +最后返回 $\max(f[n - 1][0], f[n - 1][1])$ 即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。 + + + +#### Python3 + +```python +class Solution: + def maxEnergyBoost(self, energyDrinkA: List[int], energyDrinkB: List[int]) -> int: + n = len(energyDrinkA) + f = [[0] * 2 for _ in range(n)] + f[0][0] = energyDrinkA[0] + f[0][1] = energyDrinkB[0] + for i in range(1, n): + f[i][0] = max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]) + f[i][1] = max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]) + return max(f[n - 1]) +``` + +#### Java + +```java +class Solution { + public long maxEnergyBoost(int[] energyDrinkA, int[] energyDrinkB) { + int n = energyDrinkA.length; + long[][] f = new long[n][2]; + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (int i = 1; i < n; ++i) { + f[i][0] = Math.max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = Math.max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return Math.max(f[n - 1][0], f[n - 1][1]); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long maxEnergyBoost(vector& energyDrinkA, vector& energyDrinkB) { + int n = energyDrinkA.size(); + vector> f(n, vector(2)); + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (int i = 1; i < n; ++i) { + f[i][0] = max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return max(f[n - 1][0], f[n - 1][1]); + } +}; +``` + +#### Go + +```go +func maxEnergyBoost(energyDrinkA []int, energyDrinkB []int) int64 { + n := len(energyDrinkA) + f := make([][2]int64, n) + f[0][0] = int64(energyDrinkA[0]) + f[0][1] = int64(energyDrinkB[0]) + for i := 1; i < n; i++ { + f[i][0] = max(f[i-1][0]+int64(energyDrinkA[i]), f[i-1][1]) + f[i][1] = max(f[i-1][1]+int64(energyDrinkB[i]), f[i-1][0]) + } + return max(f[n-1][0], f[n-1][1]) +} +``` + +#### TypeScript + +```ts +function maxEnergyBoost(energyDrinkA: number[], energyDrinkB: number[]): number { + const n = energyDrinkA.length; + const f: number[][] = Array.from({ length: n }, () => [0, 0]); + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (let i = 1; i < n; i++) { + f[i][0] = Math.max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = Math.max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return Math.max(...f[n - 1]!); +} +``` + + + + + + diff --git a/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/README_EN.md b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/README_EN.md new file mode 100644 index 000000000000..1a78c451360a --- /dev/null +++ b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/README_EN.md @@ -0,0 +1,181 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README_EN.md +tags: + - Array + - Dynamic Programming +--- + + + +# [3259. Maximum Energy Boost From Two Drinks](https://leetcode.com/problems/maximum-energy-boost-from-two-drinks) + +[中文文档](/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README.md) + +## Description + + + +

            You are given two integer arrays energyDrinkA and energyDrinkB of the same length n by a futuristic sports scientist. These arrays represent the energy boosts per hour provided by two different energy drinks, A and B, respectively.

            + +

            You want to maximize your total energy boost by drinking one energy drink per hour. However, if you want to switch from consuming one energy drink to the other, you need to wait for one hour to cleanse your system (meaning you won't get any energy boost in that hour).

            + +

            Return the maximum total energy boost you can gain in the next n hours.

            + +

            Note that you can start consuming either of the two energy drinks.

            + +

             

            +

            Example 1:

            + +
            +

            Input: energyDrinkA = [1,3,1], energyDrinkB = [3,1,1]

            + +

            Output: 5

            + +

            Explanation:

            + +

            To gain an energy boost of 5, drink only the energy drink A (or only B).

            +
            + +

            Example 2:

            + +
            +

            Input: energyDrinkA = [4,1,1], energyDrinkB = [1,1,3]

            + +

            Output: 7

            + +

            Explanation:

            + +

            To gain an energy boost of 7:

            + +
              +
            • Drink the energy drink A for the first hour.
            • +
            • Switch to the energy drink B and we lose the energy boost of the second hour.
            • +
            • Gain the energy boost of the drink B in the third hour.
            • +
            +
            + +

             

            +

            Constraints:

            + +
              +
            • n == energyDrinkA.length == energyDrinkB.length
            • +
            • 3 <= n <= 105
            • +
            • 1 <= energyDrinkA[i], energyDrinkB[i] <= 105
            • +
            + + + +## Solutions + + + +### Solution 1: Dynamic Programming + +We define $f[i][0]$ to represent the maximum boost energy obtained by choosing energy drink A at the $i$-th hour, and $f[i][1]$ to represent the maximum boost energy obtained by choosing energy drink B at the $i$-th hour. Initially, $f[0][0] = \textit{energyDrinkA}[0]$, $f[0][1] = \textit{energyDrinkB}[0]$. The answer is $\max(f[n - 1][0], f[n - 1][1])$. + +For $i > 0$, we have the following state transition equations: + +$$ +\begin{aligned} +f[i][0] & = \max(f[i - 1][0] + \textit{energyDrinkA}[i], f[i - 1][1]) \\ +f[i][1] & = \max(f[i - 1][1] + \textit{energyDrinkB}[i], f[i - 1][0]) +\end{aligned} +$$ + +Finally, return $\max(f[n - 1][0], f[n - 1][1])$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array. + + + +#### Python3 + +```python +class Solution: + def maxEnergyBoost(self, energyDrinkA: List[int], energyDrinkB: List[int]) -> int: + n = len(energyDrinkA) + f = [[0] * 2 for _ in range(n)] + f[0][0] = energyDrinkA[0] + f[0][1] = energyDrinkB[0] + for i in range(1, n): + f[i][0] = max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]) + f[i][1] = max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]) + return max(f[n - 1]) +``` + +#### Java + +```java +class Solution { + public long maxEnergyBoost(int[] energyDrinkA, int[] energyDrinkB) { + int n = energyDrinkA.length; + long[][] f = new long[n][2]; + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (int i = 1; i < n; ++i) { + f[i][0] = Math.max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = Math.max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return Math.max(f[n - 1][0], f[n - 1][1]); + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + long long maxEnergyBoost(vector& energyDrinkA, vector& energyDrinkB) { + int n = energyDrinkA.size(); + vector> f(n, vector(2)); + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (int i = 1; i < n; ++i) { + f[i][0] = max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return max(f[n - 1][0], f[n - 1][1]); + } +}; +``` + +#### Go + +```go +func maxEnergyBoost(energyDrinkA []int, energyDrinkB []int) int64 { + n := len(energyDrinkA) + f := make([][2]int64, n) + f[0][0] = int64(energyDrinkA[0]) + f[0][1] = int64(energyDrinkB[0]) + for i := 1; i < n; i++ { + f[i][0] = max(f[i-1][0]+int64(energyDrinkA[i]), f[i-1][1]) + f[i][1] = max(f[i-1][1]+int64(energyDrinkB[i]), f[i-1][0]) + } + return max(f[n-1][0], f[n-1][1]) +} +``` + +#### TypeScript + +```ts +function maxEnergyBoost(energyDrinkA: number[], energyDrinkB: number[]): number { + const n = energyDrinkA.length; + const f: number[][] = Array.from({ length: n }, () => [0, 0]); + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (let i = 1; i < n; i++) { + f[i][0] = Math.max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = Math.max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return Math.max(...f[n - 1]!); +} +``` + + + + + + diff --git a/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.cpp b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.cpp new file mode 100644 index 000000000000..a2ba2fbc70fd --- /dev/null +++ b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.cpp @@ -0,0 +1,14 @@ +class Solution { +public: + long long maxEnergyBoost(vector& energyDrinkA, vector& energyDrinkB) { + int n = energyDrinkA.size(); + vector> f(n, vector(2)); + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (int i = 1; i < n; ++i) { + f[i][0] = max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return max(f[n - 1][0], f[n - 1][1]); + } +}; diff --git a/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.go b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.go new file mode 100644 index 000000000000..f372dd70a1d5 --- /dev/null +++ b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.go @@ -0,0 +1,11 @@ +func maxEnergyBoost(energyDrinkA []int, energyDrinkB []int) int64 { + n := len(energyDrinkA) + f := make([][2]int64, n) + f[0][0] = int64(energyDrinkA[0]) + f[0][1] = int64(energyDrinkB[0]) + for i := 1; i < n; i++ { + f[i][0] = max(f[i-1][0]+int64(energyDrinkA[i]), f[i-1][1]) + f[i][1] = max(f[i-1][1]+int64(energyDrinkB[i]), f[i-1][0]) + } + return max(f[n-1][0], f[n-1][1]) +} diff --git a/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.java b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.java new file mode 100644 index 000000000000..d9de09299032 --- /dev/null +++ b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.java @@ -0,0 +1,13 @@ +class Solution { + public long maxEnergyBoost(int[] energyDrinkA, int[] energyDrinkB) { + int n = energyDrinkA.length; + long[][] f = new long[n][2]; + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (int i = 1; i < n; ++i) { + f[i][0] = Math.max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = Math.max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return Math.max(f[n - 1][0], f[n - 1][1]); + } +} diff --git a/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.py b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.py new file mode 100644 index 000000000000..d79c9da59d15 --- /dev/null +++ b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.py @@ -0,0 +1,10 @@ +class Solution: + def maxEnergyBoost(self, energyDrinkA: List[int], energyDrinkB: List[int]) -> int: + n = len(energyDrinkA) + f = [[0] * 2 for _ in range(n)] + f[0][0] = energyDrinkA[0] + f[0][1] = energyDrinkB[0] + for i in range(1, n): + f[i][0] = max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]) + f[i][1] = max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]) + return max(f[n - 1]) diff --git a/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.ts b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.ts new file mode 100644 index 000000000000..f8b26a4e3d11 --- /dev/null +++ b/solution/3200-3299/3259.Maximum Energy Boost From Two Drinks/Solution.ts @@ -0,0 +1,11 @@ +function maxEnergyBoost(energyDrinkA: number[], energyDrinkB: number[]): number { + const n = energyDrinkA.length; + const f: number[][] = Array.from({ length: n }, () => [0, 0]); + f[0][0] = energyDrinkA[0]; + f[0][1] = energyDrinkB[0]; + for (let i = 1; i < n; i++) { + f[i][0] = Math.max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]); + f[i][1] = Math.max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]); + } + return Math.max(...f[n - 1]!); +} diff --git a/solution/3200-3299/3260.Find the Largest Palindrome Divisible by K/README.md b/solution/3200-3299/3260.Find the Largest Palindrome Divisible by K/README.md new file mode 100644 index 000000000000..7e841a3a1cd0 --- /dev/null +++ b/solution/3200-3299/3260.Find the Largest Palindrome Divisible by K/README.md @@ -0,0 +1,117 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README.md +tags: + - 贪心 + - 数学 + - 字符串 + - 动态规划 + - 数论 +--- + + + +# [3260. 找出最大的 N 位 K 回文数](https://leetcode.cn/problems/find-the-largest-palindrome-divisible-by-k) + +[English Version](/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README_EN.md) + +## 题目描述 + + + +

            给你两个 正整数 nk

            + +

            如果整数 x 满足以下全部条件,则该整数是一个 k 回文数

            + +
              +
            • x 是一个 回文数
            • +
            • x 可以被 k 整除。
            • +
            + +

            以字符串形式返回 最大的  nk 回文数

            + +

            注意,该整数 含前导零。

            + +

             

            + +

            示例 1:

            + +
            +

            输入: n = 3, k = 5

            + +

            输出: "595"

            + +

            解释:

            + +

            595 是最大的 3 位 k 回文数。

            +
            + +

            示例 2:

            + +
            +

            输入: n = 1, k = 4

            + +

            输出: "8"

            + +

            解释:

            + +

            1 位 k 回文数只有 4 和 8。

            +
            + +

            示例 3:

            + +
            +

            输入: n = 5, k = 6

            + +

            输出: "89898"

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= n <= 105
            • +
            • 1 <= k <= 9
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3260.Find the Largest Palindrome Divisible by K/README_EN.md b/solution/3200-3299/3260.Find the Largest Palindrome Divisible by K/README_EN.md new file mode 100644 index 000000000000..c66da0f3ff63 --- /dev/null +++ b/solution/3200-3299/3260.Find the Largest Palindrome Divisible by K/README_EN.md @@ -0,0 +1,115 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README_EN.md +tags: + - Greedy + - Math + - String + - Dynamic Programming + - Number Theory +--- + + + +# [3260. Find the Largest Palindrome Divisible by K](https://leetcode.com/problems/find-the-largest-palindrome-divisible-by-k) + +[中文文档](/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README.md) + +## Description + + + +

            You are given two positive integers n and k.

            + +

            An integer x is called k-palindromic if:

            + +
              +
            • x is a palindrome.
            • +
            • x is divisible by k.
            • +
            + +

            Return the largest integer having n digits (as a string) that is k-palindromic.

            + +

            Note that the integer must not have leading zeros.

            + +

             

            +

            Example 1:

            + +
            +

            Input: n = 3, k = 5

            + +

            Output: "595"

            + +

            Explanation:

            + +

            595 is the largest k-palindromic integer with 3 digits.

            +
            + +

            Example 2:

            + +
            +

            Input: n = 1, k = 4

            + +

            Output: "8"

            + +

            Explanation:

            + +

            4 and 8 are the only k-palindromic integers with 1 digit.

            +
            + +

            Example 3:

            + +
            +

            Input: n = 5, k = 6

            + +

            Output: "89898"

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= n <= 105
            • +
            • 1 <= k <= 9
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3261.Count Substrings That Satisfy K-Constraint II/README.md b/solution/3200-3299/3261.Count Substrings That Satisfy K-Constraint II/README.md new file mode 100644 index 000000000000..395d723ee3f9 --- /dev/null +++ b/solution/3200-3299/3261.Count Substrings That Satisfy K-Constraint II/README.md @@ -0,0 +1,114 @@ +--- +comments: true +difficulty: 困难 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README.md +tags: + - 数组 + - 字符串 + - 二分查找 + - 前缀和 + - 滑动窗口 +--- + + + +# [3261. 统计满足 K 约束的子字符串数量 II](https://leetcode.cn/problems/count-substrings-that-satisfy-k-constraint-ii) + +[English Version](/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README_EN.md) + +## 题目描述 + + + +

            给你一个 二进制 字符串 s 和一个整数 k

            + +

            另给你一个二维整数数组 queries ,其中 queries[i] = [li, ri]

            + +

            如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束

            + +
              +
            • 字符串中 0 的数量最多为 k
            • +
            • 字符串中 1 的数量最多为 k
            • +
            + +

            返回一个整数数组 answer ,其中 answer[i] 表示 s[li..ri] 中满足 k 约束子字符串 的数量。

            + +

             

            + +

            示例 1:

            + +
            +

            输入:s = "0001111", k = 2, queries = [[0,6]]

            + +

            输出:[26]

            + +

            解释:

            + +

            对于查询 [0, 6]s[0..6] = "0001111" 的所有子字符串中,除 s[0..5] = "000111"s[0..6] = "0001111" 外,其余子字符串都满足 k 约束。

            +
            + +

            示例 2:

            + +
            +

            输入:s = "010101", k = 1, queries = [[0,5],[1,4],[2,3]]

            + +

            输出:[15,9,3]

            + +

            解释:

            + +

            s 的所有子字符串中,长度大于 3 的子字符串都不满足 k 约束。

            +
            + +

             

            + +

            提示:

            + +
              +
            • 1 <= s.length <= 105
            • +
            • s[i]'0''1'
            • +
            • 1 <= k <= s.length
            • +
            • 1 <= queries.length <= 105
            • +
            • queries[i] == [li, ri]
            • +
            • 0 <= li <= ri < s.length
            • +
            • 所有查询互不相同
            • +
            + + + +## 解法 + + + +### 方法一 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3261.Count Substrings That Satisfy K-Constraint II/README_EN.md b/solution/3200-3299/3261.Count Substrings That Satisfy K-Constraint II/README_EN.md new file mode 100644 index 000000000000..5e6192606234 --- /dev/null +++ b/solution/3200-3299/3261.Count Substrings That Satisfy K-Constraint II/README_EN.md @@ -0,0 +1,112 @@ +--- +comments: true +difficulty: Hard +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README_EN.md +tags: + - Array + - String + - Binary Search + - Prefix Sum + - Sliding Window +--- + + + +# [3261. Count Substrings That Satisfy K-Constraint II](https://leetcode.com/problems/count-substrings-that-satisfy-k-constraint-ii) + +[中文文档](/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README.md) + +## Description + + + +

            You are given a binary string s and an integer k.

            + +

            You are also given a 2D integer array queries, where queries[i] = [li, ri].

            + +

            A binary string satisfies the k-constraint if either of the following conditions holds:

            + +
              +
            • The number of 0's in the string is at most k.
            • +
            • The number of 1's in the string is at most k.
            • +
            + +

            Return an integer array answer, where answer[i] is the number of substrings of s[li..ri] that satisfy the k-constraint.

            + +

             

            +

            Example 1:

            + +
            +

            Input: s = "0001111", k = 2, queries = [[0,6]]

            + +

            Output: [26]

            + +

            Explanation:

            + +

            For the query [0, 6], all substrings of s[0..6] = "0001111" satisfy the k-constraint except for the substrings s[0..5] = "000111" and s[0..6] = "0001111".

            +
            + +

            Example 2:

            + +
            +

            Input: s = "010101", k = 1, queries = [[0,5],[1,4],[2,3]]

            + +

            Output: [15,9,3]

            + +

            Explanation:

            + +

            The substrings of s with a length greater than 3 do not satisfy the k-constraint.

            +
            + +

             

            +

            Constraints:

            + +
              +
            • 1 <= s.length <= 105
            • +
            • s[i] is either '0' or '1'.
            • +
            • 1 <= k <= s.length
            • +
            • 1 <= queries.length <= 105
            • +
            • queries[i] == [li, ri]
            • +
            • 0 <= li <= ri < s.length
            • +
            • All queries are distinct.
            • +
            + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python + +``` + +#### Java + +```java + +``` + +#### C++ + +```cpp + +``` + +#### Go + +```go + +``` + + + + + + diff --git a/solution/3200-3299/3262.Find Overlapping Shifts/README.md b/solution/3200-3299/3262.Find Overlapping Shifts/README.md new file mode 100644 index 000000000000..76a31ed07041 --- /dev/null +++ b/solution/3200-3299/3262.Find Overlapping Shifts/README.md @@ -0,0 +1,175 @@ +--- +comments: true +difficulty: 中等 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README.md +tags: + - 数据库 +--- + + + +# [3262. 查找重叠的班次 🔒](https://leetcode.cn/problems/find-overlapping-shifts) + +[English Version](/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README_EN.md) + +## 题目描述 + + + +

            表:EmployeeShifts

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| employee_id      | int     |
            +| start_time       | time    |
            +| end_time         | time    |
            ++------------------+---------+
            +(employee_id, start_time) 是此表的唯一主键。
            +这张表包含员工的排班工作,包括特定日期的开始和结束时间。
            +
            + +

            编写一个解决方案来为每个员工计算 重叠排班 的数量。如果一个排班的 end_time 比另一个排班的 start_time 更晚 则认为两个排班重叠。

            + +

            返回结果表以 employee_id 升序 排序。

            + +

            查询结果格式如下所示。

            + +

             

            + +

            示例:

            + +
            +

            输入:

            + +

            EmployeeShifts 表:

            + +
            ++-------------+------------+----------+
            +| employee_id | start_time | end_time |
            ++-------------+------------+----------+
            +| 1           | 08:00:00   | 12:00:00 |
            +| 1           | 11:00:00   | 15:00:00 |
            +| 1           | 14:00:00   | 18:00:00 |
            +| 2           | 09:00:00   | 17:00:00 |
            +| 2           | 16:00:00   | 20:00:00 |
            +| 3           | 10:00:00   | 12:00:00 |
            +| 3           | 13:00:00   | 15:00:00 |
            +| 3           | 16:00:00   | 18:00:00 |
            +| 4           | 08:00:00   | 10:00:00 |
            +| 4           | 09:00:00   | 11:00:00 |
            ++-------------+------------+----------+
            +
            + +

            输出:

            + +
            ++-------------+--------------------+
            +| employee_id | overlapping_shifts |
            ++-------------+--------------------+
            +| 1           | 2                  |
            +| 2           | 1                  |
            +| 4           | 1                  |
            ++-------------+--------------------+
            +
            + +

            解释:

            + +
              +
            • 员工 1 有 3 个排班: +
                +
              • 08:00:00 到 12:00:00
              • +
              • 11:00:00 到 15:00:00
              • +
              • 14:00:00 到 18:00:00
              • +
              + 第一个排班与第二个排班重叠,第二个排班与第三个排班重叠,因此有 2 个重叠排班。
            • +
            • 员工 2 有 2 个排班: +
                +
              • 09:00:00 到 17:00:00
              • +
              • 16:00:00 到 20:00:00
              • +
              + 这些排班彼此重叠,因此有 1 个重叠排班。
            • +
            • 员工 3 有 3 个排班: +
                +
              • 10:00:00 到 12:00:00
              • +
              • 13:00:00 到 15:00:00
              • +
              • 16:00:00 到 18:00:00
              • +
              + 这些排班没有重叠,所以员工 3 不包含在输出中。
            • +
            • 员工 4 有 2 个排班: +
                +
              • 08:00:00 到 10:00:00
              • +
              • 09:00:00 到 11:00:00
              • +
              + 这些排班彼此重叠,因此有 1 个重叠排班。
            • +
            + +

            输出展示了 employee_id 和至少有一个重叠排班的员工的重叠排班的数量,以 employee_id 升序排序。

            +
            + + + +## 解法 + + + +### 方法一:自连接 + 分组计数 + +我们首先使用自连接,将 `EmployeeShifts` 表连接自身。通过连接条件,确保只比较同一个员工的班次,并且检查班次之间是否存在重叠。 + +1. `t1.start_time < t1.start_time`:确保第一个班次的开始时间早于第二个班次的结束时间。 +1. `t1.end_time > t2.start_time`:确保第一个班次的结束时间晚于第二个班次的开始时间。 + +接下来,我们对数据按照 `employee_id` 进行分组,统计每个员工的重叠班次数量。 + +最后,我们筛选出重叠班次数量大于 $0$ 的员工,并按照 `employee_id` 进行升序排序。 + + + +#### MySQL + +```sql +SELECT + t1.employee_id, + COUNT(*) AS overlapping_shifts +FROM + EmployeeShifts t1 + JOIN EmployeeShifts t2 + ON t1.employee_id = t2.employee_id + AND t1.start_time < t2.start_time + AND t1.end_time > t2.start_time +GROUP BY 1 +HAVING overlapping_shifts > 0 +ORDER BY 1; +``` + +#### Pandas + +```python +import pandas as pd + + +def find_overlapping_shifts(employee_shifts: pd.DataFrame) -> pd.DataFrame: + merged_shifts = employee_shifts.merge( + employee_shifts, on="employee_id", suffixes=("_t1", "_t2") + ) + overlapping_shifts = merged_shifts[ + (merged_shifts["start_time_t1"] < merged_shifts["start_time_t2"]) + & (merged_shifts["end_time_t1"] > merged_shifts["start_time_t2"]) + ] + result = ( + overlapping_shifts.groupby("employee_id") + .size() + .reset_index(name="overlapping_shifts") + ) + result = result[result["overlapping_shifts"] > 0] + result = result.sort_values("employee_id").reset_index(drop=True) + return result +``` + + + + + + diff --git a/solution/3200-3299/3262.Find Overlapping Shifts/README_EN.md b/solution/3200-3299/3262.Find Overlapping Shifts/README_EN.md new file mode 100644 index 000000000000..0882d8f8301a --- /dev/null +++ b/solution/3200-3299/3262.Find Overlapping Shifts/README_EN.md @@ -0,0 +1,174 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README_EN.md +tags: + - Database +--- + + + +# [3262. Find Overlapping Shifts 🔒](https://leetcode.com/problems/find-overlapping-shifts) + +[中文文档](/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README.md) + +## Description + + + +

            Table: EmployeeShifts

            + +
            ++------------------+---------+
            +| Column Name      | Type    |
            ++------------------+---------+
            +| employee_id      | int     |
            +| start_time       | time    |
            +| end_time         | time    |
            ++------------------+---------+
            +(employee_id, start_time) is the unique key for this table.
            +This table contains information about the shifts worked by employees, including the start and end times on a specific date.
            +
            + +

            Write a solution to count the number of overlapping shifts for each employee. Two shifts are considered overlapping if one shift’s end_time is later than another shift’s start_time.

            + +

            Return the result table ordered by employee_id in ascending order.

            + +

            The query result format is in the following example.

            + +

             

            +

            Example:

            + +
            +

            Input:

            + +

            EmployeeShifts table:

            + +
            ++-------------+------------+----------+
            +| employee_id | start_time | end_time |
            ++-------------+------------+----------+
            +| 1           | 08:00:00   | 12:00:00 |
            +| 1           | 11:00:00   | 15:00:00 |
            +| 1           | 14:00:00   | 18:00:00 |
            +| 2           | 09:00:00   | 17:00:00 |
            +| 2           | 16:00:00   | 20:00:00 |
            +| 3           | 10:00:00   | 12:00:00 |
            +| 3           | 13:00:00   | 15:00:00 |
            +| 3           | 16:00:00   | 18:00:00 |
            +| 4           | 08:00:00   | 10:00:00 |
            +| 4           | 09:00:00   | 11:00:00 |
            ++-------------+------------+----------+
            +
            + +

            Output:

            + +
            ++-------------+--------------------+
            +| employee_id | overlapping_shifts |
            ++-------------+--------------------+
            +| 1           | 2                  |
            +| 2           | 1                  |
            +| 4           | 1                  |
            ++-------------+--------------------+
            +
            + +

            Explanation:

            + +
              +
            • Employee 1 has 3 shifts: +
                +
              • 08:00:00 to 12:00:00
              • +
              • 11:00:00 to 15:00:00
              • +
              • 14:00:00 to 18:00:00
              • +
              + The first shift overlaps with the second, and the second overlaps with the third, resulting in 2 overlapping shifts.
            • +
            • Employee 2 has 2 shifts: +
                +
              • 09:00:00 to 17:00:00
              • +
              • 16:00:00 to 20:00:00
              • +
              + These shifts overlap with each other, resulting in 1 overlapping shift.
            • +
            • Employee 3 has 3 shifts: +
                +
              • 10:00:00 to 12:00:00
              • +
              • 13:00:00 to 15:00:00
              • +
              • 16:00:00 to 18:00:00
              • +
              + None of these shifts overlap, so Employee 3 is not included in the output.
            • +
            • Employee 4 has 2 shifts: +
                +
              • 08:00:00 to 10:00:00
              • +
              • 09:00:00 to 11:00:00
              • +
              + These shifts overlap with each other, resulting in 1 overlapping shift.
            • +
            + +

            The output shows the employee_id and the count of overlapping shifts for each employee who has at least one overlapping shift, ordered by employee_id in ascending order.

            +
            + + + +## Solutions + + + +### Solution 1: Self-Join + Group Counting + +We first use a self-join to connect the `EmployeeShifts` table to itself. The join condition ensures that we only compare shifts belonging to the same employee and check if there is any overlap between shifts. + +1. `t1.start_time < t2.start_time`: Ensures that the start time of the first shift is earlier than the start time of the second shift. +2. `t1.end_time > t2.start_time`: Ensures that the end time of the first shift is later than the start time of the second shift. + +Next, we group the data by `employee_id` and count the number of overlapping shifts for each employee. + +Finally, we filter out employees with overlapping shift counts greater than $0$ and sort the results in ascending order by `employee_id`. + + + +#### MySQL + +```sql +SELECT + t1.employee_id, + COUNT(*) AS overlapping_shifts +FROM + EmployeeShifts t1 + JOIN EmployeeShifts t2 + ON t1.employee_id = t2.employee_id + AND t1.start_time < t2.start_time + AND t1.end_time > t2.start_time +GROUP BY 1 +HAVING overlapping_shifts > 0 +ORDER BY 1; +``` + +#### Pandas + +```python +import pandas as pd + + +def find_overlapping_shifts(employee_shifts: pd.DataFrame) -> pd.DataFrame: + merged_shifts = employee_shifts.merge( + employee_shifts, on="employee_id", suffixes=("_t1", "_t2") + ) + overlapping_shifts = merged_shifts[ + (merged_shifts["start_time_t1"] < merged_shifts["start_time_t2"]) + & (merged_shifts["end_time_t1"] > merged_shifts["start_time_t2"]) + ] + result = ( + overlapping_shifts.groupby("employee_id") + .size() + .reset_index(name="overlapping_shifts") + ) + result = result[result["overlapping_shifts"] > 0] + result = result.sort_values("employee_id").reset_index(drop=True) + return result +``` + + + + + + diff --git a/solution/3200-3299/3262.Find Overlapping Shifts/Solution.py b/solution/3200-3299/3262.Find Overlapping Shifts/Solution.py new file mode 100644 index 000000000000..374b21f69519 --- /dev/null +++ b/solution/3200-3299/3262.Find Overlapping Shifts/Solution.py @@ -0,0 +1,19 @@ +import pandas as pd + + +def find_overlapping_shifts(employee_shifts: pd.DataFrame) -> pd.DataFrame: + merged_shifts = employee_shifts.merge( + employee_shifts, on="employee_id", suffixes=("_t1", "_t2") + ) + overlapping_shifts = merged_shifts[ + (merged_shifts["start_time_t1"] < merged_shifts["start_time_t2"]) + & (merged_shifts["end_time_t1"] > merged_shifts["start_time_t2"]) + ] + result = ( + overlapping_shifts.groupby("employee_id") + .size() + .reset_index(name="overlapping_shifts") + ) + result = result[result["overlapping_shifts"] > 0] + result = result.sort_values("employee_id").reset_index(drop=True) + return result diff --git a/solution/3200-3299/3262.Find Overlapping Shifts/Solution.sql b/solution/3200-3299/3262.Find Overlapping Shifts/Solution.sql new file mode 100644 index 000000000000..ada0f2f90585 --- /dev/null +++ b/solution/3200-3299/3262.Find Overlapping Shifts/Solution.sql @@ -0,0 +1,12 @@ +SELECT + t1.employee_id, + COUNT(*) AS overlapping_shifts +FROM + EmployeeShifts t1 + JOIN EmployeeShifts t2 + ON t1.employee_id = t2.employee_id + AND t1.start_time < t2.start_time + AND t1.end_time > t2.start_time +GROUP BY 1 +HAVING overlapping_shifts > 0 +ORDER BY 1; diff --git a/solution/3200-3299/3263.Convert Doubly Linked List to Array I/README.md b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/README.md new file mode 100644 index 000000000000..4970e3713dd4 --- /dev/null +++ b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/README.md @@ -0,0 +1,192 @@ +--- +comments: true +difficulty: 简单 +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3263.Convert%20Doubly%20Linked%20List%20to%20Array%20I/README.md +--- + + + +# [3263. Convert Doubly Linked List to Array I 🔒](https://leetcode.cn/problems/convert-doubly-linked-list-to-array-i) + +[English Version](/solution/3200-3299/3263.Convert%20Doubly%20Linked%20List%20to%20Array%20I/README_EN.md) + +## 题目描述 + + + +

            You are given the head of a doubly linked list, which contains nodes that have a next pointer and a previous pointer.

            + +

            Return an integer array which contains the elements of the linked list in order.

            + +

             

            +

            Example 1:

            + +
            +

            Input: head = [1,2,3,4,3,2,1]

            + +

            Output: [1,2,3,4,3,2,1]

            +
            + +

            Example 2:

            + +
            +

            Input: head = [2,2,2,2,2]

            + +

            Output: [2,2,2,2,2]

            +
            + +

            Example 3:

            + +
            +

            Input: head = [3,2,3,2,3,2]

            + +

            Output: [3,2,3,2,3,2]

            +
            + +

             

            +

            Constraints:

            + +
              +
            • The number of nodes in the given list is in the range [1, 50].
            • +
            • 1 <= Node.val <= 50
            • +
            + + + +## 解法 + + + +### 方法一:直接遍历 + +我们可以直接遍历链表,将节点的值依次添加到答案数组 $\textit{ans}$ 中。 + +遍历结束后,返回答案数组 $\textit{ans}$ 即可。 + +时间复杂度 $O(n)$,其中 $n$ 为链表的长度。忽略答案数组的空间消耗,空间复杂度 $O(1)$。 + + + +#### Python3 + +```python +""" +# Definition for a Node. +class Node: + def __init__(self, val, prev=None, next=None): + self.val = val + self.prev = prev + self.next = next +""" + + +class Solution: + def toArray(self, root: "Optional[Node]") -> List[int]: + ans = [] + while root: + ans.append(root.val) + root = root.next + return ans +``` + +#### Java + +```java +/* +// Definition for a Node. +class Node { + public int val; + public Node prev; + public Node next; +}; +*/ + +class Solution { + public int[] toArray(Node head) { + List ans = new ArrayList<>(); + for (; head != null; head = head.next) { + ans.add(head.val); + } + return ans.stream().mapToInt(i -> i).toArray(); + } +} +``` + +#### C++ + +```cpp +/** + * Definition for doubly-linked list. + * class Node { + * int val; + * Node* prev; + * Node* next; + * Node() : val(0), next(nullptr), prev(nullptr) {} + * Node(int x) : val(x), next(nullptr), prev(nullptr) {} + * Node(int x, Node *prev, Node *next) : val(x), next(next), prev(prev) {} + * }; + */ +class Solution { +public: + vector toArray(Node* head) { + vector ans; + for (; head; head = head->next) { + ans.push_back(head->val); + } + return ans; + } +}; +``` + +#### Go + +```go +/** + * Definition for a Node. + * type Node struct { + * Val int + * Next *Node + * Prev *Node + * } + */ + +func toArray(head *Node) (ans []int) { + for ; head != nil; head = head.Next { + ans = append(ans, head.Val) + } + return +} +``` + +#### TypeScript + +```ts +/** + * Definition for _Node. + * class _Node { + * val: number + * prev: _Node | null + * next: _Node | null + * + * constructor(val?: number, prev? : _Node, next? : _Node) { + * this.val = (val===undefined ? 0 : val); + * this.prev = (prev===undefined ? null : prev); + * this.next = (next===undefined ? null : next); + * } + * } + */ + +function toArray(head: _Node | null): number[] { + const ans: number[] = []; + for (; head; head = head.next) { + ans.push(head.val); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3263.Convert Doubly Linked List to Array I/README_EN.md b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/README_EN.md new file mode 100644 index 000000000000..88319b5e7b12 --- /dev/null +++ b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/README_EN.md @@ -0,0 +1,192 @@ +--- +comments: true +difficulty: Easy +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3263.Convert%20Doubly%20Linked%20List%20to%20Array%20I/README_EN.md +--- + + + +# [3263. Convert Doubly Linked List to Array I 🔒](https://leetcode.com/problems/convert-doubly-linked-list-to-array-i) + +[中文文档](/solution/3200-3299/3263.Convert%20Doubly%20Linked%20List%20to%20Array%20I/README.md) + +## Description + + + +

            You are given the head of a doubly linked list, which contains nodes that have a next pointer and a previous pointer.

            + +

            Return an integer array which contains the elements of the linked list in order.

            + +

             

            +

            Example 1:

            + +
            +

            Input: head = [1,2,3,4,3,2,1]

            + +

            Output: [1,2,3,4,3,2,1]

            +
            + +

            Example 2:

            + +
            +

            Input: head = [2,2,2,2,2]

            + +

            Output: [2,2,2,2,2]

            +
            + +

            Example 3:

            + +
            +

            Input: head = [3,2,3,2,3,2]

            + +

            Output: [3,2,3,2,3,2]

            +
            + +

             

            +

            Constraints:

            + +
              +
            • The number of nodes in the given list is in the range [1, 50].
            • +
            • 1 <= Node.val <= 50
            • +
            + + + +## Solutions + + + +### Solution 1: Direct Traversal + +We can directly traverse the linked list, adding the values of the nodes to the answer array $\textit{ans}$ one by one. + +After the traversal is complete, return the answer array $\textit{ans}$. + +The time complexity is $O(n)$, where $n$ is the length of the linked list. Ignoring the space consumption of the answer array, the space complexity is $O(1)$. + + + +#### Python3 + +```python +""" +# Definition for a Node. +class Node: + def __init__(self, val, prev=None, next=None): + self.val = val + self.prev = prev + self.next = next +""" + + +class Solution: + def toArray(self, root: "Optional[Node]") -> List[int]: + ans = [] + while root: + ans.append(root.val) + root = root.next + return ans +``` + +#### Java + +```java +/* +// Definition for a Node. +class Node { + public int val; + public Node prev; + public Node next; +}; +*/ + +class Solution { + public int[] toArray(Node head) { + List ans = new ArrayList<>(); + for (; head != null; head = head.next) { + ans.add(head.val); + } + return ans.stream().mapToInt(i -> i).toArray(); + } +} +``` + +#### C++ + +```cpp +/** + * Definition for doubly-linked list. + * class Node { + * int val; + * Node* prev; + * Node* next; + * Node() : val(0), next(nullptr), prev(nullptr) {} + * Node(int x) : val(x), next(nullptr), prev(nullptr) {} + * Node(int x, Node *prev, Node *next) : val(x), next(next), prev(prev) {} + * }; + */ +class Solution { +public: + vector toArray(Node* head) { + vector ans; + for (; head; head = head->next) { + ans.push_back(head->val); + } + return ans; + } +}; +``` + +#### Go + +```go +/** + * Definition for a Node. + * type Node struct { + * Val int + * Next *Node + * Prev *Node + * } + */ + +func toArray(head *Node) (ans []int) { + for ; head != nil; head = head.Next { + ans = append(ans, head.Val) + } + return +} +``` + +#### TypeScript + +```ts +/** + * Definition for _Node. + * class _Node { + * val: number + * prev: _Node | null + * next: _Node | null + * + * constructor(val?: number, prev? : _Node, next? : _Node) { + * this.val = (val===undefined ? 0 : val); + * this.prev = (prev===undefined ? null : prev); + * this.next = (next===undefined ? null : next); + * } + * } + */ + +function toArray(head: _Node | null): number[] { + const ans: number[] = []; + for (; head; head = head.next) { + ans.push(head.val); + } + return ans; +} +``` + + + + + + diff --git a/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.cpp b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.cpp new file mode 100644 index 000000000000..c02659a356ad --- /dev/null +++ b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.cpp @@ -0,0 +1,21 @@ +/** + * Definition for doubly-linked list. + * class Node { + * int val; + * Node* prev; + * Node* next; + * Node() : val(0), next(nullptr), prev(nullptr) {} + * Node(int x) : val(x), next(nullptr), prev(nullptr) {} + * Node(int x, Node *prev, Node *next) : val(x), next(next), prev(prev) {} + * }; + */ +class Solution { +public: + vector toArray(Node* head) { + vector ans; + for (; head; head = head->next) { + ans.push_back(head->val); + } + return ans; + } +}; diff --git a/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.go b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.go new file mode 100644 index 000000000000..f7bc140b1657 --- /dev/null +++ b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.go @@ -0,0 +1,15 @@ +/** + * Definition for a Node. + * type Node struct { + * Val int + * Next *Node + * Prev *Node + * } + */ + +func toArray(head *Node) (ans []int) { + for ; head != nil; head = head.Next { + ans = append(ans, head.Val) + } + return +} diff --git a/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.java b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.java new file mode 100644 index 000000000000..fef1a77a1e0b --- /dev/null +++ b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.java @@ -0,0 +1,18 @@ +/* +// Definition for a Node. +class Node { + public int val; + public Node prev; + public Node next; +}; +*/ + +class Solution { + public int[] toArray(Node head) { + List ans = new ArrayList<>(); + for (; head != null; head = head.next) { + ans.add(head.val); + } + return ans.stream().mapToInt(i -> i).toArray(); + } +} diff --git a/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.py b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.py new file mode 100644 index 000000000000..f5498238f090 --- /dev/null +++ b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.py @@ -0,0 +1,17 @@ +""" +# Definition for a Node. +class Node: + def __init__(self, val, prev=None, next=None): + self.val = val + self.prev = prev + self.next = next +""" + + +class Solution: + def toArray(self, root: "Optional[Node]") -> List[int]: + ans = [] + while root: + ans.append(root.val) + root = root.next + return ans diff --git a/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.ts b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.ts new file mode 100644 index 000000000000..af9e2027bfeb --- /dev/null +++ b/solution/3200-3299/3263.Convert Doubly Linked List to Array I/Solution.ts @@ -0,0 +1,22 @@ +/** + * Definition for _Node. + * class _Node { + * val: number + * prev: _Node | null + * next: _Node | null + * + * constructor(val?: number, prev? : _Node, next? : _Node) { + * this.val = (val===undefined ? 0 : val); + * this.prev = (prev===undefined ? null : prev); + * this.next = (next===undefined ? null : next); + * } + * } + */ + +function toArray(head: _Node | null): number[] { + const ans: number[] = []; + for (; head; head = head.next) { + ans.push(head.val); + } + return ans; +} diff --git a/solution/CONTEST_README.md b/solution/CONTEST_README.md index b42fec17fde8..ca8a7957c7b8 100644 --- a/solution/CONTEST_README.md +++ b/solution/CONTEST_README.md @@ -26,6 +26,69 @@ comments: true ## 往期竞赛 +#### 第 411 场周赛(2024-08-18 10:30, 90 分钟) 参赛人数 3029 + +- [3258. 统计满足 K 约束的子字符串数量 I](/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README.md) +- [3259. 超级饮料的最大强化能量](/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README.md) +- [3260. 找出最大的 N 位 K 回文数](/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README.md) +- [3261. 统计满足 K 约束的子字符串数量 II](/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README.md) + +#### 第 137 场双周赛(2024-08-17 22:30, 90 分钟) 参赛人数 2198 + +- [3254. 长度为 K 的子数组的能量值 I](/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README.md) +- [3255. 长度为 K 的子数组的能量值 II](/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README.md) +- [3256. 放三个车的价值之和最大 I](/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README.md) +- [3257. 放三个车的价值之和最大 II](/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README.md) + +#### 第 410 场周赛(2024-08-11 10:30, 90 分钟) 参赛人数 2987 + +- [3248. 矩阵中的蛇](/solution/3200-3299/3248.Snake%20in%20Matrix/README.md) +- [3249. 统计好节点的数目](/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README.md) +- [3250. 单调数组对的数目 I](/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README.md) +- [3251. 单调数组对的数目 II](/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README.md) + +#### 第 409 场周赛(2024-08-04 10:30, 90 分钟) 参赛人数 3643 + +- [3242. 设计相邻元素求和服务](/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README.md) +- [3243. 新增道路查询后的最短距离 I](/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README.md) +- [3244. 新增道路查询后的最短距离 II](/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README.md) +- [3245. 交替组 III](/solution/3200-3299/3245.Alternating%20Groups%20III/README.md) + +#### 第 136 场双周赛(2024-08-03 22:30, 90 分钟) 参赛人数 2418 + +- [3238. 求出胜利玩家的数目](/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README.md) +- [3239. 最少翻转次数使二进制矩阵回文 I](/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README.md) +- [3240. 最少翻转次数使二进制矩阵回文 II](/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README.md) +- [3241. 标记所有节点需要的时间](/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README.md) + +#### 第 408 场周赛(2024-07-28 10:30, 90 分钟) 参赛人数 3369 + +- [3232. 判断是否可以赢得数字游戏](/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README.md) +- [3233. 统计不是特殊数字的数字数量](/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README.md) +- [3234. 统计 1 显著的字符串的数量](/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README.md) +- [3235. 判断矩形的两个角落是否可达](/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README.md) + +#### 第 407 场周赛(2024-07-21 10:30, 90 分钟) 参赛人数 3268 + +- [3226. 使两个整数相等的位更改次数](/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README.md) +- [3227. 字符串元音游戏](/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README.md) +- [3228. 将 1 移动到末尾的最大操作次数](/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README.md) +- [3229. 使数组等于目标数组所需的最少操作次数](/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README.md) + +#### 第 135 场双周赛(2024-07-20 22:30, 90 分钟) 参赛人数 2260 + +- [3222. 求出硬币游戏的赢家](/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README.md) +- [3223. 操作后字符串的最短长度](/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README.md) +- [3224. 使差值相等的最少数组改动次数](/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README.md) +- [3225. 网格图操作后的最大分数](/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README.md) + +#### 第 406 场周赛(2024-07-14 10:30, 90 分钟) 参赛人数 3422 + +- [3216. 交换后字典序最小的字符串](/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README.md) +- [3217. 从链表中移除在数组中存在的节点](/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README.md) +- [3218. 切蛋糕的最小总开销 I](/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README.md) +- [3219. 切蛋糕的最小总开销 II](/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README.md) + #### 第 405 场周赛(2024-07-07 10:30, 90 分钟) 参赛人数 3240 - [3210. 找出加密后的字符串](/solution/3200-3299/3210.Find%20the%20Encrypted%20String/README.md) @@ -159,28 +222,28 @@ comments: true - [3116. 单面值组合的第 K 小金额](/solution/3100-3199/3116.Kth%20Smallest%20Amount%20With%20Single%20Denomination%20Combination/README.md) - [3117. 划分数组得到最小的值之和](/solution/3100-3199/3117.Minimum%20Sum%20of%20Values%20by%20Dividing%20Array/README.md) -#### 第 128 场双周赛(2024-04-13 22:30, 90 分钟) 参赛人数 2653 +#### 第 128 场双周赛(2024-04-13 22:30, 90 分钟) 参赛人数 2654 - [3110. 字符串的分数](/solution/3100-3199/3110.Score%20of%20a%20String/README.md) - [3111. 覆盖所有点的最少矩形数目](/solution/3100-3199/3111.Minimum%20Rectangles%20to%20Cover%20Points/README.md) - [3112. 访问消失节点的最少时间](/solution/3100-3199/3112.Minimum%20Time%20to%20Visit%20Disappearing%20Nodes/README.md) - [3113. 边界元素是最大值的子数组数目](/solution/3100-3199/3113.Find%20the%20Number%20of%20Subarrays%20Where%20Boundary%20Elements%20Are%20Maximum/README.md) -#### 第 392 场周赛(2024-04-07 10:30, 90 分钟) 参赛人数 3193 +#### 第 392 场周赛(2024-04-07 10:30, 90 分钟) 参赛人数 3194 - [3105. 最长的严格递增或递减子数组](/solution/3100-3199/3105.Longest%20Strictly%20Increasing%20or%20Strictly%20Decreasing%20Subarray/README.md) - [3106. 满足距离约束且字典序最小的字符串](/solution/3100-3199/3106.Lexicographically%20Smallest%20String%20After%20Operations%20With%20Constraint/README.md) - [3107. 使数组中位数等于 K 的最少操作数](/solution/3100-3199/3107.Minimum%20Operations%20to%20Make%20Median%20of%20Array%20Equal%20to%20K/README.md) - [3108. 带权图里旅途的最小代价](/solution/3100-3199/3108.Minimum%20Cost%20Walk%20in%20Weighted%20Graph/README.md) -#### 第 391 场周赛(2024-03-31 10:30, 90 分钟) 参赛人数 4180 +#### 第 391 场周赛(2024-03-31 10:30, 90 分钟) 参赛人数 4181 - [3099. 哈沙德数](/solution/3000-3099/3099.Harshad%20Number/README.md) - [3100. 换水问题 II](/solution/3100-3199/3100.Water%20Bottles%20II/README.md) - [3101. 交替子数组计数](/solution/3100-3199/3101.Count%20Alternating%20Subarrays/README.md) - [3102. 最小化曼哈顿距离](/solution/3100-3199/3102.Minimize%20Manhattan%20Distances/README.md) -#### 第 127 场双周赛(2024-03-30 22:30, 90 分钟) 参赛人数 2950 +#### 第 127 场双周赛(2024-03-30 22:30, 90 分钟) 参赛人数 2951 - [3095. 或值至少 K 的最短子数组 I](/solution/3000-3099/3095.Shortest%20Subarray%20With%20OR%20at%20Least%20K%20I/README.md) - [3096. 得到更多分数的最少关卡数目](/solution/3000-3099/3096.Minimum%20Levels%20to%20Gain%20More%20Points/README.md) @@ -2854,7 +2917,7 @@ comments: true - [1043. 分隔数组以得到最大和](/solution/1000-1099/1043.Partition%20Array%20for%20Maximum%20Sum/README.md) - [1044. 最长重复子串](/solution/1000-1099/1044.Longest%20Duplicate%20Substring/README.md) -#### 第 135 场周赛(2019-05-05 10:30, 90 分钟) 参赛人数 548 +#### 第 135 场周赛(2019-05-05 10:30, 90 分钟) 参赛人数 549 - [1037. 有效的回旋镖](/solution/1000-1099/1037.Valid%20Boomerang/README.md) - [1038. 从二叉搜索树到更大和树](/solution/1000-1099/1038.Binary%20Search%20Tree%20to%20Greater%20Sum%20Tree/README.md) diff --git a/solution/CONTEST_README_EN.md b/solution/CONTEST_README_EN.md index d89253eaced4..4d933a032a96 100644 --- a/solution/CONTEST_README_EN.md +++ b/solution/CONTEST_README_EN.md @@ -29,6 +29,69 @@ If you want to estimate your score changes after the contest ends, you can visit ## Past Contests +#### Weekly Contest 411 + +- [3258. Count Substrings That Satisfy K-Constraint I](/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README_EN.md) +- [3259. Maximum Energy Boost From Two Drinks](/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README_EN.md) +- [3260. Find the Largest Palindrome Divisible by K](/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README_EN.md) +- [3261. Count Substrings That Satisfy K-Constraint II](/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README_EN.md) + +#### Biweekly Contest 137 + +- [3254. Find the Power of K-Size Subarrays I](/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README_EN.md) +- [3255. Find the Power of K-Size Subarrays II](/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README_EN.md) +- [3256. Maximum Value Sum by Placing Three Rooks I](/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README_EN.md) +- [3257. Maximum Value Sum by Placing Three Rooks II](/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README_EN.md) + +#### Weekly Contest 410 + +- [3248. Snake in Matrix](/solution/3200-3299/3248.Snake%20in%20Matrix/README_EN.md) +- [3249. Count the Number of Good Nodes](/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README_EN.md) +- [3250. Find the Count of Monotonic Pairs I](/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README_EN.md) +- [3251. Find the Count of Monotonic Pairs II](/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README_EN.md) + +#### Weekly Contest 409 + +- [3242. Design Neighbor Sum Service](/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README_EN.md) +- [3243. Shortest Distance After Road Addition Queries I](/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README_EN.md) +- [3244. Shortest Distance After Road Addition Queries II](/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README_EN.md) +- [3245. Alternating Groups III](/solution/3200-3299/3245.Alternating%20Groups%20III/README_EN.md) + +#### Biweekly Contest 136 + +- [3238. Find the Number of Winning Players](/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README_EN.md) +- [3239. Minimum Number of Flips to Make Binary Grid Palindromic I](/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README_EN.md) +- [3240. Minimum Number of Flips to Make Binary Grid Palindromic II](/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README_EN.md) +- [3241. Time Taken to Mark All Nodes](/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README_EN.md) + +#### Weekly Contest 408 + +- [3232. Find if Digit Game Can Be Won](/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README_EN.md) +- [3233. Find the Count of Numbers Which Are Not Special](/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README_EN.md) +- [3234. Count the Number of Substrings With Dominant Ones](/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README_EN.md) +- [3235. Check if the Rectangle Corner Is Reachable](/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README_EN.md) + +#### Weekly Contest 407 + +- [3226. Number of Bit Changes to Make Two Integers Equal](/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README_EN.md) +- [3227. Vowels Game in a String](/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README_EN.md) +- [3228. Maximum Number of Operations to Move Ones to the End](/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README_EN.md) +- [3229. Minimum Operations to Make Array Equal to Target](/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README_EN.md) + +#### Biweekly Contest 135 + +- [3222. Find the Winning Player in Coin Game](/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README_EN.md) +- [3223. Minimum Length of String After Operations](/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README_EN.md) +- [3224. Minimum Array Changes to Make Differences Equal](/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README_EN.md) +- [3225. Maximum Score From Grid Operations](/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README_EN.md) + +#### Weekly Contest 406 + +- [3216. Lexicographically Smallest String After a Swap](/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README_EN.md) +- [3217. Delete Nodes From Linked List Present in Array](/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README_EN.md) +- [3218. Minimum Cost for Cutting Cake I](/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README_EN.md) +- [3219. Minimum Cost for Cutting Cake II](/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README_EN.md) + #### Weekly Contest 405 - [3210. Find the Encrypted String](/solution/3200-3299/3210.Find%20the%20Encrypted%20String/README_EN.md) diff --git a/solution/DATABASE_README.md b/solution/DATABASE_README.md index 9552987e6c05..24636f820ef0 100644 --- a/solution/DATABASE_README.md +++ b/solution/DATABASE_README.md @@ -287,6 +287,12 @@ | 3198 | [查找每个州的城市](/solution/3100-3199/3198.Find%20Cities%20in%20Each%20State/README.md) | `数据库` | 简单 | 🔒 | | 3204 | [按位用户权限分析](/solution/3200-3299/3204.Bitwise%20User%20Permissions%20Analysis/README.md) | `数据库` | 中等 | 🔒 | | 3214 | [同比增长率](/solution/3200-3299/3214.Year%20on%20Year%20Growth%20Rate/README.md) | `数据库` | 困难 | 🔒 | +| 3220 | [奇数和偶数交易](/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README.md) | `数据库` | 中等 | | +| 3230 | [客户购买行为分析](/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README.md) | `数据库` | 中等 | 🔒 | +| 3236 | [首席执行官下属层级](/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README.md) | `数据库` | 困难 | 🔒 | +| 3246 | [英超积分榜排名](/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README.md) | `数据库` | 简单 | 🔒 | +| 3252 | [英超积分榜排名 II](/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README.md) | `数据库` | 中等 | 🔒 | +| 3262 | [查找重叠的班次](/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README.md) | | 中等 | 🔒 | ## 版权 diff --git a/solution/DATABASE_README_EN.md b/solution/DATABASE_README_EN.md index 18d7f63a90c8..efacdc1632f0 100644 --- a/solution/DATABASE_README_EN.md +++ b/solution/DATABASE_README_EN.md @@ -285,6 +285,12 @@ Press Control + F(or Command + F on | 3198 | [Find Cities in Each State](/solution/3100-3199/3198.Find%20Cities%20in%20Each%20State/README_EN.md) | `Database` | Easy | 🔒 | | 3204 | [Bitwise User Permissions Analysis](/solution/3200-3299/3204.Bitwise%20User%20Permissions%20Analysis/README_EN.md) | `Database` | Medium | 🔒 | | 3214 | [Year on Year Growth Rate](/solution/3200-3299/3214.Year%20on%20Year%20Growth%20Rate/README_EN.md) | `Database` | Hard | 🔒 | +| 3220 | [Odd and Even Transactions](/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README_EN.md) | `Database` | Medium | | +| 3230 | [Customer Purchasing Behavior Analysis](/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README_EN.md) | `Database` | Medium | 🔒 | +| 3236 | [CEO Subordinate Hierarchy](/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README_EN.md) | `Database` | Hard | 🔒 | +| 3246 | [Premier League Table Ranking](/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README_EN.md) | `Database` | Easy | 🔒 | +| 3252 | [Premier League Table Ranking II](/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README_EN.md) | `Database` | Medium | 🔒 | +| 3262 | [Find Overlapping Shifts](/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README_EN.md) | | Medium | 🔒 | ## Copyright diff --git a/solution/README.md b/solution/README.md index 9a26e3b72cde..3739034b935a 100644 --- a/solution/README.md +++ b/solution/README.md @@ -240,7 +240,7 @@ | 0227 | [基本计算器 II](/solution/0200-0299/0227.Basic%20Calculator%20II/README.md) | `栈`,`数学`,`字符串` | 中等 | | | 0228 | [汇总区间](/solution/0200-0299/0228.Summary%20Ranges/README.md) | `数组` | 简单 | | | 0229 | [多数元素 II](/solution/0200-0299/0229.Majority%20Element%20II/README.md) | `数组`,`哈希表`,`计数`,`排序` | 中等 | | -| 0230 | [二叉搜索树中第K小的元素](/solution/0200-0299/0230.Kth%20Smallest%20Element%20in%20a%20BST/README.md) | `树`,`深度优先搜索`,`二叉搜索树`,`二叉树` | 中等 | | +| 0230 | [二叉搜索树中第 K 小的元素](/solution/0200-0299/0230.Kth%20Smallest%20Element%20in%20a%20BST/README.md) | `树`,`深度优先搜索`,`二叉搜索树`,`二叉树` | 中等 | | | 0231 | [2 的幂](/solution/0200-0299/0231.Power%20of%20Two/README.md) | `位运算`,`递归`,`数学` | 简单 | | | 0232 | [用栈实现队列](/solution/0200-0299/0232.Implement%20Queue%20using%20Stacks/README.md) | `栈`,`设计`,`队列` | 简单 | | | 0233 | [数字 1 的个数](/solution/0200-0299/0233.Number%20of%20Digit%20One/README.md) | `递归`,`数学`,`动态规划` | 困难 | | @@ -318,7 +318,7 @@ | 0305 | [岛屿数量 II](/solution/0300-0399/0305.Number%20of%20Islands%20II/README.md) | `并查集`,`数组`,`哈希表` | 困难 | 🔒 | | 0306 | [累加数](/solution/0300-0399/0306.Additive%20Number/README.md) | `字符串`,`回溯` | 中等 | | | 0307 | [区域和检索 - 数组可修改](/solution/0300-0399/0307.Range%20Sum%20Query%20-%20Mutable/README.md) | `设计`,`树状数组`,`线段树`,`数组` | 中等 | | -| 0308 | [二维区域和检索 - 可变](/solution/0300-0399/0308.Range%20Sum%20Query%202D%20-%20Mutable/README.md) | `设计`,`树状数组`,`线段树`,`数组`,`矩阵` | 困难 | 🔒 | +| 0308 | [二维区域和检索 - 矩阵可修改](/solution/0300-0399/0308.Range%20Sum%20Query%202D%20-%20Mutable/README.md) | `设计`,`树状数组`,`线段树`,`数组`,`矩阵` | 困难 | 🔒 | | 0309 | [买卖股票的最佳时机含冷冻期](/solution/0300-0399/0309.Best%20Time%20to%20Buy%20and%20Sell%20Stock%20with%20Cooldown/README.md) | `数组`,`动态规划` | 中等 | | | 0310 | [最小高度树](/solution/0300-0399/0310.Minimum%20Height%20Trees/README.md) | `深度优先搜索`,`广度优先搜索`,`图`,`拓扑排序` | 中等 | | | 0311 | [稀疏矩阵的乘法](/solution/0300-0399/0311.Sparse%20Matrix%20Multiplication/README.md) | `数组`,`哈希表`,`矩阵` | 中等 | 🔒 | @@ -598,7 +598,7 @@ | 0585 | [2016年的投资](/solution/0500-0599/0585.Investments%20in%202016/README.md) | `数据库` | 中等 | | | 0586 | [订单最多的客户](/solution/0500-0599/0586.Customer%20Placing%20the%20Largest%20Number%20of%20Orders/README.md) | `数据库` | 简单 | | | 0587 | [安装栅栏](/solution/0500-0599/0587.Erect%20the%20Fence/README.md) | `几何`,`数组`,`数学` | 困难 | | -| 0588 | [设计内存文件系统](/solution/0500-0599/0588.Design%20In-Memory%20File%20System/README.md) | `设计`,`字典树`,`哈希表`,`字符串` | 困难 | 🔒 | +| 0588 | [设计内存文件系统](/solution/0500-0599/0588.Design%20In-Memory%20File%20System/README.md) | `设计`,`字典树`,`哈希表`,`字符串`,`排序` | 困难 | 🔒 | | 0589 | [N 叉树的前序遍历](/solution/0500-0599/0589.N-ary%20Tree%20Preorder%20Traversal/README.md) | `栈`,`树`,`深度优先搜索` | 简单 | | | 0590 | [N 叉树的后序遍历](/solution/0500-0599/0590.N-ary%20Tree%20Postorder%20Traversal/README.md) | `栈`,`树`,`深度优先搜索` | 简单 | | | 0591 | [标签验证器](/solution/0500-0599/0591.Tag%20Validator/README.md) | `栈`,`字符串` | 困难 | | @@ -634,7 +634,7 @@ | 0621 | [任务调度器](/solution/0600-0699/0621.Task%20Scheduler/README.md) | `贪心`,`数组`,`哈希表`,`计数`,`排序`,`堆(优先队列)` | 中等 | | | 0622 | [设计循环队列](/solution/0600-0699/0622.Design%20Circular%20Queue/README.md) | `设计`,`队列`,`数组`,`链表` | 中等 | | | 0623 | [在二叉树中增加一行](/solution/0600-0699/0623.Add%20One%20Row%20to%20Tree/README.md) | `树`,`深度优先搜索`,`广度优先搜索`,`二叉树` | 中等 | | -| 0624 | [数组列表中的最大距离](/solution/0600-0699/0624.Maximum%20Distance%20in%20Arrays/README.md) | `贪心`,`数组` | 中等 | 🔒 | +| 0624 | [数组列表中的最大距离](/solution/0600-0699/0624.Maximum%20Distance%20in%20Arrays/README.md) | `贪心`,`数组` | 中等 | | | 0625 | [最小因式分解](/solution/0600-0699/0625.Minimum%20Factorization/README.md) | `贪心`,`数学` | 中等 | 🔒 | | 0626 | [换座位](/solution/0600-0699/0626.Exchange%20Seats/README.md) | `数据库` | 中等 | | | 0627 | [变更性别](/solution/0600-0699/0627.Swap%20Salary/README.md) | `数据库` | 简单 | | @@ -652,7 +652,7 @@ | 0639 | [解码方法 II](/solution/0600-0699/0639.Decode%20Ways%20II/README.md) | `字符串`,`动态规划` | 困难 | | | 0640 | [求解方程](/solution/0600-0699/0640.Solve%20the%20Equation/README.md) | `数学`,`字符串`,`模拟` | 中等 | | | 0641 | [设计循环双端队列](/solution/0600-0699/0641.Design%20Circular%20Deque/README.md) | `设计`,`队列`,`数组`,`链表` | 中等 | | -| 0642 | [设计搜索自动补全系统](/solution/0600-0699/0642.Design%20Search%20Autocomplete%20System/README.md) | `设计`,`字典树`,`字符串`,`数据流`,`排序`,`堆(优先队列)` | 困难 | 🔒 | +| 0642 | [设计搜索自动补全系统](/solution/0600-0699/0642.Design%20Search%20Autocomplete%20System/README.md) | `深度优先搜索`,`设计`,`字典树`,`字符串`,`数据流`,`排序`,`堆(优先队列)` | 困难 | 🔒 | | 0643 | [子数组最大平均数 I](/solution/0600-0699/0643.Maximum%20Average%20Subarray%20I/README.md) | `数组`,`滑动窗口` | 简单 | | | 0644 | [子数组最大平均数 II](/solution/0600-0699/0644.Maximum%20Average%20Subarray%20II/README.md) | `数组`,`二分查找`,`前缀和` | 困难 | 🔒 | | 0645 | [错误的集合](/solution/0600-0699/0645.Set%20Mismatch/README.md) | `位运算`,`数组`,`哈希表`,`排序` | 简单 | | @@ -843,7 +843,7 @@ | 0830 | [较大分组的位置](/solution/0800-0899/0830.Positions%20of%20Large%20Groups/README.md) | `字符串` | 简单 | 第 83 场周赛 | | 0831 | [隐藏个人信息](/solution/0800-0899/0831.Masking%20Personal%20Information/README.md) | `字符串` | 中等 | 第 83 场周赛 | | 0832 | [翻转图像](/solution/0800-0899/0832.Flipping%20an%20Image/README.md) | `位运算`,`数组`,`双指针`,`矩阵`,`模拟` | 简单 | 第 84 场周赛 | -| 0833 | [字符串中的查找与替换](/solution/0800-0899/0833.Find%20And%20Replace%20in%20String/README.md) | `数组`,`字符串`,`排序` | 中等 | 第 84 场周赛 | +| 0833 | [字符串中的查找与替换](/solution/0800-0899/0833.Find%20And%20Replace%20in%20String/README.md) | `数组`,`哈希表`,`字符串`,`排序` | 中等 | 第 84 场周赛 | | 0834 | [树中距离之和](/solution/0800-0899/0834.Sum%20of%20Distances%20in%20Tree/README.md) | `树`,`深度优先搜索`,`图`,`动态规划` | 困难 | 第 84 场周赛 | | 0835 | [图像重叠](/solution/0800-0899/0835.Image%20Overlap/README.md) | `数组`,`矩阵` | 中等 | 第 84 场周赛 | | 0836 | [矩形重叠](/solution/0800-0899/0836.Rectangle%20Overlap/README.md) | `几何`,`数学` | 简单 | 第 85 场周赛 | @@ -1405,7 +1405,7 @@ | 1392 | [最长快乐前缀](/solution/1300-1399/1392.Longest%20Happy%20Prefix/README.md) | `字符串`,`字符串匹配`,`哈希函数`,`滚动哈希` | 困难 | 第 181 场周赛 | | 1393 | [股票的资本损益](/solution/1300-1399/1393.Capital%20GainLoss/README.md) | `数据库` | 中等 | | | 1394 | [找出数组中的幸运数](/solution/1300-1399/1394.Find%20Lucky%20Integer%20in%20an%20Array/README.md) | `数组`,`哈希表`,`计数` | 简单 | 第 182 场周赛 | -| 1395 | [统计作战单位数](/solution/1300-1399/1395.Count%20Number%20of%20Teams/README.md) | `树状数组`,`数组`,`动态规划` | 中等 | 第 182 场周赛 | +| 1395 | [统计作战单位数](/solution/1300-1399/1395.Count%20Number%20of%20Teams/README.md) | `树状数组`,`线段树`,`数组`,`动态规划` | 中等 | 第 182 场周赛 | | 1396 | [设计地铁系统](/solution/1300-1399/1396.Design%20Underground%20System/README.md) | `设计`,`哈希表`,`字符串` | 中等 | 第 182 场周赛 | | 1397 | [找到所有好字符串](/solution/1300-1399/1397.Find%20All%20Good%20Strings/README.md) | `字符串`,`动态规划`,`字符串匹配` | 困难 | 第 182 场周赛 | | 1398 | [购买了产品 A 和产品 B 却没有购买产品 C 的顾客](/solution/1300-1399/1398.Customers%20Who%20Bought%20Products%20A%20and%20B%20but%20Not%20C/README.md) | `数据库` | 中等 | 🔒 | @@ -1510,7 +1510,7 @@ | 1497 | [检查数组对是否可以被 k 整除](/solution/1400-1499/1497.Check%20If%20Array%20Pairs%20Are%20Divisible%20by%20k/README.md) | `数组`,`哈希表`,`计数` | 中等 | 第 195 场周赛 | | 1498 | [满足条件的子序列数目](/solution/1400-1499/1498.Number%20of%20Subsequences%20That%20Satisfy%20the%20Given%20Sum%20Condition/README.md) | `数组`,`双指针`,`二分查找`,`排序` | 中等 | 第 195 场周赛 | | 1499 | [满足不等式的最大值](/solution/1400-1499/1499.Max%20Value%20of%20Equation/README.md) | `队列`,`数组`,`滑动窗口`,`单调队列`,`堆(优先队列)` | 困难 | 第 195 场周赛 | -| 1500 | [设计文件分享系统](/solution/1500-1599/1500.Design%20a%20File%20Sharing%20System/README.md) | `设计`,`哈希表`,`数据流`,`堆(优先队列)` | 中等 | 🔒 | +| 1500 | [设计文件分享系统](/solution/1500-1599/1500.Design%20a%20File%20Sharing%20System/README.md) | `设计`,`哈希表`,`数据流`,`排序`,`堆(优先队列)` | 中等 | 🔒 | | 1501 | [可以放心投资的国家](/solution/1500-1599/1501.Countries%20You%20Can%20Safely%20Invest%20In/README.md) | `数据库` | 中等 | 🔒 | | 1502 | [判断能否形成等差数列](/solution/1500-1599/1502.Can%20Make%20Arithmetic%20Progression%20From%20Sequence/README.md) | `数组`,`排序` | 简单 | 第 196 场周赛 | | 1503 | [所有蚂蚁掉下来前的最后一刻](/solution/1500-1599/1503.Last%20Moment%20Before%20All%20Ants%20Fall%20Out%20of%20a%20Plank/README.md) | `脑筋急转弯`,`数组`,`模拟` | 中等 | 第 196 场周赛 | @@ -1798,7 +1798,7 @@ | 1785 | [构成特定和需要添加的最少元素](/solution/1700-1799/1785.Minimum%20Elements%20to%20Add%20to%20Form%20a%20Given%20Sum/README.md) | `贪心`,`数组` | 中等 | 第 231 场周赛 | | 1786 | [从第一个节点出发到最后一个节点的受限路径数](/solution/1700-1799/1786.Number%20of%20Restricted%20Paths%20From%20First%20to%20Last%20Node/README.md) | `图`,`拓扑排序`,`动态规划`,`最短路`,`堆(优先队列)` | 中等 | 第 231 场周赛 | | 1787 | [使所有区间的异或结果为零](/solution/1700-1799/1787.Make%20the%20XOR%20of%20All%20Segments%20Equal%20to%20Zero/README.md) | `位运算`,`数组`,`动态规划` | 困难 | 第 231 场周赛 | -| 1788 | [最大化花园的美观度](/solution/1700-1799/1788.Maximize%20the%20Beauty%20of%20the%20Garden/README.md) | `贪心`,`数组`,`前缀和` | 困难 | 🔒 | +| 1788 | [最大化花园的美观度](/solution/1700-1799/1788.Maximize%20the%20Beauty%20of%20the%20Garden/README.md) | `贪心`,`数组`,`哈希表`,`前缀和` | 困难 | 🔒 | | 1789 | [员工的直属部门](/solution/1700-1799/1789.Primary%20Department%20for%20Each%20Employee/README.md) | `数据库` | 简单 | | | 1790 | [仅执行一次字符串交换能否使两个字符串相等](/solution/1700-1799/1790.Check%20if%20One%20String%20Swap%20Can%20Make%20Strings%20Equal/README.md) | `哈希表`,`字符串`,`计数` | 简单 | 第 232 场周赛 | | 1791 | [找出星型图的中心节点](/solution/1700-1799/1791.Find%20Center%20of%20Star%20Graph/README.md) | `图` | 简单 | 第 232 场周赛 | @@ -1830,7 +1830,7 @@ | 1817 | [查找用户活跃分钟数](/solution/1800-1899/1817.Finding%20the%20Users%20Active%20Minutes/README.md) | `数组`,`哈希表` | 中等 | 第 235 场周赛 | | 1818 | [绝对差值和](/solution/1800-1899/1818.Minimum%20Absolute%20Sum%20Difference/README.md) | `数组`,`二分查找`,`有序集合`,`排序` | 中等 | 第 235 场周赛 | | 1819 | [序列中不同最大公约数的数目](/solution/1800-1899/1819.Number%20of%20Different%20Subsequences%20GCDs/README.md) | `数组`,`数学`,`计数`,`数论` | 困难 | 第 235 场周赛 | -| 1820 | [最多邀请的个数](/solution/1800-1899/1820.Maximum%20Number%20of%20Accepted%20Invitations/README.md) | `数组`,`回溯`,`矩阵` | 中等 | 🔒 | +| 1820 | [最多邀请的个数](/solution/1800-1899/1820.Maximum%20Number%20of%20Accepted%20Invitations/README.md) | `深度优先搜索`,`图`,`数组`,`矩阵` | 中等 | 🔒 | | 1821 | [寻找今年具有正收入的客户](/solution/1800-1899/1821.Find%20Customers%20With%20Positive%20Revenue%20this%20Year/README.md) | `数据库` | 简单 | 🔒 | | 1822 | [数组元素积的符号](/solution/1800-1899/1822.Sign%20of%20the%20Product%20of%20an%20Array/README.md) | `数组`,`数学` | 简单 | 第 236 场周赛 | | 1823 | [找出游戏的获胜者](/solution/1800-1899/1823.Find%20the%20Winner%20of%20the%20Circular%20Game/README.md) | `递归`,`队列`,`数组`,`数学`,`模拟` | 中等 | 第 236 场周赛 | @@ -1912,7 +1912,7 @@ | 1899 | [合并若干三元组以形成目标三元组](/solution/1800-1899/1899.Merge%20Triplets%20to%20Form%20Target%20Triplet/README.md) | `贪心`,`数组` | 中等 | 第 245 场周赛 | | 1900 | [最佳运动员的比拼回合](/solution/1900-1999/1900.The%20Earliest%20and%20Latest%20Rounds%20Where%20Players%20Compete/README.md) | `记忆化搜索`,`动态规划` | 困难 | 第 245 场周赛 | | 1901 | [寻找峰值 II](/solution/1900-1999/1901.Find%20a%20Peak%20Element%20II/README.md) | `数组`,`二分查找`,`矩阵` | 中等 | | -| 1902 | [给定二叉搜索树的插入顺序求深度](/solution/1900-1999/1902.Depth%20of%20BST%20Given%20Insertion%20Order/README.md) | `树`,`二叉搜索树`,`二叉树`,`有序集合` | 中等 | 🔒 | +| 1902 | [给定二叉搜索树的插入顺序求深度](/solution/1900-1999/1902.Depth%20of%20BST%20Given%20Insertion%20Order/README.md) | `树`,`二叉搜索树`,`数组`,`二叉树`,`有序集合` | 中等 | 🔒 | | 1903 | [字符串中的最大奇数](/solution/1900-1999/1903.Largest%20Odd%20Number%20in%20String/README.md) | `贪心`,`数学`,`字符串` | 简单 | 第 246 场周赛 | | 1904 | [你完成的完整对局数](/solution/1900-1999/1904.The%20Number%20of%20Full%20Rounds%20You%20Have%20Played/README.md) | `数学`,`字符串` | 中等 | 第 246 场周赛 | | 1905 | [统计子岛屿](/solution/1900-1999/1905.Count%20Sub%20Islands/README.md) | `深度优先搜索`,`广度优先搜索`,`并查集`,`数组`,`矩阵` | 中等 | 第 246 场周赛 | @@ -1947,8 +1947,8 @@ | 1934 | [确认率](/solution/1900-1999/1934.Confirmation%20Rate/README.md) | `数据库` | 中等 | | | 1935 | [可以输入的最大单词数](/solution/1900-1999/1935.Maximum%20Number%20of%20Words%20You%20Can%20Type/README.md) | `哈希表`,`字符串` | 简单 | 第 250 场周赛 | | 1936 | [新增的最少台阶数](/solution/1900-1999/1936.Add%20Minimum%20Number%20of%20Rungs/README.md) | `贪心`,`数组` | 中等 | 第 250 场周赛 | -| 1937 | [扣分后的最大得分](/solution/1900-1999/1937.Maximum%20Number%20of%20Points%20with%20Cost/README.md) | `数组`,`动态规划` | 中等 | 第 250 场周赛 | -| 1938 | [查询最大基因差](/solution/1900-1999/1938.Maximum%20Genetic%20Difference%20Query/README.md) | `位运算`,`字典树`,`数组` | 困难 | 第 250 场周赛 | +| 1937 | [扣分后的最大得分](/solution/1900-1999/1937.Maximum%20Number%20of%20Points%20with%20Cost/README.md) | `数组`,`动态规划`,`矩阵` | 中等 | 第 250 场周赛 | +| 1938 | [查询最大基因差](/solution/1900-1999/1938.Maximum%20Genetic%20Difference%20Query/README.md) | `位运算`,`深度优先搜索`,`字典树`,`数组`,`哈希表` | 困难 | 第 250 场周赛 | | 1939 | [主动请求确认消息的用户](/solution/1900-1999/1939.Users%20That%20Actively%20Request%20Confirmation%20Messages/README.md) | `数据库` | 简单 | 🔒 | | 1940 | [排序数组之间的最长公共子序列](/solution/1900-1999/1940.Longest%20Common%20Subsequence%20Between%20Sorted%20Arrays/README.md) | `数组`,`哈希表`,`计数` | 中等 | 🔒 | | 1941 | [检查是否所有字符出现次数相同](/solution/1900-1999/1941.Check%20if%20All%20Characters%20Have%20Equal%20Number%20of%20Occurrences/README.md) | `哈希表`,`字符串`,`计数` | 简单 | 第 57 场双周赛 | @@ -2132,7 +2132,7 @@ | 2119 | [反转两次的数字](/solution/2100-2199/2119.A%20Number%20After%20a%20Double%20Reversal/README.md) | `数学` | 简单 | 第 273 场周赛 | | 2120 | [执行所有后缀指令](/solution/2100-2199/2120.Execution%20of%20All%20Suffix%20Instructions%20Staying%20in%20a%20Grid/README.md) | `字符串`,`模拟` | 中等 | 第 273 场周赛 | | 2121 | [相同元素的间隔之和](/solution/2100-2199/2121.Intervals%20Between%20Identical%20Elements/README.md) | `数组`,`哈希表`,`前缀和` | 中等 | 第 273 场周赛 | -| 2122 | [还原原数组](/solution/2100-2199/2122.Recover%20the%20Original%20Array/README.md) | `数组`,`哈希表`,`枚举`,`排序` | 困难 | 第 273 场周赛 | +| 2122 | [还原原数组](/solution/2100-2199/2122.Recover%20the%20Original%20Array/README.md) | `数组`,`哈希表`,`双指针`,`枚举`,`排序` | 困难 | 第 273 场周赛 | | 2123 | [使矩阵中的 1 互不相邻的最小操作数](/solution/2100-2199/2123.Minimum%20Operations%20to%20Remove%20Adjacent%20Ones%20in%20Matrix/README.md) | `图`,`数组`,`矩阵` | 困难 | 🔒 | | 2124 | [检查是否所有 A 都在 B 之前](/solution/2100-2199/2124.Check%20if%20All%20A%27s%20Appears%20Before%20All%20B%27s/README.md) | `字符串` | 简单 | 第 274 场周赛 | | 2125 | [银行中的激光束数量](/solution/2100-2199/2125.Number%20of%20Laser%20Beams%20in%20a%20Bank/README.md) | `数组`,`数学`,`字符串`,`矩阵` | 中等 | 第 274 场周赛 | @@ -2394,7 +2394,7 @@ | 2381 | [字母移位 II](/solution/2300-2399/2381.Shifting%20Letters%20II/README.md) | `数组`,`字符串`,`前缀和` | 中等 | 第 85 场双周赛 | | 2382 | [删除操作后的最大子段和](/solution/2300-2399/2382.Maximum%20Segment%20Sum%20After%20Removals/README.md) | `并查集`,`数组`,`有序集合`,`前缀和` | 困难 | 第 85 场双周赛 | | 2383 | [赢得比赛需要的最少训练时长](/solution/2300-2399/2383.Minimum%20Hours%20of%20Training%20to%20Win%20a%20Competition/README.md) | `贪心`,`数组` | 简单 | 第 307 场周赛 | -| 2384 | [最大回文数字](/solution/2300-2399/2384.Largest%20Palindromic%20Number/README.md) | `贪心`,`哈希表`,`字符串` | 中等 | 第 307 场周赛 | +| 2384 | [最大回文数字](/solution/2300-2399/2384.Largest%20Palindromic%20Number/README.md) | `贪心`,`哈希表`,`字符串`,`计数` | 中等 | 第 307 场周赛 | | 2385 | [感染二叉树需要的总时间](/solution/2300-2399/2385.Amount%20of%20Time%20for%20Binary%20Tree%20to%20Be%20Infected/README.md) | `树`,`深度优先搜索`,`广度优先搜索`,`哈希表`,`二叉树` | 中等 | 第 307 场周赛 | | 2386 | [找出数组的第 K 大和](/solution/2300-2399/2386.Find%20the%20K-Sum%20of%20an%20Array/README.md) | `数组`,`排序`,`堆(优先队列)` | 困难 | 第 307 场周赛 | | 2387 | [行排序矩阵的中位数](/solution/2300-2399/2387.Median%20of%20a%20Row%20Wise%20Sorted%20Matrix/README.md) | `数组`,`二分查找`,`矩阵` | 中等 | 🔒 | @@ -2591,7 +2591,7 @@ | 2578 | [最小和分割](/solution/2500-2599/2578.Split%20With%20Minimum%20Sum/README.md) | `贪心`,`数学`,`排序` | 简单 | 第 99 场双周赛 | | 2579 | [统计染色格子数](/solution/2500-2599/2579.Count%20Total%20Number%20of%20Colored%20Cells/README.md) | `数学` | 中等 | 第 99 场双周赛 | | 2580 | [统计将重叠区间合并成组的方案数](/solution/2500-2599/2580.Count%20Ways%20to%20Group%20Overlapping%20Ranges/README.md) | `数组`,`排序` | 中等 | 第 99 场双周赛 | -| 2581 | [统计可能的树根数目](/solution/2500-2599/2581.Count%20Number%20of%20Possible%20Root%20Nodes/README.md) | `树`,`深度优先搜索`,`哈希表`,`动态规划` | 困难 | 第 99 场双周赛 | +| 2581 | [统计可能的树根数目](/solution/2500-2599/2581.Count%20Number%20of%20Possible%20Root%20Nodes/README.md) | `树`,`深度优先搜索`,`数组`,`哈希表`,`动态规划` | 困难 | 第 99 场双周赛 | | 2582 | [递枕头](/solution/2500-2599/2582.Pass%20the%20Pillow/README.md) | `数学`,`模拟` | 简单 | 第 335 场周赛 | | 2583 | [二叉树中的第 K 大层和](/solution/2500-2599/2583.Kth%20Largest%20Sum%20in%20a%20Binary%20Tree/README.md) | `树`,`广度优先搜索`,`二叉树`,`排序` | 中等 | 第 335 场周赛 | | 2584 | [分割数组使乘积互质](/solution/2500-2599/2584.Split%20the%20Array%20to%20Make%20Coprime%20Products/README.md) | `数组`,`哈希表`,`数学`,`数论` | 困难 | 第 335 场周赛 | @@ -2607,7 +2607,7 @@ | 2594 | [修车的最少时间](/solution/2500-2599/2594.Minimum%20Time%20to%20Repair%20Cars/README.md) | `数组`,`二分查找` | 中等 | 第 100 场双周赛 | | 2595 | [奇偶位数](/solution/2500-2599/2595.Number%20of%20Even%20and%20Odd%20Bits/README.md) | `位运算` | 简单 | 第 337 场周赛 | | 2596 | [检查骑士巡视方案](/solution/2500-2599/2596.Check%20Knight%20Tour%20Configuration/README.md) | `深度优先搜索`,`广度优先搜索`,`数组`,`矩阵`,`模拟` | 中等 | 第 337 场周赛 | -| 2597 | [美丽子集的数目](/solution/2500-2599/2597.The%20Number%20of%20Beautiful%20Subsets/README.md) | `数组`,`动态规划`,`回溯`,`排序` | 中等 | 第 337 场周赛 | +| 2597 | [美丽子集的数目](/solution/2500-2599/2597.The%20Number%20of%20Beautiful%20Subsets/README.md) | `数组`,`哈希表`,`数学`,`动态规划`,`回溯`,`组合数学`,`排序` | 中等 | 第 337 场周赛 | | 2598 | [执行操作后的最大 MEX](/solution/2500-2599/2598.Smallest%20Missing%20Non-negative%20Integer%20After%20Operations/README.md) | `贪心`,`数组`,`哈希表`,`数学` | 中等 | 第 337 场周赛 | | 2599 | [使前缀和数组非负](/solution/2500-2599/2599.Make%20the%20Prefix%20Sum%20Non-negative/README.md) | `贪心`,`数组`,`堆(优先队列)` | 中等 | 🔒 | | 2600 | [K 件物品的最大和](/solution/2600-2699/2600.K%20Items%20With%20the%20Maximum%20Sum/README.md) | `贪心`,`数学` | 简单 | 第 338 场周赛 | @@ -2648,7 +2648,7 @@ | 2635 | [转换数组中的每个元素](/solution/2600-2699/2635.Apply%20Transform%20Over%20Each%20Element%20in%20Array/README.md) | | 简单 | | | 2636 | [Promise 对象池](/solution/2600-2699/2636.Promise%20Pool/README.md) | | 中等 | 🔒 | | 2637 | [有时间限制的 Promise 对象](/solution/2600-2699/2637.Promise%20Time%20Limit/README.md) | | 中等 | | -| 2638 | [统计 K-Free 子集的总数](/solution/2600-2699/2638.Count%20the%20Number%20of%20K-Free%20Subsets/README.md) | `数组`,`动态规划`,`排序` | 中等 | 🔒 | +| 2638 | [统计 K-Free 子集的总数](/solution/2600-2699/2638.Count%20the%20Number%20of%20K-Free%20Subsets/README.md) | `数组`,`数学`,`动态规划`,`组合数学`,`排序` | 中等 | 🔒 | | 2639 | [查询网格图中每一列的宽度](/solution/2600-2699/2639.Find%20the%20Width%20of%20Columns%20of%20a%20Grid/README.md) | `数组`,`矩阵` | 简单 | 第 102 场双周赛 | | 2640 | [一个数组所有前缀的分数](/solution/2600-2699/2640.Find%20the%20Score%20of%20All%20Prefixes%20of%20an%20Array/README.md) | `数组`,`前缀和` | 中等 | 第 102 场双周赛 | | 2641 | [二叉树的堂兄弟节点 II](/solution/2600-2699/2641.Cousins%20in%20Binary%20Tree%20II/README.md) | `树`,`深度优先搜索`,`广度优先搜索`,`哈希表`,`二叉树` | 中等 | 第 102 场双周赛 | @@ -2873,7 +2873,7 @@ | 2860 | [让所有学生保持开心的分组方法数](/solution/2800-2899/2860.Happy%20Students/README.md) | `数组`,`枚举`,`排序` | 中等 | 第 363 场周赛 | | 2861 | [最大合金数](/solution/2800-2899/2861.Maximum%20Number%20of%20Alloys/README.md) | `数组`,`二分查找` | 中等 | 第 363 场周赛 | | 2862 | [完全子集的最大元素和](/solution/2800-2899/2862.Maximum%20Element-Sum%20of%20a%20Complete%20Subset%20of%20Indices/README.md) | `数组`,`数学`,`数论` | 困难 | 第 363 场周赛 | -| 2863 | [最长半递减数组](/solution/2800-2899/2863.Maximum%20Length%20of%20Semi-Decreasing%20Subarrays/README.md) | `数组`,`哈希表`,`排序` | 中等 | 🔒 | +| 2863 | [最长半递减数组](/solution/2800-2899/2863.Maximum%20Length%20of%20Semi-Decreasing%20Subarrays/README.md) | `栈`,`数组`,`排序`,`单调栈` | 中等 | 🔒 | | 2864 | [最大二进制奇数](/solution/2800-2899/2864.Maximum%20Odd%20Binary%20Number/README.md) | `贪心`,`数学`,`字符串` | 简单 | 第 364 场周赛 | | 2865 | [美丽塔 I](/solution/2800-2899/2865.Beautiful%20Towers%20I/README.md) | `栈`,`数组`,`单调栈` | 中等 | 第 364 场周赛 | | 2866 | [美丽塔 II](/solution/2800-2899/2866.Beautiful%20Towers%20II/README.md) | `栈`,`数组`,`单调栈` | 中等 | 第 364 场周赛 | @@ -3002,7 +3002,7 @@ | 2989 | [班级表现](/solution/2900-2999/2989.Class%20Performance/README.md) | `数据库` | 中等 | 🔒 | | 2990 | [贷款类型](/solution/2900-2999/2990.Loan%20Types/README.md) | `数据库` | 简单 | 🔒 | | 2991 | [最好的三家酒庄](/solution/2900-2999/2991.Top%20Three%20Wineries/README.md) | `数据库` | 困难 | 🔒 | -| 2992 | [自整除排列的数量](/solution/2900-2999/2992.Number%20of%20Self-Divisible%20Permutations/README.md) | `位运算`,`递归`,`数组`,`动态规划`,`状态压缩` | 中等 | 🔒 | +| 2992 | [自整除排列的数量](/solution/2900-2999/2992.Number%20of%20Self-Divisible%20Permutations/README.md) | `位运算`,`数组`,`动态规划`,`回溯`,`状态压缩` | 中等 | 🔒 | | 2993 | [发生在周五的交易 I](/solution/2900-2999/2993.Friday%20Purchases%20I/README.md) | `数据库` | 中等 | 🔒 | | 2994 | [发生在周五的交易 II](/solution/2900-2999/2994.Friday%20Purchases%20II/README.md) | `数据库` | 困难 | 🔒 | | 2995 | [观众变主播](/solution/2900-2999/2995.Viewers%20Turned%20Streamers/README.md) | `数据库` | 困难 | 🔒 | @@ -3184,7 +3184,7 @@ | 3171 | [找到按位或最接近 K 的子数组](/solution/3100-3199/3171.Find%20Subarray%20With%20Bitwise%20OR%20Closest%20to%20K/README.md) | `位运算`,`线段树`,`数组`,`二分查找` | 困难 | 第 400 场周赛 | | 3172 | [第二天验证](/solution/3100-3199/3172.Second%20Day%20Verification/README.md) | `数据库` | 简单 | 🔒 | | 3173 | [相邻元素的按位或](/solution/3100-3199/3173.Bitwise%20OR%20of%20Adjacent%20Elements/README.md) | `位运算`,`数组` | 简单 | 🔒 | -| 3174 | [清除数字](/solution/3100-3199/3174.Clear%20Digits/README.md) | `哈希表`,`字符串`,`模拟` | 简单 | 第 132 场双周赛 | +| 3174 | [清除数字](/solution/3100-3199/3174.Clear%20Digits/README.md) | `栈`,`字符串`,`模拟` | 简单 | 第 132 场双周赛 | | 3175 | [找到连续赢 K 场比赛的第一位玩家](/solution/3100-3199/3175.Find%20The%20First%20Player%20to%20win%20K%20Games%20in%20a%20Row/README.md) | `数组`,`模拟` | 中等 | 第 132 场双周赛 | | 3176 | [求出最长好子序列 I](/solution/3100-3199/3176.Find%20the%20Maximum%20Length%20of%20a%20Good%20Subsequence%20I/README.md) | `数组`,`哈希表`,`动态规划` | 中等 | 第 132 场双周赛 | | 3177 | [求出最长好子序列 II](/solution/3100-3199/3177.Find%20the%20Maximum%20Length%20of%20a%20Good%20Subsequence%20II/README.md) | `数组`,`哈希表`,`动态规划` | 困难 | 第 132 场双周赛 | @@ -3215,7 +3215,7 @@ | 3202 | [找出有效子序列的最大长度 II](/solution/3200-3299/3202.Find%20the%20Maximum%20Length%20of%20Valid%20Subsequence%20II/README.md) | `数组`,`动态规划` | 中等 | 第 404 场周赛 | | 3203 | [合并两棵树后的最小直径](/solution/3200-3299/3203.Find%20Minimum%20Diameter%20After%20Merging%20Two%20Trees/README.md) | `树`,`深度优先搜索`,`广度优先搜索`,`图` | 困难 | 第 404 场周赛 | | 3204 | [按位用户权限分析](/solution/3200-3299/3204.Bitwise%20User%20Permissions%20Analysis/README.md) | `数据库` | 中等 | 🔒 | -| 3205 | [最大数组跳跃得分 I](/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README.md) | `栈`,`数组`,`动态规划`,`单调栈` | 中等 | 🔒 | +| 3205 | [最大数组跳跃得分 I](/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README.md) | `栈`,`贪心`,`数组`,`动态规划`,`单调栈` | 中等 | 🔒 | | 3206 | [交替组 I](/solution/3200-3299/3206.Alternating%20Groups%20I/README.md) | `数组`,`滑动窗口` | 简单 | 第 134 场双周赛 | | 3207 | [与敌人战斗后的最大分数](/solution/3200-3299/3207.Maximum%20Points%20After%20Enemy%20Battles/README.md) | `贪心`,`数组` | 中等 | 第 134 场双周赛 | | 3208 | [交替组 II](/solution/3200-3299/3208.Alternating%20Groups%20II/README.md) | `数组`,`滑动窗口` | 中等 | 第 134 场双周赛 | @@ -3225,7 +3225,55 @@ | 3212 | [统计 X 和 Y 频数相等的子矩阵数量](/solution/3200-3299/3212.Count%20Submatrices%20With%20Equal%20Frequency%20of%20X%20and%20Y/README.md) | `数组`,`矩阵`,`前缀和` | 中等 | 第 405 场周赛 | | 3213 | [最小代价构造字符串](/solution/3200-3299/3213.Construct%20String%20with%20Minimum%20Cost/README.md) | `数组`,`字符串`,`动态规划`,`后缀数组` | 困难 | 第 405 场周赛 | | 3214 | [同比增长率](/solution/3200-3299/3214.Year%20on%20Year%20Growth%20Rate/README.md) | `数据库` | 困难 | 🔒 | -| 3215 | [用偶数异或设置位计数三元组 II](/solution/3200-3299/3215.Count%20Triplets%20with%20Even%20XOR%20Set%20Bits%20II/README.md) | | 中等 | 🔒 | +| 3215 | [用偶数异或设置位计数三元组 II](/solution/3200-3299/3215.Count%20Triplets%20with%20Even%20XOR%20Set%20Bits%20II/README.md) | `位运算`,`数组` | 中等 | 🔒 | +| 3216 | [交换后字典序最小的字符串](/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README.md) | `贪心`,`字符串` | 简单 | 第 406 场周赛 | +| 3217 | [从链表中移除在数组中存在的节点](/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README.md) | `数组`,`哈希表`,`链表` | 中等 | 第 406 场周赛 | +| 3218 | [切蛋糕的最小总开销 I](/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README.md) | `贪心`,`数组`,`动态规划`,`排序` | 中等 | 第 406 场周赛 | +| 3219 | [切蛋糕的最小总开销 II](/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README.md) | `贪心`,`数组`,`排序` | 困难 | 第 406 场周赛 | +| 3220 | [奇数和偶数交易](/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README.md) | `数据库` | 中等 | | +| 3221 | [最大数组跳跃得分 II](/solution/3200-3299/3221.Maximum%20Array%20Hopping%20Score%20II/README.md) | `栈`,`贪心`,`数组`,`单调栈` | 中等 | 🔒 | +| 3222 | [求出硬币游戏的赢家](/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README.md) | `数学`,`博弈`,`模拟` | 简单 | 第 135 场双周赛 | +| 3223 | [操作后字符串的最短长度](/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README.md) | `哈希表`,`字符串`,`计数` | 中等 | 第 135 场双周赛 | +| 3224 | [使差值相等的最少数组改动次数](/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README.md) | `数组`,`哈希表`,`前缀和` | 中等 | 第 135 场双周赛 | +| 3225 | [网格图操作后的最大分数](/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README.md) | `数组`,`动态规划`,`矩阵`,`前缀和` | 困难 | 第 135 场双周赛 | +| 3226 | [使两个整数相等的位更改次数](/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README.md) | `位运算` | 简单 | 第 407 场周赛 | +| 3227 | [字符串元音游戏](/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README.md) | `脑筋急转弯`,`数学`,`字符串`,`博弈` | 中等 | 第 407 场周赛 | +| 3228 | [将 1 移动到末尾的最大操作次数](/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README.md) | `贪心`,`字符串`,`计数` | 中等 | 第 407 场周赛 | +| 3229 | [使数组等于目标数组所需的最少操作次数](/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README.md) | `栈`,`贪心`,`数组`,`动态规划`,`单调栈` | 困难 | 第 407 场周赛 | +| 3230 | [客户购买行为分析](/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README.md) | `数据库` | 中等 | 🔒 | +| 3231 | [要删除的递增子序列的最小数量](/solution/3200-3299/3231.Minimum%20Number%20of%20Increasing%20Subsequence%20to%20Be%20Removed/README.md) | `数组`,`二分查找` | 困难 | 🔒 | +| 3232 | [判断是否可以赢得数字游戏](/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README.md) | `数组`,`数学` | 简单 | 第 408 场周赛 | +| 3233 | [统计不是特殊数字的数字数量](/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README.md) | `数组`,`数学`,`数论` | 中等 | 第 408 场周赛 | +| 3234 | [统计 1 显著的字符串的数量](/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README.md) | `字符串`,`枚举`,`滑动窗口` | 中等 | 第 408 场周赛 | +| 3235 | [判断矩形的两个角落是否可达](/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README.md) | `深度优先搜索`,`广度优先搜索`,`并查集`,`几何`,`数组`,`数学` | 困难 | 第 408 场周赛 | +| 3236 | [首席执行官下属层级](/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README.md) | `数据库` | 困难 | 🔒 | +| 3237 | [Alt 和 Tab 模拟](/solution/3200-3299/3237.Alt%20and%20Tab%20Simulation/README.md) | `数组`,`哈希表`,`模拟` | 中等 | 🔒 | +| 3238 | [求出胜利玩家的数目](/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README.md) | `数组`,`哈希表`,`计数` | 简单 | 第 136 场双周赛 | +| 3239 | [最少翻转次数使二进制矩阵回文 I](/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README.md) | `数组`,`双指针`,`矩阵` | 中等 | 第 136 场双周赛 | +| 3240 | [最少翻转次数使二进制矩阵回文 II](/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README.md) | `数组`,`双指针`,`矩阵` | 中等 | 第 136 场双周赛 | +| 3241 | [标记所有节点需要的时间](/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README.md) | `树`,`深度优先搜索`,`图`,`动态规划` | 困难 | 第 136 场双周赛 | +| 3242 | [设计相邻元素求和服务](/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README.md) | `设计`,`数组`,`哈希表`,`矩阵`,`模拟` | 简单 | 第 409 场周赛 | +| 3243 | [新增道路查询后的最短距离 I](/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README.md) | `广度优先搜索`,`图`,`数组` | 中等 | 第 409 场周赛 | +| 3244 | [新增道路查询后的最短距离 II](/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README.md) | `贪心`,`图`,`数组`,`有序集合` | 困难 | 第 409 场周赛 | +| 3245 | [交替组 III](/solution/3200-3299/3245.Alternating%20Groups%20III/README.md) | `树状数组`,`数组` | 困难 | 第 409 场周赛 | +| 3246 | [英超积分榜排名](/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README.md) | `数据库` | 简单 | 🔒 | +| 3247 | [奇数和子序列的数量](/solution/3200-3299/3247.Number%20of%20Subsequences%20with%20Odd%20Sum/README.md) | `数组`,`数学`,`动态规划`,`组合数学` | 中等 | 🔒 | +| 3248 | [矩阵中的蛇](/solution/3200-3299/3248.Snake%20in%20Matrix/README.md) | `数组`,`字符串`,`模拟` | 简单 | 第 410 场周赛 | +| 3249 | [统计好节点的数目](/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README.md) | `树`,`深度优先搜索` | 中等 | 第 410 场周赛 | +| 3250 | [单调数组对的数目 I](/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README.md) | `数组`,`数学`,`动态规划`,`组合数学`,`前缀和` | 困难 | 第 410 场周赛 | +| 3251 | [单调数组对的数目 II](/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README.md) | `数组`,`数学`,`动态规划`,`组合数学`,`前缀和` | 困难 | 第 410 场周赛 | +| 3252 | [英超积分榜排名 II](/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README.md) | `数据库` | 中等 | 🔒 | +| 3253 | [以最低成本构建字符串(简单)](/solution/3200-3299/3253.Construct%20String%20with%20Minimum%20Cost%20%28Easy%29/README.md) | | 中等 | 🔒 | +| 3254 | [长度为 K 的子数组的能量值 I](/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README.md) | `数组`,`滑动窗口` | 中等 | 第 137 场双周赛 | +| 3255 | [长度为 K 的子数组的能量值 II](/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README.md) | `数组`,`滑动窗口` | 中等 | 第 137 场双周赛 | +| 3256 | [放三个车的价值之和最大 I](/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README.md) | `数组`,`动态规划`,`枚举`,`矩阵` | 困难 | 第 137 场双周赛 | +| 3257 | [放三个车的价值之和最大 II](/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README.md) | `数组`,`动态规划`,`枚举`,`矩阵` | 困难 | 第 137 场双周赛 | +| 3258 | [统计满足 K 约束的子字符串数量 I](/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README.md) | `字符串`,`滑动窗口` | 简单 | 第 411 场周赛 | +| 3259 | [超级饮料的最大强化能量](/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README.md) | `数组`,`动态规划` | 中等 | 第 411 场周赛 | +| 3260 | [找出最大的 N 位 K 回文数](/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README.md) | `贪心`,`数学`,`字符串`,`动态规划`,`数论` | 困难 | 第 411 场周赛 | +| 3261 | [统计满足 K 约束的子字符串数量 II](/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README.md) | `数组`,`字符串`,`二分查找`,`前缀和`,`滑动窗口` | 困难 | 第 411 场周赛 | +| 3262 | [查找重叠的班次](/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README.md) | | 中等 | 🔒 | +| 3263 | [Convert Doubly Linked List to Array I](/solution/3200-3299/3263.Convert%20Doubly%20Linked%20List%20to%20Array%20I/README.md) | | 简单 | 🔒 | ## 版权 diff --git a/solution/README_EN.md b/solution/README_EN.md index 9c6f4a0d1b66..44acf5de94cd 100644 --- a/solution/README_EN.md +++ b/solution/README_EN.md @@ -596,7 +596,7 @@ Press Control + F(or Command + F on | 0585 | [Investments in 2016](/solution/0500-0599/0585.Investments%20in%202016/README_EN.md) | `Database` | Medium | | | 0586 | [Customer Placing the Largest Number of Orders](/solution/0500-0599/0586.Customer%20Placing%20the%20Largest%20Number%20of%20Orders/README_EN.md) | `Database` | Easy | | | 0587 | [Erect the Fence](/solution/0500-0599/0587.Erect%20the%20Fence/README_EN.md) | `Geometry`,`Array`,`Math` | Hard | | -| 0588 | [Design In-Memory File System](/solution/0500-0599/0588.Design%20In-Memory%20File%20System/README_EN.md) | `Design`,`Trie`,`Hash Table`,`String` | Hard | 🔒 | +| 0588 | [Design In-Memory File System](/solution/0500-0599/0588.Design%20In-Memory%20File%20System/README_EN.md) | `Design`,`Trie`,`Hash Table`,`String`,`Sorting` | Hard | 🔒 | | 0589 | [N-ary Tree Preorder Traversal](/solution/0500-0599/0589.N-ary%20Tree%20Preorder%20Traversal/README_EN.md) | `Stack`,`Tree`,`Depth-First Search` | Easy | | | 0590 | [N-ary Tree Postorder Traversal](/solution/0500-0599/0590.N-ary%20Tree%20Postorder%20Traversal/README_EN.md) | `Stack`,`Tree`,`Depth-First Search` | Easy | | | 0591 | [Tag Validator](/solution/0500-0599/0591.Tag%20Validator/README_EN.md) | `Stack`,`String` | Hard | | @@ -632,7 +632,7 @@ Press Control + F(or Command + F on | 0621 | [Task Scheduler](/solution/0600-0699/0621.Task%20Scheduler/README_EN.md) | `Greedy`,`Array`,`Hash Table`,`Counting`,`Sorting`,`Heap (Priority Queue)` | Medium | | | 0622 | [Design Circular Queue](/solution/0600-0699/0622.Design%20Circular%20Queue/README_EN.md) | `Design`,`Queue`,`Array`,`Linked List` | Medium | | | 0623 | [Add One Row to Tree](/solution/0600-0699/0623.Add%20One%20Row%20to%20Tree/README_EN.md) | `Tree`,`Depth-First Search`,`Breadth-First Search`,`Binary Tree` | Medium | | -| 0624 | [Maximum Distance in Arrays](/solution/0600-0699/0624.Maximum%20Distance%20in%20Arrays/README_EN.md) | `Greedy`,`Array` | Medium | 🔒 | +| 0624 | [Maximum Distance in Arrays](/solution/0600-0699/0624.Maximum%20Distance%20in%20Arrays/README_EN.md) | `Greedy`,`Array` | Medium | | | 0625 | [Minimum Factorization](/solution/0600-0699/0625.Minimum%20Factorization/README_EN.md) | `Greedy`,`Math` | Medium | 🔒 | | 0626 | [Exchange Seats](/solution/0600-0699/0626.Exchange%20Seats/README_EN.md) | `Database` | Medium | | | 0627 | [Swap Salary](/solution/0600-0699/0627.Swap%20Salary/README_EN.md) | `Database` | Easy | | @@ -650,7 +650,7 @@ Press Control + F(or Command + F on | 0639 | [Decode Ways II](/solution/0600-0699/0639.Decode%20Ways%20II/README_EN.md) | `String`,`Dynamic Programming` | Hard | | | 0640 | [Solve the Equation](/solution/0600-0699/0640.Solve%20the%20Equation/README_EN.md) | `Math`,`String`,`Simulation` | Medium | | | 0641 | [Design Circular Deque](/solution/0600-0699/0641.Design%20Circular%20Deque/README_EN.md) | `Design`,`Queue`,`Array`,`Linked List` | Medium | | -| 0642 | [Design Search Autocomplete System](/solution/0600-0699/0642.Design%20Search%20Autocomplete%20System/README_EN.md) | `Design`,`Trie`,`String`,`Data Stream`,`Sorting`,`Heap (Priority Queue)` | Hard | 🔒 | +| 0642 | [Design Search Autocomplete System](/solution/0600-0699/0642.Design%20Search%20Autocomplete%20System/README_EN.md) | `Depth-First Search`,`Design`,`Trie`,`String`,`Data Stream`,`Sorting`,`Heap (Priority Queue)` | Hard | 🔒 | | 0643 | [Maximum Average Subarray I](/solution/0600-0699/0643.Maximum%20Average%20Subarray%20I/README_EN.md) | `Array`,`Sliding Window` | Easy | | | 0644 | [Maximum Average Subarray II](/solution/0600-0699/0644.Maximum%20Average%20Subarray%20II/README_EN.md) | `Array`,`Binary Search`,`Prefix Sum` | Hard | 🔒 | | 0645 | [Set Mismatch](/solution/0600-0699/0645.Set%20Mismatch/README_EN.md) | `Bit Manipulation`,`Array`,`Hash Table`,`Sorting` | Easy | | @@ -841,7 +841,7 @@ Press Control + F(or Command + F on | 0830 | [Positions of Large Groups](/solution/0800-0899/0830.Positions%20of%20Large%20Groups/README_EN.md) | `String` | Easy | Weekly Contest 83 | | 0831 | [Masking Personal Information](/solution/0800-0899/0831.Masking%20Personal%20Information/README_EN.md) | `String` | Medium | Weekly Contest 83 | | 0832 | [Flipping an Image](/solution/0800-0899/0832.Flipping%20an%20Image/README_EN.md) | `Bit Manipulation`,`Array`,`Two Pointers`,`Matrix`,`Simulation` | Easy | Weekly Contest 84 | -| 0833 | [Find And Replace in String](/solution/0800-0899/0833.Find%20And%20Replace%20in%20String/README_EN.md) | `Array`,`String`,`Sorting` | Medium | Weekly Contest 84 | +| 0833 | [Find And Replace in String](/solution/0800-0899/0833.Find%20And%20Replace%20in%20String/README_EN.md) | `Array`,`Hash Table`,`String`,`Sorting` | Medium | Weekly Contest 84 | | 0834 | [Sum of Distances in Tree](/solution/0800-0899/0834.Sum%20of%20Distances%20in%20Tree/README_EN.md) | `Tree`,`Depth-First Search`,`Graph`,`Dynamic Programming` | Hard | Weekly Contest 84 | | 0835 | [Image Overlap](/solution/0800-0899/0835.Image%20Overlap/README_EN.md) | `Array`,`Matrix` | Medium | Weekly Contest 84 | | 0836 | [Rectangle Overlap](/solution/0800-0899/0836.Rectangle%20Overlap/README_EN.md) | `Geometry`,`Math` | Easy | Weekly Contest 85 | @@ -1403,7 +1403,7 @@ Press Control + F(or Command + F on | 1392 | [Longest Happy Prefix](/solution/1300-1399/1392.Longest%20Happy%20Prefix/README_EN.md) | `String`,`String Matching`,`Hash Function`,`Rolling Hash` | Hard | Weekly Contest 181 | | 1393 | [Capital GainLoss](/solution/1300-1399/1393.Capital%20GainLoss/README_EN.md) | `Database` | Medium | | | 1394 | [Find Lucky Integer in an Array](/solution/1300-1399/1394.Find%20Lucky%20Integer%20in%20an%20Array/README_EN.md) | `Array`,`Hash Table`,`Counting` | Easy | Weekly Contest 182 | -| 1395 | [Count Number of Teams](/solution/1300-1399/1395.Count%20Number%20of%20Teams/README_EN.md) | `Binary Indexed Tree`,`Array`,`Dynamic Programming` | Medium | Weekly Contest 182 | +| 1395 | [Count Number of Teams](/solution/1300-1399/1395.Count%20Number%20of%20Teams/README_EN.md) | `Binary Indexed Tree`,`Segment Tree`,`Array`,`Dynamic Programming` | Medium | Weekly Contest 182 | | 1396 | [Design Underground System](/solution/1300-1399/1396.Design%20Underground%20System/README_EN.md) | `Design`,`Hash Table`,`String` | Medium | Weekly Contest 182 | | 1397 | [Find All Good Strings](/solution/1300-1399/1397.Find%20All%20Good%20Strings/README_EN.md) | `String`,`Dynamic Programming`,`String Matching` | Hard | Weekly Contest 182 | | 1398 | [Customers Who Bought Products A and B but Not C](/solution/1300-1399/1398.Customers%20Who%20Bought%20Products%20A%20and%20B%20but%20Not%20C/README_EN.md) | `Database` | Medium | 🔒 | @@ -1508,7 +1508,7 @@ Press Control + F(or Command + F on | 1497 | [Check If Array Pairs Are Divisible by k](/solution/1400-1499/1497.Check%20If%20Array%20Pairs%20Are%20Divisible%20by%20k/README_EN.md) | `Array`,`Hash Table`,`Counting` | Medium | Weekly Contest 195 | | 1498 | [Number of Subsequences That Satisfy the Given Sum Condition](/solution/1400-1499/1498.Number%20of%20Subsequences%20That%20Satisfy%20the%20Given%20Sum%20Condition/README_EN.md) | `Array`,`Two Pointers`,`Binary Search`,`Sorting` | Medium | Weekly Contest 195 | | 1499 | [Max Value of Equation](/solution/1400-1499/1499.Max%20Value%20of%20Equation/README_EN.md) | `Queue`,`Array`,`Sliding Window`,`Monotonic Queue`,`Heap (Priority Queue)` | Hard | Weekly Contest 195 | -| 1500 | [Design a File Sharing System](/solution/1500-1599/1500.Design%20a%20File%20Sharing%20System/README_EN.md) | `Design`,`Hash Table`,`Data Stream`,`Heap (Priority Queue)` | Medium | 🔒 | +| 1500 | [Design a File Sharing System](/solution/1500-1599/1500.Design%20a%20File%20Sharing%20System/README_EN.md) | `Design`,`Hash Table`,`Data Stream`,`Sorting`,`Heap (Priority Queue)` | Medium | 🔒 | | 1501 | [Countries You Can Safely Invest In](/solution/1500-1599/1501.Countries%20You%20Can%20Safely%20Invest%20In/README_EN.md) | `Database` | Medium | 🔒 | | 1502 | [Can Make Arithmetic Progression From Sequence](/solution/1500-1599/1502.Can%20Make%20Arithmetic%20Progression%20From%20Sequence/README_EN.md) | `Array`,`Sorting` | Easy | Weekly Contest 196 | | 1503 | [Last Moment Before All Ants Fall Out of a Plank](/solution/1500-1599/1503.Last%20Moment%20Before%20All%20Ants%20Fall%20Out%20of%20a%20Plank/README_EN.md) | `Brainteaser`,`Array`,`Simulation` | Medium | Weekly Contest 196 | @@ -1796,7 +1796,7 @@ Press Control + F(or Command + F on | 1785 | [Minimum Elements to Add to Form a Given Sum](/solution/1700-1799/1785.Minimum%20Elements%20to%20Add%20to%20Form%20a%20Given%20Sum/README_EN.md) | `Greedy`,`Array` | Medium | Weekly Contest 231 | | 1786 | [Number of Restricted Paths From First to Last Node](/solution/1700-1799/1786.Number%20of%20Restricted%20Paths%20From%20First%20to%20Last%20Node/README_EN.md) | `Graph`,`Topological Sort`,`Dynamic Programming`,`Shortest Path`,`Heap (Priority Queue)` | Medium | Weekly Contest 231 | | 1787 | [Make the XOR of All Segments Equal to Zero](/solution/1700-1799/1787.Make%20the%20XOR%20of%20All%20Segments%20Equal%20to%20Zero/README_EN.md) | `Bit Manipulation`,`Array`,`Dynamic Programming` | Hard | Weekly Contest 231 | -| 1788 | [Maximize the Beauty of the Garden](/solution/1700-1799/1788.Maximize%20the%20Beauty%20of%20the%20Garden/README_EN.md) | `Greedy`,`Array`,`Prefix Sum` | Hard | 🔒 | +| 1788 | [Maximize the Beauty of the Garden](/solution/1700-1799/1788.Maximize%20the%20Beauty%20of%20the%20Garden/README_EN.md) | `Greedy`,`Array`,`Hash Table`,`Prefix Sum` | Hard | 🔒 | | 1789 | [Primary Department for Each Employee](/solution/1700-1799/1789.Primary%20Department%20for%20Each%20Employee/README_EN.md) | `Database` | Easy | | | 1790 | [Check if One String Swap Can Make Strings Equal](/solution/1700-1799/1790.Check%20if%20One%20String%20Swap%20Can%20Make%20Strings%20Equal/README_EN.md) | `Hash Table`,`String`,`Counting` | Easy | Weekly Contest 232 | | 1791 | [Find Center of Star Graph](/solution/1700-1799/1791.Find%20Center%20of%20Star%20Graph/README_EN.md) | `Graph` | Easy | Weekly Contest 232 | @@ -1828,7 +1828,7 @@ Press Control + F(or Command + F on | 1817 | [Finding the Users Active Minutes](/solution/1800-1899/1817.Finding%20the%20Users%20Active%20Minutes/README_EN.md) | `Array`,`Hash Table` | Medium | Weekly Contest 235 | | 1818 | [Minimum Absolute Sum Difference](/solution/1800-1899/1818.Minimum%20Absolute%20Sum%20Difference/README_EN.md) | `Array`,`Binary Search`,`Ordered Set`,`Sorting` | Medium | Weekly Contest 235 | | 1819 | [Number of Different Subsequences GCDs](/solution/1800-1899/1819.Number%20of%20Different%20Subsequences%20GCDs/README_EN.md) | `Array`,`Math`,`Counting`,`Number Theory` | Hard | Weekly Contest 235 | -| 1820 | [Maximum Number of Accepted Invitations](/solution/1800-1899/1820.Maximum%20Number%20of%20Accepted%20Invitations/README_EN.md) | `Array`,`Backtracking`,`Matrix` | Medium | 🔒 | +| 1820 | [Maximum Number of Accepted Invitations](/solution/1800-1899/1820.Maximum%20Number%20of%20Accepted%20Invitations/README_EN.md) | `Depth-First Search`,`Graph`,`Array`,`Matrix` | Medium | 🔒 | | 1821 | [Find Customers With Positive Revenue this Year](/solution/1800-1899/1821.Find%20Customers%20With%20Positive%20Revenue%20this%20Year/README_EN.md) | `Database` | Easy | 🔒 | | 1822 | [Sign of the Product of an Array](/solution/1800-1899/1822.Sign%20of%20the%20Product%20of%20an%20Array/README_EN.md) | `Array`,`Math` | Easy | Weekly Contest 236 | | 1823 | [Find the Winner of the Circular Game](/solution/1800-1899/1823.Find%20the%20Winner%20of%20the%20Circular%20Game/README_EN.md) | `Recursion`,`Queue`,`Array`,`Math`,`Simulation` | Medium | Weekly Contest 236 | @@ -1910,7 +1910,7 @@ Press Control + F(or Command + F on | 1899 | [Merge Triplets to Form Target Triplet](/solution/1800-1899/1899.Merge%20Triplets%20to%20Form%20Target%20Triplet/README_EN.md) | `Greedy`,`Array` | Medium | Weekly Contest 245 | | 1900 | [The Earliest and Latest Rounds Where Players Compete](/solution/1900-1999/1900.The%20Earliest%20and%20Latest%20Rounds%20Where%20Players%20Compete/README_EN.md) | `Memoization`,`Dynamic Programming` | Hard | Weekly Contest 245 | | 1901 | [Find a Peak Element II](/solution/1900-1999/1901.Find%20a%20Peak%20Element%20II/README_EN.md) | `Array`,`Binary Search`,`Matrix` | Medium | | -| 1902 | [Depth of BST Given Insertion Order](/solution/1900-1999/1902.Depth%20of%20BST%20Given%20Insertion%20Order/README_EN.md) | `Tree`,`Binary Search Tree`,`Binary Tree`,`Ordered Set` | Medium | 🔒 | +| 1902 | [Depth of BST Given Insertion Order](/solution/1900-1999/1902.Depth%20of%20BST%20Given%20Insertion%20Order/README_EN.md) | `Tree`,`Binary Search Tree`,`Array`,`Binary Tree`,`Ordered Set` | Medium | 🔒 | | 1903 | [Largest Odd Number in String](/solution/1900-1999/1903.Largest%20Odd%20Number%20in%20String/README_EN.md) | `Greedy`,`Math`,`String` | Easy | Weekly Contest 246 | | 1904 | [The Number of Full Rounds You Have Played](/solution/1900-1999/1904.The%20Number%20of%20Full%20Rounds%20You%20Have%20Played/README_EN.md) | `Math`,`String` | Medium | Weekly Contest 246 | | 1905 | [Count Sub Islands](/solution/1900-1999/1905.Count%20Sub%20Islands/README_EN.md) | `Depth-First Search`,`Breadth-First Search`,`Union Find`,`Array`,`Matrix` | Medium | Weekly Contest 246 | @@ -1945,8 +1945,8 @@ Press Control + F(or Command + F on | 1934 | [Confirmation Rate](/solution/1900-1999/1934.Confirmation%20Rate/README_EN.md) | `Database` | Medium | | | 1935 | [Maximum Number of Words You Can Type](/solution/1900-1999/1935.Maximum%20Number%20of%20Words%20You%20Can%20Type/README_EN.md) | `Hash Table`,`String` | Easy | Weekly Contest 250 | | 1936 | [Add Minimum Number of Rungs](/solution/1900-1999/1936.Add%20Minimum%20Number%20of%20Rungs/README_EN.md) | `Greedy`,`Array` | Medium | Weekly Contest 250 | -| 1937 | [Maximum Number of Points with Cost](/solution/1900-1999/1937.Maximum%20Number%20of%20Points%20with%20Cost/README_EN.md) | `Array`,`Dynamic Programming` | Medium | Weekly Contest 250 | -| 1938 | [Maximum Genetic Difference Query](/solution/1900-1999/1938.Maximum%20Genetic%20Difference%20Query/README_EN.md) | `Bit Manipulation`,`Trie`,`Array` | Hard | Weekly Contest 250 | +| 1937 | [Maximum Number of Points with Cost](/solution/1900-1999/1937.Maximum%20Number%20of%20Points%20with%20Cost/README_EN.md) | `Array`,`Dynamic Programming`,`Matrix` | Medium | Weekly Contest 250 | +| 1938 | [Maximum Genetic Difference Query](/solution/1900-1999/1938.Maximum%20Genetic%20Difference%20Query/README_EN.md) | `Bit Manipulation`,`Depth-First Search`,`Trie`,`Array`,`Hash Table` | Hard | Weekly Contest 250 | | 1939 | [Users That Actively Request Confirmation Messages](/solution/1900-1999/1939.Users%20That%20Actively%20Request%20Confirmation%20Messages/README_EN.md) | `Database` | Easy | 🔒 | | 1940 | [Longest Common Subsequence Between Sorted Arrays](/solution/1900-1999/1940.Longest%20Common%20Subsequence%20Between%20Sorted%20Arrays/README_EN.md) | `Array`,`Hash Table`,`Counting` | Medium | 🔒 | | 1941 | [Check if All Characters Have Equal Number of Occurrences](/solution/1900-1999/1941.Check%20if%20All%20Characters%20Have%20Equal%20Number%20of%20Occurrences/README_EN.md) | `Hash Table`,`String`,`Counting` | Easy | Biweekly Contest 57 | @@ -2130,7 +2130,7 @@ Press Control + F(or Command + F on | 2119 | [A Number After a Double Reversal](/solution/2100-2199/2119.A%20Number%20After%20a%20Double%20Reversal/README_EN.md) | `Math` | Easy | Weekly Contest 273 | | 2120 | [Execution of All Suffix Instructions Staying in a Grid](/solution/2100-2199/2120.Execution%20of%20All%20Suffix%20Instructions%20Staying%20in%20a%20Grid/README_EN.md) | `String`,`Simulation` | Medium | Weekly Contest 273 | | 2121 | [Intervals Between Identical Elements](/solution/2100-2199/2121.Intervals%20Between%20Identical%20Elements/README_EN.md) | `Array`,`Hash Table`,`Prefix Sum` | Medium | Weekly Contest 273 | -| 2122 | [Recover the Original Array](/solution/2100-2199/2122.Recover%20the%20Original%20Array/README_EN.md) | `Array`,`Hash Table`,`Enumeration`,`Sorting` | Hard | Weekly Contest 273 | +| 2122 | [Recover the Original Array](/solution/2100-2199/2122.Recover%20the%20Original%20Array/README_EN.md) | `Array`,`Hash Table`,`Two Pointers`,`Enumeration`,`Sorting` | Hard | Weekly Contest 273 | | 2123 | [Minimum Operations to Remove Adjacent Ones in Matrix](/solution/2100-2199/2123.Minimum%20Operations%20to%20Remove%20Adjacent%20Ones%20in%20Matrix/README_EN.md) | `Graph`,`Array`,`Matrix` | Hard | 🔒 | | 2124 | [Check if All A's Appears Before All B's](/solution/2100-2199/2124.Check%20if%20All%20A%27s%20Appears%20Before%20All%20B%27s/README_EN.md) | `String` | Easy | Weekly Contest 274 | | 2125 | [Number of Laser Beams in a Bank](/solution/2100-2199/2125.Number%20of%20Laser%20Beams%20in%20a%20Bank/README_EN.md) | `Array`,`Math`,`String`,`Matrix` | Medium | Weekly Contest 274 | @@ -2392,7 +2392,7 @@ Press Control + F(or Command + F on | 2381 | [Shifting Letters II](/solution/2300-2399/2381.Shifting%20Letters%20II/README_EN.md) | `Array`,`String`,`Prefix Sum` | Medium | Biweekly Contest 85 | | 2382 | [Maximum Segment Sum After Removals](/solution/2300-2399/2382.Maximum%20Segment%20Sum%20After%20Removals/README_EN.md) | `Union Find`,`Array`,`Ordered Set`,`Prefix Sum` | Hard | Biweekly Contest 85 | | 2383 | [Minimum Hours of Training to Win a Competition](/solution/2300-2399/2383.Minimum%20Hours%20of%20Training%20to%20Win%20a%20Competition/README_EN.md) | `Greedy`,`Array` | Easy | Weekly Contest 307 | -| 2384 | [Largest Palindromic Number](/solution/2300-2399/2384.Largest%20Palindromic%20Number/README_EN.md) | `Greedy`,`Hash Table`,`String` | Medium | Weekly Contest 307 | +| 2384 | [Largest Palindromic Number](/solution/2300-2399/2384.Largest%20Palindromic%20Number/README_EN.md) | `Greedy`,`Hash Table`,`String`,`Counting` | Medium | Weekly Contest 307 | | 2385 | [Amount of Time for Binary Tree to Be Infected](/solution/2300-2399/2385.Amount%20of%20Time%20for%20Binary%20Tree%20to%20Be%20Infected/README_EN.md) | `Tree`,`Depth-First Search`,`Breadth-First Search`,`Hash Table`,`Binary Tree` | Medium | Weekly Contest 307 | | 2386 | [Find the K-Sum of an Array](/solution/2300-2399/2386.Find%20the%20K-Sum%20of%20an%20Array/README_EN.md) | `Array`,`Sorting`,`Heap (Priority Queue)` | Hard | Weekly Contest 307 | | 2387 | [Median of a Row Wise Sorted Matrix](/solution/2300-2399/2387.Median%20of%20a%20Row%20Wise%20Sorted%20Matrix/README_EN.md) | `Array`,`Binary Search`,`Matrix` | Medium | 🔒 | @@ -2589,7 +2589,7 @@ Press Control + F(or Command + F on | 2578 | [Split With Minimum Sum](/solution/2500-2599/2578.Split%20With%20Minimum%20Sum/README_EN.md) | `Greedy`,`Math`,`Sorting` | Easy | Biweekly Contest 99 | | 2579 | [Count Total Number of Colored Cells](/solution/2500-2599/2579.Count%20Total%20Number%20of%20Colored%20Cells/README_EN.md) | `Math` | Medium | Biweekly Contest 99 | | 2580 | [Count Ways to Group Overlapping Ranges](/solution/2500-2599/2580.Count%20Ways%20to%20Group%20Overlapping%20Ranges/README_EN.md) | `Array`,`Sorting` | Medium | Biweekly Contest 99 | -| 2581 | [Count Number of Possible Root Nodes](/solution/2500-2599/2581.Count%20Number%20of%20Possible%20Root%20Nodes/README_EN.md) | `Tree`,`Depth-First Search`,`Hash Table`,`Dynamic Programming` | Hard | Biweekly Contest 99 | +| 2581 | [Count Number of Possible Root Nodes](/solution/2500-2599/2581.Count%20Number%20of%20Possible%20Root%20Nodes/README_EN.md) | `Tree`,`Depth-First Search`,`Array`,`Hash Table`,`Dynamic Programming` | Hard | Biweekly Contest 99 | | 2582 | [Pass the Pillow](/solution/2500-2599/2582.Pass%20the%20Pillow/README_EN.md) | `Math`,`Simulation` | Easy | Weekly Contest 335 | | 2583 | [Kth Largest Sum in a Binary Tree](/solution/2500-2599/2583.Kth%20Largest%20Sum%20in%20a%20Binary%20Tree/README_EN.md) | `Tree`,`Breadth-First Search`,`Binary Tree`,`Sorting` | Medium | Weekly Contest 335 | | 2584 | [Split the Array to Make Coprime Products](/solution/2500-2599/2584.Split%20the%20Array%20to%20Make%20Coprime%20Products/README_EN.md) | `Array`,`Hash Table`,`Math`,`Number Theory` | Hard | Weekly Contest 335 | @@ -2605,7 +2605,7 @@ Press Control + F(or Command + F on | 2594 | [Minimum Time to Repair Cars](/solution/2500-2599/2594.Minimum%20Time%20to%20Repair%20Cars/README_EN.md) | `Array`,`Binary Search` | Medium | Biweekly Contest 100 | | 2595 | [Number of Even and Odd Bits](/solution/2500-2599/2595.Number%20of%20Even%20and%20Odd%20Bits/README_EN.md) | `Bit Manipulation` | Easy | Weekly Contest 337 | | 2596 | [Check Knight Tour Configuration](/solution/2500-2599/2596.Check%20Knight%20Tour%20Configuration/README_EN.md) | `Depth-First Search`,`Breadth-First Search`,`Array`,`Matrix`,`Simulation` | Medium | Weekly Contest 337 | -| 2597 | [The Number of Beautiful Subsets](/solution/2500-2599/2597.The%20Number%20of%20Beautiful%20Subsets/README_EN.md) | `Array`,`Dynamic Programming`,`Backtracking`,`Sorting` | Medium | Weekly Contest 337 | +| 2597 | [The Number of Beautiful Subsets](/solution/2500-2599/2597.The%20Number%20of%20Beautiful%20Subsets/README_EN.md) | `Array`,`Hash Table`,`Math`,`Dynamic Programming`,`Backtracking`,`Combinatorics`,`Sorting` | Medium | Weekly Contest 337 | | 2598 | [Smallest Missing Non-negative Integer After Operations](/solution/2500-2599/2598.Smallest%20Missing%20Non-negative%20Integer%20After%20Operations/README_EN.md) | `Greedy`,`Array`,`Hash Table`,`Math` | Medium | Weekly Contest 337 | | 2599 | [Make the Prefix Sum Non-negative](/solution/2500-2599/2599.Make%20the%20Prefix%20Sum%20Non-negative/README_EN.md) | `Greedy`,`Array`,`Heap (Priority Queue)` | Medium | 🔒 | | 2600 | [K Items With the Maximum Sum](/solution/2600-2699/2600.K%20Items%20With%20the%20Maximum%20Sum/README_EN.md) | `Greedy`,`Math` | Easy | Weekly Contest 338 | @@ -2646,7 +2646,7 @@ Press Control + F(or Command + F on | 2635 | [Apply Transform Over Each Element in Array](/solution/2600-2699/2635.Apply%20Transform%20Over%20Each%20Element%20in%20Array/README_EN.md) | | Easy | | | 2636 | [Promise Pool](/solution/2600-2699/2636.Promise%20Pool/README_EN.md) | | Medium | 🔒 | | 2637 | [Promise Time Limit](/solution/2600-2699/2637.Promise%20Time%20Limit/README_EN.md) | | Medium | | -| 2638 | [Count the Number of K-Free Subsets](/solution/2600-2699/2638.Count%20the%20Number%20of%20K-Free%20Subsets/README_EN.md) | `Array`,`Dynamic Programming`,`Sorting` | Medium | 🔒 | +| 2638 | [Count the Number of K-Free Subsets](/solution/2600-2699/2638.Count%20the%20Number%20of%20K-Free%20Subsets/README_EN.md) | `Array`,`Math`,`Dynamic Programming`,`Combinatorics`,`Sorting` | Medium | 🔒 | | 2639 | [Find the Width of Columns of a Grid](/solution/2600-2699/2639.Find%20the%20Width%20of%20Columns%20of%20a%20Grid/README_EN.md) | `Array`,`Matrix` | Easy | Biweekly Contest 102 | | 2640 | [Find the Score of All Prefixes of an Array](/solution/2600-2699/2640.Find%20the%20Score%20of%20All%20Prefixes%20of%20an%20Array/README_EN.md) | `Array`,`Prefix Sum` | Medium | Biweekly Contest 102 | | 2641 | [Cousins in Binary Tree II](/solution/2600-2699/2641.Cousins%20in%20Binary%20Tree%20II/README_EN.md) | `Tree`,`Depth-First Search`,`Breadth-First Search`,`Hash Table`,`Binary Tree` | Medium | Biweekly Contest 102 | @@ -2871,7 +2871,7 @@ Press Control + F(or Command + F on | 2860 | [Happy Students](/solution/2800-2899/2860.Happy%20Students/README_EN.md) | `Array`,`Enumeration`,`Sorting` | Medium | Weekly Contest 363 | | 2861 | [Maximum Number of Alloys](/solution/2800-2899/2861.Maximum%20Number%20of%20Alloys/README_EN.md) | `Array`,`Binary Search` | Medium | Weekly Contest 363 | | 2862 | [Maximum Element-Sum of a Complete Subset of Indices](/solution/2800-2899/2862.Maximum%20Element-Sum%20of%20a%20Complete%20Subset%20of%20Indices/README_EN.md) | `Array`,`Math`,`Number Theory` | Hard | Weekly Contest 363 | -| 2863 | [Maximum Length of Semi-Decreasing Subarrays](/solution/2800-2899/2863.Maximum%20Length%20of%20Semi-Decreasing%20Subarrays/README_EN.md) | `Array`,`Hash Table`,`Sorting` | Medium | 🔒 | +| 2863 | [Maximum Length of Semi-Decreasing Subarrays](/solution/2800-2899/2863.Maximum%20Length%20of%20Semi-Decreasing%20Subarrays/README_EN.md) | `Stack`,`Array`,`Sorting`,`Monotonic Stack` | Medium | 🔒 | | 2864 | [Maximum Odd Binary Number](/solution/2800-2899/2864.Maximum%20Odd%20Binary%20Number/README_EN.md) | `Greedy`,`Math`,`String` | Easy | Weekly Contest 364 | | 2865 | [Beautiful Towers I](/solution/2800-2899/2865.Beautiful%20Towers%20I/README_EN.md) | `Stack`,`Array`,`Monotonic Stack` | Medium | Weekly Contest 364 | | 2866 | [Beautiful Towers II](/solution/2800-2899/2866.Beautiful%20Towers%20II/README_EN.md) | `Stack`,`Array`,`Monotonic Stack` | Medium | Weekly Contest 364 | @@ -3000,7 +3000,7 @@ Press Control + F(or Command + F on | 2989 | [Class Performance](/solution/2900-2999/2989.Class%20Performance/README_EN.md) | `Database` | Medium | 🔒 | | 2990 | [Loan Types](/solution/2900-2999/2990.Loan%20Types/README_EN.md) | `Database` | Easy | 🔒 | | 2991 | [Top Three Wineries](/solution/2900-2999/2991.Top%20Three%20Wineries/README_EN.md) | `Database` | Hard | 🔒 | -| 2992 | [Number of Self-Divisible Permutations](/solution/2900-2999/2992.Number%20of%20Self-Divisible%20Permutations/README_EN.md) | `Bit Manipulation`,`Recursion`,`Array`,`Dynamic Programming`,`Bitmask` | Medium | 🔒 | +| 2992 | [Number of Self-Divisible Permutations](/solution/2900-2999/2992.Number%20of%20Self-Divisible%20Permutations/README_EN.md) | `Bit Manipulation`,`Array`,`Dynamic Programming`,`Backtracking`,`Bitmask` | Medium | 🔒 | | 2993 | [Friday Purchases I](/solution/2900-2999/2993.Friday%20Purchases%20I/README_EN.md) | `Database` | Medium | 🔒 | | 2994 | [Friday Purchases II](/solution/2900-2999/2994.Friday%20Purchases%20II/README_EN.md) | `Database` | Hard | 🔒 | | 2995 | [Viewers Turned Streamers](/solution/2900-2999/2995.Viewers%20Turned%20Streamers/README_EN.md) | `Database` | Hard | 🔒 | @@ -3182,7 +3182,7 @@ Press Control + F(or Command + F on | 3171 | [Find Subarray With Bitwise OR Closest to K](/solution/3100-3199/3171.Find%20Subarray%20With%20Bitwise%20OR%20Closest%20to%20K/README_EN.md) | `Bit Manipulation`,`Segment Tree`,`Array`,`Binary Search` | Hard | Weekly Contest 400 | | 3172 | [Second Day Verification](/solution/3100-3199/3172.Second%20Day%20Verification/README_EN.md) | `Database` | Easy | 🔒 | | 3173 | [Bitwise OR of Adjacent Elements](/solution/3100-3199/3173.Bitwise%20OR%20of%20Adjacent%20Elements/README_EN.md) | `Bit Manipulation`,`Array` | Easy | 🔒 | -| 3174 | [Clear Digits](/solution/3100-3199/3174.Clear%20Digits/README_EN.md) | `Hash Table`,`String`,`Simulation` | Easy | Biweekly Contest 132 | +| 3174 | [Clear Digits](/solution/3100-3199/3174.Clear%20Digits/README_EN.md) | `Stack`,`String`,`Simulation` | Easy | Biweekly Contest 132 | | 3175 | [Find The First Player to win K Games in a Row](/solution/3100-3199/3175.Find%20The%20First%20Player%20to%20win%20K%20Games%20in%20a%20Row/README_EN.md) | `Array`,`Simulation` | Medium | Biweekly Contest 132 | | 3176 | [Find the Maximum Length of a Good Subsequence I](/solution/3100-3199/3176.Find%20the%20Maximum%20Length%20of%20a%20Good%20Subsequence%20I/README_EN.md) | `Array`,`Hash Table`,`Dynamic Programming` | Medium | Biweekly Contest 132 | | 3177 | [Find the Maximum Length of a Good Subsequence II](/solution/3100-3199/3177.Find%20the%20Maximum%20Length%20of%20a%20Good%20Subsequence%20II/README_EN.md) | `Array`,`Hash Table`,`Dynamic Programming` | Hard | Biweekly Contest 132 | @@ -3213,7 +3213,7 @@ Press Control + F(or Command + F on | 3202 | [Find the Maximum Length of Valid Subsequence II](/solution/3200-3299/3202.Find%20the%20Maximum%20Length%20of%20Valid%20Subsequence%20II/README_EN.md) | `Array`,`Dynamic Programming` | Medium | Weekly Contest 404 | | 3203 | [Find Minimum Diameter After Merging Two Trees](/solution/3200-3299/3203.Find%20Minimum%20Diameter%20After%20Merging%20Two%20Trees/README_EN.md) | `Tree`,`Depth-First Search`,`Breadth-First Search`,`Graph` | Hard | Weekly Contest 404 | | 3204 | [Bitwise User Permissions Analysis](/solution/3200-3299/3204.Bitwise%20User%20Permissions%20Analysis/README_EN.md) | `Database` | Medium | 🔒 | -| 3205 | [Maximum Array Hopping Score I](/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README_EN.md) | `Stack`,`Array`,`Dynamic Programming`,`Monotonic Stack` | Medium | 🔒 | +| 3205 | [Maximum Array Hopping Score I](/solution/3200-3299/3205.Maximum%20Array%20Hopping%20Score%20I/README_EN.md) | `Stack`,`Greedy`,`Array`,`Dynamic Programming`,`Monotonic Stack` | Medium | 🔒 | | 3206 | [Alternating Groups I](/solution/3200-3299/3206.Alternating%20Groups%20I/README_EN.md) | `Array`,`Sliding Window` | Easy | Biweekly Contest 134 | | 3207 | [Maximum Points After Enemy Battles](/solution/3200-3299/3207.Maximum%20Points%20After%20Enemy%20Battles/README_EN.md) | `Greedy`,`Array` | Medium | Biweekly Contest 134 | | 3208 | [Alternating Groups II](/solution/3200-3299/3208.Alternating%20Groups%20II/README_EN.md) | `Array`,`Sliding Window` | Medium | Biweekly Contest 134 | @@ -3223,7 +3223,55 @@ Press Control + F(or Command + F on | 3212 | [Count Submatrices With Equal Frequency of X and Y](/solution/3200-3299/3212.Count%20Submatrices%20With%20Equal%20Frequency%20of%20X%20and%20Y/README_EN.md) | `Array`,`Matrix`,`Prefix Sum` | Medium | Weekly Contest 405 | | 3213 | [Construct String with Minimum Cost](/solution/3200-3299/3213.Construct%20String%20with%20Minimum%20Cost/README_EN.md) | `Array`,`String`,`Dynamic Programming`,`Suffix Array` | Hard | Weekly Contest 405 | | 3214 | [Year on Year Growth Rate](/solution/3200-3299/3214.Year%20on%20Year%20Growth%20Rate/README_EN.md) | `Database` | Hard | 🔒 | -| 3215 | [Count Triplets with Even XOR Set Bits II](/solution/3200-3299/3215.Count%20Triplets%20with%20Even%20XOR%20Set%20Bits%20II/README_EN.md) | | Medium | 🔒 | +| 3215 | [Count Triplets with Even XOR Set Bits II](/solution/3200-3299/3215.Count%20Triplets%20with%20Even%20XOR%20Set%20Bits%20II/README_EN.md) | `Bit Manipulation`,`Array` | Medium | 🔒 | +| 3216 | [Lexicographically Smallest String After a Swap](/solution/3200-3299/3216.Lexicographically%20Smallest%20String%20After%20a%20Swap/README_EN.md) | `Greedy`,`String` | Easy | Weekly Contest 406 | +| 3217 | [Delete Nodes From Linked List Present in Array](/solution/3200-3299/3217.Delete%20Nodes%20From%20Linked%20List%20Present%20in%20Array/README_EN.md) | `Array`,`Hash Table`,`Linked List` | Medium | Weekly Contest 406 | +| 3218 | [Minimum Cost for Cutting Cake I](/solution/3200-3299/3218.Minimum%20Cost%20for%20Cutting%20Cake%20I/README_EN.md) | `Greedy`,`Array`,`Dynamic Programming`,`Sorting` | Medium | Weekly Contest 406 | +| 3219 | [Minimum Cost for Cutting Cake II](/solution/3200-3299/3219.Minimum%20Cost%20for%20Cutting%20Cake%20II/README_EN.md) | `Greedy`,`Array`,`Sorting` | Hard | Weekly Contest 406 | +| 3220 | [Odd and Even Transactions](/solution/3200-3299/3220.Odd%20and%20Even%20Transactions/README_EN.md) | `Database` | Medium | | +| 3221 | [Maximum Array Hopping Score II](/solution/3200-3299/3221.Maximum%20Array%20Hopping%20Score%20II/README_EN.md) | `Stack`,`Greedy`,`Array`,`Monotonic Stack` | Medium | 🔒 | +| 3222 | [Find the Winning Player in Coin Game](/solution/3200-3299/3222.Find%20the%20Winning%20Player%20in%20Coin%20Game/README_EN.md) | `Math`,`Game Theory`,`Simulation` | Easy | Biweekly Contest 135 | +| 3223 | [Minimum Length of String After Operations](/solution/3200-3299/3223.Minimum%20Length%20of%20String%20After%20Operations/README_EN.md) | `Hash Table`,`String`,`Counting` | Medium | Biweekly Contest 135 | +| 3224 | [Minimum Array Changes to Make Differences Equal](/solution/3200-3299/3224.Minimum%20Array%20Changes%20to%20Make%20Differences%20Equal/README_EN.md) | `Array`,`Hash Table`,`Prefix Sum` | Medium | Biweekly Contest 135 | +| 3225 | [Maximum Score From Grid Operations](/solution/3200-3299/3225.Maximum%20Score%20From%20Grid%20Operations/README_EN.md) | `Array`,`Dynamic Programming`,`Matrix`,`Prefix Sum` | Hard | Biweekly Contest 135 | +| 3226 | [Number of Bit Changes to Make Two Integers Equal](/solution/3200-3299/3226.Number%20of%20Bit%20Changes%20to%20Make%20Two%20Integers%20Equal/README_EN.md) | `Bit Manipulation` | Easy | Weekly Contest 407 | +| 3227 | [Vowels Game in a String](/solution/3200-3299/3227.Vowels%20Game%20in%20a%20String/README_EN.md) | `Brainteaser`,`Math`,`String`,`Game Theory` | Medium | Weekly Contest 407 | +| 3228 | [Maximum Number of Operations to Move Ones to the End](/solution/3200-3299/3228.Maximum%20Number%20of%20Operations%20to%20Move%20Ones%20to%20the%20End/README_EN.md) | `Greedy`,`String`,`Counting` | Medium | Weekly Contest 407 | +| 3229 | [Minimum Operations to Make Array Equal to Target](/solution/3200-3299/3229.Minimum%20Operations%20to%20Make%20Array%20Equal%20to%20Target/README_EN.md) | `Stack`,`Greedy`,`Array`,`Dynamic Programming`,`Monotonic Stack` | Hard | Weekly Contest 407 | +| 3230 | [Customer Purchasing Behavior Analysis](/solution/3200-3299/3230.Customer%20Purchasing%20Behavior%20Analysis/README_EN.md) | `Database` | Medium | 🔒 | +| 3231 | [Minimum Number of Increasing Subsequence to Be Removed](/solution/3200-3299/3231.Minimum%20Number%20of%20Increasing%20Subsequence%20to%20Be%20Removed/README_EN.md) | `Array`,`Binary Search` | Hard | 🔒 | +| 3232 | [Find if Digit Game Can Be Won](/solution/3200-3299/3232.Find%20if%20Digit%20Game%20Can%20Be%20Won/README_EN.md) | `Array`,`Math` | Easy | Weekly Contest 408 | +| 3233 | [Find the Count of Numbers Which Are Not Special](/solution/3200-3299/3233.Find%20the%20Count%20of%20Numbers%20Which%20Are%20Not%20Special/README_EN.md) | `Array`,`Math`,`Number Theory` | Medium | Weekly Contest 408 | +| 3234 | [Count the Number of Substrings With Dominant Ones](/solution/3200-3299/3234.Count%20the%20Number%20of%20Substrings%20With%20Dominant%20Ones/README_EN.md) | `String`,`Enumeration`,`Sliding Window` | Medium | Weekly Contest 408 | +| 3235 | [Check if the Rectangle Corner Is Reachable](/solution/3200-3299/3235.Check%20if%20the%20Rectangle%20Corner%20Is%20Reachable/README_EN.md) | `Depth-First Search`,`Breadth-First Search`,`Union Find`,`Geometry`,`Array`,`Math` | Hard | Weekly Contest 408 | +| 3236 | [CEO Subordinate Hierarchy](/solution/3200-3299/3236.CEO%20Subordinate%20Hierarchy/README_EN.md) | `Database` | Hard | 🔒 | +| 3237 | [Alt and Tab Simulation](/solution/3200-3299/3237.Alt%20and%20Tab%20Simulation/README_EN.md) | `Array`,`Hash Table`,`Simulation` | Medium | 🔒 | +| 3238 | [Find the Number of Winning Players](/solution/3200-3299/3238.Find%20the%20Number%20of%20Winning%20Players/README_EN.md) | `Array`,`Hash Table`,`Counting` | Easy | Biweekly Contest 136 | +| 3239 | [Minimum Number of Flips to Make Binary Grid Palindromic I](/solution/3200-3299/3239.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20I/README_EN.md) | `Array`,`Two Pointers`,`Matrix` | Medium | Biweekly Contest 136 | +| 3240 | [Minimum Number of Flips to Make Binary Grid Palindromic II](/solution/3200-3299/3240.Minimum%20Number%20of%20Flips%20to%20Make%20Binary%20Grid%20Palindromic%20II/README_EN.md) | `Array`,`Two Pointers`,`Matrix` | Medium | Biweekly Contest 136 | +| 3241 | [Time Taken to Mark All Nodes](/solution/3200-3299/3241.Time%20Taken%20to%20Mark%20All%20Nodes/README_EN.md) | `Tree`,`Depth-First Search`,`Graph`,`Dynamic Programming` | Hard | Biweekly Contest 136 | +| 3242 | [Design Neighbor Sum Service](/solution/3200-3299/3242.Design%20Neighbor%20Sum%20Service/README_EN.md) | `Design`,`Array`,`Hash Table`,`Matrix`,`Simulation` | Easy | Weekly Contest 409 | +| 3243 | [Shortest Distance After Road Addition Queries I](/solution/3200-3299/3243.Shortest%20Distance%20After%20Road%20Addition%20Queries%20I/README_EN.md) | `Breadth-First Search`,`Graph`,`Array` | Medium | Weekly Contest 409 | +| 3244 | [Shortest Distance After Road Addition Queries II](/solution/3200-3299/3244.Shortest%20Distance%20After%20Road%20Addition%20Queries%20II/README_EN.md) | `Greedy`,`Graph`,`Array`,`Ordered Set` | Hard | Weekly Contest 409 | +| 3245 | [Alternating Groups III](/solution/3200-3299/3245.Alternating%20Groups%20III/README_EN.md) | `Binary Indexed Tree`,`Array` | Hard | Weekly Contest 409 | +| 3246 | [Premier League Table Ranking](/solution/3200-3299/3246.Premier%20League%20Table%20Ranking/README_EN.md) | `Database` | Easy | 🔒 | +| 3247 | [Number of Subsequences with Odd Sum](/solution/3200-3299/3247.Number%20of%20Subsequences%20with%20Odd%20Sum/README_EN.md) | `Array`,`Math`,`Dynamic Programming`,`Combinatorics` | Medium | 🔒 | +| 3248 | [Snake in Matrix](/solution/3200-3299/3248.Snake%20in%20Matrix/README_EN.md) | `Array`,`String`,`Simulation` | Easy | Weekly Contest 410 | +| 3249 | [Count the Number of Good Nodes](/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README_EN.md) | `Tree`,`Depth-First Search` | Medium | Weekly Contest 410 | +| 3250 | [Find the Count of Monotonic Pairs I](/solution/3200-3299/3250.Find%20the%20Count%20of%20Monotonic%20Pairs%20I/README_EN.md) | `Array`,`Math`,`Dynamic Programming`,`Combinatorics`,`Prefix Sum` | Hard | Weekly Contest 410 | +| 3251 | [Find the Count of Monotonic Pairs II](/solution/3200-3299/3251.Find%20the%20Count%20of%20Monotonic%20Pairs%20II/README_EN.md) | `Array`,`Math`,`Dynamic Programming`,`Combinatorics`,`Prefix Sum` | Hard | Weekly Contest 410 | +| 3252 | [Premier League Table Ranking II](/solution/3200-3299/3252.Premier%20League%20Table%20Ranking%20II/README_EN.md) | `Database` | Medium | 🔒 | +| 3253 | [Construct String with Minimum Cost (Easy)](/solution/3200-3299/3253.Construct%20String%20with%20Minimum%20Cost%20%28Easy%29/README_EN.md) | | Medium | 🔒 | +| 3254 | [Find the Power of K-Size Subarrays I](/solution/3200-3299/3254.Find%20the%20Power%20of%20K-Size%20Subarrays%20I/README_EN.md) | `Array`,`Sliding Window` | Medium | Biweekly Contest 137 | +| 3255 | [Find the Power of K-Size Subarrays II](/solution/3200-3299/3255.Find%20the%20Power%20of%20K-Size%20Subarrays%20II/README_EN.md) | `Array`,`Sliding Window` | Medium | Biweekly Contest 137 | +| 3256 | [Maximum Value Sum by Placing Three Rooks I](/solution/3200-3299/3256.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20I/README_EN.md) | `Array`,`Dynamic Programming`,`Enumeration`,`Matrix` | Hard | Biweekly Contest 137 | +| 3257 | [Maximum Value Sum by Placing Three Rooks II](/solution/3200-3299/3257.Maximum%20Value%20Sum%20by%20Placing%20Three%20Rooks%20II/README_EN.md) | `Array`,`Dynamic Programming`,`Enumeration`,`Matrix` | Hard | Biweekly Contest 137 | +| 3258 | [Count Substrings That Satisfy K-Constraint I](/solution/3200-3299/3258.Count%20Substrings%20That%20Satisfy%20K-Constraint%20I/README_EN.md) | `String`,`Sliding Window` | Easy | Weekly Contest 411 | +| 3259 | [Maximum Energy Boost From Two Drinks](/solution/3200-3299/3259.Maximum%20Energy%20Boost%20From%20Two%20Drinks/README_EN.md) | `Array`,`Dynamic Programming` | Medium | Weekly Contest 411 | +| 3260 | [Find the Largest Palindrome Divisible by K](/solution/3200-3299/3260.Find%20the%20Largest%20Palindrome%20Divisible%20by%20K/README_EN.md) | `Greedy`,`Math`,`String`,`Dynamic Programming`,`Number Theory` | Hard | Weekly Contest 411 | +| 3261 | [Count Substrings That Satisfy K-Constraint II](/solution/3200-3299/3261.Count%20Substrings%20That%20Satisfy%20K-Constraint%20II/README_EN.md) | `Array`,`String`,`Binary Search`,`Prefix Sum`,`Sliding Window` | Hard | Weekly Contest 411 | +| 3262 | [Find Overlapping Shifts](/solution/3200-3299/3262.Find%20Overlapping%20Shifts/README_EN.md) | | Medium | 🔒 | +| 3263 | [Convert Doubly Linked List to Array I](/solution/3200-3299/3263.Convert%20Doubly%20Linked%20List%20to%20Array%20I/README_EN.md) | | Easy | 🔒 | ## Copyright diff --git a/solution/contest.json b/solution/contest.json index a1d8e85f2de0..7971e5d162c9 100644 --- a/solution/contest.json +++ b/solution/contest.json @@ -1 +1 @@ -[{"contest_title": "\u7b2c 83 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 83", "contest_title_slug": "weekly-contest-83", "contest_id": 5, "contest_start_time": 1525570200, "contest_duration": 5400, "user_num": 58, "question_slugs": ["positions-of-large-groups", "masking-personal-information", "consecutive-numbers-sum", "count-unique-characters-of-all-substrings-of-a-given-string"]}, {"contest_title": "\u7b2c 84 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 84", "contest_title_slug": "weekly-contest-84", "contest_id": 6, "contest_start_time": 1526175000, "contest_duration": 5400, "user_num": 656, "question_slugs": ["flipping-an-image", "find-and-replace-in-string", "image-overlap", "sum-of-distances-in-tree"]}, {"contest_title": "\u7b2c 85 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 85", "contest_title_slug": "weekly-contest-85", "contest_id": 7, "contest_start_time": 1526779800, "contest_duration": 5400, "user_num": 467, "question_slugs": ["rectangle-overlap", "push-dominoes", "new-21-game", "similar-string-groups"]}, {"contest_title": "\u7b2c 87 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 87", "contest_title_slug": "weekly-contest-87", "contest_id": 9, "contest_start_time": 1527989400, "contest_duration": 5400, "user_num": 343, "question_slugs": ["backspace-string-compare", "longest-mountain-in-array", "hand-of-straights", "shortest-path-visiting-all-nodes"]}, {"contest_title": "\u7b2c 88 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 88", "contest_title_slug": "weekly-contest-88", "contest_id": 11, "contest_start_time": 1528594200, "contest_duration": 5400, "user_num": 404, "question_slugs": ["shifting-letters", "maximize-distance-to-closest-person", "loud-and-rich", "rectangle-area-ii"]}, {"contest_title": "\u7b2c 89 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 89", "contest_title_slug": "weekly-contest-89", "contest_id": 12, "contest_start_time": 1529199000, "contest_duration": 5400, "user_num": 491, "question_slugs": ["peak-index-in-a-mountain-array", "car-fleet", "exam-room", "k-similar-strings"]}, {"contest_title": "\u7b2c 91 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 91", "contest_title_slug": "weekly-contest-91", "contest_id": 14, "contest_start_time": 1530408600, "contest_duration": 5400, "user_num": 578, "question_slugs": ["lemonade-change", "all-nodes-distance-k-in-binary-tree", "score-after-flipping-matrix", "shortest-subarray-with-sum-at-least-k"]}, {"contest_title": "\u7b2c 92 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 92", "contest_title_slug": "weekly-contest-92", "contest_id": 15, "contest_start_time": 1531013400, "contest_duration": 5400, "user_num": 610, "question_slugs": ["transpose-matrix", "smallest-subtree-with-all-the-deepest-nodes", "prime-palindrome", "shortest-path-to-get-all-keys"]}, {"contest_title": "\u7b2c 93 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 93", "contest_title_slug": "weekly-contest-93", "contest_id": 16, "contest_start_time": 1531618200, "contest_duration": 5400, "user_num": 732, "question_slugs": ["binary-gap", "reordered-power-of-2", "advantage-shuffle", "minimum-number-of-refueling-stops"]}, {"contest_title": "\u7b2c 94 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 94", "contest_title_slug": "weekly-contest-94", "contest_id": 17, "contest_start_time": 1532223000, "contest_duration": 5400, "user_num": 733, "question_slugs": ["leaf-similar-trees", "walking-robot-simulation", "koko-eating-bananas", "length-of-longest-fibonacci-subsequence"]}, {"contest_title": "\u7b2c 95 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 95", "contest_title_slug": "weekly-contest-95", "contest_id": 18, "contest_start_time": 1532827800, "contest_duration": 5400, "user_num": 831, "question_slugs": ["middle-of-the-linked-list", "stone-game", "nth-magical-number", "profitable-schemes"]}, {"contest_title": "\u7b2c 96 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 96", "contest_title_slug": "weekly-contest-96", "contest_id": 19, "contest_start_time": 1533432600, "contest_duration": 5400, "user_num": 789, "question_slugs": ["projection-area-of-3d-shapes", "boats-to-save-people", "decoded-string-at-index", "reachable-nodes-in-subdivided-graph"]}, {"contest_title": "\u7b2c 97 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 97", "contest_title_slug": "weekly-contest-97", "contest_id": 20, "contest_start_time": 1534037400, "contest_duration": 5400, "user_num": 635, "question_slugs": ["uncommon-words-from-two-sentences", "spiral-matrix-iii", "possible-bipartition", "super-egg-drop"]}, {"contest_title": "\u7b2c 98 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 98", "contest_title_slug": "weekly-contest-98", "contest_id": 21, "contest_start_time": 1534642200, "contest_duration": 5400, "user_num": 670, "question_slugs": ["fair-candy-swap", "find-and-replace-pattern", "construct-binary-tree-from-preorder-and-postorder-traversal", "sum-of-subsequence-widths"]}, {"contest_title": "\u7b2c 99 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 99", "contest_title_slug": "weekly-contest-99", "contest_id": 22, "contest_start_time": 1535247000, "contest_duration": 5400, "user_num": 725, "question_slugs": ["surface-area-of-3d-shapes", "groups-of-special-equivalent-strings", "all-possible-full-binary-trees", "maximum-frequency-stack"]}, {"contest_title": "\u7b2c 100 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 100", "contest_title_slug": "weekly-contest-100", "contest_id": 23, "contest_start_time": 1535851800, "contest_duration": 5400, "user_num": 718, "question_slugs": ["monotonic-array", "increasing-order-search-tree", "bitwise-ors-of-subarrays", "orderly-queue"]}, {"contest_title": "\u7b2c 101 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 101", "contest_title_slug": "weekly-contest-101", "contest_id": 24, "contest_start_time": 1536456600, "contest_duration": 6300, "user_num": 854, "question_slugs": ["rle-iterator", "online-stock-span", "numbers-at-most-n-given-digit-set", "valid-permutations-for-di-sequence"]}, {"contest_title": "\u7b2c 102 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 102", "contest_title_slug": "weekly-contest-102", "contest_id": 25, "contest_start_time": 1537061400, "contest_duration": 5400, "user_num": 660, "question_slugs": ["sort-array-by-parity", "fruit-into-baskets", "sum-of-subarray-minimums", "super-palindromes"]}, {"contest_title": "\u7b2c 103 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 103", "contest_title_slug": "weekly-contest-103", "contest_id": 26, "contest_start_time": 1537666200, "contest_duration": 5400, "user_num": 575, "question_slugs": ["smallest-range-i", "snakes-and-ladders", "smallest-range-ii", "online-election"]}, {"contest_title": "\u7b2c 104 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 104", "contest_title_slug": "weekly-contest-104", "contest_id": 27, "contest_start_time": 1538271000, "contest_duration": 5400, "user_num": 354, "question_slugs": ["x-of-a-kind-in-a-deck-of-cards", "partition-array-into-disjoint-intervals", "word-subsets", "cat-and-mouse"]}, {"contest_title": "\u7b2c 105 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 105", "contest_title_slug": "weekly-contest-105", "contest_id": 28, "contest_start_time": 1538875800, "contest_duration": 5400, "user_num": 393, "question_slugs": ["reverse-only-letters", "maximum-sum-circular-subarray", "complete-binary-tree-inserter", "number-of-music-playlists"]}, {"contest_title": "\u7b2c 106 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 106", "contest_title_slug": "weekly-contest-106", "contest_id": 29, "contest_start_time": 1539480600, "contest_duration": 5400, "user_num": 369, "question_slugs": ["sort-array-by-parity-ii", "minimum-add-to-make-parentheses-valid", "3sum-with-multiplicity", "minimize-malware-spread"]}, {"contest_title": "\u7b2c 107 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 107", "contest_title_slug": "weekly-contest-107", "contest_id": 30, "contest_start_time": 1540085400, "contest_duration": 5400, "user_num": 504, "question_slugs": ["long-pressed-name", "flip-string-to-monotone-increasing", "three-equal-parts", "minimize-malware-spread-ii"]}, {"contest_title": "\u7b2c 108 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 108", "contest_title_slug": "weekly-contest-108", "contest_id": 31, "contest_start_time": 1540690200, "contest_duration": 5400, "user_num": 524, "question_slugs": ["unique-email-addresses", "binary-subarrays-with-sum", "minimum-falling-path-sum", "beautiful-array"]}, {"contest_title": "\u7b2c 109 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 109", "contest_title_slug": "weekly-contest-109", "contest_id": 32, "contest_start_time": 1541295000, "contest_duration": 5400, "user_num": 439, "question_slugs": ["number-of-recent-calls", "knight-dialer", "shortest-bridge", "stamping-the-sequence"]}, {"contest_title": "\u7b2c 110 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 110", "contest_title_slug": "weekly-contest-110", "contest_id": 33, "contest_start_time": 1541903400, "contest_duration": 5400, "user_num": 346, "question_slugs": ["reorder-data-in-log-files", "range-sum-of-bst", "minimum-area-rectangle", "distinct-subsequences-ii"]}, {"contest_title": "\u7b2c 111 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 111", "contest_title_slug": "weekly-contest-111", "contest_id": 34, "contest_start_time": 1542508200, "contest_duration": 5400, "user_num": 353, "question_slugs": ["valid-mountain-array", "delete-columns-to-make-sorted", "di-string-match", "find-the-shortest-superstring"]}, {"contest_title": "\u7b2c 112 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 112", "contest_title_slug": "weekly-contest-112", "contest_id": 35, "contest_start_time": 1543113000, "contest_duration": 5400, "user_num": 299, "question_slugs": ["minimum-increment-to-make-array-unique", "validate-stack-sequences", "most-stones-removed-with-same-row-or-column", "bag-of-tokens"]}, {"contest_title": "\u7b2c 113 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 113", "contest_title_slug": "weekly-contest-113", "contest_id": 36, "contest_start_time": 1543717800, "contest_duration": 5400, "user_num": 462, "question_slugs": ["largest-time-for-given-digits", "flip-equivalent-binary-trees", "reveal-cards-in-increasing-order", "largest-component-size-by-common-factor"]}, {"contest_title": "\u7b2c 114 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 114", "contest_title_slug": "weekly-contest-114", "contest_id": 37, "contest_start_time": 1544322600, "contest_duration": 5400, "user_num": 391, "question_slugs": ["verifying-an-alien-dictionary", "array-of-doubled-pairs", "delete-columns-to-make-sorted-ii", "tallest-billboard"]}, {"contest_title": "\u7b2c 115 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 115", "contest_title_slug": "weekly-contest-115", "contest_id": 38, "contest_start_time": 1544927400, "contest_duration": 5400, "user_num": 383, "question_slugs": ["prison-cells-after-n-days", "check-completeness-of-a-binary-tree", "regions-cut-by-slashes", "delete-columns-to-make-sorted-iii"]}, {"contest_title": "\u7b2c 116 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 116", "contest_title_slug": "weekly-contest-116", "contest_id": 39, "contest_start_time": 1545532200, "contest_duration": 5400, "user_num": 369, "question_slugs": ["n-repeated-element-in-size-2n-array", "maximum-width-ramp", "minimum-area-rectangle-ii", "least-operators-to-express-number"]}, {"contest_title": "\u7b2c 117 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 117", "contest_title_slug": "weekly-contest-117", "contest_id": 41, "contest_start_time": 1546137000, "contest_duration": 5400, "user_num": 657, "question_slugs": ["univalued-binary-tree", "numbers-with-same-consecutive-differences", "vowel-spellchecker", "binary-tree-cameras"]}, {"contest_title": "\u7b2c 118 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 118", "contest_title_slug": "weekly-contest-118", "contest_id": 42, "contest_start_time": 1546741800, "contest_duration": 5400, "user_num": 383, "question_slugs": ["powerful-integers", "pancake-sorting", "flip-binary-tree-to-match-preorder-traversal", "equal-rational-numbers"]}, {"contest_title": "\u7b2c 119 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 119", "contest_title_slug": "weekly-contest-119", "contest_id": 43, "contest_start_time": 1547346600, "contest_duration": 5400, "user_num": 513, "question_slugs": ["k-closest-points-to-origin", "largest-perimeter-triangle", "subarray-sums-divisible-by-k", "odd-even-jump"]}, {"contest_title": "\u7b2c 120 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 120", "contest_title_slug": "weekly-contest-120", "contest_id": 44, "contest_start_time": 1547951400, "contest_duration": 5400, "user_num": 382, "question_slugs": ["squares-of-a-sorted-array", "longest-turbulent-subarray", "distribute-coins-in-binary-tree", "unique-paths-iii"]}, {"contest_title": "\u7b2c 121 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 121", "contest_title_slug": "weekly-contest-121", "contest_id": 45, "contest_start_time": 1548556200, "contest_duration": 5400, "user_num": 384, "question_slugs": ["string-without-aaa-or-bbb", "time-based-key-value-store", "minimum-cost-for-tickets", "triples-with-bitwise-and-equal-to-zero"]}, {"contest_title": "\u7b2c 122 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 122", "contest_title_slug": "weekly-contest-122", "contest_id": 46, "contest_start_time": 1549161000, "contest_duration": 5400, "user_num": 280, "question_slugs": ["sum-of-even-numbers-after-queries", "smallest-string-starting-from-leaf", "interval-list-intersections", "vertical-order-traversal-of-a-binary-tree"]}, {"contest_title": "\u7b2c 123 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 123", "contest_title_slug": "weekly-contest-123", "contest_id": 47, "contest_start_time": 1549765800, "contest_duration": 5400, "user_num": 247, "question_slugs": ["add-to-array-form-of-integer", "satisfiability-of-equality-equations", "broken-calculator", "subarrays-with-k-different-integers"]}, {"contest_title": "\u7b2c 124 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 124", "contest_title_slug": "weekly-contest-124", "contest_id": 48, "contest_start_time": 1550370600, "contest_duration": 5400, "user_num": 417, "question_slugs": ["cousins-in-binary-tree", "rotting-oranges", "minimum-number-of-k-consecutive-bit-flips", "number-of-squareful-arrays"]}, {"contest_title": "\u7b2c 125 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 125", "contest_title_slug": "weekly-contest-125", "contest_id": 49, "contest_start_time": 1550975400, "contest_duration": 5400, "user_num": 469, "question_slugs": ["find-the-town-judge", "available-captures-for-rook", "maximum-binary-tree-ii", "grid-illumination"]}, {"contest_title": "\u7b2c 126 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 126", "contest_title_slug": "weekly-contest-126", "contest_id": 50, "contest_start_time": 1551580200, "contest_duration": 5400, "user_num": 591, "question_slugs": ["find-common-characters", "check-if-word-is-valid-after-substitutions", "max-consecutive-ones-iii", "minimum-cost-to-merge-stones"]}, {"contest_title": "\u7b2c 127 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 127", "contest_title_slug": "weekly-contest-127", "contest_id": 52, "contest_start_time": 1552185000, "contest_duration": 5400, "user_num": 664, "question_slugs": ["maximize-sum-of-array-after-k-negations", "clumsy-factorial", "minimum-domino-rotations-for-equal-row", "construct-binary-search-tree-from-preorder-traversal"]}, {"contest_title": "\u7b2c 128 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 128", "contest_title_slug": "weekly-contest-128", "contest_id": 53, "contest_start_time": 1552789800, "contest_duration": 5400, "user_num": 1251, "question_slugs": ["complement-of-base-10-integer", "pairs-of-songs-with-total-durations-divisible-by-60", "capacity-to-ship-packages-within-d-days", "numbers-with-repeated-digits"]}, {"contest_title": "\u7b2c 129 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 129", "contest_title_slug": "weekly-contest-129", "contest_id": 54, "contest_start_time": 1553391000, "contest_duration": 5400, "user_num": 759, "question_slugs": ["partition-array-into-three-parts-with-equal-sum", "smallest-integer-divisible-by-k", "best-sightseeing-pair", "binary-string-with-substrings-representing-1-to-n"]}, {"contest_title": "\u7b2c 130 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 130", "contest_title_slug": "weekly-contest-130", "contest_id": 55, "contest_start_time": 1553999400, "contest_duration": 5400, "user_num": 1294, "question_slugs": ["binary-prefix-divisible-by-5", "convert-to-base-2", "next-greater-node-in-linked-list", "number-of-enclaves"]}, {"contest_title": "\u7b2c 131 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 131", "contest_title_slug": "weekly-contest-131", "contest_id": 56, "contest_start_time": 1554604200, "contest_duration": 5400, "user_num": 918, "question_slugs": ["remove-outermost-parentheses", "sum-of-root-to-leaf-binary-numbers", "camelcase-matching", "video-stitching"]}, {"contest_title": "\u7b2c 132 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 132", "contest_title_slug": "weekly-contest-132", "contest_id": 57, "contest_start_time": 1555209000, "contest_duration": 5400, "user_num": 1050, "question_slugs": ["divisor-game", "maximum-difference-between-node-and-ancestor", "longest-arithmetic-subsequence", "recover-a-tree-from-preorder-traversal"]}, {"contest_title": "\u7b2c 133 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 133", "contest_title_slug": "weekly-contest-133", "contest_id": 59, "contest_start_time": 1555813800, "contest_duration": 5400, "user_num": 999, "question_slugs": ["two-city-scheduling", "matrix-cells-in-distance-order", "maximum-sum-of-two-non-overlapping-subarrays", "stream-of-characters"]}, {"contest_title": "\u7b2c 134 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 134", "contest_title_slug": "weekly-contest-134", "contest_id": 64, "contest_start_time": 1556418600, "contest_duration": 5400, "user_num": 728, "question_slugs": ["moving-stones-until-consecutive", "coloring-a-border", "uncrossed-lines", "escape-a-large-maze"]}, {"contest_title": "\u7b2c 135 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 135", "contest_title_slug": "weekly-contest-135", "contest_id": 65, "contest_start_time": 1557023400, "contest_duration": 5400, "user_num": 548, "question_slugs": ["valid-boomerang", "binary-search-tree-to-greater-sum-tree", "minimum-score-triangulation-of-polygon", "moving-stones-until-consecutive-ii"]}, {"contest_title": "\u7b2c 136 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 136", "contest_title_slug": "weekly-contest-136", "contest_id": 66, "contest_start_time": 1557628200, "contest_duration": 5400, "user_num": 790, "question_slugs": ["robot-bounded-in-circle", "flower-planting-with-no-adjacent", "partition-array-for-maximum-sum", "longest-duplicate-substring"]}, {"contest_title": "\u7b2c 137 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 137", "contest_title_slug": "weekly-contest-137", "contest_id": 67, "contest_start_time": 1558233000, "contest_duration": 5400, "user_num": 766, "question_slugs": ["last-stone-weight", "remove-all-adjacent-duplicates-in-string", "longest-string-chain", "last-stone-weight-ii"]}, {"contest_title": "\u7b2c 138 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 138", "contest_title_slug": "weekly-contest-138", "contest_id": 68, "contest_start_time": 1558837800, "contest_duration": 5400, "user_num": 752, "question_slugs": ["height-checker", "grumpy-bookstore-owner", "previous-permutation-with-one-swap", "distant-barcodes"]}, {"contest_title": "\u7b2c 139 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 139", "contest_title_slug": "weekly-contest-139", "contest_id": 69, "contest_start_time": 1559442600, "contest_duration": 5400, "user_num": 785, "question_slugs": ["greatest-common-divisor-of-strings", "flip-columns-for-maximum-number-of-equal-rows", "adding-two-negabinary-numbers", "number-of-submatrices-that-sum-to-target"]}, {"contest_title": "\u7b2c 140 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 140", "contest_title_slug": "weekly-contest-140", "contest_id": 71, "contest_start_time": 1560047400, "contest_duration": 5400, "user_num": 660, "question_slugs": ["occurrences-after-bigram", "letter-tile-possibilities", "insufficient-nodes-in-root-to-leaf-paths", "smallest-subsequence-of-distinct-characters"]}, {"contest_title": "\u7b2c 141 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 141", "contest_title_slug": "weekly-contest-141", "contest_id": 72, "contest_start_time": 1560652200, "contest_duration": 5400, "user_num": 763, "question_slugs": ["duplicate-zeros", "largest-values-from-labels", "shortest-path-in-binary-matrix", "shortest-common-supersequence"]}, {"contest_title": "\u7b2c 142 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 142", "contest_title_slug": "weekly-contest-142", "contest_id": 74, "contest_start_time": 1561257000, "contest_duration": 5400, "user_num": 801, "question_slugs": ["statistics-from-a-large-sample", "car-pooling", "find-in-mountain-array", "brace-expansion-ii"]}, {"contest_title": "\u7b2c 143 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 143", "contest_title_slug": "weekly-contest-143", "contest_id": 84, "contest_start_time": 1561861800, "contest_duration": 5400, "user_num": 803, "question_slugs": ["distribute-candies-to-people", "path-in-zigzag-labelled-binary-tree", "filling-bookcase-shelves", "parsing-a-boolean-expression"]}, {"contest_title": "\u7b2c 144 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 144", "contest_title_slug": "weekly-contest-144", "contest_id": 86, "contest_start_time": 1562466600, "contest_duration": 5400, "user_num": 777, "question_slugs": ["defanging-an-ip-address", "corporate-flight-bookings", "delete-nodes-and-return-forest", "maximum-nesting-depth-of-two-valid-parentheses-strings"]}, {"contest_title": "\u7b2c 145 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 145", "contest_title_slug": "weekly-contest-145", "contest_id": 87, "contest_start_time": 1563071400, "contest_duration": 5400, "user_num": 1114, "question_slugs": ["relative-sort-array", "lowest-common-ancestor-of-deepest-leaves", "longest-well-performing-interval", "smallest-sufficient-team"]}, {"contest_title": "\u7b2c 1 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 1", "contest_title_slug": "biweekly-contest-1", "contest_id": 70, "contest_start_time": 1559399400, "contest_duration": 7200, "user_num": 197, "question_slugs": ["fixed-point", "index-pairs-of-a-string", "campus-bikes-ii", "digit-count-in-range"]}, {"contest_title": "\u7b2c 2 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 2", "contest_title_slug": "biweekly-contest-2", "contest_id": 73, "contest_start_time": 1560609000, "contest_duration": 5400, "user_num": 256, "question_slugs": ["sum-of-digits-in-the-minimum-number", "high-five", "brace-expansion", "confusing-number-ii"]}, {"contest_title": "\u7b2c 3 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 3", "contest_title_slug": "biweekly-contest-3", "contest_id": 85, "contest_start_time": 1561818600, "contest_duration": 5400, "user_num": 312, "question_slugs": ["two-sum-less-than-k", "find-k-length-substrings-with-no-repeated-characters", "the-earliest-moment-when-everyone-become-friends", "path-with-maximum-minimum-value"]}, {"contest_title": "\u7b2c 4 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 4", "contest_title_slug": "biweekly-contest-4", "contest_id": 88, "contest_start_time": 1563028200, "contest_duration": 5400, "user_num": 438, "question_slugs": ["number-of-days-in-a-month", "remove-vowels-from-a-string", "maximum-average-subtree", "divide-array-into-increasing-sequences"]}, {"contest_title": "\u7b2c 5 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 5", "contest_title_slug": "biweekly-contest-5", "contest_id": 91, "contest_start_time": 1564237800, "contest_duration": 5400, "user_num": 495, "question_slugs": ["largest-unique-number", "armstrong-number", "connecting-cities-with-minimum-cost", "parallel-courses"]}, {"contest_title": "\u7b2c 6 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 6", "contest_title_slug": "biweekly-contest-6", "contest_id": 95, "contest_start_time": 1565447400, "contest_duration": 5400, "user_num": 513, "question_slugs": ["check-if-a-number-is-majority-element-in-a-sorted-array", "minimum-swaps-to-group-all-1s-together", "analyze-user-website-visit-pattern", "string-transforms-into-another-string"]}, {"contest_title": "\u7b2c 7 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 7", "contest_title_slug": "biweekly-contest-7", "contest_id": 99, "contest_start_time": 1566657000, "contest_duration": 5400, "user_num": 561, "question_slugs": ["single-row-keyboard", "design-file-system", "minimum-cost-to-connect-sticks", "optimize-water-distribution-in-a-village"]}, {"contest_title": "\u7b2c 8 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 8", "contest_title_slug": "biweekly-contest-8", "contest_id": 103, "contest_start_time": 1567866600, "contest_duration": 5400, "user_num": 630, "question_slugs": ["count-substrings-with-only-one-distinct-letter", "before-and-after-puzzle", "shortest-distance-to-target-color", "maximum-number-of-ones"]}, {"contest_title": "\u7b2c 9 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 9", "contest_title_slug": "biweekly-contest-9", "contest_id": 108, "contest_start_time": 1569076200, "contest_duration": 5700, "user_num": 929, "question_slugs": ["how-many-apples-can-you-put-into-the-basket", "minimum-knight-moves", "find-smallest-common-element-in-all-rows", "minimum-time-to-build-blocks"]}, {"contest_title": "\u7b2c 10 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 10", "contest_title_slug": "biweekly-contest-10", "contest_id": 115, "contest_start_time": 1570285800, "contest_duration": 5400, "user_num": 738, "question_slugs": ["intersection-of-three-sorted-arrays", "two-sum-bsts", "stepping-numbers", "valid-palindrome-iii"]}, {"contest_title": "\u7b2c 11 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 11", "contest_title_slug": "biweekly-contest-11", "contest_id": 118, "contest_start_time": 1571495400, "contest_duration": 5400, "user_num": 913, "question_slugs": ["missing-number-in-arithmetic-progression", "meeting-scheduler", "toss-strange-coins", "divide-chocolate"]}, {"contest_title": "\u7b2c 12 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 12", "contest_title_slug": "biweekly-contest-12", "contest_id": 121, "contest_start_time": 1572705000, "contest_duration": 5400, "user_num": 911, "question_slugs": ["design-a-leaderboard", "array-transformation", "tree-diameter", "palindrome-removal"]}, {"contest_title": "\u7b2c 13 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 13", "contest_title_slug": "biweekly-contest-13", "contest_id": 124, "contest_start_time": 1573914600, "contest_duration": 5400, "user_num": 810, "question_slugs": ["encode-number", "smallest-common-region", "synonymous-sentences", "handshakes-that-dont-cross"]}, {"contest_title": "\u7b2c 14 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 14", "contest_title_slug": "biweekly-contest-14", "contest_id": 129, "contest_start_time": 1575124200, "contest_duration": 5400, "user_num": 871, "question_slugs": ["hexspeak", "remove-interval", "delete-tree-nodes", "number-of-ships-in-a-rectangle"]}, {"contest_title": "\u7b2c 15 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 15", "contest_title_slug": "biweekly-contest-15", "contest_id": 132, "contest_start_time": 1576333800, "contest_duration": 5400, "user_num": 797, "question_slugs": ["element-appearing-more-than-25-in-sorted-array", "remove-covered-intervals", "iterator-for-combination", "minimum-falling-path-sum-ii"]}, {"contest_title": "\u7b2c 16 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 16", "contest_title_slug": "biweekly-contest-16", "contest_id": 135, "contest_start_time": 1577543400, "contest_duration": 5400, "user_num": 822, "question_slugs": ["replace-elements-with-greatest-element-on-right-side", "sum-of-mutated-array-closest-to-target", "deepest-leaves-sum", "number-of-paths-with-max-score"]}, {"contest_title": "\u7b2c 17 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 17", "contest_title_slug": "biweekly-contest-17", "contest_id": 138, "contest_start_time": 1578753000, "contest_duration": 5400, "user_num": 897, "question_slugs": ["decompress-run-length-encoded-list", "matrix-block-sum", "sum-of-nodes-with-even-valued-grandparent", "distinct-echo-substrings"]}, {"contest_title": "\u7b2c 18 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 18", "contest_title_slug": "biweekly-contest-18", "contest_id": 143, "contest_start_time": 1579962600, "contest_duration": 5400, "user_num": 587, "question_slugs": ["rank-transform-of-an-array", "break-a-palindrome", "sort-the-matrix-diagonally", "reverse-subarray-to-maximize-array-value"]}, {"contest_title": "\u7b2c 19 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 19", "contest_title_slug": "biweekly-contest-19", "contest_id": 146, "contest_start_time": 1581172200, "contest_duration": 5400, "user_num": 1120, "question_slugs": ["number-of-steps-to-reduce-a-number-to-zero", "number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold", "angle-between-hands-of-a-clock", "jump-game-iv"]}, {"contest_title": "\u7b2c 20 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 20", "contest_title_slug": "biweekly-contest-20", "contest_id": 149, "contest_start_time": 1582381800, "contest_duration": 5400, "user_num": 1541, "question_slugs": ["sort-integers-by-the-number-of-1-bits", "apply-discount-every-n-orders", "number-of-substrings-containing-all-three-characters", "count-all-valid-pickup-and-delivery-options"]}, {"contest_title": "\u7b2c 21 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 21", "contest_title_slug": "biweekly-contest-21", "contest_id": 157, "contest_start_time": 1583591400, "contest_duration": 5400, "user_num": 1913, "question_slugs": ["increasing-decreasing-string", "find-the-longest-substring-containing-vowels-in-even-counts", "longest-zigzag-path-in-a-binary-tree", "maximum-sum-bst-in-binary-tree"]}, {"contest_title": "\u7b2c 22 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 22", "contest_title_slug": "biweekly-contest-22", "contest_id": 163, "contest_start_time": 1584801000, "contest_duration": 5400, "user_num": 2042, "question_slugs": ["find-the-distance-value-between-two-arrays", "cinema-seat-allocation", "sort-integers-by-the-power-value", "pizza-with-3n-slices"]}, {"contest_title": "\u7b2c 23 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 23", "contest_title_slug": "biweekly-contest-23", "contest_id": 169, "contest_start_time": 1586010600, "contest_duration": 5400, "user_num": 2045, "question_slugs": ["count-largest-group", "construct-k-palindrome-strings", "circle-and-rectangle-overlapping", "reducing-dishes"]}, {"contest_title": "\u7b2c 24 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 24", "contest_title_slug": "biweekly-contest-24", "contest_id": 178, "contest_start_time": 1587220200, "contest_duration": 5400, "user_num": 1898, "question_slugs": ["minimum-value-to-get-positive-step-by-step-sum", "find-the-minimum-number-of-fibonacci-numbers-whose-sum-is-k", "the-k-th-lexicographical-string-of-all-happy-strings-of-length-n", "restore-the-array"]}, {"contest_title": "\u7b2c 25 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 25", "contest_title_slug": "biweekly-contest-25", "contest_id": 192, "contest_start_time": 1588429800, "contest_duration": 5400, "user_num": 1832, "question_slugs": ["kids-with-the-greatest-number-of-candies", "max-difference-you-can-get-from-changing-an-integer", "check-if-a-string-can-break-another-string", "number-of-ways-to-wear-different-hats-to-each-other"]}, {"contest_title": "\u7b2c 26 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 26", "contest_title_slug": "biweekly-contest-26", "contest_id": 198, "contest_start_time": 1589639400, "contest_duration": 5400, "user_num": 1971, "question_slugs": ["consecutive-characters", "simplified-fractions", "count-good-nodes-in-binary-tree", "form-largest-integer-with-digits-that-add-up-to-target"]}, {"contest_title": "\u7b2c 28 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 28", "contest_title_slug": "biweekly-contest-28", "contest_id": 210, "contest_start_time": 1592058600, "contest_duration": 5400, "user_num": 2144, "question_slugs": ["final-prices-with-a-special-discount-in-a-shop", "subrectangle-queries", "find-two-non-overlapping-sub-arrays-each-with-target-sum", "allocate-mailboxes"]}, {"contest_title": "\u7b2c 30 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 30", "contest_title_slug": "biweekly-contest-30", "contest_id": 222, "contest_start_time": 1594477800, "contest_duration": 5400, "user_num": 2545, "question_slugs": ["reformat-date", "range-sum-of-sorted-subarray-sums", "minimum-difference-between-largest-and-smallest-value-in-three-moves", "stone-game-iv"]}, {"contest_title": "\u7b2c 31 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 31", "contest_title_slug": "biweekly-contest-31", "contest_id": 232, "contest_start_time": 1595687400, "contest_duration": 5400, "user_num": 2767, "question_slugs": ["count-odd-numbers-in-an-interval-range", "number-of-sub-arrays-with-odd-sum", "number-of-good-ways-to-split-a-string", "minimum-number-of-increments-on-subarrays-to-form-a-target-array"]}, {"contest_title": "\u7b2c 32 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 32", "contest_title_slug": "biweekly-contest-32", "contest_id": 237, "contest_start_time": 1596897000, "contest_duration": 5400, "user_num": 2957, "question_slugs": ["kth-missing-positive-number", "can-convert-string-in-k-moves", "minimum-insertions-to-balance-a-parentheses-string", "find-longest-awesome-substring"]}, {"contest_title": "\u7b2c 33 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 33", "contest_title_slug": "biweekly-contest-33", "contest_id": 241, "contest_start_time": 1598106600, "contest_duration": 5400, "user_num": 3304, "question_slugs": ["thousand-separator", "minimum-number-of-vertices-to-reach-all-nodes", "minimum-numbers-of-function-calls-to-make-target-array", "detect-cycles-in-2d-grid"]}, {"contest_title": "\u7b2c 34 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 34", "contest_title_slug": "biweekly-contest-34", "contest_id": 256, "contest_start_time": 1599316200, "contest_duration": 5400, "user_num": 2842, "question_slugs": ["matrix-diagonal-sum", "number-of-ways-to-split-a-string", "shortest-subarray-to-be-removed-to-make-array-sorted", "count-all-possible-routes"]}, {"contest_title": "\u7b2c 35 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 35", "contest_title_slug": "biweekly-contest-35", "contest_id": 266, "contest_start_time": 1600525800, "contest_duration": 5400, "user_num": 2839, "question_slugs": ["sum-of-all-odd-length-subarrays", "maximum-sum-obtained-of-any-permutation", "make-sum-divisible-by-p", "strange-printer-ii"]}, {"contest_title": "\u7b2c 36 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 36", "contest_title_slug": "biweekly-contest-36", "contest_id": 288, "contest_start_time": 1601735400, "contest_duration": 5400, "user_num": 2204, "question_slugs": ["design-parking-system", "alert-using-same-key-card-three-or-more-times-in-a-one-hour-period", "find-valid-matrix-given-row-and-column-sums", "find-servers-that-handled-most-number-of-requests"]}, {"contest_title": "\u7b2c 37 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 37", "contest_title_slug": "biweekly-contest-37", "contest_id": 294, "contest_start_time": 1602945000, "contest_duration": 5400, "user_num": 2104, "question_slugs": ["mean-of-array-after-removing-some-elements", "coordinate-with-maximum-network-quality", "number-of-sets-of-k-non-overlapping-line-segments", "fancy-sequence"]}, {"contest_title": "\u7b2c 38 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 38", "contest_title_slug": "biweekly-contest-38", "contest_id": 300, "contest_start_time": 1604154600, "contest_duration": 5400, "user_num": 2004, "question_slugs": ["sort-array-by-increasing-frequency", "widest-vertical-area-between-two-points-containing-no-points", "count-substrings-that-differ-by-one-character", "number-of-ways-to-form-a-target-string-given-a-dictionary"]}, {"contest_title": "\u7b2c 39 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 39", "contest_title_slug": "biweekly-contest-39", "contest_id": 306, "contest_start_time": 1605364200, "contest_duration": 5400, "user_num": 2069, "question_slugs": ["defuse-the-bomb", "minimum-deletions-to-make-string-balanced", "minimum-jumps-to-reach-home", "distribute-repeating-integers"]}, {"contest_title": "\u7b2c 40 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 40", "contest_title_slug": "biweekly-contest-40", "contest_id": 312, "contest_start_time": 1606573800, "contest_duration": 5400, "user_num": 1891, "question_slugs": ["maximum-repeating-substring", "merge-in-between-linked-lists", "design-front-middle-back-queue", "minimum-number-of-removals-to-make-mountain-array"]}, {"contest_title": "\u7b2c 41 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 41", "contest_title_slug": "biweekly-contest-41", "contest_id": 318, "contest_start_time": 1607783400, "contest_duration": 5400, "user_num": 1660, "question_slugs": ["count-the-number-of-consistent-strings", "sum-of-absolute-differences-in-a-sorted-array", "stone-game-vi", "delivering-boxes-from-storage-to-ports"]}, {"contest_title": "\u7b2c 42 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 42", "contest_title_slug": "biweekly-contest-42", "contest_id": 325, "contest_start_time": 1608993000, "contest_duration": 5400, "user_num": 1578, "question_slugs": ["number-of-students-unable-to-eat-lunch", "average-waiting-time", "maximum-binary-string-after-change", "minimum-adjacent-swaps-for-k-consecutive-ones"]}, {"contest_title": "\u7b2c 43 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 43", "contest_title_slug": "biweekly-contest-43", "contest_id": 331, "contest_start_time": 1610202600, "contest_duration": 5400, "user_num": 1631, "question_slugs": ["calculate-money-in-leetcode-bank", "maximum-score-from-removing-substrings", "construct-the-lexicographically-largest-valid-sequence", "number-of-ways-to-reconstruct-a-tree"]}, {"contest_title": "\u7b2c 44 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 44", "contest_title_slug": "biweekly-contest-44", "contest_id": 337, "contest_start_time": 1611412200, "contest_duration": 5400, "user_num": 1826, "question_slugs": ["find-the-highest-altitude", "minimum-number-of-people-to-teach", "decode-xored-permutation", "count-ways-to-make-array-with-product"]}, {"contest_title": "\u7b2c 45 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 45", "contest_title_slug": "biweekly-contest-45", "contest_id": 343, "contest_start_time": 1612621800, "contest_duration": 5400, "user_num": 1676, "question_slugs": ["sum-of-unique-elements", "maximum-absolute-sum-of-any-subarray", "minimum-length-of-string-after-deleting-similar-ends", "maximum-number-of-events-that-can-be-attended-ii"]}, {"contest_title": "\u7b2c 46 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 46", "contest_title_slug": "biweekly-contest-46", "contest_id": 349, "contest_start_time": 1613831400, "contest_duration": 5400, "user_num": 1647, "question_slugs": ["longest-nice-substring", "form-array-by-concatenating-subarrays-of-another-array", "map-of-highest-peak", "tree-of-coprimes"]}, {"contest_title": "\u7b2c 47 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 47", "contest_title_slug": "biweekly-contest-47", "contest_id": 355, "contest_start_time": 1615041000, "contest_duration": 5400, "user_num": 3085, "question_slugs": ["find-nearest-point-that-has-the-same-x-or-y-coordinate", "check-if-number-is-a-sum-of-powers-of-three", "sum-of-beauty-of-all-substrings", "count-pairs-of-nodes"]}, {"contest_title": "\u7b2c 48 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 48", "contest_title_slug": "biweekly-contest-48", "contest_id": 362, "contest_start_time": 1616250600, "contest_duration": 5400, "user_num": 2853, "question_slugs": ["second-largest-digit-in-a-string", "design-authentication-manager", "maximum-number-of-consecutive-values-you-can-make", "maximize-score-after-n-operations"]}, {"contest_title": "\u7b2c 49 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 49", "contest_title_slug": "biweekly-contest-49", "contest_id": 374, "contest_start_time": 1617460200, "contest_duration": 5400, "user_num": 3193, "question_slugs": ["determine-color-of-a-chessboard-square", "sentence-similarity-iii", "count-nice-pairs-in-an-array", "maximum-number-of-groups-getting-fresh-donuts"]}, {"contest_title": "\u7b2c 50 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 50", "contest_title_slug": "biweekly-contest-50", "contest_id": 390, "contest_start_time": 1618669800, "contest_duration": 5400, "user_num": 3608, "question_slugs": ["minimum-operations-to-make-the-array-increasing", "queries-on-number-of-points-inside-a-circle", "maximum-xor-for-each-query", "minimum-number-of-operations-to-make-string-sorted"]}, {"contest_title": "\u7b2c 51 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 51", "contest_title_slug": "biweekly-contest-51", "contest_id": 396, "contest_start_time": 1619879400, "contest_duration": 5400, "user_num": 2675, "question_slugs": ["replace-all-digits-with-characters", "seat-reservation-manager", "maximum-element-after-decreasing-and-rearranging", "closest-room"]}, {"contest_title": "\u7b2c 52 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 52", "contest_title_slug": "biweekly-contest-52", "contest_id": 402, "contest_start_time": 1621089000, "contest_duration": 5400, "user_num": 2930, "question_slugs": ["sorting-the-sentence", "incremental-memory-leak", "rotating-the-box", "sum-of-floored-pairs"]}, {"contest_title": "\u7b2c 53 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 53", "contest_title_slug": "biweekly-contest-53", "contest_id": 408, "contest_start_time": 1622298600, "contest_duration": 5400, "user_num": 3069, "question_slugs": ["substrings-of-size-three-with-distinct-characters", "minimize-maximum-pair-sum-in-array", "get-biggest-three-rhombus-sums-in-a-grid", "minimum-xor-sum-of-two-arrays"]}, {"contest_title": "\u7b2c 54 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 54", "contest_title_slug": "biweekly-contest-54", "contest_id": 414, "contest_start_time": 1623508200, "contest_duration": 5400, "user_num": 2479, "question_slugs": ["check-if-all-the-integers-in-a-range-are-covered", "find-the-student-that-will-replace-the-chalk", "largest-magic-square", "minimum-cost-to-change-the-final-value-of-expression"]}, {"contest_title": "\u7b2c 55 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 55", "contest_title_slug": "biweekly-contest-55", "contest_id": 421, "contest_start_time": 1624717800, "contest_duration": 5400, "user_num": 3277, "question_slugs": ["remove-one-element-to-make-the-array-strictly-increasing", "remove-all-occurrences-of-a-substring", "maximum-alternating-subsequence-sum", "design-movie-rental-system"]}, {"contest_title": "\u7b2c 56 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 56", "contest_title_slug": "biweekly-contest-56", "contest_id": 429, "contest_start_time": 1625927400, "contest_duration": 5400, "user_num": 2760, "question_slugs": ["count-square-sum-triples", "nearest-exit-from-entrance-in-maze", "sum-game", "minimum-cost-to-reach-destination-in-time"]}, {"contest_title": "\u7b2c 57 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 57", "contest_title_slug": "biweekly-contest-57", "contest_id": 435, "contest_start_time": 1627137000, "contest_duration": 5400, "user_num": 2933, "question_slugs": ["check-if-all-characters-have-equal-number-of-occurrences", "the-number-of-the-smallest-unoccupied-chair", "describe-the-painting", "number-of-visible-people-in-a-queue"]}, {"contest_title": "\u7b2c 86 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 86", "contest_title_slug": "weekly-contest-86", "contest_id": 8, "contest_start_time": 1527384600, "contest_duration": 5400, "user_num": 377, "question_slugs": ["magic-squares-in-grid", "keys-and-rooms", "split-array-into-fibonacci-sequence", "guess-the-word"]}, {"contest_title": "\u7b2c 90 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 90", "contest_title_slug": "weekly-contest-90", "contest_id": 13, "contest_start_time": 1529803800, "contest_duration": 5400, "user_num": 573, "question_slugs": ["buddy-strings", "score-of-parentheses", "mirror-reflection", "minimum-cost-to-hire-k-workers"]}, {"contest_title": "\u7b2c 146 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 146", "contest_title_slug": "weekly-contest-146", "contest_id": 89, "contest_start_time": 1563676200, "contest_duration": 5400, "user_num": 1189, "question_slugs": ["number-of-equivalent-domino-pairs", "shortest-path-with-alternating-colors", "minimum-cost-tree-from-leaf-values", "maximum-of-absolute-value-expression"]}, {"contest_title": "\u7b2c 147 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 147", "contest_title_slug": "weekly-contest-147", "contest_id": 90, "contest_start_time": 1564281000, "contest_duration": 5400, "user_num": 1132, "question_slugs": ["n-th-tribonacci-number", "alphabet-board-path", "largest-1-bordered-square", "stone-game-ii"]}, {"contest_title": "\u7b2c 148 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 148", "contest_title_slug": "weekly-contest-148", "contest_id": 93, "contest_start_time": 1564885800, "contest_duration": 5400, "user_num": 1251, "question_slugs": ["decrease-elements-to-make-array-zigzag", "binary-tree-coloring-game", "snapshot-array", "longest-chunked-palindrome-decomposition"]}, {"contest_title": "\u7b2c 149 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 149", "contest_title_slug": "weekly-contest-149", "contest_id": 94, "contest_start_time": 1565490600, "contest_duration": 5400, "user_num": 1351, "question_slugs": ["day-of-the-year", "number-of-dice-rolls-with-target-sum", "swap-for-longest-repeated-character-substring", "online-majority-element-in-subarray"]}, {"contest_title": "\u7b2c 150 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 150", "contest_title_slug": "weekly-contest-150", "contest_id": 96, "contest_start_time": 1566095400, "contest_duration": 5400, "user_num": 1473, "question_slugs": ["find-words-that-can-be-formed-by-characters", "maximum-level-sum-of-a-binary-tree", "as-far-from-land-as-possible", "last-substring-in-lexicographical-order"]}, {"contest_title": "\u7b2c 151 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 151", "contest_title_slug": "weekly-contest-151", "contest_id": 98, "contest_start_time": 1566700200, "contest_duration": 5400, "user_num": 1341, "question_slugs": ["invalid-transactions", "compare-strings-by-frequency-of-the-smallest-character", "remove-zero-sum-consecutive-nodes-from-linked-list", "dinner-plate-stacks"]}, {"contest_title": "\u7b2c 152 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 152", "contest_title_slug": "weekly-contest-152", "contest_id": 100, "contest_start_time": 1567305000, "contest_duration": 5400, "user_num": 1367, "question_slugs": ["prime-arrangements", "diet-plan-performance", "can-make-palindrome-from-substring", "number-of-valid-words-for-each-puzzle"]}, {"contest_title": "\u7b2c 153 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 153", "contest_title_slug": "weekly-contest-153", "contest_id": 102, "contest_start_time": 1567909800, "contest_duration": 5400, "user_num": 1434, "question_slugs": ["distance-between-bus-stops", "day-of-the-week", "maximum-subarray-sum-with-one-deletion", "make-array-strictly-increasing"]}, {"contest_title": "\u7b2c 154 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 154", "contest_title_slug": "weekly-contest-154", "contest_id": 106, "contest_start_time": 1568514600, "contest_duration": 5400, "user_num": 1299, "question_slugs": ["maximum-number-of-balloons", "reverse-substrings-between-each-pair-of-parentheses", "k-concatenation-maximum-sum", "critical-connections-in-a-network"]}, {"contest_title": "\u7b2c 155 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 155", "contest_title_slug": "weekly-contest-155", "contest_id": 107, "contest_start_time": 1569119400, "contest_duration": 5400, "user_num": 1603, "question_slugs": ["minimum-absolute-difference", "ugly-number-iii", "smallest-string-with-swaps", "sort-items-by-groups-respecting-dependencies"]}, {"contest_title": "\u7b2c 156 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 156", "contest_title_slug": "weekly-contest-156", "contest_id": 113, "contest_start_time": 1569724200, "contest_duration": 5400, "user_num": 1433, "question_slugs": ["unique-number-of-occurrences", "get-equal-substrings-within-budget", "remove-all-adjacent-duplicates-in-string-ii", "minimum-moves-to-reach-target-with-rotations"]}, {"contest_title": "\u7b2c 157 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 157", "contest_title_slug": "weekly-contest-157", "contest_id": 114, "contest_start_time": 1570329000, "contest_duration": 5400, "user_num": 1217, "question_slugs": ["minimum-cost-to-move-chips-to-the-same-position", "longest-arithmetic-subsequence-of-given-difference", "path-with-maximum-gold", "count-vowels-permutation"]}, {"contest_title": "\u7b2c 158 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 158", "contest_title_slug": "weekly-contest-158", "contest_id": 116, "contest_start_time": 1570933800, "contest_duration": 5400, "user_num": 1716, "question_slugs": ["split-a-string-in-balanced-strings", "queens-that-can-attack-the-king", "dice-roll-simulation", "maximum-equal-frequency"]}, {"contest_title": "\u7b2c 159 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 159", "contest_title_slug": "weekly-contest-159", "contest_id": 117, "contest_start_time": 1571538600, "contest_duration": 5400, "user_num": 1634, "question_slugs": ["check-if-it-is-a-straight-line", "remove-sub-folders-from-the-filesystem", "replace-the-substring-for-balanced-string", "maximum-profit-in-job-scheduling"]}, {"contest_title": "\u7b2c 160 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 160", "contest_title_slug": "weekly-contest-160", "contest_id": 119, "contest_start_time": 1572143400, "contest_duration": 5400, "user_num": 1692, "question_slugs": ["find-positive-integer-solution-for-a-given-equation", "circular-permutation-in-binary-representation", "maximum-length-of-a-concatenated-string-with-unique-characters", "tiling-a-rectangle-with-the-fewest-squares"]}, {"contest_title": "\u7b2c 161 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 161", "contest_title_slug": "weekly-contest-161", "contest_id": 120, "contest_start_time": 1572748200, "contest_duration": 5400, "user_num": 1610, "question_slugs": ["minimum-swaps-to-make-strings-equal", "count-number-of-nice-subarrays", "minimum-remove-to-make-valid-parentheses", "check-if-it-is-a-good-array"]}, {"contest_title": "\u7b2c 162 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 162", "contest_title_slug": "weekly-contest-162", "contest_id": 122, "contest_start_time": 1573353000, "contest_duration": 5400, "user_num": 1569, "question_slugs": ["cells-with-odd-values-in-a-matrix", "reconstruct-a-2-row-binary-matrix", "number-of-closed-islands", "maximum-score-words-formed-by-letters"]}, {"contest_title": "\u7b2c 163 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 163", "contest_title_slug": "weekly-contest-163", "contest_id": 123, "contest_start_time": 1573957800, "contest_duration": 5400, "user_num": 1605, "question_slugs": ["shift-2d-grid", "find-elements-in-a-contaminated-binary-tree", "greatest-sum-divisible-by-three", "minimum-moves-to-move-a-box-to-their-target-location"]}, {"contest_title": "\u7b2c 164 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 164", "contest_title_slug": "weekly-contest-164", "contest_id": 125, "contest_start_time": 1574562600, "contest_duration": 5400, "user_num": 1676, "question_slugs": ["minimum-time-visiting-all-points", "count-servers-that-communicate", "search-suggestions-system", "number-of-ways-to-stay-in-the-same-place-after-some-steps"]}, {"contest_title": "\u7b2c 165 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 165", "contest_title_slug": "weekly-contest-165", "contest_id": 128, "contest_start_time": 1575167400, "contest_duration": 5400, "user_num": 1660, "question_slugs": ["find-winner-on-a-tic-tac-toe-game", "number-of-burgers-with-no-waste-of-ingredients", "count-square-submatrices-with-all-ones", "palindrome-partitioning-iii"]}, {"contest_title": "\u7b2c 166 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 166", "contest_title_slug": "weekly-contest-166", "contest_id": 130, "contest_start_time": 1575772200, "contest_duration": 5400, "user_num": 1676, "question_slugs": ["subtract-the-product-and-sum-of-digits-of-an-integer", "group-the-people-given-the-group-size-they-belong-to", "find-the-smallest-divisor-given-a-threshold", "minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix"]}, {"contest_title": "\u7b2c 167 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 167", "contest_title_slug": "weekly-contest-167", "contest_id": 131, "contest_start_time": 1576377000, "contest_duration": 5400, "user_num": 1537, "question_slugs": ["convert-binary-number-in-a-linked-list-to-integer", "sequential-digits", "maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold", "shortest-path-in-a-grid-with-obstacles-elimination"]}, {"contest_title": "\u7b2c 168 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 168", "contest_title_slug": "weekly-contest-168", "contest_id": 133, "contest_start_time": 1576981800, "contest_duration": 5400, "user_num": 1553, "question_slugs": ["find-numbers-with-even-number-of-digits", "divide-array-in-sets-of-k-consecutive-numbers", "maximum-number-of-occurrences-of-a-substring", "maximum-candies-you-can-get-from-boxes"]}, {"contest_title": "\u7b2c 169 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 169", "contest_title_slug": "weekly-contest-169", "contest_id": 134, "contest_start_time": 1577586600, "contest_duration": 5400, "user_num": 1568, "question_slugs": ["find-n-unique-integers-sum-up-to-zero", "all-elements-in-two-binary-search-trees", "jump-game-iii", "verbal-arithmetic-puzzle"]}, {"contest_title": "\u7b2c 170 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 170", "contest_title_slug": "weekly-contest-170", "contest_id": 136, "contest_start_time": 1578191400, "contest_duration": 5400, "user_num": 1649, "question_slugs": ["decrypt-string-from-alphabet-to-integer-mapping", "xor-queries-of-a-subarray", "get-watched-videos-by-your-friends", "minimum-insertion-steps-to-make-a-string-palindrome"]}, {"contest_title": "\u7b2c 171 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 171", "contest_title_slug": "weekly-contest-171", "contest_id": 137, "contest_start_time": 1578796200, "contest_duration": 5400, "user_num": 1708, "question_slugs": ["convert-integer-to-the-sum-of-two-no-zero-integers", "minimum-flips-to-make-a-or-b-equal-to-c", "number-of-operations-to-make-network-connected", "minimum-distance-to-type-a-word-using-two-fingers"]}, {"contest_title": "\u7b2c 172 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 172", "contest_title_slug": "weekly-contest-172", "contest_id": 139, "contest_start_time": 1579401000, "contest_duration": 5400, "user_num": 1415, "question_slugs": ["maximum-69-number", "print-words-vertically", "delete-leaves-with-a-given-value", "minimum-number-of-taps-to-open-to-water-a-garden"]}, {"contest_title": "\u7b2c 173 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 173", "contest_title_slug": "weekly-contest-173", "contest_id": 142, "contest_start_time": 1580005800, "contest_duration": 5400, "user_num": 1072, "question_slugs": ["remove-palindromic-subsequences", "filter-restaurants-by-vegan-friendly-price-and-distance", "find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance", "minimum-difficulty-of-a-job-schedule"]}, {"contest_title": "\u7b2c 174 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 174", "contest_title_slug": "weekly-contest-174", "contest_id": 144, "contest_start_time": 1580610600, "contest_duration": 5400, "user_num": 1660, "question_slugs": ["the-k-weakest-rows-in-a-matrix", "reduce-array-size-to-the-half", "maximum-product-of-splitted-binary-tree", "jump-game-v"]}, {"contest_title": "\u7b2c 175 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 175", "contest_title_slug": "weekly-contest-175", "contest_id": 145, "contest_start_time": 1581215400, "contest_duration": 5400, "user_num": 2048, "question_slugs": ["check-if-n-and-its-double-exist", "minimum-number-of-steps-to-make-two-strings-anagram", "tweet-counts-per-frequency", "maximum-students-taking-exam"]}, {"contest_title": "\u7b2c 176 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 176", "contest_title_slug": "weekly-contest-176", "contest_id": 147, "contest_start_time": 1581820200, "contest_duration": 5400, "user_num": 2410, "question_slugs": ["count-negative-numbers-in-a-sorted-matrix", "product-of-the-last-k-numbers", "maximum-number-of-events-that-can-be-attended", "construct-target-array-with-multiple-sums"]}, {"contest_title": "\u7b2c 177 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 177", "contest_title_slug": "weekly-contest-177", "contest_id": 148, "contest_start_time": 1582425000, "contest_duration": 5400, "user_num": 2986, "question_slugs": ["number-of-days-between-two-dates", "validate-binary-tree-nodes", "closest-divisors", "largest-multiple-of-three"]}, {"contest_title": "\u7b2c 178 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 178", "contest_title_slug": "weekly-contest-178", "contest_id": 154, "contest_start_time": 1583029800, "contest_duration": 5400, "user_num": 3305, "question_slugs": ["how-many-numbers-are-smaller-than-the-current-number", "rank-teams-by-votes", "linked-list-in-binary-tree", "minimum-cost-to-make-at-least-one-valid-path-in-a-grid"]}, {"contest_title": "\u7b2c 179 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 179", "contest_title_slug": "weekly-contest-179", "contest_id": 156, "contest_start_time": 1583634600, "contest_duration": 5400, "user_num": 3606, "question_slugs": ["generate-a-string-with-characters-that-have-odd-counts", "number-of-times-binary-string-is-prefix-aligned", "time-needed-to-inform-all-employees", "frog-position-after-t-seconds"]}, {"contest_title": "\u7b2c 180 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 180", "contest_title_slug": "weekly-contest-180", "contest_id": 160, "contest_start_time": 1584239400, "contest_duration": 5400, "user_num": 3715, "question_slugs": ["lucky-numbers-in-a-matrix", "design-a-stack-with-increment-operation", "balance-a-binary-search-tree", "maximum-performance-of-a-team"]}, {"contest_title": "\u7b2c 181 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 181", "contest_title_slug": "weekly-contest-181", "contest_id": 162, "contest_start_time": 1584844200, "contest_duration": 5400, "user_num": 4149, "question_slugs": ["create-target-array-in-the-given-order", "four-divisors", "check-if-there-is-a-valid-path-in-a-grid", "longest-happy-prefix"]}, {"contest_title": "\u7b2c 182 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 182", "contest_title_slug": "weekly-contest-182", "contest_id": 166, "contest_start_time": 1585449000, "contest_duration": 5400, "user_num": 3911, "question_slugs": ["find-lucky-integer-in-an-array", "count-number-of-teams", "design-underground-system", "find-all-good-strings"]}, {"contest_title": "\u7b2c 183 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 183", "contest_title_slug": "weekly-contest-183", "contest_id": 168, "contest_start_time": 1586053800, "contest_duration": 5400, "user_num": 3756, "question_slugs": ["minimum-subsequence-in-non-increasing-order", "number-of-steps-to-reduce-a-number-in-binary-representation-to-one", "longest-happy-string", "stone-game-iii"]}, {"contest_title": "\u7b2c 184 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 184", "contest_title_slug": "weekly-contest-184", "contest_id": 175, "contest_start_time": 1586658600, "contest_duration": 5400, "user_num": 3847, "question_slugs": ["string-matching-in-an-array", "queries-on-a-permutation-with-key", "html-entity-parser", "number-of-ways-to-paint-n-3-grid"]}, {"contest_title": "\u7b2c 185 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 185", "contest_title_slug": "weekly-contest-185", "contest_id": 177, "contest_start_time": 1587263400, "contest_duration": 5400, "user_num": 5004, "question_slugs": ["reformat-the-string", "display-table-of-food-orders-in-a-restaurant", "minimum-number-of-frogs-croaking", "build-array-where-you-can-find-the-maximum-exactly-k-comparisons"]}, {"contest_title": "\u7b2c 186 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 186", "contest_title_slug": "weekly-contest-186", "contest_id": 185, "contest_start_time": 1587868200, "contest_duration": 5400, "user_num": 3108, "question_slugs": ["maximum-score-after-splitting-a-string", "maximum-points-you-can-obtain-from-cards", "diagonal-traverse-ii", "constrained-subsequence-sum"]}, {"contest_title": "\u7b2c 187 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 187", "contest_title_slug": "weekly-contest-187", "contest_id": 191, "contest_start_time": 1588473000, "contest_duration": 5400, "user_num": 3109, "question_slugs": ["destination-city", "check-if-all-1s-are-at-least-length-k-places-away", "longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit", "find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows"]}, {"contest_title": "\u7b2c 188 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 188", "contest_title_slug": "weekly-contest-188", "contest_id": 195, "contest_start_time": 1589077800, "contest_duration": 5400, "user_num": 3982, "question_slugs": ["build-an-array-with-stack-operations", "count-triplets-that-can-form-two-arrays-of-equal-xor", "minimum-time-to-collect-all-apples-in-a-tree", "number-of-ways-of-cutting-a-pizza"]}, {"contest_title": "\u7b2c 189 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 189", "contest_title_slug": "weekly-contest-189", "contest_id": 197, "contest_start_time": 1589682600, "contest_duration": 5400, "user_num": 3692, "question_slugs": ["number-of-students-doing-homework-at-a-given-time", "rearrange-words-in-a-sentence", "people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list", "maximum-number-of-darts-inside-of-a-circular-dartboard"]}, {"contest_title": "\u7b2c 190 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 190", "contest_title_slug": "weekly-contest-190", "contest_id": 201, "contest_start_time": 1590287400, "contest_duration": 5400, "user_num": 3352, "question_slugs": ["check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence", "maximum-number-of-vowels-in-a-substring-of-given-length", "pseudo-palindromic-paths-in-a-binary-tree", "max-dot-product-of-two-subsequences"]}, {"contest_title": "\u7b2c 191 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 191", "contest_title_slug": "weekly-contest-191", "contest_id": 203, "contest_start_time": 1590892200, "contest_duration": 5400, "user_num": 3687, "question_slugs": ["maximum-product-of-two-elements-in-an-array", "maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts", "reorder-routes-to-make-all-paths-lead-to-the-city-zero", "probability-of-a-two-boxes-having-the-same-number-of-distinct-balls"]}, {"contest_title": "\u7b2c 192 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 192", "contest_title_slug": "weekly-contest-192", "contest_id": 207, "contest_start_time": 1591497000, "contest_duration": 5400, "user_num": 3615, "question_slugs": ["shuffle-the-array", "the-k-strongest-values-in-an-array", "design-browser-history", "paint-house-iii"]}, {"contest_title": "\u7b2c 193 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 193", "contest_title_slug": "weekly-contest-193", "contest_id": 209, "contest_start_time": 1592101800, "contest_duration": 5400, "user_num": 3804, "question_slugs": ["running-sum-of-1d-array", "least-number-of-unique-integers-after-k-removals", "minimum-number-of-days-to-make-m-bouquets", "kth-ancestor-of-a-tree-node"]}, {"contest_title": "\u7b2c 194 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 194", "contest_title_slug": "weekly-contest-194", "contest_id": 213, "contest_start_time": 1592706600, "contest_duration": 5400, "user_num": 4378, "question_slugs": ["xor-operation-in-an-array", "making-file-names-unique", "avoid-flood-in-the-city", "find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree"]}, {"contest_title": "\u7b2c 195 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 195", "contest_title_slug": "weekly-contest-195", "contest_id": 215, "contest_start_time": 1593311400, "contest_duration": 5400, "user_num": 3401, "question_slugs": ["path-crossing", "check-if-array-pairs-are-divisible-by-k", "number-of-subsequences-that-satisfy-the-given-sum-condition", "max-value-of-equation"]}, {"contest_title": "\u7b2c 196 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 196", "contest_title_slug": "weekly-contest-196", "contest_id": 219, "contest_start_time": 1593916200, "contest_duration": 5400, "user_num": 5507, "question_slugs": ["can-make-arithmetic-progression-from-sequence", "last-moment-before-all-ants-fall-out-of-a-plank", "count-submatrices-with-all-ones", "minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits"]}, {"contest_title": "\u7b2c 197 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 197", "contest_title_slug": "weekly-contest-197", "contest_id": 221, "contest_start_time": 1594521000, "contest_duration": 5400, "user_num": 5275, "question_slugs": ["number-of-good-pairs", "number-of-substrings-with-only-1s", "path-with-maximum-probability", "best-position-for-a-service-centre"]}, {"contest_title": "\u7b2c 198 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 198", "contest_title_slug": "weekly-contest-198", "contest_id": 226, "contest_start_time": 1595125800, "contest_duration": 5400, "user_num": 5780, "question_slugs": ["water-bottles", "number-of-nodes-in-the-sub-tree-with-the-same-label", "maximum-number-of-non-overlapping-substrings", "find-a-value-of-a-mysterious-function-closest-to-target"]}, {"contest_title": "\u7b2c 199 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 199", "contest_title_slug": "weekly-contest-199", "contest_id": 228, "contest_start_time": 1595730600, "contest_duration": 5400, "user_num": 5232, "question_slugs": ["shuffle-string", "minimum-suffix-flips", "number-of-good-leaf-nodes-pairs", "string-compression-ii"]}, {"contest_title": "\u7b2c 200 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 200", "contest_title_slug": "weekly-contest-200", "contest_id": 235, "contest_start_time": 1596335400, "contest_duration": 5400, "user_num": 5476, "question_slugs": ["count-good-triplets", "find-the-winner-of-an-array-game", "minimum-swaps-to-arrange-a-binary-grid", "get-the-maximum-score"]}, {"contest_title": "\u7b2c 201 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 201", "contest_title_slug": "weekly-contest-201", "contest_id": 238, "contest_start_time": 1596940200, "contest_duration": 5400, "user_num": 5615, "question_slugs": ["make-the-string-great", "find-kth-bit-in-nth-binary-string", "maximum-number-of-non-overlapping-subarrays-with-sum-equals-target", "minimum-cost-to-cut-a-stick"]}, {"contest_title": "\u7b2c 202 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 202", "contest_title_slug": "weekly-contest-202", "contest_id": 242, "contest_start_time": 1597545000, "contest_duration": 5400, "user_num": 4990, "question_slugs": ["three-consecutive-odds", "minimum-operations-to-make-array-equal", "magnetic-force-between-two-balls", "minimum-number-of-days-to-eat-n-oranges"]}, {"contest_title": "\u7b2c 203 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 203", "contest_title_slug": "weekly-contest-203", "contest_id": 244, "contest_start_time": 1598149800, "contest_duration": 5400, "user_num": 5285, "question_slugs": ["most-visited-sector-in-a-circular-track", "maximum-number-of-coins-you-can-get", "find-latest-group-of-size-m", "stone-game-v"]}, {"contest_title": "\u7b2c 204 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 204", "contest_title_slug": "weekly-contest-204", "contest_id": 257, "contest_start_time": 1598754600, "contest_duration": 5400, "user_num": 4487, "question_slugs": ["detect-pattern-of-length-m-repeated-k-or-more-times", "maximum-length-of-subarray-with-positive-product", "minimum-number-of-days-to-disconnect-island", "number-of-ways-to-reorder-array-to-get-same-bst"]}, {"contest_title": "\u7b2c 205 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 205", "contest_title_slug": "weekly-contest-205", "contest_id": 260, "contest_start_time": 1599359400, "contest_duration": 5400, "user_num": 4176, "question_slugs": ["replace-all-s-to-avoid-consecutive-repeating-characters", "number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers", "minimum-time-to-make-rope-colorful", "remove-max-number-of-edges-to-keep-graph-fully-traversable"]}, {"contest_title": "\u7b2c 206 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 206", "contest_title_slug": "weekly-contest-206", "contest_id": 267, "contest_start_time": 1599964200, "contest_duration": 5400, "user_num": 4493, "question_slugs": ["special-positions-in-a-binary-matrix", "count-unhappy-friends", "min-cost-to-connect-all-points", "check-if-string-is-transformable-with-substring-sort-operations"]}, {"contest_title": "\u7b2c 207 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 207", "contest_title_slug": "weekly-contest-207", "contest_id": 278, "contest_start_time": 1600569000, "contest_duration": 5400, "user_num": 4116, "question_slugs": ["rearrange-spaces-between-words", "split-a-string-into-the-max-number-of-unique-substrings", "maximum-non-negative-product-in-a-matrix", "minimum-cost-to-connect-two-groups-of-points"]}, {"contest_title": "\u7b2c 208 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 208", "contest_title_slug": "weekly-contest-208", "contest_id": 289, "contest_start_time": 1601173800, "contest_duration": 5400, "user_num": 3582, "question_slugs": ["crawler-log-folder", "maximum-profit-of-operating-a-centennial-wheel", "throne-inheritance", "maximum-number-of-achievable-transfer-requests"]}, {"contest_title": "\u7b2c 209 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 209", "contest_title_slug": "weekly-contest-209", "contest_id": 291, "contest_start_time": 1601778600, "contest_duration": 5400, "user_num": 4023, "question_slugs": ["special-array-with-x-elements-greater-than-or-equal-x", "even-odd-tree", "maximum-number-of-visible-points", "minimum-one-bit-operations-to-make-integers-zero"]}, {"contest_title": "\u7b2c 210 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 210", "contest_title_slug": "weekly-contest-210", "contest_id": 295, "contest_start_time": 1602383400, "contest_duration": 5400, "user_num": 4007, "question_slugs": ["maximum-nesting-depth-of-the-parentheses", "maximal-network-rank", "split-two-strings-to-make-palindrome", "count-subtrees-with-max-distance-between-cities"]}, {"contest_title": "\u7b2c 211 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 211", "contest_title_slug": "weekly-contest-211", "contest_id": 297, "contest_start_time": 1602988200, "contest_duration": 5400, "user_num": 4034, "question_slugs": ["largest-substring-between-two-equal-characters", "lexicographically-smallest-string-after-applying-operations", "best-team-with-no-conflicts", "graph-connectivity-with-threshold"]}, {"contest_title": "\u7b2c 212 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 212", "contest_title_slug": "weekly-contest-212", "contest_id": 301, "contest_start_time": 1603593000, "contest_duration": 5400, "user_num": 4227, "question_slugs": ["slowest-key", "arithmetic-subarrays", "path-with-minimum-effort", "rank-transform-of-a-matrix"]}, {"contest_title": "\u7b2c 213 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 213", "contest_title_slug": "weekly-contest-213", "contest_id": 303, "contest_start_time": 1604197800, "contest_duration": 5400, "user_num": 3827, "question_slugs": ["check-array-formation-through-concatenation", "count-sorted-vowel-strings", "furthest-building-you-can-reach", "kth-smallest-instructions"]}, {"contest_title": "\u7b2c 214 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 214", "contest_title_slug": "weekly-contest-214", "contest_id": 307, "contest_start_time": 1604802600, "contest_duration": 5400, "user_num": 3598, "question_slugs": ["get-maximum-in-generated-array", "minimum-deletions-to-make-character-frequencies-unique", "sell-diminishing-valued-colored-balls", "create-sorted-array-through-instructions"]}, {"contest_title": "\u7b2c 215 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 215", "contest_title_slug": "weekly-contest-215", "contest_id": 309, "contest_start_time": 1605407400, "contest_duration": 5400, "user_num": 4429, "question_slugs": ["design-an-ordered-stream", "determine-if-two-strings-are-close", "minimum-operations-to-reduce-x-to-zero", "maximize-grid-happiness"]}, {"contest_title": "\u7b2c 216 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 216", "contest_title_slug": "weekly-contest-216", "contest_id": 313, "contest_start_time": 1606012200, "contest_duration": 5400, "user_num": 3857, "question_slugs": ["check-if-two-string-arrays-are-equivalent", "smallest-string-with-a-given-numeric-value", "ways-to-make-a-fair-array", "minimum-initial-energy-to-finish-tasks"]}, {"contest_title": "\u7b2c 217 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 217", "contest_title_slug": "weekly-contest-217", "contest_id": 315, "contest_start_time": 1606617000, "contest_duration": 5400, "user_num": 3745, "question_slugs": ["richest-customer-wealth", "find-the-most-competitive-subsequence", "minimum-moves-to-make-array-complementary", "minimize-deviation-in-array"]}, {"contest_title": "\u7b2c 218 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 218", "contest_title_slug": "weekly-contest-218", "contest_id": 319, "contest_start_time": 1607221800, "contest_duration": 5400, "user_num": 3762, "question_slugs": ["goal-parser-interpretation", "max-number-of-k-sum-pairs", "concatenation-of-consecutive-binary-numbers", "minimum-incompatibility"]}, {"contest_title": "\u7b2c 219 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 219", "contest_title_slug": "weekly-contest-219", "contest_id": 322, "contest_start_time": 1607826600, "contest_duration": 5400, "user_num": 3710, "question_slugs": ["count-of-matches-in-tournament", "partitioning-into-minimum-number-of-deci-binary-numbers", "stone-game-vii", "maximum-height-by-stacking-cuboids"]}, {"contest_title": "\u7b2c 220 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 220", "contest_title_slug": "weekly-contest-220", "contest_id": 326, "contest_start_time": 1608431400, "contest_duration": 5400, "user_num": 3691, "question_slugs": ["reformat-phone-number", "maximum-erasure-value", "jump-game-vi", "checking-existence-of-edge-length-limited-paths"]}, {"contest_title": "\u7b2c 221 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 221", "contest_title_slug": "weekly-contest-221", "contest_id": 328, "contest_start_time": 1609036200, "contest_duration": 5400, "user_num": 3398, "question_slugs": ["determine-if-string-halves-are-alike", "maximum-number-of-eaten-apples", "where-will-the-ball-fall", "maximum-xor-with-an-element-from-array"]}, {"contest_title": "\u7b2c 222 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 222", "contest_title_slug": "weekly-contest-222", "contest_id": 332, "contest_start_time": 1609641000, "contest_duration": 5400, "user_num": 3119, "question_slugs": ["maximum-units-on-a-truck", "count-good-meals", "ways-to-split-array-into-three-subarrays", "minimum-operations-to-make-a-subsequence"]}, {"contest_title": "\u7b2c 223 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 223", "contest_title_slug": "weekly-contest-223", "contest_id": 334, "contest_start_time": 1610245800, "contest_duration": 5400, "user_num": 3872, "question_slugs": ["decode-xored-array", "swapping-nodes-in-a-linked-list", "minimize-hamming-distance-after-swap-operations", "find-minimum-time-to-finish-all-jobs"]}, {"contest_title": "\u7b2c 224 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 224", "contest_title_slug": "weekly-contest-224", "contest_id": 338, "contest_start_time": 1610850600, "contest_duration": 5400, "user_num": 3795, "question_slugs": ["number-of-rectangles-that-can-form-the-largest-square", "tuple-with-same-product", "largest-submatrix-with-rearrangements", "cat-and-mouse-ii"]}, {"contest_title": "\u7b2c 225 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 225", "contest_title_slug": "weekly-contest-225", "contest_id": 340, "contest_start_time": 1611455400, "contest_duration": 5400, "user_num": 3853, "question_slugs": ["latest-time-by-replacing-hidden-digits", "change-minimum-characters-to-satisfy-one-of-three-conditions", "find-kth-largest-xor-coordinate-value", "building-boxes"]}, {"contest_title": "\u7b2c 226 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 226", "contest_title_slug": "weekly-contest-226", "contest_id": 344, "contest_start_time": 1612060200, "contest_duration": 5400, "user_num": 4034, "question_slugs": ["maximum-number-of-balls-in-a-box", "restore-the-array-from-adjacent-pairs", "can-you-eat-your-favorite-candy-on-your-favorite-day", "palindrome-partitioning-iv"]}, {"contest_title": "\u7b2c 227 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 227", "contest_title_slug": "weekly-contest-227", "contest_id": 346, "contest_start_time": 1612665000, "contest_duration": 5400, "user_num": 3546, "question_slugs": ["check-if-array-is-sorted-and-rotated", "maximum-score-from-removing-stones", "largest-merge-of-two-strings", "closest-subsequence-sum"]}, {"contest_title": "\u7b2c 228 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 228", "contest_title_slug": "weekly-contest-228", "contest_id": 350, "contest_start_time": 1613269800, "contest_duration": 5400, "user_num": 2484, "question_slugs": ["minimum-changes-to-make-alternating-binary-string", "count-number-of-homogenous-substrings", "minimum-limit-of-balls-in-a-bag", "minimum-degree-of-a-connected-trio-in-a-graph"]}, {"contest_title": "\u7b2c 229 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 229", "contest_title_slug": "weekly-contest-229", "contest_id": 352, "contest_start_time": 1613874600, "contest_duration": 5400, "user_num": 3484, "question_slugs": ["merge-strings-alternately", "minimum-number-of-operations-to-move-all-balls-to-each-box", "maximum-score-from-performing-multiplication-operations", "maximize-palindrome-length-from-subsequences"]}, {"contest_title": "\u7b2c 230 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 230", "contest_title_slug": "weekly-contest-230", "contest_id": 356, "contest_start_time": 1614479400, "contest_duration": 5400, "user_num": 3728, "question_slugs": ["count-items-matching-a-rule", "closest-dessert-cost", "equal-sum-arrays-with-minimum-number-of-operations", "car-fleet-ii"]}, {"contest_title": "\u7b2c 231 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 231", "contest_title_slug": "weekly-contest-231", "contest_id": 358, "contest_start_time": 1615084200, "contest_duration": 5400, "user_num": 4668, "question_slugs": ["check-if-binary-string-has-at-most-one-segment-of-ones", "minimum-elements-to-add-to-form-a-given-sum", "number-of-restricted-paths-from-first-to-last-node", "make-the-xor-of-all-segments-equal-to-zero"]}, {"contest_title": "\u7b2c 232 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 232", "contest_title_slug": "weekly-contest-232", "contest_id": 363, "contest_start_time": 1615689000, "contest_duration": 5400, "user_num": 4802, "question_slugs": ["check-if-one-string-swap-can-make-strings-equal", "find-center-of-star-graph", "maximum-average-pass-ratio", "maximum-score-of-a-good-subarray"]}, {"contest_title": "\u7b2c 233 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 233", "contest_title_slug": "weekly-contest-233", "contest_id": 371, "contest_start_time": 1616293800, "contest_duration": 5400, "user_num": 5010, "question_slugs": ["maximum-ascending-subarray-sum", "number-of-orders-in-the-backlog", "maximum-value-at-a-given-index-in-a-bounded-array", "count-pairs-with-xor-in-a-range"]}, {"contest_title": "\u7b2c 234 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 234", "contest_title_slug": "weekly-contest-234", "contest_id": 375, "contest_start_time": 1616898600, "contest_duration": 5400, "user_num": 4998, "question_slugs": ["number-of-different-integers-in-a-string", "minimum-number-of-operations-to-reinitialize-a-permutation", "evaluate-the-bracket-pairs-of-a-string", "maximize-number-of-nice-divisors"]}, {"contest_title": "\u7b2c 235 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 235", "contest_title_slug": "weekly-contest-235", "contest_id": 377, "contest_start_time": 1617503400, "contest_duration": 5400, "user_num": 4494, "question_slugs": ["truncate-sentence", "finding-the-users-active-minutes", "minimum-absolute-sum-difference", "number-of-different-subsequences-gcds"]}, {"contest_title": "\u7b2c 236 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 236", "contest_title_slug": "weekly-contest-236", "contest_id": 391, "contest_start_time": 1618108200, "contest_duration": 5400, "user_num": 5113, "question_slugs": ["sign-of-the-product-of-an-array", "find-the-winner-of-the-circular-game", "minimum-sideway-jumps", "finding-mk-average"]}, {"contest_title": "\u7b2c 237 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 237", "contest_title_slug": "weekly-contest-237", "contest_id": 393, "contest_start_time": 1618713000, "contest_duration": 5400, "user_num": 4577, "question_slugs": ["check-if-the-sentence-is-pangram", "maximum-ice-cream-bars", "single-threaded-cpu", "find-xor-sum-of-all-pairs-bitwise-and"]}, {"contest_title": "\u7b2c 238 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 238", "contest_title_slug": "weekly-contest-238", "contest_id": 397, "contest_start_time": 1619317800, "contest_duration": 5400, "user_num": 3978, "question_slugs": ["sum-of-digits-in-base-k", "frequency-of-the-most-frequent-element", "longest-substring-of-all-vowels-in-order", "maximum-building-height"]}, {"contest_title": "\u7b2c 239 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 239", "contest_title_slug": "weekly-contest-239", "contest_id": 399, "contest_start_time": 1619922600, "contest_duration": 5400, "user_num": 3907, "question_slugs": ["minimum-distance-to-the-target-element", "splitting-a-string-into-descending-consecutive-values", "minimum-adjacent-swaps-to-reach-the-kth-smallest-number", "minimum-interval-to-include-each-query"]}, {"contest_title": "\u7b2c 240 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 240", "contest_title_slug": "weekly-contest-240", "contest_id": 403, "contest_start_time": 1620527400, "contest_duration": 5400, "user_num": 4307, "question_slugs": ["maximum-population-year", "maximum-distance-between-a-pair-of-values", "maximum-subarray-min-product", "largest-color-value-in-a-directed-graph"]}, {"contest_title": "\u7b2c 241 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 241", "contest_title_slug": "weekly-contest-241", "contest_id": 405, "contest_start_time": 1621132200, "contest_duration": 5400, "user_num": 4491, "question_slugs": ["sum-of-all-subset-xor-totals", "minimum-number-of-swaps-to-make-the-binary-string-alternating", "finding-pairs-with-a-certain-sum", "number-of-ways-to-rearrange-sticks-with-k-sticks-visible"]}, {"contest_title": "\u7b2c 242 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 242", "contest_title_slug": "weekly-contest-242", "contest_id": 409, "contest_start_time": 1621737000, "contest_duration": 5400, "user_num": 4306, "question_slugs": ["longer-contiguous-segments-of-ones-than-zeros", "minimum-speed-to-arrive-on-time", "jump-game-vii", "stone-game-viii"]}, {"contest_title": "\u7b2c 243 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 243", "contest_title_slug": "weekly-contest-243", "contest_id": 411, "contest_start_time": 1622341800, "contest_duration": 5400, "user_num": 4493, "question_slugs": ["check-if-word-equals-summation-of-two-words", "maximum-value-after-insertion", "process-tasks-using-servers", "minimum-skips-to-arrive-at-meeting-on-time"]}, {"contest_title": "\u7b2c 244 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 244", "contest_title_slug": "weekly-contest-244", "contest_id": 415, "contest_start_time": 1622946600, "contest_duration": 5400, "user_num": 4430, "question_slugs": ["determine-whether-matrix-can-be-obtained-by-rotation", "reduction-operations-to-make-the-array-elements-equal", "minimum-number-of-flips-to-make-the-binary-string-alternating", "minimum-space-wasted-from-packaging"]}, {"contest_title": "\u7b2c 245 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 245", "contest_title_slug": "weekly-contest-245", "contest_id": 417, "contest_start_time": 1623551400, "contest_duration": 5400, "user_num": 4271, "question_slugs": ["redistribute-characters-to-make-all-strings-equal", "maximum-number-of-removable-characters", "merge-triplets-to-form-target-triplet", "the-earliest-and-latest-rounds-where-players-compete"]}, {"contest_title": "\u7b2c 246 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 246", "contest_title_slug": "weekly-contest-246", "contest_id": 422, "contest_start_time": 1624156200, "contest_duration": 5400, "user_num": 4136, "question_slugs": ["largest-odd-number-in-string", "the-number-of-full-rounds-you-have-played", "count-sub-islands", "minimum-absolute-difference-queries"]}, {"contest_title": "\u7b2c 247 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 247", "contest_title_slug": "weekly-contest-247", "contest_id": 426, "contest_start_time": 1624761000, "contest_duration": 5400, "user_num": 3981, "question_slugs": ["maximum-product-difference-between-two-pairs", "cyclically-rotating-a-grid", "number-of-wonderful-substrings", "count-ways-to-build-rooms-in-an-ant-colony"]}, {"contest_title": "\u7b2c 248 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 248", "contest_title_slug": "weekly-contest-248", "contest_id": 430, "contest_start_time": 1625365800, "contest_duration": 5400, "user_num": 4451, "question_slugs": ["build-array-from-permutation", "eliminate-maximum-number-of-monsters", "count-good-numbers", "longest-common-subpath"]}, {"contest_title": "\u7b2c 249 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 249", "contest_title_slug": "weekly-contest-249", "contest_id": 432, "contest_start_time": 1625970600, "contest_duration": 5400, "user_num": 4335, "question_slugs": ["concatenation-of-array", "unique-length-3-palindromic-subsequences", "painting-a-grid-with-three-different-colors", "merge-bsts-to-create-single-bst"]}, {"contest_title": "\u7b2c 250 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 250", "contest_title_slug": "weekly-contest-250", "contest_id": 436, "contest_start_time": 1626575400, "contest_duration": 5400, "user_num": 4315, "question_slugs": ["maximum-number-of-words-you-can-type", "add-minimum-number-of-rungs", "maximum-number-of-points-with-cost", "maximum-genetic-difference-query"]}, {"contest_title": "\u7b2c 251 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 251", "contest_title_slug": "weekly-contest-251", "contest_id": 438, "contest_start_time": 1627180200, "contest_duration": 5400, "user_num": 4747, "question_slugs": ["sum-of-digits-of-string-after-convert", "largest-number-after-mutating-substring", "maximum-compatibility-score-sum", "delete-duplicate-folders-in-system"]}, {"contest_title": "\u7b2c 252 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 252", "contest_title_slug": "weekly-contest-252", "contest_id": 442, "contest_start_time": 1627785000, "contest_duration": 5400, "user_num": 4647, "question_slugs": ["three-divisors", "maximum-number-of-weeks-for-which-you-can-work", "minimum-garden-perimeter-to-collect-enough-apples", "count-number-of-special-subsequences"]}, {"contest_title": "\u7b2c 253 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 253", "contest_title_slug": "weekly-contest-253", "contest_id": 444, "contest_start_time": 1628389800, "contest_duration": 5400, "user_num": 4570, "question_slugs": ["check-if-string-is-a-prefix-of-array", "remove-stones-to-minimize-the-total", "minimum-number-of-swaps-to-make-the-string-balanced", "find-the-longest-valid-obstacle-course-at-each-position"]}, {"contest_title": "\u7b2c 254 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 254", "contest_title_slug": "weekly-contest-254", "contest_id": 449, "contest_start_time": 1628994600, "contest_duration": 5400, "user_num": 4349, "question_slugs": ["number-of-strings-that-appear-as-substrings-in-word", "array-with-elements-not-equal-to-average-of-neighbors", "minimum-non-zero-product-of-the-array-elements", "last-day-where-you-can-still-cross"]}, {"contest_title": "\u7b2c 255 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 255", "contest_title_slug": "weekly-contest-255", "contest_id": 457, "contest_start_time": 1629599400, "contest_duration": 5400, "user_num": 4333, "question_slugs": ["find-greatest-common-divisor-of-array", "find-unique-binary-string", "minimize-the-difference-between-target-and-chosen-elements", "find-array-given-subset-sums"]}, {"contest_title": "\u7b2c 256 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 256", "contest_title_slug": "weekly-contest-256", "contest_id": 462, "contest_start_time": 1630204200, "contest_duration": 5400, "user_num": 4136, "question_slugs": ["minimum-difference-between-highest-and-lowest-of-k-scores", "find-the-kth-largest-integer-in-the-array", "minimum-number-of-work-sessions-to-finish-the-tasks", "number-of-unique-good-subsequences"]}, {"contest_title": "\u7b2c 257 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 257", "contest_title_slug": "weekly-contest-257", "contest_id": 464, "contest_start_time": 1630809000, "contest_duration": 5400, "user_num": 4278, "question_slugs": ["count-special-quadruplets", "the-number-of-weak-characters-in-the-game", "first-day-where-you-have-been-in-all-the-rooms", "gcd-sort-of-an-array"]}, {"contest_title": "\u7b2c 258 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 258", "contest_title_slug": "weekly-contest-258", "contest_id": 468, "contest_start_time": 1631413800, "contest_duration": 5400, "user_num": 4519, "question_slugs": ["reverse-prefix-of-word", "number-of-pairs-of-interchangeable-rectangles", "maximum-product-of-the-length-of-two-palindromic-subsequences", "smallest-missing-genetic-value-in-each-subtree"]}, {"contest_title": "\u7b2c 259 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 259", "contest_title_slug": "weekly-contest-259", "contest_id": 474, "contest_start_time": 1632018600, "contest_duration": 5400, "user_num": 3775, "question_slugs": ["final-value-of-variable-after-performing-operations", "sum-of-beauty-in-the-array", "detect-squares", "longest-subsequence-repeated-k-times"]}, {"contest_title": "\u7b2c 260 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 260", "contest_title_slug": "weekly-contest-260", "contest_id": 478, "contest_start_time": 1632623400, "contest_duration": 5400, "user_num": 3654, "question_slugs": ["maximum-difference-between-increasing-elements", "grid-game", "check-if-word-can-be-placed-in-crossword", "the-score-of-students-solving-math-expression"]}, {"contest_title": "\u7b2c 261 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 261", "contest_title_slug": "weekly-contest-261", "contest_id": 481, "contest_start_time": 1633228200, "contest_duration": 5400, "user_num": 3368, "question_slugs": ["minimum-moves-to-convert-string", "find-missing-observations", "stone-game-ix", "smallest-k-length-subsequence-with-occurrences-of-a-letter"]}, {"contest_title": "\u7b2c 262 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 262", "contest_title_slug": "weekly-contest-262", "contest_id": 485, "contest_start_time": 1633833000, "contest_duration": 5400, "user_num": 4261, "question_slugs": ["two-out-of-three", "minimum-operations-to-make-a-uni-value-grid", "stock-price-fluctuation", "partition-array-into-two-arrays-to-minimize-sum-difference"]}, {"contest_title": "\u7b2c 263 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 263", "contest_title_slug": "weekly-contest-263", "contest_id": 487, "contest_start_time": 1634437800, "contest_duration": 5400, "user_num": 4572, "question_slugs": ["check-if-numbers-are-ascending-in-a-sentence", "simple-bank-system", "count-number-of-maximum-bitwise-or-subsets", "second-minimum-time-to-reach-destination"]}, {"contest_title": "\u7b2c 264 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 264", "contest_title_slug": "weekly-contest-264", "contest_id": 491, "contest_start_time": 1635042600, "contest_duration": 5400, "user_num": 4659, "question_slugs": ["number-of-valid-words-in-a-sentence", "next-greater-numerically-balanced-number", "count-nodes-with-the-highest-score", "parallel-courses-iii"]}, {"contest_title": "\u7b2c 265 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 265", "contest_title_slug": "weekly-contest-265", "contest_id": 493, "contest_start_time": 1635647400, "contest_duration": 5400, "user_num": 4182, "question_slugs": ["smallest-index-with-equal-value", "find-the-minimum-and-maximum-number-of-nodes-between-critical-points", "minimum-operations-to-convert-number", "check-if-an-original-string-exists-given-two-encoded-strings"]}, {"contest_title": "\u7b2c 266 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 266", "contest_title_slug": "weekly-contest-266", "contest_id": 498, "contest_start_time": 1636252200, "contest_duration": 5400, "user_num": 4385, "question_slugs": ["count-vowel-substrings-of-a-string", "vowels-of-all-substrings", "minimized-maximum-of-products-distributed-to-any-store", "maximum-path-quality-of-a-graph"]}, {"contest_title": "\u7b2c 267 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 267", "contest_title_slug": "weekly-contest-267", "contest_id": 500, "contest_start_time": 1636857000, "contest_duration": 5400, "user_num": 4365, "question_slugs": ["time-needed-to-buy-tickets", "reverse-nodes-in-even-length-groups", "decode-the-slanted-ciphertext", "process-restricted-friend-requests"]}, {"contest_title": "\u7b2c 268 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 268", "contest_title_slug": "weekly-contest-268", "contest_id": 504, "contest_start_time": 1637461800, "contest_duration": 5400, "user_num": 4398, "question_slugs": ["two-furthest-houses-with-different-colors", "watering-plants", "range-frequency-queries", "sum-of-k-mirror-numbers"]}, {"contest_title": "\u7b2c 269 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 269", "contest_title_slug": "weekly-contest-269", "contest_id": 506, "contest_start_time": 1638066600, "contest_duration": 5400, "user_num": 4293, "question_slugs": ["find-target-indices-after-sorting-array", "k-radius-subarray-averages", "removing-minimum-and-maximum-from-array", "find-all-people-with-secret"]}, {"contest_title": "\u7b2c 270 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 270", "contest_title_slug": "weekly-contest-270", "contest_id": 510, "contest_start_time": 1638671400, "contest_duration": 5400, "user_num": 4748, "question_slugs": ["finding-3-digit-even-numbers", "delete-the-middle-node-of-a-linked-list", "step-by-step-directions-from-a-binary-tree-node-to-another", "valid-arrangement-of-pairs"]}, {"contest_title": "\u7b2c 271 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 271", "contest_title_slug": "weekly-contest-271", "contest_id": 512, "contest_start_time": 1639276200, "contest_duration": 5400, "user_num": 4562, "question_slugs": ["rings-and-rods", "sum-of-subarray-ranges", "watering-plants-ii", "maximum-fruits-harvested-after-at-most-k-steps"]}, {"contest_title": "\u7b2c 272 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 272", "contest_title_slug": "weekly-contest-272", "contest_id": 516, "contest_start_time": 1639881000, "contest_duration": 5400, "user_num": 4698, "question_slugs": ["find-first-palindromic-string-in-the-array", "adding-spaces-to-a-string", "number-of-smooth-descent-periods-of-a-stock", "minimum-operations-to-make-the-array-k-increasing"]}, {"contest_title": "\u7b2c 273 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 273", "contest_title_slug": "weekly-contest-273", "contest_id": 518, "contest_start_time": 1640485800, "contest_duration": 5400, "user_num": 4368, "question_slugs": ["a-number-after-a-double-reversal", "execution-of-all-suffix-instructions-staying-in-a-grid", "intervals-between-identical-elements", "recover-the-original-array"]}, {"contest_title": "\u7b2c 274 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 274", "contest_title_slug": "weekly-contest-274", "contest_id": 522, "contest_start_time": 1641090600, "contest_duration": 5400, "user_num": 4109, "question_slugs": ["check-if-all-as-appears-before-all-bs", "number-of-laser-beams-in-a-bank", "destroying-asteroids", "maximum-employees-to-be-invited-to-a-meeting"]}, {"contest_title": "\u7b2c 275 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 275", "contest_title_slug": "weekly-contest-275", "contest_id": 524, "contest_start_time": 1641695400, "contest_duration": 5400, "user_num": 4787, "question_slugs": ["check-if-every-row-and-column-contains-all-numbers", "minimum-swaps-to-group-all-1s-together-ii", "count-words-obtained-after-adding-a-letter", "earliest-possible-day-of-full-bloom"]}, {"contest_title": "\u7b2c 276 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 276", "contest_title_slug": "weekly-contest-276", "contest_id": 528, "contest_start_time": 1642300200, "contest_duration": 5400, "user_num": 5244, "question_slugs": ["divide-a-string-into-groups-of-size-k", "minimum-moves-to-reach-target-score", "solving-questions-with-brainpower", "maximum-running-time-of-n-computers"]}, {"contest_title": "\u7b2c 277 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 277", "contest_title_slug": "weekly-contest-277", "contest_id": 530, "contest_start_time": 1642905000, "contest_duration": 5400, "user_num": 5060, "question_slugs": ["count-elements-with-strictly-smaller-and-greater-elements", "rearrange-array-elements-by-sign", "find-all-lonely-numbers-in-the-array", "maximum-good-people-based-on-statements"]}, {"contest_title": "\u7b2c 278 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 278", "contest_title_slug": "weekly-contest-278", "contest_id": 534, "contest_start_time": 1643509800, "contest_duration": 5400, "user_num": 4643, "question_slugs": ["keep-multiplying-found-values-by-two", "all-divisions-with-the-highest-score-of-a-binary-array", "find-substring-with-given-hash-value", "groups-of-strings"]}, {"contest_title": "\u7b2c 279 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 279", "contest_title_slug": "weekly-contest-279", "contest_id": 536, "contest_start_time": 1644114600, "contest_duration": 5400, "user_num": 4132, "question_slugs": ["sort-even-and-odd-indices-independently", "smallest-value-of-the-rearranged-number", "design-bitset", "minimum-time-to-remove-all-cars-containing-illegal-goods"]}, {"contest_title": "\u7b2c 280 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 280", "contest_title_slug": "weekly-contest-280", "contest_id": 540, "contest_start_time": 1644719400, "contest_duration": 5400, "user_num": 5834, "question_slugs": ["count-operations-to-obtain-zero", "minimum-operations-to-make-the-array-alternating", "removing-minimum-number-of-magic-beans", "maximum-and-sum-of-array"]}, {"contest_title": "\u7b2c 281 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 281", "contest_title_slug": "weekly-contest-281", "contest_id": 542, "contest_start_time": 1645324200, "contest_duration": 6000, "user_num": 6005, "question_slugs": ["count-integers-with-even-digit-sum", "merge-nodes-in-between-zeros", "construct-string-with-repeat-limit", "count-array-pairs-divisible-by-k"]}, {"contest_title": "\u7b2c 282 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 282", "contest_title_slug": "weekly-contest-282", "contest_id": 546, "contest_start_time": 1645929000, "contest_duration": 5400, "user_num": 7164, "question_slugs": ["counting-words-with-a-given-prefix", "minimum-number-of-steps-to-make-two-strings-anagram-ii", "minimum-time-to-complete-trips", "minimum-time-to-finish-the-race"]}, {"contest_title": "\u7b2c 283 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 283", "contest_title_slug": "weekly-contest-283", "contest_id": 551, "contest_start_time": 1646533800, "contest_duration": 5400, "user_num": 7817, "question_slugs": ["cells-in-a-range-on-an-excel-sheet", "append-k-integers-with-minimal-sum", "create-binary-tree-from-descriptions", "replace-non-coprime-numbers-in-array"]}, {"contest_title": "\u7b2c 284 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 284", "contest_title_slug": "weekly-contest-284", "contest_id": 555, "contest_start_time": 1647138600, "contest_duration": 5400, "user_num": 8483, "question_slugs": ["find-all-k-distant-indices-in-an-array", "count-artifacts-that-can-be-extracted", "maximize-the-topmost-element-after-k-moves", "minimum-weighted-subgraph-with-the-required-paths"]}, {"contest_title": "\u7b2c 285 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 285", "contest_title_slug": "weekly-contest-285", "contest_id": 558, "contest_start_time": 1647743400, "contest_duration": 5400, "user_num": 7501, "question_slugs": ["count-hills-and-valleys-in-an-array", "count-collisions-on-a-road", "maximum-points-in-an-archery-competition", "longest-substring-of-one-repeating-character"]}, {"contest_title": "\u7b2c 286 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 286", "contest_title_slug": "weekly-contest-286", "contest_id": 564, "contest_start_time": 1648348200, "contest_duration": 5400, "user_num": 7248, "question_slugs": ["find-the-difference-of-two-arrays", "minimum-deletions-to-make-array-beautiful", "find-palindrome-with-fixed-length", "maximum-value-of-k-coins-from-piles"]}, {"contest_title": "\u7b2c 287 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 287", "contest_title_slug": "weekly-contest-287", "contest_id": 569, "contest_start_time": 1648953000, "contest_duration": 5400, "user_num": 6811, "question_slugs": ["minimum-number-of-operations-to-convert-time", "find-players-with-zero-or-one-losses", "maximum-candies-allocated-to-k-children", "encrypt-and-decrypt-strings"]}, {"contest_title": "\u7b2c 288 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 288", "contest_title_slug": "weekly-contest-288", "contest_id": 573, "contest_start_time": 1649557800, "contest_duration": 5400, "user_num": 6926, "question_slugs": ["largest-number-after-digit-swaps-by-parity", "minimize-result-by-adding-parentheses-to-expression", "maximum-product-after-k-increments", "maximum-total-beauty-of-the-gardens"]}, {"contest_title": "\u7b2c 289 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 289", "contest_title_slug": "weekly-contest-289", "contest_id": 576, "contest_start_time": 1650162600, "contest_duration": 5400, "user_num": 7293, "question_slugs": ["calculate-digit-sum-of-a-string", "minimum-rounds-to-complete-all-tasks", "maximum-trailing-zeros-in-a-cornered-path", "longest-path-with-different-adjacent-characters"]}, {"contest_title": "\u7b2c 290 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 290", "contest_title_slug": "weekly-contest-290", "contest_id": 582, "contest_start_time": 1650767400, "contest_duration": 5400, "user_num": 6275, "question_slugs": ["intersection-of-multiple-arrays", "count-lattice-points-inside-a-circle", "count-number-of-rectangles-containing-each-point", "number-of-flowers-in-full-bloom"]}, {"contest_title": "\u7b2c 291 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 291", "contest_title_slug": "weekly-contest-291", "contest_id": 587, "contest_start_time": 1651372200, "contest_duration": 5400, "user_num": 6574, "question_slugs": ["remove-digit-from-number-to-maximize-result", "minimum-consecutive-cards-to-pick-up", "k-divisible-elements-subarrays", "total-appeal-of-a-string"]}, {"contest_title": "\u7b2c 292 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 292", "contest_title_slug": "weekly-contest-292", "contest_id": 591, "contest_start_time": 1651977000, "contest_duration": 5400, "user_num": 6884, "question_slugs": ["largest-3-same-digit-number-in-string", "count-nodes-equal-to-average-of-subtree", "count-number-of-texts", "check-if-there-is-a-valid-parentheses-string-path"]}, {"contest_title": "\u7b2c 293 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 293", "contest_title_slug": "weekly-contest-293", "contest_id": 593, "contest_start_time": 1652581800, "contest_duration": 5400, "user_num": 7357, "question_slugs": ["find-resultant-array-after-removing-anagrams", "maximum-consecutive-floors-without-special-floors", "largest-combination-with-bitwise-and-greater-than-zero", "count-integers-in-intervals"]}, {"contest_title": "\u7b2c 294 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 294", "contest_title_slug": "weekly-contest-294", "contest_id": 599, "contest_start_time": 1653186600, "contest_duration": 5400, "user_num": 6640, "question_slugs": ["percentage-of-letter-in-string", "maximum-bags-with-full-capacity-of-rocks", "minimum-lines-to-represent-a-line-chart", "sum-of-total-strength-of-wizards"]}, {"contest_title": "\u7b2c 295 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 295", "contest_title_slug": "weekly-contest-295", "contest_id": 605, "contest_start_time": 1653791400, "contest_duration": 5400, "user_num": 6447, "question_slugs": ["rearrange-characters-to-make-target-string", "apply-discount-to-prices", "steps-to-make-array-non-decreasing", "minimum-obstacle-removal-to-reach-corner"]}, {"contest_title": "\u7b2c 296 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 296", "contest_title_slug": "weekly-contest-296", "contest_id": 609, "contest_start_time": 1654396200, "contest_duration": 5400, "user_num": 5721, "question_slugs": ["min-max-game", "partition-array-such-that-maximum-difference-is-k", "replace-elements-in-an-array", "design-a-text-editor"]}, {"contest_title": "\u7b2c 297 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 297", "contest_title_slug": "weekly-contest-297", "contest_id": 611, "contest_start_time": 1655001000, "contest_duration": 5400, "user_num": 5915, "question_slugs": ["calculate-amount-paid-in-taxes", "minimum-path-cost-in-a-grid", "fair-distribution-of-cookies", "naming-a-company"]}, {"contest_title": "\u7b2c 298 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 298", "contest_title_slug": "weekly-contest-298", "contest_id": 615, "contest_start_time": 1655605800, "contest_duration": 5400, "user_num": 6228, "question_slugs": ["greatest-english-letter-in-upper-and-lower-case", "sum-of-numbers-with-units-digit-k", "longest-binary-subsequence-less-than-or-equal-to-k", "selling-pieces-of-wood"]}, {"contest_title": "\u7b2c 299 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 299", "contest_title_slug": "weekly-contest-299", "contest_id": 618, "contest_start_time": 1656210600, "contest_duration": 5400, "user_num": 6108, "question_slugs": ["check-if-matrix-is-x-matrix", "count-number-of-ways-to-place-houses", "maximum-score-of-spliced-array", "minimum-score-after-removals-on-a-tree"]}, {"contest_title": "\u7b2c 300 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 300", "contest_title_slug": "weekly-contest-300", "contest_id": 647, "contest_start_time": 1656815400, "contest_duration": 5400, "user_num": 6792, "question_slugs": ["decode-the-message", "spiral-matrix-iv", "number-of-people-aware-of-a-secret", "number-of-increasing-paths-in-a-grid"]}, {"contest_title": "\u7b2c 301 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 301", "contest_title_slug": "weekly-contest-301", "contest_id": 649, "contest_start_time": 1657420200, "contest_duration": 5400, "user_num": 7133, "question_slugs": ["minimum-amount-of-time-to-fill-cups", "smallest-number-in-infinite-set", "move-pieces-to-obtain-a-string", "count-the-number-of-ideal-arrays"]}, {"contest_title": "\u7b2c 302 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 302", "contest_title_slug": "weekly-contest-302", "contest_id": 653, "contest_start_time": 1658025000, "contest_duration": 5400, "user_num": 7092, "question_slugs": ["maximum-number-of-pairs-in-array", "max-sum-of-a-pair-with-equal-sum-of-digits", "query-kth-smallest-trimmed-number", "minimum-deletions-to-make-array-divisible"]}, {"contest_title": "\u7b2c 303 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 303", "contest_title_slug": "weekly-contest-303", "contest_id": 655, "contest_start_time": 1658629800, "contest_duration": 5400, "user_num": 7032, "question_slugs": ["first-letter-to-appear-twice", "equal-row-and-column-pairs", "design-a-food-rating-system", "number-of-excellent-pairs"]}, {"contest_title": "\u7b2c 304 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 304", "contest_title_slug": "weekly-contest-304", "contest_id": 659, "contest_start_time": 1659234600, "contest_duration": 5400, "user_num": 7372, "question_slugs": ["make-array-zero-by-subtracting-equal-amounts", "maximum-number-of-groups-entering-a-competition", "find-closest-node-to-given-two-nodes", "longest-cycle-in-a-graph"]}, {"contest_title": "\u7b2c 305 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 305", "contest_title_slug": "weekly-contest-305", "contest_id": 663, "contest_start_time": 1659839400, "contest_duration": 5400, "user_num": 7465, "question_slugs": ["number-of-arithmetic-triplets", "reachable-nodes-with-restrictions", "check-if-there-is-a-valid-partition-for-the-array", "longest-ideal-subsequence"]}, {"contest_title": "\u7b2c 306 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 306", "contest_title_slug": "weekly-contest-306", "contest_id": 669, "contest_start_time": 1660444200, "contest_duration": 5400, "user_num": 7500, "question_slugs": ["largest-local-values-in-a-matrix", "node-with-highest-edge-score", "construct-smallest-number-from-di-string", "count-special-integers"]}, {"contest_title": "\u7b2c 307 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 307", "contest_title_slug": "weekly-contest-307", "contest_id": 671, "contest_start_time": 1661049000, "contest_duration": 5400, "user_num": 7064, "question_slugs": ["minimum-hours-of-training-to-win-a-competition", "largest-palindromic-number", "amount-of-time-for-binary-tree-to-be-infected", "find-the-k-sum-of-an-array"]}, {"contest_title": "\u7b2c 308 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 308", "contest_title_slug": "weekly-contest-308", "contest_id": 689, "contest_start_time": 1661653800, "contest_duration": 5400, "user_num": 6394, "question_slugs": ["longest-subsequence-with-limited-sum", "removing-stars-from-a-string", "minimum-amount-of-time-to-collect-garbage", "build-a-matrix-with-conditions"]}, {"contest_title": "\u7b2c 309 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 309", "contest_title_slug": "weekly-contest-309", "contest_id": 693, "contest_start_time": 1662258600, "contest_duration": 5400, "user_num": 7972, "question_slugs": ["check-distances-between-same-letters", "number-of-ways-to-reach-a-position-after-exactly-k-steps", "longest-nice-subarray", "meeting-rooms-iii"]}, {"contest_title": "\u7b2c 310 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 310", "contest_title_slug": "weekly-contest-310", "contest_id": 704, "contest_start_time": 1662863400, "contest_duration": 5400, "user_num": 6081, "question_slugs": ["most-frequent-even-element", "optimal-partition-of-string", "divide-intervals-into-minimum-number-of-groups", "longest-increasing-subsequence-ii"]}, {"contest_title": "\u7b2c 311 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 311", "contest_title_slug": "weekly-contest-311", "contest_id": 741, "contest_start_time": 1663468200, "contest_duration": 5400, "user_num": 6710, "question_slugs": ["smallest-even-multiple", "length-of-the-longest-alphabetical-continuous-substring", "reverse-odd-levels-of-binary-tree", "sum-of-prefix-scores-of-strings"]}, {"contest_title": "\u7b2c 312 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 312", "contest_title_slug": "weekly-contest-312", "contest_id": 746, "contest_start_time": 1664073000, "contest_duration": 5400, "user_num": 6638, "question_slugs": ["sort-the-people", "longest-subarray-with-maximum-bitwise-and", "find-all-good-indices", "number-of-good-paths"]}, {"contest_title": "\u7b2c 313 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 313", "contest_title_slug": "weekly-contest-313", "contest_id": 750, "contest_start_time": 1664677800, "contest_duration": 5400, "user_num": 5445, "question_slugs": ["number-of-common-factors", "maximum-sum-of-an-hourglass", "minimize-xor", "maximum-deletions-on-a-string"]}, {"contest_title": "\u7b2c 314 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 314", "contest_title_slug": "weekly-contest-314", "contest_id": 756, "contest_start_time": 1665282600, "contest_duration": 5400, "user_num": 4838, "question_slugs": ["the-employee-that-worked-on-the-longest-task", "find-the-original-array-of-prefix-xor", "using-a-robot-to-print-the-lexicographically-smallest-string", "paths-in-matrix-whose-sum-is-divisible-by-k"]}, {"contest_title": "\u7b2c 315 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 315", "contest_title_slug": "weekly-contest-315", "contest_id": 759, "contest_start_time": 1665887400, "contest_duration": 5400, "user_num": 6490, "question_slugs": ["largest-positive-integer-that-exists-with-its-negative", "count-number-of-distinct-integers-after-reverse-operations", "sum-of-number-and-its-reverse", "count-subarrays-with-fixed-bounds"]}, {"contest_title": "\u7b2c 316 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 316", "contest_title_slug": "weekly-contest-316", "contest_id": 764, "contest_start_time": 1666492200, "contest_duration": 5400, "user_num": 6387, "question_slugs": ["determine-if-two-events-have-conflict", "number-of-subarrays-with-gcd-equal-to-k", "minimum-cost-to-make-array-equal", "minimum-number-of-operations-to-make-arrays-similar"]}, {"contest_title": "\u7b2c 317 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 317", "contest_title_slug": "weekly-contest-317", "contest_id": 767, "contest_start_time": 1667097000, "contest_duration": 5400, "user_num": 5660, "question_slugs": ["average-value-of-even-numbers-that-are-divisible-by-three", "most-popular-video-creator", "minimum-addition-to-make-integer-beautiful", "height-of-binary-tree-after-subtree-removal-queries"]}, {"contest_title": "\u7b2c 318 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 318", "contest_title_slug": "weekly-contest-318", "contest_id": 771, "contest_start_time": 1667701800, "contest_duration": 5400, "user_num": 5670, "question_slugs": ["apply-operations-to-an-array", "maximum-sum-of-distinct-subarrays-with-length-k", "total-cost-to-hire-k-workers", "minimum-total-distance-traveled"]}, {"contest_title": "\u7b2c 319 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 319", "contest_title_slug": "weekly-contest-319", "contest_id": 773, "contest_start_time": 1668306600, "contest_duration": 5400, "user_num": 6175, "question_slugs": ["convert-the-temperature", "number-of-subarrays-with-lcm-equal-to-k", "minimum-number-of-operations-to-sort-a-binary-tree-by-level", "maximum-number-of-non-overlapping-palindrome-substrings"]}, {"contest_title": "\u7b2c 320 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 320", "contest_title_slug": "weekly-contest-320", "contest_id": 777, "contest_start_time": 1668911400, "contest_duration": 5400, "user_num": 5678, "question_slugs": ["number-of-unequal-triplets-in-array", "closest-nodes-queries-in-a-binary-search-tree", "minimum-fuel-cost-to-report-to-the-capital", "number-of-beautiful-partitions"]}, {"contest_title": "\u7b2c 321 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 321", "contest_title_slug": "weekly-contest-321", "contest_id": 779, "contest_start_time": 1669516200, "contest_duration": 5400, "user_num": 5115, "question_slugs": ["find-the-pivot-integer", "append-characters-to-string-to-make-subsequence", "remove-nodes-from-linked-list", "count-subarrays-with-median-k"]}, {"contest_title": "\u7b2c 322 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 322", "contest_title_slug": "weekly-contest-322", "contest_id": 783, "contest_start_time": 1670121000, "contest_duration": 5400, "user_num": 5085, "question_slugs": ["circular-sentence", "divide-players-into-teams-of-equal-skill", "minimum-score-of-a-path-between-two-cities", "divide-nodes-into-the-maximum-number-of-groups"]}, {"contest_title": "\u7b2c 323 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 323", "contest_title_slug": "weekly-contest-323", "contest_id": 785, "contest_start_time": 1670725800, "contest_duration": 5400, "user_num": 4671, "question_slugs": ["delete-greatest-value-in-each-row", "longest-square-streak-in-an-array", "design-memory-allocator", "maximum-number-of-points-from-grid-queries"]}, {"contest_title": "\u7b2c 324 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 324", "contest_title_slug": "weekly-contest-324", "contest_id": 790, "contest_start_time": 1671330600, "contest_duration": 5400, "user_num": 4167, "question_slugs": ["count-pairs-of-similar-strings", "smallest-value-after-replacing-with-sum-of-prime-factors", "add-edges-to-make-degrees-of-all-nodes-even", "cycle-length-queries-in-a-tree"]}, {"contest_title": "\u7b2c 325 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 325", "contest_title_slug": "weekly-contest-325", "contest_id": 795, "contest_start_time": 1671935400, "contest_duration": 5400, "user_num": 3530, "question_slugs": ["shortest-distance-to-target-string-in-a-circular-array", "take-k-of-each-character-from-left-and-right", "maximum-tastiness-of-candy-basket", "number-of-great-partitions"]}, {"contest_title": "\u7b2c 326 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 326", "contest_title_slug": "weekly-contest-326", "contest_id": 799, "contest_start_time": 1672540200, "contest_duration": 5400, "user_num": 3873, "question_slugs": ["count-the-digits-that-divide-a-number", "distinct-prime-factors-of-product-of-array", "partition-string-into-substrings-with-values-at-most-k", "closest-prime-numbers-in-range"]}, {"contest_title": "\u7b2c 327 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 327", "contest_title_slug": "weekly-contest-327", "contest_id": 801, "contest_start_time": 1673145000, "contest_duration": 5400, "user_num": 4518, "question_slugs": ["maximum-count-of-positive-integer-and-negative-integer", "maximal-score-after-applying-k-operations", "make-number-of-distinct-characters-equal", "time-to-cross-a-bridge"]}, {"contest_title": "\u7b2c 328 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 328", "contest_title_slug": "weekly-contest-328", "contest_id": 805, "contest_start_time": 1673749800, "contest_duration": 5400, "user_num": 4776, "question_slugs": ["difference-between-element-sum-and-digit-sum-of-an-array", "increment-submatrices-by-one", "count-the-number-of-good-subarrays", "difference-between-maximum-and-minimum-price-sum"]}, {"contest_title": "\u7b2c 329 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 329", "contest_title_slug": "weekly-contest-329", "contest_id": 807, "contest_start_time": 1674354600, "contest_duration": 5400, "user_num": 2591, "question_slugs": ["alternating-digit-sum", "sort-the-students-by-their-kth-score", "apply-bitwise-operations-to-make-strings-equal", "minimum-cost-to-split-an-array"]}, {"contest_title": "\u7b2c 330 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 330", "contest_title_slug": "weekly-contest-330", "contest_id": 811, "contest_start_time": 1674959400, "contest_duration": 5400, "user_num": 3399, "question_slugs": ["count-distinct-numbers-on-board", "count-collisions-of-monkeys-on-a-polygon", "put-marbles-in-bags", "count-increasing-quadruplets"]}, {"contest_title": "\u7b2c 331 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 331", "contest_title_slug": "weekly-contest-331", "contest_id": 813, "contest_start_time": 1675564200, "contest_duration": 5400, "user_num": 4256, "question_slugs": ["take-gifts-from-the-richest-pile", "count-vowel-strings-in-ranges", "house-robber-iv", "rearranging-fruits"]}, {"contest_title": "\u7b2c 332 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 332", "contest_title_slug": "weekly-contest-332", "contest_id": 817, "contest_start_time": 1676169000, "contest_duration": 5400, "user_num": 4547, "question_slugs": ["find-the-array-concatenation-value", "count-the-number-of-fair-pairs", "substring-xor-queries", "subsequence-with-the-minimum-score"]}, {"contest_title": "\u7b2c 333 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 333", "contest_title_slug": "weekly-contest-333", "contest_id": 819, "contest_start_time": 1676773800, "contest_duration": 5400, "user_num": 4969, "question_slugs": ["merge-two-2d-arrays-by-summing-values", "minimum-operations-to-reduce-an-integer-to-0", "count-the-number-of-square-free-subsets", "find-the-string-with-lcp"]}, {"contest_title": "\u7b2c 334 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 334", "contest_title_slug": "weekly-contest-334", "contest_id": 823, "contest_start_time": 1677378600, "contest_duration": 5400, "user_num": 5501, "question_slugs": ["left-and-right-sum-differences", "find-the-divisibility-array-of-a-string", "find-the-maximum-number-of-marked-indices", "minimum-time-to-visit-a-cell-in-a-grid"]}, {"contest_title": "\u7b2c 335 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 335", "contest_title_slug": "weekly-contest-335", "contest_id": 825, "contest_start_time": 1677983400, "contest_duration": 5400, "user_num": 6019, "question_slugs": ["pass-the-pillow", "kth-largest-sum-in-a-binary-tree", "split-the-array-to-make-coprime-products", "number-of-ways-to-earn-points"]}, {"contest_title": "\u7b2c 336 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 336", "contest_title_slug": "weekly-contest-336", "contest_id": 833, "contest_start_time": 1678588200, "contest_duration": 5400, "user_num": 5897, "question_slugs": ["count-the-number-of-vowel-strings-in-range", "rearrange-array-to-maximize-prefix-score", "count-the-number-of-beautiful-subarrays", "minimum-time-to-complete-all-tasks"]}, {"contest_title": "\u7b2c 337 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 337", "contest_title_slug": "weekly-contest-337", "contest_id": 839, "contest_start_time": 1679193000, "contest_duration": 5400, "user_num": 5628, "question_slugs": ["number-of-even-and-odd-bits", "check-knight-tour-configuration", "the-number-of-beautiful-subsets", "smallest-missing-non-negative-integer-after-operations"]}, {"contest_title": "\u7b2c 338 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 338", "contest_title_slug": "weekly-contest-338", "contest_id": 843, "contest_start_time": 1679797800, "contest_duration": 5400, "user_num": 5594, "question_slugs": ["k-items-with-the-maximum-sum", "prime-subtraction-operation", "minimum-operations-to-make-all-array-elements-equal", "collect-coins-in-a-tree"]}, {"contest_title": "\u7b2c 339 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 339", "contest_title_slug": "weekly-contest-339", "contest_id": 850, "contest_start_time": 1680402600, "contest_duration": 5400, "user_num": 5180, "question_slugs": ["find-the-longest-balanced-substring-of-a-binary-string", "convert-an-array-into-a-2d-array-with-conditions", "mice-and-cheese", "minimum-reverse-operations"]}, {"contest_title": "\u7b2c 340 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 340", "contest_title_slug": "weekly-contest-340", "contest_id": 854, "contest_start_time": 1681007400, "contest_duration": 5400, "user_num": 4937, "question_slugs": ["prime-in-diagonal", "sum-of-distances", "minimize-the-maximum-difference-of-pairs", "minimum-number-of-visited-cells-in-a-grid"]}, {"contest_title": "\u7b2c 341 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 341", "contest_title_slug": "weekly-contest-341", "contest_id": 856, "contest_start_time": 1681612200, "contest_duration": 5400, "user_num": 4792, "question_slugs": ["row-with-maximum-ones", "find-the-maximum-divisibility-score", "minimum-additions-to-make-valid-string", "minimize-the-total-price-of-the-trips"]}, {"contest_title": "\u7b2c 342 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 342", "contest_title_slug": "weekly-contest-342", "contest_id": 860, "contest_start_time": 1682217000, "contest_duration": 5400, "user_num": 3702, "question_slugs": ["calculate-delayed-arrival-time", "sum-multiples", "sliding-subarray-beauty", "minimum-number-of-operations-to-make-all-array-elements-equal-to-1"]}, {"contest_title": "\u7b2c 343 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 343", "contest_title_slug": "weekly-contest-343", "contest_id": 863, "contest_start_time": 1682821800, "contest_duration": 5400, "user_num": 3313, "question_slugs": ["determine-the-winner-of-a-bowling-game", "first-completely-painted-row-or-column", "minimum-cost-of-a-path-with-special-roads", "lexicographically-smallest-beautiful-string"]}, {"contest_title": "\u7b2c 344 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 344", "contest_title_slug": "weekly-contest-344", "contest_id": 867, "contest_start_time": 1683426600, "contest_duration": 5400, "user_num": 3986, "question_slugs": ["find-the-distinct-difference-array", "frequency-tracker", "number-of-adjacent-elements-with-the-same-color", "make-costs-of-paths-equal-in-a-binary-tree"]}, {"contest_title": "\u7b2c 345 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 345", "contest_title_slug": "weekly-contest-345", "contest_id": 870, "contest_start_time": 1684031400, "contest_duration": 5400, "user_num": 4165, "question_slugs": ["find-the-losers-of-the-circular-game", "neighboring-bitwise-xor", "maximum-number-of-moves-in-a-grid", "count-the-number-of-complete-components"]}, {"contest_title": "\u7b2c 346 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 346", "contest_title_slug": "weekly-contest-346", "contest_id": 874, "contest_start_time": 1684636200, "contest_duration": 5400, "user_num": 4035, "question_slugs": ["minimum-string-length-after-removing-substrings", "lexicographically-smallest-palindrome", "find-the-punishment-number-of-an-integer", "modify-graph-edge-weights"]}, {"contest_title": "\u7b2c 347 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 347", "contest_title_slug": "weekly-contest-347", "contest_id": 876, "contest_start_time": 1685241000, "contest_duration": 5400, "user_num": 3836, "question_slugs": ["remove-trailing-zeros-from-a-string", "difference-of-number-of-distinct-values-on-diagonals", "minimum-cost-to-make-all-characters-equal", "maximum-strictly-increasing-cells-in-a-matrix"]}, {"contest_title": "\u7b2c 348 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 348", "contest_title_slug": "weekly-contest-348", "contest_id": 880, "contest_start_time": 1685845800, "contest_duration": 5400, "user_num": 3909, "question_slugs": ["minimize-string-length", "semi-ordered-permutation", "sum-of-matrix-after-queries", "count-of-integers"]}, {"contest_title": "\u7b2c 349 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 349", "contest_title_slug": "weekly-contest-349", "contest_id": 882, "contest_start_time": 1686450600, "contest_duration": 5400, "user_num": 3714, "question_slugs": ["neither-minimum-nor-maximum", "lexicographically-smallest-string-after-substring-operation", "collecting-chocolates", "maximum-sum-queries"]}, {"contest_title": "\u7b2c 350 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 350", "contest_title_slug": "weekly-contest-350", "contest_id": 886, "contest_start_time": 1687055400, "contest_duration": 5400, "user_num": 3580, "question_slugs": ["total-distance-traveled", "find-the-value-of-the-partition", "special-permutations", "painting-the-walls"]}, {"contest_title": "\u7b2c 351 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 351", "contest_title_slug": "weekly-contest-351", "contest_id": 888, "contest_start_time": 1687660200, "contest_duration": 5400, "user_num": 2471, "question_slugs": ["number-of-beautiful-pairs", "minimum-operations-to-make-the-integer-zero", "ways-to-split-array-into-good-subarrays", "robot-collisions"]}, {"contest_title": "\u7b2c 352 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 352", "contest_title_slug": "weekly-contest-352", "contest_id": 892, "contest_start_time": 1688265000, "contest_duration": 5400, "user_num": 3437, "question_slugs": ["longest-even-odd-subarray-with-threshold", "prime-pairs-with-target-sum", "continuous-subarrays", "sum-of-imbalance-numbers-of-all-subarrays"]}, {"contest_title": "\u7b2c 353 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 353", "contest_title_slug": "weekly-contest-353", "contest_id": 894, "contest_start_time": 1688869800, "contest_duration": 5400, "user_num": 4113, "question_slugs": ["find-the-maximum-achievable-number", "maximum-number-of-jumps-to-reach-the-last-index", "longest-non-decreasing-subarray-from-two-arrays", "apply-operations-to-make-all-array-elements-equal-to-zero"]}, {"contest_title": "\u7b2c 354 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 354", "contest_title_slug": "weekly-contest-354", "contest_id": 898, "contest_start_time": 1689474600, "contest_duration": 5400, "user_num": 3957, "question_slugs": ["sum-of-squares-of-special-elements", "maximum-beauty-of-an-array-after-applying-operation", "minimum-index-of-a-valid-split", "length-of-the-longest-valid-substring"]}, {"contest_title": "\u7b2c 355 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 355", "contest_title_slug": "weekly-contest-355", "contest_id": 900, "contest_start_time": 1690079400, "contest_duration": 5400, "user_num": 4112, "question_slugs": ["split-strings-by-separator", "largest-element-in-an-array-after-merge-operations", "maximum-number-of-groups-with-increasing-length", "count-paths-that-can-form-a-palindrome-in-a-tree"]}, {"contest_title": "\u7b2c 356 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 356", "contest_title_slug": "weekly-contest-356", "contest_id": 904, "contest_start_time": 1690684200, "contest_duration": 5400, "user_num": 4082, "question_slugs": ["number-of-employees-who-met-the-target", "count-complete-subarrays-in-an-array", "shortest-string-that-contains-three-strings", "count-stepping-numbers-in-range"]}, {"contest_title": "\u7b2c 357 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 357", "contest_title_slug": "weekly-contest-357", "contest_id": 906, "contest_start_time": 1691289000, "contest_duration": 5400, "user_num": 4265, "question_slugs": ["faulty-keyboard", "check-if-it-is-possible-to-split-array", "find-the-safest-path-in-a-grid", "maximum-elegance-of-a-k-length-subsequence"]}, {"contest_title": "\u7b2c 358 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 358", "contest_title_slug": "weekly-contest-358", "contest_id": 910, "contest_start_time": 1691893800, "contest_duration": 5400, "user_num": 4475, "question_slugs": ["max-pair-sum-in-an-array", "double-a-number-represented-as-a-linked-list", "minimum-absolute-difference-between-elements-with-constraint", "apply-operations-to-maximize-score"]}, {"contest_title": "\u7b2c 359 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 359", "contest_title_slug": "weekly-contest-359", "contest_id": 913, "contest_start_time": 1692498600, "contest_duration": 5400, "user_num": 4101, "question_slugs": ["check-if-a-string-is-an-acronym-of-words", "determine-the-minimum-sum-of-a-k-avoiding-array", "maximize-the-profit-as-the-salesman", "find-the-longest-equal-subarray"]}, {"contest_title": "\u7b2c 360 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 360", "contest_title_slug": "weekly-contest-360", "contest_id": 918, "contest_start_time": 1693103400, "contest_duration": 5400, "user_num": 4496, "question_slugs": ["furthest-point-from-origin", "find-the-minimum-possible-sum-of-a-beautiful-array", "minimum-operations-to-form-subsequence-with-target-sum", "maximize-value-of-function-in-a-ball-passing-game"]}, {"contest_title": "\u7b2c 361 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 361", "contest_title_slug": "weekly-contest-361", "contest_id": 920, "contest_start_time": 1693708200, "contest_duration": 5400, "user_num": 4170, "question_slugs": ["count-symmetric-integers", "minimum-operations-to-make-a-special-number", "count-of-interesting-subarrays", "minimum-edge-weight-equilibrium-queries-in-a-tree"]}, {"contest_title": "\u7b2c 362 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 362", "contest_title_slug": "weekly-contest-362", "contest_id": 924, "contest_start_time": 1694313000, "contest_duration": 5400, "user_num": 4800, "question_slugs": ["points-that-intersect-with-cars", "determine-if-a-cell-is-reachable-at-a-given-time", "minimum-moves-to-spread-stones-over-grid", "string-transformation"]}, {"contest_title": "\u7b2c 363 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 363", "contest_title_slug": "weekly-contest-363", "contest_id": 926, "contest_start_time": 1694917800, "contest_duration": 5400, "user_num": 4768, "question_slugs": ["sum-of-values-at-indices-with-k-set-bits", "happy-students", "maximum-number-of-alloys", "maximum-element-sum-of-a-complete-subset-of-indices"]}, {"contest_title": "\u7b2c 364 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 364", "contest_title_slug": "weekly-contest-364", "contest_id": 930, "contest_start_time": 1695522600, "contest_duration": 5400, "user_num": 4304, "question_slugs": ["maximum-odd-binary-number", "beautiful-towers-i", "beautiful-towers-ii", "count-valid-paths-in-a-tree"]}, {"contest_title": "\u7b2c 365 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 365", "contest_title_slug": "weekly-contest-365", "contest_id": 932, "contest_start_time": 1696127400, "contest_duration": 5400, "user_num": 2909, "question_slugs": ["maximum-value-of-an-ordered-triplet-i", "maximum-value-of-an-ordered-triplet-ii", "minimum-size-subarray-in-infinite-array", "count-visited-nodes-in-a-directed-graph"]}, {"contest_title": "\u7b2c 366 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 366", "contest_title_slug": "weekly-contest-366", "contest_id": 936, "contest_start_time": 1696732200, "contest_duration": 5400, "user_num": 2790, "question_slugs": ["divisible-and-non-divisible-sums-difference", "minimum-processing-time", "apply-operations-to-make-two-strings-equal", "apply-operations-on-array-to-maximize-sum-of-squares"]}, {"contest_title": "\u7b2c 367 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 367", "contest_title_slug": "weekly-contest-367", "contest_id": 938, "contest_start_time": 1697337000, "contest_duration": 5400, "user_num": 4317, "question_slugs": ["find-indices-with-index-and-value-difference-i", "shortest-and-lexicographically-smallest-beautiful-string", "find-indices-with-index-and-value-difference-ii", "construct-product-matrix"]}, {"contest_title": "\u7b2c 368 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 368", "contest_title_slug": "weekly-contest-368", "contest_id": 942, "contest_start_time": 1697941800, "contest_duration": 5400, "user_num": 5002, "question_slugs": ["minimum-sum-of-mountain-triplets-i", "minimum-sum-of-mountain-triplets-ii", "minimum-number-of-groups-to-create-a-valid-assignment", "minimum-changes-to-make-k-semi-palindromes"]}, {"contest_title": "\u7b2c 369 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 369", "contest_title_slug": "weekly-contest-369", "contest_id": 945, "contest_start_time": 1698546600, "contest_duration": 5400, "user_num": 4121, "question_slugs": ["find-the-k-or-of-an-array", "minimum-equal-sum-of-two-arrays-after-replacing-zeros", "minimum-increment-operations-to-make-array-beautiful", "maximum-points-after-collecting-coins-from-all-nodes"]}, {"contest_title": "\u7b2c 370 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 370", "contest_title_slug": "weekly-contest-370", "contest_id": 950, "contest_start_time": 1699151400, "contest_duration": 5400, "user_num": 3983, "question_slugs": ["find-champion-i", "find-champion-ii", "maximum-score-after-applying-operations-on-a-tree", "maximum-balanced-subsequence-sum"]}, {"contest_title": "\u7b2c 371 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 371", "contest_title_slug": "weekly-contest-371", "contest_id": 952, "contest_start_time": 1699756200, "contest_duration": 5400, "user_num": 3638, "question_slugs": ["maximum-strong-pair-xor-i", "high-access-employees", "minimum-operations-to-maximize-last-elements-in-arrays", "maximum-strong-pair-xor-ii"]}, {"contest_title": "\u7b2c 372 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 372", "contest_title_slug": "weekly-contest-372", "contest_id": 956, "contest_start_time": 1700361000, "contest_duration": 5400, "user_num": 3920, "question_slugs": ["make-three-strings-equal", "separate-black-and-white-balls", "maximum-xor-product", "find-building-where-alice-and-bob-can-meet"]}, {"contest_title": "\u7b2c 373 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 373", "contest_title_slug": "weekly-contest-373", "contest_id": 958, "contest_start_time": 1700965800, "contest_duration": 5400, "user_num": 3577, "question_slugs": ["matrix-similarity-after-cyclic-shifts", "count-beautiful-substrings-i", "make-lexicographically-smallest-array-by-swapping-elements", "count-beautiful-substrings-ii"]}, {"contest_title": "\u7b2c 374 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 374", "contest_title_slug": "weekly-contest-374", "contest_id": 962, "contest_start_time": 1701570600, "contest_duration": 5400, "user_num": 4053, "question_slugs": ["find-the-peaks", "minimum-number-of-coins-to-be-added", "count-complete-substrings", "count-the-number-of-infection-sequences"]}, {"contest_title": "\u7b2c 375 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 375", "contest_title_slug": "weekly-contest-375", "contest_id": 964, "contest_start_time": 1702175400, "contest_duration": 5400, "user_num": 3518, "question_slugs": ["count-tested-devices-after-test-operations", "double-modular-exponentiation", "count-subarrays-where-max-element-appears-at-least-k-times", "count-the-number-of-good-partitions"]}, {"contest_title": "\u7b2c 376 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 376", "contest_title_slug": "weekly-contest-376", "contest_id": 968, "contest_start_time": 1702780200, "contest_duration": 5400, "user_num": 3409, "question_slugs": ["find-missing-and-repeated-values", "divide-array-into-arrays-with-max-difference", "minimum-cost-to-make-array-equalindromic", "apply-operations-to-maximize-frequency-score"]}, {"contest_title": "\u7b2c 377 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 377", "contest_title_slug": "weekly-contest-377", "contest_id": 970, "contest_start_time": 1703385000, "contest_duration": 5400, "user_num": 3148, "question_slugs": ["minimum-number-game", "maximum-square-area-by-removing-fences-from-a-field", "minimum-cost-to-convert-string-i", "minimum-cost-to-convert-string-ii"]}, {"contest_title": "\u7b2c 378 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 378", "contest_title_slug": "weekly-contest-378", "contest_id": 974, "contest_start_time": 1703989800, "contest_duration": 5400, "user_num": 2747, "question_slugs": ["check-if-bitwise-or-has-trailing-zeros", "find-longest-special-substring-that-occurs-thrice-i", "find-longest-special-substring-that-occurs-thrice-ii", "palindrome-rearrangement-queries"]}, {"contest_title": "\u7b2c 379 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 379", "contest_title_slug": "weekly-contest-379", "contest_id": 976, "contest_start_time": 1704594600, "contest_duration": 5400, "user_num": 3117, "question_slugs": ["maximum-area-of-longest-diagonal-rectangle", "minimum-moves-to-capture-the-queen", "maximum-size-of-a-set-after-removals", "maximize-the-number-of-partitions-after-operations"]}, {"contest_title": "\u7b2c 380 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 380", "contest_title_slug": "weekly-contest-380", "contest_id": 980, "contest_start_time": 1705199400, "contest_duration": 5400, "user_num": 3325, "question_slugs": ["count-elements-with-maximum-frequency", "find-beautiful-indices-in-the-given-array-i", "maximum-number-that-sum-of-the-prices-is-less-than-or-equal-to-k", "find-beautiful-indices-in-the-given-array-ii"]}, {"contest_title": "\u7b2c 381 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 381", "contest_title_slug": "weekly-contest-381", "contest_id": 982, "contest_start_time": 1705804200, "contest_duration": 5400, "user_num": 3737, "question_slugs": ["minimum-number-of-pushes-to-type-word-i", "count-the-number-of-houses-at-a-certain-distance-i", "minimum-number-of-pushes-to-type-word-ii", "count-the-number-of-houses-at-a-certain-distance-ii"]}, {"contest_title": "\u7b2c 382 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 382", "contest_title_slug": "weekly-contest-382", "contest_id": 986, "contest_start_time": 1706409000, "contest_duration": 5400, "user_num": 3134, "question_slugs": ["number-of-changing-keys", "find-the-maximum-number-of-elements-in-subset", "alice-and-bob-playing-flower-game", "minimize-or-of-remaining-elements-using-operations"]}, {"contest_title": "\u7b2c 383 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 383", "contest_title_slug": "weekly-contest-383", "contest_id": 988, "contest_start_time": 1707013800, "contest_duration": 5400, "user_num": 2691, "question_slugs": ["ant-on-the-boundary", "minimum-time-to-revert-word-to-initial-state-i", "find-the-grid-of-region-average", "minimum-time-to-revert-word-to-initial-state-ii"]}, {"contest_title": "\u7b2c 384 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 384", "contest_title_slug": "weekly-contest-384", "contest_id": 992, "contest_start_time": 1707618600, "contest_duration": 5400, "user_num": 1652, "question_slugs": ["modify-the-matrix", "number-of-subarrays-that-match-a-pattern-i", "maximum-palindromes-after-operations", "number-of-subarrays-that-match-a-pattern-ii"]}, {"contest_title": "\u7b2c 385 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 385", "contest_title_slug": "weekly-contest-385", "contest_id": 994, "contest_start_time": 1708223400, "contest_duration": 5400, "user_num": 2382, "question_slugs": ["count-prefix-and-suffix-pairs-i", "find-the-length-of-the-longest-common-prefix", "most-frequent-prime", "count-prefix-and-suffix-pairs-ii"]}, {"contest_title": "\u7b2c 386 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 386", "contest_title_slug": "weekly-contest-386", "contest_id": 998, "contest_start_time": 1708828200, "contest_duration": 5400, "user_num": 2731, "question_slugs": ["split-the-array", "find-the-largest-area-of-square-inside-two-rectangles", "earliest-second-to-mark-indices-i", "earliest-second-to-mark-indices-ii"]}, {"contest_title": "\u7b2c 387 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 387", "contest_title_slug": "weekly-contest-387", "contest_id": 1000, "contest_start_time": 1709433000, "contest_duration": 5400, "user_num": 3694, "question_slugs": ["distribute-elements-into-two-arrays-i", "count-submatrices-with-top-left-element-and-sum-less-than-k", "minimum-operations-to-write-the-letter-y-on-a-grid", "distribute-elements-into-two-arrays-ii"]}, {"contest_title": "\u7b2c 388 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 388", "contest_title_slug": "weekly-contest-388", "contest_id": 1004, "contest_start_time": 1710037800, "contest_duration": 5400, "user_num": 4291, "question_slugs": ["apple-redistribution-into-boxes", "maximize-happiness-of-selected-children", "shortest-uncommon-substring-in-an-array", "maximum-strength-of-k-disjoint-subarrays"]}, {"contest_title": "\u7b2c 389 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 389", "contest_title_slug": "weekly-contest-389", "contest_id": 1006, "contest_start_time": 1710642600, "contest_duration": 5400, "user_num": 4561, "question_slugs": ["existence-of-a-substring-in-a-string-and-its-reverse", "count-substrings-starting-and-ending-with-given-character", "minimum-deletions-to-make-string-k-special", "minimum-moves-to-pick-k-ones"]}, {"contest_title": "\u7b2c 390 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 390", "contest_title_slug": "weekly-contest-390", "contest_id": 1011, "contest_start_time": 1711247400, "contest_duration": 5400, "user_num": 4817, "question_slugs": ["maximum-length-substring-with-two-occurrences", "apply-operations-to-make-sum-of-array-greater-than-or-equal-to-k", "most-frequent-ids", "longest-common-suffix-queries"]}, {"contest_title": "\u7b2c 391 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 391", "contest_title_slug": "weekly-contest-391", "contest_id": 1014, "contest_start_time": 1711852200, "contest_duration": 5400, "user_num": 4180, "question_slugs": ["harshad-number", "water-bottles-ii", "count-alternating-subarrays", "minimize-manhattan-distances"]}, {"contest_title": "\u7b2c 392 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 392", "contest_title_slug": "weekly-contest-392", "contest_id": 1018, "contest_start_time": 1712457000, "contest_duration": 5400, "user_num": 3193, "question_slugs": ["longest-strictly-increasing-or-strictly-decreasing-subarray", "lexicographically-smallest-string-after-operations-with-constraint", "minimum-operations-to-make-median-of-array-equal-to-k", "minimum-cost-walk-in-weighted-graph"]}, {"contest_title": "\u7b2c 393 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 393", "contest_title_slug": "weekly-contest-393", "contest_id": 1020, "contest_start_time": 1713061800, "contest_duration": 5400, "user_num": 4219, "question_slugs": ["latest-time-you-can-obtain-after-replacing-characters", "maximum-prime-difference", "kth-smallest-amount-with-single-denomination-combination", "minimum-sum-of-values-by-dividing-array"]}, {"contest_title": "\u7b2c 394 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 394", "contest_title_slug": "weekly-contest-394", "contest_id": 1024, "contest_start_time": 1713666600, "contest_duration": 5400, "user_num": 3958, "question_slugs": ["count-the-number-of-special-characters-i", "count-the-number-of-special-characters-ii", "minimum-number-of-operations-to-satisfy-conditions", "find-edges-in-shortest-paths"]}, {"contest_title": "\u7b2c 395 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 395", "contest_title_slug": "weekly-contest-395", "contest_id": 1026, "contest_start_time": 1714271400, "contest_duration": 5400, "user_num": 2969, "question_slugs": ["find-the-integer-added-to-array-i", "find-the-integer-added-to-array-ii", "minimum-array-end", "find-the-median-of-the-uniqueness-array"]}, {"contest_title": "\u7b2c 396 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 396", "contest_title_slug": "weekly-contest-396", "contest_id": 1030, "contest_start_time": 1714876200, "contest_duration": 5400, "user_num": 2932, "question_slugs": ["valid-word", "minimum-number-of-operations-to-make-word-k-periodic", "minimum-length-of-anagram-concatenation", "minimum-cost-to-equalize-array"]}, {"contest_title": "\u7b2c 397 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 397", "contest_title_slug": "weekly-contest-397", "contest_id": 1032, "contest_start_time": 1715481000, "contest_duration": 5400, "user_num": 3365, "question_slugs": ["permutation-difference-between-two-strings", "taking-maximum-energy-from-the-mystic-dungeon", "maximum-difference-score-in-a-grid", "find-the-minimum-cost-array-permutation"]}, {"contest_title": "\u7b2c 398 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 398", "contest_title_slug": "weekly-contest-398", "contest_id": 1036, "contest_start_time": 1716085800, "contest_duration": 5400, "user_num": 3606, "question_slugs": ["special-array-i", "special-array-ii", "sum-of-digit-differences-of-all-pairs", "find-number-of-ways-to-reach-the-k-th-stair"]}, {"contest_title": "\u7b2c 399 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 399", "contest_title_slug": "weekly-contest-399", "contest_id": 1038, "contest_start_time": 1716690600, "contest_duration": 5400, "user_num": 3424, "question_slugs": ["find-the-number-of-good-pairs-i", "string-compression-iii", "find-the-number-of-good-pairs-ii", "maximum-sum-of-subsequence-with-non-adjacent-elements"]}, {"contest_title": "\u7b2c 400 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 400", "contest_title_slug": "weekly-contest-400", "contest_id": 1043, "contest_start_time": 1717295400, "contest_duration": 5400, "user_num": 3534, "question_slugs": ["minimum-number-of-chairs-in-a-waiting-room", "count-days-without-meetings", "lexicographically-minimum-string-after-removing-stars", "find-subarray-with-bitwise-or-closest-to-k"]}, {"contest_title": "\u7b2c 401 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 401", "contest_title_slug": "weekly-contest-401", "contest_id": 1045, "contest_start_time": 1717900200, "contest_duration": 5400, "user_num": 3160, "question_slugs": ["find-the-child-who-has-the-ball-after-k-seconds", "find-the-n-th-value-after-k-seconds", "maximum-total-reward-using-operations-i", "maximum-total-reward-using-operations-ii"]}, {"contest_title": "\u7b2c 402 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 402", "contest_title_slug": "weekly-contest-402", "contest_id": 1049, "contest_start_time": 1718505000, "contest_duration": 5400, "user_num": 3283, "question_slugs": ["count-pairs-that-form-a-complete-day-i", "count-pairs-that-form-a-complete-day-ii", "maximum-total-damage-with-spell-casting", "peaks-in-array"]}, {"contest_title": "\u7b2c 403 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 403", "contest_title_slug": "weekly-contest-403", "contest_id": 1052, "contest_start_time": 1719109800, "contest_duration": 5400, "user_num": 3112, "question_slugs": ["minimum-average-of-smallest-and-largest-elements", "find-the-minimum-area-to-cover-all-ones-i", "maximize-total-cost-of-alternating-subarrays", "find-the-minimum-area-to-cover-all-ones-ii"]}, {"contest_title": "\u7b2c 404 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 404", "contest_title_slug": "weekly-contest-404", "contest_id": 1056, "contest_start_time": 1719714600, "contest_duration": 5400, "user_num": 3486, "question_slugs": ["maximum-height-of-a-triangle", "find-the-maximum-length-of-valid-subsequence-i", "find-the-maximum-length-of-valid-subsequence-ii", "find-minimum-diameter-after-merging-two-trees"]}, {"contest_title": "\u7b2c 405 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 405", "contest_title_slug": "weekly-contest-405", "contest_id": 1058, "contest_start_time": 1720319400, "contest_duration": 5400, "user_num": 3240, "question_slugs": ["find-the-encrypted-string", "generate-binary-strings-without-adjacent-zeros", "count-submatrices-with-equal-frequency-of-x-and-y", "construct-string-with-minimum-cost"]}, {"contest_title": "\u7b2c 27 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 27", "contest_title_slug": "biweekly-contest-27", "contest_id": 204, "contest_start_time": 1590849000, "contest_duration": 5400, "user_num": 1966, "question_slugs": ["make-two-arrays-equal-by-reversing-subarrays", "check-if-a-string-contains-all-binary-codes-of-size-k", "course-schedule-iv", "cherry-pickup-ii"]}, {"contest_title": "\u7b2c 29 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 29", "contest_title_slug": "biweekly-contest-29", "contest_id": 216, "contest_start_time": 1593268200, "contest_duration": 5400, "user_num": 2260, "question_slugs": ["average-salary-excluding-the-minimum-and-maximum-salary", "the-kth-factor-of-n", "longest-subarray-of-1s-after-deleting-one-element", "parallel-courses-ii"]}, {"contest_title": "\u7b2c 58 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 58", "contest_title_slug": "biweekly-contest-58", "contest_id": 441, "contest_start_time": 1628346600, "contest_duration": 5400, "user_num": 2889, "question_slugs": ["delete-characters-to-make-fancy-string", "check-if-move-is-legal", "minimum-total-space-wasted-with-k-resizing-operations", "maximum-product-of-the-length-of-two-palindromic-substrings"]}, {"contest_title": "\u7b2c 59 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 59", "contest_title_slug": "biweekly-contest-59", "contest_id": 448, "contest_start_time": 1629556200, "contest_duration": 5400, "user_num": 3030, "question_slugs": ["minimum-time-to-type-word-using-special-typewriter", "maximum-matrix-sum", "number-of-ways-to-arrive-at-destination", "number-of-ways-to-separate-numbers"]}, {"contest_title": "\u7b2c 60 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 60", "contest_title_slug": "biweekly-contest-60", "contest_id": 461, "contest_start_time": 1630765800, "contest_duration": 5400, "user_num": 2848, "question_slugs": ["find-the-middle-index-in-array", "find-all-groups-of-farmland", "operations-on-tree", "the-number-of-good-subsets"]}, {"contest_title": "\u7b2c 61 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 61", "contest_title_slug": "biweekly-contest-61", "contest_id": 467, "contest_start_time": 1631975400, "contest_duration": 5400, "user_num": 2534, "question_slugs": ["count-number-of-pairs-with-absolute-difference-k", "find-original-array-from-doubled-array", "maximum-earnings-from-taxi", "minimum-number-of-operations-to-make-array-continuous"]}, {"contest_title": "\u7b2c 62 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 62", "contest_title_slug": "biweekly-contest-62", "contest_id": 477, "contest_start_time": 1633185000, "contest_duration": 5400, "user_num": 2619, "question_slugs": ["convert-1d-array-into-2d-array", "number-of-pairs-of-strings-with-concatenation-equal-to-target", "maximize-the-confusion-of-an-exam", "maximum-number-of-ways-to-partition-an-array"]}, {"contest_title": "\u7b2c 63 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 63", "contest_title_slug": "biweekly-contest-63", "contest_id": 484, "contest_start_time": 1634394600, "contest_duration": 5400, "user_num": 2828, "question_slugs": ["minimum-number-of-moves-to-seat-everyone", "remove-colored-pieces-if-both-neighbors-are-the-same-color", "the-time-when-the-network-becomes-idle", "kth-smallest-product-of-two-sorted-arrays"]}, {"contest_title": "\u7b2c 64 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 64", "contest_title_slug": "biweekly-contest-64", "contest_id": 490, "contest_start_time": 1635604200, "contest_duration": 5400, "user_num": 2838, "question_slugs": ["kth-distinct-string-in-an-array", "two-best-non-overlapping-events", "plates-between-candles", "number-of-valid-move-combinations-on-chessboard"]}, {"contest_title": "\u7b2c 65 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 65", "contest_title_slug": "biweekly-contest-65", "contest_id": 497, "contest_start_time": 1636813800, "contest_duration": 5400, "user_num": 2676, "question_slugs": ["check-whether-two-strings-are-almost-equivalent", "walking-robot-simulation-ii", "most-beautiful-item-for-each-query", "maximum-number-of-tasks-you-can-assign"]}, {"contest_title": "\u7b2c 66 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 66", "contest_title_slug": "biweekly-contest-66", "contest_id": 503, "contest_start_time": 1638023400, "contest_duration": 5400, "user_num": 2803, "question_slugs": ["count-common-words-with-one-occurrence", "minimum-number-of-food-buckets-to-feed-the-hamsters", "minimum-cost-homecoming-of-a-robot-in-a-grid", "count-fertile-pyramids-in-a-land"]}, {"contest_title": "\u7b2c 67 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 67", "contest_title_slug": "biweekly-contest-67", "contest_id": 509, "contest_start_time": 1639233000, "contest_duration": 5400, "user_num": 2923, "question_slugs": ["find-subsequence-of-length-k-with-the-largest-sum", "find-good-days-to-rob-the-bank", "detonate-the-maximum-bombs", "sequentially-ordinal-rank-tracker"]}, {"contest_title": "\u7b2c 68 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 68", "contest_title_slug": "biweekly-contest-68", "contest_id": 515, "contest_start_time": 1640442600, "contest_duration": 5400, "user_num": 2854, "question_slugs": ["maximum-number-of-words-found-in-sentences", "find-all-possible-recipes-from-given-supplies", "check-if-a-parentheses-string-can-be-valid", "abbreviating-the-product-of-a-range"]}, {"contest_title": "\u7b2c 69 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 69", "contest_title_slug": "biweekly-contest-69", "contest_id": 521, "contest_start_time": 1641652200, "contest_duration": 5400, "user_num": 3360, "question_slugs": ["capitalize-the-title", "maximum-twin-sum-of-a-linked-list", "longest-palindrome-by-concatenating-two-letter-words", "stamping-the-grid"]}, {"contest_title": "\u7b2c 70 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 70", "contest_title_slug": "biweekly-contest-70", "contest_id": 527, "contest_start_time": 1642861800, "contest_duration": 5400, "user_num": 3640, "question_slugs": ["minimum-cost-of-buying-candies-with-discount", "count-the-hidden-sequences", "k-highest-ranked-items-within-a-price-range", "number-of-ways-to-divide-a-long-corridor"]}, {"contest_title": "\u7b2c 71 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 71", "contest_title_slug": "biweekly-contest-71", "contest_id": 533, "contest_start_time": 1644071400, "contest_duration": 5400, "user_num": 3028, "question_slugs": ["minimum-sum-of-four-digit-number-after-splitting-digits", "partition-array-according-to-given-pivot", "minimum-cost-to-set-cooking-time", "minimum-difference-in-sums-after-removal-of-elements"]}, {"contest_title": "\u7b2c 72 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 72", "contest_title_slug": "biweekly-contest-72", "contest_id": 539, "contest_start_time": 1645281000, "contest_duration": 5400, "user_num": 4400, "question_slugs": ["count-equal-and-divisible-pairs-in-an-array", "find-three-consecutive-integers-that-sum-to-a-given-number", "maximum-split-of-positive-even-integers", "count-good-triplets-in-an-array"]}, {"contest_title": "\u7b2c 73 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 73", "contest_title_slug": "biweekly-contest-73", "contest_id": 545, "contest_start_time": 1646490600, "contest_duration": 5400, "user_num": 5132, "question_slugs": ["most-frequent-number-following-key-in-an-array", "sort-the-jumbled-numbers", "all-ancestors-of-a-node-in-a-directed-acyclic-graph", "minimum-number-of-moves-to-make-palindrome"]}, {"contest_title": "\u7b2c 74 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 74", "contest_title_slug": "biweekly-contest-74", "contest_id": 554, "contest_start_time": 1647700200, "contest_duration": 5400, "user_num": 5442, "question_slugs": ["divide-array-into-equal-pairs", "maximize-number-of-subsequences-in-a-string", "minimum-operations-to-halve-array-sum", "minimum-white-tiles-after-covering-with-carpets"]}, {"contest_title": "\u7b2c 75 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 75", "contest_title_slug": "biweekly-contest-75", "contest_id": 563, "contest_start_time": 1648909800, "contest_duration": 5400, "user_num": 4335, "question_slugs": ["minimum-bit-flips-to-convert-number", "find-triangular-sum-of-an-array", "number-of-ways-to-select-buildings", "sum-of-scores-of-built-strings"]}, {"contest_title": "\u7b2c 76 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 76", "contest_title_slug": "biweekly-contest-76", "contest_id": 572, "contest_start_time": 1650119400, "contest_duration": 5400, "user_num": 4477, "question_slugs": ["find-closest-number-to-zero", "number-of-ways-to-buy-pens-and-pencils", "design-an-atm-machine", "maximum-score-of-a-node-sequence"]}, {"contest_title": "\u7b2c 77 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 77", "contest_title_slug": "biweekly-contest-77", "contest_id": 581, "contest_start_time": 1651329000, "contest_duration": 5400, "user_num": 4211, "question_slugs": ["count-prefixes-of-a-given-string", "minimum-average-difference", "count-unguarded-cells-in-the-grid", "escape-the-spreading-fire"]}, {"contest_title": "\u7b2c 78 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 78", "contest_title_slug": "biweekly-contest-78", "contest_id": 590, "contest_start_time": 1652538600, "contest_duration": 5400, "user_num": 4347, "question_slugs": ["find-the-k-beauty-of-a-number", "number-of-ways-to-split-array", "maximum-white-tiles-covered-by-a-carpet", "substring-with-largest-variance"]}, {"contest_title": "\u7b2c 79 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 79", "contest_title_slug": "biweekly-contest-79", "contest_id": 598, "contest_start_time": 1653748200, "contest_duration": 5400, "user_num": 4250, "question_slugs": ["check-if-number-has-equal-digit-count-and-digit-value", "sender-with-largest-word-count", "maximum-total-importance-of-roads", "booking-concert-tickets-in-groups"]}, {"contest_title": "\u7b2c 80 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 80", "contest_title_slug": "biweekly-contest-80", "contest_id": 608, "contest_start_time": 1654957800, "contest_duration": 5400, "user_num": 3949, "question_slugs": ["strong-password-checker-ii", "successful-pairs-of-spells-and-potions", "match-substring-after-replacement", "count-subarrays-with-score-less-than-k"]}, {"contest_title": "\u7b2c 81 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 81", "contest_title_slug": "biweekly-contest-81", "contest_id": 614, "contest_start_time": 1656167400, "contest_duration": 5400, "user_num": 3847, "question_slugs": ["count-asterisks", "count-unreachable-pairs-of-nodes-in-an-undirected-graph", "maximum-xor-after-operations", "number-of-distinct-roll-sequences"]}, {"contest_title": "\u7b2c 82 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 82", "contest_title_slug": "biweekly-contest-82", "contest_id": 646, "contest_start_time": 1657377000, "contest_duration": 5400, "user_num": 4144, "question_slugs": ["evaluate-boolean-binary-tree", "the-latest-time-to-catch-a-bus", "minimum-sum-of-squared-difference", "subarray-with-elements-greater-than-varying-threshold"]}, {"contest_title": "\u7b2c 83 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 83", "contest_title_slug": "biweekly-contest-83", "contest_id": 652, "contest_start_time": 1658586600, "contest_duration": 5400, "user_num": 4437, "question_slugs": ["best-poker-hand", "number-of-zero-filled-subarrays", "design-a-number-container-system", "shortest-impossible-sequence-of-rolls"]}, {"contest_title": "\u7b2c 84 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 84", "contest_title_slug": "biweekly-contest-84", "contest_id": 658, "contest_start_time": 1659796200, "contest_duration": 5400, "user_num": 4574, "question_slugs": ["merge-similar-items", "count-number-of-bad-pairs", "task-scheduler-ii", "minimum-replacements-to-sort-the-array"]}, {"contest_title": "\u7b2c 85 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 85", "contest_title_slug": "biweekly-contest-85", "contest_id": 668, "contest_start_time": 1661005800, "contest_duration": 5400, "user_num": 4193, "question_slugs": ["minimum-recolors-to-get-k-consecutive-black-blocks", "time-needed-to-rearrange-a-binary-string", "shifting-letters-ii", "maximum-segment-sum-after-removals"]}, {"contest_title": "\u7b2c 86 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 86", "contest_title_slug": "biweekly-contest-86", "contest_id": 688, "contest_start_time": 1662215400, "contest_duration": 5400, "user_num": 4401, "question_slugs": ["find-subarrays-with-equal-sum", "strictly-palindromic-number", "maximum-rows-covered-by-columns", "maximum-number-of-robots-within-budget"]}, {"contest_title": "\u7b2c 87 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 87", "contest_title_slug": "biweekly-contest-87", "contest_id": 703, "contest_start_time": 1663425000, "contest_duration": 5400, "user_num": 4005, "question_slugs": ["count-days-spent-together", "maximum-matching-of-players-with-trainers", "smallest-subarrays-with-maximum-bitwise-or", "minimum-money-required-before-transactions"]}, {"contest_title": "\u7b2c 88 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 88", "contest_title_slug": "biweekly-contest-88", "contest_id": 745, "contest_start_time": 1664634600, "contest_duration": 5400, "user_num": 3905, "question_slugs": ["remove-letter-to-equalize-frequency", "longest-uploaded-prefix", "bitwise-xor-of-all-pairings", "number-of-pairs-satisfying-inequality"]}, {"contest_title": "\u7b2c 89 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 89", "contest_title_slug": "biweekly-contest-89", "contest_id": 755, "contest_start_time": 1665844200, "contest_duration": 5400, "user_num": 3984, "question_slugs": ["number-of-valid-clock-times", "range-product-queries-of-powers", "minimize-maximum-of-array", "create-components-with-same-value"]}, {"contest_title": "\u7b2c 90 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 90", "contest_title_slug": "biweekly-contest-90", "contest_id": 763, "contest_start_time": 1667053800, "contest_duration": 5400, "user_num": 3624, "question_slugs": ["odd-string-difference", "words-within-two-edits-of-dictionary", "destroy-sequential-targets", "next-greater-element-iv"]}, {"contest_title": "\u7b2c 91 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 91", "contest_title_slug": "biweekly-contest-91", "contest_id": 770, "contest_start_time": 1668263400, "contest_duration": 5400, "user_num": 3535, "question_slugs": ["number-of-distinct-averages", "count-ways-to-build-good-strings", "most-profitable-path-in-a-tree", "split-message-based-on-limit"]}, {"contest_title": "\u7b2c 92 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 92", "contest_title_slug": "biweekly-contest-92", "contest_id": 776, "contest_start_time": 1669473000, "contest_duration": 5400, "user_num": 3055, "question_slugs": ["minimum-cuts-to-divide-a-circle", "difference-between-ones-and-zeros-in-row-and-column", "minimum-penalty-for-a-shop", "count-palindromic-subsequences"]}, {"contest_title": "\u7b2c 93 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 93", "contest_title_slug": "biweekly-contest-93", "contest_id": 782, "contest_start_time": 1670682600, "contest_duration": 5400, "user_num": 2929, "question_slugs": ["maximum-value-of-a-string-in-an-array", "maximum-star-sum-of-a-graph", "frog-jump-ii", "minimum-total-cost-to-make-arrays-unequal"]}, {"contest_title": "\u7b2c 94 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 94", "contest_title_slug": "biweekly-contest-94", "contest_id": 789, "contest_start_time": 1671892200, "contest_duration": 5400, "user_num": 2298, "question_slugs": ["maximum-enemy-forts-that-can-be-captured", "reward-top-k-students", "minimize-the-maximum-of-two-arrays", "count-anagrams"]}, {"contest_title": "\u7b2c 95 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 95", "contest_title_slug": "biweekly-contest-95", "contest_id": 798, "contest_start_time": 1673101800, "contest_duration": 5400, "user_num": 2880, "question_slugs": ["categorize-box-according-to-criteria", "find-consecutive-integers-from-a-data-stream", "find-xor-beauty-of-array", "maximize-the-minimum-powered-city"]}, {"contest_title": "\u7b2c 96 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 96", "contest_title_slug": "biweekly-contest-96", "contest_id": 804, "contest_start_time": 1674311400, "contest_duration": 5400, "user_num": 2103, "question_slugs": ["minimum-common-value", "minimum-operations-to-make-array-equal-ii", "maximum-subsequence-score", "check-if-point-is-reachable"]}, {"contest_title": "\u7b2c 97 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 97", "contest_title_slug": "biweekly-contest-97", "contest_id": 810, "contest_start_time": 1675521000, "contest_duration": 5400, "user_num": 2631, "question_slugs": ["separate-the-digits-in-an-array", "maximum-number-of-integers-to-choose-from-a-range-i", "maximize-win-from-two-segments", "disconnect-path-in-a-binary-matrix-by-at-most-one-flip"]}, {"contest_title": "\u7b2c 98 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 98", "contest_title_slug": "biweekly-contest-98", "contest_id": 816, "contest_start_time": 1676730600, "contest_duration": 5400, "user_num": 3250, "question_slugs": ["maximum-difference-by-remapping-a-digit", "minimum-score-by-changing-two-elements", "minimum-impossible-or", "handling-sum-queries-after-update"]}, {"contest_title": "\u7b2c 99 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 99", "contest_title_slug": "biweekly-contest-99", "contest_id": 822, "contest_start_time": 1677940200, "contest_duration": 5400, "user_num": 3467, "question_slugs": ["split-with-minimum-sum", "count-total-number-of-colored-cells", "count-ways-to-group-overlapping-ranges", "count-number-of-possible-root-nodes"]}, {"contest_title": "\u7b2c 100 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 100", "contest_title_slug": "biweekly-contest-100", "contest_id": 832, "contest_start_time": 1679149800, "contest_duration": 5400, "user_num": 3639, "question_slugs": ["distribute-money-to-maximum-children", "maximize-greatness-of-an-array", "find-score-of-an-array-after-marking-all-elements", "minimum-time-to-repair-cars"]}, {"contest_title": "\u7b2c 101 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 101", "contest_title_slug": "biweekly-contest-101", "contest_id": 842, "contest_start_time": 1680359400, "contest_duration": 5400, "user_num": 3353, "question_slugs": ["form-smallest-number-from-two-digit-arrays", "find-the-substring-with-maximum-cost", "make-k-subarray-sums-equal", "shortest-cycle-in-a-graph"]}, {"contest_title": "\u7b2c 102 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 102", "contest_title_slug": "biweekly-contest-102", "contest_id": 853, "contest_start_time": 1681569000, "contest_duration": 5400, "user_num": 3058, "question_slugs": ["find-the-width-of-columns-of-a-grid", "find-the-score-of-all-prefixes-of-an-array", "cousins-in-binary-tree-ii", "design-graph-with-shortest-path-calculator"]}, {"contest_title": "\u7b2c 103 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 103", "contest_title_slug": "biweekly-contest-103", "contest_id": 859, "contest_start_time": 1682778600, "contest_duration": 5400, "user_num": 2299, "question_slugs": ["maximum-sum-with-exactly-k-elements", "find-the-prefix-common-array-of-two-arrays", "maximum-number-of-fish-in-a-grid", "make-array-empty"]}, {"contest_title": "\u7b2c 104 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 104", "contest_title_slug": "biweekly-contest-104", "contest_id": 866, "contest_start_time": 1683988200, "contest_duration": 5400, "user_num": 2519, "question_slugs": ["number-of-senior-citizens", "sum-in-a-matrix", "maximum-or", "power-of-heroes"]}, {"contest_title": "\u7b2c 105 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 105", "contest_title_slug": "biweekly-contest-105", "contest_id": 873, "contest_start_time": 1685197800, "contest_duration": 5400, "user_num": 2604, "question_slugs": ["buy-two-chocolates", "extra-characters-in-a-string", "maximum-strength-of-a-group", "greatest-common-divisor-traversal"]}, {"contest_title": "\u7b2c 106 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 106", "contest_title_slug": "biweekly-contest-106", "contest_id": 879, "contest_start_time": 1686407400, "contest_duration": 5400, "user_num": 2346, "question_slugs": ["check-if-the-number-is-fascinating", "find-the-longest-semi-repetitive-substring", "movement-of-robots", "find-a-good-subset-of-the-matrix"]}, {"contest_title": "\u7b2c 107 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 107", "contest_title_slug": "biweekly-contest-107", "contest_id": 885, "contest_start_time": 1687617000, "contest_duration": 5400, "user_num": 1870, "question_slugs": ["find-maximum-number-of-string-pairs", "construct-the-longest-new-string", "decremental-string-concatenation", "count-zero-request-servers"]}, {"contest_title": "\u7b2c 108 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 108", "contest_title_slug": "biweekly-contest-108", "contest_id": 891, "contest_start_time": 1688826600, "contest_duration": 5400, "user_num": 2349, "question_slugs": ["longest-alternating-subarray", "relocate-marbles", "partition-string-into-minimum-beautiful-substrings", "number-of-black-blocks"]}, {"contest_title": "\u7b2c 109 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 109", "contest_title_slug": "biweekly-contest-109", "contest_id": 897, "contest_start_time": 1690036200, "contest_duration": 5400, "user_num": 2461, "question_slugs": ["check-if-array-is-good", "sort-vowels-in-a-string", "visit-array-positions-to-maximize-score", "ways-to-express-an-integer-as-sum-of-powers"]}, {"contest_title": "\u7b2c 110 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 110", "contest_title_slug": "biweekly-contest-110", "contest_id": 903, "contest_start_time": 1691245800, "contest_duration": 5400, "user_num": 2546, "question_slugs": ["account-balance-after-rounded-purchase", "insert-greatest-common-divisors-in-linked-list", "minimum-seconds-to-equalize-a-circular-array", "minimum-time-to-make-array-sum-at-most-x"]}, {"contest_title": "\u7b2c 111 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 111", "contest_title_slug": "biweekly-contest-111", "contest_id": 909, "contest_start_time": 1692455400, "contest_duration": 5400, "user_num": 2787, "question_slugs": ["count-pairs-whose-sum-is-less-than-target", "make-string-a-subsequence-using-cyclic-increments", "sorting-three-groups", "number-of-beautiful-integers-in-the-range"]}, {"contest_title": "\u7b2c 112 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 112", "contest_title_slug": "biweekly-contest-112", "contest_id": 917, "contest_start_time": 1693665000, "contest_duration": 5400, "user_num": 2900, "question_slugs": ["check-if-strings-can-be-made-equal-with-operations-i", "check-if-strings-can-be-made-equal-with-operations-ii", "maximum-sum-of-almost-unique-subarray", "count-k-subsequences-of-a-string-with-maximum-beauty"]}, {"contest_title": "\u7b2c 113 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 113", "contest_title_slug": "biweekly-contest-113", "contest_id": 923, "contest_start_time": 1694874600, "contest_duration": 5400, "user_num": 3028, "question_slugs": ["minimum-right-shifts-to-sort-the-array", "minimum-array-length-after-pair-removals", "count-pairs-of-points-with-distance-k", "minimum-edge-reversals-so-every-node-is-reachable"]}, {"contest_title": "\u7b2c 114 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 114", "contest_title_slug": "biweekly-contest-114", "contest_id": 929, "contest_start_time": 1696084200, "contest_duration": 5400, "user_num": 2406, "question_slugs": ["minimum-operations-to-collect-elements", "minimum-number-of-operations-to-make-array-empty", "split-array-into-maximum-number-of-subarrays", "maximum-number-of-k-divisible-components"]}, {"contest_title": "\u7b2c 115 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 115", "contest_title_slug": "biweekly-contest-115", "contest_id": 935, "contest_start_time": 1697293800, "contest_duration": 5400, "user_num": 2809, "question_slugs": ["last-visited-integers", "longest-unequal-adjacent-groups-subsequence-i", "longest-unequal-adjacent-groups-subsequence-ii", "count-of-sub-multisets-with-bounded-sum"]}, {"contest_title": "\u7b2c 116 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 116", "contest_title_slug": "biweekly-contest-116", "contest_id": 941, "contest_start_time": 1698503400, "contest_duration": 5400, "user_num": 2904, "question_slugs": ["subarrays-distinct-element-sum-of-squares-i", "minimum-number-of-changes-to-make-binary-string-beautiful", "length-of-the-longest-subsequence-that-sums-to-target", "subarrays-distinct-element-sum-of-squares-ii"]}, {"contest_title": "\u7b2c 117 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 117", "contest_title_slug": "biweekly-contest-117", "contest_id": 949, "contest_start_time": 1699713000, "contest_duration": 5400, "user_num": 2629, "question_slugs": ["distribute-candies-among-children-i", "distribute-candies-among-children-ii", "number-of-strings-which-can-be-rearranged-to-contain-substring", "maximum-spending-after-buying-items"]}, {"contest_title": "\u7b2c 118 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 118", "contest_title_slug": "biweekly-contest-118", "contest_id": 955, "contest_start_time": 1700922600, "contest_duration": 5400, "user_num": 2425, "question_slugs": ["find-words-containing-character", "maximize-area-of-square-hole-in-grid", "minimum-number-of-coins-for-fruits", "find-maximum-non-decreasing-array-length"]}, {"contest_title": "\u7b2c 119 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 119", "contest_title_slug": "biweekly-contest-119", "contest_id": 961, "contest_start_time": 1702132200, "contest_duration": 5400, "user_num": 2472, "question_slugs": ["find-common-elements-between-two-arrays", "remove-adjacent-almost-equal-characters", "length-of-longest-subarray-with-at-most-k-frequency", "number-of-possible-sets-of-closing-branches"]}, {"contest_title": "\u7b2c 120 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 120", "contest_title_slug": "biweekly-contest-120", "contest_id": 967, "contest_start_time": 1703341800, "contest_duration": 5400, "user_num": 2542, "question_slugs": ["count-the-number-of-incremovable-subarrays-i", "find-polygon-with-the-largest-perimeter", "count-the-number-of-incremovable-subarrays-ii", "find-number-of-coins-to-place-in-tree-nodes"]}, {"contest_title": "\u7b2c 121 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 121", "contest_title_slug": "biweekly-contest-121", "contest_id": 973, "contest_start_time": 1704551400, "contest_duration": 5400, "user_num": 2218, "question_slugs": ["smallest-missing-integer-greater-than-sequential-prefix-sum", "minimum-number-of-operations-to-make-array-xor-equal-to-k", "minimum-number-of-operations-to-make-x-and-y-equal", "count-the-number-of-powerful-integers"]}, {"contest_title": "\u7b2c 122 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 122", "contest_title_slug": "biweekly-contest-122", "contest_id": 979, "contest_start_time": 1705761000, "contest_duration": 5400, "user_num": 2547, "question_slugs": ["divide-an-array-into-subarrays-with-minimum-cost-i", "find-if-array-can-be-sorted", "minimize-length-of-array-using-operations", "divide-an-array-into-subarrays-with-minimum-cost-ii"]}, {"contest_title": "\u7b2c 123 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 123", "contest_title_slug": "biweekly-contest-123", "contest_id": 985, "contest_start_time": 1706970600, "contest_duration": 5400, "user_num": 2209, "question_slugs": ["type-of-triangle", "find-the-number-of-ways-to-place-people-i", "maximum-good-subarray-sum", "find-the-number-of-ways-to-place-people-ii"]}, {"contest_title": "\u7b2c 124 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 124", "contest_title_slug": "biweekly-contest-124", "contest_id": 991, "contest_start_time": 1708180200, "contest_duration": 5400, "user_num": 1861, "question_slugs": ["maximum-number-of-operations-with-the-same-score-i", "apply-operations-to-make-string-empty", "maximum-number-of-operations-with-the-same-score-ii", "maximize-consecutive-elements-in-an-array-after-modification"]}, {"contest_title": "\u7b2c 125 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 125", "contest_title_slug": "biweekly-contest-125", "contest_id": 997, "contest_start_time": 1709389800, "contest_duration": 5400, "user_num": 2599, "question_slugs": ["minimum-operations-to-exceed-threshold-value-i", "minimum-operations-to-exceed-threshold-value-ii", "count-pairs-of-connectable-servers-in-a-weighted-tree-network", "find-the-maximum-sum-of-node-values"]}, {"contest_title": "\u7b2c 126 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 126", "contest_title_slug": "biweekly-contest-126", "contest_id": 1003, "contest_start_time": 1710599400, "contest_duration": 5400, "user_num": 3234, "question_slugs": ["find-the-sum-of-encrypted-integers", "mark-elements-on-array-by-performing-queries", "replace-question-marks-in-string-to-minimize-its-value", "find-the-sum-of-the-power-of-all-subsequences"]}, {"contest_title": "\u7b2c 127 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 127", "contest_title_slug": "biweekly-contest-127", "contest_id": 1010, "contest_start_time": 1711809000, "contest_duration": 5400, "user_num": 2950, "question_slugs": ["shortest-subarray-with-or-at-least-k-i", "minimum-levels-to-gain-more-points", "shortest-subarray-with-or-at-least-k-ii", "find-the-sum-of-subsequence-powers"]}, {"contest_title": "\u7b2c 128 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 128", "contest_title_slug": "biweekly-contest-128", "contest_id": 1017, "contest_start_time": 1713018600, "contest_duration": 5400, "user_num": 2653, "question_slugs": ["score-of-a-string", "minimum-rectangles-to-cover-points", "minimum-time-to-visit-disappearing-nodes", "find-the-number-of-subarrays-where-boundary-elements-are-maximum"]}, {"contest_title": "\u7b2c 129 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 129", "contest_title_slug": "biweekly-contest-129", "contest_id": 1023, "contest_start_time": 1714228200, "contest_duration": 5400, "user_num": 2511, "question_slugs": ["make-a-square-with-the-same-color", "right-triangles", "find-all-possible-stable-binary-arrays-i", "find-all-possible-stable-binary-arrays-ii"]}, {"contest_title": "\u7b2c 130 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 130", "contest_title_slug": "biweekly-contest-130", "contest_id": 1029, "contest_start_time": 1715437800, "contest_duration": 5400, "user_num": 2604, "question_slugs": ["check-if-grid-satisfies-conditions", "maximum-points-inside-the-square", "minimum-substring-partition-of-equal-character-frequency", "find-products-of-elements-of-big-array"]}, {"contest_title": "\u7b2c 131 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 131", "contest_title_slug": "biweekly-contest-131", "contest_id": 1035, "contest_start_time": 1716647400, "contest_duration": 5400, "user_num": 2537, "question_slugs": ["find-the-xor-of-numbers-which-appear-twice", "find-occurrences-of-an-element-in-an-array", "find-the-number-of-distinct-colors-among-the-balls", "block-placement-queries"]}, {"contest_title": "\u7b2c 132 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 132", "contest_title_slug": "biweekly-contest-132", "contest_id": 1042, "contest_start_time": 1717857000, "contest_duration": 5400, "user_num": 2457, "question_slugs": ["clear-digits", "find-the-first-player-to-win-k-games-in-a-row", "find-the-maximum-length-of-a-good-subsequence-i", "find-the-maximum-length-of-a-good-subsequence-ii"]}, {"contest_title": "\u7b2c 133 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 133", "contest_title_slug": "biweekly-contest-133", "contest_id": 1048, "contest_start_time": 1719066600, "contest_duration": 5400, "user_num": 2326, "question_slugs": ["find-minimum-operations-to-make-all-elements-divisible-by-three", "minimum-operations-to-make-binary-array-elements-equal-to-one-i", "minimum-operations-to-make-binary-array-elements-equal-to-one-ii", "count-the-number-of-inversions"]}, {"contest_title": "\u7b2c 134 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 134", "contest_title_slug": "biweekly-contest-134", "contest_id": 1055, "contest_start_time": 1720276200, "contest_duration": 5400, "user_num": 2411, "question_slugs": ["alternating-groups-i", "maximum-points-after-enemy-battles", "alternating-groups-ii", "number-of-subarrays-with-and-value-of-k"]}] \ No newline at end of file +[{"contest_title": "\u7b2c 83 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 83", "contest_title_slug": "weekly-contest-83", "contest_id": 5, "contest_start_time": 1525570200, "contest_duration": 5400, "user_num": 58, "question_slugs": ["positions-of-large-groups", "masking-personal-information", "consecutive-numbers-sum", "count-unique-characters-of-all-substrings-of-a-given-string"]}, {"contest_title": "\u7b2c 84 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 84", "contest_title_slug": "weekly-contest-84", "contest_id": 6, "contest_start_time": 1526175000, "contest_duration": 5400, "user_num": 656, "question_slugs": ["flipping-an-image", "find-and-replace-in-string", "image-overlap", "sum-of-distances-in-tree"]}, {"contest_title": "\u7b2c 85 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 85", "contest_title_slug": "weekly-contest-85", "contest_id": 7, "contest_start_time": 1526779800, "contest_duration": 5400, "user_num": 467, "question_slugs": ["rectangle-overlap", "push-dominoes", "new-21-game", "similar-string-groups"]}, {"contest_title": "\u7b2c 86 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 86", "contest_title_slug": "weekly-contest-86", "contest_id": 8, "contest_start_time": 1527384600, "contest_duration": 5400, "user_num": 377, "question_slugs": ["magic-squares-in-grid", "keys-and-rooms", "split-array-into-fibonacci-sequence", "guess-the-word"]}, {"contest_title": "\u7b2c 87 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 87", "contest_title_slug": "weekly-contest-87", "contest_id": 9, "contest_start_time": 1527989400, "contest_duration": 5400, "user_num": 343, "question_slugs": ["backspace-string-compare", "longest-mountain-in-array", "hand-of-straights", "shortest-path-visiting-all-nodes"]}, {"contest_title": "\u7b2c 88 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 88", "contest_title_slug": "weekly-contest-88", "contest_id": 11, "contest_start_time": 1528594200, "contest_duration": 5400, "user_num": 404, "question_slugs": ["shifting-letters", "maximize-distance-to-closest-person", "loud-and-rich", "rectangle-area-ii"]}, {"contest_title": "\u7b2c 89 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 89", "contest_title_slug": "weekly-contest-89", "contest_id": 12, "contest_start_time": 1529199000, "contest_duration": 5400, "user_num": 491, "question_slugs": ["peak-index-in-a-mountain-array", "car-fleet", "exam-room", "k-similar-strings"]}, {"contest_title": "\u7b2c 90 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 90", "contest_title_slug": "weekly-contest-90", "contest_id": 13, "contest_start_time": 1529803800, "contest_duration": 5400, "user_num": 573, "question_slugs": ["buddy-strings", "score-of-parentheses", "mirror-reflection", "minimum-cost-to-hire-k-workers"]}, {"contest_title": "\u7b2c 91 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 91", "contest_title_slug": "weekly-contest-91", "contest_id": 14, "contest_start_time": 1530408600, "contest_duration": 5400, "user_num": 578, "question_slugs": ["lemonade-change", "all-nodes-distance-k-in-binary-tree", "score-after-flipping-matrix", "shortest-subarray-with-sum-at-least-k"]}, {"contest_title": "\u7b2c 92 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 92", "contest_title_slug": "weekly-contest-92", "contest_id": 15, "contest_start_time": 1531013400, "contest_duration": 5400, "user_num": 610, "question_slugs": ["transpose-matrix", "smallest-subtree-with-all-the-deepest-nodes", "prime-palindrome", "shortest-path-to-get-all-keys"]}, {"contest_title": "\u7b2c 93 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 93", "contest_title_slug": "weekly-contest-93", "contest_id": 16, "contest_start_time": 1531618200, "contest_duration": 5400, "user_num": 732, "question_slugs": ["binary-gap", "reordered-power-of-2", "advantage-shuffle", "minimum-number-of-refueling-stops"]}, {"contest_title": "\u7b2c 94 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 94", "contest_title_slug": "weekly-contest-94", "contest_id": 17, "contest_start_time": 1532223000, "contest_duration": 5400, "user_num": 733, "question_slugs": ["leaf-similar-trees", "walking-robot-simulation", "koko-eating-bananas", "length-of-longest-fibonacci-subsequence"]}, {"contest_title": "\u7b2c 95 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 95", "contest_title_slug": "weekly-contest-95", "contest_id": 18, "contest_start_time": 1532827800, "contest_duration": 5400, "user_num": 831, "question_slugs": ["middle-of-the-linked-list", "stone-game", "nth-magical-number", "profitable-schemes"]}, {"contest_title": "\u7b2c 96 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 96", "contest_title_slug": "weekly-contest-96", "contest_id": 19, "contest_start_time": 1533432600, "contest_duration": 5400, "user_num": 789, "question_slugs": ["projection-area-of-3d-shapes", "boats-to-save-people", "decoded-string-at-index", "reachable-nodes-in-subdivided-graph"]}, {"contest_title": "\u7b2c 97 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 97", "contest_title_slug": "weekly-contest-97", "contest_id": 20, "contest_start_time": 1534037400, "contest_duration": 5400, "user_num": 635, "question_slugs": ["uncommon-words-from-two-sentences", "spiral-matrix-iii", "possible-bipartition", "super-egg-drop"]}, {"contest_title": "\u7b2c 98 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 98", "contest_title_slug": "weekly-contest-98", "contest_id": 21, "contest_start_time": 1534642200, "contest_duration": 5400, "user_num": 670, "question_slugs": ["fair-candy-swap", "find-and-replace-pattern", "construct-binary-tree-from-preorder-and-postorder-traversal", "sum-of-subsequence-widths"]}, {"contest_title": "\u7b2c 99 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 99", "contest_title_slug": "weekly-contest-99", "contest_id": 22, "contest_start_time": 1535247000, "contest_duration": 5400, "user_num": 725, "question_slugs": ["surface-area-of-3d-shapes", "groups-of-special-equivalent-strings", "all-possible-full-binary-trees", "maximum-frequency-stack"]}, {"contest_title": "\u7b2c 100 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 100", "contest_title_slug": "weekly-contest-100", "contest_id": 23, "contest_start_time": 1535851800, "contest_duration": 5400, "user_num": 718, "question_slugs": ["monotonic-array", "increasing-order-search-tree", "bitwise-ors-of-subarrays", "orderly-queue"]}, {"contest_title": "\u7b2c 101 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 101", "contest_title_slug": "weekly-contest-101", "contest_id": 24, "contest_start_time": 1536456600, "contest_duration": 6300, "user_num": 854, "question_slugs": ["rle-iterator", "online-stock-span", "numbers-at-most-n-given-digit-set", "valid-permutations-for-di-sequence"]}, {"contest_title": "\u7b2c 102 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 102", "contest_title_slug": "weekly-contest-102", "contest_id": 25, "contest_start_time": 1537061400, "contest_duration": 5400, "user_num": 660, "question_slugs": ["sort-array-by-parity", "fruit-into-baskets", "sum-of-subarray-minimums", "super-palindromes"]}, {"contest_title": "\u7b2c 103 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 103", "contest_title_slug": "weekly-contest-103", "contest_id": 26, "contest_start_time": 1537666200, "contest_duration": 5400, "user_num": 575, "question_slugs": ["smallest-range-i", "snakes-and-ladders", "smallest-range-ii", "online-election"]}, {"contest_title": "\u7b2c 104 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 104", "contest_title_slug": "weekly-contest-104", "contest_id": 27, "contest_start_time": 1538271000, "contest_duration": 5400, "user_num": 354, "question_slugs": ["x-of-a-kind-in-a-deck-of-cards", "partition-array-into-disjoint-intervals", "word-subsets", "cat-and-mouse"]}, {"contest_title": "\u7b2c 105 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 105", "contest_title_slug": "weekly-contest-105", "contest_id": 28, "contest_start_time": 1538875800, "contest_duration": 5400, "user_num": 393, "question_slugs": ["reverse-only-letters", "maximum-sum-circular-subarray", "complete-binary-tree-inserter", "number-of-music-playlists"]}, {"contest_title": "\u7b2c 106 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 106", "contest_title_slug": "weekly-contest-106", "contest_id": 29, "contest_start_time": 1539480600, "contest_duration": 5400, "user_num": 369, "question_slugs": ["sort-array-by-parity-ii", "minimum-add-to-make-parentheses-valid", "3sum-with-multiplicity", "minimize-malware-spread"]}, {"contest_title": "\u7b2c 107 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 107", "contest_title_slug": "weekly-contest-107", "contest_id": 30, "contest_start_time": 1540085400, "contest_duration": 5400, "user_num": 504, "question_slugs": ["long-pressed-name", "flip-string-to-monotone-increasing", "three-equal-parts", "minimize-malware-spread-ii"]}, {"contest_title": "\u7b2c 108 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 108", "contest_title_slug": "weekly-contest-108", "contest_id": 31, "contest_start_time": 1540690200, "contest_duration": 5400, "user_num": 524, "question_slugs": ["unique-email-addresses", "binary-subarrays-with-sum", "minimum-falling-path-sum", "beautiful-array"]}, {"contest_title": "\u7b2c 109 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 109", "contest_title_slug": "weekly-contest-109", "contest_id": 32, "contest_start_time": 1541295000, "contest_duration": 5400, "user_num": 439, "question_slugs": ["number-of-recent-calls", "knight-dialer", "shortest-bridge", "stamping-the-sequence"]}, {"contest_title": "\u7b2c 110 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 110", "contest_title_slug": "weekly-contest-110", "contest_id": 33, "contest_start_time": 1541903400, "contest_duration": 5400, "user_num": 346, "question_slugs": ["reorder-data-in-log-files", "range-sum-of-bst", "minimum-area-rectangle", "distinct-subsequences-ii"]}, {"contest_title": "\u7b2c 111 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 111", "contest_title_slug": "weekly-contest-111", "contest_id": 34, "contest_start_time": 1542508200, "contest_duration": 5400, "user_num": 353, "question_slugs": ["valid-mountain-array", "delete-columns-to-make-sorted", "di-string-match", "find-the-shortest-superstring"]}, {"contest_title": "\u7b2c 112 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 112", "contest_title_slug": "weekly-contest-112", "contest_id": 35, "contest_start_time": 1543113000, "contest_duration": 5400, "user_num": 299, "question_slugs": ["minimum-increment-to-make-array-unique", "validate-stack-sequences", "most-stones-removed-with-same-row-or-column", "bag-of-tokens"]}, {"contest_title": "\u7b2c 113 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 113", "contest_title_slug": "weekly-contest-113", "contest_id": 36, "contest_start_time": 1543717800, "contest_duration": 5400, "user_num": 462, "question_slugs": ["largest-time-for-given-digits", "flip-equivalent-binary-trees", "reveal-cards-in-increasing-order", "largest-component-size-by-common-factor"]}, {"contest_title": "\u7b2c 114 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 114", "contest_title_slug": "weekly-contest-114", "contest_id": 37, "contest_start_time": 1544322600, "contest_duration": 5400, "user_num": 391, "question_slugs": ["verifying-an-alien-dictionary", "array-of-doubled-pairs", "delete-columns-to-make-sorted-ii", "tallest-billboard"]}, {"contest_title": "\u7b2c 115 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 115", "contest_title_slug": "weekly-contest-115", "contest_id": 38, "contest_start_time": 1544927400, "contest_duration": 5400, "user_num": 383, "question_slugs": ["prison-cells-after-n-days", "check-completeness-of-a-binary-tree", "regions-cut-by-slashes", "delete-columns-to-make-sorted-iii"]}, {"contest_title": "\u7b2c 116 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 116", "contest_title_slug": "weekly-contest-116", "contest_id": 39, "contest_start_time": 1545532200, "contest_duration": 5400, "user_num": 369, "question_slugs": ["n-repeated-element-in-size-2n-array", "maximum-width-ramp", "minimum-area-rectangle-ii", "least-operators-to-express-number"]}, {"contest_title": "\u7b2c 117 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 117", "contest_title_slug": "weekly-contest-117", "contest_id": 41, "contest_start_time": 1546137000, "contest_duration": 5400, "user_num": 657, "question_slugs": ["univalued-binary-tree", "numbers-with-same-consecutive-differences", "vowel-spellchecker", "binary-tree-cameras"]}, {"contest_title": "\u7b2c 118 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 118", "contest_title_slug": "weekly-contest-118", "contest_id": 42, "contest_start_time": 1546741800, "contest_duration": 5400, "user_num": 383, "question_slugs": ["powerful-integers", "pancake-sorting", "flip-binary-tree-to-match-preorder-traversal", "equal-rational-numbers"]}, {"contest_title": "\u7b2c 119 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 119", "contest_title_slug": "weekly-contest-119", "contest_id": 43, "contest_start_time": 1547346600, "contest_duration": 5400, "user_num": 513, "question_slugs": ["k-closest-points-to-origin", "largest-perimeter-triangle", "subarray-sums-divisible-by-k", "odd-even-jump"]}, {"contest_title": "\u7b2c 120 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 120", "contest_title_slug": "weekly-contest-120", "contest_id": 44, "contest_start_time": 1547951400, "contest_duration": 5400, "user_num": 382, "question_slugs": ["squares-of-a-sorted-array", "longest-turbulent-subarray", "distribute-coins-in-binary-tree", "unique-paths-iii"]}, {"contest_title": "\u7b2c 121 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 121", "contest_title_slug": "weekly-contest-121", "contest_id": 45, "contest_start_time": 1548556200, "contest_duration": 5400, "user_num": 384, "question_slugs": ["string-without-aaa-or-bbb", "time-based-key-value-store", "minimum-cost-for-tickets", "triples-with-bitwise-and-equal-to-zero"]}, {"contest_title": "\u7b2c 122 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 122", "contest_title_slug": "weekly-contest-122", "contest_id": 46, "contest_start_time": 1549161000, "contest_duration": 5400, "user_num": 280, "question_slugs": ["sum-of-even-numbers-after-queries", "smallest-string-starting-from-leaf", "interval-list-intersections", "vertical-order-traversal-of-a-binary-tree"]}, {"contest_title": "\u7b2c 123 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 123", "contest_title_slug": "weekly-contest-123", "contest_id": 47, "contest_start_time": 1549765800, "contest_duration": 5400, "user_num": 247, "question_slugs": ["add-to-array-form-of-integer", "satisfiability-of-equality-equations", "broken-calculator", "subarrays-with-k-different-integers"]}, {"contest_title": "\u7b2c 124 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 124", "contest_title_slug": "weekly-contest-124", "contest_id": 48, "contest_start_time": 1550370600, "contest_duration": 5400, "user_num": 417, "question_slugs": ["cousins-in-binary-tree", "rotting-oranges", "minimum-number-of-k-consecutive-bit-flips", "number-of-squareful-arrays"]}, {"contest_title": "\u7b2c 125 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 125", "contest_title_slug": "weekly-contest-125", "contest_id": 49, "contest_start_time": 1550975400, "contest_duration": 5400, "user_num": 469, "question_slugs": ["find-the-town-judge", "available-captures-for-rook", "maximum-binary-tree-ii", "grid-illumination"]}, {"contest_title": "\u7b2c 126 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 126", "contest_title_slug": "weekly-contest-126", "contest_id": 50, "contest_start_time": 1551580200, "contest_duration": 5400, "user_num": 591, "question_slugs": ["find-common-characters", "check-if-word-is-valid-after-substitutions", "max-consecutive-ones-iii", "minimum-cost-to-merge-stones"]}, {"contest_title": "\u7b2c 127 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 127", "contest_title_slug": "weekly-contest-127", "contest_id": 52, "contest_start_time": 1552185000, "contest_duration": 5400, "user_num": 664, "question_slugs": ["maximize-sum-of-array-after-k-negations", "clumsy-factorial", "minimum-domino-rotations-for-equal-row", "construct-binary-search-tree-from-preorder-traversal"]}, {"contest_title": "\u7b2c 128 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 128", "contest_title_slug": "weekly-contest-128", "contest_id": 53, "contest_start_time": 1552789800, "contest_duration": 5400, "user_num": 1251, "question_slugs": ["complement-of-base-10-integer", "pairs-of-songs-with-total-durations-divisible-by-60", "capacity-to-ship-packages-within-d-days", "numbers-with-repeated-digits"]}, {"contest_title": "\u7b2c 129 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 129", "contest_title_slug": "weekly-contest-129", "contest_id": 54, "contest_start_time": 1553391000, "contest_duration": 5400, "user_num": 759, "question_slugs": ["partition-array-into-three-parts-with-equal-sum", "smallest-integer-divisible-by-k", "best-sightseeing-pair", "binary-string-with-substrings-representing-1-to-n"]}, {"contest_title": "\u7b2c 130 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 130", "contest_title_slug": "weekly-contest-130", "contest_id": 55, "contest_start_time": 1553999400, "contest_duration": 5400, "user_num": 1294, "question_slugs": ["binary-prefix-divisible-by-5", "convert-to-base-2", "next-greater-node-in-linked-list", "number-of-enclaves"]}, {"contest_title": "\u7b2c 131 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 131", "contest_title_slug": "weekly-contest-131", "contest_id": 56, "contest_start_time": 1554604200, "contest_duration": 5400, "user_num": 918, "question_slugs": ["remove-outermost-parentheses", "sum-of-root-to-leaf-binary-numbers", "camelcase-matching", "video-stitching"]}, {"contest_title": "\u7b2c 132 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 132", "contest_title_slug": "weekly-contest-132", "contest_id": 57, "contest_start_time": 1555209000, "contest_duration": 5400, "user_num": 1050, "question_slugs": ["divisor-game", "maximum-difference-between-node-and-ancestor", "longest-arithmetic-subsequence", "recover-a-tree-from-preorder-traversal"]}, {"contest_title": "\u7b2c 133 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 133", "contest_title_slug": "weekly-contest-133", "contest_id": 59, "contest_start_time": 1555813800, "contest_duration": 5400, "user_num": 999, "question_slugs": ["two-city-scheduling", "matrix-cells-in-distance-order", "maximum-sum-of-two-non-overlapping-subarrays", "stream-of-characters"]}, {"contest_title": "\u7b2c 134 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 134", "contest_title_slug": "weekly-contest-134", "contest_id": 64, "contest_start_time": 1556418600, "contest_duration": 5400, "user_num": 728, "question_slugs": ["moving-stones-until-consecutive", "coloring-a-border", "uncrossed-lines", "escape-a-large-maze"]}, {"contest_title": "\u7b2c 135 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 135", "contest_title_slug": "weekly-contest-135", "contest_id": 65, "contest_start_time": 1557023400, "contest_duration": 5400, "user_num": 549, "question_slugs": ["valid-boomerang", "binary-search-tree-to-greater-sum-tree", "minimum-score-triangulation-of-polygon", "moving-stones-until-consecutive-ii"]}, {"contest_title": "\u7b2c 136 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 136", "contest_title_slug": "weekly-contest-136", "contest_id": 66, "contest_start_time": 1557628200, "contest_duration": 5400, "user_num": 790, "question_slugs": ["robot-bounded-in-circle", "flower-planting-with-no-adjacent", "partition-array-for-maximum-sum", "longest-duplicate-substring"]}, {"contest_title": "\u7b2c 137 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 137", "contest_title_slug": "weekly-contest-137", "contest_id": 67, "contest_start_time": 1558233000, "contest_duration": 5400, "user_num": 766, "question_slugs": ["last-stone-weight", "remove-all-adjacent-duplicates-in-string", "longest-string-chain", "last-stone-weight-ii"]}, {"contest_title": "\u7b2c 138 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 138", "contest_title_slug": "weekly-contest-138", "contest_id": 68, "contest_start_time": 1558837800, "contest_duration": 5400, "user_num": 752, "question_slugs": ["height-checker", "grumpy-bookstore-owner", "previous-permutation-with-one-swap", "distant-barcodes"]}, {"contest_title": "\u7b2c 139 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 139", "contest_title_slug": "weekly-contest-139", "contest_id": 69, "contest_start_time": 1559442600, "contest_duration": 5400, "user_num": 785, "question_slugs": ["greatest-common-divisor-of-strings", "flip-columns-for-maximum-number-of-equal-rows", "adding-two-negabinary-numbers", "number-of-submatrices-that-sum-to-target"]}, {"contest_title": "\u7b2c 140 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 140", "contest_title_slug": "weekly-contest-140", "contest_id": 71, "contest_start_time": 1560047400, "contest_duration": 5400, "user_num": 660, "question_slugs": ["occurrences-after-bigram", "letter-tile-possibilities", "insufficient-nodes-in-root-to-leaf-paths", "smallest-subsequence-of-distinct-characters"]}, {"contest_title": "\u7b2c 141 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 141", "contest_title_slug": "weekly-contest-141", "contest_id": 72, "contest_start_time": 1560652200, "contest_duration": 5400, "user_num": 763, "question_slugs": ["duplicate-zeros", "largest-values-from-labels", "shortest-path-in-binary-matrix", "shortest-common-supersequence"]}, {"contest_title": "\u7b2c 142 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 142", "contest_title_slug": "weekly-contest-142", "contest_id": 74, "contest_start_time": 1561257000, "contest_duration": 5400, "user_num": 801, "question_slugs": ["statistics-from-a-large-sample", "car-pooling", "find-in-mountain-array", "brace-expansion-ii"]}, {"contest_title": "\u7b2c 143 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 143", "contest_title_slug": "weekly-contest-143", "contest_id": 84, "contest_start_time": 1561861800, "contest_duration": 5400, "user_num": 803, "question_slugs": ["distribute-candies-to-people", "path-in-zigzag-labelled-binary-tree", "filling-bookcase-shelves", "parsing-a-boolean-expression"]}, {"contest_title": "\u7b2c 144 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 144", "contest_title_slug": "weekly-contest-144", "contest_id": 86, "contest_start_time": 1562466600, "contest_duration": 5400, "user_num": 777, "question_slugs": ["defanging-an-ip-address", "corporate-flight-bookings", "delete-nodes-and-return-forest", "maximum-nesting-depth-of-two-valid-parentheses-strings"]}, {"contest_title": "\u7b2c 145 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 145", "contest_title_slug": "weekly-contest-145", "contest_id": 87, "contest_start_time": 1563071400, "contest_duration": 5400, "user_num": 1114, "question_slugs": ["relative-sort-array", "lowest-common-ancestor-of-deepest-leaves", "longest-well-performing-interval", "smallest-sufficient-team"]}, {"contest_title": "\u7b2c 146 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 146", "contest_title_slug": "weekly-contest-146", "contest_id": 89, "contest_start_time": 1563676200, "contest_duration": 5400, "user_num": 1189, "question_slugs": ["number-of-equivalent-domino-pairs", "shortest-path-with-alternating-colors", "minimum-cost-tree-from-leaf-values", "maximum-of-absolute-value-expression"]}, {"contest_title": "\u7b2c 147 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 147", "contest_title_slug": "weekly-contest-147", "contest_id": 90, "contest_start_time": 1564281000, "contest_duration": 5400, "user_num": 1132, "question_slugs": ["n-th-tribonacci-number", "alphabet-board-path", "largest-1-bordered-square", "stone-game-ii"]}, {"contest_title": "\u7b2c 148 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 148", "contest_title_slug": "weekly-contest-148", "contest_id": 93, "contest_start_time": 1564885800, "contest_duration": 5400, "user_num": 1251, "question_slugs": ["decrease-elements-to-make-array-zigzag", "binary-tree-coloring-game", "snapshot-array", "longest-chunked-palindrome-decomposition"]}, {"contest_title": "\u7b2c 149 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 149", "contest_title_slug": "weekly-contest-149", "contest_id": 94, "contest_start_time": 1565490600, "contest_duration": 5400, "user_num": 1351, "question_slugs": ["day-of-the-year", "number-of-dice-rolls-with-target-sum", "swap-for-longest-repeated-character-substring", "online-majority-element-in-subarray"]}, {"contest_title": "\u7b2c 150 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 150", "contest_title_slug": "weekly-contest-150", "contest_id": 96, "contest_start_time": 1566095400, "contest_duration": 5400, "user_num": 1473, "question_slugs": ["find-words-that-can-be-formed-by-characters", "maximum-level-sum-of-a-binary-tree", "as-far-from-land-as-possible", "last-substring-in-lexicographical-order"]}, {"contest_title": "\u7b2c 151 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 151", "contest_title_slug": "weekly-contest-151", "contest_id": 98, "contest_start_time": 1566700200, "contest_duration": 5400, "user_num": 1341, "question_slugs": ["invalid-transactions", "compare-strings-by-frequency-of-the-smallest-character", "remove-zero-sum-consecutive-nodes-from-linked-list", "dinner-plate-stacks"]}, {"contest_title": "\u7b2c 152 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 152", "contest_title_slug": "weekly-contest-152", "contest_id": 100, "contest_start_time": 1567305000, "contest_duration": 5400, "user_num": 1367, "question_slugs": ["prime-arrangements", "diet-plan-performance", "can-make-palindrome-from-substring", "number-of-valid-words-for-each-puzzle"]}, {"contest_title": "\u7b2c 153 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 153", "contest_title_slug": "weekly-contest-153", "contest_id": 102, "contest_start_time": 1567909800, "contest_duration": 5400, "user_num": 1434, "question_slugs": ["distance-between-bus-stops", "day-of-the-week", "maximum-subarray-sum-with-one-deletion", "make-array-strictly-increasing"]}, {"contest_title": "\u7b2c 154 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 154", "contest_title_slug": "weekly-contest-154", "contest_id": 106, "contest_start_time": 1568514600, "contest_duration": 5400, "user_num": 1299, "question_slugs": ["maximum-number-of-balloons", "reverse-substrings-between-each-pair-of-parentheses", "k-concatenation-maximum-sum", "critical-connections-in-a-network"]}, {"contest_title": "\u7b2c 155 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 155", "contest_title_slug": "weekly-contest-155", "contest_id": 107, "contest_start_time": 1569119400, "contest_duration": 5400, "user_num": 1603, "question_slugs": ["minimum-absolute-difference", "ugly-number-iii", "smallest-string-with-swaps", "sort-items-by-groups-respecting-dependencies"]}, {"contest_title": "\u7b2c 156 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 156", "contest_title_slug": "weekly-contest-156", "contest_id": 113, "contest_start_time": 1569724200, "contest_duration": 5400, "user_num": 1433, "question_slugs": ["unique-number-of-occurrences", "get-equal-substrings-within-budget", "remove-all-adjacent-duplicates-in-string-ii", "minimum-moves-to-reach-target-with-rotations"]}, {"contest_title": "\u7b2c 157 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 157", "contest_title_slug": "weekly-contest-157", "contest_id": 114, "contest_start_time": 1570329000, "contest_duration": 5400, "user_num": 1217, "question_slugs": ["minimum-cost-to-move-chips-to-the-same-position", "longest-arithmetic-subsequence-of-given-difference", "path-with-maximum-gold", "count-vowels-permutation"]}, {"contest_title": "\u7b2c 158 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 158", "contest_title_slug": "weekly-contest-158", "contest_id": 116, "contest_start_time": 1570933800, "contest_duration": 5400, "user_num": 1716, "question_slugs": ["split-a-string-in-balanced-strings", "queens-that-can-attack-the-king", "dice-roll-simulation", "maximum-equal-frequency"]}, {"contest_title": "\u7b2c 159 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 159", "contest_title_slug": "weekly-contest-159", "contest_id": 117, "contest_start_time": 1571538600, "contest_duration": 5400, "user_num": 1634, "question_slugs": ["check-if-it-is-a-straight-line", "remove-sub-folders-from-the-filesystem", "replace-the-substring-for-balanced-string", "maximum-profit-in-job-scheduling"]}, {"contest_title": "\u7b2c 160 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 160", "contest_title_slug": "weekly-contest-160", "contest_id": 119, "contest_start_time": 1572143400, "contest_duration": 5400, "user_num": 1692, "question_slugs": ["find-positive-integer-solution-for-a-given-equation", "circular-permutation-in-binary-representation", "maximum-length-of-a-concatenated-string-with-unique-characters", "tiling-a-rectangle-with-the-fewest-squares"]}, {"contest_title": "\u7b2c 161 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 161", "contest_title_slug": "weekly-contest-161", "contest_id": 120, "contest_start_time": 1572748200, "contest_duration": 5400, "user_num": 1610, "question_slugs": ["minimum-swaps-to-make-strings-equal", "count-number-of-nice-subarrays", "minimum-remove-to-make-valid-parentheses", "check-if-it-is-a-good-array"]}, {"contest_title": "\u7b2c 162 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 162", "contest_title_slug": "weekly-contest-162", "contest_id": 122, "contest_start_time": 1573353000, "contest_duration": 5400, "user_num": 1569, "question_slugs": ["cells-with-odd-values-in-a-matrix", "reconstruct-a-2-row-binary-matrix", "number-of-closed-islands", "maximum-score-words-formed-by-letters"]}, {"contest_title": "\u7b2c 163 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 163", "contest_title_slug": "weekly-contest-163", "contest_id": 123, "contest_start_time": 1573957800, "contest_duration": 5400, "user_num": 1605, "question_slugs": ["shift-2d-grid", "find-elements-in-a-contaminated-binary-tree", "greatest-sum-divisible-by-three", "minimum-moves-to-move-a-box-to-their-target-location"]}, {"contest_title": "\u7b2c 164 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 164", "contest_title_slug": "weekly-contest-164", "contest_id": 125, "contest_start_time": 1574562600, "contest_duration": 5400, "user_num": 1676, "question_slugs": ["minimum-time-visiting-all-points", "count-servers-that-communicate", "search-suggestions-system", "number-of-ways-to-stay-in-the-same-place-after-some-steps"]}, {"contest_title": "\u7b2c 165 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 165", "contest_title_slug": "weekly-contest-165", "contest_id": 128, "contest_start_time": 1575167400, "contest_duration": 5400, "user_num": 1660, "question_slugs": ["find-winner-on-a-tic-tac-toe-game", "number-of-burgers-with-no-waste-of-ingredients", "count-square-submatrices-with-all-ones", "palindrome-partitioning-iii"]}, {"contest_title": "\u7b2c 166 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 166", "contest_title_slug": "weekly-contest-166", "contest_id": 130, "contest_start_time": 1575772200, "contest_duration": 5400, "user_num": 1676, "question_slugs": ["subtract-the-product-and-sum-of-digits-of-an-integer", "group-the-people-given-the-group-size-they-belong-to", "find-the-smallest-divisor-given-a-threshold", "minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix"]}, {"contest_title": "\u7b2c 167 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 167", "contest_title_slug": "weekly-contest-167", "contest_id": 131, "contest_start_time": 1576377000, "contest_duration": 5400, "user_num": 1537, "question_slugs": ["convert-binary-number-in-a-linked-list-to-integer", "sequential-digits", "maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold", "shortest-path-in-a-grid-with-obstacles-elimination"]}, {"contest_title": "\u7b2c 168 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 168", "contest_title_slug": "weekly-contest-168", "contest_id": 133, "contest_start_time": 1576981800, "contest_duration": 5400, "user_num": 1553, "question_slugs": ["find-numbers-with-even-number-of-digits", "divide-array-in-sets-of-k-consecutive-numbers", "maximum-number-of-occurrences-of-a-substring", "maximum-candies-you-can-get-from-boxes"]}, {"contest_title": "\u7b2c 169 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 169", "contest_title_slug": "weekly-contest-169", "contest_id": 134, "contest_start_time": 1577586600, "contest_duration": 5400, "user_num": 1568, "question_slugs": ["find-n-unique-integers-sum-up-to-zero", "all-elements-in-two-binary-search-trees", "jump-game-iii", "verbal-arithmetic-puzzle"]}, {"contest_title": "\u7b2c 170 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 170", "contest_title_slug": "weekly-contest-170", "contest_id": 136, "contest_start_time": 1578191400, "contest_duration": 5400, "user_num": 1649, "question_slugs": ["decrypt-string-from-alphabet-to-integer-mapping", "xor-queries-of-a-subarray", "get-watched-videos-by-your-friends", "minimum-insertion-steps-to-make-a-string-palindrome"]}, {"contest_title": "\u7b2c 171 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 171", "contest_title_slug": "weekly-contest-171", "contest_id": 137, "contest_start_time": 1578796200, "contest_duration": 5400, "user_num": 1708, "question_slugs": ["convert-integer-to-the-sum-of-two-no-zero-integers", "minimum-flips-to-make-a-or-b-equal-to-c", "number-of-operations-to-make-network-connected", "minimum-distance-to-type-a-word-using-two-fingers"]}, {"contest_title": "\u7b2c 172 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 172", "contest_title_slug": "weekly-contest-172", "contest_id": 139, "contest_start_time": 1579401000, "contest_duration": 5400, "user_num": 1415, "question_slugs": ["maximum-69-number", "print-words-vertically", "delete-leaves-with-a-given-value", "minimum-number-of-taps-to-open-to-water-a-garden"]}, {"contest_title": "\u7b2c 173 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 173", "contest_title_slug": "weekly-contest-173", "contest_id": 142, "contest_start_time": 1580005800, "contest_duration": 5400, "user_num": 1072, "question_slugs": ["remove-palindromic-subsequences", "filter-restaurants-by-vegan-friendly-price-and-distance", "find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance", "minimum-difficulty-of-a-job-schedule"]}, {"contest_title": "\u7b2c 174 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 174", "contest_title_slug": "weekly-contest-174", "contest_id": 144, "contest_start_time": 1580610600, "contest_duration": 5400, "user_num": 1660, "question_slugs": ["the-k-weakest-rows-in-a-matrix", "reduce-array-size-to-the-half", "maximum-product-of-splitted-binary-tree", "jump-game-v"]}, {"contest_title": "\u7b2c 175 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 175", "contest_title_slug": "weekly-contest-175", "contest_id": 145, "contest_start_time": 1581215400, "contest_duration": 5400, "user_num": 2048, "question_slugs": ["check-if-n-and-its-double-exist", "minimum-number-of-steps-to-make-two-strings-anagram", "tweet-counts-per-frequency", "maximum-students-taking-exam"]}, {"contest_title": "\u7b2c 176 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 176", "contest_title_slug": "weekly-contest-176", "contest_id": 147, "contest_start_time": 1581820200, "contest_duration": 5400, "user_num": 2410, "question_slugs": ["count-negative-numbers-in-a-sorted-matrix", "product-of-the-last-k-numbers", "maximum-number-of-events-that-can-be-attended", "construct-target-array-with-multiple-sums"]}, {"contest_title": "\u7b2c 177 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 177", "contest_title_slug": "weekly-contest-177", "contest_id": 148, "contest_start_time": 1582425000, "contest_duration": 5400, "user_num": 2986, "question_slugs": ["number-of-days-between-two-dates", "validate-binary-tree-nodes", "closest-divisors", "largest-multiple-of-three"]}, {"contest_title": "\u7b2c 178 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 178", "contest_title_slug": "weekly-contest-178", "contest_id": 154, "contest_start_time": 1583029800, "contest_duration": 5400, "user_num": 3305, "question_slugs": ["how-many-numbers-are-smaller-than-the-current-number", "rank-teams-by-votes", "linked-list-in-binary-tree", "minimum-cost-to-make-at-least-one-valid-path-in-a-grid"]}, {"contest_title": "\u7b2c 179 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 179", "contest_title_slug": "weekly-contest-179", "contest_id": 156, "contest_start_time": 1583634600, "contest_duration": 5400, "user_num": 3606, "question_slugs": ["generate-a-string-with-characters-that-have-odd-counts", "number-of-times-binary-string-is-prefix-aligned", "time-needed-to-inform-all-employees", "frog-position-after-t-seconds"]}, {"contest_title": "\u7b2c 180 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 180", "contest_title_slug": "weekly-contest-180", "contest_id": 160, "contest_start_time": 1584239400, "contest_duration": 5400, "user_num": 3715, "question_slugs": ["lucky-numbers-in-a-matrix", "design-a-stack-with-increment-operation", "balance-a-binary-search-tree", "maximum-performance-of-a-team"]}, {"contest_title": "\u7b2c 181 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 181", "contest_title_slug": "weekly-contest-181", "contest_id": 162, "contest_start_time": 1584844200, "contest_duration": 5400, "user_num": 4149, "question_slugs": ["create-target-array-in-the-given-order", "four-divisors", "check-if-there-is-a-valid-path-in-a-grid", "longest-happy-prefix"]}, {"contest_title": "\u7b2c 182 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 182", "contest_title_slug": "weekly-contest-182", "contest_id": 166, "contest_start_time": 1585449000, "contest_duration": 5400, "user_num": 3911, "question_slugs": ["find-lucky-integer-in-an-array", "count-number-of-teams", "design-underground-system", "find-all-good-strings"]}, {"contest_title": "\u7b2c 183 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 183", "contest_title_slug": "weekly-contest-183", "contest_id": 168, "contest_start_time": 1586053800, "contest_duration": 5400, "user_num": 3756, "question_slugs": ["minimum-subsequence-in-non-increasing-order", "number-of-steps-to-reduce-a-number-in-binary-representation-to-one", "longest-happy-string", "stone-game-iii"]}, {"contest_title": "\u7b2c 184 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 184", "contest_title_slug": "weekly-contest-184", "contest_id": 175, "contest_start_time": 1586658600, "contest_duration": 5400, "user_num": 3847, "question_slugs": ["string-matching-in-an-array", "queries-on-a-permutation-with-key", "html-entity-parser", "number-of-ways-to-paint-n-3-grid"]}, {"contest_title": "\u7b2c 185 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 185", "contest_title_slug": "weekly-contest-185", "contest_id": 177, "contest_start_time": 1587263400, "contest_duration": 5400, "user_num": 5004, "question_slugs": ["reformat-the-string", "display-table-of-food-orders-in-a-restaurant", "minimum-number-of-frogs-croaking", "build-array-where-you-can-find-the-maximum-exactly-k-comparisons"]}, {"contest_title": "\u7b2c 186 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 186", "contest_title_slug": "weekly-contest-186", "contest_id": 185, "contest_start_time": 1587868200, "contest_duration": 5400, "user_num": 3108, "question_slugs": ["maximum-score-after-splitting-a-string", "maximum-points-you-can-obtain-from-cards", "diagonal-traverse-ii", "constrained-subsequence-sum"]}, {"contest_title": "\u7b2c 187 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 187", "contest_title_slug": "weekly-contest-187", "contest_id": 191, "contest_start_time": 1588473000, "contest_duration": 5400, "user_num": 3109, "question_slugs": ["destination-city", "check-if-all-1s-are-at-least-length-k-places-away", "longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit", "find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows"]}, {"contest_title": "\u7b2c 188 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 188", "contest_title_slug": "weekly-contest-188", "contest_id": 195, "contest_start_time": 1589077800, "contest_duration": 5400, "user_num": 3982, "question_slugs": ["build-an-array-with-stack-operations", "count-triplets-that-can-form-two-arrays-of-equal-xor", "minimum-time-to-collect-all-apples-in-a-tree", "number-of-ways-of-cutting-a-pizza"]}, {"contest_title": "\u7b2c 189 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 189", "contest_title_slug": "weekly-contest-189", "contest_id": 197, "contest_start_time": 1589682600, "contest_duration": 5400, "user_num": 3692, "question_slugs": ["number-of-students-doing-homework-at-a-given-time", "rearrange-words-in-a-sentence", "people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list", "maximum-number-of-darts-inside-of-a-circular-dartboard"]}, {"contest_title": "\u7b2c 190 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 190", "contest_title_slug": "weekly-contest-190", "contest_id": 201, "contest_start_time": 1590287400, "contest_duration": 5400, "user_num": 3352, "question_slugs": ["check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence", "maximum-number-of-vowels-in-a-substring-of-given-length", "pseudo-palindromic-paths-in-a-binary-tree", "max-dot-product-of-two-subsequences"]}, {"contest_title": "\u7b2c 191 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 191", "contest_title_slug": "weekly-contest-191", "contest_id": 203, "contest_start_time": 1590892200, "contest_duration": 5400, "user_num": 3687, "question_slugs": ["maximum-product-of-two-elements-in-an-array", "maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts", "reorder-routes-to-make-all-paths-lead-to-the-city-zero", "probability-of-a-two-boxes-having-the-same-number-of-distinct-balls"]}, {"contest_title": "\u7b2c 192 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 192", "contest_title_slug": "weekly-contest-192", "contest_id": 207, "contest_start_time": 1591497000, "contest_duration": 5400, "user_num": 3615, "question_slugs": ["shuffle-the-array", "the-k-strongest-values-in-an-array", "design-browser-history", "paint-house-iii"]}, {"contest_title": "\u7b2c 193 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 193", "contest_title_slug": "weekly-contest-193", "contest_id": 209, "contest_start_time": 1592101800, "contest_duration": 5400, "user_num": 3804, "question_slugs": ["running-sum-of-1d-array", "least-number-of-unique-integers-after-k-removals", "minimum-number-of-days-to-make-m-bouquets", "kth-ancestor-of-a-tree-node"]}, {"contest_title": "\u7b2c 194 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 194", "contest_title_slug": "weekly-contest-194", "contest_id": 213, "contest_start_time": 1592706600, "contest_duration": 5400, "user_num": 4378, "question_slugs": ["xor-operation-in-an-array", "making-file-names-unique", "avoid-flood-in-the-city", "find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree"]}, {"contest_title": "\u7b2c 195 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 195", "contest_title_slug": "weekly-contest-195", "contest_id": 215, "contest_start_time": 1593311400, "contest_duration": 5400, "user_num": 3401, "question_slugs": ["path-crossing", "check-if-array-pairs-are-divisible-by-k", "number-of-subsequences-that-satisfy-the-given-sum-condition", "max-value-of-equation"]}, {"contest_title": "\u7b2c 196 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 196", "contest_title_slug": "weekly-contest-196", "contest_id": 219, "contest_start_time": 1593916200, "contest_duration": 5400, "user_num": 5507, "question_slugs": ["can-make-arithmetic-progression-from-sequence", "last-moment-before-all-ants-fall-out-of-a-plank", "count-submatrices-with-all-ones", "minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits"]}, {"contest_title": "\u7b2c 197 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 197", "contest_title_slug": "weekly-contest-197", "contest_id": 221, "contest_start_time": 1594521000, "contest_duration": 5400, "user_num": 5275, "question_slugs": ["number-of-good-pairs", "number-of-substrings-with-only-1s", "path-with-maximum-probability", "best-position-for-a-service-centre"]}, {"contest_title": "\u7b2c 198 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 198", "contest_title_slug": "weekly-contest-198", "contest_id": 226, "contest_start_time": 1595125800, "contest_duration": 5400, "user_num": 5780, "question_slugs": ["water-bottles", "number-of-nodes-in-the-sub-tree-with-the-same-label", "maximum-number-of-non-overlapping-substrings", "find-a-value-of-a-mysterious-function-closest-to-target"]}, {"contest_title": "\u7b2c 199 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 199", "contest_title_slug": "weekly-contest-199", "contest_id": 228, "contest_start_time": 1595730600, "contest_duration": 5400, "user_num": 5232, "question_slugs": ["shuffle-string", "minimum-suffix-flips", "number-of-good-leaf-nodes-pairs", "string-compression-ii"]}, {"contest_title": "\u7b2c 200 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 200", "contest_title_slug": "weekly-contest-200", "contest_id": 235, "contest_start_time": 1596335400, "contest_duration": 5400, "user_num": 5476, "question_slugs": ["count-good-triplets", "find-the-winner-of-an-array-game", "minimum-swaps-to-arrange-a-binary-grid", "get-the-maximum-score"]}, {"contest_title": "\u7b2c 201 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 201", "contest_title_slug": "weekly-contest-201", "contest_id": 238, "contest_start_time": 1596940200, "contest_duration": 5400, "user_num": 5615, "question_slugs": ["make-the-string-great", "find-kth-bit-in-nth-binary-string", "maximum-number-of-non-overlapping-subarrays-with-sum-equals-target", "minimum-cost-to-cut-a-stick"]}, {"contest_title": "\u7b2c 202 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 202", "contest_title_slug": "weekly-contest-202", "contest_id": 242, "contest_start_time": 1597545000, "contest_duration": 5400, "user_num": 4990, "question_slugs": ["three-consecutive-odds", "minimum-operations-to-make-array-equal", "magnetic-force-between-two-balls", "minimum-number-of-days-to-eat-n-oranges"]}, {"contest_title": "\u7b2c 203 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 203", "contest_title_slug": "weekly-contest-203", "contest_id": 244, "contest_start_time": 1598149800, "contest_duration": 5400, "user_num": 5285, "question_slugs": ["most-visited-sector-in-a-circular-track", "maximum-number-of-coins-you-can-get", "find-latest-group-of-size-m", "stone-game-v"]}, {"contest_title": "\u7b2c 204 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 204", "contest_title_slug": "weekly-contest-204", "contest_id": 257, "contest_start_time": 1598754600, "contest_duration": 5400, "user_num": 4487, "question_slugs": ["detect-pattern-of-length-m-repeated-k-or-more-times", "maximum-length-of-subarray-with-positive-product", "minimum-number-of-days-to-disconnect-island", "number-of-ways-to-reorder-array-to-get-same-bst"]}, {"contest_title": "\u7b2c 205 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 205", "contest_title_slug": "weekly-contest-205", "contest_id": 260, "contest_start_time": 1599359400, "contest_duration": 5400, "user_num": 4176, "question_slugs": ["replace-all-s-to-avoid-consecutive-repeating-characters", "number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers", "minimum-time-to-make-rope-colorful", "remove-max-number-of-edges-to-keep-graph-fully-traversable"]}, {"contest_title": "\u7b2c 206 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 206", "contest_title_slug": "weekly-contest-206", "contest_id": 267, "contest_start_time": 1599964200, "contest_duration": 5400, "user_num": 4493, "question_slugs": ["special-positions-in-a-binary-matrix", "count-unhappy-friends", "min-cost-to-connect-all-points", "check-if-string-is-transformable-with-substring-sort-operations"]}, {"contest_title": "\u7b2c 207 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 207", "contest_title_slug": "weekly-contest-207", "contest_id": 278, "contest_start_time": 1600569000, "contest_duration": 5400, "user_num": 4116, "question_slugs": ["rearrange-spaces-between-words", "split-a-string-into-the-max-number-of-unique-substrings", "maximum-non-negative-product-in-a-matrix", "minimum-cost-to-connect-two-groups-of-points"]}, {"contest_title": "\u7b2c 208 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 208", "contest_title_slug": "weekly-contest-208", "contest_id": 289, "contest_start_time": 1601173800, "contest_duration": 5400, "user_num": 3582, "question_slugs": ["crawler-log-folder", "maximum-profit-of-operating-a-centennial-wheel", "throne-inheritance", "maximum-number-of-achievable-transfer-requests"]}, {"contest_title": "\u7b2c 209 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 209", "contest_title_slug": "weekly-contest-209", "contest_id": 291, "contest_start_time": 1601778600, "contest_duration": 5400, "user_num": 4023, "question_slugs": ["special-array-with-x-elements-greater-than-or-equal-x", "even-odd-tree", "maximum-number-of-visible-points", "minimum-one-bit-operations-to-make-integers-zero"]}, {"contest_title": "\u7b2c 210 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 210", "contest_title_slug": "weekly-contest-210", "contest_id": 295, "contest_start_time": 1602383400, "contest_duration": 5400, "user_num": 4007, "question_slugs": ["maximum-nesting-depth-of-the-parentheses", "maximal-network-rank", "split-two-strings-to-make-palindrome", "count-subtrees-with-max-distance-between-cities"]}, {"contest_title": "\u7b2c 211 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 211", "contest_title_slug": "weekly-contest-211", "contest_id": 297, "contest_start_time": 1602988200, "contest_duration": 5400, "user_num": 4034, "question_slugs": ["largest-substring-between-two-equal-characters", "lexicographically-smallest-string-after-applying-operations", "best-team-with-no-conflicts", "graph-connectivity-with-threshold"]}, {"contest_title": "\u7b2c 212 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 212", "contest_title_slug": "weekly-contest-212", "contest_id": 301, "contest_start_time": 1603593000, "contest_duration": 5400, "user_num": 4227, "question_slugs": ["slowest-key", "arithmetic-subarrays", "path-with-minimum-effort", "rank-transform-of-a-matrix"]}, {"contest_title": "\u7b2c 213 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 213", "contest_title_slug": "weekly-contest-213", "contest_id": 303, "contest_start_time": 1604197800, "contest_duration": 5400, "user_num": 3827, "question_slugs": ["check-array-formation-through-concatenation", "count-sorted-vowel-strings", "furthest-building-you-can-reach", "kth-smallest-instructions"]}, {"contest_title": "\u7b2c 214 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 214", "contest_title_slug": "weekly-contest-214", "contest_id": 307, "contest_start_time": 1604802600, "contest_duration": 5400, "user_num": 3598, "question_slugs": ["get-maximum-in-generated-array", "minimum-deletions-to-make-character-frequencies-unique", "sell-diminishing-valued-colored-balls", "create-sorted-array-through-instructions"]}, {"contest_title": "\u7b2c 215 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 215", "contest_title_slug": "weekly-contest-215", "contest_id": 309, "contest_start_time": 1605407400, "contest_duration": 5400, "user_num": 4429, "question_slugs": ["design-an-ordered-stream", "determine-if-two-strings-are-close", "minimum-operations-to-reduce-x-to-zero", "maximize-grid-happiness"]}, {"contest_title": "\u7b2c 216 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 216", "contest_title_slug": "weekly-contest-216", "contest_id": 313, "contest_start_time": 1606012200, "contest_duration": 5400, "user_num": 3857, "question_slugs": ["check-if-two-string-arrays-are-equivalent", "smallest-string-with-a-given-numeric-value", "ways-to-make-a-fair-array", "minimum-initial-energy-to-finish-tasks"]}, {"contest_title": "\u7b2c 217 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 217", "contest_title_slug": "weekly-contest-217", "contest_id": 315, "contest_start_time": 1606617000, "contest_duration": 5400, "user_num": 3745, "question_slugs": ["richest-customer-wealth", "find-the-most-competitive-subsequence", "minimum-moves-to-make-array-complementary", "minimize-deviation-in-array"]}, {"contest_title": "\u7b2c 218 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 218", "contest_title_slug": "weekly-contest-218", "contest_id": 319, "contest_start_time": 1607221800, "contest_duration": 5400, "user_num": 3762, "question_slugs": ["goal-parser-interpretation", "max-number-of-k-sum-pairs", "concatenation-of-consecutive-binary-numbers", "minimum-incompatibility"]}, {"contest_title": "\u7b2c 219 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 219", "contest_title_slug": "weekly-contest-219", "contest_id": 322, "contest_start_time": 1607826600, "contest_duration": 5400, "user_num": 3710, "question_slugs": ["count-of-matches-in-tournament", "partitioning-into-minimum-number-of-deci-binary-numbers", "stone-game-vii", "maximum-height-by-stacking-cuboids"]}, {"contest_title": "\u7b2c 220 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 220", "contest_title_slug": "weekly-contest-220", "contest_id": 326, "contest_start_time": 1608431400, "contest_duration": 5400, "user_num": 3691, "question_slugs": ["reformat-phone-number", "maximum-erasure-value", "jump-game-vi", "checking-existence-of-edge-length-limited-paths"]}, {"contest_title": "\u7b2c 221 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 221", "contest_title_slug": "weekly-contest-221", "contest_id": 328, "contest_start_time": 1609036200, "contest_duration": 5400, "user_num": 3398, "question_slugs": ["determine-if-string-halves-are-alike", "maximum-number-of-eaten-apples", "where-will-the-ball-fall", "maximum-xor-with-an-element-from-array"]}, {"contest_title": "\u7b2c 222 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 222", "contest_title_slug": "weekly-contest-222", "contest_id": 332, "contest_start_time": 1609641000, "contest_duration": 5400, "user_num": 3119, "question_slugs": ["maximum-units-on-a-truck", "count-good-meals", "ways-to-split-array-into-three-subarrays", "minimum-operations-to-make-a-subsequence"]}, {"contest_title": "\u7b2c 223 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 223", "contest_title_slug": "weekly-contest-223", "contest_id": 334, "contest_start_time": 1610245800, "contest_duration": 5400, "user_num": 3872, "question_slugs": ["decode-xored-array", "swapping-nodes-in-a-linked-list", "minimize-hamming-distance-after-swap-operations", "find-minimum-time-to-finish-all-jobs"]}, {"contest_title": "\u7b2c 224 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 224", "contest_title_slug": "weekly-contest-224", "contest_id": 338, "contest_start_time": 1610850600, "contest_duration": 5400, "user_num": 3795, "question_slugs": ["number-of-rectangles-that-can-form-the-largest-square", "tuple-with-same-product", "largest-submatrix-with-rearrangements", "cat-and-mouse-ii"]}, {"contest_title": "\u7b2c 225 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 225", "contest_title_slug": "weekly-contest-225", "contest_id": 340, "contest_start_time": 1611455400, "contest_duration": 5400, "user_num": 3853, "question_slugs": ["latest-time-by-replacing-hidden-digits", "change-minimum-characters-to-satisfy-one-of-three-conditions", "find-kth-largest-xor-coordinate-value", "building-boxes"]}, {"contest_title": "\u7b2c 226 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 226", "contest_title_slug": "weekly-contest-226", "contest_id": 344, "contest_start_time": 1612060200, "contest_duration": 5400, "user_num": 4034, "question_slugs": ["maximum-number-of-balls-in-a-box", "restore-the-array-from-adjacent-pairs", "can-you-eat-your-favorite-candy-on-your-favorite-day", "palindrome-partitioning-iv"]}, {"contest_title": "\u7b2c 227 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 227", "contest_title_slug": "weekly-contest-227", "contest_id": 346, "contest_start_time": 1612665000, "contest_duration": 5400, "user_num": 3546, "question_slugs": ["check-if-array-is-sorted-and-rotated", "maximum-score-from-removing-stones", "largest-merge-of-two-strings", "closest-subsequence-sum"]}, {"contest_title": "\u7b2c 228 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 228", "contest_title_slug": "weekly-contest-228", "contest_id": 350, "contest_start_time": 1613269800, "contest_duration": 5400, "user_num": 2484, "question_slugs": ["minimum-changes-to-make-alternating-binary-string", "count-number-of-homogenous-substrings", "minimum-limit-of-balls-in-a-bag", "minimum-degree-of-a-connected-trio-in-a-graph"]}, {"contest_title": "\u7b2c 229 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 229", "contest_title_slug": "weekly-contest-229", "contest_id": 352, "contest_start_time": 1613874600, "contest_duration": 5400, "user_num": 3484, "question_slugs": ["merge-strings-alternately", "minimum-number-of-operations-to-move-all-balls-to-each-box", "maximum-score-from-performing-multiplication-operations", "maximize-palindrome-length-from-subsequences"]}, {"contest_title": "\u7b2c 230 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 230", "contest_title_slug": "weekly-contest-230", "contest_id": 356, "contest_start_time": 1614479400, "contest_duration": 5400, "user_num": 3728, "question_slugs": ["count-items-matching-a-rule", "closest-dessert-cost", "equal-sum-arrays-with-minimum-number-of-operations", "car-fleet-ii"]}, {"contest_title": "\u7b2c 231 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 231", "contest_title_slug": "weekly-contest-231", "contest_id": 358, "contest_start_time": 1615084200, "contest_duration": 5400, "user_num": 4668, "question_slugs": ["check-if-binary-string-has-at-most-one-segment-of-ones", "minimum-elements-to-add-to-form-a-given-sum", "number-of-restricted-paths-from-first-to-last-node", "make-the-xor-of-all-segments-equal-to-zero"]}, {"contest_title": "\u7b2c 232 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 232", "contest_title_slug": "weekly-contest-232", "contest_id": 363, "contest_start_time": 1615689000, "contest_duration": 5400, "user_num": 4802, "question_slugs": ["check-if-one-string-swap-can-make-strings-equal", "find-center-of-star-graph", "maximum-average-pass-ratio", "maximum-score-of-a-good-subarray"]}, {"contest_title": "\u7b2c 233 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 233", "contest_title_slug": "weekly-contest-233", "contest_id": 371, "contest_start_time": 1616293800, "contest_duration": 5400, "user_num": 5010, "question_slugs": ["maximum-ascending-subarray-sum", "number-of-orders-in-the-backlog", "maximum-value-at-a-given-index-in-a-bounded-array", "count-pairs-with-xor-in-a-range"]}, {"contest_title": "\u7b2c 234 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 234", "contest_title_slug": "weekly-contest-234", "contest_id": 375, "contest_start_time": 1616898600, "contest_duration": 5400, "user_num": 4998, "question_slugs": ["number-of-different-integers-in-a-string", "minimum-number-of-operations-to-reinitialize-a-permutation", "evaluate-the-bracket-pairs-of-a-string", "maximize-number-of-nice-divisors"]}, {"contest_title": "\u7b2c 235 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 235", "contest_title_slug": "weekly-contest-235", "contest_id": 377, "contest_start_time": 1617503400, "contest_duration": 5400, "user_num": 4494, "question_slugs": ["truncate-sentence", "finding-the-users-active-minutes", "minimum-absolute-sum-difference", "number-of-different-subsequences-gcds"]}, {"contest_title": "\u7b2c 236 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 236", "contest_title_slug": "weekly-contest-236", "contest_id": 391, "contest_start_time": 1618108200, "contest_duration": 5400, "user_num": 5113, "question_slugs": ["sign-of-the-product-of-an-array", "find-the-winner-of-the-circular-game", "minimum-sideway-jumps", "finding-mk-average"]}, {"contest_title": "\u7b2c 237 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 237", "contest_title_slug": "weekly-contest-237", "contest_id": 393, "contest_start_time": 1618713000, "contest_duration": 5400, "user_num": 4577, "question_slugs": ["check-if-the-sentence-is-pangram", "maximum-ice-cream-bars", "single-threaded-cpu", "find-xor-sum-of-all-pairs-bitwise-and"]}, {"contest_title": "\u7b2c 238 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 238", "contest_title_slug": "weekly-contest-238", "contest_id": 397, "contest_start_time": 1619317800, "contest_duration": 5400, "user_num": 3978, "question_slugs": ["sum-of-digits-in-base-k", "frequency-of-the-most-frequent-element", "longest-substring-of-all-vowels-in-order", "maximum-building-height"]}, {"contest_title": "\u7b2c 239 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 239", "contest_title_slug": "weekly-contest-239", "contest_id": 399, "contest_start_time": 1619922600, "contest_duration": 5400, "user_num": 3907, "question_slugs": ["minimum-distance-to-the-target-element", "splitting-a-string-into-descending-consecutive-values", "minimum-adjacent-swaps-to-reach-the-kth-smallest-number", "minimum-interval-to-include-each-query"]}, {"contest_title": "\u7b2c 240 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 240", "contest_title_slug": "weekly-contest-240", "contest_id": 403, "contest_start_time": 1620527400, "contest_duration": 5400, "user_num": 4307, "question_slugs": ["maximum-population-year", "maximum-distance-between-a-pair-of-values", "maximum-subarray-min-product", "largest-color-value-in-a-directed-graph"]}, {"contest_title": "\u7b2c 241 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 241", "contest_title_slug": "weekly-contest-241", "contest_id": 405, "contest_start_time": 1621132200, "contest_duration": 5400, "user_num": 4491, "question_slugs": ["sum-of-all-subset-xor-totals", "minimum-number-of-swaps-to-make-the-binary-string-alternating", "finding-pairs-with-a-certain-sum", "number-of-ways-to-rearrange-sticks-with-k-sticks-visible"]}, {"contest_title": "\u7b2c 242 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 242", "contest_title_slug": "weekly-contest-242", "contest_id": 409, "contest_start_time": 1621737000, "contest_duration": 5400, "user_num": 4306, "question_slugs": ["longer-contiguous-segments-of-ones-than-zeros", "minimum-speed-to-arrive-on-time", "jump-game-vii", "stone-game-viii"]}, {"contest_title": "\u7b2c 243 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 243", "contest_title_slug": "weekly-contest-243", "contest_id": 411, "contest_start_time": 1622341800, "contest_duration": 5400, "user_num": 4493, "question_slugs": ["check-if-word-equals-summation-of-two-words", "maximum-value-after-insertion", "process-tasks-using-servers", "minimum-skips-to-arrive-at-meeting-on-time"]}, {"contest_title": "\u7b2c 244 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 244", "contest_title_slug": "weekly-contest-244", "contest_id": 415, "contest_start_time": 1622946600, "contest_duration": 5400, "user_num": 4430, "question_slugs": ["determine-whether-matrix-can-be-obtained-by-rotation", "reduction-operations-to-make-the-array-elements-equal", "minimum-number-of-flips-to-make-the-binary-string-alternating", "minimum-space-wasted-from-packaging"]}, {"contest_title": "\u7b2c 245 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 245", "contest_title_slug": "weekly-contest-245", "contest_id": 417, "contest_start_time": 1623551400, "contest_duration": 5400, "user_num": 4271, "question_slugs": ["redistribute-characters-to-make-all-strings-equal", "maximum-number-of-removable-characters", "merge-triplets-to-form-target-triplet", "the-earliest-and-latest-rounds-where-players-compete"]}, {"contest_title": "\u7b2c 246 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 246", "contest_title_slug": "weekly-contest-246", "contest_id": 422, "contest_start_time": 1624156200, "contest_duration": 5400, "user_num": 4136, "question_slugs": ["largest-odd-number-in-string", "the-number-of-full-rounds-you-have-played", "count-sub-islands", "minimum-absolute-difference-queries"]}, {"contest_title": "\u7b2c 247 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 247", "contest_title_slug": "weekly-contest-247", "contest_id": 426, "contest_start_time": 1624761000, "contest_duration": 5400, "user_num": 3981, "question_slugs": ["maximum-product-difference-between-two-pairs", "cyclically-rotating-a-grid", "number-of-wonderful-substrings", "count-ways-to-build-rooms-in-an-ant-colony"]}, {"contest_title": "\u7b2c 248 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 248", "contest_title_slug": "weekly-contest-248", "contest_id": 430, "contest_start_time": 1625365800, "contest_duration": 5400, "user_num": 4451, "question_slugs": ["build-array-from-permutation", "eliminate-maximum-number-of-monsters", "count-good-numbers", "longest-common-subpath"]}, {"contest_title": "\u7b2c 249 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 249", "contest_title_slug": "weekly-contest-249", "contest_id": 432, "contest_start_time": 1625970600, "contest_duration": 5400, "user_num": 4335, "question_slugs": ["concatenation-of-array", "unique-length-3-palindromic-subsequences", "painting-a-grid-with-three-different-colors", "merge-bsts-to-create-single-bst"]}, {"contest_title": "\u7b2c 250 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 250", "contest_title_slug": "weekly-contest-250", "contest_id": 436, "contest_start_time": 1626575400, "contest_duration": 5400, "user_num": 4315, "question_slugs": ["maximum-number-of-words-you-can-type", "add-minimum-number-of-rungs", "maximum-number-of-points-with-cost", "maximum-genetic-difference-query"]}, {"contest_title": "\u7b2c 251 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 251", "contest_title_slug": "weekly-contest-251", "contest_id": 438, "contest_start_time": 1627180200, "contest_duration": 5400, "user_num": 4747, "question_slugs": ["sum-of-digits-of-string-after-convert", "largest-number-after-mutating-substring", "maximum-compatibility-score-sum", "delete-duplicate-folders-in-system"]}, {"contest_title": "\u7b2c 252 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 252", "contest_title_slug": "weekly-contest-252", "contest_id": 442, "contest_start_time": 1627785000, "contest_duration": 5400, "user_num": 4647, "question_slugs": ["three-divisors", "maximum-number-of-weeks-for-which-you-can-work", "minimum-garden-perimeter-to-collect-enough-apples", "count-number-of-special-subsequences"]}, {"contest_title": "\u7b2c 253 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 253", "contest_title_slug": "weekly-contest-253", "contest_id": 444, "contest_start_time": 1628389800, "contest_duration": 5400, "user_num": 4570, "question_slugs": ["check-if-string-is-a-prefix-of-array", "remove-stones-to-minimize-the-total", "minimum-number-of-swaps-to-make-the-string-balanced", "find-the-longest-valid-obstacle-course-at-each-position"]}, {"contest_title": "\u7b2c 254 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 254", "contest_title_slug": "weekly-contest-254", "contest_id": 449, "contest_start_time": 1628994600, "contest_duration": 5400, "user_num": 4349, "question_slugs": ["number-of-strings-that-appear-as-substrings-in-word", "array-with-elements-not-equal-to-average-of-neighbors", "minimum-non-zero-product-of-the-array-elements", "last-day-where-you-can-still-cross"]}, {"contest_title": "\u7b2c 255 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 255", "contest_title_slug": "weekly-contest-255", "contest_id": 457, "contest_start_time": 1629599400, "contest_duration": 5400, "user_num": 4333, "question_slugs": ["find-greatest-common-divisor-of-array", "find-unique-binary-string", "minimize-the-difference-between-target-and-chosen-elements", "find-array-given-subset-sums"]}, {"contest_title": "\u7b2c 256 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 256", "contest_title_slug": "weekly-contest-256", "contest_id": 462, "contest_start_time": 1630204200, "contest_duration": 5400, "user_num": 4136, "question_slugs": ["minimum-difference-between-highest-and-lowest-of-k-scores", "find-the-kth-largest-integer-in-the-array", "minimum-number-of-work-sessions-to-finish-the-tasks", "number-of-unique-good-subsequences"]}, {"contest_title": "\u7b2c 257 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 257", "contest_title_slug": "weekly-contest-257", "contest_id": 464, "contest_start_time": 1630809000, "contest_duration": 5400, "user_num": 4278, "question_slugs": ["count-special-quadruplets", "the-number-of-weak-characters-in-the-game", "first-day-where-you-have-been-in-all-the-rooms", "gcd-sort-of-an-array"]}, {"contest_title": "\u7b2c 258 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 258", "contest_title_slug": "weekly-contest-258", "contest_id": 468, "contest_start_time": 1631413800, "contest_duration": 5400, "user_num": 4519, "question_slugs": ["reverse-prefix-of-word", "number-of-pairs-of-interchangeable-rectangles", "maximum-product-of-the-length-of-two-palindromic-subsequences", "smallest-missing-genetic-value-in-each-subtree"]}, {"contest_title": "\u7b2c 259 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 259", "contest_title_slug": "weekly-contest-259", "contest_id": 474, "contest_start_time": 1632018600, "contest_duration": 5400, "user_num": 3775, "question_slugs": ["final-value-of-variable-after-performing-operations", "sum-of-beauty-in-the-array", "detect-squares", "longest-subsequence-repeated-k-times"]}, {"contest_title": "\u7b2c 260 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 260", "contest_title_slug": "weekly-contest-260", "contest_id": 478, "contest_start_time": 1632623400, "contest_duration": 5400, "user_num": 3654, "question_slugs": ["maximum-difference-between-increasing-elements", "grid-game", "check-if-word-can-be-placed-in-crossword", "the-score-of-students-solving-math-expression"]}, {"contest_title": "\u7b2c 261 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 261", "contest_title_slug": "weekly-contest-261", "contest_id": 481, "contest_start_time": 1633228200, "contest_duration": 5400, "user_num": 3368, "question_slugs": ["minimum-moves-to-convert-string", "find-missing-observations", "stone-game-ix", "smallest-k-length-subsequence-with-occurrences-of-a-letter"]}, {"contest_title": "\u7b2c 262 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 262", "contest_title_slug": "weekly-contest-262", "contest_id": 485, "contest_start_time": 1633833000, "contest_duration": 5400, "user_num": 4261, "question_slugs": ["two-out-of-three", "minimum-operations-to-make-a-uni-value-grid", "stock-price-fluctuation", "partition-array-into-two-arrays-to-minimize-sum-difference"]}, {"contest_title": "\u7b2c 263 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 263", "contest_title_slug": "weekly-contest-263", "contest_id": 487, "contest_start_time": 1634437800, "contest_duration": 5400, "user_num": 4572, "question_slugs": ["check-if-numbers-are-ascending-in-a-sentence", "simple-bank-system", "count-number-of-maximum-bitwise-or-subsets", "second-minimum-time-to-reach-destination"]}, {"contest_title": "\u7b2c 264 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 264", "contest_title_slug": "weekly-contest-264", "contest_id": 491, "contest_start_time": 1635042600, "contest_duration": 5400, "user_num": 4659, "question_slugs": ["number-of-valid-words-in-a-sentence", "next-greater-numerically-balanced-number", "count-nodes-with-the-highest-score", "parallel-courses-iii"]}, {"contest_title": "\u7b2c 265 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 265", "contest_title_slug": "weekly-contest-265", "contest_id": 493, "contest_start_time": 1635647400, "contest_duration": 5400, "user_num": 4182, "question_slugs": ["smallest-index-with-equal-value", "find-the-minimum-and-maximum-number-of-nodes-between-critical-points", "minimum-operations-to-convert-number", "check-if-an-original-string-exists-given-two-encoded-strings"]}, {"contest_title": "\u7b2c 266 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 266", "contest_title_slug": "weekly-contest-266", "contest_id": 498, "contest_start_time": 1636252200, "contest_duration": 5400, "user_num": 4385, "question_slugs": ["count-vowel-substrings-of-a-string", "vowels-of-all-substrings", "minimized-maximum-of-products-distributed-to-any-store", "maximum-path-quality-of-a-graph"]}, {"contest_title": "\u7b2c 267 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 267", "contest_title_slug": "weekly-contest-267", "contest_id": 500, "contest_start_time": 1636857000, "contest_duration": 5400, "user_num": 4365, "question_slugs": ["time-needed-to-buy-tickets", "reverse-nodes-in-even-length-groups", "decode-the-slanted-ciphertext", "process-restricted-friend-requests"]}, {"contest_title": "\u7b2c 268 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 268", "contest_title_slug": "weekly-contest-268", "contest_id": 504, "contest_start_time": 1637461800, "contest_duration": 5400, "user_num": 4398, "question_slugs": ["two-furthest-houses-with-different-colors", "watering-plants", "range-frequency-queries", "sum-of-k-mirror-numbers"]}, {"contest_title": "\u7b2c 269 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 269", "contest_title_slug": "weekly-contest-269", "contest_id": 506, "contest_start_time": 1638066600, "contest_duration": 5400, "user_num": 4293, "question_slugs": ["find-target-indices-after-sorting-array", "k-radius-subarray-averages", "removing-minimum-and-maximum-from-array", "find-all-people-with-secret"]}, {"contest_title": "\u7b2c 270 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 270", "contest_title_slug": "weekly-contest-270", "contest_id": 510, "contest_start_time": 1638671400, "contest_duration": 5400, "user_num": 4748, "question_slugs": ["finding-3-digit-even-numbers", "delete-the-middle-node-of-a-linked-list", "step-by-step-directions-from-a-binary-tree-node-to-another", "valid-arrangement-of-pairs"]}, {"contest_title": "\u7b2c 271 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 271", "contest_title_slug": "weekly-contest-271", "contest_id": 512, "contest_start_time": 1639276200, "contest_duration": 5400, "user_num": 4562, "question_slugs": ["rings-and-rods", "sum-of-subarray-ranges", "watering-plants-ii", "maximum-fruits-harvested-after-at-most-k-steps"]}, {"contest_title": "\u7b2c 272 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 272", "contest_title_slug": "weekly-contest-272", "contest_id": 516, "contest_start_time": 1639881000, "contest_duration": 5400, "user_num": 4698, "question_slugs": ["find-first-palindromic-string-in-the-array", "adding-spaces-to-a-string", "number-of-smooth-descent-periods-of-a-stock", "minimum-operations-to-make-the-array-k-increasing"]}, {"contest_title": "\u7b2c 273 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 273", "contest_title_slug": "weekly-contest-273", "contest_id": 518, "contest_start_time": 1640485800, "contest_duration": 5400, "user_num": 4368, "question_slugs": ["a-number-after-a-double-reversal", "execution-of-all-suffix-instructions-staying-in-a-grid", "intervals-between-identical-elements", "recover-the-original-array"]}, {"contest_title": "\u7b2c 274 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 274", "contest_title_slug": "weekly-contest-274", "contest_id": 522, "contest_start_time": 1641090600, "contest_duration": 5400, "user_num": 4109, "question_slugs": ["check-if-all-as-appears-before-all-bs", "number-of-laser-beams-in-a-bank", "destroying-asteroids", "maximum-employees-to-be-invited-to-a-meeting"]}, {"contest_title": "\u7b2c 275 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 275", "contest_title_slug": "weekly-contest-275", "contest_id": 524, "contest_start_time": 1641695400, "contest_duration": 5400, "user_num": 4787, "question_slugs": ["check-if-every-row-and-column-contains-all-numbers", "minimum-swaps-to-group-all-1s-together-ii", "count-words-obtained-after-adding-a-letter", "earliest-possible-day-of-full-bloom"]}, {"contest_title": "\u7b2c 276 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 276", "contest_title_slug": "weekly-contest-276", "contest_id": 528, "contest_start_time": 1642300200, "contest_duration": 5400, "user_num": 5244, "question_slugs": ["divide-a-string-into-groups-of-size-k", "minimum-moves-to-reach-target-score", "solving-questions-with-brainpower", "maximum-running-time-of-n-computers"]}, {"contest_title": "\u7b2c 277 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 277", "contest_title_slug": "weekly-contest-277", "contest_id": 530, "contest_start_time": 1642905000, "contest_duration": 5400, "user_num": 5060, "question_slugs": ["count-elements-with-strictly-smaller-and-greater-elements", "rearrange-array-elements-by-sign", "find-all-lonely-numbers-in-the-array", "maximum-good-people-based-on-statements"]}, {"contest_title": "\u7b2c 278 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 278", "contest_title_slug": "weekly-contest-278", "contest_id": 534, "contest_start_time": 1643509800, "contest_duration": 5400, "user_num": 4643, "question_slugs": ["keep-multiplying-found-values-by-two", "all-divisions-with-the-highest-score-of-a-binary-array", "find-substring-with-given-hash-value", "groups-of-strings"]}, {"contest_title": "\u7b2c 279 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 279", "contest_title_slug": "weekly-contest-279", "contest_id": 536, "contest_start_time": 1644114600, "contest_duration": 5400, "user_num": 4132, "question_slugs": ["sort-even-and-odd-indices-independently", "smallest-value-of-the-rearranged-number", "design-bitset", "minimum-time-to-remove-all-cars-containing-illegal-goods"]}, {"contest_title": "\u7b2c 280 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 280", "contest_title_slug": "weekly-contest-280", "contest_id": 540, "contest_start_time": 1644719400, "contest_duration": 5400, "user_num": 5834, "question_slugs": ["count-operations-to-obtain-zero", "minimum-operations-to-make-the-array-alternating", "removing-minimum-number-of-magic-beans", "maximum-and-sum-of-array"]}, {"contest_title": "\u7b2c 281 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 281", "contest_title_slug": "weekly-contest-281", "contest_id": 542, "contest_start_time": 1645324200, "contest_duration": 6000, "user_num": 6005, "question_slugs": ["count-integers-with-even-digit-sum", "merge-nodes-in-between-zeros", "construct-string-with-repeat-limit", "count-array-pairs-divisible-by-k"]}, {"contest_title": "\u7b2c 282 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 282", "contest_title_slug": "weekly-contest-282", "contest_id": 546, "contest_start_time": 1645929000, "contest_duration": 5400, "user_num": 7164, "question_slugs": ["counting-words-with-a-given-prefix", "minimum-number-of-steps-to-make-two-strings-anagram-ii", "minimum-time-to-complete-trips", "minimum-time-to-finish-the-race"]}, {"contest_title": "\u7b2c 283 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 283", "contest_title_slug": "weekly-contest-283", "contest_id": 551, "contest_start_time": 1646533800, "contest_duration": 5400, "user_num": 7817, "question_slugs": ["cells-in-a-range-on-an-excel-sheet", "append-k-integers-with-minimal-sum", "create-binary-tree-from-descriptions", "replace-non-coprime-numbers-in-array"]}, {"contest_title": "\u7b2c 284 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 284", "contest_title_slug": "weekly-contest-284", "contest_id": 555, "contest_start_time": 1647138600, "contest_duration": 5400, "user_num": 8483, "question_slugs": ["find-all-k-distant-indices-in-an-array", "count-artifacts-that-can-be-extracted", "maximize-the-topmost-element-after-k-moves", "minimum-weighted-subgraph-with-the-required-paths"]}, {"contest_title": "\u7b2c 285 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 285", "contest_title_slug": "weekly-contest-285", "contest_id": 558, "contest_start_time": 1647743400, "contest_duration": 5400, "user_num": 7501, "question_slugs": ["count-hills-and-valleys-in-an-array", "count-collisions-on-a-road", "maximum-points-in-an-archery-competition", "longest-substring-of-one-repeating-character"]}, {"contest_title": "\u7b2c 286 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 286", "contest_title_slug": "weekly-contest-286", "contest_id": 564, "contest_start_time": 1648348200, "contest_duration": 5400, "user_num": 7248, "question_slugs": ["find-the-difference-of-two-arrays", "minimum-deletions-to-make-array-beautiful", "find-palindrome-with-fixed-length", "maximum-value-of-k-coins-from-piles"]}, {"contest_title": "\u7b2c 287 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 287", "contest_title_slug": "weekly-contest-287", "contest_id": 569, "contest_start_time": 1648953000, "contest_duration": 5400, "user_num": 6811, "question_slugs": ["minimum-number-of-operations-to-convert-time", "find-players-with-zero-or-one-losses", "maximum-candies-allocated-to-k-children", "encrypt-and-decrypt-strings"]}, {"contest_title": "\u7b2c 288 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 288", "contest_title_slug": "weekly-contest-288", "contest_id": 573, "contest_start_time": 1649557800, "contest_duration": 5400, "user_num": 6926, "question_slugs": ["largest-number-after-digit-swaps-by-parity", "minimize-result-by-adding-parentheses-to-expression", "maximum-product-after-k-increments", "maximum-total-beauty-of-the-gardens"]}, {"contest_title": "\u7b2c 289 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 289", "contest_title_slug": "weekly-contest-289", "contest_id": 576, "contest_start_time": 1650162600, "contest_duration": 5400, "user_num": 7293, "question_slugs": ["calculate-digit-sum-of-a-string", "minimum-rounds-to-complete-all-tasks", "maximum-trailing-zeros-in-a-cornered-path", "longest-path-with-different-adjacent-characters"]}, {"contest_title": "\u7b2c 290 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 290", "contest_title_slug": "weekly-contest-290", "contest_id": 582, "contest_start_time": 1650767400, "contest_duration": 5400, "user_num": 6275, "question_slugs": ["intersection-of-multiple-arrays", "count-lattice-points-inside-a-circle", "count-number-of-rectangles-containing-each-point", "number-of-flowers-in-full-bloom"]}, {"contest_title": "\u7b2c 291 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 291", "contest_title_slug": "weekly-contest-291", "contest_id": 587, "contest_start_time": 1651372200, "contest_duration": 5400, "user_num": 6574, "question_slugs": ["remove-digit-from-number-to-maximize-result", "minimum-consecutive-cards-to-pick-up", "k-divisible-elements-subarrays", "total-appeal-of-a-string"]}, {"contest_title": "\u7b2c 292 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 292", "contest_title_slug": "weekly-contest-292", "contest_id": 591, "contest_start_time": 1651977000, "contest_duration": 5400, "user_num": 6884, "question_slugs": ["largest-3-same-digit-number-in-string", "count-nodes-equal-to-average-of-subtree", "count-number-of-texts", "check-if-there-is-a-valid-parentheses-string-path"]}, {"contest_title": "\u7b2c 293 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 293", "contest_title_slug": "weekly-contest-293", "contest_id": 593, "contest_start_time": 1652581800, "contest_duration": 5400, "user_num": 7357, "question_slugs": ["find-resultant-array-after-removing-anagrams", "maximum-consecutive-floors-without-special-floors", "largest-combination-with-bitwise-and-greater-than-zero", "count-integers-in-intervals"]}, {"contest_title": "\u7b2c 294 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 294", "contest_title_slug": "weekly-contest-294", "contest_id": 599, "contest_start_time": 1653186600, "contest_duration": 5400, "user_num": 6640, "question_slugs": ["percentage-of-letter-in-string", "maximum-bags-with-full-capacity-of-rocks", "minimum-lines-to-represent-a-line-chart", "sum-of-total-strength-of-wizards"]}, {"contest_title": "\u7b2c 295 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 295", "contest_title_slug": "weekly-contest-295", "contest_id": 605, "contest_start_time": 1653791400, "contest_duration": 5400, "user_num": 6447, "question_slugs": ["rearrange-characters-to-make-target-string", "apply-discount-to-prices", "steps-to-make-array-non-decreasing", "minimum-obstacle-removal-to-reach-corner"]}, {"contest_title": "\u7b2c 296 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 296", "contest_title_slug": "weekly-contest-296", "contest_id": 609, "contest_start_time": 1654396200, "contest_duration": 5400, "user_num": 5721, "question_slugs": ["min-max-game", "partition-array-such-that-maximum-difference-is-k", "replace-elements-in-an-array", "design-a-text-editor"]}, {"contest_title": "\u7b2c 297 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 297", "contest_title_slug": "weekly-contest-297", "contest_id": 611, "contest_start_time": 1655001000, "contest_duration": 5400, "user_num": 5915, "question_slugs": ["calculate-amount-paid-in-taxes", "minimum-path-cost-in-a-grid", "fair-distribution-of-cookies", "naming-a-company"]}, {"contest_title": "\u7b2c 298 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 298", "contest_title_slug": "weekly-contest-298", "contest_id": 615, "contest_start_time": 1655605800, "contest_duration": 5400, "user_num": 6228, "question_slugs": ["greatest-english-letter-in-upper-and-lower-case", "sum-of-numbers-with-units-digit-k", "longest-binary-subsequence-less-than-or-equal-to-k", "selling-pieces-of-wood"]}, {"contest_title": "\u7b2c 299 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 299", "contest_title_slug": "weekly-contest-299", "contest_id": 618, "contest_start_time": 1656210600, "contest_duration": 5400, "user_num": 6108, "question_slugs": ["check-if-matrix-is-x-matrix", "count-number-of-ways-to-place-houses", "maximum-score-of-spliced-array", "minimum-score-after-removals-on-a-tree"]}, {"contest_title": "\u7b2c 300 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 300", "contest_title_slug": "weekly-contest-300", "contest_id": 647, "contest_start_time": 1656815400, "contest_duration": 5400, "user_num": 6792, "question_slugs": ["decode-the-message", "spiral-matrix-iv", "number-of-people-aware-of-a-secret", "number-of-increasing-paths-in-a-grid"]}, {"contest_title": "\u7b2c 301 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 301", "contest_title_slug": "weekly-contest-301", "contest_id": 649, "contest_start_time": 1657420200, "contest_duration": 5400, "user_num": 7133, "question_slugs": ["minimum-amount-of-time-to-fill-cups", "smallest-number-in-infinite-set", "move-pieces-to-obtain-a-string", "count-the-number-of-ideal-arrays"]}, {"contest_title": "\u7b2c 302 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 302", "contest_title_slug": "weekly-contest-302", "contest_id": 653, "contest_start_time": 1658025000, "contest_duration": 5400, "user_num": 7092, "question_slugs": ["maximum-number-of-pairs-in-array", "max-sum-of-a-pair-with-equal-sum-of-digits", "query-kth-smallest-trimmed-number", "minimum-deletions-to-make-array-divisible"]}, {"contest_title": "\u7b2c 303 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 303", "contest_title_slug": "weekly-contest-303", "contest_id": 655, "contest_start_time": 1658629800, "contest_duration": 5400, "user_num": 7032, "question_slugs": ["first-letter-to-appear-twice", "equal-row-and-column-pairs", "design-a-food-rating-system", "number-of-excellent-pairs"]}, {"contest_title": "\u7b2c 304 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 304", "contest_title_slug": "weekly-contest-304", "contest_id": 659, "contest_start_time": 1659234600, "contest_duration": 5400, "user_num": 7372, "question_slugs": ["make-array-zero-by-subtracting-equal-amounts", "maximum-number-of-groups-entering-a-competition", "find-closest-node-to-given-two-nodes", "longest-cycle-in-a-graph"]}, {"contest_title": "\u7b2c 305 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 305", "contest_title_slug": "weekly-contest-305", "contest_id": 663, "contest_start_time": 1659839400, "contest_duration": 5400, "user_num": 7465, "question_slugs": ["number-of-arithmetic-triplets", "reachable-nodes-with-restrictions", "check-if-there-is-a-valid-partition-for-the-array", "longest-ideal-subsequence"]}, {"contest_title": "\u7b2c 306 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 306", "contest_title_slug": "weekly-contest-306", "contest_id": 669, "contest_start_time": 1660444200, "contest_duration": 5400, "user_num": 7500, "question_slugs": ["largest-local-values-in-a-matrix", "node-with-highest-edge-score", "construct-smallest-number-from-di-string", "count-special-integers"]}, {"contest_title": "\u7b2c 307 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 307", "contest_title_slug": "weekly-contest-307", "contest_id": 671, "contest_start_time": 1661049000, "contest_duration": 5400, "user_num": 7064, "question_slugs": ["minimum-hours-of-training-to-win-a-competition", "largest-palindromic-number", "amount-of-time-for-binary-tree-to-be-infected", "find-the-k-sum-of-an-array"]}, {"contest_title": "\u7b2c 308 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 308", "contest_title_slug": "weekly-contest-308", "contest_id": 689, "contest_start_time": 1661653800, "contest_duration": 5400, "user_num": 6394, "question_slugs": ["longest-subsequence-with-limited-sum", "removing-stars-from-a-string", "minimum-amount-of-time-to-collect-garbage", "build-a-matrix-with-conditions"]}, {"contest_title": "\u7b2c 309 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 309", "contest_title_slug": "weekly-contest-309", "contest_id": 693, "contest_start_time": 1662258600, "contest_duration": 5400, "user_num": 7972, "question_slugs": ["check-distances-between-same-letters", "number-of-ways-to-reach-a-position-after-exactly-k-steps", "longest-nice-subarray", "meeting-rooms-iii"]}, {"contest_title": "\u7b2c 310 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 310", "contest_title_slug": "weekly-contest-310", "contest_id": 704, "contest_start_time": 1662863400, "contest_duration": 5400, "user_num": 6081, "question_slugs": ["most-frequent-even-element", "optimal-partition-of-string", "divide-intervals-into-minimum-number-of-groups", "longest-increasing-subsequence-ii"]}, {"contest_title": "\u7b2c 311 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 311", "contest_title_slug": "weekly-contest-311", "contest_id": 741, "contest_start_time": 1663468200, "contest_duration": 5400, "user_num": 6710, "question_slugs": ["smallest-even-multiple", "length-of-the-longest-alphabetical-continuous-substring", "reverse-odd-levels-of-binary-tree", "sum-of-prefix-scores-of-strings"]}, {"contest_title": "\u7b2c 312 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 312", "contest_title_slug": "weekly-contest-312", "contest_id": 746, "contest_start_time": 1664073000, "contest_duration": 5400, "user_num": 6638, "question_slugs": ["sort-the-people", "longest-subarray-with-maximum-bitwise-and", "find-all-good-indices", "number-of-good-paths"]}, {"contest_title": "\u7b2c 313 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 313", "contest_title_slug": "weekly-contest-313", "contest_id": 750, "contest_start_time": 1664677800, "contest_duration": 5400, "user_num": 5445, "question_slugs": ["number-of-common-factors", "maximum-sum-of-an-hourglass", "minimize-xor", "maximum-deletions-on-a-string"]}, {"contest_title": "\u7b2c 314 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 314", "contest_title_slug": "weekly-contest-314", "contest_id": 756, "contest_start_time": 1665282600, "contest_duration": 5400, "user_num": 4838, "question_slugs": ["the-employee-that-worked-on-the-longest-task", "find-the-original-array-of-prefix-xor", "using-a-robot-to-print-the-lexicographically-smallest-string", "paths-in-matrix-whose-sum-is-divisible-by-k"]}, {"contest_title": "\u7b2c 315 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 315", "contest_title_slug": "weekly-contest-315", "contest_id": 759, "contest_start_time": 1665887400, "contest_duration": 5400, "user_num": 6490, "question_slugs": ["largest-positive-integer-that-exists-with-its-negative", "count-number-of-distinct-integers-after-reverse-operations", "sum-of-number-and-its-reverse", "count-subarrays-with-fixed-bounds"]}, {"contest_title": "\u7b2c 316 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 316", "contest_title_slug": "weekly-contest-316", "contest_id": 764, "contest_start_time": 1666492200, "contest_duration": 5400, "user_num": 6387, "question_slugs": ["determine-if-two-events-have-conflict", "number-of-subarrays-with-gcd-equal-to-k", "minimum-cost-to-make-array-equal", "minimum-number-of-operations-to-make-arrays-similar"]}, {"contest_title": "\u7b2c 317 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 317", "contest_title_slug": "weekly-contest-317", "contest_id": 767, "contest_start_time": 1667097000, "contest_duration": 5400, "user_num": 5660, "question_slugs": ["average-value-of-even-numbers-that-are-divisible-by-three", "most-popular-video-creator", "minimum-addition-to-make-integer-beautiful", "height-of-binary-tree-after-subtree-removal-queries"]}, {"contest_title": "\u7b2c 318 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 318", "contest_title_slug": "weekly-contest-318", "contest_id": 771, "contest_start_time": 1667701800, "contest_duration": 5400, "user_num": 5670, "question_slugs": ["apply-operations-to-an-array", "maximum-sum-of-distinct-subarrays-with-length-k", "total-cost-to-hire-k-workers", "minimum-total-distance-traveled"]}, {"contest_title": "\u7b2c 319 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 319", "contest_title_slug": "weekly-contest-319", "contest_id": 773, "contest_start_time": 1668306600, "contest_duration": 5400, "user_num": 6175, "question_slugs": ["convert-the-temperature", "number-of-subarrays-with-lcm-equal-to-k", "minimum-number-of-operations-to-sort-a-binary-tree-by-level", "maximum-number-of-non-overlapping-palindrome-substrings"]}, {"contest_title": "\u7b2c 320 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 320", "contest_title_slug": "weekly-contest-320", "contest_id": 777, "contest_start_time": 1668911400, "contest_duration": 5400, "user_num": 5678, "question_slugs": ["number-of-unequal-triplets-in-array", "closest-nodes-queries-in-a-binary-search-tree", "minimum-fuel-cost-to-report-to-the-capital", "number-of-beautiful-partitions"]}, {"contest_title": "\u7b2c 321 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 321", "contest_title_slug": "weekly-contest-321", "contest_id": 779, "contest_start_time": 1669516200, "contest_duration": 5400, "user_num": 5115, "question_slugs": ["find-the-pivot-integer", "append-characters-to-string-to-make-subsequence", "remove-nodes-from-linked-list", "count-subarrays-with-median-k"]}, {"contest_title": "\u7b2c 322 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 322", "contest_title_slug": "weekly-contest-322", "contest_id": 783, "contest_start_time": 1670121000, "contest_duration": 5400, "user_num": 5085, "question_slugs": ["circular-sentence", "divide-players-into-teams-of-equal-skill", "minimum-score-of-a-path-between-two-cities", "divide-nodes-into-the-maximum-number-of-groups"]}, {"contest_title": "\u7b2c 323 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 323", "contest_title_slug": "weekly-contest-323", "contest_id": 785, "contest_start_time": 1670725800, "contest_duration": 5400, "user_num": 4671, "question_slugs": ["delete-greatest-value-in-each-row", "longest-square-streak-in-an-array", "design-memory-allocator", "maximum-number-of-points-from-grid-queries"]}, {"contest_title": "\u7b2c 324 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 324", "contest_title_slug": "weekly-contest-324", "contest_id": 790, "contest_start_time": 1671330600, "contest_duration": 5400, "user_num": 4167, "question_slugs": ["count-pairs-of-similar-strings", "smallest-value-after-replacing-with-sum-of-prime-factors", "add-edges-to-make-degrees-of-all-nodes-even", "cycle-length-queries-in-a-tree"]}, {"contest_title": "\u7b2c 325 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 325", "contest_title_slug": "weekly-contest-325", "contest_id": 795, "contest_start_time": 1671935400, "contest_duration": 5400, "user_num": 3530, "question_slugs": ["shortest-distance-to-target-string-in-a-circular-array", "take-k-of-each-character-from-left-and-right", "maximum-tastiness-of-candy-basket", "number-of-great-partitions"]}, {"contest_title": "\u7b2c 326 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 326", "contest_title_slug": "weekly-contest-326", "contest_id": 799, "contest_start_time": 1672540200, "contest_duration": 5400, "user_num": 3873, "question_slugs": ["count-the-digits-that-divide-a-number", "distinct-prime-factors-of-product-of-array", "partition-string-into-substrings-with-values-at-most-k", "closest-prime-numbers-in-range"]}, {"contest_title": "\u7b2c 327 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 327", "contest_title_slug": "weekly-contest-327", "contest_id": 801, "contest_start_time": 1673145000, "contest_duration": 5400, "user_num": 4518, "question_slugs": ["maximum-count-of-positive-integer-and-negative-integer", "maximal-score-after-applying-k-operations", "make-number-of-distinct-characters-equal", "time-to-cross-a-bridge"]}, {"contest_title": "\u7b2c 328 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 328", "contest_title_slug": "weekly-contest-328", "contest_id": 805, "contest_start_time": 1673749800, "contest_duration": 5400, "user_num": 4776, "question_slugs": ["difference-between-element-sum-and-digit-sum-of-an-array", "increment-submatrices-by-one", "count-the-number-of-good-subarrays", "difference-between-maximum-and-minimum-price-sum"]}, {"contest_title": "\u7b2c 329 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 329", "contest_title_slug": "weekly-contest-329", "contest_id": 807, "contest_start_time": 1674354600, "contest_duration": 5400, "user_num": 2591, "question_slugs": ["alternating-digit-sum", "sort-the-students-by-their-kth-score", "apply-bitwise-operations-to-make-strings-equal", "minimum-cost-to-split-an-array"]}, {"contest_title": "\u7b2c 330 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 330", "contest_title_slug": "weekly-contest-330", "contest_id": 811, "contest_start_time": 1674959400, "contest_duration": 5400, "user_num": 3399, "question_slugs": ["count-distinct-numbers-on-board", "count-collisions-of-monkeys-on-a-polygon", "put-marbles-in-bags", "count-increasing-quadruplets"]}, {"contest_title": "\u7b2c 331 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 331", "contest_title_slug": "weekly-contest-331", "contest_id": 813, "contest_start_time": 1675564200, "contest_duration": 5400, "user_num": 4256, "question_slugs": ["take-gifts-from-the-richest-pile", "count-vowel-strings-in-ranges", "house-robber-iv", "rearranging-fruits"]}, {"contest_title": "\u7b2c 332 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 332", "contest_title_slug": "weekly-contest-332", "contest_id": 817, "contest_start_time": 1676169000, "contest_duration": 5400, "user_num": 4547, "question_slugs": ["find-the-array-concatenation-value", "count-the-number-of-fair-pairs", "substring-xor-queries", "subsequence-with-the-minimum-score"]}, {"contest_title": "\u7b2c 333 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 333", "contest_title_slug": "weekly-contest-333", "contest_id": 819, "contest_start_time": 1676773800, "contest_duration": 5400, "user_num": 4969, "question_slugs": ["merge-two-2d-arrays-by-summing-values", "minimum-operations-to-reduce-an-integer-to-0", "count-the-number-of-square-free-subsets", "find-the-string-with-lcp"]}, {"contest_title": "\u7b2c 334 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 334", "contest_title_slug": "weekly-contest-334", "contest_id": 823, "contest_start_time": 1677378600, "contest_duration": 5400, "user_num": 5501, "question_slugs": ["left-and-right-sum-differences", "find-the-divisibility-array-of-a-string", "find-the-maximum-number-of-marked-indices", "minimum-time-to-visit-a-cell-in-a-grid"]}, {"contest_title": "\u7b2c 335 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 335", "contest_title_slug": "weekly-contest-335", "contest_id": 825, "contest_start_time": 1677983400, "contest_duration": 5400, "user_num": 6019, "question_slugs": ["pass-the-pillow", "kth-largest-sum-in-a-binary-tree", "split-the-array-to-make-coprime-products", "number-of-ways-to-earn-points"]}, {"contest_title": "\u7b2c 336 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 336", "contest_title_slug": "weekly-contest-336", "contest_id": 833, "contest_start_time": 1678588200, "contest_duration": 5400, "user_num": 5897, "question_slugs": ["count-the-number-of-vowel-strings-in-range", "rearrange-array-to-maximize-prefix-score", "count-the-number-of-beautiful-subarrays", "minimum-time-to-complete-all-tasks"]}, {"contest_title": "\u7b2c 337 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 337", "contest_title_slug": "weekly-contest-337", "contest_id": 839, "contest_start_time": 1679193000, "contest_duration": 5400, "user_num": 5628, "question_slugs": ["number-of-even-and-odd-bits", "check-knight-tour-configuration", "the-number-of-beautiful-subsets", "smallest-missing-non-negative-integer-after-operations"]}, {"contest_title": "\u7b2c 338 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 338", "contest_title_slug": "weekly-contest-338", "contest_id": 843, "contest_start_time": 1679797800, "contest_duration": 5400, "user_num": 5594, "question_slugs": ["k-items-with-the-maximum-sum", "prime-subtraction-operation", "minimum-operations-to-make-all-array-elements-equal", "collect-coins-in-a-tree"]}, {"contest_title": "\u7b2c 339 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 339", "contest_title_slug": "weekly-contest-339", "contest_id": 850, "contest_start_time": 1680402600, "contest_duration": 5400, "user_num": 5180, "question_slugs": ["find-the-longest-balanced-substring-of-a-binary-string", "convert-an-array-into-a-2d-array-with-conditions", "mice-and-cheese", "minimum-reverse-operations"]}, {"contest_title": "\u7b2c 340 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 340", "contest_title_slug": "weekly-contest-340", "contest_id": 854, "contest_start_time": 1681007400, "contest_duration": 5400, "user_num": 4937, "question_slugs": ["prime-in-diagonal", "sum-of-distances", "minimize-the-maximum-difference-of-pairs", "minimum-number-of-visited-cells-in-a-grid"]}, {"contest_title": "\u7b2c 341 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 341", "contest_title_slug": "weekly-contest-341", "contest_id": 856, "contest_start_time": 1681612200, "contest_duration": 5400, "user_num": 4792, "question_slugs": ["row-with-maximum-ones", "find-the-maximum-divisibility-score", "minimum-additions-to-make-valid-string", "minimize-the-total-price-of-the-trips"]}, {"contest_title": "\u7b2c 342 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 342", "contest_title_slug": "weekly-contest-342", "contest_id": 860, "contest_start_time": 1682217000, "contest_duration": 5400, "user_num": 3702, "question_slugs": ["calculate-delayed-arrival-time", "sum-multiples", "sliding-subarray-beauty", "minimum-number-of-operations-to-make-all-array-elements-equal-to-1"]}, {"contest_title": "\u7b2c 343 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 343", "contest_title_slug": "weekly-contest-343", "contest_id": 863, "contest_start_time": 1682821800, "contest_duration": 5400, "user_num": 3313, "question_slugs": ["determine-the-winner-of-a-bowling-game", "first-completely-painted-row-or-column", "minimum-cost-of-a-path-with-special-roads", "lexicographically-smallest-beautiful-string"]}, {"contest_title": "\u7b2c 344 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 344", "contest_title_slug": "weekly-contest-344", "contest_id": 867, "contest_start_time": 1683426600, "contest_duration": 5400, "user_num": 3986, "question_slugs": ["find-the-distinct-difference-array", "frequency-tracker", "number-of-adjacent-elements-with-the-same-color", "make-costs-of-paths-equal-in-a-binary-tree"]}, {"contest_title": "\u7b2c 345 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 345", "contest_title_slug": "weekly-contest-345", "contest_id": 870, "contest_start_time": 1684031400, "contest_duration": 5400, "user_num": 4165, "question_slugs": ["find-the-losers-of-the-circular-game", "neighboring-bitwise-xor", "maximum-number-of-moves-in-a-grid", "count-the-number-of-complete-components"]}, {"contest_title": "\u7b2c 346 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 346", "contest_title_slug": "weekly-contest-346", "contest_id": 874, "contest_start_time": 1684636200, "contest_duration": 5400, "user_num": 4035, "question_slugs": ["minimum-string-length-after-removing-substrings", "lexicographically-smallest-palindrome", "find-the-punishment-number-of-an-integer", "modify-graph-edge-weights"]}, {"contest_title": "\u7b2c 347 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 347", "contest_title_slug": "weekly-contest-347", "contest_id": 876, "contest_start_time": 1685241000, "contest_duration": 5400, "user_num": 3836, "question_slugs": ["remove-trailing-zeros-from-a-string", "difference-of-number-of-distinct-values-on-diagonals", "minimum-cost-to-make-all-characters-equal", "maximum-strictly-increasing-cells-in-a-matrix"]}, {"contest_title": "\u7b2c 348 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 348", "contest_title_slug": "weekly-contest-348", "contest_id": 880, "contest_start_time": 1685845800, "contest_duration": 5400, "user_num": 3909, "question_slugs": ["minimize-string-length", "semi-ordered-permutation", "sum-of-matrix-after-queries", "count-of-integers"]}, {"contest_title": "\u7b2c 349 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 349", "contest_title_slug": "weekly-contest-349", "contest_id": 882, "contest_start_time": 1686450600, "contest_duration": 5400, "user_num": 3714, "question_slugs": ["neither-minimum-nor-maximum", "lexicographically-smallest-string-after-substring-operation", "collecting-chocolates", "maximum-sum-queries"]}, {"contest_title": "\u7b2c 350 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 350", "contest_title_slug": "weekly-contest-350", "contest_id": 886, "contest_start_time": 1687055400, "contest_duration": 5400, "user_num": 3580, "question_slugs": ["total-distance-traveled", "find-the-value-of-the-partition", "special-permutations", "painting-the-walls"]}, {"contest_title": "\u7b2c 351 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 351", "contest_title_slug": "weekly-contest-351", "contest_id": 888, "contest_start_time": 1687660200, "contest_duration": 5400, "user_num": 2471, "question_slugs": ["number-of-beautiful-pairs", "minimum-operations-to-make-the-integer-zero", "ways-to-split-array-into-good-subarrays", "robot-collisions"]}, {"contest_title": "\u7b2c 352 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 352", "contest_title_slug": "weekly-contest-352", "contest_id": 892, "contest_start_time": 1688265000, "contest_duration": 5400, "user_num": 3437, "question_slugs": ["longest-even-odd-subarray-with-threshold", "prime-pairs-with-target-sum", "continuous-subarrays", "sum-of-imbalance-numbers-of-all-subarrays"]}, {"contest_title": "\u7b2c 353 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 353", "contest_title_slug": "weekly-contest-353", "contest_id": 894, "contest_start_time": 1688869800, "contest_duration": 5400, "user_num": 4113, "question_slugs": ["find-the-maximum-achievable-number", "maximum-number-of-jumps-to-reach-the-last-index", "longest-non-decreasing-subarray-from-two-arrays", "apply-operations-to-make-all-array-elements-equal-to-zero"]}, {"contest_title": "\u7b2c 354 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 354", "contest_title_slug": "weekly-contest-354", "contest_id": 898, "contest_start_time": 1689474600, "contest_duration": 5400, "user_num": 3957, "question_slugs": ["sum-of-squares-of-special-elements", "maximum-beauty-of-an-array-after-applying-operation", "minimum-index-of-a-valid-split", "length-of-the-longest-valid-substring"]}, {"contest_title": "\u7b2c 355 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 355", "contest_title_slug": "weekly-contest-355", "contest_id": 900, "contest_start_time": 1690079400, "contest_duration": 5400, "user_num": 4112, "question_slugs": ["split-strings-by-separator", "largest-element-in-an-array-after-merge-operations", "maximum-number-of-groups-with-increasing-length", "count-paths-that-can-form-a-palindrome-in-a-tree"]}, {"contest_title": "\u7b2c 356 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 356", "contest_title_slug": "weekly-contest-356", "contest_id": 904, "contest_start_time": 1690684200, "contest_duration": 5400, "user_num": 4082, "question_slugs": ["number-of-employees-who-met-the-target", "count-complete-subarrays-in-an-array", "shortest-string-that-contains-three-strings", "count-stepping-numbers-in-range"]}, {"contest_title": "\u7b2c 357 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 357", "contest_title_slug": "weekly-contest-357", "contest_id": 906, "contest_start_time": 1691289000, "contest_duration": 5400, "user_num": 4265, "question_slugs": ["faulty-keyboard", "check-if-it-is-possible-to-split-array", "find-the-safest-path-in-a-grid", "maximum-elegance-of-a-k-length-subsequence"]}, {"contest_title": "\u7b2c 358 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 358", "contest_title_slug": "weekly-contest-358", "contest_id": 910, "contest_start_time": 1691893800, "contest_duration": 5400, "user_num": 4475, "question_slugs": ["max-pair-sum-in-an-array", "double-a-number-represented-as-a-linked-list", "minimum-absolute-difference-between-elements-with-constraint", "apply-operations-to-maximize-score"]}, {"contest_title": "\u7b2c 359 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 359", "contest_title_slug": "weekly-contest-359", "contest_id": 913, "contest_start_time": 1692498600, "contest_duration": 5400, "user_num": 4101, "question_slugs": ["check-if-a-string-is-an-acronym-of-words", "determine-the-minimum-sum-of-a-k-avoiding-array", "maximize-the-profit-as-the-salesman", "find-the-longest-equal-subarray"]}, {"contest_title": "\u7b2c 360 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 360", "contest_title_slug": "weekly-contest-360", "contest_id": 918, "contest_start_time": 1693103400, "contest_duration": 5400, "user_num": 4496, "question_slugs": ["furthest-point-from-origin", "find-the-minimum-possible-sum-of-a-beautiful-array", "minimum-operations-to-form-subsequence-with-target-sum", "maximize-value-of-function-in-a-ball-passing-game"]}, {"contest_title": "\u7b2c 361 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 361", "contest_title_slug": "weekly-contest-361", "contest_id": 920, "contest_start_time": 1693708200, "contest_duration": 5400, "user_num": 4170, "question_slugs": ["count-symmetric-integers", "minimum-operations-to-make-a-special-number", "count-of-interesting-subarrays", "minimum-edge-weight-equilibrium-queries-in-a-tree"]}, {"contest_title": "\u7b2c 362 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 362", "contest_title_slug": "weekly-contest-362", "contest_id": 924, "contest_start_time": 1694313000, "contest_duration": 5400, "user_num": 4800, "question_slugs": ["points-that-intersect-with-cars", "determine-if-a-cell-is-reachable-at-a-given-time", "minimum-moves-to-spread-stones-over-grid", "string-transformation"]}, {"contest_title": "\u7b2c 363 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 363", "contest_title_slug": "weekly-contest-363", "contest_id": 926, "contest_start_time": 1694917800, "contest_duration": 5400, "user_num": 4768, "question_slugs": ["sum-of-values-at-indices-with-k-set-bits", "happy-students", "maximum-number-of-alloys", "maximum-element-sum-of-a-complete-subset-of-indices"]}, {"contest_title": "\u7b2c 364 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 364", "contest_title_slug": "weekly-contest-364", "contest_id": 930, "contest_start_time": 1695522600, "contest_duration": 5400, "user_num": 4304, "question_slugs": ["maximum-odd-binary-number", "beautiful-towers-i", "beautiful-towers-ii", "count-valid-paths-in-a-tree"]}, {"contest_title": "\u7b2c 365 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 365", "contest_title_slug": "weekly-contest-365", "contest_id": 932, "contest_start_time": 1696127400, "contest_duration": 5400, "user_num": 2909, "question_slugs": ["maximum-value-of-an-ordered-triplet-i", "maximum-value-of-an-ordered-triplet-ii", "minimum-size-subarray-in-infinite-array", "count-visited-nodes-in-a-directed-graph"]}, {"contest_title": "\u7b2c 366 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 366", "contest_title_slug": "weekly-contest-366", "contest_id": 936, "contest_start_time": 1696732200, "contest_duration": 5400, "user_num": 2790, "question_slugs": ["divisible-and-non-divisible-sums-difference", "minimum-processing-time", "apply-operations-to-make-two-strings-equal", "apply-operations-on-array-to-maximize-sum-of-squares"]}, {"contest_title": "\u7b2c 367 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 367", "contest_title_slug": "weekly-contest-367", "contest_id": 938, "contest_start_time": 1697337000, "contest_duration": 5400, "user_num": 4317, "question_slugs": ["find-indices-with-index-and-value-difference-i", "shortest-and-lexicographically-smallest-beautiful-string", "find-indices-with-index-and-value-difference-ii", "construct-product-matrix"]}, {"contest_title": "\u7b2c 368 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 368", "contest_title_slug": "weekly-contest-368", "contest_id": 942, "contest_start_time": 1697941800, "contest_duration": 5400, "user_num": 5002, "question_slugs": ["minimum-sum-of-mountain-triplets-i", "minimum-sum-of-mountain-triplets-ii", "minimum-number-of-groups-to-create-a-valid-assignment", "minimum-changes-to-make-k-semi-palindromes"]}, {"contest_title": "\u7b2c 369 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 369", "contest_title_slug": "weekly-contest-369", "contest_id": 945, "contest_start_time": 1698546600, "contest_duration": 5400, "user_num": 4121, "question_slugs": ["find-the-k-or-of-an-array", "minimum-equal-sum-of-two-arrays-after-replacing-zeros", "minimum-increment-operations-to-make-array-beautiful", "maximum-points-after-collecting-coins-from-all-nodes"]}, {"contest_title": "\u7b2c 370 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 370", "contest_title_slug": "weekly-contest-370", "contest_id": 950, "contest_start_time": 1699151400, "contest_duration": 5400, "user_num": 3983, "question_slugs": ["find-champion-i", "find-champion-ii", "maximum-score-after-applying-operations-on-a-tree", "maximum-balanced-subsequence-sum"]}, {"contest_title": "\u7b2c 371 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 371", "contest_title_slug": "weekly-contest-371", "contest_id": 952, "contest_start_time": 1699756200, "contest_duration": 5400, "user_num": 3638, "question_slugs": ["maximum-strong-pair-xor-i", "high-access-employees", "minimum-operations-to-maximize-last-elements-in-arrays", "maximum-strong-pair-xor-ii"]}, {"contest_title": "\u7b2c 372 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 372", "contest_title_slug": "weekly-contest-372", "contest_id": 956, "contest_start_time": 1700361000, "contest_duration": 5400, "user_num": 3920, "question_slugs": ["make-three-strings-equal", "separate-black-and-white-balls", "maximum-xor-product", "find-building-where-alice-and-bob-can-meet"]}, {"contest_title": "\u7b2c 373 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 373", "contest_title_slug": "weekly-contest-373", "contest_id": 958, "contest_start_time": 1700965800, "contest_duration": 5400, "user_num": 3577, "question_slugs": ["matrix-similarity-after-cyclic-shifts", "count-beautiful-substrings-i", "make-lexicographically-smallest-array-by-swapping-elements", "count-beautiful-substrings-ii"]}, {"contest_title": "\u7b2c 374 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 374", "contest_title_slug": "weekly-contest-374", "contest_id": 962, "contest_start_time": 1701570600, "contest_duration": 5400, "user_num": 4053, "question_slugs": ["find-the-peaks", "minimum-number-of-coins-to-be-added", "count-complete-substrings", "count-the-number-of-infection-sequences"]}, {"contest_title": "\u7b2c 375 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 375", "contest_title_slug": "weekly-contest-375", "contest_id": 964, "contest_start_time": 1702175400, "contest_duration": 5400, "user_num": 3518, "question_slugs": ["count-tested-devices-after-test-operations", "double-modular-exponentiation", "count-subarrays-where-max-element-appears-at-least-k-times", "count-the-number-of-good-partitions"]}, {"contest_title": "\u7b2c 376 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 376", "contest_title_slug": "weekly-contest-376", "contest_id": 968, "contest_start_time": 1702780200, "contest_duration": 5400, "user_num": 3409, "question_slugs": ["find-missing-and-repeated-values", "divide-array-into-arrays-with-max-difference", "minimum-cost-to-make-array-equalindromic", "apply-operations-to-maximize-frequency-score"]}, {"contest_title": "\u7b2c 377 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 377", "contest_title_slug": "weekly-contest-377", "contest_id": 970, "contest_start_time": 1703385000, "contest_duration": 5400, "user_num": 3148, "question_slugs": ["minimum-number-game", "maximum-square-area-by-removing-fences-from-a-field", "minimum-cost-to-convert-string-i", "minimum-cost-to-convert-string-ii"]}, {"contest_title": "\u7b2c 378 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 378", "contest_title_slug": "weekly-contest-378", "contest_id": 974, "contest_start_time": 1703989800, "contest_duration": 5400, "user_num": 2747, "question_slugs": ["check-if-bitwise-or-has-trailing-zeros", "find-longest-special-substring-that-occurs-thrice-i", "find-longest-special-substring-that-occurs-thrice-ii", "palindrome-rearrangement-queries"]}, {"contest_title": "\u7b2c 379 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 379", "contest_title_slug": "weekly-contest-379", "contest_id": 976, "contest_start_time": 1704594600, "contest_duration": 5400, "user_num": 3117, "question_slugs": ["maximum-area-of-longest-diagonal-rectangle", "minimum-moves-to-capture-the-queen", "maximum-size-of-a-set-after-removals", "maximize-the-number-of-partitions-after-operations"]}, {"contest_title": "\u7b2c 380 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 380", "contest_title_slug": "weekly-contest-380", "contest_id": 980, "contest_start_time": 1705199400, "contest_duration": 5400, "user_num": 3325, "question_slugs": ["count-elements-with-maximum-frequency", "find-beautiful-indices-in-the-given-array-i", "maximum-number-that-sum-of-the-prices-is-less-than-or-equal-to-k", "find-beautiful-indices-in-the-given-array-ii"]}, {"contest_title": "\u7b2c 381 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 381", "contest_title_slug": "weekly-contest-381", "contest_id": 982, "contest_start_time": 1705804200, "contest_duration": 5400, "user_num": 3737, "question_slugs": ["minimum-number-of-pushes-to-type-word-i", "count-the-number-of-houses-at-a-certain-distance-i", "minimum-number-of-pushes-to-type-word-ii", "count-the-number-of-houses-at-a-certain-distance-ii"]}, {"contest_title": "\u7b2c 382 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 382", "contest_title_slug": "weekly-contest-382", "contest_id": 986, "contest_start_time": 1706409000, "contest_duration": 5400, "user_num": 3134, "question_slugs": ["number-of-changing-keys", "find-the-maximum-number-of-elements-in-subset", "alice-and-bob-playing-flower-game", "minimize-or-of-remaining-elements-using-operations"]}, {"contest_title": "\u7b2c 383 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 383", "contest_title_slug": "weekly-contest-383", "contest_id": 988, "contest_start_time": 1707013800, "contest_duration": 5400, "user_num": 2691, "question_slugs": ["ant-on-the-boundary", "minimum-time-to-revert-word-to-initial-state-i", "find-the-grid-of-region-average", "minimum-time-to-revert-word-to-initial-state-ii"]}, {"contest_title": "\u7b2c 384 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 384", "contest_title_slug": "weekly-contest-384", "contest_id": 992, "contest_start_time": 1707618600, "contest_duration": 5400, "user_num": 1652, "question_slugs": ["modify-the-matrix", "number-of-subarrays-that-match-a-pattern-i", "maximum-palindromes-after-operations", "number-of-subarrays-that-match-a-pattern-ii"]}, {"contest_title": "\u7b2c 385 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 385", "contest_title_slug": "weekly-contest-385", "contest_id": 994, "contest_start_time": 1708223400, "contest_duration": 5400, "user_num": 2382, "question_slugs": ["count-prefix-and-suffix-pairs-i", "find-the-length-of-the-longest-common-prefix", "most-frequent-prime", "count-prefix-and-suffix-pairs-ii"]}, {"contest_title": "\u7b2c 386 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 386", "contest_title_slug": "weekly-contest-386", "contest_id": 998, "contest_start_time": 1708828200, "contest_duration": 5400, "user_num": 2731, "question_slugs": ["split-the-array", "find-the-largest-area-of-square-inside-two-rectangles", "earliest-second-to-mark-indices-i", "earliest-second-to-mark-indices-ii"]}, {"contest_title": "\u7b2c 387 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 387", "contest_title_slug": "weekly-contest-387", "contest_id": 1000, "contest_start_time": 1709433000, "contest_duration": 5400, "user_num": 3694, "question_slugs": ["distribute-elements-into-two-arrays-i", "count-submatrices-with-top-left-element-and-sum-less-than-k", "minimum-operations-to-write-the-letter-y-on-a-grid", "distribute-elements-into-two-arrays-ii"]}, {"contest_title": "\u7b2c 388 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 388", "contest_title_slug": "weekly-contest-388", "contest_id": 1004, "contest_start_time": 1710037800, "contest_duration": 5400, "user_num": 4291, "question_slugs": ["apple-redistribution-into-boxes", "maximize-happiness-of-selected-children", "shortest-uncommon-substring-in-an-array", "maximum-strength-of-k-disjoint-subarrays"]}, {"contest_title": "\u7b2c 389 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 389", "contest_title_slug": "weekly-contest-389", "contest_id": 1006, "contest_start_time": 1710642600, "contest_duration": 5400, "user_num": 4561, "question_slugs": ["existence-of-a-substring-in-a-string-and-its-reverse", "count-substrings-starting-and-ending-with-given-character", "minimum-deletions-to-make-string-k-special", "minimum-moves-to-pick-k-ones"]}, {"contest_title": "\u7b2c 390 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 390", "contest_title_slug": "weekly-contest-390", "contest_id": 1011, "contest_start_time": 1711247400, "contest_duration": 5400, "user_num": 4817, "question_slugs": ["maximum-length-substring-with-two-occurrences", "apply-operations-to-make-sum-of-array-greater-than-or-equal-to-k", "most-frequent-ids", "longest-common-suffix-queries"]}, {"contest_title": "\u7b2c 391 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 391", "contest_title_slug": "weekly-contest-391", "contest_id": 1014, "contest_start_time": 1711852200, "contest_duration": 5400, "user_num": 4181, "question_slugs": ["harshad-number", "water-bottles-ii", "count-alternating-subarrays", "minimize-manhattan-distances"]}, {"contest_title": "\u7b2c 392 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 392", "contest_title_slug": "weekly-contest-392", "contest_id": 1018, "contest_start_time": 1712457000, "contest_duration": 5400, "user_num": 3194, "question_slugs": ["longest-strictly-increasing-or-strictly-decreasing-subarray", "lexicographically-smallest-string-after-operations-with-constraint", "minimum-operations-to-make-median-of-array-equal-to-k", "minimum-cost-walk-in-weighted-graph"]}, {"contest_title": "\u7b2c 393 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 393", "contest_title_slug": "weekly-contest-393", "contest_id": 1020, "contest_start_time": 1713061800, "contest_duration": 5400, "user_num": 4219, "question_slugs": ["latest-time-you-can-obtain-after-replacing-characters", "maximum-prime-difference", "kth-smallest-amount-with-single-denomination-combination", "minimum-sum-of-values-by-dividing-array"]}, {"contest_title": "\u7b2c 394 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 394", "contest_title_slug": "weekly-contest-394", "contest_id": 1024, "contest_start_time": 1713666600, "contest_duration": 5400, "user_num": 3958, "question_slugs": ["count-the-number-of-special-characters-i", "count-the-number-of-special-characters-ii", "minimum-number-of-operations-to-satisfy-conditions", "find-edges-in-shortest-paths"]}, {"contest_title": "\u7b2c 395 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 395", "contest_title_slug": "weekly-contest-395", "contest_id": 1026, "contest_start_time": 1714271400, "contest_duration": 5400, "user_num": 2969, "question_slugs": ["find-the-integer-added-to-array-i", "find-the-integer-added-to-array-ii", "minimum-array-end", "find-the-median-of-the-uniqueness-array"]}, {"contest_title": "\u7b2c 396 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 396", "contest_title_slug": "weekly-contest-396", "contest_id": 1030, "contest_start_time": 1714876200, "contest_duration": 5400, "user_num": 2932, "question_slugs": ["valid-word", "minimum-number-of-operations-to-make-word-k-periodic", "minimum-length-of-anagram-concatenation", "minimum-cost-to-equalize-array"]}, {"contest_title": "\u7b2c 397 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 397", "contest_title_slug": "weekly-contest-397", "contest_id": 1032, "contest_start_time": 1715481000, "contest_duration": 5400, "user_num": 3365, "question_slugs": ["permutation-difference-between-two-strings", "taking-maximum-energy-from-the-mystic-dungeon", "maximum-difference-score-in-a-grid", "find-the-minimum-cost-array-permutation"]}, {"contest_title": "\u7b2c 398 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 398", "contest_title_slug": "weekly-contest-398", "contest_id": 1036, "contest_start_time": 1716085800, "contest_duration": 5400, "user_num": 3606, "question_slugs": ["special-array-i", "special-array-ii", "sum-of-digit-differences-of-all-pairs", "find-number-of-ways-to-reach-the-k-th-stair"]}, {"contest_title": "\u7b2c 399 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 399", "contest_title_slug": "weekly-contest-399", "contest_id": 1038, "contest_start_time": 1716690600, "contest_duration": 5400, "user_num": 3424, "question_slugs": ["find-the-number-of-good-pairs-i", "string-compression-iii", "find-the-number-of-good-pairs-ii", "maximum-sum-of-subsequence-with-non-adjacent-elements"]}, {"contest_title": "\u7b2c 400 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 400", "contest_title_slug": "weekly-contest-400", "contest_id": 1043, "contest_start_time": 1717295400, "contest_duration": 5400, "user_num": 3534, "question_slugs": ["minimum-number-of-chairs-in-a-waiting-room", "count-days-without-meetings", "lexicographically-minimum-string-after-removing-stars", "find-subarray-with-bitwise-or-closest-to-k"]}, {"contest_title": "\u7b2c 401 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 401", "contest_title_slug": "weekly-contest-401", "contest_id": 1045, "contest_start_time": 1717900200, "contest_duration": 5400, "user_num": 3160, "question_slugs": ["find-the-child-who-has-the-ball-after-k-seconds", "find-the-n-th-value-after-k-seconds", "maximum-total-reward-using-operations-i", "maximum-total-reward-using-operations-ii"]}, {"contest_title": "\u7b2c 402 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 402", "contest_title_slug": "weekly-contest-402", "contest_id": 1049, "contest_start_time": 1718505000, "contest_duration": 5400, "user_num": 3283, "question_slugs": ["count-pairs-that-form-a-complete-day-i", "count-pairs-that-form-a-complete-day-ii", "maximum-total-damage-with-spell-casting", "peaks-in-array"]}, {"contest_title": "\u7b2c 403 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 403", "contest_title_slug": "weekly-contest-403", "contest_id": 1052, "contest_start_time": 1719109800, "contest_duration": 5400, "user_num": 3112, "question_slugs": ["minimum-average-of-smallest-and-largest-elements", "find-the-minimum-area-to-cover-all-ones-i", "maximize-total-cost-of-alternating-subarrays", "find-the-minimum-area-to-cover-all-ones-ii"]}, {"contest_title": "\u7b2c 404 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 404", "contest_title_slug": "weekly-contest-404", "contest_id": 1056, "contest_start_time": 1719714600, "contest_duration": 5400, "user_num": 3486, "question_slugs": ["maximum-height-of-a-triangle", "find-the-maximum-length-of-valid-subsequence-i", "find-the-maximum-length-of-valid-subsequence-ii", "find-minimum-diameter-after-merging-two-trees"]}, {"contest_title": "\u7b2c 405 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 405", "contest_title_slug": "weekly-contest-405", "contest_id": 1058, "contest_start_time": 1720319400, "contest_duration": 5400, "user_num": 3240, "question_slugs": ["find-the-encrypted-string", "generate-binary-strings-without-adjacent-zeros", "count-submatrices-with-equal-frequency-of-x-and-y", "construct-string-with-minimum-cost"]}, {"contest_title": "\u7b2c 406 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 406", "contest_title_slug": "weekly-contest-406", "contest_id": 1062, "contest_start_time": 1720924200, "contest_duration": 5400, "user_num": 3422, "question_slugs": ["lexicographically-smallest-string-after-a-swap", "delete-nodes-from-linked-list-present-in-array", "minimum-cost-for-cutting-cake-i", "minimum-cost-for-cutting-cake-ii"]}, {"contest_title": "\u7b2c 407 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 407", "contest_title_slug": "weekly-contest-407", "contest_id": 1064, "contest_start_time": 1721529000, "contest_duration": 5400, "user_num": 3268, "question_slugs": ["number-of-bit-changes-to-make-two-integers-equal", "vowels-game-in-a-string", "maximum-number-of-operations-to-move-ones-to-the-end", "minimum-operations-to-make-array-equal-to-target"]}, {"contest_title": "\u7b2c 408 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 408", "contest_title_slug": "weekly-contest-408", "contest_id": 1069, "contest_start_time": 1722133800, "contest_duration": 5400, "user_num": 3369, "question_slugs": ["find-if-digit-game-can-be-won", "find-the-count-of-numbers-which-are-not-special", "count-the-number-of-substrings-with-dominant-ones", "check-if-the-rectangle-corner-is-reachable"]}, {"contest_title": "\u7b2c 409 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 409", "contest_title_slug": "weekly-contest-409", "contest_id": 1071, "contest_start_time": 1722738600, "contest_duration": 5400, "user_num": 3643, "question_slugs": ["design-neighbor-sum-service", "shortest-distance-after-road-addition-queries-i", "shortest-distance-after-road-addition-queries-ii", "alternating-groups-iii"]}, {"contest_title": "\u7b2c 410 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 410", "contest_title_slug": "weekly-contest-410", "contest_id": 1075, "contest_start_time": 1723343400, "contest_duration": 5400, "user_num": 2987, "question_slugs": ["snake-in-matrix", "count-the-number-of-good-nodes", "find-the-count-of-monotonic-pairs-i", "find-the-count-of-monotonic-pairs-ii"]}, {"contest_title": "\u7b2c 411 \u573a\u5468\u8d5b", "contest_title_en": "Weekly Contest 411", "contest_title_slug": "weekly-contest-411", "contest_id": 1077, "contest_start_time": 1723948200, "contest_duration": 5400, "user_num": 3029, "question_slugs": ["count-substrings-that-satisfy-k-constraint-i", "maximum-energy-boost-from-two-drinks", "find-the-largest-palindrome-divisible-by-k", "count-substrings-that-satisfy-k-constraint-ii"]}, {"contest_title": "\u7b2c 1 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 1", "contest_title_slug": "biweekly-contest-1", "contest_id": 70, "contest_start_time": 1559399400, "contest_duration": 7200, "user_num": 197, "question_slugs": ["fixed-point", "index-pairs-of-a-string", "campus-bikes-ii", "digit-count-in-range"]}, {"contest_title": "\u7b2c 2 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 2", "contest_title_slug": "biweekly-contest-2", "contest_id": 73, "contest_start_time": 1560609000, "contest_duration": 5400, "user_num": 256, "question_slugs": ["sum-of-digits-in-the-minimum-number", "high-five", "brace-expansion", "confusing-number-ii"]}, {"contest_title": "\u7b2c 3 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 3", "contest_title_slug": "biweekly-contest-3", "contest_id": 85, "contest_start_time": 1561818600, "contest_duration": 5400, "user_num": 312, "question_slugs": ["two-sum-less-than-k", "find-k-length-substrings-with-no-repeated-characters", "the-earliest-moment-when-everyone-become-friends", "path-with-maximum-minimum-value"]}, {"contest_title": "\u7b2c 4 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 4", "contest_title_slug": "biweekly-contest-4", "contest_id": 88, "contest_start_time": 1563028200, "contest_duration": 5400, "user_num": 438, "question_slugs": ["number-of-days-in-a-month", "remove-vowels-from-a-string", "maximum-average-subtree", "divide-array-into-increasing-sequences"]}, {"contest_title": "\u7b2c 5 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 5", "contest_title_slug": "biweekly-contest-5", "contest_id": 91, "contest_start_time": 1564237800, "contest_duration": 5400, "user_num": 495, "question_slugs": ["largest-unique-number", "armstrong-number", "connecting-cities-with-minimum-cost", "parallel-courses"]}, {"contest_title": "\u7b2c 6 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 6", "contest_title_slug": "biweekly-contest-6", "contest_id": 95, "contest_start_time": 1565447400, "contest_duration": 5400, "user_num": 513, "question_slugs": ["check-if-a-number-is-majority-element-in-a-sorted-array", "minimum-swaps-to-group-all-1s-together", "analyze-user-website-visit-pattern", "string-transforms-into-another-string"]}, {"contest_title": "\u7b2c 7 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 7", "contest_title_slug": "biweekly-contest-7", "contest_id": 99, "contest_start_time": 1566657000, "contest_duration": 5400, "user_num": 561, "question_slugs": ["single-row-keyboard", "design-file-system", "minimum-cost-to-connect-sticks", "optimize-water-distribution-in-a-village"]}, {"contest_title": "\u7b2c 8 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 8", "contest_title_slug": "biweekly-contest-8", "contest_id": 103, "contest_start_time": 1567866600, "contest_duration": 5400, "user_num": 630, "question_slugs": ["count-substrings-with-only-one-distinct-letter", "before-and-after-puzzle", "shortest-distance-to-target-color", "maximum-number-of-ones"]}, {"contest_title": "\u7b2c 9 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 9", "contest_title_slug": "biweekly-contest-9", "contest_id": 108, "contest_start_time": 1569076200, "contest_duration": 5700, "user_num": 929, "question_slugs": ["how-many-apples-can-you-put-into-the-basket", "minimum-knight-moves", "find-smallest-common-element-in-all-rows", "minimum-time-to-build-blocks"]}, {"contest_title": "\u7b2c 10 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 10", "contest_title_slug": "biweekly-contest-10", "contest_id": 115, "contest_start_time": 1570285800, "contest_duration": 5400, "user_num": 738, "question_slugs": ["intersection-of-three-sorted-arrays", "two-sum-bsts", "stepping-numbers", "valid-palindrome-iii"]}, {"contest_title": "\u7b2c 11 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 11", "contest_title_slug": "biweekly-contest-11", "contest_id": 118, "contest_start_time": 1571495400, "contest_duration": 5400, "user_num": 913, "question_slugs": ["missing-number-in-arithmetic-progression", "meeting-scheduler", "toss-strange-coins", "divide-chocolate"]}, {"contest_title": "\u7b2c 12 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 12", "contest_title_slug": "biweekly-contest-12", "contest_id": 121, "contest_start_time": 1572705000, "contest_duration": 5400, "user_num": 911, "question_slugs": ["design-a-leaderboard", "array-transformation", "tree-diameter", "palindrome-removal"]}, {"contest_title": "\u7b2c 13 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 13", "contest_title_slug": "biweekly-contest-13", "contest_id": 124, "contest_start_time": 1573914600, "contest_duration": 5400, "user_num": 810, "question_slugs": ["encode-number", "smallest-common-region", "synonymous-sentences", "handshakes-that-dont-cross"]}, {"contest_title": "\u7b2c 14 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 14", "contest_title_slug": "biweekly-contest-14", "contest_id": 129, "contest_start_time": 1575124200, "contest_duration": 5400, "user_num": 871, "question_slugs": ["hexspeak", "remove-interval", "delete-tree-nodes", "number-of-ships-in-a-rectangle"]}, {"contest_title": "\u7b2c 15 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 15", "contest_title_slug": "biweekly-contest-15", "contest_id": 132, "contest_start_time": 1576333800, "contest_duration": 5400, "user_num": 797, "question_slugs": ["element-appearing-more-than-25-in-sorted-array", "remove-covered-intervals", "iterator-for-combination", "minimum-falling-path-sum-ii"]}, {"contest_title": "\u7b2c 16 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 16", "contest_title_slug": "biweekly-contest-16", "contest_id": 135, "contest_start_time": 1577543400, "contest_duration": 5400, "user_num": 822, "question_slugs": ["replace-elements-with-greatest-element-on-right-side", "sum-of-mutated-array-closest-to-target", "deepest-leaves-sum", "number-of-paths-with-max-score"]}, {"contest_title": "\u7b2c 17 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 17", "contest_title_slug": "biweekly-contest-17", "contest_id": 138, "contest_start_time": 1578753000, "contest_duration": 5400, "user_num": 897, "question_slugs": ["decompress-run-length-encoded-list", "matrix-block-sum", "sum-of-nodes-with-even-valued-grandparent", "distinct-echo-substrings"]}, {"contest_title": "\u7b2c 18 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 18", "contest_title_slug": "biweekly-contest-18", "contest_id": 143, "contest_start_time": 1579962600, "contest_duration": 5400, "user_num": 587, "question_slugs": ["rank-transform-of-an-array", "break-a-palindrome", "sort-the-matrix-diagonally", "reverse-subarray-to-maximize-array-value"]}, {"contest_title": "\u7b2c 19 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 19", "contest_title_slug": "biweekly-contest-19", "contest_id": 146, "contest_start_time": 1581172200, "contest_duration": 5400, "user_num": 1120, "question_slugs": ["number-of-steps-to-reduce-a-number-to-zero", "number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold", "angle-between-hands-of-a-clock", "jump-game-iv"]}, {"contest_title": "\u7b2c 20 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 20", "contest_title_slug": "biweekly-contest-20", "contest_id": 149, "contest_start_time": 1582381800, "contest_duration": 5400, "user_num": 1541, "question_slugs": ["sort-integers-by-the-number-of-1-bits", "apply-discount-every-n-orders", "number-of-substrings-containing-all-three-characters", "count-all-valid-pickup-and-delivery-options"]}, {"contest_title": "\u7b2c 21 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 21", "contest_title_slug": "biweekly-contest-21", "contest_id": 157, "contest_start_time": 1583591400, "contest_duration": 5400, "user_num": 1913, "question_slugs": ["increasing-decreasing-string", "find-the-longest-substring-containing-vowels-in-even-counts", "longest-zigzag-path-in-a-binary-tree", "maximum-sum-bst-in-binary-tree"]}, {"contest_title": "\u7b2c 22 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 22", "contest_title_slug": "biweekly-contest-22", "contest_id": 163, "contest_start_time": 1584801000, "contest_duration": 5400, "user_num": 2042, "question_slugs": ["find-the-distance-value-between-two-arrays", "cinema-seat-allocation", "sort-integers-by-the-power-value", "pizza-with-3n-slices"]}, {"contest_title": "\u7b2c 23 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 23", "contest_title_slug": "biweekly-contest-23", "contest_id": 169, "contest_start_time": 1586010600, "contest_duration": 5400, "user_num": 2045, "question_slugs": ["count-largest-group", "construct-k-palindrome-strings", "circle-and-rectangle-overlapping", "reducing-dishes"]}, {"contest_title": "\u7b2c 24 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 24", "contest_title_slug": "biweekly-contest-24", "contest_id": 178, "contest_start_time": 1587220200, "contest_duration": 5400, "user_num": 1898, "question_slugs": ["minimum-value-to-get-positive-step-by-step-sum", "find-the-minimum-number-of-fibonacci-numbers-whose-sum-is-k", "the-k-th-lexicographical-string-of-all-happy-strings-of-length-n", "restore-the-array"]}, {"contest_title": "\u7b2c 25 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 25", "contest_title_slug": "biweekly-contest-25", "contest_id": 192, "contest_start_time": 1588429800, "contest_duration": 5400, "user_num": 1832, "question_slugs": ["kids-with-the-greatest-number-of-candies", "max-difference-you-can-get-from-changing-an-integer", "check-if-a-string-can-break-another-string", "number-of-ways-to-wear-different-hats-to-each-other"]}, {"contest_title": "\u7b2c 26 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 26", "contest_title_slug": "biweekly-contest-26", "contest_id": 198, "contest_start_time": 1589639400, "contest_duration": 5400, "user_num": 1971, "question_slugs": ["consecutive-characters", "simplified-fractions", "count-good-nodes-in-binary-tree", "form-largest-integer-with-digits-that-add-up-to-target"]}, {"contest_title": "\u7b2c 27 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 27", "contest_title_slug": "biweekly-contest-27", "contest_id": 204, "contest_start_time": 1590849000, "contest_duration": 5400, "user_num": 1966, "question_slugs": ["make-two-arrays-equal-by-reversing-subarrays", "check-if-a-string-contains-all-binary-codes-of-size-k", "course-schedule-iv", "cherry-pickup-ii"]}, {"contest_title": "\u7b2c 28 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 28", "contest_title_slug": "biweekly-contest-28", "contest_id": 210, "contest_start_time": 1592058600, "contest_duration": 5400, "user_num": 2144, "question_slugs": ["final-prices-with-a-special-discount-in-a-shop", "subrectangle-queries", "find-two-non-overlapping-sub-arrays-each-with-target-sum", "allocate-mailboxes"]}, {"contest_title": "\u7b2c 29 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 29", "contest_title_slug": "biweekly-contest-29", "contest_id": 216, "contest_start_time": 1593268200, "contest_duration": 5400, "user_num": 2260, "question_slugs": ["average-salary-excluding-the-minimum-and-maximum-salary", "the-kth-factor-of-n", "longest-subarray-of-1s-after-deleting-one-element", "parallel-courses-ii"]}, {"contest_title": "\u7b2c 30 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 30", "contest_title_slug": "biweekly-contest-30", "contest_id": 222, "contest_start_time": 1594477800, "contest_duration": 5400, "user_num": 2545, "question_slugs": ["reformat-date", "range-sum-of-sorted-subarray-sums", "minimum-difference-between-largest-and-smallest-value-in-three-moves", "stone-game-iv"]}, {"contest_title": "\u7b2c 31 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 31", "contest_title_slug": "biweekly-contest-31", "contest_id": 232, "contest_start_time": 1595687400, "contest_duration": 5400, "user_num": 2767, "question_slugs": ["count-odd-numbers-in-an-interval-range", "number-of-sub-arrays-with-odd-sum", "number-of-good-ways-to-split-a-string", "minimum-number-of-increments-on-subarrays-to-form-a-target-array"]}, {"contest_title": "\u7b2c 32 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 32", "contest_title_slug": "biweekly-contest-32", "contest_id": 237, "contest_start_time": 1596897000, "contest_duration": 5400, "user_num": 2957, "question_slugs": ["kth-missing-positive-number", "can-convert-string-in-k-moves", "minimum-insertions-to-balance-a-parentheses-string", "find-longest-awesome-substring"]}, {"contest_title": "\u7b2c 33 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 33", "contest_title_slug": "biweekly-contest-33", "contest_id": 241, "contest_start_time": 1598106600, "contest_duration": 5400, "user_num": 3304, "question_slugs": ["thousand-separator", "minimum-number-of-vertices-to-reach-all-nodes", "minimum-numbers-of-function-calls-to-make-target-array", "detect-cycles-in-2d-grid"]}, {"contest_title": "\u7b2c 34 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 34", "contest_title_slug": "biweekly-contest-34", "contest_id": 256, "contest_start_time": 1599316200, "contest_duration": 5400, "user_num": 2842, "question_slugs": ["matrix-diagonal-sum", "number-of-ways-to-split-a-string", "shortest-subarray-to-be-removed-to-make-array-sorted", "count-all-possible-routes"]}, {"contest_title": "\u7b2c 35 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 35", "contest_title_slug": "biweekly-contest-35", "contest_id": 266, "contest_start_time": 1600525800, "contest_duration": 5400, "user_num": 2839, "question_slugs": ["sum-of-all-odd-length-subarrays", "maximum-sum-obtained-of-any-permutation", "make-sum-divisible-by-p", "strange-printer-ii"]}, {"contest_title": "\u7b2c 36 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 36", "contest_title_slug": "biweekly-contest-36", "contest_id": 288, "contest_start_time": 1601735400, "contest_duration": 5400, "user_num": 2204, "question_slugs": ["design-parking-system", "alert-using-same-key-card-three-or-more-times-in-a-one-hour-period", "find-valid-matrix-given-row-and-column-sums", "find-servers-that-handled-most-number-of-requests"]}, {"contest_title": "\u7b2c 37 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 37", "contest_title_slug": "biweekly-contest-37", "contest_id": 294, "contest_start_time": 1602945000, "contest_duration": 5400, "user_num": 2104, "question_slugs": ["mean-of-array-after-removing-some-elements", "coordinate-with-maximum-network-quality", "number-of-sets-of-k-non-overlapping-line-segments", "fancy-sequence"]}, {"contest_title": "\u7b2c 38 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 38", "contest_title_slug": "biweekly-contest-38", "contest_id": 300, "contest_start_time": 1604154600, "contest_duration": 5400, "user_num": 2004, "question_slugs": ["sort-array-by-increasing-frequency", "widest-vertical-area-between-two-points-containing-no-points", "count-substrings-that-differ-by-one-character", "number-of-ways-to-form-a-target-string-given-a-dictionary"]}, {"contest_title": "\u7b2c 39 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 39", "contest_title_slug": "biweekly-contest-39", "contest_id": 306, "contest_start_time": 1605364200, "contest_duration": 5400, "user_num": 2069, "question_slugs": ["defuse-the-bomb", "minimum-deletions-to-make-string-balanced", "minimum-jumps-to-reach-home", "distribute-repeating-integers"]}, {"contest_title": "\u7b2c 40 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 40", "contest_title_slug": "biweekly-contest-40", "contest_id": 312, "contest_start_time": 1606573800, "contest_duration": 5400, "user_num": 1891, "question_slugs": ["maximum-repeating-substring", "merge-in-between-linked-lists", "design-front-middle-back-queue", "minimum-number-of-removals-to-make-mountain-array"]}, {"contest_title": "\u7b2c 41 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 41", "contest_title_slug": "biweekly-contest-41", "contest_id": 318, "contest_start_time": 1607783400, "contest_duration": 5400, "user_num": 1660, "question_slugs": ["count-the-number-of-consistent-strings", "sum-of-absolute-differences-in-a-sorted-array", "stone-game-vi", "delivering-boxes-from-storage-to-ports"]}, {"contest_title": "\u7b2c 42 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 42", "contest_title_slug": "biweekly-contest-42", "contest_id": 325, "contest_start_time": 1608993000, "contest_duration": 5400, "user_num": 1578, "question_slugs": ["number-of-students-unable-to-eat-lunch", "average-waiting-time", "maximum-binary-string-after-change", "minimum-adjacent-swaps-for-k-consecutive-ones"]}, {"contest_title": "\u7b2c 43 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 43", "contest_title_slug": "biweekly-contest-43", "contest_id": 331, "contest_start_time": 1610202600, "contest_duration": 5400, "user_num": 1631, "question_slugs": ["calculate-money-in-leetcode-bank", "maximum-score-from-removing-substrings", "construct-the-lexicographically-largest-valid-sequence", "number-of-ways-to-reconstruct-a-tree"]}, {"contest_title": "\u7b2c 44 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 44", "contest_title_slug": "biweekly-contest-44", "contest_id": 337, "contest_start_time": 1611412200, "contest_duration": 5400, "user_num": 1826, "question_slugs": ["find-the-highest-altitude", "minimum-number-of-people-to-teach", "decode-xored-permutation", "count-ways-to-make-array-with-product"]}, {"contest_title": "\u7b2c 45 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 45", "contest_title_slug": "biweekly-contest-45", "contest_id": 343, "contest_start_time": 1612621800, "contest_duration": 5400, "user_num": 1676, "question_slugs": ["sum-of-unique-elements", "maximum-absolute-sum-of-any-subarray", "minimum-length-of-string-after-deleting-similar-ends", "maximum-number-of-events-that-can-be-attended-ii"]}, {"contest_title": "\u7b2c 46 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 46", "contest_title_slug": "biweekly-contest-46", "contest_id": 349, "contest_start_time": 1613831400, "contest_duration": 5400, "user_num": 1647, "question_slugs": ["longest-nice-substring", "form-array-by-concatenating-subarrays-of-another-array", "map-of-highest-peak", "tree-of-coprimes"]}, {"contest_title": "\u7b2c 47 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 47", "contest_title_slug": "biweekly-contest-47", "contest_id": 355, "contest_start_time": 1615041000, "contest_duration": 5400, "user_num": 3085, "question_slugs": ["find-nearest-point-that-has-the-same-x-or-y-coordinate", "check-if-number-is-a-sum-of-powers-of-three", "sum-of-beauty-of-all-substrings", "count-pairs-of-nodes"]}, {"contest_title": "\u7b2c 48 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 48", "contest_title_slug": "biweekly-contest-48", "contest_id": 362, "contest_start_time": 1616250600, "contest_duration": 5400, "user_num": 2853, "question_slugs": ["second-largest-digit-in-a-string", "design-authentication-manager", "maximum-number-of-consecutive-values-you-can-make", "maximize-score-after-n-operations"]}, {"contest_title": "\u7b2c 49 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 49", "contest_title_slug": "biweekly-contest-49", "contest_id": 374, "contest_start_time": 1617460200, "contest_duration": 5400, "user_num": 3193, "question_slugs": ["determine-color-of-a-chessboard-square", "sentence-similarity-iii", "count-nice-pairs-in-an-array", "maximum-number-of-groups-getting-fresh-donuts"]}, {"contest_title": "\u7b2c 50 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 50", "contest_title_slug": "biweekly-contest-50", "contest_id": 390, "contest_start_time": 1618669800, "contest_duration": 5400, "user_num": 3608, "question_slugs": ["minimum-operations-to-make-the-array-increasing", "queries-on-number-of-points-inside-a-circle", "maximum-xor-for-each-query", "minimum-number-of-operations-to-make-string-sorted"]}, {"contest_title": "\u7b2c 51 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 51", "contest_title_slug": "biweekly-contest-51", "contest_id": 396, "contest_start_time": 1619879400, "contest_duration": 5400, "user_num": 2675, "question_slugs": ["replace-all-digits-with-characters", "seat-reservation-manager", "maximum-element-after-decreasing-and-rearranging", "closest-room"]}, {"contest_title": "\u7b2c 52 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 52", "contest_title_slug": "biweekly-contest-52", "contest_id": 402, "contest_start_time": 1621089000, "contest_duration": 5400, "user_num": 2930, "question_slugs": ["sorting-the-sentence", "incremental-memory-leak", "rotating-the-box", "sum-of-floored-pairs"]}, {"contest_title": "\u7b2c 53 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 53", "contest_title_slug": "biweekly-contest-53", "contest_id": 408, "contest_start_time": 1622298600, "contest_duration": 5400, "user_num": 3069, "question_slugs": ["substrings-of-size-three-with-distinct-characters", "minimize-maximum-pair-sum-in-array", "get-biggest-three-rhombus-sums-in-a-grid", "minimum-xor-sum-of-two-arrays"]}, {"contest_title": "\u7b2c 54 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 54", "contest_title_slug": "biweekly-contest-54", "contest_id": 414, "contest_start_time": 1623508200, "contest_duration": 5400, "user_num": 2479, "question_slugs": ["check-if-all-the-integers-in-a-range-are-covered", "find-the-student-that-will-replace-the-chalk", "largest-magic-square", "minimum-cost-to-change-the-final-value-of-expression"]}, {"contest_title": "\u7b2c 55 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 55", "contest_title_slug": "biweekly-contest-55", "contest_id": 421, "contest_start_time": 1624717800, "contest_duration": 5400, "user_num": 3277, "question_slugs": ["remove-one-element-to-make-the-array-strictly-increasing", "remove-all-occurrences-of-a-substring", "maximum-alternating-subsequence-sum", "design-movie-rental-system"]}, {"contest_title": "\u7b2c 56 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 56", "contest_title_slug": "biweekly-contest-56", "contest_id": 429, "contest_start_time": 1625927400, "contest_duration": 5400, "user_num": 2760, "question_slugs": ["count-square-sum-triples", "nearest-exit-from-entrance-in-maze", "sum-game", "minimum-cost-to-reach-destination-in-time"]}, {"contest_title": "\u7b2c 57 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 57", "contest_title_slug": "biweekly-contest-57", "contest_id": 435, "contest_start_time": 1627137000, "contest_duration": 5400, "user_num": 2933, "question_slugs": ["check-if-all-characters-have-equal-number-of-occurrences", "the-number-of-the-smallest-unoccupied-chair", "describe-the-painting", "number-of-visible-people-in-a-queue"]}, {"contest_title": "\u7b2c 58 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 58", "contest_title_slug": "biweekly-contest-58", "contest_id": 441, "contest_start_time": 1628346600, "contest_duration": 5400, "user_num": 2889, "question_slugs": ["delete-characters-to-make-fancy-string", "check-if-move-is-legal", "minimum-total-space-wasted-with-k-resizing-operations", "maximum-product-of-the-length-of-two-palindromic-substrings"]}, {"contest_title": "\u7b2c 59 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 59", "contest_title_slug": "biweekly-contest-59", "contest_id": 448, "contest_start_time": 1629556200, "contest_duration": 5400, "user_num": 3030, "question_slugs": ["minimum-time-to-type-word-using-special-typewriter", "maximum-matrix-sum", "number-of-ways-to-arrive-at-destination", "number-of-ways-to-separate-numbers"]}, {"contest_title": "\u7b2c 60 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 60", "contest_title_slug": "biweekly-contest-60", "contest_id": 461, "contest_start_time": 1630765800, "contest_duration": 5400, "user_num": 2848, "question_slugs": ["find-the-middle-index-in-array", "find-all-groups-of-farmland", "operations-on-tree", "the-number-of-good-subsets"]}, {"contest_title": "\u7b2c 61 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 61", "contest_title_slug": "biweekly-contest-61", "contest_id": 467, "contest_start_time": 1631975400, "contest_duration": 5400, "user_num": 2534, "question_slugs": ["count-number-of-pairs-with-absolute-difference-k", "find-original-array-from-doubled-array", "maximum-earnings-from-taxi", "minimum-number-of-operations-to-make-array-continuous"]}, {"contest_title": "\u7b2c 62 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 62", "contest_title_slug": "biweekly-contest-62", "contest_id": 477, "contest_start_time": 1633185000, "contest_duration": 5400, "user_num": 2619, "question_slugs": ["convert-1d-array-into-2d-array", "number-of-pairs-of-strings-with-concatenation-equal-to-target", "maximize-the-confusion-of-an-exam", "maximum-number-of-ways-to-partition-an-array"]}, {"contest_title": "\u7b2c 63 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 63", "contest_title_slug": "biweekly-contest-63", "contest_id": 484, "contest_start_time": 1634394600, "contest_duration": 5400, "user_num": 2828, "question_slugs": ["minimum-number-of-moves-to-seat-everyone", "remove-colored-pieces-if-both-neighbors-are-the-same-color", "the-time-when-the-network-becomes-idle", "kth-smallest-product-of-two-sorted-arrays"]}, {"contest_title": "\u7b2c 64 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 64", "contest_title_slug": "biweekly-contest-64", "contest_id": 490, "contest_start_time": 1635604200, "contest_duration": 5400, "user_num": 2838, "question_slugs": ["kth-distinct-string-in-an-array", "two-best-non-overlapping-events", "plates-between-candles", "number-of-valid-move-combinations-on-chessboard"]}, {"contest_title": "\u7b2c 65 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 65", "contest_title_slug": "biweekly-contest-65", "contest_id": 497, "contest_start_time": 1636813800, "contest_duration": 5400, "user_num": 2676, "question_slugs": ["check-whether-two-strings-are-almost-equivalent", "walking-robot-simulation-ii", "most-beautiful-item-for-each-query", "maximum-number-of-tasks-you-can-assign"]}, {"contest_title": "\u7b2c 66 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 66", "contest_title_slug": "biweekly-contest-66", "contest_id": 503, "contest_start_time": 1638023400, "contest_duration": 5400, "user_num": 2803, "question_slugs": ["count-common-words-with-one-occurrence", "minimum-number-of-food-buckets-to-feed-the-hamsters", "minimum-cost-homecoming-of-a-robot-in-a-grid", "count-fertile-pyramids-in-a-land"]}, {"contest_title": "\u7b2c 67 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 67", "contest_title_slug": "biweekly-contest-67", "contest_id": 509, "contest_start_time": 1639233000, "contest_duration": 5400, "user_num": 2923, "question_slugs": ["find-subsequence-of-length-k-with-the-largest-sum", "find-good-days-to-rob-the-bank", "detonate-the-maximum-bombs", "sequentially-ordinal-rank-tracker"]}, {"contest_title": "\u7b2c 68 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 68", "contest_title_slug": "biweekly-contest-68", "contest_id": 515, "contest_start_time": 1640442600, "contest_duration": 5400, "user_num": 2854, "question_slugs": ["maximum-number-of-words-found-in-sentences", "find-all-possible-recipes-from-given-supplies", "check-if-a-parentheses-string-can-be-valid", "abbreviating-the-product-of-a-range"]}, {"contest_title": "\u7b2c 69 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 69", "contest_title_slug": "biweekly-contest-69", "contest_id": 521, "contest_start_time": 1641652200, "contest_duration": 5400, "user_num": 3360, "question_slugs": ["capitalize-the-title", "maximum-twin-sum-of-a-linked-list", "longest-palindrome-by-concatenating-two-letter-words", "stamping-the-grid"]}, {"contest_title": "\u7b2c 70 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 70", "contest_title_slug": "biweekly-contest-70", "contest_id": 527, "contest_start_time": 1642861800, "contest_duration": 5400, "user_num": 3640, "question_slugs": ["minimum-cost-of-buying-candies-with-discount", "count-the-hidden-sequences", "k-highest-ranked-items-within-a-price-range", "number-of-ways-to-divide-a-long-corridor"]}, {"contest_title": "\u7b2c 71 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 71", "contest_title_slug": "biweekly-contest-71", "contest_id": 533, "contest_start_time": 1644071400, "contest_duration": 5400, "user_num": 3028, "question_slugs": ["minimum-sum-of-four-digit-number-after-splitting-digits", "partition-array-according-to-given-pivot", "minimum-cost-to-set-cooking-time", "minimum-difference-in-sums-after-removal-of-elements"]}, {"contest_title": "\u7b2c 72 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 72", "contest_title_slug": "biweekly-contest-72", "contest_id": 539, "contest_start_time": 1645281000, "contest_duration": 5400, "user_num": 4400, "question_slugs": ["count-equal-and-divisible-pairs-in-an-array", "find-three-consecutive-integers-that-sum-to-a-given-number", "maximum-split-of-positive-even-integers", "count-good-triplets-in-an-array"]}, {"contest_title": "\u7b2c 73 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 73", "contest_title_slug": "biweekly-contest-73", "contest_id": 545, "contest_start_time": 1646490600, "contest_duration": 5400, "user_num": 5132, "question_slugs": ["most-frequent-number-following-key-in-an-array", "sort-the-jumbled-numbers", "all-ancestors-of-a-node-in-a-directed-acyclic-graph", "minimum-number-of-moves-to-make-palindrome"]}, {"contest_title": "\u7b2c 74 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 74", "contest_title_slug": "biweekly-contest-74", "contest_id": 554, "contest_start_time": 1647700200, "contest_duration": 5400, "user_num": 5442, "question_slugs": ["divide-array-into-equal-pairs", "maximize-number-of-subsequences-in-a-string", "minimum-operations-to-halve-array-sum", "minimum-white-tiles-after-covering-with-carpets"]}, {"contest_title": "\u7b2c 75 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 75", "contest_title_slug": "biweekly-contest-75", "contest_id": 563, "contest_start_time": 1648909800, "contest_duration": 5400, "user_num": 4335, "question_slugs": ["minimum-bit-flips-to-convert-number", "find-triangular-sum-of-an-array", "number-of-ways-to-select-buildings", "sum-of-scores-of-built-strings"]}, {"contest_title": "\u7b2c 76 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 76", "contest_title_slug": "biweekly-contest-76", "contest_id": 572, "contest_start_time": 1650119400, "contest_duration": 5400, "user_num": 4477, "question_slugs": ["find-closest-number-to-zero", "number-of-ways-to-buy-pens-and-pencils", "design-an-atm-machine", "maximum-score-of-a-node-sequence"]}, {"contest_title": "\u7b2c 77 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 77", "contest_title_slug": "biweekly-contest-77", "contest_id": 581, "contest_start_time": 1651329000, "contest_duration": 5400, "user_num": 4211, "question_slugs": ["count-prefixes-of-a-given-string", "minimum-average-difference", "count-unguarded-cells-in-the-grid", "escape-the-spreading-fire"]}, {"contest_title": "\u7b2c 78 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 78", "contest_title_slug": "biweekly-contest-78", "contest_id": 590, "contest_start_time": 1652538600, "contest_duration": 5400, "user_num": 4347, "question_slugs": ["find-the-k-beauty-of-a-number", "number-of-ways-to-split-array", "maximum-white-tiles-covered-by-a-carpet", "substring-with-largest-variance"]}, {"contest_title": "\u7b2c 79 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 79", "contest_title_slug": "biweekly-contest-79", "contest_id": 598, "contest_start_time": 1653748200, "contest_duration": 5400, "user_num": 4250, "question_slugs": ["check-if-number-has-equal-digit-count-and-digit-value", "sender-with-largest-word-count", "maximum-total-importance-of-roads", "booking-concert-tickets-in-groups"]}, {"contest_title": "\u7b2c 80 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 80", "contest_title_slug": "biweekly-contest-80", "contest_id": 608, "contest_start_time": 1654957800, "contest_duration": 5400, "user_num": 3949, "question_slugs": ["strong-password-checker-ii", "successful-pairs-of-spells-and-potions", "match-substring-after-replacement", "count-subarrays-with-score-less-than-k"]}, {"contest_title": "\u7b2c 81 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 81", "contest_title_slug": "biweekly-contest-81", "contest_id": 614, "contest_start_time": 1656167400, "contest_duration": 5400, "user_num": 3847, "question_slugs": ["count-asterisks", "count-unreachable-pairs-of-nodes-in-an-undirected-graph", "maximum-xor-after-operations", "number-of-distinct-roll-sequences"]}, {"contest_title": "\u7b2c 82 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 82", "contest_title_slug": "biweekly-contest-82", "contest_id": 646, "contest_start_time": 1657377000, "contest_duration": 5400, "user_num": 4144, "question_slugs": ["evaluate-boolean-binary-tree", "the-latest-time-to-catch-a-bus", "minimum-sum-of-squared-difference", "subarray-with-elements-greater-than-varying-threshold"]}, {"contest_title": "\u7b2c 83 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 83", "contest_title_slug": "biweekly-contest-83", "contest_id": 652, "contest_start_time": 1658586600, "contest_duration": 5400, "user_num": 4437, "question_slugs": ["best-poker-hand", "number-of-zero-filled-subarrays", "design-a-number-container-system", "shortest-impossible-sequence-of-rolls"]}, {"contest_title": "\u7b2c 84 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 84", "contest_title_slug": "biweekly-contest-84", "contest_id": 658, "contest_start_time": 1659796200, "contest_duration": 5400, "user_num": 4574, "question_slugs": ["merge-similar-items", "count-number-of-bad-pairs", "task-scheduler-ii", "minimum-replacements-to-sort-the-array"]}, {"contest_title": "\u7b2c 85 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 85", "contest_title_slug": "biweekly-contest-85", "contest_id": 668, "contest_start_time": 1661005800, "contest_duration": 5400, "user_num": 4193, "question_slugs": ["minimum-recolors-to-get-k-consecutive-black-blocks", "time-needed-to-rearrange-a-binary-string", "shifting-letters-ii", "maximum-segment-sum-after-removals"]}, {"contest_title": "\u7b2c 86 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 86", "contest_title_slug": "biweekly-contest-86", "contest_id": 688, "contest_start_time": 1662215400, "contest_duration": 5400, "user_num": 4401, "question_slugs": ["find-subarrays-with-equal-sum", "strictly-palindromic-number", "maximum-rows-covered-by-columns", "maximum-number-of-robots-within-budget"]}, {"contest_title": "\u7b2c 87 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 87", "contest_title_slug": "biweekly-contest-87", "contest_id": 703, "contest_start_time": 1663425000, "contest_duration": 5400, "user_num": 4005, "question_slugs": ["count-days-spent-together", "maximum-matching-of-players-with-trainers", "smallest-subarrays-with-maximum-bitwise-or", "minimum-money-required-before-transactions"]}, {"contest_title": "\u7b2c 88 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 88", "contest_title_slug": "biweekly-contest-88", "contest_id": 745, "contest_start_time": 1664634600, "contest_duration": 5400, "user_num": 3905, "question_slugs": ["remove-letter-to-equalize-frequency", "longest-uploaded-prefix", "bitwise-xor-of-all-pairings", "number-of-pairs-satisfying-inequality"]}, {"contest_title": "\u7b2c 89 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 89", "contest_title_slug": "biweekly-contest-89", "contest_id": 755, "contest_start_time": 1665844200, "contest_duration": 5400, "user_num": 3984, "question_slugs": ["number-of-valid-clock-times", "range-product-queries-of-powers", "minimize-maximum-of-array", "create-components-with-same-value"]}, {"contest_title": "\u7b2c 90 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 90", "contest_title_slug": "biweekly-contest-90", "contest_id": 763, "contest_start_time": 1667053800, "contest_duration": 5400, "user_num": 3624, "question_slugs": ["odd-string-difference", "words-within-two-edits-of-dictionary", "destroy-sequential-targets", "next-greater-element-iv"]}, {"contest_title": "\u7b2c 91 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 91", "contest_title_slug": "biweekly-contest-91", "contest_id": 770, "contest_start_time": 1668263400, "contest_duration": 5400, "user_num": 3535, "question_slugs": ["number-of-distinct-averages", "count-ways-to-build-good-strings", "most-profitable-path-in-a-tree", "split-message-based-on-limit"]}, {"contest_title": "\u7b2c 92 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 92", "contest_title_slug": "biweekly-contest-92", "contest_id": 776, "contest_start_time": 1669473000, "contest_duration": 5400, "user_num": 3055, "question_slugs": ["minimum-cuts-to-divide-a-circle", "difference-between-ones-and-zeros-in-row-and-column", "minimum-penalty-for-a-shop", "count-palindromic-subsequences"]}, {"contest_title": "\u7b2c 93 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 93", "contest_title_slug": "biweekly-contest-93", "contest_id": 782, "contest_start_time": 1670682600, "contest_duration": 5400, "user_num": 2929, "question_slugs": ["maximum-value-of-a-string-in-an-array", "maximum-star-sum-of-a-graph", "frog-jump-ii", "minimum-total-cost-to-make-arrays-unequal"]}, {"contest_title": "\u7b2c 94 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 94", "contest_title_slug": "biweekly-contest-94", "contest_id": 789, "contest_start_time": 1671892200, "contest_duration": 5400, "user_num": 2298, "question_slugs": ["maximum-enemy-forts-that-can-be-captured", "reward-top-k-students", "minimize-the-maximum-of-two-arrays", "count-anagrams"]}, {"contest_title": "\u7b2c 95 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 95", "contest_title_slug": "biweekly-contest-95", "contest_id": 798, "contest_start_time": 1673101800, "contest_duration": 5400, "user_num": 2880, "question_slugs": ["categorize-box-according-to-criteria", "find-consecutive-integers-from-a-data-stream", "find-xor-beauty-of-array", "maximize-the-minimum-powered-city"]}, {"contest_title": "\u7b2c 96 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 96", "contest_title_slug": "biweekly-contest-96", "contest_id": 804, "contest_start_time": 1674311400, "contest_duration": 5400, "user_num": 2103, "question_slugs": ["minimum-common-value", "minimum-operations-to-make-array-equal-ii", "maximum-subsequence-score", "check-if-point-is-reachable"]}, {"contest_title": "\u7b2c 97 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 97", "contest_title_slug": "biweekly-contest-97", "contest_id": 810, "contest_start_time": 1675521000, "contest_duration": 5400, "user_num": 2631, "question_slugs": ["separate-the-digits-in-an-array", "maximum-number-of-integers-to-choose-from-a-range-i", "maximize-win-from-two-segments", "disconnect-path-in-a-binary-matrix-by-at-most-one-flip"]}, {"contest_title": "\u7b2c 98 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 98", "contest_title_slug": "biweekly-contest-98", "contest_id": 816, "contest_start_time": 1676730600, "contest_duration": 5400, "user_num": 3250, "question_slugs": ["maximum-difference-by-remapping-a-digit", "minimum-score-by-changing-two-elements", "minimum-impossible-or", "handling-sum-queries-after-update"]}, {"contest_title": "\u7b2c 99 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 99", "contest_title_slug": "biweekly-contest-99", "contest_id": 822, "contest_start_time": 1677940200, "contest_duration": 5400, "user_num": 3467, "question_slugs": ["split-with-minimum-sum", "count-total-number-of-colored-cells", "count-ways-to-group-overlapping-ranges", "count-number-of-possible-root-nodes"]}, {"contest_title": "\u7b2c 100 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 100", "contest_title_slug": "biweekly-contest-100", "contest_id": 832, "contest_start_time": 1679149800, "contest_duration": 5400, "user_num": 3639, "question_slugs": ["distribute-money-to-maximum-children", "maximize-greatness-of-an-array", "find-score-of-an-array-after-marking-all-elements", "minimum-time-to-repair-cars"]}, {"contest_title": "\u7b2c 101 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 101", "contest_title_slug": "biweekly-contest-101", "contest_id": 842, "contest_start_time": 1680359400, "contest_duration": 5400, "user_num": 3353, "question_slugs": ["form-smallest-number-from-two-digit-arrays", "find-the-substring-with-maximum-cost", "make-k-subarray-sums-equal", "shortest-cycle-in-a-graph"]}, {"contest_title": "\u7b2c 102 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 102", "contest_title_slug": "biweekly-contest-102", "contest_id": 853, "contest_start_time": 1681569000, "contest_duration": 5400, "user_num": 3058, "question_slugs": ["find-the-width-of-columns-of-a-grid", "find-the-score-of-all-prefixes-of-an-array", "cousins-in-binary-tree-ii", "design-graph-with-shortest-path-calculator"]}, {"contest_title": "\u7b2c 103 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 103", "contest_title_slug": "biweekly-contest-103", "contest_id": 859, "contest_start_time": 1682778600, "contest_duration": 5400, "user_num": 2299, "question_slugs": ["maximum-sum-with-exactly-k-elements", "find-the-prefix-common-array-of-two-arrays", "maximum-number-of-fish-in-a-grid", "make-array-empty"]}, {"contest_title": "\u7b2c 104 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 104", "contest_title_slug": "biweekly-contest-104", "contest_id": 866, "contest_start_time": 1683988200, "contest_duration": 5400, "user_num": 2519, "question_slugs": ["number-of-senior-citizens", "sum-in-a-matrix", "maximum-or", "power-of-heroes"]}, {"contest_title": "\u7b2c 105 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 105", "contest_title_slug": "biweekly-contest-105", "contest_id": 873, "contest_start_time": 1685197800, "contest_duration": 5400, "user_num": 2604, "question_slugs": ["buy-two-chocolates", "extra-characters-in-a-string", "maximum-strength-of-a-group", "greatest-common-divisor-traversal"]}, {"contest_title": "\u7b2c 106 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 106", "contest_title_slug": "biweekly-contest-106", "contest_id": 879, "contest_start_time": 1686407400, "contest_duration": 5400, "user_num": 2346, "question_slugs": ["check-if-the-number-is-fascinating", "find-the-longest-semi-repetitive-substring", "movement-of-robots", "find-a-good-subset-of-the-matrix"]}, {"contest_title": "\u7b2c 107 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 107", "contest_title_slug": "biweekly-contest-107", "contest_id": 885, "contest_start_time": 1687617000, "contest_duration": 5400, "user_num": 1870, "question_slugs": ["find-maximum-number-of-string-pairs", "construct-the-longest-new-string", "decremental-string-concatenation", "count-zero-request-servers"]}, {"contest_title": "\u7b2c 108 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 108", "contest_title_slug": "biweekly-contest-108", "contest_id": 891, "contest_start_time": 1688826600, "contest_duration": 5400, "user_num": 2349, "question_slugs": ["longest-alternating-subarray", "relocate-marbles", "partition-string-into-minimum-beautiful-substrings", "number-of-black-blocks"]}, {"contest_title": "\u7b2c 109 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 109", "contest_title_slug": "biweekly-contest-109", "contest_id": 897, "contest_start_time": 1690036200, "contest_duration": 5400, "user_num": 2461, "question_slugs": ["check-if-array-is-good", "sort-vowels-in-a-string", "visit-array-positions-to-maximize-score", "ways-to-express-an-integer-as-sum-of-powers"]}, {"contest_title": "\u7b2c 110 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 110", "contest_title_slug": "biweekly-contest-110", "contest_id": 903, "contest_start_time": 1691245800, "contest_duration": 5400, "user_num": 2546, "question_slugs": ["account-balance-after-rounded-purchase", "insert-greatest-common-divisors-in-linked-list", "minimum-seconds-to-equalize-a-circular-array", "minimum-time-to-make-array-sum-at-most-x"]}, {"contest_title": "\u7b2c 111 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 111", "contest_title_slug": "biweekly-contest-111", "contest_id": 909, "contest_start_time": 1692455400, "contest_duration": 5400, "user_num": 2787, "question_slugs": ["count-pairs-whose-sum-is-less-than-target", "make-string-a-subsequence-using-cyclic-increments", "sorting-three-groups", "number-of-beautiful-integers-in-the-range"]}, {"contest_title": "\u7b2c 112 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 112", "contest_title_slug": "biweekly-contest-112", "contest_id": 917, "contest_start_time": 1693665000, "contest_duration": 5400, "user_num": 2900, "question_slugs": ["check-if-strings-can-be-made-equal-with-operations-i", "check-if-strings-can-be-made-equal-with-operations-ii", "maximum-sum-of-almost-unique-subarray", "count-k-subsequences-of-a-string-with-maximum-beauty"]}, {"contest_title": "\u7b2c 113 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 113", "contest_title_slug": "biweekly-contest-113", "contest_id": 923, "contest_start_time": 1694874600, "contest_duration": 5400, "user_num": 3028, "question_slugs": ["minimum-right-shifts-to-sort-the-array", "minimum-array-length-after-pair-removals", "count-pairs-of-points-with-distance-k", "minimum-edge-reversals-so-every-node-is-reachable"]}, {"contest_title": "\u7b2c 114 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 114", "contest_title_slug": "biweekly-contest-114", "contest_id": 929, "contest_start_time": 1696084200, "contest_duration": 5400, "user_num": 2406, "question_slugs": ["minimum-operations-to-collect-elements", "minimum-number-of-operations-to-make-array-empty", "split-array-into-maximum-number-of-subarrays", "maximum-number-of-k-divisible-components"]}, {"contest_title": "\u7b2c 115 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 115", "contest_title_slug": "biweekly-contest-115", "contest_id": 935, "contest_start_time": 1697293800, "contest_duration": 5400, "user_num": 2809, "question_slugs": ["last-visited-integers", "longest-unequal-adjacent-groups-subsequence-i", "longest-unequal-adjacent-groups-subsequence-ii", "count-of-sub-multisets-with-bounded-sum"]}, {"contest_title": "\u7b2c 116 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 116", "contest_title_slug": "biweekly-contest-116", "contest_id": 941, "contest_start_time": 1698503400, "contest_duration": 5400, "user_num": 2904, "question_slugs": ["subarrays-distinct-element-sum-of-squares-i", "minimum-number-of-changes-to-make-binary-string-beautiful", "length-of-the-longest-subsequence-that-sums-to-target", "subarrays-distinct-element-sum-of-squares-ii"]}, {"contest_title": "\u7b2c 117 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 117", "contest_title_slug": "biweekly-contest-117", "contest_id": 949, "contest_start_time": 1699713000, "contest_duration": 5400, "user_num": 2629, "question_slugs": ["distribute-candies-among-children-i", "distribute-candies-among-children-ii", "number-of-strings-which-can-be-rearranged-to-contain-substring", "maximum-spending-after-buying-items"]}, {"contest_title": "\u7b2c 118 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 118", "contest_title_slug": "biweekly-contest-118", "contest_id": 955, "contest_start_time": 1700922600, "contest_duration": 5400, "user_num": 2425, "question_slugs": ["find-words-containing-character", "maximize-area-of-square-hole-in-grid", "minimum-number-of-coins-for-fruits", "find-maximum-non-decreasing-array-length"]}, {"contest_title": "\u7b2c 119 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 119", "contest_title_slug": "biweekly-contest-119", "contest_id": 961, "contest_start_time": 1702132200, "contest_duration": 5400, "user_num": 2472, "question_slugs": ["find-common-elements-between-two-arrays", "remove-adjacent-almost-equal-characters", "length-of-longest-subarray-with-at-most-k-frequency", "number-of-possible-sets-of-closing-branches"]}, {"contest_title": "\u7b2c 120 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 120", "contest_title_slug": "biweekly-contest-120", "contest_id": 967, "contest_start_time": 1703341800, "contest_duration": 5400, "user_num": 2542, "question_slugs": ["count-the-number-of-incremovable-subarrays-i", "find-polygon-with-the-largest-perimeter", "count-the-number-of-incremovable-subarrays-ii", "find-number-of-coins-to-place-in-tree-nodes"]}, {"contest_title": "\u7b2c 121 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 121", "contest_title_slug": "biweekly-contest-121", "contest_id": 973, "contest_start_time": 1704551400, "contest_duration": 5400, "user_num": 2218, "question_slugs": ["smallest-missing-integer-greater-than-sequential-prefix-sum", "minimum-number-of-operations-to-make-array-xor-equal-to-k", "minimum-number-of-operations-to-make-x-and-y-equal", "count-the-number-of-powerful-integers"]}, {"contest_title": "\u7b2c 122 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 122", "contest_title_slug": "biweekly-contest-122", "contest_id": 979, "contest_start_time": 1705761000, "contest_duration": 5400, "user_num": 2547, "question_slugs": ["divide-an-array-into-subarrays-with-minimum-cost-i", "find-if-array-can-be-sorted", "minimize-length-of-array-using-operations", "divide-an-array-into-subarrays-with-minimum-cost-ii"]}, {"contest_title": "\u7b2c 123 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 123", "contest_title_slug": "biweekly-contest-123", "contest_id": 985, "contest_start_time": 1706970600, "contest_duration": 5400, "user_num": 2209, "question_slugs": ["type-of-triangle", "find-the-number-of-ways-to-place-people-i", "maximum-good-subarray-sum", "find-the-number-of-ways-to-place-people-ii"]}, {"contest_title": "\u7b2c 124 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 124", "contest_title_slug": "biweekly-contest-124", "contest_id": 991, "contest_start_time": 1708180200, "contest_duration": 5400, "user_num": 1861, "question_slugs": ["maximum-number-of-operations-with-the-same-score-i", "apply-operations-to-make-string-empty", "maximum-number-of-operations-with-the-same-score-ii", "maximize-consecutive-elements-in-an-array-after-modification"]}, {"contest_title": "\u7b2c 125 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 125", "contest_title_slug": "biweekly-contest-125", "contest_id": 997, "contest_start_time": 1709389800, "contest_duration": 5400, "user_num": 2599, "question_slugs": ["minimum-operations-to-exceed-threshold-value-i", "minimum-operations-to-exceed-threshold-value-ii", "count-pairs-of-connectable-servers-in-a-weighted-tree-network", "find-the-maximum-sum-of-node-values"]}, {"contest_title": "\u7b2c 126 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 126", "contest_title_slug": "biweekly-contest-126", "contest_id": 1003, "contest_start_time": 1710599400, "contest_duration": 5400, "user_num": 3234, "question_slugs": ["find-the-sum-of-encrypted-integers", "mark-elements-on-array-by-performing-queries", "replace-question-marks-in-string-to-minimize-its-value", "find-the-sum-of-the-power-of-all-subsequences"]}, {"contest_title": "\u7b2c 127 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 127", "contest_title_slug": "biweekly-contest-127", "contest_id": 1010, "contest_start_time": 1711809000, "contest_duration": 5400, "user_num": 2951, "question_slugs": ["shortest-subarray-with-or-at-least-k-i", "minimum-levels-to-gain-more-points", "shortest-subarray-with-or-at-least-k-ii", "find-the-sum-of-subsequence-powers"]}, {"contest_title": "\u7b2c 128 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 128", "contest_title_slug": "biweekly-contest-128", "contest_id": 1017, "contest_start_time": 1713018600, "contest_duration": 5400, "user_num": 2654, "question_slugs": ["score-of-a-string", "minimum-rectangles-to-cover-points", "minimum-time-to-visit-disappearing-nodes", "find-the-number-of-subarrays-where-boundary-elements-are-maximum"]}, {"contest_title": "\u7b2c 129 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 129", "contest_title_slug": "biweekly-contest-129", "contest_id": 1023, "contest_start_time": 1714228200, "contest_duration": 5400, "user_num": 2511, "question_slugs": ["make-a-square-with-the-same-color", "right-triangles", "find-all-possible-stable-binary-arrays-i", "find-all-possible-stable-binary-arrays-ii"]}, {"contest_title": "\u7b2c 130 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 130", "contest_title_slug": "biweekly-contest-130", "contest_id": 1029, "contest_start_time": 1715437800, "contest_duration": 5400, "user_num": 2604, "question_slugs": ["check-if-grid-satisfies-conditions", "maximum-points-inside-the-square", "minimum-substring-partition-of-equal-character-frequency", "find-products-of-elements-of-big-array"]}, {"contest_title": "\u7b2c 131 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 131", "contest_title_slug": "biweekly-contest-131", "contest_id": 1035, "contest_start_time": 1716647400, "contest_duration": 5400, "user_num": 2537, "question_slugs": ["find-the-xor-of-numbers-which-appear-twice", "find-occurrences-of-an-element-in-an-array", "find-the-number-of-distinct-colors-among-the-balls", "block-placement-queries"]}, {"contest_title": "\u7b2c 132 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 132", "contest_title_slug": "biweekly-contest-132", "contest_id": 1042, "contest_start_time": 1717857000, "contest_duration": 5400, "user_num": 2457, "question_slugs": ["clear-digits", "find-the-first-player-to-win-k-games-in-a-row", "find-the-maximum-length-of-a-good-subsequence-i", "find-the-maximum-length-of-a-good-subsequence-ii"]}, {"contest_title": "\u7b2c 133 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 133", "contest_title_slug": "biweekly-contest-133", "contest_id": 1048, "contest_start_time": 1719066600, "contest_duration": 5400, "user_num": 2326, "question_slugs": ["find-minimum-operations-to-make-all-elements-divisible-by-three", "minimum-operations-to-make-binary-array-elements-equal-to-one-i", "minimum-operations-to-make-binary-array-elements-equal-to-one-ii", "count-the-number-of-inversions"]}, {"contest_title": "\u7b2c 134 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 134", "contest_title_slug": "biweekly-contest-134", "contest_id": 1055, "contest_start_time": 1720276200, "contest_duration": 5400, "user_num": 2411, "question_slugs": ["alternating-groups-i", "maximum-points-after-enemy-battles", "alternating-groups-ii", "number-of-subarrays-with-and-value-of-k"]}, {"contest_title": "\u7b2c 135 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 135", "contest_title_slug": "biweekly-contest-135", "contest_id": 1061, "contest_start_time": 1721485800, "contest_duration": 5400, "user_num": 2260, "question_slugs": ["find-the-winning-player-in-coin-game", "minimum-length-of-string-after-operations", "minimum-array-changes-to-make-differences-equal", "maximum-score-from-grid-operations"]}, {"contest_title": "\u7b2c 136 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 136", "contest_title_slug": "biweekly-contest-136", "contest_id": 1068, "contest_start_time": 1722695400, "contest_duration": 5400, "user_num": 2418, "question_slugs": ["find-the-number-of-winning-players", "minimum-number-of-flips-to-make-binary-grid-palindromic-i", "minimum-number-of-flips-to-make-binary-grid-palindromic-ii", "time-taken-to-mark-all-nodes"]}, {"contest_title": "\u7b2c 137 \u573a\u53cc\u5468\u8d5b", "contest_title_en": "Biweekly Contest 137", "contest_title_slug": "biweekly-contest-137", "contest_id": 1074, "contest_start_time": 1723905000, "contest_duration": 5400, "user_num": 2198, "question_slugs": ["find-the-power-of-k-size-subarrays-i", "find-the-power-of-k-size-subarrays-ii", "maximum-value-sum-by-placing-three-rooks-i", "maximum-value-sum-by-placing-three-rooks-ii"]}] \ No newline at end of file diff --git a/solution/main.py b/solution/main.py index 366e4aa9decf..df5a3b35eaa5 100644 --- a/solution/main.py +++ b/solution/main.py @@ -299,7 +299,16 @@ def format_time(timestamp: int) -> str: def get_data(self, retry: int = 3): try: - res = requests.get(self.contest_url, timeout=6, verify=False).json() + print(self.contest_url) + headers = { + 'User-Agent': user_agent, + 'Host': 'leetcode.cn', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + } + res = requests.get( + self.contest_url, timeout=6, verify=False, headers=headers + ) + res = res.json() if not res or "error" in res or not res["questions"]: return {} questions = res["questions"] @@ -360,6 +369,7 @@ def get_contests(fetch_new=True) -> List: if c.contest_title_slug in d: continue contest_data = c.get_data(retry=10) + time.sleep(1) if not contest_data: cnt += 1 if cnt > 2: @@ -453,7 +463,7 @@ def run(): ) or spider.get_question_detail_en(slug, retry=8) if not detail: continue - time.sleep(0.3) + time.sleep(1) question_details[slug] = Spider.format_question_detail( detail, str(qid).zfill(4) ) diff --git a/solution/template.md b/solution/template.md index 74fde530156f..49f37e677b5b 100644 --- a/solution/template.md +++ b/solution/template.md @@ -195,10 +195,10 @@ If you want to estimate your score changes after the contest ends, you can visit - - {} + + # [{}. {}]({}) [English Version]({}) @@ -219,27 +219,9 @@ If you want to estimate your score changes after the contest ends, you can visit -#### Python3 - -```python - -``` - -#### Java - -```java - -``` - -#### C++ - -```cpp - -``` - -#### Go +#### Shell -```go +```bash ``` @@ -279,27 +261,9 @@ If you want to estimate your score changes after the contest ends, you can visit -#### Python3 - -```python - -``` - -#### Java - -```java - -``` - -#### C++ - -```cpp +#### Shell -``` - -#### Go - -```go +```bash ``` diff --git a/solution/util.py b/solution/util.py index 5ac1bc7db1a9..1187e07f648c 100644 --- a/solution/util.py +++ b/solution/util.py @@ -54,9 +54,7 @@ def load_ratings(): category_readme_cn = load_template("category_readme_template") category_readme_en = load_template("category_readme_template_en") -category_dict = { - "Database": "数据库", -} +category_dict = {"Database": "数据库"} def load_cookies() -> Tuple[str, str]: @@ -177,11 +175,11 @@ def generate_question_readme(result): readme_template_cn, readme_template_en = select_templates(category) paid_only = " 🔒" if item["paid_only"] else "" rating_item = rating_dict.get(str(item["frontend_question_id"])) - rating = rating_item.get('Rating', 0) if rating_item else '' + rating = rating_item.get("Rating", 0) if rating_item else "" source = ( - rating_item.get('ContestID_zh') + " " + rating_item.get('ProblemIndex') + rating_item.get("ContestID_zh") + " " + rating_item.get("ProblemIndex") if rating_item - else '' + else "" ) # 生成 metadata """ @@ -195,20 +193,22 @@ def generate_question_readme(result): edit_url: https://github.com/doocs/leetcode/edit/main/solution/0000-0099/0001.Two%20Sum/README.md --- """ + cat = category_dict.get(category, category) + cat = cat.title() if cat and cat[0].islower() else cat metadata = { - "tags": item["tags_cn"], + "tags": item["tags_cn"] or [cat], "difficulty": item["difficulty_cn"], "rating": rating, "comments": True, "edit_url": f'https://github.com/doocs/leetcode/edit/main{item["relative_path_cn"]}', "source": source, } - if not item['tags_cn']: - metadata.pop('tags') + if not item["tags_cn"] or metadata["tags"] == ["Algorithms"]: + metadata.pop("tags") if not rating: - metadata.pop('rating') + metadata.pop("rating") if not source: - metadata.pop('source') + metadata.pop("source") yaml_metadata = yaml.dump( metadata, default_flow_style=False, allow_unicode=True ) @@ -228,24 +228,26 @@ def generate_question_readme(result): ) source = ( - rating_item.get('ContestID_en') + " " + rating_item.get('ProblemIndex') + rating_item.get("ContestID_en") + " " + rating_item.get("ProblemIndex") if rating_item - else '' + else "" ) + + cat = category.title() if category and category[0].islower() else category metadata = { - "tags": item["tags_en"], + "tags": item["tags_en"] or [cat], "difficulty": item["difficulty_en"], "rating": rating, "comments": True, "edit_url": f'https://github.com/doocs/leetcode/edit/main{item["relative_path_en"]}', "source": source, } - if not item['tags_cn']: - metadata.pop('tags') + if not item["tags_cn"] or metadata["tags"] == ["Algorithms"]: + metadata.pop("tags") if not rating: - metadata.pop('rating') + metadata.pop("rating") if not source: - metadata.pop('source') + metadata.pop("source") yaml_metadata = yaml.dump( metadata, default_flow_style=False, allow_unicode=True ) @@ -363,27 +365,29 @@ def refresh(result): readme_template_cn, readme_template_en = select_templates(category) rating_item = rating_dict.get(str(front_question_id)) - rating = int(rating_item.get('Rating', 0)) if rating_item else '' + rating = int(rating_item.get("Rating", 0)) if rating_item else "" source = ( - rating_item.get('ContestID_zh') + " " + rating_item.get('ProblemIndex') + rating_item.get("ContestID_zh") + " " + rating_item.get("ProblemIndex") if rating_item - else '' + else "" ) - + cat = category_dict.get(category, category) + cat = cat.title() if cat and cat[0].islower() else cat metadata = { - "tags": question["tags_cn"], + "tags": question["tags_cn"] or [cat], "difficulty": question["difficulty_cn"], "rating": rating, "comments": True, "edit_url": f'https://github.com/doocs/leetcode/edit/main{question["relative_path_cn"]}', "source": source, } - if not question['tags_cn']: - metadata.pop('tags') + + if (not question["tags_cn"] and not cat) or metadata["tags"] == ["Algorithms"]: + metadata.pop("tags") if not rating: - metadata.pop('rating') + metadata.pop("rating") if not source: - metadata.pop('source') + metadata.pop("source") yaml_metadata = yaml.dump( metadata, default_flow_style=False, allow_unicode=True ) @@ -402,25 +406,28 @@ def refresh(result): ) source = ( - rating_item.get('ContestID_en') + " " + rating_item.get('ProblemIndex') + rating_item.get("ContestID_en") + " " + rating_item.get("ProblemIndex") if rating_item - else '' + else "" ) + cat = category.title() if category and category[0].islower() else category metadata = { - "tags": question["tags_en"], + "tags": question["tags_en"] or [cat], "difficulty": question["difficulty_en"], "rating": rating, "comments": True, "edit_url": f'https://github.com/doocs/leetcode/edit/main{question["relative_path_en"]}', "source": source, } - if not question['tags_en']: - metadata.pop('tags') + if (not question["tags_en"] and not [category]) or metadata["tags"] == [ + "Algorithms" + ]: + metadata.pop("tags") if not rating: - metadata.pop('rating') + metadata.pop("rating") if not source: - metadata.pop('source') + metadata.pop("source") yaml_metadata = yaml.dump( metadata, default_flow_style=False, allow_unicode=True )