diff --git a/.gitignore b/.gitignore index 4d29575..6cb7809 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # production /build +/spider # misc .DS_Store diff --git a/README.md b/README.md index 9231e7a..3bb69c8 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,10 @@ |---App.js 主逻辑都在这里 ``` -## 构建 + +## 构建 +- npm run auto 自动生成问题解答json - npm run build - 然后将 build 文件夹的内容添加到扩展中即可,具体方式见上面的`功能介绍`。 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a2c5a1d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,14644 @@ +{ + "name": "leetcode-cheat", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ant-design/colors": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/@ant-design/colors/download/@ant-design/colors-3.2.2.tgz", + "integrity": "sha1-WtQ9YZ6RHzSI66wwPWBuZqhCOQM=", + "requires": { + "tinycolor2": "^1.4.1" + } + }, + "@ant-design/css-animation": { + "version": "1.7.2", + "resolved": "https://registry.npm.taobao.org/@ant-design/css-animation/download/@ant-design/css-animation-1.7.2.tgz", + "integrity": "sha1-TuXS7A+3zAp4tE4cgmKL1GIax+M=" + }, + "@ant-design/icons": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/@ant-design/icons/download/@ant-design/icons-4.2.1.tgz", + "integrity": "sha1-bz6l2Yq3ggcuTpy7cPJeRAOuGms=", + "requires": { + "@ant-design/colors": "^3.1.0", + "@ant-design/icons-svg": "^4.0.0", + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "insert-css": "^2.0.0", + "rc-util": "^5.0.1" + } + }, + "@ant-design/icons-svg": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/@ant-design/icons-svg/download/@ant-design/icons-svg-4.1.0.tgz", + "integrity": "sha1-SAsCX0sg73/o9H1KSEbk/uhOoGw=" + }, + "@ant-design/react-slick": { + "version": "0.26.1", + "resolved": "https://registry.npm.taobao.org/@ant-design/react-slick/download/@ant-design/react-slick-0.26.1.tgz?cache=0&sync_timestamp=1589251404552&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Freact-slick%2Fdownload%2F%40ant-design%2Freact-slick-0.26.1.tgz", + "integrity": "sha1-FGKtE0KoOvUbfqTuCuHXbZHRs9M=", + "requires": { + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "lodash": "^4.17.15", + "resize-observer-polyfill": "^1.5.0" + } + }, + "@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.10.1.tgz?cache=0&sync_timestamp=1590617298858&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.10.1.tgz", + "integrity": "sha1-1UgcUJXaocV+FuVMb5GYRDr7Sf8=", + "requires": { + "@babel/highlight": "^7.10.1" + } + }, + "@babel/compat-data": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/compat-data/download/@babel/compat-data-7.10.1.tgz", + "integrity": "sha1-sQhf/nLNF78sDueQ/An5YmARsts=", + "requires": { + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "@babel/core": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/core/download/@babel/core-7.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcore%2Fdownload%2F%40babel%2Fcore-7.9.0.tgz", + "integrity": "sha1-rJd7U4t34TL/cG87ik260JwDxW4=", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@babel/generator": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.10.2.tgz?cache=0&sync_timestamp=1590868955737&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fgenerator%2Fdownload%2F%40babel%2Fgenerator-7.10.2.tgz", + "integrity": "sha1-D6W1sjiduL/fzDSStVHuIPXdaak=", + "requires": { + "@babel/types": "^7.10.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.10.1.tgz?cache=0&sync_timestamp=1590617495113&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-annotate-as-pure%2Fdownload%2F%40babel%2Fhelper-annotate-as-pure-7.10.1.tgz", + "integrity": "sha1-9tCKzG9wu9WbQ2JiVT+y4lmhomg=", + "requires": { + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-builder-binary-assignment-operator-visitor%2Fdownload%2F%40babel%2Fhelper-builder-binary-assignment-operator-visitor-7.10.1.tgz", + "integrity": "sha1-DsfZvoF0k0UyZh+HeD6xjXIpAFk=", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-builder-react-jsx": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-builder-react-jsx/download/@babel/helper-builder-react-jsx-7.10.1.tgz", + "integrity": "sha1-oyfwz5g69VVHAbEhXeVKAZ8JtTI=", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-builder-react-jsx-experimental": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-builder-react-jsx-experimental/download/@babel/helper-builder-react-jsx-experimental-7.10.1.tgz", + "integrity": "sha1-mn1YrRhNOsO6+xpFLOwrrX5KC8g=", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.1", + "@babel/helper-module-imports": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.10.2.tgz?cache=0&sync_timestamp=1590869015082&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-compilation-targets%2Fdownload%2F%40babel%2Fhelper-compilation-targets-7.10.2.tgz", + "integrity": "sha1-oX2XI7bix1ApnSoU1GN8dpNtgoU=", + "requires": { + "@babel/compat-data": "^7.10.1", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.10.2.tgz?cache=0&sync_timestamp=1590869014139&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-create-class-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-class-features-plugin-7.10.2.tgz", + "integrity": "sha1-dHQpV3DyF9vPKIv3Vy6yE9tG7mc=", + "requires": { + "@babel/helper-function-name": "^7.10.1", + "@babel/helper-member-expression-to-functions": "^7.10.1", + "@babel/helper-optimise-call-expression": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/helper-replace-supers": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.10.1.tgz?cache=0&sync_timestamp=1590617496931&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-create-regexp-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-regexp-features-plugin-7.10.1.tgz", + "integrity": "sha1-G4/uqxWUy8+/OrWju8q6wEaO/b0=", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.1", + "@babel/helper-regex": "^7.10.1", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-define-map/download/@babel/helper-define-map-7.10.1.tgz?cache=0&sync_timestamp=1590617497687&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-define-map%2Fdownload%2F%40babel%2Fhelper-define-map-7.10.1.tgz", + "integrity": "sha1-XmnugwhkhHDdeQDRWcBEwQKFIh0=", + "requires": { + "@babel/helper-function-name": "^7.10.1", + "@babel/types": "^7.10.1", + "lodash": "^4.17.13" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.10.1.tgz?cache=0&sync_timestamp=1590617498698&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-explode-assignable-expression%2Fdownload%2F%40babel%2Fhelper-explode-assignable-expression-7.10.1.tgz", + "integrity": "sha1-6ddjBe4RYspGc1euJd+U8XmvK34=", + "requires": { + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-function-name": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-function-name/download/@babel/helper-function-name-7.10.1.tgz?cache=0&sync_timestamp=1590617298411&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-function-name%2Fdownload%2F%40babel%2Fhelper-function-name-7.10.1.tgz", + "integrity": "sha1-kr1jgpv8khWsqdne+oX1a1OUVPQ=", + "requires": { + "@babel/helper-get-function-arity": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.10.1.tgz", + "integrity": "sha1-cwM5CoG6fLWWE4laGSuThQ43P30=", + "requires": { + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-hoist-variables/download/@babel/helper-hoist-variables-7.10.1.tgz?cache=0&sync_timestamp=1590617495977&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-hoist-variables%2Fdownload%2F%40babel%2Fhelper-hoist-variables-7.10.1.tgz", + "integrity": "sha1-fnfILl3K4evxIxdMOFqq2/eH0Hc=", + "requires": { + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.10.1.tgz?cache=0&sync_timestamp=1590617494746&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-member-expression-to-functions%2Fdownload%2F%40babel%2Fhelper-member-expression-to-functions-7.10.1.tgz", + "integrity": "sha1-Qyln/X4SpK/vZsRofUyiK8BFbxU=", + "requires": { + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-module-imports/download/@babel/helper-module-imports-7.10.1.tgz?cache=0&sync_timestamp=1590617391715&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-module-imports%2Fdownload%2F%40babel%2Fhelper-module-imports-7.10.1.tgz", + "integrity": "sha1-3TMb1FvMxWbOdwBOnQX+F63ROHY=", + "requires": { + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-module-transforms": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.10.1.tgz?cache=0&sync_timestamp=1590617408279&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-module-transforms%2Fdownload%2F%40babel%2Fhelper-module-transforms-7.10.1.tgz", + "integrity": "sha1-JOLwjuaDLGCxV7sJNshr73IQxiI=", + "requires": { + "@babel/helper-module-imports": "^7.10.1", + "@babel/helper-replace-supers": "^7.10.1", + "@babel/helper-simple-access": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.10.1.tgz?cache=0&sync_timestamp=1590617495485&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-optimise-call-expression%2Fdownload%2F%40babel%2Fhelper-optimise-call-expression-7.10.1.tgz", + "integrity": "sha1-tKHyVhhwzhJHzt2wKjhg+pbXJUM=", + "requires": { + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.10.1.tgz?cache=0&sync_timestamp=1590617525191&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-plugin-utils%2Fdownload%2F%40babel%2Fhelper-plugin-utils-7.10.1.tgz", + "integrity": "sha1-7Fpc8O7JJbZsYFgDKLEiwBIwoSc=" + }, + "@babel/helper-regex": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-regex/download/@babel/helper-regex-7.10.1.tgz", + "integrity": "sha1-Ahzxp7qZgi+ZMiKgAcw/7IMlW5Y=", + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-remap-async-to-generator/download/@babel/helper-remap-async-to-generator-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-remap-async-to-generator%2Fdownload%2F%40babel%2Fhelper-remap-async-to-generator-7.10.1.tgz", + "integrity": "sha1-utaqpP85zo1Lgsyq4L/g99u19DI=", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.1", + "@babel/helper-wrap-function": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-replace-supers%2Fdownload%2F%40babel%2Fhelper-replace-supers-7.10.1.tgz", + "integrity": "sha1-7GhZ0gxdgIf2otxOAU23Iol18T0=", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.1", + "@babel/helper-optimise-call-expression": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-simple-access/download/@babel/helper-simple-access-7.10.1.tgz?cache=0&sync_timestamp=1590617400870&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-simple-access%2Fdownload%2F%40babel%2Fhelper-simple-access-7.10.1.tgz", + "integrity": "sha1-CPt+Iqzp64Mm9+OSChwgUvE9hR4=", + "requires": { + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.10.1.tgz", + "integrity": "sha1-xvS+HLwV46ho5MZKF9XTHXVNo18=", + "requires": { + "@babel/types": "^7.10.1" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.10.1.tgz?cache=0&sync_timestamp=1590617286975&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.10.1.tgz", + "integrity": "sha1-V3CwwagmxPU/Xt5eFTFj4DGOlLU=" + }, + "@babel/helper-wrap-function": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.10.1.tgz?cache=0&sync_timestamp=1590617498978&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-wrap-function%2Fdownload%2F%40babel%2Fhelper-wrap-function-7.10.1.tgz", + "integrity": "sha1-lW0TENZpYlenr9R+TELf2l387ck=", + "requires": { + "@babel/helper-function-name": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/helpers": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/helpers/download/@babel/helpers-7.10.1.tgz?cache=0&sync_timestamp=1590617407271&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelpers%2Fdownload%2F%40babel%2Fhelpers-7.10.1.tgz", + "integrity": "sha1-poJ7fLl1ydnO9f1h2Rn2DYhEqXM=", + "requires": { + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.10.1.tgz", + "integrity": "sha1-hB0Ji6YTuhpCeis4PXnjVVLDiuA=", + "requires": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.10.2.tgz?cache=0&sync_timestamp=1590869015720&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.10.2.tgz", + "integrity": "sha1-hxgH8QRCuS/5fkeDubVPagyoEtA=" + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-async-generator-functions%2Fdownload%2F%40babel%2Fplugin-proposal-async-generator-functions-7.10.1.tgz", + "integrity": "sha1-aRGvW6LmFcT/PEl/4vR7Nb9tflU=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/helper-remap-async-to-generator": "^7.10.1", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.10.1.tgz?cache=0&sync_timestamp=1590617500094&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-class-properties%2Fdownload%2F%40babel%2Fplugin-proposal-class-properties-7.10.1.tgz", + "integrity": "sha1-BGvH9lULsI2b0dTwYPX1pPEIfgE=", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-decorators/download/@babel/plugin-proposal-decorators-7.8.3.tgz?cache=0&sync_timestamp=1590617499010&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-decorators%2Fdownload%2F%40babel%2Fplugin-proposal-decorators-7.8.3.tgz", + "integrity": "sha1-IVaGCrZcWr8GjD9nBCGEBBBmVD4=", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-decorators": "^7.8.3" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-dynamic-import/download/@babel/plugin-proposal-dynamic-import-7.10.1.tgz", + "integrity": "sha1-42l53B3Dtz9taBb8SVHaI2NIjvA=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.10.1.tgz?cache=0&sync_timestamp=1590617487236&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-json-strings%2Fdownload%2F%40babel%2Fplugin-proposal-json-strings-7.10.1.tgz", + "integrity": "sha1-seaR7iTGUbWl4yITIisjeXNK/wk=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz", + "integrity": "sha1-AtyiFnOEL/L+djrCU3d/I16bv3g=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.10.1.tgz?cache=0&sync_timestamp=1590617647710&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-numeric-separator%2Fdownload%2F%40babel%2Fplugin-proposal-numeric-separator-7.10.1.tgz", + "integrity": "sha1-qaOLw094vf2YHnkcJ8b9zsR4wSM=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-numeric-separator": "^7.10.1" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.10.1.tgz", + "integrity": "sha1-y6RJCKyfFCZQtKZbiqBr80eNX7Y=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.1" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.10.1.tgz?cache=0&sync_timestamp=1590617524388&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-optional-catch-binding%2Fdownload%2F%40babel%2Fplugin-proposal-optional-catch-binding-7.10.1.tgz", + "integrity": "sha1-yfhtmTBfn6UxtWj/WrjJZLiyI9I=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.10.1.tgz?cache=0&sync_timestamp=1590617587766&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-optional-chaining%2Fdownload%2F%40babel%2Fplugin-proposal-optional-chaining-7.10.1.tgz", + "integrity": "sha1-FfXW0icIYpRRqRvij4+sxVsOgYw=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-private-methods/download/@babel/plugin-proposal-private-methods-7.10.1.tgz", + "integrity": "sha1-7YXoBYqw/jCcP0SOXhtzyonNtZg=", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-unicode-property-regex%2Fdownload%2F%40babel%2Fplugin-proposal-unicode-property-regex-7.10.1.tgz", + "integrity": "sha1-3AT+sl4t1wwSsF1oAZDhOPosDG8=", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha1-qYP7Gusuw/btBCohD2QOkOeG/g0=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-class-properties/download/@babel/plugin-syntax-class-properties-7.10.1.tgz", + "integrity": "sha1-1bwGRZE99bF61+2g+iMIMwveNMU=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-decorators/download/@babel/plugin-syntax-decorators-7.10.1.tgz?cache=0&sync_timestamp=1590617485835&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-decorators%2Fdownload%2F%40babel%2Fplugin-syntax-decorators-7.10.1.tgz", + "integrity": "sha1-FrhpxL6vyaRCVlFHvafOCWe9TxM=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha1-Yr+Ysto80h1iYVT8lu5bPLaOrLM=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-flow/download/@babel/plugin-syntax-flow-7.10.1.tgz", + "integrity": "sha1-zUu8pi+0Arq6yxdPZPhzQxDXQvA=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha1-AcohtmjNghjJ5kDLbdiMVBKyyWo=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.10.1.tgz?cache=0&sync_timestamp=1590617488045&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-jsx%2Fdownload%2F%40babel%2Fplugin-syntax-jsx-7.10.1.tgz", + "integrity": "sha1-CuNxE0pCuR1UGP6zyMjUPhVl0to=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-nullish-coalescing-operator/download/@babel/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha1-Fn7XA2iIYIH3S1w2xlqIwDtm0ak=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-numeric-separator/download/@babel/plugin-syntax-numeric-separator-7.10.1.tgz", + "integrity": "sha1-JXYe50ELyM+XMnunQe6U5KYbfZk=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha1-YOIl7cvZimQDMqLnLdPmbxr1WHE=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha1-YRGiZbz7Ag6579D9/X0mQCue1sE=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha1-T2nCq5UWfgGAzVM2YT+MV4j31Io=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-top-level-await/download/@babel/plugin-syntax-top-level-await-7.10.1.tgz", + "integrity": "sha1-i4cz+MVzl7PqpH3bqIQVhtyu82I=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-typescript/download/@babel/plugin-syntax-typescript-7.10.1.tgz", + "integrity": "sha1-XoK8J7tCArk7lJsCnmmdtTZzOBA=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.10.1.tgz?cache=0&sync_timestamp=1590617488714&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-arrow-functions%2Fdownload%2F%40babel%2Fplugin-transform-arrow-functions-7.10.1.tgz", + "integrity": "sha1-y17jo28IY8BurQtAm0zEOoibKVs=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-async-to-generator/download/@babel/plugin-transform-async-to-generator-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-async-to-generator%2Fdownload%2F%40babel%2Fplugin-transform-async-to-generator-7.10.1.tgz", + "integrity": "sha1-5RU+saPgKPeRlO2Kekv1X4YrIGI=", + "requires": { + "@babel/helper-module-imports": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/helper-remap-async-to-generator": "^7.10.1" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.10.1.tgz", + "integrity": "sha1-FGhW51bVSyD/8UuBlFaz4BgguF0=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.10.1.tgz?cache=0&sync_timestamp=1590617489049&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-block-scoping%2Fdownload%2F%40babel%2Fplugin-transform-block-scoping-7.10.1.tgz", + "integrity": "sha1-Rwktico0WBFFHNDcXZFgWYJwXV4=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "lodash": "^4.17.13" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-classes%2Fdownload%2F%40babel%2Fplugin-transform-classes-7.10.1.tgz", + "integrity": "sha1-bhHdbE365w9UBICkcCR37XZtcz8=", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.1", + "@babel/helper-define-map": "^7.10.1", + "@babel/helper-function-name": "^7.10.1", + "@babel/helper-optimise-call-expression": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/helper-replace-supers": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.10.1.tgz?cache=0&sync_timestamp=1590617489784&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-computed-properties%2Fdownload%2F%40babel%2Fplugin-transform-computed-properties-7.10.1.tgz", + "integrity": "sha1-Wao5kGRCnWTc5c9275uQtyRevQc=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.10.1.tgz?cache=0&sync_timestamp=1590617489227&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-destructuring%2Fdownload%2F%40babel%2Fplugin-transform-destructuring-7.10.1.tgz", + "integrity": "sha1-q9WOUTN4Fco6IqM2uF9iuZjnGQc=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-dotall-regex/download/@babel/plugin-transform-dotall-regex-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-dotall-regex%2Fdownload%2F%40babel%2Fplugin-transform-dotall-regex-7.10.1.tgz", + "integrity": "sha1-kguf7C14u1frtkpkTVwrpnzBBO4=", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-duplicate-keys/download/@babel/plugin-transform-duplicate-keys-7.10.1.tgz?cache=0&sync_timestamp=1590617489638&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-duplicate-keys%2Fdownload%2F%40babel%2Fplugin-transform-duplicate-keys-7.10.1.tgz", + "integrity": "sha1-yQCnk76wlrydTQqdDN4ZUY/8g7k=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-exponentiation-operator%2Fdownload%2F%40babel%2Fplugin-transform-exponentiation-operator-7.10.1.tgz", + "integrity": "sha1-J5wxFnVqYN1ub15Ii6eVfbnFnrM=", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-flow-strip-types/download/@babel/plugin-transform-flow-strip-types-7.9.0.tgz", + "integrity": "sha1-ijU4qkBDTgALj0Sjxcmscim9I5I=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-flow": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.10.1.tgz?cache=0&sync_timestamp=1590617490212&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-for-of%2Fdownload%2F%40babel%2Fplugin-transform-for-of-7.10.1.tgz", + "integrity": "sha1-/wERl4TrDuMiWOhkYVe6JQH8/aU=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.10.1.tgz", + "integrity": "sha1-TtRv1uHY/eKi7HsDxm2FPSySQn0=", + "requires": { + "@babel/helper-function-name": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.10.1.tgz", + "integrity": "sha1-V5T42oKEayLk5mMeoWWLznCOtGo=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-member-expression-literals/download/@babel/plugin-transform-member-expression-literals-7.10.1.tgz", + "integrity": "sha1-kDR8ujG8pvOUs/e9ldK7/Z/OLzk=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-amd%2Fdownload%2F%40babel%2Fplugin-transform-modules-amd-7.10.1.tgz", + "integrity": "sha1-ZZUOjgV5fr0v5TK5bhn8VIKh1So=", + "requires": { + "@babel/helper-module-transforms": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-commonjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-commonjs-7.10.1.tgz", + "integrity": "sha1-1f9LRBPtl//e2ZlhBW4fuYD7kwE=", + "requires": { + "@babel/helper-module-transforms": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/helper-simple-access": "^7.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-systemjs/download/@babel/plugin-transform-modules-systemjs-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-systemjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-systemjs-7.10.1.tgz", + "integrity": "sha1-mWLksKxqry4gQxraPY7HIILL/7Y=", + "requires": { + "@babel/helper-hoist-variables": "^7.10.1", + "@babel/helper-module-transforms": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-umd%2Fdownload%2F%40babel%2Fplugin-transform-modules-umd-7.10.1.tgz", + "integrity": "sha1-6ggJEf/G6yGEClGXo57eTuZ7FZU=", + "requires": { + "@babel/helper-module-transforms": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", + "integrity": "sha1-oqcr/6ICrA4tBQav0JOcXsvEjGw=", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.10.1.tgz", + "integrity": "sha1-buQaXmSNp2MuIrb7VAEuh/YS8yQ=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.10.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-object-super%2Fdownload%2F%40babel%2Fplugin-transform-object-super-7.10.1.tgz", + "integrity": "sha1-LjAWsK2/JimDvw1RIdZ2pe2cT94=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/helper-replace-supers": "^7.10.1" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.10.1.tgz", + "integrity": "sha1-slk4o8X64DVBRKcgsHsydm9oPd0=", + "requires": { + "@babel/helper-get-function-arity": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-property-literals/download/@babel/plugin-transform-property-literals-7.10.1.tgz", + "integrity": "sha1-z/xzFSGSMO2B3FPkYlv4aBW2BQ0=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-constant-elements/download/@babel/plugin-transform-react-constant-elements-7.10.1.tgz?cache=0&sync_timestamp=1590617579457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-constant-elements%2Fdownload%2F%40babel%2Fplugin-transform-react-constant-elements-7.10.1.tgz", + "integrity": "sha1-x/EXpUZXy6P50yAS4FD8iZgt+eE=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-display-name/download/@babel/plugin-transform-react-display-name-7.10.1.tgz", + "integrity": "sha1-5qM/bUjfshPdpeAH0Mf/graj2O8=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx/download/@babel/plugin-transform-react-jsx-7.10.1.tgz?cache=0&sync_timestamp=1590617592587&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-7.10.1.tgz", + "integrity": "sha1-kfVEJIuhMUht7LXZgG2mpuGaKJY=", + "requires": { + "@babel/helper-builder-react-jsx": "^7.10.1", + "@babel/helper-builder-react-jsx-experimental": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-jsx": "^7.10.1" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-development/download/@babel/plugin-transform-react-jsx-development-7.10.1.tgz?cache=0&sync_timestamp=1590617591473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx-development%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-development-7.10.1.tgz", + "integrity": "sha1-GsYwDYso7zge5I5v7EMMw4BHt/M=", + "requires": { + "@babel/helper-builder-react-jsx-experimental": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-jsx": "^7.10.1" + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-self/download/@babel/plugin-transform-react-jsx-self-7.10.1.tgz", + "integrity": "sha1-IhQ+FDiNcuuIZJYGu55G9CG8OCE=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-jsx": "^7.10.1" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-source/download/@babel/plugin-transform-react-jsx-source-7.10.1.tgz", + "integrity": "sha1-MNs9TuPN67smqCqXA2c3FHd6QnM=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-jsx": "^7.10.1" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-pure-annotations/download/@babel/plugin-transform-react-pure-annotations-7.10.1.tgz", + "integrity": "sha1-9efHVdPnYU1Mkm4UT1AWSKUne3A=", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.10.1.tgz?cache=0&sync_timestamp=1590617523541&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-regenerator%2Fdownload%2F%40babel%2Fplugin-transform-regenerator-7.10.1.tgz", + "integrity": "sha1-EOF1y+e9tjzJs5+bP4I8XHxcVJA=", + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-reserved-words/download/@babel/plugin-transform-reserved-words-7.10.1.tgz", + "integrity": "sha1-D8ECcxK00cMnaleJDIrjvMC2SoY=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-runtime/download/@babel/plugin-transform-runtime-7.9.0.tgz", + "integrity": "sha1-RUaMCudMwTIE4dOx9M5u6DJYrws=", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.10.1.tgz?cache=0&sync_timestamp=1590617494359&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-shorthand-properties%2Fdownload%2F%40babel%2Fplugin-transform-shorthand-properties-7.10.1.tgz", + "integrity": "sha1-6LVPI4ocy65ILE3OlGGArnsxQ/M=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.10.1.tgz", + "integrity": "sha1-DG1higxEYaJ0QYRgooycz1I5p8g=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.10.1.tgz?cache=0&sync_timestamp=1590617492839&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-sticky-regex%2Fdownload%2F%40babel%2Fplugin-transform-sticky-regex-7.10.1.tgz", + "integrity": "sha1-kPyJt1JiKL7ZhCz/NYgnCno5OwA=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/helper-regex": "^7.10.1" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.10.1.tgz", + "integrity": "sha1-kUx7f0dSxXDqAFU7QoTa2AcOhig=", + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-typeof-symbol/download/@babel/plugin-transform-typeof-symbol-7.10.1.tgz?cache=0&sync_timestamp=1590619661466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-typeof-symbol%2Fdownload%2F%40babel%2Fplugin-transform-typeof-symbol-7.10.1.tgz", + "integrity": "sha1-YMAjm2mWXRZrgKhN5zFcG8fguw4=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-typescript/download/@babel/plugin-transform-typescript-7.10.1.tgz", + "integrity": "sha1-LFTa6iMfYCRoaG2fqnbxgqlFB6Y=", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-syntax-typescript": "^7.10.1" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-unicode-escapes/download/@babel/plugin-transform-unicode-escapes-7.10.1.tgz?cache=0&sync_timestamp=1590617592403&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-unicode-escapes%2Fdownload%2F%40babel%2Fplugin-transform-unicode-escapes-7.10.1.tgz", + "integrity": "sha1-rdD4SD2rYFcNngPOzvbAI6qMmUA=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.10.1.tgz", + "integrity": "sha1-a1jyrqe2jfN6xQJdnIh1JEOmtD8=", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1" + } + }, + "@babel/preset-env": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.10.2.tgz?cache=0&sync_timestamp=1590868958159&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.10.2.tgz", + "integrity": "sha1-cVkw8s+Fc7CSgAXuVivtUvtl/fs=", + "requires": { + "@babel/compat-data": "^7.10.1", + "@babel/helper-compilation-targets": "^7.10.2", + "@babel/helper-module-imports": "^7.10.1", + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-proposal-async-generator-functions": "^7.10.1", + "@babel/plugin-proposal-class-properties": "^7.10.1", + "@babel/plugin-proposal-dynamic-import": "^7.10.1", + "@babel/plugin-proposal-json-strings": "^7.10.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1", + "@babel/plugin-proposal-numeric-separator": "^7.10.1", + "@babel/plugin-proposal-object-rest-spread": "^7.10.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.1", + "@babel/plugin-proposal-optional-chaining": "^7.10.1", + "@babel/plugin-proposal-private-methods": "^7.10.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.1", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.1", + "@babel/plugin-transform-arrow-functions": "^7.10.1", + "@babel/plugin-transform-async-to-generator": "^7.10.1", + "@babel/plugin-transform-block-scoped-functions": "^7.10.1", + "@babel/plugin-transform-block-scoping": "^7.10.1", + "@babel/plugin-transform-classes": "^7.10.1", + "@babel/plugin-transform-computed-properties": "^7.10.1", + "@babel/plugin-transform-destructuring": "^7.10.1", + "@babel/plugin-transform-dotall-regex": "^7.10.1", + "@babel/plugin-transform-duplicate-keys": "^7.10.1", + "@babel/plugin-transform-exponentiation-operator": "^7.10.1", + "@babel/plugin-transform-for-of": "^7.10.1", + "@babel/plugin-transform-function-name": "^7.10.1", + "@babel/plugin-transform-literals": "^7.10.1", + "@babel/plugin-transform-member-expression-literals": "^7.10.1", + "@babel/plugin-transform-modules-amd": "^7.10.1", + "@babel/plugin-transform-modules-commonjs": "^7.10.1", + "@babel/plugin-transform-modules-systemjs": "^7.10.1", + "@babel/plugin-transform-modules-umd": "^7.10.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.10.1", + "@babel/plugin-transform-object-super": "^7.10.1", + "@babel/plugin-transform-parameters": "^7.10.1", + "@babel/plugin-transform-property-literals": "^7.10.1", + "@babel/plugin-transform-regenerator": "^7.10.1", + "@babel/plugin-transform-reserved-words": "^7.10.1", + "@babel/plugin-transform-shorthand-properties": "^7.10.1", + "@babel/plugin-transform-spread": "^7.10.1", + "@babel/plugin-transform-sticky-regex": "^7.10.1", + "@babel/plugin-transform-template-literals": "^7.10.1", + "@babel/plugin-transform-typeof-symbol": "^7.10.1", + "@babel/plugin-transform-unicode-escapes": "^7.10.1", + "@babel/plugin-transform-unicode-regex": "^7.10.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.10.2", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "@babel/preset-modules": { + "version": "0.1.3", + "resolved": "https://registry.npm.taobao.org/@babel/preset-modules/download/@babel/preset-modules-0.1.3.tgz", + "integrity": "sha1-EyQrU7XvjIg8PPfd3VWzbOgPvHI=", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/preset-react/download/@babel/preset-react-7.10.1.tgz", + "integrity": "sha1-4quK6aNj7DB7k2WJ8H7XUxkt4EE=", + "requires": { + "@babel/helper-plugin-utils": "^7.10.1", + "@babel/plugin-transform-react-display-name": "^7.10.1", + "@babel/plugin-transform-react-jsx": "^7.10.1", + "@babel/plugin-transform-react-jsx-development": "^7.10.1", + "@babel/plugin-transform-react-jsx-self": "^7.10.1", + "@babel/plugin-transform-react-jsx-source": "^7.10.1", + "@babel/plugin-transform-react-pure-annotations": "^7.10.1" + } + }, + "@babel/preset-typescript": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/preset-typescript/download/@babel/preset-typescript-7.9.0.tgz", + "integrity": "sha1-h3BacrHw1Z3yHBeffD0u9LFs4ZI=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-typescript": "^7.9.0" + } + }, + "@babel/runtime": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.10.2.tgz", + "integrity": "sha1-0QPyHyYCSX04NIoy4AhjfVBtuDk=", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/runtime-corejs3/download/@babel/runtime-corejs3-7.10.2.tgz", + "integrity": "sha1-NRF5fd+aPW885GuZzINRhIF+qk4=", + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.10.1.tgz", + "integrity": "sha1-4WcVSpTLXxSyjcWPU1bSFi9TmBE=", + "requires": { + "@babel/code-frame": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "@babel/traverse": { + "version": "7.10.1", + "resolved": "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.10.1.tgz", + "integrity": "sha1-u87zAx5BUqbAtQFH9JWN9Uyg3Sc=", + "requires": { + "@babel/code-frame": "^7.10.1", + "@babel/generator": "^7.10.1", + "@babel/helper-function-name": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.10.2", + "resolved": "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.10.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.10.2.tgz", + "integrity": "sha1-MCg74xytDb9vsAvUBkHKDqZ1Fy0=", + "requires": { + "@babel/helper-validator-identifier": "^7.10.1", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/@cnakazawa/watch/download/@cnakazawa/watch-1.0.4.tgz", + "integrity": "sha1-+GSuhQBND8q29QvpFBxNo2jRZWo=", + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/@csstools/convert-colors/download/@csstools/convert-colors-1.4.0.tgz", + "integrity": "sha1-rUldxBsS511YjG24uYNPCPoTHrc=" + }, + "@csstools/normalize.css": { + "version": "10.1.0", + "resolved": "https://registry.npm.taobao.org/@csstools/normalize.css/download/@csstools/normalize.css-10.1.0.tgz", + "integrity": "sha1-8JULuhiBlRLUL3GX5WxRiqSRzxg=" + }, + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npm.taobao.org/@hapi/address/download/@hapi/address-2.1.4.tgz?cache=0&sync_timestamp=1584171913757&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Faddress%2Fdownload%2F%40hapi%2Faddress-2.1.4.tgz", + "integrity": "sha1-XWftQ/P9QaadS5/3tW58DR0KgeU=" + }, + "@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/@hapi/bourne/download/@hapi/bourne-1.3.2.tgz?cache=0&sync_timestamp=1578129065689&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Fbourne%2Fdownload%2F%40hapi%2Fbourne-1.3.2.tgz", + "integrity": "sha1-CnCVreoGckPOMoPhtWuKj0U7JCo=" + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npm.taobao.org/@hapi/hoek/download/@hapi/hoek-8.5.1.tgz?cache=0&sync_timestamp=1583989992589&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Fhoek%2Fdownload%2F%40hapi%2Fhoek-8.5.1.tgz", + "integrity": "sha1-/elgZMpEbeyMVajC8TCVewcMbgY=" + }, + "@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npm.taobao.org/@hapi/joi/download/@hapi/joi-15.1.1.tgz?cache=0&sync_timestamp=1584145124617&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Fjoi%2Fdownload%2F%40hapi%2Fjoi-15.1.1.tgz", + "integrity": "sha1-xnW4pxKW8Cgz+NbSQ7NMV7jOGdc=", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npm.taobao.org/@hapi/topo/download/@hapi/topo-3.1.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Ftopo%2Fdownload%2F%40hapi%2Ftopo-3.1.6.tgz", + "integrity": "sha1-aNk1+j6uf91asNf5U/MgXYsr/Ck=", + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/console/download/@jest/console-24.9.0.tgz", + "integrity": "sha1-ebG8Bvt0qM+wHL3t+UVYSxuXB/A=", + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/core/download/@jest/core-24.9.0.tgz", + "integrity": "sha1-LOzNC5MYH5xIUOdPKprUPTUTacQ=", + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-3.2.0.tgz", + "integrity": "sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s=" + } + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/environment/download/@jest/environment-24.9.0.tgz", + "integrity": "sha1-IeOvotZcBYbL1svv4gi6+t5Eqxg=", + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/fake-timers/download/@jest/fake-timers-24.9.0.tgz", + "integrity": "sha1-uj5r8O7NCaY2BJiWQ00wZjZUDJM=", + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/reporters/download/@jest/reporters-24.9.0.tgz", + "integrity": "sha1-hmYO/44rlmHQQqjpigKLjWMaW0M=", + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/source-map/download/@jest/source-map-24.9.0.tgz", + "integrity": "sha1-DiY6lEML5LQdpoPMwea//ioZFxQ=", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-3.1.0.tgz", + "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=" + } + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/test-result/download/@jest/test-result-24.9.0.tgz", + "integrity": "sha1-EXluiqnb+I6gJXV7MVJZWtBroMo=", + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/test-sequencer/download/@jest/test-sequencer-24.9.0.tgz", + "integrity": "sha1-+PM081tiWk8vNV8v5+YDba0uazE=", + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/transform/download/@jest/transform-24.9.0.tgz", + "integrity": "sha1-SuJ2iyllU/rasJ6ewRlUPJCxbFY=", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-24.9.0.tgz", + "integrity": "sha1-Y8smy3UA0Gnlo4lEGnxqtekJ/Fk=", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/@mrmlnc/readdir-enhanced/download/@mrmlnc/readdir-enhanced-2.2.1.tgz", + "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=", + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/@nodelib/fs.stat/download/@nodelib/fs.stat-1.1.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40nodelib%2Ffs.stat%2Fdownload%2F%40nodelib%2Ffs.stat-1.1.3.tgz", + "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=" + }, + "@sheerun/mutationobserver-shim": { + "version": "0.3.3", + "resolved": "https://registry.npm.taobao.org/@sheerun/mutationobserver-shim/download/@sheerun/mutationobserver-shim-0.3.3.tgz", + "integrity": "sha1-VAXujkRO0hLbROeTUfDHClgqriU=" + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-add-jsx-attribute/download/@svgr/babel-plugin-add-jsx-attribute-4.2.0.tgz", + "integrity": "sha1-2ty2IYUDUy1ohLIQ5/PFAsqqRLE=" + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-remove-jsx-attribute/download/@svgr/babel-plugin-remove-jsx-attribute-4.2.0.tgz", + "integrity": "sha1-KXVQuajAxzN76hK9/IqAu2b4Wrw=" + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-remove-jsx-empty-expression/download/@svgr/babel-plugin-remove-jsx-empty-expression-4.2.0.tgz", + "integrity": "sha1-wZYwLz5o6ragXpivnKhXC8ExMcc=" + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-replace-jsx-attribute-value/download/@svgr/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz", + "integrity": "sha1-MQ7Ad13oCKai5P1CaMJF/XNMEWU=" + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "4.3.3", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-svg-dynamic-title/download/@svgr/babel-plugin-svg-dynamic-title-4.3.3.tgz", + "integrity": "sha1-LN7ddH5bGyntTCQeRiVqrIEQ3ZM=" + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-svg-em-dimensions/download/@svgr/babel-plugin-svg-em-dimensions-4.2.0.tgz", + "integrity": "sha1-mpR5HJoogQjSCp0sxkysgg8UE5E=" + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-transform-react-native-svg/download/@svgr/babel-plugin-transform-react-native-svg-4.2.0.tgz", + "integrity": "sha1-FRSHMihDNZocqGsho4Ff0hqItxc=" + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-plugin-transform-svg-component/download/@svgr/babel-plugin-transform-svg-component-4.2.0.tgz", + "integrity": "sha1-Xx4viGsshcZ+dtpC8Pa+Gxdntpc=" + }, + "@svgr/babel-preset": { + "version": "4.3.3", + "resolved": "https://registry.npm.taobao.org/@svgr/babel-preset/download/@svgr/babel-preset-4.3.3.tgz", + "integrity": "sha1-p12MLyAqwOV3Tmv8Fl0CizmhMWw=", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^4.2.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^4.2.0", + "@svgr/babel-plugin-svg-dynamic-title": "^4.3.3", + "@svgr/babel-plugin-svg-em-dimensions": "^4.2.0", + "@svgr/babel-plugin-transform-react-native-svg": "^4.2.0", + "@svgr/babel-plugin-transform-svg-component": "^4.2.0" + } + }, + "@svgr/core": { + "version": "4.3.3", + "resolved": "https://registry.npm.taobao.org/@svgr/core/download/@svgr/core-4.3.3.tgz", + "integrity": "sha1-s3uJ1bdX3Gbox0FW0Aw2gzjSQpM=", + "requires": { + "@svgr/plugin-jsx": "^4.3.3", + "camelcase": "^5.3.1", + "cosmiconfig": "^5.2.1" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "4.3.2", + "resolved": "https://registry.npm.taobao.org/@svgr/hast-util-to-babel-ast/download/@svgr/hast-util-to-babel-ast-4.3.2.tgz", + "integrity": "sha1-HVoIL3uSnvjx9XiVAjj2MOFFMrg=", + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@svgr/plugin-jsx": { + "version": "4.3.3", + "resolved": "https://registry.npm.taobao.org/@svgr/plugin-jsx/download/@svgr/plugin-jsx-4.3.3.tgz", + "integrity": "sha1-4rqRPb376FJSo02xAavH69UJkvo=", + "requires": { + "@babel/core": "^7.4.5", + "@svgr/babel-preset": "^4.3.3", + "@svgr/hast-util-to-babel-ast": "^4.3.2", + "svg-parser": "^2.0.0" + } + }, + "@svgr/plugin-svgo": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/@svgr/plugin-svgo/download/@svgr/plugin-svgo-4.3.1.tgz", + "integrity": "sha1-2qwKPYcuP1WTXGWI3TcDNoZenjI=", + "requires": { + "cosmiconfig": "^5.2.1", + "merge-deep": "^3.0.2", + "svgo": "^1.2.2" + } + }, + "@svgr/webpack": { + "version": "4.3.3", + "resolved": "https://registry.npm.taobao.org/@svgr/webpack/download/@svgr/webpack-4.3.3.tgz", + "integrity": "sha1-E8wkI789/y1JTxaxfrfqy4aJUBc=", + "requires": { + "@babel/core": "^7.4.5", + "@babel/plugin-transform-react-constant-elements": "^7.0.0", + "@babel/preset-env": "^7.4.5", + "@babel/preset-react": "^7.0.0", + "@svgr/core": "^4.3.3", + "@svgr/plugin-jsx": "^4.3.3", + "@svgr/plugin-svgo": "^4.3.1", + "loader-utils": "^1.2.3" + } + }, + "@testing-library/dom": { + "version": "6.16.0", + "resolved": "https://registry.npm.taobao.org/@testing-library/dom/download/@testing-library/dom-6.16.0.tgz", + "integrity": "sha1-BK2iftdK1MDw2YShJFuymx/ZC6k=", + "requires": { + "@babel/runtime": "^7.8.4", + "@sheerun/mutationobserver-shim": "^0.3.2", + "@types/testing-library__dom": "^6.12.1", + "aria-query": "^4.0.2", + "dom-accessibility-api": "^0.3.0", + "pretty-format": "^25.1.0", + "wait-for-expect": "^3.0.2" + }, + "dependencies": { + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-25.5.0.tgz", + "integrity": "sha1-TWpHk/e5WZ/DaAh3uFapfbzPKp0=", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.5", + "resolved": "https://registry.npm.taobao.org/@types/yargs/download/@types/yargs-15.0.5.tgz?cache=0&sync_timestamp=1589406630222&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-15.0.5.tgz", + "integrity": "sha1-lH6aZWFIO97prf/Jg+kaaQKvi3k=", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.2.1.tgz", + "integrity": "sha1-kK51xCTQCNJiTFvynq0xd+v881k=", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-3.0.0.tgz?cache=0&sync_timestamp=1585815759944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-3.0.0.tgz", + "integrity": "sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ=", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=" + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npm.taobao.org/pretty-format/download/pretty-format-25.5.0.tgz?cache=0&sync_timestamp=1588675385734&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-format%2Fdownload%2Fpretty-format-25.5.0.tgz", + "integrity": "sha1-eHPB13T2gsNLjUi2dDor8qxVeRo=", + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.1.0.tgz", + "integrity": "sha1-aOMlkd9z4lrRxLSRCKLsUHliv9E=", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/jest-dom": { + "version": "4.2.4", + "resolved": "https://registry.npm.taobao.org/@testing-library/jest-dom/download/@testing-library/jest-dom-4.2.4.tgz", + "integrity": "sha1-AN+gy92DfZo8Kn8/CiSOpue4l0I=", + "requires": { + "@babel/runtime": "^7.5.1", + "chalk": "^2.4.1", + "css": "^2.2.3", + "css.escape": "^1.5.1", + "jest-diff": "^24.0.0", + "jest-matcher-utils": "^24.0.0", + "lodash": "^4.17.11", + "pretty-format": "^24.0.0", + "redent": "^3.0.0" + } + }, + "@testing-library/react": { + "version": "9.5.0", + "resolved": "https://registry.npm.taobao.org/@testing-library/react/download/@testing-library/react-9.5.0.tgz", + "integrity": "sha1-cVMWVaeJC2Hnehs5RS++3wRyyl4=", + "requires": { + "@babel/runtime": "^7.8.4", + "@testing-library/dom": "^6.15.0", + "@types/testing-library__react": "^9.1.2" + } + }, + "@testing-library/user-event": { + "version": "7.2.1", + "resolved": "https://registry.npm.taobao.org/@testing-library/user-event/download/@testing-library/user-event-7.2.1.tgz", + "integrity": "sha1-KtToRBdaNzjLnnBkvl6gcLiGOhw=" + }, + "@types/babel__core": { + "version": "7.1.8", + "resolved": "https://registry.npm.taobao.org/@types/babel__core/download/@types/babel__core-7.1.8.tgz", + "integrity": "sha1-BX9yWso2QfSfwRx6h6neXsWIpdc=", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.1", + "resolved": "https://registry.npm.taobao.org/@types/babel__generator/download/@types/babel__generator-7.6.1.tgz", + "integrity": "sha1-SQF2ezl+hxGuuZ3405bXunt/DgQ=", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npm.taobao.org/@types/babel__template/download/@types/babel__template-7.0.2.tgz", + "integrity": "sha1-T/Y9a1Lt2sHee5daUiPtMuzqkwc=", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.12", + "resolved": "https://registry.npm.taobao.org/@types/babel__traverse/download/@types/babel__traverse-7.0.12.tgz?cache=0&sync_timestamp=1591055771569&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fbabel__traverse%2Fdownload%2F%40types%2Fbabel__traverse-7.0.12.tgz", + "integrity": "sha1-IvSaAo5pRlOQ+HuxA+vWG9CGuPU=", + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/@types/color-name/download/@types/color-name-1.1.1.tgz", + "integrity": "sha1-HBJhu+qhCoBVu8XYq4S3sq/IRqA=" + }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/@types/eslint-visitor-keys/download/@types/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha1-HuMNeVRMqE1o1LPNsK9PIFZj3S0=" + }, + "@types/glob": { + "version": "7.1.2", + "resolved": "https://registry.npm.taobao.org/@types/glob/download/@types/glob-7.1.2.tgz", + "integrity": "sha1-BsomUhNTpUXZSgrcdPOKWdIyyYc=", + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/@types/istanbul-lib-coverage/download/@types/istanbul-lib-coverage-2.0.2.tgz", + "integrity": "sha1-edeni61CGfTAPWVXocctnKa6YtU=" + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/@types/istanbul-lib-report/download/@types/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha1-wUwk8Y6oGQwRjudWK3/5mjZVJoY=", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/@types/istanbul-reports/download/@types/istanbul-reports-1.1.2.tgz", + "integrity": "sha1-6HXMaJ5HvOVJ7IHz315vbxHPrrI=", + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npm.taobao.org/@types/json-schema/download/@types/json-schema-7.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fjson-schema%2Fdownload%2F%40types%2Fjson-schema-7.0.4.tgz", + "integrity": "sha1-OP1z3f2bVaux4bLtV4y1W9e30zk=" + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/@types/minimatch/download/@types/minimatch-3.0.3.tgz", + "integrity": "sha1-PcoOPzOyAPx9ETnAzZbBJoyt/Z0=" + }, + "@types/node": { + "version": "14.0.11", + "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.0.11.tgz", + "integrity": "sha1-YdSIbiQk2nO3slVH9Z/ctTTBZaM=" + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/@types/parse-json/download/@types/parse-json-4.0.0.tgz?cache=0&sync_timestamp=1588201631592&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fparse-json%2Fdownload%2F%40types%2Fparse-json-4.0.0.tgz", + "integrity": "sha1-L4u0QUNNFjs1+4/9zNcTiSf/uMA=" + }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npm.taobao.org/@types/prop-types/download/@types/prop-types-15.7.3.tgz?cache=0&sync_timestamp=1588201821986&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fprop-types%2Fdownload%2F%40types%2Fprop-types-15.7.3.tgz", + "integrity": "sha1-KrDV2i5YFflLC51LldHl8kOrLKc=" + }, + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npm.taobao.org/@types/q/download/@types/q-1.5.4.tgz", + "integrity": "sha1-FZJUFOCtLNdlv+9YhC9+JqesyyQ=" + }, + "@types/react": { + "version": "16.9.35", + "resolved": "https://registry.npm.taobao.org/@types/react/download/@types/react-16.9.35.tgz?cache=0&sync_timestamp=1589187921077&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Freact%2Fdownload%2F%40types%2Freact-16.9.35.tgz", + "integrity": "sha1-oIMNFy6Krdm9QXCboigaMSS702g=", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-dom": { + "version": "16.9.8", + "resolved": "https://registry.npm.taobao.org/@types/react-dom/download/@types/react-dom-16.9.8.tgz", + "integrity": "sha1-/kweEd/GcVVzPfpqplEItJcctCM=", + "requires": { + "@types/react": "*" + } + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/@types/stack-utils/download/@types/stack-utils-1.0.1.tgz", + "integrity": "sha1-CoUdO9lkmPolwzq3J47TvWXwbD4=" + }, + "@types/testing-library__dom": { + "version": "6.14.0", + "resolved": "https://registry.npm.taobao.org/@types/testing-library__dom/download/@types/testing-library__dom-6.14.0.tgz", + "integrity": "sha1-Gu3oMctO1KOYRI31osVLVKNlZE4=", + "requires": { + "pretty-format": "^24.3.0" + } + }, + "@types/testing-library__react": { + "version": "9.1.3", + "resolved": "https://registry.npm.taobao.org/@types/testing-library__react/download/@types/testing-library__react-9.1.3.tgz", + "integrity": "sha1-NeymHMbqkjVDeW8WA0iCoWA9cwI=", + "requires": { + "@types/react-dom": "*", + "@types/testing-library__dom": "*", + "pretty-format": "^25.1.0" + }, + "dependencies": { + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-25.5.0.tgz", + "integrity": "sha1-TWpHk/e5WZ/DaAh3uFapfbzPKp0=", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.5", + "resolved": "https://registry.npm.taobao.org/@types/yargs/download/@types/yargs-15.0.5.tgz?cache=0&sync_timestamp=1589406630222&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-15.0.5.tgz", + "integrity": "sha1-lH6aZWFIO97prf/Jg+kaaQKvi3k=", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.2.1.tgz", + "integrity": "sha1-kK51xCTQCNJiTFvynq0xd+v881k=", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-3.0.0.tgz?cache=0&sync_timestamp=1585815759944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-3.0.0.tgz", + "integrity": "sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ=", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=" + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npm.taobao.org/pretty-format/download/pretty-format-25.5.0.tgz?cache=0&sync_timestamp=1588675385734&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-format%2Fdownload%2Fpretty-format-25.5.0.tgz", + "integrity": "sha1-eHPB13T2gsNLjUi2dDor8qxVeRo=", + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.1.0.tgz", + "integrity": "sha1-aOMlkd9z4lrRxLSRCKLsUHliv9E=", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@types/yargs": { + "version": "13.0.9", + "resolved": "https://registry.npm.taobao.org/@types/yargs/download/@types/yargs-13.0.9.tgz?cache=0&sync_timestamp=1589406630222&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-13.0.9.tgz", + "integrity": "sha1-RAKOl0NDx6/POWDxorEJnDmnteE=", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npm.taobao.org/@types/yargs-parser/download/@types/yargs-parser-15.0.0.tgz?cache=0&sync_timestamp=1588204007425&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs-parser%2Fdownload%2F%40types%2Fyargs-parser-15.0.0.tgz", + "integrity": "sha1-yz+fdBhp4gzOMw/765JxWQSDiC0=" + }, + "@typescript-eslint/eslint-plugin": { + "version": "2.34.0", + "resolved": "https://registry.npm.taobao.org/@typescript-eslint/eslint-plugin/download/@typescript-eslint/eslint-plugin-2.34.0.tgz", + "integrity": "sha1-b4zopGx96kpvHRcdK7j7rm2sK+k=", + "requires": { + "@typescript-eslint/experimental-utils": "2.34.0", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.34.0", + "resolved": "https://registry.npm.taobao.org/@typescript-eslint/experimental-utils/download/@typescript-eslint/experimental-utils-2.34.0.tgz", + "integrity": "sha1-01JLZEzbQO687KZ/jPPkzJyPmA8=", + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.34.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "2.34.0", + "resolved": "https://registry.npm.taobao.org/@typescript-eslint/parser/download/@typescript-eslint/parser-2.34.0.tgz", + "integrity": "sha1-UCUmMMoxloVCDpo5ygX+GFola8g=", + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.34.0", + "@typescript-eslint/typescript-estree": "2.34.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "2.34.0", + "resolved": "https://registry.npm.taobao.org/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-2.34.0.tgz", + "integrity": "sha1-FK62NTs57wcyzH8bgoUpSTfPN9U=", + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.3.2.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.2.tgz", + "integrity": "sha1-YElisFK4HtB4aq6EOJ/7pw/9OTg=" + } + } + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ast/download/@webassemblyjs/ast-1.8.5.tgz", + "integrity": "sha1-UbHF/mV2o0lTv0slPfnw1JDZ41k=", + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/floating-point-hex-parser/download/@webassemblyjs/floating-point-hex-parser-1.8.5.tgz?cache=0&sync_timestamp=1580600186633&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Ffloating-point-hex-parser%2Fdownload%2F%40webassemblyjs%2Ffloating-point-hex-parser-1.8.5.tgz", + "integrity": "sha1-G6kmopI2E+3OSW/VsC6M6KX0lyE=" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-api-error/download/@webassemblyjs/helper-api-error-1.8.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-api-error%2Fdownload%2F%40webassemblyjs%2Fhelper-api-error-1.8.5.tgz", + "integrity": "sha1-xJ2tIvZFInxe22EL25aX8aq3Ifc=" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-buffer/download/@webassemblyjs/helper-buffer-1.8.5.tgz", + "integrity": "sha1-/qk+Qphj3V5DOFVfQikjhaZT8gQ=" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-code-frame/download/@webassemblyjs/helper-code-frame-1.8.5.tgz", + "integrity": "sha1-mnQP9I4/qjAisd/1RCPfmqKTwl4=", + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-fsm/download/@webassemblyjs/helper-fsm-1.8.5.tgz", + "integrity": "sha1-ugt9Oz9+RzPaYFnJMyJ12GBwJFI=" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-module-context/download/@webassemblyjs/helper-module-context-1.8.5.tgz", + "integrity": "sha1-3vS5knsBAdyMu9jR7bW3ucguskU=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-bytecode/download/@webassemblyjs/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha1-U3p1Dt31weky83RCBlUckcG5PmE=" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/helper-wasm-section/download/@webassemblyjs/helper-wasm-section-1.8.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fhelper-wasm-section%2Fdownload%2F%40webassemblyjs%2Fhelper-wasm-section-1.8.5.tgz", + "integrity": "sha1-dMpqa8vhnlCjtrRihH5pUD5r/L8=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/ieee754/download/@webassemblyjs/ieee754-1.8.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fieee754%2Fdownload%2F%40webassemblyjs%2Fieee754-1.8.5.tgz", + "integrity": "sha1-cSMp2+8kDza/V70ve4+5v0FUQh4=", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/leb128/download/@webassemblyjs/leb128-1.8.5.tgz", + "integrity": "sha1-BE7es06mefPgTNT9mCTV41dnrhA=", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/utf8/download/@webassemblyjs/utf8-1.8.5.tgz", + "integrity": "sha1-qL87XY/+mGx8Hjc8y9wqCRXwztw=" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-edit/download/@webassemblyjs/wasm-edit-1.8.5.tgz", + "integrity": "sha1-li2hKqWswcExyBxCMpkcgs5W4Bo=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-gen/download/@webassemblyjs/wasm-gen-1.8.5.tgz", + "integrity": "sha1-VIQHZsLBAC62TtGr5yCt7XFPmLw=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-opt/download/@webassemblyjs/wasm-opt-1.8.5.tgz", + "integrity": "sha1-sk2fa6UDlK8TSfUQr6j/y4pj0mQ=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wasm-parser/download/@webassemblyjs/wasm-parser-1.8.5.tgz", + "integrity": "sha1-IVdvDsiLkUJzV7hTY4NmjvfGa40=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-parser/download/@webassemblyjs/wast-parser-1.8.5.tgz", + "integrity": "sha1-4Q7s1ULQ5705T2gnxJ899tTu+4w=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npm.taobao.org/@webassemblyjs/wast-printer/download/@webassemblyjs/wast-printer-1.8.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40webassemblyjs%2Fwast-printer%2Fdownload%2F%40webassemblyjs%2Fwast-printer-1.8.5.tgz", + "integrity": "sha1-EUu8SB/RDKDiOzVg+oEnSLC65bw=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/@xtuc/ieee754/download/@xtuc/ieee754-1.2.0.tgz", + "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npm.taobao.org/@xtuc/long/download/@xtuc/long-4.2.2.tgz", + "integrity": "sha1-0pHGpOl5ibXGHZrPOWrk/hM6cY0=" + }, + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/abab/download/abab-2.0.3.tgz?cache=0&sync_timestamp=1573609091746&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fabab%2Fdownload%2Fabab-2.0.3.tgz", + "integrity": "sha1-Yj4gdeAustPyR15J+ZyRhGRnkHo=" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz", + "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "7.2.0", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-7.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-7.2.0.tgz", + "integrity": "sha1-F+p+QNfIZA/1SmlMiJwm8xcE7/4=" + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npm.taobao.org/acorn-globals/download/acorn-globals-4.3.4.tgz", + "integrity": "sha1-n6GSat3BHJcwjE5m163Q1Awycuc=", + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-6.4.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-6.4.1.tgz", + "integrity": "sha1-Ux5Yuj9RudrLmmZGyk3r9bFMpHQ=" + } + } + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-5.2.0.tgz", + "integrity": "sha1-TGYGkXPW/daO2FI5/CViJhgrLr4=" + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npm.taobao.org/acorn-walk/download/acorn-walk-6.2.0.tgz", + "integrity": "sha1-Ejy487hMIXHx9/slJhWxx4prGow=" + }, + "address": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/address/download/address-1.1.2.tgz", + "integrity": "sha1-vxEWycdYxRt6kz0pa3LCIe2UKLY=" + }, + "adjust-sourcemap-loader": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/adjust-sourcemap-loader/download/adjust-sourcemap-loader-2.0.0.tgz", + "integrity": "sha1-ZHEUOvdewCM0shn1S8eXDFL7KaQ=", + "requires": { + "assert": "1.4.1", + "camelcase": "5.0.0", + "loader-utils": "1.2.3", + "object-path": "0.11.4", + "regex-parser": "2.2.10" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-5.0.0.tgz", + "integrity": "sha1-AylVJ9WL081Kp1Nj81sujZe+L0I=" + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&sync_timestamp=1586045666090&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.2.3.tgz?cache=0&sync_timestamp=1584445172927&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-1.2.3.tgz", + "integrity": "sha1-H/XcaRHJ8KBiUxpMBLYJQGEIwsc=", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + } + } + }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/aggregate-error/download/aggregate-error-3.0.1.tgz", + "integrity": "sha1-2y/nJG5Tb0DZtUQqOeEX191qJOA=", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.2.tgz?cache=0&sync_timestamp=1587339911109&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.2.tgz", + "integrity": "sha1-xinF7O0XuvMUQ3kY0tqIyZ1ZWM0=", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/ajv-errors/download/ajv-errors-1.0.1.tgz", + "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=" + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.4.1.tgz", + "integrity": "sha1-75FuJxxkrBIXH9g4TqrmsjRYVNo=" + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/alphanum-sort/download/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npm.taobao.org/ansi-colors/download/ansi-colors-3.2.4.tgz", + "integrity": "sha1-46PaS/uubIapwoViXeEkojQCb78=" + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-4.3.1.tgz", + "integrity": "sha1-pcR8xDGB8fOP/XB2g3cA05VSKmE=", + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npm.taobao.org/type-fest/download/type-fest-0.11.0.tgz", + "integrity": "sha1-l6vwhyMQ/tiKXEZrJWgVdhReM/E=" + } + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npm.taobao.org/ansi-html/download/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz", + "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "requires": { + "color-convert": "^1.9.0" + } + }, + "antd": { + "version": "4.3.2", + "resolved": "https://registry.npm.taobao.org/antd/download/antd-4.3.2.tgz?cache=0&sync_timestamp=1591457865604&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fantd%2Fdownload%2Fantd-4.3.2.tgz", + "integrity": "sha1-FnAEAwYmZgz/Rr4tbxD+N7bri7c=", + "requires": { + "@ant-design/css-animation": "^1.7.2", + "@ant-design/icons": "^4.2.1", + "@ant-design/react-slick": "~0.26.1", + "array-tree-filter": "^2.1.0", + "classnames": "^2.2.6", + "copy-to-clipboard": "^3.2.0", + "lodash": "^4.17.13", + "moment": "^2.25.3", + "omit.js": "^1.0.2", + "raf": "^3.4.1", + "rc-animate": "~3.1.0", + "rc-cascader": "~1.2.0", + "rc-checkbox": "~2.2.0", + "rc-collapse": "~2.0.0", + "rc-dialog": "~8.0.0", + "rc-drawer": "~4.0.0", + "rc-dropdown": "~3.1.2", + "rc-field-form": "~1.4.1", + "rc-input-number": "~5.0.0", + "rc-mentions": "~1.2.0", + "rc-menu": "~8.3.0", + "rc-notification": "~4.4.0", + "rc-pagination": "~2.2.5", + "rc-picker": "~1.6.1", + "rc-progress": "~3.0.0", + "rc-rate": "~2.7.0", + "rc-resize-observer": "^0.2.3", + "rc-select": "~11.0.0", + "rc-slider": "~9.3.0", + "rc-steps": "~4.0.0", + "rc-switch": "~3.2.0", + "rc-table": "~7.7.2", + "rc-tabs": "~11.3.1", + "rc-tooltip": "~4.2.0", + "rc-tree": "~3.3.0", + "rc-tree-select": "~4.0.0", + "rc-trigger": "~4.3.0", + "rc-upload": "~3.1.0", + "rc-util": "^5.0.1", + "scroll-into-view-if-needed": "^2.2.25", + "warning": "^4.0.3" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-2.0.0.tgz", + "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/aproba/download/aproba-1.2.0.tgz", + "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/aria-query/download/aria-query-4.0.2.tgz", + "integrity": "sha1-JQaHtMzeGrhtEn2gQyrjVS/HsUU=", + "requires": { + "@babel/runtime": "^7.7.4", + "@babel/runtime-corejs3": "^7.7.4" + } + }, + "arity-n": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/arity-n/download/arity-n-1.0.4.tgz", + "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=" + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/arr-diff/download/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/arr-union/download/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/array-equal/download/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/array-flatten/download/array-flatten-2.1.2.tgz?cache=0&sync_timestamp=1574313293899&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-flatten%2Fdownload%2Farray-flatten-2.1.2.tgz", + "integrity": "sha1-JO+AoowaiTYX4hSbDG0NeIKTsJk=" + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/array-includes/download/array-includes-3.1.1.tgz", + "integrity": "sha1-zdZ+aFK9+cEhVGB4ZzIlXtJFk0g=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/array-tree-filter/download/array-tree-filter-2.1.0.tgz", + "integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-union%2Fdownload%2Farray-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/array-uniq/download/array-uniq-1.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-uniq%2Fdownload%2Farray-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/array.prototype.flat/download/array.prototype.flat-1.2.3.tgz?cache=0&sync_timestamp=1576170357219&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray.prototype.flat%2Fdownload%2Farray.prototype.flat-1.2.3.tgz", + "integrity": "sha1-DegrQmsDGNv9uUAInjiwQ9N/bHs=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/arrify/download/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/asap/download/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npm.taobao.org/asn1.js/download/asn1.js-4.10.1.tgz", + "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=" + } + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/assert/download/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/assign-symbols/download/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npm.taobao.org/ast-types-flow/download/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/astral-regex/download/astral-regex-1.0.0.tgz", + "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=" + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npm.taobao.org/async/download/async-2.6.3.tgz", + "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/async-each/download/async-each-1.0.3.tgz", + "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/async-limiter/download/async-limiter-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync-limiter%2Fdownload%2Fasync-limiter-1.0.1.tgz", + "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=" + }, + "async-validator": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/async-validator/download/async-validator-3.3.0.tgz", + "integrity": "sha1-HZIZO75g1tbIskZpLHAF6e0UqO4=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/atob/download/atob-2.1.2.tgz", + "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=" + }, + "autoprefixer": { + "version": "9.8.0", + "resolved": "https://registry.npm.taobao.org/autoprefixer/download/autoprefixer-9.8.0.tgz", + "integrity": "sha1-aOLSvve6TDplQ29mLQpWp0HlZRE=", + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001061", + "chalk": "^2.4.2", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.30", + "postcss-value-parser": "^4.1.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.10.0", + "resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.10.0.tgz", + "integrity": "sha1-oXs6jqgRBg501H0wYSJACtRJeuI=" + }, + "axobject-query": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/axobject-query/download/axobject-query-2.1.2.tgz?cache=0&sync_timestamp=1581193348497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxobject-query%2Fdownload%2Faxobject-query-2.1.2.tgz", + "integrity": "sha1-K9/8A3HmQ+XwO6mQZdUXm5ynl5k=" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-code-frame%2Fdownload%2Fbabel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz?cache=0&sync_timestamp=1585815759944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-3.0.2.tgz?cache=0&sync_timestamp=1586796305651&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-tokens%2Fdownload%2Fjs-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&sync_timestamp=1582676152339&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz", + "integrity": "sha1-aWjlaKkQt4+zd5zdi2rC9HmUMjI=", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, + "babel-extract-comments": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/babel-extract-comments/download/babel-extract-comments-1.0.0.tgz", + "integrity": "sha1-Cirt+BQX7TkbheGLRhTmk6A1GiE=", + "requires": { + "babylon": "^6.18.0" + } + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/babel-jest/download/babel-jest-24.9.0.tgz", + "integrity": "sha1-P8Mny4RnuJ0U17xw4xUQSng8zVQ=", + "requires": { + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + } + }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.1.0.tgz?cache=0&sync_timestamp=1584715959282&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-loader%2Fdownload%2Fbabel-loader-8.1.0.tgz", + "integrity": "sha1-xhHVESvVIJq+i5+oTD5NolJ18cM=", + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=" + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npm.taobao.org/babel-plugin-dynamic-import-node/download/babel-plugin-dynamic-import-node-2.3.3.tgz?cache=0&sync_timestamp=1587496311403&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-plugin-dynamic-import-node%2Fdownload%2Fbabel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha1-hP2hnJduxcbe/vV/lCez3vZuF6M=", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/babel-plugin-istanbul/download/babel-plugin-istanbul-5.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-plugin-istanbul%2Fdownload%2Fbabel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha1-30reg9iXqS3wacTZolzyZxKTyFQ=", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + } + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/babel-plugin-jest-hoist/download/babel-plugin-jest-hoist-24.9.0.tgz?cache=0&sync_timestamp=1588615318965&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-plugin-jest-hoist%2Fdownload%2Fbabel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha1-T4NwketAfgFEfIhDy+xUbQAC11Y=", + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npm.taobao.org/babel-plugin-macros/download/babel-plugin-macros-2.8.0.tgz?cache=0&sync_timestamp=1575737872812&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-plugin-macros%2Fdownload%2Fbabel-plugin-macros-2.8.0.tgz", + "integrity": "sha1-D5WKfMZVax5lNERl2ZERoeXhATg=", + "requires": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-6.0.0.tgz", + "integrity": "sha1-2k/uhTxS9rHmk19BwaL8UL1KmYI=", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npm.taobao.org/import-fresh/download/import-fresh-3.2.1.tgz?cache=0&sync_timestamp=1573664960772&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-3.2.1.tgz", + "integrity": "sha1-Yz/2GFBueTr1rJG/SLcmd+FcvmY=", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-5.0.0.tgz", + "integrity": "sha1-c+URTJhtFD76NxLU6iTbmkJm9g8=", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-4.0.0.tgz", + "integrity": "sha1-hO0BwKe6OAr+CdkKjBgNzZ0DBDs=" + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/resolve-from/download/resolve-from-4.0.0.tgz", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=" + } + } + }, + "babel-plugin-named-asset-import": { + "version": "0.3.6", + "resolved": "https://registry.npm.taobao.org/babel-plugin-named-asset-import/download/babel-plugin-named-asset-import-0.3.6.tgz", + "integrity": "sha1-yXUKGzjYURLJ4Wa/PvfF28YF9L4=" + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npm.taobao.org/babel-plugin-syntax-object-rest-spread/download/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npm.taobao.org/babel-plugin-transform-object-rest-spread/download/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + }, + "babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npm.taobao.org/babel-plugin-transform-react-remove-prop-types/download/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha1-8u2vm0xqX75cHWeL+1MQeMFVXzo=" + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/babel-preset-jest/download/babel-preset-jest-24.9.0.tgz?cache=0&sync_timestamp=1588615296185&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-preset-jest%2Fdownload%2Fbabel-preset-jest-24.9.0.tgz", + "integrity": "sha1-GStSHiIX+x0fZ89z9wwzZlCtPNw=", + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "babel-preset-react-app": { + "version": "9.1.2", + "resolved": "https://registry.npm.taobao.org/babel-preset-react-app/download/babel-preset-react-app-9.1.2.tgz", + "integrity": "sha1-VHddl2WIqKbRqZIBpwK+/sr0gDA=", + "requires": { + "@babel/core": "7.9.0", + "@babel/plugin-proposal-class-properties": "7.8.3", + "@babel/plugin-proposal-decorators": "7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.8.3", + "@babel/plugin-proposal-numeric-separator": "7.8.3", + "@babel/plugin-proposal-optional-chaining": "7.9.0", + "@babel/plugin-transform-flow-strip-types": "7.9.0", + "@babel/plugin-transform-react-display-name": "7.8.3", + "@babel/plugin-transform-runtime": "7.9.0", + "@babel/preset-env": "7.9.0", + "@babel/preset-react": "7.9.1", + "@babel/preset-typescript": "7.9.0", + "@babel/runtime": "7.9.0", + "babel-plugin-macros": "2.8.0", + "babel-plugin-transform-react-remove-prop-types": "0.4.24" + }, + "dependencies": { + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.8.3.tgz?cache=0&sync_timestamp=1590617500094&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-class-properties%2Fdownload%2F%40babel%2Fplugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha1-XgZlSvXNBLYIkVqtqbKmeIAERk4=", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha1-5FciU/3u1lzd7s/as/kor+sv1dI=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.8.3.tgz?cache=0&sync_timestamp=1590617647710&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-numeric-separator%2Fdownload%2F%40babel%2Fplugin-proposal-numeric-separator-7.8.3.tgz", + "integrity": "sha1-XWdpQJaZ7Js7aGhM2BFs7f+Tutg=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.9.0.tgz?cache=0&sync_timestamp=1590617587766&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-optional-chaining%2Fdownload%2F%40babel%2Fplugin-proposal-optional-chaining-7.9.0.tgz", + "integrity": "sha1-MdsWsVTDnWuKZFKSRyuYOUwpKlg=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-transform-react-display-name/download/@babel/plugin-transform-react-display-name-7.8.3.tgz", + "integrity": "sha1-cN7Zh8kWCfeDU9120vsqC7mR6OU=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/preset-env": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.9.0.tgz?cache=0&sync_timestamp=1590868958159&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.9.0.tgz", + "integrity": "sha1-pfxCSA6VCuj12fjyu8A/UnIt86g=", + "requires": { + "@babel/compat-data": "^7.9.0", + "@babel/helper-compilation-targets": "^7.8.7", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-numeric-separator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.9.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.9.0", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.9.0", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.9.0", + "@babel/plugin-transform-modules-commonjs": "^7.9.0", + "@babel/plugin-transform-modules-systemjs": "^7.9.0", + "@babel/plugin-transform-modules-umd": "^7.9.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.7", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.7", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.4", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.9.0", + "browserslist": "^4.9.1", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/preset-react": { + "version": "7.9.1", + "resolved": "https://registry.npm.taobao.org/@babel/preset-react/download/@babel/preset-react-7.9.1.tgz", + "integrity": "sha1-s0ZAPDbVjDu1RBSCcqDO/ZwoZ3o=", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-react-display-name": "^7.8.3", + "@babel/plugin-transform-react-jsx": "^7.9.1", + "@babel/plugin-transform-react-jsx-development": "^7.9.0", + "@babel/plugin-transform-react-jsx-self": "^7.9.0", + "@babel/plugin-transform-react-jsx-source": "^7.9.0" + } + }, + "@babel/runtime": { + "version": "7.9.0", + "resolved": "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.9.0.tgz", + "integrity": "sha1-M37aZ0AfWwZqbyBaMRPUrBi6SVs=", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz?cache=0&sync_timestamp=1584052392667&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.11.1.tgz", + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npm.taobao.org/babylon/download/babylon-6.18.0.tgz", + "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npm.taobao.org/base/download/base-0.11.2.tgz", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz", + "integrity": "sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE=" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/batch/download/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npm.taobao.org/big.js/download/big.js-5.2.2.tgz", + "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=" + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.0.0.tgz", + "integrity": "sha1-I8DfFPaogHf1+YbA0WfsA8PVU3w=" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npm.taobao.org/bindings/download/bindings-1.5.0.tgz", + "integrity": "sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbluebird%2Fdownload%2Fbluebird-3.7.2.tgz", + "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=" + }, + "bn.js": { + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.2.tgz", + "integrity": "sha1-yWhpAtPJoncp9DqxD515wgBNp7A=" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npm.taobao.org/body-parser/download/body-parser-1.19.0.tgz", + "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz", + "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1579334008444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=" + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npm.taobao.org/bonjour/download/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/boolbase/download/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/brorand/download/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/browser-process-hrtime/download/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha1-PJtLfXgsgSHlbxAQbYTA0P/JRiY=" + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npm.taobao.org/browser-resolve/download/browser-resolve-1.11.3.tgz", + "integrity": "sha1-m3y7PQ9RDky4a9vXlhJNKLWJCvY=", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/browserify-aes/download/browserify-aes-1.2.0.tgz", + "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/browserify-cipher/download/browserify-cipher-1.0.1.tgz", + "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/browserify-des/download/browserify-des-1.0.2.tgz", + "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/browserify-rsa/download/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=" + } + } + }, + "browserify-sign": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/browserify-sign/download/browserify-sign-4.2.0.tgz", + "integrity": "sha1-VF0LGwfmssmSEQgr8bEsznoLDhE=", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.2", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=" + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/browserify-zlib/download/browserify-zlib-0.2.0.tgz", + "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.12.0", + "resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.12.0.tgz?cache=0&sync_timestamp=1587419256330&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.12.0.tgz", + "integrity": "sha1-BsbVcVoe3mxR/Dn/Z/1kf3QLZW0=", + "requires": { + "caniuse-lite": "^1.0.30001043", + "electron-to-chromium": "^1.3.413", + "node-releases": "^1.1.53", + "pkg-up": "^2.0.0" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/bser/download/bser-2.1.1.tgz", + "integrity": "sha1-5nh9og7OnQeZhTPP2d5vXDj0vAU=", + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npm.taobao.org/buffer/download/buffer-4.9.2.tgz", + "integrity": "sha1-Iw6tNEACmIZEhBqwJEr4xEu+Pvg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz", + "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=" + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/buffer-indexof/download/buffer-indexof-1.1.1.tgz", + "integrity": "sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/buffer-xor/download/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cacache": { + "version": "13.0.1", + "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz", + "integrity": "sha1-qAAMIWlwiQgvhSh6GuxuOCAkpxw=", + "requires": { + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz", + "integrity": "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w=", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/call-me-maybe/download/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/caller-callsite/download/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/caller-path/download/caller-path-2.0.0.tgz?cache=0&sync_timestamp=1574395542397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaller-path%2Fdownload%2Fcaller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + }, + "camel-case": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/camel-case/download/camel-case-4.1.1.tgz", + "integrity": "sha1-H8QchU8A4vfQE53+uhVC1olv5Uc=", + "requires": { + "pascal-case": "^3.1.1", + "tslib": "^1.10.0" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz", + "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=" + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/caniuse-api/download/caniuse-api-3.0.0.tgz", + "integrity": "sha1-Xk2Q4idJYdRikZl99Znj7QCO5MA=", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001078", + "resolved": "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001078.tgz", + "integrity": "sha1-4bbirjJ7ah7BH2Xseg3eHnCTB0w=" + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/capture-exit/download/capture-exit-2.0.0.tgz", + "integrity": "sha1-+5U7+uvreB9iiYI52rtCbQilCaQ=", + "requires": { + "rsvp": "^4.8.4" + } + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/case-sensitive-paths-webpack-plugin/download/case-sensitive-paths-webpack-plugin-2.3.0.tgz?cache=0&sync_timestamp=1579125374167&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcase-sensitive-paths-webpack-plugin%2Fdownload%2Fcase-sensitive-paths-webpack-plugin-2.3.0.tgz", + "integrity": "sha1-I6xhPMmoVuT4j/i7c7u16YmCXPc=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz?cache=0&sync_timestamp=1585815759944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz", + "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npm.taobao.org/chardet/download/chardet-0.7.0.tgz?cache=0&sync_timestamp=1588893413176&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchardet%2Fdownload%2Fchardet-0.7.0.tgz", + "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=" + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npm.taobao.org/cheerio/download/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha1-CUY21CWy6cD065GkbAVjDJoai/Y=", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + }, + "dependencies": { + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/css-what/download/css-what-2.1.3.tgz", + "integrity": "sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI=", + "dev": true + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.1.tgz", + "integrity": "sha1-HsQFnihLq+027sKUHUqXChic58A=", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz?cache=0&sync_timestamp=1589052712571&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomutils%2Fdownload%2Fdomutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fentities%2Fdownload%2Fentities-1.1.2.tgz", + "integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=", + "dev": true + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/parse5/download/parse5-3.0.3.tgz?cache=0&sync_timestamp=1586991218581&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse5%2Fdownload%2Fparse5-3.0.3.tgz", + "integrity": "sha1-BC95L/3TaFFVHPTp4Gazh0q0W1w=", + "dev": true, + "requires": { + "@types/node": "*" + } + } + } + }, + "chokidar": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-3.4.0.tgz?cache=0&sync_timestamp=1587911257758&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.4.0.tgz", + "integrity": "sha1-swYRQjzjdjV8dlubj5BLn7o8C+g=", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.1.tgz", + "integrity": "sha1-xV7PAhheJGklk5kxDBc84xIzsUI=", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz", + "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=", + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz", + "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz", + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz", + "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=", + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/chownr/download/chownr-1.1.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchownr%2Fdownload%2Fchownr-1.1.4.tgz", + "integrity": "sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs=" + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/chrome-trace-event/download/chrome-trace-event-1.0.2.tgz", + "integrity": "sha1-I0CQ7pfH1K0aLEvq4nUF3v/GCKQ=", + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ci-info/download/ci-info-2.0.0.tgz", + "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/cipher-base/download/cipher-base-1.0.4.tgz", + "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npm.taobao.org/classnames/download/classnames-2.2.6.tgz", + "integrity": "sha1-Q5Nb/90pHzJtrQogUwmzjQD2UM4=" + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npm.taobao.org/clean-css/download/clean-css-4.2.3.tgz", + "integrity": "sha1-UHtd59l7SO5T2ErbAWD/YhY4D3g=", + "requires": { + "source-map": "~0.6.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/clean-stack/download/clean-stack-2.2.0.tgz", + "integrity": "sha1-7oRy27Ep5yezHooQpCfe6d/kAIs=" + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-3.1.0.tgz", + "integrity": "sha1-JkMFp65JDR0Dvwybp8kl0XU68wc=", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/cli-width/download/cli-width-2.2.1.tgz?cache=0&sync_timestamp=1586877902436&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcli-width%2Fdownload%2Fcli-width-2.2.1.tgz", + "integrity": "sha1-sEM9C06chH7xiGik7xb9X8gnHEg=" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-5.0.0.tgz", + "integrity": "sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U=", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "clone-deep": { + "version": "0.2.4", + "resolved": "https://registry.npm.taobao.org/clone-deep/download/clone-deep-0.2.4.tgz", + "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", + "requires": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npm.taobao.org/co/download/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/coa/download/coa-2.0.2.tgz", + "integrity": "sha1-Q/bCEVG07yv1cYfbDXPeIp4+fsM=", + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/color/download/color-3.1.2.tgz", + "integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz", + "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npm.taobao.org/color-string/download/color-string-1.5.3.tgz", + "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz", + "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=" + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npm.taobao.org/common-tags/download/common-tags-1.8.0.tgz", + "integrity": "sha1-jjFT5ULUo56bEFVENK+q+YlWqTc=" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommondir%2Fdownload%2Fcommondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz", + "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=" + }, + "compose-function": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/compose-function/download/compose-function-3.0.3.tgz", + "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=", + "requires": { + "arity-n": "^1.0.4" + } + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npm.taobao.org/compressible/download/compressible-2.0.18.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcompressible%2Fdownload%2Fcompressible-2.0.18.tgz", + "integrity": "sha1-r1PMprBw1MPAdQ+9dyhqbXzEb7o=", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npm.taobao.org/compression/download/compression-1.7.4.tgz", + "integrity": "sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48=", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "compute-scroll-into-view": { + "version": "1.0.14", + "resolved": "https://registry.npm.taobao.org/compute-scroll-into-view/download/compute-scroll-into-view-1.0.14.tgz", + "integrity": "sha1-gOPrsl1qqJ9C5TOVbLSxagTP51k=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz", + "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "confusing-browser-globals": { + "version": "1.0.9", + "resolved": "https://registry.npm.taobao.org/confusing-browser-globals/download/confusing-browser-globals-1.0.9.tgz", + "integrity": "sha1-crwTtIPAJ2gBaBhx1ImFFvj1T90=" + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/connect-history-api-fallback/download/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w=" + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/console-browserify/download/console-browserify-1.2.0.tgz?cache=0&sync_timestamp=1572252287978&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconsole-browserify%2Fdownload%2Fconsole-browserify-1.2.0.tgz", + "integrity": "sha1-ZwY871fOts9Jk6KrOlWECujEkzY=" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/constants-browserify/download/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npm.taobao.org/contains-path/download/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz", + "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.7.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconvert-source-map%2Fdownload%2Fconvert-source-map-1.7.0.tgz", + "integrity": "sha1-F6LLiC1/d9NJBYXizmxSRCSjpEI=", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/cookie/download/cookie-0.4.0.tgz", + "integrity": "sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/copy-concurrently/download/copy-concurrently-1.0.5.tgz", + "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-to-clipboard": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/copy-to-clipboard/download/copy-to-clipboard-3.3.1.tgz?cache=0&sync_timestamp=1582385612192&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcopy-to-clipboard%2Fdownload%2Fcopy-to-clipboard-3.3.1.tgz", + "integrity": "sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=", + "requires": { + "toggle-selection": "^1.0.6" + } + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.11.tgz", + "integrity": "sha1-OIMUafmSK97Y7iHJ3EaYXgOZMIw=" + }, + "core-js-compat": { + "version": "3.6.5", + "resolved": "https://registry.npm.taobao.org/core-js-compat/download/core-js-compat-3.6.5.tgz", + "integrity": "sha1-KlHZpOJd/W5pAlGqgfmePAVIHxw=", + "requires": { + "browserslist": "^4.8.5", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.0.0.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.0.0.tgz", + "integrity": "sha1-XzyjV2HkfgWyBsba/yz4FPAxa44=" + } + } + }, + "core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npm.taobao.org/core-js-pure/download/core-js-pure-3.6.5.tgz", + "integrity": "sha1-x5519eONvIWmYtke6lK4JW1TuBM=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-5.2.1.tgz", + "integrity": "sha1-BA9yaAnFked6F8CjYmykW08Wixo=", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/create-ecdh/download/create-ecdh-4.0.3.tgz", + "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=" + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/create-hash/download/create-hash-1.2.0.tgz", + "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npm.taobao.org/create-hmac/download/create-hmac-1.1.7.tgz", + "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz", + "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz", + "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npm.taobao.org/css/download/css-2.2.4.tgz", + "integrity": "sha1-xkZ1XHOXHyu6amAeLPL9cbEpiSk=", + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/css-blank-pseudo/download/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha1-3979MlS/ioICeZNnTM81SDv8s8U=", + "requires": { + "postcss": "^7.0.5" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/css-declaration-sorter/download/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha1-wZiUD2OnbX42wecQGLABchBUyyI=", + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npm.taobao.org/css-has-pseudo/download/css-has-pseudo-0.10.0.tgz", + "integrity": "sha1-PGQqs0yiQsWcQaEl35EFhB9pZu4=", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-2.0.0.tgz", + "integrity": "sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM=" + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-5.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-5.0.0.tgz", + "integrity": "sha1-JJBENWaXsztk8aj3yAki3d7nGVw=", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "css-loader": { + "version": "3.4.2", + "resolved": "https://registry.npm.taobao.org/css-loader/download/css-loader-3.4.2.tgz", + "integrity": "sha1-0/2zNYtD8jO3hQHF7XscbaYTMgI=", + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.23", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.1.1", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.2", + "schema-utils": "^2.6.0" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=" + } + } + }, + "css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/css-prefers-color-scheme/download/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha1-b4MKJxQZnU8NDQu4onkW7WXP8fQ=", + "requires": { + "postcss": "^7.0.5" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/css-select/download/css-select-2.1.0.tgz", + "integrity": "sha1-ajRlM1ZjWTSoG6ymjQJVQyEF2+8=", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/css-select-base-adapter/download/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc=" + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npm.taobao.org/css-tree/download/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha1-mL69YsTB2flg7DQM+fdSLjBwmiI=", + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + } + }, + "css-what": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/css-what/download/css-what-3.3.0.tgz", + "integrity": "sha1-EP7Glqns4uWRrHctdZqsq6w4zTk=" + }, + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/css.escape/download/css.escape-1.5.1.tgz", + "integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=" + }, + "cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npm.taobao.org/cssdb/download/cssdb-4.4.0.tgz", + "integrity": "sha1-O/LypowQ9cagir2SN4Mx7oA83bA=" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-3.0.0.tgz", + "integrity": "sha1-N3QZGZA7hoVl4cCep0dEXNGJg+4=" + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npm.taobao.org/cssnano/download/cssnano-4.1.10.tgz", + "integrity": "sha1-CsQfCxPRPUZUh+ERt3jULaYxuLI=", + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npm.taobao.org/cssnano-preset-default/download/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha1-UexmLM/KD4izltzZZ5zbkxvhf3Y=", + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/cssnano-util-get-arguments/download/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=" + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/cssnano-util-get-match/download/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=" + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/cssnano-util-raw-cache/download/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha1-sm1f1fcqEd/np4RvtMZyYPlr8oI=", + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/cssnano-util-same-parent/download/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha1-V0CC+yhZ0ttDOFWDXZqEVuoYu/M=" + }, + "csso": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/csso/download/csso-4.0.3.tgz?cache=0&sync_timestamp=1585052130344&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcsso%2Fdownload%2Fcsso-4.0.3.tgz", + "integrity": "sha1-DZmF3IUsfMKyys+74QeQFNGo6QM=", + "requires": { + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npm.taobao.org/css-tree/download/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha1-K/8//huz93bPfu/ZHuXLp3oUnus=", + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.6.tgz", + "integrity": "sha1-hS3GD8ql2qLoz2yRicRA7T4EKXg=" + } + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npm.taobao.org/cssom/download/cssom-0.3.8.tgz?cache=0&sync_timestamp=1573719337707&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcssom%2Fdownload%2Fcssom-0.3.8.tgz", + "integrity": "sha1-nxJ29bK0Y/IRTT8sdSUK+MGjb0o=" + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/cssstyle/download/cssstyle-1.4.0.tgz", + "integrity": "sha1-nTEyginTxWXGHlhrAgQaKPzNzPE=", + "requires": { + "cssom": "0.3.x" + } + }, + "csstype": { + "version": "2.6.10", + "resolved": "https://registry.npm.taobao.org/csstype/download/csstype-2.6.10.tgz?cache=0&sync_timestamp=1586935655811&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcsstype%2Fdownload%2Fcsstype-2.6.10.tgz", + "integrity": "sha1-5jr1DmbXwmbttrMpCc/Qqr4Dkos=" + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/cyclist/download/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/d/download/d-1.0.1.tgz", + "integrity": "sha1-hpgJU3LVjb7jRv/Qxwk/mfj561o=", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "damerau-levenshtein": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/damerau-levenshtein/download/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha1-FDwWQcs9hcYMMjKeJoma3qhwF5E=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/data-urls/download/data-urls-1.1.0.tgz", + "integrity": "sha1-Fe4Fgrql4iu1nHcUDaj5x2lju/4=", + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/whatwg-url/download/whatwg-url-7.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhatwg-url%2Fdownload%2Fwhatwg-url-7.1.0.tgz", + "integrity": "sha1-wsSS8eymEpiO/T0iZr4bn8YXDQY=", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "date-format": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/date-format/download/date-format-3.0.0.tgz", + "integrity": "sha1-64eANlx9KxURB4+0keZHl4DzrZU=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz", + "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.1.1.tgz", + "integrity": "sha1-tcmMlCzv+vfLBR4k4UNKJaLmB2o=", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz?cache=0&sync_timestamp=1590419212936&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdefault-gateway%2Fdownload%2Fdefault-gateway-4.2.0.tgz", + "integrity": "sha1-FnEEx1AMIRX23WmwpTa7jtcgVSs=", + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz", + "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/del/download/del-4.1.1.tgz", + "integrity": "sha1-no8RciLqRKMf86FWwEm5kFKp8LQ=", + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/globby/download/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/p-map/download/p-map-2.1.0.tgz", + "integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=" + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/des.js/download/des.js-1.0.1.tgz", + "integrity": "sha1-U4IULhvcU/hdhtU+X0qn3rkeCEM=", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/detect-newline/download/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.4.tgz", + "integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=" + }, + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/detect-port-alt/download/detect-port-alt-1.1.6.tgz", + "integrity": "sha1-JHB96r6TLUo89iEwICfCsmZWgnU=", + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/diff-sequences/download/diff-sequences-24.9.0.tgz?cache=0&sync_timestamp=1588615296719&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdiff-sequences%2Fdownload%2Fdiff-sequences-24.9.0.tgz", + "integrity": "sha1-VxXWJE4qpl9Iu6C8ly2wsLEelbU=" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz", + "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=" + } + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/dir-glob/download/dir-glob-2.0.0.tgz", + "integrity": "sha1-CyBdK2rvmCOMooZZioIE0p0KADQ=", + "requires": { + "arrify": "^1.0.1", + "path-type": "^3.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/dns-equal/download/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/dns-packet/download/dns-packet-1.3.1.tgz", + "integrity": "sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo=", + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/dns-txt/download/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/doctrine/download/doctrine-3.0.0.tgz", + "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=", + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-accessibility-api": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/dom-accessibility-api/download/dom-accessibility-api-0.3.0.tgz", + "integrity": "sha1-UR5Zk91nO5fIfqR9ug44kvfgyYM=" + }, + "dom-align": { + "version": "1.12.0", + "resolved": "https://registry.npm.taobao.org/dom-align/download/dom-align-1.12.0.tgz", + "integrity": "sha1-VvtxVt8LkQmYMDZNLUj4iWP1opw=" + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/dom-converter/download/dom-converter-0.2.0.tgz", + "integrity": "sha1-ZyGp2u4uKTaClVtq/kFncWJ7t2g=", + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.2.2.tgz", + "integrity": "sha1-GvuB9TNxcXXUeGVd68XjMtn5u1E=", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-2.0.1.tgz", + "integrity": "sha1-H4vf6R9aeAYydOgDtL3O326U+U0=" + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz?cache=0&sync_timestamp=1590072081382&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomain-browser%2Fdownload%2Fdomain-browser-1.2.0.tgz", + "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=" + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz", + "integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8=" + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/domexception/download/domexception-1.0.1.tgz", + "integrity": "sha1-k3RCZEymoxJh7zbj7Gd/6AVYLJA=", + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz", + "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/domutils/download/domutils-1.7.0.tgz?cache=0&sync_timestamp=1589052712571&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomutils%2Fdownload%2Fdomutils-1.7.0.tgz", + "integrity": "sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-case": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/dot-case/download/dot-case-3.0.3.tgz", + "integrity": "sha1-IdO1Lvqroupf2odbsaqBJFIc9Ko=", + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + } + }, + "dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/dot-prop/download/dot-prop-5.2.0.tgz?cache=0&sync_timestamp=1572620767955&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdot-prop%2Fdownload%2Fdot-prop-5.2.0.tgz", + "integrity": "sha1-w07MKVVtxF8fTCJpe29JBODMT8s=", + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npm.taobao.org/dotenv/download/dotenv-8.2.0.tgz", + "integrity": "sha1-l+YZJZradQ7qPk6j4mvO6lQksWo=" + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz", + "integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=" + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npm.taobao.org/duplexify/download/duplexify-3.7.1.tgz", + "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "electron-to-chromium": { + "version": "1.3.464", + "resolved": "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.464.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.464.tgz", + "integrity": "sha1-/hP+qgj2+GXTyJ1dcuVMGU9GOqU=" + }, + "elliptic": { + "version": "6.5.2", + "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.2.tgz", + "integrity": "sha1-BcVnjXFzwEnYykM1UiJKSV0ON2I=", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=" + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-8.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-8.0.0.tgz", + "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz", + "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz?cache=0&sync_timestamp=1569416272686&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fend-of-stream%2Fdownload%2Fend-of-stream-1.4.4.tgz", + "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/enhanced-resolve/download/enhanced-resolve-4.1.1.tgz?cache=0&sync_timestamp=1591175115319&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenhanced-resolve%2Fdownload%2Fenhanced-resolve-4.1.1.tgz", + "integrity": "sha1-KTfiuAZs0P584JkKmPDXGjUYn2Y=", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.5.0.tgz", + "integrity": "sha1-MkwBKIuIZSlm0WHbd4OHIIRajjw=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/entities/download/entities-2.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fentities%2Fdownload%2Fentities-2.0.3.tgz", + "integrity": "sha1-XEh+V0Krk8Fau12iJ1m4WQ7AO38=" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npm.taobao.org/errno/download/errno-0.1.7.tgz", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz", + "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.5.tgz", + "integrity": "sha1-2MnR1myJgfuSAOIlHXme7pJ3Suk=", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.2.1.tgz", + "integrity": "sha1-5VzUyc3BiLzvsDs2bHNjI/xciYo=", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npm.taobao.org/es5-ext/download/es5-ext-0.10.53.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes5-ext%2Fdownload%2Fes5-ext-0.10.53.tgz", + "integrity": "sha1-k8WjrP2+8nUiCtcmRK0C7hg2jeE=", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/es6-iterator/download/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npm.taobao.org/es6-symbol/download/es6-symbol-3.1.3.tgz", + "integrity": "sha1-utXTwbzawoJp9MszHkMceKxwXRg=", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescape-string-regexp%2Fdownload%2Fescape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.14.2", + "resolved": "https://registry.npm.taobao.org/escodegen/download/escodegen-1.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescodegen%2Fdownload%2Fescodegen-1.14.2.tgz", + "integrity": "sha1-FKtxv1AmwqoIFzr7oixvMXMoSoQ=", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npm.taobao.org/eslint/download/eslint-6.8.0.tgz?cache=0&sync_timestamp=1591401814806&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint%2Fdownload%2Feslint-6.8.0.tgz", + "integrity": "sha1-YiYtZylzn5J1cjgkMC+yJ8jJP/s=", + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npm.taobao.org/eslint-utils/download/eslint-utils-1.4.3.tgz?cache=0&sync_timestamp=1577351142754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-utils%2Fdownload%2Feslint-utils-1.4.3.tgz", + "integrity": "sha1-dP7HxU0Hdrb2fgJRBAtYBlZOmB8=", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npm.taobao.org/globals/download/globals-12.4.0.tgz", + "integrity": "sha1-oYgTV2pBsAokqX5/gVkYwuGZJfg=", + "requires": { + "type-fest": "^0.8.1" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npm.taobao.org/import-fresh/download/import-fresh-3.2.1.tgz?cache=0&sync_timestamp=1573664960772&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-3.2.1.tgz", + "integrity": "sha1-Yz/2GFBueTr1rJG/SLcmd+FcvmY=", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/regexpp/download/regexpp-2.0.1.tgz", + "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=" + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/resolve-from/download/resolve-from-4.0.0.tgz", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=" + } + } + }, + "eslint-config-react-app": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/eslint-config-react-app/download/eslint-config-react-app-5.2.1.tgz", + "integrity": "sha1-aYv3ru4n8M6gE56u8mHHv33WI98=", + "requires": { + "confusing-browser-globals": "^1.0.9" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.3", + "resolved": "https://registry.npm.taobao.org/eslint-import-resolver-node/download/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha1-26pStrKBa1C8ZxGvdUIt6AjphAQ=", + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "eslint-loader": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/eslint-loader/download/eslint-loader-3.0.3.tgz", + "integrity": "sha1-4Bjj0nIjgdmCsSAa21aBnHO0gMo=", + "requires": { + "fs-extra": "^8.1.0", + "loader-fs-cache": "^1.0.2", + "loader-utils": "^1.2.3", + "object-hash": "^2.0.1", + "schema-utils": "^2.6.1" + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npm.taobao.org/eslint-module-utils/download/eslint-module-utils-2.6.0.tgz?cache=0&sync_timestamp=1585438056134&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-module-utils%2Fdownload%2Feslint-module-utils-2.6.0.tgz", + "integrity": "sha1-V569CU9Wr3eX0ZyYZsnJSGYpv6Y=", + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-flowtype": { + "version": "4.6.0", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-flowtype/download/eslint-plugin-flowtype-4.6.0.tgz", + "integrity": "sha1-grK9byF3Dg5d7t4CKORWyzUwhFE=", + "requires": { + "lodash": "^4.17.15" + } + }, + "eslint-plugin-import": { + "version": "2.20.1", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-import/download/eslint-plugin-import-2.20.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-import%2Fdownload%2Feslint-plugin-import-2.20.1.tgz", + "integrity": "sha1-gCQjGW3LEdnOhDWl/AKm07RpObM=", + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npm.taobao.org/doctrine/download/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz?cache=0&sync_timestamp=1575620436254&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg-up%2Fdownload%2Fread-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + } + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.2.3", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-jsx-a11y/download/eslint-plugin-jsx-a11y-6.2.3.tgz", + "integrity": "sha1-uHKgnV3lGvcKl9se6n3JMwQ3CKo=", + "requires": { + "@babel/runtime": "^7.4.5", + "aria-query": "^3.0.0", + "array-includes": "^3.0.3", + "ast-types-flow": "^0.0.7", + "axobject-query": "^2.0.2", + "damerau-levenshtein": "^1.0.4", + "emoji-regex": "^7.0.2", + "has": "^1.0.3", + "jsx-ast-utils": "^2.2.1" + }, + "dependencies": { + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/aria-query/download/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=" + } + } + }, + "eslint-plugin-react": { + "version": "7.19.0", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-react/download/eslint-plugin-react-7.19.0.tgz", + "integrity": "sha1-bQj5ZzYoqmnFVZ0zSJ6FXYNVFmY=", + "requires": { + "array-includes": "^3.1.1", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.2.3", + "object.entries": "^1.1.1", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.15.1", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.2", + "xregexp": "^4.3.0" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/doctrine/download/doctrine-2.1.0.tgz", + "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz", + "integrity": "sha1-sllBtUloIxzC0bt2p5y38sC/hEQ=", + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/eslint-plugin-react-hooks/download/eslint-plugin-react-hooks-1.7.0.tgz?cache=0&sync_timestamp=1590539263706&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-react-hooks%2Fdownload%2Feslint-plugin-react-hooks-1.7.0.tgz", + "integrity": "sha1-YhC21aNyBfC5KFj4laToJwIKfQQ=" + }, + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-5.1.0.tgz", + "integrity": "sha1-0Plx3+WcaeDK2mhLI9Sdv4JgDOU=", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/eslint-utils/download/eslint-utils-2.0.0.tgz?cache=0&sync_timestamp=1577351142754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-utils%2Fdownload%2Feslint-utils-2.0.0.tgz", + "integrity": "sha1-e+HMcPJ6cqds0UqmmLyr7WiQ4c0=", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/eslint-visitor-keys/download/eslint-visitor-keys-1.2.0.tgz?cache=0&sync_timestamp=1591268786714&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-visitor-keys%2Fdownload%2Feslint-visitor-keys-1.2.0.tgz", + "integrity": "sha1-dEFayISHRJX3jsKpc0lSU0TJgfo=" + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npm.taobao.org/espree/download/espree-6.2.1.tgz?cache=0&sync_timestamp=1591269414186&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fespree%2Fdownload%2Fespree-6.2.1.tgz", + "integrity": "sha1-d/xy4f10SiBSwg84pbV1gy6Cc0o=", + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz", + "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=" + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/esquery/download/esquery-1.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fesquery%2Fdownload%2Fesquery-1.3.1.tgz", + "integrity": "sha1-t4tYKKqOIU4p+3TE1bdS4cAz2lc=", + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/estraverse/download/estraverse-5.1.0.tgz?cache=0&sync_timestamp=1586968779444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Festraverse%2Fdownload%2Festraverse-5.1.0.tgz", + "integrity": "sha1-N0MJ05/ZNa5QDnuS6Ka0xyDllkI=" + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/esrecurse/download/esrecurse-4.2.1.tgz", + "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/estraverse/download/estraverse-4.3.0.tgz?cache=0&sync_timestamp=1586968779444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Festraverse%2Fdownload%2Festraverse-4.3.0.tgz", + "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0=" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/esutils/download/esutils-2.0.3.tgz", + "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npm.taobao.org/eventemitter3/download/eventemitter3-4.0.4.tgz", + "integrity": "sha1-tUY6zmNaCD0Bi9x8kXtMXxCoU4Q=" + }, + "events": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/events/download/events-3.1.0.tgz?cache=0&sync_timestamp=1578498239809&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fevents%2Fdownload%2Fevents-3.1.0.tgz", + "integrity": "sha1-hCea8bNMt1qoi/X/KR9tC9mzGlk=" + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npm.taobao.org/eventsource/download/eventsource-1.0.7.tgz", + "integrity": "sha1-j7xyyT/NNAiAkLwKTmT0tc7m2NA=", + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz", + "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.4", + "resolved": "https://registry.npm.taobao.org/exec-sh/download/exec-sh-0.3.4.tgz", + "integrity": "sha1-OgGM61JsxvbfK7UEsr/o46STTsU=" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/execa/download/execa-1.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexeca%2Fdownload%2Fexeca-1.0.0.tgz", + "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/exit/download/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/expect/download/expect-24.9.0.tgz", + "integrity": "sha1-t1FltIFwdPpKFXeU9G/p8boVtso=", + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npm.taobao.org/express/download/express-4.17.1.tgz?cache=0&sync_timestamp=1585184256196&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexpress%2Fdownload%2Fexpress-4.17.1.tgz", + "integrity": "sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ=", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/array-flatten/download/array-flatten-1.1.1.tgz?cache=0&sync_timestamp=1574313293899&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-flatten%2Fdownload%2Farray-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz", + "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=" + } + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/ext/download/ext-1.4.0.tgz?cache=0&sync_timestamp=1575036693653&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fext%2Fdownload%2Fext-1.4.0.tgz", + "integrity": "sha1-ia56BxWPedNVF4gpBDJAd+Q3kkQ=", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/type/download/type-2.0.0.tgz", + "integrity": "sha1-Xxb/bvLrRPJgSU2uJxAzspwJqcM=" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz", + "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/external-editor/download/external-editor-3.1.0.tgz", + "integrity": "sha1-ywP3QL764D6k0oPK7SdBqD8zVJU=", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1579334008444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.1.tgz", + "integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ=" + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npm.taobao.org/fast-glob/download/fast-glob-2.2.7.tgz", + "integrity": "sha1-aVOFfDr6R1//ku5gFdUtpwpM050=", + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1584836110944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/fb-watchman/download/fb-watchman-2.0.1.tgz?cache=0&sync_timestamp=1575658859576&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffb-watchman%2Fdownload%2Ffb-watchman-2.0.1.tgz", + "integrity": "sha1-/IT7OdJwnPP/bXQ3BhV7tXCKioU=", + "requires": { + "bser": "2.1.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.2.tgz", + "integrity": "sha1-tO7oFIq7Adzx0aw0Nn1Z4S+mHW4=" + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/figures/download/figures-3.2.0.tgz?cache=0&sync_timestamp=1581865404867&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffigures%2Fdownload%2Ffigures-3.2.0.tgz", + "integrity": "sha1-YlwYvSk8YE3EqN2y/r8MiDQXRq8=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/file-entry-cache/download/file-entry-cache-5.0.1.tgz", + "integrity": "sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w=", + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-loader": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/file-loader/download/file-loader-4.3.0.tgz", + "integrity": "sha1-eA8ED3KbPRgBnyBgX3I+hEuKWK8=", + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.5.0" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz", + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", + "optional": true + }, + "filesize": { + "version": "6.0.1", + "resolved": "https://registry.npm.taobao.org/filesize/download/filesize-6.0.1.tgz", + "integrity": "sha1-+FC1CZCcfIb35FDqGQBsMcLtPS8=" + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.2.tgz", + "integrity": "sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0=", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz?cache=0&sync_timestamp=1583734591888&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-cache-dir%2Fdownload%2Ffind-cache-dir-2.1.0.tgz", + "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/flat-cache/download/flat-cache-2.0.1.tgz", + "integrity": "sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA=", + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/flatted/download/flatted-2.0.2.tgz?cache=0&sync_timestamp=1590517213403&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fflatted%2Fdownload%2Fflatted-2.0.2.tgz", + "integrity": "sha1-RXWyHivO50NKqb5mL0t7X5wrUTg=" + }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/flatten/download/flatten-1.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fflatten%2Fdownload%2Fflatten-1.0.3.tgz", + "integrity": "sha1-wSg6yfJ7Noq8HjbR/3sEUBowNWs=" + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/flush-write-stream/download/flush-write-stream-1.1.1.tgz", + "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "follow-redirects": { + "version": "1.11.0", + "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.11.0.tgz", + "integrity": "sha1-r6FPCLoSpSljFA/kMhJliJe8Dss=", + "requires": { + "debug": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npm.taobao.org/for-own/download/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "fork-ts-checker-webpack-plugin": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/fork-ts-checker-webpack-plugin/download/fork-ts-checker-webpack-plugin-3.1.1.tgz?cache=0&sync_timestamp=1591455914469&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffork-ts-checker-webpack-plugin%2Fdownload%2Ffork-ts-checker-webpack-plugin-3.1.1.tgz", + "integrity": "sha1-oWQsDT5l9QwswXQunAqA9EH4axk=", + "requires": { + "babel-code-frame": "^6.22.0", + "chalk": "^2.4.1", + "chokidar": "^3.3.0", + "micromatch": "^3.1.10", + "minimatch": "^3.0.4", + "semver": "^5.6.0", + "tapable": "^1.0.0", + "worker-rpc": "^0.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz", + "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/forwarded/download/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/fragment-cache/download/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz?cache=0&sync_timestamp=1591231538901&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-2.1.0.tgz?cache=0&sync_timestamp=1579628584498&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-minipass%2Fdownload%2Ffs-minipass-2.1.0.tgz", + "integrity": "sha1-f1A2/b8SxjwWkZDL5BmchSJx+fs=", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.1.2.tgz", + "integrity": "sha1-TAofs0vGjlQ7S4Kp7Dkr+9qECAU=", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.1.tgz", + "integrity": "sha1-WPQ2H/mH5f9uHnohCCeqNx6qwmk=" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz", + "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=" + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/get-own-enumerable-property-symbols/download/get-own-enumerable-property-symbols-3.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fget-own-enumerable-property-symbols%2Fdownload%2Fget-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha1-tf3nfyLL4185C04ImSLFC85u9mQ=" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz", + "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz", + "integrity": "sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.1.tgz?cache=0&sync_timestamp=1584836110944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.1.tgz", + "integrity": "sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=", + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/glob-to-regexp/download/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/global-modules/download/global-modules-2.0.0.tgz", + "integrity": "sha1-mXYFrSNF8n9RU5vqJldEISFcd4A=", + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/global-prefix/download/global-prefix-3.0.0.tgz", + "integrity": "sha1-/IX3MGTfafUEIfR/iD/luRO6m5c=", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npm.taobao.org/globals/download/globals-11.12.0.tgz", + "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=" + }, + "globby": { + "version": "8.0.2", + "resolved": "https://registry.npm.taobao.org/globby/download/globby-8.0.2.tgz", + "integrity": "sha1-VpdhnM2VxSdduy1vqkIIfBqUHY0=", + "requires": { + "array-union": "^1.0.1", + "dir-glob": "2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npm.taobao.org/ignore/download/ignore-3.3.10.tgz?cache=0&sync_timestamp=1590809289115&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fignore%2Fdownload%2Fignore-3.3.10.tgz", + "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1588086924019&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz", + "integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/growly/download/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" + }, + "gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/gzip-size/download/gzip-size-5.1.1.tgz", + "integrity": "sha1-y5vuaS+HwGErIyhAqHOQTkwTUnQ=", + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=" + } + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/handle-thing/download/handle-thing-2.0.1.tgz", + "integrity": "sha1-hX95zjWVgMNA1DCBzGSJcNC7I04=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.3.tgz", + "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "harmony-reflect": { + "version": "1.6.1", + "resolved": "https://registry.npm.taobao.org/harmony-reflect/download/harmony-reflect-1.6.1.tgz", + "integrity": "sha1-wQjU8rtFHv73o3hh/b2ucsm976k=" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz?cache=0&sync_timestamp=1568144153016&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-ansi%2Fdownload%2Fhas-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.1.tgz?cache=0&sync_timestamp=1573950719586&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-symbols%2Fdownload%2Fhas-symbols-1.0.1.tgz", + "integrity": "sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/hash-base/download/hash-base-3.1.0.tgz", + "integrity": "sha1-VcOB2eBuHSmXqIO0o/3f5/DTrzM=", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=" + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npm.taobao.org/hash.js/download/hash.js-1.1.7.tgz", + "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz", + "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=" + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/hex-color-regex/download/hex-color-regex-1.1.0.tgz", + "integrity": "sha1-TAb8y0YC/iYCs8k9+C1+fb8aio4=" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npm.taobao.org/hoist-non-react-statics/download/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha1-7OCsr3HWLClpwuxZ/v9CpLGoW0U=", + "requires": { + "react-is": "^16.7.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.8.tgz?cache=0&sync_timestamp=1583044512484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhosted-git-info%2Fdownload%2Fhosted-git-info-2.8.8.tgz", + "integrity": "sha1-dTm9S8Hg4KiVgVouAmJCCxKFhIg=" + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/hsl-regex/download/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=" + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/hsla-regex/download/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/html-comment-regex/download/html-comment-regex-1.1.2.tgz", + "integrity": "sha1-l9RoiutcgYhqNk+qDK0d2hTUM6c=" + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/html-encoding-sniffer/download/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha1-5w2EuU2lOqN14R/jo1G+ZkLKRvg=", + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/html-entities/download/html-entities-1.3.1.tgz?cache=0&sync_timestamp=1586616304085&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtml-entities%2Fdownload%2Fhtml-entities-1.3.1.tgz", + "integrity": "sha1-+5oaS1sUxdq6gtPjTGrk/nAaDkQ=" + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/html-escaper/download/html-escaper-2.0.2.tgz", + "integrity": "sha1-39YAJ9o2o238viNiYsAKWCJoFFM=" + }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/html-minifier-terser/download/html-minifier-terser-5.1.1.tgz", + "integrity": "sha1-ki6W8fO7YIMsJjS3mIQJY4mx8FQ=", + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-4.1.1.tgz", + "integrity": "sha1-n9YCvZNilOnp70aj9NaWQESxgGg=" + } + } + }, + "html-webpack-plugin": { + "version": "4.0.0-beta.11", + "resolved": "https://registry.npm.taobao.org/html-webpack-plugin/download/html-webpack-plugin-4.0.0-beta.11.tgz?cache=0&sync_timestamp=1588268193119&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtml-webpack-plugin%2Fdownload%2Fhtml-webpack-plugin-4.0.0-beta.11.tgz", + "integrity": "sha1-MFmmkUS1rs75dwgZbKMvnmhndxU=", + "requires": { + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.15", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + }, + "dependencies": { + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.0.tgz", + "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + } + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz", + "integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fentities%2Fdownload%2Fentities-1.1.2.tgz", + "integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=" + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npm.taobao.org/http-deceiver/download/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.2.tgz", + "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "http-parser-js": { + "version": "0.5.2", + "resolved": "https://registry.npm.taobao.org/http-parser-js/download/http-parser-js-0.5.2.tgz?cache=0&sync_timestamp=1572714277347&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-parser-js%2Fdownload%2Fhttp-parser-js-0.5.2.tgz", + "integrity": "sha1-2i4x0jezk6rnKs5DiC3X4nCo/3c=" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npm.taobao.org/http-proxy/download/http-proxy-1.18.1.tgz", + "integrity": "sha1-QBVB8FNIhLv5UmAzTnL4juOXZUk=", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha1-GDx9xKoUeRUDBkmMIQza+WCApDo=", + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/https-browserify/download/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "iconv-lite": { + "version": "0.5.1", + "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.5.1.tgz?cache=0&sync_timestamp=1579334008444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.5.1.tgz", + "integrity": "sha1-skJdPHsY9yGfLKZj0QO925FxjWQ=", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/icss-utils/download/icss-utils-4.1.1.tgz", + "integrity": "sha1-IRcLU3ie4nRHwvR91oMIFAP5pGc=", + "requires": { + "postcss": "^7.0.14" + } + }, + "identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/identity-obj-proxy/download/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ=", + "requires": { + "harmony-reflect": "^1.4.6" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npm.taobao.org/ieee754/download/ieee754-1.1.13.tgz", + "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npm.taobao.org/ignore/download/ignore-4.0.6.tgz?cache=0&sync_timestamp=1590809289115&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fignore%2Fdownload%2Fignore-4.0.6.tgz", + "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=" + }, + "immer": { + "version": "1.10.0", + "resolved": "https://registry.npm.taobao.org/immer/download/immer-1.10.0.tgz?cache=0&sync_timestamp=1590573746097&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimmer%2Fdownload%2Fimmer-1.10.0.tgz", + "integrity": "sha1-utZ2BbqcgQJ12R4cKkfUWC6YKG0=" + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/import-cwd/download/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/import-fresh/download/import-fresh-2.0.0.tgz?cache=0&sync_timestamp=1573664960772&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/import-from/download/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/import-local/download/import-local-2.0.0.tgz", + "integrity": "sha1-VQcL44pZk88Y72236WH1vuXFoJ0=", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/indent-string/download/indent-string-4.0.0.tgz", + "integrity": "sha1-Yk+PRJfWGbLZdoUx1Y9BIoVNclE=" + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/indexes-of/download/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/infer-owner/download/infer-owner-1.0.4.tgz", + "integrity": "sha1-xM78qo5RBRwqQLos6KPScpWvlGc=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npm.taobao.org/ini/download/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=" + }, + "inquirer": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/inquirer/download/inquirer-7.1.0.tgz", + "integrity": "sha1-EpigGFmIPhfHJkuChwrhA0+S3Sk=", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.2.1.tgz", + "integrity": "sha1-kK51xCTQCNJiTFvynq0xd+v881k=", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-3.0.0.tgz?cache=0&sync_timestamp=1585815759944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-3.0.0.tgz", + "integrity": "sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ=", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz", + "integrity": "sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI=", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.1.0.tgz", + "integrity": "sha1-aOMlkd9z4lrRxLSRCKLsUHliv9E=", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "insert-css": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/insert-css/download/insert-css-2.0.0.tgz", + "integrity": "sha1-610Ql7dUL0x56jBg067gfQU4gPQ=" + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/internal-ip/download/internal-ip-4.3.0.tgz", + "integrity": "sha1-hFRSuq2dLKO2nGNaE3rLmg2tCQc=", + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/internal-slot/download/internal-slot-1.0.2.tgz", + "integrity": "sha1-nC6fs82OXkJWxvRf4xAGf8+jeKM=", + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz", + "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/invert-kv/download/invert-kv-2.0.0.tgz?cache=0&sync_timestamp=1589565904735&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finvert-kv%2Fdownload%2Finvert-kv-2.0.0.tgz", + "integrity": "sha1-c5P1r6Weyf9fZ6J2INEcIm4+7AI=" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/ip-regex/download/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.9.1.tgz", + "integrity": "sha1-v/OFQ+64mEglB5/zoqjmy9RngbM=" + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/is-arguments/download/is-arguments-1.0.4.tgz", + "integrity": "sha1-P6+WbHy6D/Q3+zH2JQCC/PBEjPM=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz", + "integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz?cache=0&sync_timestamp=1588707106955&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-buffer%2Fdownload%2Fis-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.0.tgz", + "integrity": "sha1-gzNlYLVKOONeOi33r9BFTWkUaLs=" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-ci/download/is-ci-2.0.0.tgz", + "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-color-stop/download/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-date-object/download/is-date-object-1.0.2.tgz", + "integrity": "sha1-vac28s2P0G0yhE53Q7+nSUw7/X4=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-5.1.0.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-5.1.0.tgz", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npm.taobao.org/is-directory/download/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-docker/download/is-docker-2.0.0.tgz", + "integrity": "sha1-LLDfDnXi0GT+GGTDfN6st7Lc8ls=" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-generator-fn/download/is-generator-fn-2.1.0.tgz", + "integrity": "sha1-fRQK3DiarzARqPKipM+m+q3/sRg=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz", + "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-obj/download/is-obj-2.0.0.tgz", + "integrity": "sha1-Rz+wXZc3BeP9liBUUBjKjiLvSYI=" + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/is-path-cwd/download/is-path-cwd-2.2.0.tgz", + "integrity": "sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s=" + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-path-in-cwd/download/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha1-v+Lcomxp85cmWkAJljYCk1oFOss=", + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-path-inside/download/is-path-inside-2.1.0.tgz?cache=0&sync_timestamp=1569835858319&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-path-inside%2Fdownload%2Fis-path-inside-2.1.0.tgz", + "integrity": "sha1-fJgQWH1lmkDSe8201WFuqwWUlLI=", + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-plain-obj/download/is-plain-obj-1.1.0.tgz?cache=0&sync_timestamp=1579602945303&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-plain-obj%2Fdownload%2Fis-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.0.tgz", + "integrity": "sha1-7OOOOJ5JDfDcIcrqK9WW+Yf3Z/8=", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-regexp/download/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-resolvable/download/is-resolvable-1.1.0.tgz", + "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=" + }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-root/download/is-root-2.1.0.tgz", + "integrity": "sha1-gJ4YEpzxEpZEMCpPhUQDXVGYSpw=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/is-string/download/is-string-1.0.5.tgz", + "integrity": "sha1-QEk+0ZjvP/R3uMf5L2ROyCpc06Y=" + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/is-svg/download/is-svg-3.0.0.tgz?cache=0&sync_timestamp=1579236224749&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-svg%2Fdownload%2Fis-svg-3.0.0.tgz", + "integrity": "sha1-kyHb0pwhLlypnE+peUxxS8r6L3U=", + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/is-symbol/download/is-symbol-1.0.3.tgz", + "integrity": "sha1-OOEBS55jKb4N6dJKQU/XRB7GGTc=", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/is-wsl/download/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npm.taobao.org/istanbul-lib-coverage/download/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha1-Z18KtpUD+tSx2En3NrqsqAM0T0k=" + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/istanbul-lib-instrument/download/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha1-pfY9kfC7wMPkee9MXeAnM17G1jA=", + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npm.taobao.org/istanbul-lib-report/download/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha1-WoETzXRtQ8SInro2qxDn1QybTzM=", + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npm.taobao.org/istanbul-lib-source-maps/download/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha1-KEmXxIIRdS7EhiU9qX44ed77qMg=", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npm.taobao.org/istanbul-reports/download/istanbul-reports-2.2.7.tgz?cache=0&sync_timestamp=1585931692719&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fistanbul-reports%2Fdownload%2Fistanbul-reports-2.2.7.tgz", + "integrity": "sha1-XZOfYjfXtIOTzAlZ6rQM1P0FaTE=", + "requires": { + "html-escaper": "^2.0.0" + } + }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest/download/jest-24.9.0.tgz", + "integrity": "sha1-mH0pDAWgi1LFYYjBAC42jtsAcXE=", + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" + }, + "dependencies": { + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-cli/download/jest-cli-24.9.0.tgz", + "integrity": "sha1-rS3mLQdHLUGcarwwH8QyuYsQ0q8=", + "requires": { + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" + } + } + } + }, + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-changed-files/download/jest-changed-files-24.9.0.tgz", + "integrity": "sha1-CNjBXreaf6P8mCabwUtFHugvgDk=", + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-config/download/jest-config-24.9.0.tgz", + "integrity": "sha1-+xu8YMc6Rq8DWQcZ76SCXm5N0bU=", + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-diff/download/jest-diff-24.9.0.tgz", + "integrity": "sha1-kxt9DVd4obr3RSy4FuMl43JAVdo=", + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-docblock/download/jest-docblock-24.9.0.tgz?cache=0&sync_timestamp=1588614998936&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-docblock%2Fdownload%2Fjest-docblock-24.9.0.tgz", + "integrity": "sha1-eXAgGAK6Vg4cQJLMJcvt9a9ajOI=", + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-each/download/jest-each-24.9.0.tgz", + "integrity": "sha1-6y2mAuKmEImNvF8fbfO6hrVfiwU=", + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-environment-jsdom/download/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha1-SwgGx/yU+V7bNpppzCd47sK3N1s=", + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-jsdom-fourteen": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/jest-environment-jsdom-fourteen/download/jest-environment-jsdom-fourteen-1.0.1.tgz", + "integrity": "sha1-TNAEL1i0q2ZpUNllMuyy/BiPlvs=", + "requires": { + "@jest/environment": "^24.3.0", + "@jest/fake-timers": "^24.3.0", + "@jest/types": "^24.3.0", + "jest-mock": "^24.0.0", + "jest-util": "^24.0.0", + "jsdom": "^14.1.0" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-6.4.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-6.4.1.tgz", + "integrity": "sha1-Ux5Yuj9RudrLmmZGyk3r9bFMpHQ=" + }, + "jsdom": { + "version": "14.1.0", + "resolved": "https://registry.npm.taobao.org/jsdom/download/jsdom-14.1.0.tgz?cache=0&sync_timestamp=1585532008781&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsdom%2Fdownload%2Fjsdom-14.1.0.tgz", + "integrity": "sha1-kWRjtglJVrCmwXgslOOAzTDhmBs=", + "requires": { + "abab": "^2.0.0", + "acorn": "^6.0.4", + "acorn-globals": "^4.3.0", + "array-equal": "^1.0.0", + "cssom": "^0.3.4", + "cssstyle": "^1.1.1", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.0", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.1.3", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "saxes": "^3.1.9", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.5.0", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^6.1.2", + "xml-name-validator": "^3.0.0" + } + }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/parse5/download/parse5-5.1.0.tgz?cache=0&sync_timestamp=1586991218581&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse5%2Fdownload%2Fparse5-5.1.0.tgz", + "integrity": "sha1-xZNByXI/QUxFKXVWTHwApo1YrNI=" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/whatwg-url/download/whatwg-url-7.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhatwg-url%2Fdownload%2Fwhatwg-url-7.1.0.tgz", + "integrity": "sha1-wsSS8eymEpiO/T0iZr4bn8YXDQY=", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npm.taobao.org/ws/download/ws-6.2.1.tgz", + "integrity": "sha1-RC/fCkftZPWbal2P8TD0dI7VJPs=", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-environment-node/download/jest-environment-node-24.9.0.tgz", + "integrity": "sha1-Mz0tJ5b5aH8q7r8HQrUZ8zwcv9M=", + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-get-type/download/jest-get-type-24.9.0.tgz?cache=0&sync_timestamp=1588615294899&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-get-type%2Fdownload%2Fjest-get-type-24.9.0.tgz", + "integrity": "sha1-FoSgyKUPLkkBtmRK6GH1ee7S7w4=" + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-haste-map/download/jest-haste-map-24.9.0.tgz?cache=0&sync_timestamp=1588675386461&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-haste-map%2Fdownload%2Fjest-haste-map-24.9.0.tgz", + "integrity": "sha1-s4pdZCdJNOIfpBeump++t3zqrH0=", + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "dependencies": { + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz", + "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + } + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-jasmine2/download/jest-jasmine2-24.9.0.tgz", + "integrity": "sha1-H3sb0yQsF3TmKsq7NkbZavw75qA=", + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-leak-detector/download/jest-leak-detector-24.9.0.tgz", + "integrity": "sha1-tmXep8dxAMXE99/LFTtlzwfc+Wo=", + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-matcher-utils/download/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha1-9bNmHV5ijf/m3WUlHf2uDofDoHM=", + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-message-util/download/jest-message-util-24.9.0.tgz?cache=0&sync_timestamp=1588675383416&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-message-util%2Fdownload%2Fjest-message-util-24.9.0.tgz", + "integrity": "sha1-Un9UoeOA9eICqNEUmw7IcvQxGeM=", + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-mock/download/jest-mock-24.9.0.tgz?cache=0&sync_timestamp=1588702712448&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-mock%2Fdownload%2Fjest-mock-24.9.0.tgz", + "integrity": "sha1-wig1VB7jebkIZzrVEIeiGFwT8cY=", + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npm.taobao.org/jest-pnp-resolver/download/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha1-7NrmBMB3p/vHDe+21RfDwciYkjo=" + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-regex-util/download/jest-regex-util-24.9.0.tgz?cache=0&sync_timestamp=1588615314194&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-regex-util%2Fdownload%2Fjest-regex-util-24.9.0.tgz", + "integrity": "sha1-wT+zOAveIr9ldUMsST6o/jeWVjY=" + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-resolve/download/jest-resolve-24.9.0.tgz?cache=0&sync_timestamp=1588675359135&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-resolve%2Fdownload%2Fjest-resolve-24.9.0.tgz", + "integrity": "sha1-3/BMdoevNMTdflJIktnPd+XRcyE=", + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-resolve-dependencies/download/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha1-rQVRmJWcTPuopPBmxnOj8HhlB6s=", + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-runner/download/jest-runner-24.9.0.tgz", + "integrity": "sha1-V0+v29VEVcKzS0vfQ2WiOFf830I=", + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-runtime/download/jest-runtime-24.9.0.tgz", + "integrity": "sha1-nxRYOvak9zFKap2fAibhp4HI5Kw=", + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-serializer/download/jest-serializer-24.9.0.tgz?cache=0&sync_timestamp=1588615324737&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-serializer%2Fdownload%2Fjest-serializer-24.9.0.tgz", + "integrity": "sha1-5tfX75bTHouQeacUdUxdXFgojnM=" + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-snapshot/download/jest-snapshot-24.9.0.tgz", + "integrity": "sha1-7I6cpPLsDFyHro+SXPl0l7DpUbo=", + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-util/download/jest-util-24.9.0.tgz?cache=0&sync_timestamp=1588675507466&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-util%2Fdownload%2Fjest-util-24.9.0.tgz", + "integrity": "sha1-c5aBTkhTbS6Fo33j5MQx18sUAWI=", + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-3.1.0.tgz", + "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=" + } + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-validate/download/jest-validate-24.9.0.tgz?cache=0&sync_timestamp=1588675384729&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-validate%2Fdownload%2Fjest-validate-24.9.0.tgz", + "integrity": "sha1-B3XFU2DRc82FTkAYB1bU/1Le+Ks=", + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "jest-watch-typeahead": { + "version": "0.4.2", + "resolved": "https://registry.npm.taobao.org/jest-watch-typeahead/download/jest-watch-typeahead-0.4.2.tgz?cache=0&sync_timestamp=1588680156060&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-watch-typeahead%2Fdownload%2Fjest-watch-typeahead-0.4.2.tgz", + "integrity": "sha1-5b6Vlpin+iMCIppQgsSIw8h4Cko=", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.1", + "jest-regex-util": "^24.9.0", + "jest-watcher": "^24.3.0", + "slash": "^3.0.0", + "string-length": "^3.1.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/slash/download/slash-3.0.0.tgz", + "integrity": "sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ=" + }, + "string-length": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string-length/download/string-length-3.1.0.tgz", + "integrity": "sha1-EH74wjRW4Yeoq9SmEWL/SsbiWDc=", + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^5.2.0" + } + } + } + }, + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-watcher/download/jest-watcher-24.9.0.tgz", + "integrity": "sha1-S1bl0c7/AF9biOUo3Jr8jdTtKzs=", + "requires": { + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-3.2.0.tgz", + "integrity": "sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s=" + } + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/jest-worker/download/jest-worker-24.9.0.tgz?cache=0&sync_timestamp=1588614797364&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-worker%2Fdownload%2Fjest-worker-24.9.0.tgz", + "integrity": "sha1-Xb/bWy0yLphWeJgjipaXvM5ns+U=", + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz?cache=0&sync_timestamp=1586796305651&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-tokens%2Fdownload%2Fjs-tokens-4.0.0.tgz", + "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=" + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.14.0.tgz?cache=0&sync_timestamp=1590172281856&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-yaml%2Fdownload%2Fjs-yaml-3.14.0.tgz", + "integrity": "sha1-p6NBcPJqIbsWJCTYray0ETpp5II=", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npm.taobao.org/jsdom/download/jsdom-11.12.0.tgz?cache=0&sync_timestamp=1585532008781&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsdom%2Fdownload%2Fjsdom-11.12.0.tgz", + "integrity": "sha1-GoDUDd03ih3lllbp5txaO6hle8g=", + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-5.7.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-5.7.4.tgz", + "integrity": "sha1-Po2KmUfQWZoXltECJddDL0pKz14=" + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-2.5.2.tgz", + "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&sync_timestamp=1567740720822&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json-stable-stringify/download/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/json2mq/download/json2mq-0.2.0.tgz", + "integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=", + "requires": { + "string-convert": "^0.2.0" + } + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npm.taobao.org/json3/download/json3-3.3.3.tgz", + "integrity": "sha1-f8EON1/FrkLEcFpcwKpvYr4wW4E=" + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.3.tgz?cache=0&sync_timestamp=1586045666090&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-2.1.3.tgz", + "integrity": "sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM=", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz?cache=0&sync_timestamp=1583593992319&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npm.taobao.org/jsonify/download/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jsx-ast-utils": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/jsx-ast-utils/download/jsx-ast-utils-2.3.0.tgz?cache=0&sync_timestamp=1590377704686&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsx-ast-utils%2Fdownload%2Fjsx-ast-utils-2.3.0.tgz", + "integrity": "sha1-7dcneU6ihNf9pXUBXtGwzeAomrY=", + "requires": { + "array-includes": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/killable/download/killable-1.0.1.tgz", + "integrity": "sha1-TIzkQRh6Bhx0dPuHygjipjgZSJI=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/kleur/download/kleur-3.0.3.tgz", + "integrity": "sha1-p5yezIbuHOP6YgbRIWxQHxR/wH4=" + }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/last-call-webpack-plugin/download/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha1-l0LfDhDjz0blwDgcLekNOnotdVU=", + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/lazy-cache/download/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/lcid/download/lcid-2.0.0.tgz", + "integrity": "sha1-bvXS32DlL4LrIopMNz6NHzlyU88=", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/left-pad/download/left-pad-1.3.0.tgz", + "integrity": "sha1-W4o6d2Xf4AEmHd6RVYnngvjJTR4=" + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/leven/download/leven-3.1.0.tgz", + "integrity": "sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I=" + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/levenary/download/levenary-1.1.1.tgz", + "integrity": "sha1-hCqe6Y0gdap/ru2+MmeekgX0b3c=", + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flevn%2Fdownload%2Flevn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/lines-and-columns/download/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "loader-fs-cache": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/loader-fs-cache/download/loader-fs-cache-1.0.3.tgz", + "integrity": "sha1-8IZXZG1gcHi+LwoDL4vWndbyd9k=", + "requires": { + "find-cache-dir": "^0.1.1", + "mkdirp": "^0.5.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-0.1.1.tgz?cache=0&sync_timestamp=1583734591888&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-cache-dir%2Fdownload%2Ffind-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "requires": { + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "requires": { + "find-up": "^1.0.0" + } + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz", + "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=" + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.4.0.tgz?cache=0&sync_timestamp=1584445172927&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-1.4.0.tgz", + "integrity": "sha1-xXm140yzSxp07cbB+za/o3HVphM=", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&sync_timestamp=1586045666090&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.15.tgz", + "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/lodash._reinterpolate/download/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npm.taobao.org/lodash.memoize/download/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npm.taobao.org/lodash.sortby/download/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npm.taobao.org/lodash.template/download/lodash.template-4.5.0.tgz", + "integrity": "sha1-+XYZXPPzR9DV9SSDVp/oAxzM6Ks=", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/lodash.templatesettings/download/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha1-5IExDwSdPPbUfpEq0JMTsVTw+zM=", + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "log4js": { + "version": "6.3.0", + "resolved": "https://registry.npm.taobao.org/log4js/download/log4js-6.3.0.tgz", + "integrity": "sha1-EN+vu0NDUaPjAnegC5h5RG9xW8s=", + "dev": true, + "requires": { + "date-format": "^3.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.1", + "rfdc": "^1.1.4", + "streamroller": "^2.2.4" + } + }, + "loglevel": { + "version": "1.6.8", + "resolved": "https://registry.npm.taobao.org/loglevel/download/loglevel-1.6.8.tgz", + "integrity": "sha1-iiX7ddCSIw7NRFcnDYC1TigBEXE=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/loose-envify/download/loose-envify-1.4.0.tgz", + "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/lower-case/download/lower-case-2.0.1.tgz?cache=0&sync_timestamp=1575602715052&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flower-case%2Fdownload%2Flower-case-2.0.1.tgz", + "integrity": "sha1-Oe6zbjlhFcwF4pQi6uqeaSyUCMc=", + "requires": { + "tslib": "^1.10.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz", + "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", + "requires": { + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyallist%2Fdownload%2Fyallist-3.1.1.tgz", + "integrity": "sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=" + } + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz?cache=0&sync_timestamp=1587567875186&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-dir%2Fdownload%2Fmake-dir-2.1.0.tgz", + "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npm.taobao.org/makeerror/download/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "requires": { + "tmpl": "1.0.x" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npm.taobao.org/mamacro/download/mamacro-0.0.3.tgz", + "integrity": "sha1-rSyVdhl8nxq/MI0Hh4Zb2XWj8+Q=" + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npm.taobao.org/map-age-cleaner/download/map-age-cleaner-0.1.3.tgz", + "integrity": "sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo=", + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/map-visit/download/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz", + "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.4.tgz", + "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/mem/download/mem-4.3.0.tgz?cache=0&sync_timestamp=1586703910620&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmem%2Fdownload%2Fmem-4.3.0.tgz", + "integrity": "sha1-Rhr0l7xK4JYIzbLmDu+2m/90QXg=", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "merge-deep": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/merge-deep/download/merge-deep-3.0.2.tgz", + "integrity": "sha1-85+hAKTxvTT/KffSv0UI+7jYOtI=", + "requires": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/merge-stream/download/merge-stream-2.0.0.tgz", + "integrity": "sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/merge2/download/merge2-1.4.1.tgz", + "integrity": "sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "microevent.ts": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/microevent.ts/download/microevent.ts-0.1.1.tgz", + "integrity": "sha1-cLCbg/Q99RctAgWmMCW84Pc1f6A=" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/miller-rabin/download/miller-rabin-4.0.1.tgz", + "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=" + } + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-2.4.6.tgz?cache=0&sync_timestamp=1590596728112&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-2.4.6.tgz", + "integrity": "sha1-5bQHyQ20QvK+tbFiNz0Htpr/pNE=" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.44.0.tgz", + "integrity": "sha1-+hHF6wrKEzS0Izy01S8QxaYnL5I=" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.27.tgz", + "integrity": "sha1-R5SfmOJ56lMRn1ci4PNOUpvsAJ8=", + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-2.1.0.tgz", + "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=" + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/min-indent/download/min-indent-1.0.1.tgz?cache=0&sync_timestamp=1590693908857&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmin-indent%2Fdownload%2Fmin-indent-1.0.1.tgz", + "integrity": "sha1-pj9oFnOzBXH76LwlaGrnRu76mGk=" + }, + "mini-css-extract-plugin": { + "version": "0.9.0", + "resolved": "https://registry.npm.taobao.org/mini-css-extract-plugin/download/mini-css-extract-plugin-0.9.0.tgz", + "integrity": "sha1-R/LPB6oWWrNXM7H8l9TEbAVkM54=", + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "mini-store": { + "version": "3.0.5", + "resolved": "https://registry.npm.taobao.org/mini-store/download/mini-store-3.0.5.tgz", + "integrity": "sha1-GzgI7l6Bc+zcv0OwKRN+mnK7n7g=", + "requires": { + "hoist-non-react-statics": "^3.3.2", + "shallowequal": "^1.0.2" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz", + "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1584051509720&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=" + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npm.taobao.org/minipass/download/minipass-3.1.3.tgz", + "integrity": "sha1-fUL/HzljVILhX5zbUxhN7r1YFf0=", + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/minipass-collect/download/minipass-collect-1.0.2.tgz", + "integrity": "sha1-IrgTv3Rdxu26JXa5QAIq1u3Ixhc=", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/minipass-flush/download/minipass-flush-1.0.5.tgz", + "integrity": "sha1-gucTXX6JpQ/+ZGEKeHlTxMTLs3M=", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/minipass-pipeline/download/minipass-pipeline-1.2.3.tgz", + "integrity": "sha1-VfeDkwfXSFnW6K2pw+vnLOwhajQ=", + "requires": { + "minipass": "^3.0.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz", + "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz", + "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/mixin-object/download/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npm.taobao.org/for-in/download/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=" + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1588819864223&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz", + "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=", + "requires": { + "minimist": "^1.2.5" + } + }, + "moment": { + "version": "2.26.0", + "resolved": "https://registry.npm.taobao.org/moment/download/moment-2.26.0.tgz?cache=0&sync_timestamp=1589957212921&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmoment%2Fdownload%2Fmoment-2.26.0.tgz", + "integrity": "sha1-Xh+Cxrr8pug+gIswyHBe7Q3L05o=" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npm.taobao.org/multicast-dns/download/multicast-dns-6.2.3.tgz", + "integrity": "sha1-oOx72QVcQoL3kMPIL04o2zsxsik=", + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/multicast-dns-service-types/download/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.8.tgz", + "integrity": "sha1-FjDEKyJR/4HiooPelqVJfqkuXg0=" + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npm.taobao.org/nan/download/nan-2.14.1.tgz", + "integrity": "sha1-174036MQW5FJTDFHCJMV7/iHSwE=", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz", + "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/natural-compare/download/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz", + "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=" + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npm.taobao.org/neo-async/download/neo-async-2.6.1.tgz", + "integrity": "sha1-rCetpmFn+ohJpq3dg39rGJrSCBw=" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/next-tick/download/next-tick-1.0.0.tgz?cache=0&sync_timestamp=1581393811508&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnext-tick%2Fdownload%2Fnext-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz", + "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=" + }, + "no-case": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/no-case/download/no-case-3.0.3.tgz", + "integrity": "sha1-whtDTB/+SLOQh+hs+00lgunfGPg=", + "requires": { + "lower-case": "^2.0.1", + "tslib": "^1.10.0" + } + }, + "node-forge": { + "version": "0.9.0", + "resolved": "https://registry.npm.taobao.org/node-forge/download/node-forge-0.9.0.tgz?cache=0&sync_timestamp=1569524669712&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-forge%2Fdownload%2Fnode-forge-0.9.0.tgz", + "integrity": "sha1-1iQFDtu0SHStyhK7mlLsY8t4JXk=" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/node-int64/download/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/node-libs-browser/download/node-libs-browser-2.2.1.tgz", + "integrity": "sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU=", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npm.taobao.org/util/download/util-0.11.1.tgz?cache=0&sync_timestamp=1588238331562&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil%2Fdownload%2Futil-0.11.1.tgz", + "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + } + } + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/node-modules-regexp/download/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=" + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npm.taobao.org/node-notifier/download/node-notifier-5.4.3.tgz", + "integrity": "sha1-y3La+UyTkECY4oucWQ/YZuRkvVA=", + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "node-releases": { + "version": "1.1.58", + "resolved": "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.58.tgz", + "integrity": "sha1-juIO7zD6YOUnVfzAlC3vWnNP6TU=" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz", + "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" + } + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/normalize-range/download/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/normalize-url/download/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz", + "integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=", + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npm.taobao.org/num2fraction/download/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/nwsapi/download/nwsapi-2.2.0.tgz?cache=0&sync_timestamp=1572824577484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnwsapi%2Fdownload%2Fnwsapi-2.2.0.tgz", + "integrity": "sha1-IEh5qePQaP8qVROcLHcngGgaOLc=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz", + "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-hash": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/object-hash/download/object-hash-2.0.3.tgz", + "integrity": "sha1-0S2wROA80so9d8BXDYciWwLh5uo=" + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/object-inspect/download/object-inspect-1.7.0.tgz?cache=0&sync_timestamp=1573451929207&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-inspect%2Fdownload%2Fobject-inspect-1.7.0.tgz", + "integrity": "sha1-9Pa9GBrXfwBrXs5gvQtvOY/3Smc=" + }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/object-is/download/object-is-1.1.2.tgz", + "integrity": "sha1-xdLof/nhGfeLegiEQVGeLuwVc7Y=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/object-keys/download/object-keys-1.1.1.tgz", + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=" + }, + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npm.taobao.org/object-path/download/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/object.assign/download/object.assign-4.1.0.tgz", + "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/object.entries/download/object.entries-1.1.2.tgz?cache=0&sync_timestamp=1590009612950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject.entries%2Fdownload%2Fobject.entries-1.1.2.tgz", + "integrity": "sha1-vHPwCstra7FsIDQ0sQ+afnl9Ot0=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/object.fromentries/download/object.fromentries-2.0.2.tgz?cache=0&sync_timestamp=1576176796889&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject.fromentries%2Fdownload%2Fobject.fromentries-2.0.2.tgz", + "integrity": "sha1-SgnJubs4Q90PiazbUXp5TU81Wsk=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/object.getownpropertydescriptors/download/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha1-Npvx+VktiridcS3O1cuBx8U1Jkk=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/object.values/download/object.values-1.1.1.tgz", + "integrity": "sha1-aKmezeNWt+kpWjxeDOMdyMlT3l4=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/obuf/download/obuf-1.1.2.tgz", + "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=" + }, + "omit.js": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/omit.js/download/omit.js-1.0.2.tgz", + "integrity": "sha1-kaFPDrqEBm36AVvzDkdMR/MLyFg=", + "requires": { + "babel-runtime": "^6.23.0" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/on-headers/download/on-headers-1.0.2.tgz", + "integrity": "sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/onetime/download/onetime-5.1.0.tgz", + "integrity": "sha1-//DzyRYX/mK7UBiWNumayKbfe+U=", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "7.0.4", + "resolved": "https://registry.npm.taobao.org/open/download/open-7.0.4.tgz", + "integrity": "sha1-woqdMV5cmDQL+Xn9yy5YZkqhDYM=", + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "dependencies": { + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/is-wsl/download/is-wsl-2.2.0.tgz", + "integrity": "sha1-dKTHbnfKn9P5MvKQwX6jJs0VcnE=", + "requires": { + "is-docker": "^2.0.0" + } + } + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npm.taobao.org/opn/download/opn-5.5.0.tgz", + "integrity": "sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w=", + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optimize-css-assets-webpack-plugin": { + "version": "5.0.3", + "resolved": "https://registry.npm.taobao.org/optimize-css-assets-webpack-plugin/download/optimize-css-assets-webpack-plugin-5.0.3.tgz", + "integrity": "sha1-4vHU2UrYwK+JZ+vXzxONyx7xRXI=", + "requires": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npm.taobao.org/optionator/download/optionator-0.8.3.tgz?cache=0&sync_timestamp=1585966141328&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Foptionator%2Fdownload%2Foptionator-0.8.3.tgz", + "integrity": "sha1-hPodA2/p08fiHZmIS2ARZ+yPtJU=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/original/download/original-1.0.2.tgz", + "integrity": "sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8=", + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/os-browserify/download/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/os-locale/download/os-locale-3.1.0.tgz?cache=0&sync_timestamp=1584865550362&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fos-locale%2Fdownload%2Fos-locale-3.1.0.tgz", + "integrity": "sha1-qAKm7hfyTBBIOrmTVxnO9O0Wvxo=", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-defer/download/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-each-series/download/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz?cache=0&sync_timestamp=1560955759606&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-finally%2Fdownload%2Fp-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/p-is-promise/download/p-is-promise-2.1.0.tgz", + "integrity": "sha1-kYzrrqJIpiz3/6uOO8qMX4gvxC4=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-1.3.0.tgz", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-map/download/p-map-3.0.0.tgz", + "integrity": "sha1-1wTZr4orpoTiYA2aIVmD1BQal50=", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-reduce/download/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/p-retry/download/p-retry-3.0.1.tgz", + "integrity": "sha1-MWtMiJPiyNwc+okfQGxLQivr8yg=", + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npm.taobao.org/pako/download/pako-1.0.11.tgz", + "integrity": "sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8=" + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/parallel-transform/download/parallel-transform-1.2.0.tgz", + "integrity": "sha1-kEnKN9bLIYLDsdLHIL6U0UpYFPw=", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "param-case": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/param-case/download/param-case-3.0.3.tgz", + "integrity": "sha1-S+Qfg5nv9iHFbuu4KaXkUdmAEjg=", + "requires": { + "dot-case": "^3.0.3", + "tslib": "^1.10.0" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/parent-module/download/parent-module-1.0.1.tgz", + "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=", + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-3.1.0.tgz", + "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=" + } + } + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npm.taobao.org/parse-asn1/download/parse-asn1-5.1.5.tgz", + "integrity": "sha1-ADJxND2ljclMrOSU+u89IUfs6g4=", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/parse5/download/parse5-4.0.0.tgz?cache=0&sync_timestamp=1586991218581&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse5%2Fdownload%2Fparse5-4.0.0.tgz", + "integrity": "sha1-bXhlbj2o14tOwLkG98CO8d/j9gg=" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz", + "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=" + }, + "pascal-case": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/pascal-case/download/pascal-case-3.1.1.tgz", + "integrity": "sha1-WsGXUTPtYZKB6Ikglz0s0fJ53l8=", + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npm.taobao.org/path-browserify/download/path-browserify-0.0.1.tgz", + "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/path-is-inside/download/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz?cache=0&sync_timestamp=1574442298523&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-key%2Fdownload%2Fpath-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz", + "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-3.0.0.tgz", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", + "requires": { + "pify": "^3.0.0" + } + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/pbkdf2/download/pbkdf2-3.1.1.tgz", + "integrity": "sha1-y4cksPramEWWhW0abrr9NYRlS5Q=", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz", + "integrity": "sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/pirates/download/pirates-4.0.1.tgz", + "integrity": "sha1-ZDqSyviUVm+RsrmG0sZpUKji+4c=", + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz", + "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + } + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-up/download/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "requires": { + "find-up": "^2.1.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/pn/download/pn-1.1.0.tgz", + "integrity": "sha1-4vTO8OIZ9GPBeas3Rj5OHs3Muvs=" + }, + "pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npm.taobao.org/pnp-webpack-plugin/download/pnp-webpack-plugin-1.6.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpnp-webpack-plugin%2Fdownload%2Fpnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha1-yXEaxNxIpoXauvyG+Lbdn434QUk=", + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "portfinder": { + "version": "1.0.26", + "resolved": "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.26.tgz", + "integrity": "sha1-R1ZY1WyjC+1yrH8TeO01C9G2TnA=", + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "7.0.32", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-7.0.32.tgz", + "integrity": "sha1-QxDW7jRwU9o0M9sr5JKIPWLOxZ0=", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-attribute-case-insensitive/download/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha1-2T5GtQRYnpSscnewRjImxoBBqIA=", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" + } + }, + "postcss-browser-comments": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-browser-comments/download/postcss-browser-comments-3.0.0.tgz", + "integrity": "sha1-EkjS2TX7cgU8jh9hqEpXKS2fZek=", + "requires": { + "postcss": "^7" + } + }, + "postcss-calc": { + "version": "7.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-calc/download/postcss-calc-7.0.2.tgz?cache=0&sync_timestamp=1582015512279&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-calc%2Fdownload%2Fpostcss-calc-7.0.2.tgz", + "integrity": "sha1-UE780AjKAnMSBWiweSsWzc3oqsE=", + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-color-functional-notation/download/postcss-color-functional-notation-2.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-color-functional-notation%2Fdownload%2Fpostcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha1-Xv03qI+6vrAKKWbR5T2Yztk/dOA=", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-color-gray/download/postcss-color-gray-5.0.0.tgz", + "integrity": "sha1-Uyox65CfjaiYzv/ilv3B+GS+hUc=", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-color-hex-alpha/download/postcss-color-hex-alpha-5.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-color-hex-alpha%2Fdownload%2Fpostcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha1-qNnKTDnUl8lmHjdLnFGJnvD4c4g=", + "requires": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + } + }, + "postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-color-mod-function/download/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha1-gWuhRawRzDy2uqkFp1pJ+QPk0x0=", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-color-rebeccapurple/download/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha1-x6ib6HK7dORbHjAiv+V0iCPm3nc=", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-colormin/download/postcss-colormin-4.0.3.tgz", + "integrity": "sha1-rgYLzpPteUrHEmTwgTLVUJVr04E=", + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-convert-values/download/postcss-convert-values-4.0.1.tgz", + "integrity": "sha1-yjgT7U2g+BL51DcDWE5Enr4Ymn8=", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npm.taobao.org/postcss-custom-media/download/postcss-custom-media-7.0.8.tgz", + "integrity": "sha1-//0T/+/61zYhvl84cHaiiwApTgw=", + "requires": { + "postcss": "^7.0.14" + } + }, + "postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npm.taobao.org/postcss-custom-properties/download/postcss-custom-properties-8.0.11.tgz?cache=0&sync_timestamp=1582211711757&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-custom-properties%2Fdownload%2Fpostcss-custom-properties-8.0.11.tgz", + "integrity": "sha1-LWF3LW6S8i9eDVJgLfj65G+jDZc=", + "requires": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + } + }, + "postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-custom-selectors/download/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha1-ZIWMbrLs/y+0HQsoyd17PbTef7o=", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-2.0.0.tgz", + "integrity": "sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM=" + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-5.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-5.0.0.tgz", + "integrity": "sha1-JJBENWaXsztk8aj3yAki3d7nGVw=", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-dir-pseudo-class/download/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha1-bjpBd9Dts6vMhf22+7HCbauuq6I=", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-2.0.0.tgz", + "integrity": "sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM=" + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-5.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-5.0.0.tgz", + "integrity": "sha1-JJBENWaXsztk8aj3yAki3d7nGVw=", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-discard-comments/download/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha1-H7q9LCRr/2qq15l7KwkY9NevQDM=", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-discard-duplicates/download/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha1-P+EzzTyCKC5VD8myORdqkge3hOs=", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-discard-empty/download/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha1-yMlR6fc+2UKAGUWERKAq2Qu592U=", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-discard-overridden/download/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha1-ZSrvipZybwKfXj4AFG7npOdV/1c=", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-double-position-gradients/download/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha1-/JJ9Uv3ciWyzooEuvF3xR+EQUi4=", + "requires": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-env-function/download/postcss-env-function-2.0.2.tgz", + "integrity": "sha1-Dz49PFfwlKksK69LYkHwsNpTZdc=", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-flexbugs-fixes": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/postcss-flexbugs-fixes/download/postcss-flexbugs-fixes-4.1.0.tgz", + "integrity": "sha1-4JSp3xeD4iALexn4ddytOzr/iyA=", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-focus-visible/download/postcss-focus-visible-4.0.0.tgz?cache=0&sync_timestamp=1586839653287&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-focus-visible%2Fdownload%2Fpostcss-focus-visible-4.0.0.tgz", + "integrity": "sha1-R30QcROt5gJLFBKDF63ivR4XBG4=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-focus-within/download/postcss-focus-within-3.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-focus-within%2Fdownload%2Fpostcss-focus-within-3.0.0.tgz", + "integrity": "sha1-djuHiFls7puHTJmSAc3egGWe9oA=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-font-variant": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-font-variant/download/postcss-font-variant-4.0.0.tgz", + "integrity": "sha1-cd08bBCg2EbF7aB4A0OWF7u6usw=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-gap-properties/download/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha1-QxwZKrPtlqPD0J8v9hWWD5AsFxU=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-image-set-function/download/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha1-KJIKLymUW+1MMZjX32SW1BDT8og=", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-initial": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-initial/download/postcss-initial-3.0.2.tgz?cache=0&sync_timestamp=1572520300770&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-initial%2Fdownload%2Fpostcss-initial-3.0.2.tgz", + "integrity": "sha1-8BhWNpSzwWro6qvjxYWsYxljey0=", + "requires": { + "lodash.template": "^4.5.0", + "postcss": "^7.0.2" + } + }, + "postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-lab-function/download/postcss-lab-function-2.0.1.tgz?cache=0&sync_timestamp=1587794511164&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-lab-function%2Fdownload%2Fpostcss-lab-function-2.0.1.tgz", + "integrity": "sha1-u1GmhWzRIomrSuINseOCHvE9fS4=", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/postcss-load-config/download/postcss-load-config-2.1.0.tgz", + "integrity": "sha1-yE1pK3u3tB3c7ZTuYuirMbQXsAM=", + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-loader/download/postcss-loader-3.0.0.tgz", + "integrity": "sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0=", + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-logical/download/postcss-logical-3.0.0.tgz", + "integrity": "sha1-JJXQ+LgunyYnJfdflAGzTntF1bU=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-media-minmax/download/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha1-t1u2y8IXyKxJQz4S8iBIgUpPXtU=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npm.taobao.org/postcss-merge-longhand/download/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha1-YvSaE+Sg7gTnuY9CuxYGLKJUniQ=", + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-merge-rules/download/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha1-NivqT/Wh+Y5AdacTxsslrv75plA=", + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz", + "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-font-values/download/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha1-zUw0TM5HQ0P6xdgiBqssvLiv1aY=", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-gradients/download/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha1-k7KcL/UJnFNe7NpWxKpuZlpmNHE=", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-params/download/postcss-minify-params-4.0.2.tgz", + "integrity": "sha1-a5zvAwwR41Jh+V9hjJADbWgNuHQ=", + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-minify-selectors/download/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha1-4uXrQL/uUA0M2SQ1APX46kJi+9g=", + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz", + "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-extract-imports/download/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha1-gYcZoa4doyX5gyRGsBE27rSTzX4=", + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-3.0.2.tgz", + "integrity": "sha1-6KZWG+kUqvPAUodjd1JMqQ27eRU=", + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-2.2.0.tgz?cache=0&sync_timestamp=1584619207390&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-scope%2Fdownload%2Fpostcss-modules-scope-2.2.0.tgz", + "integrity": "sha1-OFyuATzHdD9afXYC0Qc6iequYu4=", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-values/download/postcss-modules-values-3.0.0.tgz", + "integrity": "sha1-W1AA1uuuKbQlUwG0o6VFdEI+fxA=", + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-nesting/download/postcss-nesting-7.0.1.tgz", + "integrity": "sha1-tQrXt/AXPlteOIDDUBNEcD4EwFI=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-normalize": { + "version": "8.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-normalize/download/postcss-normalize-8.0.1.tgz", + "integrity": "sha1-kOgKd2PX/fLaby8Pgr6DLOT2Z3Y=", + "requires": { + "@csstools/normalize.css": "^10.1.0", + "browserslist": "^4.6.2", + "postcss": "^7.0.17", + "postcss-browser-comments": "^3.0.0", + "sanitize.css": "^10.0.0" + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-charset/download/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha1-izWt067oOhNrBHHg1ZvlilAoXdQ=", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-display-values/download/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha1-Db4EpM6QY9RmftK+R2u4MMglk1o=", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-positions/download/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha1-BfdX+E8mBDc3g2ipH4ky1LECkX8=", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-repeat-style/download/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha1-xOu8KJ85kaAo1EdRy90RkYsXkQw=", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-string/download/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha1-zUTECrB6DHo23F6Zqs4eyk7CaQw=", + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-timing-functions/download/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha1-jgCcoqOUnNr4rSPmtquZy159KNk=", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-unicode/download/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha1-hBvUj9zzAZrUuqdJOj02O1KuHPs=", + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-url/download/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha1-EOQ3+GvHx+WPe5ZS7YeNqqlfquE=", + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/normalize-url/download/normalize-url-3.3.0.tgz", + "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=" + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-normalize-whitespace/download/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha1-vx1AcP5Pzqh9E0joJdjMDF+qfYI=", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-ordered-values/download/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha1-DPdcgg7H1cTSgBiVWeC1ceusDu4=", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-overflow-shorthand/download/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha1-MezzUOnG9t3CUKePDD4RHzLdTDA=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-page-break/download/postcss-page-break-2.0.0.tgz", + "integrity": "sha1-rdUtDgpSjKvmr+6LRuKrsnffRr8=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-place/download/postcss-place-4.0.1.tgz", + "integrity": "sha1-6fOdM9LcWE5G7h20Wtt3yp0dzGI=", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } + }, + "postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npm.taobao.org/postcss-preset-env/download/postcss-preset-env-6.7.0.tgz", + "integrity": "sha1-w03az4+QI4OzWtHgMPF49M3xGKU=", + "requires": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + } + }, + "postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-pseudo-class-any-link/download/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha1-LtPu05OzcCh53sSocDKyENrrBNE=", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-2.0.0.tgz", + "integrity": "sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM=" + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-5.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-5.0.0.tgz", + "integrity": "sha1-JJBENWaXsztk8aj3yAki3d7nGVw=", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/postcss-reduce-initial/download/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha1-f9QuvqXpyBRgljniwuhK4nC6SN8=", + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-reduce-transforms/download/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha1-F++kBerMbge+NBSlyi0QdGgdTik=", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-replace-overflow-wrap/download/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha1-YbNg/9rtyoTHyRjSsPDQ6lWasBw=", + "requires": { + "postcss": "^7.0.2" + } + }, + "postcss-safe-parser": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-safe-parser/download/postcss-safe-parser-4.0.1.tgz", + "integrity": "sha1-h1bZ5MNv3OLHKwkbvIyhdqsfzeo=", + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-selector-matches/download/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha1-ccgkj5F7osyTA3yWN+4JxkQ2/P8=", + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "postcss-selector-not": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-selector-not/download/postcss-selector-not-4.0.0.tgz", + "integrity": "sha1-xo/3upZSdJnoMnJKJnTWVgO2RcA=", + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-6.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-6.0.2.tgz", + "integrity": "sha1-k0z3mdAWyDQRhZ4J3Oyt4BKG7Fw=", + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/postcss-svgo/download/postcss-svgo-4.0.2.tgz", + "integrity": "sha1-F7mXvHEbMzurFDqu07jT1uPTglg=", + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz", + "integrity": "sha1-n/giVH4okyE88cMO+lGsX9G6goE=" + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-unique-selectors/download/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha1-lEaRHzKJv9ZMbWgPBzwDsfnuS6w=", + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.1.0.tgz", + "integrity": "sha1-RD9qIM7WSBor2k+oUypuVdeJoss=" + }, + "postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/postcss-values-parser/download/postcss-values-parser-2.0.1.tgz", + "integrity": "sha1-2otHLZAdoeIFtHvcmGN7np5VDl8=", + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/prepend-http/download/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "pretty-bytes": { + "version": "5.3.0", + "resolved": "https://registry.npm.taobao.org/pretty-bytes/download/pretty-bytes-5.3.0.tgz", + "integrity": "sha1-8oSeJ9t5+01s/iR2T8QTTxZZifI=" + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/pretty-error/download/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "requires": { + "renderkid": "^2.0.1", + "utila": "~0.4" + } + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npm.taobao.org/pretty-format/download/pretty-format-24.9.0.tgz?cache=0&sync_timestamp=1588675385734&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-format%2Fdownload%2Fpretty-format-24.9.0.tgz", + "integrity": "sha1-EvrDGzcBmk7qPBGqmpWet2KKp8k=", + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npm.taobao.org/private/download/private-0.1.8.tgz", + "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/progress/download/progress-2.0.3.tgz", + "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=" + }, + "promise": { + "version": "8.1.0", + "resolved": "https://registry.npm.taobao.org/promise/download/promise-8.1.0.tgz", + "integrity": "sha1-aXwlw9/nQ13Xn81Yw4oTWIjq8F4=", + "requires": { + "asap": "~2.0.6" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/promise-inflight/download/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "prompts": { + "version": "2.3.2", + "resolved": "https://registry.npm.taobao.org/prompts/download/prompts-2.3.2.tgz", + "integrity": "sha1-SAVy2J7POVZtK9P+LJ/Mt8TAsGg=", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.4" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npm.taobao.org/prop-types/download/prop-types-15.7.2.tgz", + "integrity": "sha1-UsQedbjIfnK52TYOAga5ncv/psU=", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.6.tgz", + "integrity": "sha1-/cIzZQVEfT8vLGOO0nLK9hS7sr8=", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz?cache=0&sync_timestamp=1585170332277&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpsl%2Fdownload%2Fpsl-1.8.0.tgz", + "integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ=" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/public-encrypt/download/public-encrypt-4.0.3.tgz", + "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.11.9.tgz", + "integrity": "sha1-JtVWgpRY+dHoH8SJUkk9C6NQeCg=" + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz", + "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/pumpify/download/pumpify-1.5.1.tgz?cache=0&sync_timestamp=1569938272548&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpumpify%2Fdownload%2Fpumpify-1.5.1.tgz", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz", + "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fq%2Fdownload%2Fq-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz", + "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npm.taobao.org/query-string/download/query-string-4.3.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fquery-string%2Fdownload%2Fquery-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/querystring-es3/download/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/querystringify/download/querystringify-2.1.1.tgz", + "integrity": "sha1-YOWl/WSn+L+k0qsu1v30yFutFU4=" + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz", + "integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=", + "requires": { + "performance-now": "^2.1.0" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz", + "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/randomfill/download/randomfill-1.0.4.tgz", + "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz", + "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.0.tgz", + "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz", + "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1579334008444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "rc-align": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/rc-align/download/rc-align-4.0.0.tgz", + "integrity": "sha1-elshIFG92EC0BqatVHB2U0qENpE=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "dom-align": "^1.7.0", + "rc-util": "^5.0.1", + "resize-observer-polyfill": "^1.5.1" + } + }, + "rc-animate": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/rc-animate/download/rc-animate-3.1.0.tgz", + "integrity": "sha1-BRtonCxxlOTIrgFtMqDl+d5si6o=", + "requires": { + "@ant-design/css-animation": "^1.7.2", + "classnames": "^2.2.6", + "raf": "^3.4.0", + "rc-util": "^5.0.1" + } + }, + "rc-cascader": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/rc-cascader/download/rc-cascader-1.2.0.tgz", + "integrity": "sha1-RryQRK854TlLle2E700Tl648jeA=", + "requires": { + "array-tree-filter": "^2.1.0", + "rc-trigger": "^4.0.0", + "rc-util": "^5.0.1", + "warning": "^4.0.1" + } + }, + "rc-checkbox": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/rc-checkbox/download/rc-checkbox-2.2.0.tgz", + "integrity": "sha1-oM6Vw08F4OuIJmQXRRjNS6o23Ok=", + "requires": { + "babel-runtime": "^6.23.0", + "classnames": "2.x" + } + }, + "rc-collapse": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/rc-collapse/download/rc-collapse-2.0.0.tgz?cache=0&sync_timestamp=1588909102953&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-collapse%2Fdownload%2Frc-collapse-2.0.0.tgz", + "integrity": "sha1-CMWUL4IAW0NCztAtmDWB5MQc0yQ=", + "requires": { + "@ant-design/css-animation": "^1.7.2", + "classnames": "2.x", + "rc-animate": "3.x", + "react-is": "^16.7.0", + "shallowequal": "^1.1.0" + } + }, + "rc-dialog": { + "version": "8.0.0", + "resolved": "https://registry.npm.taobao.org/rc-dialog/download/rc-dialog-8.0.0.tgz", + "integrity": "sha1-/gZYrZ6e3bvav5G6YQTjnB6fkZU=", + "requires": { + "babel-runtime": "6.x", + "rc-animate": "3.x", + "rc-util": "^5.0.1" + } + }, + "rc-drawer": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/rc-drawer/download/rc-drawer-4.0.1.tgz?cache=0&sync_timestamp=1591272388742&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-drawer%2Fdownload%2Frc-drawer-4.0.1.tgz", + "integrity": "sha1-6xNQUCGogiOA+ZBLDlxm4pG7m2Q=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.0.1" + } + }, + "rc-dropdown": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/rc-dropdown/download/rc-dropdown-3.1.2.tgz", + "integrity": "sha1-UZm9UyrIUZgTo0fRlKtLDO5wIzM=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-trigger": "^4.0.0" + } + }, + "rc-field-form": { + "version": "1.4.4", + "resolved": "https://registry.npm.taobao.org/rc-field-form/download/rc-field-form-1.4.4.tgz?cache=0&sync_timestamp=1590932213547&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-field-form%2Fdownload%2Frc-field-form-1.4.4.tgz", + "integrity": "sha1-NonRmorNK7n+f/QydbxCFw1i8g0=", + "requires": { + "@babel/runtime": "^7.8.4", + "async-validator": "^3.0.3", + "rc-util": "^5.0.0" + } + }, + "rc-input-number": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/rc-input-number/download/rc-input-number-5.0.1.tgz", + "integrity": "sha1-uvvqEVFv3DSuMJ3Va5mrEatryb8=", + "requires": { + "classnames": "^2.2.0", + "rc-util": "^5.0.1" + } + }, + "rc-mentions": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/rc-mentions/download/rc-mentions-1.2.0.tgz?cache=0&sync_timestamp=1590767787673&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-mentions%2Fdownload%2Frc-mentions-1.2.0.tgz", + "integrity": "sha1-VDR6w8aZMYr58UgorK0BLzLNUc0=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-menu": "^8.0.1", + "rc-trigger": "^4.3.0", + "rc-util": "^5.0.1" + } + }, + "rc-menu": { + "version": "8.3.1", + "resolved": "https://registry.npm.taobao.org/rc-menu/download/rc-menu-8.3.1.tgz?cache=0&sync_timestamp=1590904662279&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-menu%2Fdownload%2Frc-menu-8.3.1.tgz", + "integrity": "sha1-Gujyd5LeRzTSnS7DU0EIge5loAw=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "mini-store": "^3.0.1", + "rc-animate": "^3.1.0", + "rc-trigger": "^4.2.0", + "rc-util": "^5.0.1", + "resize-observer-polyfill": "^1.5.0", + "shallowequal": "^1.1.0" + } + }, + "rc-notification": { + "version": "4.4.0", + "resolved": "https://registry.npm.taobao.org/rc-notification/download/rc-notification-4.4.0.tgz?cache=0&sync_timestamp=1590765018666&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-notification%2Fdownload%2Frc-notification-4.4.0.tgz", + "integrity": "sha1-GS0ILNbimVcF9DxpKRYmMccePbE=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-animate": "3.x", + "rc-util": "^5.0.1" + } + }, + "rc-pagination": { + "version": "2.2.5", + "resolved": "https://registry.npm.taobao.org/rc-pagination/download/rc-pagination-2.2.5.tgz", + "integrity": "sha1-QNZ1wG1gQJm+kYMbAZyhn0DBmZ0=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1" + } + }, + "rc-picker": { + "version": "1.6.2", + "resolved": "https://registry.npm.taobao.org/rc-picker/download/rc-picker-1.6.2.tgz", + "integrity": "sha1-X/aL1rDEp4RkBX0/L5HDwNud9eQ=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "moment": "^2.24.0", + "rc-trigger": "^4.0.0", + "rc-util": "^5.0.1", + "shallowequal": "^1.1.0" + } + }, + "rc-progress": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/rc-progress/download/rc-progress-3.0.0.tgz?cache=0&sync_timestamp=1589511750860&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-progress%2Fdownload%2Frc-progress-3.0.0.tgz", + "integrity": "sha1-zqMkzo/DFCHNgV2UpGSaiin4+Ns=", + "requires": { + "classnames": "^2.2.6" + } + }, + "rc-rate": { + "version": "2.7.0", + "resolved": "https://registry.npm.taobao.org/rc-rate/download/rc-rate-2.7.0.tgz?cache=0&sync_timestamp=1590828370148&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-rate%2Fdownload%2Frc-rate-2.7.0.tgz", + "integrity": "sha1-SkNtwrcjl5aPTT3zdCcEiIo5URI=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + } + }, + "rc-resize-observer": { + "version": "0.2.3", + "resolved": "https://registry.npm.taobao.org/rc-resize-observer/download/rc-resize-observer-0.2.3.tgz", + "integrity": "sha1-gmgoTRdm0WMkCxaCZhrntZvEUj0=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.0", + "resize-observer-polyfill": "^1.5.1" + } + }, + "rc-select": { + "version": "11.0.0", + "resolved": "https://registry.npm.taobao.org/rc-select/download/rc-select-11.0.0.tgz?cache=0&sync_timestamp=1591423699778&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-select%2Fdownload%2Frc-select-11.0.0.tgz", + "integrity": "sha1-S+NfcMu3VdnGkc6P+GoEDfRlv0I=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-animate": "^3.0.0", + "rc-trigger": "^4.3.0", + "rc-util": "^5.0.1", + "rc-virtual-list": "^1.1.2", + "warning": "^4.0.3" + } + }, + "rc-slider": { + "version": "9.3.0", + "resolved": "https://registry.npm.taobao.org/rc-slider/download/rc-slider-9.3.0.tgz?cache=0&sync_timestamp=1590765874201&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-slider%2Fdownload%2Frc-slider-9.3.0.tgz", + "integrity": "sha1-iMhS3iUy9IgBIIevtrW8hQa55DE=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-tooltip": "^4.0.0", + "rc-util": "^5.0.0", + "shallowequal": "^1.1.0" + } + }, + "rc-steps": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/rc-steps/download/rc-steps-4.0.0.tgz", + "integrity": "sha1-/ukX10n+Gha8ySDtwJikOeGRF3Q=", + "requires": { + "@babel/runtime": "^7.10.2", + "classnames": "^2.2.3", + "rc-util": "^5.0.1" + } + }, + "rc-switch": { + "version": "3.2.0", + "resolved": "https://registry.npm.taobao.org/rc-switch/download/rc-switch-3.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-switch%2Fdownload%2Frc-switch-3.2.0.tgz", + "integrity": "sha1-qja7QXQJ/0zH1ULsQ4HLXYfP7cE=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.1" + } + }, + "rc-table": { + "version": "7.7.2", + "resolved": "https://registry.npm.taobao.org/rc-table/download/rc-table-7.7.2.tgz", + "integrity": "sha1-e2ef9ZGtFRSEL/L/2ki50758sVs=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "raf": "^3.4.1", + "rc-resize-observer": "^0.2.0", + "rc-util": "^5.0.0", + "shallowequal": "^1.1.0" + } + }, + "rc-tabs": { + "version": "11.3.1", + "resolved": "https://registry.npm.taobao.org/rc-tabs/download/rc-tabs-11.3.1.tgz", + "integrity": "sha1-Zj1i+lJkDDbihZUHibxqpeafaGE=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "raf": "^3.4.1", + "rc-dropdown": "^3.1.0", + "rc-menu": "^8.2.1", + "rc-resize-observer": "^0.2.1", + "rc-trigger": "^4.2.1", + "rc-util": "^5.0.0" + } + }, + "rc-tooltip": { + "version": "4.2.1", + "resolved": "https://registry.npm.taobao.org/rc-tooltip/download/rc-tooltip-4.2.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tooltip%2Fdownload%2Frc-tooltip-4.2.1.tgz", + "integrity": "sha1-waLVAX7gOncakwHA39tG39+P75Q=", + "requires": { + "rc-trigger": "^4.2.1" + } + }, + "rc-tree": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/rc-tree/download/rc-tree-3.3.0.tgz?cache=0&sync_timestamp=1590768419935&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tree%2Fdownload%2Frc-tree-3.3.0.tgz", + "integrity": "sha1-m9g59JkxtXWiLiOFxdvdLt16Sks=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-animate": "^3.1.0", + "rc-util": "^5.0.0", + "rc-virtual-list": "^1.1.0" + } + }, + "rc-tree-select": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/rc-tree-select/download/rc-tree-select-4.0.0.tgz", + "integrity": "sha1-C4IayYdfn9fHE2fAIWNAPCKw7oE=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-select": "^11.0.0", + "rc-tree": "^3.1.0", + "rc-util": "^5.0.1" + } + }, + "rc-trigger": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/rc-trigger/download/rc-trigger-4.3.0.tgz?cache=0&sync_timestamp=1590767284735&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-trigger%2Fdownload%2Frc-trigger-4.3.0.tgz", + "integrity": "sha1-lOoYUdEjNZcW0dwwMAg8AVqS7Ps=", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "raf": "^3.4.1", + "rc-align": "^4.0.0", + "rc-animate": "^3.0.0", + "rc-util": "^5.0.1" + } + }, + "rc-upload": { + "version": "3.1.3", + "resolved": "https://registry.npm.taobao.org/rc-upload/download/rc-upload-3.1.3.tgz", + "integrity": "sha1-2Rzm3sjm4b1bSyrXKWrXeABKGks=", + "requires": { + "classnames": "^2.2.5" + } + }, + "rc-util": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/rc-util/download/rc-util-5.0.1.tgz", + "integrity": "sha1-JqVRXKCAuC9ct/O2MZlmgkqShHY=", + "requires": { + "react-is": "^16.12.0", + "shallowequal": "^1.1.0" + } + }, + "rc-virtual-list": { + "version": "1.1.5", + "resolved": "https://registry.npm.taobao.org/rc-virtual-list/download/rc-virtual-list-1.1.5.tgz", + "integrity": "sha1-bt9yIoMMfdcy9iaYyEaLfwisjew=", + "requires": { + "classnames": "^2.2.6", + "raf": "^3.4.1", + "rc-util": "^5.0.0" + } + }, + "react": { + "version": "16.13.1", + "resolved": "https://registry.npm.taobao.org/react/download/react-16.13.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact%2Fdownload%2Freact-16.13.1.tgz", + "integrity": "sha1-LoGIIvGpdDEiwGPWQQ2FweOv5I4=", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-app-polyfill": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/react-app-polyfill/download/react-app-polyfill-1.0.6.tgz", + "integrity": "sha1-iQ+NfyhCzmBz8DCxF96RMKXzhfA=", + "requires": { + "core-js": "^3.5.0", + "object-assign": "^4.1.1", + "promise": "^8.0.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.3", + "whatwg-fetch": "^3.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-3.6.5.tgz", + "integrity": "sha1-c5XcJzrzf7LlDpvT2f6EEoUjHRo=" + } + } + }, + "react-dev-utils": { + "version": "10.2.1", + "resolved": "https://registry.npm.taobao.org/react-dev-utils/download/react-dev-utils-10.2.1.tgz?cache=0&sync_timestamp=1584749206461&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact-dev-utils%2Fdownload%2Freact-dev-utils-10.2.1.tgz", + "integrity": "sha1-9t4yWuJfpNVG0J30uxvv3G3RnBk=", + "requires": { + "@babel/code-frame": "7.8.3", + "address": "1.1.2", + "browserslist": "4.10.0", + "chalk": "2.4.2", + "cross-spawn": "7.0.1", + "detect-port-alt": "1.1.6", + "escape-string-regexp": "2.0.0", + "filesize": "6.0.1", + "find-up": "4.1.0", + "fork-ts-checker-webpack-plugin": "3.1.1", + "global-modules": "2.0.0", + "globby": "8.0.2", + "gzip-size": "5.1.1", + "immer": "1.10.0", + "inquirer": "7.0.4", + "is-root": "2.1.0", + "loader-utils": "1.2.3", + "open": "^7.0.2", + "pkg-up": "3.1.0", + "react-error-overlay": "^6.0.7", + "recursive-readdir": "2.2.2", + "shell-quote": "1.7.2", + "strip-ansi": "6.0.0", + "text-table": "0.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.8.3.tgz?cache=0&sync_timestamp=1590617298858&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.8.3.tgz", + "integrity": "sha1-M+JZA9dIEYFTThLsCiXxa2/PQZ4=", + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "browserslist": { + "version": "4.10.0", + "resolved": "https://registry.npm.taobao.org/browserslist/download/browserslist-4.10.0.tgz?cache=0&sync_timestamp=1587419256330&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.10.0.tgz", + "integrity": "sha1-8XlzeRPq8NK5jkkmrBymoVy8xqk=", + "requires": { + "caniuse-lite": "^1.0.30001035", + "electron-to-chromium": "^1.3.378", + "node-releases": "^1.1.52", + "pkg-up": "^3.1.0" + } + }, + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-7.0.1.tgz", + "integrity": "sha1-CrVihuD3wk4VPQTMKqAn5DqaXRQ=", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescape-string-regexp%2Fdownload%2Fescape-string-regexp-2.0.0.tgz", + "integrity": "sha1-owME6Z2qMuI7L9IPUbq9B8/8o0Q=" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-4.1.0.tgz", + "integrity": "sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk=", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "dependencies": { + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz", + "integrity": "sha1-Gvujlq/WdqbUJQTQpno6frn2KqA=", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-4.1.0.tgz", + "integrity": "sha1-o0KLtwiLOmApL2aRkni3wpetTwc=", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-4.0.0.tgz", + "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=" + } + } + }, + "inquirer": { + "version": "7.0.4", + "resolved": "https://registry.npm.taobao.org/inquirer/download/inquirer-7.0.4.tgz", + "integrity": "sha1-ma9b3kcVOryiP1x/ww2yR/OdpwM=", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&sync_timestamp=1586045666090&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.2.3.tgz?cache=0&sync_timestamp=1584445172927&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-1.2.3.tgz", + "integrity": "sha1-H/XcaRHJ8KBiUxpMBLYJQGEIwsc=", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/path-key/download/path-key-3.1.1.tgz?cache=0&sync_timestamp=1574442298523&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-key%2Fdownload%2Fpath-key-3.1.1.tgz", + "integrity": "sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=" + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/pkg-up/download/pkg-up-3.1.0.tgz", + "integrity": "sha1-EA7CNcwVDk/UJRlBJZaihRKg3vU=", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fshebang-command%2Fdownload%2Fshebang-command-2.0.0.tgz", + "integrity": "sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo=", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-3.0.0.tgz", + "integrity": "sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI=" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz", + "integrity": "sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI=", + "requires": { + "ansi-regex": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=" + } + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/which/download/which-2.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhich%2Fdownload%2Fwhich-2.0.2.tgz", + "integrity": "sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "react-dom": { + "version": "16.13.1", + "resolved": "https://registry.npm.taobao.org/react-dom/download/react-dom-16.13.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact-dom%2Fdownload%2Freact-dom-16.13.1.tgz", + "integrity": "sha1-wb03MxoEhsB47lTEdAcgmTsuDn8=", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-error-overlay": { + "version": "6.0.7", + "resolved": "https://registry.npm.taobao.org/react-error-overlay/download/react-error-overlay-6.0.7.tgz", + "integrity": "sha1-Hc+0WatnHVP2YKmRUTyy8KBVMQg=" + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npm.taobao.org/react-is/download/react-is-16.13.1.tgz", + "integrity": "sha1-eJcppNw23imZ3BVt1sHZwYzqVqQ=" + }, + "react-scripts": { + "version": "3.4.1", + "resolved": "https://registry.npm.taobao.org/react-scripts/download/react-scripts-3.4.1.tgz", + "integrity": "sha1-9VEpi1xxmFzEkbms88jowK462go=", + "requires": { + "@babel/core": "7.9.0", + "@svgr/webpack": "4.3.3", + "@typescript-eslint/eslint-plugin": "^2.10.0", + "@typescript-eslint/parser": "^2.10.0", + "babel-eslint": "10.1.0", + "babel-jest": "^24.9.0", + "babel-loader": "8.1.0", + "babel-plugin-named-asset-import": "^0.3.6", + "babel-preset-react-app": "^9.1.2", + "camelcase": "^5.3.1", + "case-sensitive-paths-webpack-plugin": "2.3.0", + "css-loader": "3.4.2", + "dotenv": "8.2.0", + "dotenv-expand": "5.1.0", + "eslint": "^6.6.0", + "eslint-config-react-app": "^5.2.1", + "eslint-loader": "3.0.3", + "eslint-plugin-flowtype": "4.6.0", + "eslint-plugin-import": "2.20.1", + "eslint-plugin-jsx-a11y": "6.2.3", + "eslint-plugin-react": "7.19.0", + "eslint-plugin-react-hooks": "^1.6.1", + "file-loader": "4.3.0", + "fs-extra": "^8.1.0", + "fsevents": "2.1.2", + "html-webpack-plugin": "4.0.0-beta.11", + "identity-obj-proxy": "3.0.0", + "jest": "24.9.0", + "jest-environment-jsdom-fourteen": "1.0.1", + "jest-resolve": "24.9.0", + "jest-watch-typeahead": "0.4.2", + "mini-css-extract-plugin": "0.9.0", + "optimize-css-assets-webpack-plugin": "5.0.3", + "pnp-webpack-plugin": "1.6.4", + "postcss-flexbugs-fixes": "4.1.0", + "postcss-loader": "3.0.0", + "postcss-normalize": "8.0.1", + "postcss-preset-env": "6.7.0", + "postcss-safe-parser": "4.0.1", + "react-app-polyfill": "^1.0.6", + "react-dev-utils": "^10.2.1", + "resolve": "1.15.0", + "resolve-url-loader": "3.1.1", + "sass-loader": "8.0.2", + "semver": "6.3.0", + "style-loader": "0.23.1", + "terser-webpack-plugin": "2.3.5", + "ts-pnp": "1.1.6", + "url-loader": "2.3.0", + "webpack": "4.42.0", + "webpack-dev-server": "3.10.3", + "webpack-manifest-plugin": "2.2.0", + "workbox-webpack-plugin": "4.3.1" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-4.0.0.tgz?cache=0&sync_timestamp=1575620436254&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg-up%2Fdownload%2Fread-pkg-up-4.0.0.tgz", + "integrity": "sha1-GyIcYIi6d5lgHICPkRYcZuWPiXg=", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-3.6.0.tgz", + "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.4.0.tgz?cache=0&sync_timestamp=1584985807685&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-3.4.0.tgz", + "integrity": "sha1-n9zN+ekVWAVEkiGsZF6DA6tbmto=", + "requires": { + "picomatch": "^2.2.1" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/realpath-native/download/realpath-native-1.1.0.tgz", + "integrity": "sha1-IAMpT+oj+wZy8kduviL89Jii1lw=", + "requires": { + "util.promisify": "^1.0.0" + } + }, + "recursive-readdir": { + "version": "2.2.2", + "resolved": "https://registry.npm.taobao.org/recursive-readdir/download/recursive-readdir-2.2.2.tgz", + "integrity": "sha1-mUb7MnThYo3m42svZxSVO0hFCU8=", + "requires": { + "minimatch": "3.0.4" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/redent/download/redent-3.0.0.tgz", + "integrity": "sha1-5Ve3mYMWu1PJ8fVvpiY1LGljBZ8=", + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/regenerate/download/regenerate-1.4.1.tgz", + "integrity": "sha1-ytkq2Oa1kXc0hfvgWkhcr09Ffm8=" + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz?cache=0&sync_timestamp=1583946996794&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerate-unicode-properties%2Fdownload%2Fregenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha1-5d5xEdZV57pgwFfb6f83yH5lzew=", + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.5.tgz?cache=0&sync_timestamp=1584052392667&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.13.5.tgz", + "integrity": "sha1-2Hih0JS0MG0QuQlkhLM+vVXiZpc=" + }, + "regenerator-transform": { + "version": "0.14.4", + "resolved": "https://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.14.4.tgz", + "integrity": "sha1-UmaFeJZRjRYWp4oEeTN6MOqXTMc=", + "requires": { + "@babel/runtime": "^7.8.4", + "private": "^0.1.8" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regex-parser": { + "version": "2.2.10", + "resolved": "https://registry.npm.taobao.org/regex-parser/download/regex-parser-2.2.10.tgz", + "integrity": "sha1-nmao9z2JoQdhbmOznU3t3+6RKzc=" + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/regexp.prototype.flags/download/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha1-erqJs8E6ZFCdq888qNn7ub31y3U=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/regexpp/download/regexpp-3.1.0.tgz", + "integrity": "sha1-IG0K0KVkjP+9uK5GQ489xRyfeOI=" + }, + "regexpu-core": { + "version": "4.7.0", + "resolved": "https://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.7.0.tgz?cache=0&sync_timestamp=1583949999327&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregexpu-core%2Fdownload%2Fregexpu-core-4.7.0.tgz", + "integrity": "sha1-/L9FjFBDGwu3tF1pZ7gZLZHz2Tg=", + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npm.taobao.org/regjsgen/download/regjsgen-0.5.2.tgz?cache=0&sync_timestamp=1590335980151&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregjsgen%2Fdownload%2Fregjsgen-0.5.2.tgz", + "integrity": "sha1-kv8pX7He7L9uzaslQ9IH6RqjNzM=" + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npm.taobao.org/regjsparser/download/regjsparser-0.6.4.tgz?cache=0&sync_timestamp=1583896720909&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregjsparser%2Fdownload%2Fregjsparser-0.6.4.tgz", + "integrity": "sha1-p2n4aEMIQBpm6bUp0kNv9NBmYnI=", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npm.taobao.org/relateurl/download/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "renderkid": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/renderkid/download/renderkid-2.0.3.tgz", + "integrity": "sha1-OAF5wv9a4TZcUivy/Pz/AcW3QUk=", + "requires": { + "css-select": "^1.1.0", + "dom-converter": "^0.2", + "htmlparser2": "^3.3.0", + "strip-ansi": "^3.0.0", + "utila": "^0.4.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/css-what/download/css-what-2.1.3.tgz", + "integrity": "sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI=" + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz?cache=0&sync_timestamp=1589052712571&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomutils%2Fdownload%2Fdomutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz", + "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz", + "integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/request-promise-core/download/request-promise-core-1.1.3.tgz", + "integrity": "sha1-6aPAgbUTgN/qZ3M2Bh/qh5qCnuk=", + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npm.taobao.org/request-promise-native/download/request-promise-native-1.0.8.tgz?cache=0&sync_timestamp=1572829773221&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frequest-promise-native%2Fdownload%2Frequest-promise-native-1.0.8.tgz", + "integrity": "sha1-pFW5YLgm5E4r+Jma9k3/K/5YyzY=", + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-2.0.0.tgz", + "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ=" + }, + "resolve": { + "version": "1.15.0", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.15.0.tgz", + "integrity": "sha1-G3ypYHPrtS50H/15n2s56kYsZ/U=", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/resolve-cwd/download/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "resolve-url-loader": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/resolve-url-loader/download/resolve-url-loader-3.1.1.tgz", + "integrity": "sha1-KJMYlfoeq5vgZH07KVjBAK48C/A=", + "requires": { + "adjust-sourcemap-loader": "2.0.0", + "camelcase": "5.3.1", + "compose-function": "3.0.3", + "convert-source-map": "1.7.0", + "es6-iterator": "2.0.3", + "loader-utils": "1.2.3", + "postcss": "7.0.21", + "rework": "1.0.1", + "rework-visit": "1.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&sync_timestamp=1586045666090&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.2.3.tgz?cache=0&sync_timestamp=1584445172927&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-1.2.3.tgz", + "integrity": "sha1-H/XcaRHJ8KBiUxpMBLYJQGEIwsc=", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "postcss": { + "version": "7.0.21", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-7.0.21.tgz", + "integrity": "sha1-BrsHgkwZwgIcXQVtWxDDW5iffhc=", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/restore-cursor/download/restore-cursor-3.1.0.tgz", + "integrity": "sha1-OfZ8VLOnpYzqUjbZXPADQjljH34=", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=" + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npm.taobao.org/retry/download/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/rework/download/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "requires": { + "convert-source-map": "^0.3.3", + "css": "^2.0.0" + }, + "dependencies": { + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npm.taobao.org/convert-source-map/download/convert-source-map-0.3.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconvert-source-map%2Fdownload%2Fconvert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=" + } + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/rework-visit/download/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=" + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npm.taobao.org/rfdc/download/rfdc-1.1.4.tgz", + "integrity": "sha1-unLME2egzNnPgahws7WL060H+MI=", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/rgb-regex/download/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=" + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/rgba-regex/download/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-2.6.3.tgz", + "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/ripemd160/download/ripemd160-2.0.2.tgz", + "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npm.taobao.org/rsvp/download/rsvp-4.8.5.tgz", + "integrity": "sha1-yPFVMR0Wf2jyHhaN9x7FsIMRNzQ=" + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npm.taobao.org/run-async/download/run-async-2.4.1.tgz", + "integrity": "sha1-hEDsz5nqPnC9QJ1JqriOEMGJpFU=" + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npm.taobao.org/rxjs/download/rxjs-6.5.5.tgz", + "integrity": "sha1-xciE4wlMjP7jG/J+uH5UzPyH+ew=", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz?cache=0&sync_timestamp=1571687334026&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-regex%2Fdownload%2Fsafe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/sane/download/sane-4.1.0.tgz", + "integrity": "sha1-7Ygf2SJzOmxGG8GJ3CtsAG8//e0=", + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + } + }, + "sanitize.css": { + "version": "10.0.0", + "resolved": "https://registry.npm.taobao.org/sanitize.css/download/sanitize.css-10.0.0.tgz", + "integrity": "sha1-tcslR+lthimmCUdURmUkOx3DZXo=" + }, + "sass-loader": { + "version": "8.0.2", + "resolved": "https://registry.npm.taobao.org/sass-loader/download/sass-loader-8.0.2.tgz", + "integrity": "sha1-3r7NjDziQ8dkVPLoKQSCFQOACQ0=", + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" + }, + "dependencies": { + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/clone-deep/download/clone-deep-4.0.1.tgz", + "integrity": "sha1-wZ/Zvbv4WUK0/ZechNz31fB8I4c=", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/shallow-clone/download/shallow-clone-3.0.1.tgz", + "integrity": "sha1-jymBrZJTH1UDWwH7IwdppA4C76M=", + "requires": { + "kind-of": "^6.0.2" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" + }, + "saxes": { + "version": "3.1.11", + "resolved": "https://registry.npm.taobao.org/saxes/download/saxes-3.1.11.tgz", + "integrity": "sha1-1Z0f0zLskq2YouCy7mRHAjhLHFs=", + "requires": { + "xmlchars": "^2.1.1" + } + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npm.taobao.org/scheduler/download/scheduler-0.19.1.tgz?cache=0&sync_timestamp=1588782643536&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fscheduler%2Fdownload%2Fscheduler-0.19.1.tgz", + "integrity": "sha1-Tz4u0sGn1laB9MhU+oxaHMtA8ZY=", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.7.0.tgz", + "integrity": "sha1-FxUfdtjq5n+793lgwzxnatn078c=", + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "scroll-into-view-if-needed": { + "version": "2.2.25", + "resolved": "https://registry.npm.taobao.org/scroll-into-view-if-needed/download/scroll-into-view-if-needed-2.2.25.tgz", + "integrity": "sha1-EXt7x8Ybx6K3hyoJhLxzoZvG6WE=", + "requires": { + "compute-scroll-into-view": "^1.0.14" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + }, + "selfsigned": { + "version": "1.10.7", + "resolved": "https://registry.npm.taobao.org/selfsigned/download/selfsigned-1.10.7.tgz?cache=0&sync_timestamp=1569952074772&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fselfsigned%2Fdownload%2Fselfsigned-1.10.7.tgz", + "integrity": "sha1-2lgZ/QSdVXTyjoipvMbbxubzkGs=", + "requires": { + "node-forge": "0.9.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1586886301819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npm.taobao.org/send/download/send-0.17.1.tgz", + "integrity": "sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg=", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz?cache=0&sync_timestamp=1590596728112&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=" + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz", + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=" + } + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-2.1.2.tgz?cache=0&sync_timestamp=1590665885842&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-2.1.2.tgz", + "integrity": "sha1-7OxTsOAxe9yV73arcHS3OEeF+mE=" + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/serve-index/download/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npm.taobao.org/serve-static/download/serve-static-1.14.1.tgz", + "integrity": "sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk=", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/set-value/download/set-value-2.0.1.tgz?cache=0&sync_timestamp=1585775409029&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fset-value%2Fdownload%2Fset-value-2.0.1.tgz", + "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/setimmediate/download/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz", + "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz", + "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/shallow-clone/download/shallow-clone-0.1.2.tgz", + "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^2.0.1", + "lazy-cache": "^0.2.3", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-2.0.1.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-2.0.1.tgz", + "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", + "requires": { + "is-buffer": "^1.0.2" + } + }, + "lazy-cache": { + "version": "0.2.7", + "resolved": "https://registry.npm.taobao.org/lazy-cache/download/lazy-cache-0.2.7.tgz", + "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=" + } + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/shallowequal/download/shallowequal-1.1.0.tgz", + "integrity": "sha1-GI1SHelbkIdAT9TctosT3wrk5/g=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fshebang-command%2Fdownload%2Fshebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npm.taobao.org/shell-quote/download/shell-quote-1.7.2.tgz", + "integrity": "sha1-Z6fQLHbJ2iT5nSCAj8re0ODgS+I=" + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/shellwords/download/shellwords-0.1.1.tgz", + "integrity": "sha1-1rkYHBpI05cyTISHHvvPxz/AZUs=" + }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/side-channel/download/side-channel-1.0.2.tgz", + "integrity": "sha1-310auttOS/SvHNiFK/Ey0veHaUc=", + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz?cache=0&sync_timestamp=1585253373618&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsignal-exit%2Fdownload%2Fsignal-exit-3.0.3.tgz", + "integrity": "sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw=" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npm.taobao.org/simple-swizzle/download/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.3.2.tgz", + "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=" + } + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/sisteransi/download/sisteransi-1.0.5.tgz", + "integrity": "sha1-E01oEpd1ZDfMBcoBNw06elcQde0=" + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/slash/download/slash-2.0.0.tgz", + "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=" + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/slice-ansi/download/slice-ansi-2.1.0.tgz", + "integrity": "sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY=", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz?cache=0&sync_timestamp=1579194040958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkind-of%2Fdownload%2Fkind-of-6.0.3.tgz", + "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "requires": { + "kind-of": "^3.2.0" + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npm.taobao.org/sockjs/download/sockjs-0.3.19.tgz?cache=0&sync_timestamp=1583783910272&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsockjs%2Fdownload%2Fsockjs-0.3.19.tgz", + "integrity": "sha1-2Xa76ACve9IK4IWY1YI5NQiZPA0=", + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/sockjs-client/download/sockjs-client-1.4.0.tgz", + "integrity": "sha1-yfJWjhnI/YFztJl+o0IOC7MGx9U=", + "requires": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "requires": { + "ms": "^2.1.1" + } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.11.3.tgz", + "integrity": "sha1-XA6aiWjokSwoZjn96XeosgnyUI4=", + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/sort-keys/download/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz", + "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.3.tgz?cache=0&sync_timestamp=1584829552965&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-resolve%2Fdownload%2Fsource-map-resolve-0.5.3.tgz", + "integrity": "sha1-GQhmvs51U+H48mei7oLGBrVQmho=", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.19.tgz?cache=0&sync_timestamp=1587719493563&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.5.19.tgz", + "integrity": "sha1-qYti+G3K9PZzmWSMCFKRq56P7WE=", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/source-map-url/download/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz?cache=0&sync_timestamp=1590161967473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-correct%2Fdownload%2Fspdx-correct-3.1.1.tgz", + "integrity": "sha1-3s6BrJweZxPl99G28X1Gj6U9iak=", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz?cache=0&sync_timestamp=1587422511430&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-exceptions%2Fdownload%2Fspdx-exceptions-2.3.0.tgz", + "integrity": "sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0=" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha1-z3D1BILu/cmOPOCmgz5KU87rpnk=", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-3.0.5.tgz", + "integrity": "sha1-NpS1gEVnpFjTyARYQqY1hjL2JlQ=" + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/spdy/download/spdy-4.0.2.tgz?cache=0&sync_timestamp=1585970558936&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdy%2Fdownload%2Fspdy-4.0.2.tgz", + "integrity": "sha1-t09GYgOj7aRSwCSSuR+56EonZ3s=", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/spdy-transport/download/spdy-transport-3.0.0.tgz", + "integrity": "sha1-ANSGOmQArXXfkzYaFghgXl3NzzE=", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz", + "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-7.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssri%2Fdownload%2Fssri-7.1.0.tgz", + "integrity": "sha1-ksJBv23oI2W1x/tL126XVSLhKU0=", + "requires": { + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npm.taobao.org/stable/download/stable-0.1.8.tgz", + "integrity": "sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88=" + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/stack-utils/download/stack-utils-1.0.2.tgz", + "integrity": "sha1-M+ujiXeIVYvr/C2wWdwVjsNs67g=" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/stealthy-require/download/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/stream-browserify/download/stream-browserify-2.0.2.tgz", + "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/stream-each/download/stream-each-1.2.3.tgz", + "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz?cache=0&sync_timestamp=1588701139074&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstream-http%2Fdownload%2Fstream-http-2.8.3.tgz", + "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.1.tgz", + "integrity": "sha1-1wiCgVWasneEJCebCHfaPDktWj0=" + }, + "streamroller": { + "version": "2.2.4", + "resolved": "https://registry.npm.taobao.org/streamroller/download/streamroller-2.2.4.tgz", + "integrity": "sha1-wZjO1C25QIamGTYIGHzoCl8rDlM=", + "dev": true, + "requires": { + "date-format": "^2.1.0", + "debug": "^4.1.1", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/date-format/download/date-format-2.1.0.tgz", + "integrity": "sha1-MdW16iEc9f12TNOLr50DPffhJc8=", + "dev": true + } + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/string-convert/download/string-convert-0.2.1.tgz", + "integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c=" + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/string-length/download/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-4.2.0.tgz", + "integrity": "sha1-lSGCxGzHssMT0VluYjmSvRY7crU=", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz", + "integrity": "sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz", + "integrity": "sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI=", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "string.prototype.matchall": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/string.prototype.matchall/download/string.prototype.matchall-4.0.2.tgz", + "integrity": "sha1-SLtRAyb7n962ozzqqBpuoE73ZI4=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2" + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimend/download/string.prototype.trimend-1.0.1.tgz?cache=0&sync_timestamp=1586465233837&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimend%2Fdownload%2Fstring.prototype.trimend-1.0.1.tgz", + "integrity": "sha1-hYEqa4R6wAInD1gIFGBkyZX7aRM=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimleft/download/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha1-RAiqLl1t3QyagHObCH+8BnwDs8w=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimright/download/string.prototype.trimright-2.1.2.tgz?cache=0&sync_timestamp=1585557209944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimright%2Fdownload%2Fstring.prototype.trimright-2.1.2.tgz", + "integrity": "sha1-x28c7zDyG7rYr+uNsVEUls+w8qM=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/string.prototype.trimstart/download/string.prototype.trimstart-1.0.1.tgz?cache=0&sync_timestamp=1586465234129&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimstart%2Fdownload%2Fstring.prototype.trimstart-1.0.1.tgz", + "integrity": "sha1-FK9tnzSwU/fPyJty+PLuFLkDmlQ=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.3.0.tgz", + "integrity": "sha1-QvEUWUpGzxqOMLCoT1bHjD7awh4=", + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589129010497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=" + } + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npm.taobao.org/stringify-object/download/stringify-object-3.3.0.tgz", + "integrity": "sha1-cDBlrvyhkwDTzoivT1s5VtdVZik=", + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-comments": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/strip-comments/download/strip-comments-1.0.2.tgz", + "integrity": "sha1-grnEXn8FhzvuU/NxaK+TCqNoZ50=", + "requires": { + "babel-extract-comments": "^1.0.0", + "babel-plugin-transform-object-rest-spread": "^6.26.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/strip-indent/download/strip-indent-3.0.0.tgz", + "integrity": "sha1-wy4c7pQLazQyx3G8LFS8znPNMAE=", + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-3.1.0.tgz?cache=0&sync_timestamp=1586160054577&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-json-comments%2Fdownload%2Fstrip-json-comments-3.1.0.tgz", + "integrity": "sha1-djjTFCISns9EV0QACfugP5+awYA=" + }, + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npm.taobao.org/style-loader/download/style-loader-0.23.1.tgz", + "integrity": "sha1-y5FUYG8+dxq2xKtjcCahBJF02SU=", + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/stylehacks/download/stylehacks-4.0.3.tgz", + "integrity": "sha1-Zxj8r00eB9ihMYaQiB6NlnJqcdU=", + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz", + "integrity": "sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA=", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "requires": { + "has-flag": "^3.0.0" + } + }, + "svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/svg-parser/download/svg-parser-2.0.4.tgz", + "integrity": "sha1-/cLinhOVFzYUC3bLEiyO5mMOtrU=" + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/svgo/download/svgo-1.3.2.tgz?cache=0&sync_timestamp=1572433377078&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsvgo%2Fdownload%2Fsvgo-1.3.2.tgz", + "integrity": "sha1-ttxRHAYzRsnkFbgeQ0ARRbltQWc=", + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npm.taobao.org/symbol-tree/download/symbol-tree-3.2.4.tgz", + "integrity": "sha1-QwY30ki6d+B4iDlR+5qg7tfGP6I=" + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npm.taobao.org/table/download/table-5.4.6.tgz", + "integrity": "sha1-EpLRlQDOP4YFOwXw6Ofko7shB54=", + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/tapable/download/tapable-1.1.3.tgz?cache=0&sync_timestamp=1589549557661&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftapable%2Fdownload%2Ftapable-1.1.3.tgz", + "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I=" + }, + "terser": { + "version": "4.7.0", + "resolved": "https://registry.npm.taobao.org/terser/download/terser-4.7.0.tgz", + "integrity": "sha1-FYUs8aCOMlaoBCjoZaL6iT/7oAY=", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "2.3.5", + "resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.3.5.tgz?cache=0&sync_timestamp=1591189528067&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-2.3.5.tgz", + "integrity": "sha1-WtlxrM5cUXRAuoc+pPCWh94vSoE=", + "requires": { + "cacache": "^13.0.1", + "find-cache-dir": "^3.2.0", + "jest-worker": "^25.1.0", + "p-limit": "^2.2.2", + "schema-utils": "^2.6.4", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.4.3", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.3.1.tgz?cache=0&sync_timestamp=1583734591888&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-cache-dir%2Fdownload%2Ffind-cache-dir-3.3.1.tgz", + "integrity": "sha1-ibM/rUpGcNqpT4Vff74x1thP6IA=", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-4.1.0.tgz", + "integrity": "sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk=", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=" + }, + "jest-worker": { + "version": "25.5.0", + "resolved": "https://registry.npm.taobao.org/jest-worker/download/jest-worker-25.5.0.tgz?cache=0&sync_timestamp=1588614797364&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-worker%2Fdownload%2Fjest-worker-25.5.0.tgz", + "integrity": "sha1-JhHQcbec6g9D7lej0RhZOsFUfbE=", + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz", + "integrity": "sha1-Gvujlq/WdqbUJQTQpno6frn2KqA=", + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-3.1.0.tgz?cache=0&sync_timestamp=1587567875186&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-dir%2Fdownload%2Fmake-dir-3.1.0.tgz", + "integrity": "sha1-QV6WcEazp/HRhSd9hKpYIDcmoT8=", + "requires": { + "semver": "^6.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-4.1.0.tgz", + "integrity": "sha1-o0KLtwiLOmApL2aRkni3wpetTwc=", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-4.0.0.tgz", + "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-4.2.0.tgz", + "integrity": "sha1-8JkTPfft5CLoHR2ESCcO6z5CYfM=", + "requires": { + "find-up": "^4.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.1.0.tgz", + "integrity": "sha1-aOMlkd9z4lrRxLSRCKLsUHliv9E=", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npm.taobao.org/test-exclude/download/test-exclude-5.2.3.tgz", + "integrity": "sha1-w9Ph4xHrfuQF4JLawQrv0JCR6sA=", + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npm.taobao.org/text-table/download/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/throat/download/throat-4.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fthroat%2Fdownload%2Fthroat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npm.taobao.org/through/download/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz", + "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/thunky/download/thunky-1.1.0.tgz", + "integrity": "sha1-Wrr3FKlAXbBQRzK7zNLO3Z75U30=" + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npm.taobao.org/timers-browserify/download/timers-browserify-2.0.11.tgz", + "integrity": "sha1-gAsfPu4nLlvFPuRloE0OgEwxIR8=", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/timsort/download/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/tinycolor2/download/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/tmpl/download/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz?cache=0&sync_timestamp=1580550347606&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fto-fast-properties%2Fdownload%2Fto-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/to-regex/download/to-regex-3.0.2.tgz", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/toggle-selection/download/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz", + "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz?cache=0&sync_timestamp=1584645751908&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-2.5.0.tgz", + "integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/tr46/download/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, + "ts-pnp": { + "version": "1.1.6", + "resolved": "https://registry.npm.taobao.org/ts-pnp/download/ts-pnp-1.1.6.tgz?cache=0&sync_timestamp=1585245674012&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fts-pnp%2Fdownload%2Fts-pnp-1.1.6.tgz", + "integrity": "sha1-OJokOW1CWg0xYultK0Y4kA/cKJo=" + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npm.taobao.org/tslib/download/tslib-1.13.0.tgz", + "integrity": "sha1-yIHhPMcBWJTtkUhi0nZDb6mkcEM=" + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npm.taobao.org/tsutils/download/tsutils-3.17.1.tgz", + "integrity": "sha1-7XGZF/EcoN7lhicrKsSeAVot11k=", + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz?cache=0&sync_timestamp=1581364183265&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftweetnacl%2Fdownload%2Ftweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/type/download/type-1.2.0.tgz", + "integrity": "sha1-hI3XaY2vo+VKbEeedZxLw/GIR6A=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npm.taobao.org/type-fest/download/type-fest-0.8.1.tgz", + "integrity": "sha1-CeJJ696FHTseSNJ8EFREZn8XuD0=" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz", + "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=" + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha1-DZH2AO7rMJaqlisdb8iIduZOpTE=" + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-1.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funicode-property-aliases-ecmascript%2Fdownload%2Funicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha1-3Vepn2IHvt/0Yoq++5TFDblByPQ=" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz", + "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/uniq/download/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/uniqs/download/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/unique-filename/download/unique-filename-1.1.1.tgz", + "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/unique-slug/download/unique-slug-2.0.2.tgz", + "integrity": "sha1-uqvOkQg/xk6UWw861hPiZPfNTmw=", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/unquote/download/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/upath/download/upath-1.2.0.tgz", + "integrity": "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz", + "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npm.taobao.org/url/download/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-loader": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/url-loader/download/url-loader-2.3.0.tgz", + "integrity": "sha1-4OLvZY8APvuMpBsPP/v3a6uIZYs=", + "requires": { + "loader-utils": "^1.2.3", + "mime": "^2.4.4", + "schema-utils": "^2.5.0" + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npm.taobao.org/url-parse/download/url-parse-1.4.7.tgz", + "integrity": "sha1-qKg1NejACjFuQDpdtKwbm4U64ng=", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz", + "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npm.taobao.org/util/download/util-0.10.3.tgz?cache=0&sync_timestamp=1588238331562&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil%2Fdownload%2Futil-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.1.tgz", + "integrity": "sha1-a693dLgO6w91INi4HQeYKlmruu4=", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/utila/download/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1590000998251&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", + "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=" + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/v8-compile-cache/download/v8-compile-cache-2.1.1.tgz?cache=0&sync_timestamp=1590871780233&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fv8-compile-cache%2Fdownload%2Fv8-compile-cache-2.1.1.tgz", + "integrity": "sha1-VLw83UMxe8qR413K8wWxpyN950U=" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/vendors/download/vendors-1.0.4.tgz", + "integrity": "sha1-4rgApT56Kbk1BsPPQRANFsTErY4=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/vm-browserify/download/vm-browserify-1.1.2.tgz?cache=0&sync_timestamp=1572870776965&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvm-browserify%2Fdownload%2Fvm-browserify-1.1.2.tgz", + "integrity": "sha1-eGQcSIuObKkadfUR56OzKobl3aA=" + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/w3c-hr-time/download/w3c-hr-time-1.0.2.tgz", + "integrity": "sha1-ConN9cwVgi35w2BUNnaWPgzDCM0=", + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/w3c-xmlserializer/download/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha1-MEhcp9cKb9BSQgo9Ev2Q5jOc55Q=", + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, + "wait-for-expect": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/wait-for-expect/download/wait-for-expect-3.0.2.tgz", + "integrity": "sha1-0vFLL3t3jJuCFEEJyPqJzqrapGM=" + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npm.taobao.org/walker/download/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "requires": { + "makeerror": "1.0.x" + } + }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/warning/download/warning-4.0.3.tgz", + "integrity": "sha1-Fungd+uKhtavfWSqHgX9hbRnjKM=", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "watchpack": { + "version": "1.7.2", + "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.2.tgz", + "integrity": "sha1-wC5NTUmRPD5+EiwzJTZa+dMx6ao=", + "requires": { + "chokidar": "^3.4.0", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/watchpack-chokidar2/download/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha1-mUihhmy71suCTeoTp+1pH2yN3/A=", + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-1.13.1.tgz", + "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=", + "optional": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-2.1.8.tgz?cache=0&sync_timestamp=1587911257758&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-2.1.8.tgz", + "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=", + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz", + "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1584836110944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=", + "optional": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz?cache=0&sync_timestamp=1584985807685&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-2.2.1.tgz", + "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npm.taobao.org/wbuf/download/wbuf-1.7.3.tgz", + "integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/webidl-conversions/download/webidl-conversions-4.0.2.tgz", + "integrity": "sha1-qFWYCx8LazWbodXZ+zmulB+qY60=" + }, + "webpack": { + "version": "4.42.0", + "resolved": "https://registry.npm.taobao.org/webpack/download/webpack-4.42.0.tgz", + "integrity": "sha1-uQFjXdYXk5HZB0CmPJP3bzmIPrg=", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npm.taobao.org/acorn/download/acorn-6.4.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-6.4.1.tgz", + "integrity": "sha1-Ux5Yuj9RudrLmmZGyk3r9bFMpHQ=" + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-12.0.4.tgz", + "integrity": "sha1-ZovL0QWutfHZL+JVcOyVJcj6pAw=", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-4.0.3.tgz", + "integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-3.1.0.tgz?cache=0&sync_timestamp=1590665885842&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-3.1.0.tgz", + "integrity": "sha1-i/OpFwcSZk7yVhtEtpHq/jmSFOo=", + "requires": { + "randombytes": "^2.1.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-6.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssri%2Fdownload%2Fssri-6.0.1.tgz", + "integrity": "sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg=", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "terser-webpack-plugin": { + "version": "1.4.4", + "resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-1.4.4.tgz?cache=0&sync_timestamp=1591189528067&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-1.4.4.tgz", + "integrity": "sha1-LGNUQ0cyS6r6mla6rd8WNMir/C8=", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^3.1.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-3.7.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-dev-middleware%2Fdownload%2Fwebpack-dev-middleware-3.7.2.tgz", + "integrity": "sha1-ABnD23FuP6XOy/ZPKriKdLqzMfM=", + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "webpack-dev-server": { + "version": "3.10.3", + "resolved": "https://registry.npm.taobao.org/webpack-dev-server/download/webpack-dev-server-3.10.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-dev-server%2Fdownload%2Fwebpack-dev-server-3.10.3.tgz", + "integrity": "sha1-81lFA2gT5X71gsJCDve0cOFNOvA=", + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.2.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.6", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.25", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.4.0", + "spdy": "^4.0.1", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-1.13.1.tgz", + "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=" + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-2.1.8.tgz?cache=0&sync_timestamp=1587911257758&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-2.1.8.tgz", + "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-4.1.0.tgz", + "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "requires": { + "locate-path": "^3.0.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz", + "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-1.0.3.tgz", + "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=" + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1584836110944&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-3.0.3.tgz", + "integrity": "sha1-lsaiK2ojkpsR6gr7GDbDatSl1pg=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=" + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", + "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz?cache=0&sync_timestamp=1584985807685&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-2.2.1.tgz", + "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npm.taobao.org/ws/download/ws-6.2.1.tgz", + "integrity": "sha1-RC/fCkftZPWbal2P8TD0dI7VJPs=", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npm.taobao.org/yargs/download/yargs-12.0.5.tgz", + "integrity": "sha1-BfWZe2CWR7ZPZrgeO0sQo2jnrRM=", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-11.1.1.tgz", + "integrity": "sha1-h5oIZZc7yp9rq1y987HGfsfTvPQ=", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/webpack-log/download/webpack-log-2.0.0.tgz", + "integrity": "sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8=", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-manifest-plugin": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/webpack-manifest-plugin/download/webpack-manifest-plugin-2.2.0.tgz?cache=0&sync_timestamp=1571924970736&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-manifest-plugin%2Fdownload%2Fwebpack-manifest-plugin-2.2.0.tgz", + "integrity": "sha1-GcpptDWwuux+KfvpD7QBXeLeTxY=", + "requires": { + "fs-extra": "^7.0.0", + "lodash": ">=3.5 <5", + "object.entries": "^1.1.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.1.tgz?cache=0&sync_timestamp=1591231538901&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-7.0.1.tgz", + "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npm.taobao.org/webpack-sources/download/webpack-sources-1.4.3.tgz", + "integrity": "sha1-7t2OwLko+/HL/plOItLYkPMwqTM=", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npm.taobao.org/websocket-driver/download/websocket-driver-0.7.4.tgz?cache=0&sync_timestamp=1591289007652&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebsocket-driver%2Fdownload%2Fwebsocket-driver-0.7.4.tgz", + "integrity": "sha1-ia1Slbv2S0gKvLox5JU6ynBvV2A=", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npm.taobao.org/websocket-extensions/download/websocket-extensions-0.1.4.tgz", + "integrity": "sha1-f4RzvIOd/YdgituV1+sHUhFXikI=" + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/whatwg-encoding/download/whatwg-encoding-1.0.5.tgz", + "integrity": "sha1-WrrPd3wyFmpR0IXWtPPn0nET3bA=", + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1579334008444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz", + "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/whatwg-fetch/download/whatwg-fetch-3.0.0.tgz", + "integrity": "sha1-/IBORYzEYACbGiuWa8iBfSV4rvs=" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/whatwg-mimetype/download/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha1-PUseAxLSB5h5+Cav8Y2+7KWWD78=" + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npm.taobao.org/whatwg-url/download/whatwg-url-6.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhatwg-url%2Fdownload%2Fwhatwg-url-6.5.0.tgz", + "integrity": "sha1-8t8Cv/F2/WUHDfdK1cy7WhmZZag=", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhich%2Fdownload%2Fwhich-1.3.1.tgz", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz", + "integrity": "sha1-YQY29rH3A4kb00dxzLF/uTtHB5w=" + }, + "workbox-background-sync": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-background-sync/download/workbox-background-sync-4.3.1.tgz", + "integrity": "sha1-JoIbm/Funjf9HWQCie3dwIr9GVA=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-broadcast-update": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-broadcast-update/download/workbox-broadcast-update-4.3.1.tgz", + "integrity": "sha1-4sAoCxSeOlBJg7dXYGrQQfMyw1s=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-build": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-build/download/workbox-build-4.3.1.tgz?cache=0&sync_timestamp=1587741750011&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-build%2Fdownload%2Fworkbox-build-4.3.1.tgz", + "integrity": "sha1-QU9w+01t5H9lOGCLgOxSQS0jPmQ=", + "requires": { + "@babel/runtime": "^7.3.4", + "@hapi/joi": "^15.0.0", + "common-tags": "^1.8.0", + "fs-extra": "^4.0.2", + "glob": "^7.1.3", + "lodash.template": "^4.4.0", + "pretty-bytes": "^5.1.0", + "stringify-object": "^3.3.0", + "strip-comments": "^1.0.2", + "workbox-background-sync": "^4.3.1", + "workbox-broadcast-update": "^4.3.1", + "workbox-cacheable-response": "^4.3.1", + "workbox-core": "^4.3.1", + "workbox-expiration": "^4.3.1", + "workbox-google-analytics": "^4.3.1", + "workbox-navigation-preload": "^4.3.1", + "workbox-precaching": "^4.3.1", + "workbox-range-requests": "^4.3.1", + "workbox-routing": "^4.3.1", + "workbox-strategies": "^4.3.1", + "workbox-streams": "^4.3.1", + "workbox-sw": "^4.3.1", + "workbox-window": "^4.3.1" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-4.0.3.tgz?cache=0&sync_timestamp=1591231538901&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-4.0.3.tgz", + "integrity": "sha1-DYUhIuW8W+tFP7Ao6cDJvzY0DJQ=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "workbox-cacheable-response": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-cacheable-response/download/workbox-cacheable-response-4.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-cacheable-response%2Fdownload%2Fworkbox-cacheable-response-4.3.1.tgz", + "integrity": "sha1-9T4HkXnAlaPxnlMTsoSXXJFCjJE=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-core": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-core/download/workbox-core-4.3.1.tgz", + "integrity": "sha1-AF0sagahcUN6/WyikEpXJ+zXO+Y=" + }, + "workbox-expiration": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-expiration/download/workbox-expiration-4.3.1.tgz?cache=0&sync_timestamp=1587741746763&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-expiration%2Fdownload%2Fworkbox-expiration-4.3.1.tgz", + "integrity": "sha1-15BDNWICnlaDfzQdf1U8Snjr6SE=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-google-analytics": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-google-analytics/download/workbox-google-analytics-4.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-google-analytics%2Fdownload%2Fworkbox-google-analytics-4.3.1.tgz", + "integrity": "sha1-ntoBg7EDiQtcJW5vTqFaHxVIUZo=", + "requires": { + "workbox-background-sync": "^4.3.1", + "workbox-core": "^4.3.1", + "workbox-routing": "^4.3.1", + "workbox-strategies": "^4.3.1" + } + }, + "workbox-navigation-preload": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-navigation-preload/download/workbox-navigation-preload-4.3.1.tgz?cache=0&sync_timestamp=1587741747576&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-navigation-preload%2Fdownload%2Fworkbox-navigation-preload-4.3.1.tgz", + "integrity": "sha1-Kcjk21hDgDs0zZbcFV+evZr6RT0=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-precaching": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-precaching/download/workbox-precaching-4.3.1.tgz?cache=0&sync_timestamp=1587741747006&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-precaching%2Fdownload%2Fworkbox-precaching-4.3.1.tgz", + "integrity": "sha1-n8Re0SLZS74fDqlYT/WUCWB3HLo=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-range-requests": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-range-requests/download/workbox-range-requests-4.3.1.tgz?cache=0&sync_timestamp=1587741749446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-range-requests%2Fdownload%2Fworkbox-range-requests-4.3.1.tgz", + "integrity": "sha1-+KRwGIkiFFy/DAmpotXjVkUkTnQ=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-routing": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-routing/download/workbox-routing-4.3.1.tgz?cache=0&sync_timestamp=1587741748887&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-routing%2Fdownload%2Fworkbox-routing-4.3.1.tgz", + "integrity": "sha1-pnWEGvYj4LsMZ85O2OckrAvtDNo=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-strategies": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-strategies/download/workbox-strategies-4.3.1.tgz?cache=0&sync_timestamp=1587741748360&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-strategies%2Fdownload%2Fworkbox-strategies-4.3.1.tgz", + "integrity": "sha1-0r4DxO8hTBFeGrKcnHWcn+Pp5kY=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-streams": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-streams/download/workbox-streams-4.3.1.tgz?cache=0&sync_timestamp=1587741748623&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-streams%2Fdownload%2Fworkbox-streams-4.3.1.tgz", + "integrity": "sha1-C1facOmCVy3gnIdC3Qy0Cmt8LMM=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-sw": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-sw/download/workbox-sw-4.3.1.tgz?cache=0&sync_timestamp=1587741753655&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-sw%2Fdownload%2Fworkbox-sw-4.3.1.tgz", + "integrity": "sha1-32njlcR5700USZNyvNhMD14kYWQ=" + }, + "workbox-webpack-plugin": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-webpack-plugin/download/workbox-webpack-plugin-4.3.1.tgz?cache=0&sync_timestamp=1587741750563&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fworkbox-webpack-plugin%2Fdownload%2Fworkbox-webpack-plugin-4.3.1.tgz", + "integrity": "sha1-R/9eocwHS2xA+1qGEIhjokEg1L0=", + "requires": { + "@babel/runtime": "^7.0.0", + "json-stable-stringify": "^1.0.1", + "workbox-build": "^4.3.1" + } + }, + "workbox-window": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/workbox-window/download/workbox-window-4.3.1.tgz", + "integrity": "sha1-7mBRvxDwavpUg8m436BTGZTt4PM=", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npm.taobao.org/worker-farm/download/worker-farm-1.7.0.tgz", + "integrity": "sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag=", + "requires": { + "errno": "~0.1.7" + } + }, + "worker-rpc": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/worker-rpc/download/worker-rpc-0.1.1.tgz", + "integrity": "sha1-y1Zb1tcHGo8WZgaGBR6WmtMvVNU=", + "requires": { + "microevent.ts": "~0.1.1" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-5.1.0.tgz", + "integrity": "sha1-H9H2cjXVttD+54EFYAG/tpTAOwk=", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/write/download/write-1.0.3.tgz", + "integrity": "sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM=", + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npm.taobao.org/write-file-atomic/download/write-file-atomic-2.4.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwrite-file-atomic%2Fdownload%2Fwrite-file-atomic-2.4.1.tgz", + "integrity": "sha1-0LBUY8GIroBDlv1asqNwBir4dSk=", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npm.taobao.org/ws/download/ws-5.2.2.tgz", + "integrity": "sha1-3/7xSGa46NyRM1glFNG++vlumA8=", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/xml-name-validator/download/xml-name-validator-3.0.0.tgz", + "integrity": "sha1-auc+Bt5NjG5H+fsYH3jWSK1FfGo=" + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/xmlchars/download/xmlchars-2.2.0.tgz", + "integrity": "sha1-Bg/hvLf5x2/ioX24apvDq4lCEMs=" + }, + "xregexp": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/xregexp/download/xregexp-4.3.0.tgz", + "integrity": "sha1-fpLnPZF0qZpZdD9npM6HmgS1rlA=", + "requires": { + "@babel/runtime-corejs3": "^7.8.3" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz", + "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/y18n/download/y18n-4.0.0.tgz", + "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyallist%2Fdownload%2Fyallist-4.0.0.tgz", + "integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=" + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npm.taobao.org/yaml/download/yaml-1.10.0.tgz?cache=0&sync_timestamp=1589623533772&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyaml%2Fdownload%2Fyaml-1.10.0.tgz", + "integrity": "sha1-O1k63ZRIdgd9TWg/7gEIG9n/8x4=" + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npm.taobao.org/yargs/download/yargs-13.3.2.tgz", + "integrity": "sha1-rX/+/sGqWVZayRX4Lcyzipwxot0=", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=" + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1591460606987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz", + "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-13.1.2.tgz", + "integrity": "sha1-Ew8JcC667vJlDVTObj5XBvek+zg=", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/package.json b/package.json index f3d8522..5fc284e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "auto": "node scripts/curl-leetcode.js && node scripts/generate-leetcode.js" + }, "eslintConfig": { "extends": "react-app" @@ -31,5 +33,10 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "cheerio": "^1.0.0-rc.3", + "iconv-lite": "^0.5.1", + "log4js": "^6.3.0" } } diff --git a/scripts/LeetCodeProvider.js b/scripts/LeetCodeProvider.js new file mode 100644 index 0000000..20c622e --- /dev/null +++ b/scripts/LeetCodeProvider.js @@ -0,0 +1,66 @@ + + +const request = require('request') +const Iconv = require('iconv-lite') +const cheerio = require('cheerio') +const Logger = require('./Logger') + + + +class LeetCodeProvider { + + + static getInstance() { + return this.oInstance || (this.oInstance = new LeetCodeProvider) + } + + getProblemsTitle() { + return new Promise((ok,unExpect) => { + + Logger.success('正在获取问题列表...') + + request({ + method:'GET', + url:'https://github.com/azl397985856/leetcode/tree/master/problems', + encoding:null}, + (error,response,body) => { + if(error) { + unExpect(Logger.error('获取问题列表失败',error) && error) + } else { + let aProblemTitles =[] + let sHtml = Iconv.decode(body, 'utf-8').toString() + cheerio.load(sHtml)('.js-navigation-item .content .js-navigation-open ').each((idx,ele)=> aProblemTitles.push(ele.attribs['title']) ) + Logger.success('获取问题列表成功') + ok(aProblemTitles) + } + }) + + }) + } + + getProblemDetail(problemNameWithExt) { + return new Promise((ok, unExpect) => { + + Logger.success('正在抓取问题:', problemNameWithExt) + + request({ + method:'GET', + url:`https://raw.githubusercontent.com/azl397985856/leetcode/master/problems/${problemNameWithExt}`, + encoding:null + }, + (error,response,body) => { + if (error) { + unExpect(Logger.error(`抓取问题 "${problemNameWithExt}" 失败`,error) && error) + } else { + let markdown = Iconv.decode(body, 'utf-8').toString() + Logger.success(`抓取问题 "${problemNameWithExt}" 成功!`) + ok(markdown) + } + + }) +}) +} + +} + +module.exports = LeetCodeProvider \ No newline at end of file diff --git a/scripts/Logger.js b/scripts/Logger.js new file mode 100644 index 0000000..72a5820 --- /dev/null +++ b/scripts/Logger.js @@ -0,0 +1,24 @@ + +const log4js = require("log4js"); + +const logger = log4js.getLogger() + +logger.level = 'debug' + +logger.category = 'LeetCode' + +class Logger { + + + + static success(...args) { + logger.info(...args) + } + + static error(...args) { + logger.error(...args) + } + +} + +module.exports = Logger \ No newline at end of file diff --git a/scripts/constants.js b/scripts/constants.js new file mode 100644 index 0000000..c597a01 --- /dev/null +++ b/scripts/constants.js @@ -0,0 +1,10 @@ + + + +module.exports = { + support_language: [ + 'java', + 'python', + 'js' + ] +} \ No newline at end of file diff --git a/scripts/curl-leetcode.js b/scripts/curl-leetcode.js new file mode 100644 index 0000000..026ce8a --- /dev/null +++ b/scripts/curl-leetcode.js @@ -0,0 +1,64 @@ +const LeetCodeProvider = require('./LeetCodeProvider') + +const Logger = require('./Logger') + +const Utils = require('./utils') + +/** + * 请求处理频率 ms + */ +const requestRate = 300 + +/** + * 当前请求问题索引 + */ +let requsetNumber = 0 + + +const getProblemDetail = (questionsName, requsetNumber) => { + +const cachedFilesName = Utils.getDirsFileName('spider/row-markdown') + +if ( cachedFilesName.includes(questionsName[requsetNumber]) ) { + + Logger.success(`${questionsName[requsetNumber]}命中缓存, 跳过。。。`) + + requsetNumber++ + + setTimeout(() => { + + getProblemDetail(questionsName, requsetNumber) + + }, requestRate) +} + else { + + questionsName[requsetNumber] && LeetCodeProvider.getInstance().getProblemDetail(questionsName[requsetNumber]).then(markDown => { + + Logger.success(`问题: "${questionsName[requsetNumber]}" | 结果: ${JSON.stringify(markDown)}`) + + Utils.writeFileSync('spider/row-markdown/',questionsName[requsetNumber],markDown) + + requsetNumber++ + }).catch(Logger.error).then(() => { + + setTimeout(() => { + + questionsName[requsetNumber] && getProblemDetail(questionsName, requsetNumber) + + }, requestRate) + }) + } + +} + + +LeetCodeProvider.getInstance().getProblemsTitle().then(questionsName => { + + getProblemDetail(questionsName, requsetNumber) + +}) + + + + diff --git a/scripts/generate-leetcode.js b/scripts/generate-leetcode.js new file mode 100644 index 0000000..76498d4 --- /dev/null +++ b/scripts/generate-leetcode.js @@ -0,0 +1,74 @@ +const Utils = require('./utils') +const Logger = require('./Logger') +const { support_language } = require('./constants') + + + + +const genertateLeetcodeToJson = () => { +const rowMarkdowns = Utils.getDirsFileName('spider/row-markdown') + +rowMarkdowns.forEach(filename => { + + let languageResloved = [] + let markdown + + try { + + Logger.success(`开始读取${filename}`) + + markdown = Utils.readFileSync(`spider/row-markdown/`,filename) + + Logger.success(`读取${filename}完毕`) + + } + catch (error) { + + Logger.error(`读取${filename}失败`,error) + } + + + /** + * 此替换是为了解决正则匹配java时出现的问题 + */ + + markdown = markdown.replace(/```javascript/g, '```js') + + support_language.forEach(lang => { + + markdown.replace(Utils.genRegByLang(lang), (noUseMatch, $1) => { + + languageResloved.push({ + lang, + code: $1 + }) + + }) + + + let oCustomStruct = { + question: filename.slice(0,-3), + companys: ['TODO'], + tags: ['TODO'], + reslove: languageResloved + } + + + + Logger.success(`开始生成 "${filename}"`) + + Utils.writeFileSync('spider/yield-db-json',`${filename.slice(0,-3)}.json`, JSON.stringify(oCustomStruct, null, 2)) + + Logger.success(`生成 "${filename}" 完毕`) + + }) + + + + + }) + + +} + +genertateLeetcodeToJson() \ No newline at end of file diff --git a/scripts/utils.js b/scripts/utils.js new file mode 100644 index 0000000..5e02e60 --- /dev/null +++ b/scripts/utils.js @@ -0,0 +1,46 @@ +const fs = require('fs') +const { resolve : pathResolve } = require('path') + + const { support_language } = require('./constants') + + +class Utils { + + + /** + * 获取不同语言的正则表达式 + * + * @static + * @param {*} lang + * @returns + * @memberof Utils + */ + static genRegByLang(lang) { + return new RegExp( `(?:\`\`\`${lang})((.|[\r\n])*?)(?:\`\`\`)`,'g') + } + + + static readFileSync(relativePath,filename) { + return fs.readFileSync(pathResolve(__dirname, '../',relativePath,filename),{encoding:'utf8'}) + } + + static getDirsFileName(dir) { + return fs.readdirSync(pathResolve(__dirname, '../', dir), {encoding:'utf8'}) + } + + + + static writeFileSync(dir,name,content) { + fs.writeFileSync(pathResolve(__dirname, '../', dir ,name),content) + } + + + +} + + + + + + +module.exports = Utils \ No newline at end of file diff --git a/spider/row-markdown/1.TwoSum.en.md b/spider/row-markdown/1.TwoSum.en.md new file mode 100644 index 0000000..4e80118 --- /dev/null +++ b/spider/row-markdown/1.TwoSum.en.md @@ -0,0 +1,50 @@ +## Problem +https://leetcode-cn.com/problems/two-sum + +## Problem Description +``` +Given an array of integers, return indices of the two numbers such that they add up to a specific target. + +You may assume that each input would have exactly one solution, and you may not use the same element twice. + +Example: + +Given nums = [2, 7, 11, 15], target = 9, + +Because nums[0] + nums[1] = 2 + 7 = 9, +return [0, 1]. +``` + +## Solution +The easiest solution to come up with is Brute Force. We could write two for-loops to traverse every element, and find the target numbers that meet the requirement. However, the time complexity of this solution is O(N^2), while the space complexity is O(1). Apparently, we need to find a way to optimize this solution since the time complexity is too high. What we could do is to record the numbers we have traversed and the relevant index with a Map. Whenever we meet a new number during traversal, we go back to the Map and check whether the `diff` between this number and the target number appeared before. If it did, the problem has been solved and there's no need to continue. + +## Key Points + - Find the difference instead of the sum + - Connect every number with its index through the help of Map + - Less time by more space. Reduce the time complexity from O(N) to O(1) + + ## Code + - Support Language: JS + +```js +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +const twoSum = function (nums, target) { + const map = new Map(); + for (let i = 0; i < nums.length; i++) { + const diff = target - nums[i]; + if (map.has(diff)) { + return [map.get(diff), i]; + } + map.set(nums[i], i); + } +} +``` + +***Complexity Anlysis*** + +- *Time Complexity*: O(N) +- *Space Complexity*:O(N) diff --git a/spider/row-markdown/1.TwoSum.md b/spider/row-markdown/1.TwoSum.md new file mode 100644 index 0000000..2f82994 --- /dev/null +++ b/spider/row-markdown/1.TwoSum.md @@ -0,0 +1,50 @@ +## 题目地址 +https://leetcode-cn.com/problems/two-sum + +## 题目描述 +``` +给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 + +你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 + +示例: + +给定 nums = [2, 7, 11, 15], target = 9 + +因为 nums[0] + nums[1] = 2 + 7 = 9 +所以返回 [0, 1] +``` +## 思路 +最容易想到的就是暴力枚举,我们可以利用两层 for 循环来遍历每个元素,并查找满足条件的目标元素。不过这样时间复杂度为 O(N^2),空间复杂度为 O(1),时间复杂度较高,我们要想办法进行优化。我们可以增加一个 Map 记录已经遍历过的数字及其对应的索引值。这样当遍历一个新数字的时候去 Map 里查询,target 与该数的差值是否已经在前面的数字中出现过。如果出现过,那么已经得出答案,就不必再往下执行了。 + +## 关键点 + +- 求和转换为求差 +- 借助 Map 结构将数组中每个元素及其索引相互对应 +- 以空间换时间,将查找时间从 O(N) 降低到 O(1) + +## 代码 +* 语言支持:JS + +```js +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +const twoSum = function (nums, target) { + const map = new Map(); + for (let i = 0; i < nums.length; i++) { + const diff = target - nums[i]; + if (map.has(diff)) { + return [map.get(diff), i]; + } + map.set(nums[i], i); + } +} +``` + +***复杂度分析*** + +- 时间复杂度:O(N) +- 空间复杂度:O(N) diff --git a/spider/row-markdown/101.symmetric-tree.md b/spider/row-markdown/101.symmetric-tree.md new file mode 100644 index 0000000..5aecc4f --- /dev/null +++ b/spider/row-markdown/101.symmetric-tree.md @@ -0,0 +1,111 @@ +## 题目地址(101. 对称二叉树) + +https://leetcode-cn.com/problems/symmetric-tree/ + +## 题目描述 + +``` +给定一个二叉树,检查它是否是镜像对称的。 + +  + +例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 + + 1 + / \ + 2 2 + / \ / \ +3 4 4 3 +  + +但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: + + 1 + / \ + 2 2 + \ \ + 3 3 +  + +进阶: + +你可以运用递归和迭代两种方法解决这个问题吗? + + +``` + +## 思路 + +看到这题的时候,我的第一直觉是 DFS。然后我就想:`如果左子树是镜像,并且右子树也是镜像,是不是就说明整体是镜像?`。经过几秒的思考, 这显然是不对的,不符合题意。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfbmeoo45bj31200iuabh.jpg) + +很明显其中左子树中的节点会和右子树中的节点进行比较,我把比较的元素进行了颜色区分,方便大家看。 + +这里我的想法是:`遍历每一个节点的时候,我都可以通过某种方法知道它对应的对称节点是谁。这样的话我直接比较两者是否一致就行了。` + +最初我的想法是两次遍历,第一次遍历的同时将遍历结果存储到哈希表中,然后第二次遍历去哈希表取。 + +这种方法可行,但是需要 N 的空间(N 为节点总数)。我想到如果两者可以同时进行遍历,是不是就省去了哈希表的开销。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfbso8u6myj31a30u0tf5.jpg) + +如果不明白的话,我举个简单例子: + +``` +给定一个数组,检查它是否是镜像对称的。例如,数组 [1,2,2,3,2,2,1] 是对称的。 +``` + +如果用哈希表的话大概是: + +```py +seen = dict() +for i, num in enumerate(nums): + seen[i] = num +for i, num in enumerate(nums): + if seen[len(nums) - 1 - i] != num: + return False +return True +``` + +而同时遍历的话大概是这样的: + +```py +l = 0 +r = len(nums) - 1 + +while l < r: + if nums[l] != nums[r]: return False + l += 1 + r -= 1 +return True + +``` + +> 其实更像本题一点的话应该是从中间分别向两边扩展 😂 + +## 代码 + +```py + +class Solution: + def isSymmetric(self, root: TreeNode) -> bool: + def dfs(root1, root2): + if root1 == root2: return True + if not root1 or not root2: return False + if root1.val != root2.val: return False + return dfs(root1.left, root2.right) and dfs(root1.right, root2.left) + if not root: return True + return dfs(root.left, root.right) +``` + +**_复杂度分析_** + +- 时间复杂度:$O(N)$,其中 N 为节点数。 +- 空间复杂度:递归的深度最高为节点数,因此空间复杂度是 $O(N)$,其中 N 为节点数。 + +更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 30K star 啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfaq00p8stj30x20iw7b0.jpg) diff --git a/spider/row-markdown/1011.capacity-to-ship-packages-within-d-days-cn.md b/spider/row-markdown/1011.capacity-to-ship-packages-within-d-days-cn.md new file mode 100644 index 0000000..5e257be --- /dev/null +++ b/spider/row-markdown/1011.capacity-to-ship-packages-within-d-days-cn.md @@ -0,0 +1,167 @@ +## 题目地址(1011. 在 D 天内送达包裹的能力) + +https://leetcode-cn.com/problems/capacity-to-ship-packages-within-d-days + +## 题目描述 + +传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。 + +传送带上的第 i  个包裹的重量为  weights[i]。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。 + +返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。 + +示例 1: + +输入:weights = [1,2,3,4,5,6,7,8,9,10], D = 5 +输出:15 +解释: +船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示: +第 1 天:1, 2, 3, 4, 5 +第 2 天:6, 7 +第 3 天:8 +第 4 天:9 +第 5 天:10 + +请注意,货物必须按照给定的顺序装运,因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。 +示例 2: + +输入:weights = [3,2,2,4,1,4], D = 3 +输出:6 +解释: +船舶最低载重 6 就能够在 3 天内送达所有包裹,如下所示: +第 1 天:3, 2 +第 2 天:2, 4 +第 3 天:1, 4 +示例 3: + +输入:weights = [1,2,3,1,1], D = 4 +输出:3 +解释: +第 1 天:1 +第 2 天:2 +第 3 天:3 +第 4 天:1, 1 + +提示: + +1 <= D <= weights.length <= 50000 +1 <= weights[i] <= 500 + +## 思路 + +这道题和[猴子吃香蕉](https://github.com/azl397985856/leetcode/blob/master/problems/875.koko-eating-bananas.md) 简直一摸一样,没有看过的建议看一下那道题。 + +像这种题如何你能发现本质的考点,那么 AC 是瞬间的事情。 这道题本质上就是从 1,2,3,4,。。。total(其中 toal 是总的货物重量)的有限离散数据中查找给定的数。这里我们不是直接查找 target,而是查找恰好能够在 D 天运完的载货量。 + +- 容量是 1 可以运完么? +- 容量是 2 可以运完么? +- 容量是 3 可以运完么? +- 。。。 +- 容量是 total 可以运完么?(当然可以,因为 D 大于等于 1) + +上面不断询问的过程如果回答是 yes 我们直接 return 即可。如果回答是 no,我们继续往下询问。 + +这是一个典型的二分问题,只不过我们的判断条件略有不同,大概是: + +```python +def canShip(opacity): + # 指定船的容量是否可以在D天运完 + lo = 0 + hi = total + while lo < hi: + mid = (lo + hi) // 2 + if canShip(mid): + hi = mid + else: + lo = mid + 1 + + return lo +``` + +## 关键点解析 + +- 能够识别出是给定的有限序列查找一个数字(二分查找),要求你对二分查找以及变体十分熟悉 + +## 代码 + +* 语言支持:`JS`,`Python` + +`python`: + +```python +class Solution: + def shipWithinDays(self, weights: List[int], D: int) -> int: + lo = 0 + hi = 0 + + def canShip(opacity): + days = 1 + remain = opacity + for weight in weights: + if weight > opacity: + return False + remain -= weight + if remain < 0: + days += 1 + remain = opacity - weight + return days <= D + + for weight in weights: + hi += weight + while lo < hi: + mid = (lo + hi) // 2 + if canShip(mid): + hi = mid + else: + lo = mid + 1 + + return lo +``` + +`js`: + +```js +/** + * @param {number[]} weights + * @param {number} D + * @return {number} + */ +var shipWithinDays = function(weights, D) { + let high = weights.reduce((acc, cur) => acc + cur) + let low = 0 + + while(low < high) { + let mid = Math.floor((high + low) / 2) + if (canShip(mid)) { + high = mid + } else { + low = mid + 1 + } + } + + return low + + function canShip(opacity) { + let remain = opacity + let count = 1 + for (let weight of weights) { + if (weight > opacity) { + return false + } + remain -= weight + if (remain < 0) { + count++ + remain = opacity - weight + } + if (count > D) { + return false + } + } + return count <= D + } +}; +``` + +## 扩展 + +## 参考 diff --git a/spider/row-markdown/1011.capacity-to-ship-packages-within-d-days-en.md b/spider/row-markdown/1011.capacity-to-ship-packages-within-d-days-en.md new file mode 100644 index 0000000..a313d6e --- /dev/null +++ b/spider/row-markdown/1011.capacity-to-ship-packages-within-d-days-en.md @@ -0,0 +1,187 @@ +## Problem + +https://leetcode-cn.com/problems/capacity-to-ship-packages-within-d-days + +## Problem Description + +A conveyor belt has packages that must be shipped from one port to another within D days. + +The i-th package on the conveyor belt has a weight of weights[i]. Each day, we load the ship with packages on the conveyor belt (in the order given by weights). We may not load more weight than the maximum weight capacity of the ship. + +Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within D days. + +**Example 1:** + +``` +Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5 +Output: 15 +Explanation: +A ship capacity of 15 is the minimum to ship all the packages in 5 days like this: +1st day: 1, 2, 3, 4, 5 +2nd day: 6, 7 +3rd day: 8 +4th day: 9 +5th day: 10 + +Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed. +``` + +**Example 2:** + +``` +Input: weights = [3,2,2,4,1,4], D = 3 +Output: 6 +Explanation: +A ship capacity of 6 is the minimum to ship all the packages in 3 days like this: +1st day: 3, 2 +2nd day: 2, 4 +3rd day: 1, 4 +``` + +**Example 3:** + +``` +Input: weights = [1,2,3,1,1], D = 4 +Output: 3 +Explanation: +1st day: 1 +2nd day: 2 +3rd day: 3 +4th day: 1, 1 +``` + + + + **Note:** + +1. `1 <= D <= weights.length <= 50000` +2. `1 <= weights[i] <= 500` + + + +## Solution + +The problem is same as [**LeetCode 875 koko-eating-bananas**] (https://github.com/azl397985856/leetcode/blob/master/problems/875.koko-eating-bananas-en.md) practically. + +It is easy to solve this kind of problems if you take a closer look into it. + + +The essence is to search a given number in finite discrete data like [ 1,2,3,4, ... , total ]. + +However, We should find the cargo that can be shipped in D days rather than look for the target directly. + + +Consider the following questions: + +- Can it be shipped if the capacity is 1? +- Can it be shipped if the capacity is 2? +- Can it be shipped if the capacity is 3? +- ... +- Can it be shipped if the capacity is total ? ( Yeap we can, D is greater than or equal to 1) + +During the process, we directly `return` if the answer is *yes*. + +If the answer is *no*, just keep asking. + +This is a typical binary search problem, the only difference is the judgement condition: + + +```python +def canShip(opacity): + # Whether the capacity of the specified ship can be shipped in D days + lo = 0 + hi = total + while lo < hi: + mid = (lo + hi) // 2 + if canShip(mid): + hi = mid + else: + lo = mid + 1 + return lo +``` + +## Key Points + +- if you are so familiar with binary search as well its transformation, you can easily find out that using binary search to find one number in a given number sequence of a certain length. + +## Code (`JS/Python`) + +- `Python` + +```python +class Solution: + def shipWithinDays(self, weights: List[int], D: int) -> int: + lo = 0 + hi = 0 + + def canShip(opacity): + days = 1 + remain = opacity + for weight in weights: + if weight > opacity: + return False + remain -= weight + if remain < 0: + days += 1 + remain = opacity - weight + return days <= D + + for weight in weights: + hi += weight + while lo < hi: + mid = (lo + hi) // 2 + if canShip(mid): + hi = mid + else: + lo = mid + 1 + + return lo +``` + +- `JavaScript` + +```js +/** + * @param {number[]} weights + * @param {number} D + * @return {number} + */ +var shipWithinDays = function(weights, D) { + let high = weights.reduce((acc, cur) => acc + cur) + let low = 0 + + while(low < high) { + let mid = Math.floor((high + low) / 2) + if (canShip(mid)) { + high = mid + } else { + low = mid + 1 + } + } + + return low + + function canShip(opacity) { + let remain = opacity + let count = 1 + for (let weight of weights) { + if (weight > opacity) { + return false + } + remain -= weight + if (remain < 0) { + count++ + remain = opacity - weight + } + if (count > D) { + return false + } + } + return count <= D + } +}; +``` + +## References + +## Extension diff --git a/spider/row-markdown/1014.best-sightseeing-pair.md b/spider/row-markdown/1014.best-sightseeing-pair.md new file mode 100644 index 0000000..45caa61 --- /dev/null +++ b/spider/row-markdown/1014.best-sightseeing-pair.md @@ -0,0 +1,92 @@ +## 题目地址(1014. 最佳观光组合) + +https://leetcode-cn.com/problems/best-sightseeing-pair/description/ + +## 题目描述 + +给定正整数数组  A,A[i]  表示第 i 个观光景点的评分,并且两个景点  i 和  j  之间的距离为  j - i。 + +一对景点(i < j)组成的观光组合的得分为(A[i] + A[j] + i - j):景点的评分之和减去它们两者之间的距离。 + +返回一对观光景点能取得的最高分。 + +示例: + +输入:[8,1,5,2,6] +输出:11 +解释:i = 0, j = 2, A[i] + A[j] + i - j = 8 + 5 + 0 - 2 = 11 + +提示: + +2 <= A.length <= 50000 +1 <= A[i] <= 1000 + +## 思路 + +最简单的思路就是两两组合,找出最大的,妥妥超时,我们来看下代码: + +```python +class Solution: + def maxScoreSightseeingPair(self, A: List[int]) -> int: + n = len(A) + res = 0 + for i in range(n - 1): + for j in range(i + 1, n): + res = max(res, A[i] + A[j] + i - j) + return res +``` + +我们思考如何优化。 其实我们可以遍历一遍数组,对于数组的每一项`A[j] - j` 我们都去前面找`最大`的 A[i] + i (这样才能保证结果最大)。 + +我们考虑使用动态规划来解决, 我们使用 dp[i] 来表示 数组 A 前 i 项的`A[i] + i`的最大值。 + +```python +class Solution: + def maxScoreSightseeingPair(self, A: List[int]) -> int: + n = len(A) + dp = [float('-inf')] * (n + 1) + res = 0 + for i in range(n): + dp[i + 1] = max(dp[i], A[i] + i) + res = max(res, dp[i] + A[i] - i) + return res +``` + +如上其实我们发现,dp[i + 1] 只和 dp[i] 有关,这是一个空间优化的信号。我们其实可以使用一个变量来记录,而不必要使用一个数组,代码见下方。 + +## 关键点解析 + +- 空间换时间 +- dp 空间优化 + +## 代码 + +```python +class Solution: + def maxScoreSightseeingPair(self, A: List[int]) -> int: + n = len(A) + pre = A[0] + 0 + res = 0 + for i in range(1, n): + res = max(res, pre + A[i] - i) + pre = max(pre, A[i] + i) + return res +``` + +## 小技巧 + +Python 的代码如果不使用 max,而是使用 if else 效率目测会更高,大家可以试一下。 + +```python +class Solution: + def maxScoreSightseeingPair(self, A: List[int]) -> int: + n = len(A) + pre = A[0] + 0 + res = 0 + for i in range(1, n): + # res = max(res, pre + A[i] - i) + # pre = max(pre, A[i] + i) + res = res if res > pre + A[i] - i else pre + A[i] - i + pre = pre if pre > A[i] + i else A[i] + i + return res +``` diff --git a/spider/row-markdown/1015.smallest-integer-divisible-by-k.md b/spider/row-markdown/1015.smallest-integer-divisible-by-k.md new file mode 100644 index 0000000..bbfca68 --- /dev/null +++ b/spider/row-markdown/1015.smallest-integer-divisible-by-k.md @@ -0,0 +1,100 @@ +## 题目地址 + +https://leetcode-cn.com/problems/smallest-integer-divisible-by-k/description/ + +## 题目描述 + +``` +给定正整数 K,你需要找出可以被 K 整除的、仅包含数字 1 的最小正整数 N。 + +返回 N 的长度。如果不存在这样的 N,就返回 -1。 + +  + +示例 1: + +输入:1 +输出:1 +解释:最小的答案是 N = 1,其长度为 1。 +示例 2: + +输入:2 +输出:-1 +解释:不存在可被 2 整除的正整数 N 。 +示例 3: + +输入:3 +输出:3 +解释:最小的答案是 N = 111,其长度为 3。 +  + +提示: + +1 <= K <= 10^5 + +``` + +## 思路 + +这道题是说给定一个 K 值,能否找到一个形如 1,11,111,1111 。。。 这样的数字 n 使得 n % K == 0。 + +首先容易想到的是如果 K 是 2,4,5, 6,8 结尾的话,一定是不行的。直观的解法是从 1,11,111,1111 。。。 这样一直除下去,直到碰到可以整除的,我们返回即可。 但是如果这个数字根本就无法整除怎么办?没错,我们会无限循环下去。我们应该在什么时刻跳出循环,返回 - 1 (表示不能整除)呢? + +我们拿题目给出的不能整除的 2 来说。 + +- 1 // 2 等于 1 +- 11 // 2 等于 1 +- 111 // 2 等于 1 +- ... + +我们再来一个不能整除的例子 6: + +- 1 // 6 等于 1 +- 11 // 6 等于 5 +- 111 // 6 等于 3 +- 1111 // 6 等于 1 +- 11111 // 6 等于 5 +- ... + +通过观察我们发现不断整除的过程,会陷入无限循环,对于 2 来说,其循环节就是 1。对于 6 来说,其循环节来说就是 153。而且由于我们的分母是 6,也就是说余数的可能性一共只有六种情况 0,1,2,3,4,5。 + +上面是感性的认识, 接下来我们从数学上予以证明。上面的算法用公式来表示就是`mod = (10 \* mod + 1) % K`。假如出现了相同的数,我们可以肯定之后会无限循环。比如 153 之后出现了 1,我们可以肯定之后一定是 35。。。 因为我们的 mod 只是和前一个 mod 有关,上面的公式是一个`纯函数`。 + +## 关键点解析 + +- 数学(无限循环与循环节) + +## 代码 + +```python +# +# @lc app=leetcode.cn id=1015 lang=python3 +# +# [1015] 可被 K 整除的最小整数 +# + +# @lc code=start + + +class Solution: + def smallestRepunitDivByK(self, K: int) -> int: + if K % 10 in [2, 4, 5, 6, 8]: + return - 1 + seen = set() + mod = 0 + for i in range(1, K + 1): + mod = (mod * 10 + 1) % K + if mod in seen: + return -1 + if mod == 0: + return ix + seen.add(mod) + + # @lc code=end + + +``` + +## 相关题目 + +- [166. 分数到小数](https://leetcode-cn.com/problems/fraction-to-recurring-decimal/) diff --git a/spider/row-markdown/1019.next-greater-node-in-linked-list.md b/spider/row-markdown/1019.next-greater-node-in-linked-list.md new file mode 100644 index 0000000..964a378 --- /dev/null +++ b/spider/row-markdown/1019.next-greater-node-in-linked-list.md @@ -0,0 +1,102 @@ +## 题目地址 + +https://leetcode-cn.com/problems/next-greater-node-in-linked-list/submissions/ + +## 题目描述 + +``` +给出一个以头节点 head 作为第一个节点的链表。链表中的节点分别编号为:node_1, node_2, node_3, ... 。 + +每个节点都可能有下一个更大值(next larger value):对于 node_i,如果其 next_larger(node_i) 是 node_j.val,那么就有 j > i 且  node_j.val > node_i.val,而 j 是可能的选项中最小的那个。如果不存在这样的 j,那么下一个更大值为 0 。 + +返回整数答案数组 answer,其中 answer[i] = next_larger(node_{i+1}) 。 + +注意:在下面的示例中,诸如 [2,1,5] 这样的输入(不是输出)是链表的序列化表示,其头节点的值为 2,第二个节点值为 1,第三个节点值为 5 。 + +  + +示例 1: + +输入:[2,1,5] +输出:[5,5,0] +示例 2: + +输入:[2,7,4,3,5] +输出:[7,0,5,5,0] +示例 3: + +输入:[1,7,5,1,9,2,5,1] +输出:[7,9,9,9,0,5,0,0] +  + +提示: + +对于链表中的每个节点,1 <= node.val <= 10^9 +给定列表的长度在 [0, 10000] 范围内 +``` + +## 思路 + +看完题目就应该想到单调栈才行,LeetCode 上关于单调栈的题目还不少,难度都不小。但是一旦你掌握了这个算法,那么这些题目对你来说都不是问题了。 + +如果你不用单调栈,那么可以暴力$O(N^2)$的时间复杂度解决,只需要双层循环即可。但是这种做法应该是过不了关的。使用单调栈可以将时间复杂度降低到线性,当然需要额外的$O(N)$的空间复杂度。 + +顾名思义,单调栈即满足单调性的栈结构。与单调队列相比,其只在一端进行进出。为了描述方便,以下举例及代码以维护一个整数的单调递减栈为例。将一个元素插入单调栈时,为了维护栈的单调性,需要在保证将该元素插入到栈顶后整个栈满足单调性的前提下弹出最少的元素。 + +例如,栈中自顶向下的元素为 1,2,4,5 ,插入元素 3 时为了保证单调性需要依次弹出元素 : + +- 最开始栈是这样的: [5,4,2,1] +- 为了维护递减特性,1,2 需要被移除。此时栈是这样的: [5,4] +- 我们将 3 push 到栈顶即可 +- 此时栈是这样的: [5,4,3] + +用代码描述如下: + +Python Code: + +```python +def monoStack(list): + st = [] + for v in list: + while len(st) > 0 and v > st[-1]: + st.pop() + st.append(v) + return st +monoStack([5, 4, 2, 1, 3]) # output: [5, 4, 3] +``` + +## 关键点 + +- 单调栈(单调递减栈) +- 单调栈的代码模板 + +## 代码 + +Python Code: + +```python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def nextLargerNodes(self, head): + res, st = [], [] + while head: + while len(st) > 0 and head.val > st[-1][1]: + res[st.pop()[0]] = head.val + st.append((len(res), head.val)) + res.append(0) + head = head.next + return res +``` + +## 扩展 + +甚至可以做到 O(1)的空间复杂度,请参考[C# O(n) time O(1) space]() + +## 相关题目 + +- [毎日一题 - 739.Daily Temperatures](https://github.com/azl397985856/leetcode/blob/master/daily/2019-06-06.md) diff --git a/spider/row-markdown/102.binary-tree-level-order-traversal.md b/spider/row-markdown/102.binary-tree-level-order-traversal.md new file mode 100644 index 0000000..747510e --- /dev/null +++ b/spider/row-markdown/102.binary-tree-level-order-traversal.md @@ -0,0 +1,246 @@ + +## 题目地址 +https://leetcode.com/problems/binary-tree-level-order-traversal/description/ + +## 题目描述 +``` +给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。 + +  + +示例: +二叉树:[3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +返回其层次遍历结果: + +[ + [3], + [9,20], + [15,7] +] +``` + +## 思路 + +这是一个典型的二叉树遍历问题, 关于二叉树遍历,我总结了一个[专题](https://github.com/azl397985856/leetcode/blob/master/thinkings/binary-tree-traversal.md),大家可以先去看下那个,然后再来刷这道题。 + +这道题可以借助`队列`实现,首先把root入队,然后入队一个特殊元素Null(来表示每层的结束)。 + + +然后就是while(queue.length), 每次处理一个节点,都将其子节点(在这里是left和right)放到队列中。 + +然后不断的出队, 如果出队的是null,则表式这一层已经结束了,我们就继续push一个null。 + +如果不入队特殊元素Null来表示每层的结束,则在while循环开始时保存当前队列的长度,以保证每次只遍历一层(参考下面的C++ Code)。 + +> 如果采用递归方式,则需要将当前节点,当前所在的level以及结果数组传递给递归函数。在递归函数中,取出节点的值,添加到level参数对应结果数组元素中(参考下面的C++ Code 或 Python Code)。 + + +## 关键点解析 + +- 队列 + +- 队列中用Null(一个特殊元素)来划分每层 + +- 树的基本操作- 遍历 - 层次遍历(BFS) + +- 注意塞入null的时候,判断一下当前队列是否为空,不然会无限循环 + + +## 代码 +* 语言支持:JS,C++,Python3 + +Javascript Code: +```js +/* + * @lc app=leetcode id=102 lang=javascript + * + * [102] Binary Tree Level Order Traversal + * + * https://leetcode.com/problems/binary-tree-level-order-traversal/description/ + * + * algorithms + * Medium (47.18%) + * Total Accepted: 346.4K + * Total Submissions: 731.3K + * Testcase Example: '[3,9,20,null,null,15,7]' + * + * Given a binary tree, return the level order traversal of its nodes' values. + * (ie, from left to right, level by level). + * + * + * For example: + * Given binary tree [3,9,20,null,null,15,7], + * + * + * ⁠ 3 + * ⁠ / \ + * ⁠ 9 20 + * ⁠ / \ + * ⁠ 15 7 + * + * + * + * return its level order traversal as: + * + * [ + * ⁠ [3], + * ⁠ [9,20], + * ⁠ [15,7] + * ] + * + * + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +var levelOrder = function(root) { + if (!root) return []; + const items = []; // 存放所有节点 + const queue = [root, null]; // null 简化操作 + let levelNodes = []; // 存放每一层的节点 + + while (queue.length > 0) { + const t = queue.shift(); + + if (t) { + levelNodes.push(t.val) + if (t.left) { + queue.push(t.left); + } + if (t.right) { + queue.push(t.right); + } + } else { // 一层已经遍历完了 + items.push(levelNodes); + levelNodes = []; + if (queue.length > 0) { + queue.push(null) + } + } + } + + return items; +}; + +``` +C++ Code: +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ + + // 迭代 +class Solution { +public: + vector> levelOrder(TreeNode* root) { + auto ret = vector>(); + if (root == nullptr) return ret; + auto q = vector(); + q.push_back(root); + auto level = 0; + while (!q.empty()) + { + auto sz = q.size(); + ret.push_back(vector()); + for (auto i = 0; i < sz; ++i) + { + auto t = q.front(); + q.erase(q.begin()); + ret[level].push_back(t->val); + if (t->left != nullptr) q.push_back(t->left); + if (t->right != nullptr) q.push_back(t->right); + } + ++level; + } + return ret; + } +}; + +// 递归 +class Solution { +public: + vector> levelOrder(TreeNode* root) { + vector> v; + levelOrder(root, 0, v); + return v; + } +private: + void levelOrder(TreeNode* root, int level, vector>& v) { + if (root == NULL) return; + if (v.size() < level + 1) v.resize(level + 1); + v[level].push_back(root->val); + levelOrder(root->left, level + 1, v); + levelOrder(root->right, level + 1, v); + } +}; +``` +Python Code: +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + def levelOrder(self, root: TreeNode) -> List[List[int]]: + """递归法""" + if root is None: + return [] + + result = [] + + def add_to_result(level, node): + """递归函数 + :param level int 当前在二叉树的层次 + :param node TreeNode 当前节点 + """ + if level > len(result) - 1: + result.append([]) + + result[level].append(node.val) + if node.left: + add_to_result(level+1, node.left) + if node.right: + add_to_result(level+1, node.right) + + add_to_result(0, root) + return result +``` + +***复杂度分析*** +- 时间复杂度:$O(N)$,其中N为树中节点总数。 +- 空间复杂度:$O(N)$,其中N为树中节点总数。 + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +## 扩展 + +实际上这道题方法很多, 比如经典的三色标记法。 + +## 相关题目 +- [103.binary-tree-zigzag-level-order-traversal](./103.binary-tree-zigzag-level-order-traversal.md) +- [104.maximum-depth-of-binary-tree](./104.maximum-depth-of-binary-tree.md) diff --git a/spider/row-markdown/1020.number-of-enclaves.md b/spider/row-markdown/1020.number-of-enclaves.md new file mode 100644 index 0000000..bd77a25 --- /dev/null +++ b/spider/row-markdown/1020.number-of-enclaves.md @@ -0,0 +1,163 @@ +## 题目地址 + +https://leetcode-cn.com/problems/number-of-enclaves/ + +## 题目描述 + +``` +给出一个二维数组 A,每个单元格为 0(代表海)或 1(代表陆地)。 + +移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。 + +返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。 + +  + +示例 1: + +输入:[[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] +输出:3 +解释: +有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。 +示例 2: + +输入:[[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]] +输出:0 +解释: +所有 1 都在边界上或可以到达边界。 +  + +提示: + +1 <= A.length <= 500 +1 <= A[i].length <= 500 +0 <= A[i][j] <= 1 +所有行的大小都相同 + +``` + +## 解法一 (暴力法) + +### 思路 + +这是一个典型的可以使用 DFS 进行解决的一类题目, LeetCode 相关的题目有很多。 + +对于这种题目不管是思路还是代码都有很大的相似性,我们来看下。 + +暴力法的思路很简单,我们遍历整个矩阵: + +- 如果遍历到 0,我们不予理会 +- 如果遍历到 1. 我们将其加到 temp +- 我们不断拓展边界(上下左右) +- 如果 dfs 过程中碰到了边界,说明我们可以逃脱,我们将累加的 temp 清空 +- 如果 dfs 过程之后没有碰到边界,说明我们无法逃脱。我们将 temp 加到 cnt +- 最终返回 cnt 即可 + +### 关键点解析 + +- visited 记录访问过的节点,防止重复计算 + +### 代码 + +Python Code: + +```python +class Solution: + temp = 0 + meetEdge = False + + def numEnclaves(self, A: List[List[int]]) -> int: + cnt = 0 + m = len(A) + n = len(A[0]) + visited = set() + + def dfs(i, j): + if i < 0 or i >= m or j < 0 or j >= n or (i, j) in visited: + return + visited.add((i, j)) + if A[i][j] == 1: + self.temp += 1 + else: + return + if i == 0 or i == m - 1 or j == 0 or j == n - 1: + self.meetEdge = True + dfs(i + 1, j) + dfs(i - 1, j) + dfs(i, j + 1) + dfs(i, j - 1) + for i in range(m): + for j in range(n): + dfs(i, j) + if not self.meetEdge: + cnt += self.temp + self.meetEdge = False + self.temp = 0 + return cnt + +``` + +## 解法二 (消除法) + +### 思路 + +上面的解法时间复杂度和空间复杂度都很差,我们考虑进行优化, 这里我们使用消除法。 + +- 从矩阵边界开始 dfs +- 如果碰到 1 就将其变成 0 +- 如果碰到 0 则什么都不做 +- 最后我们遍历整个矩阵,数一下 1 的个数即可。 + +### 关键点解析 + +- dfs 消除法 + +### 代码 + +Python Code: + +```python +# +# @lc app=leetcode.cn id=1020 lang=python3 +# +# [1020] 飞地的数量 +# + +# @lc code=start + + +class Solution: + + def numEnclaves(self, A: List[List[int]]) -> int: + cnt = 0 + m = len(A) + n = len(A[0]) + + def dfs(i, j): + if i < 0 or i >= m or j < 0 or j >= n or A[i][j] == 0: + return + A[i][j] = 0 + + dfs(i + 1, j) + dfs(i - 1, j) + dfs(i, j + 1) + dfs(i, j - 1) + for i in range(m): + dfs(i, 0) + dfs(i, n - 1) + for j in range(1, n - 1): + dfs(0, j) + dfs(m - 1, j) + for i in range(m): + for j in range(n): + if A[i][j] == 1: + cnt += 1 + return cnt + + # @lc code=end + +``` + +## 参考 + +- [200.number-of-islands](https://github.com/azl397985856/leetcode/blob/master/problems/200.number-of-islands.md) diff --git a/spider/row-markdown/1023.camelcase-matching.md b/spider/row-markdown/1023.camelcase-matching.md new file mode 100644 index 0000000..cfeb796 --- /dev/null +++ b/spider/row-markdown/1023.camelcase-matching.md @@ -0,0 +1,136 @@ +## 题目地址 + +https://leetcode-cn.com/problems/camelcase-matching/ + +## 题目描述 + +``` +如果我们可以将小写字母插入模式串 pattern 得到待查询项 query,那么待查询项与给定模式串匹配。(我们可以在任何位置插入每个字符,也可以插入 0 个字符。) + +给定待查询列表 queries,和模式串 pattern,返回由布尔值组成的答案列表 answer。只有在待查项 queries[i] 与模式串 pattern 匹配时, answer[i] 才为 true,否则为 false。 + +  + +示例 1: + +输入:queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FB" +输出:[true,false,true,true,false] +示例: +"FooBar" 可以这样生成:"F" + "oo" + "B" + "ar"。 +"FootBall" 可以这样生成:"F" + "oot" + "B" + "all". +"FrameBuffer" 可以这样生成:"F" + "rame" + "B" + "uffer". +示例 2: + +输入:queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FoBa" +输出:[true,false,true,false,false] +解释: +"FooBar" 可以这样生成:"Fo" + "o" + "Ba" + "r". +"FootBall" 可以这样生成:"Fo" + "ot" + "Ba" + "ll". +示例 3: + +输出:queries = ["FooBar","FooBarTest","FootBall","FrameBuffer","ForceFeedBack"], pattern = "FoBaT" +输入:[false,true,false,false,false] +解释: +"FooBarTest" 可以这样生成:"Fo" + "o" + "Ba" + "r" + "T" + "est". +  + +提示: + +1 <= queries.length <= 100 +1 <= queries[i].length <= 100 +1 <= pattern.length <= 100 +所有字符串都仅由大写和小写英文字母组成。 + +``` + +## 思路 + +这道题是一道典型的双指针题目。不过这里的双指针并不是指向同一个数组或者字符串,而是指向多个,这道题是指向两个,分别是 query 和 pattern,这种题目非常常见,能够识别和掌握这种题目的解题模板非常重要。对 queries 的每一项我们的逻辑是一样的,这里就以其中一项为例进行讲解。 + +以 query 为 FooBar,pattern 为 FB 为例。 + +首先我们来简化一下问题,假如我们没有`可以在任何位置插入每个字符,也可以插入 0 个字符。`这个规则。我们的问题会比较简单,这个时候我们的算法是什么样的呢?一起来看下: + +1. 首先我们建立两个指针 i 和 j 分别指向 query 和 pattern 的首字母。 +2. 当 i 和 j 指向的字母相同的时候,我们同时向后移动两个指针一个单位。 +3. 当 i 和 j 指向的字母不同的时候,我们直接返回 False + +假如我们要找到的不是子串,而是子序列怎么办?我们不妨假设判断 pattern 是否是 query 的子序列。 其实 LeetCode 实际上也有这样的题目,我们来看下: + +1. 首先我们建立两个指针 i 和 j 分别指向 query 和 pattern 的首字母。 +2. 当 i 和 j 指向的字母相同的时候,我们同时向后移动两个指针一个单位。 +3. 当 i 和 j 指向的字母不同的时候,我们移动 i 指针。 +4. 当 i 超出 query 范围的时候,我们只需要判断 pattern 是否达到了终点即可。当然我们也可以提前退出。 + +我们直接参考下 LeetCode [392. 判断子序列](https://leetcode-cn.com/problems/is-subsequence/)。 + +代码: + +> 给定字符串 s 和 t ,判断 s 是否为 t 的子序列 + +Python Code: + +```python +class Solution: + def isSubsequence(self, s: str, t: str) -> bool: + i = 0 + j = 0 + while j < len(t): + if i < len(s) and s[i] == t[j]: + i += 1 + j += 1 + else: + j += 1 + if i >= len (s): + return True + return i == len(s) +``` + +然后我们加上`可以在任何位置插入每个字符,也可以插入 0 个字符。`这个规则。来看下有什么不同: + +1. 首先我们建立两个指针 i 和 j 分别指向 query 和 pattern 的首字母。 +2. 当 i 和 j 指向的字母相同的时候,我们同时向后移动两个指针一个单位。 +3. 当 i 和 j 指向的字母不同的时候,我们继续判断 i 指向的元素是否是小写。 +4. 如果是小写我们只把 i 向后移动一个单位。 +5. 如果不是小写我们直接返回 False + +## 关键点解析 + +- 双指针 +- 字符串匹配 +- 子序列 +- 子串 + +## 代码 + +Python Code: + +```python +class Solution: + def camelMatch(self, queries: List[str], pattern: str) -> List[bool]: + res = [] + for query in queries: + i = 0 + j = 0 + while i < len(query): + if j < len(pattern) and query[i] == pattern[j]: + i += 1 + j += 1 + elif query[i].islower(): + i += 1 + else: + break + if i == len(query) and j == len(pattern): + res.append(True) + else: + res.append(False) + return res +``` + +## 扩展 + +这是一个符合直觉的解法,但是却不是一个很优秀的解法,那么你有想到什么优秀的解法么? + +## 参考 + +- [392. 判断子序列](https://leetcode-cn.com/problems/is-subsequence/) diff --git a/spider/row-markdown/103.binary-tree-zigzag-level-order-traversal.md b/spider/row-markdown/103.binary-tree-zigzag-level-order-traversal.md new file mode 100644 index 0000000..7cf53ec --- /dev/null +++ b/spider/row-markdown/103.binary-tree-zigzag-level-order-traversal.md @@ -0,0 +1,213 @@ + +## 题目地址 +https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/ + +## 题目描述 +和leetcode 102 基本是一样的,思路是完全一样的。 + +``` +Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). + +For example: +Given binary tree [3,9,20,null,null,15,7], + 3 + / \ + 9 20 + / \ + 15 7 +return its zigzag level order traversal as: +[ + [3], + [20,9], + [15,7] +] +``` + +## 思路 + +这道题可以借助`队列`实现,首先把root入队,然后入队一个特殊元素Null(来表示每层的结束)。 + + +然后就是while(queue.length), 每次处理一个节点,都将其子节点(在这里是left和right)放到队列中。 + +然后不断的出队, 如果出队的是null,则表式这一层已经结束了,我们就继续push一个null。 + + +## 关键点解析 + +- 队列 + +- 队列中用Null(一个特殊元素)来划分每层 + +- 树的基本操作- 遍历 - 层次遍历(BFS) + + +## 代码 + +* 语言支持:JS,C++ + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=103 lang=javascript + * + * [103] Binary Tree Zigzag Level Order Traversal + * + * https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/ + * + * algorithms + * Medium (40.57%) + * Total Accepted: 201.2K + * Total Submissions: 493.7K + * Testcase Example: '[3,9,20,null,null,15,7]' + * + * Given a binary tree, return the zigzag level order traversal of its nodes' + * values. (ie, from left to right, then right to left for the next level and + * alternate between). + * + * + * For example: + * Given binary tree [3,9,20,null,null,15,7], + * + * ⁠ 3 + * ⁠ / \ + * ⁠ 9 20 + * ⁠ / \ + * ⁠ 15 7 + * + * + * + * return its zigzag level order traversal as: + * + * [ + * ⁠ [3], + * ⁠ [20,9], + * ⁠ [15,7] + * ] + * + * + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +var zigzagLevelOrder = function(root) { + if (!root) return []; + const items = []; + let isOdd = true; + let levelNodes = []; + + const queue = [root, null]; + + + while(queue.length > 0) { + const t = queue.shift(); + + if (t) { + levelNodes.push(t.val) + if (t.left) { + queue.push(t.left) + } + if (t.right) { + queue.push(t.right) + } + } else { + if (!isOdd) { + levelNodes = levelNodes.reverse(); + } + items.push(levelNodes) + levelNodes = []; + isOdd = !isOdd; + if (queue.length > 0) { + queue.push(null); + } + } + } + + return items + +}; +``` +C++ Code: +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector> zigzagLevelOrder(TreeNode* root) { + auto ret = vector>(); + if (root == nullptr) return ret; + auto queue = vector{root}; + auto isOdd = true; + while (!queue.empty()) { + auto sz = queue.size(); + auto level = vector(); + for (auto i = 0; i < sz; ++i) { + auto n = queue.front(); + queue.erase(queue.begin()); + if (isOdd) level.push_back(n->val); + else level.insert(level.begin(), n->val); + if (n->left != nullptr) queue.push_back(n->left); + if (n->right != nullptr) queue.push_back(n->right); + } + isOdd = !isOdd; + ret.push_back(level); + } + return ret; + } +}; +``` +## 拓展 + +由于二叉树是递归结构,因此,可以采用递归的方式来处理。在递归时需要保留当前的层次信息(从0开始),作为参数传递给下一次递归调用。 + +### 描述 + +1. 当前层次为偶数时,将当前节点放到当前层的结果数组尾部 +2. 当前层次为奇数时,将当前节点放到当前层的结果数组头部 +3. 递归对左子树进行之字形遍历,层数参数为当前层数+1 +4. 递归对右子树进行之字形遍历,层数参数为当前层数+1 + +### C++实现 + +```C++ +class Solution { +public: + vector> zigzagLevelOrder(TreeNode* root) { + auto ret = vector>(); + zigzagLevelOrder(root, 0, ret); + return ret; + } +private: + void zigzagLevelOrder(const TreeNode* root, int level, vector>& ret) { + if (root == nullptr || level < 0) return; + if (ret.size() <= level) { + ret.push_back(vector()); + } + if (level % 2 == 0) ret[level].push_back(root->val); + else ret[level].insert(ret[level].begin(), root->val); + zigzagLevelOrder(root->left, level + 1, ret); + zigzagLevelOrder(root->right, level + 1, ret); + } +}; +``` + +## 相关题目 +- [102.binary-tree-level-order-traversal](./102.binary-tree-level-order-traversal.md) +- [104.maximum-depth-of-binary-tree](./104.maximum-depth-of-binary-tree.md) + diff --git a/spider/row-markdown/1031.maximum-sum-of-two-non-overlapping-subarrays.md b/spider/row-markdown/1031.maximum-sum-of-two-non-overlapping-subarrays.md new file mode 100644 index 0000000..f376480 --- /dev/null +++ b/spider/row-markdown/1031.maximum-sum-of-two-non-overlapping-subarrays.md @@ -0,0 +1,126 @@ +## 题目地址 +https://leetcode.com/problems/maximum-sum-of-two-non-overlapping-subarrays/ + +## 题目描述 + +``` +Given an array A of non-negative integers, return the maximum sum of elements in two non-overlapping (contiguous) subarrays, which have lengths L and M. (For clarification, the L-length subarray could occur before or after the M-length subarray.) + +Formally, return the largest V for which V = (A[i] + A[i+1] + ... + A[i+L-1]) + (A[j] + A[j+1] + ... + A[j+M-1]) and either: + +0 <= i < i + L - 1 < j < j + M - 1 < A.length, or +0 <= j < j + M - 1 < i < i + L - 1 < A.length. + + +Example 1: + +Input: A = [0,6,5,2,2,5,1,9,4], L = 1, M = 2 +Output: 20 +Explanation: One choice of subarrays is [9] with length 1, and [6,5] with length 2. +Example 2: + +Input: A = [3,8,1,3,2,1,8,9,0], L = 3, M = 2 +Output: 29 +Explanation: One choice of subarrays is [3,8,1] with length 3, and [8,9] with length 2. +Example 3: + +Input: A = [2,1,5,6,0,9,5,0,3,8], L = 4, M = 3 +Output: 31 +Explanation: One choice of subarrays is [5,6,0,9] with length 4, and [3,8] with length 3. + + +Note: + +L >= 1 +M >= 1 +L + M <= A.length <= 1000 +0 <= A[i] <= 1000 +``` + +## 思路(动态规划) + +题目中要求在前N(数组长度)个数中找出长度分别为L和M的非重叠子数组之和的最大值, 因此, 我们可以定义数组A中前i个数可构成的非重叠子数组L和M的最大值为SUMM[i], 并找到SUMM[i]和SUMM[i-1]的关系, 那么最终解就是SUMM[N]. 以下为图解: + +![1031.Maximum Sum of Two Non-Overlapping Subarrays](../assets/problems/1031.maximum-sum-of-two-non-overlapping-subarrays.png) + +## 关键点解析 + +1. 注意图中描述的都是A[i-1], 而不是A[i], 因为base case为空数组, 而不是A[0]; +2. 求解图中ASUM数组的时候, 注意定义的是ASUM[i] = sum(A[0:i]), 因此当i等于0时, A[0:0]为空数组, 即: ASUM[0]为0, 而ASUM[1]才等于A[0]; +3. 求解图中MAXL数组时, 注意i < L时, 没有意义, 因为长度不够, 所以从i = L时才开始求解; +4. 求解图中MAXM数组时, 也一样, 要从i = M时才开始求解; +5. 求解图中SUMM数组时, 因为我们需要一个L子数组和一个M子数组, 因此长度要大于等于L+M才有意义, 所以要从i = L + M时开始求解. + +## 代码 + +* 语言支持: Python + +Python Code: +```python +class Solution: + def maxSumTwoNoOverlap(self, a: List[int], l: int, m: int) -> int: + """ + + define asum[i] as the sum of subarray, a[0:i] + define maxl[i] as the maximum sum of l-length subarray in a[0:i] + define maxm[i] as the maximum sum of m-length subarray in a[0:i] + define msum[i] as the maximum sum of non-overlap l-length subarray and m-length subarray + + case 1: a[i] is both not in l-length subarray and m-length subarray, then msum[i] = msum[i - 1] + case 2: a[i] is in l-length subarray, then msum[i] = asum[i] - asum[i-l] + maxm[i-l] + case 3: a[i] is in m-length subarray, then msum[i] = asum[i] - asum[i-m] + maxl[i-m] + + so, msum[i] = max(msum[i - 1], asum[i] - asum[i-l] + maxl[i-l], asum[i] - asum[i-m] + maxm[i-m]) + """ + + alen, tlen = len(a), l + m + asum = [0] * (alen + 1) + maxl = [0] * (alen + 1) + maxm = [0] * (alen + 1) + msum = [0] * (alen + 1) + + for i in range(tlen): + if i == 1: + asum[i] = a[i - 1] + elif i > 1: + asum[i] = asum[i - 1] + a[i - 1] + if i >= l: + maxl[i] = max(maxl[i - 1], asum[i] - asum[i - l]) + if i >= m: + maxm[i] = max(maxm[i - 1], asum[i] - asum[i - m]) + + for i in range(tlen, alen + 1): + asum[i] = asum[i - 1] + a[i - 1] + suml = asum[i] - asum[i - l] + summ = asum[i] - asum[i - m] + maxl[i] = max(maxl[i - 1], suml) + maxm[i] = max(maxm[i - 1], summ) + msum[i] = max(msum[i - 1], suml + maxm[i - l], summ + maxl[i - m]) + + return msum[-1] +``` + +## 扩展 + +1. 代码中, 求解了4个动态规划数组来求解最终值, 有没有可能只用两个数组来求解该题, 可以的话, 需要保留的又是哪两个数组? +2. 代码中, 求解的4动态规划数组的顺序能否改变, 哪些能改, 哪些不能改? + +如果采用前缀和数组的话,可以只使用O(n)的空间来存储前缀和,O(1)的动态规划状态空间来完成。C++代码如下: +```C++ +class Solution { +public: + int maxSumTwoNoOverlap(vector& A, int L, int M) { + auto tmp = vector{A[0]}; + for (auto i = 1; i < A.size(); ++i) { + tmp.push_back(A[i] + tmp[i - 1]); + } + auto res = tmp[L + M - 1], lMax = tmp[L - 1], mMax = tmp[M - 1]; + for (auto i = L + M; i < tmp.size(); ++i) { + lMax = max(lMax, tmp[i - M] - tmp[i - M - L]); + mMax = max(mMax, tmp[i - L] - tmp[i - L - M]); + res = max(res, max(lMax + tmp[i] - tmp[i - M], mMax + tmp[i] - tmp[i - L])); + } + return res; + } +}; +``` diff --git a/spider/row-markdown/104.maximum-depth-of-binary-tree.md b/spider/row-markdown/104.maximum-depth-of-binary-tree.md new file mode 100644 index 0000000..a526541 --- /dev/null +++ b/spider/row-markdown/104.maximum-depth-of-binary-tree.md @@ -0,0 +1,152 @@ +## 题目地址 + +https://leetcode.com/problems/maximum-depth-of-binary-tree/description/ + +## 题目描述 + +``` +Given a binary tree, find its maximum depth. + +The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. + +Note: A leaf is a node with no children. + +Example: + +Given binary tree [3,9,20,null,null,15,7], + + 3 + / \ + 9 20 + / \ + 15 7 +return its depth = 3. + +``` + +## 思路 + +由于树是一种递归的数据结构,因此用递归去解决的时候往往非常容易,这道题恰巧也是如此, +用递归实现的代码如下: + +```js +var maxDepth = function(root) { + if (!root) return 0; + if (!root.left && !root.right) return 1; + return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); +}; +``` + +如果使用迭代呢? 我们首先应该想到的是树的各种遍历,由于我们求的是深度,因此 +使用层次遍历(BFS)是非常合适的。 我们只需要记录有多少层即可。相关思路请查看[binary-tree-traversal](../thinkings/binary-tree-traversal.md) + +## 关键点解析 + +- 队列 + +- 队列中用 Null(一个特殊元素)来划分每层,或者在对每层进行迭代之前保存当前队列元素的个数(即当前层所含元素个数) + +- 树的基本操作- 遍历 - 层次遍历(BFS) + +## 代码 +* 语言支持:JS,C++,Python + +JavaScript Code: +```js +/* + * @lc app=leetcode id=104 lang=javascript + * + * [104] Maximum Depth of Binary Tree + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var maxDepth = function(root) { + if (!root) return 0; + if (!root.left && !root.right) return 1; + + // 层次遍历 BFS + let cur = root; + const queue = [root, null]; + let depth = 1; + + while ((cur = queue.shift()) !== undefined) { + if (cur === null) { + // 注意⚠️: 不处理会无限循环,进而堆栈溢出 + if (queue.length === 0) return depth; + depth++; + queue.push(null); + continue; + } + const l = cur.left; + const r = cur.right; + + if (l) queue.push(l); + if (r) queue.push(r); + } + + return depth; +}; +``` +C++ Code: +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + int maxDepth(TreeNode* root) { + if (root == nullptr) return 0; + auto q = vector(); + auto d = 0; + q.push_back(root); + while (!q.empty()) + { + ++d; + auto sz = q.size(); + for (auto i = 0; i < sz; ++i) + { + auto t = q.front(); + q.erase(q.begin()); + if (t->left != nullptr) q.push_back(t->left); + if (t->right != nullptr) q.push_back(t->right); + } + } + return d; + } +}; +``` + +Python Code: +```python +class Solution: + def maxDepth(self, root: TreeNode) -> int: + if not root: return 0 + q, depth = [root, None], 1 + while q: + node = q.pop(0) + if node: + if node.left: q.append(node.left) + if node.right: q.append(node.right) + elif q: + q.append(None) + depth += 1 + return depth +``` +## 相关题目 +- [102.binary-tree-level-order-traversal](./102.binary-tree-level-order-traversal.md) +- [103.binary-tree-zigzag-level-order-traversal](./103.binary-tree-zigzag-level-order-traversal.md) diff --git a/spider/row-markdown/105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md b/spider/row-markdown/105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md new file mode 100644 index 0000000..24c8091 --- /dev/null +++ b/spider/row-markdown/105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md @@ -0,0 +1,113 @@ +## 问题地址/Problem URL + +https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ + +## 问题介绍/Problem Description + +Given preorder and inorder traversal of a tree, construct the binary tree. + +Note: +You may assume that duplicates do not exist in the tree. + +For example, given + +```java +preorder = [3,9,20,15,7] +inorder = [9,3,15,20,7] +``` + +Return the following binary tree: + +```bash + 3 + / \ + 9 20 + / \ + 15 7 +``` + +## 思路/Thinking Path + +目标是构造二叉树。 + +构造二叉树需要根的值、左子树和右子树。 + +此问题可被抽象为:从前序遍历和中序遍历中找到根节点、左子树和右子树。 + +先找根: +由前序遍历的性质,第`0`个节点为当前树的根节点。 +再找左右子树: +在中序遍历中找到这个根节点,设其下标为`i`。由中序遍历的性质,`0 ~ i-1` 是左子树的中序遍历,`i+1 ~ inorder.length-1`是右子树的中序遍历。 + +然后递归求解,终止条件是左右子树为`null`。 + +We are going to construct a binary tree from its preorder and inorder traversal. + +To build a binary tree, it requires us to creact a new `TreeNode` as the root with filling in the root value. And then, find its left child and right child recursively until the left or right child is `null`. + +Now this problem is abstracted as how to find the root node, left child and right child from the preorder traversal and inorder traversal. + +In preorder traversal, the first node (`preorder[0]`) is the root of current binary tree. In inorder traversal, find the location of this root which is `i`. The left sub-tree is `0 to i-1` and the right sub-tree is `i+1 to inorder.length-1` in inorder traversal. + +Then applying the previous operation to the left and right sub-trees. + +## 关键解析/Key Points + +如何在前序遍历的数组里找到左右子树的: +- 根据前序遍历的定义可知,每个当前数组的第一个元素就是当前子树的根节点的值 +- 在中序遍历数组中找到这个值,设其下标为`inRoot` + - 当前中序遍历数组的起点`inStart`到`inRoot`之间就是左子树,其长度`leftChldLen`为`inRoot-inStart` + - 当前中序遍历数组的终点`inEnd`和`inRoot`之间就是右子树 +- 前序遍历和中序遍历中左子树的长度是相等的,所以在前序遍历数组中,根节点下标`preStart`往后数`leftChldLen`即为左子树的最后一个节点,其下标为`preStart+leftChldLen`,右子树的第一个节点下标为`preStart+leftChldLen+1`。 + +**PLEASE READ THE CODE BEFORE READING THIS PART** + +If you can't figure out how to get the index of the left and right child, please read this. + +- index of current node in preorder array is preStart(or whatever your call it), it's the root of a subtree. +- according to the properties of preoder traversal, all right sub-tree nodes are behine all left sub-tree nodes. The length of left sub-tree can help us to divide left and right sub-trees. +- the length of left sub-tree can be find in the inorder traversal. The location of current node is `inRoot`(or whatever your call it). The start index of current inorder array is `inStart`(or whatever your call it). So, the lenght of the left sub-tree is `leftChldLen = inRoot - inStart`. + +![explain](../assets/problems/105.index_explain.jpg) + +## 代码/Code + +- Java + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public TreeNode buildTree(int[] preorder, int[] inorder) { + if (preorder.length != inorder.length) return null; + + HashMap map = new HashMap<> (); + + for (int i=0; i map) { + if (preStart>preEnd || inStart>inEnd) return null; + + TreeNode root = new TreeNode(preorder[prestart]); + int inRoot = map.get(preorder[preStart]); + int leftChldLen = inRoot - inStart; + + root.left = helper(preorder, preStart+1, preStart+leftChldLen, inorder, inStart, inRoot-1, map); + root.left = helper(preorder, preStart+leftChldLen+1, preEnd, inorder, inRoot+1, inEnd, map); + + return root; + } +} +``` \ No newline at end of file diff --git a/spider/row-markdown/11.container-with-most-water.md b/spider/row-markdown/11.container-with-most-water.md new file mode 100644 index 0000000..b6b5de3 --- /dev/null +++ b/spider/row-markdown/11.container-with-most-water.md @@ -0,0 +1,125 @@ +## 题目地址 +https://leetcode.com/problems/container-with-most-water/description/ + +## 题目描述 +``` +Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. + +Note: You may not slant the container and n is at least 2. +``` + +![11.container-with-most-water-question](../assets/problems/11.container-with-most-water-question.jpg) +``` + +The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49. + + + +Example: + +Input: [1,8,6,2,5,4,8,3,7] +Output: 49 +``` + +## 思路 +符合直觉的解法是,我们可以对两两进行求解,计算可以承载的水量。 然后不断更新最大值,最后返回最大值即可。 +这种解法,需要两层循环,时间复杂度是O(n^2) + +eg: + +```js + // 这个解法比较暴力,效率比较低 + // 时间复杂度是O(n^2) + let max = 0; + for(let i = 0; i < height.length; i++) { + for(let j = i + 1; j < height.length; j++) { + const currentArea = Math.abs(i - j) * Math.min(height[i], height[j]); + if (currentArea > max) { + max = currentArea; + } + } + } + return max; + +``` + +> 这种符合直觉的解法有点像冒泡排序, 大家可以稍微类比一下 + +那么有没有更加优的解法呢?我们来换个角度来思考这个问题,上述的解法是通过两两组合,这无疑是完备的, +那我门是否可以先计算长度为n的面积,然后计算长度为n-1的面积,... 计算长度为1的面积。 这样去不断更新最大值呢? +很显然这种解法也是完备的,但是似乎时间复杂度还是O(n ^ 2), 不要着急。 + +考虑一下,如果我们计算n-1长度的面积的时候,是直接直接排除一半的结果的。 + +如图: + +![11.container-with-most-water](../assets/problems/11.container-with-most-water.png) + + +比如我们计算n面积的时候,假如左侧的线段高度比右侧的高度低,那么我们通过左移右指针来将长度缩短为n-1的做法是没有意义的, +因为`新的形成的面积变成了(n-1) * heightOfLeft 这个面积一定比刚才的长度为n的面积nn * heightOfLeft 小` + +也就是说最大面积`一定是当前的面积或者通过移动短的线段得到`。 +## 关键点解析 + +- 双指针优化时间复杂度 + + +## 代码 +* 语言支持:JS,C++ + +JavaScript Code: + +```js +/** + * @param {number[]} height + * @return {number} + */ +var maxArea = function(height) { + if (!height || height.length <= 1) return 0; + + let leftPos = 0; + let rightPos = height.length - 1; + let max = 0; + while(leftPos < rightPos) { + + const currentArea = Math.abs(leftPos - rightPos) * Math.min(height[leftPos] , height[rightPos]); + if (currentArea > max) { + max = currentArea; + } + // 更新小的 + if (height[leftPos] < height[rightPos]) { + leftPos++; + } else { // 如果相等就随便了 + rightPos--; + } + } + + return max; +}; +``` +C++ Code: +```C++ +class Solution { +public: + int maxArea(vector& height) { + auto ret = 0ul, leftPos = 0ul, rightPos = height.size() - 1; + while( leftPos < rightPos) + { + ret = std::max(ret, std::min(height[leftPos], height[rightPos]) * (rightPos - leftPos)); + if (height[leftPos] < height[rightPos]) ++leftPos; + else --rightPos; + } + return ret; + } +}; +``` + +***复杂度分析*** +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(1)$ + + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/1104.path-in-zigzag-labelled-binary-tree.md b/spider/row-markdown/1104.path-in-zigzag-labelled-binary-tree.md new file mode 100644 index 0000000..2355775 --- /dev/null +++ b/spider/row-markdown/1104.path-in-zigzag-labelled-binary-tree.md @@ -0,0 +1,80 @@ +## 题目地址 + +https://leetcode-cn.com/problems/path-in-zigzag-labelled-binary-tree/description/ + +## 题目描述 + +在一棵无限的二叉树上,每个节点都有两个子节点,树中的节点 逐行 依次按 “之” 字形进行标记。 + +如下图所示,在奇数行(即,第一行、第三行、第五行……)中,按从左到右的顺序进行标记; + +而偶数行(即,第二行、第四行、第六行……)中,按从右到左的顺序进行标记。 + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gaihhb1ysbj310p0gu3zx.jpg) + +给你树上某一个节点的标号 label,请你返回从根节点到该标号为 label 节点的路径,该路径是由途经的节点标号所组成的。 + +示例 1: + +输入:label = 14 +输出:[1,3,4,14] +示例 2: + +输入:label = 26 +输出:[1,2,6,10,26] + +提示: + +1 <= label <= 10^6 + +## 思路 + +假如这道题不是之字形,那么就会非常简单。 我们可以根据子节点的 label 轻松地求出父节点的 label,公示是 label // 2(其中 label 为子节点的 label)。 + +如果是这样的话,这道题应该是 easy 难度,代码也不难写出。我们继续考虑之字形。我们不妨先观察一下,找下规律。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gaihn0ktanj30lu093gme.jpg) + +以上图最后一行为例,对于 15 节点,之字变换之前对应的应该是 8 节点。14 节点对应的是 9 节点。。。 + +全部列举出来是这样的: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gaihota82cj30mk0b6wfp.jpg) + +我们发现之字变换前后的 label 相加是一个定值。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gaihpnlpicj309b08dmxl.jpg) + +因此我们只需要求解出每一层的这个定值,然后减去当前值就好了。(注意我们不需要区分偶数行和奇数行) +问题的关键转化为求解这个定值,这个定值其实很好求,因为每一层的最大值和最小值我们很容易求,而最大值和最小值的和正是我们要求的这个数字。 + +最大值和最小值这么求呢?由满二叉树的性质,我们知道每一层的最小值就是`2 ** (level - 1)`,而最大值是`2 ** level - 1`。 因此我们只要知道 level 即可,level 非常容易求出,具体可以看下面代码。 + +## 关键点 + +- 满二叉树的性质: + +1. 最小值是`2 ** (level - 1)`,最大值是`2 ** level - 1`,其中 level 是树的深度。 +2. 假如父节点的索引为 i,那么左子节点就是 2\*i, 右边子节点就是 2\*i + 1。 +3. 假如子节点的索引是 i,那么父节点的索引就是 i // 2。 + +- 先思考一般情况(不是之字形), 然后通过观察找出规律 + +## 代码 + +```python +class Solution: + def pathInZigZagTree(self, label: int) -> List[int]: + level = 0 + res = [] + # for each level, ranged from 2 ** (level - 1) to 2 ** level - 1 + while 2 ** level - 1 < label: + level += 1 + + while level > 0: + res.insert(0, label) + label = 2 ** (level - 1) + 2 ** level - 1 - label + label //= 2 + level -= 1 + return res +``` diff --git a/spider/row-markdown/113.path-sum-ii.md b/spider/row-markdown/113.path-sum-ii.md new file mode 100644 index 0000000..e0e3d09 --- /dev/null +++ b/spider/row-markdown/113.path-sum-ii.md @@ -0,0 +1,166 @@ +## 题目地址 +https://leetcode.com/problems/path-sum-ii/description/ + +## 题目描述 +``` +Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. + +Note: A leaf is a node with no children. + +Example: + +Given the below binary tree and sum = 22, + + 5 + / \ + 4 8 + / / \ + 11 13 4 + / \ / \ +7 2 5 1 +Return: + +[ + [5,4,11,2], + [5,8,4,5] +] +``` + +## 思路 + +这道题目是求集合,并不是`求值`,而是枚举所有可能,因此动态规划不是特别切合,因此我们需要考虑别的方法。 + +这种题目其实有一个通用的解法,就是回溯法。 +网上也有大神给出了这种回溯法解题的 +[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。 +除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。 + +我们先来看下通用解法的解题思路,我画了一张图: + +![backtrack](../assets/problems/backtrack.png) + +通用写法的具体代码见下方代码区。 + +## 关键点解析 + +- 回溯法 +- backtrack 解题公式 + + +## 代码 + +* 语言支持:JS,C++,Python3 + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=113 lang=javascript + * + * [113] Path Sum II + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +function backtrack(root, sum, res, tempList) { + if (root === null) return; + if (root.left === null && root.right === null && sum === root.val) + return res.push([...tempList, root.val]); + + tempList.push(root.val); + backtrack(root.left, sum - root.val, res, tempList); + + backtrack(root.right, sum - root.val, res, tempList); + tempList.pop(); +} +/** + * @param {TreeNode} root + * @param {number} sum + * @return {number[][]} + */ +var pathSum = function(root, sum) { + if (root === null) return []; + const res = []; + backtrack(root, sum, res, []); + return res; +}; +``` +C++ Code: +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector> pathSum(TreeNode* root, int sum) { + auto ret = vector>(); + auto temp = vector(); + backtrack(root, sum, ret, temp); + return ret; + } +private: + void backtrack(const TreeNode* root, int sum, vector>& ret, vector& tempList) { + if (root == nullptr) return; + tempList.push_back(root->val); + if (root->val == sum && root->left == nullptr && root->right == nullptr) { + ret.push_back(tempList); + } else { + backtrack(root->left, sum - root->val, ret, tempList); + backtrack(root->right, sum - root->val, ret, tempList); + } + tempList.pop_back(); + } +}; +``` +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: + if not root: + return [] + + result = [] + + def trace_node(pre_list, left_sum, node): + new_list = pre_list.copy() + new_list.append(node.val) + if not node.left and not node.right: + # 这个判断可以和上面的合并,但分开写会快几毫秒,可以省去一些不必要的判断 + if left_sum == node.val: + result.append(new_list) + else: + if node.left: + trace_node(new_list, left_sum-node.val, node.left) + if node.right: + trace_node(new_list, left_sum-node.val, node.right) + + trace_node([], sum, root) + return result +``` +## 相关题目 + +- [39.combination-sum](./39.combination-sum.md) +- [40.combination-sum-ii](./40.combination-sum-ii.md) +- [46.permutations](./46.permutations.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [78.subsets](./78.subsets.md) +- [90.subsets-ii](./90.subsets-ii.md) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md) + + diff --git a/spider/row-markdown/1131.maximum-of-absolute-value-expression.md b/spider/row-markdown/1131.maximum-of-absolute-value-expression.md new file mode 100644 index 0000000..763af24 --- /dev/null +++ b/spider/row-markdown/1131.maximum-of-absolute-value-expression.md @@ -0,0 +1,187 @@ +## 题目地址(1131. 绝对值表达式的最大值) + +https://leetcode-cn.com/problems/maximum-of-absolute-value-expression/description/ + +## 题目描述 + +给你两个长度相等的整数数组,返回下面表达式的最大值: + +|arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j| + +其中下标 i,j 满足 0 <= i, j < arr1.length。 + +示例 1: + +输入:arr1 = [1,2,3,4], arr2 = [-1,4,5,6] +输出:13 +示例 2: + +输入:arr1 = [1,-2,-5,0,10], arr2 = [0,-2,-1,-7,-4] +输出:20 + +提示: + +2 <= arr1.length == arr2.length <= 40000 +-10^6 <= arr1[i], arr2[i] <= 10^6 + +## 解法一(数学分析) + +### 思路 + +如图我们要求的是这样一个表达式的最大值。arr1 和 arr2 为两个不同的数组,且二者长度相同。i 和 j 是两个合法的索引。 + +> 红色竖线表示的是绝对值的符号 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gamo3dx1bej30q003y74f.jpg) + +我们对其进行分类讨论,有如下八种情况: + +> |arr1[i] -arr1[j]| 两种情况 +> |arr2[i] -arr2[j]| 两种情况 +> |i - j| 两种情况 +> 因此一共是 2 \* 2 \* 2 = 8 种 + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gamosnsknej30tg0viq6w.jpg) + +由于 i 和 j 之前没有大小关系,也就说二者可以相互替代。因此: + +- 1 等价于 8 +- 2 等价于 7 +- 3 等价于 6 +- 4 等价于 5 + +也就是说我们只需要计算 1,2,3,4 的最大值就可以了。(当然你可以选择其他组合,只要完备就行) + +为了方便,我们将 i 和 j 都提取到一起: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gamp5sizefj30qs0g6gmx.jpg) + +容易看出等式的最大值就是前面的最大值,和后面最小值的差值。如图: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gamp9c3g9lj30r20kcabx.jpg) + +再仔细观察,会发现前面部分和后面部分是一样的,原因还是上面所说的 i 和 j 可以互换。因此我们要做的就是: + +- 遍历一遍数组,然后计算四个表达式, arr1[i] + arr2[i] + i,arr1[i] - arr2[i] + i,arr2[i] - arr1[i] + i 和 -1 \* arr2[i] - arr1[i] + i 的 最大值和最小值。 +- 然后分别取出四个表达式最大值和最小值的差值(就是这个表达式的最大值) +- 四个表达式最大值再取出最大值 + +### 关键点 + +- 数学分析 + +### 代码 + +```python +class Solution: + def maxAbsValExpr(self, arr1: List[int], arr2: List[int]) -> int: + A = [] + B = [] + C = [] + D = [] + for i in range(len(arr1)): + a, b, c, d = arr1[i] + arr2[i] + i, arr1[i] - arr2[i] + \ + i, arr2[i] - arr1[i] + i, -1 * arr2[i] - arr1[i] + i + A.append(a) + B.append(b) + C.append(c) + D.append(d) + return max(max(A) - min(A), max(B) - min(B), max(C) - min(C), max(D) - min(D)) +``` + +## 解法二(曼哈顿距离) + +### 思路 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gampnn032tj308l0a8mxl.jpg) + +(图来自: https://zh.wikipedia.org/wiki/%E6%9B%BC%E5%93%88%E9%A0%93%E8%B7%9D%E9%9B%A2) + +一维曼哈顿距离可以理解为一条线上两点之间的距离: |x1 - x2|,其值为 max(x1 - x2, x2 - x1) + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gampr362oaj30l004mdfv.jpg) + +在平面上,坐标(x1, y1)的点 P1 与坐标(x2, y2)的点 P2 的曼哈顿距离为:|x1-x2| + |y1 - y2|,其值为 max(x1 - x2 + y1 - y2, x2 - x1 + y1 - y2, x1 - x2 + y2 - y1, x2 -x1 + y2 - y1) + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gampwhua9fj30rq0lmdgl.jpg) + +然后这道题目是更复杂的三维曼哈顿距离,其中(i, arr[i], arr[j])可以看作三位空间中的一个点,问题转化为曼哈顿距离最远的两个点的距离。 +延续上面的思路,|x1-x2| + |y1 - y2| + |z1 - z2|,其值为 : + +max( + +x1 - x2 + y1 - y2 + z1 - z2, + +x1 - x2 + y1 - y2 + z2 - z1, + +x2 - x1 + y1 - y2 + z1 - z2, + +x2 - x1 + y1 - y2 + z2 - z1, + +x1 - x2 + y2 - y1 + z1 - z2, + +x1 - x2 + y2 - y1 + z2- z1, + +x2 -x1 + y2 - y1 + z1 - z2, + +x2 -x1 + y2 - y1 + z2 - z1 + +) + +我们可以将 1 和 2 放在一起方便计算: + +max( + +x1 + y1 + z1 - (x2 + y2 + z2), + +x1 + y1 - z1 - (x2 + y2 - z2) + +... + +) + +我们甚至可以扩展到 n 维,具体代码见下方。 + +### 关键点 + +- 曼哈顿距离 +- 曼哈顿距离代码模板 + +> 解题模板可以帮助你快速并且更少错误的解题,更多解题模板请期待我的[新书](https://lucifer.ren/blog/2019/12/11/draft/)(未完成) + +### 代码 + +```python +class Solution: + def maxAbsValExpr(self, arr1: List[int], arr2: List[int]) -> int: + # 曼哈顿距离模板代码 + sign = [1, -1] + n = len(arr1) + dists = [] + # 三维模板 + for a in sign: + for b in sign: + for c in sign: + maxDist = float('-inf') + minDist = float('inf') + # 分别计算所有点的曼哈顿距离 + for i in range(n): + dist = arr1[i] * a + arr2[i] * b + i * c + maxDist = max(maxDist, dist) + minDist = min(minDist, dist) + # 将所有的点的曼哈顿距离放到dists中 + dists.append(maxDist - minDist) + return max(dists) +``` + +## 总结 + +可以看出其实两种解法都是一样的,只是思考角度不一样。 + +## 相关题目 + +- [1030. 距离顺序排列矩阵单元格](https://leetcode-cn.com/problems/matrix-cells-in-distance-order/) + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gamq577lgsj30xd0jzwjb.jpg) + +- [1162. 地图分析](https://leetcode-cn.com/problems/as-far-from-land-as-possible/) diff --git a/spider/row-markdown/1168.optimize-water-distribution-in-a-village-cn.md b/spider/row-markdown/1168.optimize-water-distribution-in-a-village-cn.md new file mode 100644 index 0000000..f0398a6 --- /dev/null +++ b/spider/row-markdown/1168.optimize-water-distribution-in-a-village-cn.md @@ -0,0 +1,187 @@ +## 题目地址 +https://leetcode.com/problems/optimize-water-distribution-in-a-village/ + +## 题目描述 +``` +There are n houses in a village. We want to supply water for all the houses by building wells and laying pipes. + +For each house i, we can either build a well inside it directly with cost wells[i], or pipe in water from another well to it. The costs to lay pipes between houses are given by the array pipes, where each pipes[i] = [house1, house2, cost] represents the cost to connect house1 and house2 together using a pipe. Connections are bidirectional. + +Find the minimum total cost to supply water to all houses. + +Example 1: + +Input: n = 3, wells = [1,2,2], pipes = [[1,2,1],[2,3,1]] +Output: 3 +Explanation: +The image shows the costs of connecting houses using pipes. +The best strategy is to build a well in the first house with cost 1 and connect the other houses to it with cost 2 so the total cost is 3. + +Constraints: + +1 <= n <= 10000 +wells.length == n +0 <= wells[i] <= 10^5 +1 <= pipes.length <= 10000 +1 <= pipes[i][0], pipes[i][1] <= n +0 <= pipes[i][2] <= 10^5 +pipes[i][0] != pipes[i][1] +``` +example 1 pic: + +![example 1](../assets/problems/1168.optimize-water-distribution-in-a-village-example1.png) + +## 思路 +题意,在每个城市打井需要一定的花费,也可以用其他城市的井水,城市之间建立连接管道需要一定的花费,怎么样安排可以花费最少的前灌溉所有城市。 + +这是一道连通所有点的最短路径/最小生成树问题,把城市看成图中的点,管道连接城市看成是连接两个点之间的边。这里打井的花费是直接在点上,而且并不是所有 +点之间都有边连接,为了方便,我们可以假想一个点`(root)0`,这里自身点的花费可以与 `0` 连接,花费可以是 `0-i` 之间的花费。这样我们就可以构建一个连通图包含所有的点和边。 +那在一个连通图中求最短路径/最小生成树的问题. + +参考延伸阅读中,维基百科针对这类题给出的几种解法。 + +解题步骤: +1. 创建 `POJO EdgeCost(node1, node2, cost) - 节点1 和 节点2 连接边的花费`。 +2. 假想一个`root` 点 `0`,构建图 +3. 连通所有节点和 `0`,`[0,i] - i 是节点 [1,n]`,`0-1` 是节点 `0` 和 `1` 的边,边的值是节点 `i` 上打井的花费 `wells[i]`; +4. 把打井花费和城市连接点转换成图的节点和边。 +5. 对图的边的值排序(从小到大) +6. 遍历图的边,判断两个节点有没有连通 (`Union-Find`), + - 已连通就跳过,继续访问下一条边 + - 没有连通,记录花费,连通节点 +7. 若所有节点已连通,求得的最小路径即为最小花费,返回 +8. 对于每次`union`, 节点数 `n-1`, 如果 `n==0` 说明所有节点都已连通,可以提前退出,不需要继续访问剩余的边。 + +> 这里用加权Union-Find 判断两个节点是否连通,和连通未连通的节点。 + +举例:`n = 5, wells=[1,2,2,3,2], pipes=[[1,2,1],[2,3,1],[4,5,7]]` + +如图: + +![minimum cost](../assets/problems/1168.optimize-water-distribution-in-a-village-1.png) + +从图中可以看到,最后所有的节点都是连通的。 + +#### 复杂度分析 +- *时间复杂度:* `O(ElogE) - E 是图的边的个数` +- *空间复杂度:* `O(E)` + +> 一个图最多有 `n(n-1)/2 - n 是图中节点个数` 条边 (完全连通图) + +## 关键点分析 +1. 构建图,得出所有边 +2. 对所有边排序 +3. 遍历所有的边(从小到大) +4. 对于每条边,检查是否已经连通,若没有连通,加上边上的值,连通两个节点。若已连通,跳过。 + +## 代码 (`Java/Python3`) +*Java code* +```java + class OptimizeWaterDistribution { + public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) { + List costs = new ArrayList<>(); + for (int i = 1; i <= n; i++) { + costs.add(new EdgeCost(0, i, wells[i - 1])); + } + for (int[] p : pipes) { + costs.add(new EdgeCost(p[0], p[1], p[2])); + } + Collections.sort(costs); + int minCosts = 0; + UnionFind uf = new UnionFind(n); + for (EdgeCost edge : costs) { + int rootX = uf.find(edge.node1); + int rootY = uf.find(edge.node2); + if (rootX == rootY) continue; + minCosts += edge.cost; + uf.union(edge.node1, edge.node2); + // for each union, we connnect one node + n--; + // if all nodes already connected, terminate early + if (n == 0) { + return minCosts; + } + } + return minCosts; + } + + class EdgeCost implements Comparable { + int node1; + int node2; + int cost; + public EdgeCost(int node1, int node2, int cost) { + this.node1 = node1; + this.node2 = node2; + this.cost = cost; + } + + @Override + public int compareTo(EdgeCost o) { + return this.cost - o.cost; + } + } + + class UnionFind { + int[] parent; + int[] rank; + public UnionFind(int n) { + parent = new int[n + 1]; + for (int i = 0; i <= n; i++) { + parent[i] = i; + } + rank = new int[n + 1]; + } + public int find(int x) { + return x == parent[x] ? x : find(parent[x]); + } + public void union(int x, int y) { + int px = find(x); + int py = find(y); + if (px == py) return; + if (rank[px] >= rank[py]) { + parent[py] = px; + rank[px] += rank[py]; + } else { + parent[px] = py; + rank[py] += rank[px]; + } + } + } + } +``` +*Pythong3 code* +```python +class Solution: + def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int: + union_find = {i: i for i in range(n + 1)} + + def find(x): + return x if x == union_find[x] else find(union_find[x]) + + def union(x, y): + px = find(x) + py = find(y) + union_find[px] = py + + graph_wells = [[cost, 0, i] for i, cost in enumerate(wells, 1)] + graph_pipes = [[cost, i, j] for i, j, cost in pipes] + min_costs = 0 + for cost, x, y in sorted(graph_wells + graph_pipes): + if find(x) == find(y): + continue + union(x, y) + min_costs += cost + n -= 1 + if n == 0: + return min_costs +``` + +## 延伸阅读 + +1. [最短路径问题](https://www.wikiwand.com/zh-hans/%E6%9C%80%E7%9F%AD%E8%B7%AF%E9%97%AE%E9%A2%98) +2. [Dijkstra算法](https://www.wikiwand.com/zh-hans/戴克斯特拉算法) +3. [Floyd-Warshall算法](https://www.wikiwand.com/zh-hans/Floyd-Warshall%E7%AE%97%E6%B3%95) +4. [Bellman-Ford算法](https://www.wikiwand.com/zh-hans/%E8%B4%9D%E5%B0%94%E6%9B%BC-%E7%A6%8F%E7%89%B9%E7%AE%97%E6%B3%95) +5. [Kruskal算法](https://www.wikiwand.com/zh-hans/%E5%85%8B%E9%B2%81%E6%96%AF%E5%85%8B%E5%B0%94%E6%BC%94%E7%AE%97%E6%B3%95) +6. [Prim's 算法](https://www.wikiwand.com/zh-hans/%E6%99%AE%E6%9E%97%E5%A7%86%E7%AE%97%E6%B3%95) +7. [最小生成树](https://www.wikiwand.com/zh/%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91) \ No newline at end of file diff --git a/spider/row-markdown/1168.optimize-water-distribution-in-a-village-en.md b/spider/row-markdown/1168.optimize-water-distribution-in-a-village-en.md new file mode 100644 index 0000000..3eac1ad --- /dev/null +++ b/spider/row-markdown/1168.optimize-water-distribution-in-a-village-en.md @@ -0,0 +1,194 @@ +## Problem + + + + +https://leetcode.com/problems/optimize-water-distribution-in-a-village/ +## Problem Description + +## 题目描述 +``` +There are n houses in a village. We want to supply water for all the houses by building wells and laying pipes. + +For each house i, we can either build a well inside it directly with cost wells[i], or pipe in water from another well to it. The costs to lay pipes between houses are given by the array pipes, where each pipes[i] = [house1, house2, cost] represents the cost to connect house1 and house2 together using a pipe. Connections are bidirectional. + +Find the minimum total cost to supply water to all houses. + +Example 1: + +Input: n = 3, wells = [1,2,2], pipes = [[1,2,1],[2,3,1]] +Output: 3 +Explanation: +The image shows the costs of connecting houses using pipes. +The best strategy is to build a well in the first house with cost 1 and connect the other houses to it with cost 2 so the total cost is 3. + +Constraints: + +1 <= n <= 10000 +wells.length == n +0 <= wells[i] <= 10^5 +1 <= pipes.length <= 10000 +1 <= pipes[i][0], pipes[i][1] <= n +0 <= pipes[i][2] <= 10^5 +pipes[i][0] != pipes[i][1] +``` +example 1 pic: + +![example 1](../assets/problems/1168.optimize-water-distribution-in-a-village-example1.png) + + +## Solution + +From example graph, we can see that this is Shortest path problem/Minimum spanning tree problem. In this problem, in a graph, view cities as nodes, pipe connects two cities as edges with cost. +here, wells costs, it is self connected edge, we can add extra node as root node `0`, and connect all `0` and `i` with costs `wells[i]`. So that we can have one graph/tree, +and how to get minimun spanning trees / shortest path problem in a graph. Please see below detailed steps for analysis. + +Analysis Steps: +1. Create `POJO EdgeCost(node1, node2, cost) - node1, node2, and cost of connect node1 and node2` +2. Assume on `root node 0`,build graph with `node 0 and all nodes(cities)` +3. Connect all nodes with`0`,`[0,i] - i is nodes range from [1,n]`,`0-1` meaning `node 0` and `node 1` connect edge ,value is node `i`'s cost `wells[i]`; +4. Turn cities into nodes, wells' costs and pipes' into costs into edges value which connected into two cities. +5. Sort all edges (from min to max) +6. Scan all edges, check whether 2 nodes connected or not:(`Union-Find`), + - if already connected, continue check next edge + - if not yet connected, +costs, connect 2 nodes +7. If all nodes already connected, get minimum costs, return result +8. (#7 Optimization) for each `union`, total nodes number `n-1`, if `n==0`, then meaning all nodes already connected, can terminate early. + +> Here use weighted-Union-find to check whether 2 nodes connceted or not, and union not connected nodes. + +For example:`n = 5, wells=[1,2,2,3,2], pipes=[[1,2,1],[2,3,1],[4,5,7]]` + +As below pic: + +![minimum cost](../assets/problems/1168.optimize-water-distribution-in-a-village-1.png) + +From pictures, we can see that all nodes already connected with minimum costs. + +#### Complexity Analysis +- *Time Complexity:* `O(ElogE) - E number of edge in graph` +- *Space Complexity:* `O(E)` + + + +> A graph at most have `n(n-1)/2 - n number of nodes in graph` edges ([Complete Graph](https://www.wikiwand.com/en/Complete_graph)) + +## Key Points +1. Build graph with all possible edges. +2. Sort edges by value (costs) +3. Iterate all edges (from min value to max value) +4. For each edges, check whether two nodes already connected (union-find), + - if already connected, then skip + - if not connected, then union two nodes, add costs to result + +## Code (`Java/Python3`) +*Java code* +```java + class OptimizeWaterDistribution { + public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) { + List costs = new ArrayList<>(); + for (int i = 1; i <= n; i++) { + costs.add(new EdgeCost(0, i, wells[i - 1])); + } + for (int[] p : pipes) { + costs.add(new EdgeCost(p[0], p[1], p[2])); + } + Collections.sort(costs); + int minCosts = 0; + UnionFind uf = new UnionFind(n); + for (EdgeCost edge : costs) { + int rootX = uf.find(edge.node1); + int rootY = uf.find(edge.node2); + if (rootX == rootY) continue; + minCosts += edge.cost; + uf.union(edge.node1, edge.node2); + // for each union, we connnect one node + n--; + // if all nodes already connected, terminate early + if (n == 0) { + return minCosts; + } + } + return minCosts; + } + + class EdgeCost implements Comparable { + int node1; + int node2; + int cost; + public EdgeCost(int node1, int node2, int cost) { + this.node1 = node1; + this.node2 = node2; + this.cost = cost; + } + + @Override + public int compareTo(EdgeCost o) { + return this.cost - o.cost; + } + } + + class UnionFind { + int[] parent; + int[] rank; + public UnionFind(int n) { + parent = new int[n + 1]; + for (int i = 0; i <= n; i++) { + parent[i] = i; + } + rank = new int[n + 1]; + } + public int find(int x) { + return x == parent[x] ? x : find(parent[x]); + } + public void union(int x, int y) { + int px = find(x); + int py = find(y); + if (px == py) return; + if (rank[px] >= rank[py]) { + parent[py] = px; + rank[px] += rank[py]; + } else { + parent[px] = py; + rank[py] += rank[px]; + } + } + } + } +``` +*Pythong3 code* +```python +class Solution: + def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int: + union_find = {i: i for i in range(n + 1)} + + def find(x): + return x if x == union_find[x] else find(union_find[x]) + + def union(x, y): + px = find(x) + py = find(y) + union_find[px] = py + + graph_wells = [[cost, 0, i] for i, cost in enumerate(wells, 1)] + graph_pipes = [[cost, i, j] for i, j, cost in pipes] + min_costs = 0 + for cost, x, y in sorted(graph_wells + graph_pipes): + if find(x) == find(y): + continue + union(x, y) + min_costs += cost + n -= 1 + if n == 0: + return min_costs +``` + +## External Resources + +1. [Shortest path problem](https://www.wikiwand.com/en/Shortest_path_problem) +2. [Dijkstra's algorithm](https://www.wikiwand.com/en/Dijkstra%27s_algorithm) +3. [Floyd–Warshall algorithm](https://www.wikiwand.com/en/Floyd%E2%80%93Warshall_algorithm) +4. [Bellman–Ford algorithm](https://www.wikiwand.com/en/Bellman%E2%80%93Ford_algorithm) +5. [Kruskal's algorithm](https://www.wikiwand.com/en/Kruskal%27s_algorithm) +6. [Prim's algorithm](https://www.wikiwand.com/en/Prim%27s_algorithm) +7. [Minimum spanning tree](https://www.wikiwand.com/en/Minimum_spanning_tree) \ No newline at end of file diff --git a/spider/row-markdown/1186.maximum-subarray-sum-with-one-deletion.md b/spider/row-markdown/1186.maximum-subarray-sum-with-one-deletion.md new file mode 100644 index 0000000..40e15d3 --- /dev/null +++ b/spider/row-markdown/1186.maximum-subarray-sum-with-one-deletion.md @@ -0,0 +1,161 @@ +## 题目地址 + +https://leetcode.com/problems/maximum-subarray-sum-with-one-deletion/ + +## 题目描述 + +``` + +给你一个整数数组,返回它的某个 非空 子数组(连续元素)在执行一次可选的删除操作后,所能得到的最大元素总和。 + +换句话说,你可以从原数组中选出一个子数组,并可以决定要不要从中删除一个元素(只能删一次哦),(删除后)子数组中至少应当有一个元素,然后该子数组(剩下)的元素总和是所有子数组之中最大的。 + +注意,删除一个元素后,子数组 不能为空。 + +请看示例: + +示例 1: + +输入:arr = [1,-2,0,3] +输出:4 +解释:我们可以选出 [1, -2, 0, 3],然后删掉 -2,这样得到 [1, 0, 3],和最大。 +示例 2: + +输入:arr = [1,-2,-2,3] +输出:3 +解释:我们直接选出 [3],这就是最大和。 +示例 3: + +输入:arr = [-1,-1,-1,-1] +输出:-1 +解释:最后得到的子数组不能为空,所以我们不能选择 [-1] 并从中删去 -1 来得到 0。 + 我们应该直接选择 [-1],或者选择 [-1, -1] 再从中删去一个 -1。 +  + +提示: + +1 <= arr.length <= 10^5 +-10^4 <= arr[i] <= 10^4 + +``` + +## 思路 + +### 暴力法 + +符合知觉的做法是求出所有的情况,然后取出最大的。 我们只需要两层循环接口,外循环用于确定我们丢弃的元素,内循环用于计算subArraySum。 + +```python + class Solution: + def maximumSum(self, arr: List[int]) -> int: + res = arr[0] + def maxSubSum(arr, skip): + res = maxSub = float("-inf") + + for i in range(len(arr)): + if i == skip: + continue + maxSub = max(arr[i], maxSub + arr[i]) + res = max(res, maxSub) + return res + # 这里循环到了len(arr)项,表示的是一个都不删除的情况 + for i in range(len(arr) + 1): + res = max(res, maxSubSum(arr, i)) + return res +``` + +### 空间换时间 + +上面的做法在LC上会TLE, 因此我们需要换一种思路,既然超时了,我们是否可以从空间换时间的角度思考呢?我们可以分别从头尾遍历,建立两个subArraySub的数组l和r。 其实这个不难想到,很多题目都用到了这个技巧。 + +具体做法: + +- 一层遍历, 建立l数组,l[i]表示从左边开始的以arr[i]结尾的subArraySum的最大值 +- 一层遍历, 建立r数组,r[i]表示从右边开始的以arr[i]结尾的subArraySum的最大值 +- 一层遍历, 计算 l[i - 1] + r[i + 1] 的最大值 +> l[i - 1] + r[i + 1]的含义就是删除arr[i]的子数组最大值 +- 上面的这个步骤得到了删除一个的子数组最大值, 不删除的只需要在上面循环顺便计算一下即可 + + + +```python +class Solution: + def maximumSum(self, arr: List[int]) -> int: + n = len(arr) + l = [arr[0]] * n + r = [arr[n - 1]] * n + if n == 1: + return arr[0] + res = arr[0] + for i in range(1, n): + l[i] = max(l[i - 1] + arr[i], arr[i]) + res = max(res, l[i]) + for i in range(n - 2, -1, -1): + r[i] = max(r[i + 1] + arr[i], arr[i]) + res = max(res, r[i]) + for i in range(1, n - 1): + res = max(res, l[i - 1] + r[i + 1]) + + return res + +``` + +### 动态规划 + +上面的算法虽然时间上有所改善,但是正如标题所说,空间复杂度是O(n),有没有办法改进呢?答案是使用动态规划。 + +具体过程: + +- 定义max0,表示以arr[i]结尾且一个都不漏的最大子数组和 +- 定义max1,表示以arr[i]或者arr[i - 1]结尾,可以漏一个的最大子数组和 +- 遍历数组,更新max1和max0(注意先更新max1,因为max1用到了上一个max0) +- 其中` max1 = max(max1 + arr[i], max0)`, 即删除arr[i - 1]或者删除arr[i] +- 其中` max0 = max(max0 + arr[i], arr[i])`, 一个都不删除 + +```python +# +# @lc app=leetcode.cn id=1186 lang=python3 +# +# [1186] 删除一次得到子数组最大和 +# + +# @lc code=start + + +class Solution: + def maximumSum(self, arr: List[int]) -> int: + # DP + max0 = arr[0] + max1 = arr[0] + res = arr[0] + n = len(arr) + if n == 1: + return max0 + + for i in range(1, n): + # 先更新max1,再更新max0,因为max1用到了上一个max0 + max1 = max(max1 + arr[i], max0) + max0 = max(max0 + arr[i], arr[i]) + res = max(res, max0, max1) + return res + + +# @lc code=end + + +``` +## 关键点解析 + +- 空间换时间 +- 头尾双数组 +- 动态规划 + +## 相关题目 + +- [42.trapping-rain-water](./42.trapping-rain-water.md) + + + + + + diff --git a/spider/row-markdown/121.best-time-to-buy-and-sell-stock.md b/spider/row-markdown/121.best-time-to-buy-and-sell-stock.md new file mode 100644 index 0000000..d30c088 --- /dev/null +++ b/spider/row-markdown/121.best-time-to-buy-and-sell-stock.md @@ -0,0 +1,116 @@ + +## 题目地址 +https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/ + +## 题目描述 + +``` +Say you have an array for which the ith element is the price of a given stock on day i. + +If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit. + +Note that you cannot sell a stock before you buy one. + +Example 1: + +Input: [7,1,5,3,6,4] +Output: 5 +Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. + Not 7-1 = 6, as selling price needs to be larger than buying price. +Example 2: + +Input: [7,6,4,3,1] +Output: 0 +Explanation: In this case, no transaction is done, i.e. max profit = 0. +``` + +## 思路 + +由于我们是想获取到最大的利润,我们的策略应该是低点买入,高点卖出。 + +由于题目对于交易次数有限制,只能交易一次,因此问题的本质其实就是求波峰浪谷的差值的最大值。 + +用图表示的话就是这样: + +![](https://tva1.sinaimg.cn/large/0082zybply1gbx7rzp9e1j30jg0c23zs.jpg) + +## 关键点解析 + +- 这类题只要你在心中(或者别的地方)画出上面这种图就很容易解决 + +## 代码 + +语言支持:JS,Python,C++ + +JS Code: + +```js +/** + * @param {number[]} prices + * @return {number} + */ +var maxProfit = function(prices) { + let min = prices[0]; + let profit = 0; + // 7 1 5 3 6 4 + for(let i = 1; i < prices.length; i++) { + if (prices[i] > prices[i -1]) { + profit = Math.max(profit, prices[i] - min); + } else { + min = Math.min(min, prices[i]);; + } + } + + return profit; +}; +``` + + + +Python Code: + +```python +class Solution: + def maxProfit(self, prices: 'List[int]') -> int: + if not prices: return 0 + + min_price = float('inf') + max_profit = 0 + + for price in prices: + if price < min_price: + min_price = price + elif max_profit < price - min_price: + max_profit = price - min_price + return max_profit +``` + +C++ Code: +```c++ +/** + * 系统上C++的测试用例中的输入有[],因此需要加一个判断 + */ +class Solution { +public: + int maxProfit(vector& prices) { + if (prices.empty()) return 0; + auto min = prices[0]; + auto profit = 0; + for (auto i = 1; i < prices.size(); ++i) { + if (prices[i] > prices[i -1]) { + profit = max(profit, prices[i] - min); + } else { + min = std::min(min, prices[i]);; + } + } + return profit; + } +}; +``` + + + +## 相关题目 + +- [122.best-time-to-buy-and-sell-stock-ii](./122.best-time-to-buy-and-sell-stock-ii.md) +- [309.best-time-to-buy-and-sell-stock-with-cooldown](./309.best-time-to-buy-and-sell-stock-with-cooldown.md) diff --git a/spider/row-markdown/1218.longest-arithmetic-subsequence-of-given-difference.md b/spider/row-markdown/1218.longest-arithmetic-subsequence-of-given-difference.md new file mode 100644 index 0000000..06440d4 --- /dev/null +++ b/spider/row-markdown/1218.longest-arithmetic-subsequence-of-given-difference.md @@ -0,0 +1,104 @@ +## 题目地址 + +https://leetcode-cn.com/problems/longest-arithmetic-subsequence-of-given-difference/ + +## 题目描述 + +``` + +给你一个整数数组 arr 和一个整数 difference,请你找出 arr 中所有相邻元素之间的差等于给定 difference 的等差子序列,并返回其中最长的等差子序列的长度。 + +  + +示例 1: + +输入:arr = [1,2,3,4], difference = 1 +输出:4 +解释:最长的等差子序列是 [1,2,3,4]。 +示例 2: + +输入:arr = [1,3,5,7], difference = 1 +输出:1 +解释:最长的等差子序列是任意单个元素。 +示例 3: + +输入:arr = [1,5,7,8,5,3,4,2,1], difference = -2 +输出:4 +解释:最长的等差子序列是 [7,5,3,1]。 +  + +提示: + +1 <= arr.length <= 10^5 +-10^4 <= arr[i], difference <= 10^4 + +``` + +## 思路 + +最直观的思路是双层循环,我们暴力的枚举出以每一个元素为开始元素,以最后元素结尾的的所有情况。很明显这是所有的情况,这就是暴力法的精髓, 很明显这种解法会TLE(超时),不过我们先来看一下代码,顺着这个思维继续思考。 + +### 暴力法 + +```python + def longestSubsequence(self, arr: List[int], difference: int) -> int: + n = len(arr) + res = 1 + for i in range(n): + count = 1 + for j in range(i + 1, n): + if arr[i] + difference * count == arr[j]: + count += 1 + + if count > res: + res = count + + return res +``` +### 动态规划 + +上面的时间复杂度是O(n^2), 有没有办法降低到O(n)呢?很容易想到的是空间换时间的解决方案。 + +我的想法是将`以每一个元素结尾的最长等差子序列的长度`统统存起来,即`dp[num] = maxLen` 这样我们遍历到一个新的元素的时候,就去之前的存储中去找`dp[num - difference]`, 如果找到了,就更新当前的`dp[num] = dp[num - difference] + 1`, 否则就是不进行操作(还是默认值1)。 + +这种空间换时间的做法的时间和空间复杂度都是O(n)。 + + +## 关键点解析 + +- 将`以每一个元素结尾的最长等差子序列的长度`统统存起来 + + +## 代码 + +```python +# +# @lc app=leetcode.cn id=1218 lang=python3 +# +# [1218] 最长定差子序列 +# + +# @lc code=start + + +class Solution: + + # 动态规划 + def longestSubsequence(self, arr: List[int], difference: int) -> int: + n = len(arr) + res = 1 + dp = {} + for num in arr: + dp[num] = 1 + if num - difference in dp: + dp[num] = dp[num - difference] + 1 + + return max(dp.values()) + +# @lc code=end +``` + +## 相关题目 + + + diff --git a/spider/row-markdown/122.best-time-to-buy-and-sell-stock-ii.md b/spider/row-markdown/122.best-time-to-buy-and-sell-stock-ii.md new file mode 100644 index 0000000..142b299 --- /dev/null +++ b/spider/row-markdown/122.best-time-to-buy-and-sell-stock-ii.md @@ -0,0 +1,95 @@ + +## 题目地址 +https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/ + +## 题目描述 + +``` +Say you have an array for which the ith element is the price of a given stock on day i. + +Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times). + +Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again). + +Example 1: + +Input: [7,1,5,3,6,4] +Output: 7 +Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. + Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. +Example 2: + +Input: [1,2,3,4,5] +Output: 4 +Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. + Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are + engaging multiple transactions at the same time. You must sell before buying again. +Example 3: + +Input: [7,6,4,3,1] +Output: 0 +Explanation: In this case, no transaction is done, i.e. max profit = 0. +``` + +## 思路 + +由于我们是想获取到最大的利润,我们的策略应该是低点买入,高点卖出。 + +由于题目对于交易次数没有限制,因此只要能够赚钱的机会我们都不应该放过。 + +> 如下图,我们只需要求出加粗部分的总和即可 + +用图表示的话就是这样: + +![122.best-time-to-buy-and-sell-stock-ii](../assets/problems/122.best-time-to-buy-and-sell-stock-ii.png) + +## 关键点解析 + +- 这类题只要你在心中(或者别的地方)画出上面这种图就很容易解决 + +## 代码 + +语言支持:JS,Python + +JS Code: + +```js +/** + * @param {number[]} prices + * @return {number} + */ +var maxProfit = function(prices) { + let profit = 0; + + for(let i = 1; i < prices.length; i++) { + if (prices[i] > prices[i -1]) { + profit = profit + prices[i] - prices[i - 1]; + } + } + + return profit; +}; +``` + + + +Python Code: + +```python +class Solution: + def maxProfit(self, prices: 'List[int]') -> int: + gains = [prices[i] - prices[i-1] for i in range(1, len(prices)) + if prices[i] - prices[i-1] > 0] + return sum(gains) +#评论区里都讲这是一道开玩笑的送分题. +``` + + + + + +## 相关题目 + +- [121.best-time-to-buy-and-sell-stock](./121.best-time-to-buy-and-sell-stock.md) +- [309.best-time-to-buy-and-sell-stock-with-cooldown](./309.best-time-to-buy-and-sell-stock-with-cooldown.md) + diff --git a/spider/row-markdown/1227.airplane-seat-assignment-probability.md b/spider/row-markdown/1227.airplane-seat-assignment-probability.md new file mode 100644 index 0000000..bf9b2ec --- /dev/null +++ b/spider/row-markdown/1227.airplane-seat-assignment-probability.md @@ -0,0 +1,249 @@ +## 题目地址(1227. 飞机座位分配概率) + +https://leetcode-cn.com/problems/airplane-seat-assignment-probability/description/ + +## 题目描述 + +``` + +有 n 位乘客即将登机,飞机正好有 n 个座位。第一位乘客的票丢了,他随便选了一个座位坐下。 + +剩下的乘客将会: + +如果他们自己的座位还空着,就坐到自己的座位上, + +当他们自己的座位被占用时,随机选择其他座位 +第 n 位乘客坐在自己的座位上的概率是多少? + +  + +示例 1: + +输入:n = 1 +输出:1.00000 +解释:第一个人只会坐在自己的位置上。 +示例 2: + +输入: n = 2 +输出: 0.50000 +解释:在第一个人选好座位坐下后,第二个人坐在自己的座位上的概率是 0.5。 +  + +提示: + +1 <= n <= 10^5 + + +``` + +## 暴力递归 + +这是一道 LeetCode 为数不多的概率题,我们来看下。 + +### 思路 + +我们定义原问题为 f(n)。对于第一个人来说,他有 n 中选择,就是分别选择 n 个座位中的一个。由于选择每个位置的概率是相同的,那么选择每个位置的概率应该都是 1 / n。 + +我们分三种情况来讨论: + +- 如果第一个人选择了第一个人的位置(也就是选择了自己的位置),那么剩下的人按照票上的座位做就好了,这种情况第 n 个人一定能做到自己的位置 +- 如果第一个人选择了第 n 个人的位置,那么第 n 个人肯定坐不到自己的位置。 +- 如果第一个人选择了第 i (1 < i < n)个人的位置,那么第 i 个人就相当于变成了“票丢的人”,此时问题转化为 f(n - i + 1)。 + +此时的问题转化关系如图: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gb12n0omuuj31bc0ju405.jpg) +(红色表示票丢的人) + +整个过程分析: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gb12nhestaj318u0bg76f.jpg) + +### 代码 + +代码支持 Python3: + +Python3 Code: + +```python +class Solution: + def nthPersonGetsNthSeat(self, n: int) -> float: + if n == 1: + return 1 + if n == 2: + return 0.5 + res = 1 / n + for i in range(2, n): + res += self.nthPersonGetsNthSeat(n - i + 1) * 1 / n + return res +``` + +上述代码会栈溢出。 + +## 暴力递归 + hashtable + +### 思路 + +我们考虑使用记忆化递归来减少重复计算,虽然这种做法可以减少运行时间,但是对减少递归深度没有帮助。还是会栈溢出。 + +### 代码 + +代码支持 Python3: + +Python3 Code: + +```python +class Solution: + seen = {} + + def nthPersonGetsNthSeat(self, n: int) -> float: + if n == 1: + return 1 + if n == 2: + return 0.5 + if n in self.seen: + return self.seen[n] + res = 1 / n + for i in range(2, n): + res += self.nthPersonGetsNthSeat(n - i + 1) * 1 / n + self.seen[n] = res + return res +``` + +## 动态规划 + +### 思路 + +上面做法会栈溢出。其实我们根本不需要运行就应该能判断出栈溢出,题目已经给了数据规模是 1 <= n <= 10 \*\* 5。 这个量级不管什么语言,除非使用尾递归,不然一般都会栈溢出,具体栈深度大家可以查阅相关资料。 + +既然是栈溢出,那么我们考虑使用迭代来完成。 很容易想到使用动态规划来完成。其实递归都写出来,写一个朴素版的动态规划也难不到哪去,毕竟动态规划就是记录子问题,并建立子问题之间映射而已,这和递归并无本质区别。 + +### 代码 + +代码支持 Python3: + +Python3 Code: + +```python +class Solution: + def nthPersonGetsNthSeat(self, n: int) -> float: + if n == 1: + return 1 + if n == 2: + return 0.5 + + dp = [1, .5] * n + + for i in range(2, n): + dp[i] = 1 / n + for j in range(2, i): + dp[i] += dp[i - j + 1] * 1 / n + return dp[-1] +``` + +这种思路的代码超时了,并且仅仅执行了 35/100 testcase 就超时了。 + +## 数学分析 + +### 思路 + +我们还需要进一步优化时间复杂度,我们需要思考是否可以在线形的时间内完成。 + +我们继续前面的思路进行分析, 不难得出,我们不妨称其为等式 1: + +``` +f(n) += 1/n + 0 + 1/n * (f(n-1) + f(n-2) + ... + f(2)) += 1/n * (f(n-1) + f(n-2) + ... + f(2) + 1) += 1/n * (f(n-1) + f(n-2) + ... + f(2) + f(1)) +``` + +似乎更复杂了?没关系,我们继续往下看,我们看下 f(n - 1),我们不妨称其为等式 2。 + +``` +f(n-1) = 1/(n-1) * (f(n-2) + f(n-3) + ... + f(1)) +``` + +我们将等式 1 和等式 2 两边分别同时乘以 n 和 n - 1 + +``` +n * f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(1) +(n-1) * f(n-1) = f(n-2) + f(n-3) + ... + f(1) +``` + +我们将两者相减: + +``` +n * f(n) - (n-1)*f(n-1) = f(n-1) +``` + +我们继续将 (n-1)\*f(n-1) 移到等式右边,得到: + +``` +n * f(n) = n * f(n-1) +``` + +也就是说: + +``` +f(n) = f(n - 1) +``` + +当然前提是 n 大于 2。 + +既然如此,我们就可以减少一层循环, 我们用这个思路来优化一下上面的 dp 解法。这种解法终于可以 AC 了。 + +### 代码 + +代码支持 Python3: + +Python3 Code: + +```python +class Solution: + def nthPersonGetsNthSeat(self, n: int) -> float: + if n == 1: + return 1 + if n == 2: + return 0.5 + + dp = [1, .5] * n + + for i in range(2, n): + dp[i] = 1/n+(n-2)/n * dp[n-1] + return dp[-1] +``` + +## 优化数学分析 + +### 思路 + +上面我们通过数学分析,得出了当 n 大于 2 时: + +``` +f(n) = f(n - 1) +``` + +那么是不是意味着我们随便求出一个 n 就好了? 比如我们求出 n = 2 的时候的值,是不是就知道 n 为任意数的值了。 我们不难想出 n = 2 时候,概率是 0.5,因此只要 n 大于 1 就是 0.5 概率,否则就是 1 概率。 + +### 代码 + +代码支持 Python3: + +Python3 Code: + +```python +class Solution: + def nthPersonGetsNthSeat(self, n: int) -> float: + return 1 if n == 1 else .5 + +``` + +## 关键点 + +- 概率分析 +- 数学推导 +- 动态规划 +- 递归 + mapper +- 栈限制大小 +- 尾递归 diff --git a/spider/row-markdown/124.binary-tree-maximum-path-sum.md b/spider/row-markdown/124.binary-tree-maximum-path-sum.md new file mode 100644 index 0000000..1c4c660 --- /dev/null +++ b/spider/row-markdown/124.binary-tree-maximum-path-sum.md @@ -0,0 +1,154 @@ + +## 题目地址 +https://leetcode.com/problems/binary-tree-maximum-path-sum/description/ + +## 题目描述 + +``` +Given a non-empty binary tree, find the maximum path sum. + +For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root. + +Example 1: + +Input: [1,2,3] + + 1 + / \ + 2 3 + +Output: 6 +Example 2: + +Input: [-10,9,20,null,null,15,7] + + -10 + / \ + 9 20 + / \ + 15 7 + +Output: 42 +``` + +## 思路 + + 这道题目的path让我误解了,然后浪费了很多时间来解这道题 + 我觉得leetcode给的demo太少了,不足以让我理解path的概念 + 因此我这里自己画了一个图,来补充一下,帮助大家理解path的概念,不要像我一样理解错啦。 + + 首先是官网给的两个例子: + + ![124.binary-tree-maximum-path-sum](../assets/problems/124.binary-tree-maximum-path-sum.jpg) + + 接着是我自己画的一个例子: + + ![124.binary-tree-maximum-path-sum](../assets/problems/124.binary-tree-maximum-path-sum-1.jpg) + +大家可以结合上面的demo来继续理解一下path, 除非你理解了path,否则不要往下看。 + + + 树的题目,基本都是考察递归思想的。因此我们需要思考如何去定义我们的递归函数, + 在这里我定义了一个递归函数,它的功能是,`返回以当前节点为根节点的MathPath` + 但是有两个条件: + + 1. 第一是跟节点必须选择 + 2. 第二是左右子树只能选择一个 + + 为什么要有这两个条件? + + 我的想法是原问题可以转化为: + + 以每一个节点为根节点,我们分别求出max path,最后计算最大值,因此第一个条件需要满足. + + 对于第二个,由于递归函数子节点的返回值会被父节点使用,因此我们如果两个孩子都选择了 + 就不符合max path的定义了,这也是我没有理解题意,绕了很大弯子的原因。 + + + 因此我的做法就是不断调用递归函数,然后在调用过程中不断计算和更新max,最后在主函数中将max返回即可。 + +## 关键点解析 + +- 递归 +- 理解题目中的path定义 + +## 代码 + +代码支持:JavaScript,Java + +- JavaScript + +```js + + +/* + * @lc app=leetcode id=124 lang=javascript + * + * [124] Binary Tree Maximum Path Sum + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +function helper(node, payload) { + if (node === null) return 0; + + const l = helper(node.left, payload); + const r = helper(node.right, payload); + + payload.max = Math.max( + node.val + Math.max(0, l) + Math.max(0, r), + payload.max + ); + + return node.val + Math.max(l, r, 0); +} +/** + * @param {TreeNode} root + * @return {number} + */ +var maxPathSum = function(root) { + if (root === null) return 0; + const payload = { + max: root.val + }; + helper(root, payload); + return payload.max; +}; +``` + +- Java + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + int ans; + public int maxPathSum(TreeNode root) { + ans = Integer.MIN_VALUE; + helper(root); // recursion + return ans; + } + + public int helper(TreeNode root) { + if (root == null) return 0; + int leftMax = Math.max(0, helper(root.left)); // find the max sub-path sum in left sub-tree + int rightMax = Math.max(0, helper(root.right)); // find the max sub-path sum in right sub-tree + ans = Math.max(ans, leftMax+rightMax+root.val); // find the max path sum at current node + return max(leftMax, rightMax) + root.val; // according to the definition of path, the return value of current node can only be that the sum of current node value plus either left or right max path sum. + } +} +``` + +## 相关题目 +- [113.path-sum-ii](./113.path-sum-ii.md) diff --git a/spider/row-markdown/125.valid-palindrome.md b/spider/row-markdown/125.valid-palindrome.md new file mode 100644 index 0000000..b7578be --- /dev/null +++ b/spider/row-markdown/125.valid-palindrome.md @@ -0,0 +1,147 @@ + +## 题目地址 + +https://leetcode.com/problems/valid-palindrome/description/ + +## 题目描述 + +``` +Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. + +Note: For the purpose of this problem, we define empty string as valid palindrome. + +Example 1: + +Input: "A man, a plan, a canal: Panama" +Output: true +Example 2: + +Input: "race a car" +Output: false + +``` + +## 思路 + +这是一道考察回文的题目,而且是最简单的形式,即判断一个字符串是否是回文。 + +针对这个问题,我们可以使用头尾双指针, + +- 如果两个指针的元素不相同,则直接返回false, +- 如果两个指针的元素相同,我们同时更新头尾指针,循环。 直到头尾指针相遇。 + +时间复杂度为O(n). + +拿“noon”这样一个回文串来说,我们的判断过程是这样的: + +![125.valid-palindrome-1](../assets/problems/125.valid-palindrome-1.png) + +拿“abaa”这样一个不是回文的字符串来说,我们的判断过程是这样的: + +![125.valid-palindrome-2](../assets/problems/125.valid-palindrome-2.png) + + + +## 关键点解析 + +- 双指针 + +## 代码 + +* 语言支持:JS,C++,Python + +JavaScript Code: + +```js + +/* + * @lc app=leetcode id=125 lang=javascript + * + * [125] Valid Palindrome + */ +// 只处理英文字符(题目忽略大小写,我们前面全部转化成了小写, 因此这里我们只判断小写)和数字 +function isValid(c) { + const charCode = c.charCodeAt(0); + const isDigit = + charCode >= "0".charCodeAt(0) && charCode <= "9".charCodeAt(0); + const isChar = charCode >= "a".charCodeAt(0) && charCode <= "z".charCodeAt(0); + + return isDigit || isChar; +} +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function(s) { + s = s.toLowerCase(); + let left = 0; + let right = s.length - 1; + + while (left < right) { + if (!isValid(s[left])) { + left++; + continue; + } + if (!isValid(s[right])) { + right--; + continue; + } + + if (s[left] === s[right]) { + left++; + right--; + } else { + break; + } + } + + return right <= left; +}; +``` +C++ Code: +```C++ +class Solution { +public: + bool isPalindrome(string s) { + if (s.empty()) + return true; + const char* s1 = s.c_str(); + const char* e = s1 + s.length() - 1; + while (e > s1) { + if (!isalnum(*s1)) {++s1; continue;} + if (!isalnum(*e)) {--e; continue;} + if (tolower(*s1) != tolower(*e)) return false; + else {--e; ++s1;} + } + return true; + } +}; +``` + +Python Code: + +```python +class Solution: + def isPalindrome(self, s: str) -> bool: + left, right = 0, len(s) - 1 + while left < right: + if not s[left].isalnum(): + left += 1 + continue + if not s[right].isalnum(): + right -= 1 + continue + if s[left].lower() == s[right].lower(): + left += 1 + right -= 1 + else: + break + return right <= left + + def isPalindrome2(self, s: str) -> bool: + """ + 使用语言特性进行求解 + """ + s = ''.join(i for i in s if i.isalnum()).lower() + return s == s[::-1] +``` diff --git a/spider/row-markdown/1260.shift-2d-grid.md b/spider/row-markdown/1260.shift-2d-grid.md new file mode 100644 index 0000000..1729456 --- /dev/null +++ b/spider/row-markdown/1260.shift-2d-grid.md @@ -0,0 +1,144 @@ +## 题目地址(1260. 二维网格迁移) + +https://leetcode-cn.com/problems/shift-2d-grid/description/ + +## 题目描述 + +``` + +给你一个 n 行 m 列的二维网格 grid 和一个整数 k。你需要将 grid 迁移 k 次。 + +每次「迁移」操作将会引发下述活动: + +位于 grid[i][j] 的元素将会移动到 grid[i][j + 1]。 +位于 grid[i][m - 1] 的元素将会移动到 grid[i + 1][0]。 +位于 grid[n - 1][m - 1] 的元素将会移动到 grid[0][0]。 +请你返回 k 次迁移操作后最终得到的 二维网格。 + +  + +示例 1: + + + +输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1 +输出:[[9,1,2],[3,4,5],[6,7,8]] +示例 2: + + + +输入:grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4 +输出:[[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]] +示例 3: + +输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9 +输出:[[1,2,3],[4,5,6],[7,8,9]] +  + +提示: + +1 <= grid.length <= 50 +1 <= grid[i].length <= 50 +-1000 <= grid[i][j] <= 1000 +0 <= k <= 100 + + +``` + +## 暴力法 + +我们直接翻译题目,没有任何 hack 的做法。 + +### 代码 + +```python +from copy import deepcopy + +class Solution: + def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]: + n = len(grid) + m = len(grid[0]) + for _ in range(k): + old = deepcopy(grid) + for i in range(n): + for j in range(m): + if j == m - 1: + grid[(i + 1) % n][0] = old[i][j] + elif i == n - 1 and j == m - 1: + grid[0][0] = old[i][j] + else: + grid[i][j + 1] = old[i][j] + return grid +``` + +由于是 easy,上述做法勉强可以过,我们考虑优化。 + +## 数学分析 + +### 思路 + +我们仔细观察矩阵会发现,其实这样的矩阵迁移是有规律的。 如图: +![image](https://user-images.githubusercontent.com/12479470/72203575-4f6e4c00-34a8-11ea-8765-03fc856d4ea6.png) + +因此这个问题就转化为我们一直的一维矩阵转移问题,LeetCode 也有原题[189. 旋转数组](https://leetcode-cn.com/problems/rotate-array/),同时我也写了一篇文章[文科生都能看懂的循环移位算法](https://lucifer.ren/blog/2019/12/11/rotate-list/)专门讨论这个,最终我们使用的是三次旋转法,相关数学证明也有写,很详细,这里不再赘述。 + +LeetCode 真的是喜欢换汤不换药呀 😂 + +### 代码 + +Python 代码: + +```python +# +# @lc app=leetcode.cn id=1260 lang=python3 +# +# [1260] 二维网格迁移 +# + +# @lc code=start + + +class Solution: + def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]: + n = len(grid) + m = len(grid[0]) + # 二维到一维 + arr = [grid[i][j] for i in range(n) for j in range(m)] + # 取模,缩小k的范围,避免无意义的运算 + k %= m * n + res = [] + # 首尾交换法 + + def reverse(l, r): + while l < r: + t = arr[l] + arr[l] = arr[r] + arr[r] = t + l += 1 + r -= 1 + # 三次旋转 + reverse(0, m * n - k - 1) + reverse(m * n - k, m * n - 1) + reverse(0, m * n - 1) + # 一维到二维 + row = [] + for i in range(m * n): + if i > 0 and i % m == 0: + res.append(row) + row = [] + row.append(arr[i]) + res.append(row) + + return res + +# @lc code=end + +``` + +## 相关题目 + +- [189. 旋转数组](https://leetcode-cn.com/problems/rotate-array/) + +## 参考 + +- [文科生都能看懂的循环移位算法](https://lucifer.ren/blog/2019/12/11/rotate-list/) diff --git a/spider/row-markdown/1261.find-elements-in-a-contaminated-binary-tree.md b/spider/row-markdown/1261.find-elements-in-a-contaminated-binary-tree.md new file mode 100644 index 0000000..a5d5c5e --- /dev/null +++ b/spider/row-markdown/1261.find-elements-in-a-contaminated-binary-tree.md @@ -0,0 +1,249 @@ +# 题目地址(1261. 在受污染的二叉树中查找元素) + +https://leetcode-cn.com/problems/find-elements-in-a-contaminated-binary-tree/submissions/ + +## 题目描述 + +``` +给出一个满足下述规则的二叉树: + +root.val == 0 +如果 treeNode.val == x 且 treeNode.left != null,那么 treeNode.left.val == 2 * x + 1 +如果 treeNode.val == x 且 treeNode.right != null,那么 treeNode.right.val == 2 * x + 2 +现在这个二叉树受到「污染」,所有的 treeNode.val 都变成了 -1。 + +请你先还原二叉树,然后实现 FindElements 类: + +FindElements(TreeNode* root) 用受污染的二叉树初始化对象,你需要先把它还原。 +bool find(int target) 判断目标值 target 是否存在于还原后的二叉树中并返回结果。 +  + +示例 1: + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gasy4qroxoj308w03b3yi.jpg) + +输入: +["FindElements","find","find"] +[[[-1,null,-1]],[1],[2]] +输出: +[null,false,true] +解释: +FindElements findElements = new FindElements([-1,null,-1]); +findElements.find(1); // return False +findElements.find(2); // return True +示例 2: + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gasy5mlo3mj30b405iwep.jpg) + +输入: +["FindElements","find","find","find"] +[[[-1,-1,-1,-1,-1]],[1],[3],[5]] +输出: +[null,true,true,false] +解释: +FindElements findElements = new FindElements([-1,-1,-1,-1,-1]); +findElements.find(1); // return True +findElements.find(3); // return True +findElements.find(5); // return False +示例 3: + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gasy5sr25yj308i07maa8.jpg) + +输入: +["FindElements","find","find","find","find"] +[[[-1,null,-1,-1,null,-1]],[2],[3],[4],[5]] +输出: +[null,true,false,false,true] +解释: +FindElements findElements = new FindElements([-1,null,-1,-1,null,-1]); +findElements.find(2); // return True +findElements.find(3); // return False +findElements.find(4); // return False +findElements.find(5); // return True +  + +提示: + +TreeNode.val == -1 +二叉树的高度不超过 20 +节点的总数在 [1, 10^4] 之间 +调用 find() 的总次数在 [1, 10^4] 之间 +0 <= target <= 10^6 + +``` + +## 暴力法 + +### 思路 + +最简单想法就是递归建立树,然后 find 的时候递归查找即可,代码也很简单。 + +### 代码 + +Pythpn Code: + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class FindElements: + node = None + def __init__(self, root: TreeNode): + def recover(node): + if not node: + return node; + if node.left: + node.left.val = 2 * node.val + 1 + if node.right: + node.right.val = 2 * node.val + 2 + recover(node.left) + recover(node.right) + return node + root.val = 0 + self.node = recover(root) + + + def find(self, target: int) -> bool: + def findInTree(node, target): + if not node: + return False + if node.val == target: + return True + return findInTree(node.left, target) or findInTree(node.right, target) + return findInTree(self.node, target) + + + + +# Your FindElements object will be instantiated and called as such: +# obj = FindElements(root) +# param_1 = obj.find(target) +``` + +上述代码会超时,我们来考虑优化。 + +## 空间换时间 + +### 思路 + +上述代码会超时,我们考虑使用空间换时间。 建立树的时候,我们将所有值存到一个集合中去。当需要 find 的时候,我们直接查找 set 即可,时间复杂度 O(1)。 + +### 代码 + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class FindElements: + def __init__(self, root: TreeNode): + # set 不能放在init外侧。 因为测试用例之间不会销毁FindElements的变量 + self.seen = set() + def recover(node): + if not node: + return node; + if node.left: + node.left.val = 2 * node.val + 1 + self.seen.add(node.left.val) + if node.right: + node.right.val = 2 * node.val + 2 + self.seen.add(node.right.val) + recover(node.left) + recover(node.right) + return node + root.val = 0 + self.seen.add(0) + self.node = recover(root) + + + def find(self, target: int) -> bool: + return target in self.seen + + + + +# Your FindElements object will be instantiated and called as such: +# obj = FindElements(root) +# param_1 = obj.find(target) +``` + +这种解法可以 AC,但是在数据量非常大的时候,可能 MLE,我们继续考虑优化。 + +## 二进制法 + +### 思路 + +这是一种非常巧妙的做法。 + +如果我们把树中的数全部加 1 会怎么样? + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gasypfuvuvj30rs0kudjr.jpg) +(图参考 https://leetcode.com/problems/find-elements-in-a-contaminated-binary-tree/discuss/431229/Python-Special-Way-for-find()-without-HashSet-O(1)-Space-O(logn)-Time) + +仔细观察发现,每一行的左右子树分别有不同的前缀: + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gasz0x09koj312y0sgnnt.jpg) + +Ok,那么算法就来了。为了便于理解,我们来举个具体的例子,比如 target 是 9,我们首先将其加 1,二进制表示就是 1010。不考虑第一位,就是 010,我们只要: + +- 0 向左 👈 +- 1 向右 👉 +- - 0 向左 👈 + +就可以找到 9 了。 + +> 0 表示向左 , 1 表示向右 + +### 代码 + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class FindElements: + node = None + def __init__(self, root: TreeNode): + def recover(node): + if not node: + return node; + if node.left: + node.left.val = 2 * node.val + 1 + if node.right: + node.right.val = 2 * node.val + 2 + recover(node.left) + recover(node.right) + return node + root.val = 0 + self.node = recover(root) + + + def find(self, target: int) -> bool: + node = self.node + for bit in bin(target+1)[3:]: + node = node and (node.left, node.right)[int(bit)] + return bool(node) + + + + +# Your FindElements object will be instantiated and called as such: +# obj = FindElements(root) +# param_1 = obj.find(target) +``` + +## 关键点解析 + +- 空间换时间 +- 二进制思维 +- 将 target + 1 diff --git a/spider/row-markdown/1262.greatest-sum-divisible-by-three.md b/spider/row-markdown/1262.greatest-sum-divisible-by-three.md new file mode 100644 index 0000000..a6d3802 --- /dev/null +++ b/spider/row-markdown/1262.greatest-sum-divisible-by-three.md @@ -0,0 +1,241 @@ +# 题目地址(1262. 可被三整除的最大和) + +https://leetcode-cn.com/problems/greatest-sum-divisible-by-three/description/ + +## 题目描述 + +``` +给你一个整数数组 nums,请你找出并返回能被三整除的元素最大和。 + +  + +示例 1: + +输入:nums = [3,6,5,1,8] +输出:18 +解释:选出数字 3, 6, 1 和 8,它们的和是 18(可被 3 整除的最大和)。 +示例 2: + +输入:nums = [4] +输出:0 +解释:4 不能被 3 整除,所以无法选出数字,返回 0。 +示例 3: + +输入:nums = [1,2,3,4,4] +输出:12 +解释:选出数字 1, 3, 4 以及 4,它们的和是 12(可被 3 整除的最大和)。 +  + +提示: + +1 <= nums.length <= 4 * 10^4 +1 <= nums[i] <= 10^4 + +``` + +## 暴力法 + +### 思路 + +一种方式是找出所有的能够被 3 整除的子集,然后挑选出和最大的。由于我们选出了所有的子集,那么时间复杂度就是 $O(2^N)$ , 毫无疑问会超时。这里我们使用回溯法找子集,如果不清楚回溯法,可以参考我之前的题解,很多题目都用到了,比如[78.subsets](https://github.com/azl397985856/leetcode/blob/master/problems/78.subsets.md)。 + +更多回溯题目,可以访问上方链接查看(可以使用一套模板搞定): + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gatuu0yfh8j30f60c4ab3.jpg) + +### 代码 + +```python +class Solution: + def maxSumDivThree(self, nums: List[int]) -> int: + self.res = 0 + def backtrack(temp, start): + total = sum(temp) + if total % 3 == 0: + self.res = max(self.res, total) + for i in range(start, len(nums)): + temp.append(nums[i]) + backtrack(temp, i + 1) + temp.pop(-1) + + + backtrack([], 0) + + return self.res +``` + +## 减法 + 排序 + +减法的核心思想是,我们求出总和。如果总和不满足题意,我们尝试减去最小的数,使之满足题意。 + +### 思路 + +这种算法的思想,具体来说就是: + +- 我们将所有的数字加起来,我们不妨设为 total +- total 除以 3,得到一个余数 mod, mod 可能值有 0,1,2. +- 同时我们建立两个数组,一个是余数为 1 的数组 one,一个是余数为 2 的数组 two +- 如果 mod 为 0,我们直接返回即可。 +- 如果 mod 为 1,我们可以减去 one 数组中最小的一个(如果有的话),或者减去两个 two 数组中最小的(如果有的话),究竟减去谁取决谁更小。 +- 如果 mod 为 2,我们可以减去 two 数组中最小的一个(如果有的话),或者减去两个 one 数组中最小的(如果有的话),究竟减去谁取决谁更小。 + +由于我们需要取 one 和 two 中最小的一个或者两个,因此对数组 one 和 two 进行排序是可行的,如果基于排序的话,时间复杂度大致为 $O(NlogN)$,这种算法可以通过。 + +以题目中的例 1 为例: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gatvdy1zb1j30u00x2wgx.jpg) + +以题目中的例 2 为例: + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gatvem1xm4j30u00xvq59.jpg) + +### 代码 + +```python +class Solution: + def maxSumDivThree(self, nums: List[int]) -> int: + one = [] + two = [] + total = 0 + + for num in nums: + total += num + if num % 3 == 1: + one.append(num) + if num % 3 == 2: + two.append(num) + one.sort() + two.sort() + if total % 3 == 0: + return total + elif total % 3 == 1 and one: + if len(two) >= 2 and one[0] > two[0] + two[1]: + return total - two[0] - two[1] + return total - one[0] + elif total % 3 == 2 and two: + if len(one) >= 2 and two[0] > one[0] + one[1]: + return total - one[0] - one[1] + return total - two[0] + return 0 +``` + +## 减法 + 非排序 + +### 思路 + +上面的解法使用到了排序。 我们其实观察发现,我们只是用到了 one 和 two 的最小的两个数。因此我们完全可以在线形的时间和常数的空间完成这个算法。我们只需要分别记录 one 和 two 的最小值和次小值即可,在这里,我使用了两个长度为 2 的数组来表示,第一项是最小值,第二项是次小值。 + +### 代码 + +```python +class Solution: + def maxSumDivThree(self, nums: List[int]) -> int: + one = [float('inf')] * 2 + two = [float('inf')] * 2 + total = 0 + + for num in nums: + total += num + if num % 3 == 1: + if num < one[0]: + t = one[0] + one[0] = num + one[1] = t + elif num < one[1]: + one[1] = num + if num % 3 == 2: + if num < two[0]: + t = two[0] + two[0] = num + two[1] = t + elif num < two[1]: + two[1] = num + if total % 3 == 0: + return total + elif total % 3 == 1 and one: + if len(two) >= 2 and one[0] > two[0] + two[1]: + return total - two[0] - two[1] + return total - one[0] + elif total % 3 == 2 and two: + if len(one) >= 2 and two[0] > one[0] + one[1]: + return total - one[0] - one[1] + return total - two[0] + return 0 +``` + +## 有限状态机 + +### 思路 + +我在[数据结构与算法在前端领域的应用 - 第二篇](https://lucifer.ren/blog/2019/09/19/algorthimn-fe-2/) 中讲到了有限状态机。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gatub3vftxj30eq0bfta0.jpg) + +状态机表示若干个状态以及在这些状态之间的转移和动作等行为的数学模型。通俗的描述状态机就是定义了一套状态変更的流程:状态机包含一个状态集合,定义当状态机处于某一个状态的时候它所能接收的事件以及可执行的行为,执行完成后,状态机所处的状态。 + +状态机使用非常广泛,比如正则表达式的引擎,编译器的词法和语法分析,网络协议,企业应用等很多领域都会用到。 + +拿本题中来说,我们从左到右扫描数组的过程,将会不断改变状态机的状态。 + +我们使用 state 数组来表示本题的状态: + +- state[0] 表示 mod 为 0 的 最大和 +- state[1] 表示 mod 为 1 的 最大和 +- state[2] 表示 mod 为 1 的 最大和 + +我们的状态转移方程就会很容易。说到状态转移方程,你可能会想到动态规划。没错!这种思路可以直接翻译成动态规划,算法完全一样。如果你看过我上面提到的文章,那么状态转移方程对你来说就会很容易。如果你不清楚,那么请往下看: + +- 我们从左往右不断读取数字,我们不妨设这个数字为 num。 +- 如果 num % 3 为 0。 那么我们的 state[0], state[1], state[2] 可以直接加上 num(题目限定了 num 为非负), 因为任何数字加上 3 的倍数之后,mod 3 的值是不变的。 +- 如果 num % 3 为 1。 我们知道 state[2] + num 会变成一个能被三整除的数,但是这个数字不一定比当前的 state[0]大。 代码表示就是`max(state[2] + num, state[0])`。同理 state[1] 和 state[2] 的转移逻辑类似。 +- 同理 num % 3 为 2 也是类似的逻辑。 +- 最后我们返回 state[0]即可。 + +### 代码 + +```python +class Solution: + def maxSumDivThree(self, nums: List[int]) -> int: + state = [0, float('-inf'), float('-inf')] + + for num in nums: + if num % 3 == 0: + state = [state[0] + num, state[1] + num, state[2] + num] + if num % 3 == 1: + a = max(state[2] + num, state[0]) + b = max(state[0] + num, state[1]) + c = max(state[1] + num, state[2]) + state = [a, b, c] + if num % 3 == 2: + a = max(state[1] + num, state[0]) + b = max(state[2] + num, state[1]) + c = max(state[0] + num, state[2]) + state = [a, b, c] + return state[0] +``` + +当然这个代码还可以简化: + +```python +class Solution: + def maxSumDivThree(self, nums: List[int]) -> int: + state = [0, float('-inf'), float('-inf')] + + for num in nums: + temp = [0] * 3 + for i in range(3): + temp[(i + num) % 3] = max(state[(i + num) % 3], state[i] + num) + state = temp + + return state[0] +``` + +## 关键点解析 + +- 贪婪法 +- 状态机 +- 数学分析 + +## 扩展 + +实际上,我们可以采取加法(贪婪策略),感兴趣的可以试一下。 diff --git a/spider/row-markdown/128.longest-consecutive-sequence.md b/spider/row-markdown/128.longest-consecutive-sequence.md new file mode 100644 index 0000000..65ab0e6 --- /dev/null +++ b/spider/row-markdown/128.longest-consecutive-sequence.md @@ -0,0 +1,88 @@ +## 题目地址 + +https://leetcode.com/problems/longest-consecutive-sequence/description/ + +## 题目描述 + +``` +Given an unsorted array of integers, find the length of the longest consecutive elements sequence. + +Your algorithm should run in O(n) complexity. + +Example: + +Input: [100, 4, 200, 1, 3, 2] +Output: 4 +Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4. +Accepted +200,786 +Submissions +485,346 + +``` + +## 思路 + +这是一道最最长连续数字序列长度的题目, 官网给出的难度是`hard`. + +符合直觉的做法是先排序,然后用一个变量记录最大值,遍历去更新最大值即可, + +代码: + +```js +if (nums.length === 0) return 0; +let count = 1; +let maxCount = 1; +// 这里其实可以不需要排序,这么做只不过是为了方便理解 +nums = [...new Set(nums)].sort((a, b) => a - b); +for (let i = 0; i < nums.length - 1; i++) { + if (nums[i + 1] - nums[i] === 1) { + count++; + } else { + if (count > maxCount) { + maxCount = count; + } + count = 1; + } +} +return Math.max(count, maxCount); +``` + +但是需要排序时间复杂度会上升,题目要求时间复杂度为 O(n), +那么我们其实可以不用排序去解决的。 + +思路就是将之前”排序之后,通过比较前后元素是否相差 1 来判断是否连续“的思路改为 +不排序而是`直接遍历,然后在内部循环里面查找是否存在当前值的邻居元素`,但是马上有一个 +问题,内部我们`查找是否存在当前值的邻居元素`的过程如果使用数组,时间复杂度是 O(n), +那么总体的复杂度就是 O(n^2),完全不可以接受。怎么办呢? + +我们换个思路,用空间来换时间。比如用类似于 hashmap 这样的数据结构优化查询部分,将时间复杂度降低到 O(1), 代码见后面`代码部分` + +## 关键点解析 + +- 空间换时间 + +## 代码 + +```js +/** + * @param {number[]} nums + * @return {number} + */ +var longestConsecutive = function(nums) { + set = new Set(nums); + let max = 0; + let temp = 0; + set.forEach(x => { + // 说明x是连续序列的开头元素 + if (!set.has(x - 1)) { + temp = x + 1; + while (set.has(y)) { + temp = temp + 1; + } + max = Math.max(max, y - x); // y - x 就是从x开始到最后有多少连续的数字 + } + }); + return max; +}; +``` diff --git a/spider/row-markdown/129.sum-root-to-leaf-numbers.md b/spider/row-markdown/129.sum-root-to-leaf-numbers.md new file mode 100644 index 0000000..551629c --- /dev/null +++ b/spider/row-markdown/129.sum-root-to-leaf-numbers.md @@ -0,0 +1,244 @@ +## 题目地址 + +https://leetcode.com/problems/sum-root-to-leaf-numbers/description/ + +## 题目描述 + +``` +Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. + +An example is the root-to-leaf path 1->2->3 which represents the number 123. + +Find the total sum of all root-to-leaf numbers. + +Note: A leaf is a node with no children. + +Example: + +Input: [1,2,3] + 1 + / \ + 2 3 +Output: 25 +Explanation: +The root-to-leaf path 1->2 represents the number 12. +The root-to-leaf path 1->3 represents the number 13. +Therefore, sum = 12 + 13 = 25. +Example 2: + +Input: [4,9,0,5,1] + 4 + / \ + 9 0 + / \ +5 1 +Output: 1026 +Explanation: +The root-to-leaf path 4->9->5 represents the number 495. +The root-to-leaf path 4->9->1 represents the number 491. +The root-to-leaf path 4->0 represents the number 40. +Therefore, sum = 495 + 491 + 40 = 1026. + +``` + +## 思路 + +这是一道非常适合训练递归的题目。虽然题目不难,但是要想一次写正确,并且代码要足够优雅却不是很容易。 + +这里我们的思路是定一个递归的helper函数,用来帮助我们完成递归操作。 +递归函数的功能是将它的左右子树相加,注意这里不包括这个节点本身,否则会多加, +我们其实关注的就是叶子节点的值,然后通过层层回溯到root,返回即可。 + +整个过程如图所示: + +![129.sum-root-to-leaf-numbers-1](../assets/problems/129.sum-root-to-leaf-numbers-1.jpg) + + +那么数字具体的计算逻辑,如图所示,相信大家通过这个不难发现规律: + +![129.sum-root-to-leaf-numbers-2](../assets/problems/129.sum-root-to-leaf-numbers-2.jpg) + +## 关键点解析 + +- 递归分析 + +## 代码 + +* 语言支持:JS,C++,Python + +JavaScipt Code: + +```js +/* + * @lc app=leetcode id=129 lang=javascript + * + * [129] Sum Root to Leaf Numbers + */ +function helper(node, cur) { + if (node === null) return 0; + const next = node.val + cur * 10; + + if (node.left === null && node.right === null) return next; + + const l = helper(node.left, next); + const r = helper(node.right, next); + + return l + r; +} +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var sumNumbers = function(root) { + // tag: `tree` `dfs` `math` + return helper(root, 0); +}; +``` + +C++ Code: +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + int sumNumbers(TreeNode* root) { + return helper(root, 0); + } +private: + int helper(const TreeNode* root, int val) { + if (root == nullptr) return 0; + auto ret = root->val + val * 10; + if (root->left == nullptr && root->right == nullptr) + return ret; + auto l = helper(root->left, ret); + auto r = helper(root->right, ret); + return l + r; + } +}; +``` + +Python Code: + +```python +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + def sumNumbers(self, root: TreeNode) -> int: + + def helper(node, cur_val): + if not node: return 0 + next_val = cur_val * 10 + node.val + + if not (node.left or node.right): + return next_val + + left_val = helper(node.left, next_val) + right_val = helper(node.right, next_val) + + return left_val + right_val + + return helper(root, 0) +``` + +## 拓展 + +通常来说,可以利用队列、栈等数据结构将递归算法转为递推算法。 + +### 描述 + +使用两个队列: +1. 当前和队列:保存上一层每个结点的当前和(比如49和40) +2. 结点队列:保存当前层所有的非空结点 + +每次循环按层处理结点队列。处理步骤: +1. 从结点队列取出一个结点 +2. 从当前和队列将上一层对应的当前和取出来 +3. 若左子树非空,则将该值乘以10加上左子树的值,并添加到当前和队列中 +4. 若右子树非空,则将该值乘以10加上右子树的值,并添加到当前和队列中 +5. 若左右子树均为空时,将该节点的当前和加到返回值中 + +## 实现 + +* 语言支持:C++,Python + +C++ Code: + +```C++ +class Solution { +public: + int sumNumbers(TreeNode* root) { + if (root == nullptr) return 0; + auto ret = 0; + auto runningSum = vector{root->val}; + auto queue = vector{root}; + while (!queue.empty()) { + auto sz = queue.size(); + for (auto i = 0; i < sz; ++i) { + auto n = queue.front(); + queue.erase(queue.begin()); + auto tmp = runningSum.front(); + runningSum.erase(runningSum.begin()); + if (n->left != nullptr) { + runningSum.push_back(tmp * 10 + n->left->val); + queue.push_back(n->left); + } + if (n->right != nullptr) { + runningSum.push_back(tmp * 10 + n->right->val); + queue.push_back(n->right); + } + if (n->left == nullptr && n->right == nullptr) { + ret += tmp; + } + } + } + return ret; + } +}; +``` + +Python Code: + +```python +class Solution: + def sumNumbers(self, root: TreeNode) -> int: + if not root: return 0 + result = 0 + node_queue, sum_queue = [root], [root.val] + while node_queue: + for i in node_queue: + cur_node = node_queue.pop(0) + cur_val = sum_queue.pop(0) + if cur_node.left: + node_queue.append(cur_node.left) + sum_queue.append(cur_val * 10 + cur_node.left.val) + if cur_node.right: + node_queue.append(cur_node.right) + sum_queue.append(cur_val * 10 + cur_node.right.val) + if not (cur_node.left or cur_node.right): + result += cur_val + return result +``` + +## 相关题目 + +- [sum-of-root-to-leaf-binary-numbers](https://leetcode.com/problems/sum-of-root-to-leaf-binary-numbers/) + +> 这道题和本题太像了,跟一道题没啥区别 diff --git a/spider/row-markdown/1297.maximum-number-of-occurrences-of-a-substring.md b/spider/row-markdown/1297.maximum-number-of-occurrences-of-a-substring.md new file mode 100644 index 0000000..194fea2 --- /dev/null +++ b/spider/row-markdown/1297.maximum-number-of-occurrences-of-a-substring.md @@ -0,0 +1,144 @@ +# 题目地址(1297. 子串的最大出现次数) + +https://leetcode-cn.com/problems/maximum-number-of-occurrences-of-a-substring + +## 题目描述 + +``` +给你一个字符串 s ,请你返回满足以下条件且出现次数最大的 任意 子串的出现次数: + +子串中不同字母的数目必须小于等于 maxLetters 。 +子串的长度必须大于等于 minSize 且小于等于 maxSize 。 + + +示例 1: + +输入:s = "aababcaab", maxLetters = 2, minSize = 3, maxSize = 4 +输出:2 +解释:子串 "aab" 在原字符串中出现了 2 次。 +它满足所有的要求:2 个不同的字母,长度为 3 (在 minSize 和 maxSize 范围内)。 +示例 2: + +输入:s = "aaaa", maxLetters = 1, minSize = 3, maxSize = 3 +输出:2 +解释:子串 "aaa" 在原字符串中出现了 2 次,且它们有重叠部分。 +示例 3: + +输入:s = "aabcabcab", maxLetters = 2, minSize = 2, maxSize = 3 +输出:3 +示例 4: + +输入:s = "abcde", maxLetters = 2, minSize = 3, maxSize = 3 +输出:0 + + +提示: + +1 <= s.length <= 10^5 +1 <= maxLetters <= 26 +1 <= minSize <= maxSize <= min(26, s.length) +s 只包含小写英文字母。 +``` + +## 暴力法 + +题目给的数据量不是很大,为 1 <= maxLetters <= 26,我们试一下暴力法。 + +### 思路 + +暴力法如下: + +- 先找出所有满足长度大于等于 minSize 且小于等于 maxSize 的所有子串。(平方的复杂度) +- 对于 maxLetter 满足题意的子串,我们统计其出现次数。时间复杂度为 O(k),其中 k 为子串长度 +- 返回最大的出现次数 + +### 代码 + +Pythpn Code: + +```python +class Solution: + def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int: + n = len(s) + letters = set() + cnts = dict() + res = 0 + for i in range(n - minSize + 1): + length = minSize + while i + length <= n and length <= maxSize: + t = s[i:i + length] + for c in t: + if len(letters) > maxLetters: + break + letters.add(c) + if len(letters) <= maxLetters: + cnts[t] = cnts.get(t, 0) + 1 + res = max(res, cnts[t]) + letters.clear() + length += 1 + return res +``` + +上述代码会超时。我们来利用剪枝来优化。 + +## 剪枝 + +### 思路 + +还是暴力法的思路,不过我们在此基础上进行一些优化。首先我们需要仔细阅读题目,如果你足够细心或者足够有经验,可能会发现其实题目中 maxSize 没有任何用处,属于干扰信息。 + +也就是说我们没有必要统计`长度大于等于 minSize 且小于等于 maxSize 的所有子串`,而是统计长度为 minSize 的所有字串即可。原因是,如果一个大于 minSize 长度的字串若是满足条件,那么该子串其中必定有至少一个长度为 minSize 的字串满足条件。因此一个大于 minSize 长度的字串出现了 n 次,那么该子串其中必定有一个长度为 minSize 的子串出现了 n 次。 + +### 代码 + +代码支持 Python3,Java: + +Python Code: + +```python + def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int: + counter, res = {}, 0 + for i in range(0, len(s) - minSize + 1): + sub = s[i : i + minSize] + if len(set(sub)) <= maxLetters: + counter[sub] = counter.get(sub, 0) + 1 + res = max(res, counter[sub]) + return res; + +# @lc code=end +``` + +Java Code: + +```java + public int maxFreq(String s, int maxLetters, int minSize, int maxSize) { + Map counter = new HashMap<>(); + int res = 0; + for (int i = 0; i < s.length() - minSize + 1; i++) { + String substr = s.substring(i, i + minSize); + if (checkNum(substr, maxLetters)) { + int newVal = counter.getOrDefault(substr, 0) + 1; + counter.put(substr, newVal); + res = Math.max(res, newVal); + } + } + return res; +} +public boolean checkNum(String substr, int maxLetters) { + Set set = new HashSet<>(); + for (int i = 0; i < substr.length(); i++) + set.add(substr.charAt(i)); + return set.size() <= maxLetters; +} + +``` + +## 关键点解析 + +- 滑动窗口 +- 识别题目干扰信息 +- 看题目限制条件,对于本题有用的信息是`1 <= maxLetters <= 26` + +## 扩展 + +我们也可以使用滑动窗口来解决,感兴趣的可以试试看。 diff --git a/spider/row-markdown/130.surrounded-regions.md b/spider/row-markdown/130.surrounded-regions.md new file mode 100644 index 0000000..060ec58 --- /dev/null +++ b/spider/row-markdown/130.surrounded-regions.md @@ -0,0 +1,159 @@ +## 题目地址 + +https://leetcode.com/problems/surrounded-regions/description/ + +## 题目描述 + +``` +Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. + +A region is captured by flipping all 'O's into 'X's in that surrounded region. + +Example: + +X X X X +X O O X +X X O X +X O X X +After running your function, the board should be: + +X X X X +X X X X +X X X X +X O X X +Explanation: + +Surrounded regions shouldn’t be on the border, which means that any 'O' on the border of the board are not flipped to 'X'. Any 'O' that is not on the border and it is not connected to an 'O' on the border will be flipped to 'X'. Two cells are connected if they are adjacent cells connected horizontally or vertically. + +``` + +## 思路 + +我们需要将所有被X包围的O变成X,并且题目明确说了边缘的所有O都是不可以变成X的。 + +![130.surrounded-regions](../assets/problems/130.surrounded-regions-1.jpg) + +其实我们观察会发现,我们除了边缘的O以及和边缘O连通的O是不需要变成X的,其他都要变成X。 + +经过上面的思考,问题转化为连通区域问题。 这里我们需要标记一下`边缘的O以及和边缘O连通的O`。 +我们当然可以用额外的空间去存,但是对于这道题目而言,我们完全可以mutate。这样就空间复杂度会好一点。 + +整个过程如图所示: + +> 我将`边缘的O以及和边缘O连通的O` 标记为了 "A" + +![130.surrounded-regions](../assets/problems/130.surrounded-regions-2.jpg) + + + +## 关键点解析 + +- 二维数组DFS解题模板 +- 转化问题为`连通区域问题` +- 直接mutate原数组,节省空间 + +## 代码 + +* 语言支持:JS,Python3 + +```js + + + +/* + * @lc app=leetcode id=130 lang=javascript + * + * [130] Surrounded Regions + */ +// 将O以及周边的O转化为A +function mark(board, i, j, rows, cols) { + if (i < 0 || i > rows - 1 || j < 0 || j > cols - 1 || board[i][j] !== "O") + return; + + board[i][j] = "A"; + mark(board, i + 1, j, rows, cols); + mark(board, i - 1, j, rows, cols); + mark(board, i, j + 1, rows, cols); + mark(board, i, j - 1, rows, cols); +} +/** + * @param {character[][]} board + * @return {void} Do not return anything, modify board in-place instead. + */ +var solve = function(board) { + const rows = board.length; + if (rows === 0) return []; + const cols = board[0].length; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (i === 0 || i == rows - 1 || j === 0 || j === cols - 1) { + mark(board, i, j, rows, cols); + } + } + } + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (board[i][j] === "O") { + board[i][j] = "X"; + } else if (board[i][j] === "A") { + board[i][j] = "O"; + } + } + } + + return board; +}; +``` +Python Code: +```python +class Solution: + def solve(self, board: List[List[str]]) -> None: + """ + Do not return anything, modify board in-place instead. + """ + # 如果数组长或宽小于等于2,则不需要替换 + if len(board) <= 2 or len(board[0]) <= 2: + return + + row, col = len(board), len(board[0]) + + def dfs(i, j): + """ + 深度优先算法,如果符合条件,替换为A并进一步测试,否则停止 + """ + if i < 0 or j < 0 or i >= row or j >= col or board[i][j] != 'O': + return + board[i][j] = 'A' + + dfs(i - 1, j) + dfs(i + 1, j) + dfs(i, j - 1) + dfs(i, j + 1) + + # 从外围开始 + for i in range(row): + dfs(i, 0) + dfs(i, col-1) + + for j in range(col): + dfs(0, j) + dfs(row-1, j) + + # 最后完成替换 + for i in range(row): + for j in range(col): + if board[i][j] == 'O': + board[i][j] = 'X' + elif board[i][j] == 'A': + board[i][j] = 'O' +``` + +## 相关题目 + +- [200.number-of-islands](./200.number-of-islands.md) + +> 解题模板是一样的 + + diff --git a/spider/row-markdown/131.palindrome-partitioning.md b/spider/row-markdown/131.palindrome-partitioning.md new file mode 100644 index 0000000..e241a9d --- /dev/null +++ b/spider/row-markdown/131.palindrome-partitioning.md @@ -0,0 +1,120 @@ + +## 题目地址 + +https://leetcode.com/problems/palindrome-partitioning/description/ + +## 题目描述 + +``` +Given a string s, partition s such that every substring of the partition is a palindrome. + +Return all possible palindrome partitioning of s. + +Example: + +Input: "aab" +Output: +[ + ["aa","b"], + ["a","a","b"] +] + +``` + +## 思路 + +这是一道求解所有可能性的题目, 这时候可以考虑使用回溯法。 回溯法解题的模板我们已经在很多题目中用过了, +这里就不多说了。大家可以结合其他几道题目加深一下理解。 + + +## 关键点解析 + +- 回溯法 + +## 代码 + +* 语言支持:JS,Python3 + +```js + + +/* + * @lc app=leetcode id=131 lang=javascript + * + * [131] Palindrome Partitioning + */ + +function isPalindrom(s) { + let left = 0; + let right = s.length - 1; + + while(left < right && s[left] === s[right]) { + left++; + right--; + } + + return left >= right; +} + function backtrack(s, list, tempList, start) { + const sliced = s.slice(start); + + if (isPalindrom(sliced) && (tempList.join("").length === s.length)) list.push([...tempList]); + + for(let i = 0; i < sliced.length; i++) { + const sub = sliced.slice(0, i + 1); + if (isPalindrom(sub)) { + tempList.push(sub); + } else { + continue; + } + backtrack(s, list, tempList, start + i + 1); + tempList.pop(); + } + } +/** + * @param {string} s + * @return {string[][]} + */ +var partition = function(s) { + // "aab" + // ["aa", "b"] + // ["a", "a", "b"] + const list = []; + backtrack(s, list, [], 0); + return list; +}; + + +``` +```python +class Solution: + def partition(self, s: str) -> List[List[str]]: + """回溯法""" + + res = [] + + def helper(s, tmp): + """ + 如果是空字符串,说明已经处理完毕 + 否则逐个字符往前测试,判断是否是回文 + 如果是,则处理剩余字符串,并将已经得到的列表作为参数 + """ + if not s: + res.append(tmp) + for i in range(1, len(s) + 1): + if s[:i] == s[:i][::-1]: + helper(s[i:], tmp + [s[:i]]) + + helper(s, []) + return res +``` + +## 相关题目 +- [39.combination-sum](./39.combination-sum.md) +- [40.combination-sum-ii](./40.combination-sum-ii.md) +- [46.permutations](./46.permutations.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [78.subsets](./78.subsets.md) +- [90.subsets-ii](./90.subsets-ii.md) +- [113.path-sum-ii](./113.path-sum-ii.md) + diff --git a/spider/row-markdown/1310.xor-queries-of-a-subarray.md b/spider/row-markdown/1310.xor-queries-of-a-subarray.md new file mode 100644 index 0000000..cf9292f --- /dev/null +++ b/spider/row-markdown/1310.xor-queries-of-a-subarray.md @@ -0,0 +1,168 @@ +# 题目地址(1310. 子数组异或查询) + +https://leetcode-cn.com/problems/xor-queries-of-a-subarray + +## 题目描述 + +``` +有一个正整数数组 arr,现给你一个对应的查询数组 queries,其中 queries[i] = [Li, Ri]。 + +对于每个查询 i,请你计算从 Li 到 Ri 的 XOR 值(即 arr[Li] xor arr[Li+1] xor ... xor arr[Ri])作为本次查询的结果。 + +并返回一个包含给定查询 queries 所有结果的数组。 + + + +示例 1: + +输入:arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]] +输出:[2,7,14,8] +解释: +数组中元素的二进制表示形式是: +1 = 0001 +3 = 0011 +4 = 0100 +8 = 1000 +查询的 XOR 值为: +[0,1] = 1 xor 3 = 2 +[1,2] = 3 xor 4 = 7 +[0,3] = 1 xor 3 xor 4 xor 8 = 14 +[3,3] = 8 +示例 2: + +输入:arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]] +输出:[8,0,4,4] + + +提示: + +1 <= arr.length <= 3 * 10^4 +1 <= arr[i] <= 10^9 +1 <= queries.length <= 3 * 10^4 +queries[i].length == 2 +0 <= queries[i][0] <= queries[i][1] < arr.length +``` + +## 暴力法 + +### 思路 + +最直观的思路是双层循环即可,果不其然超时了。 + +### 代码 + +```python + +class Solution: + def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]: + res = [] + for (L, R) in queries: + i = L + xor = 0 + while i <= R: + xor ^= arr[i] + i += 1 + res.append(xor) + return res +``` + +## 前缀表达式 + +### 思路 + +比较常见的是前缀和,这个概念其实很容易理解,即一个数组中,第 n 位存储的是数组前 n 个数字的和。 + +对 [1,2,3,4,5,6] 来说,其前缀和可以是 pre=[1,3,6,10,15,21]。我们可以使用公式 pre[𝑖]=pre[𝑖−1]+nums[𝑖]得到每一位前缀和的值,从而通过前缀和进行相应的计算和解题。其实前缀和的概念很简单,但困难的是如何在题目中使用前缀和以及如何使用前缀和的关系来进行解题。 + +这道题是前缀对前缀异或,我们利用了异或的性质 `x ^ y ^ x = y`。 + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gaqll5r048j30fm0bfglz.jpg) + +### 代码 + +代码支持 Python3,Java,C++: + +Python Code: + +```python +# +# @lc app=leetcode.cn id=1218 lang=python3 +# +# [1218] 最长定差子序列 +# + +# @lc code=start + + +class Solution: + def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]: + pre = [0] + res = [] + for i in range(len(arr)): + pre.append(pre[i] ^ arr[i]) + for (L, R) in queries: + res.append(pre[L] ^ pre[R + 1]) + return res + +# @lc code=end +``` + +Java Code: + +```java + public int[] xorQueries(int[] arr, int[][] queries) { + + int[] preXor = new int[arr.length]; + preXor[0] = 0; + + for (int i = 1; i < arr.length; i++) + preXor[i] = preXor[i - 1] ^ arr[i - 1]; + + int[] res = new int[queries.length]; + + for (int i = 0; i < queries.length; i++) { + + int left = queries[i][0], right = queries[i][1]; + res[i] = arr[right] ^ preXor[right] ^ preXor[left]; + } + + return res; + } + +``` + +C++ Code: + +```c++ +class Solution { +public: + vector xorQueries(vector& arr, vector>& queries) { + vectorres; + for(int i=1; itemp :queries){ + if(temp[0]==0){ + res.push_back(arr[temp[1]]); + } + else{ + res.push_back(arr[temp[0]-1]^arr[temp[1]]); + } + } + return res; + } +}; +``` + +## 关键点解析 + +- 异或的性质 x ^ y ^ x = y +- 前缀表达式 + +## 相关题目 + +- [303. 区域和检索 - 数组不可变](https://leetcode-cn.com/problems/range-sum-query-immutable/description/) + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gaql7eqyg6j30u00ft0vx.jpg) + +- [1186.删除一次得到子数组最大和](https://lucifer.ren/blog/2019/12/11/leetcode-1186/) diff --git a/spider/row-markdown/1332.remove-palindromic-subsequences.md b/spider/row-markdown/1332.remove-palindromic-subsequences.md new file mode 100644 index 0000000..fe4b081 --- /dev/null +++ b/spider/row-markdown/1332.remove-palindromic-subsequences.md @@ -0,0 +1,97 @@ +# 题目地址(1332. 删除回文子序列) + +https://leetcode-cn.com/problems/remove-palindromic-subsequences/ + +## 题目描述 + +``` +给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。 + +返回删除给定字符串中所有字符(字符串为空)的最小删除次数。 + +「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。 + +「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。 + +  + +示例 1: + +输入:s = "ababa" +输出:1 +解释:字符串本身就是回文序列,只需要删除一次。 +示例 2: + +输入:s = "abb" +输出:2 +解释:"abb" -> "bb" -> "". +先删除回文子序列 "a",然后再删除 "bb"。 +示例 3: + +输入:s = "baabb" +输出:2 +解释:"baabb" -> "b" -> "". +先删除回文子序列 "baab",然后再删除 "b"。 +示例 4: + +输入:s = "" +输出:0 +  + +提示: + +0 <= s.length <= 1000 +s 仅包含字母 'a'  和 'b' +在真实的面试中遇到过这道题? +``` + +## 思路 + +这又是一道“抖机灵”的题目,类似的题目有[1297.maximum-number-of-occurrences-of-a-substring](https://github.com/azl397985856/leetcode/blob/77db8fa47c7ee0a14b320f7c2d22f7c61ae53c35/problems/1297.maximum-number-of-occurrences-of-a-substring.md) + +由于只有 a 和 b 两个字符。其实最多的消除次数就是 2。因为我们无论如何都可以先消除全部的 1 再消除全部的 2(先消除 2 也一样),这样只需要两次即可完成。 我们再看一下题目给的一次消除的情况,题目给的例子是“ababa”,我们发现其实它本身就是一个回文串,所以才可以一次全部消除。那么思路就有了: + +- 如果 s 是回文,则我们需要一次消除 +- 否则需要两次 +- 一定要注意特殊情况, 对于空字符串,我们需要 0 次 + +## 代码 + +代码支持:Python3 + +Python3 Code: + +```python + +class Solution: + def removePalindromeSub(self, s: str) -> int: + if s == '': + return 0 + def isPalindrome(s): + l = 0 + r = len(s) - 1 + while l < r: + if s[l] != s[r]: + return False + l += 1 + r -= 1 + return True + return 1 if isPalindrome(s) else 2 +``` + +如果你觉得判断回文不是本题重点,也可以简单实现: + +Python3 Code: + +```python +class Solution: + def removePalindromeSub(self, s: str) -> int: + if s == '': + return 0 + return 1 if s == s[::-1] else 2 + +``` + +## 关键点解析 + +- 注意审题目,一定要利用题目条件“只含有 a 和 b 两个字符”否则容易做的很麻烦 diff --git a/spider/row-markdown/1334.find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance.md b/spider/row-markdown/1334.find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance.md new file mode 100644 index 0000000..cb0de61 --- /dev/null +++ b/spider/row-markdown/1334.find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance.md @@ -0,0 +1,118 @@ +# 题目地址(1334. 阈值距离内邻居最少的城市) + +https://leetcode-cn.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/ + +## 题目描述 + +``` +有 n 个城市,按从 0 到 n-1 编号。给你一个边数组 edges,其中 edges[i] = [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边,距离阈值是一个整数 distanceThreshold。 + +返回能通过某些路径到达其他城市数目最少、且路径距离 最大 为 distanceThreshold 的城市。如果有多个这样的城市,则返回编号最大的城市。 + +注意,连接城市 i 和 j 的路径的距离等于沿该路径的所有边的权重之和。 + +  + +示例 1: + +``` + +![image.png](http://ww1.sinaimg.cn/large/e9f490c8ly1gbh9v5ygtsj20qo0k0aap.jpg) + +``` + + + +输入:n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4 +输出:3 +解释:城市分布图如上。 +每个城市阈值距离 distanceThreshold = 4 内的邻居城市分别是: +城市 0 -> [城市 1, 城市 2]  +城市 1 -> [城市 0, 城市 2, 城市 3]  +城市 2 -> [城市 0, 城市 1, 城市 3]  +城市 3 -> [城市 1, 城市 2]  +城市 0 和 3 在阈值距离 4 以内都有 2 个邻居城市,但是我们必须返回城市 3,因为它的编号最大。 +示例 2: + +``` + +![image.png](http://ww1.sinaimg.cn/large/e9f490c8ly1gbh9vg1w43j20qo0k0js8.jpg) + +``` + +输入:n = 5, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]], distanceThreshold = 2 +输出:0 +解释:城市分布图如上。  +每个城市阈值距离 distanceThreshold = 2 内的邻居城市分别是: +城市 0 -> [城市 1]  +城市 1 -> [城市 0, 城市 4]  +城市 2 -> [城市 3, 城市 4]  +城市 3 -> [城市 2, 城市 4] +城市 4 -> [城市 1, 城市 2, 城市 3]  +城市 0 在阈值距离 4 以内只有 1 个邻居城市。 +  + +提示: + +2 <= n <= 100 +1 <= edges.length <= n * (n - 1) / 2 +edges[i].length == 3 +0 <= fromi < toi < n +1 <= weighti, distanceThreshold <= 10^4 +所有 (fromi, toi) 都是不同的。 + + +``` + +## 思路 + +这道题的本质就是: + +1. 在一个无向图中寻找每两个城镇的最小距离,我们使用 Floyd-Warshall 算法(英语:Floyd-Warshall algorithm),中文亦称弗洛伊德算法,是解决任意两点间的最短路径的一种算法。 +2. 筛选最小距离不大于  distanceThreshold 的城镇。 +3. 统计每个城镇,其满足条件的城镇有多少个 +4. 我们找出最少的即可 + +Floyd-Warshall 算法的时间复杂度和空间复杂度都是$O(N^3)$, 而空间复杂度可以优化到$O(N^2)$。Floyd-Warshall 的基本思想是对于每两个点之间的最小距离,要么经过中间节点 k,要么不经过,我们取两者的最小值,这是一种动态规划思想,详细的解法可以参考[Floyd-Warshall 算法(wikipedia)](https://zh.wikipedia.org/wiki/Floyd-Warshall%E7%AE%97%E6%B3%95) + +## 代码 + +代码支持:Python3 + +Python3 Code: + +```python +class Solution: + def findTheCity(self, n: int, edges: List[List[int]], distanceThreshold: int) -> int: + # 构建dist矩阵 + dist = [[float('inf')] * n for _ in range(n)] + for i, j, w in edges: + dist[i][j] = w + dist[j][i] = w + for i in range(n): + dist[i][i] = 0 + for k in range(n): + for i in range(n): + for j in range(n): + dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]) + + # 过滤 + res = 0 + minCnt = float('inf') + for i in range(n): + cnt = 0 + for d in dist[i]: + if d <= distanceThreshold: + cnt += 1 + if cnt <= minCnt: + minCnt = cnt + res = i + return res + + +``` + +## 关键点解析 + +- Floyd-Warshall 算法 +- 你可以将本文给的 Floyd-Warshall 算法当成一种解题模板使用 diff --git a/spider/row-markdown/136.single-number.md b/spider/row-markdown/136.single-number.md new file mode 100644 index 0000000..b309968 --- /dev/null +++ b/spider/row-markdown/136.single-number.md @@ -0,0 +1,147 @@ +## 题目地址 + +https://leetcode.com/problems/single-number/description/ + +## 题目描述 + +``` +Given a non-empty array of integers, every element appears twice except for one. Find that single one. + +Note: + +Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? +``` + +## 思路 + +根据题目描述,由于加上了时间复杂度必须是 O(n),并且空间复杂度为 O(1)的条件,因此不能用排序方法,也不能使用 map 数据结构。 + +我们可以利用二进制异或的性质来完成,将所有数字异或即得到唯一出现的数字。 + +## 关键点 + +1. 异或的性质 + 两个数字异或的结果`a^b`是将 a 和 b 的二进制每一位进行运算,得出的数字。 运算的逻辑是 + 如果同一位的数字相同则为 0,不同则为 1 + +2. 异或的规律 + +- 任何数和本身异或则为`0` + +- 任何数和 0 异或是`本身` + +3. 很多人只是记得异或的性质和规律,但是缺乏对其本质的理解,导致很难想到这种解法(我本人也没想到) + +4. bit 运算 + +## 代码 + +* 语言支持:JS,C++,Python + +JavaScrip Code: +```js +/* + * @lc app=leetcode id=136 lang=javascript + * + * [136] Single Number + * + * https://leetcode.com/problems/single-number/description/ + * + * algorithms + * Easy (59.13%) + * Total Accepted: 429.3K + * Total Submissions: 724.1K + * Testcase Example: '[2,2,1]' + * + * Given a non-empty array of integers, every element appears twice except for + * one. Find that single one. + * + * Note: + * + * Your algorithm should have a linear runtime complexity. Could you implement + * it without using extra memory? + * + * Example 1: + * + * + * Input: [2,2,1] + * Output: 1 + * + * + * Example 2: + * + * + * Input: [4,1,2,1,2] + * Output: 4 + * + * + */ +/** + * @param {number[]} nums + * @return {number} + */ +var singleNumber = function(nums) { + let ret = 0; + for (let index = 0; index < nums.length; index++) { + const element = nums[index]; + ret = ret ^ element; + } + return ret; +}; +``` +C++: +```C++ +class Solution { +public: + int singleNumber(vector& nums) { + auto ret = 0; + for (auto i : nums) ret ^= i; + return ret; + } +}; + +// C++ one-liner +class Solution { +public: + int singleNumber(vector& nums) { + return accumulate(nums.cbegin(), nums.cend(), 0, bit_xor()); + } +}; +``` + +Python Code: + +```python +class Solution: + def singleNumber(self, nums: List[int]) -> int: + single_number = 0 + for num in nums: + single_number ^= num + return single_number +``` + +## 延伸 + +有一个 n 个元素的数组,除了两个数只出现一次外,其余元素都出现两次,让你找出这两个只出现一次的数分别是几,要求时间复杂度为 O(n) 且再开辟的内存空间固定(与 n 无关)。 + +和上面一样,只是这次不是一个数字,而是两个数字。还是按照上面的思路,我们进行一次全员异或操作, +得到的结果就是那两个只出现一次的不同的数字的异或结果。 + +我们刚才讲了异或的规律中有一个`任何数和本身异或则为0`, 因此我们的思路是能不能将这两个不同的数字分成两组 A 和 B。 +分组需要满足两个条件. + +1. 两个独特的的数字分成不同组 + +2. 相同的数字分成相同组 + +这样每一组的数据进行异或即可得到那两个数字。 + +问题的关键点是我们怎么进行分组呢? + +由于异或的性质是,同一位相同则为 0,不同则为 1. 我们将所有数字异或的结果一定不是 0,也就是说至少有一位是 1. + +我们随便取一个, 分组的依据就来了, 就是你取的那一位是 0 分成 1 组,那一位是 1 的分成一组。 +这样肯定能保证`2. 相同的数字分成相同组`, 不同的数字会被分成不同组么。 很明显当然可以, 因此我们选择是 1,也就是 +说`两个独特的的数字`在那一位一定是不同的,因此两个独特元素一定会被分成不同组。 + +Done! diff --git a/spider/row-markdown/1371.find-the-longest-substring-containing-vowels-in-even-counts.en.md b/spider/row-markdown/1371.find-the-longest-substring-containing-vowels-in-even-counts.en.md new file mode 100644 index 0000000..479e3ca --- /dev/null +++ b/spider/row-markdown/1371.find-the-longest-substring-containing-vowels-in-even-counts.en.md @@ -0,0 +1,359 @@ +## Problem + +https://leetcode.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/ + +## Description + +``` +Given the string s, return the size of the longest substring containing each vowel an even number of times. That is, 'a', 'e', 'i', 'o', and 'u' must appear an even number of times. + +Example 1: + +Input: s = "eleetminicoworoep" +Output: 13 +Explanation: The longest substring is "leetminicowor" which contains two each of the vowels: e, i and o and zero of the vowels: a and u. + +Example 2: + +Input: s = "leetcodeisgreat" +Output: 5 +Explanation: The longest substring is "leetc" which contains two e's. + +Example 3: + +Input: s = "bcbcbc" +Output: 6 +Explanation: In this case, the given string "bcbcbc" is the longest because all vowels: a, e, i, o and u appear zero times. + +Constraints: + +1 <= s.length <= 5 x 10^5 +s contains only lowercase English letters. +``` + +## Approach1: Brute Force and Pruning + +### Algorithm + +My first thought on this problem is to try it with the sliding window technique, which is abandoned immediately because we need to expand or narrow the range of the sliding window (a resizable one), which is not an easy job in this particular case for that this problem involves parity, not like the ones asking for "the longest substring with the most vowels". + +Suddenly I'm at a loss, so I decide to try brute force, which is simple and straightforward. + +- Find all the substrings by using two loops. +- Use a variable `max` to record the maximum length of the substring that meets the condition. +- For each substring, count the numbers of vowels. If all numbers are even, update `max`. + +I do a little trick in the implementation. While enumerating all possible substrings, I start with the longest one, in which case an early return can be achieved, that is, the desired result will be returned once it's found, eliminating the necessity to maintain maximum value. We get less code and higher efficiency in this way. + +### Code(`Python3/JavaScript`) + +Python3 Code: +```py +class Solution: + def findTheLongestSubstring(self, s: str) -> int: + for i in range(len(s), 0, -1): + for j in range(len(s) - i + 1): + sub = s[j:j + i] + has_odd_vowel = False + for vowel in ['a', 'e', 'i', 'o', 'u']: + if sub.count(vowel) % 2 != 0: + has_odd_vowel = True + break + if not has_odd_vowel: return i + return 0 +``` + +JavaScript Code: +```js + * @param {string} s + * @return {number} + */ +var findTheLongestSubstring = function (s) { + const vowels = ['a', 'e', 'i', 'o', 'u'] + const hasEvenVowels = s => !vowels.some(v => (s.match(new RegExp(v, 'g'))||[]).length % 2 !== 0) + + for (let subStrLen = s.length; subStrLen >= 0; subStrLen--) { + let remove = s.length - subStrLen + 1 + + for (let start = 0; start < remove; start++) { + let subStr = s.slice(start, start + subStrLen) + if (hasEvenVowels(subStr)) { + return subStrLen + } + } + } +}; +``` + +### Complexity Analysis + +- Time complexity: $O(n^3)$. Considering every substring takes $O(n^2)$ time. For each of the subarray we calculate the numbers of vowels taking $O(n^2)$ time in the worst case, taking a total of $O(n^3)$ time. +- Space complexity: $O(1)$. + +## Approach2: Prefix Sum + Pruning + +### Algorithm + +Notice that in the last approach there is a step for `counting the numbers of vowels for each substring`. If we look closely, we will discover a lot of duplicate computations. Optimization at this part will get us better efficiency. + +For problems involving consecutive numbers, we can consider using prefix sum to get to a better solution. + +By using this strategy we trade space complexity for time complexity, reducing the time complexity to $O(n ^ 2)$, while increasing the space complexity to $O(n)$, which is a worthwhile trade-off in many situations. + +### Code(`Python3/Java/JavaScript`) + +Python3 Code: +```py +class Solution: + i_mapper = { + "a": 0, + "e": 1, + "i": 2, + "o": 3, + "u": 4 + } + def check(self, s, pre, l, r): + for i in range(5): + if s[l] in self.i_mapper and i == self.i_mapper[s[l]]: cnt = 1 + else: cnt = 0 + if (pre[r][i] - pre[l][i] + cnt) % 2 != 0: return False + return True + def findTheLongestSubstring(self, s: str) -> int: + n = len(s) + + pre = [[0] * 5 for _ in range(n)] + + # pre + for i in range(n): + for j in range(5): + if s[i] in self.i_mapper and self.i_mapper[s[i]] == j: + pre[i][j] = pre[i - 1][j] + 1 + else: + pre[i][j] = pre[i - 1][j] + for i in range(n - 1, -1, -1): + for j in range(n - i): + if self.check(s, pre, j, i + j): + return i + 1 + return 0 +``` + +Java Code: +```java +class Solution { + public int findTheLongestSubstring(String s) { + + int len = s.length(); + + if (len == 0) + return 0; + + int[][] preSum = new int[len][5]; + int start = getIndex(s.charAt(0)); + if (start != -1) + preSum[0][start]++; + + // preSum + for (int i = 1; i < len; i++) { + + int idx = getIndex(s.charAt(i)); + + for (int j = 0; j < 5; j++) { + + if (idx == j) + preSum[i][j] = preSum[i - 1][j] + 1; + else + preSum[i][j] = preSum[i - 1][j]; + } + } + + for (int i = len - 1; i >= 0; i--) { + + for (int j = 0; j < len - i; j++) { + if (checkValid(preSum, s, i, i + j)) + return i + 1 + } + } + return 0 + } + + + public boolean checkValid(int[][] preSum, String s, int left, int right) { + + int idx = getIndex(s.charAt(left)); + + for (int i = 0; i < 5; i++) + if (((preSum[right][i] - preSum[left][i] + (idx == i ? 1 : 0)) & 1) == 1) + return false; + + return true; + } + public int getIndex(char ch) { + + if (ch == 'a') + return 0; + else if (ch == 'e') + return 1; + else if (ch == 'i') + return 2; + else if (ch == 'o') + return 3; + else if (ch == 'u') + return 4; + else + return -1; + } +} +``` + +JavaScript Code: +```js +/** + * @param {string} s + * @return {number} + */ +var findTheLongestSubstring = function (s) { + const prefixes = Array(s.length + 1).fill(0).map(el => Array(5).fill(0)) + const vowels = { + a: 0, + e: 1, + i: 2, + o: 3, + u: 4 + } + + for (let i = 1; i < s.length + 1; i++) { + const letter = s[i - 1] + for (let j = 0; j < 5; j++) { + prefixes[i][j] = prefixes[i - 1][j] + } + if (letter in vowels) { + prefixes[i][vowels[letter]] = prefixes[i - 1][vowels[letter]] + 1 + } + } + + const check = (s, prefixes, l, r) => { + for (let i = 0; i < 5; i++) { + const count = s[l] in vowels && vowels[s[l]] === i + if ((prefixes[r + 1][i] - prefixes[l + 1][i] + count) % 2 !== 0) { + return false + } + } + return true + } + + for (let r = s.length - 1; r >= 0; r--) { + for (let l = 0; l < s.length - r; l++) { + if (check(s, prefixes, l, l + r)) { + return r + 1 + } + } + } + + return 0 +}; +``` + +### Complexity Analysis + +- Time complexity: $O(n^2)$. +- Space complexity: $O(n)$. + +## Approach 3: Prefix Sum + State Compression + +### Algorithm + +In approach 2 we reduce the time complexity by trading space (prefix) for time. However, the time complexity of $O(n^2)$ is still a lot. Is there still room for optimization? + +All we care about is parity. We don't need to count the specific number of occurrences of each vowel. Instead, we can use two states `odd or even`. Since we only need to deal with two states, we can consider using bit operation. + +- Use a 5-bit binary to represent the parity of the number of occurrences of each vowel with 0 for even and 1 for odd. +- The 5 bits of the binary represent 'uoiea' respectively. For example, `10110` means the current substring includes even numbers of 'a' and 'o' and odd numbers of 'e', 'i', and 'u'. +- This binary is assigned to `cur` in the code below. + +Why are we using 0 for even numbers and 1 for odd numbers? Keep reading. + +This algorithm involves elementary mathematics knowledge. + +- If two numbers are of the same parity, then the subtraction must be even. +- If two numbers are of different parity, then the subtraction must be odd. + +Now let's look at the question again. `Why are we using 0 for even numbers and 1 for odd numbers?` Because we want to use the XOR bitwise operation, which works as follows. + +- If XOR is performed on the two binaries, each bit will be bit-operated. +-If two bits are the same, we get 0, otherwise, we get 1. + +This is very similar to the above mathematics knowledge. If the parity of two numbers is the same, we get an even number, otherwise, we get an odd number. So it is natural to use 0 for even numbers and 1 for odd numbers. + +### Code(`Python3/JavaScript`) + +Python3 Code: +```py +class Solution: + def findTheLongestSubstring(self, s: str) -> int: + mapper = { + "a": 1, + "e": 2, + "i": 4, + "o": 8, + "u": 16 + } + seen = {0: -1} + res = cur = 0 + + for i in range(len(s)): + if s[i] in mapper: + cur ^= mapper.get(s[i]) + # If all numbers are of the same parity, then the subtraction must be even. + if cur in seen: + res = max(res, i - seen.get(cur)) + else: + seen[cur] = i + return res +``` + +JavaScript Code: +```js +/** + * @param {string} s + * @return {number} + */ +var findTheLongestSubstring = function (s) { + const mapper = { + "a": 1, + "e": 2, + "i": 4, + "o": 8, + "u": 16 + } + + let max = 0, cur = 0 + const seen = { 0: -1 } + for (let i = 0; i < s.length; i++) { + if (s[i] in mapper) { + cur ^= mapper[s[i]] + } + if (cur in seen) { + max = Math.max(max, i - seen[cur]) + } + else { + seen[cur] = i + } + } + + return max +}; +``` + +### Complexity Analysis + +- Time complexity: $O(n)$. +- Space complexity: $O(n)$. + +## Keypoints + +- Prefix Sum +- State Compression + +## Extension + +- [You can do whatever you want while mastering prefix sum](https://lucifer.ren/blog/2020/01/09/1310.xor-queries-of-a-subarray/)(Chinese) diff --git a/spider/row-markdown/1371.find-the-longest-substring-containing-vowels-in-even-counts.md b/spider/row-markdown/1371.find-the-longest-substring-containing-vowels-in-even-counts.md new file mode 100644 index 0000000..72620d5 --- /dev/null +++ b/spider/row-markdown/1371.find-the-longest-substring-containing-vowels-in-even-counts.md @@ -0,0 +1,265 @@ +# 题目地址(1371. 每个元音包含偶数次的最长子字符串) + +https://leetcode-cn.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/ + +## 题目描述 + +``` +给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了偶数次。 + +  + +示例 1: + +输入:s = "eleetminicoworoep" +输出:13 +解释:最长子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 个,以及 0 个 a,u 。 +示例 2: + +输入:s = "leetcodeisgreat" +输出:5 +解释:最长子字符串是 "leetc" ,其中包含 2 个 e 。 +示例 3: + +输入:s = "bcbcbc" +输出:6 +解释:这个示例中,字符串 "bcbcbc" 本身就是最长的,因为所有的元音 a,e,i,o,u 都出现了 0 次。 +  + +提示: + +1 <= s.length <= 5 x 10^5 +s 只包含小写英文字母。 + +``` + +## 暴力法 + 剪枝 + +### 思路 + +首先拿到这道题的时候,我想到第一反应是滑动窗口行不行。 但是很快这个想法就被我否定了,因为滑动窗口(这里是可变滑动窗口)我们需要扩张和收缩窗口大小,而这里不那么容易。因为题目要求的是奇偶性,而不是类似“元音出现最多的子串”等。 + +突然一下子没了思路。那就试试暴力法吧。暴力法的思路比较朴素和直观。 那就是`双层循环找到所有子串,然后对于每一个子串,统计元音个数,如果子串的元音个数都是偶数,则更新答案,最后返回最大的满足条件的子串长度即可`。 + +这里我用了一个小的 trick。枚举所有子串的时候,我是从最长的子串开始枚举的,这样我找到一个满足条件的直接返回就行了(early return),不必维护最大值。`这样不仅减少了代码量,还提高了效率。` + +### 代码 + +代码支持:Python3 + +Python3 Code: + +```python + +class Solution: + def findTheLongestSubstring(self, s: str) -> int: + for i in range(len(s), 0, -1): + for j in range(len(s) - i + 1): + sub = s[j:j + i] + has_odd_vowel = False + for vowel in ['a', 'e', 'i', 'o', 'u']: + if sub.count(vowel) % 2 != 0: + has_odd_vowel = True + break + if not has_odd_vowel: return i + return 0 + +``` + +**复杂度分析** + +- 时间复杂度:双层循环找出所有子串的复杂度是$O(n^2)$,统计元音个数复杂度也是$O(n)$,因此这种算法的时间复杂度为$O(n^3)$。 +- 空间复杂度:$O(1)$ + +## 前缀和 + 剪枝 + +### 思路 + +上面思路中`对于每一个子串,统计元音个数`,我们仔细观察的话,会发现有很多重复的统计。那么优化这部分的内容就可以获得更好的效率。 + +对于这种连续的数字问题,这里我们考虑使用[前缀和](https://oi-wiki.org/basic/prefix-sum/)来优化。 + +经过这种空间换时间的策略之后,我们的时间复杂度会降低到$O(n ^ 2)$,但是相应空间复杂度会上升到$O(n)$,这种取舍在很多情况下是值得的。 + +### 代码 + +代码支持:Python3,Java + +Python3 Code: + +```python +class Solution: + i_mapper = { + "a": 0, + "e": 1, + "i": 2, + "o": 3, + "u": 4 + } + def check(self, s, pre, l, r): + for i in range(5): + if s[l] in self.i_mapper and i == self.i_mapper[s[l]]: cnt = 1 + else: cnt = 0 + if (pre[r][i] - pre[l][i] + cnt) % 2 != 0: return False + return True + def findTheLongestSubstring(self, s: str) -> int: + n = len(s) + + pre = [[0] * 5 for _ in range(n)] + + # pre + for i in range(n): + for j in range(5): + if s[i] in self.i_mapper and self.i_mapper[s[i]] == j: + pre[i][j] = pre[i - 1][j] + 1 + else: + pre[i][j] = pre[i - 1][j] + for i in range(n - 1, -1, -1): + for j in range(n - i): + if self.check(s, pre, j, i + j): + return i + 1 + return 0 +``` + +Java Code: + +```java +class Solution { + public int findTheLongestSubstring(String s) { + + int len = s.length(); + + if (len == 0) + return 0; + + int[][] preSum = new int[len][5]; + int start = getIndex(s.charAt(0)); + if (start != -1) + preSum[0][start]++; + + // preSum + for (int i = 1; i < len; i++) { + + int idx = getIndex(s.charAt(i)); + + for (int j = 0; j < 5; j++) { + + if (idx == j) + preSum[i][j] = preSum[i - 1][j] + 1; + else + preSum[i][j] = preSum[i - 1][j]; + } + } + + for (int i = len - 1; i >= 0; i--) { + + for (int j = 0; j < len - i; j++) { + if (checkValid(preSum, s, i, i + j)) + return i + 1 + } + } + return 0 + } + + + public boolean checkValid(int[][] preSum, String s, int left, int right) { + + int idx = getIndex(s.charAt(left)); + + for (int i = 0; i < 5; i++) + if (((preSum[right][i] - preSum[left][i] + (idx == i ? 1 : 0)) & 1) == 1) + return false; + + return true; + } + public int getIndex(char ch) { + + if (ch == 'a') + return 0; + else if (ch == 'e') + return 1; + else if (ch == 'i') + return 2; + else if (ch == 'o') + return 3; + else if (ch == 'u') + return 4; + else + return -1; + } +} +``` + +**复杂度分析** + +- 时间复杂度:$O(n^2)$。 +- 空间复杂度:$O(n)$ + +## 前缀和 + 状态压缩 + +### 思路 + +前面的前缀和思路,我们通过空间(prefix)换取时间的方式降低了时间复杂度。但是时间复杂度仍然是平方,我们是否可以继续优化呢? + +实际上由于我们只关心奇偶性,并不关心每一个元音字母具体出现的次数。因此我们可以使用`是奇数,是偶数`两个状态来表示,由于只有两个状态,我们考虑使用位运算。 + +我们使用 5 位的二进制来表示以 i 结尾的字符串中包含各个元音的奇偶性,其中 0 表示偶数,1 表示奇数,并且最低位表示 a,然后依次是 e,i,o,u。比如 `10110` 则表示的是包含偶数个 a 和 o,奇数个 e,i,u,我们用变量 `cur` 来表示。 + +为什么用 0 表示偶数?1 表示奇数? + +回答这个问题,你需要继续往下看。 + +其实这个解法还用到了一个性质,这个性质是小学数学知识: + +- 如果两个数字奇偶性相同,那么其相减一定是偶数。 +- 如果两个数字奇偶性不同,那么其相减一定是奇数。 + +看到这里,我们再来看上面抛出的问题`为什么用 0 表示偶数?1 表示奇数?`。因为这里我们打算用异或运算,而异或的性质是: + +如果对两个二进制做异或,会对其每一位进行位运算,如果相同则位 0,否则位 1。这和上面的性质非常相似。上面说`奇偶性相同则位偶数,否则为奇数`。因此很自然地`用 0 表示偶数?1 表示奇数`会更加方便。 + +### 代码 + +代码支持:Python3 + +Python3 Code: + +```python + +class Solution: + def findTheLongestSubstring(self, s: str) -> int: + mapper = { + "a": 1, + "e": 2, + "i": 4, + "o": 8, + "u": 16 + } + seen = {0: -1} + res = cur = 0 + + for i in range(len(s)): + if s[i] in mapper: + cur ^= mapper.get(s[i]) + # 全部奇偶性都相同,相减一定都是偶数 + if cur in seen: + res = max(res, i - seen.get(cur)) + else: + seen[cur] = i + return res + +``` + +**复杂度分析** + +- 时间复杂度:$O(n)$。 +- 空间复杂度:$O(n)$ + +## 关键点解析 + +- 前缀和 +- 状态压缩 + +## 相关题目 + +- [掌握前缀表达式真的可以为所欲为!](https://lucifer.ren/blog/2020/01/09/1310.xor-queries-of-a-subarray/) diff --git a/spider/row-markdown/139.word-break.md b/spider/row-markdown/139.word-break.md new file mode 100644 index 0000000..142b3ba --- /dev/null +++ b/spider/row-markdown/139.word-break.md @@ -0,0 +1,143 @@ + +## 题目地址 + +https://leetcode.com/problems/word-break/description/ + +## 题目描述 + +``` +Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. + +Note: + +The same word in the dictionary may be reused multiple times in the segmentation. +You may assume the dictionary does not contain duplicate words. +Example 1: + +Input: s = "leetcode", wordDict = ["leet", "code"] +Output: true +Explanation: Return true because "leetcode" can be segmented as "leet code". +Example 2: + +Input: s = "applepenapple", wordDict = ["apple", "pen"] +Output: true +Explanation: Return true because "applepenapple" can be segmented as "apple pen apple". + Note that you are allowed to reuse a dictionary word. +Example 3: + +Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] +Output: false + +``` + +## 思路 + +这道题是给定一个字典和一个句子,判断该句子是否可以由字典里面的单词组出来,一个单词可以用多次。 + +暴力的方法是无解的,复杂度极其高。 我们考虑其是否可以拆分为小问题来解决。 +对于问题`(s, wordDict)` 我们是否可以用(s', wordDict) 来解决。 其中s' 是s 的子序列, +当s'变成寻常(长度为0)的时候问题就解决了。 我们状态转移方程变成了这道题的难点。 + +我们可以建立一个数组dp, dp[i]代表 字符串 s.substring(0, i) 能否由字典里面的单词组成, +值得注意的是,这里我们无法建立dp[i] 和 dp[i - 1] 的关系, +我们可以建立的是dp[i - word.length] 和 dp[i] 的关系。 + +我们用图来感受一下: + +![139.word-break-1](../assets/problems/139.word-break-1.png) + + +没有明白也没有关系,我们分步骤解读一下: + +(以下的图左边都代表s,右边都是dict,灰色代表没有处理的字符,绿色代表匹配成功,红色代表匹配失败) + +![139.word-break-2](../assets/problems/139.word-break-2.png) + +![139.word-break-3](../assets/problems/139.word-break-3.png) + +![139.word-break-4](../assets/problems/139.word-break-4.png) + +![139.word-break-5](../assets/problems/139.word-break-5.png) + + +上面分步解释了算法的基本过程,下面我们感性认识下这道题,我把它比喻为 +你正在`往一个老式手电筒🔦中装电池` + +![139.word-break-6](../assets/problems/139.word-break-6.png) + +## 代码 + +```js +/* + * @lc app=leetcode id=139 lang=javascript + * + * [139] Word Break + * + * https://leetcode.com/problems/word-break/description/ + * + * algorithms + * Medium (34.45%) + * Total Accepted: 317.8K + * Total Submissions: 913.9K + * Testcase Example: '"leetcode"\n["leet","code"]' + * + * Given a non-empty string s and a dictionary wordDict containing a list of + * non-empty words, determine if s can be segmented into a space-separated + * sequence of one or more dictionary words. + * + * Note: + * + * + * The same word in the dictionary may be reused multiple times in the + * segmentation. + * You may assume the dictionary does not contain duplicate words. + * + * + * Example 1: + * + * + * Input: s = "leetcode", wordDict = ["leet", "code"] + * Output: true + * Explanation: Return true because "leetcode" can be segmented as "leet + * code". + * + * + * Example 2: + * + * + * Input: s = "applepenapple", wordDict = ["apple", "pen"] + * Output: true + * Explanation: Return true because "applepenapple" can be segmented as "apple + * pen apple". + * Note that you are allowed to reuse a dictionary word. + * + * + * Example 3: + * + * + * Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] + * Output: false + * + * + */ +/** + * @param {string} s + * @param {string[]} wordDict + * @return {boolean} + */ +var wordBreak = function(s, wordDict) { + const dp = Array(s.length + 1); + dp[0] = true; + for (let i = 0; i < s.length + 1; i++) { + for (let word of wordDict) { + if (dp[i - word.length] && word.length <= i) { + if (s.substring(i - word.length, i) === word) { + dp[i] = true; + } + } + } + } + + return dp[s.length] || false; +}; +``` diff --git a/spider/row-markdown/144.binary-tree-preorder-traversal.md b/spider/row-markdown/144.binary-tree-preorder-traversal.md new file mode 100644 index 0000000..12e92fb --- /dev/null +++ b/spider/row-markdown/144.binary-tree-preorder-traversal.md @@ -0,0 +1,156 @@ +## 题目地址 + +https://leetcode.com/problems/binary-tree-preorder-traversal/description/ + +## 题目描述 + +``` +Given a binary tree, return the preorder traversal of its nodes' values. + +Example: + +Input: [1,null,2,3] + 1 + \ + 2 + / + 3 + +Output: [1,2,3] +Follow up: Recursive solution is trivial, could you do it iteratively? + +``` + +## 思路 + +这道题目是前序遍历,这个和之前的`leetcode 94 号问题 - 中序遍历`完全不一回事。 + +前序遍历是`根左右`的顺序,注意是`根`开始,那么就很简单。直接先将根节点入栈,然后 +看有没有右节点,有则入栈,再看有没有左节点,有则入栈。 然后出栈一个元素,重复即可。 + +> 其他树的非递归遍历课没这么简单 + +## 关键点解析 + +- 二叉树的基本操作(遍历) + > 不同的遍历算法差异还是蛮大的 +- 如果非递归的话利用栈来简化操作 + +- 如果数据规模不大的话,建议使用递归 + +- 递归的问题需要注意两点,一个是终止条件,一个如何缩小规模 + +1. 终止条件,自然是当前这个元素是 null(链表也是一样) + +2. 由于二叉树本身就是一个递归结构, 每次处理一个子树其实就是缩小了规模, + 难点在于如何合并结果,这里的合并结果其实就是`mid.concat(left).concat(right)`, + mid 是一个具体的节点,left 和 right`递归求出即可` + +## 代码 + +- 语言支持:JS,C++ + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=144 lang=javascript + * + * [144] Binary Tree Preorder Traversal + * + * https://leetcode.com/problems/binary-tree-preorder-traversal/description/ + * + * algorithms + * Medium (50.36%) + * Total Accepted: 314K + * Total Submissions: 621.2K + * Testcase Example: '[1,null,2,3]' + * + * Given a binary tree, return the preorder traversal of its nodes' values. + * + * Example: + * + * + * Input: [1,null,2,3] + * ⁠ 1 + * ⁠ \ + * ⁠ 2 + * ⁠ / + * ⁠ 3 + * + * Output: [1,2,3] + * + * + * Follow up: Recursive solution is trivial, could you do it iteratively? + * + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +var preorderTraversal = function(root) { + // 1. Recursive solution + + // if (!root) return []; + + // return [root.val].concat(preorderTraversal(root.left)).concat(preorderTraversal(root.right)); + + // 2. iterative solutuon + + if (!root) return []; + const ret = []; + const stack = [root]; + let t = stack.pop(); + + while (t) { + ret.push(t.val); + if (t.right) { + stack.push(t.right); + } + if (t.left) { + stack.push(t.left); + } + t = stack.pop(); + } + + return ret; +}; +``` + +C++ Code: + +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector preorderTraversal(TreeNode* root) { + vector v; + vector s; + while (root != NULL || !s.empty()) { + while (root != NULL) { + v.push_back(root->val); + s.push_back(root); + root = root->left; + } + root = s.back()->right; + s.pop_back(); + } + return v; + } +}; +``` diff --git a/spider/row-markdown/1449.form-largest-integer-with-digits-that-add-up-to-target.md b/spider/row-markdown/1449.form-largest-integer-with-digits-that-add-up-to-target.md new file mode 100644 index 0000000..033a525 --- /dev/null +++ b/spider/row-markdown/1449.form-largest-integer-with-digits-that-add-up-to-target.md @@ -0,0 +1,214 @@ +# 题目地址(1449. 数位成本和为目标值的最大数字) + +https://leetcode-cn.com/problems/form-largest-integer-with-digits-that-add-up-to-target/ + +## 题目描述 + +``` +给你一个整数数组 cost 和一个整数 target 。请你返回满足如下规则可以得到的 最大 整数: + +给当前结果添加一个数位(i + 1)的成本为 cost[i] (cost 数组下标从 0 开始)。 +总成本必须恰好等于 target 。 +添加的数位中没有数字 0 。 +由于答案可能会很大,请你以字符串形式返回。 + +如果按照上述要求无法得到任何整数,请你返回 "0" 。 + +  + +示例 1: + +输入:cost = [4,3,2,5,6,7,2,5,5], target = 9 +输出:"7772" +解释:添加数位 '7' 的成本为 2 ,添加数位 '2' 的成本为 3 。所以 "7772" 的代价为 2*3+ 3*1 = 9 。 "997" 也是满足要求的数字,但 "7772" 是较大的数字。 + 数字 成本 + 1 -> 4 + 2 -> 3 + 3 -> 2 + 4 -> 5 + 5 -> 6 + 6 -> 7 + 7 -> 2 + 8 -> 5 + 9 -> 5 +示例 2: + +输入:cost = [7,6,5,5,5,6,8,7,8], target = 12 +输出:"85" +解释:添加数位 '8' 的成本是 7 ,添加数位 '5' 的成本是 5 。"85" 的成本为 7 + 5 = 12 。 +示例 3: + +输入:cost = [2,4,6,2,4,6,4,4,4], target = 5 +输出:"0" +解释:总成本是 target 的条件下,无法生成任何整数。 +示例 4: + +输入:cost = [6,10,15,40,40,40,40,40,40], target = 47 +输出:"32211" +  + +提示: + +cost.length == 9 +1 <= cost[i] <= 5000 +1 <= target <= 5000 + +``` + +## 思路 + +由于数组可以重复选择,因此这是一个完全背包问题。 + +### 01 背包 + +对于 01 背包问题,我们的套路是: + +```py +for i in 0 to N: + for j in 1 to V + 1: + dp[j] = max(dp[j], dp[j - cost[i]) +``` + +而一般我们为了处理边界问题,我们一般会这么写代码: + +```py +for i in 1 to N + 1: + # 这里是倒序的,原因在于这里是01背包。 + for j in V to 0: + dp[j] = max(dp[j], dp[j - cost[i - 1]) +``` + +其中 dp[j] 表示只能选择前 i 个物品,背包容量为 j 的情况下,能够获得的最大价值。 + +> dp[j] 不是没 i 么? 其实我这里 i 指的是 dp[j]当前所处的循环中的 i 值 + +### 完全背包问题 + +回到问题,我们这是完全背包问题: + +```py +for i in 1 to N + 1: + # 这里不是倒序,原因是我们这里是完全背包问题 + for j in 1 to V + 1: + dp[j] = max(dp[j], dp[j - cost[i - 1]) + +``` + +### 为什么 01 背包需要倒序,而完全背包则不可以 + +实际上,这是一个骚操作,我来详细给你讲一下。 + +其实要回答这个问题,我要先将 01 背包和完全背包退化二维的情况。 + +对于 01 背包: + +```py +for i in 1 to N + 1: + for j in V to 0: + dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - cost[i - 1]) +``` + +注意等号左边是 i,右边是 i - 1,这很好理解,因为 i 只能取一次嘛。 + +那么如果我们不降序遍历会怎么样呢? + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfaqt9hh8hj30uy0giabo.jpg) + +如图橙色部分表示已经遍历的部分,而让我们去用[j - cost[i - 1]] 往前面回溯的时候,实际上回溯的是 dp[i]j - cost[i - 1]],而不是 dp[i - 1]j - cost[i - 1]]。 + +如果是降序就可以了,如图: + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfaqtkc1cmj30u80fcmyo.jpg) + +这个明白的话,我们继续思考为什么完全背包就要不降序了呢? + +我们还是像上面一样写出二维的代码: + +```py +for i in 1 to N + 1: + for j in 1 to V + 1: + dp[i][j] = max(dp[i - 1][j], dp[i][j - cost[i - 1]) + +``` + +由于 i 可以取无数次,那么正序遍历正好可以满足,如上图。 + +### 恰好装满 VS 可以不装满 + +题目有两种可能,一种是要求背包恰好装满,一种是可以不装满(只要不超过容量就行)。而本题是要求`恰好装满`的。而这两种情况仅仅影响我们`dp数组初始化`。 + +- 恰好装满。只需要初始化 dp[0] 为 0, 其他初始化为负数即可。 +- 可以不装满。 只需要全部初始化为 0,即可, + +原因很简单,我多次强调过 dp 数组本质上是记录了一个个自问题。 dp[0]是一个子问题,dp[1]是一个子问题。。。 + +有了上面的知识就不难理解了。 初始化的时候,我们还没有进行任何选择,那么也就是说 dp[0] = 0,因为我们可以通过什么都不选达到最大值 0。而 dp[1],dp[2]...则在当前什么都不选的情况下无法达成,也就是无解,因为为了区分,我们可以用负数来表示,当然你可以用任何可以区分的东西表示,比如 None。 + +### 回到本题 + +而这道题和普通的完全背包不一样,这个是选择一个组成的最大数。由小学数学知识`一个数字的全排列中,按照数字降序排列是最大的`,我这里用了一个骚操作,那就是 cost 从后往前遍历,因为后面表示的数字大。 + +## 代码 + +```py +class Solution: + def largestNumber(self, cost: List[int], target: int) -> str: + dp = [0] + [float('-inf')] * target + for i in range(9, 0, -1): + for j in range(1, target+1): + if j >= cost[i - 1]: + dp[j] = max(dp[j], (dp[j-cost[i - 1]] * 10) + i) + return str(dp[target]) if dp[target] > 0 else '0' + +``` + +**_复杂度分析_** + +- 时间复杂度:$O(target))$ +- 空间复杂度:$O(target)$ + +## 扩展 + +最后贴几个我写过的背包问题,让大家看看历史是多么的相似。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfaqty4tg3j31iq0sotdg.jpg) +([322. 硬币找零(完全背包问题)](https://github.com/azl397985856/leetcode/blob/master/problems/322.coin-change.md)) + +> 这里内外循环和本题正好是反的,我只是为了"秀技"(好玩),实际上在这里对答案并不影响。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfaqu6xzg5j31go0gwq4o.jpg) +([518. 零钱兑换 II](https://github.com/azl397985856/leetcode/blob/master/problems/518.coin-change-2.md)) + +> 这里内外循环和本题正好是反的,但是这里必须这么做,否则结果是不对的,具体可以点进去链接看我那个题解 + +所以这两层循环的位置起的实际作用是什么? 代表的含义有什么不同? + +本质上: + +```py +for i in 1 to N + 1: + for j in V to 0: + ... + +``` + +这种情况选择物品 1 和物品 3(随便举的例子),是一种方式。选择物品 3 个物品 1(注意是有顺序的)是同一种方式。 **原因在于你是固定物品,去扫描容量**。 + +而: + +```py +for j in V to 0: + for i in 1 to N + 1: + ... + +``` + +这种情况选择物品 1 和物品 3(随便举的例子),是一种方式。选择物品 3 个物品 1(注意是有顺序的)也是一种方式。**原因在于你是固定容量,去扫描物品**。 + +**因此总的来说,如果你认为[1,3]和[3,1]是一种,那么就用方法 1 的遍历,否则用方法 2。** + +更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 30K star 啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfaq00p8stj30x20iw7b0.jpg) diff --git a/spider/row-markdown/145.binary-tree-postorder-traversal.md b/spider/row-markdown/145.binary-tree-postorder-traversal.md new file mode 100644 index 0000000..0b20ea2 --- /dev/null +++ b/spider/row-markdown/145.binary-tree-postorder-traversal.md @@ -0,0 +1,135 @@ +## 题目地址 +https://leetcode.com/problems/binary-tree-postorder-traversal/description/ + +## 题目描述 + +``` +Given a binary tree, return the postorder traversal of its nodes' values. + +For example: +Given binary tree {1,#,2,3}, + + 1 + \ + 2 + / + 3 + + +return [3,2,1]. + +Note: Recursive solution is trivial, could you do it iteratively? + +``` + +## 思路 + +相比于前序遍历,后续遍历思维上难度要大些,前序遍历是通过一个stack,首先压入父亲结点,然后弹出父亲结点,并输出它的value,之后压人其右儿子,左儿子即可。 + +然而后序遍历结点的访问顺序是:左儿子 -> 右儿子 -> 自己。那么一个结点需要两种情况下才能够输出: +第一,它已经是叶子结点; +第二,它不是叶子结点,但是它的儿子已经输出过。 + +那么基于此我们只需要记录一下当前输出的结点即可。对于一个新的结点,如果它不是叶子结点,儿子也没有访问,那么就需要将它的右儿子,左儿子压入。 +如果它满足输出条件,则输出它,并记录下当前输出结点。输出在stack为空时结束。 + + +## 关键点解析 + +- 二叉树的基本操作(遍历) +> 不同的遍历算法差异还是蛮大的 +- 如果非递归的话利用栈来简化操作 + +- 如果数据规模不大的话,建议使用递归 + +- 递归的问题需要注意两点,一个是终止条件,一个如何缩小规模 + +1. 终止条件,自然是当前这个元素是null(链表也是一样) + +2. 由于二叉树本身就是一个递归结构, 每次处理一个子树其实就是缩小了规模, +难点在于如何合并结果,这里的合并结果其实就是`left.concat(right).concat(mid)`, +mid是一个具体的节点,left和right`递归求出即可` + + +## 代码 + +```js +/* + * @lc app=leetcode id=145 lang=javascript + * + * [145] Binary Tree Postorder Traversal + * + * https://leetcode.com/problems/binary-tree-postorder-traversal/description/ + * + * algorithms + * Hard (47.06%) + * Total Accepted: 242.6K + * Total Submissions: 512.8K + * Testcase Example: '[1,null,2,3]' + * + * Given a binary tree, return the postorder traversal of its nodes' values. + * + * Example: + * + * + * Input: [1,null,2,3] + * ⁠ 1 + * ⁠ \ + * ⁠ 2 + * ⁠ / + * ⁠ 3 + * + * Output: [3,2,1] + * + * + * Follow up: Recursive solution is trivial, could you do it iteratively? + * + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +var postorderTraversal = function(root) { + // 1. Recursive solution + + // if (!root) return []; + + // return postorderTraversal(root.left).concat(postorderTraversal(root.right)).concat(root.val); + + // 2. iterative solutuon + + if (!root) return []; + const ret = []; + const stack = [root]; + let p = root; // 标识元素,用来判断节点是否应该出栈 + + while (stack.length > 0) { + const top = stack[stack.length - 1]; + if ( + top.left === p || + top.right === p || // 子节点已经遍历过了 + (top.left === null && top.right === null) // 叶子元素 + ) { + p = stack.pop(); + ret.push(p.val); + } else { + if (top.right) { + stack.push(top.right); + } + if (top.left) { + stack.push(top.left); + } + } + } + + return ret; +}; + +``` diff --git a/spider/row-markdown/146.lru-cache.md b/spider/row-markdown/146.lru-cache.md new file mode 100644 index 0000000..0abd272 --- /dev/null +++ b/spider/row-markdown/146.lru-cache.md @@ -0,0 +1,112 @@ +## 题目地址 +https://leetcode.com/problems/lru-cache/description/ + +## 题目描述 + +``` +Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put. + +get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. +put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. + +Follow up: +Could you do both operations in O(1) time complexity? + +Example: + +LRUCache cache = new LRUCache( 2 /* capacity */ ); + +cache.put(1, 1); +cache.put(2, 2); +cache.get(1); // returns 1 +cache.put(3, 3); // evicts key 2 +cache.get(2); // returns -1 (not found) +cache.put(4, 4); // evicts key 1 +cache.get(1); // returns -1 (not found) +cache.get(3); // returns 3 +cache.get(4); // returns 4 + +``` + +## 思路 + +`本题已被收录到我的新书中,敬请期待~` + +由于是保留是最近使用的 N 条数据,这就和队列的特性很符合, 先进入队列的,先出队列。 + +因此思路就是用一个队列来记录目前缓存的所有 key, 每次 push 都进行判断,如果 +超出最大容量限制则进行清除缓存的操作, 具体清除谁就按照刚才说的队列方式进行处理,同时对 key 进行入队操作。 + +get 的时候,如果缓存中有,则调整队列(具体操作为删除指定元素和入队两个操作)。 缓存中没有则返回-1 + +## 关键点解析 + +- 队列简化操作 + +- 队列的操作是这道题的灵魂, 很容易少考虑情况 + +## 代码 + +```js +/** + * @param {number} capacity + */ +var LRUCache = function(capacity) { + this.cache = {}; + this.capacity = capacity; + this.size = 0; + this.queue = []; +}; + +/** + * @param {number} key + * @return {number} + */ +LRUCache.prototype.get = function(key) { + const hit = this.cache[key]; + + if (hit !== undefined) { + this.queue = this.queue.filter(q => q !== key); + this.queue.push(key); + return hit; + } + return -1; +}; + +/** + * @param {number} key + * @param {number} value + * @return {void} + */ +LRUCache.prototype.put = function(key, value) { + const hit = this.cache[key]; + + // update cache + this.cache[key] = value; + + if (!hit) { + // invalid cache and resize size; + if (this.size === this.capacity) { + // invalid cache + const key = this.queue.shift(); + this.cache[key] = undefined; + } else { + this.size = this.size + 1; + } + this.queue.push(key); + } else { + this.queue = this.queue.filter(q => q !== key); + this.queue.push(key); + } +}; + +/** + * Your LRUCache object will be instantiated and called as such: + * var obj = new LRUCache(capacity) + * var param_1 = obj.get(key) + * obj.put(key,value) + */ + +``` + +本题删除的时间复杂度是不符合要求的。 应该采用双向链表在 O(1) 时间找到前驱进行删除。 diff --git a/spider/row-markdown/15.3-sum.md b/spider/row-markdown/15.3-sum.md new file mode 100644 index 0000000..c354bef --- /dev/null +++ b/spider/row-markdown/15.3-sum.md @@ -0,0 +1,125 @@ +## 题目地址 +https://leetcode.com/problems/3sum/description/ + +## 题目描述 +``` +Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. + +Note: + +The solution set must not contain duplicate triplets. + +Example: + +Given array nums = [-1, 0, 1, 2, -1, -4], + +A solution set is: +[ + [-1, 0, 1], + [-1, -1, 2] +] + +``` +## 思路 + +我们采用`分治`的思想. 想要找出三个数相加等于0,我们可以数组依次遍历, +每一项a[i]我们都认为它是最终能够用组成0中的一个数字,那么我们的目标就是找到 +剩下的元素(除a[i])`两个`相加等于-a[i]. + +通过上面的思路,我们的问题转化为了`给定一个数组,找出其中两个相加等于给定值`, +这个问题是比较简单的, 我们只需要对数组进行排序,然后双指针解决即可。 加上我们需要外层遍历依次数组,因此总的时间复杂度应该是O(N^2)。 + +思路如图所示: + +![15.3-sum](../assets/problems/15.3-sum.png) + +> 在这里之所以要排序解决是因为, 我们算法的瓶颈在这里不在于排序,而在于O(N^2),如果我们瓶颈是排序,就可以考虑别的方式了 + + +> 如果找某一个特定元素,一个指针就够了。如果是找两个元素满足一定关系(比如求和等于特定值),需要双指针, +当然前提是数组有序。 +## 关键点解析 + +- 排序之后,用双指针 +- 分治 + +## 代码 +```js + +/* + * @lc app=leetcode id=15 lang=javascript + * + * [15] 3Sum + * + * https://leetcode.com/problems/3sum/description/ + * + * algorithms + * Medium (23.51%) + * Total Accepted: 531.5K + * Total Submissions: 2.2M + * Testcase Example: '[-1,0,1,2,-1,-4]' + * + * Given an array nums of n integers, are there elements a, b, c in nums such + * that a + b + c = 0? Find all unique triplets in the array which gives the + * sum of zero. + * + * Note: + * + * The solution set must not contain duplicate triplets. + * + * Example: + * + * + * Given array nums = [-1, 0, 1, 2, -1, -4], + * + * A solution set is: + * [ + * ⁠ [-1, 0, 1], + * ⁠ [-1, -1, 2] + * ] + * + * + */ +/** + * @param {number[]} nums + * @return {number[][]} + */ +var threeSum = function(nums) { + if (nums.length < 3) return []; + const list = []; + nums.sort((a, b) => a - b); + for (let i = 0; i < nums.length; i++) { + //nums is sorted,so it's impossible to have a sum = 0 + if (nums[i] > 0) break; + // skip duplicated result without set + if (i > 0 && nums[i] === nums[i - 1]) continue; + let left = i + 1; + let right = nums.length - 1; + + // for each index i + // we want to find the triplet [i, left, right] which sum to 0 + while (left < right) { + // since left < right, and left > i, no need to compare i === left and i === right. + if (nums[left] + nums[right] + nums[i] === 0) { + list.push([nums[left], nums[right], nums[i]]); + // skip duplicated result without set + while(nums[left] === nums[left + 1]) { + left++; + } + left++; + // skip duplicated result without set + while(nums[right] === nums[right - 1]) { + right--; + } + right--; + continue; + } else if (nums[left] + nums[right] + nums[i] > 0) { + right--; + } else { + left++; + } + } + } + return list; +}; +``` diff --git a/spider/row-markdown/150.evaluate-reverse-polish-notation.md b/spider/row-markdown/150.evaluate-reverse-polish-notation.md new file mode 100644 index 0000000..8b56c0d --- /dev/null +++ b/spider/row-markdown/150.evaluate-reverse-polish-notation.md @@ -0,0 +1,142 @@ + + +## 题目地址 +https://leetcode.com/problems/evaluate-reverse-polish-notation/description/ + +## 题目描述 + +``` +Evaluate the value of an arithmetic expression in Reverse Polish Notation. + +Valid operators are +, -, *, /. Each operand may be an integer or another expression. + +Note: + +Division between two integers should truncate toward zero. +The given RPN expression is always valid. That means the expression would always evaluate to a result and there won't be any divide by zero operation. +``` +## 思路 +逆波兰表达式又叫做后缀表达式。在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为`中缀表示`。 + +波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法,按此方法,每一运算符都置于其运算对象之后,故称为`后缀表示`。 + +> 逆波兰表达式是一种十分有用的表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)*(c+d)转换为ab+cd+* + + +## 关键点 + +1. 栈的基本用法 + +2. 如果你用的是JS的话,需要注意/ 和 其他很多语言是不一样的 + +3. 如果你用的是JS的话,需要先将字符串转化为数字。否则有很多意想不到的结果 + +4. 操作符的顺序应该是 先出栈的是第二位,后出栈的是第一位。 这在不符合交换律的操作中很重要, 比如减法和除法。 + +## 代码 + +```js +/* + * @lc app=leetcode id=150 lang=javascript + * + * [150] Evaluate Reverse Polish Notation + * + * https://leetcode.com/problems/evaluate-reverse-polish-notation/description/ + * + * algorithms + * Medium (31.43%) + * Total Accepted: 153.3K + * Total Submissions: 485.8K + * Testcase Example: '["2","1","+","3","*"]' + * + * Evaluate the value of an arithmetic expression in Reverse Polish Notation. + * + * Valid operators are +, -, *, /. Each operand may be an integer or another + * expression. + * + * Note: + * + * + * Division between two integers should truncate toward zero. + * The given RPN expression is always valid. That means the expression would + * always evaluate to a result and there won't be any divide by zero + * operation. + * + * + * Example 1: + * + * + * Input: ["2", "1", "+", "3", "*"] + * Output: 9 + * Explanation: ((2 + 1) * 3) = 9 + * + * + * Example 2: + * + * + * Input: ["4", "13", "5", "/", "+"] + * Output: 6 + * Explanation: (4 + (13 / 5)) = 6 + * + * + * Example 3: + * + * + * Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] + * Output: 22 + * Explanation: + * ⁠ ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 + * = ((10 * (6 / (12 * -11))) + 17) + 5 + * = ((10 * (6 / -132)) + 17) + 5 + * = ((10 * 0) + 17) + 5 + * = (0 + 17) + 5 + * = 17 + 5 + * = 22 + * + * + */ +/** + * @param {string[]} tokens + * @return {number} + */ +var evalRPN = function(tokens) { + // 这种算法的前提是 tokens是有效的, + // 当然这由算法来保证 + const stack = []; + + for (let index = 0; index < tokens.length; index++) { + const token = tokens[index]; + // 对于运算数, 我们直接入栈 + if (!Number.isNaN(Number(token))) { + stack.push(token); + } else { + // 遇到操作符,我们直接大胆运算,不用考虑算术优先级 + // 然后将运算结果入栈即可 + + // 当然如果题目进一步扩展,允许使用单目等其他运算符,我们的算法需要做微小的调整 + const a = Number(stack.pop()); + const b = Number(stack.pop()); + if (token === "*") { + stack.push(b * a); + } else if (token === "/") { + stack.push(b / a >> 0); + } else if (token === "+") { + stack.push(b + a); + } else if (token === "-") { + stack.push(b - a); + } + } + } + + return stack.pop(); +}; + +``` + +## 扩展 + +逆波兰表达式中只改变运算符的顺序,并不会改变操作数的相对顺序,这是一个重要的性质。 +另外逆波兰表达式完全不关心操作符的优先级,这在中缀表达式中是做不到的,这很有趣,感兴趣的可以私下查找资料研究下为什么会这样。 + + + diff --git a/spider/row-markdown/152.maximum-product-subarray.md b/spider/row-markdown/152.maximum-product-subarray.md new file mode 100644 index 0000000..3ed9c07 --- /dev/null +++ b/spider/row-markdown/152.maximum-product-subarray.md @@ -0,0 +1,141 @@ +## 题目地址 + +https://leetcode.com/problems/maximum-product-subarray/description/ + +## 题目描述 +``` +给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 + +  + +示例 1: + +输入: [2,3,-2,4] +输出: 6 +解释: 子数组 [2,3] 有最大乘积 6。 +示例 2: + +输入: [-2,0,-1] +输出: 0 +解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 +``` + +## 思路 + +这道题目要我们求解连续的 n 个数中乘积最大的积是多少。这里提到了连续,笔者首先想到的就是滑动窗口,但是这里比较特殊,我们不能仅仅维护一个最大值,因此最小值(比如-20)乘以一个比较小的数(比如-10) +可能就会很大。 因此这种思路并不方便。 + +首先来暴力求解,我们使用两层循环来枚举所有可能项,这种解法的时间复杂度是O(n^2), 代码如下: + +```js +var maxProduct = function(nums) { + let max = nums[0]; + let temp = null; + for (let i = 0; i < nums.length; i++) { + temp = nums[i]; + for (let j = i + 1; j < nums.length; j++) { + temp *= nums[j]; + max = Math.max(temp, max); + } + } + + return max; +}; +``` + + + +前面说了`最小值(比如-20)乘以一个比较小的数(比如-10)可能就会很大` 。因此我们需要同时记录乘积最大值和乘积最小值,然后比较元素和这两个的乘积,去不断更新最大值。当然,我们也可以选择只取当前元素。因此实际上我们的选择有三种,而如何选择就取决于哪个选择带来的价值最大(乘积最大或者最小)。 + +![](https://pic.leetcode-cn.com/7d39989d10d982d44cbd6b6f693cf5171865c0654f7c3754e27ec1afc2c0de5d.jpg) + +这种思路的解法由于只需要遍历一次,其时间复杂度是O(n),代码见下方代码区。 + +## 关键点 + +- 同时记录乘积最大值和乘积最小值 +## 代码 + +代码支持:Python3,JavaScript + + + +Python3 Code: + + +```python + + +class Solution: + def maxProduct(self, nums: List[int]) -> int: + n = len(nums) + max__dp = [1] * (n + 1) + min_dp = [1] * (n + 1) + ans = float('-inf') + + for i in range(1, n + 1): + max__dp[i] = max(max__dp[i - 1] * nums[i - 1], + min_dp[i - 1] * nums[i - 1], nums[i - 1]) + min_dp[i] = min(max__dp[i - 1] * nums[i - 1], + min_dp[i - 1] * nums[i - 1], nums[i - 1]) + ans = max(ans, max__dp[i]) + return ans + ``` + + +**复杂度分析** +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(N)$ + + +当我们知道动态转移方程的时候,其实应该发现了。我们的dp[i] 只和 dp[i - 1]有关,这是一个空间优化的信号,告诉我们`可以借助两个额外变量记录即可`。 + + +Python3 Code: + + +```python + +class Solution: + def maxProduct(self, nums: List[int]) -> int: + n = len(nums) + a = b = 1 + ans = float('-inf') + + for i in range(1, n + 1): + temp = a + a = max(a * nums[i - 1], + b * nums[i - 1], nums[i - 1]) + b = min(temp * nums[i - 1], + b * nums[i - 1], nums[i - 1]) + ans = max(ans, a) + return ans + +``` + +JavaScript Code: + +```js +var maxProduct = function(nums) { + let max = nums[0]; + let min = nums[0]; + let res = nums[0]; + + for (let i = 1; i < nums.length; i++) { + let tmp = min; + min = Math.min(nums[i], Math.min(max * nums[i], min * nums[i])); // 取最小 + max = Math.max(nums[i], Math.max(max * nums[i], tmp * nums[i])); /// 取最大 + res = Math.max(res, max); + } + return res; +}; +``` + + +**复杂度分析** +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(1)$ + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 diff --git a/spider/row-markdown/155.min-stack.md b/spider/row-markdown/155.min-stack.md new file mode 100644 index 0000000..ab07da5 --- /dev/null +++ b/spider/row-markdown/155.min-stack.md @@ -0,0 +1,304 @@ +# 题目地址 + +https://leetcode.com/problems/min-stack/description/ + +# 题目描述 + +``` +Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. + +push(x) -- Push element x onto stack. +pop() -- Removes the element on top of the stack. +top() -- Get the top element. +getMin() -- Retrieve the minimum element in the stack. +Example: +MinStack minStack = new MinStack(); +minStack.push(-2); +minStack.push(0); +minStack.push(-3); +minStack.getMin(); --> Returns -3. +minStack.pop(); +minStack.top(); --> Returns 0. +minStack.getMin(); --> Returns -2. + +``` + +# 差值法 + +## 思路 + +符合直觉的方法是,每次对栈进行修改操作(push和pop)的时候更新最小值。 然后getMin只需要返回我们计算的最小值即可, +top也是直接返回栈顶元素即可。 这种做法每次修改栈都需要更新最小值,因此时间复杂度是O(n). + +![](https://pic.leetcode-cn.com/7beed41b8dc0325445721a36b7db34e1af902441b67996d2eeadcb1f5a5e33d9.jpg) + +是否有更高效的算法呢?答案是有的。 + +我们每次入栈的时候,保存的不再是真正的数字,而是它与当前最小值的差(当前元素没有入栈的时候的最小值)。 +这样我们pop和top的时候拿到栈顶元素再加上**上一个**最小值即可。 +另外我们在push和pop的时候去更新min,这样getMin的时候就简单了,直接返回min。 + +> 注意上面加粗的“上一个”,不是“当前的最小值” + +经过上面的分析,问题的关键转化为“如何求得上一个最小值”,解决这个的关键点在于利用min。 + +pop或者top的时候: + +- 如果栈顶元素小于0,说明栈顶是当前最小的元素,它出栈会对min造成影响,我们需要去更新min。 +上一个最小的是“min - 栈顶元素”,我们需要将上一个最小值更新为当前的最小值 + + > 因为栈顶元素入栈的时候的通过 `栈顶元素 = 真实值 - 上一个最小的元素` 得到的, + 而真实值 = min, 因此可以得出`上一个最小的元素 = 真实值 -栈顶元素` + +- 如果栈顶元素大于0,说明它对最小值`没有影响`,上一个最小值就是上上个最小值。 + +![](https://pic.leetcode-cn.com/7da0473d92d70bb47ce7b62303c062e5f517b09d1bf501c4ad341b65415d5c43.jpg) +![](https://pic.leetcode-cn.com/aefec54238c942c484837ea6c724304fb179d3d64f110481d955d9eea65c4fc5.jpg) + +## 关键点 + +- 最小栈存储的不应该是真实值,而是真实值和min的差值 +- top的时候涉及到对数据的还原,这里千万注意是**上一个**最小值 + +## 代码 + +* 语言支持:JS,Python + +Javascript Code: + +```js +/* + * @lc app=leetcode id=155 lang=javascript + * + * [155] Min Stack + */ +/** + * initialize your data structure here. + */ +var MinStack = function() { + this.stack = []; + this.minV = Number.MAX_VALUE; +}; + +/** + * @param {number} x + * @return {void} + */ +MinStack.prototype.push = function(x) { + // update 'min' + const minV = this.minV; + if (x < this.minV) { + this.minV = x; + } + return this.stack.push(x - minV); +}; + +/** + * @return {void} + */ +MinStack.prototype.pop = function() { + const item = this.stack.pop(); + const minV = this.minV; + + if (item < 0) { + this.minV = minV - item; + return minV; + } + return item + minV; +}; + +/** + * @return {number} + */ +MinStack.prototype.top = function() { + const item = this.stack[this.stack.length - 1]; + const minV = this.minV; + + if (item < 0) { + return minV; + } + return item + minV; +}; + +/** + * @return {number} + */ +MinStack.prototype.min = function() { + return this.minV; +}; + +/** + * Your MinStack object will be instantiated and called as such: + * var obj = new MinStack() + * obj.push(x) + * obj.pop() + * var param_3 = obj.top() + * var param_4 = obj.min() + */ +``` + +Python Code: + +```python +class MinStack: + + def __init__(self): + """ + initialize your data structure here. + """ + self.minV = float('inf') + self.stack = [] + + def push(self, x: int) -> None: + self.stack.append(x - self.minV) + if x < self.minV: + self.minV = x + + def pop(self) -> None: + if not self.stack: + return + tmp = self.stack.pop() + if tmp < 0: + self.minV -= tmp + + def top(self) -> int: + if not self.stack: + return + tmp = self.stack[-1] + if tmp < 0: + return self.minV + else: + return self.minV + tmp + + def min(self) -> int: + return self.minV + + + +# Your MinStack object will be instantiated and called as such: +# obj = MinStack() +# obj.push(x) +# obj.pop() +# param_3 = obj.top() +# param_4 = obj.min() +``` + +**复杂度分析** +- 时间复杂度:O(1) +- 空间复杂度:O(1) + + +# 两个栈 + +## 思路 + +我们使用两个栈: + +- 一个栈存放全部的元素,push,pop都是正常操作这个正常栈。 +- 另一个存放最小栈。 每次push,如果比最小栈的栈顶还小,我们就push进最小栈,否则不操作 +- 每次pop的时候,我们都判断其是否和最小栈栈顶元素相同,如果相同,那么我们pop掉最小栈的栈顶元素即可 + +## 关键点 + +- 往minstack中 push的判断条件。 应该是stack为空或者x小于等于minstack栈顶元素 + + +## 代码 + +JavaScript: + +```js +/** + * initialize your data structure here. + */ +var MinStack = function() { + this.stack = [] + this.minStack = [] +}; + +/** + * @param {number} x + * @return {void} + */ +MinStack.prototype.push = function(x) { + this.stack.push(x) + if (this.minStack.length == 0 || x <= this.minStack[this.minStack.length - 1]) { + this.minStack.push(x) + } +}; + +/** + * @return {void} + */ +MinStack.prototype.pop = function() { + const x = this.stack.pop() + if (x !== void 0 && x === this.minStack[this.minStack.length - 1]) { + this.minStack.pop() + } +}; + +/** + * @return {number} + */ +MinStack.prototype.top = function() { + return this.stack[this.stack.length - 1] +}; + +/** + * @return {number} + */ +MinStack.prototype.min = function() { + return this.minStack[this.minStack.length - 1] +}; + +/** + * Your MinStack object will be instantiated and called as such: + * var obj = new MinStack() + * obj.push(x) + * obj.pop() + * var param_3 = obj.top() + * var param_4 = obj.min() + */ +``` + + +Python3: + +```python +class MinStack: + + def __init__(self): + """ + initialize your data structure here. + """ + self.stack = [] + self.minstack = [] + + def push(self, x: int) -> None: + self.stack.append(x) + if not self.minstack or x <= self.minstack[-1]: + self.minstack.append(x) + + def pop(self) -> None: + tmp = self.stack.pop() + if tmp == self.minstack[-1]: + self.minstack.pop() + + def top(self) -> int: + return self.stack[-1] + + def min(self) -> int: + return self.minstack[-1] + + +# Your MinStack object will be instantiated and called as such: +# obj = MinStack() +# obj.push(x) +# obj.pop() +# param_3 = obj.top() +# param_4 = obj.min() +``` + +**复杂度分析** +- 时间复杂度:O(1) +- 空间复杂度:O(N) diff --git a/spider/row-markdown/167.two-sum-ii-input-array-is-sorted.md b/spider/row-markdown/167.two-sum-ii-input-array-is-sorted.md new file mode 100644 index 0000000..9453655 --- /dev/null +++ b/spider/row-markdown/167.two-sum-ii-input-array-is-sorted.md @@ -0,0 +1,125 @@ + +## 题目地址 +https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/description/ + +## 题目描述 + +这是leetcode头号题目`two sum`的第二个版本,难度简单。 + +``` +Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. + +The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. + +Note: + +Your returned answers (both index1 and index2) are not zero-based. +You may assume that each input would have exactly one solution and you may not use the same element twice. +Example: + +Input: numbers = [2,7,11,15], target = 9 +Output: [1,2] +Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2. + +``` + +## 思路 + +由于题目没有对空间复杂度有求,用一个hashmap 存储已经访问过的数字即可。 + +假如题目空间复杂度有要求,由于数组是有序的,只需要双指针即可。一个left指针,一个right指针, +如果left + right 值 大于target 则 right左移动, 否则left右移,代码见下方python code。 + +> 如果数组无序,需要先排序(从这里也可以看出排序是多么重要的操作) + + +## 关键点解析 + +无 + + +## 代码 + +* 语言支持:JS,Python + +Javascript Code: + +```js +/* + * @lc app=leetcode id=167 lang=javascript + * + * [167] Two Sum II - Input array is sorted + * + * https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/description/ + * + * algorithms + * Easy (49.46%) + * Total Accepted: 221.8K + * Total Submissions: 447K + * Testcase Example: '[2,7,11,15]\n9' + * + * Given an array of integers that is already sorted in ascending order, find + * two numbers such that they add up to a specific target number. + * + * The function twoSum should return indices of the two numbers such that they + * add up to the target, where index1 must be less than index2. + * + * Note: + * + * + * Your returned answers (both index1 and index2) are not zero-based. + * You may assume that each input would have exactly one solution and you may + * not use the same element twice. + * + * + * Example: + * + * + * Input: numbers = [2,7,11,15], target = 9 + * Output: [1,2] + * Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2. + * + */ +/** + * @param {number[]} numbers + * @param {number} target + * @return {number[]} + */ +var twoSum = function(numbers, target) { + const visited = {} // 记录出现的数字, 空间复杂度N + + for (let index = 0; index < numbers.length; index++) { + const element = numbers[index]; + if (visited[target - element] !== void 0) { + return [visited[target - element], index + 1] + } + visited[element] = index + 1; + } + return []; +}; +``` + +Python Code: + +```python +class Solution: + def twoSum(self, numbers: List[int], target: int) -> List[int]: + visited = {} + for index, number in enumerate(numbers): + if target - number in visited: + return [visited[target-number], index+1] + else: + visited[number] = index + 1 + +# 双指针思路实现 +class Solution: + def twoSum(self, numbers: List[int], target: int) -> List[int]: + left, right = 0, len(numbers) - 1 + while left < right: + if numbers[left] + numbers[right] < target: + left += 1 + if numbers[left] + numbers[right] > target: + right -= 1 + if numbers[left] + numbers[right] == target: + return [left+1, right+1] +``` diff --git a/spider/row-markdown/169.majority-element.md b/spider/row-markdown/169.majority-element.md new file mode 100644 index 0000000..e96aa91 --- /dev/null +++ b/spider/row-markdown/169.majority-element.md @@ -0,0 +1,84 @@ + +## 题目地址 +https://leetcode.com/problems/majority-element/description/ + +## 题目描述 + +``` +Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times. + +You may assume that the array is non-empty and the majority element always exist in the array. + +Example 1: + +Input: [3,2,3] +Output: 3 +Example 2: + +Input: [2,2,1,1,1,2,2] +Output: 2 + +``` + +## 思路 + +符合直觉的做法是利用额外的空间去记录每个元素出现的次数,并用一个单独的变量记录当前出现次数最多的元素。 + +但是这种做法空间复杂度较高,有没有可能进行优化呢? 答案就是用"投票算法"。 + +投票算法的原理是通过不断消除不同元素直到没有不同元素,剩下的元素就是我们要找的元素。 + +![](https://tva1.sinaimg.cn/large/0082zybply1gbv38hcpf2j30mz0cjjt4.jpg) + +## 关键点解析 + +- 投票算法 + + +## 代码 + +* 语言支持:JS,Python + +Javascript Code: + +```js +var majorityElement = function(nums) { + let count = 1; + let majority = nums[0]; + for(let i = 1; i < nums.length; i++) { + if (count === 0) { + majority = nums[i]; + } + if (nums[i] === majority) { + count ++; + } else { + count --; + } + } + return majority; +}; +``` + +Python Code: + +```python +class Solution: + def majorityElement(self, nums: List[int]) -> int: + count, majority = 1, nums[0] + for num in nums[1:]: + if count == 0: + majority = num + if num == majority: + count += 1 + else: + count -= 1 + return majority +``` + +**复杂度分析** +- 时间复杂度:$O(N)$,其中N为数组长度 +- 空间复杂度:$O(1)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/17.Letter-Combinations-of-a-Phone-Number.md b/spider/row-markdown/17.Letter-Combinations-of-a-Phone-Number.md new file mode 100644 index 0000000..3845eb7 --- /dev/null +++ b/spider/row-markdown/17.Letter-Combinations-of-a-Phone-Number.md @@ -0,0 +1,77 @@ +## 题目地址 +https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number + +## 题目描述 +``` +给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 + +给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 + +示例: + +输入:"23" +输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. + +说明: +尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。 + +``` + +## 思路 +使用回溯法进行求解,回溯是一种通过穷举所有可能情况来找到所有解的算法。如果一个候选解最后被发现并不是可行解,回溯算法会舍弃它,并在前面的一些步骤做出一些修改,并重新尝试找到可行解。究其本质,其实就是枚举。 + +如果没有更多的数字需要被输入,说明当前的组合已经产生。 + +如果还有数字需要被输入: +- 遍历下一个数字所对应的所有映射的字母 +- 将当前的字母添加到组合最后,也就是 str + tmp[r] + +## 关键点 +利用回溯思想解题,在for循环中调用递归。 + +## 代码 +* 语言支持:JS + +```js +/** + * @param {string} digits + * @return {string[]} + */ +const letterCombinations = function (digits) { + if (!digits) { + return []; + } + const len = digits.length; + const map = new Map(); + map.set('2', 'abc'); + map.set('3', 'def'); + map.set('4', 'ghi'); + map.set('5', 'jkl'); + map.set('6', 'mno'); + map.set('7', 'pqrs'); + map.set('8', 'tuv'); + map.set('9', 'wxyz'); + const result = []; + + function generate(i, str) { + if (i == len) { + result.push(str); + return; + } + const tmp = map.get(digits[i]); + for (let r = 0; r < tmp.length; r++) { + generate(i + 1, str + tmp[r]); + } + } + generate(0, ''); + return result; +}; +``` + +***复杂度分析*** + +N + M 是输入数字的总数 + +- 时间复杂度:O(3^N * 4^M) +- 空间复杂度:O(3^N * 4^M) + diff --git a/spider/row-markdown/172.factorial-trailing-zeroes.md b/spider/row-markdown/172.factorial-trailing-zeroes.md new file mode 100644 index 0000000..59b25d8 --- /dev/null +++ b/spider/row-markdown/172.factorial-trailing-zeroes.md @@ -0,0 +1,96 @@ + +## 题目地址 +https://leetcode.com/problems/factorial-trailing-zeroes/description/ + +## 题目描述 + +``` +Given an integer n, return the number of trailing zeroes in n!. + +Example 1: + +Input: 3 +Output: 0 +Explanation: 3! = 6, no trailing zero. +Example 2: + +Input: 5 +Output: 1 +Explanation: 5! = 120, one trailing zero. +Note: Your solution should be in logarithmic time complexity. + +``` + +## 思路 + +我们需要求解这n个数字相乘的结果末尾有多少个0,由于题目要求log的复杂度,因此暴力求解是不行的。 + +通过观察,我们发现如果想要结果末尾是0,必须是分解质因数之后,2 和 5 相乘才行,同时因数分解之后发现5的个数远小于2, +因此我们只需要求解这n数字分解质因数之后一共有多少个5即可. + +![172.factorial-trailing-zeroes-2](../assets/problems/172.factorial-trailing-zeroes-2.png) + +如图如果n为30,那么结果应该是图中红色5的个数,即7。 + +![172.factorial-trailing-zeroes-1](../assets/problems/172.factorial-trailing-zeroes-1.png) + +我们的结果并不是直接f(n) = n / 5, 比如n为30, 25中是有两个5的。 +类似,n为150,会有7个这样的数字,通过观察我们发现规律`f(n) = n/5 + n/5^2 + n/5^3 + n/5^4 + n/5^5+..` + +![172.factorial-trailing-zeroes-3](../assets/problems/172.factorial-trailing-zeroes-3.png) + +如果可以发现上面的规律,用递归还是循环实现这个算式就看你的了。 +## 关键点解析 + +- 数论 + +## 代码 + +* 语言支持:JS,Python + +Javascript Code: + +```js +/* + * @lc app=leetcode id=172 lang=javascript + * + * [172] Factorial Trailing Zeroes + */ +/** + * @param {number} n + * @return {number} + */ +var trailingZeroes = function(n) { + // tag: 数论 + + // if (n === 0) return n; + + // 递归: f(n) = n / 5 + f(n / 5) + // return Math.floor(n / 5) + trailingZeroes(Math.floor(n / 5)); + let count = 0; + while (n >= 5) { + count += Math.floor(n / 5); + n = Math.floor(n / 5); + } + return count; +}; +``` + +Python Code: + +```python +class Solution: + def trailingZeroes(self, n: int) -> int: + count = 0 + while n >= 5: + n = n // 5 + count += n + return count + + +# 递归 +class Solution: + def trailingZeroes(self, n: int) -> int: + if n == 0: return 0 + return n // 5 + self.trailingZeroes(n // 5) +``` diff --git a/spider/row-markdown/19.removeNthNodeFromEndofList.md b/spider/row-markdown/19.removeNthNodeFromEndofList.md new file mode 100644 index 0000000..26d7aa0 --- /dev/null +++ b/spider/row-markdown/19.removeNthNodeFromEndofList.md @@ -0,0 +1,168 @@ +## 题目地址 +https://leetcode.com/problems/remove-nth-node-from-end-of-list/description + +## 题目描述 +Given a linked list, remove the n-th node from the end of list and return its head. + +Example: + +Given linked list: 1->2->3->4->5, and n = 2. + +After removing the second node from the end, the linked list becomes 1->2->3->5. +Note: + +Given n will always be valid. + +Follow up: + +Could you do this in one pass? + +## 思路 + +双指针,指针A先移动n次, 指针B再开始移动。当A到达null的时候, 指针b的位置正好是倒数n + +我们可以设想假设设定了双指针p和q的话,当q指向末尾的NULL,p与q之间相隔的元素个数为n时,那么删除掉p的下一个指针就完成了要求。 + +设置虚拟节点dummyHead指向head + +设定双指针p和q,初始都指向虚拟节点dummyHead + +移动q,直到p与q之间相隔的元素个数为n + +同时移动p与q,直到q指向的为NULL + +将p的下一个节点指向下下个节点 + + + +![19.removeNthNodeFromEndOfList](../assets/19.removeNthNodeFromEndOfList.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) + +## 关键点解析 + +1. 链表这种数据结构的特点和使用 + +2. 使用双指针 + +3. 使用一个dummyHead简化操作 + +## 代码 + +Support: JS, Java + +- Javascript Implementation + +```js +/* + * @lc app=leetcode id=19 lang=javascript + * + * [19] Remove Nth Node From End of List + * + * https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/ + * + * algorithms + * Medium (34.03%) + * Total Accepted: 360.1K + * Total Submissions: 1.1M + * Testcase Example: '[1,2,3,4,5]\n2' + * + * Given a linked list, remove the n-th node from the end of list and return + * its head. + * + * Example: + * + * + * Given linked list: 1->2->3->4->5, and n = 2. + * + * After removing the second node from the end, the linked list becomes + * 1->2->3->5. + * + * + * Note: + * + * Given n will always be valid. + * + * Follow up: + * + * Could you do this in one pass? + * + */ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} n + * @return {ListNode} + */ +var removeNthFromEnd = function(head, n) { + let i = -1; + const noop = { + next: null + }; + + const dummyHead = new ListNode(); // 增加一个dummyHead 简化操作 + dummyHead.next = head; + + let currentP1 = dummyHead; + let currentP2 = dummyHead; + + + while (currentP1) { + + if (i === n) { + currentP2 = currentP2.next; + } + + if (i !== n) { + i++; + } + + currentP1 = currentP1.next; + } + + currentP2.next = ((currentP2 || noop).next || noop).next; + + return dummyHead.next; +}; + +``` + +- Java Code + +```java +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +class Solution { + public ListNode removeNthFromEnd(ListNode head, int n) { + TreeNode dummy = new TreeNode(0); + dummy.next = head; + TreeNode first = dummy; + TreeNode second = dummy; + + if (int i=0; i<=n; i++) { + first = first.next; + } + + while (first != null) { + first = first.next; + second = second.next; + } + + second.next = second.next.next; + + return dummy.next; + } +} +``` \ No newline at end of file diff --git a/spider/row-markdown/190.reverse-bits.md b/spider/row-markdown/190.reverse-bits.md new file mode 100644 index 0000000..768ff8c --- /dev/null +++ b/spider/row-markdown/190.reverse-bits.md @@ -0,0 +1,188 @@ +## 题目地址 +https://leetcode.com/problems/reverse-bits/description/ + +## 题目描述 + +``` +Reverse bits of a given 32 bits unsigned integer. + + + +Example 1: + +Input: 00000010100101000001111010011100 +Output: 00111001011110000010100101000000 +Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000. +Example 2: + +Input: 11111111111111111111111111111101 +Output: 10111111111111111111111111111111 +Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10101111110010110010011101101001. + + +Note: + +Note that in some languages such as Java, there is no unsigned integer type. In this case, both input and output will be given as signed integer type and should not affect your implementation, as the internal binary representation of the integer is the same whether it is signed or unsigned. +In Java, the compiler represents the signed integers using 2's complement notation. Therefore, in Example 2 above the input represents the signed integer -3 and the output represents the signed integer -1073741825. + +``` + +## 思路 + +这道题是给定一个32位的无符号整型,让你按位翻转, 第一位变成最后一位, 第二位变成倒数第二位。。。 + +那么思路就是`双指针` + +> 这个指针可以加引号 + +- n从高位开始逐步左, res从低位(0)开始逐步右移 +- 逐步判断,如果该位是1,就res + 1 , 如果是该位是0, 就res + 0 +- 32位全部遍历完,则遍历结束 + + +## 关键点解析 + +1. 可以用任何数字和1进行位运算的结果都取决于该数字最后一位的特性简化操作和提高性能 + +eg : + +- n & 1 === 1, 说明n的最后一位是1 +- n & 1 === 0, 说明n的最后一位是0 + +2. 对于JS,ES规范在之前很多版本都是没有无符号整形的, 转化为无符号,可以用一个trick`n >>> 0 ` + +3. 双"指针" 模型 + +4. bit 运算 + + +## 代码 + +* 语言支持:JS,C++,Python + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=190 lang=javascript + * + * [190] Reverse Bits + * + * https://leetcode.com/problems/reverse-bits/description/ + * + * algorithms + * Easy (30.30%) + * Total Accepted: 173.7K + * Total Submissions: 568.2K + * Testcase Example: '00000010100101000001111010011100' + * + * Reverse bits of a given 32 bits unsigned integer. + * + * + * + * Example 1: + * + * + * Input: 00000010100101000001111010011100 + * Output: 00111001011110000010100101000000 + * Explanation: The input binary string 00000010100101000001111010011100 + * represents the unsigned integer 43261596, so return 964176192 which its + * binary representation is 00111001011110000010100101000000. + * + * + * Example 2: + * + * + * Input: 11111111111111111111111111111101 + * Output: 10111111111111111111111111111111 + * Explanation: The input binary string 11111111111111111111111111111101 + * represents the unsigned integer 4294967293, so return 3221225471 which its + * binary representation is 10101111110010110010011101101001. + * + * + * + * Note: + * + * + * Note that in some languages such as Java, there is no unsigned integer type. + * In this case, both input and output will be given as signed integer type and + * should not affect your implementation, as the internal binary representation + * of the integer is the same whether it is signed or unsigned. + * In Java, the compiler represents the signed integers using 2's complement + * notation. Therefore, in Example 2 above the input represents the signed + * integer -3 and the output represents the signed integer -1073741825. + * + * + * + * + * Follow up: + * + * If this function is called many times, how would you optimize it? + * + */ +/** + * @param {number} n - a positive integer + * @return {number} - a positive integer + */ +var reverseBits = function(n) { + let res = 0; + for (let i = 0; i < 32; i++) { + res = (res << 1) + (n & 1); + n = n >>> 1; + } + + return res >>> 0; +}; +``` + +C++ Code: + +```C++ +class Solution { +public: + uint32_t reverseBits(uint32_t n) { + auto ret = 0; + for (auto i = 0; i < 32; ++i) { + ret = (ret << 1) + (n & 1); + n >>= 1; + } + return ret; + } +}; +``` + +Python Code: + +```python +class Solution: + # @param n, an integer + # @return an integer + def reverseBits(self, n): + result = 0 + for i in range(32): + result = (result << 1) + (n & 1) + n >>= 1 + return result +``` + +## 拓展 +不使用迭代也可以完成相同的操作: +1. 两两相邻的1位对调 +2. 两两相邻的2位对调 +3. 两两相邻的4位对调 +4. 两两相邻的8位对调 +5. 两两相邻的16位对调 + +C++代码如下: +```C++ +class Solution { +public: + uint32_t reverseBits(uint32_t n) { + auto ret = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1); + ret = ((ret & 0xcccccccc) >> 2) | ((ret & 0x33333333) << 2); + ret = ((ret & 0xf0f0f0f0) >> 4) | ((ret & 0x0f0f0f0f) << 4); + ret = ((ret & 0xff00ff00) >> 8) | ((ret & 0x00ff00ff) << 8); + return ((ret & 0xffff0000) >> 16) | ((ret & 0x0000ffff) << 16); + } +}; +``` diff --git a/spider/row-markdown/191.number-of-1-bits.md b/spider/row-markdown/191.number-of-1-bits.md new file mode 100644 index 0000000..b4f8bc3 --- /dev/null +++ b/spider/row-markdown/191.number-of-1-bits.md @@ -0,0 +1,141 @@ +## 题目地址 +https://leetcode.com/problems/number-of-1-bits/description/ + +## 题目描述 + +``` +Write a function that takes an unsigned integer and return the number of '1' bits it has (also known as the Hamming weight). + + + +Example 1: + +Input: 00000000000000000000000000001011 +Output: 3 +Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits. +Example 2: + +Input: 00000000000000000000000010000000 +Output: 1 +Explanation: The input binary string 00000000000000000000000010000000 has a total of one '1' bit. +Example 3: + +Input: 11111111111111111111111111111101 +Output: 31 +Explanation: The input binary string 11111111111111111111111111111101 has a total of thirty one '1' bits. + + +Note: + +Note that in some languages such as Java, there is no unsigned integer type. In this case, the input will be given as signed integer type and should not affect your implementation, as the internal binary representation of the integer is the same whether it is signed or unsigned. +In Java, the compiler represents the signed integers using 2's complement notation. Therefore, in Example 3 above the input represents the signed integer -3. + +``` + +## 思路 + +这个题目的大意是: 给定一个无符号的整数, 返回其用二进制表式的时候的1的个数。 + +这里用一个trick, 可以轻松求出。 就是`n & (n - 1)` 可以`消除` n 最后的一个1的原理。 + +> 为什么能消除最后一个1, 其实也比较简单,大家自己想一下 + +这样我们可以不断进行`n = n & (n - 1)`直到n === 0 , 说明没有一个1了。 +这个时候`我们消除了多少1变成一个1都没有了, 就说明n有多少个1了`。 + +## 关键点解析 + +1. `n & (n - 1)` 可以`消除` n 最后的一个1的原理 简化操作 + +2. bit 运算 + + +## 代码 + +语言支持:JS, C++,Python + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=191 lang=javascript + * + */ +/** + * @param {number} n - a positive integer + * @return {number} + */ +var hammingWeight = function(n) { + let count = 0; + while (n !== 0) { + n = n & (n - 1); + count++; + } + + return count; +}; + +``` + +C++ code: + +```c++ +class Solution { +public: + int hammingWeight(uint32_t v) { + auto count = 0; + while (v != 0) { + v &= (v - 1); + ++count; + } + return count; + } +}; +``` + +Python Code: + +```python +class Solution(object): + def hammingWeight(self, n): + """ + :type n: int + :rtype: int + """ + count = 0 + while n: + n &= n - 1 + count += 1 + return count +``` + +## 扩展 +可以使用位操作来达到目的。例如8位的整数21: + +![number-of-1-bits](../assets/problems/191.number-of-1-bits.png) + +C++ Code: +```c++ +const uint32_t ODD_BIT_MASK = 0xAAAAAAAA; +const uint32_t EVEN_BIT_MASK = 0x55555555; +const uint32_t ODD_2BIT_MASK = 0xCCCCCCCC; +const uint32_t EVEN_2BIT_MASK = 0x33333333; +const uint32_t ODD_4BIT_MASK = 0xF0F0F0F0; +const uint32_t EVEN_4BIT_MASK = 0x0F0F0F0F; +const uint32_t ODD_8BIT_MASK = 0xFF00FF00; +const uint32_t EVEN_8BIT_MASK = 0x00FF00FF; +const uint32_t ODD_16BIT_MASK = 0xFFFF0000; +const uint32_t EVEN_16BIT_MASK = 0x0000FFFF; + +class Solution { +public: + + int hammingWeight(uint32_t v) { + v = (v & EVEN_BIT_MASK) + ((v & ODD_BIT_MASK) >> 1); + v = (v & EVEN_2BIT_MASK) + ((v & ODD_2BIT_MASK) >> 2); + v = (v & EVEN_4BIT_MASK) + ((v & ODD_4BIT_MASK) >> 4); + v = (v & EVEN_8BIT_MASK) + ((v & ODD_8BIT_MASK) >> 8); + return (v & EVEN_16BIT_MASK) + ((v & ODD_16BIT_MASK) >> 16); + } +}; +``` diff --git a/spider/row-markdown/198.house-robber.md b/spider/row-markdown/198.house-robber.md new file mode 100644 index 0000000..c294a2b --- /dev/null +++ b/spider/row-markdown/198.house-robber.md @@ -0,0 +1,186 @@ +## 题目地址 + +https://leetcode.com/problems/house-robber/description/ + +## 题目描述 + +``` +You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. + +Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. + +Example 1: + +Input: [1,2,3,1] +Output: 4 +Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). + Total amount you can rob = 1 + 3 = 4. +Example 2: + +Input: [2,7,9,3,1] +Output: 12 +Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). + Total amount you can rob = 2 + 9 + 1 = 12. + +``` + +## 思路 + +这是一道非常典型且简单的动态规划问题,但是在这里我希望通过这个例子, +让大家对动态规划问题有一点认识。 + +为什么别人的动态规划可以那么写,为什么没有用 dp 数组就搞定了。 +比如别人的爬楼梯问题怎么就用 fibnacci 搞定了?为什么?在这里我们就来看下。 + +思路还是和其他简单的动态规划问题一样,我们本质上在解决`对于第[i] 个房子,我们抢还是不抢。`的问题。 + +判断的标准就是总价值哪个更大, 那么对于抢的话`就是当前的房子可以抢的价值 + dp[i - 2]` + +> i - 1 不能抢,否则会触发警铃 + +如果不抢的话,就是`dp[i - 1]`. + +> 这里的 dp 其实就是`子问题`. + +状态转移方程也不难写`dp[i] = Math.max(dp[i - 2] + nums[i - 2], dp[i - 1]);`(注:这里为了方便计算,令 `dp[0]`和 `dp[1]`都等于 0,所以 `dp[i]`对应的是 `nums[i - 2]`) + +上述过程用图来表示的话,是这样的: + +![198.house-robber](../assets/problems/198.house-robber.png) + +我们仔细观察的话,其实我们只需要保证前一个 dp[i - 1] 和 dp[i - 2] 两个变量就好了, +比如我们计算到 i = 6 的时候,即需要计算 dp[6]的时候, 我们需要 dp[5], dp[4],但是我们 +不需要 dp[3], dp[2] ... + +因此代码可以简化为: + +```js +let a = 0; +let b = 0; + +for (let i = 0; i < nums.length; i++) { + const temp = b; + b = Math.max(a + nums[i], b); + a = temp; +} + +return b; +``` + +如上的代码,我们可以将空间复杂度进行优化,从 O(n)降低到 O(1), +类似的优化在 DP 问题中不在少数。 + +> 动态规划问题是递归问题查表,避免重复计算,从而节省时间。 +> 如果我们对问题加以分析和抽象,有可能对空间上进一步优化 + +## 关键点解析 + +## 代码 + +* 语言支持:JS,C++,Python + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=198 lang=javascript + * + * [198] House Robber + * + * https://leetcode.com/problems/house-robber/description/ + * + * algorithms + * Easy (40.80%) + * Total Accepted: 312.1K + * Total Submissions: 762.4K + * Testcase Example: '[1,2,3,1]' + * + * You are a professional robber planning to rob houses along a street. Each + * house has a certain amount of money stashed, the only constraint stopping + * you from robbing each of them is that adjacent houses have security system + * connected and it will automatically contact the police if two adjacent + * houses were broken into on the same night. + * + * Given a list of non-negative integers representing the amount of money of + * each house, determine the maximum amount of money you can rob tonight + * without alerting the police. + * + * Example 1: + * + * + * Input: [1,2,3,1] + * Output: 4 + * Explanation: Rob house 1 (money = 1) and then rob house 3 (money = + * 3). + * Total amount you can rob = 1 + 3 = 4. + * + * Example 2: + * + * + * Input: [2,7,9,3,1] + * Output: 12 + * Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house + * 5 (money = 1). + * Total amount you can rob = 2 + 9 + 1 = 12. + * + * + */ +/** + * @param {number[]} nums + * @return {number} + */ +var rob = function(nums) { + // Tag: DP + const dp = []; + dp[0] = 0; + dp[1] = 0; + + for (let i = 2; i < nums.length + 2; i++) { + dp[i] = Math.max(dp[i - 2] + nums[i - 2], dp[i - 1]); + } + + return dp[nums.length + 1]; +}; +``` + +C++ Code: + +> 与JavaScript代码略有差异,但状态迁移方程是一样的。 + +```C++ +class Solution { +public: + int rob(vector& nums) { + if (nums.empty()) return 0; + auto sz = nums.size(); + if (sz == 1) return nums[0]; + auto prev = nums[0]; + auto cur = max(prev, nums[1]); + for (auto i = 2; i < sz; ++i) { + auto tmp = cur; + cur = max(nums[i] + prev, cur); + prev = tmp; + } + return cur; + } +}; +``` + +Python Code: + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + if not nums: + return 0 + + length = len(nums) + if length == 1: + return nums[0] + else: + prev = nums[0] + cur = max(prev, nums[1]) + for i in range(2, length): + cur, prev = max(prev + nums[i], cur), cur + return cur +``` diff --git a/spider/row-markdown/199.binary-tree-right-side-view.md b/spider/row-markdown/199.binary-tree-right-side-view.md new file mode 100644 index 0000000..40a844b --- /dev/null +++ b/spider/row-markdown/199.binary-tree-right-side-view.md @@ -0,0 +1,160 @@ +## 题目地址 + +https://leetcode.com/problems/binary-tree-right-side-view/description/ + +## 题目描述 + +``` +Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom. + +Example: + +Input: [1,2,3,null,5,null,4] +Output: [1, 3, 4] +Explanation: + + 1 <--- + / \ +2 3 <--- + \ \ + 5 4 <--- +``` + +## 思路 + +> 这道题和 leetcode 102 号问题《102.binary-tree-level-order-traversal》很像 + +这道题可以借助`队列`实现,首先把 root 入队,然后入队一个特殊元素 Null(来表示每层的结束)。 + +然后就是 while(queue.length), 每次处理一个节点,都将其子节点(在这里是 left 和 right)放到队列中。 + +然后不断的出队, 如果出队的是 null,则表式这一层已经结束了,我们就继续 push 一个 null。 + +## 关键点解析 + +- 队列 + +- 队列中用 Null(一个特殊元素)来划分每层 + +- 树的基本操作- 遍历 - 层次遍历(BFS) + +- 二叉树的右视图可以看作是层次遍历每次只取每一层的最右边的元素 + +## 代码 + +* 语言支持:JS,C++ + +Javascript Code: +```js +/* + * @lc app=leetcode id=199 lang=javascript + * + * [199] Binary Tree Right Side View + * + * https://leetcode.com/problems/binary-tree-right-side-view/description/ + * + * algorithms + * Medium (46.74%) + * Total Accepted: 156.1K + * Total Submissions: 332.3K + * Testcase Example: '[1,2,3,null,5,null,4]' + * + * Given a binary tree, imagine yourself standing on the right side of it, + * return the values of the nodes you can see ordered from top to bottom. + * + * Example: + * + * + * Input: [1,2,3,null,5,null,4] + * Output: [1, 3, 4] + * Explanation: + * + * ⁠ 1 <--- + * ⁠/ \ + * 2 3 <--- + * ⁠\ \ + * ⁠ 5 4 <--- + * + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +var rightSideView = function(root) { + if (!root) return []; + + const ret = []; + const queue = [root, null]; + + let levelNodes = []; + + while (queue.length > 0) { + const node = queue.shift(); + if (node !== null) { + levelNodes.push(node.val); + if (node.right) { + queue.push(node.right); + } + if (node.left) { + queue.push(node.left); + } + } else { + // 一层遍历已经结束 + ret.push(levelNodes[0]); + if (queue.length > 0) { + queue.push(null); + } + levelNodes = []; + } + } + + return ret; +}; +``` +C++ Code: +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector rightSideView(TreeNode* root) { + auto ret = vector(); + if (root == nullptr) return ret; + auto q = queue(); + q.push(root); + while (!q.empty()) { + auto sz = q.size(); + for (auto i = 0; i < sz; ++i) { + auto n = q.front(); + q.pop(); + if (n->left != nullptr ) q.push(n->left); + if (n->right != nullptr ) q.push(n->right); + if (i == sz - 1) ret.push_back(n->val); + } + } + return ret; + } +}; +``` + +## 扩展 + +假如题目变成求二叉树的左视图呢? + +很简单我们只需要取 queue 的最后一个元素即可。 或者存的时候反着来也行 + +> 其实我们没必要存储 levelNodes,而是只存储每一层最右的元素,这样空间复杂度就不是 n 了, 就是 logn 了。 diff --git a/spider/row-markdown/2.addTwoNumbers.en.md b/spider/row-markdown/2.addTwoNumbers.en.md new file mode 100644 index 0000000..0a1cfd2 --- /dev/null +++ b/spider/row-markdown/2.addTwoNumbers.en.md @@ -0,0 +1,174 @@ +## Problem +https://leetcode.com/problems/add-two-numbers/description/ + +## Problem Description +``` +You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. + +You may assume the two numbers do not contain any leading zero, except the number 0 itself. + +Example + +Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) +Output: 7 -> 0 -> 8 +Explanation: 342 + 465 = 807. + +``` +## Solution + +Define a new variable `carried` that represents the carry value during the calculation, and a new linked list +Traverse the two linked lists from the start to the end simultaneously, and calculate the sum of node value from each linked list. The sum of the result and `carried` would be appended as a new node to the end of the new linked list. + +![2.addTwoNumbers](../assets/2.addTwoNumbers.gif) + +(Image Reference: https://github.com/MisterBooo/LeetCodeAnimation) + +## Key Point Analysis + +1. The characteristics and application of this data structure - linked list + +2. Define a variable named `carried` to replace the role of carry-over, calculate `carried` after each sum and apply it to the next round's calculation + +## Code +* Language Support: JS, C++ + +JavaScript: +```js +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ +var addTwoNumbers = function(l1, l2) { + if (l1 === null || l2 === null) return null + + // using dummyHead can simplify linked list's calculation, dummyHead.next points to the new linked list + let dummyHead = new ListNode(0) + let cur1 = l1 + let cur2 = l2 + let cur = dummyHead // cur is for the calculation in new linked list + let carry = 0 // carry-over symbol + + while (cur1 !== null || cur2 !== null) { + let val1 = cur1 !== null ? cur1.val : 0 + let val2 = cur2 !== null ? cur2.val : 0 + let sum = val1 + val2 + carry + let newNode = new ListNode(sum % 10) // the result of sum%10 ranges from 0 to 9, which is the value of the current digit + carry = sum >= 10 ? 1 : 0 // sum>=10, carry=1, so carry-over exists here + cur.next = newNode + cur = cur.next + + if (cur1 !== null) { + cur1 = cur1.next + } + + if (cur2 !== null) { + cur2 = cur2.next + } + } + + if (carry > 0) { + // If there's still carry-over in the end, then add a new node + cur.next = new ListNode(carry) + } + + return dummyHead.next +}; +``` +C++ +> C++ code is slightly different from the JavaScript code above: the step that checks whether carry equals to 0 is put in the while-loop. +```c++ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + ListNode* ret = nullptr; + ListNode* cur = nullptr; + int carry = 0; + while (l1 != nullptr || l2 != nullptr || carry != 0) { + carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val); + auto temp = new ListNode(carry % 10); + carry /= 10; + if (ret == nullptr) { + ret = temp; + cur = ret; + } + else { + cur->next = temp; + cur = cur->next; + } + l1 = l1 == nullptr ? nullptr : l1->next; + l2 = l2 == nullptr ? nullptr : l2->next; + } + return ret; + } +}; +``` +## Extension +The singly-linked list also has a recursive structure based on its definition. Therefore, the recursive apporach works on reversing a linked list, as well. +> Because a singly-linked list is a linear data structure, the recursive approach means that the use of stack would also be linear. When the linked list's length reaches a certain level, the recursion would result in a stack overflow. Therefore, using recursion to manipulate a linked list is not recommended in reality. + +### Description + +1. Add up the first node of two linked lists, and covert the result to a number between 0 and 10, record the carry-over as well. +2. Proceed to add up the two linked lists after the first node with carry-over recursively +3. Point the next of the head node from the first step to the linked list returned from the second step + +### C++ Implementation +```C++ +// Normal recursion +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + return addTwoNumbers(l1, l2, 0); + } + +private: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2, int carry) { + if (l1 == nullptr && l2 == nullptr && carry == 0) return nullptr; + carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val); + auto ret = new ListNode(carry % 10); + ret->next = addTwoNumbers(l1 == nullptr ? l1 : l1->next, + l2 == nullptr ? l2 : l2->next, + carry / 10); + return ret; + } +}; +// (Similiar) Tail recursion +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + ListNode* head = nullptr; + addTwoNumbers(head, nullptr, l1, l2, 0); + return head; + } + +private: + void addTwoNumbers(ListNode*& head, ListNode* cur, ListNode* l1, ListNode* l2, int carry) { + if (l1 == nullptr && l2 == nullptr && carry == 0) return; + carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val); + auto temp = new ListNode(carry % 10); + if (cur == nullptr) { + head = temp; + cur = head; + } else { + cur->next = temp; + cur = cur->next; + } + addTwoNumbers(head, cur, l1 == nullptr ? l1 : l1->next, l2 == nullptr ? l2 : l2->next, carry / 10); + } +}; \ No newline at end of file diff --git a/spider/row-markdown/2.addTwoNumbers.md b/spider/row-markdown/2.addTwoNumbers.md new file mode 100644 index 0000000..ecfac15 --- /dev/null +++ b/spider/row-markdown/2.addTwoNumbers.md @@ -0,0 +1,176 @@ +## 题目地址 +https://leetcode.com/problems/add-two-numbers/description/ + +## 题目描述 +``` +You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. + +You may assume the two numbers do not contain any leading zero, except the number 0 itself. + +Example + +Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) +Output: 7 -> 0 -> 8 +Explanation: 342 + 465 = 807. + +``` +## 思路 + +设立一个表示进位的变量carried,建立一个新链表, +把输入的两个链表从头往后同时处理,每两个相加,将结果加上carried后的值作为一个新节点到新链表后面。 + +![2.addTwoNumbers](../assets/2.addTwoNumbers.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) + +## 关键点解析 + +1. 链表这种数据结构的特点和使用 + +2. 用一个carried变量来实现进位的功能,每次相加之后计算carried,并用于下一位的计算 + +## 代码 +* 语言支持:JS,C++ + +JavaScript: +```js +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ +var addTwoNumbers = function(l1, l2) { + if (l1 === null || l2 === null) return null + + // 使用dummyHead可以简化对链表的处理,dummyHead.next指向新链表 + let dummyHead = new ListNode(0) + let cur1 = l1 + let cur2 = l2 + let cur = dummyHead // cur用于计算新链表 + let carry = 0 // 进位标志 + + while (cur1 !== null || cur2 !== null) { + let val1 = cur1 !== null ? cur1.val : 0 + let val2 = cur2 !== null ? cur2.val : 0 + let sum = val1 + val2 + carry + let newNode = new ListNode(sum % 10) // sum%10取模结果范围为0~9,即为当前节点的值 + carry = sum >= 10 ? 1 : 0 // sum>=10,carry=1,表示有进位 + cur.next = newNode + cur = cur.next + + if (cur1 !== null) { + cur1 = cur1.next + } + + if (cur2 !== null) { + cur2 = cur2.next + } + } + + if (carry > 0) { + // 如果最后还有进位,新加一个节点 + cur.next = new ListNode(carry) + } + + return dummyHead.next +}; +``` +C++ +> C++代码与上面的JavaScript代码略有不同:将carry是否为0的判断放到了while循环中 +```c++ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + ListNode* ret = nullptr; + ListNode* cur = nullptr; + int carry = 0; + while (l1 != nullptr || l2 != nullptr || carry != 0) { + carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val); + auto temp = new ListNode(carry % 10); + carry /= 10; + if (ret == nullptr) { + ret = temp; + cur = ret; + } + else { + cur->next = temp; + cur = cur->next; + } + l1 = l1 == nullptr ? nullptr : l1->next; + l2 = l2 == nullptr ? nullptr : l2->next; + } + return ret; + } +}; +``` +## 拓展 + +通过单链表的定义可以得知,单链表也是递归结构,因此,也可以使用递归的方式来进行reverse操作。 +> 由于单链表是线性的,使用递归方式将导致栈的使用也是线性的,当链表长度达到一定程度时,递归会导致爆栈,因此,现实中并不推荐使用递归方式来操作链表。 + +### 描述 + +1. 将两个链表的第一个节点值相加,结果转为0-10之间的个位数,并设置进位信息 +2. 将两个链表第一个节点以后的链表做带进位的递归相加 +3. 将第一步得到的头节点的next指向第二步返回的链表 + +### C++实现 +```C++ +// 普通递归 +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + return addTwoNumbers(l1, l2, 0); + } + +private: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2, int carry) { + if (l1 == nullptr && l2 == nullptr && carry == 0) return nullptr; + carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val); + auto ret = new ListNode(carry % 10); + ret->next = addTwoNumbers(l1 == nullptr ? l1 : l1->next, + l2 == nullptr ? l2 : l2->next, + carry / 10); + return ret; + } +}; +// (类似)尾递归 +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + ListNode* head = nullptr; + addTwoNumbers(head, nullptr, l1, l2, 0); + return head; + } + +private: + void addTwoNumbers(ListNode*& head, ListNode* cur, ListNode* l1, ListNode* l2, int carry) { + if (l1 == nullptr && l2 == nullptr && carry == 0) return; + carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val); + auto temp = new ListNode(carry % 10); + if (cur == nullptr) { + head = temp; + cur = head; + } else { + cur->next = temp; + cur = cur->next; + } + addTwoNumbers(head, cur, l1 == nullptr ? l1 : l1->next, l2 == nullptr ? l2 : l2->next, carry / 10); + } +}; +``` diff --git a/spider/row-markdown/20.validParentheses.md b/spider/row-markdown/20.validParentheses.md new file mode 100644 index 0000000..43edfcd --- /dev/null +++ b/spider/row-markdown/20.validParentheses.md @@ -0,0 +1,131 @@ +## 题目地址 +https://leetcode.com/problems/valid-parentheses/description + +## 题目描述 + +``` +Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. + +An input string is valid if: + +Open brackets must be closed by the same type of brackets. +Open brackets must be closed in the correct order. +Note that an empty string is also considered valid. + +Example 1: + +Input: "()" +Output: true +Example 2: + +Input: "()[]{}" +Output: true +Example 3: + +Input: "(]" +Output: false +Example 4: + +Input: "([)]" +Output: false +Example 5: + +Input: "{[]}" +Output: true +``` + +## 思路 + +关于这道题的思路,邓俊辉讲的非常好,没有看过的同学可以看一下,[视频地址](http://www.xuetangx.com/courses/course-v1:TsinghuaX+30240184+sp/courseware/ad1a23c053df4501a3facd66ef6ccfa9/8d6f450e7f7a445098ae1d507fda80f6/)。 + +使用栈,遍历输入字符串 + +如果当前字符为左半边括号时,则将其压入栈中 + +如果遇到右半边括号时,分类讨论: + +1)如栈不为空且为对应的左半边括号,则取出栈顶元素,继续循环 + +2)若此时栈为空,则直接返回 false + +3)若不为对应的左半边括号,反之返回 false + +![20.validParentheses](../assets/20.validParentheses.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) + +> 值得注意的是,如果题目要求只有一种括号,那么我们其实可以使用更简洁,更省内存的方式 - 计数器来进行求解,而 +不必要使用栈。 + +> 事实上,这类问题还可以进一步扩展,我们可以去解析类似 HTML 等标记语法, 比如

+ +## 关键点解析 + +1. 栈的基本特点和操作 +2. 如果你用的是 JS 没有现成的栈,可以用数组来模拟 +入: push 出:pop + +> 入: push 出 shift 就是队列 +## 代码 + +* 语言支持:JS,Python + +Javascript Code: +```js +/** + * @param {string} s + * @return {boolean} + */ +var isValid = function(s) { + let valid = true; + const stack = []; + const mapper = { + '{': "}", + "[": "]", + "(": ")" + } + + for(let i in s) { + const v = s[i]; + if (['(', '[', '{'].indexOf(v) > -1) { + stack.push(v); + } else { + const peak = stack.pop(); + if (v !== mapper[peak]) { + return false; + } + } + } + + if (stack.length > 0) return false; + + return valid; +}; +``` +Python Code: +``` + class Solution: + def isValid(self,s): + stack = [] + map = { + "{":"}", + "[":"]", + "(":")" + } + for x in s: + if x in map: + stack.append(map[x]) + else: + if len(stack)!=0: + top_element = stack.pop() + if x != top_element: + return False + else: + continue + else: + return False + return len(stack) == 0 +``` + +## 扩展 +如果让你检查 XML 标签是否闭合如何检查, 更进一步如果要你实现一个简单的 XML 的解析器,应该怎么实现? diff --git a/spider/row-markdown/200.number-of-islands.md b/spider/row-markdown/200.number-of-islands.md new file mode 100644 index 0000000..4615308 --- /dev/null +++ b/spider/row-markdown/200.number-of-islands.md @@ -0,0 +1,165 @@ +## 题目地址 + +https://leetcode.com/problems/number-of-islands/description/ + +## 题目描述 + +``` +Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. + +Example 1: + +Input: +11110 +11010 +11000 +00000 + +Output: 1 +Example 2: + +Input: +11000 +11000 +00100 +00011 + +Output: 3 + +``` + +## 思路 + +如图,我们其实就是要求红色区域的个数,换句话说就是求连续区域的个数。 + +![200.number-of-islands](../assets/problems/200.number-of-islands.jpg) + +符合直觉的做法是用DFS来解: + +- 我们需要建立一个 visited 数组用来记录某个位置是否被访问过。 +- 对于一个为 `1` 且未被访问过的位置,我们递归进入其上下左右位置上为 `1` 的数,将其 visited 变成 true。 +- 重复上述过程 +- 找完相邻区域后,我们将结果 res 自增1,然后我们在继续找下一个为 `1` 且未被访问过的位置,直至遍历完. + +但是这道题目只是让我们求连通区域的个数,因此我们其实不需要额外的空间去存储visited信息。 +注意到上面的过程,我们对于数字为0的其实不会进行操作的,也就是对我们“没用”。 因此对于已经访问的元素, +我们可以将其置为0即可。 + + +## 关键点解析 + +- 二维数组DFS解题模板 +- 将已经访问的元素置为0,省去visited的空间开销 + +## 代码 + +* 语言支持:JS, python3,Java + +Java Code: + +```java + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) return 0; + + int count = 0; + for (int row = 0; row < grid.length; row++) { + for (int col = 0; col < grid[0].length; col++) { + if (grid[row][col] == '1') { + dfs(grid, row, col); + count++; + } + } + } + return count; + } + + private void dfs(char[][] grid,int row,int col) { + if (row<0||row== grid.length||col<0||col==grid[0].length||grid[row][col]!='1') { + return; + } + grid[row][col] = '0'; + dfs(grid, row-1, col); + dfs(grid, row+1, col); + dfs(grid, row, col+1); + dfs(grid, row, col-1); + } +``` + +Javascript Code: +```js +/* + * @lc app=leetcode id=200 lang=javascript + * + * [200] Number of Islands + */ +function helper(grid, i, j, rows, cols) { + if (i < 0 || j < 0 || i > rows - 1 || j > cols - 1 || grid[i][j] === "0") + return; + + grid[i][j] = "0"; + + helper(grid, i + 1, j, rows, cols); + helper(grid, i, j + 1, rows, cols); + helper(grid, i - 1, j, rows, cols); + helper(grid, i, j - 1, rows, cols); +} +/** + * @param {character[][]} grid + * @return {number} + */ +var numIslands = function(grid) { + let res = 0; + const rows = grid.length; + if (rows === 0) return 0; + const cols = grid[0].length; + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === "1") { + helper(grid, i, j, rows, cols); + res++; + } + } + } + return res; +}; +``` + +python code: + +``` python +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + if not grid: return 0 + + count = 0 + for i in range(len(grid)): + for j in range(len(grid[0])): + if grid[i][j] == '1': + self.dfs(grid, i, j) + count += 1 + + return count + + def dfs(self, grid, i, j): + if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or grid[i][j] != '1': + return + grid[i][j] = '0' + self.dfs(grid, i + 1, j) + self.dfs(grid, i - 1, j) + self.dfs(grid, i, j + 1) + self.dfs(grid, i, j - 1) + +``` + +**复杂度分析** +- 时间复杂度:$O(m * n)$ +- 空间复杂度:$O(m * n)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) + + +## 相关题目 + +- [695. 岛屿的最大面积](https://leetcode-cn.com/problems/max-area-of-island/solution/695-dao-yu-de-zui-da-mian-ji-dfspython3-by-fe-luci/) diff --git a/spider/row-markdown/201.bitwise-and-of-numbers-range.md b/spider/row-markdown/201.bitwise-and-of-numbers-range.md new file mode 100644 index 0000000..5d148cc --- /dev/null +++ b/spider/row-markdown/201.bitwise-and-of-numbers-range.md @@ -0,0 +1,126 @@ + +## 题目地址 +https://leetcode.com/problems/bitwise-and-of-numbers-range/description/ + +## 题目描述 + +``` +Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. + +Example 1: + +Input: [5,7] +Output: 4 +Example 2: + +Input: [0,1] +Output: 0 + +``` + +## 思路 + +一个显而易见的解法是, 从m到n依次进行`求与`的操作。 + +```js + + let res = m; + for (let i = m + 1; i <= n; i++) { + res = res & i; + } + return res; + +``` + +但是, 如果你把这个solution提交的话,很显然不会通过, 会超时。 + +我们依旧还是用trick来简化操作。 我们利用的性质是, n个连续数字求与的时候,前m位都是1. + +举题目给的例子:[5,7] 共 5, 6,7三个数字, 用二进制表示 101, 110,111, +这三个数字特点是第一位都是1,后面几位求与一定是0. + +再来一个明显的例子:[20, 24], 共 20, 21, 22, 23,24五个数字,二进制表示就是 + +``` +0001 0100 +0001 0101 +0001 0110 +0001 0111 +0001 1000 +``` + +这五个数字特点是第四位都是1,后面几位求与一定是0. + +因此我们的思路就是, 求出这个数字区间的数字前多少位都是1了,那么他们求与的结果一定是前几位数字,然后后面都是0. + + +## 关键点解析 + + +- n个连续数字求与的时候,前m位都是1 + +- 可以用递归实现, 个人认为比较难想到 + +- bit 运算 + +代码: + +```js + +(n > m) ? (rangeBitwiseAnd(m/2, n/2) << 1) : m; + +``` + +> 每次问题规模缩小一半, 这是二分法吗? + +## 代码 + +语言支持:JavaSCript,Python3 + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=201 lang=javascript + * + * [201] Bitwise AND of Numbers Range + * + */ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +var rangeBitwiseAnd = function(m, n) { + let count = 0; + while (m !== n) { + m = m >> 1; + n = n >> 1; + count++; + } + + return n << count; +}; + +``` + +Python Code: + +```python +class Solution: + def rangeBitwiseAnd(self, m: int, n: int) -> int: + cnt = 0 + while m != n: + m >>= 1 + n >>= 1 + cnt += 1 + + return m << cnt + ``` + + **复杂度分析** + + - 时间复杂度:最坏的情况我们需要循环N次,最好的情况是一次都不需要, 因此时间复杂度取决于我们移动的位数,具体移动的次数取决于我们的输入,平均来说时间复杂度为 $O(N)$,其中N为M和N的二进制表示的位数。 + - 空间复杂度:$O(1)$ + + diff --git a/spider/row-markdown/203.remove-linked-list-elements.md b/spider/row-markdown/203.remove-linked-list-elements.md new file mode 100644 index 0000000..7955c00 --- /dev/null +++ b/spider/row-markdown/203.remove-linked-list-elements.md @@ -0,0 +1,90 @@ +## 题目地址 +https://leetcode.com/problems/remove-linked-list-elements/description/ + +## 题目描述 +``` +Remove all elements from a linked list of integers that have value val. + +Example: + +Input: 1->2->6->3->4->5->6, val = 6 +Output: 1->2->3->4->5 + +``` + +## 思路 +这个一个链表基本操作的题目,思路就不多说了。 +## 关键点解析 + +- 链表的基本操作(删除指定节点) +- 虚拟节点 dummy 简化操作 + +> 其实设置 dummy 节点就是为了处理特殊位置(头节点),这这道题就是如果头节点是给定的需要删除的节点呢? +为了保证代码逻辑的一致性,即不需要为头节点特殊定制逻辑,才采用的虚拟节点。 + +- 如果连续两个节点都是要删除的节点,这个情况容易被忽略。 +eg: + +```js +// 只有下个节点不是要删除的节点才更新 current +if (!next || next.val !== val) { + current = next; +} + +``` + +## 代码 + +* 语言支持:JS,Python + +Javascript Code: + +```js +/** + * @param {ListNode} head + * @param {number} val + * @return {ListNode} + */ +var removeElements = function(head, val) { + const dummy = { + next: head + } + let current = dummy; + + while(current && current.next) { + let next = current.next; + if (next.val === val) { + current.next = next.next; + next = next.next; + } + + if (!next || next.val !== val) { + current = next; + } + } + + return dummy.next; +}; +``` + +Python Code: + +```python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def removeElements(self, head: ListNode, val: int) -> ListNode: + prev = ListNode(0) + prev.next = head + cur = prev + while cur.next: + if cur.next.val == val: + cur.next = cur.next.next + else: + cur = cur.next + return prev.next +``` diff --git a/spider/row-markdown/206.reverse-linked-list.md b/spider/row-markdown/206.reverse-linked-list.md new file mode 100644 index 0000000..2a29e71 --- /dev/null +++ b/spider/row-markdown/206.reverse-linked-list.md @@ -0,0 +1,225 @@ +## 题目地址 +https://leetcode.com/problems/reverse-linked-list/description/ + +## 题目描述 +Reverse a singly linked list. + +Example: + +Input: 1->2->3->4->5->NULL +Output: 5->4->3->2->1->NULL +Follow up: + +A linked list can be reversed either iteratively or recursively. Could you implement both? + +## 思路 +这个就是常规操作了,使用一个变量记录前驱 pre,一个变量记录后继 next. + +不断更新`current.next = pre` 就好了 +## 关键点解析 + +- 链表的基本操作(交换) +- 虚拟节点 dummy 简化操作 +- 注意更新 current 和 pre 的位置, 否则有可能出现溢出 + +## 代码 + +语言支持:JS, C++, Python,Java + +JavaScript Code: + +```js +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +var reverseList = function(head) { + if (!head || !head.next) return head; + + let cur = head; + let pre = null; + + while(cur) { + const next = cur.next; + cur.next = pre; + pre = cur; + cur = next; + } + + return pre; +}; + +``` + +C++ Code: + +```c++ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode* reverseList(ListNode* head) { + ListNode* prev = NULL; + ListNode* cur = head; + ListNode* next = NULL; + while (cur != NULL) { + next = cur->next; + cur->next = prev; + prev = cur; + cur = next; + } + return prev; + } +}; +``` + +Python Code: + +```python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def reverseList(self, head: ListNode) -> ListNode: + if not head: return None + prev = None + cur = head + while cur: + cur.next, prev, cur = prev, cur, cur.next + return prev +``` + +Java Code: + +```java +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +class Solution { + public ListNode reverseList(ListNode head) { + ListNode pre = null, cur = head; + + while (cur != null) { + ListNode next = cur.next; + cur.next = pre; + pre = cur; + cur = next; + } + + return pre; + } +} +``` + +## 拓展 + +通过单链表的定义可以得知,单链表也是递归结构,因此,也可以使用递归的方式来进行 reverse 操作。 +> 由于单链表是线性的,使用递归方式将导致栈的使用也是线性的,当链表长度达到一定程度时,递归会导致爆栈,因此,现实中并不推荐使用递归方式来操作链表。 + +### 描述 + +1. 除第一个节点外,递归将链表 reverse +2. 将第一个节点添加到已 reverse 的链表之后 + +> 这里需要注意的是,每次需要保存已经 reverse 的链表的头节点和尾节点 + +### C++实现 +```c++ +// 普通递归 +class Solution { +public: + ListNode* reverseList(ListNode* head) { + ListNode* tail = nullptr; + return reverseRecursive(head, tail); + } + + ListNode* reverseRecursive(ListNode *head, ListNode *&tail) { + if (head == nullptr) { + tail = nullptr; + return head; + } + if (head->next == nullptr) { + tail = head; + return head; + } + auto h = reverseRecursive(head->next, tail); + if (tail != nullptr) { + tail->next = head; + tail = head; + head->next = nullptr; + } + return h; + } +}; + +// (类似)尾递归 +class Solution { +public: + ListNode* reverseList(ListNode* head) { + if (head == nullptr) return head; + return reverseRecursive(nullptr, head, head->next); + } + + ListNode* reverseRecursive(ListNode *prev, ListNode *head, ListNode *next) + { + if (next == nullptr) return head; + auto n = next->next; + next->next = head; + head->next = prev; + return reverseRecursive(head, next, n); + } +}; +``` + +### JavaScript 实现 +```javascript +var reverseList = function(head) { + // 递归结束条件 + if (head === null || head.next === null) { + return head + } + + // 递归反转 子链表 + let newReverseList = reverseList(head.next) + // 获取原来链表的第 2 个节点 newReverseListTail + let newReverseListTail = head.next + // 调整原来头结点和第 2 个节点的指向 + newReverseListTail.next = head + head.next = null + + // 将调整后的链表返回 + return newReverseList +} +``` + +### Python 实现 +```python +class Solution: + def reverseList(self, head: ListNode) -> ListNode: + if not head or not head.next: return head + ans = self.reverseList(head.next) + head.next.next = head + head.next = None + return ans +``` diff --git a/spider/row-markdown/208.implement-trie-prefix-tree.md b/spider/row-markdown/208.implement-trie-prefix-tree.md new file mode 100644 index 0000000..959d3e9 --- /dev/null +++ b/spider/row-markdown/208.implement-trie-prefix-tree.md @@ -0,0 +1,196 @@ +## 题目地址 + +https://leetcode.com/problems/implement-trie-prefix-tree/description/ + +## 题目描述 + +``` +Implement a trie with insert, search, and startsWith methods. + +Example: + +Trie trie = new Trie(); + +trie.insert("apple"); +trie.search("apple"); // returns true +trie.search("app"); // returns false +trie.startsWith("app"); // returns true +trie.insert("app"); +trie.search("app"); // returns true +Note: + +You may assume that all inputs are consist of lowercase letters a-z. +All inputs are guaranteed to be non-empty strings. + +``` + +## 思路 + +这是一道很直接的题目,上来就让你实现`前缀树(字典树)`。这算是基础数据结构中的 +知识了,不清楚什么是字典树的可以查阅相关资料。 + +我们看到题目给出的使用方法`new Trie`, `insert`,`search`和`startWith`. + +为了区分`search`和`startWith`我们需要增加一个标示来区分当前节点是否是某个单词的结尾。 +因此节点的数据结构应该是: + +```js +function TrieNode(val) { + this.val = val; // 当前的字母 + this.children = []; // 题目要求字典仅有a-z,那么其长度最大为26(26个字母) + this.isWord = false; +} +``` + +每次 insert 我们其实都是从根节点出发,一个一个找到我们需要添加的节点,修改 children 的值. + +我们应该修改哪一个 child 呢? 我们需要一个函数来计算索引 + +```js +function computeIndex(c) { + return c.charCodeAt(0) - "a".charCodeAt(0); +} +``` + +其实不管 insert, search 和 startWith 的逻辑都是差不多的,都是从 root 出发, +找到我们需要操作的 child, 然后进行相应操作(添加,修改,返回)。 + +![208.implement-trie-prefix-tree-1](../assets/problems/208.implement-trie-prefix-tree-1.png) + +## 关键点解析 + +- 前缀树 + +- 核心逻辑 + +```js + const c = word[i]; + const current = computeIndex(c) +if (!ws.children[current]) { + ws.children[current] = new TrieNode(c); + } + ws = ws.children[current]; // 深度递增 +} + +``` + +## 代码 + +```js +/* + * @lc app=leetcode id=208 lang=javascript + * + * [208] Implement Trie (Prefix Tree) + * + * https://leetcode.com/problems/implement-trie-prefix-tree/description/ + * + * algorithms + * Medium (36.93%) + * Total Accepted: 172K + * Total Submissions: 455.5K + * Testcase Example: '["Trie","insert","search","search","startsWith","insert","search"]\n[[],["apple"],["apple"],["app"],["app"],["app"],["app"]]' + * + * Implement a trie with insert, search, and startsWith methods. + * + * Example: + * + * + * Trie trie = new Trie(); + * + * trie.insert("apple"); + * trie.search("apple"); // returns true + * trie.search("app"); // returns false + * trie.startsWith("app"); // returns true + * trie.insert("app"); + * trie.search("app"); // returns true + * + * + * Note: + * + * + * You may assume that all inputs are consist of lowercase letters a-z. + * All inputs are guaranteed to be non-empty strings. + * + * + */ +function TrieNode(val) { + this.val = val; + this.children = []; + this.isWord = false; +} + +function computeIndex(c) { + return c.charCodeAt(0) - "a".charCodeAt(0); +} +/** + * Initialize your data structure here. + */ +var Trie = function() { + this.root = new TrieNode(null); +}; + +/** + * Inserts a word into the trie. + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function(word) { + let ws = this.root; + for (let i = 0; i < word.length; i++) { + const c = word[i]; + const current = computeIndex(c); + if (!ws.children[current]) { + ws.children[current] = new TrieNode(c); + } + ws = ws.children[current]; + } + ws.isWord = true; +}; + +/** + * Returns if the word is in the trie. + * @param {string} word + * @return {boolean} + */ +Trie.prototype.search = function(word) { + let ws = this.root; + for (let i = 0; i < word.length; i++) { + const c = word[i]; + const current = computeIndex(c); + if (!ws.children[current]) return false; + ws = ws.children[current]; + } + return ws.isWord; +}; + +/** + * Returns if there is any word in the trie that starts with the given prefix. + * @param {string} prefix + * @return {boolean} + */ +Trie.prototype.startsWith = function(prefix) { + let ws = this.root; + for (let i = 0; i < prefix.length; i++) { + const c = prefix[i]; + const current = computeIndex(c); + if (!ws.children[current]) return false; + ws = ws.children[current]; + } + return true; +}; + +/** + * Your Trie object will be instantiated and called as such: + * var obj = new Trie() + * obj.insert(word) + * var param_2 = obj.search(word) + * var param_3 = obj.startsWith(prefix) + */ +``` + +## 相关题目 + +- [0211.add-and-search-word-data-structure-design](./211.add-and-search-word-data-structure-design.md) +- [0212.word-search-ii](./212.word-search-ii.md) +- [0472.concatenated-words](./problems/472.concatenated-words.md) +- [0820.short-encoding-of-words](https://github.com/azl397985856/leetcode/blob/master/problems/820.short-encoding-of-words.md) diff --git a/spider/row-markdown/209.minimum-size-subarray-sum.md b/spider/row-markdown/209.minimum-size-subarray-sum.md new file mode 100644 index 0000000..df3c648 --- /dev/null +++ b/spider/row-markdown/209.minimum-size-subarray-sum.md @@ -0,0 +1,157 @@ +## 题目地址 + +https://leetcode.com/problems/minimum-size-subarray-sum/description/ + +## 题目描述 + +``` +Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead. + +Example: + +Input: s = 7, nums = [2,3,1,2,4,3] +Output: 2 +Explanation: the subarray [4,3] has the minimal length under the problem constraint. +Follow up: +If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n). + +``` + +## 思路 + +用滑动窗口来记录序列, 每当滑动窗口中的 sum 超过 s, 就去更新最小值,并根据先进先出的原则更新滑动窗口,直至 sum 刚好小于 s + +![209.minimum-size-subarray-sum](../assets/problems/209.minimum-size-subarray-sum.png) + +> 这道题目和 leetcode 3 号题目有点像,都可以用滑动窗口的思路来解决 + +## 关键点 + +- 滑动窗口简化操作(滑窗口适合用于求解这种要求`连续`的题目) + +## 代码 + +- 语言支持:JS,C++,Python + +Python Code: + +```python + +class Solution: + def minSubArrayLen(self, s: int, nums: List[int]) -> int: + l = total = 0 + ans = len(nums) + 1 + for r in range(len(nums)): + total += nums[r] + while total >= s: + ans = min(ans, r - l + 1) + total -= nums[l] + l += 1 + return 0 if ans == len(nums) + 1 else ans +``` + + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=209 lang=javascript + * + * [209] Minimum Size Subarray Sum + * + */ +/** + * @param {number} s + * @param {number[]} nums + * @return {number} + */ +var minSubArrayLen = function(s, nums) { + if (nums.length === 0) return 0; + const slideWindow = []; + let acc = 0; + let min = null; + + for (let i = 0; i < nums.length + 1; i++) { + const num = nums[i]; + + while (acc >= s) { + if (min === null || slideWindow.length < min) { + min = slideWindow.length; + } + acc = acc - slideWindow.shift(); + } + + slideWindow.push(num); + + acc = slideWindow.reduce((a, b) => a + b, 0); + } + + return min || 0; +}; +``` + +C++ Code: + +```C++ +class Solution { +public: + int minSubArrayLen(int s, vector& nums) { + int num_len= nums.size(); + int left=0, right=0, total=0, min_len= num_len+1; + while (right < num_len) { + do { + total += nums[right++]; + } while (right < num_len && total < s); + while (left < right && total - nums[left] >= s) total -= nums[left++]; + if (total >=s && min_len > right - left) + min_len = right- left; + } + return min_len <= num_len ? min_len: 0; + } +}; +``` + +**复杂度分析** +- 时间复杂度:$O(N)$,其中 N 为数组大小。 +- 空间复杂度:$O(1)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) + +## 扩展 + +如果题目要求是 sum = s, 而不是 sum >= s 呢? + +eg: + +```js +var minSubArrayLen = function(s, nums) { + if (nums.length === 0) return 0; + const slideWindow = []; + let acc = 0; + let min = null; + + for (let i = 0; i < nums.length + 1; i++) { + const num = nums[i]; + + while (acc > s) { + acc = acc - slideWindow.shift(); + } + if (acc === s) { + if (min === null || slideWindow.length < min) { + min = slideWindow.length; + } + slideWindow.shift(); + } + + slideWindow.push(num); + + acc = slideWindow.reduce((a, b) => a + b, 0); + } + + return min || 0; +}; +``` + + diff --git a/spider/row-markdown/21.MergeTwoSortedLists.md b/spider/row-markdown/21.MergeTwoSortedLists.md new file mode 100644 index 0000000..86b5ce7 --- /dev/null +++ b/spider/row-markdown/21.MergeTwoSortedLists.md @@ -0,0 +1,63 @@ +## 题目地址 +https://leetcode-cn.com/problems/merge-two-sorted-lists + +## 题目描述 +``` +将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  + +示例: + +输入:1->2->4, 1->3->4 +输出:1->1->2->3->4->4 + +``` + +## 思路 +使用递归来解题,将两个链表头部较小的一个与剩下的元素合并,并返回排好序的链表头,当两条链表中的一条为空时终止递归。 + + +## 关键点 + +- 掌握链表数据结构 +- 考虑边界情况 + +## 代码 +* 语言支持:JS + +```js +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ +const mergeTwoLists = function (l1, l2) { + if (l1 === null) { + return l2; + } + if (l2 === null) { + return l1; + } + if (l1.val < l2.val) { + l1.next = mergeTwoLists(l1.next, l2); + return l1; + } else { + l2.next = mergeTwoLists(l1, l2.next); + return l2; + } +}; +``` + +***复杂度分析*** + +M、N 是两条链表 l1、l2 的长度 + +- 时间复杂度:O(M+N) +- 空间复杂度:O(M+N) + diff --git a/spider/row-markdown/211.add-and-search-word-data-structure-design.md b/spider/row-markdown/211.add-and-search-word-data-structure-design.md new file mode 100644 index 0000000..a0b4037 --- /dev/null +++ b/spider/row-markdown/211.add-and-search-word-data-structure-design.md @@ -0,0 +1,172 @@ +## 题目地址(211. 添加与搜索单词 - 数据结构设计) + +https://leetcode-cn.com/problems/add-and-search-word-data-structure-design/description/ + +## 题目描述 + +``` +设计一个支持以下两种操作的数据结构: + +void addWord(word) +bool search(word) +search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z 。 . 可以表示任何一个字母。 + +示例: + +addWord("bad") +addWord("dad") +addWord("mad") +search("pad") -> false +search("bad") -> true +search(".ad") -> true +search("b..") -> true +说明: + +你可以假设所有单词都是由小写字母 a-z 组成的。 + +``` + +## 思路 + +我们首先不考虑字符"."的情况。这种情况比较简单,我们 addWord 直接添加到数组尾部,search 则线性查找即可。 + +接下来我们考虑特殊字符“.”,其实也不难,只不过 search 的时候,判断如果是“.”, 我们认为匹配到了,继续往后匹配即可。 + +上面的代码复杂度会比较高,我们考虑优化。如果你熟悉前缀树的话,应该注意到这可以使用前缀树来进行优化。前缀树优化之后每次查找复杂度是$O(h)$, 其中 h 是前缀树深度,也就是最长的字符串长度。 + +关于前缀树,LeetCode 有很多题目。有的是直接考察,让你实现一个前缀树,有的是间接考察,比如本题。前缀树代码见下方,大家之后可以直接当成前缀树的解题模板使用。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gb5dmstsxxj30mz0gqmzh.jpg) + +由于我们这道题需要考虑特殊字符".",因此我们需要对标准前缀树做一点改造,insert 不做改变,我们只需要改变 search 即可,代码(Python 3): + +```python +def search(self, word): + """ + Returns if the word is in the trie. + :type word: str + :rtype: bool + """ + curr = self.Trie + for i, w in enumerate(word): + if w == '.': + wizards = [] + for k in curr.keys(): + if k == '#': + continue + wizards.append(self.search(word[:i] + k + word[i + 1:])) + return any(wizards) + if w not in curr: + return False + curr = curr[w] + return "#" in curr +``` + +标准的前缀树搜索我也贴一下代码,大家可以对比一下: + +```python +def search(self, word): + """ + Returns if the word is in the trie. + :type word: str + :rtype: bool + """ + curr = self.Trie + for w in word: + if w not in curr: + return False + curr = curr[w] + return "#" in curr +``` + +## 关键点 + +- 前缀树(也叫字典树),英文名 Trie(读作 tree 或者 try) + +## 代码 + +- 语言支持:Python3 + +Python3 Code: + +关于 Trie 的代码: + +```python +class Trie: + + def __init__(self): + """ + Initialize your data structure here. + """ + self.Trie = {} + + def insert(self, word): + """ + Inserts a word into the trie. + :type word: str + :rtype: void + """ + curr = self.Trie + for w in word: + if w not in curr: + curr[w] = {} + curr = curr[w] + curr['#'] = 1 + + def search(self, word): + """ + Returns if the word is in the trie. + :type word: str + :rtype: bool + """ + curr = self.Trie + for i, w in enumerate(word): + if w == '.': + wizards = [] + for k in curr.keys(): + if k == '#': + continue + wizards.append(self.search(word[:i] + k + word[i + 1:])) + return any(wizards) + if w not in curr: + return False + curr = curr[w] + return "#" in curr +``` + +主逻辑代码: + +```python +class WordDictionary: + + def __init__(self): + """ + Initialize your data structure here. + """ + self.trie = Trie() + + def addWord(self, word: str) -> None: + """ + Adds a word into the data structure. + """ + self.trie.insert(word) + + def search(self, word: str) -> bool: + """ + Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. + """ + return self.trie.search(word) + + +# Your WordDictionary object will be instantiated and called as such: +# obj = WordDictionary() +# obj.addWord(word) +# param_2 = obj.search(word) +``` + +## 相关题目 + +- [0208.implement-trie-prefix-tree](./208.implement-trie-prefix-tree.md) +- [0212.word-search-ii](./212.word-search-ii.md) +- [0472.concatenated-words](./problems/472.concatenated-words.md) +- [0820.short-encoding-of-words](https://github.com/azl397985856/leetcode/blob/master/problems/820.short-encoding-of-words.md) diff --git a/spider/row-markdown/212.word-search-ii.md b/spider/row-markdown/212.word-search-ii.md new file mode 100644 index 0000000..fe978fa --- /dev/null +++ b/spider/row-markdown/212.word-search-ii.md @@ -0,0 +1,142 @@ +## 题目地址(212. 单词搜索 II) + +https://leetcode-cn.com/problems/word-search-ii/description/ + +## 题目描述 + +``` +给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。 + +单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。 + +示例: + +输入: +words = ["oath","pea","eat","rain"] and board = +[ + ['o','a','a','n'], + ['e','t','a','e'], + ['i','h','k','r'], + ['i','f','l','v'] +] + +输出: ["eat","oath"] +说明: +你可以假设所有输入都由小写字母 a-z 组成。 + +提示: + +你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯? +如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。 + +``` + +## 思路 + +我们需要对矩阵中每一项都进行深度优先遍历(DFS)。 递归的终点是 + +1. 超出边界 +2. 递归路径上组成的单词不在 words 的前缀。 + +比如题目示例:words = ["oath","pea","eat","rain"],那么对于 oa,oat 满足条件,因为他们都是 oath 的前缀,但是 oaa 就不满足条件。 + +为了防止环的出现,我们需要记录访问过的节点。而返回结果是需要去重的。出于简单考虑,我们使用集合(set),最后返回的时候重新转化为 list。 + +刚才我提到了一个关键词“前缀”,我们考虑使用前缀树来优化。使得复杂度降低为$O(h)$, 其中 h 是前缀树深度,也就是最长的字符串长度。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gb5dmstsxxj30mz0gqmzh.jpg) + +## 关键点 + +- 前缀树(也叫字典树),英文名 Trie(读作 tree 或者 try) +- DFS +- hashmap 结合 dfs 记录访问过的元素的时候,注意结束之后需要将 hashmap 的值重置。(下方代码的`del seen[(i, j)]`) + +## 代码 + +- 语言支持:Python3 + +Python3 Code: + +关于 Trie 的代码: + +```python +class Trie: + + def __init__(self): + """ + Initialize your data structure here. + """ + self.Trie = {} + + def insert(self, word): + """ + Inserts a word into the trie. + :type word: str + :rtype: void + """ + curr = self.Trie + for w in word: + if w not in curr: + curr[w] = {} + curr = curr[w] + curr['#'] = 1 + + def startsWith(self, prefix): + """ + Returns if there is any word in the trie that starts with the given prefix. + :type prefix: str + :rtype: bool + """ + + curr = self.Trie + for w in prefix: + if w not in curr: + return False + curr = curr[w] + return True +``` + +主逻辑代码: + +```python +class Solution: + def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: + m = len(board) + if m == 0: + return [] + n = len(board[0]) + trie = Trie() + seen = None + res = set() + for word in words: + trie.insert(word) + + def dfs(s, i, j): + if (i, j) in seen or i < 0 or i >= m or j < 0 or j >= n or not trie.startsWith(s): + return + s += board[i][j] + seen[(i, j)] = True + + if s in words: + res.add(s) + dfs(s, i + 1, j) + dfs(s, i - 1, j) + dfs(s, i, j + 1) + dfs(s, i, j - 1) + + del seen[(i, j)] + + for i in range(m): + for j in range(n): + seen = dict() + dfs("", i, j) + return list(res) +``` + +## 相关题目 + +- [0208.implement-trie-prefix-tree](./208.implement-trie-prefix-tree.md) +- [0211.add-and-search-word-data-structure-design](./211.add-and-search-word-data-structure-design.md) +- [0472.concatenated-words](./problems/472.concatenated-words.md) +- [0820.short-encoding-of-words](https://github.com/azl397985856/leetcode/blob/master/problems/820.short-encoding-of-words.md) diff --git a/spider/row-markdown/215.kth-largest-element-in-an-array.md b/spider/row-markdown/215.kth-largest-element-in-an-array.md new file mode 100644 index 0000000..47f7415 --- /dev/null +++ b/spider/row-markdown/215.kth-largest-element-in-an-array.md @@ -0,0 +1,155 @@ +## 题目地址 +https://leetcode.com/problems/kth-largest-element-in-an-array/ + +## 题目描述 + +``` +Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. + +Example 1: + +Input: [3,2,1,5,6,4] and k = 2 +Output: 5 +Example 2: + +Input: [3,2,3,1,2,4,5,5,6] and k = 4 +Output: 4 +Note: +You may assume k is always valid, 1 ≤ k ≤ array's length. +``` + +## 思路 + +这道题要求在一个无序的数组中,返回第K大的数。根据时间复杂度不同,这题有3种不同的解法。 + +#### 解法一 (排序) +很直观的解法就是给数组排序,这样求解第`K`大的数,就等于是从小到大排好序的数组的第`(n-K)`小的数 (n 是数组的长度)。 + +例如: +``` +[3,2,1,5,6,4], k = 2 +1. 数组排序: + [1,2,3,4,5,6], +2. 找第(n-k)小的数 + n-k=4, nums[4]=5 (第2大的数) +``` +*时间复杂度:* `O(nlogn) - n 是数组长度。` + +#### 解法二 - 小顶堆(Heap) +可以维护一个大小为`K`的小顶堆,堆顶是最小元素,当堆的`size > K` 的时候,删除堆顶元素. +扫描一遍数组,最后堆顶就是第`K`大的元素。 直接返回。 + +例如: +![heap](../assets/problems/215.kth-largest-element-in-an-array-heap.jpg) + +*时间复杂度*:`O(n * logk) , n is array length` +*空间复杂度*:`O(k)` + +跟排序相比,以空间换时间。 + +#### 解法三 - Quick Select + +Quick Select 类似快排,选取pivot,把小于pivot的元素都移到pivot之前,这样pivot所在位置就是第pivot index 小的元素。 +但是不需要完全给数组排序,只要找到当前pivot的位置是否是在第(n-k)小的位置,如果是,找到第k大的数直接返回。 + +具体步骤: +``` +1. 在数组区间随机取`pivot index = left + random[right-left]`. +2. 根据pivot 做 partition,在数组区间,把小于pivot的数都移到pivot左边。 +3. 得到pivot的位置 index,`compare(index, (n-k))`. + a. index == n-k -> 找到第`k`大元素,直接返回结果。 + b. index < n-k -> 说明在`index`右边,继续找数组区间`[index+1, right]` + c. index > n-k -> 那么第`k`大数在`index`左边,继续查找数组区间`[left, index-1]`. + +例子,【3,2,3,1,2,4,5,5,6], k = 4 + +如下图: +``` +![quick select](../assets/problems/215.kth-largest-element-in-an-array-quick-select.jpg) + +*时间复杂度*: + - 平均是:`O(n)` + - 最坏的情况是:`O(n * n)` + +## 关键点分析 +1. 直接排序很简单 +2. 堆(Heap)主要是要维护一个K大小的小顶堆,扫描一遍数组,最后堆顶元素即是所求。 +3. Quick Select, 关键是是取pivot,对数组区间做partition,比较pivot的位置,类似二分,取pivot左边或右边继续递归查找。 + +## 代码(Java code) +*解法一 - 排序* +```java +class KthLargestElementSort { + public int findKthlargest2(int[] nums, int k) { + Arrays.sort(nums); + return nums[nums.length - k]; + } +} +``` + +*解法二 - Heap (PriorityQueue)* +```java +class KthLargestElementHeap { + public int findKthLargest(int[] nums, int k) { + PriorityQueue pq = new PriorityQueue<>(); + for (int num : nums) { + pq.offer(num); + if (pq.size() > k) { + pq.poll(); + } + } + return pq.poll(); + } +} +``` + +*解法三 - Quick Select* +```java +class KthLargestElementQuickSelect { + static Random random = new Random(); + public int findKthLargest3(int[] nums, int k) { + int len = nums.length; + return select(nums, 0, len - 1, len - k); + } + + private int select(int[] nums, int left, int right, int k) { + if (left == right) return nums[left]; + // random select pivotIndex between left and right + int pivotIndex = left + random.nextInt(right - left); + // do partition, move smaller than pivot number into pivot left + int pos = partition(nums, left, right, pivotIndex); + if (pos == k) { + return nums[pos]; + } else if (pos > k) { + return select(nums, left, pos - 1, k); + } else { + return select(nums, pos + 1, right, k); + } + } + + private int partition(int[] nums, int left, int right, int pivotIndex) { + int pivot = nums[pivotIndex]; + // move pivot to end + swap(nums, right, pivotIndex); + int pos = left; + // move smaller num to pivot left + for (int i = left; i <= right; i++) { + if (nums[i] < pivot) { + swap(nums, pos++, i); + } + } + // move pivot to original place + swap(nums, right, pos); + return pos; + } + + private void swap(int[] nums, int i, int j) { + int tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + } +} +``` + +## 参考(References) +1. [Quick Select Wiki](https://en.wikipedia.org/wiki/Quickselect) \ No newline at end of file diff --git a/spider/row-markdown/219.contains-duplicate-ii.md b/spider/row-markdown/219.contains-duplicate-ii.md new file mode 100644 index 0000000..c2c85b9 --- /dev/null +++ b/spider/row-markdown/219.contains-duplicate-ii.md @@ -0,0 +1,137 @@ + +## 题目地址 +https://leetcode.com/problems/contains-duplicate-ii/description/ + +## 题目描述 + + +``` +Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k. + +Example 1: + +Input: nums = [1,2,3,1], k = 3 +Output: true +Example 2: + +Input: nums = [1,0,1,1], k = 1 +Output: true +Example 3: + +Input: nums = [1,2,3,1,2,3], k = 2 +Output: false + +``` + +## 思路 + +由于题目没有对空间复杂度有求,用一个hashmap 存储已经访问过的数字即可, +每次访问都会看hashmap中是否有这个元素,有的话拿出索引进行比对,是否满足条件(相隔不大于k),如果满足返回true即可。 + + +## 关键点解析 + +无 + + +## 代码 + +* 语言支持:JS,Python,C++ + +Javascript Code: + +```js +/* + * @lc app=leetcode id=219 lang=javascript + * + * [219] Contains Duplicate II + * + * https://leetcode.com/problems/contains-duplicate-ii/description/ + * + * algorithms + * Easy (34.75%) + * Total Accepted: 187.3K + * Total Submissions: 537.5K + * Testcase Example: '[1,2,3,1]\n3' + * + * Given an array of integers and an integer k, find out whether there are two + * distinct indices i and j in the array such that nums[i] = nums[j] and the + * absolute difference between i and j is at most k. + * + * + * Example 1: + * + * + * Input: nums = [1,2,3,1], k = 3 + * Output: true + * + * + * + * Example 2: + * + * + * Input: nums = [1,0,1,1], k = 1 + * Output: true + * + * + * + * Example 3: + * + * + * Input: nums = [1,2,3,1,2,3], k = 2 + * Output: false + * + * + * + * + * + */ +/** + * @param {number[]} nums + * @param {number} k + * @return {boolean} + */ +var containsNearbyDuplicate = function(nums, k) { + const visited = {}; + for(let i = 0; i < nums.length; i++) { + const num = nums[i]; + if (visited[num] !== undefined && i - visited[num] <= k) { + return true; + } + visited[num] = i; + } + return false +}; +``` + +Python Code: + +```python +class Solution: + def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool: + d = {} + for index, num in enumerate(nums): + if num in d and index - d[num] <= k: + return True + d[num] = index + return False +``` +C++ Code: +```C++ +class Solution { +public: + bool containsNearbyDuplicate(vector& nums, int k) { + auto m = unordered_map(); + for (int i = 0; i < nums.size(); ++i) { + auto iter = m.find(nums[i]); + if (iter != m.end()) { + if (i - m[nums[i]] <= k) { + return true; + } + } + m[nums[i]] = i; + } + return false; + } +}; +``` diff --git a/spider/row-markdown/22.GenerateParentheses.md b/spider/row-markdown/22.GenerateParentheses.md new file mode 100644 index 0000000..352f265 --- /dev/null +++ b/spider/row-markdown/22.GenerateParentheses.md @@ -0,0 +1,72 @@ +## 题目地址 +https://leetcode-cn.com/problems/generate-parentheses + +## 题目描述 +``` +数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 + +示例: + +输入:n = 3 +输出:[ + "((()))", + "(()())", + "(())()", + "()(())", + "()()()" + ] + +``` + +## 思路 + +深度优先搜索(回溯思想),从空字符串开始构造,做加法。 + + +## 关键点 + +- 当 l < r 时记得剪枝 + + +## 代码 +* 语言支持:JS + +```js +/** + * @param {number} n + * @return {string[]} + * @param l 左括号已经用了几个 + * @param r 右括号已经用了几个 + * @param str 当前递归得到的拼接字符串结果 + * @param res 结果集 + */ +const generateParenthesis = function (n) { + const res = []; + + function dfs(l, r, str) { + if (l == n && r == n) { + return res.push(str); + } + // l 小于 r 时不满足条件 剪枝 + if (l < r) { + return; + } + // l 小于 n 时可以插入左括号,最多可以插入 n 个 + if (l < n) { + dfs(l + 1, r, str + '('); + } + // r < l 时 可以插入右括号 + if (r < l) { + dfs(l, r + 1, str + ')'); + } + } + dfs(0, 0, ''); + return res; +}; +``` + + +***复杂度分析*** + +- 时间复杂度:O(2^N) +- 空间复杂度:O(2^N) diff --git a/spider/row-markdown/221.maximal-square.md b/spider/row-markdown/221.maximal-square.md new file mode 100644 index 0000000..7053d7b --- /dev/null +++ b/spider/row-markdown/221.maximal-square.md @@ -0,0 +1,127 @@ + +## 题目地址 + +https://leetcode.com/problems/maximal-square/ + +## 题目描述 + + +``` +Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area. + +Example: + +Input: + +1 0 1 0 0 +1 0 1 1 1 +1 1 1 1 1 +1 0 0 1 0 + +Output: 4 +``` + +## 思路 + +![221.maximal-square](../assets/problems/221.maximal-square-1.jpg) + +符合直觉的做法是暴力求解处所有的正方形,逐一计算面积,然后记录最大的。这种时间复杂度很高。 + +我们考虑使用动态规划,我们使用dp[i][j]表示以matrix[i][j]为右下角的顶点的可以组成的最大正方形的边长。 +那么我们只需要计算所有的i,j组合,然后求出最大值即可。 + +我们来看下dp[i][j] 怎么推导。 首先我们要看matrix[i][j], 如果matrix[i][j]等于0,那么就不用看了,直接等于0。 +如果matrix[i][j]等于1,那么我们将matrix[[i][j]分别往上和往左进行延伸,直到碰到一个0为止。 + +如图 dp[3][3] 的计算。 matrix[3][3]等于1,我们分别往上和往左进行延伸,直到碰到一个0为止,上面长度为1,左边为3。 +dp[2][2]等于1(之前已经计算好了),那么其实这里的瓶颈在于三者的最小值, 即`Min(1, 1, 3)`, 也就是`1`。 那么dp[3][3] 就等于 +`Min(1, 1, 3) + 1`。 + +![221.maximal-square](../assets/problems/221.maximal-square-2.jpg) + +dp[i - 1][j - 1]我们直接拿到,关键是`往上和往左进行延伸`, 最直观的做法是我们内层加一个循环去做就好了。 +但是我们仔细观察一下,其实我们根本不需要这样算。 我们可以直接用dp[i - 1][j]和dp[i][j -1]。 +具体就是`Min(dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]) + 1`。 + +![221.maximal-square](../assets/problems/221.maximal-square-3.jpg) + +事实上,这道题还有空间复杂度O(N)的解法,其中N指的是列数。 +大家可以去这个[leetcode讨论](https://leetcode.com/problems/maximal-square/discuss/61803/C%2B%2B-space-optimized-DP)看一下。 +## 关键点解析 + +- DP +- 递归公式可以利用dp[i - 1][j]和dp[i][j -1]的计算结果,而不用重新计算 +- 空间复杂度可以降低到O(n), n为列数 + +## 代码 + +代码支持:Python,JavaScript: + +Python Code: + +```python +class Solution: + def maximalSquare(self, matrix: List[List[str]]) -> int: + res = 0 + m = len(matrix) + if m == 0: + return 0 + n = len(matrix[0]) + dp = [[0] * (n + 1) for _ in range(m + 1)] + + for i in range(1, m + 1): + for j in range(1, n + 1): + dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 if matrix[i - 1][j - 1] == "1" else 0 + res = max(res, dp[i][j]) + return res ** 2 +``` + + +JavaScript Code: + +```js + +/* + * @lc app=leetcode id=221 lang=javascript + * + * [221] Maximal Square + */ +/** + * @param {character[][]} matrix + * @return {number} + */ +var maximalSquare = function(matrix) { + if (matrix.length === 0) return 0; + const dp = []; + const rows = matrix.length; + const cols = matrix[0].length; + let max = Number.MIN_VALUE; + + for (let i = 0; i < rows + 1; i++) { + if (i === 0) { + dp[i] = Array(cols + 1).fill(0); + } else { + dp[i] = [0]; + } + } + + for (let i = 1; i < rows + 1; i++) { + for (let j = 1; j < cols + 1; j++) { + if (matrix[i - 1][j - 1] === "1") { + dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1; + max = Math.max(max, dp[i][j]); + } else { + dp[i][j] = 0; + } + } + } + + return max * max; +}; +``` + + +***复杂度分析*** + +- 时间复杂度:$O(M * N)$,其中M为行数,N为列数。 +- 空间复杂度:$O(M * N)$,其中M为行数,N为列数。 diff --git a/spider/row-markdown/226.invert-binary-tree.md b/spider/row-markdown/226.invert-binary-tree.md new file mode 100644 index 0000000..664bcf1 --- /dev/null +++ b/spider/row-markdown/226.invert-binary-tree.md @@ -0,0 +1,183 @@ + +## 题目地址 +https://leetcode.com/problems/invert-binary-tree/description/ + +## 题目描述 + +``` +Invert a binary tree. + +Example: + +Input: + + 4 + / \ + 2 7 + / \ / \ +1 3 6 9 +Output: + + 4 + / \ + 7 2 + / \ / \ +9 6 3 1 +Trivia: +This problem was inspired by this original tweet by Max Howell: + +Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off. +``` + +## 思路 +遍历树(随便怎么遍历),然后将左右子树交换位置。 +## 关键点解析 + +- 递归简化操作 +- 如果树很高,建议使用栈来代替递归 +- 这道题目对顺序没要求的,因此队列数组操作都是一样的,无任何区别 + +## 代码 + +* 语言支持:JS,Python,C++ + +Javascript Code: + +```js +/* + * @lc app=leetcode id=226 lang=javascript + * + * [226] Invert Binary Tree + * + * https://leetcode.com/problems/invert-binary-tree/description/ + * + * algorithms + * Easy (57.14%) + * Total Accepted: 311K + * Total Submissions: 540.6K + * Testcase Example: '[4,2,7,1,3,6,9]' + * + * Invert a binary tree. + * + * Example: + * + * Input: + * + * + * ⁠ 4 + * ⁠ / \ + * ⁠ 2 7 + * ⁠/ \ / \ + * 1 3 6 9 + * + * Output: + * + * + * ⁠ 4 + * ⁠ / \ + * ⁠ 7 2 + * ⁠/ \ / \ + * 9 6 3 1 + * + * Trivia: + * This problem was inspired by this original tweet by Max Howell: + * + * Google: 90% of our engineers use the software you wrote (Homebrew), but you + * can’t invert a binary tree on a whiteboard so f*** off. + * + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +var invertTree = function(root) { + if (!root) return root; + // 递归 + // const left = root.left; + // const right = root.right; + // root.right = invertTree(left); + // root.left = invertTree(right); + // 我们用stack来模拟递归 + // 本质上递归是利用了执行栈,执行栈也是一种栈 + // 其实这里使用队列也是一样的,因为这里顺序不重要 + + const stack = [root]; + let current = null; + while ((current = stack.shift())) { + const left = current.left; + const right = current.right; + current.right = left; + current.left = right; + if (left) { + stack.push(left); + } + if (right) { + stack.push(right); + } + } + return root; +}; +``` + +Python Code: + +```python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + def invertTree(self, root: TreeNode) -> TreeNode: + if not root: + return None + stack = [root] + while stack: + node = stack.pop(0) + node.left, node.right = node.right, node.left + if node.left: + stack.append(node.left) + if node.right: + stack.append(node.right) + return root +``` +C++ Code: +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + TreeNode* invertTree(TreeNode* root) { + if (root == NULL) return root; + auto q = queue(); + q.push(root); + while (!q.empty()) { + auto n = q.front(); q.pop(); + swap(n->left, n->right); + if (n->left != nullptr) { + q.push(n->left); + } + if (n->right != nullptr) { + q.push(n->right); + } + } + return root; + } +}; +``` diff --git a/spider/row-markdown/229.majority-element-ii.md b/spider/row-markdown/229.majority-element-ii.md new file mode 100644 index 0000000..bbe4b64 --- /dev/null +++ b/spider/row-markdown/229.majority-element-ii.md @@ -0,0 +1,167 @@ + +## 题目地址 +https://leetcode.com/problems/majority-element-ii/description/ + +## 题目描述 + +``` +Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. + +Note: The algorithm should run in linear time and in O(1) space. + +Example 1: + +Input: [3,2,3] +Output: [3] +Example 2: + +Input: [1,1,1,3,3,2,2,2] +Output: [1,2] +``` + +## 思路 + +这道题目和[169.majority-element](./169.majority-element.md) 很像。 + +我们仍然可以采取同样的方法 - “摩尔投票法”, 具体的思路可以参考上面的题目。 + +但是这里有一个不同的是这里的众数不再是超过`1 / 2`,而是超过`1 / 3`。 +题目也说明了,超过三分之一的有可能有多个(实际上就是0,1,2三种可能)。 + +因此我们不能只用一个counter来解决了。 我们的思路是同时使用两个counter,其他思路和上一道题目一样。 + +最后需要注意的是两个counter不一定都满足条件,这两个counter只是出现次数最多的两个数字。 +有可能不满足出现次数大于1/3, 因此最后我们需要进行过滤筛选。 + +这里画了一个图,大家可以感受一下: + +![229.majority-element-ii-1](../assets/problems/229.majority-element-ii-1.jpeg) + +![229.majority-element-ii-1](../assets/problems/229.majority-element-ii-2.jpeg) + + + +## 关键点解析 + +- 摩尔投票法 +- 两个counter +- 最后得到的只是出现次数最多的两个数字,有可能不满足出现次数大于1/3 + +## 代码 + +JavaScript代码: + +```js +/* + * @lc app=leetcode id=229 lang=javascript + * + * [229] Majority Element II + */ +/** + * @param {number[]} nums + * @return {number[]} + */ +var majorityElement = function(nums) { + const res = []; + const len = nums.length; + let n1 = null, + n2 = null, + cnt1 = 0, + cnt2 = 0; + + for (let i = 0; i < len; i++) { + if (n1 === nums[i]) { + cnt1++; + } else if (n2 === nums[i]) { + cnt2++; + } else if (cnt1 === 0) { + n1 = nums[i]; + cnt1++; + } else if (cnt2 === 0) { + n2 = nums[i]; + cnt2++; + } else { + cnt1--; + cnt2--; + } + } + + cnt1 = 0; + cnt2 = 0; + + for (let i = 0; i < len; i++) { + if (n1 === nums[i]) { + cnt1++; + } else if (n2 === nums[i]) { + cnt2++; + } + } + + if (cnt1 > (len / 3) >>> 0) { + res.push(n1); + } + if (cnt2 > (len / 3) >>> 0) { + res.push(n2); + } + + return res; +}; + +``` + +Java代码: + +```java +/* + * @lc app=leetcode id=229 lang=java + * + * [229] Majority Element II + */ +class Solution { + public List majorityElement(int[] nums) { + List res = new ArrayList(); + if (nums == null || nums.length == 0) + return res; + int n1 = nums[0], n2 = nums[0], cnt1 = 0, cnt2 = 0, len = nums.length; + for (int i = 0; i < len; i++) { + if (nums[i] == n1) + cnt1++; + else if (nums[i] == n2) + cnt2++; + else if (cnt1 == 0) { + n1 = nums[i]; + cnt1 = 1; + } else if (cnt2 == 0) { + n2 = nums[i]; + cnt2 = 1; + } else { + cnt1--; + cnt2--; + } + } + cnt1 = 0; + cnt2 = 0; + for (int i = 0; i < len; i++) { + if (nums[i] == n1) + cnt1++; + else if (nums[i] == n2) + cnt2++; + } + if (cnt1 > len / 3) + res.add(n1); + if (cnt2 > len / 3 && n1 != n2) + res.add(n2); + return res; + } +} + +``` + + +## 扩展 + +如果题目中3变成了k,怎么解决? + +大家可以自己思考一下,我这里给一个参考链接:https://leetcode.com/problems/majority-element-ii/discuss/63500/JAVA-Easy-Version-To-Understand!!!!!!!!!!!!/64925 + +这个实现说实话不是很好,大家可以优化一下。 diff --git a/spider/row-markdown/23.merge-k-sorted-lists.md b/spider/row-markdown/23.merge-k-sorted-lists.md new file mode 100644 index 0000000..ba72dd0 --- /dev/null +++ b/spider/row-markdown/23.merge-k-sorted-lists.md @@ -0,0 +1,162 @@ +## 题目地址(23. 合并 K 个排序链表) + +https://leetcode-cn.com/problems/merge-k-sorted-lists/description/ + +## 题目描述 + +合并  k  个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 + +示例: + +输入: +[ +  1->4->5, +  1->3->4, +  2->6 +] +输出: 1->1->2->3->4->4->5->6 + +## 思路 + +这道题目是合并 k 个已排序的链表,号称 leetcode 目前`最难`的链表题。 和之前我们解决的[88.merge-sorted-array](./88.merge-sorted-array.md)很像。 +他们有两点区别: + +1. 这道题的数据结构是链表,那道是数组。这个其实不复杂,毕竟都是线性的数据结构。 + +2. 这道题需要合并 k 个元素,那道则只需要合并两个。这个是两题的关键差别,也是这道题难度为`hard`的原因。 + +因此我们可以看出,这道题目是`88.merge-sorted-array`的进阶版本。其实思路也有点像,我们来具体分析下第二条。 +如果你熟悉合并排序的话,你会发现它就是`合并排序的一部分`。 + +具体我们可以来看一个动画 + +![23.merge-k-sorted-lists](../assets/problems/23.merge-k-sorted-lists.gif) + +(动画来自 https://zhuanlan.zhihu.com/p/61796021 ) + +## 关键点解析 + +- 分治 +- 归并排序(merge sort) + +## 代码 + +代码支持 JavaScript, Python3 + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=23 lang=javascript + * + * [23] Merge k Sorted Lists + * + * https://leetcode.com/problems/merge-k-sorted-lists/description/ + * + */ +function mergeTwoLists(l1, l2) { + const dummyHead = {}; + let current = dummyHead; + // l1: 1 -> 3 -> 5 + // l2: 2 -> 4 -> 6 + while (l1 !== null && l2 !== null) { + if (l1.val < l2.val) { + current.next = l1; // 把小的添加到结果链表 + current = current.next; // 移动结果链表的指针 + l1 = l1.next; // 移动小的那个链表的指针 + } else { + current.next = l2; + current = current.next; + l2 = l2.next; + } + } + + if (l1 === null) { + current.next = l2; + } else { + current.next = l1; + } + return dummyHead.next; +} +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode[]} lists + * @return {ListNode} + */ +var mergeKLists = function(lists) { + // 图参考: https://zhuanlan.zhihu.com/p/61796021 + if (lists.length === 0) return null; + if (lists.length === 1) return lists[0]; + if (lists.length === 2) { + return mergeTwoLists(lists[0], lists[1]); + } + + const mid = lists.length >> 1; + const l1 = []; + for (let i = 0; i < mid; i++) { + l1[i] = lists[i]; + } + + const l2 = []; + for (let i = mid, j = 0; i < lists.length; i++, j++) { + l2[j] = lists[i]; + } + + return mergeTwoLists(mergeKLists(l1), mergeKLists(l2)); +}; +``` + +Python3 Code: + +``` python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def mergeKLists(self, lists: List[ListNode]) -> ListNode: + n = len(lists) + + # basic cases + if lenth == 0: return None + if lenth == 1: return lists[0] + if lenth == 2: return self.mergeTwoLists(lists[0], lists[1]) + + # divide and conqure if not basic cases + mid = n // 2 + return self.mergeTwoLists(self.mergeKLists(lists[:mid]), self.mergeKLists(lists[mid:n])) + + + def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: + res = ListNode(0) + c1, c2, c3 = l1, l2, res + while c1 or c2: + if c1 and c2: + if c1.val < c2.val: + c3.next = ListNode(c1.val) + c1 = c1.next + else: + c3.next = ListNode(c2.val) + c2 = c2.next + c3 = c3.next + elif c1: + c3.next = c1 + break + else: + c3.next = c2 + break + + return res.next +``` + +## 相关题目 + +- [88.merge-sorted-array](./88.merge-sorted-array.md) diff --git a/spider/row-markdown/230.kth-smallest-element-in-a-bst.md b/spider/row-markdown/230.kth-smallest-element-in-a-bst.md new file mode 100644 index 0000000..b11e07d --- /dev/null +++ b/spider/row-markdown/230.kth-smallest-element-in-a-bst.md @@ -0,0 +1,189 @@ +## 题目地址 + +https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/ + +## 题目描述 + +``` +Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. + +Note: +You may assume k is always valid, 1 ≤ k ≤ BST's total elements. + +Example 1: + +Input: root = [3,1,4,null,2], k = 1 + 3 + / \ + 1 4 + \ + 2 +Output: 1 +Example 2: + +Input: root = [5,3,6,2,4,null,null,1], k = 3 + 5 + / \ + 3 6 + / \ + 2 4 + / + 1 +Output: 3 +Follow up: +What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? + +``` + +## 思路 + +解法一: + +由于‘中序遍历一个二叉查找树(BST)的结果是一个有序数组’ ,因此我们只需要在遍历到第k个,返回当前元素即可。 +中序遍历相关思路请查看[binary-tree-traversal](../thinkings/binary-tree-traversal.md) + +解法二: + +联想到二叉搜索树的性质,root 大于左子树,小于右子树,如果左子树的节点数目等于 K-1,那么 root 就是结果,否则如果左子树节点数目小于 K-1,那么结果必然在右子树,否则就在左子树。 +因此在搜索的时候同时返回节点数目,跟 K 做对比,就能得出结果了。 + + +## 关键点解析 + +- 中序遍历 + +## 代码 + +解法一: + +JavaScript Code: + +```js + + +/* + * @lc app=leetcode id=230 lang=javascript + * + * [230] Kth Smallest Element in a BST + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} k + * @return {number} + */ +var kthSmallest = function(root, k) { + const stack = [root]; + let cur = root; + let i = 0; + + function insertAllLefts(cur) { + while(cur && cur.left) { + const l = cur.left; + stack.push(l); + cur = l; + } + } + insertAllLefts(cur); + + while(cur = stack.pop()) { + i++; + if (i === k) return cur.val; + const r = cur.right; + + if (r) { + stack.push(r); + insertAllLefts(r); + } + } + + return -1; + + +}; +``` + +Java Code: + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +private int count = 1; +private int res; + +public int KthSmallest (TreeNode root, int k) { + inorder(root, k); + return res; +} + +public void inorder (TreeNode root, int k) { + if (root == null) return; + + inorder(root.left, k); + + if (count++ == k) { + res = root.val; + return; + } + + inorder(root.right, k); +} +``` + +解法二: + +JavaScript Code: + +```js + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +function nodeCount(node) { + if (node === null) return 0; + + const l = nodeCount(node.left); + const r = nodeCount(node.right); + + return 1 + l + r; +} +/** + * @param {TreeNode} root + * @param {number} k + * @return {number} + */ +var kthSmallest = function(root, k) { + const c = nodeCount(root.left); + if (c === k - 1) return root.val; + else if (c < k - 1) return kthSmallest(root.right, k - c - 1); + return kthSmallest(root.left, k) +}; + +``` + +## 扩展 + +这道题有一个follow up: + +`What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? + How would you optimize the kthSmallest routine?` + +大家可以思考一下。 + diff --git a/spider/row-markdown/232.implement-queue-using-stacks.md b/spider/row-markdown/232.implement-queue-using-stacks.md new file mode 100644 index 0000000..d5f4b1e --- /dev/null +++ b/spider/row-markdown/232.implement-queue-using-stacks.md @@ -0,0 +1,252 @@ +## 题目地址 + +https://leetcode.com/problems/implement-queue-using-stacks/description/ + +## 题目描述 + +``` +Implement the following operations of a queue using stacks. + +push(x) -- Push element x to the back of queue. +pop() -- Removes the element from in front of queue. +peek() -- Get the front element. +empty() -- Return whether the queue is empty. +Example: + +MyQueue queue = new MyQueue(); + +queue.push(1); +queue.push(2); +queue.peek(); // returns 1 +queue.pop(); // returns 1 +queue.empty(); // returns false +Notes: + +You must use only standard operations of a stack -- which means only push to top, peek/pop from top, size, and is empty operations are valid. +Depending on your language, stack may not be supported natively. You may simulate a stack by using a list or deque (double-ended queue), as long as you use only standard operations of a stack. +You may assume that all operations are valid (for example, no pop or peek operations will be called on an empty queue). +``` + +## 思路 + +这道题目是让我们用栈来模拟实现队列。 我们知道栈和队列都是一种受限的数据结构。 +栈的特点是只能在一端进行所有操作,队列的特点是只能在一端入队,另一端出队。 + +在这里我们可以借助另外一个栈,也就是说用两个栈来实现队列的效果。这种做法的时间复杂度和空间复杂度都是O(n)。 + +由于栈只能操作一端,因此我们peek或者pop的时候也只去操作顶部元素,要达到目的 +我们需要在push的时候将队头的元素放到栈顶即可。 + +因此我们只需要在push的时候,用一下辅助栈即可。 +具体做法是先将栈清空并依次放到另一个辅助栈中,辅助栈中的元素再次放回栈中,最后将新的元素push进去即可。 + +比如我们现在栈中已经是1,2,3,4了。 我们现在要push一个5. + +push之前是这样的: + +![232.implement-queue-using-stacks.drawio](../assets/problems/232.implement-queue-using-stacks-1.jpg) + +然后我们将栈中的元素转移到辅助栈: + +![232.implement-queue-using-stacks.drawio](../assets/problems/232.implement-queue-using-stacks-2.jpg) + +最后将新的元素添加到栈顶。 + +![232.implement-queue-using-stacks.drawio](../assets/problems/232.implement-queue-using-stacks-3.jpg) + + +整个过程是这样的: + +![232.implement-queue-using-stacks.drawio](../assets/problems/232.implement-queue-using-stacks-4.jpg) +## 关键点解析 + +- 在push的时候利用辅助栈(双栈) + +## 代码 + +* 语言支持:JS, Python, Java + +Javascript Code: + +```js +/* + * @lc app=leetcode id=232 lang=javascript + * + * [232] Implement Queue using Stacks + */ +/** + * Initialize your data structure here. + */ +var MyQueue = function() { + // tag: queue stack array + this.stack = []; + this.helperStack = []; +}; + +/** + * Push element x to the back of queue. + * @param {number} x + * @return {void} + */ +MyQueue.prototype.push = function(x) { + let cur = null; + while ((cur = this.stack.pop())) { + this.helperStack.push(cur); + } + this.helperStack.push(x); + + while ((cur = this.helperStack.pop())) { + this.stack.push(cur); + } +}; + +/** + * Removes the element from in front of queue and returns that element. + * @return {number} + */ +MyQueue.prototype.pop = function() { + return this.stack.pop(); +}; + +/** + * Get the front element. + * @return {number} + */ +MyQueue.prototype.peek = function() { + return this.stack[this.stack.length - 1]; +}; + +/** + * Returns whether the queue is empty. + * @return {boolean} + */ +MyQueue.prototype.empty = function() { + return this.stack.length === 0; +}; + +/** + * Your MyQueue object will be instantiated and called as such: + * var obj = new MyQueue() + * obj.push(x) + * var param_2 = obj.pop() + * var param_3 = obj.peek() + * var param_4 = obj.empty() + */ +``` + +Python Code: + +```python +class MyQueue: + + def __init__(self): + """ + Initialize your data structure here. + """ + self.stack = [] + self.help_stack = [] + + def push(self, x: int) -> None: + """ + Push element x to the back of queue. + """ + while self.stack: + self.help_stack.append(self.stack.pop()) + self.help_stack.append(x) + while self.help_stack: + self.stack.append(self.help_stack.pop()) + + def pop(self) -> int: + """ + Removes the element from in front of queue and returns that element. + """ + return self.stack.pop() + + def peek(self) -> int: + """ + Get the front element. + """ + return self.stack[-1] + + def empty(self) -> bool: + """ + Returns whether the queue is empty. + """ + return not bool(self.stack) + + +# Your MyQueue object will be instantiated and called as such: +# obj = MyQueue() +# obj.push(x) +# param_2 = obj.pop() +# param_3 = obj.peek() +# param_4 = obj.empty() +``` + +Java Code + +```java +class MyQueue { + Stack pushStack = new Stack<> (); + Stack popStack = new Stack<> (); + + /** Initialize your data structure here. */ + public MyQueue() { + + } + + /** Push element x to the back of queue. */ + public void push(int x) { + while (!popStack.isEmpty()) { + pushStack.push(popStack.pop()); + } + pushStack.push(x); + } + + /** Removes the element from in front of queue and returns that element. */ + public int pop() { + while (!pushStack.isEmpty()) { + popStack.push(pushStack.pop()); + } + return popStack.pop(); + } + + /** Get the front element. */ + public int peek() { + while (!pushStack.isEmpty()) { + popStack.push(pushStack.pop()); + } + return popStack.peek(); + } + + /** Returns whether the queue is empty. */ + public boolean empty() { + return pushStack.isEmpty() && popStack.isEmpty(); + } +} + +/** + * Your MyQueue object will be instantiated and called as such: + * MyQueue obj = new MyQueue(); + * obj.push(x); + * int param_2 = obj.pop(); + * int param_3 = obj.peek(); + * boolean param_4 = obj.empty(); + */ +```` + +## 扩展 + - 类似的题目有用队列实现栈,思路是完全一样的,大家有兴趣可以试一下。 + - 栈混洗也是借助另外一个栈来完成的,从这点来看,两者有相似之处。 + +## 延伸阅读 + +实际上现实中也有使用两个栈来实现队列的情况,那么为什么我们要用两个stack来实现一个queue? + +其实使用两个栈来替代一个队列的实现是为了在多进程中分开对同一个队列对读写操作。一个栈是用来读的,另一个是用来写的。当且仅当读栈满时或者写栈为空时,读写操作才会发生冲突。 + +当只有一个线程对栈进行读写操作的时候,总有一个栈是空的。在多线程应用中,如果我们只有一个队列,为了线程安全,我们在读或者写队列的时候都需要锁住整个队列。而在两个栈的实现中,只要写入栈不为空,那么`push`操作的锁就不会影响到`pop`。 + +- [reference](https://leetcode.com/problems/implement-queue-using-stacks/discuss/64284/Do-you-know-when-we-should-use-two-stacks-to-implement-a-queue) + +- [further reading](https://stackoverflow.com/questions/2050120/why-use-two-stacks-to-make-a-queue/2050402#2050402) diff --git a/spider/row-markdown/236.lowest-common-ancestor-of-a-binary-tree.md b/spider/row-markdown/236.lowest-common-ancestor-of-a-binary-tree.md new file mode 100644 index 0000000..f5a85d6 --- /dev/null +++ b/spider/row-markdown/236.lowest-common-ancestor-of-a-binary-tree.md @@ -0,0 +1,129 @@ +## 题目地址 + +https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/ + +## 题目描述 + +``` +Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. + +According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).” + +Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4] + +``` +![236.lowest-common-ancestor-of-a-binary-tree](../assets/problems/236.lowest-common-ancestor-of-a-binary-tree-1.png) + +``` +Example 1: + +Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 +Output: 3 +Explanation: The LCA of nodes 5 and 1 is 3. +Example 2: + +Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 +Output: 5 +Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition. + + +Note: + +All of the nodes' values will be unique. +p and q are different and both values will exist in the binary tree. +``` + +## 思路 + +这道题目是求解二叉树中,两个给定节点的最近的公共祖先。是一道非常经典的二叉树题目。 + +我们之前说过树是一种递归的数据结构,因此使用递归方法解决二叉树问题从写法上来看是最简单的,这道题目也不例外。 + +用递归的思路去思考树是一种非常重要的能力。 + + +如果大家这样去思考的话,问题就会得到简化,我们的目标就是分别在左右子树进行查找p和q。 如果p没有在左子树,那么它一定在右子树(题目限定p一定在树中), +反之亦然。 + +对于具体的代码而言就是,我们假设这个树就一个结构,然后尝试去解决,然后在适当地方去递归自身即可。 如下图所示: + +![236.lowest-common-ancestor-of-a-binary-tree-2](../assets/problems/236.lowest-common-ancestor-of-a-binary-tree-2.png) + +我们来看下核心代码: + +```js + // 如果我们找到了p,直接进行返回,那如果下面就是q呢? 其实这没有影响,但是还是要多考虑一下 + if (!root || root === p || root === q) return root; + const left = lowestCommonAncestor(root.left, p, q); // 去左边找,我们期望返回找到的节点 + const right = lowestCommonAncestor(root.right, p, q);// 去右边找,我们期望返回找到的节点 + if (!left) return right; // 左子树找不到,返回右子树 + if (!right) return left; // 右子树找不到,返回左子树 + return root; // 左右子树分别有一个,则返回root + +``` + +> 如果没有明白的话,请多花时间消化一下 + +## 关键点解析 + +- 用递归的思路去思考树 + +## 代码 + +代码支持: JavaScript, Python3 + +- JavaScript Code: + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} p + * @param {TreeNode} q + * @return {TreeNode} + */ +var lowestCommonAncestor = function(root, p, q) { + if (!root || root === p || root === q) return root; + const left = lowestCommonAncestor(root.left, p, q); + const right = lowestCommonAncestor(root.right, p, q); + if (!left) return right; // 左子树找不到,返回右子树 + if (!right) return left; // 右子树找不到,返回左子树 + return root; // 左右子树分别有一个,则返回root +}; +``` + +- Python Code: + +``` python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + if not root or root == p or root == q: + return root + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + + if not left: + return right + if not right: + return left + else: + return root + +``` + +## 扩展 +如果递归的结束条件改为`if (!root || root.left === p || root.right === q) return root;` 代表的是什么意思,对结果有什么样的影响? + diff --git a/spider/row-markdown/238.product-of-array-except-self.md b/spider/row-markdown/238.product-of-array-except-self.md new file mode 100644 index 0000000..ab8a79f --- /dev/null +++ b/spider/row-markdown/238.product-of-array-except-self.md @@ -0,0 +1,84 @@ +## 题目地址(238. 除自身以外数组的乘积) + +https://leetcode.com/problems/product-of-array-except-self/description/ + +## 题目描述 + +``` +给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。 + +  + +示例: + +输入: [1,2,3,4] +输出: [24,12,8,6] +  + +提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。 + +说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。 + +进阶: +你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。) + + +``` + +## 思路 + +这道题的意思是给定一个数组,返回一个新的数组,这个数组每一项都是其他项的乘积。 +符合直觉的思路是两层循环,时间复杂度是O(n^2),但是题目要求`Please solve it without division and in O(n)`。 + +因此我们需要换一种思路,由于输出的每一项都需要用到别的元素,因此一次遍历是绝对不行的。 +考虑我们先进行一次遍历, 然后维护一个数组,第i项代表前i个元素(不包括i)的乘积。 +然后我们反向遍历一次,然后维护另一个数组,同样是第i项代表前i个元素(不包括i)的乘积。 + +![238.product-of-array-except-self](../assets/problems/238.product-of-array-except-self.png) + +有意思的是第一个数组和第二个数组的反转(reverse)做乘法(有点像向量运算)就是我们想要的运算。 + +其实我们进一步观察,我们不需要真的创建第二个数组(第二个数组只是做中间运算使用),而是直接修改第一个数组即可。 + +## 关键点解析 + +- 两次遍历, 一次正向,一次反向。 +- 维护一个数组,第i项代表前i个元素(不包括i)的乘积 + +## 代码 + +```js +/** + * @param {number[]} nums + * @return {number[]} + */ +var productExceptSelf = function(nums) { + const ret = []; + + for (let i = 0, temp = 1; i < nums.length; i++) { + ret[i] = temp; + temp *= nums[i]; + } + // 此时ret[i]存放的是前i个元素相乘的结果(不包含第i个) + + // 如果没有上面的循环的话, + // ret经过下面的循环会变成ret[i]存放的是后i个元素相乘的结果(不包含第i个) + + // 我们的目标是ret[i]存放的所有数字相乘的结果(不包含第i个) + + // 因此我们只需要对于上述的循环产生的ret[i]基础上运算即可 + for (let i = nums.length - 1, temp = 1; i >= 0; i--) { + ret[i] *= temp; + temp *= nums[i]; + } + return ret; +}; +``` + +***复杂度分析*** +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(N)$ + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。 + +大家也可以关注我的公众号《力扣加加》获取更多更新鲜的LeetCode题解 diff --git a/spider/row-markdown/239.sliding-window-maximum.md b/spider/row-markdown/239.sliding-window-maximum.md new file mode 100644 index 0000000..f45f39c --- /dev/null +++ b/spider/row-markdown/239.sliding-window-maximum.md @@ -0,0 +1,142 @@ +## 题目地址 + +https://leetcode.com/problems/sliding-window-maximum/description/ + +## 题目描述 + +``` +Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window. + +Example: + +Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 +Output: [3,3,5,5,6,7] +Explanation: + +Window position Max +--------------- ----- +[1 3 -1] -3 5 3 6 7 3 + 1 [3 -1 -3] 5 3 6 7 3 + 1 3 [-1 -3 5] 3 6 7 5 + 1 3 -1 [-3 5 3] 6 7 5 + 1 3 -1 -3 [5 3 6] 7 6 + 1 3 -1 -3 5 [3 6 7] 7 +Note: +You may assume k is always valid, 1 ≤ k ≤ input array's size for non-empty array. + +Follow up: +Could you solve it in linear time? +``` + +## 思路 + +符合直觉的想法是直接遍历 nums, 然后然后用一个变量 slideWindow 去承载 k 个元素, +然后对 slideWindow 求最大值,这是可以的,时间复杂度是 O(n \* k).代码如下: + +JavaScript: + +```js +var maxSlidingWindow = function(nums, k) { + // bad 时间复杂度O(n * k) + if (nums.length === 0 || k === 0) return []; + let slideWindow = []; + const ret = []; + for (let i = 0; i < nums.length - k + 1; i++) { + for (let j = 0; j < k; j++) { + slideWindow.push(nums[i + j]); + } + ret.push(Math.max(...slideWindow)); + slideWindow = []; + } + return ret; +}; +``` +Python3: + +```python +class Solution: + def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: + if k == 0: return [] + res = [] + for r in range(k - 1, len(nums)): + res.append(max(nums[r - k + 1:r + 1])) + return res +``` + +但是如果真的是这样,这道题也不会是 hard 吧?这道题有一个 follow up,要求你用线性的时间去完成。 +我们可以用双端队列来完成,思路是用一个双端队列来保存`接下来的滑动窗口可能成为最大值的数`。具体做法: + + +- 入队列 + +- 移除失效元素,失效元素有两种 + +1. 一种是已经超出窗口范围了,比如我遍历到第4个元素,k = 3,那么i = 0的元素就不应该出现在双端队列中了 +具体就是`索引大于 i - k + 1的元素都应该被清除` + +2. 小于当前元素都没有利用价值了,具体就是`从后往前遍历(双端队列是一个递减队列)双端队列,如果小于当前元素就出队列` + + +如果你仔细观察的话,发现双端队列其实是一个递减的一个队列。因此队首的元素一定是最大的。用图来表示就是: + +![](https://tva1.sinaimg.cn/large/0082zybply1gbvyn8ufbvj30hb0di75s.jpg) + +## 关键点解析 + +- 双端队列简化时间复杂度 + +- 滑动窗口 + +## 代码 + + +JavaScript: + +```js +var maxSlidingWindow = function(nums, k) { + // 双端队列优化时间复杂度, 时间复杂度O(n) + const deque = []; // 存放在接下来的滑动窗口可能成为最大值的数 + const ret = []; + for (let i = 0; i < nums.length; i++) { + // 清空失效元素 + while (deque[0] < i - k + 1) { + deque.shift(); + } + + while (nums[deque[deque.length - 1]] < nums[i]) { + deque.pop(); + } + + deque.push(i); + + if (i >= k - 1) { + ret.push(nums[deque[0]]); + } + } + return ret; +}; +``` + +Python3: + +```python +class Solution: + def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: + deque, res, n = [], [], len(nums) + for i in range(n): + while deque and deque[0] < i - k + 1: + deque.pop(0) + while deque and nums[i] > nums[deque[-1]]: + deque.pop(-1) + deque.append(i) + if i >= k - 1: res.append(nums[deque[0]]) + return res + + +``` + +## 扩展 + +### 为什么用双端队列 +因为删除无效元素的时候,会清除队首的元素(索引太小了 +)或者队尾(元素太小了)的元素。 因此需要同时对队首和队尾进行操作,使用双端队列是一种合乎情理的做法。 diff --git a/spider/row-markdown/24.swapNodesInPairs.md b/spider/row-markdown/24.swapNodesInPairs.md new file mode 100644 index 0000000..368a353 --- /dev/null +++ b/spider/row-markdown/24.swapNodesInPairs.md @@ -0,0 +1,94 @@ +## 题目地址 +https://leetcode.com/problems/swap-nodes-in-pairs/description/ + +## 题目描述 +Given a linked list, swap every two adjacent nodes and return its head. + +You may not modify the values in the list's nodes, only nodes itself may be changed. + + + +Example: + +Given 1->2->3->4, you should return the list as 2->1->4->3. +## 思路 + +设置一个 dummy 节点简化操作,dummy next 指向 head。 + +1. 初始化 first 为第一个节点 +2. 初始化 second 为第二个节点 +3. 初始化 current 为 dummy +4. first.next = second.next +5. second.next = first +6. current.next = second +7. current 移动两格 +8. 重复 + +![24.swap-nodes-in-pairs](../assets/24.swap-nodes-in-pairs.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) + +## 关键点解析 + +1. 链表这种数据结构的特点和使用 + +2. dummyHead 简化操作 + +## 代码 + +* 语言支持:JS,Python3 + +```js +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +var swapPairs = function(head) { + const dummy = new ListNode(0); + dummy.next = head; + let current = dummy; + while (current.next != null && current.next.next != null) { + // 初始化双指针 + const first = current.next; + const second = current.next.next; + + // 更新双指针和 current 指针 + first.next = second.next; + second.next = first; + current.next = second; + + // 更新指针 + current = current.next.next; + } + return dummy.next; +}; + +``` +Python3 Code: +```python +class Solution: + def swapPairs(self, head: ListNode) -> ListNode: + """ + 用递归实现链表相邻互换: + 第一个节点的 next 是第三、第四个节点交换的结果,第二个节点的 next 是第一个节点; + 第三个节点的 next 是第五、第六个节点交换的结果,第四个节点的 next 是第三个节点; + 以此类推 + :param ListNode head + :return ListNode + """ + # 如果为 None 或 next 为 None,则直接返回 + if not head or not head.next: + return head + + _next = head.next + head.next = self.swapPairs(_next.next) + _next.next = head + return _next +``` diff --git a/spider/row-markdown/240.search-a-2-d-matrix-ii.md b/spider/row-markdown/240.search-a-2-d-matrix-ii.md new file mode 100644 index 0000000..8be96b8 --- /dev/null +++ b/spider/row-markdown/240.search-a-2-d-matrix-ii.md @@ -0,0 +1,112 @@ + +## 题目地址 +https://leetcode.com/problems/search-a-2d-matrix-ii/description/ + +## 题目描述 + +``` +Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: + +Integers in each row are sorted in ascending from left to right. +Integers in each column are sorted in ascending from top to bottom. +Example: + +Consider the following matrix: + +[ + [1, 4, 7, 11, 15], + [2, 5, 8, 12, 19], + [3, 6, 9, 16, 22], + [10, 13, 14, 17, 24], + [18, 21, 23, 26, 30] +] +Given target = 5, return true. + +Given target = 20, return false. + +``` + +## 思路 + +符合直觉的做法是两层循环遍历,时间复杂度是O(m * n), +有没有时间复杂度更好的做法呢? 答案是有,那就是充分运用矩阵的特性(横向纵向都递增), +我们可以从角落(左下或者右上)开始遍历,这样时间复杂度是O(m + n). + +![](https://tva1.sinaimg.cn/large/0082zybply1gbrcf58gsqj30ft0b4wfv.jpg) + +其中蓝色代表我们选择的起点元素, 红色代表目标元素。 + +## 关键点解析 + +- 从角落开始遍历,利用递增的特性简化时间复杂度 + + +## 代码 + +代码支持:JavaScript, Python3 + + +JavaScript Code: + +```js + +/* + * @lc app=leetcode id=240 lang=javascript + * + * [240] Search a 2D Matrix II + * + * https://leetcode.com/problems/search-a-2d-matrix-ii/description/ + * + * + */ +/** + * @param {number[][]} matrix + * @param {number} target + * @return {boolean} + */ +var searchMatrix = function(matrix, target) { + if (!matrix || matrix.length === 0) return 0; + + let colIndex = 0; + let rowIndex = matrix.length - 1; + while(rowIndex > 0 && target < matrix[rowIndex][colIndex]) { + rowIndex --; + } + + while(colIndex < matrix[0].length) { + if (target === matrix[rowIndex][colIndex]) return true; + if (target > matrix[rowIndex][colIndex]) { + colIndex ++; + } else if (rowIndex > 0){ + rowIndex --; + } else { + return false; + } + } + + return false; +}; +``` + +Python Code: + +```python +class Solution: + def searchMatrix(self, matrix, target): + m = len(matrix) + if m == 0: + return False + n = len(matrix[0]) + i = m - 1 + j = 0 + + while i >= 0 and j < n: + if matrix[i][j] == target: + return True + if matrix[i][j] > target: + i -= 1 + else: + j += 1 + return False +``` + diff --git a/spider/row-markdown/25.reverse-nodes-in-k-groups-cn.md b/spider/row-markdown/25.reverse-nodes-in-k-groups-cn.md new file mode 100644 index 0000000..8286815 --- /dev/null +++ b/spider/row-markdown/25.reverse-nodes-in-k-groups-cn.md @@ -0,0 +1,249 @@ +## 题目地址 +https://leetcode.com/problems/reverse-nodes-in-k-group/ + +## 题目描述 +``` +Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. + +k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is. + +Example: + +Given this linked list: 1->2->3->4->5 + +For k = 2, you should return: 2->1->4->3->5 + +For k = 3, you should return: 3->2->1->4->5 + +Note: + +Only constant extra memory is allowed. +You may not alter the values in the list's nodes, only nodes itself may be changed. + +``` + +## 思路 +题意是以 `k` 个nodes为一组进行翻转,返回翻转后的`linked list`. + +从左往右扫描一遍`linked list`,扫描过程中,以k为单位把数组分成若干段,对每一段进行翻转。给定首尾nodes,如何对链表进行翻转。 + +链表的翻转过程,初始化一个为`null `的 `previous node(prev)`,然后遍历链表的同时,当前`node (curr)`的下一个(next)指向前一个`node(prev)`, +在改变当前node的指向之前,用一个临时变量记录当前node的下一个`node(curr.next)`. 即 +``` +ListNode temp = curr.next; +curr.next = prev; +prev = curr; +curr = temp; +``` + +举例如图:翻转整个链表 `1->2->3->4->null` -> `4->3->2->1->null` + +![reverse linked list](../assets/problems/25.reverse-nodes-in-k-groups-1.PNG) + +这里是对每一组(`k个nodes`)进行翻转, + +1. 先分组,用一个`count`变量记录当前节点的个数 + +2. 用一个`start` 变量记录当前分组的起始节点位置的前一个节点 + +3. 用一个`end `变量记录要翻转的最后一个节点位置 + +4. 翻转一组(`k个nodes`)即`(start, end) - start and end exclusively`。 + +5. 翻转后,`start`指向翻转后链表, 区间`(start,end)`中的最后一个节点, 返回`start` 节点。 + +6. 如果不需要翻转,`end` 就往后移动一个(`end=end.next`),每一次移动,都要`count+1`. + +如图所示 步骤4和5: 翻转区间链表区间`(start, end)` + +![reverse linked list range in (start, end)](../assets/problems/25.reverse-nodes-in-k-groups-3.png) + + +举例如图,`head=[1,2,3,4,5,6,7,8], k = 3` + + +![reverse k nodes in linked list](../assets/problems/25.reverse-nodes-in-k-groups-2.PNG) + + +>**NOTE**: 一般情况下对链表的操作,都有可能会引入一个新的`dummy node`,因为`head`有可能会改变。这里`head 从1->3`, +`dummy (List(0)) `保持不变。 + +#### 复杂度分析 +- *时间复杂度:* `O(n) - n is number of Linked List` +- *空间复杂度:* `O(1)` + +## 关键点分析 +1. 创建一个dummy node +2. 对链表以k为单位进行分组,记录每一组的起始和最后节点位置 +3. 对每一组进行翻转,更换起始和最后的位置 +4. 返回`dummy.next`. + +## 代码 (`Java/Python3/javascript`) +*Java Code* +```java +class ReverseKGroupsLinkedList { + public ListNode reverseKGroup(ListNode head, int k) { + if (head == null || k == 1) { + return head; + } + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode start = dummy; + ListNode end = head; + int count = 0; + while (end != null) { + count++; + // group + if (count % k == 0) { + // reverse linked list (start, end] + start = reverse(start, end.next); + end = start.next; + } else { + end = end.next; + } + } + return dummy.next; + } + + /** + * reverse linked list from range (start, end), return last node. + * for example: + * 0->1->2->3->4->5->6->7->8 + * | | + * start end + * + * After call start = reverse(start, end) + * + * 0->3->2->1->4->5->6->7->8 + * | | + * start end + * first + * + */ + private ListNode reverse(ListNode start, ListNode end) { + ListNode curr = start.next; + ListNode prev = start; + ListNode first = curr; + while (curr != end){ + ListNode temp = curr.next; + curr.next = prev; + prev = curr; + curr = temp; + } + start.next = prev; + first.next = curr; + return first; + } +} +``` + +*Python3 Cose* +```python +class Solution: + def reverseKGroup(self, head: ListNode, k: int) -> ListNode: + if head is None or k < 2: + return head + dummy = ListNode(0) + dummy.next = head + start = dummy + end = head + count = 0 + while end: + count += 1 + if count % k == 0: + start = self.reverse(start, end.next) + end = start.next + else: + end = end.next + return dummy.next + + def reverse(self, start, end): + prev, curr = start, start.next + first = curr + while curr != end: + temp = curr.next + curr.next = prev + prev = curr + curr = temp + start.next = prev + first.next = curr + return first +``` + +*javascript code* +```js +/** + * @param {ListNode} head + * @param {number} k + * @return {ListNode} + */ +var reverseKGroup = function(head, k) { + // 标兵 + let dummy = new ListNode() + dummy.next = head + let [start, end] = [dummy, dummy.next] + let count = 0 + while(end) { + count++ + if (count % k === 0) { + start = reverseList(start, end.next) + end = start.next + } else { + end = end.next + } + } + return dummy.next + + // 翻转stat -> end的链表 + function reverseList(start, end) { + let [pre, cur] = [start, start.next] + const first = cur + while(cur !== end) { + let next = cur.next + cur.next = pre + pre = cur + cur = next + } + start.next = pre + first.next = cur + return first + } +}; + +``` + +## 参考(References) +- [Leetcode Discussion (yellowstone)](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea) + +## 扩展 + +- 要求从后往前以`k`个为一组进行翻转。**(字节跳动(ByteDance)面试题)** + + 例子,`1->2->3->4->5->6->7->8, k = 3`, + + 从后往前以`k=3`为一组, + - `6->7->8` 为一组翻转为`8->7->6`, + - `3->4->5`为一组翻转为`5->4->3`. + - `1->2`只有2个nodes少于`k=3`个,不翻转。 + + 最后返回: `1->2->5->4->3->8->7->6` + +这里的思路跟从前往后以`k`个为一组进行翻转类似,可以进行预处理: + +1. 翻转链表 + +2. 对翻转后的链表进行从前往后以k为一组翻转。 + +3. 翻转步骤2中得到的链表。 + +例子:`1->2->3->4->5->6->7->8, k = 3` + +1. 翻转链表得到:`8->7->6->5->4->3->2->1` + +2. 以k为一组翻转: `6->7->8->3->4->5->2->1` + +3. 翻转步骤#2链表: `1->2->5->4->3->8->7->6` + +## 类似题目 +- [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/) \ No newline at end of file diff --git a/spider/row-markdown/25.reverse-nodes-in-k-groups-en.md b/spider/row-markdown/25.reverse-nodes-in-k-groups-en.md new file mode 100644 index 0000000..9cf1d31 --- /dev/null +++ b/spider/row-markdown/25.reverse-nodes-in-k-groups-en.md @@ -0,0 +1,214 @@ +## Problem +https://leetcode.com/problems/reverse-nodes-in-k-group/ + +## Problem Description +``` +Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. + +k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is. + +Example: + +Given this linked list: 1->2->3->4->5 + +For k = 2, you should return: 2->1->4->3->5 + +For k = 3, you should return: 3->2->1->4->5 + +Note: + +Only constant extra memory is allowed. +You may not alter the values in the list's nodes, only nodes itself may be changed. + +``` + +## Solution +Traverse `linked list` from left to right, during traverse, group nodes in k, then reverse each group. +How to reverse a linked list given start, end node? + +Reverse linked list: + +1. Initial a prev node `null` + +2. For each move, use temp node to keep current next node. + +3. During traverse, update current node pointing to previous node, update previous pointing to current node + +4. Update current to temp + +``` +ListNode temp = curr.next; +curr.next = prev; +prev = curr; +curr = temp; +``` + +For example(as below pic): reverse the whole linked list `1->2->3->4->null` -> `4->3->2->1->null` + +![reverse linked list](../assets/problems/25.reverse-nodes-in-k-groups-1.PNG) + +Here Reverse each group(`k nodes`): + +1. First group, use `count` keep track linked list counts when traverse linked list + +2. Use `start` to keep track each group start node position. + +3. Use `end ` to keep track each group end node position + +4. Reverse(`k nodes`)AKA: `(start, end) - start and end exclusively`. + +5. After reverse, update `start` point to reversed group last node. + +6. If `counts % k != 0`, then `end` move to next(`end=end.next`), for each move`count+1`. + +As below pic show steps 4 and 5, reverse linked list in range `(start, end)`: + +![reverse linked list range in (start, end)](../assets/problems/25.reverse-nodes-in-k-groups-3.png) + + +For example(as below pic),`head=[1,2,3,4,5,6,7,8], k = 3` + + +![reverse k nodes in linked list](../assets/problems/25.reverse-nodes-in-k-groups-2.PNG) + + +>**NOTE**: Usually we create a `dummy node` to solve linked list problem, because head node may be changed during operation. +for example: here `head updated from 1->3`, and `dummy (List(0)) ` keep the same. + +#### Complexity Analysis +- *Time Complexity:* `O(n) - n is number of Linked List` +- *Space Complexity:* `O(1)` + +## Key Points +1. create a dummy node, `dummy = ListNode(0)` +2. Group linked list as `k=3`, keep track of start and end node for each group. +3. Reverse each group, update start and end node references +4. return `dummy.next`. + +## Code (`Java/Python3`) +*Java Code* +```java +class ReverseKGroupsLinkedList { + public ListNode reverseKGroup(ListNode head, int k) { + if (head == null || k == 1) { + return head; + } + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode start = dummy; + ListNode end = head; + int count = 0; + while (end != null) { + count++; + // group + if (count % k == 0) { + // reverse linked list (start, end] + start = reverse(start, end.next); + end = start.next; + } else { + end = end.next; + } + } + return dummy.next; + } + + /** + * reverse linked list from range (start, end), return last node. + * for example: + * 0->1->2->3->4->5->6->7->8 + * | | + * start end + * + * After call start = reverse(start, end) + * + * 0->3->2->1->4->5->6->7->8 + * | | + * start end + * + * @return the reversed list's 'start' node, which is the precedence of node end + */ + private ListNode reverse(ListNode start, ListNode end) { + ListNode curr = start.next; + ListNode prev = start; + ListNode first = curr; + while (curr != end){ + ListNode temp = curr.next; + curr.next = prev; + prev = curr; + curr = temp; + } + start.next = prev; + first.next = curr; + return first; + } +} +``` + +*Python3 Cose* +```python +class Solution: + def reverseKGroup(self, head: ListNode, k: int) -> ListNode: + if head is None or k < 2: + return head + dummy = ListNode(0) + dummy.next = head + start = dummy + end = head + count = 0 + while end: + count += 1 + if count % k == 0: + start = self.reverse(start, end.next) + end = start.next + else: + end = end.next + return dummy.next + + def reverse(self, start, end): + prev, curr = start, start.next + first = curr + while curr != end: + temp = curr.next + curr.next = prev + prev = curr + curr = temp + start.next = prev + first.next = curr + return first +``` + +## References +- [Leetcode Discussion (yellowstone)](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea) + +## Extension + +- Require from right to left reverse nodes in k groups. **(ByteDance Interview)** + + Example,`1->2->3->4->5->6->7->8, k = 3`, + + From right to left, group as `k=3`: + - `6->7->8` reverse to `8->7->6`, + - `3->4->5` reverse to `5->4->3`. + - `1->2` only has 2 nodes, which less than `k=3`, do nothing. + + return: `1->2->5->4->3->8->7->6` + +Here, we pre-process linked list, reverse it first, then using Reverse nodes in K groups solution: + +1. Reverse linked list + +2. From left to right, reverse linked list group as k nodes. + +3. Reverse step #2 linked list + +For example:`1->2->3->4->5->6->7->8, k = 3` + +1. Reverse linked list: `8->7->6->5->4->3->2->1` + +2. Reverse nodes in k groups: `6->7->8->3->4->5->2->1` + +3. Reverse step#2 linked list: `1->2->5->4->3->8->7->6` + +## Similar Problems +- [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/) \ No newline at end of file diff --git a/spider/row-markdown/26.remove-duplicates-from-sorted-array.md b/spider/row-markdown/26.remove-duplicates-from-sorted-array.md new file mode 100644 index 0000000..eedbdb1 --- /dev/null +++ b/spider/row-markdown/26.remove-duplicates-from-sorted-array.md @@ -0,0 +1,127 @@ +## 题目地址 +https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/ + +## 题目描述 +Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length. + +Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. + +Example 1: + +Given nums = [1,1,2], + +Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. + +It doesn't matter what you leave beyond the returned length. +Example 2: + +Given nums = [0,0,1,1,1,2,2,3,3,4], + +Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively. + +It doesn't matter what values are set beyond the returned length. +Clarification: + +Confused why the returned value is an integer but your answer is an array? + +Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. + +Internally you can think of this: + +``` +// nums is passed in by reference. (i.e., without making a copy) +int len = removeDuplicates(nums); + +// any modification to nums in your function would be known by the caller. +// using the length returned by your function, it prints the first len elements. +for (int i = 0; i < len; i++) { + print(nums[i]); +} +``` + +## 思路 + +使用快慢指针来记录遍历的坐标。 + +- 开始时这两个指针都指向第一个数字 + +- 如果两个指针指的数字相同,则快指针向前走一步 + +- 如果不同,则两个指针都向前走一步 + +- 当快指针走完整个数组后,慢指针当前的坐标加 1 就是数组中不同数字的个数 + +![26.remove-duplicates-from-sorted-array](../assets/26.remove-duplicates-from-sorted-array.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) + +## 关键点解析 + +- 双指针 + +这道题如果不要求,O(n) 的时间复杂度, O(1) 的空间复杂度的话,会很简单。 +但是这道题是要求的,这种题的思路一般都是采用双指针 + +- 如果是数据是无序的,就不可以用这种方式了,从这里也可以看出排序在算法中的基础性和重要性。 + +- 注意nums为空时的边界条件。 + +## 代码 + +* 语言支持:JS,Python,C++ + +Javascript Code: +```js +/** + * @param {number[]} nums + * @return {number} + */ +var removeDuplicates = function(nums) { + const size = nums.length; + if(size==0) return 0; + let slowP = 0; + for (let fastP = 0; fastP < size; fastP++) { + if (nums[fastP] !== nums[slowP]) { + slowP++; + nums[slowP] = nums[fastP] + } + } + return slowP + 1; +}; +``` + +Python Code: +```python +class Solution: + def removeDuplicates(self, nums: List[int]) -> int: + if nums: + slow = 0 + for fast in range(1, len(nums)): + if nums[fast] != nums[slow]: + slow += 1 + nums[slow] = nums[fast] + return slow + 1 + else: + return 0 +``` + +C++ Code: +```cpp +class Solution { +public: + int removeDuplicates(vector& nums) { + if(nums.empty()) return 0; + int fast,slow; + fast=slow=0; + while(fast!=nums.size()){ + if(nums[fast]==nums[slow]) fast++; + else { + slow++; + nums[slow]=nums[fast]; + fast++; + } + } + return slow+1; + } +}; +``` diff --git a/spider/row-markdown/263.ugly-number.md b/spider/row-markdown/263.ugly-number.md new file mode 100644 index 0000000..d8e04d5 --- /dev/null +++ b/spider/row-markdown/263.ugly-number.md @@ -0,0 +1,109 @@ +## 题目地址 + +https://leetcode.com/problems/ugly-number/description/ + +## 题目描述 + +``` +Write a program to check whether a given number is an ugly number. + +Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. + +Example 1: + +Input: 6 +Output: true +Explanation: 6 = 2 × 3 +Example 2: + +Input: 8 +Output: true +Explanation: 8 = 2 × 2 × 2 +Example 3: + +Input: 14 +Output: false +Explanation: 14 is not ugly since it includes another prime factor 7. +Note: + +1 is typically treated as an ugly number. +Input is within the 32-bit signed integer range: [−231, 231 − 1]. + +``` + +## 思路 + +题目要求给定一个数字,判断是否为“丑陋数”(ugly number), 丑陋数是指只包含质因子2, 3, 5的正整数。 + +![263.ugly-number](../assets/problems/263.ugly-number.png) + +根据定义,我们将给定数字除以2、3、5(顺序无所谓),直到无法整除。 +如果得到1,说明是所有因子都是2或3或5,如果不是1,则不是丑陋数。 + +这就好像我们判断一个数字是否为n(n为大于1的正整数)的幂次方一样,我们只需要 +不断除以n,直到无法整除,如果得到1,那么就是n的幂次方。 这道题的不同在于 +它不再是某一个数字的幂次方,而是三个数字(2,3,5),不过解题思路还是一样的。 + +转化为代码可以是: + +```js + + while(num % 2 === 0) num = num / 2; + while(num % 3 === 0) num = num / 3; + while(num % 5 === 0) num = num / 5; + + return num === 1; + +``` + +> 我下方给出的代码是用了递归实现,只是给大家看下不同的写法而已。 + +## 关键点 +- 数论 +- 因数分解 + +## 代码 + +* 语言支持:JS, Python + +Javascript Code: + +```js +/* + * @lc app=leetcode id=263 lang=javascript + * + * [263] Ugly Number + */ +/** + * @param {number} num + * @return {boolean} + */ +var isUgly = function(num) { + // TAG: 数论 + if (num <= 0) return false; + if (num === 1) return true; + + const list = [2, 3, 5]; + + if (list.includes(num)) return true; + + for (let i of list) { + if (num % i === 0) return isUgly(Math.floor(num / i)); + } + return false; +}; +``` + +Python Code: + +```python +# 非递归写法 +class Solution: + def isUgly(self, num: int) -> bool: + if num <= 0: + return False + for i in (2, 3, 5): + while num % i == 0: + num /= i + return num == 1 +``` diff --git a/spider/row-markdown/279.perfect-squares.md b/spider/row-markdown/279.perfect-squares.md new file mode 100644 index 0000000..174e364 --- /dev/null +++ b/spider/row-markdown/279.perfect-squares.md @@ -0,0 +1,140 @@ +## 题目地址 + +https://leetcode.com/problems/perfect-squares/description/ + +## 题目描述 + +``` +Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n. + +Example 1: + +Input: n = 12 +Output: 3 +Explanation: 12 = 4 + 4 + 4. +Example 2: + +Input: n = 13 +Output: 2 +Explanation: 13 = 4 + 9. + +``` + +## 思路 + +直接递归处理即可,但是这种暴力的解法很容易超时。如果你把递归的过程化成一棵树的话(其实就是递归树), +可以看出中间有很多重复的计算。 + +如果能将重复的计算缓存下来,说不定能够解决时间复杂度太高的问题。 + +> 递归对内存的要求也很高, 如果数字非常大,也会面临爆栈的风险,将递归转化为循环可以解决。 + +递归 + 缓存的方式代码如下: + +```js +const mapper = {}; + +function d(n, level) { + if (n === 0) return level; + + let i = 1; + const arr = []; + + while (n - i * i >= 0) { + const hit = mapper[n - i * i]; + if (hit) { + arr.push(hit + level); + } else { + const depth = d(n - i * i, level + 1) - level; + mapper[n - i * i] = depth; + arr.push(depth + level); + } + i++; + } + + return Math.min(...arr); +} +/** + * @param {number} n + * @return {number} + */ +var numSquares = function(n) { + return d(n, 0); +}; +``` + +如果使用 DP,其实本质上和递归 + 缓存 差不多。 + +DP 的代码见代码区。 + +## 关键点解析 + +- 如果用递归 + 缓存, 缓存的设计很重要 + 我的做法是 key 就是 n,value 是以 n 为起点,到达底端的深度。 + 下次取出缓存的时候用当前的 level + 存的深度 就是我们想要的 level. + +- 使用动态规划的核心点还是选和不选的问题 + +```js +for (let i = 1; i <= n; i++) { + for (let j = 1; j * j <= i; j++) { + // 不选(dp[i]) 还是 选(dp[i - j * j]) + dp[i] = Math.min(dp[i], dp[i - j * j] + 1); + } +} +``` + +## 代码 + +```js +/* + * @lc app=leetcode id=279 lang=javascript + * + * [279] Perfect Squares + * + * https://leetcode.com/problems/perfect-squares/description/ + * + * algorithms + * Medium (40.98%) + * Total Accepted: 168.2K + * Total Submissions: 408.5K + * Testcase Example: '12' + * + * Given a positive integer n, find the least number of perfect square numbers + * (for example, 1, 4, 9, 16, ...) which sum to n. + * + * Example 1: + * + * + * Input: n = 12 + * Output: 3 + * Explanation: 12 = 4 + 4 + 4. + * + * Example 2: + * + * + * Input: n = 13 + * Output: 2 + * Explanation: 13 = 4 + 9. + */ +/** + * @param {number} n + * @return {number} + */ +var numSquares = function(n) { + if (n <= 0) { + return 0; + } + + const dp = Array(n + 1).fill(Number.MAX_VALUE); + dp[0] = 0; + for (let i = 1; i <= n; i++) { + for (let j = 1; j * j <= i; j++) { + // 不选(dp[i]) 还是 选(dp[i - j * j]) + dp[i] = Math.min(dp[i], dp[i - j * j] + 1); + } + } + + return dp[n]; +}; +``` diff --git a/spider/row-markdown/283.move-zeroes.md b/spider/row-markdown/283.move-zeroes.md new file mode 100644 index 0000000..f4eb15e --- /dev/null +++ b/spider/row-markdown/283.move-zeroes.md @@ -0,0 +1,99 @@ + +## 题目地址 +https://leetcode.com/problems/move-zeroes/description/ + +## 题目描述 +``` +Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. + +Example: + +Input: [0,1,0,3,12] +Output: [1,3,12,0,0] +Note: + +You must do this in-place without making a copy of the array. +Minimize the total number of operations. + +``` +## 思路 + +如果题目没有要求 modify in-place 的话,我们可以先遍历一遍将包含 0 的和不包含 0 的存到两个数组, +然后拼接两个数组即可。 但是题目要求 modify in-place, 也就是不需要借助额外的存储空间,刚才的方法 +空间复杂度是 O(n). + +那么如果 modify in-place 呢? 空间复杂度降低为 1。 + +我们可以借助一个游标记录位置,然后遍历一次,将非 0 的原地修改,最后补 0 即可。 + +## 关键点解析 + +无 + +## 代码 + +* 语言支持:JS, C++, Python + +JavaScript Code: + +```js +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ +var moveZeroes = function(nums) { + let index = 0; + for(let i = 0; i < nums.length; i++) { + const num = nums[i]; + if (num !== 0) { + nums[index++] = num; + } + } + + for(let i = index; i < nums.length; i++) { + nums[index++] = 0; + } +}; +``` + +C++ Code: + +> 解题思想与上面 JavaScript 一致,做了少许代码优化(非性能优化,因为时间复杂度都是 O(n)): +> 增加一个游标来记录下一个待处理的元素的位置,这样只需要写一次循环即可。 + +```C++ +class Solution { +public: + void moveZeroes(vector& nums) { + vector::size_type nonZero = 0; + vector::size_type next = 0; + while (next < nums.size()) { + if (nums[next] != 0) { + // 使用 std::swap() 会带来 8ms 的性能损失 + // swap(nums[next], nums[nonZero]); + auto tmp = nums[next]; + nums[next] = nums[nonZero]; + nums[nonZero] = tmp; + ++nonZero; + } + ++next; + } + } +}; +``` + +Python Code: + +```python +class Solution: + def moveZeroes(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + slow = fast = 0 + while fast < len(nums): + if nums[fast] != 0: + nums[fast], nums[slow] = nums[slow], nums[fast] + slow += 1 + fast += 1 +``` diff --git a/spider/row-markdown/29.divide-two-integers.md b/spider/row-markdown/29.divide-two-integers.md new file mode 100644 index 0000000..b324dad --- /dev/null +++ b/spider/row-markdown/29.divide-two-integers.md @@ -0,0 +1,172 @@ +## 题目地址 +https://leetcode.com/problems/divide-two-integers/description/ + +## 题目描述 +``` +Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator. + +Return the quotient after dividing dividend by divisor. + +The integer division should truncate toward zero. + +Example 1: + +Input: dividend = 10, divisor = 3 +Output: 3 +Example 2: + +Input: dividend = 7, divisor = -3 +Output: -2 +Note: + +Both dividend and divisor will be 32-bit signed integers. +The divisor will never be 0. +Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows. + +``` + +## 思路 + +符合直觉的做法是,减数一次一次减去被减数,不断更新差,直到差小于0,我们减了多少次,结果就是多少。 + +核心代码: + +```js + let acc = divisor; + let count = 0; + + while (dividend - acc >= 0) { + acc += divisor; + count++; + } + + return count; + +``` + +这种做法简单直观,但是性能却比较差. 下面来介绍一种性能更好的方法。 + +![29.divide-two-integers](../assets/problems/29.divide-two-integers.png) + +通过上面这样的分析,我们直到可以使用二分法来解决,性能有很大的提升。 + +## 关键点解析 + +- 二分查找 + +- 正负数的判断中,这样判断更简单。 + +```js +const isNegative = dividend > 0 !== divisor > 0; +``` + + +## 代码 + +* 语言支持:JS,Python3 + +```js + + +/* + * @lc app=leetcode id=29 lang=javascript + * + * [29] Divide Two Integers + */ +/** + * @param {number} dividend + * @param {number} divisor + * @return {number} + */ +var divide = function(dividend, divisor) { + if (divisor === 1) return dividend; + + // 这种方法很巧妙,即符号相同则为正,不同则为负 + const isNegative = dividend > 0 !== divisor > 0; + + const MAX_INTERGER = Math.pow(2, 31); + + const res = helper(Math.abs(dividend), Math.abs(divisor)); + + // overflow + if (res > MAX_INTERGER - 1 || res < -1 * MAX_INTERGER) { + return MAX_INTERGER - 1; + } + + return isNegative ? -1 * res : res; +}; + +function helper(dividend, divisor) { + // 二分法 + if (dividend <= 0) return 0; + if (dividend < divisor) return 0; + if (divisor === 1) return dividend; + + let acc = 2 * divisor; + let count = 1; + + while (dividend - acc > 0) { + acc += acc; + count += count; + } + // 直接使用位移运算,比如acc >> 1会有问题 + const last = dividend - Math.floor(acc / 2); + + return count + helper(last, divisor); +} +``` +Python3 Code: +```python +class Solution: + def divide(self, dividend: int, divisor: int) -> int: + """ + 二分法 + :param int divisor + :param int dividend + :return int + """ + # 错误处理 + if divisor == 0: + raise ZeroDivisionError + if abs(divisor) == 1: + result = dividend if 1 == divisor else -dividend + return min(2**31-1, max(-2**31, result)) + + # 确定结果的符号 + sign = ((dividend >= 0) == (divisor >= 0)) + + result = 0 + # abs也可以直接写在while条件中,不过可能会多计算几次 + _divisor = abs(divisor) + _dividend = abs(dividend) + + while _divisor <= _dividend: + r, _dividend = self._multi_divide(_divisor, _dividend) + result += r + + result = result if sign else -result + + # 注意返回值不能超过32位有符号数的表示范围 + return min(2**31-1, max(-2**31, result)) + + def _multi_divide(self, divisor, dividend): + """ + 翻倍除法,如果可以被除,则下一步除数翻倍,直至除数大于被除数, + 返回商加总的结果与被除数的剩余值; + 这里就不做异常处理了; + :param int divisor + :param int dividend + :return tuple result, left_dividend + """ + result = 0 + times_count = 1 + while divisor <= dividend: + dividend -= divisor + result += times_count + times_count += times_count + divisor += divisor + return result, dividend +``` + +## 相关题目 +- [875.koko-eating-bananas](./875.koko-eating-bananas.md) diff --git a/spider/row-markdown/295.find-median-from-data-stream.md b/spider/row-markdown/295.find-median-from-data-stream.md new file mode 100644 index 0000000..2ac1b36 --- /dev/null +++ b/spider/row-markdown/295.find-median-from-data-stream.md @@ -0,0 +1,325 @@ +## 题目地址 + +https://leetcode.com/problems/find-median-from-data-stream/description/ + +## 题目描述 + +``` +Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. + +For example, +[2,3,4], the median is 3 + +[2,3], the median is (2 + 3) / 2 = 2.5 + +Design a data structure that supports the following two operations: + +void addNum(int num) - Add a integer number from the data stream to the data structure. +double findMedian() - Return the median of all elements so far. + + +Example: + +addNum(1) +addNum(2) +findMedian() -> 1.5 +addNum(3) +findMedian() -> 2 + + +Follow up: + +If all integer numbers from the stream are between 0 and 100, how would you optimize it? +If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it? + +``` + +## 思路 + +这道题目是求动态数据的中位数,在 leetcode 难度为`hard`. 如果这道题是求静态数据的中位数,我们用数组去存储, +空间复杂度 O(1), 时间复杂度 O(1) + +> 空间复杂度指的是除了存储数据之外额外开辟的用于计算等任务的内存空间 + +代码也比较简单 + +```js +function findMedian(a) { + return a.length % 2 === 0 + ? (a[a.length >> 1] + a[a.length >> (1 + 1)]) / 2 + : a[a.length >> 1]; +} +``` + +但是题目要求是动态数据, 那么是否可以每次添加数据的时候,都去排一次序呢? +假如我们每次插入都用`快速排序`进行排序的话,那么时间复杂度是 O(nlogn) + O(1) + +> O(nlogn) 是排序的时间复杂度 O(1)是查询中位数的时间复杂度 + +如果你用这种思路进行的话, 恐怕 leetcode 会超时。 + +那么如何优化呢? 答案是使用堆, Java, C++等语言都有`优先级队列`中这种数据结构, +优先级队列本质上就是一个堆。 关于堆和优先级队列的关系,我会放在《数据结构和算法》部分讲解。这里不赘述 + +如果借助堆这种数据结构, 就可以轻易实现了。 + +具体的做法是,建立两个堆,这两个堆需要满足: + +1. 大顶堆元素都比小顶堆小(由于堆的特点其实只要比较堆顶即可) +2. 大顶堆元素不小于小顶堆,且最多比小顶堆多一个元素 + +满足上面两个条件的话,如果想要找到中位数,就比较简单了 + +- 如果两个堆数量相等(本质是总数为偶数), 就两个堆顶元素的平均数 +- 如果两个堆数量不相等(本质是总数为奇数), 就取大顶堆的堆顶元素 + +比如对于[1,2,3] 求中位数: + +![295.find-median-from-data-stream-1](../assets/problems/295.find-median-from-data-stream-1.png) + +再比如对于[1,2,3, 4] 求中位数: + +![295.find-median-from-data-stream-2](../assets/problems/295.find-median-from-data-stream-2.png) +## 关键点解析 + +- 用两个堆(一个大顶堆,一个小顶堆)来简化时间复杂度 +- 用优先级队列简化操作 + +> JavaScript 不像 Java, C++等语言都有`优先级队列`中这种数据结构, 因此大家可以使用社区的实现 +> 个人认为没有非要纠结于优先级队列怎么实现, 至少这道题不是考这个的 +> 优先级队列的实现个人认为已经超过了这道题想考察的范畴 +## 代码 + +如果不使用现成的`优先级队列`这种数据结构,代码可能是这样的: + +```js +/** + * initialize your data structure here. + */ +var MedianFinder = function() { + this.maxHeap = []; + this.minHeap = []; +}; + +function minHeapify() { + this.minHeap.unshift(null); + const a = this.minHeap; + + // 为了方便大家理解,这里选用了粗暴的实现 + // 时间复杂度为O(n) + // 其实可以降到O(logn), 具体细节我不想在这里讲解和实现 + for (let i = a.length - 1; i >> 1 > 0; i--) { + // 自下往上堆化 + if (a[i] < a[i >> 1]) { // 如果子元素更小,则交换位置 + const temp = a[i]; + this.minHeap[i] = a[i >> 1]; + this.minHeap[i >> 1] = temp; + } + } + this.minHeap.shift(null); +} + +function maxHeapify() { + this.maxHeap.unshift(null); + const a = this.maxHeap; + + // 为了方便大家理解,这里选用了粗暴的实现 + // 时间复杂度为O(n) + // 其实可以降到O(logn), 具体细节我不想在这里讲解和实现 + for (let i = a.length - 1; i >> 1 > 0; i--) { + // 自下往上堆化 + if (a[i] > a[i >> 1]) { // 如果子元素更大,则交换位置 + const temp = a[i]; + this.maxHeap[i] = a[i >> 1]; + this.maxHeap[i >> 1] = temp; + } + } + this.maxHeap.shift(null); +} + +/** + * @param {number} num + * @return {void} + */ +MedianFinder.prototype.addNum = function(num) { + // 为了大家容易理解,这部分代码写的比较冗余 + + // 插入 + if (num >= (this.minHeap[0] || Number.MIN_VALUE)) { + this.minHeap.push(num); + } else { + this.maxHeap.push(num); + } + // 调整两个堆的节点数量平衡 + // 使得大顶堆的数量最多大于小顶堆一个, 且一定不小于小顶堆数量 + if (this.maxHeap.length > this.minHeap.length + 1) { + // 大顶堆的堆顶元素移动到小顶堆 + this.minHeap.push(this.maxHeap.shift()); + } + + if (this.minHeap.length > this.maxHeap.length) { + // 小顶堆的堆顶元素移动到大顶堆 + this.maxHeap.push(this.minHeap.shift()); + } + + // 调整堆顶元素 + if (this.maxHeap[0] > this.minHeap[0]) { + const temp = this.maxHeap[0]; + this.maxHeap[0] = this.minHeap[0]; + this.minHeap[0] = temp; + } + + // 堆化 + maxHeapify.call(this); + minHeapify.call(this); +}; + +/** + * @return {number} + */ +MedianFinder.prototype.findMedian = function() { + if ((this.maxHeap.length + this.minHeap.length) % 2 === 0) { + return (this.minHeap[0] + this.maxHeap[0]) / 2; + } else { + return this.maxHeap[0]; + } +}; + +/** + * Your MedianFinder object will be instantiated and called as such: + * var obj = new MedianFinder() + * obj.addNum(num) + * var param_2 = obj.findMedian() + */ +``` + +其中`minHeapify` 和 `maxHeapify` 的过程都有一个hack操作,就是: + +```js + +this.heap.unshift(null); +// .... +this.heap.shift(null); + +``` + +其实就是为了存储的数据从1开始,这样方便计算。 即对于下标为i的元素, `i >> 1` 一定是父节点的下标。 + +![295.find-median-from-data-stream-3](../assets/problems/295.find-median-from-data-stream-3.png) + +> 这是因为我用满二叉树来存储的堆 + +这个实现比较繁琐,下面介绍一种优雅的方式,假设JS和Java和C++等语言一样有`PriorityQueue`这种数据结构,那么我们实现就比较简单了。 + +代码: + +> 关于PriorityQueue的实现,感兴趣的可以看下 https://github.com/janogonzalez/priorityqueuejs + +```js +/* + * @lc app=leetcode id=295 lang=javascript + * + * [295] Find Median from Data Stream + * + * https://leetcode.com/problems/find-median-from-data-stream/description/ + * + * algorithms + * Hard (35.08%) + * Total Accepted: 101.2K + * Total Submissions: 282.4K + * Testcase Example: '["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]\n[[],[1],[2],[],[3],[]]' + * + * Median is the middle value in an ordered integer list. If the size of the + * list is even, there is no middle value. So the median is the mean of the two + * middle value. + * For example, + * + * [2,3,4], the median is 3 + * + * [2,3], the median is (2 + 3) / 2 = 2.5 + * + * Design a data structure that supports the following two operations: + * + * + * void addNum(int num) - Add a integer number from the data stream to the data + * structure. + * double findMedian() - Return the median of all elements so far. + * + * + * + * + * Example: + * + * + * addNum(1) + * addNum(2) + * findMedian() -> 1.5 + * addNum(3) + * findMedian() -> 2 + * + * + * + * + * Follow up: + * + * + * If all integer numbers from the stream are between 0 and 100, how would you + * optimize it? + * If 99% of all integer numbers from the stream are between 0 and 100, how + * would you optimize it? + * + * + */ +/** + * initialize your data structure here. + */ +var MedianFinder = function() { + this.maxHeap = new PriorityQueue((a, b) => a - b); + this.minHeap = new PriorityQueue((a, b) => b - a); +}; + +/** + * @param {number} num + * @return {void} + */ +MedianFinder.prototype.addNum = function(num) { + // 我们的目标就是建立两个堆,一个大顶堆,一个小顶堆 + // 结合中位数的特点 + // 这两个堆需要满足: + // 1. 大顶堆元素都比小顶堆小(由于堆的特点其实只要比较堆顶即可) + // 2. 大顶堆元素不小于小顶堆,且最多比小顶堆多一个元素 + + // 满足上面两个条件的话,如果想要找到中位数,就比较简单了 + // 如果两个堆数量相等(本质是总数为偶数), 就两个堆顶元素的平均数 + // 如果两个堆数量不相等(本质是总数为奇数), 就取大顶堆的堆顶元素 + + // 问题如果保证满足上述两个特点 + + // 1. 保证第一点 + this.maxHeap.enq(num); + // 由于小顶堆的所有数都来自大顶堆的堆顶元素(最大值) + // 因此可以保证第一点 + this.minHeap.enq(this.maxHeap.deq()); + + // 2. 保证第二点 + if (this.maxHeap.size() < this.minHeap.size()){ + this.maxHeap.enq(this.minHeap.deq()); + } +}; + +/** + * @return {number} + */ +MedianFinder.prototype.findMedian = function() { + if (this.maxHeap.size() == this.minHeap.size()) return (this.maxHeap.peek() + this.minHeap.peek()) / 2.0; + else return this.maxHeap.peek(); +}; + +/** + * Your MedianFinder object will be instantiated and called as such: + * var obj = new MedianFinder() + * obj.addNum(num) + * var param_2 = obj.findMedian() + */ + +``` diff --git a/spider/row-markdown/3.longestSubstringWithoutRepeatingCharacters.md b/spider/row-markdown/3.longestSubstringWithoutRepeatingCharacters.md new file mode 100644 index 0000000..fd54533 --- /dev/null +++ b/spider/row-markdown/3.longestSubstringWithoutRepeatingCharacters.md @@ -0,0 +1,102 @@ +## 题目地址 + +https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ + +## 题目描述 + +Given a string, find the length of the longest substring without repeating characters. + +Examples: + +``` +Given "abcabcbb", the answer is "abc", which the length is 3. + +Given "bbbbb", the answer is "b", with the length of 1. + +Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring. +``` + +## 思路 + +用一个 hashmap 来建立字符和其出现位置之间的映射。 + +维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。 + +(1)如果当前遍历到的字符从未出现过,那么直接扩大右边界; + +(2)如果当前遍历到的字符出现过,则缩小窗口(左边索引向右移动),然后继续观察当前遍历到的字符; + +(3)重复(1)(2),直到左边索引无法再移动; + +(4)维护一个结果 res,每次用出现过的窗口大小来更新结果 res,最后返回 res 获取结果。 + +![3.longestSubstringWithoutRepeatingCharacters](../assets/3.longestSubstringWithoutRepeatingCharacters.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) + +## 关键点 + +1. 用一个 mapper 记录出现过并且没有被删除的字符 +2. 用一个滑动窗口记录当前 index 开始的最大的不重复的字符序列 +3. 用 res 去记录目前位置最大的长度,每次滑动窗口更新就去决定是否需要更新 res + +## 代码 + +代码支持:JavaScript,Python3 + +JavaScript Code: + +```js +/** + * @param {string} s + * @return {number} + */ +var lengthOfLongestSubstring = function(s) { + const mapper = {}; // 记录已经出现过的charactor + let res = 0; + let slidingWindow = []; + + for (let c of s) { + if (mapper[c]) { + // 已经出现过了 + // 则删除 + const delIndex = slidingWindow.findIndex(_c => _c === c); + + for (let i = 0; i < delIndex; i++) { + mapper[slidingWindow[i]] = false; + } + + slidingWindow = slidingWindow.slice(delIndex + 1).concat(c); + } else { + // 新字符 + if (slidingWindow.push(c) > res) { + res = slidingWindow.length; + } + } + mapper[c] = true; + } + return res; +}; +``` + +Python3 Code: + +```python +from collections import defaultdict + + +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + l = 0 + ans = 0 + counter = defaultdict(lambda: 0) + + for r in range(len(s)): + while counter.get(s[r], 0) != 0: + counter[s[l]] = counter.get(s[l], 0) - 1 + l += 1 + counter[s[r]] += 1 + ans = max(ans, r - l + 1) + + return ans +``` diff --git a/spider/row-markdown/30.substring-with-concatenation-of-all-words.md b/spider/row-markdown/30.substring-with-concatenation-of-all-words.md new file mode 100644 index 0000000..ce9999e --- /dev/null +++ b/spider/row-markdown/30.substring-with-concatenation-of-all-words.md @@ -0,0 +1,75 @@ +## 题目地址(30. 串联所有单词的子串) + +https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/description/ + +## 题目描述 + +``` +给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。 + +注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。 + +  + +示例 1: + +输入: + s = "barfoothefoobarman", + words = ["foo","bar"] +输出:[0,9] +解释: +从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。 +输出的顺序不重要, [9,0] 也是有效答案。 +示例 2: + +输入: + s = "wordgoodgoodgoodbestword", + words = ["word","good","best","word"] +输出:[] + + +``` + +## 思路 + +本题是要我们找出 words 中`所有单词按照任意顺序串联`形成的单词中恰好出现在 s 中的索引,因此顺序是不重要的。换句话说,我们只要统计每一个单词的出现情况即可。以题目中 s = "barfoothefoobarman", words = ["foo","bar"] 为例。 我们只需要统计 foo 出现了一次,bar 出现了一次即可。我们只需要在 s 中找到同样包含一次 foo 和一次 bar 的子串即可。由于 words 中的字符串都是等长的,因此编码上也会比较简单。 + +1. 我们的目标状态是 Counter(words),即对 words 进行一次计数。 +2. 我们只需从头开始遍历一次数组,每次截取 word 长度的字符,一共截取 words 长度次即可。 +3. 如果我们截取的 Counter 和 Counter(words)一致,则加入到 res +4. 否则我们继续一个指针,继续执行步骤二 +5. 重复执行这个逻辑直到达到数组尾部 + +## 关键点解析 + +- Counter + +## 代码 + +- 语言支持:Python3 + +```python +from collections import Counter + + +class Solution: + def findSubstring(self, s: str, words: List[str]) -> List[int]: + if not s or not words: + return [] + res = [] + n = len(words) + word_len = len(words[0]) + window_len = word_len * n + target = Counter(words) + i = 0 + while i < len(s) - window_len + 1: + sliced = [] + start = i + for _ in range(n): + sliced.append(s[start:start + word_len]) + start += word_len + if Counter(sliced) == target: + res.append(i) + i += 1 + return res +``` diff --git a/spider/row-markdown/301.remove-invalid-parentheses.md b/spider/row-markdown/301.remove-invalid-parentheses.md new file mode 100644 index 0000000..9e30850 --- /dev/null +++ b/spider/row-markdown/301.remove-invalid-parentheses.md @@ -0,0 +1,141 @@ + +## 题目地址 +https://leetcode.com/problems/remove-invalid-parentheses/description/ + +## 题目描述 +``` +Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results. + +Note: The input string may contain letters other than the parentheses ( and ). + +Example 1: + +Input: "()())()" +Output: ["()()()", "(())()"] +Example 2: + +Input: "(a)())()" +Output: ["(a)()()", "(a())()"] +Example 3: + +Input: ")(" +Output: [""] + +``` + +## 思路 + +我们的思路是先写一个函数用来判断给定字符串是否是有效的。 然后再写一个函数,这个函数 +依次删除第i个字符,判断是否有效,有效则添加进最终的返回数组。 + +这样的话实现的功能就是, 删除`一个` 小括号使之有效的所有可能。因此只需要递归调用`依次删除第i个字符`的功能就可以了。 + +而且由于题目要求是要删除最少的小括号,因此我们的思路是使用广度优先遍历,而不是深度有限的遍历。 + +![301.remove-invalid-parentheses](../assets/problems/301.remove-invalid-parentheses.png) + +> 没有动图,请脑补 + +## 关键点解析 + +- 广度优先遍历 + +- 使用队列简化操作 + +- 使用一个visited的mapper, 来避免遍历同样的字符串 + + +## 代码 +```js +/* + * @lc app=leetcode id=301 lang=javascript + * + * [301] Remove Invalid Parentheses + * + * https://leetcode.com/problems/remove-invalid-parentheses/description/ + * + * algorithms + * Hard (38.52%) + * Total Accepted: 114.3K + * Total Submissions: 295.4K + * Testcase Example: '"()())()"' + * + * Remove the minimum number of invalid parentheses in order to make the input + * string valid. Return all possible results. + * + * Note: The input string may contain letters other than the parentheses ( and + * ). + * + * Example 1: + * + * + * Input: "()())()" + * Output: ["()()()", "(())()"] + * + * + * Example 2: + * + * + * Input: "(a)())()" + * Output: ["(a)()()", "(a())()"] + * + * + * Example 3: + * + * + * Input: ")(" + * Output: [""] + * + */ +var isValid = function(s) { + let openParenthes = 0; + for(let i = 0; i < s.length; i++) { + if (s[i] === '(') { + openParenthes++; + } else if (s[i] === ')') { + if (openParenthes === 0) return false; + openParenthes--; + } + } + return openParenthes === 0; +}; +/** + * @param {string} s + * @return {string[]} + */ +var removeInvalidParentheses = function(s) { + if (!s || s.length === 0) return [""]; + const ret = []; + const queue = [s]; + const visited = {}; + let current = null; + let removedParentheses = 0; // 只记录最小改动 + + while ((current = queue.shift())) { + let hit = isValid(current); + if (hit) { + if (!removedParentheses) { + removedParentheses = s.length - current.length + } + if (s.length - current.length > removedParentheses) return ret.length === 0 ? [""] : ret;; + ret.unshift(current); + continue; + } + for (let i = 0; i < current.length; i++) { + if (current[i] !== ')' && current[i] !== '(') continue; + const subString = current.slice(0, i).concat(current.slice(i + 1)); + if (visited[subString]) continue; + visited[subString] = true; + queue.push(subString); + } + } + + return ret.length === 0 ? [""] : ret; +}; +``` + +## 扩展 + +相似问题: + +[validParentheses](./validParentheses.md) diff --git a/spider/row-markdown/309.best-time-to-buy-and-sell-stock-with-cooldown.md b/spider/row-markdown/309.best-time-to-buy-and-sell-stock-with-cooldown.md new file mode 100644 index 0000000..c2372d3 --- /dev/null +++ b/spider/row-markdown/309.best-time-to-buy-and-sell-stock-with-cooldown.md @@ -0,0 +1,106 @@ +## 题目地址 + +https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/ + +## 题目描述 + +``` +Say you have an array for which the ith element is the price of a given stock on day i. + +Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions: + +You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). +After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day) +Example: + +Input: [1,2,3,0,2] +Output: 3 +Explanation: transactions = [buy, sell, cooldown, buy, sell] +``` + +## 思路 + +这是一道典型的 DP 问题, DP 问题的核心是找到状态和状态转移方程。 + +这道题目的状态似乎比我们常见的那种 DP 问题要多,这里的状态有 buy sell cooldown 三种, +我们可以用三个数组来表示这这三个状态,buy,sell, cooldown. + +- buy[i]表示第 i 天,且以 buy 结尾的最大利润 +- sell[i]表示第 i 天,且以 sell 结尾的最大利润 +- cooldown[i]表示第 i 天,且以 sell 结尾的最大利润 + +我们思考一下,其实 cooldown 这个状态数组似乎没有什么用,因此 cooldown 不会对`profit`产生 +任何影响。 我们可以进一步缩小为两种状态。 + +- buy[i] 表示第 i 天,且以 buy 或者 coolwown 结尾的最大利润 +- sell[i] 表示第 i 天,且以 sell 或者 cooldown 结尾的最大利润 + +对应的状态转移方程如下: + +> 这个需要花点时间来理解 + +``` + buy[i] = Math.max(buy[i - 1], sell[i - 2] - prices[i]); + sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]); +``` + +我们来分析一下,buy[i]对应第 i 的 action 只能是 buy 或者 cooldown。 + +- 如果是 cooldown,那么 profit 就是 buy[i - 1] +- 如果是 buy,那么就是`前一个卖的profit减去今天买股票花的钱`,即 sell[i -2] - prices[i] + +> 注意这里是 i - 2,不是 i-1 ,因为有 cooldown 的限制 + +sell[i]对应第 i 的 action 只能是 sell 或者 cooldown。 + +- 如果是 cooldown,那么 profit 就是 sell[i - 1] +- 如果是 sell,那么就是`前一次买的时候获取的利润加上这次卖的钱`,即 buy[i - 1] + prices[i] + +## 关键点解析 + +- 多状态动态规划 + +## 代码 + +```js +/* + * @lc app=leetcode id=309 lang=javascript + * + * [309] Best Time to Buy and Sell Stock with Cooldown + * + */ +/** + * @param {number[]} prices + * @return {number} + */ +var maxProfit = function(prices) { + if (prices == null || prices.length <= 1) return 0; + + // 定义状态变量 + const buy = []; + const sell = []; + // 寻常 + buy[0] = -prices[0]; + buy[1] = Math.max(-prices[0], -prices[1]); + sell[0] = 0; + sell[1] = Math.max(0, prices[1] - prices[0]); + for (let i = 2; i < prices.length; i++) { + // 状态转移方程 + // 第i天只能是买或者cooldown + // 如果买利润就是sell[i - 2] - prices[i], 注意这里是i - 2,不是 i-1 ,因为有cooldown的限制 + // cooldown就是buy[i -1] + buy[i] = Math.max(buy[i - 1], sell[i - 2] - prices[i]); + // 第i天只能是卖或者cooldown + // 如果卖利润就是buy[i -1] + prices[i] + // cooldown就是sell[i -1] + sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]); + } + + return Math.max(buy[prices.length - 1], sell[prices.length - 1], 0); +}; +``` + +## 相关题目 + +- [121.best-time-to-buy-and-sell-stock](./121.best-time-to-buy-and-sell-stock.md) +- [122.best-time-to-buy-and-sell-stock-ii](./122.best-time-to-buy-and-sell-stock-ii.md) diff --git a/spider/row-markdown/31.next-permutation.md b/spider/row-markdown/31.next-permutation.md new file mode 100644 index 0000000..29c8f00 --- /dev/null +++ b/spider/row-markdown/31.next-permutation.md @@ -0,0 +1,175 @@ +## 题目地址 + +https://leetcode.com/problems/next-permutation/description/ + +## 题目描述 + +``` +Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. + +If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). + +The replacement must be in-place and use only constant extra memory. + +Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. + +1,2,3 → 1,3,2 +3,2,1 → 1,2,3 +1,1,5 → 1,5,1 + +``` + +## 思路 + +符合直觉的方法是我们按顺序求出所有的排列,如果当前排列等于 nums,那么我直接取下一个 +但是这种做法不符合 constant space 要求(题目要求直接修改原数组),时间复杂度也太高,为 O(n!),肯定不是合适的解。 + +这种题目比较抽象,写几个例子通常会帮助理解问题的规律。我找了几个例子,其中蓝色背景表示的是当前数字找下一个更大排列的时候`需要改变的元素`. + +![31.next-permutation](../assets/problems/31.next-permutation-1.jpg) + +我们不难发现,蓝色的数字都是从后往前第一个不递增的元素,并且我们的下一个更大的排列 +只需要改变蓝色的以及之后部分即可,前面的不需要变。 + +那么怎么改变蓝色的以及后面部分呢?为了使增量最小, +由于前面我们观察发现,其实剩下的元素从左到右是递减的,而我们想要变成递增的,我们只需要不断交换首尾元素即可。 + + +另外我们也可以以回溯的角度来思考这个问题,让我们先回溯一次: + +![31.next-permutation-2](../assets/problems/31.next-permutation-2.jpg) + +这个时候可以选择的元素只有2,我们无法组成更大的排列,我们继续回溯,直到如图: + +![31.next-permutation-3](../assets/problems/31.next-permutation-3.jpg) + +我们发现我们可以交换4或者2实现变大的效果,但是要保证变大的幅度最小(下一个更大), +我们需要选择最小的,由于之前我们发现后面是从左到右递减的,显然就是交换最右面大于1的。 + +之后就是不断交换使之幅度最小: + +![31.next-permutation-4](../assets/problems/31.next-permutation-4.jpg) + +## 关键点解析 +- 写几个例子通常会帮助理解问题的规律 +- 在有序数组中首尾指针不断交换位置即可实现reverse +- 找到从右边起`第一个大于nums[i]的`,并将其和nums[i]进行交换 +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=31 lang=javascript + * + * [31] Next Permutation + */ + +function reverseRange(A, i, j) { + while (i < j) { + const temp = A[i]; + A[i] = A[j]; + A[j] = temp; + i++; + j--; + } +} +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ +var nextPermutation = function(nums) { + // 时间复杂度O(n) 空间复杂度O(1) + if (nums == null || nums.length <= 1) return; + + let i = nums.length - 2; + // 从后往前找到第一个降序的,相当于找到了我们的回溯点 + while (i > -1 && nums[i + 1] <= nums[i]) i--; + + // 如果找了就swap + if (i > -1) { + let j = nums.length - 1; + // 找到从右边起第一个大于nums[i]的,并将其和nums[i]进行交换 + // 因为如果交换的数字比nums[i]还要小肯定不符合题意 + while (nums[j] <= nums[i]) j--; + const temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } + + // 最后我们只需要将剩下的元素从左到右,依次填入当前最小的元素就可以保证是大于当前排列的最小值了 + // [i + 1, A.length -1]的元素进行反转 + + reverseRange(nums, i + 1, nums.length - 1); +}; +``` +Python3 Code: +```python +class Solution: + def nextPermutation(self, nums): + """ + Do not return anything, modify nums in-place instead. + :param list nums + """ + # 第一步,从后往前,找到下降点 + down_index = None + for i in range(len(nums)-2, -1, -1): + if nums[i] < nums[i+1]: + down_index = i + break + # 如果没有下降点,重新排列 + if down_index is None: + nums.reverse() + # 如果有下降点 + else: + # 第二步,从后往前,找到比下降点大的数,对换位置 + for i in range(len(nums)-1, i, -1): + if nums[down_index] < nums[i]: + nums[down_index], nums[i] = nums[i], nums[down_index] + break + # 第三部,重新排列下降点之后的数 + i, j = down_index+1, len(nums)-1 + while i < j: + nums[i], nums[j] = nums[j], nums[i] + i += 1 + j -= 1 +``` + +Python3 Code: + +```python +class Solution: + def nextPermutation(self, nums): + """ + Do not return anything, modify nums in-place instead. + :param list nums + """ + # 第一步,从后往前,找到下降点 + down_index = None + for i in range(len(nums)-2, -1, -1): + if nums[i] < nums[i+1]: + down_index = i + break + # 如果没有下降点,重新排列 + if down_index is None: + nums.reverse() + # 如果有下降点 + else: + # 第二步,从后往前,找到比下降点大的数,对换位置 + for i in range(len(nums)-1, i, -1): + if nums[down_index] < nums[i]: + nums[down_index], nums[i] = nums[i], nums[down_index] + break + # 第三步,重新排列下降点之后的数 + i, j = down_index+1, len(nums)-1 + while i < j: + nums[i], nums[j] = nums[j], nums[i] + i += 1 + j -= 1 +``` + +## 相关题目 + +- [46.next-permutation](./46.next-permutation.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [60.permutation-sequence](./60.permutation-sequence.md)(TODO) diff --git a/spider/row-markdown/312.burst-balloons.md b/spider/row-markdown/312.burst-balloons.md new file mode 100644 index 0000000..572e7e2 --- /dev/null +++ b/spider/row-markdown/312.burst-balloons.md @@ -0,0 +1,124 @@ +### 题目地址(312. 戳气球) + +https://leetcode-cn.com/problems/burst-balloons/ + +### 题目描述 + +``` +有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 + +现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。 + +求所能获得硬币的最大数量。 + +说明: + +你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。 +0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 +示例: + +输入: [3,1,5,8] +输出: 167 +解释: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] +  coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 +``` + +### 思路 + +#### 回溯法 + +分析一下这道题,就是要截破所有的气球,获得硬币的最大数量,然后左右两边的气球相邻了。那就截呗,我的第一反应就是暴力,回溯法;但是肯定会超时,为什么呢?因为题目给的气球数量有点多,最多 500 个;500 的阶乘,会超时爆栈;但是我们依然写一下代码,找下突破口,小伙伴们千万不要看不起暴力,暴力是优化的突破口;如果小伙伴对回溯法不太熟悉,我建议你记住下面的模版,也可以看我之前写的文章,回溯法基本可以使用以下的模版写。回溯法省心省力,0 智商负担,懂的朋友都懂,QAQ。 + +#### 代码 + +```js +var maxCoins = function (nums) { + let res = Number.MIN_VALUE; + backtrack(nums, 0); + return res; + // 回溯法,状态树很大 + function backtrack(nums, score) { + if (nums.length == 0) { + res = Math.max(res, score); + return; + } + for (let i = 0, n = nums.length; i < n; i++) { + let point = + (i - 1 < 0 ? 1 : nums[i - 1]) * + nums[i] * + (i + 1 >= n ? 1 : nums[i + 1]); + let tempNums = [].concat(nums); + // 做选择 在 nums 中删除元素 nums[i] + nums.splice(i, 1); + // 递归回溯 + backtrack(nums, score + point); + // 撤销选择 + nums = [...tempNums]; + } + } +}; +``` + +#### 动态规划 + +回溯法的缺点也很明显,复杂度很高,对应本题截气球;小伙伴们可以脑补一下执行过程的状态树,这里我偷个懒就不画了;通过仔细观察这个状态树,我们会发现这个状态树的【选择】上,会有一些重复的选择分支;很明显存在了重复子问题;自然我就想到了能不能用动态规划来解决; + +判读能不能用动态规划解决,还有一个问题,就是必须存在最优子结构;什么意思呢?其实就是根据局部最优,推导出答案;假设我们截破第 k 个气球是最优策略的最后一步,和上一步有没有联系呢?根据题目意思,截破第 k 个,前一个和后一个就变成相邻的了,看似是会有联系,其实是没有的。因为截破第 k 个和 k-1 个是没有联系的,脑补一下回溯法的状态树就更加明确了; + +既然用动态规划,那就老套路了,把动态规划的三个问题想清楚定义好;然后找出题目的【状态】和【选择】,然后根据【状态】枚举,枚举的过程中根据【选择】计算递推就能得到答案了。 + +那本题的【选择】是什么呢?就是截哪一个气球。那【状态】呢?就是题目给的气球数量。 + +1. 定义状态 + +- 这里有个细节,就是题目说明有两个虚拟气球,nums[-1] = nums[n] = 1;如果当前截破的气球是最后一个或者第一个,前面/后面没有气球了,不能乘以 0,而是乘以 1。 +- 定义状态的最关键两个点,往子问题(问题规模变小)想,最后一步最优策略是什么;我们假设最后截破的气球是 k,截破 k 获得最大数量的银币就是 nums[i] _ nums[k] _ nums[j] 再加上前面截破的最大数量和后面的最大数量,即:nums[i] _ nums[k] _ nums[j] + 前面最大数量 + 后面最大数量,就是答案。 +- 而如果我们不考虑两个虚拟气球而直接定义状态,截到最后两个气球的时候又该怎么定义状态来避免和前面的产生联系呢?这两个虚拟气球就恰到好处了,太细节了;这也是本题的一个难点之一。 +- 那我们可以这样来定义状态,dp[i][j] = x 表示,戳破气球 i 和气球 j 之间(开区间,不包括 i 和 j)的所有气球,可以获得的最大硬币数为 x。为什么开区间?因为不能和已经计算过的产生联系,我们这样定义之后,利用两个虚拟气球,截到最后两个气球的时候就完美的避开了所有状态的联系,太细节了。 + +2. 状态转移方程 + +- 而对于 dp[i][j],i 和 j 之间会有很多气球,到底该截哪个先呢?我们直接设为 k,枚举选择最优的 k 就可以了。 +- 所以,最终的状态转移方程为:dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + nums[k] + nums[i] + nums[j]) + +3. 初始值和边界 + +- 由于我们利用了两个虚拟气球,边界就是气球数 n + 2 +- 初始值,当 i == j 时,很明显两个之间没有气球,所有为 0; + +4. 如何枚举状态 + +- 因为我们最终要求的答案是 dp[0][n + 1],就是截破虚拟气球之间的所有气球获得的最大值; +- 当 i == j 时,i 和 j 之间是没有气球的,所以枚举的状态很明显是 dp table 的左上部分,也就是 j 大于 i,如下图所示,只给出一部分方便思考。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfckn1vngxj30lk0aodgf.jpg) + +> 从上图可以看出,我们需要从下到上,从左到右进行遍历。 + +#### 代码 + +```js +var maxCoins = function (nums) { + let n = nums.length; + // 添加两侧的虚拟气球 + let points = [1, ...nums, 1]; + let dp = Array.from(Array(n + 2), () => Array(n + 2).fill(0)); + // 最后一行开始遍历,从下往上 + for (let i = n; i >= 0; i--) { + // 从左往右 + for (let j = i + 1; j < n + 2; j++) { + for (let k = i + 1; k < j; k++) { + dp[i][j] = Math.max( + dp[i][j], + points[j] * points[k] * points[i] + dp[i][k] + dp[k][j] + ); + } + } + } + return dp[0][n + 1]; +}; +``` + +### 总结 + +简单的 dp 题目会直接告诉你怎么定义状态,告诉你怎么选择计算,你只需要根据套路判断一下能不能用 dp 解题即可,而判断能不能,往往暴力就是突破口。而困难点的 dp,我觉的都是细节问题了,要注意的细节太多了。感觉力扣加加,路西法大佬,把我领进了动态规划的大门,共勉。 diff --git a/spider/row-markdown/32.longest-valid-parentheses.md b/spider/row-markdown/32.longest-valid-parentheses.md new file mode 100644 index 0000000..370d896 --- /dev/null +++ b/spider/row-markdown/32.longest-valid-parentheses.md @@ -0,0 +1,110 @@ +## 题目地址 +https://leetcode.com/problems/longest-valid-parentheses/ + +## 题目描述 + +``` +Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. + +Example 1: + +Input: "(()" +Output: 2 +Explanation: The longest valid parentheses substring is "()" +Example 2: + +Input: ")()())" +Output: 4 +Explanation: The longest valid parentheses substring is "()()" +``` + +## 思路(动态规划) + +所有的动态规划问题, 首先需要解决的就是如何寻找合适的子问题. +该题需要我们找到最长的有效括号对, 我们首先想到的就是定义**dp[i]为前i个字符串的最长有效括号对长度**, 但是随后我们会发现, 这样的定义, 我们无法找到dp[i]和dp[i-1]的任何关系. +所以, 我们需要重新找一个新的定义: 定义**dp[i]为以第i个字符结尾的最长有效括号对长度**. 然后, 我们通过下面这个例子找一下dp[i]和dp[i-1]之间的关系. + +```python +s = '(())())' +``` + +从上面的例子我们可以观察出一下几点结论(**描述中i为图中的dp数组的下标, 对应s的下标应为i-1, 第i个字符的i从1开始**). +1. base case: 空字符串的最长有效括号对长度肯定为0, 即: dp[0] = 0; +2. s的第**1**个字符结尾的最长有效括号对长度为0, s的第**2**个字符结尾的最长有效括号对长度也为0, 这个时候我们可以得出结论: 最长有效括号对不可能以'('结尾, 即: dp[1] = d[2] = 0; +3. 当i等于3时, 我们可以看出dp[2]=0, dp[3]=2, 因为第2个字符(**s[1]**)和第3个字符(**s[2]**)是配对的; + 当i等于4时, 我们可以看出dp[3]=2, dp[4]=4, 因为我们配对的是第1个字符(**s[0]**)和第4个字符(**s[3]**); + 因此, 我们可以得出结论: 如果第**i**个字符和第i-1-dp[i-1]个字符是配对的, 则dp[i] = dp[i-1] + 2, 其中: i-1-dp[i-1] >= 1, 因为第0个字符没有任何意义; +4. 根据第3条规则来计算的话, 我们发现dp[5]=0, dp[6]=2, 但是显然, dp[6]应该为6才对, 但是我们发现可以将"(())"和"()"进行拼接, 即: dp[i] += dp[i-dp[i]], 即: dp[6] = 2 + dp[6-2] = 2 + dp[4] = 6 + +根据以上规则, 我们求解dp数组的结果为: [0, 0, 0, 2, 4, 0, 6, 0], 其中最长有效括号对的长度为6. 以下为图解: +![32.longest-valid-parentheses](../assets/problems/32.longest-valid-parentheses.png) + +## 关键点解析 + +1. 第3点特征, 需要检查的字符是s[i-1]和s[i-2-dp[i-1]], 根据定义可知: i-1 >= dp[i-1], 但是i-2不一定大于dp[i-1], 因此, 需要检查越界; +3. 第4点特征最容易遗漏, 还有就是不需要检查越界, 因为根据定义可知: i >= dp[i], 所以dp[i-dp[i]]的边界情况是dp[0]; + +## 思路(栈) +主要思路和常规的括号解法一样,遇到'('入栈,遇到')'出栈,并计算两个括号之间的长度。 +因为这个题存在非法括号对的情况且求是合法括号对的最大长度 所以有两个注意点是: +1. **栈中存的是符号的下标** +2. **当栈为空时且当前扫描到的符号是')'时,需要将这个符号入栈作为分割符** + +## 代码 + +* 语言支持: Python, javascript + +Python Code: +``` +class Solution: + def longestValidParentheses(self, s: str) -> int: + mlen = 0 + slen = len(s) + dp = [0] * (slen + 1) + for i in range(1, len(s) + 1): + # 有效的括号对不可能会以'('结尾的 + if s[i - 1] == '(': + continue + + left_paren = i - 2 - dp[i - 1] + if left_paren >= 0 and s[left_paren] == '(': + dp[i] = dp[i - 1] + 2 + + # 拼接有效括号对 + if dp[i - dp[i]]: + dp[i] += dp[i - dp[i]] + + # 更新最大有效扩对长度 + if dp[i] > mlen: + mlen = dp[i] + + return mlen +``` + +javascript code: +```js +// 用栈来解 +var longestValidParentheses = function(s) { + let stack = new Array() + let longest = 0 + stack.push(-1) + for(let i = 0; i < s.length; i++) { + if (s[i] === '(') { + stack.push(i) + } else { + stack.pop() + if (stack.length === 0) { + stack.push(i) + } else { + longest = Math.max(longest, i - stack[stack.length - 1]) + } + } + } + return longest +}; +``` + +## 扩展 + +1. 如果判断的不仅仅只有'('和')', 还有'[', ']', '{'和'}', 该怎么办? +2. 如果输出的不是长度, 而是任意一个最长有效括号对的字符串, 该怎么办? diff --git a/spider/row-markdown/322.coin-change.md b/spider/row-markdown/322.coin-change.md new file mode 100644 index 0000000..3839254 --- /dev/null +++ b/spider/row-markdown/322.coin-change.md @@ -0,0 +1,179 @@ + +## 题目地址 +https://leetcode.com/problems/coin-change/description/ + +## 题目描述 +``` +You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1. + +Example 1: + +Input: coins = [1, 2, 5], amount = 11 +Output: 3 +Explanation: 11 = 5 + 5 + 1 +Example 2: + +Input: coins = [2], amount = 3 +Output: -1 +Note: +You may assume that you have an infinite number of each kind of coin. + +``` +## 思路 + + +假如我们把coin逆序排列,然后逐个取,取到刚好不大于amout,依次类推。 + +``` +eg: 对于 [1,2,5] 组成 11 块 + +- 排序[5,2,1] + +- 取第一个5, 更新amout 为 11 - 5 = 6 (1⃣️) + 6 > 5 继续更新 为 6 - 5 = 1 (2⃣️) + 1 < 5 退出 + +- 取第二个2 + 1 < 2 退出 + +- 取最后一个元素,也就是1 + + 1 === 1 更新为 1 - 1 = 0 (3⃣️) + +- amout 为 0 退出 + + +因此结果是 3 +``` + +熟悉贪心算法的同学应该已经注意到了,这就是贪心算法,贪心算法更amount尽快地变得更小。 +`经验表明,贪心策略是正确的`。 注意,我说的是经验表明, 贪心算法也有可能出错。 就拿这道题目来说, +他也是不正确的! 比如 `coins = [1, 5, 11] amout = 15`, 因此这种做法有时候不靠谱,我们还是采用靠谱的做法. + +如果我们暴力求解,对于所有的组合都计算一遍,然后比较, 那么这样的复杂度是 2 的 n 次方(这个可以通过数学公式证明,这里不想啰嗦了), +这个是不可以接受的。那么我们是否可以动态规划解决呢?答案是可以,原因就是可以划分为子问题,子问题可以推导出原问题 + +对于动态规划我们可以先画一个二维表,然后观察,其是否可以用一维表代替。 +关于动态规划为什么要画表,我已经在[这篇文章](../thinkings/dynamic-programming.md)解释了 + +比较容易想到的是二维数组: + +```python +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + if amount < 0: + return - 1 + dp = [[amount + 1 for _ in range(len(coins) + 1)] + for _ in range(amount + 1)] + # 初始化第一行为0,其他为最大值(也就是amount + 1) + + for j in range(len(coins) + 1): + dp[0][j] = 0 + + for i in range(1, amount + 1): + for j in range(1, len(coins) + 1): + if i - coins[j - 1] >= 0: + dp[i][j] = min( + dp[i][j - 1], dp[i - coins[j - 1]][j] + 1) + else: + dp[i][j] = dp[i][j - 1] + + return -1 if dp[-1][-1] == amount + 1 else dp[-1][-1] + ``` + + **复杂度分析** +- 时间复杂度:$O(amonut * len(coins))$ +- 空间复杂度:$O(amount * len(coins))$ + +dp[i][j] 依赖于` dp[i][j - 1]`和 `dp[i - coins[j - 1]][j] + 1)` 这是一个优化的信号,我们可以将其优化到一维,具体见下方。 +## 关键点解析 + +- 动态规划 + +- 子问题 + +用dp[i] 来表示组成i块钱,需要最少的硬币数,那么 + +1. 第j个硬币我可以选择不拿 这个时候, 硬币数 = dp[i] + +2. 第j个硬币我可以选择拿 这个时候, 硬币数 = dp[i - coins[j]] + 1 + +- 和背包问题不同, 硬币是可以拿任意个 + +- 对于每一个 dp[i] 我们都选择遍历一遍 coin, 不断更新 dp[i] + +## 代码 + + +* 语言支持:JS,C++,Python3 + +JavaScript Code: +```js + +var coinChange = function(coins, amount) { + if (amount === 0) { + return 0; + } + const dp = Array(amount + 1).fill(Number.MAX_VALUE) + dp[0] = 0; + for (let i = 1; i < dp.length; i++) { + for (let j = 0; j < coins.length; j++) { + if (i - coins[j] >= 0) { + dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); + } + } + } + + return dp[dp.length - 1] === Number.MAX_VALUE ? -1 : dp[dp.length - 1]; + + +}; +``` +C++ Code: +> C++中采用INT_MAX,因此判断时需要加上`dp[a - coin] < INT_MAX`以防止溢出 +```C++ +class Solution { +public: + int coinChange(vector& coins, int amount) { + auto dp = vector(amount + 1, INT_MAX); + dp[0] = 0; + for (auto a = 1; a <= amount; ++a) { + for (const auto & coin : coins) { + if (a >= coin && dp[a - coin] < INT_MAX) { + dp[a] = min(dp[a], dp[a-coin] + 1); + } + } + } + return dp[amount] == INT_MAX ? -1 : dp[amount]; + } +}; +``` + +Python3 Code: + +```python +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + dp = [amount + 1] * (amount + 1) + dp[0] = 0 + + for i in range(1, amount + 1): + for j in range(len(coins)): + if i >= coins[j]: + dp[i] = min(dp[i], dp[i - coins[j]] + 1) + + return -1 if dp[-1] == amount + 1 else dp[-1] +``` + +**复杂度分析** +- 时间复杂度:$O(amonut * len(coins))$ +- 空间复杂度:$O(amount)$ + + +## 扩展 + +这是一道很简单描述的题目, 因此很多时候会被用到大公司的电面中。 + +相似问题: + +[518.coin-change-2](https://github.com/azl397985856/leetcode/blob/master/problems/518.coin-change-2.md) diff --git a/spider/row-markdown/328.odd-even-linked-list.md b/spider/row-markdown/328.odd-even-linked-list.md new file mode 100644 index 0000000..d91266f --- /dev/null +++ b/spider/row-markdown/328.odd-even-linked-list.md @@ -0,0 +1,122 @@ +## 题目地址 + +https://leetcode.com/problems/odd-even-linked-list/description/ + +## 题目描述 + +``` +Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes. + +You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity. + +Example 1: + +Input: 1->2->3->4->5->NULL +Output: 1->3->5->2->4->NULL +Example 2: + +Input: 2->1->3->5->6->4->7->NULL +Output: 2->3->6->7->1->5->4->NULL +Note: + +The relative order inside both the even and odd groups should remain as it was in the input. +The first node is considered odd, the second node even and so on ... +``` + +## 思路 + +符合直觉的想法是,先遍历一遍找出奇数的节点。然后再遍历一遍找出偶数节点,最后串起来。 + +但是有两个问题,如果不修改节点的话,需要借助额外的空间,空间复杂度是 N。如果修改的话,会对第二次遍历(遍历偶数节点)造成影响。 + +因此可以采用一种做法: 遍历一次,每一步同时修改两个节点就好了,这样就可以规避上面两个问题。 + +## 关键点解析 + +- 用虚拟节点来简化操作 + +- 循环的结束条件设置为 `odd && odd.next && even && even.next`, 不应该是`odd && even`, 否则需要记录一下奇数节点的最后一个节点,复杂了操作 + +## 代码 + +- 语言支持:JS,C++ + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=328 lang=javascript + * + * [328] Odd Even Linked List + * + * + */ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +var oddEvenList = function(head) { + if (!head || !head.next) return head; + + const dummyHead1 = { + next: head + }; + const dummyHead2 = { + next: head.next + }; + + let odd = dummyHead1.next; + let even = dummyHead2.next; + + while (odd && odd.next && even && even.next) { + const oddNext = odd.next.next; + const evenNext = even.next.next; + + odd.next = oddNext; + even.next = evenNext; + + odd = oddNext; + even = evenNext; + } + + odd.next = dummyHead2.next; + + return dummyHead1.next; +}; +``` + +C++ Code: + +```C++ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode* oddEvenList(ListNode* head) { + if (head == nullptr) return head; + auto odd = head, evenHead = head->next, even = head->next; + // 因为“每次循环之后依然保持odd在even之前”,循环条件可以只判断even和even->next是否为空,修改odd和even的指向的操作也可以简化 + while (even != nullptr && even->next != nullptr) { + odd->next = even->next; + odd = odd->next; + even->next = odd->next; + even = even->next; + } + odd->next = evenHead; + return head; + } +}; +``` diff --git a/spider/row-markdown/33.search-in-rotated-sorted-array.md b/spider/row-markdown/33.search-in-rotated-sorted-array.md new file mode 100644 index 0000000..96d81c6 --- /dev/null +++ b/spider/row-markdown/33.search-in-rotated-sorted-array.md @@ -0,0 +1,149 @@ +## 题目地址 +https://leetcode.com/problems/search-in-rotated-sorted-array/ + +## 题目描述 + +``` +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. + +(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). + +You are given a target value to search. If found in the array return its index, otherwise return -1. + +You may assume no duplicate exists in the array. + +Your algorithm's runtime complexity must be in the order of O(log n). + +Example 1: + +Input: nums = [4,5,6,7,0,1,2], target = 0 +Output: 4 +Example 2: + +Input: nums = [4,5,6,7,0,1,2], target = 3 +Output: -1 + +``` + +## 思路 + +这是一个我在网上看到的前端头条技术终面的一个算法题。 + +题目要求时间复杂度为logn,因此基本就是二分法了。 这道题目不是直接的有序数组,不然就是easy了。 + +首先要知道,我们随便选择一个点,将数组分为前后两部分,其中一部分一定是有序的。 + +具体步骤: + +- 我们可以先找出mid,然后根据mid来判断,mid是在有序的部分还是无序的部分 + +假如mid小于start,则mid一定在右边有序部分。 +假如mid大于等于start, 则mid一定在左边有序部分。 + +> 注意等号的考虑 + +- 然后我们继续判断target在哪一部分, 我们就可以舍弃另一部分了 + +我们只需要比较target和有序部分的边界关系就行了。 比如mid在右侧有序部分,即[mid, end] +那么我们只需要判断 target >= mid && target <= end 就能知道target在右侧有序部分,我们就 +可以舍弃左边部分了(start = mid + 1), 反之亦然。 + +我们以([6,7,8,1,2,3,4,5], 4)为例讲解一下: + +![search-in-rotated-sorted-array-1](../assets/problems/search-in-rotated-sorted-array-1.jpg) + + +![search-in-rotated-sorted-array-1](../assets/problems/search-in-rotated-sorted-array-2.jpg) + + +## 关键点解析 + +- 二分法 +- 找出有序区间,然后根据target是否在有序区间舍弃一半元素 +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=33 lang=javascript + * + * [33] Search in Rotated Sorted Array + */ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +var search = function(nums, target) { + // 时间复杂度:O(logn) + // 空间复杂度:O(1) + // [6,7,8,1,2,3,4,5] + let start = 0; + let end = nums.length - 1; + + while (start <= end) { + const mid = start + ((end - start) >> 1); + if (nums[mid] === target) return mid; + + // [start, mid]有序 + + // ️⚠️注意这里的等号 + if (nums[mid] >= nums[start]) { + //target 在 [start, mid] 之间 + + // 其实target不可能等于nums[mid], 但是为了对称,我还是加上了等号 + if (target >= nums[start] && target <= nums[mid]) { + end = mid - 1; + } else { + //target 不在 [start, mid] 之间 + start = mid + 1; + } + } else { + // [mid, end]有序 + + // target 在 [mid, end] 之间 + if (target >= nums[mid] && target <= nums[end]) { + start = mid + 1; + } else { + // target 不在 [mid, end] 之间 + end = mid - 1; + } + } + } + + return -1; +}; +``` +Python3 Code: +```python +class Solution: + def search(self, nums: List[int], target: int) -> int: + """用二分法,先判断左右两边哪一边是有序的,再判断是否在有序的列表之内""" + if len(nums) <= 0: + return -1 + + left = 0 + right = len(nums) - 1 + while left < right: + mid = (right - left) // 2 + left + if nums[mid] == target: + return mid + + # 如果中间的值大于最左边的值,说明左边有序 + if nums[mid] > nums[left]: + if nums[left] <= target <= nums[mid]: + right = mid + else: + # 这里 +1,因为上面是 <= 符号 + left = mid + 1 + # 否则右边有序 + else: + # 注意:这里必须是 mid+1,因为根据我们的比较方式,mid属于左边的序列 + if nums[mid+1] <= target <= nums[right]: + left = mid + 1 + else: + right = mid + + return left if nums[left] == target else -1 +``` diff --git a/spider/row-markdown/334.increasing-triplet-subsequence.md b/spider/row-markdown/334.increasing-triplet-subsequence.md new file mode 100644 index 0000000..7c359e3 --- /dev/null +++ b/spider/row-markdown/334.increasing-triplet-subsequence.md @@ -0,0 +1,106 @@ + +## 题目地址 +https://leetcode.com/problems/increasing-triplet-subsequence/description/ + +## 题目描述 + +``` +Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array. + +Formally the function should: + +Return true if there exists i, j, k +such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false. +Note: Your algorithm should run in O(n) time complexity and O(1) space complexity. + +Example 1: + +Input: [1,2,3,4,5] +Output: true +Example 2: + +Input: [5,4,3,2,1] +Output: false +``` + +## 思路 +这道题是求解顺序数字是否有三个递增的排列, 注意这里没有要求连续的,因此诸如滑动窗口的思路是不可以的。 +题目要求O(n)的时间复杂度和O(1)的空间复杂度,因此暴力的做法就不用考虑了。 + +我们的目标就是`依次`找到三个数字,其顺序是递增的。因此我们的做法可以是依次遍历, +然后维护三个变量,分别记录最小值,第二小值,第三小值。只要我们能够填满这三个变量就返回true,否则返回false。 + +![334.increasing-triplet-subsequence](../assets/problems/334.increasing-triplet-subsequence.png) +## 关键点解析 + +- 维护三个变量,分别记录最小值,第二小值,第三小值。只要我们能够填满这三个变量就返回true,否则返回false + +## 代码 +```js + + +/* + * @lc app=leetcode id=334 lang=javascript + * + * [334] Increasing Triplet Subsequence + * + * https://leetcode.com/problems/increasing-triplet-subsequence/description/ + * + * algorithms + * Medium (39.47%) + * Total Accepted: 89.6K + * Total Submissions: 226.6K + * Testcase Example: '[1,2,3,4,5]' + * + * Given an unsorted array return whether an increasing subsequence of length 3 + * exists or not in the array. + * + * Formally the function should: + * + * Return true if there exists i, j, k + * such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return + * false. + * + * Note: Your algorithm should run in O(n) time complexity and O(1) space + * complexity. + * + * + * Example 1: + * + * + * Input: [1,2,3,4,5] + * Output: true + * + * + * + * Example 2: + * + * + * Input: [5,4,3,2,1] + * Output: false + * + * + * + */ +/** + * @param {number[]} nums + * @return {boolean} + */ +var increasingTriplet = function(nums) { + if (nums.length < 3) return false; + let n1 = Number.MAX_VALUE; + let n2 = Number.MAX_VALUE; + + for(let i = 0; i < nums.length; i++) { + if (nums[i] <= n1) { + n1 = nums[i] + } else if (nums[i] <= n2) { + n2 = nums[i] + } else { + return true; + } + } + + return false; +}; +``` diff --git a/spider/row-markdown/335.self-crossing.md b/spider/row-markdown/335.self-crossing.md new file mode 100644 index 0000000..0ff9482 --- /dev/null +++ b/spider/row-markdown/335.self-crossing.md @@ -0,0 +1,117 @@ +## 题目地址(335. 路径交叉) + +https://leetcode-cn.com/problems/self-crossing/ + +## 题目描述 + +``` +给定一个含有 n 个正数的数组 x。从点 (0,0) 开始,先向北移动 x[0] 米,然后向西移动 x[1] 米,向南移动 x[2] 米,向东移动 x[3] 米,持续移动。也就是说,每次移动后你的方位会发生逆时针变化。 + +编写一个 O(1) 空间复杂度的一趟扫描算法,判断你所经过的路径是否相交。 + +  + +示例 1: + +┌───┐ +│   │ +└───┼──> +    │ + +输入: [2,1,1,2] +输出: true +示例 2: + +┌──────┐ +│      │ +│ +│ +└────────────> + +输入: [1,2,3,4] +输出: false +示例 3: + +┌───┐ +│   │ +└───┼> + +输入: [1,1,1,1] +输出: true + +``` + +## 思路 + +符合直觉的做法是$O(N)$时间和空间复杂度的算法。这种算法非常简单,但是题目要求我们使用空间复杂度为$O(1)$的做法。 + +关于空间复杂度为$O(N)$的算法可以参考我之前的[874.walking-robot-simulation](https://github.com/azl397985856/leetcode/blob/be15d243a3b93d7efa731d0589a54a63cbff61ae/problems/874.walking-robot-simulation.md)。 思路基本是类似,只不过 obstacles(障碍物)不是固定的,而是我们不断遍历的时候动态生成的,我们每遇到一个点,就将其标记为 obstacle。随着算法的进行,我们的 obstacles 逐渐增大,最终和 N 一个量级。 + +我们考虑进行优化。我们仔细观察发现,如果想让其不相交,从大的范围来看只有两种情况: + +1. 我们画的圈不断增大。 +2. 我们画的圈不断减少。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gbepb3y3uwj30te1dagn5.jpg) +(有没有感觉像迷宫?) + +这样我们会发现,其实我们画最新一笔的时候,并不是之前画的所有的都需要考虑,我们只需要最近的几个就可以了,实际上是最近的五个,不过不知道也没关系,我们稍后会讲解。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gbepcb2ojwj30to0lamxm.jpg) + +红色部分指的是我们需要考虑的,而剩余没有被红色标注的部分则无需考虑。不是因为我们无法与之相交,而是我们`一旦与之相交,则必然我们也一定会与红色标记部分相交`。 + +然而我们画的方向也是不用考虑的。比如我当前画的方向是从左到右,那和我画的方向是从上到下有区别么?在这里是没区别的,不信我帮你将上图顺时针旋转 90 度看一下: + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gbepgmzlopj30mk1cwwfn.jpg) + +方向对于我们考虑是否相交没有差别。 + +当我们仔细思考的时候,会发现其实相交的情况只有以下几种: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gbepi1aegtj30ro0o6aat.jpg) + +这个时候代码就呼之欲出了。 + +- 我们只需要遍历数组 x,假设当前是第 i 个元素。 +- 如果 x[i] >= x[i - 2] and x[i - 1] <= x[i - 3],则相交(第一种情况) +- 如果 x[i - 1] <= x[i - 3] and x[i - 2] <= x[i],则相交(第二种情况) +- 如果 i > 3 and x[i - 1] == x[i - 3] and x[i] + x[i - 4] == x[i - 2],则相交(第三种情况) +- 如果 i > 4 and x[i] + x[i - 4] >= x[i - 2] and x[i - 1] >= x[i - 3] - x[i - 5] \ + and x[i - 1] <= x[i - 3] and x[i - 2] >= x[i - 4] and x[i - 3] >= x[i - 5] ,则相交(第四种情况) +- 否则不相交 + +## 关键点解析 + +- 一定要画图辅助 +- 对于这种$O(1)$空间复杂度有固定的套路。常见的有: + +1. 直接修改原数组 +2. 滑动窗口(当前状态并不是和之前所有状态有关,而是仅和某几个有关)。 + +我们采用的是滑动窗口。但是难点就在于我们怎么知道当前状态和哪几个有关。对于这道题来说,画图或许可以帮助你打开思路。另外面试的时候说出$O(N)$的思路也不失为一个帮助你冷静分析问题的手段。 + +## 代码 + +代码支持:Python3 + +Python3 Code: + +```python +class Solution: + def isSelfCrossing(self, x: List[int]) -> bool: + n = len(x) + if n < 4: + return False + for i in range(3, n): + if x[i] >= x[i - 2] and x[i - 1] <= x[i - 3]: + return True + if x[i - 1] <= x[i - 3] and x[i - 2] <= x[i]: + return True + if i > 3 and x[i - 1] == x[i - 3] and x[i] + x[i - 4] == x[i - 2]: + return True + if i > 4 and x[i] + x[i - 4] >= x[i - 2] and x[i - 1] >= x[i - 3] - x[i - 5] \ + and x[i - 1] <= x[i - 3] and x[i - 2] >= x[i - 4] and x[i - 3] >= x[i - 5]: + return True + return False +``` diff --git a/spider/row-markdown/342.power-of-four.md b/spider/row-markdown/342.power-of-four.md new file mode 100644 index 0000000..b07b83f --- /dev/null +++ b/spider/row-markdown/342.power-of-four.md @@ -0,0 +1,131 @@ +## 题目地址 + +https://leetcode.com/problems/power-of-four/description/ + +## 题目描述 + +``` +Given an integer (signed 32 bits), write a function to check whether it is a power of 4. + +Example 1: + +Input: 16 +Output: true +Example 2: + +Input: 5 +Output: false +Follow up: Could you solve it without loops/recursion? + +``` + +## 思路 + +符合直觉的做法是不停除以 4 直到不能整除,然后判断是否为 1 即可。 代码如下: + +```js +while (num && num % 4 == 0) { + num /= 4; +} +return num == 1; +``` + +但是这道题目有一个 follow up: “你是否可以不使用循环/递归完成”。因此我们需要换种思路。 + +我们先来看下,4 的幂次方用 2 进制表示是什么样的. + +![263.342.power-of-four-1](../assets/problems/342.power-of-four-1.png) + +发现规律: 4 的幂次方的二进制表示 1 的位置都是在奇数位(且不在最低位),其他位置都为 0 + +我们还可以发现: 2 的幂次方的特点是最低位之外,其他位置有且仅有一个 1(1 可以在任意位置) + +我们进一步分析,如果一个数字是四的幂次方,那么只需要满足: + +1. 是 2 的幂次方, 就能保证最低位之外,其他位置有且仅有一个 1 +2. 这个 1 不在偶数位置,一定在奇数位置 + +对于第一点,如果保证一个数字是 2 的幂次方呢? 显然不能不停除以 2,看结果是否等于 1,这样就循环了。 +我们可以使用一个 trick, 如果一个数字 n 是 2 的幂次方,那么 n & (n - 1) 一定等于 0, +这个可以作为思考题,大家思考一下。 + +对于第二点,我们可以取一个特殊数字,这个特殊数字,奇数位置都是 1,偶数位置都是 0,然后和这个特殊数字 +`求与`, 如果等于本身,那么毫无疑问,这个 1 不再偶数位置,一定在奇数位置,因为如果在偶数位置,`求与`的结果就是 0 了 +题目要求 n 是 32 位有符号整形,那么我们的特殊数字就应该是`01010101010101010101010101010101`(不用数了,一共 32 位)。 + +![263.342.power-of-four-2](../assets/problems/342.power-of-four-2.png) + +如上图,64和这个特殊数字求与,得到的是本身。 8 是 2的次方,但是不是4的次方,我们求与结果就是0了。 + +为了体现自己的逼格,我们可以使用计算器,来找一个逼格比较高的数字,这里我选了十六进制,结果是`0x55555555`。 + +![263.342.power-of-four](../assets/problems/342.power-of-four.png) + +代码见下方代码区。 + +说实话,这种做法不容易想到,其实还有一种方法。 +如果一个数字是 4 的幂次方,那么只需要满足: + +1. 是二的倍数 +2. 减去 1 是三的倍数 + +代码如下: + +```js +return num > 0 && (num & (num - 1)) === 0 && (num - 1) % 3 === 0; +``` + +## 关键点 + +- 数论 +- 2的幂次方特点(数学性质以及二进制表示) +- 4的幂次方特点(数学性质以及二进制表示) + +## 代码 + +语言支持:JS, Python + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=342 lang=javascript + * + * [342] Power of Four + */ +/** + * @param {number} num + * @return {boolean} + */ +var isPowerOfFour = function(num) { + // tag: 数论 + + if (num === 1) return true; + if (num < 4) return false; + + if ((num & (num - 1)) !== 0) return false; + + return (num & 0x55555555) === num; +}; +``` + +Python Code: + +```python +class Solution: + def isPowerOfFour(self, num: int) -> bool: + if num == 1: + return True + elif num < 4: + return False + else: + if not num & (num-1) == 0: + return False + else: + return num & 0x55555555 == num + + # 另一种解法:将数字转化为二进制表示的字符串,利用字符串的相关操作进行判断 + def isPowerOfFour(self, num: int) -> bool: + binary_num = bin(num)[2:] + return binary_num.strip('0') == '1' and len(binary_num) % 2 == 1 +``` diff --git a/spider/row-markdown/343.integer-break.md b/spider/row-markdown/343.integer-break.md new file mode 100644 index 0000000..6f4e735 --- /dev/null +++ b/spider/row-markdown/343.integer-break.md @@ -0,0 +1,191 @@ +## 题目地址(343. 整数拆分) + +https://leetcode-cn.com/problems/integer-break/ + +## 题目描述 + +给定一个正整数  n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 + +示例 1: + +输入: 2 +输出: 1 +解释: 2 = 1 + 1, 1 × 1 = 1。 +示例  2: + +输入: 10 +输出: 36 +解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。 +说明: 你可以假设  n  不小于 2 且不大于 58。 + +## 思路 + +希望通过这篇题解让大家知道“题解区的水有多深”,让大家知道“什么才是好的题解”。 + +我看了很多人的题解直接就是两句话,然后跟上代码: + +```python +class Solution: + def integerBreak(self, n: int) -> int: + dp = [1] * (n + 1) + for i in range(3, n + 1): + for j in range(1, i): + dp[i] = max(j * dp[i - j], j * (i - j), dp[i]) + return dp[n] +``` + +这种题解说实话,只针对那些”自己会, 然后去题解区看看有没有新的更好的解法的人“。但是大多数看题解的人是那种`自己没思路,不会做的人`。那么这种题解就没什么用了。 + +我认为`好的题解应该是新手友好的,并且能够将解题人思路完整展现的题解`。比如看到这个题目,我首先想到了什么(对错没有关系),然后头脑中经过怎么样的筛选将算法筛选到具体某一个或某几个。我的最终算法是如何想到的,有没有一些先行知识。 + +当然我也承认自己有很多题解也是直接给的答案,这对很多人来说用处不大,甚至有可能有反作用,给他们一种”我已经会了“的假象。实际上他们根本不懂解题人本身原本的想法, 也许是写题解的人觉得”这很自然“,也可能”只是为了秀技“。 + +Ok,下面来讲下`我是如何解这道题的`。 + +### 抽象 + +首先看到这道题,自然而然地先对问题进行抽象,这种抽象能力是必须的。LeetCode 实际上有很多这种穿着华丽外表的题,当你把这个衣服扒开的时候,会发现都是差不多的,甚至两个是一样的,这样的例子实际上有很多。 就本题来说,就有一个剑指 Offer 的原题[《剪绳子》](https://leetcode-cn.com/problems/jian-sheng-zi-lcof/)和其本质一样,只是换了描述方式。类似的有力扣 137 和 645 等等,大家可以自己去归纳总结。 + +> 137 和 645 我贴个之前写的题解 https://leetcode-cn.com/problems/single-number/solution/zhi-chu-xian-yi-ci-de-shu-xi-lie-wei-yun-suan-by-3/ + +**培养自己抽象问题的能力,不管是在算法上还是工程上。** 务必记住这句话! + +数学是一门非常抽象的学科,同时也很方便我们抽象问题。为了显得我的题解比较高级,引入一些你们看不懂的数学符号也是很有必要的(开玩笑,没有什么高级数学符号啦)。 + +> 实际上这道题可以用纯数学角度来解,但是我相信大多数人并不想看。即使你看了,大多人的感受也是“好 nb,然而并没有什么用”。 + +这道题抽象一下就是: + +令: +![](https://tva1.sinaimg.cn/large/007S8ZIlly1geu3kolxoyj305o03cwef.jpg) +(图 1) +求: +![](https://tva1.sinaimg.cn/large/007S8ZIlly1geu3jy6mxkj305o0360sp.jpg) +(图 2) + +## 第一直觉 + +经过上面的抽象,我的第一直觉这可能是一个数学题,我回想了下数学知识,然后用数学法 AC 了。 数学就是这么简单平凡且枯燥。 + +然而如果没有数学的加持的情况下,我继续思考怎么做。我想是否可以枚举所有的情况(如图 1),然后对其求最大值(如图 2)。 + +问题转化为如何枚举所有的情况。经过了几秒钟的思考,我发现这是一个很明显的递归问题。 具体思考过程如下: + +- 我们将原问题抽象为 f(n) +- 那么 f(n) 等价于 max(1 \* fn(n - 1), 2 \* f(n - 2), ..., (n - 1) \* f(1))。 + +用数学公式表示就是: + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1geu3swzc9ej30co03yaa4.jpg) +(图 3) + +截止目前,是一点点数学 + 一点点递归,我们继续往下看。现在问题是不是就很简单啦?直接翻译图三为代码即可,我们来看下这个时候的代码: + +```python +class Solution: + def integerBreak(self, n: int) -> int: + if n == 2: return 1 + res = 0 + for i in range(1, n): + res = max(res, max(i * self.integerBreak(n - i),i * (n - i))) + return res +``` + +毫无疑问,超时了。原因很简单,就是算法中包含了太多的重复计算。如果经常看我的题解的话,这句话应该不陌生。我随便截一个我之前讲过这个知识点的图。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1geu3zfz89jj313p0u0wnj.jpg) +(图 4) + +> 原文链接:https://github.com/azl397985856/leetcode/blob/master/thinkings/dynamic-programming.md + +大家可以尝试自己画图理解一下。 + +> 看到这里,有没有种殊途同归的感觉呢? + +## 考虑优化 + +如上,我们可以考虑使用记忆化递归的方式来解决。只是用一个 hashtable 存储计算过的值即可。 + +```python +class Solution: + @lru_cache() + def integerBreak(self, n: int) -> int: + if n == 2: return 1 + res = 0 + for i in range(1, n): + res = max(res, max(i * self.integerBreak(n - i),i * (n - i))) + return res +``` + +为了简单起见(偷懒起见),我直接用了 lru_cache 注解, 上面的代码是可以 AC 的。 + +## 动态规划 + +看到这里的同学应该发现了,这个套路是不是很熟悉?下一步就是将其改造成动态规划了。 + +如图 4,我们的思考方式是从顶向下,这符合人们思考问题的方式。将其改造成如下图的自底向上方式就是动态规划。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1geu4a1grbvj31eq0r0wj8.jpg) +(图 5) + +现在再来看下文章开头的代码: + +```python +class Solution: + def integerBreak(self, n: int) -> int: + dp = [1] * (n + 1) + for i in range(3, n + 1): + for j in range(1, i): + dp[i] = max(j * dp[i - j], j * (i - j), dp[i]) + return dp[n] +``` + +dp table 存储的是图 3 中 f(n)的值。一个自然的想法是令 dp[i] 等价于 f(i)。而由于上面分析了原问题等价于 f(n),那么很自然的原问题也等价于 dp[n]。 + +而 dp[i]等价于 f(i),那么上面针对 f(i) 写的递归公式对 dp[i] 也是适用的,我们拿来试试。 + +``` +// 关键语句 +res = max(res, max(i * self.integerBreak(n - i),i * (n - i))) +``` + +翻译过来就是: + +``` +dp[i] = max(dp[i], max(i * dp(n - i),i * (n - i))) +``` + +而这里的 n 是什么呢?我们说了`dp是自底向下的思考方式`,那么在达到 n 之前是看不到整体的`n` 的。因此这里的 n 实际上是 1,2,3,4... n。 + +自然地,我们用一层循环来生成上面一系列的 n 值。接着我们还要生成一系列的 i 值,注意到 n - i 是要大于 0 的,因此 i 只需要循环到 n - 1 即可。 + +思考到这里,我相信上面的代码真的是`不难得出`了。 + +## 关键点 + +- 数学抽象 +- 递归分析 +- 记忆化递归 +- 动态规划 + +## 代码 + +```python +class Solution: + def integerBreak(self, n: int) -> int: + dp = [1] * (n + 1) + for i in range(3, n + 1): + for j in range(1, i): + dp[i] = max(j * dp[i - j], j * (i - j), dp[i]) + return dp[n] +``` + +## 总结 + +培养自己的解题思维很重要, 不要直接看别人的答案。而是要将别人的东西变成自己的, 而要做到这一点,你就要知道“他们是怎么想到的”,“想到这点是不是有什么前置知识”,“类似题目有哪些”。 + +最优解通常不是一下子就想到了,这需要你在不那么优的解上摔了很多次跟头之后才能记住的。因此在你没有掌握之前,不要直接去看最优解。 在你掌握了之后,我不仅鼓励你去写最优解,还鼓励去一题多解,从多个解决思考问题。 到了那个时候, 萌新也会惊讶地呼喊“哇塞, 这题还可以这么解啊?”。 你也会低调地发出“害,解题就是这么简单平凡且枯燥。”的声音。 + +## 扩展 + +正如我开头所说,这种套路实在是太常见了。希望大家能够识别这种问题的本质,彻底掌握这种套路。另外我对这个套路也在我的新书《LeetCode 题解》中做了介绍,本书目前刚完成草稿的编写,如果你想要第一时间获取到我们的题解新书,那么请发送邮件到 `azl397985856@gmail.com`,标题著明“书籍《LeetCode 题解》预定”字样。。 diff --git a/spider/row-markdown/349.intersection-of-two-arrays.md b/spider/row-markdown/349.intersection-of-two-arrays.md new file mode 100644 index 0000000..17b255e --- /dev/null +++ b/spider/row-markdown/349.intersection-of-two-arrays.md @@ -0,0 +1,126 @@ + +## 题目地址 +https://leetcode.com/problems/intersection-of-two-arrays/description/ + +## 题目描述 + +``` +Given two arrays, write a function to compute their intersection. + +Example 1: + +Input: nums1 = [1,2,2,1], nums2 = [2,2] +Output: [2] +Example 2: + +Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] +Output: [9,4] +Note: + +Each element in the result must be unique. +The result can be in any order. + +``` + +## 思路 + +先遍历第一个数组,将其存到hashtable中, +然后遍历第二个数组,如果在hashtable中存在就push到return,然后清空hashtable即可。 + +## 关键点解析 + +无 + +## 代码 + +* 语言支持:JS, Python + +Javascript Code: + +```js +/* + * @lc app=leetcode id=349 lang=javascript + * + * [349] Intersection of Two Arrays + * + * https://leetcode.com/problems/intersection-of-two-arrays/description/ + * + * algorithms + * Easy (53.11%) + * Total Accepted: 203.6K + * Total Submissions: 380.9K + * Testcase Example: '[1,2,2,1]\n[2,2]' + * + * Given two arrays, write a function to compute their intersection. + * + * Example 1: + * + * + * Input: nums1 = [1,2,2,1], nums2 = [2,2] + * Output: [2] + * + * + * + * Example 2: + * + * + * Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] + * Output: [9,4] + * + * + * Note: + * + * + * Each element in the result must be unique. + * The result can be in any order. + * + * + * + * + */ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[]} + */ +var intersection = function(nums1, nums2) { + const visited = {}; + const ret = []; + for(let i = 0; i < nums1.length; i++) { + const num = nums1[i]; + + visited[num] = num; + } + + for(let i = 0; i < nums2.length; i++) { + const num = nums2[i]; + + if (visited[num] !== undefined) { + ret.push(num); + visited[num] = undefined; + } + } + + return ret; + +}; +``` + +Python Code: + +```python +class Solution: + def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: + visited, result = {}, [] + for num in nums1: + visited[num] = num + for num in nums2: + if num in visited: + result.append(num) + visited.pop(num) + return result + + # 另一种解法:利用 Python 中的集合进行计算 + def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: + return set(nums1) & set(nums2) +``` diff --git a/spider/row-markdown/365.water-and-jug-problem.md b/spider/row-markdown/365.water-and-jug-problem.md new file mode 100644 index 0000000..6db3684 --- /dev/null +++ b/spider/row-markdown/365.water-and-jug-problem.md @@ -0,0 +1,208 @@ + +## 题目地址 +https://leetcode.com/problems/water-and-jug-problem/description/ + +## 题目描述 + +``` +You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You need to determine whether it is possible to measure exactly z litres using these two jugs. + +If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end. + +Operations allowed: + +Fill any of the jugs completely with water. +Empty any of the jugs. +Pour water from one jug into another till the other jug is completely full or the first jug itself is empty. +Example 1: (From the famous "Die Hard" example) + +Input: x = 3, y = 5, z = 4 +Output: True +Example 2: + +Input: x = 2, y = 6, z = 5 +Output: False + +``` + + +## BFS(超时) + +### 思路 + +两个水壶的水我们考虑成状态,然后我们不断进行倒的操作,改变状态。那么初始状态就是(0 0) 目标状态就是 (any, z)或者 (z, any),其中any 指的是任意升水。 + + +已题目的例子,其过程示意图,其中括号表示其是由哪个状态转移过来的: + +0 0 +3 5(0 0) 3 0 (0 0 )0 5(0 0) +3 2(0 5) 0 3(0 0) +0 2(3 2) +2 0(0 2) +2 5(2 0) +3 4(2 5) bingo + +### 代码 + +```python +class Solution: + def canMeasureWater(self, x: int, y: int, z: int) -> bool: + if x + y < z: + return False + queue = [(0, 0)] + seen = set((0, 0)) + + while(len(queue) > 0): + a, b = queue.pop(0) + if a ==z or b == z or a + b == z: + return True + states = set() + + states.add((x, b)) + states.add((a, y)) + states.add((0, b)) + states.add((a, 0)) + states.add((min(x, b + a), 0 if b < x - a else b - (x - a))) + states.add((0 if a + b < y else a - (y - b), min(b + a, y))) + for state in states: + if state in seen: + continue; + queue.append(state) + seen.add(state) + return False +``` + +**复杂度分析** + +- 时间复杂度:由于状态最多有$O((x + 1) * (y + 1))$ 种,因此总的时间复杂度为$O(x * y)$。 +- 空间复杂度:我们使用了队列来存储状态,set 存储已经访问的元素,空间复杂度和状态数目一致,因此空间复杂度是$O(x * y)$。 + +上面的思路很直观,但是很遗憾这个算法在 LeetCode 的表现是 TLE(Time Limit Exceeded)。不过如果你能在真实面试中写出这样的算法,我相信大多数情况是可以过关的。 + +我们来看一下有没有别的解法。实际上,上面的算法就是一个标准的 BFS。如果从更深层次去看这道题,会发现这道题其实是一道纯数学问题,类似的纯数学问题在 LeetCode 中也会有一些,不过大多数这种题目,我们仍然可以采取其他方式 AC。那么让我们来看一下如何用数学的方式来解这个题。 + +## 数学法 - 最大公约数 + +### 思路 + +这是一道关于`数论`的题目,确切地说是关于`裴蜀定理`(英语:Bézout's identity)的题目。 + +摘自wiki的定义: + +``` +对任意两个整数 a、b,设 d是它们的最大公约数。那么关于未知数 x和 y的线性丢番图方程(称为裴蜀等式): + +ax+by=m + +有整数解 (x,y) 当且仅当 m是 d的整数倍。裴蜀等式有解时必然有无穷多个解。 + +``` + +因此这道题可以完全转化为`裴蜀定理`。还是以题目给的例子`x = 3, y = 5, z = 4`,我们其实可以表示成`3 * 3 - 1 * 5 = 4`, 即`3 * x - 1 * y = z`。我们用a和b分别表示3 +升的水壶和5升的水壶。那么我们可以: + + +- 倒满a(**1**) +- 将a倒到b +- 再次倒满a(**2**) +- 再次将a倒到b(a这个时候还剩下1升) +- 倒空b(**-1**) +- 将剩下的1升倒到b +- 将a倒满(**3**) +- 将a倒到b +- b此时正好是4升 + +上面的过程就是`3 * x - 1 * y = z`的具体过程解释。 + +**也就是说我们只需要求出x和y的最大公约数d,并判断z是否是d的整数倍即可。** + + +### 代码 + +代码支持:Python3,JavaScript + + +Python Code: + +```python +class Solution: + def canMeasureWater(self, x: int, y: int, z: int) -> bool: + if x + y < z: + return False + + if (z == 0): + return True + + if (x == 0): + return y == z + + if (y == 0): + return x == z + + def GCD(a, b): + smaller = min(a, b) + while smaller: + if a % smaller == 0 and b % smaller == 0: + return smaller + smaller -= 1 + + return z % GCD(x, y) == 0 +``` + +JavaScript: + + +```js +/** + * @param {number} x + * @param {number} y + * @param {number} z + * @return {boolean} + */ +var canMeasureWater = function(x, y, z) { + if (x + y < z) return false; + + if (z === 0) return true; + + if (x === 0) return y === z; + + if (y === 0) return x === z; + + function GCD(a, b) { + let min = Math.min(a, b); + while (min) { + if (a % min === 0 && b % min === 0) return min; + min--; + } + return 1; + } + + return z % GCD(x, y) === 0; +}; +``` + +实际上求最大公约数还有更好的方式,比如辗转相除法: + +```python +def GCD(a, b): + if b == 0: return a + return GCD(b, a % b) +``` + +**复杂度分析** + +- 时间复杂度:$O(log(max(a, b)))$ +- 空间复杂度:空间复杂度取决于递归的深度,因此空间复杂度为 $O(log(max(a, b)))$ + + +## 关键点分析 + +- 数论 +- 裴蜀定理 + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经接近30K star啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/371.sum-of-two-integers.md b/spider/row-markdown/371.sum-of-two-integers.md new file mode 100644 index 0000000..a52df6a --- /dev/null +++ b/spider/row-markdown/371.sum-of-two-integers.md @@ -0,0 +1,61 @@ + +## 题目地址 +https://leetcode.com/problems/sum-of-two-integers/description/ + +## 题目描述 + +``` +Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. + +Example 1: + +Input: a = 1, b = 2 +Output: 3 +Example 2: + +Input: a = -2, b = 3 +Output: 1 + +``` + +## 思路 + +不能使用加减法来求加法。 我们只能朝着位元算的角度来思考了。 + +由于`异或`是`相同则位0,不同则位1`,因此我们可以把异或看成是一种不进位的加减法。 + +![371.sum-of-two-integers-1](../assets/problems/371.sum-of-two-integers-1.png) + +由于`与`是`全部位1则位1,否则位0`,因此我们可以求与之后左移一位来表示进位。 + +![371.sum-of-two-integers-2](../assets/problems/371.sum-of-two-integers-2.png) + +然后我们对上述两个元算结果递归求解即可。 递归的结束条件就是其中一个为0,我们直接返回另一个。 + +## 关键点解析 + +- 位运算 +- 异或是一种不进位的加减法 +- 求与之后左移一位来可以表示进位 + +## 代码 +```js +/* + * @lc app=leetcode id=371 lang=javascript + * + * [371] Sum of Two Integers + */ +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +var getSum = function(a, b) { + if (a === 0) return b; + + if (b === 0) return a; + + return getSum(a ^ b, (a & b) << 1); +}; +``` + diff --git a/spider/row-markdown/378.kth-smallest-element-in-a-sorted-matrix.md b/spider/row-markdown/378.kth-smallest-element-in-a-sorted-matrix.md new file mode 100644 index 0000000..8054da9 --- /dev/null +++ b/spider/row-markdown/378.kth-smallest-element-in-a-sorted-matrix.md @@ -0,0 +1,155 @@ +## 题目地址 + +https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/description/ + +## 题目描述 + +``` +Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix. + +Note that it is the kth smallest element in the sorted order, not the kth distinct element. + +Example: + +matrix = [ + [ 1, 5, 9], + [10, 11, 13], + [12, 13, 15] +], +k = 8, + +return 13. +Note: +You may assume k is always valid, 1 ≤ k ≤ n2. +``` + +## 思路 + +显然用大顶堆可以解决,时间复杂度 Klogn n 为总的数字个数, +但是这种做法没有利用题目中 sorted matrix 的特点,因此不是一种好的做法. + +一个巧妙的方法是二分法,我们分别从第一个和最后一个向中间进行扫描,并且计算出中间的数值与数组中的进行比较, +可以通过计算中间值在这个数组中排多少位,然后得到比中间值小的或者大的数字有多少个,然后与 k 进行比较,如果比 k 小则说明中间值太小了,则向后移动,否则向前移动。 + +这个题目的二分确实很难想,我们来一步一步解释。 + +最普通的二分法是有序数组中查找指定值(或者说满足某个条件的值)。由于是有序的,我们可以根据索引关系来确定大小关系, +因此这种思路比较直接,但是对于这道题目索引大小和数字大小没有直接的关系,因此这种二分思想就行不通了。 + +![378.kth-smallest-element-in-a-sorted-matrix-1](../assets/problems/378.kth-smallest-element-in-a-sorted-matrix-1.jpg) + +(普通的基于索引判断的二分法) + +- 我们能够找到矩阵中最大的元素(右下角)和最小的元素(左上角)。我们可以求出值的中间,而不是上面那种普通二分法的索引的中间。 + +![378.kth-smallest-element-in-a-sorted-matrix-3](../assets/problems/378.kth-smallest-element-in-a-sorted-matrix-3.jpg) + +- 找到中间值之后,我们可以拿这个值去计算有多少元素是小于等于它的。 +具体方式就是比较行的最后一列,如果中间值比最后一列大,说明中间元素肯定大于这一行的所有元素。 否则我们从后往前遍历直到不大于。 + +![378.kth-smallest-element-in-a-sorted-matrix-2](../assets/problems/378.kth-smallest-element-in-a-sorted-matrix-2.jpg) + +- 上一步我们会计算一个count,我们拿这个count和k进行比较 + +- 如果count小于k,说明我们选择的中间值太小了,肯定不符合条件,我们需要调整左区间为mid + 1 + +- 如果count大于k,说明我们选择的中间值正好或者太大了。我们调整右区间 mid + +> 由于count大于k 也可能我们选择的值是正好的, 因此这里不能调整为mid - 1, 否则可能会得不到结果 + +- 最后直接返回start, end, 或者 mid都可以,因此三者最终会收敛到矩阵中的一个元素,这个元素也正是我们要找的元素。 + +整个计算过程是这样的: + +![378.kth-smallest-element-in-a-sorted-matrix-4](../assets/problems/378.kth-smallest-element-in-a-sorted-matrix-4.jpg) + +这里有一个大家普遍都比较疑惑的点,也是我当初非常疑惑,困扰我很久的点, leetcode评论区也有很多人来问,就是“能够确保最终我们找到的元素一定在矩阵中么?” + +答案是可以, `相等的时候一定在matrix里面。 因为原问题一定有解,找下界使得start不断的逼近于真实的元素`. + +我是看了评论区一个大神的评论才明白的,以下是[@GabrielaSong](https://leetcode.com/gabrielasong/)的评论原文: + +``` +The lo we returned is guaranteed to be an element in the matrix is because: +Let us assume element m is the kth smallest number in the matrix, and x is the number of element m in the matrix. +When we are about to reach convergence, if mid=m-1, its count value (the number of elements which are <= mid) would be k-x, +so we would set lo as (m-1)+1=m, in this case the hi will finally reach lo; +and if mid=m+1, its count value would be k+x-1, so we would set hi as m+1, in this case the lo will finally reach m. +To sum up, because the number lo found by binary search find is exactly the element which has k number of elements in the matrix that are <= lo, + The equal sign guarantees there exists and only exists one number in range satisfying this condition. + So lo must be the only element satisfying this element in the matrix. + +``` + +更多解释,可以参考[leetcode discuss](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/discuss/85173/Share-my-thoughts-and-Clean-Java-Code) + +> 如果是普通的二分查找,我们是基于索引去找,因此不会有这个问题。 + + +## 关键点解析 + +- 二分查找 + +- 有序矩阵的套路(文章末尾还有一道有序矩阵的题目) + +- 堆(优先级队列) + +## 代码 + +```js +/* + * @lc app=leetcode id=378 lang=javascript + * + * [378] Kth Smallest Element in a Sorted Matrix + */ +function notGreaterCount(matrix, target) { + // 等价于在matrix 中搜索mid,搜索的过程中利用有序的性质记录比mid小的元素个数 + + // 我们选择左下角,作为开始元素 + let curRow = 0; + // 多少列 + const COL_COUNT = matrix[0].length; + // 最后一列的索引 + const LAST_COL = COL_COUNT - 1; + let res = 0; + + while (curRow < matrix.length) { + // 比较最后一列的数据和target的大小 + if (matrix[curRow][LAST_COL] < target) { + res += COL_COUNT; + } else { + let i = COL_COUNT - 1; + while (i < COL_COUNT && matrix[curRow][i] > target) { + i--; + } + // 注意这里要加1 + res += i + 1; + } + curRow++; + } + + return res; +} +/** + * @param {number[][]} matrix + * @param {number} k + * @return {number} + */ +var kthSmallest = function(matrix, k) { + if (matrix.length < 1) return null; + let start = matrix[0][0]; + let end = matrix[matrix.length - 1][matrix[0].length - 1]; + while (start < end) { + const mid = start + ((end - start) >> 1); + const count = notGreaterCount(matrix, mid); + if (count < k) start = mid + 1; + else end = mid; + } + // 返回start,mid, end 都一样 + return start; +}; +``` + +## 相关题目 + +- [240.search-a-2-d-matrix-ii](./240.search-a-2-d-matrix-ii.md) diff --git a/spider/row-markdown/380.insert-delete-getrandom-o1.md b/spider/row-markdown/380.insert-delete-getrandom-o1.md new file mode 100644 index 0000000..09bb4ea --- /dev/null +++ b/spider/row-markdown/380.insert-delete-getrandom-o1.md @@ -0,0 +1,169 @@ +## 题目地址(380. 常数时间插入、删除和获取随机元素) + +https://leetcode-cn.com/problems/insert-delete-getrandom-o1/description/ + +## 题目描述 + +``` +设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。 + +insert(val):当元素 val 不存在时,向集合中插入该项。 +remove(val):元素 val 存在时,从集合中移除该项。 +getRandom:随机返回现有集合中的一项。每个元素应该有相同的概率被返回。 +示例 : + +// 初始化一个空的集合。 +RandomizedSet randomSet = new RandomizedSet(); + +// 向集合中插入 1 。返回 true 表示 1 被成功地插入。 +randomSet.insert(1); + +// 返回 false ,表示集合中不存在 2 。 +randomSet.remove(2); + +// 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。 +randomSet.insert(2); + +// getRandom 应随机返回 1 或 2 。 +randomSet.getRandom(); + +// 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。 +randomSet.remove(1); + +// 2 已在集合中,所以返回 false 。 +randomSet.insert(2); + +// 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。 +randomSet.getRandom(); + +``` + +## 思路 + +这是一个设计题。这道题的核心就是考察基本数据结构和算法的操作以及复杂度。 + +我们来回顾一下基础知识: + +- 数组支持随机访问,其按照索引查询的时间复杂度为$O(1)$,按值查询的时间复杂度为$O(N)$, 而插入和删除的时间复杂度为$O(N)$。 +- 链表不支持随机访问,其查询的时间复杂度为$O(N)$,但是对于插入和删除的复杂度为$O(1)$(不考虑找到选要处理的节点花费的时间)。 +- 对于哈希表,正常情况下其查询复杂度平均为$O(N)$,插入和删除的复杂度为$O(1)$。 + +由于题目要求 getRandom 返回要随机并且要在$O(1)$复杂度内,那么如果单纯使用链表或者哈希表肯定是不行的。 + +而又由于对于插入和删除也需要复杂度为$O(1)$,因此单纯使用数组也是不行的,因此考虑多种使用数据结构来实现。 + +> 实际上 LeetCode 设计题,几乎没有单纯一个数据结构搞定的,基本都需要多种数据结构结合,这个时候需要你对各种数据结构以及其基本算法的复杂度有着清晰的认知。 + +对于 getRandom 用数组很简单。对于判断是否已经有了存在的元素,我们使用哈希表也很容易做到。因此我们可以将数组随机访问,以及哈希表$O(1)$按检索值的特性结合起来,即同时使用这两种数据结构。 + +对于删除和插入,我们需要一些技巧。 + +对于插入: + +- 我们直接往 append,并将其插入哈希表即可。 +- 对于删除,我们需要做到 O(1)。删除哈希表很明显可以,但是对于数组,平均时间复杂度为 O(1)。 + +因此如何应付删除的这种性能开销呢? 我们知道对于数据删除,我们的时间复杂度来源于 + +1. `查找到要删除的元素` +2. 以及`重新排列被删除元素后面的元素`。 + +对于 1,我们可以通过哈希表来实现。 key 是插入的数字,value 是数组对应的索引。删除的时候我们根据 key 反查出索引就可以快速找到。 + +> 题目说明了不会存在重复元素,所以我们可以这么做。思考一下,如果没有这个限制会怎么样? + +对于 2,我们可以通过和数组最后一项进行交换的方式来实现,这样就避免了数据移动。同时数组其他项的索引仍然保持不变,非常好! + +> 相应地,我们插入的时候,需要维护哈希表 + +图解: + +以依次【1,2,3,4】之后为初始状态,那么此时状态是这样的: + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfjm9sg9olj30pg11wwiu.jpg) + +而当要插入一个新的5的时候, 我们只需要分别向数组末尾和哈希表中插入这条记录即可。 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfjmanhni6j30ka126tdm.jpg) + +而删除的时候稍微有一点复杂: + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfjmbib4v5j30z60u049j.jpg) + +## 关键点解析 + +- 数组 +- 哈希表 +- 数组 + 哈希表 +- 基本算法时间复杂度分析 + +## 代码 + +```python +from random import random + + +class RandomizedSet: + + def __init__(self): + """ + Initialize your data structure here. + """ + self.data = dict() + self.arr = [] + self.n = 0 + + def insert(self, val: int) -> bool: + """ + Inserts a value to the set. Returns true if the set did not already contain the specified element. + """ + if val in self.data: + return False + self.data[val] = self.n + self.arr.append(val) + self.n += 1 + + return True + + def remove(self, val: int) -> bool: + """ + Removes a value from the set. Returns true if the set contained the specified element. + """ + if val not in self.data: + return False + i = self.data[val] + # 更新data + self.data[self.arr[-1]] = i + self.data.pop(val) + # 更新arr + self.arr[i] = self.arr[-1] + # 删除最后一项 + self.arr.pop() + self.n -= 1 + + return True + + def getRandom(self) -> int: + """ + Get a random element from the set. + """ + + return self.arr[int(random() * self.n)] + + +# Your RandomizedSet object will be instantiated and called as such: +# obj = RandomizedSet() +# param_1 = obj.insert(val) +# param_2 = obj.remove(val) +# param_3 = obj.getRandom() +``` + +***复杂度分析*** +- 时间复杂度:$O(1)$ +- 空间复杂度:$O(1)$ + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。 + +大家也可以关注我的公众号《力扣加加》获取更多更新鲜的LeetCode题解 + +![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg) diff --git a/spider/row-markdown/39.combination-sum.md b/spider/row-markdown/39.combination-sum.md new file mode 100644 index 0000000..be782f4 --- /dev/null +++ b/spider/row-markdown/39.combination-sum.md @@ -0,0 +1,180 @@ +## 题目地址 +https://leetcode.com/problems/combination-sum/description/ + +## 题目描述 +``` +Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target. + +The same repeated number may be chosen from candidates unlimited number of times. + +Note: + +All numbers (including target) will be positive integers. +The solution set must not contain duplicate combinations. +Example 1: + +Input: candidates = [2,3,6,7], target = 7, +A solution set is: +[ + [7], + [2,2,3] +] +Example 2: + +Input: candidates = [2,3,5], target = 8, +A solution set is: +[ + [2,2,2,2], + [2,3,3], + [3,5] +] + +``` + +## 思路 + +这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。 + +这种题目其实有一个通用的解法,就是回溯法。 +网上也有大神给出了这种回溯法解题的 +[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。 +除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。 + +我们先来看下通用解法的解题思路,我画了一张图: + +![backtrack](../assets/problems/backtrack.png) + +通用写法的具体代码见下方代码区。 + +## 关键点解析 + +- 回溯法 +- backtrack 解题公式 + + +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=39 lang=javascript + * + * [39] Combination Sum + * + * https://leetcode.com/problems/combination-sum/description/ + * + * algorithms + * Medium (46.89%) + * Total Accepted: 326.7K + * Total Submissions: 684.2K + * Testcase Example: '[2,3,6,7]\n7' + * + * Given a set of candidate numbers (candidates) (without duplicates) and a + * target number (target), find all unique combinations in candidates where the + * candidate numbers sums to target. + * + * The same repeated number may be chosen from candidates unlimited number of + * times. + * + * Note: + * + * + * All numbers (including target) will be positive integers. + * The solution set must not contain duplicate combinations. + * + * + * Example 1: + * + * + * Input: candidates = [2,3,6,7], target = 7, + * A solution set is: + * [ + * ⁠ [7], + * ⁠ [2,2,3] + * ] + * + * + * Example 2: + * + * + * Input: candidates = [2,3,5], target = 8, + * A solution set is: + * [ + * [2,2,2,2], + * [2,3,3], + * [3,5] + * ] + * + */ + +function backtrack(list, tempList, nums, remain, start) { + if (remain < 0) return; + else if (remain === 0) return list.push([...tempList]); + for (let i = start; i < nums.length; i++) { + tempList.push(nums[i]); + backtrack(list, tempList, nums, remain - nums[i], i); // 数字可以重复使用, i + 1代表不可以重复利用 + tempList.pop(); + } +} +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +var combinationSum = function(candidates, target) { + const list = []; + backtrack(list, [], candidates.sort((a, b) => a - b), target, 0); + return list; +}; +``` +Python3 Code: +```python +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + """ + 回溯法,层层递减,得到符合条件的路径就加入结果集中,超出则剪枝; + 主要是要注意一些细节,避免重复等; + """ + size = len(candidates) + if size <= 0: + return [] + + # 先排序,便于后面剪枝 + candidates.sort() + + path = [] + res = [] + self._find_path(target, path, res, candidates, 0, size) + + return res + + def _find_path(self, target, path, res, candidates, begin, size): + """沿着路径往下走""" + if target == 0: + res.append(path.copy()) + else: + for i in range(begin, size): + left_num = target - candidates[i] + # 如果剩余值为负数,说明超过了,剪枝 + if left_num < 0: + break + # 否则把当前值加入路径 + path.append(candidates[i]) + # 为避免重复解,我们把比当前值小的参数也从下一次寻找中剔除, + # 因为根据他们得出的解一定在之前就找到过了 + self._find_path(left_num, path, res, candidates, i, size) + # 记得把当前值移出路径,才能进入下一个值的路径 + path.pop() +``` + +## 相关题目 + +- [40.combination-sum-ii](./40.combination-sum-ii.md) +- [46.permutations](./46.permutations.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [78.subsets](./78.subsets.md) +- [90.subsets-ii](./90.subsets-ii.md) +- [113.path-sum-ii](./113.path-sum-ii.md) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md) + diff --git a/spider/row-markdown/4.median-of-two-sorted-array.md b/spider/row-markdown/4.median-of-two-sorted-array.md new file mode 100644 index 0000000..2916411 --- /dev/null +++ b/spider/row-markdown/4.median-of-two-sorted-array.md @@ -0,0 +1,270 @@ +## 题目地址(4. 寻找两个正序数组的中位数) +https://leetcode.com/problems/median-of-two-sorted-arrays/ + +## 题目描述 +``` +给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。 + +请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 + +你可以假设 nums1 和 nums2 不会同时为空。 + +  + +示例 1: + +nums1 = [1, 3] +nums2 = [2] + +则中位数是 2.0 +示例 2: + +nums1 = [1, 2] +nums2 = [3, 4] + +则中位数是 (2 + 3)/2 = 2.5 + +``` + +## 思路 +首先了解一下Median的概念,一个数组中median就是把数组分成左右等分的中位数。 + +如下图: +![image.png](https://pic.leetcode-cn.com/100b34b378d0667969e7a4ca537c74e5103ce302731796740b3fa62b8bc55629-image.png) + + +这道题,很容易想到暴力解法,时间复杂度和空间复杂度都是`O(m+n)`, 不符合题中给出`O(log(m+n))`时间复杂度的要求。 +我们可以从简单的解法入手,试了一下,暴力解法也是可以被Leetcode Accept的. 分析中会给出两种解法,暴力求解和二分解法。 + +#### 解法一 - 暴力 (Brute Force) +暴力解主要是要merge两个排序的数组`(A,B)`成一个排序的数组。 + +用两个`pointer(i,j)`,`i` 从数组`A`起始位置开始,即`i=0`开始,`j` 从数组`B`起始位置, 即`j=0`开始. +一一比较 `A[i] 和 B[j]`, +1. 如果`A[i] <= B[j]`, 则把`A[i]` 放入新的数组中,i往后移一位,即 `i+1`. +2. 如果`A[i] > B[j]`, 则把`B[j]` 放入新的数组中,j往后移一位,即 `j+1`. +3. 重复步骤#1 和 #2,直到`i`移到`A`最后,或者`j`移到`B`最后。 +4. 如果`j`移动到`B`数组最后,那么直接把剩下的所有`A`依次放入新的数组中. +5. 如果`i`移动到`A`数组最后,那么直接把剩下的所有`B`依次放入新的数组中. + +Merge的过程如下图。 +![image.png](https://pic.leetcode-cn.com/966c9a0fea7a5f433b82d660f82c5d8184a2ac73b8362d7be435aa0f63377a4c-image.png) + + + +*时间复杂度: `O(m+n) - m is length of A, n is length of B`* + +*空间复杂度: `O(m+n)`* + +#### 解法二 - 二分查找 (Binary Search) +由于题中给出的数组都是排好序的,在排好序的数组中查找很容易想到可以用二分查找(Binary Search), 这里对数组长度小的做二分, +保证数组A 和 数组B 做partition 之后 + +`len(Aleft)+len(Bleft)=(m+n+1)/2 - m是数组A的长度, n是数组B的长度` + +对数组A的做partition的位置是区间`[0,m]` + +如图: +![image.png](https://pic.leetcode-cn.com/816717da264c9e6970bfe0d696d9076febfe04b819f80a224cf2c73845d0f161-image.png) + +下图给出几种不同情况的例子(注意但左边或者右边没有元素的时候,左边用`INF_MIN`,右边用`INF_MAX`表示左右的元素: +![image.png](https://pic.leetcode-cn.com/fe03bdcf4db4d74a0bebaa2907df3038c080e5915932fd581d06d4eb930b3035-image.png) + +下图给出具体做的partition 解题的例子步骤, +![image.png](https://pic.leetcode-cn.com/1c2093328c4edf06e416d0f43a94ed42b5a46ecc9f7ed72004b40b9fb47e12a4-image.png) + + +*时间复杂度: `O(log(min(m, n)) - m is length of A, n is length of B`* + +*空间复杂度: `O(1)` - 这里没有用额外的空间* + +## 关键点分析 +1. 暴力求解,在线性时间内merge两个排好序的数组成一个数组。 +2. 二分查找,关键点在于 + - 要partition两个排好序的数组成左右两等份,partition需要满足`len(Aleft)+len(Bleft)=(m+n+1)/2 - m是数组A的长度, n是数组B的长度` + + - 并且partition后 A左边最大(`maxLeftA`), A右边最小(`minRightA`), B左边最大(`maxLeftB`), B右边最小(`minRightB`) 满足 +`(maxLeftA <= minRightB && maxLeftB <= minRightA)` + +有了这两个条件,那么median就在这四个数中,根据奇数或者是偶数, +``` +奇数: +median = max(maxLeftA, maxLeftB) +偶数: +median = (max(maxLeftA, maxLeftB) + min(minRightA, minRightB)) / 2 +``` + +## 代码 + + +代码支持: Java,JS: + + +Java Code: + +*解法一 - 暴力解法(Brute force)* + +```java [] +class MedianTwoSortedArrayBruteForce { + public double findMedianSortedArrays(int[] nums1, int[] nums2) { + int[] newArr = mergeTwoSortedArray(nums1, nums2); + int n = newArr.length; + if (n % 2 == 0) { + // even + return (double) (newArr[n / 2] + newArr[n / 2 - 1]) / 2; + } else { + // odd + return (double) newArr[n / 2]; + } + } + private int[] mergeTwoSortedArray(int[] nums1, int[] nums2) { + int m = nums1.length; + int n = nums2.length; + int[] res = new int[m + n]; + int i = 0; + int j = 0; + int idx = 0; + while (i < m && j < n) { + if (nums1[i] <= nums2[j]) { + res[idx++] = nums1[i++]; + } else { + res[idx++] = nums2[j++]; + } + } + while (i < m) { + res[idx++] = nums1[i++]; + } + while (j < n) { + res[idx++] = nums2[j++]; + } + return res; + } +} +``` +```javascript [] +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var findMedianSortedArrays = function(nums1, nums2) { + // 归并排序 + const merged = [] + let i = 0 + let j = 0 + while(i < nums1.length && j < nums2.length) { + if (nums1[i] < nums2[j]) { + merged.push(nums1[i++]) + } else { + merged.push(nums2[j++]) + } + } + while(i < nums1.length) { + merged.push(nums1[i++]) + } + while(j < nums2.length) { + merged.push(nums2[j++]) + } + + const { length } = merged + return length % 2 === 1 + ? merged[Math.floor(length / 2)] + : (merged[length / 2] + merged[length / 2 - 1]) / 2 +}; +``` + +***复杂度分析*** +- 时间复杂度:$O(max(m, n))$ +- 空间复杂度:$O(m + n)$ + +*解法二 - 二分查找(Binary Search)* +```js [] +/** + * 二分解法 + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var findMedianSortedArrays = function(nums1, nums2) { + // make sure to do binary search for shorten array + if (nums1.length > nums2.length) { + [nums1, nums2] = [nums2, nums1] + } + const m = nums1.length + const n = nums2.length + let low = 0 + let high = m + while(low <= high) { + const i = low + Math.floor((high - low) / 2) + const j = Math.floor((m + n + 1) / 2) - i + + const maxLeftA = i === 0 ? -Infinity : nums1[i-1] + const minRightA = i === m ? Infinity : nums1[i] + const maxLeftB = j === 0 ? -Infinity : nums2[j-1] + const minRightB = j === n ? Infinity : nums2[j] + + if (maxLeftA <= minRightB && minRightA >= maxLeftB) { + return (m + n) % 2 === 1 + ? Math.max(maxLeftA, maxLeftB) + : (Math.max(maxLeftA, maxLeftB) + Math.min(minRightA, minRightB)) / 2 + } else if (maxLeftA > minRightB) { + high = i - 1 + } else { + low = low + 1 + } + } +}; +``` +```java [] +class MedianSortedTwoArrayBinarySearch { + public static double findMedianSortedArraysBinarySearch(int[] nums1, int[] nums2) { + // do binary search for shorter length array, make sure time complexity log(min(m,n)). + if (nums1.length > nums2.length) { + return findMedianSortedArraysBinarySearch(nums2, nums1); + } + int m = nums1.length; + int n = nums2.length; + int lo = 0; + int hi = m; + while (lo <= hi) { + // partition A position i + int i = lo + (hi - lo) / 2; + // partition B position j + int j = (m + n + 1) / 2 - i; + + int maxLeftA = i == 0 ? Integer.MIN_VALUE : nums1[i - 1]; + int minRightA = i == m ? Integer.MAX_VALUE : nums1[i]; + + int maxLeftB = j == 0 ? Integer.MIN_VALUE : nums2[j - 1]; + int minRightB = j == n ? Integer.MAX_VALUE : nums2[j]; + + if (maxLeftA <= minRightB && maxLeftB <= minRightA) { + // total length is even + if ((m + n) % 2 == 0) { + return (double) (Math.max(maxLeftA, maxLeftB) + Math.min(minRightA, minRightB)) / 2; + } else { + // total length is odd + return (double) Math.max(maxLeftA, maxLeftB); + } + } else if (maxLeftA > minRightB) { + // binary search left half + hi = i - 1; + } else { + // binary search right half + lo = i + 1; + } + } + return 0.0; + } +} +``` +***复杂度分析*** +- 时间复杂度:$O(log(min(m, n)))$ +- 空间复杂度:$O(log(min(m, n)))$ + + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/40.combination-sum-ii.md b/spider/row-markdown/40.combination-sum-ii.md new file mode 100644 index 0000000..9a2d3e1 --- /dev/null +++ b/spider/row-markdown/40.combination-sum-ii.md @@ -0,0 +1,182 @@ +## 题目地址 +https://leetcode.com/problems/combination-sum-ii/description/ + +## 题目描述 +``` +Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target. + +Each number in candidates may only be used once in the combination. + +Note: + +All numbers (including target) will be positive integers. +The solution set must not contain duplicate combinations. +Example 1: + +Input: candidates = [10,1,2,7,6,1,5], target = 8, +A solution set is: +[ + [1, 7], + [1, 2, 5], + [2, 6], + [1, 1, 6] +] +Example 2: + +Input: candidates = [2,5,2,1,2], target = 5, +A solution set is: +[ + [1,2,2], + [5] +] + +``` + +## 思路 + +这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。 + +这种题目其实有一个通用的解法,就是回溯法。 +网上也有大神给出了这种回溯法解题的 +[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。 +除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。 + +我们先来看下通用解法的解题思路,我画了一张图: + +![backtrack](../assets/problems/backtrack.png) + +通用写法的具体代码见下方代码区。 + +## 关键点解析 + +- 回溯法 +- backtrack 解题公式 + + +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=40 lang=javascript + * + * [40] Combination Sum II + * + * https://leetcode.com/problems/combination-sum-ii/description/ + * + * algorithms + * Medium (40.31%) + * Total Accepted: 212.8K + * Total Submissions: 519K + * Testcase Example: '[10,1,2,7,6,1,5]\n8' + * + * Given a collection of candidate numbers (candidates) and a target number + * (target), find all unique combinations in candidates where the candidate + * numbers sums to target. + * + * Each number in candidates may only be used once in the combination. + * + * Note: + * + * + * All numbers (including target) will be positive integers. + * The solution set must not contain duplicate combinations. + * + * + * Example 1: + * + * + * Input: candidates = [10,1,2,7,6,1,5], target = 8, + * A solution set is: + * [ + * ⁠ [1, 7], + * ⁠ [1, 2, 5], + * ⁠ [2, 6], + * ⁠ [1, 1, 6] + * ] + * + * + * Example 2: + * + * + * Input: candidates = [2,5,2,1,2], target = 5, + * A solution set is: + * [ + * [1,2,2], + * [5] + * ] + * + * + */ +function backtrack(list, tempList, nums, remain, start) { + if (remain < 0) return; + else if (remain === 0) return list.push([...tempList]); + for (let i = start; i < nums.length; i++) { + // 和39.combination-sum 的其中一个区别就是这道题candidates可能有重复 + // 代码表示就是下面这一行 + if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates + tempList.push(nums[i]); + backtrack(list, tempList, nums, remain - nums[i], i + 1); // i + 1代表不可以重复利用, i 代表数字可以重复使用 + tempList.pop(); + } + } +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +var combinationSum2 = function(candidates, target) { + const list = []; + backtrack(list, [], candidates.sort((a, b) => a - b), target, 0); + return list; +}; +``` +Python3 Code: +```python +class Solution: + def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]: + """ + 与39题的区别是不能重用元素,而元素可能有重复; + 不能重用好解决,回溯的index往下一个就行; + 元素可能有重复,就让结果的去重麻烦一些; + """ + size = len(candidates) + if size == 0: + return [] + + # 还是先排序,主要是方便去重 + candidates.sort() + + path = [] + res = [] + self._find_path(candidates, path, res, target, 0, size) + + return res + + def _find_path(self, candidates, path, res, target, begin, size): + if target == 0: + res.append(path.copy()) + else: + for i in range(begin, size): + left_num = target - candidates[i] + if left_num < 0: + break + # 如果存在重复的元素,前一个元素已经遍历了后一个元素与之后元素组合的所有可能 + if i > begin and candidates[i] == candidates[i-1]: + continue + path.append(candidates[i]) + # 开始的 index 往后移了一格 + self._find_path(candidates, path, res, left_num, i+1, size) + path.pop() +``` + +## 相关题目 + +- [39.combination-sum](./39.combination-sum.md) +- [46.permutations](./46.permutations.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [78.subsets](./78.subsets.md) +- [90.subsets-ii](./90.subsets-ii.md) +- [113.path-sum-ii](./113.path-sum-ii.md) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md) diff --git a/spider/row-markdown/416.partition-equal-subset-sum.md b/spider/row-markdown/416.partition-equal-subset-sum.md new file mode 100644 index 0000000..5dab5ef --- /dev/null +++ b/spider/row-markdown/416.partition-equal-subset-sum.md @@ -0,0 +1,284 @@ +### 题目地址 + +#### [416. 分割等和子集](https://leetcode-cn.com/problems/partition-equal-subset-sum/) + +### 题目描述 + +> 给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 +> +> 注意: +> +> 每个数组中的元素不会超过 100 +> 数组的大小不会超过 200 +> +> 示例 1: +> +> 输入: [1, 5, 11, 5] +> +> 输出: true +> +> 解释: 数组可以分割成 [1, 5, 5] 和 [11]. +> +> 示例 2: +> +> 输入: [1, 2, 3, 5] +> +> 输出: false +> +> 解释: 数组不能分割成两个元素和相等的子集. + +### 思路 + +抽象能力不管是在工程还是算法中都占据着绝对重要的位置。比如上题我们可以抽象为: + +**给定一个非空数组,和是 sum,能否找到这样的一个子序列,使其和为 2/sum** + +我们做过二数和,三数和, 四数和,看到这种类似的题会不会舒适一点,思路更开阔一点。 + +老司机们看到转化后的题,会立马想到背包问题,这里会提供**深度优先搜索**和**背包**两种解法。 + +### 深度优先遍历 + +我们再来看下题目描述,sum 有两种情况, + +1. 如果 sum % 2 === 1, 则肯定无解,因为 sum/2 为小数,而数组全由整数构成,子数组和不可能为小数。 +2. 如果 sum % 2 === 0, 需要找到和为 2/sum 的子序列 + 针对 2,我们要在 nums 里找到满足条件的子序列 subNums。 这个过程可以类比为在一个大篮子里面有 N 个球,每个球代表不同的数字,我们用一小篮子去抓取球,使得拿到的球数字和为 2/sum。那么很自然的一个想法就是,对大篮子里面的每一个球,我们考虑取它或者不取它,如果我们足够耐心,最后肯定能穷举所有的情况,判断是否有解。上述思维表述为伪代码如下: + +``` +令 target = sum / 2, nums 为输入数组, cur 为当前当前要选择的数字的索引 +nums 为输入数组,target为当前求和目标,cur为当前判断的数 +function dfs(nums, target, cur) + 如果target < 0 或者 cur > nums.length + return false + 否则 + 如果 target = 0, 说明找到答案了,返回true + 否则 + 取当前数或者不取,进入递归 dfs(nums, target - nums[cur], cur + 1) || dfs(nums, target, cur + 1) +``` + +因为对每个数都考虑取不取,所以这里时间复杂度是 O(2 ^ n), 其中 n 是 nums 数组长度, + +#### javascript 实现 + +```javascript +var canPartition = function (nums) { + let sum = nums.reduce((acc, num) => acc + num, 0); + if (sum % 2) { + return false; + } + sum = sum / 2; + return dfs(nums, sum, 0); +}; + +function dfs(nums, target, cur) { + if (target < 0 || cur > nums.length) { + return false; + } + return ( + target === 0 || + dfs(nums, target - nums[cur], cur + 1) || + dfs(nums, target, cur + 1) + ); +} +``` + +不出所料,这里是超时了,我们看看有没优化空间 + +1. 如果 nums 中最大值 > 2/sum, 那么肯定无解 +2. 在搜索过程中,我们对每个数都是取或者不取,并且数组中所有项都为正数。我们设取的数和为 `pickedSum`,不难得 pickedSum <= 2/sum, 同时要求丢弃的数为 `discardSum`,不难得 pickedSum <= 2 / sum。 + +我们同时引入这两个约束条件加强剪枝: + +优化后的代码如下 + +```javascript +var canPartition = function (nums) { + let sum = nums.reduce((acc, num) => acc + num, 0); + if (sum % 2) { + return false; + } + sum = sum / 2; + nums = nums.sort((a, b) => b - a); + if (sum < nums[0]) { + return false; + } + return dfs(nums, sum, sum, 0); +}; + +function dfs(nums, pickRemain, discardRemain, cur) { + if (pickRemain === 0 || discardRemain === 0) { + return true; + } + + if (pickRemain < 0 || discardRemain < 0 || cur > nums.length) { + return false; + } + + return ( + dfs(nums, pickRemain - nums[cur], discardRemain, cur + 1) || + dfs(nums, pickRemain, discardRemain - nums[cur], cur + 1) + ); +} +``` + +leetcode 是 AC 了,但是时间复杂度 O(2 ^ n), 算法时间复杂度很差,我们看看有没更好的。 + +### DP 解法 + +在用 DFS 是时候,我们是不关心取数的规律的,只要保证接下来要取的数在之前没有被取过即可。那如果我们有规律去安排取数策略的时候会怎么样呢,比如第一次取数安排在第一位,第二位取数安排在第二位,在判断第 i 位是取数的时候,我们是已经知道前 i-1 个数每次是否取的所有子序列组合,记集合 S 为这个子序列的和。再看第 i 位取数的情况, 有两种情况取或者不取 + +1. 取的情况,如果 target-nums[i]在集合 S 内,则返回 true,说明前 i 个数能找到和为 target 的序列 +2. 不取的情况,如果 target 在集合 S 内,则返回 true,否则返回 false + +也就是说,前 i 个数能否构成和为 target 的子序列取决为前 i-1 数的情况。 + +记 F[i, target] 为 nums 数组内前 i 个数能否构成和为 target 的子序列的可能,则状态转移方程为 + +`F[i, target] = F[i - 1, target] || F[i - 1, target - nums[i]]` + +状态转移方程出来了,代码就很好写了,DFS + DP 都可以解,有不清晰的可以参考下 [递归和动态规划](../thinkings/dynamic-programming.md), +这里只提供 DP 解法 + +#### 伪代码表示 + +``` +n = nums.length +target 为 nums 各数之和 +如果target不能被2整除, + 返回false + +令dp为n * target 的二维矩阵, 并初始为false +遍历0:n, dp[i][0] = true 表示前i个数组成和为0的可能 + +遍历 0 到 n + 遍历 0 到 target + if 当前值j大于nums[i] + dp[i + 1][j] = dp[i][j-nums[i]] || dp[i][j] + else + dp[i+1][j] = dp[i][j] +``` + +算法时间复杂度 O(n\*m), 空间复杂度 O(n\*m), m 为 sum(nums) / 2 + +#### javascript 实现 + +```js +var canPartition = function (nums) { + let sum = nums.reduce((acc, num) => acc + num, 0); + if (sum % 2) { + return false; + } else { + sum = sum / 2; + } + + const dp = Array.from(nums).map(() => + Array.from({ length: sum + 1 }).fill(false) + ); + + for (let i = 0; i < nums.length; i++) { + dp[i][0] = true; + } + + for (let i = 0; i < dp.length - 1; i++) { + for (let j = 0; j < dp[0].length; j++) { + dp[i + 1][j] = + j - nums[i] >= 0 ? dp[i][j] || dp[i][j - nums[i]] : dp[i][j]; + } + } + + return dp[nums.length - 1][sum]; +}; +``` + +再看看有没有优化空间,看状态转移方程 +`F[i, target] = F[i - 1, target] || F[i - 1, target - nums[i]]` +第 n 行的状态只依赖于第 n-1 行的状态,也就是说我们可以把二维空间压缩成一维 + +伪代码 + +``` +遍历 0 到 n + 遍历 j 从 target 到 0 + if 当前值j大于nums[i] + dp[j] = dp[j-nums[i]] || dp[j] + else + dp[j] = dp[j] +``` + +时间复杂度 O(n\*m), 空间复杂度 O(n) +javascript 实现 + +```js +var canPartition = function (nums) { + let sum = nums.reduce((acc, num) => acc + num, 0); + if (sum % 2) { + return false; + } + sum = sum / 2; + const dp = Array.from({ length: sum + 1 }).fill(false); + dp[0] = true; + + for (let i = 0; i < nums.length; i++) { + for (let j = sum; j > 0; j--) { + dp[j] = dp[j] || (j - nums[i] >= 0 && dp[j - nums[i]]); + } + } + + return dp[sum]; +}; +``` + +其实这道题和 [leetcode 518](https://leetcode-cn.com/problems/coin-change-2/) 是换皮题,它们都可以归属于背包问题 + +## 背包问题 + +### 背包问题描述 + +有 N 件物品和一个容量为 V 的背包。放入第 i 件物品耗费的费用是 Ci,得到的 +价值是 Wi。求解将哪些物品装入背包可使价值总和最大。 + +背包问题的特性是,每种物品,我们都可以选择放或者不放。令 F[i, v]表示前 i 件物品放入到容量为 v 的背包的状态。 + +针对上述背包,F[i, v]表示能得到最大价值,那么状态转移方程为 + +``` +F[i, v] = max{F[i-1, v], F[i-1, v-Ci] + Wi} +``` + +针对 416. 分割等和子集这题,F[i, v]的状态含义就表示前 i 个数能组成和为 v 的可能,状态转移方程为 + +``` +F[i, v] = F[i-1, v] || F[i-1, v-Ci] +``` + +再回过头来看下[leetcode 518](https://leetcode-cn.com/problems/coin-change-2/), 原题如下 + +> 给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 + +带入背包思想,F[i,v] 表示用前 i 种硬币能兑换金额数为 v 的组合数,状态转移方程为 +`F[i, v] = F[i-1, v] + F[i-1, v-Ci]` + +#### javascript 实现 + +```javascript +/** + * @param {number} amount + * @param {number[]} coins + * @return {number} + */ +var change = function (amount, coins) { + const dp = Array.from({ length: amount + 1 }).fill(0); + dp[0] = 1; + for (let i = 0; i < coins.length; i++) { + for (let j = 1; j <= amount; j++) { + dp[j] = dp[j] + (j - coins[i] >= 0 ? dp[j - coins[i]] : 0); + } + } + return dp[amount]; +}; +``` + +### 参考 + +[背包九讲](https://raw.githubusercontent.com/tianyicui/pack/master/V2.pdf) diff --git a/spider/row-markdown/42.trapping-rain-water.md b/spider/row-markdown/42.trapping-rain-water.md new file mode 100644 index 0000000..baaedce --- /dev/null +++ b/spider/row-markdown/42.trapping-rain-water.md @@ -0,0 +1,111 @@ +## 题目地址 +https://leetcode.com/problems/trapping-rain-water/description/ + +## 题目描述 + + +``` +Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. + + +The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image! + + +``` + +![42.trapping-rain-water-1](../assets/problems/42.trapping-rain-water-1.png) + +``` +Example: + +Input: [0,1,0,2,1,0,1,3,2,1,2,1] +Output: 6 + +``` + +## 思路 + +这是一道雨水收集的问题, 难度为`hard`. 如图所示,让我们求下过雨之后最多可以积攒多少的水。 + +如果采用暴力求解的话,思路应该是height数组依次求和,然后相加。 + +伪代码: + +```js + +for(let i = 0; i < height.length; i++) { + area += (h[i] - height[i]) * 1; // h为下雨之后的水位 +} + +``` +问题转化为求h,那么h[i]又等于`左右两侧柱子的最大值中的较小值`,即 +`h[i] = Math.min(左边柱子最大值, 右边柱子最大值)` + +如上图那么h为 [0, 1, 1, 2, 2, 2 ,2, 3, 2, 2, 2, 1] + +问题的关键在于求解`左边柱子最大值`和`右边柱子最大值`, +我们其实可以用两个数组来表示`leftMax`, `rightMax`, +以leftMax为例,leftMax[i]代表i的左侧柱子的最大值,因此我们维护两个数组即可。 +## 关键点解析 + +- 建模 `h[i] = Math.min(左边柱子最大值, 右边柱子最大值)`(h为下雨之后的水位) + +## 代码 + +代码支持 JavaScript,Python3: + +JavaScript Code: + +```js + +/* + * @lc app=leetcode id=42 lang=javascript + * + * [42] Trapping Rain Water + * + */ +/** + * @param {number[]} height + * @return {number} + */ +var trap = function(height) { + let max = 0; + let volumn = 0; + const leftMax = []; + const rightMax = []; + + for(let i = 0; i < height.length; i++) { + leftMax[i] = max = Math.max(height[i], max); + } + + max = 0; + + for(let i = height.length - 1; i >= 0; i--) { + rightMax[i] = max = Math.max(height[i], max); + } + + for(let i = 0; i < height.length; i++) { + volumn = volumn + Math.min(leftMax[i], rightMax[i]) - height[i] + } + + return volumn; +}; + +``` + +Python Code: + +```python +class Solution: + def trap(self, heights: List[int]) -> int: + n = len(heights) + l, r = [0] * (n + 1), [0] * (n + 1) + ans = 0 + for i in range(1, len(heights) + 1): + l[i] = max(l[i - 1], heights[i - 1]) + for i in range(len(heights) - 1, 0, -1): + r[i] = max(r[i + 1], heights[i]) + for i in range(len(heights)): + ans += max(0, min(l[i + 1], r[i]) - heights[i]) + return ans +``` diff --git a/spider/row-markdown/437.path-sum-iii.md b/spider/row-markdown/437.path-sum-iii.md new file mode 100644 index 0000000..869ccf0 --- /dev/null +++ b/spider/row-markdown/437.path-sum-iii.md @@ -0,0 +1,159 @@ +## 题目地址 + +https://leetcode.com/problems/path-sum-iii/description/ + +## 题目描述 + +``` +You are given a binary tree in which each node contains an integer value. + +Find the number of paths that sum to a given value. + +The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). + +The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000. + +Example: + +root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 + + 10 + / \ + 5 -3 + / \ \ + 3 2 11 + / \ \ +3 -2 1 + +Return 3. The paths that sum to 8 are: + +1. 5 -> 3 +2. 5 -> 2 -> 1 +3. -3 -> 11 +``` + +## 思路 +这道题目是要我们求解出任何一个节点出发到子孙节点的路径中和为指定值。 +注意这里,不一定是从根节点出发,也不一定在叶子节点结束。 + +一种简单的思路就是直接递归解决,空间复杂度O(n) 时间复杂度介于O(nlogn) 和 O(n^2), +具体代码: + +```js +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +// the number of the paths starting from self +function helper(root, sum) { + if (root === null) return 0; + const l = helper(root.left, sum - root.val); + const r = helper(root.right, sum - root.val); + + return l + r + (root.val === sum ? 1 : 0); +} +/** + * @param {TreeNode} root + * @param {number} sum + * @return {number} + */ +var pathSum = function(root, sum) { +// 空间复杂度O(n) 时间复杂度介于O(nlogn) 和 O(n^2) + // tag: dfs tree + if (root === null) return 0; + // the number of the paths starting from self + const self = helper(root, sum); + // we don't know the answer, so we just pass it down + const l = pathSum(root.left, sum); + // we don't know the answer, so we just pass it down + const r = pathSum(root.right, sum); + + return self + l + r; +}; + +``` + + +但是还有一种空间复杂度更加优秀的算法,利用hashmap来避免重复计算,时间复杂度和空间复杂度都是O(n)。 +这种思路是`subarray-sum-equals-k`的升级版本,如果那道题目你可以O(n)解决,这道题目难度就不会很大, +只是将数组换成了二叉树。关于具体的思路可以看[这道题目](./560.subarray-sum-equals-k.md) + + +这里有一个不一样的地方,这里我说明一下,就是为什么要有`hashmap[acc] = hashmap[acc] - 1;`, +原因很简单,就是我们DFS的时候,从底部往上回溯的时候,map的值应该也回溯。如果你对回溯法比较熟悉的话, +应该很容易理解,如果不熟悉可以参考[这道题目](./46.permutations.md), 这道题目就是通过`tempList.pop()`来完成的。 + +另外我画了一个图,相信看完你就明白了。 + +当我们执行到底部的时候: + +![437.path-sum-iii](../assets/problems/437.path-sum-iii-1.jpg) + +接着往上回溯: + +![437.path-sum-iii-2](../assets/problems/437.path-sum-iii-2.jpg) + +很容易看出,我们的hashmap不应该有第一张图的那个记录了,因此需要减去。 + + +具体实现见下方代码区。 + +## 关键点解析 + +- 通过hashmap,以时间换空间 +- 对于这种连续的元素求和问题,有一个共同的思路,可以参考[这道题目](./560.subarray-sum-equals-k.md) + +## 代码 + +* 语言支持:JS + +```js + + +/* + * @lc app=leetcode id=437 lang=javascript + * + * [437] Path Sum III + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +function helper(root, acc, target, hashmap) { + // see also : https://leetcode.com/problems/subarray-sum-equals-k/ + + if (root === null) return 0; + let count = 0; + acc += root.val; + if (acc === target) count++; + if (hashmap[acc - target] !== void 0) { + count += hashmap[acc - target]; + } + if (hashmap[acc] === void 0) { + hashmap[acc] = 1; + } else { + hashmap[acc] += 1; + } + const res = + count + + helper(root.left, acc, target, hashmap) + + helper(root.right, acc, target, hashmap); + + // 这里要注意别忘记了 + hashmap[acc] = hashmap[acc] - 1; + + return res; +} + +var pathSum = function(root, sum) { + // 时间复杂度和空间复杂度都是O(n) + const hashmap = {}; + return helper(root, 0, sum, hashmap); +}; +``` diff --git a/spider/row-markdown/445.add-two-numbers-ii.md b/spider/row-markdown/445.add-two-numbers-ii.md new file mode 100644 index 0000000..3f8e2e7 --- /dev/null +++ b/spider/row-markdown/445.add-two-numbers-ii.md @@ -0,0 +1,259 @@ +## 题目地址 + +https://leetcode.com/problems/add-two-numbers-ii/description/ + +## 题目描述 + +``` +You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. + +You may assume the two numbers do not contain any leading zero, except the number 0 itself. + +Follow up: +What if you cannot modify the input lists? In other words, reversing the lists is not allowed. + +Example: + +Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) +Output: 7 -> 8 -> 0 -> 7 + +``` + +## 思路 + +由于需要从低位开始加,然后进位。 因此可以采用栈来简化操作。 +依次将两个链表的值分别入栈 stack1 和 stack2,然后相加入栈 stack,进位操作用一个变量 carried 记录即可。 + +最后根据 stack 生成最终的链表即可。 + +> 也可以先将两个链表逆置,然后相加,最后将结果再次逆置。 + +## 关键点解析 + +- 栈的基本操作 +- carried 变量记录进位 +- 循环的终止条件设置成`stack.length > 0` 可以简化操作 +- 注意特殊情况, 比如 1 + 99 = 100 + +## 代码 + +- 语言支持:JS,C++, Python3 + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=445 lang=javascript + * + * [445] Add Two Numbers II + */ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ +var addTwoNumbers = function(l1, l2) { + const stack1 = []; + const stack2 = []; + const stack = []; + + let cur1 = l1; + let cur2 = l2; + let curried = 0; + + while (cur1) { + stack1.push(cur1.val); + cur1 = cur1.next; + } + + while (cur2) { + stack2.push(cur2.val); + cur2 = cur2.next; + } + + let a = null; + let b = null; + + while (stack1.length > 0 || stack2.length > 0) { + a = Number(stack1.pop()) || 0; + b = Number(stack2.pop()) || 0; + + stack.push((a + b + curried) % 10); + + if (a + b + curried >= 10) { + curried = 1; + } else { + curried = 0; + } + } + + if (curried === 1) { + stack.push(1); + } + + const dummy = {}; + + let current = dummy; + + while (stack.length > 0) { + current.next = { + val: stack.pop(), + next: null + }; + + current = current.next; + } + + return dummy.next; +}; +``` + +C++ Code: + +```C++ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + auto carry = 0; + auto ret = (ListNode*)nullptr; + auto s1 = vector(); + toStack(l1, s1); + auto s2 = vector(); + toStack(l2, s2); + while (!s1.empty() || !s2.empty() || carry != 0) { + auto v1 = 0; + auto v2 = 0; + if (!s1.empty()) { + v1 = s1.back(); + s1.pop_back(); + } + if (!s2.empty()) { + v2 = s2.back(); + s2.pop_back(); + } + auto v = v1 + v2 + carry; + carry = v / 10; + auto tmp = new ListNode(v % 10); + tmp->next = ret; + ret = tmp; + } + return ret; + } +private: + // 此处若返回而非传入vector,跑完所有测试用例多花8ms + void toStack(const ListNode* l, vector& ret) { + while (l != nullptr) { + ret.push_back(l->val); + l = l->next; + } + } +}; + +// 逆置,相加,再逆置。跑完所有测试用例比第一种解法少花4ms +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + auto rl1 = reverseList(l1); + auto rl2 = reverseList(l2); + auto ret = add(rl1, rl2); + return reverseList(ret); + } +private: + ListNode* reverseList(ListNode* head) { + ListNode* prev = NULL; + ListNode* cur = head; + ListNode* next = NULL; + while (cur != NULL) { + next = cur->next; + cur->next = prev; + prev = cur; + cur = next; + } + return prev; + } + + ListNode* add(ListNode* l1, ListNode* l2) { + ListNode* ret = nullptr; + ListNode* cur = nullptr; + int carry = 0; + while (l1 != nullptr || l2 != nullptr || carry != 0) { + carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val); + auto temp = new ListNode(carry % 10); + carry /= 10; + if (ret == nullptr) { + ret = temp; + cur = ret; + } + else { + cur->next = temp; + cur = cur->next; + } + l1 = l1 == nullptr ? nullptr : l1->next; + l2 = l2 == nullptr ? nullptr : l2->next; + } + return ret; + } +}; +``` + +Python Code: + +```python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: + def listToStack(l: ListNode) -> list: + stack, c = [], l + while c: + stack.append(c.val) + c = c.next + return stack + + # transfer l1 and l2 into stacks + stack1, stack2 = listToStack(l1), listToStack(l2) + + # add stack1 and stack2 + diff = abs(len(stack1) - len(stack2)) + stack1 = ([0]*diff + stack1 if len(stack1) < len(stack2) else stack1) + stack2 = ([0]*diff + stack2 if len(stack2) < len(stack1) else stack2) + stack3 = [x + y for x, y in zip(stack1, stack2)] + + # calculate carry for each item in stack3 and add one to the item before it + carry = 0 + for i, val in enumerate(stack3[::-1]): + index = len(stack3) - i - 1 + carry, stack3[index] = divmod(val + carry, 10) + if carry and index == 0: + stack3 = [1] + stack3 + elif carry: + stack3[index - 1] += 1 + + # transfer stack3 to a linkedList + result = ListNode(0) + c = result + for item in stack3: + c.next = ListNode(item) + c = c.next + + return result.next +``` diff --git a/spider/row-markdown/454.4-sum-ii.md b/spider/row-markdown/454.4-sum-ii.md new file mode 100644 index 0000000..6cadc5a --- /dev/null +++ b/spider/row-markdown/454.4-sum-ii.md @@ -0,0 +1,103 @@ + + +## 题目地址 +https://leetcode.com/problems/4sum-ii/description/ + +## 题目描述 + +``` +Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero. + +To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1. + +Example: + +Input: +A = [ 1, 2] +B = [-2,-1] +C = [-1, 2] +D = [ 0, 2] + +Output: +2 + +Explanation: +The two tuples are: +1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0 +2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0 +``` +## 思路 + +如果按照常规思路去完成查找需要四层遍历,时间复杂是O(n^4), 显然是行不通的。 +因此我们有必要想一种更加高效的算法。 + +我一个思路就是我们将四个数组分成两组,两两结合。 +然后我们分别计算`两两结合能够算出的和有哪些,以及其对应的个数`。 + +如图: + +![454.4-sum-ii](../assets/problems/454.4-sum-ii.png) + + +这个时候我们得到了两个`hashTable`, 我们只需要进行简单的数学运算就可以得到结果。 + +## 关键点解析 + +- 空间换时间 +- 两两分组,求出两两结合能够得出的可能数,然后合并即可。 + +## 代码 + +语言支持: `JavaScript`,`Python3` + +`JavaScript`: +```js + +/* + * @lc app=leetcode id=454 lang=javascript + * + * [454] 4Sum II + * + * https://leetcode.com/problems/4sum-ii/description/ +/** + * @param {number[]} A + * @param {number[]} B + * @param {number[]} C + * @param {number[]} D + * @return {number} + */ +var fourSumCount = function(A, B, C, D) { + const sumMapper = {}; + let res = 0; + for (let i = 0; i < A.length; i++) { + for (let j = 0; j < B.length; j++) { + sumMapper[A[i] + B[j]] = (sumMapper[A[i] + B[j]] || 0) + 1; + } + } + + for (let i = 0; i < C.length; i++) { + for (let j = 0; j < D.length; j++) { + res += sumMapper[- (C[i] + D[j])] || 0; + } + } + + return res; +}; +``` + +`Python3`: + +```python +class Solution: + def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int: + mapper = {} + res = 0 + for i in A: + for j in B: + mapper[i + j] = mapper.get(i + j, 0) + 1 + + for i in C: + for j in D: + res += mapper.get(-1 * (i + j), 0) + return res + ``` diff --git a/spider/row-markdown/455.AssignCookies.md b/spider/row-markdown/455.AssignCookies.md new file mode 100644 index 0000000..a0e38ca --- /dev/null +++ b/spider/row-markdown/455.AssignCookies.md @@ -0,0 +1,82 @@ +## 题目地址 +https://leetcode-cn.com/problems/assign-cookies + +## 题目描述 +``` +假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 + +注意: + +你可以假设胃口值为正。 +一个小朋友最多只能拥有一块饼干。 + +示例 1: + +输入: [1,2,3], [1,1] + +输出: 1 + +解释: + +你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 +虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 +所以你应该输出1。 + +示例 2: + +输入: [1,2], [1,2,3] + +输出: 2 + +解释: + +你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 +你拥有的饼干数量和尺寸都足以让所有孩子满足。 +所以你应该输出2. +``` + +## 思路 +贪心算法+双指针求解 + +给一个孩子的饼干应当尽量小并且能满足孩子,大的留来满足胃口大的孩子。因为胃口小的孩子最容易得到满足,所以优先满足胃口小的孩子需求。按照从小到大的顺序使用饼干尝试是否可满足某个孩子。 + + +## 关键点 + +将需求因子 g 和 s 分别从小到大进行排序,使用贪心思想,配合双指针,每个饼干只尝试一次,成功则换下一个孩子来尝试。 + + +## 代码 +* 语言支持:JS + +```js +/** + * @param {number[]} g + * @param {number[]} s + * @return {number} + */ +const findContentChildren = function (g, s) { + g = g.sort((a, b) => a - b); + s = s.sort((a, b) => a - b); + let gi = 0; // 胃口值 + let sj = 0; // 饼干尺寸 + let res = 0; + while (gi < g.length && sj < s.length) { + // 当饼干 sj >= 胃口 gi 时,饼干满足胃口,更新满足的孩子数并移动指针 + if (s[sj] >= g[gi]) { + gi++; + sj++; + res++; + } else { + // 当饼干 sj < 胃口 gi 时,饼干不能满足胃口,需要换大的 + sj++; + } + } + return res; +}; +``` + +***复杂度分析*** + +- 时间复杂度:O(NlogN) +- 空间复杂度:O(1) diff --git a/spider/row-markdown/46.permutations.md b/spider/row-markdown/46.permutations.md new file mode 100644 index 0000000..db55f9c --- /dev/null +++ b/spider/row-markdown/46.permutations.md @@ -0,0 +1,177 @@ +## 题目地址 +https://leetcode.com/problems/permutations/description/ + +## 题目描述 +``` +Given a collection of distinct integers, return all possible permutations. + +Example: + +Input: [1,2,3] +Output: +[ + [1,2,3], + [1,3,2], + [2,1,3], + [2,3,1], + [3,1,2], + [3,2,1] +] + +``` + +## 思路 + +这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。 + +这种题目其实有一个通用的解法,就是回溯法。 +网上也有大神给出了这种回溯法解题的 +[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。 +除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。 + +我们先来看下通用解法的解题思路,我画了一张图: + +![backtrack](../assets/problems/backtrack.png) + +通用写法的具体代码见下方代码区。 + +## 关键点解析 + +- 回溯法 +- backtrack 解题公式 + +## 代码 + +* 语言支持: Javascript, Python3 + +Javascript Code: + +```js +/* + * @lc app=leetcode id=46 lang=javascript + * + * [46] Permutations + * + * https://leetcode.com/problems/permutations/description/ + * + * algorithms + * Medium (53.60%) + * Total Accepted: 344.6K + * Total Submissions: 642.9K + * Testcase Example: '[1,2,3]' + * + * Given a collection of distinct integers, return all possible permutations. + * + * Example: + * + * + * Input: [1,2,3] + * Output: + * [ + * ⁠ [1,2,3], + * ⁠ [1,3,2], + * ⁠ [2,1,3], + * ⁠ [2,3,1], + * ⁠ [3,1,2], + * ⁠ [3,2,1] + * ] + * + * + */ +function backtrack(list, tempList, nums) { + if (tempList.length === nums.length) return list.push([...tempList]); + for(let i = 0; i < nums.length; i++) { + if (tempList.includes(nums[i])) continue; + tempList.push(nums[i]); + backtrack(list, tempList, nums); + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var permute = function(nums) { + const list = []; + backtrack(list, [], nums) + return list +}; +``` +Python3 Code: +```Python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + """itertools库内置了这个函数""" + return itertools.permutations(nums) + + def permute2(self, nums: List[int]) -> List[List[int]]: + """自己写回溯法""" + res = [] + def _backtrace(nums, pre_list): + if len(nums) <= 0: + res.append(pre_list) + else: + for i in nums: + # 注意copy一份新的调用,否则无法正常循环 + p_list = pre_list.copy() + p_list.append(i) + left_nums = nums.copy() + left_nums.remove(i) + _backtrace(left_nums, p_list) + _backtrace(nums, []) + return res +``` + +Python Code: + +```Python +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + """itertools库内置了这个函数""" + import itertools + return itertools.permutations(nums) + + def permute2(self, nums: List[int]) -> List[List[int]]: + """自己写回溯法""" + res = [] + def _backtrace(nums, pre_list): + if len(nums) <= 0: + res.append(pre_list) + else: + for i in nums: + # 注意copy一份新的调用,否则无法正常循环 + p_list = pre_list.copy() + p_list.append(i) + left_nums = nums.copy() + left_nums.remove(i) + _backtrace(left_nums, p_list) + _backtrace(nums, []) + return res + + def permute3(self, nums: List[int]) -> List[List[int]]: + """回溯的另一种写法""" + res = [] + length = len(nums) + def _backtrack(start=0): + if start == length: + # nums[:] 返回 nums 的一个副本,指向新的引用,这样后续的操作不会影响已经已知解 + res.append(nums[:]) + for i in range(start, length): + nums[start], nums[i] = nums[i], nums[start] + _backtrack(start+1) + nums[start], nums[i] = nums[i], nums[start] + _backtrack() + return res +``` + +## 相关题目 + +- [31.next-permutation](./31.next-permutation.md) +- [39.combination-sum](./39.combination-sum.md) +- [40.combination-sum-ii](./40.combination-sum-ii.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [60.permutation-sequence](./60.permutation-sequence.md) +- [78.subsets](./78.subsets.md) +- [90.subsets-ii](./90.subsets-ii.md) +- [113.path-sum-ii](./113.path-sum-ii.md) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md) diff --git a/spider/row-markdown/460.lfu-cache.md b/spider/row-markdown/460.lfu-cache.md new file mode 100644 index 0000000..d9e9f30 --- /dev/null +++ b/spider/row-markdown/460.lfu-cache.md @@ -0,0 +1,242 @@ +## 题目地址 +https://leetcode.com/problems/lfu-cache/ + +## 题目描述 + +``` +Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get and put. + +get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. +put(key, value) - Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted. + +Follow up: +Could you do both operations in O(1) time complexity? + +Example: + +LFUCache cache = new LFUCache( 2 /* capacity */ ); + +cache.put(1, 1); +cache.put(2, 2); +cache.get(1); // returns 1 +cache.put(3, 3); // evicts key 2 +cache.get(2); // returns -1 (not found) +cache.get(3); // returns 3. +cache.put(4, 4); // evicts key 1. +cache.get(1); // returns -1 (not found) +cache.get(3); // returns 3 +cache.get(4); // returns 4 +``` + +## 思路 + +`本题已被收录到我的新书中,敬请期待~` + +[LFU(Least frequently used)](https://www.wikiwand.com/en/Least_frequently_used) 但内存容量满的情况下,有新的数据进来,需要更多空间的时候,就需要删除被访问频率最少的元素。 + +举个例子,比如说 cache 容量是 3,按顺序依次放入 `1,2,1,2,1,3`, cache 已存满 3 个元素 (1,2,3), 这时如果想放入一个新的元素 4 的时候,就需要腾出一个元素空间。 +用 LFU,这里就淘汰 3, 因为 3 的次数只出现依次, 1 和 2 出现的次数都比 3 多。 + +题中 `get` 和 `put` 都是 `O(1)`的时间复杂度,那么删除和增加都是`O(1)`,可以想到用双链表,和`HashMap`,用一个`HashMap, nodeMap,` 保存当前`key`,和 `node{key, value, frequent} `的映射。 +这样`get(key)`的操作就是`O(1)`. 如果要删除一个元素,那么就需要另一个`HashMap,freqMap,`保存元素出现次数`(frequent)`和双链表`(DoublyLinkedlist)` 映射, +这里双链表存的是 frequent 相同的元素。每次`get`或`put`的时候,`frequent+1`,然后把`node`插入到双链表的`head node, head.next=node` +每次删除`freqent`最小的双链表的`tail node, tail.prev`。 + +用给的例子举例说明: + ``` + 1. put(1, 1), + - 首先查找 nodeMap 中有没有 key=1 对应的 value, + 没有就新建 node(key, value, freq) -> node1(1, 1, 1), 插入 nodeMap,{[1, node1]} + - 查找 freqMap 中有没有 freq=1 对应的 value, + 没有就新建 doublylinkedlist(head, tail), 把 node1 插入 doublylinkedlist head->next = node1. + 如下图, + ``` +![460.lfu-cache-1](../assets/problems/460.lfu-cache-1.jpg) + ``` + 2. put(2, 2), + - 首先查找 nodeMap 中有没有 key=2 对应的 value, + 没有就新建 node(key, value, freq) -> node2(2, 2, 1), 插入 nodeMap,{[1, node1], [2, node2]} + - 查找 freqMap 中有没有 freq=1 对应的 value, + 没有就新建 doublylinkedlist(head, tail), 把 node2 插入 doublylinkedlist head->next = node2. + 如下图, + ``` +![460.lfu-cache-2](../assets/problems/460.lfu-cache-2.jpg) + ``` + 3. get(1), + - 首先查找 nodeMap 中有没有 key=1 对应的 value,nodeMap:{[1, node1], [2, node2]}, + 找到 node1,把 node1 freq+1 -> node1(1,1,2) + - 更新 freqMap,删除 freq=1,node1 + - 更新 freqMap,插入 freq=2,node1 + 如下图, + ``` +![460.lfu-cache-3](../assets/problems/460.lfu-cache-3.jpg) + ``` + 4. put(3, 3), + - 判断 cache 的 capacity,已满,需要淘汰使用次数最少的元素,找到最小的 freq=1,删除双链表 tail node.prev + 如果 tailnode.prev != null, 删除。然后从 nodeMap 中删除对应的 key。 + - 首先查找 nodeMap 中有没有 key=3 对应的 value, + 没有就新建 node(key, value, freq) -> node3(3, 3, 1), 插入 nodeMap,{[1, node1], [3, node3]} + - 查找 freqMap 中有没有 freq=1 对应的 value, + 没有就新建 doublylinkedlist(head, tail), 把 node3 插入 doublylinkedlist head->next = node3. + 如下图, + ``` +![460.lfu-cache-4](../assets/problems/460.lfu-cache-4.jpg) + ``` + 5. get(2) + - 查找 nodeMap,如果没有对应的 key 的 value,返回 -1。 + + 6. get(3) + - 首先查找 nodeMap 中有没有 key=3 对应的 value,nodeMap:{[1, node1], [3, node3]}, + 找到 node3,把 node3 freq+1 -> node3(3,3,2) + - 更新 freqMap,删除 freq=1,node3 + - 更新 freqMap,插入 freq=2,node3 + 如下图, + ``` +![460.lfu-cache-5](../assets/problems/460.lfu-cache-5.jpg) + ``` + 7. put(4, 4), + - 判断 cache 的 capacity,已满,需要淘汰使用次数最少的元素,找到最小的 freq=1,删除双链表 tail node.prev + 如果 tailnode.prev != null, 删除。然后从 nodeMap 中删除对应的 key。 + - 首先查找 nodeMap 中有没有 key=4 对应的 value, + 没有就新建 node(key, value, freq) -> node4(4, 4, 1), 插入 nodeMap,{[4, node4], [3, node3]} + - 查找 freqMap 中有没有 freq=1 对应的 value, + 没有就新建 doublylinkedlist(head, tail), 把 node4 插入 doublylinkedlist head->next = node4. + 如下图, + ``` +![460.lfu-cache-6](../assets/problems/460.lfu-cache-6.jpg) + ``` + 8. get(1) + - 查找 nodeMap,如果没有对应的 key 的 value,返回 -1。 + + 9. get(3) + - 首先查找 nodeMap 中有没有 key=3 对应的 value,nodeMap:{[4, node4], [3, node3]}, + 找到 node3,把 node3 freq+1 -> node3(3,3,3) + - 更新 freqMap,删除 freq=2,node3 + - 更新 freqMap,插入 freq=3,node3 + 如下图, + ``` +![460.lfu-cache-7](../assets/problems/460.lfu-cache-7.jpg) + ``` + 10. get(4) + - 首先查找 nodeMap 中有没有 key=4 对应的 value,nodeMap:{[4, node4], [3, node3]}, + 找到 node4,把 node4 freq+1 -> node4(4,4,2) + - 更新 freqMap,删除 freq=1,node4 + - 更新 freqMap,插入 freq=2,node4 + 如下图, + ``` +![460.lfu-cache-8](../assets/problems/460.lfu-cache-8.jpg) + +## 关键点分析 +用两个`Map`分别保存 `nodeMap {key, node}` 和 `freqMap{frequent, DoublyLinkedList}`。 +实现`get` 和 `put`操作都是`O(1)`的时间复杂度。 + +可以用 Java 自带的一些数据结构,比如 HashLinkedHashSet,这样就不需要自己自建 Node,DoublelyLinkedList。 +可以很大程度的缩减代码量。 + +## 代码(Java code) +```java +public class LC460LFUCache { + class Node { + int key, val, freq; + Node prev, next; + + Node(int key, int val) { + this.key = key; + this.val = val; + freq = 1; + } + } + + class DoubleLinkedList { + private Node head; + private Node tail; + private int size; + + DoubleLinkedList() { + head = new Node(0, 0); + tail = new Node(0, 0); + head.next = tail; + tail.prev = head; + } + + void add(Node node) { + head.next.prev = node; + node.next = head.next; + node.prev = head; + head.next = node; + size++; + } + + void remove(Node node) { + node.prev.next = node.next; + node.next.prev = node.prev; + size--; + } + + // always remove last node if last node exists + Node removeLast() { + if (size > 0) { + Node node = tail.prev; + remove(node); + return node; + } else return null; + } + } + + // cache capacity + private int capacity; + // min frequent + private int minFreq; + Map nodeMap; + Map freqMap; + public LC460LFUCache(int capacity) { + this.minFreq = 0; + this.capacity = capacity; + nodeMap = new HashMap<>(); + freqMap = new HashMap<>(); + } + + public int get(int key) { + Node node = nodeMap.get(key); + if (node == null) return -1; + update(node); + return node.val; + } + + public void put(int key, int value) { + if (capacity == 0) return; + Node node; + if (nodeMap.containsKey(key)) { + node = nodeMap.get(key); + node.val = value; + update(node); + } else { + node = new Node(key, value); + nodeMap.put(key, node); + if (nodeMap.size() == capacity) { + DoubleLinkedList lastList = freqMap.get(minFreq); + nodeMap.remove(lastList.removeLast().key); + } + minFreq = 1; + DoubleLinkedList newList = freqMap.getOrDefault(node.freq, new DoubleLinkedList()); + newList.add(node); + freqMap.put(node.freq, newList); + } + } + + private void update(Node node) { + DoubleLinkedList oldList = freqMap.get(node.freq); + oldList.remove(node); + if (node.freq == minFreq && oldList.size == 0) minFreq++; + node.freq++; + DoubleLinkedList newList = freqMap.getOrDefault(node.freq, new DoubleLinkedList()); + newList.add(node); + freqMap.put(node.freq, newList); + } + } +``` + +## 参考(References) +1. [LFU(Least frequently used) Cache](https://www.wikiwand.com/en/Least_frequently_used) +2. [Leetcode discussion mylzsd](https://leetcode.com/problems/lfu-cache/discuss/94547/Java-O(1)-Solution-Using-Two-HashMap-and-One-DoubleLinkedList) +3. [Leetcode discussion aaaeeeo](https://leetcode.com/problems/lfu-cache/discuss/94547/Java-O(1)-Solution-Using-Two-HashMap-and-One-DoubleLinkedList) diff --git a/spider/row-markdown/47.permutations-ii.md b/spider/row-markdown/47.permutations-ii.md new file mode 100644 index 0000000..0ab000f --- /dev/null +++ b/spider/row-markdown/47.permutations-ii.md @@ -0,0 +1,140 @@ +## 题目地址 +https://leetcode.com/problems/permutations-ii/description/ + +## 题目描述 +``` +Given a collection of numbers that might contain duplicates, return all possible unique permutations. + +Example: + +Input: [1,1,2] +Output: +[ + [1,1,2], + [1,2,1], + [2,1,1] +] + +``` + +## 思路 + +这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。 + +这种题目其实有一个通用的解法,就是回溯法。 +网上也有大神给出了这种回溯法解题的 +[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。 +除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。 + +我们先来看下通用解法的解题思路,我画了一张图: + +![backtrack](../assets/problems/backtrack.png) + +通用写法的具体代码见下方代码区。 + +## 关键点解析 + +- 回溯法 +- backtrack 解题公式 + + +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=47 lang=javascript + * + * [47] Permutations II + * + * https://leetcode.com/problems/permutations-ii/description/ + * + * algorithms + * Medium (39.29%) + * Total Accepted: 234.1K + * Total Submissions: 586.2K + * Testcase Example: '[1,1,2]' + * + * Given a collection of numbers that might contain duplicates, return all + * possible unique permutations. + * + * Example: + * + * + * Input: [1,1,2] + * Output: + * [ + * ⁠ [1,1,2], + * ⁠ [1,2,1], + * ⁠ [2,1,1] + * ] + * + * + */ +function backtrack(list, nums, tempList, visited) { + if (tempList.length === nums.length) return list.push([...tempList]); + for (let i = 0; i < nums.length; i++) { + // 和46.permutations的区别是这道题的nums是可以重复的 + // 我们需要过滤这种情况 + if (visited[i]) continue; // 不能用tempList.includes(nums[i])了,因为有重复 + // visited[i - 1] 这个判断容易忽略 + if (i > 0 && nums[i] === nums[i - 1] && visited[i - 1]) continue; + + visited[i] = true; + tempList.push(nums[i]); + backtrack(list, nums, tempList, visited); + visited[i] = false; + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var permuteUnique = function(nums) { + const list = []; + backtrack(list, nums.sort((a, b) => a - b), [], []); + return list; +}; +``` +Python3 code: +```Python +class Solution: + def permuteUnique(self, nums: List[int]) -> List[List[int]]: + """与46题一样,当然也可以直接调用itertools的函数,然后去重""" + return list(set(itertools.permutations(nums))) + + def permuteUnique(self, nums: List[int]) -> List[List[int]]: + """自己写回溯法,与46题相比,需要去重""" + # 排序是为了去重 + nums.sort() + res = [] + def _backtrace(nums, pre_list): + if len(nums) <= 0: + res.append(pre_list) + else: + for i in range(len(nums)): + # 如果是同样的数字,则之前一定已经生成了对应可能 + if i > 0 and nums[i] == nums[i-1]: + continue + p_list = pre_list.copy() + p_list.append(nums[i]) + left_nums = nums.copy() + left_nums.pop(i) + _backtrace(left_nums, p_list) + _backtrace(nums, []) + return res +``` + +## 相关题目 + +- [31.next-permutation](./31.next-permutation.md) +- [39.combination-sum](./39.combination-sum.md) +- [40.combination-sum-ii](./40.combination-sum-ii.md) +- [46.permutations](./46.permutations.md) +- [60.permutation-sequence](./60.permutation-sequence.md)(TODO) +- [78.subsets](./78.subsets.md) +- [90.subsets-ii](./90.subsets-ii.md) +- [113.path-sum-ii](./113.path-sum-ii.md) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md) diff --git a/spider/row-markdown/472.concatenated-words.md b/spider/row-markdown/472.concatenated-words.md new file mode 100644 index 0000000..409948d --- /dev/null +++ b/spider/row-markdown/472.concatenated-words.md @@ -0,0 +1,121 @@ +## 题目地址(472. 连接词) + +https://leetcode-cn.com/problems/concatenated-words/ + +## 题目描述 + +``` +给定一个不含重复单词的列表,编写一个程序,返回给定单词列表中所有的连接词。 + +连接词的定义为:一个字符串完全是由至少两个给定数组中的单词组成的。 + +示例: + +输入: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"] + +输出: ["catsdogcats","dogcatsdog","ratcatdogcat"] + +解释: "catsdogcats"由"cats", "dog" 和 "cats"组成; + "dogcatsdog"由"dog", "cats"和"dog"组成; + "ratcatdogcat"由"rat", "cat", "dog"和"cat"组成。 +说明: + +给定数组的元素总数不超过 10000。 +给定数组中元素的长度总和不超过 600000。 +所有输入字符串只包含小写字母。 +不需要考虑答案输出的顺序。 +``` + +## 思路 + +本题我的思路是直接使用前缀树来解决。**标准的前缀树模板**我在之前的题解中提到了,感兴趣的可以到下方的相关题目中查看。 + +这道题这里我们不需要 search,我们的做法是: + +- 先进行一次遍历,将 words 全部插入(insert)到前缀树中。 +- 然后再进行一次遍历,查找每一个单词有几个单词表中的单词组成 +- 如果大于 2,则将其加入到 res 中 +- 最后返回 res 即可 + +我们构造的前缀树大概是这样的: + +![472.concatenated-words.png](http://ww1.sinaimg.cn/large/e9f490c8ly1gbkcox4r06j21eb15fgq8.jpg) + +问题的关键在于第二步中的**查找每一个单词有几个单词表中的单词组成**。 其实如果你了解前缀树的话应该不难写出来。 比如查找 catsdogcats: + +- 我们先从 c 到 a 到 t,发现 t 是单词结尾,我们数量 + 1 +- 然后将剩下的部分“sdogcats”重新执行上述过程。 +- s 发现找不到,我们返回 0 +- 因此最终结果是 1 + +很明显这个逻辑是错误的,正确的划分应该是: + +- 我们先从 c 到 a 到 t,再到 s,此时数量 + 1 +- 然后将剩下的“dogcats”重复上述过程 +- dog 找到了,数量 + 1 +- 最后将 cats 加入。也找到了,数量再加 1 + +由于我们并不知道 cat 这里断开,结果更大?还是 cats 这里断开结果更大?因此我们的做法是将其全部递归求出,然后取出最大值即可。如果我们直接这样递归的话,可能会超时,卡在最后一个测试用例上。一个简单的方式是记忆化递归,从而避免重复计算,经测试这种方法能够通过。 + +## 代码 + +代码支持:Python3 + +Python3 Code: + +```python +class Trie: + + def __init__(self): + self.Trie = {} + self.visited = {} + + def insert(self, word): + curr = self.Trie + for w in word: + if w not in curr: + curr[w] = {} + curr = curr[w] + curr['#'] = 1 + + def cntWords(self, word): + if not word: + return 0 + if word in self.visited: + return self.visited[word] + curr = self.Trie + res = float('-inf') + + for i, w in enumerate(word): + if w not in curr: + return res + curr = curr[w] + if '#' in curr: + res = max(res, 1 + self.cntWords(word[i + 1:])) + self.visited[word] = res + return res + + +class Solution: + def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]: + self.trie = Trie() + res = [] + + for word in words: + self.trie.insert(word) + for word in words: + if self.trie.cntWords(word) >= 2: + res.append(word) + return res +``` + +## 关键点分析 + +- 前缀树 + +## 相关题目 + +- [0208.implement-trie-prefix-tree](https://github.com/azl397985856/leetcode/blob/b8e8fa5f0554926efa9039495b25ed7fc158372a/problems/208.implement-trie-prefix-tree.md) +- [0211.add-and-search-word-data-structure-design](https://github.com/azl397985856/leetcode/blob/b0b69f8f11dace3a9040b54532105d42e88e6599/problems/211.add-and-search-word-data-structure-design.md) +- [0212.word-search-ii](https://github.com/azl397985856/leetcode/blob/b0b69f8f11dace3a9040b54532105d42e88e6599/problems/212.word-search-ii.md) +- [0820.short-encoding-of-words](https://github.com/azl397985856/leetcode/blob/master/problems/820.short-encoding-of-words.md) diff --git a/spider/row-markdown/474.ones-and-zeros-en.md b/spider/row-markdown/474.ones-and-zeros-en.md new file mode 100644 index 0000000..f6e1da7 --- /dev/null +++ b/spider/row-markdown/474.ones-and-zeros-en.md @@ -0,0 +1,299 @@ +## Problem +https://leetcode.com/problems/ones-and-zeroes/ + +## Problem Description +``` +In the computer world, use restricted resource you have to generate maximum benefit is what we always want to pursue. + +For now, suppose you are a dominator of m 0s and n 1s respectively. On the other hand, there is an array with strings consisting of only 0s and 1s. + +Now your task is to find the maximum number of strings that you can form with given m 0s and n 1s. Each 0 and 1 can be used at most once. + +Note: + +The given numbers of 0s and 1s will both not exceed 100 +The size of given string array won't exceed 600. + +Example 1: + +Input: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3 +Output: 4 + +Explanation: This are totally 4 strings can be formed by the using of 5 0s and 3 1s, which are “10,”0001”,”1”,”0” + +Example 2: + +Input: Array = {"10", "0", "1"}, m = 1, n = 1 +Output: 2 + +Explanation: You could form "10", but then you'd have nothing left. Better form "0" and "1". +``` + + +## Solution + +When see the requirement of returning maximum number, length etc, and not require to list all possible value. Usually it can +be solved by DP. + +This problem we can see is a `0-1 backpack` issue, either take current string or not take current string. + +And during interview, DP problem is hard to come up with immediately, recommend starting from Brute force, then optimize the solution step by step, until interviewer is happy, :-) + +Below give 4 solutions based on complexities analysis. + +#### Solution #1 - Brute Force (Recursively) + +Brute force solution is to calculate all possible subsets. Then count `0s` and `1s` for each subset, use global variable `max` to keep track of maximum number. +if `count(0) <= m && count(1) <= n;`, then current string can be taken into counts. + +for `strs` length `len`, total subsets are `2^len`, Time Complexity is too high in this solution. + +#### Complexity Analysis +- *Time Complexity:* `O(2^len * s) - len is Strs length, s is the average string length ` +- *Space Complexity:* `O(1)` + +#### Solution #2 - Memorization + Recursive +In Solution #1, brute force, we used recursive to calculate all subsets, in reality, many cases are duplicate, so that we can use +memorization to record those subsets which realdy been calculated, avoid dup calculation. Use a memo array, if already calculated, +then return memo value, otherwise, set the max value into memo. + +`memo[i][j][k] - maximum number of strings can be formed by j 0s and k 1s in range [0, i] strings` + +`helper(strs, i, j, k, memo)` recursively: +1. if `memo[i][j][k] != 0`, meaning already checked for j 0s and k 1s case, return value. +2. if not checked, then check condition `count0 <= j && count1 <= k`, + a. if true,take current strings `strs[i]`, so` 0s -> j-count0`, and `1s -> k-count1`, + check next string `helper(strs, i+1, j-count0, k-count1, memo)` +3. not take current string `strs[i]`, check next string `helper(strs, i+1, j, k, memo)` +4. save max value into`memo[i][j][k]` +5. recursively + +#### Complexity Analysis +- *Time Complexity:* `O(l * m * n) - l is length of strs, m is number of 0s, n is number of 1s` +- *Space Complexity:* `O(l * m * n) - memo 3D Array` + +#### Solution #3 - 3D DP +In Solution #2, used memorization + recursive, this Solution use 3D DP to represent iterative way + +`dp[i][j][k] - the maximum number of strings can be formed using j 0s and k 1s in range [0, i] strings` + +DP Formula: +`dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - count0][k - count1])` - `count0 - number of 0s in strs[i]` and `count1 - number of 1s in strs[i]` + + compare `j` and `count0`, `k` and `count1`, based on taking current string or not, DP formula as below: +- `j >= count0 && k >= count1`, + + `dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - count0][k - count1] + 1)` + +- not meet condition, not take current string + + `dp[i][j][k] = dp[i - 1][j][k]` + +`dp[l][m][n]` is result. + +#### Complexity Analysis +- *Time Complexity:* `O(l * m * n) - l is strs length, m is number of 0s, n is number of 1s` +- *Space Complexity:* `O(l * m * n) - dp 3D array` + +#### Solution #4 - 2D DP + +In Solution #3, we kept track all state value, but we only need previous state, so we can reduce 3 dimention to 2 dimention array, +here we use `dp[2][m][n]`, rotate track previous and current values. Further observation, we notice that first row (track previous state), +we don't need the whole row values, we only care about 2 position value: `dp[i - 1][j][k]` and `dp[i - 1][j - count0][k - count1]`. +so it can be reduced to 2D array. `dp[m][n]`. + +2D DP definition: + +`dp[m+1][n+1] - maximum counts, m is number of 0, n is number of 1` + +DP formula: + +`dp[i][j] = max(dp[i][j], dp[i - count0][j - count1] + 1)` + +For example: + +![ones and zeros 2d dp](../assets/problems/474.ones-and-zeros-2d-dp.png) + +#### +- *Time Complexity:* `O(l * m * n) - l is strs length,m is number of 0,n number of 1` +- *Space Complexity:* `O(m * n) - dp 2D array` + +## Key Points Analysis + +## Code (`Java/Python3`) +#### Solution #1 - Recursive (TLE) +*Java code* +```java +class OnesAndZerosBFRecursive { + public int findMaxForm2(String[] strs, int m, int n) { + return helper(strs, 0, m, n); + } + private int helper(String[] strs, int idx, int j, int k) { + if (idx == strs.length) return 0; + // count current idx string number of zeros and ones + int[] counts = countZeroOnes(strs[idx]); + // if j >= count0 && k >= count1, take current index string + int takeCurrStr = j - counts[0] >= 0 && k - counts[1] >= 0 + ? 1 + helper(strs, idx + 1, j - counts[0], k - counts[1]) + : -1; + // don't take current index string strs[idx], continue next string + int notTakeCurrStr = helper(strs, idx + 1, j, k); + return Math.max(takeCurrStr, notTakeCurrStr); + } + private int[] countZeroOnes(String s) { + int[] res = new int[2]; + for (char ch : s.toCharArray()) { + res[ch - '0']++; + } + return res; + } +} +``` + +*Python3 code* +```python +class Solution: + def findMaxForm(self, strs: List[str], m: int, n: int) -> int: + return self.helper(strs, m, n, 0) + + def helper(self, strs, m, n, idx): + if idx == len(strs): + return 0 + take_curr_str = -1 + count0, count1 = strs[idx].count('0'), strs[idx].count('1') + if m >= count0 and n >= count1: + take_curr_str = max(take_curr_str, self.helper(strs, m - count0, n - count1, idx + 1) + 1) + not_take_curr_str = self.helper(strs, m, n, idx + 1) + return max(take_curr_str, not_take_curr_str) + +``` + +#### Solution #2 - Memorization + Recursive +*Java code* +```java +class OnesAndZerosMemoRecur { + public int findMaxForm4(String[] strs, int m, int n) { + return helper(strs, 0, m, n, new int[strs.length][m + 1][n + 1]); + } + private int helper(String[] strs, int idx, int j, int k, int[][][] memo) { + if (idx == strs.length) return 0; + // check if already calculated, return value + if (memo[idx][j][k] != 0) { + return memo[idx][j][k]; + } + int[] counts = countZeroOnes(strs[idx]); + // if satisfy condition, take current string, strs[idx], update count0 and count1 + int takeCurrStr = j - counts[0] >= 0 && k - counts[1] >= 0 + ? 1 + helper(strs, idx + 1, j - counts[0], k - counts[1], memo) + : -1; + // not take current string + int notTakeCurrStr = helper(strs, idx + 1, j, k, memo); + // always keep track the max value into memory + memo[idx][j][k] = Math.max(takeCurrStr, notTakeCurrStr); + return memo[idx][j][k]; + } + private int[] countZeroOnes(String s) { + int[] res = new int[2]; + for (char ch : s.toCharArray()) { + res[ch - '0']++; + } + return res; + } +} +``` + +*Python3 code* - (TLE) +```python +class Solution: + def findMaxForm(self, strs: List[str], m: int, n: int) -> int: + memo = {k:[[0]*(n+1) for _ in range(m+1)] for k in range(len(strs)+1)} + return self.helper(strs, 0, m, n, memo) + + def helper(self, strs, idx, m, n, memo): + if idx == len(strs): + return 0 + if memo[idx][m][n] != 0: + return memo[idx][m][n] + take_curr_str = -1 + count0, count1 = strs[idx].count('0'), strs[idx].count('1') + if m >= count0 and n >= count1: + take_curr_str = max(take_curr_str, self.helper(strs, idx + 1, m - count0, n - count1, memo) + 1) + not_take_curr_str = self.helper(strs, idx + 1, m, n, memo) + memo[idx][m][n] = max(take_curr_str, not_take_curr_str) + return memo[idx][m][n] +``` + + +#### Solution #3 - 3D DP +*Java code* +```java +class OnesAndZeros3DDP { + public int findMaxForm(String[] strs, int m, int n) { + int l = strs.length; + int [][][] d = new int[l + 1][m + 1][n + 1]; + for (int i = 0; i <= l; i ++){ + int [] nums = new int[]{0,0}; + if (i > 0){ + nums = countZeroOnes(strs[i - 1]); + } + for (int j = 0; j <= m; j ++){ + for (int k = 0; k <= n; k ++){ + if (i == 0) { + d[i][j][k] = 0; + } else if (j >= nums[0] && k >= nums[1]){ + d[i][j][k] = Math.max(d[i - 1][j][k], d[i - 1][j - nums[0]][k - nums[1]] + 1); + } else { + d[i][j][k] = d[i - 1][j][k]; + } + } + } + } + return d[l][m][n]; + } +} +``` +#### Solution #4 - 2D DP +*Java code* +```java +class OnesAndZeros2DDP { + public int findMaxForm(String[] strs, int m, int n) { + int[][] dp = new int[m + 1][n + 1]; + for (String s : strs) { + int[] counts = countZeroOnes(s); + for (int i = m; i >= counts[0]; i--) { + for (int j = n; j >= counts[1]; j--) { + dp[i][j] = Math.max(1 + dp[i - counts[0]][j - counts[1]], dp[i][j]); + } + } + } + return dp[m][n]; + } + private int[] countZeroOnes(String s) { + int[] res = new int[2]; + for (char ch : s.toCharArray()) { + res[ch - '0']++; + } + return res; + } +} + +``` +*Python3 code* +```python +class Solution: + def findMaxForm(self, strs: List[str], m: int, n: int) -> int: + l = len(strs) + dp = [[0]*(n+1) for _ in range(m+1)] + for i in range(1, l + 1): + count0, count1 = strs[i - 1].count('0'), strs[i - 1].count('1') + for i in reversed(range(count0, m + 1)): + for j in reversed(range(count1, n + 1)): + dp[i][j] = max(dp[i][j], 1 + dp[i - count0][j - count1]) + return dp[m][n] +``` + +## Similar problems + +- [Leetcode 600. Non-negative Integers without Consecutive Ones](https://leetcode.com/problems/non-negative-integers-without-consecutive-ones/) +- [Leetcode 322. Coin Change](https://leetcode.com/problems/coin-change/) + diff --git a/spider/row-markdown/48.rotate-image.md b/spider/row-markdown/48.rotate-image.md new file mode 100644 index 0000000..9cf8f59 --- /dev/null +++ b/spider/row-markdown/48.rotate-image.md @@ -0,0 +1,148 @@ +## 题目地址 + +https://leetcode.com/problems/rotate-image/description/ + +## 题目描述 + +``` +You are given an n x n 2D matrix representing an image. + +Rotate the image by 90 degrees (clockwise). + +Note: + +You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. + +Example 1: + +Given input matrix = +[ + [1,2,3], + [4,5,6], + [7,8,9] +], + +rotate the input matrix in-place such that it becomes: +[ + [7,4,1], + [8,5,2], + [9,6,3] +] +Example 2: + +Given input matrix = +[ + [ 5, 1, 9,11], + [ 2, 4, 8,10], + [13, 3, 6, 7], + [15,14,12,16] +], + +rotate the input matrix in-place such that it becomes: +[ + [15,13, 2, 5], + [14, 3, 4, 1], + [12, 6, 8, 9], + [16, 7,10,11] +] + +``` + +## 思路 + +这道题目让我们 in-place,也就说空间复杂度要求 O(1),如果没有这个限制的话,很简单。 + +通过观察发现,我们只需要将第 i 行变成第 n - i - 1 列, 因此我们只需要保存一个原有矩阵,然后按照这个规律一个个更新即可。 + +![48.rotate-image-1](../assets/problems/48.rotate-image-1.png) + +代码: + +```js +var rotate = function(matrix) { + // 时间复杂度O(n^2) 空间复杂度O(n) + const oMatrix = JSON.parse(JSON.stringify(matrix)); // clone + const n = oMatrix.length; + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + matrix[j][n - i - 1] = oMatrix[i][j]; + } + } +}; +``` + +如果要求空间复杂度是O(1)的话,我们可以用一个temp记录即可,这个时候就不能逐个遍历了。 +比如遍历到1的时候,我们把1存到temp,然后更新1的值为7。 1被换到了3的位置,我们再将3存到temp,依次类推。 +但是这种解法写起来比较麻烦,这里我就不写了。 + +事实上有一个更加巧妙的做法,我们可以巧妙地利用对称轴旋转达到我们的目的,如图,我们先进行一次以对角线为轴的翻转,然后 +再进行一次以水平轴心线为轴的翻转即可。 + +![48.rotate-image-2](../assets/problems/48.rotate-image-2.png) + +这种做法的时间复杂度是O(n^2) ,空间复杂度是O(1) + +## 关键点解析 + +- 矩阵旋转操作 + +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=48 lang=javascript + * + * [48] Rotate Image + */ +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ +var rotate = function(matrix) { + // 时间复杂度O(n^2) 空间复杂度O(1) + + // 做法: 先沿着对角线翻转,然后沿着水平线翻转 + const n = matrix.length; + function swap(arr, [i, j], [m, n]) { + const temp = arr[i][j]; + arr[i][j] = arr[m][n]; + arr[m][n] = temp; + } + for (let i = 0; i < n - 1; i++) { + for (let j = 0; j < n - i; j++) { + swap(matrix, [i, j], [n - j - 1, n - i - 1]); + } + } + + for (let i = 0; i < n / 2; i++) { + for (let j = 0; j < n; j++) { + swap(matrix, [i, j], [n - i - 1, j]); + } + } +}; +``` +Python3 Code: +```Python +class Solution: + def rotate(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + 先做矩阵转置(即沿着对角线翻转),然后每个列表翻转; + """ + n = len(matrix) + for i in range(n): + for j in range(i, n): + matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] + for m in matrix: + m.reverse() + + def rotate2(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + 通过内置函数zip,可以简单实现矩阵转置,下面的代码等于先整体翻转,后转置; + 不过这种写法的空间复杂度其实是O(n); + """ + matrix[:] = map(list, zip(*matrix[::-1])) +``` diff --git a/spider/row-markdown/49.group-anagrams.md b/spider/row-markdown/49.group-anagrams.md new file mode 100644 index 0000000..e8c7c69 --- /dev/null +++ b/spider/row-markdown/49.group-anagrams.md @@ -0,0 +1,122 @@ +## 题目地址 + +https://leetcode.com/problems/group-anagrams/description/ + +## 题目描述 + +``` +Given an array of strings, group anagrams together. + +Example: + +Input: ["eat", "tea", "tan", "ate", "nat", "bat"], +Output: +[ + ["ate","eat","tea"], + ["nat","tan"], + ["bat"] +] +Note: + +All inputs will be in lowercase. +The order of your output does not matter. +``` + +## 思路 + +一个简单的解法就是遍历数组,然后对每一项都进行排序,然后将其添加到 hashTable 中,最后输出 hashTable 中保存的值即可。 + +这种做法空间复杂度 O(n), 假设排序算法用的快排,那么时间复杂度为 O(n \* klogk), n 为数组长度,k 为字符串的平均长度 + +代码: + +```js +var groupAnagrams = function(strs) { + const hashTable = {}; + + function sort(str) { + return str + .split("") + .sort() + .join(""); + } + + // 这个方法需要排序,因此不是很优,但是很直观,容易想到 + for (let i = 0; i < strs.length; i++) { + const str = strs[i]; + const key = sort(str); + if (!hashTable[key]) { + hashTable[key] = [str]; + } else { + hashTable[key].push(str); + } + } + + return Object.values(hashTable); +}; +``` + +下面我们介绍另外一种方法,我们建立一个 26 长度的 counts 数组(如果区分大小写,我们可以建立 52 个,如果支持其他字符依次类推)。 +然后我们给每一个字符一个固定的数组下标,然后我们只需要更新每个字符出现的次数。 最后形成的 counts 数组如果一致,则说明他们可以通过 +交换顺序得到。这种算法空间复杂度 O(n), 时间复杂度 O(n \* k), n 为数组长度,k 为字符串的平均长度. + +![49.group-anagrams](../assets/problems/49.group-anagrams.png) + +## 关键点解析 + +- 桶排序 + +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=49 lang=javascript + * + * [49] Group Anagrams + */ +/** + * @param {string[]} strs + * @return {string[][]} + */ +var groupAnagrams = function(strs) { + // 类似桶排序 + + let counts = []; + const hashTable = {}; + for (let i = 0; i < strs.length; i++) { + const str = strs[i]; + counts = Array(26).fill(0); + for (let j = 0; j < str.length; j++) { + counts[str[j].charCodeAt(0) - "a".charCodeAt(0)]++; + } + const key = counts.join(""); + if (!hashTable[key]) { + hashTable[key] = [str]; + } else { + hashTable[key].push(str); + } + } + + return Object.values(hashTable); +}; +``` +Python3 Code: +```Python +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + """ + 思路同上,在Python中,这里涉及到3个知识点: + 1. 使用内置的 defaultdict 字典设置默认值; + 2. 内置的 ord 函数,计算ASCII值(等于chr)或Unicode值(等于unichr); + 3. 列表不可哈希,不能作为字典的键,因此这里转为元组; + """ + str_dict = collections.defaultdict(list) + for s in strs: + s_key = [0] * 26 + for c in s: + s_key[ord(c)-ord('a')] += 1 + str_dict[tuple(s_key)].append(s) + return str_dict.values() +``` diff --git a/spider/row-markdown/493.reverse-pairs.md b/spider/row-markdown/493.reverse-pairs.md new file mode 100644 index 0000000..0470c97 --- /dev/null +++ b/spider/row-markdown/493.reverse-pairs.md @@ -0,0 +1,120 @@ +## 题目地址(493. 翻转对) + +https://leetcode-cn.com/problems/reverse-pairs/description/ + +## 题目描述 + +``` +给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。 + +你需要返回给定数组中的重要翻转对的数量。 + +示例 1: + +输入: [1,3,2,3,1] +输出: 2 +示例 2: + +输入: [2,4,3,5,1] +输出: 3 +注意: + +给定数组的长度不会超过50000。 +输入数组中的所有数字都在32位整数的表示范围内。 + +``` + +## 暴力法 + +### 思路 + +读完这道题你应该就能联想到逆序数才行。求解逆序数最简单的做法是使用双层循环暴力求解。我们仿照求解决逆序数的解法来解这道题(其实唯一的区别就是系数从 1 变成了 2)。 + +### 代码 + +代码支持:Python3 + +Python3 Code: + +```python +class Solution(object): + def reversePairs(self, nums): + n = len(nums) + cnt = 0 + for i in range(n): + for j in range(i + 1, n): + if nums[i] > 2 * nums[j]: + cnt += 1 + return cnt +``` + +## 分治法 + +### 思路 + +如果你能够想到逆序数,那么你很可能直到使用类似归并排序的方法可以求解逆序数。实际上逆序数只是归并排序的副产物而已。 + +我们在正常的归并排序的代码中去计算逆序数即可。由于每次分治的过程,左右两段数组分别是有序的,因此我们可以减少一些运算。 从时间复杂度的角度上讲,我们从$O(N^2)$优化到了 $O(NlogN)$。 + +具体来说,对两段有序的数组,有序数组内部是不需要计算逆序数的。 我们计算逆序数的逻辑只是计算两个数组之间的逆序数,我们假设两个数组是 A 和 B,并且 A 数组最大的元素不大于 B 数组最小的元素。而要做到这样,我们只需要常规的归并排序即可。 + +接下来问题转化为求解两个有序数组之间的逆序数,并且两个有序数组之间满足关系`A数组最大的元素不大于B数组最小的元素`。 + +关于计算逆序数的核心代码(Python3): + +```python +l = r = 0 +while l < len(left) and r < len(right): + if left[l] <= 2 * right[r]: + l += 1 + else: + self.cnt += len(left) - l + r += 1 +``` + +### 代码 + +代码支持:Python3 + +Python3 Code: + +```python +class Solution(object): + def reversePairs(self, nums): + self.cnt = 0 + + def mergeSort(lst): + L = len(lst) + if L <= 1: + return lst + return mergeTwo(mergeSort(lst[:L//2]), mergeSort(lst[L//2:])) + + def mergeTwo(left, right): + l = r = 0 + while l < len(left) and r < len(right): + if left[l] <= 2 * right[r]: + l += 1 + else: + self.cnt += len(left) - l + r += 1 + return sorted(left+right) + + mergeSort(nums) + return self.cnt + +``` + +对于具体的排序过程我们偷懒直接使用了语言内置的方法 sorted,这在很多时候是有用的,即使你是参加面试,这种方式通常也是允许的。省略非核心的考点,可以使得问题更加聚焦,这是一种解决问题的思路,在工作中也很有用。 + +## 关键点解析 + +- 归并排序 +- 逆序数 +- 分治 +- 识别考点,其他非重点可以使用语言内置方法 + +## 代码 + +## 扩展 + +这道题还有很多别的解法,感性的可以参考下这个题解 [General principles behind problems similar to "Reverse Pairs"](https://leetcode.com/problems/reverse-pairs/discuss/97268/General-principles-behind-problems-similar-to-%22Reverse-Pairs%22) diff --git a/spider/row-markdown/494.target-sum.md b/spider/row-markdown/494.target-sum.md new file mode 100644 index 0000000..6611e25 --- /dev/null +++ b/spider/row-markdown/494.target-sum.md @@ -0,0 +1,98 @@ +## 题目地址 + +https://leetcode.com/problems/target-sum/description/ + +## 题目描述 + +``` +You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol. + +Find out how many ways to assign symbols to make sum of integers equal to target S. + +Example 1: +Input: nums is [1, 1, 1, 1, 1], S is 3. +Output: 5 +Explanation: + +-1+1+1+1+1 = 3 ++1-1+1+1+1 = 3 ++1+1-1+1+1 = 3 ++1+1+1-1+1 = 3 ++1+1+1+1-1 = 3 + +There are 5 ways to assign symbols to make the sum of nums be target 3. +Note: +The length of the given array is positive and will not exceed 20. +The sum of elements in the given array will not exceed 1000. +Your output answer is guaranteed to be fitted in a 32-bit integer. + +``` + +## 思路 + +题目是给定一个数组,让你在数字前面添加 `+`或者`-`,使其和等于 target. + +![494.target-sum](../assets/problems/494.target-sum.png) + +暴力法的时间复杂度是指数级别的,因此我们不予考虑。我们需要换种思路. + +我们将最终的结果分成两组,一组是我们添加了`+`的,一组是我们添加了`-`的。 + +![494.target-sum-2](../assets/problems/494.target-sum-2.png) + +如上图,问题转化为如何求其中一组,我们不妨求前面标`+`的一组 + +> 如果求出一组,另一组实际就已知了,即总集和这一组的差集。 + +通过进一步分析,我们得到了这样的关系: + +![494.target-sum-3](../assets/problems/494.target-sum-3.png) + +因此问题转化为,求解`sumCount(nums, target)`,即 nums 数组中能够组成 +target 的总数一共有多少种,这是一道我们之前做过的题目,使用动态规划可以解决。 + +## 关键点解析 + +- 对元素进行分组,分组的依据是符号, 是`+` 或者 `-` +- 通过数学公式推导可以简化我们的求解过程,这需要一点`数学知识和数学意识` + +## 代码 + +```js +/* + * @lc app=leetcode id=494 lang=javascript + * + * [494] Target Sum + * + */ +// 这个是我们熟悉的问题了 +// 我们这里需要求解的是nums里面有多少种可以组成target的方式 +var sumCount = function(nums, target) { + // 这里通过观察,我们没必要使用二维数组去存储这些计算结果 + // 使用一维数组可以有效节省空间 + const dp = Array(target + 1).fill(0); + dp[0] = 1; + for (let i = 0; i < nums.length; i++) { + for (let j = target; j >= nums[i]; j--) { + dp[j] += dp[j - nums[i]]; + } + } + return dp[target]; +}; +const add = nums => nums.reduce((a, b) => (a += b), 0); +/** + * @param {number[]} nums + * @param {number} S + * @return {number} + */ +var findTargetSumWays = function(nums, S) { + const sum = add(nums); + if (sum < S) return 0; + if ((S + sum) % 2 === 1) return 0; + return sumCount(nums, (S + sum) >> 1); +}; +``` + +## 扩展 + +如果这道题目并没有限定所有的元素以及 target 都是正数怎么办? diff --git a/spider/row-markdown/5.longest-palindromic-substring.md b/spider/row-markdown/5.longest-palindromic-substring.md new file mode 100644 index 0000000..0edaffc --- /dev/null +++ b/spider/row-markdown/5.longest-palindromic-substring.md @@ -0,0 +1,134 @@ +## 题目地址(5. 最长回文子串) + +https://leetcode-cn.com/problems/longest-palindromic-substring/ + +## 题目描述 + +给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 + +示例 1: + +输入: "babad" +输出: "bab" +注意: "aba" 也是一个有效答案。 +示例 2: + +输入: "cbbd" +输出: "bb" + +## 思路 + +这是一道最长回文的题目,要我们求出给定字符串的最大回文子串。 + +![5.longest-palindromic-substring](../assets/problems/5.longest-palindromic-substring-1.png) + +解决这类问题的核心思想就是两个字“延伸”,具体来说 + +- 如果在一个不是回文字符串的字符串两端添加任何字符,或者在回文串左右分别加不同的字符,得到的一定不是回文串 +- 如果一个字符串不是回文串,或者在回文串左右分别加不同的字符,得到的一定不是回文串 + +事实上,上面的分析已经建立了大问题和小问题之间的关联, +基于此,我们可以建立动态规划模型。 + +我们可以用 dp[i][j] 表示 s 中从 i 到 j(包括 i 和 j)是否可以形成回文, +状态转移方程只是将上面的描述转化为代码即可: + +```js +if (s[i] === s[j] && dp[i + 1][j - 1]) { + dp[i][j] = true; +} +``` +![5.longest-palindromic-substring-2](../assets/problems/5.longest-palindromic-substring-2.png) + +base case就是一个字符(轴对称点是本身),或者两个字符(轴对称点是介于两者之间的虚拟点)。 + +![5.longest-palindromic-substring-3](../assets/problems/5.longest-palindromic-substring-3.png) +## 关键点 + +- ”延伸“(extend) + +## 代码 + +代码支持:Python,JavaScript: + +Python Code: + +```python +class Solution: + def longestPalindrome(self, s: str) -> str: + n = len(s) + if n == 0: + return "" + res = s[0] + def extend(i, j, s): + while(i >= 0 and j < len(s) and s[i] == s[j]): + i -= 1 + j += 1 + return s[i + 1:j] + + for i in range(n - 1): + e1 = extend(i, i, s) + e2 = extend(i, i + 1, s) + if max(len(e1), len(e2)) > len(res): + res = e1 if len(e1) > len(e2) else e2 + return res +``` + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=5 lang=javascript + * + * [5] Longest Palindromic Substring + */ +/** + * @param {string} s + * @return {string} + */ +var longestPalindrome = function(s) { + // babad + // tag : dp + if (!s || s.length === 0) return ""; + let res = s[0]; + + const dp = []; + + // 倒着遍历简化操作, 这么做的原因是dp[i][..]依赖于dp[i + 1][..] + for (let i = s.length - 1; i >= 0; i--) { + dp[i] = []; + for (let j = i; j < s.length; j++) { + if (j - i === 0) dp[i][j] = true; + // specail case 1 + else if (j - i === 1 && s[i] === s[j]) dp[i][j] = true; + // specail case 2 + else if (s[i] === s[j] && dp[i + 1][j - 1]) { + // state transition + dp[i][j] = true; + } + + if (dp[i][j] && j - i + 1 > res.length) { + // update res + res = s.slice(i, j + 1); + } + } + } + + return res; +}; +``` + + +***复杂度分析*** +- 时间复杂度:$O(N^2)$ +- 空间复杂度:$O(N^2)$ + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) + +## 相关题目 + +- [516.longest-palindromic-subsequence](./516.longest-palindromic-subsequence.md) diff --git a/spider/row-markdown/50.pow-x-n.md b/spider/row-markdown/50.pow-x-n.md new file mode 100644 index 0000000..42291b1 --- /dev/null +++ b/spider/row-markdown/50.pow-x-n.md @@ -0,0 +1,189 @@ +## 题目地址(50. Pow(x, n)) + +https://leetcode-cn.com/problems/powx-n/description/ + +## 题目描述 + +``` +实现 pow(x, n) ,即计算 x 的 n 次幂函数。 + +示例 1: + +输入: 2.00000, 10 +输出: 1024.00000 +示例 2: + +输入: 2.10000, 3 +输出: 9.26100 +示例 3: + +输入: 2.00000, -2 +输出: 0.25000 +解释: 2-2 = 1/22 = 1/4 = 0.25 +说明: + +-100.0 < x < 100.0 +n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。 + +``` + +## 解法零 - 遍历法 + +### 思路 + +这道题是让我们实现数学函数`幂`,因此直接调用系统内置函数是不被允许的。 + +符合直觉的做法是`将x乘以n次`,这种做法的时间复杂度是$O(N)$。 + +经实际测试,这种做法果然超时了。测试用例通过 291/304,在 `0.00001\n2147483647`这个测试用例挂掉了。如果是面试,这个解法可以作为一种兜底解法。 + +### 代码 + +语言支持: Python3 + +Python3 Code: + +```python +class Solution: + def myPow(self, x: float, n: int) -> float: + if n == 0: + return 1 + if n < 0: + return 1 / self.myPow(x, -n) + res = 1 + for _ in range(n): + res *= x + return res +``` + +## 解法一 - 普通递归(超时法) + +### 思路 + +首先我们要知道: + +- 如果想要求 x ^ 4,那么我们可以求 (x^2)^2 +- 如果是奇数,会有一点不同。 比如 x ^ 5 就等价于 x \* (x^2)^2。 + +> 当然 x ^ 5 可以等价于 (x ^ 2) ^ 2.5, 但是这不相当于直接调用了幂函数了么。对于整数,我们可以很方便的模拟,但是小数就不方便了。 + +我们的思路就是: + +- 将 n 地板除 2,我们不妨设结果为 a +- 那么 myPow(x, n) 就等价于 `myPow(x, a) * myPow(x, n - a)` + +很可惜这种算法也会超时,原因在于重复计算会比较多,你可以试一下缓存一下计算看能不能通过。 + +> 如果你搞不清楚有哪些重复计算,建议画图理解一下。 + +### 代码 + +语言支持: Python3 + +Python3 Code: + +```python +class Solution: + def myPow(self, x: float, n: int) -> float: + if n == 0: + return 1 + if n == 1: + return x + if n < 0: + return 1 / self.myPow(x, -n) + return self.myPow(x, n // 2) * self.myPow(x, n - n // 2) +``` + +## 解法二 - 优化递归 + +### 思路 + +上面的解法每次直接 myPow 都会调用两次自己。我们不从缓存计算角度,而是从减少这种调用的角度来优化。 + +我们考虑 myPow 只调用一次自身可以么? 没错,是可以的。 + +我们的思路就是: + +- 如果 n 是偶数,我们将 n 折半,底数变为 x^2 +- 如果 n 是奇数, 我们将 n 减去 1 ,底数不变,得到的结果再乘上底数 x + +这样终于可以 AC。 + +### 代码 + +语言支持: Python3 + +Python3 Code: + +```python +class Solution: + def myPow(self, x: float, n: int) -> float: + if n == 0: + return 1 + if n == 1: + return x + if n < 0: + return 1 / self.myPow(x, -n) + return self.myPow(x _ x, n // 2) if n % 2 == 0 else x _ self.myPow(x, n - 1) +``` + +## 解法三 - 位运算 + +### 思路 + +我们来从位(bit)的角度来看一下这道题。如果你经常看我的题解和文章的话,可能知道我之前写过几次相关的“从位的角度思考分治法”,比如 LeetCode [458.可怜的小猪](https://leetcode-cn.com/problems/poor-pigs/description/)。 + +以 x 的 10 次方举例。10 的 2 进制是 1010,然后用 2 进制转 10 进制的方法把它展成 2 的幂次的和。 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gbdseolzbmj30t802mjrk.jpg) + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gbdssrrsh6j30xp0u040e.jpg) + +因此我们的算法就是: + +- 不断的求解 x 的 2^0 次方,x 的 2^1 次方,x 的 2^2 次方等等。 +- 将 n 转化为二进制表示 +- 将 n 的二进制表示中`1的位置`pick 出来。比如 n 的第 i 位为 1,那么就将 x^i pick 出来。 +- 将 pick 出来的结果相乘 + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gbdtiky90rj30vq0hcab4.jpg) + +这里有两个问题: + +第一个问题是`似乎我们需要存储 x^i 以便后续相乘的时候用到`。实际上,我们并不需要这么做。我们可以采取一次遍历的方式来完成,具体看代码。 + +第二个问题是,如果我们从低位到高位计算的时候,我们如何判断最高位置是否为 1?我们需要一个 bitmask 来完成,这种算法我们甚至需要借助一个额外的变量。 然而我们可以 hack 一下,直接从高位到低位进行计算,这个时候我们只需要判断最后一位是否为 1 就可以了,这个就简单了,我们直接和 1 进行一次`与运算`即可。 + +### 代码 + +语言支持: Python3 + +Python3 Code: + +```python +class Solution: + def myPow(self, x: float, n: int) -> float: + if n < 0: + return 1 / self.myPow(x, -n) + res = 1 + while n: + if n & 1 == 1: + res *= x + x *= x + n >>= 1 + return res +``` + +## 关键点解析 + +- 超时分析 +- hashtable +- 数学分析 +- 位运算 +- 二进制转十进制 + +## 相关题目 + +- [458.可怜的小猪](https://leetcode-cn.com/problems/poor-pigs/description/) + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gbdrfn9n2wj30wn0u0dp2.jpg) diff --git a/spider/row-markdown/501.Find-Mode-in-Binary-Search-Tree.md b/spider/row-markdown/501.Find-Mode-in-Binary-Search-Tree.md new file mode 100644 index 0000000..ab93db0 --- /dev/null +++ b/spider/row-markdown/501.Find-Mode-in-Binary-Search-Tree.md @@ -0,0 +1,89 @@ +## Problem on Leetcode + +https://leetcode.com/problems/find-mode-in-binary-search-tree/ + +## Description + +Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred element) in the given BST. + +Assume a BST is defined as follows: + +- The left subtree of a node contains only nodes with keys less than or equal to the node's key. +- The right subtree of a node contains only nodes with keys greater than or equal to the node's key. +- Both the left and right subtrees must also be binary search trees. + +For example: +Given BST `[1,null,2,2]`, + +```bash + 1 + \ + 2 + / + 2 +``` + +return `[2]`. + +Note: If a tree has more than one mode, you can return them in any order. + +Follow up: Could you do that without using any extra space? (Assume that the implicit stack space incurred due to recursion does not count). + +## Ideas + +Basically, it needs traversing, counting and recording. `map` can be used to help us to do record and count. +For doing that without using any extra space, the property of BST will be used. For each node, the value of the left child is no greater than its value, while the value of right child is no less than the its value. So, when traversing each node, only the value of previous node is required to be compared with the value of current node for counting. +As the problem shown, an array of intergers will be returned. While the number of modes is unknown, using `ArrayList` to store all outputs is a good choice because `ArrayList` can be converted into array conveniently. + +## Codes + +Supported Language: `Java` + +- Java Code: + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + List list = new ArrayList<> (); + TreeNode preNode = null; + int max = 0, count = 0; + + public int[] findMode(TreeNode root) { + helper(root); + int[] res = new int[list.size()]; + for (int i=0; i max) { + list.clear(); + list.add(root.val); + max = count; + } else if (max == count) { + list.add(root.val); + } + preNode = root; + helper(root.right); + } +} +``` \ No newline at end of file diff --git a/spider/row-markdown/516.longest-palindromic-subsequence.md b/spider/row-markdown/516.longest-palindromic-subsequence.md new file mode 100644 index 0000000..17a0b20 --- /dev/null +++ b/spider/row-markdown/516.longest-palindromic-subsequence.md @@ -0,0 +1,96 @@ +## 题目地址 + +https://leetcode.com/problems/longest-palindromic-subsequence/description/ + +## 题目描述 + +``` +Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000. + +Example 1: +Input: + +"bbbab" +Output: +4 +One possible longest palindromic subsequence is "bbbb". +Example 2: +Input: + +"cbbd" +Output: +2 +One possible longest palindromic subsequence is "bb". +``` + +## 思路 + +这是一道最长回文的题目,要我们求出给定字符串的最大回文子序列。 + +![516.longest-palindromic-subsequence-1](../assets/problems/516.longest-palindromic-subsequence-1.png) + +解决这类问题的核心思想就是两个字“延伸”,具体来说 + +- 如果一个字符串是回文串,那么在它左右分别加上一个相同的字符,那么它一定还是一个回文串,因此`回文长度增加2` +- 如果一个字符串不是回文串,或者在回文串左右分别加不同的字符,得到的一定不是回文串,因此`回文长度不变,我们取[i][j-1]和[i+1][j]的较大值` + +![516.longest-palindromic-subsequence-2](../assets/problems/516.longest-palindromic-subsequence-2.png) + +事实上,上面的分析已经建立了大问题和小问题之间的关联, +基于此,我们可以建立动态规划模型。 + +我们可以用 dp[i][j] 表示 s 中从 i 到 j(包括 i 和 j)的回文序列长度, +状态转移方程只是将上面的描述转化为代码即可: + +```js +if (s[i] === s[j]) { + dp[i][j] = dp[i + 1][j - 1] + 2; +} else { + dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]); +} +``` + +base case 就是一个字符(轴对称点是本身) + +![516.longest-palindromic-subsequence-3](../assets/problems/516.longest-palindromic-subsequence-3.png) + +## 关键点 + +- ”延伸“(extend) + +## 代码 + +```js +/* + * @lc app=leetcode id=516 lang=javascript + * + * [516] Longest Palindromic Subsequence + */ +/** + * @param {string} s + * @return {number} + */ +var longestPalindromeSubseq = function(s) { + // bbbab 返回4 + // tag : dp + const dp = []; + + for (let i = s.length - 1; i >= 0; i--) { + dp[i] = Array(s.length).fill(0); + for (let j = i; j < s.length; j++) { + if (i - j === 0) dp[i][j] = 1; + else if (s[i] === s[j]) { + dp[i][j] = dp[i + 1][j - 1] + 2; + } else { + dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]); + } + } + } + + return dp[0][s.length - 1]; +}; +``` + +## 相关题目 + +- [5.longest-palindromic-substring](./5.longest-palindromic-substring.md) diff --git a/spider/row-markdown/518.coin-change-2.md b/spider/row-markdown/518.coin-change-2.md new file mode 100644 index 0000000..73298ed --- /dev/null +++ b/spider/row-markdown/518.coin-change-2.md @@ -0,0 +1,197 @@ +## 题目地址(518. 零钱兑换 II) + +https://leetcode-cn.com/problems/coin-change-2/description/ + +## 题目描述 + +给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 + +示例 1: + +输入: amount = 5, coins = [1, 2, 5] +输出: 4 +解释: 有四种方式可以凑成总金额: +5=5 +5=2+2+1 +5=2+1+1+1 +5=1+1+1+1+1 +示例 2: + +输入: amount = 3, coins = [2] +输出: 0 +解释: 只用面额 2 的硬币不能凑成总金额 3。 +示例 3: + +输入: amount = 10, coins = [10] +输出: 1 + +注意: + +你可以假设: + +0 <= amount (总金额) <= 5000 +1 <= coin (硬币面额) <= 5000 +硬币种类不超过 500 种 +结果符合 32 位符号整数 + +## 思路 + +这个题目和 coin-change 的思路比较类似。 + +我们还是按照 coin-change 的思路来, 如果将问题画出来大概是这样: + +![](https://tva1.sinaimg.cn/large/0082zybply1gcb7ezp3juj30fi0c1ta6.jpg) + +进一步我们可以对问题进行空间复杂度上的优化(这种写法比较难以理解,但是相对更省空间) + +![](https://tva1.sinaimg.cn/large/0082zybply1gcb7fc1qtvj30ix0ay0u8.jpg) + +> 这里用动图会更好理解, 有时间的话我会做一个动图出来, 现在大家脑补一下吧 + +## 关键点解析 + +- 动态规划 + +- 子问题 + +用 dp[i] 来表示组成 i 块钱,需要最少的硬币数,那么 + +1. 第 j 个硬币我可以选择不拿 这个时候, 组成数 = dp[i] + +2. 第 j 个硬币我可以选择拿 这个时候, 组成数 = dp[i - coins[j]] + dp[i] + +- 和01背包问题不同, 硬币是可以拿任意个,属于完全背包问题 + +- 对于每一个 dp[i] 我们都选择遍历一遍 coin, 不断更新 dp[i] + +eg: + +```js +if (amount === 0) return 1; + +const dp = [Array(amount + 1).fill(1)]; + +for (let i = 1; i < amount + 1; i++) { + dp[i] = Array(coins.length + 1).fill(0); + for (let j = 1; j < coins.length + 1; j++) { + // 从1开始可以简化运算 + if (i - coins[j - 1] >= 0) { + // 注意这里是coins[j -1]而不是coins[j] + dp[i][j] = dp[i][j - 1] + dp[i - coins[j - 1]][j]; // 由于可以重复使用硬币所以这里是j不是j-1 + } else { + dp[i][j] = dp[i][j - 1]; + } + } +} + +return dp[dp.length - 1][coins.length]; +``` + +- 当我们选择一维数组去解的时候,内外循环将会对结果造成影响 + +![](https://tva1.sinaimg.cn/large/0082zybply1gcb7fjfon6j30j00bddh2.jpg) + +eg: + +```js +// 这种答案是不对的。 +// 原因在于比如amount = 5, coins = [1,2,5] +// 这种算法会将[1,2,2] [2,1,2] [2, 2, 1] 算成不同的 + +if (amount === 0) return 1; + +const dp = [1].concat(Array(amount).fill(0)); + +for (let i = 1; i < amount + 1; i++) { + for (let j = 0; j < coins.length; j++) { + if (i - coins[j] >= 0) { + dp[i] = dp[i] + dp[i - coins[j]]; + } + } +} + +return dp[dp.length - 1]; + +// 正确的写法应该是内外循环调换一下, 具体可以看下方代码区 +``` + +## 代码 + + +代码支持:Python3,JavaScript: + + +JavaSCript Code: + +```js +/* + * @lc app=leetcode id=518 lang=javascript + * + * [518] Coin Change 2 + * + */ +/** + * @param {number} amount + * @param {number[]} coins + * @return {number} + */ +var change = function(amount, coins) { + if (amount === 0) return 1; + + const dp = [1].concat(Array(amount).fill(0)); + + for (let j = 0; j < coins.length; j++) { + for (let i = 1; i < amount + 1; i++) { + if (i - coins[j] >= 0) { + dp[i] = dp[i] + dp[i - coins[j]]; + } + } + } + + return dp[dp.length - 1]; +}; +``` + +Python Code: + +```python +class Solution: + def change(self, amount: int, coins: List[int]) -> int: + dp = [0] * (amount + 1) + dp[0] = 1 + + for j in range(len(coins)): + for i in range(1, amount + 1): + if i >= coins[j]: + dp[i] += dp[i - coins[j]] + + return dp[-1] +``` + +## 扩展 + +这是一道很简单描述的题目, 因此很多时候会被用到大公司的电面中。 + +相似问题: + +[322.coin-change](./322.coin-change.md) + +## 附录 + +Python 二维解法(不推荐,但是可以帮助理解): + +```python +class Solution: + def change(self, amount: int, coins: List[int]) -> int: + dp = [[0 for _ in range(len(coins) + 1)] for _ in range(amount + 1)] + for j in range(len(coins) + 1): + dp[0][j] = 1 + + for i in range(amount + 1): + for j in range(1, len(coins) + 1): + if i >= coins[j - 1]: + dp[i][j] = dp[i - coins[j - 1]][j] + dp[i][j - 1] + else: + dp[i][j] = dp[i][j - 1] + return dp[-1][-1] +``` diff --git a/spider/row-markdown/52.N-Queens-II.md b/spider/row-markdown/52.N-Queens-II.md new file mode 100644 index 0000000..e3175ea --- /dev/null +++ b/spider/row-markdown/52.N-Queens-II.md @@ -0,0 +1,83 @@ +## 题目地址 +https://leetcode-cn.com/problems/n-queens-ii + +## 题目描述 +``` +n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 + +给定一个整数 n,返回 n 皇后不同的解决方案的数量。 + +示例: + +输入: 4 +输出: 2 +解释: 4 皇后问题存在如下两个不同的解法。 + +[ + [".Q..",  // 解法 1 +  "...Q", +  "Q...", +  "..Q."], + + ["..Q.",  // 解法 2 +  "Q...", +  "...Q", +  ".Q.."] +] +``` + +## 思路 +使用深度优先搜索配合位运算,二进制为 1 代表不可放置,0 相反 + +利用如下位运算公式: + +- x & -x :得到最低位的 1 代表除最后一位 1 保留,其他位全部为 0 +- x & (x-1):清零最低位的 1 代表将最后一位 1 变成 0 +- x & ((1 << n) - 1):将 x 最高位至第 n 位(含)清零 + +## 关键点 + +- 位运算 +- DFS(深度优先搜索) + +## 代码 +* 语言支持:JS + +```js +/** + * @param {number} n + * @return {number} + * @param row 当前层 + * @param cols 列 + * @param pie 左斜线 + * @param na 右斜线 + */ +const totalNQueens = function (n) { + let res = 0; + const dfs = (n, row, cols, pie, na) => { + if (row >= n) { + res++; + return; + } + // 将所有能放置 Q 的位置由 0 变成 1,以便进行后续的位遍历 + // 也就是得到当前所有的空位 + let bits = (~(cols | pie | na)) & ((1 << n) - 1); + while (bits) { + // 取最低位的1 + let p = bits & -bits; + // 把P位置上放入皇后 + bits = bits & (bits - 1); + // row + 1 搜索下一行可能的位置 + // cols | p 目前所有放置皇后的列 + // (pie | p) << 1 和 (na | p) >> 1) 与已放置过皇后的位置 位于一条斜线上的位置 + dfs(n, row + 1, cols | p, (pie | p) << 1, (na | p) >> 1); + } + } + dfs(n, 0, 0, 0, 0); + return res; +}; +``` +***复杂度分析*** + +- 时间复杂度:O(N!) +- 空间复杂度:O(N) diff --git a/spider/row-markdown/53.maximum-sum-subarray-cn.md b/spider/row-markdown/53.maximum-sum-subarray-cn.md new file mode 100644 index 0000000..7f09c6c --- /dev/null +++ b/spider/row-markdown/53.maximum-sum-subarray-cn.md @@ -0,0 +1,369 @@ +## 题目地址 +https://leetcode.com/problems/maximum-subarray/ + +## 题目描述 +``` +Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. + +Example: + +Input: [-2,1,-3,4,-1,2,1,-5,4], +Output: 6 +Explanation: [4,-1,2,1] has the largest sum = 6. +Follow up: + +If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. +``` + +## 思路 + +这道题求解连续最大子序列和,以下从时间复杂度角度分析不同的解题思路。 + +#### 解法一 - 暴力解 (暴力出奇迹, 噢耶!) +一般情况下,先从暴力解分析,然后再进行一步步的优化。 + +**原始暴力解:**(超时) + +求子序列和,那么我们要知道子序列的首尾位置,然后计算首尾之间的序列和。用2个for循环可以枚举所有子序列的首尾位置。 +然后用一个for循环求解序列和。这里时间复杂度太高,`O(n^3)`. + +#### 复杂度分析 +- *时间复杂度:* `O(n^3) - n 是数组长度` +- *空间复杂度:* `O(1)` + +#### 解法二 - 前缀和 + 暴力解 +**优化暴力解:** (震惊,居然AC了) + +在暴力解的基础上,用前缀和我们可以优化到暴力解`O(n^2)`, 这里以空间换时间。 +这里可以使用原数组表示`prefixSum`, 省空间。 + +求序列和可以用前缀和(`prefixSum`) 来优化,给定子序列的首尾位置`(l, r),` +那么序列和 `subarraySum=prefixSum[r] - prefixSum[l - 1];` +用一个全局变量`maxSum`, 比较每次求解的子序列和,`maxSum = max(maxSum, subarraySum)`. + +#### 复杂度分析 +- *时间复杂度:* `O(n^2) - n 是数组长度` +- *空间复杂度:* `O(n) - prefixSum 数组空间为n` + +>如果用更改原数组表示前缀和数组,空间复杂度降为`O(1)` + +但是时间复杂度还是太高,还能不能更优化。答案是可以,前缀和还可以优化到`O(n)`. + +#### 解法三 - 优化前缀和 - from [**@lucifer**](https://github.com/azl397985856) + +我们定义函数` S(i)` ,它的功能是计算以 `0(包括 0)`开始加到 `i(包括 i)`的值。 + +那么 `S(j) - S(i - 1)` 就等于 从 `i` 开始(包括 i)加到 `j`(包括 j)的值。 + +我们进一步分析,实际上我们只需要遍历一次计算出所有的 `S(i)`, 其中 `i = 0,1,2....,n-1。` +然后我们再减去之前的` S(k)`,其中 `k = 0,1,i - 1`,中的最小值即可。 因此我们需要 +用一个变量来维护这个最小值,还需要一个变量维护最大值。 + +#### 复杂度分析 +- *时间复杂度:* `O(n) - n 是数组长度` +- *空间复杂度:* `O(1)` + +#### 解法四 - [分治法](https://www.wikiwand.com/zh-hans/%E5%88%86%E6%B2%BB%E6%B3%95) + +我们把数组`nums`以中间位置(`m`)分为左(`left`)右(`right`)两部分. 那么有, +`left = nums[0]...nums[m - 1]` 和 `right = nums[m + 1]...nums[n-1]` + +最大子序列和的位置有以下三种情况: +1. 考虑中间元素`nums[m]`, 跨越左右两部分,这里从中间元素开始,往左求出后缀最大,往右求出前缀最大, 保持连续性。 +2. 不考虑中间元素,最大子序列和出现在左半部分,递归求解左边部分最大子序列和 +3. 不考虑中间元素,最大子序列和出现在右半部分,递归求解右边部分最大子序列和 + +分别求出三种情况下最大子序列和,三者中最大值即为最大子序列和。 + +举例说明,如下图: +![](https://tva1.sinaimg.cn/large/0082zybply1gbv3hguiadj31400u044t.jpg) + +#### 复杂度分析 +- *时间复杂度:* `O(nlogn) - n 是数组长度` +- *空间复杂度:* `O(logn)` - 因为调用栈的深度最多是logn。 + +#### 解法五 - [动态规划](https://www.wikiwand.com/zh-hans/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92) +动态规划的难点在于找到状态转移方程, + +`dp[i] - 表示到当前位置 i 的最大子序列和` + +状态转移方程为: +`dp[i] = max(dp[i - 1] + nums[i], nums[i])` + +初始化:`dp[0] = nums[0]` + +从状态转移方程中,我们只关注前一个状态的值,所以不需要开一个数组记录位置所有子序列和,只需要两个变量, + +`currMaxSum - 累计最大和到当前位置i` + +`maxSum - 全局最大子序列和`: + +- `currMaxSum = max(currMaxSum + nums[i], nums[i])` +- `maxSum = max(currMaxSum, maxSum)` + +如图: +![](https://tva1.sinaimg.cn/large/0082zybply1gbv3hpz9tvj30pj0h2dh1.jpg) + +#### 复杂度分析 +- *时间复杂度:* `O(n) - n 是数组长度` +- *空间复杂度:* `O(1)` + +## 关键点分析 +1. 暴力解,列举所有组合子序列首尾位置的组合,求解最大的子序列和, 优化可以预先处理,得到前缀和 +2. 分治法,每次从中间位置把数组分为左右中三部分, 分别求出左右中(这里中是包括中间元素的子序列)最大和。对左右分别深度递归,三者中最大值即为当前最大子序列和。 +3. 动态规划,找到状态转移方程,求到当前位置最大和。 + +## 代码 (`Java/Python3/Javascript`) +#### 解法二 - 前缀和 + 暴力 +*Java code* +```java +class MaximumSubarrayPrefixSum { + public int maxSubArray(int[] nums) { + int len = nums.length; + int maxSum = Integer.MIN_VALUE; + int sum = 0; + for (int i = 0; i < len; i++) { + sum = 0; + for (int j = i; j < len; j++) { + sum += nums[j]; + maxSum = Math.max(maxSum, sum); + } + } + return maxSum; + } +} +``` +*Python3 code* `(TLE)` +```python +import sys +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + maxSum = -sys.maxsize + sum = 0 + for i in range(n): + sum = 0 + for j in range(i, n): + sum += nums[j] + maxSum = max(maxSum, sum) + + return maxSum +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) + +```javascript +function LSS(list) { + const len = list.length; + let max = -Number.MAX_VALUE; + let sum = 0; + for (let i = 0; i < len; i++) { + sum = 0; + for (let j = i; j < len; j++) { + sum += list[j]; + if (sum > max) { + max = sum; + } + } + } + + return max; +} +``` +#### 解法三 - 优化前缀和 +*Java code* +```java +class MaxSumSubarray { + public int maxSubArray3(int[] nums) { + int maxSum = nums[0]; + int sum = 0; + int minSum = 0; + for (int num : nums) { + // prefix Sum + sum += num; + // update maxSum + maxSum = Math.max(maxSum, sum - minSum); + // update minSum + minSum = Math.min(minSum, sum); + } + return maxSum; + } +} +``` +*Python3 code* +```python +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + maxSum = nums[0] + minSum = sum = 0 + for i in range(n): + sum += nums[i] + maxSum = max(maxSum, sum - minSum) + minSum = min(minSum, sum) + + return maxSum +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) +```javascript +function LSS(list) { + const len = list.length; + let max = list[0]; + let min = 0; + let sum = 0; + for (let i = 0; i < len; i++) { + sum += list[i]; + if (sum - min > max) max = sum - min; + if (sum < min) { + min = sum; + } + } + + return max; +} +``` + +#### 解法四 - 分治法 + +*Java code* +```java +class MaximumSubarrayDivideConquer { + public int maxSubArrayDividConquer(int[] nums) { + if (nums == null || nums.length == 0) return 0; + return helper(nums, 0, nums.length - 1); + } + private int helper(int[] nums, int l, int r) { + if (l > r) return Integer.MIN_VALUE; + int mid = (l + r) >>> 1; + int left = helper(nums, l, mid - 1); + int right = helper(nums, mid + 1, r); + int leftMaxSum = 0; + int sum = 0; + // left surfix maxSum start from index mid - 1 to l + for (int i = mid - 1; i >= l; i--) { + sum += nums[i]; + leftMaxSum = Math.max(leftMaxSum, sum); + } + int rightMaxSum = 0; + sum = 0; + // right prefix maxSum start from index mid + 1 to r + for (int i = mid + 1; i <= r; i++) { + sum += nums[i]; + rightMaxSum = Math.max(sum, rightMaxSum); + } + // max(left, right, crossSum) + return Math.max(leftMaxSum + rightMaxSum + nums[mid], Math.max(left, right)); + } +} +``` + +*Python3 code* + +```python +import sys +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + return self.helper(nums, 0, len(nums) - 1) + def helper(self, nums, l, r): + if l > r: + return -sys.maxsize + mid = (l + r) // 2 + left = self.helper(nums, l, mid - 1) + right = self.helper(nums, mid + 1, r) + left_suffix_max_sum = right_prefix_max_sum = 0 + sum = 0 + for i in reversed(range(l, mid)): + sum += nums[i] + left_suffix_max_sum = max(left_suffix_max_sum, sum) + sum = 0 + for i in range(mid + 1, r + 1): + sum += nums[i] + right_prefix_max_sum = max(right_prefix_max_sum, sum) + cross_max_sum = left_suffix_max_sum + right_prefix_max_sum + nums[mid] + return max(cross_max_sum, left, right) +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) + +```javascript +function helper(list, m, n) { + if (m === n) return list[m]; + let sum = 0; + let lmax = -Number.MAX_VALUE; + let rmax = -Number.MAX_VALUE; + const mid = ((n - m) >> 1) + m; + const l = helper(list, m, mid); + const r = helper(list, mid + 1, n); + for (let i = mid; i >= m; i--) { + sum += list[i]; + if (sum > lmax) lmax = sum; + } + + sum = 0; + + for (let i = mid + 1; i <= n; i++) { + sum += list[i]; + if (sum > rmax) rmax = sum; + } + + return Math.max(l, r, lmax + rmax); +} + +function LSS(list) { + return helper(list, 0, list.length - 1); +} +``` + +#### 解法五 - 动态规划 + +*Java code* + ```java +class MaximumSubarrayDP { + public int maxSubArray(int[] nums) { + int currMaxSum = nums[0]; + int maxSum = nums[0]; + for (int i = 1; i < nums.length; i++) { + currMaxSum = Math.max(currMaxSum + nums[i], nums[i]); + maxSum = Math.max(maxSum, currMaxSum); + } + return maxSum; + } +} +``` + +*Python3 code* +```python +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + max_sum_ending_curr_index = max_sum = nums[0] + for i in range(1, n): + max_sum_ending_curr_index = max(max_sum_ending_curr_index + nums[i], nums[i]) + max_sum = max(max_sum_ending_curr_index, max_sum) + + return max_sum +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) + +```javascript +function LSS(list) { + const len = list.length; + let max = list[0]; + for (let i = 1; i < len; i++) { + list[i] = Math.max(0, list[i - 1]) + list[i]; + if (list[i] > max) max = list[i]; + } + + return max; +} +``` + +## 扩展 +- 如果数组是二维数组,求最大子数组的和? +- 如果要求最大子序列的乘积? + +## 相似题 +- [Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/) +- [Longest Turbulent Subarray](https://leetcode.com/problems/longest-turbulent-subarray/) diff --git a/spider/row-markdown/53.maximum-sum-subarray-en.md b/spider/row-markdown/53.maximum-sum-subarray-en.md new file mode 100644 index 0000000..965f140 --- /dev/null +++ b/spider/row-markdown/53.maximum-sum-subarray-en.md @@ -0,0 +1,389 @@ +## Problem +https://leetcode.com/problems/maximum-subarray/ + +## Problem Description +``` +Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. + +Example: + +Input: [-2,1,-3,4,-1,2,1,-5,4], +Output: 6 +Explanation: [4,-1,2,1] has the largest sum = 6. +Follow up: + +If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. +``` + +## Solution + +Below will explain 4 different approaches to solve this problem. + +#### Solution #1 - Brute Force +Usually start from brute force when you don't have any idea, then step by step to optimize your solution. + +**Brute Force:**(TLE) + +Subarray sum, we then need to know subarray range [l, r], 2 `for` loop, list all possible subarrays, then 1 `for` loop to calculate current subarray sum, +using a global variable to keep track `maxSum`. This approach has very bad performance,time complexity is `O(n^3)`. + +#### Complexity Analysis +- *Time Complexity:* `O(n^3) - n array length` +- *Space Complexity:* `O(1)` + +#### Solution #2 - PrefixSum + Brute Force + +**Optimal brute force:** (AC) + +With brute force approach, we can precalculate prefixSum, so that no need to calculate subarray sum every time, time complexity can reduce to `O(n^2)` + +calculate prefixSum, for giving subarray range `[l,r]`, +current subarray sum: `subarraySum = prefixSum[r] - prefixSum[l - 1];` +global variable `maxSum`, compare every possible subarray sum to record max sum, `maxSum = max(maxSum, subarraySum)`. + + +#### Complexity Analysis +- *Time Complexity:* `O(n^2) - n array length` +- *Space Complexity:* `O(n) - prefixSum array length n` + +>If update original input array to represent prefix sum, then space will reduce to `O(1)` + +With this optimization, the time complexity is still too high, can we come up better optimization approach. + +yes, optimized prefix sum + +#### Solution #3 - optimized prefix sum - from [**@lucifer**](https://github.com/azl397985856) + +we define` S(i)` ,use to calculate sum from range `[0, i]`。 + +then `S(j) - S(i - 1)` is sum of range `[i, j]`. + +Here, we can get all `S[i] , (i = 0,1,2....,n-1)` with one loop array. +at the same time, we get min sum from `S[k], (k = 0,1,i-1)`, then + +`maxSum = max(maxSum, S[i] - minSum)`. + +Here we maintain two variables `minSum`, `maxSum`. + +#### Complexity Analysis +- *Time Complexity:* `O(n) - n array length` +- *Space Complexity:* `O(1)` + + +#### Solution #4 - [Divide and Conquer](https://www.wikiwand.com/en/Divide-and-conquer_algorithm) + +We partition array `nums` into two smaller arrays (`left` and `right`) from middle index `m`, + +Then we have two arrays: +- `left = nums[0]...nums[m - 1]` +- `right = nums[m + 1]...nums[n-1]` + +The maximum subarray sum can be either one of below three maximum sum: +1. Consider middle element `nums[m]`, Cross left and right subarray, the maximum sum is sum of + +maximum left array suffix sum - leftMaxSum, maximum right array prefix sum - rightMaxSum and middle element - nums[m] +-> `crossMaxSum = leftMaxSum + rightMaxSum + nums[m]` + +2. Dont' contain middle element `nums[m]`, maxSum is in `left`, left do recursive return max. +3. Don't contain middle element `nums[m]`, maxSum is in `right`, right do recursive return max. + +The maximum sum is `max(left, right, crossMaxSum)` + +For example, `nums=[-2,1,-3,4,-1,2,1,-5,4]` + +![maximum subarray sum divide conquer](../assets/problems/53.maximum-sum-subarray-divideconquer.png) + + +#### Complexity Analysis +- *Time Complexity:* `O(nlogn) - n input array length` +- *Space Complexity:* `O(1)` + +#### Solution #5 - [Dynamic Programing](https://www.wikiwand.com/zh-hans/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92) +Key points of DP is to find DP formula and initial state. Assume we have + +`dp[i] - maximum sum of subarray that ends at index i` + +DP formula: +`dp[i] = max(dp[i - 1] + nums[i], nums[i])` + +Initial state:`dp[0] = nums[0]` + +From above DP formula, notice only need to access its previous element at each step. In this case, we can use two variables, + +`currMaxSum - maximum sum of subarray that must end with current index i`. + +`maxSum - global maximum subarray sum` + +- `currMaxSum = max(currMaxSum + nums[i], nums[i]` +- `maxSum = max(currMaxSum, maxSum)` + +As below pic: +![maximum subarray sum dp](../assets/problems/53.maximum-sum-subarray-dp.png) + +#### Complexity Analysis +- *Time Complexity:* `O(n) - n array length` +- *Space Complexity:* `O(1)` + + +## Key Points +1. Brute force, list all possible subarray, calculate sum for each subarray (use prefixSum to optimize), return max. +2. Divide and Conquer, from middle index, divide array into left and right part. +Recursively get left maximum sum and right maximum sum, and include middle element maximum sum. +`return max(leftMaxSum, rightMaxSum, and crossMaxSum)`. +3. Dynamic Programming, find DP formula and initial state, and identify initial value, return maximum sum subarray。 + +## Code (`Java/Python3/Javascript`) +#### Solution #2 - PrefixSum + Brute Force +*Java code* +```java +class MaximumSubarrayPrefixSum { + public int maxSubArray(int[] nums) { + int len = nums.length; + int maxSum = Integer.MIN_VALUE; + int sum = 0; + for (int i = 0; i < len; i++) { + sum = 0; + for (int j = i; j < len; j++) { + sum += nums[j]; + maxSum = Math.max(maxSum, sum); + } + } + return maxSum; + } +} +``` +*Python3 code* `(TLE)` +```python +import sys +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + maxSum = -sys.maxsize + sum = 0 + for i in range(n): + sum = 0 + for j in range(i, n): + sum += nums[j] + maxSum = max(maxSum, sum) + + return maxSum +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) + +```javascript +function LSS(list) { + const len = list.length; + let max = -Number.MAX_VALUE; + let sum = 0; + for (let i = 0; i < len; i++) { + sum = 0; + for (let j = i; j < len; j++) { + sum += list[j]; + if (sum > max) { + max = sum; + } + } + } + + return max; +} +``` + +#### Solution #3 + +*Java code* +```java +class MaxSumSubarray { + public int maxSubArray3(int[] nums) { + int maxSum = nums[0]; + int sum = 0; + int minSum = 0; + for (int num : nums) { + // prefix Sum + sum += num; + // update maxSum + maxSum = Math.max(maxSum, sum - minSum); + // update minSum + minSum = Math.min(minSum, sum); + } + return maxSum; + } +} +``` +*Python3 code* +```python +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + maxSum = nums[0] + minSum = sum = 0 + for i in range(n): + sum += nums[i] + maxSum = max(maxSum, sum - minSum) + minSum = min(minSum, sum) + + return maxSum +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) +```javascript +function LSS(list) { + const len = list.length; + let max = list[0]; + let min = 0; + let sum = 0; + for (let i = 0; i < len; i++) { + sum += list[i]; + if (sum - min > max) max = sum - min; + if (sum < min) { + min = sum; + } + } + + return max; +} +``` + +#### Solution #4 - Divide and Conquer + +*Java code* +```java +class MaximumSubarrayDivideConquer { + public int maxSubArrayDividConquer(int[] nums) { + if (nums == null || nums.length == 0) return 0; + return helper(nums, 0, nums.length - 1); + } + private int helper(int[] nums, int l, int r) { + if (l > r) return Integer.MIN_VALUE; + int mid = (l + r) >>> 1; + int left = helper(nums, l, mid - 1); + int right = helper(nums, mid + 1, r); + int leftMaxSum = 0; + int sum = 0; + // left surfix maxSum start from index mid - 1 to l + for (int i = mid - 1; i >= l; i--) { + sum += nums[i]; + leftMaxSum = Math.max(leftMaxSum, sum); + } + int rightMaxSum = 0; + sum = 0; + // right prefix maxSum start from index mid + 1 to r + for (int i = mid + 1; i <= r; i++) { + sum += nums[i]; + rightMaxSum = Math.max(sum, rightMaxSum); + } + // max(left, right, crossSum) + return Math.max(leftMaxSum + rightMaxSum + nums[mid], Math.max(left, right)); + } +} +``` + +*Python3 code* + +```python +import sys +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + return self.helper(nums, 0, len(nums) - 1) + def helper(self, nums, l, r): + if l > r: + return -sys.maxsize + mid = (l + r) // 2 + left = self.helper(nums, l, mid - 1) + right = self.helper(nums, mid + 1, r) + left_suffix_max_sum = right_prefix_max_sum = 0 + sum = 0 + for i in reversed(range(l, mid)): + sum += nums[i] + left_suffix_max_sum = max(left_suffix_max_sum, sum) + sum = 0 + for i in range(mid + 1, r + 1): + sum += nums[i] + right_prefix_max_sum = max(right_prefix_max_sum, sum) + cross_max_sum = left_suffix_max_sum + right_prefix_max_sum + nums[mid] + return max(cross_max_sum, left, right) +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) + +```javascript +function helper(list, m, n) { + if (m === n) return list[m]; + let sum = 0; + let lmax = -Number.MAX_VALUE; + let rmax = -Number.MAX_VALUE; + const mid = ((n - m) >> 1) + m; + const l = helper(list, m, mid); + const r = helper(list, mid + 1, n); + for (let i = mid; i >= m; i--) { + sum += list[i]; + if (sum > lmax) lmax = sum; + } + + sum = 0; + + for (let i = mid + 1; i <= n; i++) { + sum += list[i]; + if (sum > rmax) rmax = sum; + } + + return Math.max(l, r, lmax + rmax); +} + +function LSS(list) { + return helper(list, 0, list.length - 1); +} +``` +#### Solution #5 - Dynamic Programming + + *Java code* + ```java +class MaximumSubarrayDP { + public int maxSubArray(int[] nums) { + int currMaxSum = nums[0]; + int maxSum = nums[0]; + for (int i = 1; i < nums.length; i++) { + currMaxSum = Math.max(currMaxSum + nums[i], nums[i]); + maxSum = Math.max(maxSum, currMaxSum); + } + return maxSum; + } +} +``` + +*Python3 code* +```python +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + n = len(nums) + max_sum_ending_curr_index = max_sum = nums[0] + for i in range(1, n): + max_sum_ending_curr_index = max(max_sum_ending_curr_index + nums[i], nums[i]) + max_sum = max(max_sum_ending_curr_index, max_sum) + + return max_sum +``` + +*Javascript code* from [**@lucifer**](https://github.com/azl397985856) + +```javascript +function LSS(list) { + const len = list.length; + let max = list[0]; + for (let i = 1; i < len; i++) { + list[i] = Math.max(0, list[i - 1]) + list[i]; + if (list[i] > max) max = list[i]; + } + + return max; +} +``` + +## Follow Up +- When given M*N matrix, how to calculate maximum submatrix sum? +- When given array, return maximum product subarray? compare with maximum sum subarray, what is the difference? + +## Similar Questions +- [Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/) +- [Longest Turbulent Subarray](https://leetcode.com/problems/longest-turbulent-subarray/) diff --git a/spider/row-markdown/547.friend-circles-en.md b/spider/row-markdown/547.friend-circles-en.md new file mode 100644 index 0000000..47e6377 --- /dev/null +++ b/spider/row-markdown/547.friend-circles-en.md @@ -0,0 +1,231 @@ +## Problem +https://leetcode.com/problems/friend-circles/ + +## Problem Description +``` +There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. +For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. +And we defined a friend circle is a group of students who are direct or indirect friends. + +Given a N*N matrix M representing the friend relationship between students in the class. +If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. +And you have to output the total number of friend circles among all the students. + +Example 1: + +Input: +[[1,1,0], + [1,1,0], + [0,0,1]] +Output: 2 +Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. +The 2nd student himself is in a friend circle. So return 2. +Example 2: + +Input: +[[1,1,0], + [1,1,1], + [0,1,1]] +Output: 1 +Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends, +so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1. +Note: + +N is in range [1,200]. +M[i][i] = 1 for all students. +If M[i][j] = 1, then M[j][i] = 1. +``` + +## Solution + +We can view a given matrix as [Adjacency Matrix](https://www.wikiwand.com/en/Adjacency_matrix) of a graph. In this case, +this problem become to find number of connected components in a undirected graph. + +For example, how to transfer Adjacency Matrix into a graph problem. As below pic: + +![adjacency matrix](../assets/problems/547.friend-circle-1.png) + +Connected components in a graph problem usually can be solved using *DFS*, *BFS*, *Union-Find*. + +Below we will explain details on each approach. + +#### Approach #1. DFS +1. Do DFS starting from every node, use `visited` array to mark visited node. +2. For each node DFS, visit all its directly connected nodes. +3. For each node DFS, DFS search will search all connected nodes, thus we count one DFS as one connected component. + +as below pic show *DFS* traverse process: + +![friend circle DFS](../assets/problems/547.friend-circle-dfs.png) + +#### Complexity Analysis +- *Time Complexity:* `O(n*n) - n is the number of students, traverse n*n matrix` +- *Space Complexity:* `O(n) - visited array of size n` + +#### Approach #2. BFS (Level traverse) + +1. Start from one node, visit all its directly connected nodes, or visit all nodes in the same level. +2. Use `visited` array to mark already visited nodes. +3. Increment count when start with a new node. + +as below pic show *BFS* (Level traverse) traverse process: + +![friend circle BFS](../assets/problems/547.friend-circle-bfs.png) + +#### Complexity Analysis +- *Time Complexity:* `O(n*n) - n is the number of students, traverse n*n matrix` +- *Space Complexity:* `O(n) - queue and visited array of size n` + +#### Approach #3. [Union-Find](https://snowan.github.io/post/union-find/) + +Determine number of connected components, Union Find is good algorithm to use. + +Use `parent` array, for every node, all its directly connected nodes will be `union`, +so that two connected nodes have the same parent. After traversal all nodes, we just need to calculate +the number of different values in `parent` array. + +For each union, total count minus 1, after traversal and union all connected nodes, simply +return counts. + +Here use **weighted-union-find** to reduce `union` and `find` methods operation time. + +To know more details and implementations, see further reading lists. + +as below Union-Find approach process: + +![friend circle union-find](../assets/problems/547.friend-circle-uf.png) + +> **Note:** here using weighted-union-find to avoid Union and Find take `O(n)` in the worst case. + +#### Complexity Analysis +- *Time Complexity:* `O(n*n*log(n) - traverse n*n matrix, weighted-union-find, union and find takes log(n) time complexity.` +- *Space Complexity:* `O(n) - parent and rank array of size n` + +## Key Points +1. Transform Adjacency matrix into Graph +2. Notice that it actually is to find number of connected components problem. +3. Connected components problem approaches (DFS, BFS, Union-Find). + +## Code (`Java`) +*Java code* - **DFS** +```java +class FindCirclesDFS { + public int findCircleNumDFS(int[][] M) { + if (M == null || M.length == 0 || M[0].length == 0) return 0; + int n = M.length; + int numCircles = 0; + boolean[] visited = new boolean[n]; + for (int i = 0; i < n; i++) { + if (!visited[i]) { + dfs(M, i, visited, n); + numCircles++; + } + } + return numCircles; + } + + private void dfs(int[][] M, int i, boolean[] visited, int n) { + for (int j = 0; j < n; j++) { + if (M[i][j] == 1 && !visited[j]) { + visited[j] = true; + dfs(M, j, visited, n); + } + } + } +} +``` + +*Java code* - **BFS** +```java +class FindCircleBFS { + public int findCircleNumBFS(int[][] M) { + if (M == null || M.length == 0) return 0; + int numCircle = 0; + int n = M.length; + boolean[] visited = new boolean[n]; + Queue queue = new LinkedList<>(); + for (int i = 0; i < n; i++) { + // already visited, skip + if (visited[i]) continue; + queue.add(i); + while (!queue.isEmpty()) { + int curr = queue.poll(); + visited[curr] = true; + for (int j = 0; j < n; j++) { + if (M[curr][j] == 1 && !visited[j]) { + queue.add(j); + } + } + } + numCircle++; + } + return numCircle; + } +} +``` + +*Java code* - **Union-Find** +```java +class FindCircleUF { + public int findCircleNumUF(int[][] M) { + if (M == null || M.length == 0 || M[0].length == 0) return 0; + int n = M.length; + UnionFind uf = new UnionFind(n); + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + // union friends + if (M[i][j] == 1) { + uf.union(i, j); + } + } + } + return uf.count; + } +} + +class UnionFind { + int count; + int[] parent; + int[] rank; + + public UnionFind(int n) { + count = n; + parent = new int[n]; + rank = new int[n]; + for (int i = 0; i < n; i++) { + parent[i] = i; + } + } + + public int find(int a) { + return parent[a] == a ? a : find(parent[a]); + } + + public void union(int a, int b) { + int rootA = find(a); + int rootB = find(b); + if (rootA == rootB) return; + if (rank[rootA] <= rank[rootB]) { + parent[rootA] = rootB; + rank[rootB] += rank[rootA]; + } else { + parent[rootB] = rootA; + rank[rootA] += rank[rootB]; + } + count--; + } + + public int count() { + return count; + } +} +``` + +## References (Further reading) +1. [Adjacency Matrix Wiki](https://www.wikiwand.com/en/Adjacency_matrix) +2. [Union-Find Wiki](https://www.wikiwand.com/en/Disjoint-set_data_structure) +3. [Algorighms 4 union-find](https://www.cs.princeton.edu/~rs/AlgsDS07/01UnionFind.pdf) + +## Similar Problems +1. [323. Number of Connected Components in an Undirected Graph](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/) +2. [1101. The Earliest Moment When Everyone Become Friends](https://leetcode.com/problems/the-earliest-moment-when-everyone-become-friends/) diff --git a/spider/row-markdown/547.friend-circles.md b/spider/row-markdown/547.friend-circles.md new file mode 100644 index 0000000..a334ee5 --- /dev/null +++ b/spider/row-markdown/547.friend-circles.md @@ -0,0 +1,86 @@ +## 题目地址(547. 朋友圈) + +https://leetcode-cn.com/problems/friend-circles/ + +## 题目描述 + +班上有  N  名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B  的朋友,B 是 C  的朋友,那么我们可以认为 A 也是 C  的朋友。所谓的朋友圈,是指所有朋友的集合。 + +给定一个  N \* N  的矩阵  M,表示班级中学生之间的朋友关系。如果 M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。 + +示例 1: + +输入: +[[1,1,0], +[1,1,0], +[0,0,1]] +输出: 2 +说明:已知学生 0 和学生 1 互为朋友,他们在一个朋友圈。 +第 2 个学生自己在一个朋友圈。所以返回 2。 +示例 2: + +输入: +[[1,1,0], +[1,1,1], +[0,1,1]] +输出: 1 +说明:已知学生 0 和学生 1 互为朋友,学生 1 和学生 2 互为朋友,所以学生 0 和学生 2 也是朋友,所以他们三个在一个朋友圈,返回 1。 +注意: + +N 在[1,200]的范围内。 +对于所有学生,有 M[i][i] = 1。 +如果有 M[i][j] = 1,则有 M[j][i] = 1。 + +## 思路 + +并查集有一个功能是可以轻松计算出连通分量,然而本题的朋友圈的个数,本质上就是连通分量的个数,因此用并查集可以完美解决。 + +为了简单更加清晰,我将并查集模板代码单尽量独拿出来。 + +## 代码 + +`find`, `union`, `connected` 都是典型的模板方法。 懂的同学可能也发现了,我没有做路径压缩,这直接导致 find union connected 的时间复杂度最差的情况退化到 $O(N)$。 + +当然优化也不难,我们只需要给每一个顶层元素设置一个 size 用来表示连通分量的大小,这样 union 的时候我们将小的拼接到大的上即可。 另外 find 的时候我们甚至可以路径压缩,将树高限定到常数,这样时间复杂度可以降低到 $O(1)$。 + +```python +class UF: + parent = {} + cnt = 0 + def __init__(self, M): + n = len(M) + for i in range(n): + self.parent[i] = i + self.cnt += 1 + + def find(self, x): + while x != self.parent[x]: + x = self.parent[x] + return x + def union(self, p, q): + if self.connected(p, q): return + self.parent[self.find(p)] = self.find(q) + self.cnt -= 1 + def connected(self, p, q): + return self.find(p) == self.find(q) + +class Solution: + def findCircleNum(self, M: List[List[int]]) -> int: + n = len(M) + uf = UF(M) + for i in range(n): + for j in range(i): + if M[i][j] == 1: + uf.union(i, j) + return uf.cnt + +``` + +**复杂度分析** + +- 时间复杂度:平均 $O(logN)$,最坏的情况是 $O(N)$ +- 空间复杂度:我们使用了 parent, 因此空间复杂度为 $O(N)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/55.jump-game.md b/spider/row-markdown/55.jump-game.md new file mode 100644 index 0000000..db822c3 --- /dev/null +++ b/spider/row-markdown/55.jump-game.md @@ -0,0 +1,78 @@ + +## 题目地址 +https://leetcode.com/problems/jump-game/description/ + +## 题目描述 +``` +Given an array of non-negative integers, you are initially positioned at the first index of the array. + +Each element in the array represents your maximum jump length at that position. + +Determine if you are able to reach the last index. + +Example 1: + +Input: [2,3,1,1,4] +Output: true +Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index. +Example 2: + +Input: [3,2,1,0,4] +Output: false +Explanation: You will always arrive at index 3 no matter what. Its maximum + jump length is 0, which makes it impossible to reach the last index. + +``` + +## 思路 + +这道题目是一道典型的`贪心`类型题目。思路就是用一个变量记录当前能够到达的最大的索引,我们逐个遍历数组中的元素去更新这个索引。变量完成判断这个索引是否大于数组下表即可。 +## 关键点解析 + +- 建模 (记录和更新当前位置能够到达的最大的索引即可) + +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/** + * @param {number[]} nums + * @return {boolean} + */ +var canJump = function(nums) { + let max = 0; // 能够走到的数组下标 + + for(let i = 0; i < nums.length; i++) { + if (max < i) return false; // 当前这一步都走不到,后面更走不到了 + max = Math.max(nums[i] + i, max); + } + + return max >= nums.length - 1 +}; + +``` +Python3 Code: +```Python +class Solution: + def canJump(self, nums: List[int]) -> bool: + """思路同上""" + _max = 0 + _len = len(nums) + for i in range(_len-1): + if _max < i: + return False + _max = max(_max, nums[i] + i) + # 下面这个判断可有可无,但提交的时候数据会好看点 + if _max >= _len - 1: + return True + return _max >= _len - 1 +``` + +***复杂度分析*** +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(1)$ + +更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 diff --git a/spider/row-markdown/56.merge-intervals.md b/spider/row-markdown/56.merge-intervals.md new file mode 100644 index 0000000..9acfdab --- /dev/null +++ b/spider/row-markdown/56.merge-intervals.md @@ -0,0 +1,100 @@ + +## 题目地址 +https://leetcode.com/problems/merge-intervals/description/ + +## 题目描述 +``` +Given a collection of intervals, merge all overlapping intervals. + +Example 1: + +Input: [[1,3],[2,6],[8,10],[15,18]] +Output: [[1,6],[8,10],[15,18]] +Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6]. +Example 2: + +Input: [[1,4],[4,5]] +Output: [[1,5]] +Explanation: Intervals [1,4] and [4,5] are considered overlapping. +NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature. + +``` + +## 思路 + +- 先对数组进行排序,排序的依据就是每一项的第一个元素的大小。 +- 然后我们对数组进行遍历,遍历的时候两两运算(具体运算逻辑见下) +- 判断是否相交,如果不相交,则跳过 +- 如果相交,则合并两项 +## 关键点解析 + +- 对数组进行排序简化操作 +- 如果不排序,需要借助一些hack,这里不介绍了 + +## 代码 + +* 语言支持: Javascript,Python3 + +```js + + +/* + * @lc app=leetcode id=56 lang=javascript + * + * [56] Merge Intervals + */ +/** + * @param {number[][]} intervals + * @return {number[][]} + */ + +function intersected(a, b) { + if (a[0] > b[1] || a[1] < b[0]) return false; + return true; +} + +function mergeTwo(a, b) { + return [Math.min(a[0], b[0]), Math.max(a[1], b[1])]; +} +var merge = function(intervals) { + // 这种算法需要先排序 + intervals.sort((a, b) => a[0] - b[0]); + for (let i = 0; i < intervals.length - 1; i++) { + const cur = intervals[i]; + const next = intervals[i + 1]; + + if (intersected(cur, next)) { + intervals[i] = undefined; + intervals[i + 1] = mergeTwo(cur, next); + } + } + return intervals.filter(q => q); +}; +``` +Python3 Code: +```Python +class Solution: + def merge(self, intervals: List[List[int]]) -> List[List[int]]: + """先排序,后合并""" + if len(intervals) <= 1: + return intervals + + # 排序 + def get_first(a_list): + return a_list[0] + intervals.sort(key=get_first) + + # 合并 + res = [intervals[0]] + for i in range(1, len(intervals)): + if intervals[i][0] <= res[-1][1]: + res[-1] = [res[-1][0], max(res[-1][1], intervals[i][1])] + else: + res.append(intervals[i]) + + return res +``` + +***复杂度分析*** +- 时间复杂度:由于采用了排序,因此复杂度大概为 $O(NlogN)$ +- 空间复杂度:$O(N)$ diff --git a/spider/row-markdown/560.subarray-sum-equals-k.en.md b/spider/row-markdown/560.subarray-sum-equals-k.en.md new file mode 100644 index 0000000..c368848 --- /dev/null +++ b/spider/row-markdown/560.subarray-sum-equals-k.en.md @@ -0,0 +1,146 @@ +## Problem + +https://leetcode.com/problems/subarray-sum-equals-k/description/ + +## Problem Description + +``` +Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k. + +Example 1: +Input:nums = [1,1,1], k = 2 +Output: 2 +Note: +The length of the array is in range [1, 20,000]. +The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7]. +``` + +## Solution + +The simplest method is `Brute-force`. Consider every possible subarray, find the sum of the elements of each of those subarrays and check for the equality of the sum with `k`. Whenever the sum equals `k`, we increment the `count`. Time Complexity is O(n^2). Implementation is as followed. + +```py +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + cnt, n = 0, len(nums) + for i in range(n): + for j in range(i, n): + if (sum(nums[i:j + 1]) == k): cnt += 1 + return cnt +``` + +If we implement the `sum()` method on our own, we get the time of complexity O(n^3). + +```py +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + cnt, n = 0, len(nums) + for i in range(n): + for j in range(i, n): + sum = 0 + for x in range(i, j + 1): + sum += nums[x] + if (sum == k): cnt += 1 + return cnt +``` + +At first glance I think "maybe it can be solved by using the sliding window technique". However, I give that thought up when I find out that the given array may contain negative numbers, which makes it more complicated to expand or narrow the range of the sliding window. Then I think about using a prefix sum array, with which we can obtain the sum of the elements between every two indices by subtracting the prefix sum corresponding to the two indices. It sounds feasible, so I implement it as followed. + +```py +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + cnt, n = 0, len(nums) + pre = [0] * (n + 1) + for i in range(1, n + 1): + pre[i] = pre[i - 1] + nums[i - 1] + for i in range(1, n + 1): + for j in range(i, n + 1): + if (pre[j] - pre[i - 1] == k): cnt += 1 + return cnt +``` + +Actually, there is a more clever way to do this. Instead of using a prefix sum array, we use a hashmap to reduce the time complexity to O(n). + +Algorithm: + +- We make use of a hashmap to store the cumulative sum `acc` and the number of times the same sum occurs. We use `acc` as the `key` of the hashmap and the number of times the same `acc` occurs as the `value`. + +- We traverse over the given array and keep on finding the cumulative sum `acc`. Every time we encounter a new `acc` we add a new entry to the hashmap. If the same `acc` occurs, we increment the count corresponding to that `acc` in the hashmap. If `acc` equals `k`, obviously `count` should be incremented. If `acc - k` got, we should increment `account` by `hashmap[acc - k]`. + +- The idea behind this is that if the cumulative sum upto two indices is the same, the sum of the elements between those two indices is zero. So if the cumulative sum upto two indices is at a different of `k`, the sum of the elements between those indices is `k`. As `hashmap[acc - k]` keeps track of the number of times a subarray with sum `acc - k` has occured upto the current index, by doing a simple substraction `acc - (acc - k)` we can see that `hashmap[acc - k]` actually also determines the number of times a subarray with sum `k` has occured upto the current index. So we increment the `count` by `hashmap[acc - k]`. + +Here is a graph demonstrating this algorithm in the case of `nums = [1,2,3,3,0,3,4,2], k = 6`. + +![560.subarray-sum-equals-k](../assets/problems/560.subarray-sum-equals-k.jpg) + +When we are at `nums[3]`, the hashmap is as the picture shows, and `count` is 2 by this time. `[1, 2, 3]` accounts for one of the count, and `[3, 3]` accounts for another. + +The subarray `[3, 3]` is obtained from `hashmap[acc - k]`, which is `hashmap[9 - 6]`. + +## Key Points + +- Prefix sum array +- Make use of a hashmap to track cumulative sum and avoid repetitive calculation. + +## Code (`JavaScript/Python`) + +*JavaScript Code* +```js +/* + * @lc app=leetcode id=560 lang=javascript + * + * [560] Subarray Sum Equals K + */ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var subarraySum = function (nums, k) { + const hashmap = {}; + let acc = 0; + let count = 0; + + for (let i = 0; i < nums.length; i++) { + acc += nums[i]; + + if (acc === k) count++; + + if (hashmap[acc - k] !== void 0) { + count += hashmap[acc - k]; + } + + if (hashmap[acc] === void 0) { + hashmap[acc] = 1; + } else { + hashmap[acc] += 1; + } + } + + return count; +}; +``` + +*Python Cose* + +```py +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + d = {} + acc = count = 0 + for num in nums: + acc += num + if acc == k: + count += 1 + if acc - k in d: + count += d[acc-k] + if acc in d: + d[acc] += 1 + else: + d[acc] = 1 + return count +``` + +## Extension + +There is a similar but a bit more complicated problem. Link to the problem: [437.path-sum-iii](https://github.com/azl397985856/leetcode/blob/master/problems/437.path-sum-iii.md)(Chinese). diff --git a/spider/row-markdown/560.subarray-sum-equals-k.md b/spider/row-markdown/560.subarray-sum-equals-k.md new file mode 100644 index 0000000..bc4df1d --- /dev/null +++ b/spider/row-markdown/560.subarray-sum-equals-k.md @@ -0,0 +1,135 @@ +## 题目地址 + +https://leetcode.com/problems/subarray-sum-equals-k/description/ + +## 题目描述 + +``` +Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k. + +Example 1: +Input:nums = [1,1,1], k = 2 +Output: 2 +Note: +The length of the array is in range [1, 20,000]. +The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7]. + +``` + +## 思路 + +符合直觉的做法是暴力求解所有的子数组,然后分别计算和,如果等于 k,count 就+1.这种做法的时间复杂度为 O(n^2),代码如下: + +```python +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + cnt, n = 0, len(nums) + for i in range(n): + sum = 0 + for j in range(i, n): + sum += nums[j] + if (sum == k): cnt += 1 + return cnt +``` + +实际上刚开始看到这题目的时候,我想“是否可以用滑动窗口解决?”。但是很快我就放弃了,因为看了下数组中项的取值范围有负数,这样我们扩张或者收缩窗口就比较复杂。第二个想法是前缀和,保存一个数组的前缀和,然后利用差分法得出任意区间段的和,这种想法是可行的,代码如下: + +```python +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + cnt, n = 0, len(nums) + pre = [0] * (n + 1) + for i in range(1, n + 1): + pre[i] = pre[i - 1] + nums[i - 1] + for i in range(1, n + 1): + for j in range(i, n + 1): + if (pre[j] - pre[i - 1] == k): cnt += 1 + return cnt +``` + +这里有一种更加巧妙的方法,可以不使用前缀和数组,而是使用 hashmap 来简化时间复杂度,这种算法的时间复杂度可以达到 O(n). + +具体算法: + +- 维护一个 hashmap,hashmap 的 key 为累加值 acc,value 为累加值 acc 出现的次数。 +- 迭代数组,然后不断更新 acc 和 hashmap,如果 acc 等于 k,那么很明显应该+1. 如果 hashmap[acc - k] 存在,我们就把它加到结果中去即可。 + +语言比较难以解释,我画了一个图来演示 nums = [1,2,3,3,0,3,4,2], k = 6 的情况。 + +![560.subarray-sum-equals-k](../assets/problems/560.subarray-sum-equals-k.jpg) + +如图,当访问到 nums[3]的时候,hashmap 如图所示,这个时候 count 为 2. +其中之一是[1,2,3],这个好理解。还有一个是[3,3]. + +这个[3,3]正是我们通过 hashmap[acc - k]即 hashmap[9 - 6]得到的。 + +## 关键点解析 + +- 前缀和 +- 可以利用 hashmap 记录和的累加值来避免重复计算 + +## 代码 + +- 语言支持:JS, Python + +Javascript Code: + +```js +/* + * @lc app=leetcode id=560 lang=javascript + * + * [560] Subarray Sum Equals K + */ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var subarraySum = function (nums, k) { + const hashmap = {}; + let acc = 0; + let count = 0; + + for (let i = 0; i < nums.length; i++) { + acc += nums[i]; + + if (acc === k) count++; + + if (hashmap[acc - k] !== void 0) { + count += hashmap[acc - k]; + } + + if (hashmap[acc] === void 0) { + hashmap[acc] = 1; + } else { + hashmap[acc] += 1; + } + } + + return count; +}; +``` + +Python Code: + +```python +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + d = {} + acc = count = 0 + for num in nums: + acc += num + if acc == k: + count += 1 + if acc - k in d: + count += d[acc-k] + if acc in d: + d[acc] += 1 + else: + d[acc] = 1 + return count +``` + +## 扩展 + +这是一道类似的题目,但是会稍微复杂一点, 题目地址: [437.path-sum-iii](./437.path-sum-iii.md) diff --git a/spider/row-markdown/575.distribute-candies.md b/spider/row-markdown/575.distribute-candies.md new file mode 100644 index 0000000..7920275 --- /dev/null +++ b/spider/row-markdown/575.distribute-candies.md @@ -0,0 +1,71 @@ +## 题目地址 +https://leetcode.com/problems/distribute-candies/description/ + +## 题目描述 + +``` +Given an integer array with even length, where different numbers in this array represent different kinds of candies. Each number means one candy of the corresponding kind. You need to distribute these candies equally in number to brother and sister. Return the maximum number of kinds of candies the sister could gain. +Example 1: +Input: candies = [1,1,2,2,3,3] +Output: 3 +Explanation: +There are three different kinds of candies (1, 2 and 3), and two candies for each kind. +Optimal distribution: The sister has candies [1,2,3] and the brother has candies [1,2,3], too. +The sister has three different kinds of candies. +Example 2: +Input: candies = [1,1,2,3] +Output: 2 +Explanation: For example, the sister has candies [2,3] and the brother has candies [1,1]. +The sister has two different kinds of candies, the brother has only one kind of candies. +Note: + +The length of the given array is in range [2, 10,000], and will be even. +The number in given array is in range [-100,000, 100,000]. +``` + +## 思路 +由于糖果是偶数,并且我们只需要做到两个人糖果数量一样即可。 + +考虑两种情况: + +![575.distribute-candies](../assets/problems/575.distribute-candies.png) + +- 如果糖果种类大于n / 2(糖果种类数为n),妹妹最多可以获得的糖果种类应该是`n / 2`(因为妹妹只有n / 2个糖). +- 糖果种类数小于n / 2, 妹妹能够得到的糖果种类可以是糖果的种类数(糖果种类本身就这么多). + +因此我们发现,妹妹能够获得的糖果种类的制约因素其实是糖果种类数。 + +## 关键点解析 + +- 这是一道逻辑题目,因此如果逻辑分析清楚了,代码是自然而然的 + + +## 代码 + +* 语言支持:JS, Python + +Javascript Code: + +```js +/* + * @lc app=leetcode id=575 lang=javascript + * + * [575] Distribute Candies + */ +/** + * @param {number[]} candies + * @return {number} + */ +var distributeCandies = function(candies) { + const count = new Set(candies); + return Math.min(count.size, candies.length >> 1); +}; +``` + +Python Code: + +```python +class Solution: + def distributeCandies(self, candies: List[int]) -> int: + return min(len(set(candies)), len(candies) >> 1) +``` diff --git a/spider/row-markdown/60.permutation-sequence.md b/spider/row-markdown/60.permutation-sequence.md new file mode 100644 index 0000000..c6706f0 --- /dev/null +++ b/spider/row-markdown/60.permutation-sequence.md @@ -0,0 +1,96 @@ +## 题目地址(第 K 个排列) + +https://leetcode-cn.com/problems/permutation-sequence/description/ + +## 标签 + +- 数学 +- 回溯 +- 找规律 +- factorial + +## 公司 + +Twitter + +## 题目描述 + +``` +给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。 + +按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: + +"123" +"132" +"213" +"231" +"312" +"321" +给定 n 和 k,返回第 k 个排列。 + +说明: + +给定 n 的范围是 [1, 9]。 +给定 k 的范围是[1, n!]。 +示例 1: + +输入: n = 3, k = 3 +输出: "213" +示例 2: + +输入: n = 4, k = 9 +输出: "2314" +``` + +## 思路 + +LeetCode 上关于排列的题目截止目前(2020-01-06)主要有三种类型: + +- 生成全排列 +- 生成下一个排列 +- 生成第 k 个排列(我们的题目就是这种) + +我们不可能求出所有的排列,然后找到第 k 个之后返回。因为排列的组合是 N!,要比 2^n 还要高很多,非常有可能超时。我们必须使用一些巧妙的方法。 + +我们以题目中的 n= 3 k = 3 为例: + +- "123" +- "132" +- "213" +- "231" +- "312" +- "321" + +可以看出 1xx,2xx 和 3xx 都有两个,如果你知道阶乘的话,实际上是 2!个。 我们想要找的是第 3 个。那么我们可以直接跳到 2 开头,我们排除了以 1 开头的排列,问题缩小了,我们将 2 加入到结果集,我们不断重复上述的逻辑,知道结果集的元素为 n 即可。 + +## 关键点解析 + +- 找规律 +- 排列组合 + +## 代码 + +- 语言支持: Python3 + +```python +import math + +class Solution: + def getPermutation(self, n: int, k: int) -> str: + res = "" + candidates = [str(i) for i in range(1, n + 1)] + + while n != 0: + facto = math.factorial(n - 1) + # i 表示前面被我们排除的组数,也就是k所在的组的下标 + # k // facto 是不行的, 比如在 k % facto == 0的情况下就会有问题 + i = math.ceil(k / facto) - 1 + # 我们把candidates[i]加入到结果集,然后将其弹出candidates(不能重复使用元素) + res += candidates[i] + candidates.pop(i) + # k 缩小了 facto * i + k -= facto * i + # 每次迭代我们实际上就处理了一个元素,n 减去 1,当n == 0 说明全部处理完成,我们退出循环 + n -= 1 + return res +``` diff --git a/spider/row-markdown/609.find-duplicate-file-in-system.md b/spider/row-markdown/609.find-duplicate-file-in-system.md new file mode 100644 index 0000000..8b3ab50 --- /dev/null +++ b/spider/row-markdown/609.find-duplicate-file-in-system.md @@ -0,0 +1,180 @@ + +## 题目地址 +https://leetcode.com/problems/find-duplicate-file-in-system/description/ + +## 题目描述 + +``` +Given a list of directory info including directory path, and all the files with contents in this directory, you need to find out all the groups of duplicate files in the file system in terms of their paths. + +A group of duplicate files consists of at least two files that have exactly the same content. + +A single directory info string in the input list has the following format: + +"root/d1/d2/.../dm f1.txt(f1_content) f2.txt(f2_content) ... fn.txt(fn_content)" + +It means there are n files (f1.txt, f2.txt ... fn.txt with content f1_content, f2_content ... fn_content, respectively) in directory root/d1/d2/.../dm. Note that n >= 1 and m >= 0. If m = 0, it means the directory is just the root directory. + +The output is a list of group of duplicate file paths. For each group, it contains all the file paths of the files that have the same content. A file path is a string that has the following format: + +"directory_path/file_name.txt" + +Example 1: + +Input: +["root/a 1.txt(abcd) 2.txt(efgh)", "root/c 3.txt(abcd)", "root/c/d 4.txt(efgh)", "root 4.txt(efgh)"] +Output: +[["root/a/2.txt","root/c/d/4.txt","root/4.txt"],["root/a/1.txt","root/c/3.txt"]] + + +Note: + +No order is required for the final output. +You may assume the directory name, file name and file content only has letters and digits, and the length of file content is in the range of [1,50]. +The number of files given is in the range of [1,20000]. +You may assume no files or directories share the same name in the same directory. +You may assume each given directory info represents a unique directory. Directory path and file info are separated by a single blank space. + + +Follow-up beyond contest: + +1. Imagine you are given a real file system, how will you search files? DFS or BFS? + +2. If the file content is very large (GB level), how will you modify your solution? + +3. If you can only read the file by 1kb each time, how will you modify your solution? + +4. What is the time complexity of your modified solution? What is the most time-consuming part and memory consuming part of it? How to optimize? + +5. How to make sure the duplicated files you find are not false positive? + +``` + +## 思路 +思路就是hashtable去存储,key为文件内容,value为fullfilename, +遍历一遍去填充hashtable, 最后将hashtable中的值打印出来即可。 + +> 当且仅当有重复内容,我们才打印,因此我们需要过滤一下, 类似 filter(q => q.length >= 2) +## 关键点解析 + +- hashtable + +## 代码 +```js + + +/* + * @lc app=leetcode id=609 lang=javascript + * + * [609] Find Duplicate File in System + * + * https://leetcode.com/problems/find-duplicate-file-in-system/description/ + * + * algorithms + * Medium (54.21%) + * Total Accepted: 24.1K + * Total Submissions: 44.2K + * Testcase Example: '["root/a 1.txt(abcd) 2.txt(efgh)","root/c 3.txt(abcd)","root/c/d 4.txt(efgh)","root 4.txt(efgh)"]' + * + * Given a list of directory info including directory path, and all the files + * with contents in this directory, you need to find out all the groups of + * duplicate files in the file system in terms of their paths. + * + * A group of duplicate files consists of at least two files that have exactly + * the same content. + * + * A single directory info string in the input list has the following format: + * + * "root/d1/d2/.../dm f1.txt(f1_content) f2.txt(f2_content) ... + * fn.txt(fn_content)" + * + * It means there are n files (f1.txt, f2.txt ... fn.txt with content + * f1_content, f2_content ... fn_content, respectively) in directory + * root/d1/d2/.../dm. Note that n >= 1 and m >= 0. If m = 0, it means the + * directory is just the root directory. + * + * The output is a list of group of duplicate file paths. For each group, it + * contains all the file paths of the files that have the same content. A file + * path is a string that has the following format: + * + * "directory_path/file_name.txt" + * + * Example 1: + * + * + * Input: + * ["root/a 1.txt(abcd) 2.txt(efgh)", "root/c 3.txt(abcd)", "root/c/d + * 4.txt(efgh)", "root 4.txt(efgh)"] + * Output: + * + * [["root/a/2.txt","root/c/d/4.txt","root/4.txt"],["root/a/1.txt","root/c/3.txt"]] + * + * + * + * + * Note: + * + * + * No order is required for the final output. + * You may assume the directory name, file name and file content only has + * letters and digits, and the length of file content is in the range of + * [1,50]. + * The number of files given is in the range of [1,20000]. + * You may assume no files or directories share the same name in the same + * directory. + * You may assume each given directory info represents a unique directory. + * Directory path and file info are separated by a single blank space. + * + * + * + * Follow-up beyond contest: + * + * + * Imagine you are given a real file system, how will you search files? DFS or + * BFS? + * If the file content is very large (GB level), how will you modify your + * solution? + * If you can only read the file by 1kb each time, how will you modify your + * solution? + * What is the time complexity of your modified solution? What is the most + * time-consuming part and memory consuming part of it? How to optimize? + * How to make sure the duplicated files you find are not false positive? + * + * + */ +/** + * @param {string[]} paths + * @return {string[][]} + */ +var findDuplicate = function(paths) { + const hashmap = {}; + + for (let path of paths) { + const [folder, ...files] = path.split(" "); + for (let file of files) { + const lpi = file.indexOf("("); + const rpi = file.lastIndexOf(")"); + const filename = file.slice(0, lpi); + const content = file.slice(lpi, rpi); + const fullname = `${folder}/${filename}`; + if (!hashmap[content]) hashmap[content] = []; + hashmap[content].push(fullname); + } + } + + return Object.values(hashmap).filter(q => q.length >= 2); +}; +``` + +## 扩展 +leetcode官方给的扩展我觉得就很有意思,虽然很`老套`, 这里还是列一下好了,大家可以作为思考题来思考一下。 + +1. Imagine you are given a real file system, how will you search files? DFS or BFS? + +2. If the file content is very large (GB level), how will you modify your solution? + +3. If you can only read the file by 1kb each time, how will you modify your solution? + +4. What is the time complexity of your modified solution? What is the most time-consuming part and memory consuming part of it? How to optimize? + +5. How to make sure the duplicated files you find are not false positive? diff --git a/spider/row-markdown/62.unique-paths.md b/spider/row-markdown/62.unique-paths.md new file mode 100644 index 0000000..8076e82 --- /dev/null +++ b/spider/row-markdown/62.unique-paths.md @@ -0,0 +1,171 @@ + +## 题目地址 +https://leetcode.com/problems/unique-paths/description/ + +## 题目描述 +``` + +A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). + +The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). + +How many possible unique paths are there? +``` +![](https://tva1.sinaimg.cn/large/0082zybply1gca6k99jmoj30b4053mxa.jpg) + +``` +Above is a 7 x 3 grid. How many possible unique paths are there? + +Note: m and n will be at most 100. + +Example 1: + +Input: m = 3, n = 2 +Output: 3 +Explanation: +From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: +1. Right -> Right -> Down +2. Right -> Down -> Right +3. Down -> Right -> Right +Example 2: + +Input: m = 7, n = 3 +Output: 28 +``` + +## 思路 + +这是一道典型的适合使用动态规划解决的题目,它和爬楼梯等都属于动态规划中最简单的题目,因此也经常会被用于面试之中。 + +读完题目你就能想到动态规划的话,建立模型并解决恐怕不是难事。其实我们很容易看出,由于机器人只能右移动和下移动, +因此第[i, j]个格子的总数应该等于[i - 1, j] + [i, j -1], 因为第[i,j]个格子一定是从左边或者上面移动过来的。 + +![](https://tva1.sinaimg.cn/large/0082zybply1gca6kj31o4j304z07gt8u.jpg) + +代码大概是: + +JS Code: + +```js + const dp = []; + for (let i = 0; i < m + 1; i++) { + dp[i] = []; + dp[i][0] = 0; + } + for (let i = 0; i < n + 1; i++) { + dp[0][i] = 0; + } + for (let i = 1; i < m + 1; i++) { + for(let j = 1; j < n + 1; j++) { + dp[i][j] = j === 1 ? 1 : dp[i - 1][j] + dp[i][j - 1]; // 转移方程 + } + } + + return dp[m][n]; + +``` + +Python Code: + +```python +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + d = [[1] * n for _ in range(m)] + + for col in range(1, m): + for row in range(1, n): + d[col][row] = d[col - 1][row] + d[col][row - 1] + + return d[m - 1][n - 1] + ``` + + **复杂度分析** + + - 时间复杂度:$O(M * N)$ + - 空间复杂度:$O(M * N)$ + +由于dp[i][j] 只依赖于左边的元素和上面的元素,因此空间复杂度可以进一步优化, 优化到O(n). + +![](https://tva1.sinaimg.cn/large/0082zybply1gca6l63ax7j30gr09w3zp.jpg) + +具体代码请查看代码区。 + + +当然你也可以使用记忆化递归的方式来进行,由于递归深度的原因,性能比上面的方法差不少: + +> 直接暴力递归的话会超时。 + +Python3 Code: +```python +class Solution: + visited = dict() + + def uniquePaths(self, m: int, n: int) -> int: + if (m, n) in self.visited: + return self.visited[(m, n)] + if m == 1 or n == 1: + return 1 + cnt = self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1) + self.visited[(m, n)] = cnt + return cnt + ``` + +## 关键点 + +- 记忆化递归 +- 基本动态规划问题 +- 空间复杂度可以进一步优化到O(n), 这会是一个考点 +## 代码 + +代码支持JavaScript,Python3 + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=62 lang=javascript + * + * [62] Unique Paths + * + * https://leetcode.com/problems/unique-paths/description/ + */ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +var uniquePaths = function(m, n) { + const dp = Array(n).fill(1); + + for(let i = 1; i < m; i++) { + for(let j = 1; j < n; j++) { + dp[j] = dp[j] + dp[j - 1]; + } + } + + return dp[n - 1]; +}; +``` + +Python3 Code: + +```python +class Solution: + + def uniquePaths(self, m: int, n: int) -> int: + dp = [1] * n + for _ in range(1, m): + for j in range(1, n): + dp[j] += dp[j - 1] + return dp[n - 1] +``` + + **复杂度分析** + + - 时间复杂度:$O(M * N)$ + - 空间复杂度:$O(N)$ + + ## 扩展 + + 你可以做到比$O(M * N)$更快,比$O(N)$更省内存的算法么?这里有一份[资料](https://leetcode.com/articles/unique-paths/)可供参考。 + > 提示: 考虑数学 diff --git a/spider/row-markdown/721.accounts-merge.md b/spider/row-markdown/721.accounts-merge.md new file mode 100644 index 0000000..cb9ac89 --- /dev/null +++ b/spider/row-markdown/721.accounts-merge.md @@ -0,0 +1,78 @@ +## 题目地址(721. 账户合并) + +https://leetcode-cn.com/problems/accounts-merge/ + +## 题目描述 + +给定一个列表 accounts,每个元素 accounts[i]  是一个字符串列表,其中第一个元素 accounts[i][0]  是   名称 (name),其余元素是 emails 表示该帐户的邮箱地址。 + +现在,我们想合并这些帐户。如果两个帐户都有一些共同的邮件地址,则两个帐户必定属于同一个人。请注意,即使两个帐户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的帐户,但其所有帐户都具有相同的名称。 + +合并帐户后,按以下格式返回帐户:每个帐户的第一个元素是名称,其余元素是按顺序排列的邮箱地址。accounts 本身可以以任意顺序返回。 + +例子 1: + +Input: +accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]] +Output: [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]] +Explanation: +第一个和第三个 John 是同一个人,因为他们有共同的电子邮件 "johnsmith@mail.com"。 +第二个 John 和 Mary 是不同的人,因为他们的电子邮件地址没有被其他帐户使用。 +我们可以以任何顺序返回这些列表,例如答案[['Mary','mary@mail.com'],['John','johnnybravo@mail.com'], +['John','john00@mail.com','john_newyork@mail.com','johnsmith@mail.com']]仍然会被接受。 + +注意: + +accounts 的长度将在[1,1000]的范围内。 +accounts[i]的长度将在[1,10]的范围内。 +accounts[i][j]的长度将在[1,30]的范围内。 + +## 思路 + +我们抛开 name 不管。 我们只根据 email 建立并查集即可。这样一个连通分量中的 email 就是一个人,我们在用一个 hashtable 记录 email 和 name 的映射,将其输出即可。 + +> 如果题目不要求我们输出 name,我们自然根本不需要 hashtable 做映射 + +## 代码 + +`find`, `union`, `connected` 都是典型的模板方法。 懂的同学可能也发现了,我没有做路径压缩,这直接导致 find union connected 的时间复杂度最差的情况退化到 $O(N)$。 + +当然优化也不难,我们只需要给每一个顶层元素设置一个 size 用来表示连通分量的大小,这样 union 的时候我们将小的拼接到大的上即可。 另外 find 的时候我们甚至可以路径压缩,将树高限定到常数,这样时间复杂度可以降低到 $O(1)$。 + +```python +class UF: + def __init__(self): + self.parent = {} + + def find(self, x): + self.parent.setdefault(x, x) + while x != self.parent[x]: + x = self.parent[x] + return x + def union(self, p, q): + self.parent[self.find(p)] = self.find(q) + + +class Solution: + def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]: + uf = UF() + email_to_name = {} + res = collections.defaultdict(list) + for account in accounts: + for i in range(1, len(account)): + email_to_name[account[i]] = account[0] + if i < len(account) - 1:uf.union(account[i], account[i + 1]) + for email in email_to_name: + res[uf.find(email)].append(email) + + return [[email_to_name[value[0]]] + sorted(value) for value in res.values()] +``` + +**复杂度分析** + +- 时间复杂度:平均 $O(logN)$,最坏的情况是 $O(N)$ +- 空间复杂度:我们使用了 parent, 因此空间复杂度为 $O(N)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/73.set-matrix-zeroes.md b/spider/row-markdown/73.set-matrix-zeroes.md new file mode 100644 index 0000000..6509cec --- /dev/null +++ b/spider/row-markdown/73.set-matrix-zeroes.md @@ -0,0 +1,253 @@ +## 题目地址 + +https://leetcode.com/problems/set-matrix-zeroes/description/ + +## 题目描述 + +``` +Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place. + +Example 1: + +Input: +[ + [1,1,1], + [1,0,1], + [1,1,1] +] +Output: +[ + [1,0,1], + [0,0,0], + [1,0,1] +] +Example 2: + +Input: +[ + [0,1,2,0], + [3,4,5,2], + [1,3,1,5] +] +Output: +[ + [0,0,0,0], + [0,4,5,0], + [0,3,1,0] +] +Follow up: + +- A straight forward solution using O(mn) space is probably a bad idea. +- A simple improvement uses O(m + n) space, but still not the best solution. +- Could you devise a constant space solution? + +``` + +## 思路 + +符合直觉的想法是,使用一个 m + n 的数组来表示每一行每一列是否”全部是 0“, +先遍历一遍去构建这样的 m + n 数组,然后根据这个 m + n 数组去修改 matrix 即可。 + +![73.set-matrix-zeroes-1](../assets/problems/73.set-matrix-zeroes-1.png) + +这样的时间复杂度 O(m \* n), 空间复杂度 O(m + n). + +代码如下: + +```js +var setZeroes = function(matrix) { + if (matrix.length === 0) return matrix; + const m = matrix.length; + const n = matrix[0].length; + const zeroes = Array(m + n).fill(false); + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const item = matrix[i][j]; + + if (item === 0) { + zeroes[i] = true; + zeroes[m + j] = true; + } + } + } + + for (let i = 0; i < m; i++) { + if (zeroes[i]) { + matrix[i] = Array(n).fill(0); + } + } + + for (let i = 0; i < n; i++) { + if (zeroes[m + i]) { + for (let j = 0; j < m; j++) { + matrix[j][i] = 0; + } + } + } + + return matrix; +}; +``` + +但是这道题目还有一个follow up, 要求使用O(1)的时间复杂度。因此上述的方法就不行了。 +但是我们要怎么去存取这些信息(哪一行哪一列应该全部为0)呢? + +一种思路是使用第一行第一列的数据来代替上述的zeros数组。 这样我们就不必借助额外的存储空间,空间复杂度自然就是O(1)了。 + +由于我们不能先操作第一行和第一列, 因此我们需要记录下”第一行和第一列是否全是0“这样的一个数据,最后根据这个信息去 +修改第一行和第一列。 + +具体步骤如下: + +- 记录下”第一行和第一列是否全是0“这样的一个数据 +- 遍历除了第一行和第一列之外的所有的数据,如果是0,那就更新第一行第一列中对应的元素为0 +> 你可以把第一行第一列看成我们上面那种解法使用的m + n 数组。 +- 根据第一行第一列的数据,更新matrix +- 最后根据我们最开始记录的”第一行和第一列是否全是0“去更新第一行和第一列即可 + +![73.set-matrix-zeroes-2](../assets/problems/73.set-matrix-zeroes-2.png) + + +## 关键点 +- 使用第一行和第一列来替代我们m + n 数组 +- 先记录下”第一行和第一列是否全是0“这样的一个数据,否则会因为后续对第一行第一列的更新造成数据丢失 +- 最后更新第一行第一列 +## 代码 + +* 语言支持:JS,Python3 + +```js +/* + * @lc app=leetcode id=73 lang=javascript + * + * [73] Set Matrix Zeroes + */ +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ +var setZeroes = function(matrix) { + if (matrix.length === 0) return matrix; + const m = matrix.length; + const n = matrix[0].length; + + // 时间复杂度 O(m * n), 空间复杂度 O(1) + let firstRow = false; // 第一行是否应该全部为0 + let firstCol = false; // 第一列是否应该全部为0 + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const item = matrix[i][j]; + if (item === 0) { + if (i === 0) { + firstRow = true; + } + if (j === 0) { + firstCol = true; + } + matrix[0][j] = 0; + matrix[i][0] = 0; + } + } + } + + for (let i = 1; i < m; i++) { + for (let j = 1; j < n; j++) { + const item = matrix[i][j]; + if (matrix[0][j] == 0 || matrix[i][0] == 0) { + matrix[i][j] = 0; + } + } + } + + // 最后处理第一行和第一列 + + if (firstRow) { + for (let i = 0; i < n; i++) { + matrix[0][i] = 0; + } + } + + if (firstCol) { + for (let i = 0; i < m; i++) { + matrix[i][0] = 0; + } + } + + return matrix; +}; +``` +Python3 Code: + +直接修改第一行和第一列为0的解法: +```python +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + def setRowZeros(matrix: List[List[int]], i:int) -> None: + C = len(matrix[0]) + matrix[i] = [0] * C + + def setColZeros(matrix: List[List[int]], j:int) -> None: + R = len(matrix) + for i in range(R): + matrix[i][j] = 0 + + isCol = False + R = len(matrix) + C = len(matrix[0]) + + for i in range(R): + if matrix[i][0] == 0: + isCol = True + for j in range(1, C): + if matrix[i][j] == 0: + matrix[i][0] = 0 + matrix[0][j] = 0 + for j in range(1, C): + if matrix[0][j] == 0: + setColZeros(matrix, j) + + for i in range(R): + if matrix[i][0] == 0: + setRowZeros(matrix, i) + + if isCol: + setColZeros(matrix, 0) + +``` + +另一种方法是用一个特殊符合标记需要改变的结果,只要这个特殊标记不在我们的题目数据范围(0和1)即可,这里用None。 +```python +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + """ + 这题要解决的问题是,必须有个地方记录判断结果,但又不能影响下一步的判断条件; + 直接改为0的话,会影响下一步的判断条件; + 因此,有一种思路是先改为None,最后再将None改为0; + 从条件上看,如果可以将第一行、第二行作为记录空间,那么,用None应该也不算违背题目条件; + """ + rows = len(matrix) + cols = len(matrix[0]) + # 遍历矩阵,用None记录要改的地方,注意如果是0则要保留,否则会影响下一步判断 + for r in range(rows): + for c in range(cols): + if matrix[r][c] is not None and matrix[r][c] == 0: + # 改值 + for i in range(rows): + matrix[i][c] = None if matrix[i][c] != 0 else 0 + for j in range(cols): + matrix[r][j] = None if matrix[r][j] != 0 else 0 + # 再次遍历,将None改为0 + for r in range(rows): + for c in range(cols): + if matrix[r][c] is None: + matrix[r][c] = 0 +``` + +## 扩展 + +为什么选择第一行第一列,选择其他行和列可以么?为什么? diff --git a/spider/row-markdown/75.sort-colors.md b/spider/row-markdown/75.sort-colors.md new file mode 100644 index 0000000..1282b9e --- /dev/null +++ b/spider/row-markdown/75.sort-colors.md @@ -0,0 +1,73 @@ +## 题目地址 +https://leetcode.com/problems/sort-colors/description/ + +## 题目描述 +Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue. + +Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. + +Note: You are not suppose to use the library's sort function for this problem. + +Example: + +Input: [2,0,2,1,1,0] +Output: [0,0,1,1,2,2] +Follow up: + +A rather straight forward solution is a two-pass algorithm using counting sort. +First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. +Could you come up with a one-pass algorithm using only constant space? + +## 思路 +这个问题是典型的荷兰国旗问题 (https://en.wikipedia.org/wiki/Dutch_national_flag_problem)。 因为我们可以将红白蓝三色小球想象成条状物,有序排列后正好组成荷兰国旗。 + +有两种解决思路。 + +## 解法一 +- 遍历数组,统计红白蓝三色球(0,1,2)的个数 +- 根据红白蓝三色球(0,1,2)的个数重排数组 + +这种思路的时间复杂度:$O(n)$,需要遍历数组两次。 + +## 解法二 + +我们可以把数组分成三部分,前部(全部是0),中部(全部是1)和后部(全部是2)三个部分。每一个元素(红白蓝分别对应0、1、2)必属于其中之一。将前部和后部各排在数组的前边和后边,中部自然就排好了。 + +我们用三个指针,设置两个指针begin指向前部的末尾的下一个元素(刚开始默认前部无0,所以指向第一个位置),end指向后部开头的前一个位置(刚开始默认后部无2,所以指向最后一个位置),然后设置一个遍历指针current,从头开始进行遍历。 + +这种思路的时间复杂度也是$O(n)$, 只需要遍历数组一次。 + +### 关键点解析 + + +- 荷兰国旗问题 +- counting sort + +### 代码 + +代码支持: Python3 + +Python3 Code: + +``` python +class Solution: + def sortColors(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + p0 = cur = 0 + p2 = len(nums) - 1 + + while cur <= p2: + if nums[cur] == 0: + nums[cur], nums[p0] = nums[p0], nums[cur] + p0 += 1 + cur += 1 + elif nums[cur] == 2: + nums[cur], nums[p2] = nums[p2], nums[cur] + p2 -= 1 + else: + cur += 1 +``` + + diff --git a/spider/row-markdown/78.subsets-en.md b/spider/row-markdown/78.subsets-en.md new file mode 100644 index 0000000..e8242d9 --- /dev/null +++ b/spider/row-markdown/78.subsets-en.md @@ -0,0 +1,136 @@ +## Problem Link +https://leetcode.com/problems/subsets/description/ + +## Description +``` +Given a set of distinct integers, nums, return all possible subsets (the power set). + +Note: The solution set must not contain duplicate subsets. + +Example: + +Input: nums = [1,2,3] +Output: +[ + [3], + [1], + [2], + [1,2,3], + [1,3], + [2,3], + [1,2], + [] +] + + +``` + +## Solution + +Since this problem is seeking `Subset` not `Extreme Value`, dynamic programming is not an ideal solution. Other approaches should be taken into our consideration. + +Actually, there is a general approach to solve problems similar to this one -- backtracking. Given a [Code Template](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)) here, it demonstrates how backtracking works with varieties of problems. Apart from current one, many problems can be solved by such a general approach. For more details, please check the `Related Problems` section below. + +Given a picture as followed, let's start with problem-solving ideas of this general solution. + +![backtrack](../assets/problems/backtrack.png) + +See Code Template details below. + +## Key Points + +- Backtrack Approach +- Backtrack Code Template/ Formula + + +## Code + +* Supported Language:JS,C++ + +JavaScript Code: +```js + +/* + * @lc app=leetcode id=78 lang=javascript + * + * [78] Subsets + * + * https://leetcode.com/problems/subsets/description/ + * + * algorithms + * Medium (51.19%) + * Total Accepted: 351.6K + * Total Submissions: 674.8K + * Testcase Example: '[1,2,3]' + * + * Given a set of distinct integers, nums, return all possible subsets (the + * power set). + * + * Note: The solution set must not contain duplicate subsets. + * + * Example: + * + * + * Input: nums = [1,2,3] + * Output: + * [ + * ⁠ [3], + * [1], + * [2], + * [1,2,3], + * [1,3], + * [2,3], + * [1,2], + * [] + * ] + * + */ +function backtrack(list, tempList, nums, start) { + list.push([...tempList]); + for(let i = start; i < nums.length; i++) { + tempList.push(nums[i]); + backtrack(list, tempList, nums, i + 1); + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var subsets = function(nums) { + const list = []; + backtrack(list, [], nums, 0); + return list; +}; +``` +C++ Code: +```C++ +class Solution { +public: + vector> subsets(vector& nums) { + auto ret = vector>(); + auto tmp = vector(); + backtrack(ret, tmp, nums, 0); + return ret; + } + + void backtrack(vector>& list, vector& tempList, vector& nums, int start) { + list.push_back(tempList); + for (auto i = start; i < nums.size(); ++i) { + tempList.push_back(nums[i]); + backtrack(list, tempList, nums, i + 1); + tempList.pop_back(); + } + } +}; +``` + +## Related Problems + +- [39.combination-sum](./39.combination-sum.md)(chinese) +- [40.combination-sum-ii](./40.combination-sum-ii.md)(chinese) +- [46.permutations](./46.permutations.md)(chinese) +- [47.permutations-ii](./47.permutations-ii.md)(chinese) +- [90.subsets-ii](./90.subsets-ii-en.md) +- [113.path-sum-ii](./113.path-sum-ii.md)(chinese) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md)(chinese) diff --git a/spider/row-markdown/78.subsets.md b/spider/row-markdown/78.subsets.md new file mode 100644 index 0000000..00a8864 --- /dev/null +++ b/spider/row-markdown/78.subsets.md @@ -0,0 +1,142 @@ + +## 题目地址 +https://leetcode.com/problems/subsets/description/ + +## 题目描述 +``` +Given a set of distinct integers, nums, return all possible subsets (the power set). + +Note: The solution set must not contain duplicate subsets. + +Example: + +Input: nums = [1,2,3] +Output: +[ + [3], + [1], + [2], + [1,2,3], + [1,3], + [2,3], + [1,2], + [] +] + + +``` + +## 思路 + +这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。 + +这种题目其实有一个通用的解法,就是回溯法。 +网上也有大神给出了这种回溯法解题的 +[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。 +除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。 + +我们先来看下通用解法的解题思路,我画了一张图: + +![backtrack](../assets/problems/backtrack.png) + +通用写法的具体代码见下方代码区。 + +## 关键点解析 + +- 回溯法 +- backtrack 解题公式 + + +## 代码 + +* 语言支持:JS,C++ + +JavaScript Code: +```js + +/* + * @lc app=leetcode id=78 lang=javascript + * + * [78] Subsets + * + * https://leetcode.com/problems/subsets/description/ + * + * algorithms + * Medium (51.19%) + * Total Accepted: 351.6K + * Total Submissions: 674.8K + * Testcase Example: '[1,2,3]' + * + * Given a set of distinct integers, nums, return all possible subsets (the + * power set). + * + * Note: The solution set must not contain duplicate subsets. + * + * Example: + * + * + * Input: nums = [1,2,3] + * Output: + * [ + * ⁠ [3], + * [1], + * [2], + * [1,2,3], + * [1,3], + * [2,3], + * [1,2], + * [] + * ] + * + */ +function backtrack(list, tempList, nums, start) { + list.push([...tempList]); + for(let i = start; i < nums.length; i++) { + tempList.push(nums[i]); + backtrack(list, tempList, nums, i + 1); + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var subsets = function(nums) { + const list = []; + backtrack(list, [], nums, 0); + return list; +}; +``` +C++ Code: +```C++ +class Solution { +public: + vector> subsets(vector& nums) { + auto ret = vector>(); + auto tmp = vector(); + backtrack(ret, tmp, nums, 0); + return ret; + } + + void backtrack(vector>& list, vector& tempList, vector& nums, int start) { + list.push_back(tempList); + for (auto i = start; i < nums.size(); ++i) { + tempList.push_back(nums[i]); + backtrack(list, tempList, nums, i + 1); + tempList.pop_back(); + } + } +}; +``` + +## 相关题目 + +- [39.combination-sum](./39.combination-sum.md) +- [40.combination-sum-ii](./40.combination-sum-ii.md) +- [46.permutations](./46.permutations.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [90.subsets-ii](./90.subsets-ii.md) +- [113.path-sum-ii](./113.path-sum-ii.md) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md) + + diff --git a/spider/row-markdown/79.word-search-en.md b/spider/row-markdown/79.word-search-en.md new file mode 100644 index 0000000..ed3e745 --- /dev/null +++ b/spider/row-markdown/79.word-search-en.md @@ -0,0 +1,242 @@ +## Problem +https://leetcode.com/problems/word-search/ + +## Problem Description +``` +Given a 2D board and a word, find if the word exists in the grid. + +The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. + +Example: + +board = +[ + ['A','B','C','E'], + ['S','F','C','S'], + ['A','D','E','E'] +] + +Given word = "ABCCED", return true. +Given word = "SEE", return true. +Given word = "ABCB", return false. +``` + +## Solution + +This problem does not give start position, or direction restriction, so +1. Scan board, find starting position with matching word first letter +2. From starting position, DFS (4 (up, down, left, right 4 directions) match word's rest letters +3. For each visited letter, mark it as visited, here use `board[i][j] = '*'` to represent visited. +4. If one direction cannot continue, backtracking, mark start position unvisited, mark `board[i][j] = word[start]` +5. If found any matching, terminate +6. Otherwise, no matching found, return false. + +For example: + +board, word:`SEE` as below pic: +``` +1. Scan board, found board[1,0] = word[0],match word first letter。 +2. DFS(up, down, left, right 4 directions) + +as below pic: +``` +![word search 1](../assets/problems/79.word-search-en-1.png) + +Staring position(1,0), check whether adjacent cells match word next letter `E`. +``` +1. mark current position(1,0)as visited,board[1][0] = '*' +2. Up(0,0)letter='A' not match, +3. Down(2,0)letter='A',not match, +4. Left(-1,0)out of board boundry,not match, +5. right(1,1)letter='F',not match + +as below pic: +``` +![word search 2](../assets/problems/79.word-search-2.png) + +Didn't find matching from starting position, so +``` +1. backtracking,mart start position(1,0)as unvisited, board[1][0] = 'S'. +2. scan board, find next start position(1,3)which match word first letter + +as below pic: +``` +![word search 3](../assets/problems/79.word-search-3.png) + +New starting position(1,3),check whether adjacent cells match word next letter `E`. +``` +1. mark current position(1, 3)as already visited,board[1][3] = '*' +2. Up(0,3)letter='E', match, continue DFS search,refer position(0,3)DFS search steps. +3. Down(2,3)letter='E',match, since #2 DFS didn't find word matching, continue DFS search, rfer to position (2, 3) DFS search steps. +4. Left(1,2)letter='C',not match, +5. Right(1,4)out of board boundry,not match + +as below pic: +``` +![word search 4](../assets/problems/79.word-search-4.png) + +Start position(0,3), DFS,check whether adjacent cells match word next letter `E` +``` +1. marck current position(0,3)already visited,board[0][3] = '*' +2. Up (-1,3)out of board boundry,not match +3. Down(1,3)already visited, +4. Left(0,2)letter='C',not match +5. Right(1,4)out of board boundry,not match + +as below pic: +``` +![word search 5](../assets/problems/79.word-search-5.png) + +Start from position(0,3)not matching word, start position (2, 3) DFS search: +``` +1. Backtracking,mark(0,3)as unvisited。board[0][3] = 'E'. +2. Backtracking to next position(2,3),DFS,check whether adjacent cells match word next letter 'E' +3. Up (1,3)visited, continue +4. Down(3,3)out of board boundry,not match +5. Left(2,2)letter='E', match +6. Right(2,4)out of board boundry,not match + +as below pic: +``` +![word search 6](../assets/problems/79.word-search-6.png) + +Found match with word, return `True`. +![word search 7](../assets/problems/79.word-search-7.png) + +#### Complexity Analysis +- *Time Complexity:* `O(m*n) - m is number of board rows, n is number of board columns ` +- *Space Complexity:* `O(1) - no extra space` + +>**Note**:if use Set or boolean[][] mark position visited,need extra space `O(m*n)`. + +## Key Points + +- Scan board, find start position which match word first letter, DFS +- Remember visited letter +- Backtracking if not found matching + +## Code (`Java/Javascript/Python3`) +*Java Code* +```java +public class LC79WordSearch { + public boolean exist(char[][] board, String word) { + if (board == null || board.length == 0 || board[0].length == 0 + || word == null || word.length() == 0) return true; + int rows = board.length; + int cols = board[0].length; + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + // scan board, start with word first character + if (board[r][c] == word.charAt(0)) { + if (helper(board, word, r, c, 0)) { + return true; + } + } + } + } + return false; + } + + private boolean helper(char[][] board, String word, int r, int c, int start) { + // already match word all characters, return true + if (start == word.length()) return true; + if (!isValid(board, r, c) || + board[r][c] != word.charAt(start)) return false; + // mark visited + board[r][c] = '*'; + boolean res = helper(board, word, r + 1, c, start + 1) + || helper(board, word, r, c + 1, start + 1) + || helper(board, word, r - 1, c, start + 1) + || helper(board, word, r, c - 1, start + 1); + // backtracking to start position + board[r][c] = word.charAt(start); + return res; + } + + private boolean isValid(char[][] board, int r, int c) { + return r >= 0 && r < board.length && c >= 0 && c < board[0].length; + } +} +``` + +*Python3 Code* +```python +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + m = len(board) + n = len(board[0]) + + def dfs(board, r, c, word, index): + if index == len(word): + return True + if r < 0 or r >= m or c < 0 or c >= n or board[r][c] != word[index]: + return False + board[r][c] = '*' + res = dfs(board, r - 1, c, word, index + 1) or dfs(board, r + 1, c, word, index + 1) or dfs(board, r, c - 1, word, index + 1) or dfs(board, r, c + 1, word, index + 1) + board[r][c] = word[index] + return res + + for r in range(m): + for c in range(n): + if board[r][c] == word[0]: + if dfs(board, r, c, word, 0): + return True +``` + +*Javascript Code* from [**@lucifer**](https://github.com/azl397985856) +```javascript +/* + * @lc app=leetcode id=79 lang=javascript + * + * [79] Word Search + */ +function DFS(board, row, col, rows, cols, word, cur) { + // 边界检查 + if (row >= rows || row < 0) return false; + if (col >= cols || col < 0) return false; + + const item = board[row][col]; + + if (item !== word[cur]) return false; + + if (cur + 1 === word.length) return true; + + // If use HashMap keep track visited letters, then need manual clear HashMap for each backtrack which needs extra space. + // here we use a little trick + board[row][col] = null; + + // UP, DOWN, LEFT, RIGHT + const res = + DFS(board, row + 1, col, rows, cols, word, cur + 1) || + DFS(board, row - 1, col, rows, cols, word, cur + 1) || + DFS(board, row, col - 1, rows, cols, word, cur + 1) || + DFS(board, row, col + 1, rows, cols, word, cur + 1); + + board[row][col] = item; + + return res; +} +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function(board, word) { + if (word.length === 0) return true; + if (board.length === 0) return false; + + const rows = board.length; + const cols = board[0].length; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + const hit = DFS(board, i, j, rows, cols, word, 0); + if (hit) return true; + } + } + return false; +}; +``` + +## References +1. [Backtracking Wiki](https://www.wikiwand.com/en/Backtracking) \ No newline at end of file diff --git a/spider/row-markdown/79.word-search.md b/spider/row-markdown/79.word-search.md new file mode 100644 index 0000000..99adc5d --- /dev/null +++ b/spider/row-markdown/79.word-search.md @@ -0,0 +1,237 @@ +## 题目地址 +https://leetcode.com/problems/word-search/ + +## 题目描述 +``` +Given a 2D board and a word, find if the word exists in the grid. + +The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. + +Example: + +board = +[ + ['A','B','C','E'], + ['S','F','C','S'], + ['A','D','E','E'] +] + +Given word = "ABCCED", return true. +Given word = "SEE", return true. +Given word = "ABCB", return false. +``` + +## 思路 + +在2D表中搜索是否有满足给定单词的字符组合,要求所有字符都是相邻的(方向不限). 题中也没有要求字符的起始和结束位置。 + +在起始位置不确定的情况下,扫描二维数组,找到字符跟给定单词的第一个字符相同的,四个方向(上,下,左,右)分别DFS搜索, +如果任意方向满足条件,则返回结果。不满足,回溯,重新搜索。 + +举例说明:如图二维数组,单词:"SEE" +``` +1. 扫描二维数组,找到board[1,0] = word[0],匹配单词首字母。 +2. 做DFS(上,下,左,右 四个方向) + +如下图: +``` +![word search 1](../assets/problems/79.word-search-1.png) + +起始位置(1,0),判断相邻的字符是否匹配单词下一个字符 `E`. +``` +1. 标记当前字符(1,0)为已经访问过,board[1][0] = '*' +2. 上(0,0)字符为 'A' 不匹配, +3. 下(2,0)字符为 'A',不匹配, +4. 左(-1,0)超越边界,不匹配, +5. 右(1,1)字符 'F',不匹配 + +如下图: +``` +![word search 2](../assets/problems/79.word-search-2.png) + +由于从起始位置DFS都不满足条件,所以 +``` +1. 回溯,标记起始位置(1,0)为未访问。board[1][0] = 'S'. +2. 然后继续扫描二维数组,找到下一个起始位置(1,3) + +如下图: +``` +![word search 3](../assets/problems/79.word-search-3.png) + +起始位置(1,3),判断相邻的字符是否匹配单词下一个字符 `E`. +``` +1. 标记当前字符(1, 3)为已经访问过,board[1][3] = '*' +2. 上(0,3)字符为 'E', 匹配, 继续DFS搜索(参考位置为(0,3)位置DFS搜索步骤描述) +3. 下(2,3)字符为 'E',匹配, #2匹配,先进行#2 DFS搜索,由于#2 DFS搜索没有找到与单词匹配,继续DFS搜索(参考位置为(2,3)DFS搜索步骤描述) +4. 左(1,2)字符为 'C',不匹配, +5. 右(1,4)超越边界,不匹配 + +如下图: +``` +![word search 4](../assets/problems/79.word-search-4.png) + +位置(0,3)满足条件,继续DFS,判断相邻的字符是否匹配单词下一个字符 `E` +``` +1. 标记当前字符(0,3)为已经访问过,board[0][3] = '*' +2. 上 (-1,3)超越边界,不匹配 +3. 下(1,3)已经访问过, +4. 左(0,2)字符为 'C',不匹配 +5. 右(1,4)超越边界,不匹配 + +如下图 +``` +![word search 5](../assets/problems/79.word-search-5.png) + +从位置(0,3)DFS不满足条件,继续位置(2,3)DFS搜索 +``` +1. 回溯,标记起始位置(0,3)为未访问。board[0][3] = 'E'. +2. 回到满足条件的位置(2,3),继续DFS搜索,判断相邻的字符是否匹配单词下一个字符 'E' +3. 上 (1,3)已访问过 +4. 下(3,3)超越边界,不匹配 +5. 左(2,2)字符为 'E',匹配 +6. 右(2,4)超越边界,不匹配 + +如下图: +``` +![word search 6](../assets/problems/79.word-search-6.png) + +单词匹配完成,满足条件,返回 `True`. +![word search 7](../assets/problems/79.word-search-7.png) + +#### 复杂度分析 +- *时间复杂度:* `O(m*n) - m 是二维数组行数, n 是二维数组列数` +- *空间复杂度:* `O(1) - 这里在原数组中标记当前访问过,没有用到额外空间` + +>**注意**:如果用 Set 或者是 boolean[][]来标记字符位置是否已经访问过,需要额外的空间 `O(m*n)`. + +## 关键点分析 +- 遍历二维数组的每一个点,找到起始点相同的字符,做DFS +- DFS过程中,要记录已经访问过的节点,防止重复遍历,这里(Java Code中)用 `*` 表示当前已经访问过,也可以用Set或者是boolean[][]数组记录访问过的节点位置。 +- 是否匹配当前单词中的字符,不符合回溯,这里记得把当前 `*` 重新设为当前字符。如果用Set或者是boolean[][]数组,记得把当前位置重设为没有访问过。 + +## 代码 (`Java/Javascript/Python3`) +*Java Code* +```java +public class LC79WordSearch { + public boolean exist(char[][] board, String word) { + if (board == null || board.length == 0 || board[0].length == 0 + || word == null || word.length() == 0) return true; + int rows = board.length; + int cols = board[0].length; + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + // scan board, start with word first character + if (board[r][c] == word.charAt(0)) { + if (helper(board, word, r, c, 0)) { + return true; + } + } + } + } + return false; + } + + private boolean helper(char[][] board, String word, int r, int c, int start) { + // already match word all characters, return true + if (start == word.length()) return true; + if (!isValid(board, r, c) || + board[r][c] != word.charAt(start)) return false; + // mark visited + board[r][c] = '*'; + boolean res = helper(board, word, r - 1, c, start + 1) // 上 + || helper(board, word, r + 1, c, start + 1) // 下 + || helper(board, word, r, c - 1, start + 1) // 左 + || helper(board, word, r, c + 1, start + 1); // 右 + // backtracking to start position + board[r][c] = word.charAt(start); + return res; + } + + private boolean isValid(char[][] board, int r, int c) { + return r >= 0 && r < board.length && c >= 0 && c < board[0].length; + } +} +``` + +*Python3 Code* +```python +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + m = len(board) + n = len(board[0]) + + def dfs(board, r, c, word, index): + if index == len(word): + return True + if r < 0 or r >= m or c < 0 or c >= n or board[r][c] != word[index]: + return False + board[r][c] = '*' + res = dfs(board, r - 1, c, word, index + 1) or dfs(board, r + 1, c, word, index + 1) or dfs(board, r, c - 1, word, index + 1) or dfs(board, r, c + 1, word, index + 1) + board[r][c] = word[index] + return res + + for r in range(m): + for c in range(n): + if board[r][c] == word[0]: + if dfs(board, r, c, word, 0): + return True +``` + +*Javascript Code* from [**@lucifer**](https://github.com/azl397985856) +```javascript +/* + * @lc app=leetcode id=79 lang=javascript + * + * [79] Word Search + */ +function DFS(board, row, col, rows, cols, word, cur) { + // 边界检查 + if (row >= rows || row < 0) return false; + if (col >= cols || col < 0) return false; + + const item = board[row][col]; + + if (item !== word[cur]) return false; + + if (cur + 1 === word.length) return true; + + // 如果你用hashmap记录访问的字母, 那么你需要每次backtrack的时候手动清除hashmap,并且需要额外的空间 + // 这里我们使用一个little trick + + board[row][col] = null; + + // 上下左右 + const res = + DFS(board, row + 1, col, rows, cols, word, cur + 1) || + DFS(board, row - 1, col, rows, cols, word, cur + 1) || + DFS(board, row, col - 1, rows, cols, word, cur + 1) || + DFS(board, row, col + 1, rows, cols, word, cur + 1); + + board[row][col] = item; + + return res; +} +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function(board, word) { + if (word.length === 0) return true; + if (board.length === 0) return false; + + const rows = board.length; + const cols = board[0].length; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + const hit = DFS(board, i, j, rows, cols, word, 0); + if (hit) return true; + } + } + return false; +}; +``` + +## 参考(References) +1. [回溯法 Wiki](https://www.wikiwand.com/zh/%E5%9B%9E%E6%BA%AF%E6%B3%95) \ No newline at end of file diff --git a/spider/row-markdown/80.remove-duplicates-from-sorted-array-ii.md b/spider/row-markdown/80.remove-duplicates-from-sorted-array-ii.md new file mode 100644 index 0000000..1d2efee --- /dev/null +++ b/spider/row-markdown/80.remove-duplicates-from-sorted-array-ii.md @@ -0,0 +1,106 @@ +## 题目地址(删除排序数组中的重复项 II) + +https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/description/ + +## 题目描述 + +``` +给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。 + +不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 + +示例 1: + +给定 nums = [1,1,1,2,2,3], + +函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 + +你不需要考虑数组中超出新长度后面的元素。 +示例 2: + +给定 nums = [0,0,1,1,1,1,2,3,3], + +函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 + +你不需要考虑数组中超出新长度后面的元素。 +说明: + +为什么返回数值是整数,但输出的答案是数组呢? + +请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 + +你可以想象内部操作如下: + +// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 +int len = removeDuplicates(nums); + +// 在函数里修改输入数组对于调用者是可见的。 +// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。 +for (int i = 0; i < len; i++) { + print(nums[i]); +} + +``` + +## 思路 + +”删除排序“类题目截止到现在(2020-1-15)一共有四道题: + +![](https://tva1.sinaimg.cn/large/006tNbRwly1gax0eadc5ej30x60ce76i.jpg) + +这道题是[26.remove-duplicates-from-sorted-array](./26.remove-duplicates-from-sorted-array.md) 的进阶版本,唯一的不同是不再是全部元素唯一,而是全部元素不超过 2 次。实际上这种问题可以更抽象一步,即“删除排序数组中的重复项,使得相同数字最多出现 k 次” +。 那么这道题 k 就是 2, 26.remove-duplicates-from-sorted-array 的 k 就是 1。 + +上一题我们使用了快慢指针来实现,这道题也是一样,只不过逻辑稍有不同。 其实快慢指针本质是读写指针,在这里我们的快指针实际上就是读指针,而慢指针恰好相当于写指针。”快慢指针的说法“便于描述和记忆,“读写指针”的说法更便于理解本质。本文中,以下内容均描述为快慢指针。 + +- 初始化快慢指针 slow , fast ,全部指向索引为 0 的元素。 +- fast 每次移动一格 +- 慢指针选择性移动,即只有写入数据之后才移动。是否写入数据取决于 slow - 2 对应的数字和 fast 对应的数字是否一致。 +- 如果一致,我们不应该写。 否则我们就得到了三个相同的数字,不符合题意 +- 如果不一致,我们需要将 fast 指针的数据写入到 slow 指针。 +- 重复这个过程,直到 fast 走到头,说明我们已无数字可写。 + +图解(红色的两个数字,表示我们需要比较的两个数字): + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gax0oyt4yhj30n10hpdgc.jpg) + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gax0p3ri3ij30ga0880ss.jpg) + +## 关键点分析 + +- 快慢指针 +- 读写指针 +- 删除排序问题 + +## 代码 + +代码支持: Python + +Python Code: + +```python +class Solution: + def removeDuplicates(self, nums: List[int]) -> int: + # 写指针 + i = 0 + K = 2 + for num in nums: + if i < K or num != nums[i-K]: + nums[i] = num + i += 1 + return i +``` + +基于这套代码,你可以轻易地实现 k 为任意正整数的算法。 + +## 相关题目 + +正如上面所说,相关题目一共有三道(排除自己)。其中一道我们仓库已经讲到了。剩下两道原理类似,但是实际代码和细节有很大不同,原因就在于数组可以随机访问,而链表不行。 感兴趣的可以做一下剩下的两道链表题。 + +- 82. 删除排序链表中的重复元素 II + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gax0txa7gbj31lq0tg0zm.jpg) + +- 83. 删除排序链表中的重复元素 + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gax0uzm0euj318c0se44t.jpg) diff --git a/spider/row-markdown/820.short-encoding-of-words.md b/spider/row-markdown/820.short-encoding-of-words.md new file mode 100644 index 0000000..037765e --- /dev/null +++ b/spider/row-markdown/820.short-encoding-of-words.md @@ -0,0 +1,121 @@ +## 题目地址(820. 单词的压缩编码) + +https://leetcode-cn.com/problems/walking-robot-simulation/submissions/ + +## 题目描述 + +``` +给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。 + +例如,如果这个列表是 ["time", "me", "bell"],我们就可以将其表示为 S = "time#bell#" 和 indexes = [0, 2, 5]。 + +对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 "#" 结束,来恢复我们之前的单词列表。 + +那么成功对给定单词列表进行编码的最小字符串长度是多少呢? + +  + +示例: + +输入: words = ["time", "me", "bell"] +输出: 10 +说明: S = "time#bell#" , indexes = [0, 2, 5] 。 +  + +提示: + +1 <= words.length <= 2000 +1 <= words[i].length <= 7 +每个单词都是小写字母 。 + +``` + + +## 思路 + +读完题目之后就发现这题是一个后缀树。 因此符合直觉的想法是使用前缀树 + 倒序插入的形式来模拟后缀树。 + + +下面的代码看起来复杂,但是很多题目我都是用这个模板,稍微调整下细节就能AC。我这里总结了一套[前缀树专题](https://github.com/azl397985856/leetcode/blob/master/thinkings/trie.md) + +![image.png](https://pic.leetcode-cn.com/e54b2b2d133dc0071e552138eb1f64617bdc1ecba415b6ba65b022177f343a28-image.png) + +前缀树的 api 主要有以下几个: + +- `insert(word)`: 插入一个单词 +- `search(word)`:查找一个单词是否存在 +- `startWith(word)`: 查找是否存在以 word 为前缀的单词 + +其中 startWith 是前缀树最核心的用法,其名称前缀树就从这里而来。大家可以先拿 208 题开始,熟悉一下前缀树,然后再尝试别的题目。 + +一个前缀树大概是这个样子: + +![image.png](https://pic.leetcode-cn.com/5707f704af10748fe17f65d8201e6e5d93f5595d5907bfecb242ad2a1a149994-image.png) + + +如图每一个节点存储一个字符,然后外加一个控制信息表示是否是单词结尾,实际使用过程可能会有细微差别,不过变化不大。 + + +这道题需要考虑edge case, 比如这个列表是 ["time", "time", "me", "bell"] 这种包含重复元素的情况,这里我使用hashset来去重。 + +## 关键点 + +- 前缀树 +- 去重 + +## 代码 + +```python +class Trie: + + def __init__(self): + """ + Initialize your data structure here. + """ + self.Trie = {} + + def insert(self, word): + """ + Inserts a word into the trie. + :type word: str + :rtype: void + """ + curr = self.Trie + for w in word: + if w not in curr: + curr[w] = {} + curr = curr[w] + curr['#'] = 1 + + def isTail(self, word): + """ + Returns if the word is in the trie. + :type word: str + :rtype: bool + """ + curr = self.Trie + for w in word: + curr = curr[w] + return len(curr) == 1 +class Solution: + def minimumLengthEncoding(self, words: List[str]) -> int: + trie = Trie() + cnt = 0 + words = set(words) + for word in words: + trie.insert(word[::-1]) + for word in words: + if trie.isTail(word[::-1]): + cnt += len(word) + 1 + return cnt + +``` + +***复杂度分析*** +- 时间复杂度:$O(N)$,其中N为单词长度列表中的总字符数,比如["time", "me"],就是 4 + 2 = 6。 +- 空间复杂度:$O(N)$,其中N为单词长度列表中的总字符数,比如["time", "me"],就是 4 + 2 = 6。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) + diff --git a/spider/row-markdown/84.largest-rectangle-in-histogram.md b/spider/row-markdown/84.largest-rectangle-in-histogram.md new file mode 100644 index 0000000..073c0d1 --- /dev/null +++ b/spider/row-markdown/84.largest-rectangle-in-histogram.md @@ -0,0 +1,183 @@ +## 题目地址(84. 柱状图中最大的矩形) + +https://leetcode-cn.com/problems/largest-rectangle-in-histogram/ + +## 题目描述 + +` +给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 + +求在该柱状图中,能够勾勒出来的矩形的最大面积。 + +![](https://tva1.sinaimg.cn/large/00831rSTly1gch1kvdoy5j305805oaa1.jpg) + +以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为  [2,1,5,6,2,3]。 + +![](https://tva1.sinaimg.cn/large/00831rSTly1gch1l4m3clj305805owem.jpg) + +图中阴影部分为所能勾勒出的最大矩形面积,其面积为  10  个单位。 + +示例: + +输入:[2,1,5,6,2,3] +输出:10 + +## 暴力枚举 - 左右端点法(TLE) + +### 思路 + +我们暴力尝试`所有可能的矩形`。由于矩阵是二维图形, 我我们可以使用`左右两个端点来唯一确认一个矩阵`。因此我们使用双层循环枚举所有的可能性即可。 而矩形的面积等于`(右端点坐标 - 左端点坐标 + 1) * 最小的高度`,最小的高度我们可以在遍历的时候顺便求出。 + +### 代码 + +```python +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + n, ans = len(heights), 0 + if n != 0: + ans = heights[0] + for i in range(n): + height = heights[i] + for j in range(i, n): + height = min(height, heights[j]) + ans = max(ans, (j - i + 1) * height) + return ans +``` + +**复杂度分析** + +- 时间复杂度:$O(N^2)$ +- 空间复杂度:$O(1)$ + +## 暴力枚举 - 中心扩展法(TLE) + +### 思路 + +我们仍然暴力尝试`所有可能的矩形`。只不过我们这一次从中心向两边进行扩展。对于每一个 i,我们计算出其左边第一个高度小于它的索引 p,同样地,计算出右边第一个高度小于它的索引 q。那么以 i 为最低点能够构成的面积就是`(q - p - 1) * heights[i]`。 这种算法毫无疑问也是正确的。 我们证明一下,假设 f(i) 表示求以 i 为最低点的情况下,所能形成的最大矩阵面积。那么原问题转化为`max(f(0), f(1), f(2), ..., f(n - 1))`。 + +具体算法如下: + +- 我们使用 l 和 r 数组。l[i] 表示 左边第一个高度小于它的索引,r[i] 表示 右边第一个高度小于它的索引。 +- 我们从前往后求出 l,再从后往前计算出 r。 +- 再次遍历求出所有的可能面积,并取出最大的。 + +### 代码 + +```python +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + n = len(heights) + l, r, ans = [-1] * n, [n] * n, 0 + for i in range(1, n): + j = i - 1 + while j >= 0 and heights[j] >= heights[i]: + j -= 1 + l[i] = j + for i in range(n - 2, -1, -1): + j = i + 1 + while j < n and heights[j] >= heights[i]: + j += 1 + r[i] = j + for i in range(n): + ans = max(ans, heights[i] * (r[i] - l[i] - 1)) + return ans + +``` + +**复杂度分析** + +- 时间复杂度:$O(N^2)$ +- 空间复杂度:$O(N)$ + +## 优化中心扩展法(Accepted) + +### 思路 + +实际上我们内层循环没必要一步一步移动,我们可以直接将`j -= 1` 改成 `j = l[j]`, `j += 1` 改成 `j = r[j]`。 + +### 代码 + +```python +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + n = len(heights) + l, r, ans = [-1] * n, [n] * n, 0 + + for i in range(1, n): + j = i - 1 + while j >= 0 and heights[j] >= heights[i]: + j = l[j] + l[i] = j + for i in range(n - 2, -1, -1): + j = i + 1 + while j < n and heights[j] >= heights[i]: + j = r[j] + r[i] = j + for i in range(n): + ans = max(ans, heights[i] * (r[i] - l[i] - 1)) + return ans + +``` + +**复杂度分析** + +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(N)$ + +## 单调栈(Accepted) + +### 思路 + +实际上,读完第二种方法的时候,你应该注意到了。我们的核心是求左边第一个比 i 小的和右边第一个比 i 小的。 如果你熟悉单调栈的话,那么应该会想到这是非常适合使用单调栈来处理的场景。 + +从左到右遍历柱子,对于每一个柱子,我们想找到第一个高度小于它的柱子,那么我们就可以使用一个单调递增栈来实现。 如果柱子大于栈顶的柱子,那么说明不是我们要找的柱子,我们把它塞进去继续遍历,如果比栈顶小,那么我们就找到了第一个小于的柱子。 **对于栈顶元素,其右边第一个小于它的就是当前遍历到的柱子,左边第一个小于它的就是栈中下一个要被弹出的元素**,因此以当前栈顶为最小柱子的面积为**当前栈顶的柱子高度 * (当前遍历到的柱子索引 - 1 - 栈中下一个要被弹出的元素索引 - 1 + 1)** + +这种方法只需要遍历一次,并用一个栈。由于每一个元素最多进栈出栈一次,因此时间和空间复杂度都是$O(N)$。 + +为了统一算法逻辑,减少边界处理,我在 heights 首尾添加了两个哨兵元素,**这样我们可以保证所有的柱子都会出栈**。 + +### 代码 + +```python +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + n, heights, st, ans = len(heights), [0] + heights + [0], [], 0 + for i in range(n + 2): + while st and heights[st[-1]] > heights[i]: + ans = max(ans, heights[st.pop(-1)] * (i - st[-1] - 1)) + st.append(i) + return ans +``` + +**复杂度分析** + +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(N)$ + + +2020-05-30更新: + +有的观众反应看不懂为啥需要两个哨兵。 其实末尾的哨兵就是为了将栈清空,防止遍历完成栈中还有没参与运算的数据。 + +而前面的哨兵有什么用呢? 我这里把上面代码进行了拆解: + +```py +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + n, heights, st, ans = len(heights),[0] + heights + [0], [], 0 + for i in range(n + 2): + while st and heights[st[-1]] > heights[i]: + a = heights[st[-1]] + # 如果没有前面的哨兵,这里可能会越界。 + st.pop() + ans = max(ans, a * (i - 1 - st[-1])) + st.append(i) + return ans + ``` + + + + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/85.maximal-rectangle.md b/spider/row-markdown/85.maximal-rectangle.md new file mode 100644 index 0000000..78e2593 --- /dev/null +++ b/spider/row-markdown/85.maximal-rectangle.md @@ -0,0 +1,78 @@ +## 题目地址(85. 最大矩形) + +https://leetcode-cn.com/problems/maximal-rectangle/ + +## 题目描述 + +给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。 + +示例: + +输入: +``` +[ + ["1","0","1","0","0"], + ["1","0","1","1","1"], + ["1","1","1","1","1"], + ["1","0","0","1","0"] +] +``` +输出:6 + +## 思路 + +我在 [【84. 柱状图中最大的矩形】多种方法(Python3)](https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/84-zhu-zhuang-tu-zhong-zui-da-de-ju-xing-duo-chong/ "【84. 柱状图中最大的矩形】多种方法(Python3)") 使用了多种方法来解决。 然而在这道题,我们仍然可以使用完全一样的思路去完成。 不熟悉的可以看下我的题解。本题解是基于那道题的题解来进行的。 + +拿题目给的例子来说: + +``` +[ + ["1","0","1","0","0"], + ["1","0","1","1","1"], + ["1","1","1","1","1"], + ["1","0","0","1","0"] +] +``` + +我们逐行扫描得到 `84. 柱状图中最大的矩形` 中的 heights 数组: + +![](https://pic.leetcode-cn.com/aaa258e37c34d5028f56b1c172300c278ff439f209431010561d7b8a7d8eae2a.jpg) + +这样我们就可以使用`84. 柱状图中最大的矩形` 中的解法来进行了,这里我们使用单调栈来解。 + +## 代码 + +```python +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + n, heights, st, ans = len(heights), [0] + heights + [0], [], 0 + for i in range(n + 2): + while st and heights[st[-1]] > heights[i]: + ans = max(ans, heights[st.pop(-1)] * (i - st[-1] - 1)) + st.append(i) + + return ans + def maximalRectangle(self, matrix: List[List[str]]) -> int: + m = len(matrix) + if m == 0: return 0 + n = len(matrix[0]) + heights = [0] * n + ans = 0 + for i in range(m): + for j in range(n): + if matrix[i][j] == "0": + heights[j] = 0 + else: + heights[j] += 1 + ans = max(ans, self.largestRectangleArea(heights)) + return ans + +``` + +**复杂度分析** +- 时间复杂度:$O(M * N)$ +- 空间复杂度:$O(N)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) \ No newline at end of file diff --git a/spider/row-markdown/86.partition-list.md b/spider/row-markdown/86.partition-list.md new file mode 100644 index 0000000..12b07ed --- /dev/null +++ b/spider/row-markdown/86.partition-list.md @@ -0,0 +1,144 @@ +## 题目地址 +https://leetcode.com/problems/partition-list/description/ + +## 题目描述 +Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. + +You should preserve the original relative order of the nodes in each of the two partitions. + +Example: + +Input: head = 1->4->3->2->5->2, x = 3 +Output: 1->2->2->4->3->5 + +## 思路 + +- 设定两个虚拟节点,dummyHead1用来保存小于该值的链表,dummyHead2来保存大于等于该值的链表 + +- 遍历整个原始链表,将小于该值的放于dummyHead1中,其余的放置在dummyHead2中 + +遍历结束后,将dummyHead2插入到dummyHead1后面 + +![86.partition-list](../assets/86.partition-list.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) +## 关键点解析 + +- 链表的基本操作(遍历) +- 虚拟节点dummy 简化操作 +- 遍历完成之后记得`currentL1.next = null;`否则会内存溢出 + +> 如果单纯的遍历是不需要上面操作的,但是我们的遍历会导致currentL1.next和currentL2.next +中有且仅有一个不是null, 如果不这么操作的话会导致两个链表成环,造成溢出。 + + +## 代码 + +* 语言支持: Javascript,Python3 + +```js +/* + * @lc app=leetcode id=86 lang=javascript + * + * [86] Partition List + * + * https://leetcode.com/problems/partition-list/description/ + * + * algorithms + * Medium (36.41%) + * Total Accepted: 155.1K + * Total Submissions: 425.1K + * Testcase Example: '[1,4,3,2,5,2]\n3' + * + * Given a linked list and a value x, partition it such that all nodes less + * than x come before nodes greater than or equal to x. + * + * You should preserve the original relative order of the nodes in each of the + * two partitions. + * + * Example: + * + * + * Input: head = 1->4->3->2->5->2, x = 3 + * Output: 1->2->2->4->3->5 + * + * + */ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} x + * @return {ListNode} + */ +var partition = function(head, x) { + const dummyHead1 = { + next: null + } + const dummyHead2 = { + next: null + } + + let current = { + next: head + }; + let currentL1 = dummyHead1; + let currentL2 = dummyHead2; + while(current.next) { + current = current.next; + if (current.val < x) { + currentL1.next = current; + currentL1 = current; + } else { + currentL2.next = current; + currentL2 = current; + } + } + + currentL2.next = null; + + currentL1.next = dummyHead2.next; + + return dummyHead1.next; +}; +``` +Python3 Code: +```python +class Solution: + def partition(self, head: ListNode, x: int) -> ListNode: + """在原链表操作,思路基本一致,只是通过指针进行区分而已""" + # 在链表最前面设定一个初始node作为锚点,方便返回最后的结果 + first_node = ListNode(0) + first_node.next = head + # 设计三个指针,一个指向小于x的最后一个节点,即前后分离点 + # 一个指向当前遍历节点的前一个节点 + # 一个指向当前遍历的节点 + sep_node = first_node + pre_node = first_node + current_node = head + + while current_node is not None: + if current_node.val < x: + # 注意有可能出现前一个节点就是分离节点的情况 + if pre_node is sep_node: + pre_node = current_node + sep_node = current_node + current_node = current_node.next + else: + # 这段次序比较烧脑 + pre_node.next = current_node.next + current_node.next = sep_node.next + sep_node.next = current_node + sep_node = current_node + current_node = pre_node.next + else: + pre_node = current_node + current_node = pre_node.next + + return first_node.next +``` diff --git a/spider/row-markdown/874.walking-robot-simulation.md b/spider/row-markdown/874.walking-robot-simulation.md new file mode 100644 index 0000000..f2ed8b1 --- /dev/null +++ b/spider/row-markdown/874.walking-robot-simulation.md @@ -0,0 +1,118 @@ +## 题目地址(874. 模拟行走机器人) + +https://leetcode-cn.com/problems/walking-robot-simulation/submissions/ + +## 题目描述 + +``` +机器人在一个无限大小的网格上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令: + +-2:向左转 90 度 +-1:向右转 90 度 +1 <= x <= 9:向前移动 x 个单位长度 +在网格上有一些格子被视为障碍物。 + +第 i 个障碍物位于网格点  (obstacles[i][0], obstacles[i][1]) + +如果机器人试图走到障碍物上方,那么它将停留在障碍物的前一个网格方块上,但仍然可以继续该路线的其余部分。 + +返回从原点到机器人的最大欧式距离的平方。 + +  + +示例 1: + +输入: commands = [4,-1,3], obstacles = [] +输出: 25 +解释: 机器人将会到达 (3, 4) +示例 2: + +输入: commands = [4,-1,4,-2,4], obstacles = [[2,4]] +输出: 65 +解释: 机器人在左转走到 (1, 8) 之前将被困在 (1, 4) 处 +  + +提示: + +0 <= commands.length <= 10000 +0 <= obstacles.length <= 10000 +-30000 <= obstacle[i][0] <= 30000 +-30000 <= obstacle[i][1] <= 30000 +答案保证小于 2 ^ 31 + + +``` + +## 思路 + +这道题之所以是简单难度,是因为其没有什么技巧。你只需要看懂题目描述,然后把题目描述转化为代码即可。 + +唯一需要注意的是查找障碍物的时候如果你采用的是`线形查找`会很慢,很可能会超时。 + +> 我实际测试了一下,确实会超时 + +- 一种方式是使用排序,然后二分查找,如果采用基于比较的排序算法,那么这种算法的瓶颈在于排序本身,也就是$O(NlogN)$。 +- 另一种方式是使用集合,将 obstacles 放入集合,然后需要的时候进行查询,查询的时候的时间复杂度为$O(1)$。 + +这里我们采用第二种方式。 + +接下来我们来“翻译”一下题目。 + +- 由于机器人只能往前走。因此机器人往东西南北哪个方向走取决于它的`朝向`。 +- 我们使用枚举来表示当前机器人的`朝向`。 +- 题目只有两种方式改变`朝向`,一种是左转(-2),另一种是右转(-1)。 +- 题目要求的是机器人在`运动过程中距离原点的最大值`,而不是最终位置距离原点的距离。 + +为了代码书写简单,我建立了一个直角坐标系。用`机器人的朝向和 x 轴正方向的夹角度数`来作为枚举值,并且这个度数是 `0 <= deg < 360`。我们不难知道,其实这个取值就是`0`, `90`,`180`,`270` 四个值。那么当 0 度的时候,我们只需要不断地 x+1,90 度的时候我们不断地 y + 1 等等。 + +![](https://tva1.sinaimg.cn/large/006tNbRwgy1gbdnsywx97j31020r8gmt.jpg) + +## 关键点解析 + +- 理解题意,这道题容易理解错题意,求解为`最终位置距离原点的距离` +- 建立坐标系 +- 使用集合简化线形查找的时间复杂度。 + +## 代码 + +代码支持: Python3 + +Python3 Code: + +```python +class Solution: + def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int: + pos = [0, 0] + deg = 90 + ans = 0 + obstaclesSet = set(map(tuple, obstacles)) + + for command in commands: + if command == -1: + deg = (deg + 270) % 360 + elif command == -2: + deg = (deg + 90) % 360 + else: + if deg == 0: + i = 0 + while i < command and not (pos[0] + 1, pos[1]) in obstaclesSet: + pos[0] += 1 + i += 1 + if deg == 90: + i = 0 + while i < command and not (pos[0], pos[1] + 1) in obstaclesSet: + pos[1] += 1 + i += 1 + if deg == 180: + i = 0 + while i < command and not (pos[0] - 1, pos[1]) in obstaclesSet: + pos[0] -= 1 + i += 1 + if deg == 270: + i = 0 + while i < command and not (pos[0], pos[1] - 1) in obstaclesSet: + pos[1] -= 1 + i += 1 + ans = max(ans, pos[0] ** 2 + pos[1] ** 2) + return ans +``` diff --git a/spider/row-markdown/875.koko-eating-bananas.md b/spider/row-markdown/875.koko-eating-bananas.md new file mode 100644 index 0000000..197effc --- /dev/null +++ b/spider/row-markdown/875.koko-eating-bananas.md @@ -0,0 +1,155 @@ +## 题目地址 +https://leetcode.com/problems/koko-eating-bananas/description/ + +## 题目描述 +``` +Koko loves to eat bananas. There are N piles of bananas, the i-th pile has piles[i] bananas. The guards have gone and will come back in H hours. + +Koko can decide her bananas-per-hour eating speed of K. Each hour, she chooses some pile of bananas, and eats K bananas from that pile. If the pile has less than K bananas, she eats all of them instead, and won't eat any more bananas during this hour. + +Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back. + +Return the minimum integer K such that she can eat all the bananas within H hours. + + + +Example 1: + +Input: piles = [3,6,7,11], H = 8 +Output: 4 +Example 2: + +Input: piles = [30,11,23,4,20], H = 5 +Output: 30 +Example 3: + +Input: piles = [30,11,23,4,20], H = 6 +Output: 23 + + +Note: + +1 <= piles.length <= 10^4 +piles.length <= H <= 10^9 +1 <= piles[i] <= 10^9 + +``` + +## 思路 +符合直觉的做法是,选择最大的堆的香蕉数,然后试一下能不能行,如果不行则直接返回上次计算的结果, +如果行,我们减少1个香蕉,试试行不行,依次类推。计算出刚好不行的即可。这种解法的时间复杂度是O(n)。 + +这道题如果能看出来是二分法解决,那么其实很简单。为什么它是二分问题呢? +我这里画了个图,我相信你看了就明白了。 + +![koko-eating-bananas](../assets/problems/koko-eating-bananas.png) + +## 关键点解析 + +- 二分查找 + + +## 代码 + +```js +/* + * @lc app=leetcode id=875 lang=javascript + * + * [875] Koko Eating Bananas + * + * https://leetcode.com/problems/koko-eating-bananas/description/ + * + * algorithms + * Medium (44.51%) + * Total Accepted: 11.3K + * Total Submissions: 24.8K + * Testcase Example: '[3,6,7,11]\n8' + * + * Koko loves to eat bananas.  There are N piles of bananas, the i-th pile has + * piles[i] bananas.  The guards have gone and will come back in H hours. + * + * Koko can decide her bananas-per-hour eating speed of K.  Each hour, she + * chooses some pile of bananas, and eats K bananas from that pile.  If the + * pile has less than K bananas, she eats all of them instead, and won't eat + * any more bananas during this hour. + * + * Koko likes to eat slowly, but still wants to finish eating all the bananas + * before the guards come back. + * + * Return the minimum integer K such that she can eat all the bananas within H + * hours. + * + * + * + * + * + * + * + * Example 1: + * + * + * Input: piles = [3,6,7,11], H = 8 + * Output: 4 + * + * + * + * Example 2: + * + * + * Input: piles = [30,11,23,4,20], H = 5 + * Output: 30 + * + * + * + * Example 3: + * + * + * Input: piles = [30,11,23,4,20], H = 6 + * Output: 23 + * + * + * + * + * Note: + * + * + * 1 <= piles.length <= 10^4 + * piles.length <= H <= 10^9 + * 1 <= piles[i] <= 10^9 + * + * + * + * + * + */ + + function canEatAllBananas(piles, H, mid) { + let h = 0; + for(let pile of piles) { + h += Math.ceil(pile / mid); + } + + return h <= H; + } +/** + * @param {number[]} piles + * @param {number} H + * @return {number} + */ +var minEatingSpeed = function(piles, H) { + let lo = 1, + hi = Math.max(...piles); + + while(lo <= hi) { + let mid = lo + ((hi - lo) >> 1); + if (canEatAllBananas(piles, H, mid)) { + hi = mid - 1; + } else { + lo = mid + 1; + } + } + + return lo; // 不能选择hi +}; +``` + diff --git a/spider/row-markdown/877.stone-game.md b/spider/row-markdown/877.stone-game.md new file mode 100644 index 0000000..44468a8 --- /dev/null +++ b/spider/row-markdown/877.stone-game.md @@ -0,0 +1,83 @@ +## 题目地址 + +https://leetcode.com/problems/stone-game/description/ + +## 题目描述 + +``` +Alex and Lee play a game with piles of stones. There are an even number of piles arranged in a row, and each pile has a positive integer number of stones piles[i]. + +The objective of the game is to end with the most stones. The total number of stones is odd, so there are no ties. + +Alex and Lee take turns, with Alex starting first. Each turn, a player takes the entire pile of stones from either the beginning or the end of the row. This continues until there are no more piles left, at which point the person with the most stones wins. + +Assuming Alex and Lee play optimally, return True if and only if Alex wins the game. + + + +Example 1: + +Input: [5,3,4,5] +Output: true +Explanation: +Alex starts first, and can only take the first 5 or the last 5. +Say he takes the first 5, so that the row becomes [3, 4, 5]. +If Lee takes 3, then the board is [4, 5], and Alex takes 5 to win with 10 points. +If Lee takes the last 5, then the board is [3, 4], and Alex takes 4 to win with 9 points. +This demonstrated that taking the first 5 was a winning move for Alex, so we return true. + + +Note: + +2 <= piles.length <= 500 +piles.length is even. +1 <= piles[i] <= 500 +sum(piles) is odd. + +``` + +## 思路 + +由于 piles 是偶数的,并且 piles 的总和是奇数的。 + +因此 Alex`可以做到`要不拿的全部是奇数,要么全部是偶数。 + +举个例子: 比如 Alex 第一次先拿第一个 + +这里有两种情况: + +1. Lee 如果拿了第二块(偶数),那么 Alex 继续拿第三块,以此类推。。。 + +2. Lee 如果拿了最后一块(偶数),那么 Alex 继续拿倒数第二块,以此类推。。。 + +因此 Alex`可以`做到只拿奇数或者偶数,只是他可以控制的,因此他要做的就是数一下,奇数加起来多还是偶数加起来多就好了。 +奇数多就全部选奇数,偶数就全部选偶数。 Lee 是没有这种自由权的。 + +## 关键点解析 + +- 可以用 DP(动态规划) + +- 可以从数学的角度去分析 + +> ......(😅) + +## 代码 + +```js +/** + * @param {number[]} piles + * @return {boolean} + */ +var stoneGame = function(piles) { + return true; +}; +``` + +## 扩展 + +腾讯面试题:一共 100 只弓箭 你和你的对手共用。你们每次只能射出一支箭或者两支箭,射击交替进行,设计一个算法,保证自己获胜。 + +答案: 先手,剩下的是 3 的倍数就行(100-1=99),然后按照 3 的倍数射箭必赢。 +比如你先拿了 1,剩下 99 个。 对手拿了 1,你就拿 2。这样持续 33 次就赢了。如果对手拿了 2 个,你就拿 1 个,这样持续 33 次你也是赢的。 + +> 这是一种典型的博弈问题, 你和对手交替进行,对手的行动影响你接下来的策略。 这算是一种最简单的博弈问题了 diff --git a/spider/row-markdown/88.merge-sorted-array.md b/spider/row-markdown/88.merge-sorted-array.md new file mode 100644 index 0000000..9d7be96 --- /dev/null +++ b/spider/row-markdown/88.merge-sorted-array.md @@ -0,0 +1,195 @@ +## 题目地址 + +https://leetcode-cn.com/problems/merge-sorted-array/ + +## 题目描述 + +``` +给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。 + +说明: + +初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 +你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。 +示例: + +输入: +nums1 = [1,2,3,0,0,0], m = 3 +nums2 = [2,5,6], n = 3 + +输出: [1,2,2,3,5,6] +``` + +## 思路 + +符合直觉的做法是`将nums2插到num1的末尾, 然后排序` + + +具体代码: + +```js + // 这种解法连m都用不到 + // 这显然不是出题人的意思 + if (n === 0) return; + let current2 = 0; + for(let i = nums1.length - 1; i >= nums1.length - n ; i--) { + nums1[i] = nums2[current2++]; + } + nums1.sort((a, b) => a - b); // 当然你可以自己写排序,这里懒得写了,因为已经偏离了题目本身 + +``` + +这道题目其实和基本排序算法中的`merge sort`非常像,但是 merge sort 很多时候,合并的时候我们通常是 +新建一个数组,这样就很简单。 但是这道题目要求的是`原地修改`. + +这就和 merge sort 的 merge 过程有点不同,我们先来回顾一下 merge sort 的 merge 过程。 + +merge 的过程`可以`是先比较两个数组的头元素,然后将较小的推到最终的数组中,并将其从原数组中出队列。 +循环直到两个数组都为空。 + +具体代码如下: + +```js +// 将nums1 和 nums2 合并 +function merge(nums1, nums2) { + let ret = []; + while (nums1.length || nums2.length) { + // 为了方便大家理解,这里代码有点赘余 + if (nums1.length === 0) { + ret.push(nums2.shift()); + continue; + } + + if (nums2.length === 0) { + ret.push(nums1.shift()); + continue; + } + const a = nums1[0]; + const b = nums2[0]; + if (a > b) { + ret.push(nums2.shift()); + } else { + ret.push(nums1.shift()); + } + } + return ret; +} +``` + +这里要求原地修改,其实我们能只要从后往前比较,并从后往前插入即可。 + +我们需要三个指针: + +1. current 用于记录当前填补到那个位置了 + +2. m 用于记录 nums1 数组处理到哪个元素了 + +3. n 用于记录 nums2 数组处理到哪个元素了 + +如图所示: + +- 灰色代表 num2 数组已经处理过的元素 +- 红色代表当前正在进行比较的元素 +- 绿色代表已经就位的元素 + +![88.merge-sorted-array-1](../assets/problems/88.merge-sorted-array-1.png) +![88.merge-sorted-array-2](../assets/problems/88.merge-sorted-array-2.png) +![88.merge-sorted-array-3](../assets/problems/88.merge-sorted-array-3.png) + +## 关键点解析 + +- 从后往前比较,并从后往前插入 + +## 代码 + +代码支持:Python3, C++, JavaScript + + +JavaSCript Code: + +```js +var merge = function(nums1, m, nums2, n) { + // 设置一个指针,指针初始化指向nums1的末尾(根据#62,应该是index为 m+n-1 的位置,因为nums1的长度有可能更长) + // 然后不断左移指针更新元素 + let current = m + n - 1; + + while (current >= 0) { + // 没必要继续了 + if (n === 0) return; + + // 为了方便大家理解,这里代码有点赘余 + if (m < 1) { + nums1[current--] = nums2[--n]; + continue; + } + + if (n < 1) { + nums1[current--] = nums1[--m]; + continue; + } + // 取大的填充 nums1的末尾 + // 然后更新 m 或者 n + if (nums1[m - 1] > nums2[n - 1]) { + nums1[current--] = nums1[--m]; + } else { + nums1[current--] = nums2[--n]; + } + } +}; +``` + +C++ code: +``` +class Solution { +public: + void merge(vector& nums1, int m, vector& nums2, int n) { + int current = m + n - 1; + while (current >= 0) { + if (n == 0) return; + if (m < 1) { + nums1[current--] = nums2[--n]; + continue; + } + if (n < 1) { + nums1[current--] = nums1[--m]; + continue; + } + if (nums1[m - 1] > nums2[n - 1]) nums1[current--] = nums1[--m]; + else nums1[current--] = nums2[--n]; + } + } +}; +``` + +Python Code +```python +class Solution: + def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: + """ + Do not return anything, modify nums1 in-place instead. + """ + # 整体思路相似,只不过没有使用 current 指针记录当前填补位置 + while m > 0 and n > 0: + if nums1[m-1] <= nums2[n-1]: + nums1[m+n-1] = nums2[n-1] + n -= 1 + else: + nums1[m+n-1] = nums1[m-1] + m -=1 + """ + 由于没有使用 current,第一步比较结束后有两种情况: + 1. 指针 m>0,n=0,此时不需要做任何处理 + 2. 指针 n>0,m=0,此时需要将 nums2 指针左侧元素全部拷贝到 nums1 的前 n 位 + """ + if n > 0: + nums1[:n] = nums2[:n] +``` + + +**复杂度分析** +- 时间复杂度:$O(M + N)$ +- 空间复杂度:$O(1)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/887.super-egg-drop.md b/spider/row-markdown/887.super-egg-drop.md new file mode 100644 index 0000000..2d6d9b4 --- /dev/null +++ b/spider/row-markdown/887.super-egg-drop.md @@ -0,0 +1,130 @@ + +## 题目地址 +https://leetcode.com/problems/super-egg-drop/description/ + +## 题目描述 + +``` +You are given K eggs, and you have access to a building with N floors from 1 to N. + +Each egg is identical in function, and if an egg breaks, you cannot drop it again. + +You know that there exists a floor F with 0 <= F <= N such that any egg dropped at a floor higher than F will break, and any egg dropped at or below floor F will not break. + +Each move, you may take an egg (if you have an unbroken one) and drop it from any floor X (with 1 <= X <= N). + +Your goal is to know with certainty what the value of F is. + +What is the minimum number of moves that you need to know with certainty what F is, regardless of the initial value of F? + + + +Example 1: + +Input: K = 1, N = 2 +Output: 2 +Explanation: +Drop the egg from floor 1. If it breaks, we know with certainty that F = 0. +Otherwise, drop the egg from floor 2. If it breaks, we know with certainty that F = 1. +If it didn't break, then we know with certainty F = 2. +Hence, we needed 2 moves in the worst case to know what F is with certainty. +Example 2: + +Input: K = 2, N = 6 +Output: 3 +Example 3: + +Input: K = 3, N = 14 +Output: 4 + + +Note: + +1 <= K <= 100 +1 <= N <= 10000 + + +``` + +## 思路 + +这是一道典型的动态规划题目,但是又和一般的动态规划不一样。 + +拿题目给的例子为例,两个鸡蛋,六层楼,我们最少扔几次? + +![887.super-egg-drop-1](../assets/problems/887.super-egg-drop-1.png) + +一个符合直觉的做法是,建立dp[i][j], 代表i个鸡蛋,j层楼最少扔几次,然后我们取dp[K][N]即可。 + +代码大概这样的: + +```js + const dp = Array(K + 1); + dp[0] = Array(N + 1).fill(0); + for (let i = 1; i < K + 1; i++) { + dp[i] = [0]; + for (let j = 1; j < N + 1; j++) { + // 只有一个鸡蛋 + if (i === 1) { + dp[i][j] = j; + continue; + } + // 只有一层楼 + if (j === 1) { + dp[i][j] = 1; + continue; + } + + // 每一层我们都模拟一遍 + const all = []; + for (let k = 1; k < j + 1; k++) { + const brokenCount = dp[i - 1][k - 1]; // 如果碎了 + const notBrokenCount = dp[i][j - k]; // 如果没碎 + all.push(Math.max(brokenCount, notBrokenCount)); // 最坏的可能 + } + dp[i][j] = Math.min(...all) + 1; // 最坏的集合中我们取最好的情况 + } + } + + return dp[K][N]; +``` + +果不其然,当我提交的时候,超时了。 这个的时复杂度是很高的,可以看到,我们内层暴力的求解所有可能,然后 +取最好的,这个过程非常耗时,大概是O(N^2 * K). + +然后我看了一位leetcode[网友](https://leetcode.com/lee215/)的回答, +他的想法是`dp[M][K]means that, given K eggs and M moves,what is the maximum number of floor that we can check.` + +我们按照他的思路重新建模: + +![887.super-egg-drop-2](../assets/problems/887.super-egg-drop-2.png) + +可以看到右下角的部分根本就不需要计算,从而节省很多时间 +## 关键点解析 + +- dp建模思路要发生变化, 即 +`dp[M][K]means that, given K eggs and M moves,what is the maximum number of floor that we can check.` + + +## 代码 + + +```js +/** + * @param {number} K + * @param {number} N + * @return {number} + */ +var superEggDrop = function(K, N) { + // 不选择dp[K][M]的原因是dp[M][K]可以简化操作 + const dp = Array(N + 1).fill(0).map(_ => Array(K + 1).fill(0)) + + let m = 0; + while (dp[m][K] < N) { + m++; + for (let k = 1; k <= K; ++k) + dp[m][k] = dp[m - 1][k - 1] + 1 + dp[m - 1][k]; + } + return m; +}; +``` diff --git a/spider/row-markdown/895.maximum-frequency-stack.md b/spider/row-markdown/895.maximum-frequency-stack.md new file mode 100644 index 0000000..b7d4eb8 --- /dev/null +++ b/spider/row-markdown/895.maximum-frequency-stack.md @@ -0,0 +1,114 @@ +## 题目地址(895. 最大频率栈) + +https://leetcode-cn.com/problems/maximum-frequency-stack/ + +## 题目描述 + +``` +实现 FreqStack,模拟类似栈的数据结构的操作的一个类。 + +FreqStack 有两个函数: + +push(int x),将整数 x 推入栈中。 +pop(),它移除并返回栈中出现最频繁的元素。 +如果最频繁的元素不只一个,则移除并返回最接近栈顶的元素。 +  + +示例: + +输入: +["FreqStack","push","push","push","push","push","push","pop","pop","pop","pop"], +[[],[5],[7],[5],[7],[4],[5],[],[],[],[]] +输出:[null,null,null,null,null,null,null,5,7,5,4] +解释: +执行六次 .push 操作后,栈自底向上为 [5,7,5,7,4,5]。然后: + +pop() -> 返回 5,因为 5 是出现频率最高的。 +栈变成 [5,7,5,7,4]。 + +pop() -> 返回 7,因为 5 和 7 都是频率最高的,但 7 最接近栈顶。 +栈变成 [5,7,5,4]。 + +pop() -> 返回 5 。 +栈变成 [5,7,4]。 + +pop() -> 返回 4 。 +栈变成 [5,7]。 +  + +提示: + +对 FreqStack.push(int x) 的调用中 0 <= x <= 10^9。 +如果栈的元素数目为零,则保证不会调用  FreqStack.pop()。 +单个测试样例中,对 FreqStack.push 的总调用次数不会超过 10000。 +单个测试样例中,对 FreqStack.pop 的总调用次数不会超过 10000。 +所有测试样例中,对 FreqStack.push 和 FreqStack.pop 的总调用次数不会超过 150000。 + +``` + +## 思路 + +我们以题目给的例子来讲解。 + +- 使用fraq 来存储对应的数字出现次数。key 是数字,value频率 + +![](https://tva1.sinaimg.cn/large/00831rSTly1gda26lkj3aj30d00la76l.jpg) + +- 由于题目限制“如果最频繁的元素不只一个,则移除并返回最接近栈顶的元素。”,我们考虑使用栈来维护一个频率表 fraq_stack。key是频率,value是数字组成的栈。 + +![](https://tva1.sinaimg.cn/large/00831rSTly1gda28hw3gaj30k20i8n10.jpg) + +- 同时用max_fraq 记录当前的最大频率值。 + +- 第一次pop的时候,我们最大的频率是3。由fraq_stack 知道我们需要pop掉5。 + +![](https://tva1.sinaimg.cn/large/00831rSTly1gda2aojd9pj31160nadmq.jpg) + +- 之后pop依次是这样的(红色数字表示顺序) + +![](https://tva1.sinaimg.cn/large/00831rSTly1gda2ci160nj30pk0ki42y.jpg) + +## 关键点解析 + +- 栈的基本性质 +- hashtable的基本性质 +- push和pop的时候同时更新fraq,max_fraq 和 fraq_stack。 + +## 代码 + +```python +class FreqStack: + + def __init__(self): + self.fraq = collections.defaultdict(lambda: 0) + self.fraq_stack = collections.defaultdict(list) + self.max_fraq = 0 + + def push(self, x: int) -> None: + self.fraq[x] += 1 + if self.fraq[x] > self.max_fraq: + self.max_fraq = self.fraq[x] + self.fraq_stack[self.fraq[x]].append(x) + + def pop(self) -> int: + ans = self.fraq_stack[self.max_fraq].pop() + self.fraq[ans] -= 1 + if not self.fraq_stack[self.max_fraq]: + self.max_fraq -= 1 + return ans + +# Your FreqStack object will be instantiated and called as such: +# obj = FreqStack() +# obj.push(x) +# param_2 = obj.pop() +``` + +***复杂度分析*** +- 时间复杂度:push 和 pop 平均时间复杂度是 $O(1)$ +- 空间复杂度:$O(N)$,其中N为数字的总数。 + +大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) + + diff --git a/spider/row-markdown/90.subsets-ii-en.md b/spider/row-markdown/90.subsets-ii-en.md new file mode 100644 index 0000000..a17cb31 --- /dev/null +++ b/spider/row-markdown/90.subsets-ii-en.md @@ -0,0 +1,166 @@ +## Problem Link + +https://leetcode.com/problems/subsets-ii/description/ + +## Description +``` +Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set). + +Note: The solution set must not contain duplicate subsets. + +Example: + +Input: [1,2,2] +Output: +[ + [2], + [1], + [1,2,2], + [2,2], + [1,2], + [] +] + +``` + +## Solution + +Since this problem is seeking `Subset` not `Extreme Value`, dynamic programming is not an ideal solution. Other approaches should be taken into our consideration. + +Actually, there is a general approach to solve problems similar to this one -- backtracking. Given a [Code Template](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)) here, it demonstrates how backtracking works with varieties of problems. Apart from current one, many problems can be solved by such a general approach. For more details, please check the `Related Problems` section below. + +Given a picture as followed, let's start with problem-solving ideas of this general solution. + +![backtrack](../assets/problems/backtrack.png) + +See Code Template details below. + +## Key Points + +- Backtrack Approach +- Backtrack Code Template/ Formula + +## Code + +* Supported Language:JS,C++,Python3 + +JavaScript Code: + +```js + + +/* + * @lc app=leetcode id=90 lang=javascript + * + * [90] Subsets II + * + * https://leetcode.com/problems/subsets-ii/description/ + * + * algorithms + * Medium (41.53%) + * Total Accepted: 197.1K + * Total Submissions: 469.1K + * Testcase Example: '[1,2,2]' + * + * Given a collection of integers that might contain duplicates, nums, return + * all possible subsets (the power set). + * + * Note: The solution set must not contain duplicate subsets. + * + * Example: + * + * + * Input: [1,2,2] + * Output: + * [ + * ⁠ [2], + * ⁠ [1], + * ⁠ [1,2,2], + * ⁠ [2,2], + * ⁠ [1,2], + * ⁠ [] + * ] + * + * + */ +function backtrack(list, tempList, nums, start) { + list.push([...tempList]); + for(let i = start; i < nums.length; i++) { + //nums can be duplicated, which is different from Problem 78 - subsets + //So the situation should be taken into consideration + if (i > start && nums[i] === nums[i - 1]) continue; + tempList.push(nums[i]); + backtrack(list, tempList, nums, i + 1) + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var subsetsWithDup = function(nums) { + const list = []; + backtrack(list, [], nums.sort((a, b) => a - b), 0, []) + return list; +}; +``` +C++ Code: + +```C++ +class Solution { +private: + void subsetsWithDup(vector& nums, size_t start, vector& tmp, vector>& res) { + res.push_back(tmp); + for (auto i = start; i < nums.size(); ++i) { + if (i > start && nums[i] == nums[i - 1]) continue; + tmp.push_back(nums[i]); + subsetsWithDup(nums, i + 1, tmp, res); + tmp.pop_back(); + } + } +public: + vector> subsetsWithDup(vector& nums) { + auto tmp = vector(); + auto res = vector>(); + sort(nums.begin(), nums.end()); + subsetsWithDup(nums, 0, tmp, res); + return res; + } +}; +``` +Python Code: + +```Python +class Solution: + def subsetsWithDup(self, nums: List[int], sorted: bool=False) -> List[List[int]]: + """Backtrack Approach: by sorting parameters first to avoid repeting sort later""" + if not nums: + return [[]] + elif len(nums) == 1: + return [[], nums] + else: + # Sorting first to filter duplicated numbers + # Note,this problem takes higher time complexity + # So, it could greatly improve time efficiency by adding one parameter to avoid repeting sort in following procedures + if not sorted: + nums.sort() + # Backtrack Approach + pre_lists = self.subsetsWithDup(nums[:-1], sorted=True) + all_lists = [i+[nums[-1]] for i in pre_lists] + pre_lists + # distinct elements + result = [] + for i in all_lists: + if i not in result: + result.append(i) + return result +``` + +## Related Problems + +- [39.combination-sum](./39.combination-sum.md)(chinese) +- [40.combination-sum-ii](./40.combination-sum-ii.md)(chinese) +- [46.permutations](./46.permutations.md)(chinese) +- [47.permutations-ii](./47.permutations-ii.md)(chinese) +- [78.subsets](./78.subsets-en.md) +- [113.path-sum-ii](./113.path-sum-ii.md)(chinese) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md)(chinese) diff --git a/spider/row-markdown/90.subsets-ii.md b/spider/row-markdown/90.subsets-ii.md new file mode 100644 index 0000000..36c2e84 --- /dev/null +++ b/spider/row-markdown/90.subsets-ii.md @@ -0,0 +1,174 @@ + +## 题目地址 +https://leetcode.com/problems/subsets-ii/description/ + +## 题目描述 +``` +Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set). + +Note: The solution set must not contain duplicate subsets. + +Example: + +Input: [1,2,2] +Output: +[ + [2], + [1], + [1,2,2], + [2,2], + [1,2], + [] +] + +``` + +## 思路 + +这道题目是求集合,并不是`求极值`,因此动态规划不是特别切合,因此我们需要考虑别的方法。 + +这种题目其实有一个通用的解法,就是回溯法。 +网上也有大神给出了这种回溯法解题的 +[通用写法](https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)),这里的所有的解法使用通用方法解答。 +除了这道题目还有很多其他题目可以用这种通用解法,具体的题目见后方相关题目部分。 + +我们先来看下通用解法的解题思路,我画了一张图: + +![backtrack](../assets/problems/backtrack.png) + +通用写法的具体代码见下方代码区。 + +## 关键点解析 + +- 回溯法 +- backtrack 解题公式 + + +## 代码 + +* 语言支持:JS,C++,Python3 + +JavaScript Code: + +```js + + +/* + * @lc app=leetcode id=90 lang=javascript + * + * [90] Subsets II + * + * https://leetcode.com/problems/subsets-ii/description/ + * + * algorithms + * Medium (41.53%) + * Total Accepted: 197.1K + * Total Submissions: 469.1K + * Testcase Example: '[1,2,2]' + * + * Given a collection of integers that might contain duplicates, nums, return + * all possible subsets (the power set). + * + * Note: The solution set must not contain duplicate subsets. + * + * Example: + * + * + * Input: [1,2,2] + * Output: + * [ + * ⁠ [2], + * ⁠ [1], + * ⁠ [1,2,2], + * ⁠ [2,2], + * ⁠ [1,2], + * ⁠ [] + * ] + * + * + */ +function backtrack(list, tempList, nums, start) { + list.push([...tempList]); + for(let i = start; i < nums.length; i++) { + // 和78.subsets的区别在于这道题nums可以有重复 + // 因此需要过滤这种情况 + if (i > start && nums[i] === nums[i - 1]) continue; + tempList.push(nums[i]); + backtrack(list, tempList, nums, i + 1) + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var subsetsWithDup = function(nums) { + const list = []; + backtrack(list, [], nums.sort((a, b) => a - b), 0, []) + return list; +}; +``` +C++ Code: + +```C++ +class Solution { +private: + void subsetsWithDup(vector& nums, size_t start, vector& tmp, vector>& res) { + res.push_back(tmp); + for (auto i = start; i < nums.size(); ++i) { + if (i > start && nums[i] == nums[i - 1]) continue; + tmp.push_back(nums[i]); + subsetsWithDup(nums, i + 1, tmp, res); + tmp.pop_back(); + } + } +public: + vector> subsetsWithDup(vector& nums) { + auto tmp = vector(); + auto res = vector>(); + sort(nums.begin(), nums.end()); + subsetsWithDup(nums, 0, tmp, res); + return res; + } +}; +``` +Python Code: + +```Python +class Solution: + def subsetsWithDup(self, nums: List[int], sorted: bool=False) -> List[List[int]]: + """回溯法,通过排序参数避免重复排序""" + if not nums: + return [[]] + elif len(nums) == 1: + return [[], nums] + else: + # 先排序,以便去重 + # 注意,这道题排序花的时间比较多 + # 因此,增加一个参数,使后续过程不用重复排序,可以大幅提高时间效率 + if not sorted: + nums.sort() + # 回溯法 + pre_lists = self.subsetsWithDup(nums[:-1], sorted=True) + all_lists = [i+[nums[-1]] for i in pre_lists] + pre_lists + # 去重 + result = [] + for i in all_lists: + if i not in result: + result.append(i) + return result +``` + +## 相关题目 + +- [39.combination-sum](./39.combination-sum.md) +- [40.combination-sum-ii](./40.combination-sum-ii.md) +- [46.permutations](./46.permutations.md) +- [47.permutations-ii](./47.permutations-ii.md) +- [78.subsets](./78.subsets.md) +- [113.path-sum-ii](./113.path-sum-ii.md) +- [131.palindrome-partitioning](./131.palindrome-partitioning.md) + + + + diff --git a/spider/row-markdown/900.rle-iterator.md b/spider/row-markdown/900.rle-iterator.md new file mode 100644 index 0000000..0ad6267 --- /dev/null +++ b/spider/row-markdown/900.rle-iterator.md @@ -0,0 +1,110 @@ +## 题目地址 + +https://leetcode.com/problems/rle-iterator/description/ + +## 题目描述 + +``` +Write an iterator that iterates through a run-length encoded sequence. + +The iterator is initialized by RLEIterator(int[] A), where A is a run-length encoding of some sequence. More specifically, for all even i, A[i] tells us the number of times that the non-negative integer value A[i+1] is repeated in the sequence. + +The iterator supports one function: next(int n), which exhausts the next n elements (n >= 1) and returns the last element exhausted in this way. If there is no element left to exhaust, next returns -1 instead. + +For example, we start with A = [3,8,0,9,2,5], which is a run-length encoding of the sequence [8,8,8,5,5]. This is because the sequence can be read as "three eights, zero nines, two fives". + + + +Example 1: + +Input: ["RLEIterator","next","next","next","next"], [[[3,8,0,9,2,5]],[2],[1],[1],[2]] +Output: [null,8,8,5,-1] +Explanation: +RLEIterator is initialized with RLEIterator([3,8,0,9,2,5]). +This maps to the sequence [8,8,8,5,5]. +RLEIterator.next is then called 4 times: + +.next(2) exhausts 2 terms of the sequence, returning 8. The remaining sequence is now [8, 5, 5]. + +.next(1) exhausts 1 term of the sequence, returning 8. The remaining sequence is now [5, 5]. + +.next(1) exhausts 1 term of the sequence, returning 5. The remaining sequence is now [5]. + +.next(2) exhausts 2 terms, returning -1. This is because the first term exhausted was 5, +but the second term did not exist. Since the last term exhausted does not exist, we return -1. + +Note: + +0 <= A.length <= 1000 +A.length is an even integer. +0 <= A[i] <= 10^9 +There are at most 1000 calls to RLEIterator.next(int n) per test case. +Each call to RLEIterator.next(int n) will have 1 <= n <= 10^9. + +``` + +## 思路 + +这是一个游程编码的典型题目。 + +该算法分为两个部分,一个是初始化,一个是调用`next(n)`. + +我们需要做的就是初始化的时候,记住这个A。 然后每次调用`next(n)`的时候只需要 + +判断n是否大于A[i](i从0开始) + +- 如果大于A[i], 那就说明不够,我们移除数组前两项,更新n,重复1 + +- 如果小于A[i], 则说明够了,更新A[i] + +这样做,我们每次都要更新A,还有一种做法就是不更新A,而是`伪更新`,即用一个变量记录,当前访问到的数组位置。 + +> 很多时候我们需要原始的,那么就必须这种放了,我的解法就是这种方法。 + + +## 关键点解析 + + + +## 代码 + +```js +/** + * @param {number[]} A + */ +var RLEIterator = function(A) { + this.A = A; + this.current = 0; +}; + + +/** + * @param {number} n + * @return {number} + */ +RLEIterator.prototype.next = function(n) { + const A = this.A; + while(this.current < A.length && A[this.current] < n){ + n = n - A[this.current]; + this.current += 2; + } + + if(this.current >= A.length){ + return -1; + } + + A[this.current] = A[this.current] - n; // 更新Count + return A[this.current + 1]; // 返回element +}; + +/** + * Your RLEIterator object will be instantiated and called as such: + * var obj = new RLEIterator(A) + * var param_1 = obj.next(n) + */ +``` + +## 扩展阅读 + +[哈夫曼编码和游程编码](../thinkings/run-length-encode-and-huffman-encode.md) + diff --git a/spider/row-markdown/91.decode-ways.md b/spider/row-markdown/91.decode-ways.md new file mode 100644 index 0000000..c7bb381 --- /dev/null +++ b/spider/row-markdown/91.decode-ways.md @@ -0,0 +1,129 @@ + +## 题目地址 +https://leetcode.com/problems/decode-ways/description/ + +## 题目描述 +``` +A message containing letters from A-Z is being encoded to numbers using the following mapping: + +'A' -> 1 +'B' -> 2 +... +'Z' -> 26 +Given a non-empty string containing only digits, determine the total number of ways to decode it. + +Example 1: + +Input: "12" +Output: 2 +Explanation: It could be decoded as "AB" (1 2) or "L" (12). +Example 2: + +Input: "226" +Output: 3 +Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6). +``` + +## 思路 + +这道题目和爬楼梯问题有异曲同工之妙。 + +这也是一道典型的动态规划题目。我们来思考: + +- 对于一个数字来说[1,9]这九个数字能够被识别为一种编码方式 +- 对于两个数字来说[10, 26]这几个数字能被识别为一种编码方式 + +我们考虑用dp[i]来切分子问题, 那么dp[i]表示的意思是当前字符串的以索引i结尾的子问题。 +这样的话,我们最后只需要取dp[s.length] 就可以解决问题了。 + +关于递归公式,让我们`先局部后整体`。对于局部,我们遍历到一个元素的时候, +我们有两种方式来组成编码方式,第一种是这个元素本身(需要自身是[1,9]), +第二种是它和前一个元素组成[10, 26]。 用伪代码来表示的话就是: +`dp[i] = 以自身去编码(一位) + 以前面的元素和自身去编码(两位)` .这显然是完备的, +这样我们通过层层推导就可以得到结果。 + + +## 关键点解析 + +- 爬楼梯问题(我把这种题目统称为爬楼梯问题) + + +## 代码 + +```js + + +/* + * @lc app=leetcode id=91 lang=javascript + * + * [91] Decode Ways + * + * https://leetcode.com/problems/decode-ways/description/ + * + * algorithms + * Medium (21.93%) + * Total Accepted: 254.4K + * Total Submissions: 1.1M + * Testcase Example: '"12"' + * + * A message containing letters from A-Z is being encoded to numbers using the + * following mapping: + * + * + * 'A' -> 1 + * 'B' -> 2 + * ... + * 'Z' -> 26 + * + * + * Given a non-empty string containing only digits, determine the total number + * of ways to decode it. + * + * Example 1: + * + * + * Input: "12" + * Output: 2 + * Explanation: It could be decoded as "AB" (1 2) or "L" (12). + * + * + * Example 2: + * + * + * Input: "226" + * Output: 3 + * Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 + * 6). + * + */ +/** + * @param {string} s + * @return {number} + */ +var numDecodings = function(s) { + if (s == null || s.length == 0) { + return 0; + } + const dp = Array(s.length + 1).fill(0); + dp[0] = 1; + dp[1] = s[0] !== "0" ? 1 : 0; + for (let i = 2; i < s.length + 1; i++) { + const one = +s.slice(i - 1, i); + const two = +s.slice(i - 2, i); + + if (two >= 10 && two <= 26) { + dp[i] = dp[i - 2]; + } + + if (one >= 1 && one <= 9) { + dp[i] += dp[i - 1]; + } + } + + return dp[dp.length - 1]; +}; +``` + +## 扩展 + +如果编码的范围不再是1-26,而是三位的话怎么办? diff --git a/spider/row-markdown/912.sort-an-array.md b/spider/row-markdown/912.sort-an-array.md new file mode 100644 index 0000000..f98daf5 --- /dev/null +++ b/spider/row-markdown/912.sort-an-array.md @@ -0,0 +1,154 @@ + +## 题目地址 +https://leetcode.com/problems/sort-an-array/ + +## 题目描述 +``` +Given an array of integers nums, sort the array in ascending order. + + + +Example 1: + +Input: [5,2,3,1] +Output: [1,2,3,5] +Example 2: + +Input: [5,1,1,2,0,0] +Output: [0,0,1,1,2,5] + + +Note: + +1 <= A.length <= 10000 +-50000 <= A[i] <= 50000 +``` + +## 思路 + +这是一个很少见的直接考察`排序`的题目。 其他题目一般都是暗含`排序`,这道题则简单粗暴,直接让你排序。 +并且这道题目的难度是`Medium`, 笔者感觉有点不可思议。 + +我们先来看题目的限制条件,这其实在选择算法的过程中是重要的。 看到这道题的时候,大脑就闪现出了各种排序算法, +这也算是一个复习`排序算法`的机会吧。 + +题目的限制条件是有两个,第一是元素个数不超过10k,这个不算大。 另外一个是数组中的每一项范围都是`-50k`到`50k`(包含左右区间)。 +看到这里,基本我就排除了时间复杂度为O(n^2)的算法。 + +> 我没有试时间复杂度 O(n^2) 的解法,大家可以试一下,看是不是会TLE。 + +剩下的就是基于比较的`nlogn`算法,以及基于特定条件的O(n)算法。 + +由于平时很少用到`计数排序`等O(n)的排序算法,一方面是空间复杂度不是常量,另一方面是其要求数据范围不是很大才行,不然会浪费很多空间。 +但是这道题我感觉可以试一下。 在这里,我用了两种方法,一种是`计数排序`,一种是`快速排序`来解决。 大家也可以尝试用别的解法来解决。 + +### 解法一 - 计数排序 + +时间复杂度O(n)空间复杂度O(m) m 为数组中值的取值范围,在这道题就是`50000 * 2 + 1`。 + +我们只需要准备一个数组取值范围的数字,然后遍历一遍,将每一个元素放到这个数组对应位置就好了, +放的规则是`索引为数字的值,value为出现的次数`。 + +这样一次遍历,我们统计出了所有的数字出现的位置和次数。 我们再来一次遍历,将其输出到即可。 + +![sort-an-array-1](../assets/problems/912.sort-an-array-1.png) + + +### 解法二 - 快速排序 + +快速排序和归并排序都是分支思想来进行排序的算法, 并且二者都非常流行。 快速排序的核心点在于选择轴元素。 + +每次我们将数组分成两部分,一部分是比pivot(轴元素)大的,另一部分是不比pivot大的。 我们不断重复这个过程, +直到问题的规模缩小的寻常(即只有一个元素的情况)。 + +快排的核心点在于如何选择轴元素,一般而言,选择轴元素有三种策略: + +- 数组最左边的元素 +- 数组最右边的元素 +- 数组中间的元素(我采用的是这种,大家可以尝试下别的) +- 数组随机一项元素 + + +![sort-an-array-2](../assets/problems/912.sort-an-array-2.png) + +(图片来自: https://www.geeksforgeeks.org/quick-sort/) + +> 图片中的轴元素是最后面的元素,而提供的解法是中间元素,这点需要注意,但是这并不影响理解。 + + +## 关键点解析 + +- 排序算法 +- 注意题目的限制条件从而选择合适的算法 + + +## 代码 + +计数排序: + +代码支持: JavaScript +```js +/** + * @param {number[]} nums + * @return {number[]} + */ +var sortArray = function(nums) { + const counts = Array(50000 * 2 + 1).fill(0); + const res = []; + for(const num of nums) counts[50000 + num] += 1; + for(let i in counts) { + while(counts[i]--) { + res.push(i - 50000) + } + } + return res; +}; +``` + + +快速排序: + +代码支持: JavaScript +```js +function swap(nums, a, b) { + const temp = nums[a]; + nums[a] = nums[b]; + nums[b] = temp; +} + +function helper(nums, start, end) { + if (start >= end) return; + const pivotIndex = start + ((end - start) >>> 1) + const pivot = nums[pivotIndex] + let i = start; + let j = end; + while (i <= j) { + while (nums[i] < pivot) i++; + while (nums[j] > pivot) j--; + if (i <= j) { + swap(nums, i, j); + i++; + j--; + } + } + helper(nums, start, j); + helper(nums, i, end); +} + +/** + * @param {number[]} nums + * @return {number[]} + */ +var sortArray = function(nums) { + helper(nums, 0, nums.length - 1); + return nums; +}; +``` + +## 扩展 + +- 你是否可以用其他方式排序算法解决 + +## 参考 + +- [QuickSort - geeksforgeeks](https://www.geeksforgeeks.org/quick-sort/) diff --git a/spider/row-markdown/92.reverse-linked-list-ii.md b/spider/row-markdown/92.reverse-linked-list-ii.md new file mode 100644 index 0000000..3278c21 --- /dev/null +++ b/spider/row-markdown/92.reverse-linked-list-ii.md @@ -0,0 +1,289 @@ +## 题目地址 +https://leetcode.com/problems/reverse-linked-list-ii/description/ + +## 题目描述 +Reverse a linked list from position m to n. Do it in one-pass. + +Note: 1 ≤ m ≤ n ≤ length of list. + +Example: + +Input: 1->2->3->4->5->NULL, m = 2, n = 4 +Output: 1->4->3->2->5->NULL + +## 思路 + +这道题和[206.reverse-linked-list](https://github.com/azl397985856/leetcode/blob/master/problems/206.reverse-linked-list.md) 有点类似,并且这道题是206的升级版。 让我们反转某一个区间,而不是整个链表,我们可以将206看作本题的特殊情况(special case)。 + +核心在于**取出需要反转的这一小段链表,反转完后再插入到原先的链表中。** + +以本题为例: + +反转的是2,3,4这三个点,那么我们可以先取出2,用cur指针指向2,然后当取出3的时候,我们将3指向2的,把cur指针前移到3,依次类推,到4后停止,这样我们得到一个新链表4->3->2, cur指针指向4。 + +对于原链表来说,有两个点的位置很重要,需要用指针记录下来,分别是1和5,把新链表插入的时候需要这两个点的位置。用pre指针记录1的位置当4结点被取走后,5的位置需要记下来 + +这样我们就可以把反转后的那一小段链表加入到原链表中 + +![92.reverse-linked-list-ii](../assets/92.reverse-linked-list-ii.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) + + +首先我们直接返回head是不行的。 当 m 不等于1的时候是没有问题的,但只要 m 为1,就会有问题。 + +```python +class Solution: + def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: + pre = None + cur = head + i = 0 + p1 = p2 = p3 = p4 = None + # ... + if p1: + p1.next = p3 + else: + dummy.next = p3 + if p2: + p2.next = p4 + return head +``` + + 如上代码是不可以的,我们考虑使用dummy节点。 + ```python + class Solution: + def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: + pre = None + cur = head + i = 0 + p1 = p2 = p3 = p4 = None + dummy = ListNode(0) + dummy.next = head + + # ... + + if p1: + p1.next = p3 + else: + dummy.next = p3 + if p2: + p2.next = p4 + + return dummy.next + ``` + + 关于链表反转部分, 顺序比较重要,我们需要: + + - 先 cur.next = pre + - 再 更新p2和p2.next(其中要设置p2.next = None,否则会互相应用,造成无限循环) + - 最后更新 pre 和 cur + + 上述的顺序不能错,不然会有问题。原因就在于`p2.next = None`,如果这个放在最后,那么我们的cur会提前断开。 + + ```python + while cur: + i += 1 + if i == m - 1: + p1 = cur + next = cur.next + if m < i <= n: + cur.next = pre + + if i == m: + p2 = cur + p2.next = None + + if i == n: + p3 = cur + + if i == n + 1: + p4 = cur + + pre = cur + cur = next + ``` + +## 关键点解析 + +- 链表的基本操作 +- 考虑特殊情况 m 是 1 或者 n是链表长度的情况,我们可以采用虚拟节点dummy 简化操作 +- 用四个变量记录特殊节点, 然后操作这四个节点使之按照一定方式连接即可。 +- 注意更新current和pre的位置, 否则有可能出现溢出 + + +## 代码 + +语言支持:JS, C++, Python3 + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=92 lang=javascript + * + * [92] Reverse Linked List II + * + * https://leetcode.com/problems/reverse-linked-list-ii/description/ + */ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} m + * @param {number} n + * @return {ListNode} + */ +var reverseBetween = function(head, m, n) { + // 虚拟节点,简化操作 + const dummyHead = { + next: head + } + + let cur = dummyHead.next; // 当前遍历的节点 + let pre = cur; // 因为要反转,因此我们需要记住前一个节点 + let index = 0; // 链表索引,用来判断是否是特殊位置(头尾位置) + + // 上面提到的四个特殊节点 + let p1 = p2 = p3 = p4 = null + + while(cur) { + const next = cur.next; + index++; + + // 对 (m - n) 范围内的节点进行反转 + if (index > m && index <= n) { + cur.next = pre; + } + + // 下面四个if都是边界, 用于更新四个特殊节点的值 + if (index === m - 1) { + p1 = cur; + } + if (index === m) { + p2 = cur; + } + + if (index === n) { + p3 = cur; + } + + if (index === n + 1) { + p4 = cur;; + } + + pre = cur; + + cur = next; + } + + // 两个链表合并起来 + (p1 || dummyHead).next = p3; // 特殊情况需要考虑 + p2.next = p4; + + return dummyHead.next; +}; + +``` +C++ Code: +```c++ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode* reverseBetween(ListNode* head, int s, int e) { + if (s == e) return head; + ListNode* prev = nullptr; + auto cur = head; + for (int i = 1; i < s; ++i) { + prev = cur; + cur = cur->next; + } + // 此时各指针指向: + // x -> x -> x -> x -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> x -> x -> x -> + // ^head ^prev ^cur + ListNode* p = nullptr; + auto c = cur; + auto tail = c; + ListNode* n = nullptr; + for (int i = s; i <= e; ++i) { + n = c->next; + c->next = p; + p = c; + c = n; + } + // 此时各指针指向: + // x -> x -> x -> x 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 x -> x -> x -> + // ^head ^prev ^p ^cur ^c + // ^tail + if (prev != nullptr) { // 若指向前一个节点的指针不为空,则说明s在链表中间(不是头节点) + prev->next = p; + cur->next = c; + return head; + } else { + if (tail != nullptr) tail->next = c; + return p; + } + } +}; +``` +Python Code: +```Python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: + """采用先翻转中间部分,之后与不变的前后部分拼接的思路""" + # 处理特殊情况 + if m == n: + return head + + # 例行性的先放一个开始节点,方便操作 + first = ListNode(0) + first.next = head + + # 通过以下两个节点记录拼接点 + before_m = first # 原链表m前的部分 + after_n = None # 原链表n后的部分 + + # 通过以下两个节点记录翻转后的链表 + between_mn_head = None + between_mn_end = None + + index = 0 + cur_node = first + while index < n: + index += 1 + cur_node = cur_node.next + if index == m - 1: + before_m = cur_node + elif index == m: + between_mn_end = ListNode(cur_node.val) + between_mn_head = between_mn_end + elif index > m: + temp = between_mn_head + between_mn_head = ListNode(cur_node.val) + between_mn_head.next = temp + if index == n: + after_n = cur_node.next + + # 进行拼接 + between_mn_end.next = after_n + before_m.next = between_mn_head + + return first.next +``` diff --git a/spider/row-markdown/935.knight-dialer.md b/spider/row-markdown/935.knight-dialer.md new file mode 100644 index 0000000..1e4aa39 --- /dev/null +++ b/spider/row-markdown/935.knight-dialer.md @@ -0,0 +1,115 @@ + +## 题目地址 (935. 骑士拨号器) +https://leetcode-cn.com/problems/knight-dialer/ + +## 题目描述 +``` +国际象棋中的骑士可以按下图所示进行移动: + +``` + +![](https://tva1.sinaimg.cn/large/00831rSTly1gcgzhjw437j305305p3yi.jpg) + +```           + +这一次,我们将 “骑士” 放在电话拨号盘的任意数字键(如上图所示)上,接下来,骑士将会跳 N-1 步。每一步必须是从一个数字键跳到另一个数字键。 + +每当它落在一个键上(包括骑士的初始位置),都会拨出键所对应的数字,总共按下 N 位数字。 + +你能用这种方式拨出多少个不同的号码? + +因为答案可能很大,所以输出答案模 10^9 + 7。 + +  + +示例 1: + +输入:1 +输出:10 +示例 2: + +输入:2 +输出:20 +示例 3: + +输入:3 +输出:46 +  + +提示: + +1 <= N <= 5000 + +``` + +## 深度优先遍历(DFS) + +### 思路 + +这道题要求解一个数字。并且每一个格子能够跳的状态是确定的。 因此我们的思路就是“状态机”(动态规划),暴力遍历(BFS or DFS),这里我们使用 DFS。(注意这几种思路并无本质不同) + +对于每一个号码键盘,我们可以转移的状态是确定的,我们做一个”预处理“,将这些状态转移记录到一个数组 jump,其中 jump[i] 表示 i 位置可以跳的点(用一个数组来表示)。问题转化为: + +- 从 0 开始所有的路径 +- 从 1 开始所有的路径 +- 从 2 开始所有的路径 +- ... +- 从 9 开始所有的路径 + +不管从几开始思路都是一样的。 我们使用一个函数 f(i, n) 表示`骑士在 i 的位置,还剩下 N 步可以走`的时候可以拨出的总的号码数。那么问题就是求解 `f(0, N) + f(1, N) + f(2, N) + ... + f(9, N)`。对于 f(i, n),我们初始化 cnt 为 0,由于 i 能跳的格子是 jump[i],我们将其 `cnt += f(j, n - 1)`,其中 j 属于 jump[i],最终返回 cnt 即可。 + +不难看出,这种算法有大量重复计算,我们使用记忆化递归形式来减少重复计算。 这种算法勉强通过。 + +### 代码 + +```python +class Solution: + def knightDialer(self, N: int) -> int: + cnt = 0 + jump = [[4, 6], [6, 8], [7, 9], [4, 8], [ + 0, 3, 9], [], [0, 1, 7], [2, 6], [1, 3], [2, 4]] + visited = dict() + + def helper(i, n): + if (i, n) in visited: return visited[(i, n)] + if n == 1: + return 1 + cnt = 0 + for j in jump[i]: + cnt += helper(j, n - 1) + visited[(i, n)] = cnt + return cnt + for i in range(10): + cnt += helper(i, N) + return cnt % (10**9 + 7) +``` + +**复杂度分析** +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(N)$ + +## 朴素遍历 + +### 思路 + +我们使用迭代的形式来优化上述过程。我们初始化十个变量分别表示键盘不同位置能够拨出的号码数,并且初始化为 1。接下来我们只要循环 N - 1 次,不断更新状态即可。不过这种算法和上述算法并无本质不同。 + +### 代码 + +```python +class Solution: + def knightDialer(self, N: int) -> int: + a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 1 + for _ in range(N - 1): + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = a4 + a6, a6 + a8, a7 + \ + a9, a4 + a8, a0 + a3 + a9, 0, a0 + a1 + a7, a2 + a6, a1 + a3, a2 + a4 + return (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9) % (10**9 + 7) +``` + +**复杂度分析** +- 时间复杂度:$O(N)$ +- 空间复杂度:$O(1)$ + +欢迎关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 + +![](https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502) diff --git a/spider/row-markdown/94.binary-tree-inorder-traversal.md b/spider/row-markdown/94.binary-tree-inorder-traversal.md new file mode 100644 index 0000000..4c8c02a --- /dev/null +++ b/spider/row-markdown/94.binary-tree-inorder-traversal.md @@ -0,0 +1,270 @@ +## 题目地址 +https://leetcode.com/problems/binary-tree-inorder-traversal/description/ + +## 题目描述 +``` +Given a binary tree, return the inorder traversal of its nodes' values. + +Example: + +Input: [1,null,2,3] + 1 + \ + 2 + / + 3 + +Output: [1,3,2] +Follow up: Recursive solution is trivial, could you do it iteratively? +``` +## 思路 + +递归的方式相对简单,非递归的方式借助栈这种数据结构实现起来会相对轻松。 + +如果采用非递归,可以用栈(Stack)的思路来处理问题。 + +中序遍历的顺序为左-根-右,具体算法为: + +- 从根节点开始,先将根节点压入栈 + +- 然后再将其所有左子结点压入栈,取出栈顶节点,保存节点值 + +- 再将当前指针移到其右子节点上,若存在右子节点,则在下次循环时又可将其所有左子结点压入栈中, 重复上步骤 + +![94.binary-tree-inorder-traversal](../assets/94.binary-tree-inorder-traversal.gif) + +(图片来自: https://github.com/MisterBooo/LeetCodeAnimation) +## 关键点解析 + +- 二叉树的基本操作(遍历) +> 不同的遍历算法差异还是蛮大的 +- 如果非递归的话利用栈来简化操作 + +- 如果数据规模不大的话,建议使用递归 + +- 递归的问题需要注意两点,一个是终止条件,一个如何缩小规模 + +1. 终止条件,自然是当前这个元素是null(链表也是一样) + +2. 由于二叉树本身就是一个递归结构, 每次处理一个子树其实就是缩小了规模, +难点在于如何合并结果,这里的合并结果其实就是`left.concat(mid).concat(right)`, +mid是一个具体的节点,left和right`递归求出即可` + + +## 代码 + +* 语言支持:JS,C++,Python3, Java + +JavaScript Code: + +```js +/* + * @lc app=leetcode id=94 lang=javascript + * + * [94] Binary Tree Inorder Traversal + * + * https://leetcode.com/problems/binary-tree-inorder-traversal/description/ + * + * algorithms + * Medium (55.22%) + * Total Accepted: 422.4K + * Total Submissions: 762.1K + * Testcase Example: '[1,null,2,3]' + * + * Given a binary tree, return the inorder traversal of its nodes' values. + * + * Example: + * + * + * Input: [1,null,2,3] + * ⁠ 1 + * ⁠ \ + * ⁠ 2 + * ⁠ / + * ⁠ 3 + * + * Output: [1,3,2] + * + * Follow up: Recursive solution is trivial, could you do it iteratively? + * + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +var inorderTraversal = function(root) { + // 1. Recursive solution + // if (!root) return []; + // const left = root.left ? inorderTraversal(root.left) : []; + // const right = root.right ? inorderTraversal(root.right) : []; + // return left.concat([root.val]).concat(right); + + // 2. iterative solutuon + if (!root) return []; + const stack = [root]; + const ret = []; + let left = root.left; + + let item = null; // stack 中弹出的当前项 + + while(left) { + stack.push(left); + left = left.left; + } + + while(item = stack.pop()) { + ret.push(item.val); + let t = item.right; + + while(t) { + stack.push(t); + t = t.left; + } + } + + return ret; + +}; + +``` +C++ Code: + +```c++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + vector inorderTraversal(TreeNode* root) { + vector s; + vector v; + while (root != NULL || !s.empty()) { + for (; root != NULL; root = root->left) + s.push_back(root); + v.push_back(s.back()->val); + root = s.back()->right; + s.pop_back(); + } + return v; + } +}; +``` +Python Code: +```Python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + def inorderTraversal(self, root: TreeNode) -> List[int]: + """ + 1. 递归法可以一行代码完成,无需讨论; + 2. 迭代法一般需要通过一个栈保存节点顺序,我们这里直接使用列表 + - 首先,我要按照中序遍历的顺序存入栈,这边用的逆序,方便从尾部开始处理 + - 在存入栈时加入一个是否需要深化的参数 + - 在回头取值时,这个参数应该是否,即直接取值 + - 简单调整顺序,即可实现前序和后序遍历 + """ + # 递归法 + # if root is None: + # return [] + # return self.inorderTraversal(root.left)\ + # + [root.val]\ + # + self.inorderTraversal(root.right) + # 迭代法 + result = [] + stack = [(1, root)] + while stack: + go_deeper, node = stack.pop() + if node is None: + continue + if go_deeper: + # 左右节点还需继续深化,并且入栈是先右后左 + stack.append((1, node.right)) + # 节点自身已遍历,回头可以直接取值 + stack.append((0, node)) + stack.append((1, node.left)) + else: + result.append(node.val) + return result +``` + +Java Code: + +- recursion + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + List res = new LinkedList<>(); + public List inorderTraversal(TreeNode root) { + inorder(root); + return res; + } + + public void inorder (TreeNode root) { + if (root == null) return; + + inorder(root.left); + + res.add(root.val); + + inorder(root.right); + } +} +``` + +- iteration + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public List inorderTraversal(TreeNode root) { + List res = new ArrayList<> (); + Stack stack = new Stack<> (); + + while (root != null || !stack.isEmpty()) { + while (root != null) { + stack.push(root); + root = root.left; + } + root = stack.pop(); + res.add(root.val); + root = root.right; + } + return res; + } +} +``` diff --git a/spider/row-markdown/95.unique-binary-search-trees-ii.md b/spider/row-markdown/95.unique-binary-search-trees-ii.md new file mode 100644 index 0000000..603c8e4 --- /dev/null +++ b/spider/row-markdown/95.unique-binary-search-trees-ii.md @@ -0,0 +1,78 @@ +## 题目地址(95. 不同的二叉搜索树 II) + +https://leetcode-cn.com/problems/unique-binary-search-trees-ii/description/ + +## 题目描述 + +``` +给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树。 + +示例: + +输入: 3 +输出: +[ +  [1,null,3,2], +  [3,2,null,1], +  [3,1,null,null,2], +  [2,1,3], +  [1,null,2,null,3] +] +解释: +以上的输出对应以下 5 种不同结构的二叉搜索树: + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 + + +``` + +## 思路 + +这是一个经典的使用分治思路的题目。基本思路和[96.unique-binary-search-trees](./96.unique-binary-search-trees.md)一样。 + +只是我们需要求解的不仅仅是数字,而是要求解所有的组合。我们假设问题 f(1, n) 是求解 1 到 n(两端包含)的所有二叉树。那么我们的目标就是求解 f(1, n)。 + +我们将问题进一步划分为子问题,假如左侧和右侧的树分别求好了,我们是不是只要运用组合的原理,将左右两者进行做和就好了,我们需要两层循环来完成这个过程。 + +## 关键点解析 + +- 分治法 + +## 代码 + +- 语言支持:Python3 + +Python3 Code: + +```Python +class Solution: + def generateTrees(self, n: int) -> List[TreeNode]: + if not n: + return [] + + def generateTree(start, end): + if start > end: + return [None] + res = [] + for i in range(start, end + 1): + ls = generateTree(start, i - 1) + rs = generateTree(i + 1, end) + for l in ls: + for r in rs: + node = TreeNode(i) + node.left = l + node.right = r + res.append(node) + + return res + + return generateTree(1, n) +``` + +## 相关题目 + +- [96.unique-binary-search-trees](./96.unique-binary-search-trees.md) diff --git a/spider/row-markdown/96.unique-binary-search-trees.md b/spider/row-markdown/96.unique-binary-search-trees.md new file mode 100644 index 0000000..effd3bb --- /dev/null +++ b/spider/row-markdown/96.unique-binary-search-trees.md @@ -0,0 +1,88 @@ +## 题目地址(96. 不同的二叉搜索树) + +https://leetcode-cn.com/problems/unique-binary-search-trees-ii/description/ + +## 题目描述 + +``` +给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? + +示例: + +输入: 3 +输出: 5 +解释: +给定 n = 3, 一共有 5 种不同结构的二叉搜索树: + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 + +``` + +## 思路 + +这是一个经典的使用分治思路的题目。 + +对于数字 n ,我们可以 1- n 这样的离散整数分成左右两部分。我们不妨设其分别为 A 和 B。那么问题转化为 A 和 B 所能组成的 BST 的数量的笛卡尔积。而对于 A 和 B 以及原问题除了规模,没有不同,这不就是分治思路么?至于此,我们只需要考虑边界即可,边界很简单就是 n 小于等于 1 的时候,我们返回 1。 + +具体来说: + +- 生成一个[1:n + 1] 的数组 +- 我们遍历一次数组,对于每一个数组项,我们执行以下逻辑 +- 对于每一项,我们都假设其是断点。断点左侧的是 A,断点右侧的是 B。 +- 那么 A 就是 i - 1 个数, 那么 B 就是 n - i 个数 +- 我们递归,并将 A 和 B 的结果相乘即可。 + +> 其实我们发现,题目的答案只和 n 有关,和具体 n 个数的具体组成,只要是有序数组即可。 + +题目没有明确 n 的取值范围,我们试一下暴力递归。 + +代码(Python3): + +```python +class Solution: + def numTrees(self, n: int) -> int: + if n <= 1: + return 1 + res = 0 + for i in range(1, n + 1): + res += self.numTrees(i - 1) * self.numTrees(n - i) + return res +``` + +上面的代码会超时,并没有栈溢出,因此我们考虑使用 hashmap 来优化,代码见下方代码区。 + +## 关键点解析 + +- 分治法 +- 笛卡尔积 +- 记忆化递归 + +## 代码 + +- 语言支持:Python3 + +Python3 Code: + +```Python +class Solution: + visited = dict() + + def numTrees(self, n: int) -> int: + if n in self.visited: + return self.visited.get(n) + if n <= 1: + return 1 + res = 0 + for i in range(1, n + 1): + res += self.numTrees(i - 1) * self.numTrees(n - i) + self.visited[n] = res + return res +``` + +## 相关题目 + +- [95.unique-binary-search-trees-ii](./95.unique-binary-search-trees-ii.md) diff --git a/spider/row-markdown/98.validate-binary-search-tree.md b/spider/row-markdown/98.validate-binary-search-tree.md new file mode 100644 index 0000000..2a08c27 --- /dev/null +++ b/spider/row-markdown/98.validate-binary-search-tree.md @@ -0,0 +1,344 @@ +## 题目地址 +https://leetcode.com/problems/validate-binary-search-tree/description/ + +## 题目描述 +``` +Given a binary tree, determine if it is a valid binary search tree (BST). + +Assume a BST is defined as follows: + +The left subtree of a node contains only nodes with keys less than the node's key. +The right subtree of a node contains only nodes with keys greater than the node's key. +Both the left and right subtrees must also be binary search trees. + + +Example 1: + + 2 + / \ + 1 3 + +Input: [2,1,3] +Output: true +Example 2: + + 5 + / \ + 1 4 + / \ + 3 6 + +Input: [5,1,4,null,null,3,6] +Output: false +Explanation: The root node's value is 5 but its right child's value is 4. + + +``` + +## 思路 +### 中序遍历 +这道题是让你验证一棵树是否为二叉查找树(BST)。 由于中序遍历的性质`如果一个树遍历的结果是有序数组,那么他也是一个二叉查找树(BST)`, +我们只需要中序遍历,然后两两判断是否有逆序的元素对即可,如果有,则不是BST,否则即为一个BST。 + +### 定义法 +根据定义,一个结点若是在根的左子树上,那它应该小于根结点的值而大于左子树最小值;若是在根的右子树上,那它应该大于根结点的值而小于右子树最大值。也就是说,每一个结点必须落在某个取值范围: +1. 根结点的取值范围为(考虑某个结点为最大或最小整数的情况):(long_min, long_max) +2. 左子树的取值范围为:(current_min, root.value) +3. 右子树的取值范围为:(root.value, current_max) + +## 关键点解析 + +- 二叉树的基本操作(遍历) +- 中序遍历一个二叉查找树(BST)的结果是一个有序数组 +- 如果一个树遍历的结果是有序数组,那么他也是一个二叉查找树(BST) + +## 代码 + +### 中序遍历 + +* 语言支持:JS,C++, Java + +JavaScript Code: +```js +/* + * @lc app=leetcode id=98 lang=javascript + * + * [98] Validate Binary Search Tree + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isValidBST = function(root) { + if (root === null) return true; + if (root.left === null && root.right === null) return true; + const stack = [root]; + let cur = root; + let pre = null; + + function insertAllLefts(cur) { + while(cur && cur.left) { + const l = cur.left; + stack.push(l); + cur = l; + } + } + insertAllLefts(cur); + + while(cur = stack.pop()) { + if (pre && cur.val <= pre.val) return false; + const r = cur.right; + + if (r) { + stack.push(r); + insertAllLefts(r); + } + pre = cur; + } + + return true; +}; + +``` + +C++ Code: + +```c++ +// 递归 +class Solution { +public: + bool isValidBST(TreeNode* root) { + TreeNode* prev = nullptr; + return validateBstInorder(root, prev); + } + +private: + bool validateBstInorder(TreeNode* root, TreeNode*& prev) { + if (root == nullptr) return true; + if (!validateBstInorder(root->left, prev)) return false; + if (prev != nullptr && prev->val >= root->val) return false; + prev = root; + return validateBstInorder(root->right, prev); + } +}; + +// 迭代 +class Solution { +public: + bool isValidBST(TreeNode* root) { + auto s = vector(); + TreeNode* prev = nullptr; + while (root != nullptr || !s.empty()) { + while (root != nullptr) { + s.push_back(root); + root = root->left; + } + root = s.back(); + s.pop_back(); + if (prev != nullptr && prev->val >= root->val) return false; + prev = root; + root = root->right; + } + return true; + } +}; +``` + +Java Code: + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public boolean isValidBST(TreeNode root) { + Stack stack = new Stack<> (); + TreeNode previous = null; + + while (root != null || !stack.isEmpty()) { + while (root != null) { + stack.push(root); + root = root.left; + } + root = stack.pop(); + if (previous != null && root.val <= previous.val ) return false; + previous = root; + root = root.right; + } + return true; + } +} +``` + +### 定义法 + +* 语言支持:C++,Python3, Java, JS + +C++ Code: + +```C++ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +// 递归 +class Solution { +public: + bool isValidBST(TreeNode* root) { + return helper(root, LONG_MIN, LONG_MAX); + } +private: + bool helper(const TreeNode* root, long min, long max) { + if (root == nullptr) return true; + if (root->val >= max || root->val <= min) return false; + return helper(root->left, min, root->val) && helper(root->right, root->val, max); + } +}; + +// 循环 +class Solution { +public: + bool isValidBST(TreeNode* root) { + if (root == nullptr) return true; + auto ranges = queue>(); + ranges.push(make_pair(LONG_MIN, LONG_MAX)); + auto nodes = queue(); + nodes.push(root); + while (!nodes.empty()) { + auto sz = nodes.size(); + for (auto i = 0; i < sz; ++i) { + auto range = ranges.front(); + ranges.pop(); + auto n = nodes.front(); + nodes.pop(); + if (n->val >= range.second || n->val <= range.first) { + return false; + } + if (n->left != nullptr) { + ranges.push(make_pair(range.first, n->val)); + nodes.push(n->left); + } + if (n->right != nullptr) { + ranges.push(make_pair(n->val, range.second)); + nodes.push(n->right); + } + } + } + return true; + } +}; +``` + +Python Code: + +```Python +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, x): +# self.val = x +# self.left = None +# self.right = None + +class Solution: + def isValidBST(self, root: TreeNode, area: tuple=(-float('inf'), float('inf'))) -> bool: + """思路如上面的分析,用Python表达会非常直白 + :param root TreeNode 节点 + :param area tuple 取值区间 + """ + if root is None: + return True + + is_valid_left = root.left is None or\ + (root.left.val < root.val and area[0] < root.left.val < area[1]) + is_valid_right = root.right is None or\ + (root.right.val > root.val and area[0] < root.right.val < area[1]) + + # 左右节点都符合,说明本节点符合要求 + is_valid = is_valid_left and is_valid_right + + # 递归下去 + return is_valid\ + and self.isValidBST(root.left, (area[0], root.val))\ + and self.isValidBST(root.right, (root.val, area[1])) +``` + +Java Code: + +```java +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +class Solution { + public boolean isValidBST(TreeNode root) { + return helper(root, null, null); + } + + private boolean helper(TreeNode root, Integer lower, Integer higher) { + if (root == null) return true; + + if (lower != null && root.val <= lower) return false; + if (higher != null && root.val >= higher) return false; + + if (!helper(root.left, lower, root.val)) return false; + if (!helper(root.right, root.val, higher)) return false; + + return true; + } +} +``` + +JavaScript Code: + +```javascript +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isValidBST = function (root) { + if (!root) return true; + return valid(root); +}; + +function valid(root, min = -Infinity, max = Infinity) { + if (!root) return true; + const val = root.val; + if (val <= min) return false; + if (val >= max) return false; + return valid(root.left, min, val) && valid(root.right, val, max) +} +``` + +## 相关题目 + +[230.kth-smallest-element-in-a-bst](./230.kth-smallest-element-in-a-bst.md) diff --git a/spider/yield-db-json/1.TwoSum.en.json b/spider/yield-db-json/1.TwoSum.en.json new file mode 100644 index 0000000..416cace --- /dev/null +++ b/spider/yield-db-json/1.TwoSum.en.json @@ -0,0 +1,10 @@ +{ + "question": "1.TwoSum.en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/1.TwoSum.json b/spider/yield-db-json/1.TwoSum.json new file mode 100644 index 0000000..bd73d80 --- /dev/null +++ b/spider/yield-db-json/1.TwoSum.json @@ -0,0 +1,10 @@ +{ + "question": "1.TwoSum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/101.symmetric-tree.json b/spider/yield-db-json/101.symmetric-tree.json new file mode 100644 index 0000000..584c314 --- /dev/null +++ b/spider/yield-db-json/101.symmetric-tree.json @@ -0,0 +1,10 @@ +{ + "question": "101.symmetric-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/1011.capacity-to-ship-packages-within-d-days-cn.json b/spider/yield-db-json/1011.capacity-to-ship-packages-within-d-days-cn.json new file mode 100644 index 0000000..129b912 --- /dev/null +++ b/spider/yield-db-json/1011.capacity-to-ship-packages-within-d-days-cn.json @@ -0,0 +1,19 @@ +{ + "question": "1011.capacity-to-ship-packages-within-d-days-cn", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\ndef canShip(opacity):\n # 指定船的容量是否可以在D天运完\n lo = 0\n hi = total\n while lo < hi:\n mid = (lo + hi) // 2\n if canShip(mid):\n hi = mid\n else:\n lo = mid + 1\n\n return lo\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def shipWithinDays(self, weights: List[int], D: int) -> int:\n lo = 0\n hi = 0\n\n def canShip(opacity):\n days = 1\n remain = opacity\n for weight in weights:\n if weight > opacity:\n return False\n remain -= weight\n if remain < 0:\n days += 1\n remain = opacity - weight\n return days <= D\n\n for weight in weights:\n hi += weight\n while lo < hi:\n mid = (lo + hi) // 2\n if canShip(mid):\n hi = mid\n else:\n lo = mid + 1\n\n return lo\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1011.capacity-to-ship-packages-within-d-days-en.json b/spider/yield-db-json/1011.capacity-to-ship-packages-within-d-days-en.json new file mode 100644 index 0000000..3e2a3c6 --- /dev/null +++ b/spider/yield-db-json/1011.capacity-to-ship-packages-within-d-days-en.json @@ -0,0 +1,19 @@ +{ + "question": "1011.capacity-to-ship-packages-within-d-days-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\r\ndef canShip(opacity):\r\n # Whether the capacity of the specified ship can be shipped in D days\r\n lo = 0\r\n hi = total\r\n while lo < hi:\r\n mid = (lo + hi) // 2\r\n if canShip(mid):\r\n hi = mid\r\n else:\r\n lo = mid + 1\r\n return lo\r\n" + }, + { + "lang": "python", + "code": "\r\nclass Solution:\r\n def shipWithinDays(self, weights: List[int], D: int) -> int:\r\n lo = 0\r\n hi = 0\r\n\r\n def canShip(opacity):\r\n days = 1\r\n remain = opacity\r\n for weight in weights:\r\n if weight > opacity:\r\n return False\r\n remain -= weight\r\n if remain < 0:\r\n days += 1\r\n remain = opacity - weight\r\n return days <= D\r\n\r\n for weight in weights:\r\n hi += weight\r\n while lo < hi:\r\n mid = (lo + hi) // 2\r\n if canShip(mid):\r\n hi = mid\r\n else:\r\n lo = mid + 1\r\n\r\n return lo\r\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1014.best-sightseeing-pair.json b/spider/yield-db-json/1014.best-sightseeing-pair.json new file mode 100644 index 0000000..9010169 --- /dev/null +++ b/spider/yield-db-json/1014.best-sightseeing-pair.json @@ -0,0 +1,27 @@ +{ + "question": "1014.best-sightseeing-pair", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxScoreSightseeingPair(self, A: List[int]) -> int:\n n = len(A)\n res = 0\n for i in range(n - 1):\n for j in range(i + 1, n):\n res = max(res, A[i] + A[j] + i - j)\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxScoreSightseeingPair(self, A: List[int]) -> int:\n n = len(A)\n dp = [float('-inf')] * (n + 1)\n res = 0\n for i in range(n):\n dp[i + 1] = max(dp[i], A[i] + i)\n res = max(res, dp[i] + A[i] - i)\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxScoreSightseeingPair(self, A: List[int]) -> int:\n n = len(A)\n pre = A[0] + 0\n res = 0\n for i in range(1, n):\n res = max(res, pre + A[i] - i)\n pre = max(pre, A[i] + i)\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxScoreSightseeingPair(self, A: List[int]) -> int:\n n = len(A)\n pre = A[0] + 0\n res = 0\n for i in range(1, n):\n # res = max(res, pre + A[i] - i)\n # pre = max(pre, A[i] + i)\n res = res if res > pre + A[i] - i else pre + A[i] - i\n pre = pre if pre > A[i] + i else A[i] + i\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1015.smallest-integer-divisible-by-k.json b/spider/yield-db-json/1015.smallest-integer-divisible-by-k.json new file mode 100644 index 0000000..dfe07c2 --- /dev/null +++ b/spider/yield-db-json/1015.smallest-integer-divisible-by-k.json @@ -0,0 +1,15 @@ +{ + "question": "1015.smallest-integer-divisible-by-k", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n#\n# @lc app=leetcode.cn id=1015 lang=python3\n#\n# [1015] 可被 K 整除的最小整数\n#\n\n# @lc code=start\n\n\nclass Solution:\n def smallestRepunitDivByK(self, K: int) -> int:\n if K % 10 in [2, 4, 5, 6, 8]:\n return - 1\n seen = set()\n mod = 0\n for i in range(1, K + 1):\n mod = (mod * 10 + 1) % K\n if mod in seen:\n return -1\n if mod == 0:\n return ix\n seen.add(mod)\n\n # @lc code=end\n\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1019.next-greater-node-in-linked-list.json b/spider/yield-db-json/1019.next-greater-node-in-linked-list.json new file mode 100644 index 0000000..d8ad4b2 --- /dev/null +++ b/spider/yield-db-json/1019.next-greater-node-in-linked-list.json @@ -0,0 +1,19 @@ +{ + "question": "1019.next-greater-node-in-linked-list", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\ndef monoStack(list):\n st = []\n for v in list:\n while len(st) > 0 and v > st[-1]:\n st.pop()\n st.append(v)\n return st\nmonoStack([5, 4, 2, 1, 3]) # output: [5, 4, 3]\n" + }, + { + "lang": "python", + "code": "\n# Definition for singly-linked list.\n# class ListNode:\n# def __init__(self, x):\n# self.val = x\n# self.next = None\n\nclass Solution:\n def nextLargerNodes(self, head):\n res, st = [], []\n while head:\n while len(st) > 0 and head.val > st[-1][1]:\n res[st.pop()[0]] = head.val\n st.append((len(res), head.val))\n res.append(0)\n head = head.next\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/102.binary-tree-level-order-traversal.json b/spider/yield-db-json/102.binary-tree-level-order-traversal.json new file mode 100644 index 0000000..0919fd9 --- /dev/null +++ b/spider/yield-db-json/102.binary-tree-level-order-traversal.json @@ -0,0 +1,15 @@ +{ + "question": "102.binary-tree-level-order-traversal", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# Definition for a binary tree node.\n# class TreeNode:\n# def __init__(self, x):\n# self.val = x\n# self.left = None\n# self.right = None\n\nclass Solution:\n def levelOrder(self, root: TreeNode) -> List[List[int]]:\n \"\"\"递归法\"\"\"\n if root is None:\n return []\n \n result = []\n \n def add_to_result(level, node):\n \"\"\"递归函数\n :param level int 当前在二叉树的层次\n :param node TreeNode 当前节点\n \"\"\"\n if level > len(result) - 1:\n result.append([])\n \n result[level].append(node.val)\n if node.left:\n add_to_result(level+1, node.left)\n if node.right:\n add_to_result(level+1, node.right)\n \n add_to_result(0, root)\n return result\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1020.number-of-enclaves.json b/spider/yield-db-json/1020.number-of-enclaves.json new file mode 100644 index 0000000..8e094dd --- /dev/null +++ b/spider/yield-db-json/1020.number-of-enclaves.json @@ -0,0 +1,19 @@ +{ + "question": "1020.number-of-enclaves", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n temp = 0\n meetEdge = False\n\n def numEnclaves(self, A: List[List[int]]) -> int:\n cnt = 0\n m = len(A)\n n = len(A[0])\n visited = set()\n\n def dfs(i, j):\n if i < 0 or i >= m or j < 0 or j >= n or (i, j) in visited:\n return\n visited.add((i, j))\n if A[i][j] == 1:\n self.temp += 1\n else:\n return\n if i == 0 or i == m - 1 or j == 0 or j == n - 1:\n self.meetEdge = True\n dfs(i + 1, j)\n dfs(i - 1, j)\n dfs(i, j + 1)\n dfs(i, j - 1)\n for i in range(m):\n for j in range(n):\n dfs(i, j)\n if not self.meetEdge:\n cnt += self.temp\n self.meetEdge = False\n self.temp = 0\n return cnt\n\n" + }, + { + "lang": "python", + "code": "\n#\n# @lc app=leetcode.cn id=1020 lang=python3\n#\n# [1020] 飞地的数量\n#\n\n# @lc code=start\n\n\nclass Solution:\n\n def numEnclaves(self, A: List[List[int]]) -> int:\n cnt = 0\n m = len(A)\n n = len(A[0])\n\n def dfs(i, j):\n if i < 0 or i >= m or j < 0 or j >= n or A[i][j] == 0:\n return\n A[i][j] = 0\n\n dfs(i + 1, j)\n dfs(i - 1, j)\n dfs(i, j + 1)\n dfs(i, j - 1)\n for i in range(m):\n dfs(i, 0)\n dfs(i, n - 1)\n for j in range(1, n - 1):\n dfs(0, j)\n dfs(m - 1, j)\n for i in range(m):\n for j in range(n):\n if A[i][j] == 1:\n cnt += 1\n return cnt\n\n # @lc code=end\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1023.camelcase-matching.json b/spider/yield-db-json/1023.camelcase-matching.json new file mode 100644 index 0000000..7bea21d --- /dev/null +++ b/spider/yield-db-json/1023.camelcase-matching.json @@ -0,0 +1,19 @@ +{ + "question": "1023.camelcase-matching", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def isSubsequence(self, s: str, t: str) -> bool:\n i = 0\n j = 0\n while j < len(t):\n if i < len(s) and s[i] == t[j]:\n i += 1\n j += 1\n else:\n j += 1\n if i >= len (s):\n return True\n return i == len(s)\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def camelMatch(self, queries: List[str], pattern: str) -> List[bool]:\n res = []\n for query in queries:\n i = 0\n j = 0\n while i < len(query):\n if j < len(pattern) and query[i] == pattern[j]:\n i += 1\n j += 1\n elif query[i].islower():\n i += 1\n else:\n break\n if i == len(query) and j == len(pattern):\n res.append(True)\n else:\n res.append(False)\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/103.binary-tree-zigzag-level-order-traversal.json b/spider/yield-db-json/103.binary-tree-zigzag-level-order-traversal.json new file mode 100644 index 0000000..b7f15ff --- /dev/null +++ b/spider/yield-db-json/103.binary-tree-zigzag-level-order-traversal.json @@ -0,0 +1,10 @@ +{ + "question": "103.binary-tree-zigzag-level-order-traversal", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/1031.maximum-sum-of-two-non-overlapping-subarrays.json b/spider/yield-db-json/1031.maximum-sum-of-two-non-overlapping-subarrays.json new file mode 100644 index 0000000..0e880fc --- /dev/null +++ b/spider/yield-db-json/1031.maximum-sum-of-two-non-overlapping-subarrays.json @@ -0,0 +1,15 @@ +{ + "question": "1031.maximum-sum-of-two-non-overlapping-subarrays", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxSumTwoNoOverlap(self, a: List[int], l: int, m: int) -> int:\n \"\"\"\n\n define asum[i] as the sum of subarray, a[0:i]\n define maxl[i] as the maximum sum of l-length subarray in a[0:i]\n define maxm[i] as the maximum sum of m-length subarray in a[0:i]\n define msum[i] as the maximum sum of non-overlap l-length subarray and m-length subarray\n\n case 1: a[i] is both not in l-length subarray and m-length subarray, then msum[i] = msum[i - 1]\n case 2: a[i] is in l-length subarray, then msum[i] = asum[i] - asum[i-l] + maxm[i-l]\n case 3: a[i] is in m-length subarray, then msum[i] = asum[i] - asum[i-m] + maxl[i-m]\n\n so, msum[i] = max(msum[i - 1], asum[i] - asum[i-l] + maxl[i-l], asum[i] - asum[i-m] + maxm[i-m])\n \"\"\"\n\n alen, tlen = len(a), l + m\n asum = [0] * (alen + 1)\n maxl = [0] * (alen + 1)\n maxm = [0] * (alen + 1)\n msum = [0] * (alen + 1)\n\n for i in range(tlen):\n if i == 1:\n asum[i] = a[i - 1]\n elif i > 1:\n asum[i] = asum[i - 1] + a[i - 1]\n if i >= l:\n maxl[i] = max(maxl[i - 1], asum[i] - asum[i - l])\n if i >= m:\n maxm[i] = max(maxm[i - 1], asum[i] - asum[i - m])\n\n for i in range(tlen, alen + 1):\n asum[i] = asum[i - 1] + a[i - 1]\n suml = asum[i] - asum[i - l]\n summ = asum[i] - asum[i - m]\n maxl[i] = max(maxl[i - 1], suml)\n maxm[i] = max(maxm[i - 1], summ)\n msum[i] = max(msum[i - 1], suml + maxm[i - l], summ + maxl[i - m])\n\n return msum[-1]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/104.maximum-depth-of-binary-tree.json b/spider/yield-db-json/104.maximum-depth-of-binary-tree.json new file mode 100644 index 0000000..73e737f --- /dev/null +++ b/spider/yield-db-json/104.maximum-depth-of-binary-tree.json @@ -0,0 +1,15 @@ +{ + "question": "104.maximum-depth-of-binary-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxDepth(self, root: TreeNode) -> int:\n if not root: return 0\n q, depth = [root, None], 1\n while q:\n node = q.pop(0)\n if node:\n if node.left: q.append(node.left)\n if node.right: q.append(node.right)\n elif q:\n q.append(None)\n depth += 1\n return depth\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.json b/spider/yield-db-json/105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.json new file mode 100644 index 0000000..49f8e25 --- /dev/null +++ b/spider/yield-db-json/105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.json @@ -0,0 +1,19 @@ +{ + "question": "105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\npreorder = [3,9,20,15,7]\ninorder = [9,3,15,20,7]\n" + }, + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nclass Solution {\n public TreeNode buildTree(int[] preorder, int[] inorder) {\n if (preorder.length != inorder.length) return null;\n \n HashMap map = new HashMap<> ();\n\n for (int i=0; i map) {\n if (preStart>preEnd || inStart>inEnd) return null;\n \n TreeNode root = new TreeNode(preorder[prestart]);\n int inRoot = map.get(preorder[preStart]);\n int leftChldLen = inRoot - inStart;\n\n root.left = helper(preorder, preStart+1, preStart+leftChldLen, inorder, inStart, inRoot-1, map);\n root.left = helper(preorder, preStart+leftChldLen+1, preEnd, inorder, inRoot+1, inEnd, map);\n\n return root;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/11.container-with-most-water.json b/spider/yield-db-json/11.container-with-most-water.json new file mode 100644 index 0000000..77cef43 --- /dev/null +++ b/spider/yield-db-json/11.container-with-most-water.json @@ -0,0 +1,10 @@ +{ + "question": "11.container-with-most-water", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/1104.path-in-zigzag-labelled-binary-tree.json b/spider/yield-db-json/1104.path-in-zigzag-labelled-binary-tree.json new file mode 100644 index 0000000..36c11b7 --- /dev/null +++ b/spider/yield-db-json/1104.path-in-zigzag-labelled-binary-tree.json @@ -0,0 +1,15 @@ +{ + "question": "1104.path-in-zigzag-labelled-binary-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def pathInZigZagTree(self, label: int) -> List[int]:\n level = 0\n res = []\n # for each level, ranged from 2 ** (level - 1) to 2 ** level - 1\n while 2 ** level - 1 < label:\n level += 1\n\n while level > 0:\n res.insert(0, label)\n label = 2 ** (level - 1) + 2 ** level - 1 - label\n label //= 2\n level -= 1\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/113.path-sum-ii.json b/spider/yield-db-json/113.path-sum-ii.json new file mode 100644 index 0000000..cb8204a --- /dev/null +++ b/spider/yield-db-json/113.path-sum-ii.json @@ -0,0 +1,15 @@ +{ + "question": "113.path-sum-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# Definition for a binary tree node.\n# class TreeNode:\n# def __init__(self, x):\n# self.val = x\n# self.left = None\n# self.right = None\n\nclass Solution:\n def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:\n if not root:\n return []\n \n result = []\n \n def trace_node(pre_list, left_sum, node):\n new_list = pre_list.copy()\n new_list.append(node.val)\n if not node.left and not node.right:\n # 这个判断可以和上面的合并,但分开写会快几毫秒,可以省去一些不必要的判断\n if left_sum == node.val:\n result.append(new_list)\n else:\n if node.left:\n trace_node(new_list, left_sum-node.val, node.left)\n if node.right:\n trace_node(new_list, left_sum-node.val, node.right)\n \n trace_node([], sum, root)\n return result\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1131.maximum-of-absolute-value-expression.json b/spider/yield-db-json/1131.maximum-of-absolute-value-expression.json new file mode 100644 index 0000000..e7915ca --- /dev/null +++ b/spider/yield-db-json/1131.maximum-of-absolute-value-expression.json @@ -0,0 +1,19 @@ +{ + "question": "1131.maximum-of-absolute-value-expression", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxAbsValExpr(self, arr1: List[int], arr2: List[int]) -> int:\n A = []\n B = []\n C = []\n D = []\n for i in range(len(arr1)):\n a, b, c, d = arr1[i] + arr2[i] + i, arr1[i] - arr2[i] + \\\n i, arr2[i] - arr1[i] + i, -1 * arr2[i] - arr1[i] + i\n A.append(a)\n B.append(b)\n C.append(c)\n D.append(d)\n return max(max(A) - min(A), max(B) - min(B), max(C) - min(C), max(D) - min(D))\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxAbsValExpr(self, arr1: List[int], arr2: List[int]) -> int:\n # 曼哈顿距离模板代码\n sign = [1, -1]\n n = len(arr1)\n dists = []\n # 三维模板\n for a in sign:\n for b in sign:\n for c in sign:\n maxDist = float('-inf')\n minDist = float('inf')\n # 分别计算所有点的曼哈顿距离\n for i in range(n):\n dist = arr1[i] * a + arr2[i] * b + i * c\n maxDist = max(maxDist, dist)\n minDist = min(minDist, dist)\n # 将所有的点的曼哈顿距离放到dists中\n dists.append(maxDist - minDist)\n return max(dists)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1168.optimize-water-distribution-in-a-village-cn.json b/spider/yield-db-json/1168.optimize-water-distribution-in-a-village-cn.json new file mode 100644 index 0000000..98bdc61 --- /dev/null +++ b/spider/yield-db-json/1168.optimize-water-distribution-in-a-village-cn.json @@ -0,0 +1,19 @@ +{ + "question": "1168.optimize-water-distribution-in-a-village-cn", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n class OptimizeWaterDistribution {\n public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) {\n List costs = new ArrayList<>();\n for (int i = 1; i <= n; i++) {\n costs.add(new EdgeCost(0, i, wells[i - 1]));\n }\n for (int[] p : pipes) {\n costs.add(new EdgeCost(p[0], p[1], p[2]));\n }\n Collections.sort(costs);\n int minCosts = 0;\n UnionFind uf = new UnionFind(n);\n for (EdgeCost edge : costs) {\n int rootX = uf.find(edge.node1);\n int rootY = uf.find(edge.node2);\n if (rootX == rootY) continue;\n minCosts += edge.cost;\n uf.union(edge.node1, edge.node2);\n // for each union, we connnect one node\n n--;\n // if all nodes already connected, terminate early\n if (n == 0) {\n return minCosts;\n }\n }\n return minCosts;\n }\n \n class EdgeCost implements Comparable {\n int node1;\n int node2;\n int cost;\n public EdgeCost(int node1, int node2, int cost) {\n this.node1 = node1;\n this.node2 = node2;\n this.cost = cost;\n }\n \n @Override\n public int compareTo(EdgeCost o) {\n return this.cost - o.cost;\n }\n }\n \n class UnionFind {\n int[] parent;\n int[] rank;\n public UnionFind(int n) {\n parent = new int[n + 1];\n for (int i = 0; i <= n; i++) {\n parent[i] = i;\n }\n rank = new int[n + 1];\n }\n public int find(int x) {\n return x == parent[x] ? x : find(parent[x]);\n }\n public void union(int x, int y) {\n int px = find(x);\n int py = find(y);\n if (px == py) return;\n if (rank[px] >= rank[py]) {\n parent[py] = px;\n rank[px] += rank[py];\n } else {\n parent[px] = py;\n rank[py] += rank[px];\n }\n }\n }\n }\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int:\n union_find = {i: i for i in range(n + 1)}\n \n def find(x):\n return x if x == union_find[x] else find(union_find[x])\n \n def union(x, y):\n px = find(x)\n py = find(y)\n union_find[px] = py\n \n graph_wells = [[cost, 0, i] for i, cost in enumerate(wells, 1)]\n graph_pipes = [[cost, i, j] for i, j, cost in pipes]\n min_costs = 0\n for cost, x, y in sorted(graph_wells + graph_pipes):\n if find(x) == find(y):\n continue\n union(x, y)\n min_costs += cost\n n -= 1\n if n == 0:\n return min_costs\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1168.optimize-water-distribution-in-a-village-en.json b/spider/yield-db-json/1168.optimize-water-distribution-in-a-village-en.json new file mode 100644 index 0000000..926e9b7 --- /dev/null +++ b/spider/yield-db-json/1168.optimize-water-distribution-in-a-village-en.json @@ -0,0 +1,19 @@ +{ + "question": "1168.optimize-water-distribution-in-a-village-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n class OptimizeWaterDistribution {\n public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) {\n List costs = new ArrayList<>();\n for (int i = 1; i <= n; i++) {\n costs.add(new EdgeCost(0, i, wells[i - 1]));\n }\n for (int[] p : pipes) {\n costs.add(new EdgeCost(p[0], p[1], p[2]));\n }\n Collections.sort(costs);\n int minCosts = 0;\n UnionFind uf = new UnionFind(n);\n for (EdgeCost edge : costs) {\n int rootX = uf.find(edge.node1);\n int rootY = uf.find(edge.node2);\n if (rootX == rootY) continue;\n minCosts += edge.cost;\n uf.union(edge.node1, edge.node2);\n // for each union, we connnect one node\n n--;\n // if all nodes already connected, terminate early\n if (n == 0) {\n return minCosts;\n }\n }\n return minCosts;\n }\n \n class EdgeCost implements Comparable {\n int node1;\n int node2;\n int cost;\n public EdgeCost(int node1, int node2, int cost) {\n this.node1 = node1;\n this.node2 = node2;\n this.cost = cost;\n }\n \n @Override\n public int compareTo(EdgeCost o) {\n return this.cost - o.cost;\n }\n }\n \n class UnionFind {\n int[] parent;\n int[] rank;\n public UnionFind(int n) {\n parent = new int[n + 1];\n for (int i = 0; i <= n; i++) {\n parent[i] = i;\n }\n rank = new int[n + 1];\n }\n public int find(int x) {\n return x == parent[x] ? x : find(parent[x]);\n }\n public void union(int x, int y) {\n int px = find(x);\n int py = find(y);\n if (px == py) return;\n if (rank[px] >= rank[py]) {\n parent[py] = px;\n rank[px] += rank[py];\n } else {\n parent[px] = py;\n rank[py] += rank[px];\n }\n }\n }\n }\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int:\n union_find = {i: i for i in range(n + 1)}\n \n def find(x):\n return x if x == union_find[x] else find(union_find[x])\n \n def union(x, y):\n px = find(x)\n py = find(y)\n union_find[px] = py\n \n graph_wells = [[cost, 0, i] for i, cost in enumerate(wells, 1)]\n graph_pipes = [[cost, i, j] for i, j, cost in pipes]\n min_costs = 0\n for cost, x, y in sorted(graph_wells + graph_pipes):\n if find(x) == find(y):\n continue\n union(x, y)\n min_costs += cost\n n -= 1\n if n == 0:\n return min_costs\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1186.maximum-subarray-sum-with-one-deletion.json b/spider/yield-db-json/1186.maximum-subarray-sum-with-one-deletion.json new file mode 100644 index 0000000..ecc660e --- /dev/null +++ b/spider/yield-db-json/1186.maximum-subarray-sum-with-one-deletion.json @@ -0,0 +1,23 @@ +{ + "question": "1186.maximum-subarray-sum-with-one-deletion", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n class Solution:\n def maximumSum(self, arr: List[int]) -> int:\n res = arr[0]\n def maxSubSum(arr, skip):\n res = maxSub = float(\"-inf\")\n \n for i in range(len(arr)):\n if i == skip:\n continue\n maxSub = max(arr[i], maxSub + arr[i])\n res = max(res, maxSub)\n return res\n\t\t# 这里循环到了len(arr)项,表示的是一个都不删除的情况\n for i in range(len(arr) + 1):\n res = max(res, maxSubSum(arr, i))\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maximumSum(self, arr: List[int]) -> int:\n n = len(arr)\n l = [arr[0]] * n\n r = [arr[n - 1]] * n\n if n == 1:\n return arr[0]\n res = arr[0]\n for i in range(1, n):\n l[i] = max(l[i - 1] + arr[i], arr[i])\n res = max(res, l[i])\n for i in range(n - 2, -1, -1):\n r[i] = max(r[i + 1] + arr[i], arr[i])\n res = max(res, r[i])\n for i in range(1, n - 1):\n res = max(res, l[i - 1] + r[i + 1])\n \n return res\n\n" + }, + { + "lang": "python", + "code": "\n#\n# @lc app=leetcode.cn id=1186 lang=python3\n#\n# [1186] 删除一次得到子数组最大和\n#\n\n# @lc code=start\n\n\nclass Solution:\n def maximumSum(self, arr: List[int]) -> int:\n # DP\n max0 = arr[0]\n max1 = arr[0]\n res = arr[0]\n n = len(arr)\n if n == 1:\n return max0\n\n for i in range(1, n):\n # 先更新max1,再更新max0,因为max1用到了上一个max0\n max1 = max(max1 + arr[i], max0)\n max0 = max(max0 + arr[i], arr[i])\n res = max(res, max0, max1)\n return res\n\n\n# @lc code=end\n\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/121.best-time-to-buy-and-sell-stock.json b/spider/yield-db-json/121.best-time-to-buy-and-sell-stock.json new file mode 100644 index 0000000..4e546b9 --- /dev/null +++ b/spider/yield-db-json/121.best-time-to-buy-and-sell-stock.json @@ -0,0 +1,15 @@ +{ + "question": "121.best-time-to-buy-and-sell-stock", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxProfit(self, prices: 'List[int]') -> int:\n if not prices: return 0\n\n min_price = float('inf')\n max_profit = 0\n\n for price in prices:\n if price < min_price:\n min_price = price\n elif max_profit < price - min_price:\n max_profit = price - min_price\n return max_profit\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1218.longest-arithmetic-subsequence-of-given-difference.json b/spider/yield-db-json/1218.longest-arithmetic-subsequence-of-given-difference.json new file mode 100644 index 0000000..473e754 --- /dev/null +++ b/spider/yield-db-json/1218.longest-arithmetic-subsequence-of-given-difference.json @@ -0,0 +1,19 @@ +{ + "question": "1218.longest-arithmetic-subsequence-of-given-difference", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n def longestSubsequence(self, arr: List[int], difference: int) -> int:\n n = len(arr)\n res = 1\n for i in range(n):\n count = 1\n for j in range(i + 1, n):\n if arr[i] + difference * count == arr[j]:\n count += 1\n\n if count > res:\n res = count\n\n return res\n" + }, + { + "lang": "python", + "code": "\n#\n# @lc app=leetcode.cn id=1218 lang=python3\n#\n# [1218] 最长定差子序列\n#\n\n# @lc code=start\n\n\nclass Solution:\n\n # 动态规划\n def longestSubsequence(self, arr: List[int], difference: int) -> int:\n n = len(arr)\n res = 1\n dp = {}\n for num in arr:\n dp[num] = 1\n if num - difference in dp:\n dp[num] = dp[num - difference] + 1\n\n return max(dp.values())\n\n# @lc code=end\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/122.best-time-to-buy-and-sell-stock-ii.json b/spider/yield-db-json/122.best-time-to-buy-and-sell-stock-ii.json new file mode 100644 index 0000000..d7c5301 --- /dev/null +++ b/spider/yield-db-json/122.best-time-to-buy-and-sell-stock-ii.json @@ -0,0 +1,15 @@ +{ + "question": "122.best-time-to-buy-and-sell-stock-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxProfit(self, prices: 'List[int]') -> int:\n gains = [prices[i] - prices[i-1] for i in range(1, len(prices))\n if prices[i] - prices[i-1] > 0]\n return sum(gains)\n#评论区里都讲这是一道开玩笑的送分题.\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1227.airplane-seat-assignment-probability.json b/spider/yield-db-json/1227.airplane-seat-assignment-probability.json new file mode 100644 index 0000000..faf00da --- /dev/null +++ b/spider/yield-db-json/1227.airplane-seat-assignment-probability.json @@ -0,0 +1,31 @@ +{ + "question": "1227.airplane-seat-assignment-probability", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def nthPersonGetsNthSeat(self, n: int) -> float:\n if n == 1:\n return 1\n if n == 2:\n return 0.5\n res = 1 / n\n for i in range(2, n):\n res += self.nthPersonGetsNthSeat(n - i + 1) * 1 / n\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n seen = {}\n\n def nthPersonGetsNthSeat(self, n: int) -> float:\n if n == 1:\n return 1\n if n == 2:\n return 0.5\n if n in self.seen:\n return self.seen[n]\n res = 1 / n\n for i in range(2, n):\n res += self.nthPersonGetsNthSeat(n - i + 1) * 1 / n\n self.seen[n] = res\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def nthPersonGetsNthSeat(self, n: int) -> float:\n if n == 1:\n return 1\n if n == 2:\n return 0.5\n\n dp = [1, .5] * n\n\n for i in range(2, n):\n dp[i] = 1 / n\n for j in range(2, i):\n dp[i] += dp[i - j + 1] * 1 / n\n return dp[-1]\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def nthPersonGetsNthSeat(self, n: int) -> float:\n if n == 1:\n return 1\n if n == 2:\n return 0.5\n\n dp = [1, .5] * n\n\n for i in range(2, n):\n dp[i] = 1/n+(n-2)/n * dp[n-1]\n return dp[-1]\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def nthPersonGetsNthSeat(self, n: int) -> float:\n return 1 if n == 1 else .5\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/124.binary-tree-maximum-path-sum.json b/spider/yield-db-json/124.binary-tree-maximum-path-sum.json new file mode 100644 index 0000000..dfab1f4 --- /dev/null +++ b/spider/yield-db-json/124.binary-tree-maximum-path-sum.json @@ -0,0 +1,15 @@ +{ + "question": "124.binary-tree-maximum-path-sum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nclass Solution {\n int ans;\n public int maxPathSum(TreeNode root) {\n ans = Integer.MIN_VALUE;\n helper(root); // recursion\n return ans;\n }\n\n public int helper(TreeNode root) {\n if (root == null) return 0;\n int leftMax = Math.max(0, helper(root.left)); // find the max sub-path sum in left sub-tree\n int rightMax = Math.max(0, helper(root.right)); // find the max sub-path sum in right sub-tree\n ans = Math.max(ans, leftMax+rightMax+root.val); // find the max path sum at current node\n return max(leftMax, rightMax) + root.val; // according to the definition of path, the return value of current node can only be that the sum of current node value plus either left or right max path sum.\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/125.valid-palindrome.json b/spider/yield-db-json/125.valid-palindrome.json new file mode 100644 index 0000000..1a54433 --- /dev/null +++ b/spider/yield-db-json/125.valid-palindrome.json @@ -0,0 +1,15 @@ +{ + "question": "125.valid-palindrome", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def isPalindrome(self, s: str) -> bool:\n left, right = 0, len(s) - 1\n while left < right:\n if not s[left].isalnum():\n left += 1\n continue\n if not s[right].isalnum():\n right -= 1\n continue\n if s[left].lower() == s[right].lower():\n left += 1\n right -= 1\n else:\n break\n return right <= left\n\n def isPalindrome2(self, s: str) -> bool:\n \"\"\"\n 使用语言特性进行求解\n \"\"\"\n s = ''.join(i for i in s if i.isalnum()).lower()\n return s == s[::-1]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1260.shift-2d-grid.json b/spider/yield-db-json/1260.shift-2d-grid.json new file mode 100644 index 0000000..60a1e42 --- /dev/null +++ b/spider/yield-db-json/1260.shift-2d-grid.json @@ -0,0 +1,19 @@ +{ + "question": "1260.shift-2d-grid", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nfrom copy import deepcopy\n\nclass Solution:\n def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:\n n = len(grid)\n m = len(grid[0])\n for _ in range(k):\n old = deepcopy(grid)\n for i in range(n):\n for j in range(m):\n if j == m - 1:\n grid[(i + 1) % n][0] = old[i][j]\n elif i == n - 1 and j == m - 1:\n grid[0][0] = old[i][j]\n else:\n grid[i][j + 1] = old[i][j]\n return grid\n" + }, + { + "lang": "python", + "code": "\n#\n# @lc app=leetcode.cn id=1260 lang=python3\n#\n# [1260] 二维网格迁移\n#\n\n# @lc code=start\n\n\nclass Solution:\n def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:\n n = len(grid)\n m = len(grid[0])\n # 二维到一维\n arr = [grid[i][j] for i in range(n) for j in range(m)]\n # 取模,缩小k的范围,避免无意义的运算\n k %= m * n\n res = []\n # 首尾交换法\n\n def reverse(l, r):\n while l < r:\n t = arr[l]\n arr[l] = arr[r]\n arr[r] = t\n l += 1\n r -= 1\n # 三次旋转\n reverse(0, m * n - k - 1)\n reverse(m * n - k, m * n - 1)\n reverse(0, m * n - 1)\n # 一维到二维\n row = []\n for i in range(m * n):\n if i > 0 and i % m == 0:\n res.append(row)\n row = []\n row.append(arr[i])\n res.append(row)\n\n return res\n\n# @lc code=end\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1261.find-elements-in-a-contaminated-binary-tree.json b/spider/yield-db-json/1261.find-elements-in-a-contaminated-binary-tree.json new file mode 100644 index 0000000..c36acdd --- /dev/null +++ b/spider/yield-db-json/1261.find-elements-in-a-contaminated-binary-tree.json @@ -0,0 +1,23 @@ +{ + "question": "1261.find-elements-in-a-contaminated-binary-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# Definition for a binary tree node.\n# class TreeNode:\n# def __init__(self, x):\n# self.val = x\n# self.left = None\n# self.right = None\n\nclass FindElements:\n node = None\n def __init__(self, root: TreeNode):\n def recover(node):\n if not node:\n return node;\n if node.left:\n node.left.val = 2 * node.val + 1\n if node.right:\n node.right.val = 2 * node.val + 2\n recover(node.left)\n recover(node.right)\n return node\n root.val = 0\n self.node = recover(root)\n\n\n def find(self, target: int) -> bool:\n def findInTree(node, target):\n if not node:\n return False\n if node.val == target:\n return True\n return findInTree(node.left, target) or findInTree(node.right, target)\n return findInTree(self.node, target)\n\n\n\n\n# Your FindElements object will be instantiated and called as such:\n# obj = FindElements(root)\n# param_1 = obj.find(target)\n" + }, + { + "lang": "python", + "code": "\n# Definition for a binary tree node.\n# class TreeNode:\n# def __init__(self, x):\n# self.val = x\n# self.left = None\n# self.right = None\n\nclass FindElements:\n def __init__(self, root: TreeNode):\n # set 不能放在init外侧。 因为测试用例之间不会销毁FindElements的变量\n self.seen = set()\n def recover(node):\n if not node:\n return node;\n if node.left:\n node.left.val = 2 * node.val + 1\n self.seen.add(node.left.val)\n if node.right:\n node.right.val = 2 * node.val + 2\n self.seen.add(node.right.val)\n recover(node.left)\n recover(node.right)\n return node\n root.val = 0\n self.seen.add(0)\n self.node = recover(root)\n\n\n def find(self, target: int) -> bool:\n return target in self.seen\n\n\n\n\n# Your FindElements object will be instantiated and called as such:\n# obj = FindElements(root)\n# param_1 = obj.find(target)\n" + }, + { + "lang": "python", + "code": "\n# Definition for a binary tree node.\n# class TreeNode:\n# def __init__(self, x):\n# self.val = x\n# self.left = None\n# self.right = None\n\nclass FindElements:\n node = None\n def __init__(self, root: TreeNode):\n def recover(node):\n if not node:\n return node;\n if node.left:\n node.left.val = 2 * node.val + 1\n if node.right:\n node.right.val = 2 * node.val + 2\n recover(node.left)\n recover(node.right)\n return node\n root.val = 0\n self.node = recover(root)\n\n\n def find(self, target: int) -> bool:\n node = self.node\n for bit in bin(target+1)[3:]:\n node = node and (node.left, node.right)[int(bit)]\n return bool(node)\n\n\n\n\n# Your FindElements object will be instantiated and called as such:\n# obj = FindElements(root)\n# param_1 = obj.find(target)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1262.greatest-sum-divisible-by-three.json b/spider/yield-db-json/1262.greatest-sum-divisible-by-three.json new file mode 100644 index 0000000..6503139 --- /dev/null +++ b/spider/yield-db-json/1262.greatest-sum-divisible-by-three.json @@ -0,0 +1,31 @@ +{ + "question": "1262.greatest-sum-divisible-by-three", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxSumDivThree(self, nums: List[int]) -> int:\n self.res = 0\n def backtrack(temp, start):\n total = sum(temp)\n if total % 3 == 0:\n self.res = max(self.res, total)\n for i in range(start, len(nums)):\n temp.append(nums[i])\n backtrack(temp, i + 1)\n temp.pop(-1)\n\n\n backtrack([], 0)\n\n return self.res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSumDivThree(self, nums: List[int]) -> int:\n one = []\n two = []\n total = 0\n\n for num in nums:\n total += num\n if num % 3 == 1:\n one.append(num)\n if num % 3 == 2:\n two.append(num)\n one.sort()\n two.sort()\n if total % 3 == 0:\n return total\n elif total % 3 == 1 and one:\n if len(two) >= 2 and one[0] > two[0] + two[1]:\n return total - two[0] - two[1]\n return total - one[0]\n elif total % 3 == 2 and two:\n if len(one) >= 2 and two[0] > one[0] + one[1]:\n return total - one[0] - one[1]\n return total - two[0]\n return 0\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSumDivThree(self, nums: List[int]) -> int:\n one = [float('inf')] * 2\n two = [float('inf')] * 2\n total = 0\n\n for num in nums:\n total += num\n if num % 3 == 1:\n if num < one[0]:\n t = one[0]\n one[0] = num\n one[1] = t\n elif num < one[1]:\n one[1] = num\n if num % 3 == 2:\n if num < two[0]:\n t = two[0]\n two[0] = num\n two[1] = t\n elif num < two[1]:\n two[1] = num\n if total % 3 == 0:\n return total\n elif total % 3 == 1 and one:\n if len(two) >= 2 and one[0] > two[0] + two[1]:\n return total - two[0] - two[1]\n return total - one[0]\n elif total % 3 == 2 and two:\n if len(one) >= 2 and two[0] > one[0] + one[1]:\n return total - one[0] - one[1]\n return total - two[0]\n return 0\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSumDivThree(self, nums: List[int]) -> int:\n state = [0, float('-inf'), float('-inf')]\n\n for num in nums:\n if num % 3 == 0:\n state = [state[0] + num, state[1] + num, state[2] + num]\n if num % 3 == 1:\n a = max(state[2] + num, state[0])\n b = max(state[0] + num, state[1])\n c = max(state[1] + num, state[2])\n state = [a, b, c]\n if num % 3 == 2:\n a = max(state[1] + num, state[0])\n b = max(state[2] + num, state[1])\n c = max(state[0] + num, state[2])\n state = [a, b, c]\n return state[0]\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSumDivThree(self, nums: List[int]) -> int:\n state = [0, float('-inf'), float('-inf')]\n\n for num in nums:\n temp = [0] * 3\n for i in range(3):\n temp[(i + num) % 3] = max(state[(i + num) % 3], state[i] + num)\n state = temp\n\n return state[0]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/128.longest-consecutive-sequence.json b/spider/yield-db-json/128.longest-consecutive-sequence.json new file mode 100644 index 0000000..3f964ad --- /dev/null +++ b/spider/yield-db-json/128.longest-consecutive-sequence.json @@ -0,0 +1,10 @@ +{ + "question": "128.longest-consecutive-sequence", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/129.sum-root-to-leaf-numbers.json b/spider/yield-db-json/129.sum-root-to-leaf-numbers.json new file mode 100644 index 0000000..8f11dfc --- /dev/null +++ b/spider/yield-db-json/129.sum-root-to-leaf-numbers.json @@ -0,0 +1,19 @@ +{ + "question": "129.sum-root-to-leaf-numbers", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# class TreeNode:\n# def __init__(self, x):\n# self.val = x\n# self.left = None\n# self.right = None\n\nclass Solution:\n def sumNumbers(self, root: TreeNode) -> int:\n\n def helper(node, cur_val):\n if not node: return 0\n next_val = cur_val * 10 + node.val\n\n if not (node.left or node.right):\n return next_val\n\n left_val = helper(node.left, next_val)\n right_val = helper(node.right, next_val)\n\n return left_val + right_val\n\n return helper(root, 0)\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def sumNumbers(self, root: TreeNode) -> int:\n if not root: return 0\n result = 0\n node_queue, sum_queue = [root], [root.val]\n while node_queue:\n for i in node_queue:\n cur_node = node_queue.pop(0)\n cur_val = sum_queue.pop(0)\n if cur_node.left:\n node_queue.append(cur_node.left)\n sum_queue.append(cur_val * 10 + cur_node.left.val)\n if cur_node.right:\n node_queue.append(cur_node.right)\n sum_queue.append(cur_val * 10 + cur_node.right.val)\n if not (cur_node.left or cur_node.right):\n result += cur_val\n return result\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1297.maximum-number-of-occurrences-of-a-substring.json b/spider/yield-db-json/1297.maximum-number-of-occurrences-of-a-substring.json new file mode 100644 index 0000000..9fdcffe --- /dev/null +++ b/spider/yield-db-json/1297.maximum-number-of-occurrences-of-a-substring.json @@ -0,0 +1,23 @@ +{ + "question": "1297.maximum-number-of-occurrences-of-a-substring", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n public int maxFreq(String s, int maxLetters, int minSize, int maxSize) {\n Map counter = new HashMap<>();\n int res = 0;\n for (int i = 0; i < s.length() - minSize + 1; i++) {\n String substr = s.substring(i, i + minSize);\n if (checkNum(substr, maxLetters)) {\n int newVal = counter.getOrDefault(substr, 0) + 1;\n counter.put(substr, newVal);\n res = Math.max(res, newVal);\n }\n }\n return res;\n}\npublic boolean checkNum(String substr, int maxLetters) {\n Set set = new HashSet<>();\n for (int i = 0; i < substr.length(); i++)\n set.add(substr.charAt(i));\n return set.size() <= maxLetters;\n}\n\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int:\n n = len(s)\n letters = set()\n cnts = dict()\n res = 0\n for i in range(n - minSize + 1):\n length = minSize\n while i + length <= n and length <= maxSize:\n t = s[i:i + length]\n for c in t:\n if len(letters) > maxLetters:\n break\n letters.add(c)\n if len(letters) <= maxLetters:\n cnts[t] = cnts.get(t, 0) + 1\n res = max(res, cnts[t])\n letters.clear()\n length += 1\n return res\n" + }, + { + "lang": "python", + "code": "\n def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int:\n counter, res = {}, 0\n for i in range(0, len(s) - minSize + 1):\n sub = s[i : i + minSize]\n if len(set(sub)) <= maxLetters:\n counter[sub] = counter.get(sub, 0) + 1\n res = max(res, counter[sub])\n return res;\n\n# @lc code=end\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/130.surrounded-regions.json b/spider/yield-db-json/130.surrounded-regions.json new file mode 100644 index 0000000..cb60409 --- /dev/null +++ b/spider/yield-db-json/130.surrounded-regions.json @@ -0,0 +1,15 @@ +{ + "question": "130.surrounded-regions", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def solve(self, board: List[List[str]]) -> None:\n \"\"\"\n Do not return anything, modify board in-place instead.\n \"\"\"\n # 如果数组长或宽小于等于2,则不需要替换\n if len(board) <= 2 or len(board[0]) <= 2:\n return\n \n row, col = len(board), len(board[0])\n \n def dfs(i, j):\n \"\"\"\n 深度优先算法,如果符合条件,替换为A并进一步测试,否则停止\n \"\"\"\n if i < 0 or j < 0 or i >= row or j >= col or board[i][j] != 'O':\n return\n board[i][j] = 'A'\n \n dfs(i - 1, j)\n dfs(i + 1, j)\n dfs(i, j - 1)\n dfs(i, j + 1)\n \n # 从外围开始\n for i in range(row):\n dfs(i, 0)\n dfs(i, col-1)\n \n for j in range(col):\n dfs(0, j)\n dfs(row-1, j)\n \n # 最后完成替换\n for i in range(row):\n for j in range(col):\n if board[i][j] == 'O':\n board[i][j] = 'X'\n elif board[i][j] == 'A':\n board[i][j] = 'O'\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/131.palindrome-partitioning.json b/spider/yield-db-json/131.palindrome-partitioning.json new file mode 100644 index 0000000..89ce62e --- /dev/null +++ b/spider/yield-db-json/131.palindrome-partitioning.json @@ -0,0 +1,15 @@ +{ + "question": "131.palindrome-partitioning", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def partition(self, s: str) -> List[List[str]]:\n \"\"\"回溯法\"\"\"\n \n res = []\n \n def helper(s, tmp):\n \"\"\"\n 如果是空字符串,说明已经处理完毕\n 否则逐个字符往前测试,判断是否是回文\n 如果是,则处理剩余字符串,并将已经得到的列表作为参数\n \"\"\"\n if not s:\n res.append(tmp)\n for i in range(1, len(s) + 1):\n if s[:i] == s[:i][::-1]:\n helper(s[i:], tmp + [s[:i]])\n \n helper(s, [])\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1310.xor-queries-of-a-subarray.json b/spider/yield-db-json/1310.xor-queries-of-a-subarray.json new file mode 100644 index 0000000..54439a6 --- /dev/null +++ b/spider/yield-db-json/1310.xor-queries-of-a-subarray.json @@ -0,0 +1,23 @@ +{ + "question": "1310.xor-queries-of-a-subarray", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n public int[] xorQueries(int[] arr, int[][] queries) {\n\n int[] preXor = new int[arr.length];\n preXor[0] = 0;\n\n for (int i = 1; i < arr.length; i++)\n preXor[i] = preXor[i - 1] ^ arr[i - 1];\n\n int[] res = new int[queries.length];\n\n for (int i = 0; i < queries.length; i++) {\n\n int left = queries[i][0], right = queries[i][1];\n res[i] = arr[right] ^ preXor[right] ^ preXor[left];\n }\n\n return res;\n }\n\n" + }, + { + "lang": "python", + "code": "\n\nclass Solution:\n def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]:\n \t\tres = []\n for (L, R) in queries:\n i = L\n xor = 0\n while i <= R:\n xor ^= arr[i]\n i += 1\n res.append(xor)\n return res\n" + }, + { + "lang": "python", + "code": "\n#\n# @lc app=leetcode.cn id=1218 lang=python3\n#\n# [1218] 最长定差子序列\n#\n\n# @lc code=start\n\n\nclass Solution:\n def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]:\n\t\tpre = [0]\n res = []\n for i in range(len(arr)):\n pre.append(pre[i] ^ arr[i])\n for (L, R) in queries:\n res.append(pre[L] ^ pre[R + 1])\n return res\n\n# @lc code=end\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1332.remove-palindromic-subsequences.json b/spider/yield-db-json/1332.remove-palindromic-subsequences.json new file mode 100644 index 0000000..1d8a387 --- /dev/null +++ b/spider/yield-db-json/1332.remove-palindromic-subsequences.json @@ -0,0 +1,19 @@ +{ + "question": "1332.remove-palindromic-subsequences", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n\nclass Solution:\n def removePalindromeSub(self, s: str) -> int:\n if s == '':\n return 0\n def isPalindrome(s):\n l = 0\n r = len(s) - 1\n while l < r:\n if s[l] != s[r]:\n return False\n l += 1\n r -= 1\n return True\n return 1 if isPalindrome(s) else 2\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def removePalindromeSub(self, s: str) -> int:\n if s == '':\n return 0\n return 1 if s == s[::-1] else 2\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1334.find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance.json b/spider/yield-db-json/1334.find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance.json new file mode 100644 index 0000000..d0e0b12 --- /dev/null +++ b/spider/yield-db-json/1334.find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance.json @@ -0,0 +1,15 @@ +{ + "question": "1334.find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def findTheCity(self, n: int, edges: List[List[int]], distanceThreshold: int) -> int:\n # 构建dist矩阵\n dist = [[float('inf')] * n for _ in range(n)]\n for i, j, w in edges:\n dist[i][j] = w\n dist[j][i] = w\n for i in range(n):\n dist[i][i] = 0\n for k in range(n):\n for i in range(n):\n for j in range(n):\n dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])\n\n # 过滤\n res = 0\n minCnt = float('inf')\n for i in range(n):\n cnt = 0\n for d in dist[i]:\n if d <= distanceThreshold:\n cnt += 1\n if cnt <= minCnt:\n minCnt = cnt\n res = i\n return res\n\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/136.single-number.json b/spider/yield-db-json/136.single-number.json new file mode 100644 index 0000000..5b2b649 --- /dev/null +++ b/spider/yield-db-json/136.single-number.json @@ -0,0 +1,15 @@ +{ + "question": "136.single-number", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def singleNumber(self, nums: List[int]) -> int:\n single_number = 0\n for num in nums:\n single_number ^= num\n return single_number\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1371.find-the-longest-substring-containing-vowels-in-even-counts.en.json b/spider/yield-db-json/1371.find-the-longest-substring-containing-vowels-in-even-counts.en.json new file mode 100644 index 0000000..dec674c --- /dev/null +++ b/spider/yield-db-json/1371.find-the-longest-substring-containing-vowels-in-even-counts.en.json @@ -0,0 +1,15 @@ +{ + "question": "1371.find-the-longest-substring-containing-vowels-in-even-counts.en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass Solution {\n public int findTheLongestSubstring(String s) {\n\n int len = s.length();\n\n if (len == 0)\n return 0;\n\n int[][] preSum = new int[len][5];\n int start = getIndex(s.charAt(0));\n if (start != -1)\n preSum[0][start]++;\n\n // preSum\n for (int i = 1; i < len; i++) {\n\n int idx = getIndex(s.charAt(i));\n\n for (int j = 0; j < 5; j++) {\n\n if (idx == j)\n preSum[i][j] = preSum[i - 1][j] + 1;\n else\n preSum[i][j] = preSum[i - 1][j];\n }\n }\n\n for (int i = len - 1; i >= 0; i--) {\n\n for (int j = 0; j < len - i; j++) {\n if (checkValid(preSum, s, i, i + j))\n return i + 1\n }\n }\n return 0\n }\n\n\n public boolean checkValid(int[][] preSum, String s, int left, int right) {\n\n int idx = getIndex(s.charAt(left));\n\n for (int i = 0; i < 5; i++)\n if (((preSum[right][i] - preSum[left][i] + (idx == i ? 1 : 0)) & 1) == 1)\n return false;\n\n return true;\n }\n public int getIndex(char ch) {\n\n if (ch == 'a')\n return 0;\n else if (ch == 'e')\n return 1;\n else if (ch == 'i')\n return 2;\n else if (ch == 'o')\n return 3;\n else if (ch == 'u')\n return 4;\n else\n return -1;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/1371.find-the-longest-substring-containing-vowels-in-even-counts.json b/spider/yield-db-json/1371.find-the-longest-substring-containing-vowels-in-even-counts.json new file mode 100644 index 0000000..88c0018 --- /dev/null +++ b/spider/yield-db-json/1371.find-the-longest-substring-containing-vowels-in-even-counts.json @@ -0,0 +1,27 @@ +{ + "question": "1371.find-the-longest-substring-containing-vowels-in-even-counts", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass Solution {\n public int findTheLongestSubstring(String s) {\n\n int len = s.length();\n\n if (len == 0)\n return 0;\n\n int[][] preSum = new int[len][5];\n int start = getIndex(s.charAt(0));\n if (start != -1)\n preSum[0][start]++;\n\n // preSum\n for (int i = 1; i < len; i++) {\n\n int idx = getIndex(s.charAt(i));\n\n for (int j = 0; j < 5; j++) {\n\n if (idx == j)\n preSum[i][j] = preSum[i - 1][j] + 1;\n else\n preSum[i][j] = preSum[i - 1][j];\n }\n }\n\n for (int i = len - 1; i >= 0; i--) {\n\n for (int j = 0; j < len - i; j++) {\n if (checkValid(preSum, s, i, i + j))\n return i + 1\n }\n }\n return 0\n }\n\n\n public boolean checkValid(int[][] preSum, String s, int left, int right) {\n\n int idx = getIndex(s.charAt(left));\n\n for (int i = 0; i < 5; i++)\n if (((preSum[right][i] - preSum[left][i] + (idx == i ? 1 : 0)) & 1) == 1)\n return false;\n\n return true;\n }\n public int getIndex(char ch) {\n\n if (ch == 'a')\n return 0;\n else if (ch == 'e')\n return 1;\n else if (ch == 'i')\n return 2;\n else if (ch == 'o')\n return 3;\n else if (ch == 'u')\n return 4;\n else\n return -1;\n }\n}\n" + }, + { + "lang": "python", + "code": "\n\nclass Solution:\n def findTheLongestSubstring(self, s: str) -> int:\n for i in range(len(s), 0, -1):\n for j in range(len(s) - i + 1):\n sub = s[j:j + i]\n has_odd_vowel = False\n for vowel in ['a', 'e', 'i', 'o', 'u']:\n if sub.count(vowel) % 2 != 0:\n has_odd_vowel = True\n break\n if not has_odd_vowel: return i\n return 0\n\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n i_mapper = {\n \"a\": 0,\n \"e\": 1,\n \"i\": 2,\n \"o\": 3,\n \"u\": 4\n }\n def check(self, s, pre, l, r):\n for i in range(5):\n if s[l] in self.i_mapper and i == self.i_mapper[s[l]]: cnt = 1\n else: cnt = 0\n if (pre[r][i] - pre[l][i] + cnt) % 2 != 0: return False\n return True\n def findTheLongestSubstring(self, s: str) -> int:\n n = len(s)\n\n pre = [[0] * 5 for _ in range(n)]\n\n # pre\n for i in range(n):\n for j in range(5):\n if s[i] in self.i_mapper and self.i_mapper[s[i]] == j:\n pre[i][j] = pre[i - 1][j] + 1\n else:\n pre[i][j] = pre[i - 1][j]\n for i in range(n - 1, -1, -1):\n for j in range(n - i):\n if self.check(s, pre, j, i + j):\n return i + 1\n return 0\n" + }, + { + "lang": "python", + "code": "\n\nclass Solution:\n def findTheLongestSubstring(self, s: str) -> int:\n mapper = {\n \"a\": 1,\n \"e\": 2,\n \"i\": 4,\n \"o\": 8,\n \"u\": 16\n }\n seen = {0: -1}\n res = cur = 0\n\n for i in range(len(s)):\n if s[i] in mapper:\n cur ^= mapper.get(s[i])\n # 全部奇偶性都相同,相减一定都是偶数\n if cur in seen:\n res = max(res, i - seen.get(cur))\n else:\n seen[cur] = i\n return res\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/139.word-break.json b/spider/yield-db-json/139.word-break.json new file mode 100644 index 0000000..33d9edf --- /dev/null +++ b/spider/yield-db-json/139.word-break.json @@ -0,0 +1,10 @@ +{ + "question": "139.word-break", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/144.binary-tree-preorder-traversal.json b/spider/yield-db-json/144.binary-tree-preorder-traversal.json new file mode 100644 index 0000000..4b852d9 --- /dev/null +++ b/spider/yield-db-json/144.binary-tree-preorder-traversal.json @@ -0,0 +1,10 @@ +{ + "question": "144.binary-tree-preorder-traversal", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/1449.form-largest-integer-with-digits-that-add-up-to-target.json b/spider/yield-db-json/1449.form-largest-integer-with-digits-that-add-up-to-target.json new file mode 100644 index 0000000..c55bccc --- /dev/null +++ b/spider/yield-db-json/1449.form-largest-integer-with-digits-that-add-up-to-target.json @@ -0,0 +1,10 @@ +{ + "question": "1449.form-largest-integer-with-digits-that-add-up-to-target", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/145.binary-tree-postorder-traversal.json b/spider/yield-db-json/145.binary-tree-postorder-traversal.json new file mode 100644 index 0000000..9af84bd --- /dev/null +++ b/spider/yield-db-json/145.binary-tree-postorder-traversal.json @@ -0,0 +1,10 @@ +{ + "question": "145.binary-tree-postorder-traversal", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/146.lru-cache.json b/spider/yield-db-json/146.lru-cache.json new file mode 100644 index 0000000..daa45b1 --- /dev/null +++ b/spider/yield-db-json/146.lru-cache.json @@ -0,0 +1,10 @@ +{ + "question": "146.lru-cache", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/15.3-sum.json b/spider/yield-db-json/15.3-sum.json new file mode 100644 index 0000000..ce71656 --- /dev/null +++ b/spider/yield-db-json/15.3-sum.json @@ -0,0 +1,10 @@ +{ + "question": "15.3-sum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/150.evaluate-reverse-polish-notation.json b/spider/yield-db-json/150.evaluate-reverse-polish-notation.json new file mode 100644 index 0000000..9a534a8 --- /dev/null +++ b/spider/yield-db-json/150.evaluate-reverse-polish-notation.json @@ -0,0 +1,10 @@ +{ + "question": "150.evaluate-reverse-polish-notation", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/152.maximum-product-subarray.json b/spider/yield-db-json/152.maximum-product-subarray.json new file mode 100644 index 0000000..91ababa --- /dev/null +++ b/spider/yield-db-json/152.maximum-product-subarray.json @@ -0,0 +1,19 @@ +{ + "question": "152.maximum-product-subarray", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n\n\nclass Solution:\n def maxProduct(self, nums: List[int]) -> int:\n n = len(nums)\n max__dp = [1] * (n + 1)\n min_dp = [1] * (n + 1)\n ans = float('-inf')\n\n for i in range(1, n + 1):\n max__dp[i] = max(max__dp[i - 1] * nums[i - 1],\n min_dp[i - 1] * nums[i - 1], nums[i - 1])\n min_dp[i] = min(max__dp[i - 1] * nums[i - 1],\n min_dp[i - 1] * nums[i - 1], nums[i - 1])\n ans = max(ans, max__dp[i])\n return ans\n " + }, + { + "lang": "python", + "code": "\n\nclass Solution:\n def maxProduct(self, nums: List[int]) -> int:\n n = len(nums)\n a = b = 1\n ans = float('-inf')\n\n for i in range(1, n + 1):\n temp = a\n a = max(a * nums[i - 1],\n b * nums[i - 1], nums[i - 1])\n b = min(temp * nums[i - 1],\n b * nums[i - 1], nums[i - 1])\n ans = max(ans, a)\n return ans\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/155.min-stack.json b/spider/yield-db-json/155.min-stack.json new file mode 100644 index 0000000..74e640a --- /dev/null +++ b/spider/yield-db-json/155.min-stack.json @@ -0,0 +1,19 @@ +{ + "question": "155.min-stack", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass MinStack:\n\n def __init__(self):\n \"\"\"\n initialize your data structure here.\n \"\"\"\n self.minV = float('inf')\n self.stack = []\n\n def push(self, x: int) -> None:\n self.stack.append(x - self.minV)\n if x < self.minV:\n self.minV = x\n\n def pop(self) -> None:\n if not self.stack:\n return\n tmp = self.stack.pop()\n if tmp < 0:\n self.minV -= tmp\n\n def top(self) -> int:\n if not self.stack:\n return\n tmp = self.stack[-1]\n if tmp < 0:\n return self.minV\n else:\n return self.minV + tmp\n\n def min(self) -> int:\n return self.minV\n\n\n\n# Your MinStack object will be instantiated and called as such:\n# obj = MinStack()\n# obj.push(x)\n# obj.pop()\n# param_3 = obj.top()\n# param_4 = obj.min()\n" + }, + { + "lang": "python", + "code": "\nclass MinStack:\n\n def __init__(self):\n \"\"\"\n initialize your data structure here.\n \"\"\"\n self.stack = []\n self.minstack = []\n\n def push(self, x: int) -> None:\n self.stack.append(x)\n if not self.minstack or x <= self.minstack[-1]:\n self.minstack.append(x)\n\n def pop(self) -> None:\n tmp = self.stack.pop()\n if tmp == self.minstack[-1]:\n self.minstack.pop()\n\n def top(self) -> int:\n return self.stack[-1]\n\n def min(self) -> int:\n return self.minstack[-1]\n\n\n# Your MinStack object will be instantiated and called as such:\n# obj = MinStack()\n# obj.push(x)\n# obj.pop()\n# param_3 = obj.top()\n# param_4 = obj.min()\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/167.two-sum-ii-input-array-is-sorted.json b/spider/yield-db-json/167.two-sum-ii-input-array-is-sorted.json new file mode 100644 index 0000000..c4aeca8 --- /dev/null +++ b/spider/yield-db-json/167.two-sum-ii-input-array-is-sorted.json @@ -0,0 +1,15 @@ +{ + "question": "167.two-sum-ii-input-array-is-sorted", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def twoSum(self, numbers: List[int], target: int) -> List[int]:\n visited = {}\n for index, number in enumerate(numbers):\n if target - number in visited:\n return [visited[target-number], index+1]\n else:\n visited[number] = index + 1\n\n# 双指针思路实现\nclass Solution:\n def twoSum(self, numbers: List[int], target: int) -> List[int]:\n left, right = 0, len(numbers) - 1\n while left < right:\n if numbers[left] + numbers[right] < target:\n left += 1\n if numbers[left] + numbers[right] > target:\n right -= 1\n if numbers[left] + numbers[right] == target:\n return [left+1, right+1]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/169.majority-element.json b/spider/yield-db-json/169.majority-element.json new file mode 100644 index 0000000..e37ade3 --- /dev/null +++ b/spider/yield-db-json/169.majority-element.json @@ -0,0 +1,15 @@ +{ + "question": "169.majority-element", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def majorityElement(self, nums: List[int]) -> int:\n count, majority = 1, nums[0]\n for num in nums[1:]:\n if count == 0:\n majority = num\n if num == majority:\n count += 1\n else:\n count -= 1\n return majority\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/17.Letter-Combinations-of-a-Phone-Number.json b/spider/yield-db-json/17.Letter-Combinations-of-a-Phone-Number.json new file mode 100644 index 0000000..8212ff7 --- /dev/null +++ b/spider/yield-db-json/17.Letter-Combinations-of-a-Phone-Number.json @@ -0,0 +1,10 @@ +{ + "question": "17.Letter-Combinations-of-a-Phone-Number", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/172.factorial-trailing-zeroes.json b/spider/yield-db-json/172.factorial-trailing-zeroes.json new file mode 100644 index 0000000..b7c3dbd --- /dev/null +++ b/spider/yield-db-json/172.factorial-trailing-zeroes.json @@ -0,0 +1,15 @@ +{ + "question": "172.factorial-trailing-zeroes", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def trailingZeroes(self, n: int) -> int:\n count = 0\n while n >= 5:\n n = n // 5\n count += n\n return count\n\n\n# 递归\nclass Solution:\n def trailingZeroes(self, n: int) -> int:\n if n == 0: return 0\n return n // 5 + self.trailingZeroes(n // 5)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/19.removeNthNodeFromEndofList.json b/spider/yield-db-json/19.removeNthNodeFromEndofList.json new file mode 100644 index 0000000..dbb0fef --- /dev/null +++ b/spider/yield-db-json/19.removeNthNodeFromEndofList.json @@ -0,0 +1,15 @@ +{ + "question": "19.removeNthNodeFromEndofList", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/**\n * Definition for singly-linked list.\n * public class ListNode {\n * int val;\n * ListNode next;\n * ListNode(int x) { val = x; }\n * }\n */\nclass Solution {\n public ListNode removeNthFromEnd(ListNode head, int n) {\n TreeNode dummy = new TreeNode(0);\n dummy.next = head;\n TreeNode first = dummy;\n TreeNode second = dummy;\n\n if (int i=0; i<=n; i++) {\n first = first.next;\n }\n\n while (first != null) {\n first = first.next;\n second = second.next;\n }\n\n second.next = second.next.next;\n\n return dummy.next;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/190.reverse-bits.json b/spider/yield-db-json/190.reverse-bits.json new file mode 100644 index 0000000..a793749 --- /dev/null +++ b/spider/yield-db-json/190.reverse-bits.json @@ -0,0 +1,15 @@ +{ + "question": "190.reverse-bits", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n # @param n, an integer\n # @return an integer\n def reverseBits(self, n):\n result = 0\n for i in range(32):\n result = (result << 1) + (n & 1)\n n >>= 1\n return result\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/191.number-of-1-bits.json b/spider/yield-db-json/191.number-of-1-bits.json new file mode 100644 index 0000000..bf1240c --- /dev/null +++ b/spider/yield-db-json/191.number-of-1-bits.json @@ -0,0 +1,15 @@ +{ + "question": "191.number-of-1-bits", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution(object):\n def hammingWeight(self, n):\n \"\"\"\n :type n: int\n :rtype: int\n \"\"\"\n count = 0\n while n:\n n &= n - 1\n count += 1\n return count\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/198.house-robber.json b/spider/yield-db-json/198.house-robber.json new file mode 100644 index 0000000..4e450b3 --- /dev/null +++ b/spider/yield-db-json/198.house-robber.json @@ -0,0 +1,15 @@ +{ + "question": "198.house-robber", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def rob(self, nums: List[int]) -> int:\n if not nums:\n return 0\n\n length = len(nums)\n if length == 1:\n return nums[0]\n else:\n prev = nums[0]\n cur = max(prev, nums[1])\n for i in range(2, length):\n cur, prev = max(prev + nums[i], cur), cur\n return cur\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/199.binary-tree-right-side-view.json b/spider/yield-db-json/199.binary-tree-right-side-view.json new file mode 100644 index 0000000..0e2a277 --- /dev/null +++ b/spider/yield-db-json/199.binary-tree-right-side-view.json @@ -0,0 +1,10 @@ +{ + "question": "199.binary-tree-right-side-view", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/2.addTwoNumbers.en.json b/spider/yield-db-json/2.addTwoNumbers.en.json new file mode 100644 index 0000000..1fed6ab --- /dev/null +++ b/spider/yield-db-json/2.addTwoNumbers.en.json @@ -0,0 +1,10 @@ +{ + "question": "2.addTwoNumbers.en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/2.addTwoNumbers.json b/spider/yield-db-json/2.addTwoNumbers.json new file mode 100644 index 0000000..07c0227 --- /dev/null +++ b/spider/yield-db-json/2.addTwoNumbers.json @@ -0,0 +1,10 @@ +{ + "question": "2.addTwoNumbers", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/20.validParentheses.json b/spider/yield-db-json/20.validParentheses.json new file mode 100644 index 0000000..9b8cf23 --- /dev/null +++ b/spider/yield-db-json/20.validParentheses.json @@ -0,0 +1,10 @@ +{ + "question": "20.validParentheses", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/200.number-of-islands.json b/spider/yield-db-json/200.number-of-islands.json new file mode 100644 index 0000000..a71d5a0 --- /dev/null +++ b/spider/yield-db-json/200.number-of-islands.json @@ -0,0 +1,15 @@ +{ + "question": "200.number-of-islands", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n public int numIslands(char[][] grid) {\n if (grid == null || grid.length == 0 || grid[0].length == 0) return 0;\n\n int count = 0;\n for (int row = 0; row < grid.length; row++) {\n for (int col = 0; col < grid[0].length; col++) {\n if (grid[row][col] == '1') {\n dfs(grid, row, col);\n count++;\n }\n }\n }\n return count;\n }\n\n private void dfs(char[][] grid,int row,int col) {\n if (row<0||row== grid.length||col<0||col==grid[0].length||grid[row][col]!='1') {\n return;\n }\n grid[row][col] = '0';\n dfs(grid, row-1, col);\n dfs(grid, row+1, col);\n dfs(grid, row, col+1);\n dfs(grid, row, col-1);\n }\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/201.bitwise-and-of-numbers-range.json b/spider/yield-db-json/201.bitwise-and-of-numbers-range.json new file mode 100644 index 0000000..e019ce8 --- /dev/null +++ b/spider/yield-db-json/201.bitwise-and-of-numbers-range.json @@ -0,0 +1,15 @@ +{ + "question": "201.bitwise-and-of-numbers-range", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def rangeBitwiseAnd(self, m: int, n: int) -> int:\n cnt = 0\n while m != n:\n m >>= 1\n n >>= 1\n cnt += 1\n\n return m << cnt\n " + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/203.remove-linked-list-elements.json b/spider/yield-db-json/203.remove-linked-list-elements.json new file mode 100644 index 0000000..8089a68 --- /dev/null +++ b/spider/yield-db-json/203.remove-linked-list-elements.json @@ -0,0 +1,15 @@ +{ + "question": "203.remove-linked-list-elements", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# Definition for singly-linked list.\n# class ListNode:\n# def __init__(self, x):\n# self.val = x\n# self.next = None\n\nclass Solution:\n def removeElements(self, head: ListNode, val: int) -> ListNode:\n prev = ListNode(0)\n prev.next = head\n cur = prev\n while cur.next:\n if cur.next.val == val:\n cur.next = cur.next.next\n else:\n cur = cur.next\n return prev.next\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/206.reverse-linked-list.json b/spider/yield-db-json/206.reverse-linked-list.json new file mode 100644 index 0000000..4788e85 --- /dev/null +++ b/spider/yield-db-json/206.reverse-linked-list.json @@ -0,0 +1,23 @@ +{ + "question": "206.reverse-linked-list", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/**\n * Definition for singly-linked list.\n * public class ListNode {\n * int val;\n * ListNode next;\n * ListNode(int x) { val = x; }\n * }\n */\nclass Solution {\n public ListNode reverseList(ListNode head) {\n ListNode pre = null, cur = head;\n\n while (cur != null) {\n ListNode next = cur.next;\n cur.next = pre;\n pre = cur;\n cur = next;\n }\n\n return pre;\n }\n}\n" + }, + { + "lang": "python", + "code": "\n# Definition for singly-linked list.\n# class ListNode:\n# def __init__(self, x):\n# self.val = x\n# self.next = None\n\nclass Solution:\n def reverseList(self, head: ListNode) -> ListNode:\n if not head: return None\n prev = None\n cur = head\n while cur:\n cur.next, prev, cur = prev, cur, cur.next\n return prev\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def reverseList(self, head: ListNode) -> ListNode:\n if not head or not head.next: return head\n ans = self.reverseList(head.next)\n head.next.next = head\n head.next = None\n return ans\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/208.implement-trie-prefix-tree.json b/spider/yield-db-json/208.implement-trie-prefix-tree.json new file mode 100644 index 0000000..f2808d4 --- /dev/null +++ b/spider/yield-db-json/208.implement-trie-prefix-tree.json @@ -0,0 +1,10 @@ +{ + "question": "208.implement-trie-prefix-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/209.minimum-size-subarray-sum.json b/spider/yield-db-json/209.minimum-size-subarray-sum.json new file mode 100644 index 0000000..7fd7453 --- /dev/null +++ b/spider/yield-db-json/209.minimum-size-subarray-sum.json @@ -0,0 +1,15 @@ +{ + "question": "209.minimum-size-subarray-sum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n\nclass Solution:\n def minSubArrayLen(self, s: int, nums: List[int]) -> int:\n l = total = 0\n ans = len(nums) + 1\n for r in range(len(nums)):\n total += nums[r]\n while total >= s:\n ans = min(ans, r - l + 1)\n total -= nums[l]\n l += 1\n return 0 if ans == len(nums) + 1 else ans\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/21.MergeTwoSortedLists.json b/spider/yield-db-json/21.MergeTwoSortedLists.json new file mode 100644 index 0000000..20b6ecb --- /dev/null +++ b/spider/yield-db-json/21.MergeTwoSortedLists.json @@ -0,0 +1,10 @@ +{ + "question": "21.MergeTwoSortedLists", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/211.add-and-search-word-data-structure-design.json b/spider/yield-db-json/211.add-and-search-word-data-structure-design.json new file mode 100644 index 0000000..f5d9fe2 --- /dev/null +++ b/spider/yield-db-json/211.add-and-search-word-data-structure-design.json @@ -0,0 +1,27 @@ +{ + "question": "211.add-and-search-word-data-structure-design", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\ndef search(self, word):\n \"\"\"\n Returns if the word is in the trie.\n :type word: str\n :rtype: bool\n \"\"\"\n curr = self.Trie\n for i, w in enumerate(word):\n if w == '.':\n wizards = []\n for k in curr.keys():\n if k == '#':\n continue\n wizards.append(self.search(word[:i] + k + word[i + 1:]))\n return any(wizards)\n if w not in curr:\n return False\n curr = curr[w]\n return \"#\" in curr\n" + }, + { + "lang": "python", + "code": "\ndef search(self, word):\n \"\"\"\n Returns if the word is in the trie.\n :type word: str\n :rtype: bool\n \"\"\"\n curr = self.Trie\n for w in word:\n if w not in curr:\n return False\n curr = curr[w]\n return \"#\" in curr\n" + }, + { + "lang": "python", + "code": "\nclass Trie:\n\n def __init__(self):\n \"\"\"\n Initialize your data structure here.\n \"\"\"\n self.Trie = {}\n\n def insert(self, word):\n \"\"\"\n Inserts a word into the trie.\n :type word: str\n :rtype: void\n \"\"\"\n curr = self.Trie\n for w in word:\n if w not in curr:\n curr[w] = {}\n curr = curr[w]\n curr['#'] = 1\n\n def search(self, word):\n \"\"\"\n Returns if the word is in the trie.\n :type word: str\n :rtype: bool\n \"\"\"\n curr = self.Trie\n for i, w in enumerate(word):\n if w == '.':\n wizards = []\n for k in curr.keys():\n if k == '#':\n continue\n wizards.append(self.search(word[:i] + k + word[i + 1:]))\n return any(wizards)\n if w not in curr:\n return False\n curr = curr[w]\n return \"#\" in curr\n" + }, + { + "lang": "python", + "code": "\nclass WordDictionary:\n\n def __init__(self):\n \"\"\"\n Initialize your data structure here.\n \"\"\"\n self.trie = Trie()\n\n def addWord(self, word: str) -> None:\n \"\"\"\n Adds a word into the data structure.\n \"\"\"\n self.trie.insert(word)\n\n def search(self, word: str) -> bool:\n \"\"\"\n Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.\n \"\"\"\n return self.trie.search(word)\n\n\n# Your WordDictionary object will be instantiated and called as such:\n# obj = WordDictionary()\n# obj.addWord(word)\n# param_2 = obj.search(word)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/212.word-search-ii.json b/spider/yield-db-json/212.word-search-ii.json new file mode 100644 index 0000000..a1da16f --- /dev/null +++ b/spider/yield-db-json/212.word-search-ii.json @@ -0,0 +1,19 @@ +{ + "question": "212.word-search-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Trie:\n\n def __init__(self):\n \"\"\"\n Initialize your data structure here.\n \"\"\"\n self.Trie = {}\n\n def insert(self, word):\n \"\"\"\n Inserts a word into the trie.\n :type word: str\n :rtype: void\n \"\"\"\n curr = self.Trie\n for w in word:\n if w not in curr:\n curr[w] = {}\n curr = curr[w]\n curr['#'] = 1\n\n def startsWith(self, prefix):\n \"\"\"\n Returns if there is any word in the trie that starts with the given prefix.\n :type prefix: str\n :rtype: bool\n \"\"\"\n\n curr = self.Trie\n for w in prefix:\n if w not in curr:\n return False\n curr = curr[w]\n return True\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:\n m = len(board)\n if m == 0:\n return []\n n = len(board[0])\n trie = Trie()\n seen = None\n res = set()\n for word in words:\n trie.insert(word)\n\n def dfs(s, i, j):\n if (i, j) in seen or i < 0 or i >= m or j < 0 or j >= n or not trie.startsWith(s):\n return\n s += board[i][j]\n seen[(i, j)] = True\n\n if s in words:\n res.add(s)\n dfs(s, i + 1, j)\n dfs(s, i - 1, j)\n dfs(s, i, j + 1)\n dfs(s, i, j - 1)\n\n del seen[(i, j)]\n\n for i in range(m):\n for j in range(n):\n seen = dict()\n dfs(\"\", i, j)\n return list(res)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/215.kth-largest-element-in-an-array.json b/spider/yield-db-json/215.kth-largest-element-in-an-array.json new file mode 100644 index 0000000..ac7431e --- /dev/null +++ b/spider/yield-db-json/215.kth-largest-element-in-an-array.json @@ -0,0 +1,23 @@ +{ + "question": "215.kth-largest-element-in-an-array", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass KthLargestElementSort {\n public int findKthlargest2(int[] nums, int k) {\n Arrays.sort(nums);\n return nums[nums.length - k];\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass KthLargestElementHeap {\n public int findKthLargest(int[] nums, int k) {\n PriorityQueue pq = new PriorityQueue<>();\n for (int num : nums) {\n pq.offer(num);\n if (pq.size() > k) {\n pq.poll();\n }\n }\n return pq.poll();\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass KthLargestElementQuickSelect {\n static Random random = new Random();\n public int findKthLargest3(int[] nums, int k) {\n int len = nums.length;\n return select(nums, 0, len - 1, len - k);\n }\n \n private int select(int[] nums, int left, int right, int k) {\n if (left == right) return nums[left];\n // random select pivotIndex between left and right\n int pivotIndex = left + random.nextInt(right - left);\n // do partition, move smaller than pivot number into pivot left\n int pos = partition(nums, left, right, pivotIndex);\n if (pos == k) {\n return nums[pos];\n } else if (pos > k) {\n return select(nums, left, pos - 1, k);\n } else {\n return select(nums, pos + 1, right, k);\n }\n }\n \n private int partition(int[] nums, int left, int right, int pivotIndex) {\n int pivot = nums[pivotIndex];\n // move pivot to end\n swap(nums, right, pivotIndex);\n int pos = left;\n // move smaller num to pivot left\n for (int i = left; i <= right; i++) {\n if (nums[i] < pivot) {\n swap(nums, pos++, i);\n }\n }\n // move pivot to original place\n swap(nums, right, pos);\n return pos;\n }\n \n private void swap(int[] nums, int i, int j) {\n int tmp = nums[i];\n nums[i] = nums[j];\n nums[j] = tmp;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/219.contains-duplicate-ii.json b/spider/yield-db-json/219.contains-duplicate-ii.json new file mode 100644 index 0000000..d346987 --- /dev/null +++ b/spider/yield-db-json/219.contains-duplicate-ii.json @@ -0,0 +1,15 @@ +{ + "question": "219.contains-duplicate-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:\n d = {}\n for index, num in enumerate(nums):\n if num in d and index - d[num] <= k:\n return True\n d[num] = index\n return False\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/22.GenerateParentheses.json b/spider/yield-db-json/22.GenerateParentheses.json new file mode 100644 index 0000000..d0bd920 --- /dev/null +++ b/spider/yield-db-json/22.GenerateParentheses.json @@ -0,0 +1,10 @@ +{ + "question": "22.GenerateParentheses", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/221.maximal-square.json b/spider/yield-db-json/221.maximal-square.json new file mode 100644 index 0000000..03328f9 --- /dev/null +++ b/spider/yield-db-json/221.maximal-square.json @@ -0,0 +1,15 @@ +{ + "question": "221.maximal-square", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maximalSquare(self, matrix: List[List[str]]) -> int:\n res = 0\n m = len(matrix)\n if m == 0:\n return 0\n n = len(matrix[0])\n dp = [[0] * (n + 1) for _ in range(m + 1)]\n\n for i in range(1, m + 1):\n for j in range(1, n + 1):\n dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 if matrix[i - 1][j - 1] == \"1\" else 0\n res = max(res, dp[i][j])\n return res ** 2\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/226.invert-binary-tree.json b/spider/yield-db-json/226.invert-binary-tree.json new file mode 100644 index 0000000..5ddb700 --- /dev/null +++ b/spider/yield-db-json/226.invert-binary-tree.json @@ -0,0 +1,15 @@ +{ + "question": "226.invert-binary-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# Definition for a binary tree node.\n# class TreeNode:\n# def __init__(self, x):\n# self.val = x\n# self.left = None\n# self.right = None\n\nclass Solution:\n def invertTree(self, root: TreeNode) -> TreeNode:\n if not root:\n return None\n stack = [root]\n while stack:\n node = stack.pop(0)\n node.left, node.right = node.right, node.left\n if node.left:\n stack.append(node.left)\n if node.right:\n stack.append(node.right)\n return root\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/229.majority-element-ii.json b/spider/yield-db-json/229.majority-element-ii.json new file mode 100644 index 0000000..0f90671 --- /dev/null +++ b/spider/yield-db-json/229.majority-element-ii.json @@ -0,0 +1,15 @@ +{ + "question": "229.majority-element-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/*\n * @lc app=leetcode id=229 lang=java\n *\n * [229] Majority Element II\n */\nclass Solution {\n public List majorityElement(int[] nums) {\n List res = new ArrayList();\n if (nums == null || nums.length == 0)\n return res;\n int n1 = nums[0], n2 = nums[0], cnt1 = 0, cnt2 = 0, len = nums.length;\n for (int i = 0; i < len; i++) {\n if (nums[i] == n1)\n cnt1++;\n else if (nums[i] == n2)\n cnt2++;\n else if (cnt1 == 0) {\n n1 = nums[i];\n cnt1 = 1;\n } else if (cnt2 == 0) {\n n2 = nums[i];\n cnt2 = 1;\n } else {\n cnt1--;\n cnt2--;\n }\n }\n cnt1 = 0;\n cnt2 = 0;\n for (int i = 0; i < len; i++) {\n if (nums[i] == n1)\n cnt1++;\n else if (nums[i] == n2)\n cnt2++;\n }\n if (cnt1 > len / 3)\n res.add(n1);\n if (cnt2 > len / 3 && n1 != n2)\n res.add(n2);\n return res;\n }\n}\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/23.merge-k-sorted-lists.json b/spider/yield-db-json/23.merge-k-sorted-lists.json new file mode 100644 index 0000000..e8b52ca --- /dev/null +++ b/spider/yield-db-json/23.merge-k-sorted-lists.json @@ -0,0 +1,10 @@ +{ + "question": "23.merge-k-sorted-lists", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/230.kth-smallest-element-in-a-bst.json b/spider/yield-db-json/230.kth-smallest-element-in-a-bst.json new file mode 100644 index 0000000..413884b --- /dev/null +++ b/spider/yield-db-json/230.kth-smallest-element-in-a-bst.json @@ -0,0 +1,15 @@ +{ + "question": "230.kth-smallest-element-in-a-bst", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nprivate int count = 1;\nprivate int res;\n\npublic int KthSmallest (TreeNode root, int k) {\n inorder(root, k);\n return res;\n}\n\npublic void inorder (TreeNode root, int k) {\n if (root == null) return;\n\n inorder(root.left, k);\n\n if (count++ == k) {\n res = root.val;\n return;\n }\n \n inorder(root.right, k);\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/232.implement-queue-using-stacks.json b/spider/yield-db-json/232.implement-queue-using-stacks.json new file mode 100644 index 0000000..9bbe95d --- /dev/null +++ b/spider/yield-db-json/232.implement-queue-using-stacks.json @@ -0,0 +1,19 @@ +{ + "question": "232.implement-queue-using-stacks", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass MyQueue {\n Stack pushStack = new Stack<> ();\n Stack popStack = new Stack<> ();\n\n /** Initialize your data structure here. */\n public MyQueue() {\n\n }\n \n /** Push element x to the back of queue. */\n public void push(int x) {\n while (!popStack.isEmpty()) {\n pushStack.push(popStack.pop());\n }\n pushStack.push(x);\n }\n \n /** Removes the element from in front of queue and returns that element. */\n public int pop() {\n while (!pushStack.isEmpty()) {\n popStack.push(pushStack.pop());\n }\n return popStack.pop();\n }\n \n /** Get the front element. */\n public int peek() {\n while (!pushStack.isEmpty()) {\n popStack.push(pushStack.pop());\n }\n return popStack.peek();\n }\n \n /** Returns whether the queue is empty. */\n public boolean empty() {\n return pushStack.isEmpty() && popStack.isEmpty();\n }\n}\n\n/**\n * Your MyQueue object will be instantiated and called as such:\n * MyQueue obj = new MyQueue();\n * obj.push(x);\n * int param_2 = obj.pop();\n * int param_3 = obj.peek();\n * boolean param_4 = obj.empty();\n */\n" + }, + { + "lang": "python", + "code": "\nclass MyQueue:\n\n def __init__(self):\n \"\"\"\n Initialize your data structure here.\n \"\"\"\n self.stack = []\n self.help_stack = []\n\n def push(self, x: int) -> None:\n \"\"\"\n Push element x to the back of queue.\n \"\"\"\n while self.stack:\n self.help_stack.append(self.stack.pop())\n self.help_stack.append(x)\n while self.help_stack:\n self.stack.append(self.help_stack.pop())\n\n def pop(self) -> int:\n \"\"\"\n Removes the element from in front of queue and returns that element.\n \"\"\"\n return self.stack.pop()\n\n def peek(self) -> int:\n \"\"\"\n Get the front element.\n \"\"\"\n return self.stack[-1]\n\n def empty(self) -> bool:\n \"\"\"\n Returns whether the queue is empty.\n \"\"\"\n return not bool(self.stack)\n\n\n# Your MyQueue object will be instantiated and called as such:\n# obj = MyQueue()\n# obj.push(x)\n# param_2 = obj.pop()\n# param_3 = obj.peek()\n# param_4 = obj.empty()\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/236.lowest-common-ancestor-of-a-binary-tree.json b/spider/yield-db-json/236.lowest-common-ancestor-of-a-binary-tree.json new file mode 100644 index 0000000..1633c97 --- /dev/null +++ b/spider/yield-db-json/236.lowest-common-ancestor-of-a-binary-tree.json @@ -0,0 +1,10 @@ +{ + "question": "236.lowest-common-ancestor-of-a-binary-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/238.product-of-array-except-self.json b/spider/yield-db-json/238.product-of-array-except-self.json new file mode 100644 index 0000000..b6f6d85 --- /dev/null +++ b/spider/yield-db-json/238.product-of-array-except-self.json @@ -0,0 +1,10 @@ +{ + "question": "238.product-of-array-except-self", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/239.sliding-window-maximum.json b/spider/yield-db-json/239.sliding-window-maximum.json new file mode 100644 index 0000000..8eb8f4e --- /dev/null +++ b/spider/yield-db-json/239.sliding-window-maximum.json @@ -0,0 +1,19 @@ +{ + "question": "239.sliding-window-maximum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:\n if k == 0: return []\n res = []\n for r in range(k - 1, len(nums)):\n res.append(max(nums[r - k + 1:r + 1]))\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:\n deque, res, n = [], [], len(nums)\n for i in range(n):\n while deque and deque[0] < i - k + 1:\n deque.pop(0)\n while deque and nums[i] > nums[deque[-1]]:\n deque.pop(-1)\n deque.append(i)\n if i >= k - 1: res.append(nums[deque[0]])\n return res\n\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/24.swapNodesInPairs.json b/spider/yield-db-json/24.swapNodesInPairs.json new file mode 100644 index 0000000..2f194a9 --- /dev/null +++ b/spider/yield-db-json/24.swapNodesInPairs.json @@ -0,0 +1,15 @@ +{ + "question": "24.swapNodesInPairs", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def swapPairs(self, head: ListNode) -> ListNode:\n \"\"\"\n 用递归实现链表相邻互换:\n 第一个节点的 next 是第三、第四个节点交换的结果,第二个节点的 next 是第一个节点;\n 第三个节点的 next 是第五、第六个节点交换的结果,第四个节点的 next 是第三个节点;\n 以此类推\n :param ListNode head\n :return ListNode\n \"\"\"\n # 如果为 None 或 next 为 None,则直接返回\n if not head or not head.next:\n return head\n\n _next = head.next\n head.next = self.swapPairs(_next.next)\n _next.next = head\n return _next\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/240.search-a-2-d-matrix-ii.json b/spider/yield-db-json/240.search-a-2-d-matrix-ii.json new file mode 100644 index 0000000..295ff9a --- /dev/null +++ b/spider/yield-db-json/240.search-a-2-d-matrix-ii.json @@ -0,0 +1,15 @@ +{ + "question": "240.search-a-2-d-matrix-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def searchMatrix(self, matrix, target):\n m = len(matrix)\n if m == 0:\n return False\n n = len(matrix[0])\n i = m - 1\n j = 0\n\n while i >= 0 and j < n:\n if matrix[i][j] == target:\n return True\n if matrix[i][j] > target:\n i -= 1\n else:\n j += 1\n return False\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/25.reverse-nodes-in-k-groups-cn.json b/spider/yield-db-json/25.reverse-nodes-in-k-groups-cn.json new file mode 100644 index 0000000..6325585 --- /dev/null +++ b/spider/yield-db-json/25.reverse-nodes-in-k-groups-cn.json @@ -0,0 +1,19 @@ +{ + "question": "25.reverse-nodes-in-k-groups-cn", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass ReverseKGroupsLinkedList {\n public ListNode reverseKGroup(ListNode head, int k) {\n if (head == null || k == 1) {\n return head;\n }\n ListNode dummy = new ListNode(0);\n dummy.next = head;\n\n ListNode start = dummy;\n ListNode end = head;\n int count = 0;\n while (end != null) {\n count++;\n // group\n if (count % k == 0) {\n // reverse linked list (start, end]\n start = reverse(start, end.next);\n end = start.next;\n } else {\n end = end.next;\n }\n }\n return dummy.next;\n }\n\n /**\n * reverse linked list from range (start, end), return last node.\n * for example:\n * 0->1->2->3->4->5->6->7->8\n * | |\n * start end\n *\n * After call start = reverse(start, end)\n *\n * 0->3->2->1->4->5->6->7->8\n * | |\n * start end\n * first\n *\n */\n private ListNode reverse(ListNode start, ListNode end) {\n ListNode curr = start.next;\n ListNode prev = start;\n ListNode first = curr;\n while (curr != end){\n ListNode temp = curr.next;\n curr.next = prev;\n prev = curr;\n curr = temp;\n }\n start.next = prev;\n first.next = curr;\n return first;\n }\n}\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def reverseKGroup(self, head: ListNode, k: int) -> ListNode:\n if head is None or k < 2:\n return head\n dummy = ListNode(0)\n dummy.next = head\n start = dummy\n end = head\n count = 0\n while end:\n count += 1\n if count % k == 0:\n start = self.reverse(start, end.next)\n end = start.next\n else:\n end = end.next\n return dummy.next\n\n def reverse(self, start, end):\n prev, curr = start, start.next\n first = curr\n while curr != end:\n temp = curr.next\n curr.next = prev\n prev = curr\n curr = temp\n start.next = prev\n first.next = curr\n return first\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/25.reverse-nodes-in-k-groups-en.json b/spider/yield-db-json/25.reverse-nodes-in-k-groups-en.json new file mode 100644 index 0000000..1d75cb8 --- /dev/null +++ b/spider/yield-db-json/25.reverse-nodes-in-k-groups-en.json @@ -0,0 +1,19 @@ +{ + "question": "25.reverse-nodes-in-k-groups-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass ReverseKGroupsLinkedList {\n public ListNode reverseKGroup(ListNode head, int k) {\n if (head == null || k == 1) {\n return head;\n }\n ListNode dummy = new ListNode(0);\n dummy.next = head;\n \n ListNode start = dummy;\n ListNode end = head;\n int count = 0;\n while (end != null) {\n count++;\n // group\n if (count % k == 0) {\n // reverse linked list (start, end]\n start = reverse(start, end.next);\n end = start.next;\n } else {\n end = end.next;\n }\n }\n return dummy.next;\n }\n \n /** \n * reverse linked list from range (start, end), return last node.\n * for example: \n * 0->1->2->3->4->5->6->7->8\n * | |\n * start end\n * \n * After call start = reverse(start, end)\n * \n * 0->3->2->1->4->5->6->7->8\n * | |\n * start end\n * \n * @return the reversed list's 'start' node, which is the precedence of node end\n */\n private ListNode reverse(ListNode start, ListNode end) {\n ListNode curr = start.next;\n ListNode prev = start;\n ListNode first = curr;\n while (curr != end){\n ListNode temp = curr.next;\n curr.next = prev;\n prev = curr;\n curr = temp;\n }\n start.next = prev;\n first.next = curr;\n return first;\n }\n}\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def reverseKGroup(self, head: ListNode, k: int) -> ListNode:\n if head is None or k < 2:\n return head\n dummy = ListNode(0)\n dummy.next = head\n start = dummy\n end = head\n count = 0\n while end:\n count += 1\n if count % k == 0:\n start = self.reverse(start, end.next)\n end = start.next\n else:\n end = end.next\n return dummy.next\n \n def reverse(self, start, end):\n prev, curr = start, start.next\n first = curr\n while curr != end:\n temp = curr.next\n curr.next = prev\n prev = curr\n curr = temp\n start.next = prev\n first.next = curr\n return first\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/26.remove-duplicates-from-sorted-array.json b/spider/yield-db-json/26.remove-duplicates-from-sorted-array.json new file mode 100644 index 0000000..8222ccc --- /dev/null +++ b/spider/yield-db-json/26.remove-duplicates-from-sorted-array.json @@ -0,0 +1,15 @@ +{ + "question": "26.remove-duplicates-from-sorted-array", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def removeDuplicates(self, nums: List[int]) -> int:\n if nums:\n slow = 0\n for fast in range(1, len(nums)):\n if nums[fast] != nums[slow]:\n slow += 1\n nums[slow] = nums[fast]\n return slow + 1\n else:\n return 0\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/263.ugly-number.json b/spider/yield-db-json/263.ugly-number.json new file mode 100644 index 0000000..57d263d --- /dev/null +++ b/spider/yield-db-json/263.ugly-number.json @@ -0,0 +1,15 @@ +{ + "question": "263.ugly-number", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# 非递归写法\nclass Solution:\n def isUgly(self, num: int) -> bool:\n if num <= 0:\n return False\n for i in (2, 3, 5):\n while num % i == 0:\n num /= i\n return num == 1\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/279.perfect-squares.json b/spider/yield-db-json/279.perfect-squares.json new file mode 100644 index 0000000..0afd6fe --- /dev/null +++ b/spider/yield-db-json/279.perfect-squares.json @@ -0,0 +1,10 @@ +{ + "question": "279.perfect-squares", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/283.move-zeroes.json b/spider/yield-db-json/283.move-zeroes.json new file mode 100644 index 0000000..3b17517 --- /dev/null +++ b/spider/yield-db-json/283.move-zeroes.json @@ -0,0 +1,15 @@ +{ + "question": "283.move-zeroes", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def moveZeroes(self, nums: List[int]) -> None:\n \"\"\"\n Do not return anything, modify nums in-place instead.\n \"\"\"\n slow = fast = 0\n while fast < len(nums):\n if nums[fast] != 0:\n nums[fast], nums[slow] = nums[slow], nums[fast]\n slow += 1\n fast += 1\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/29.divide-two-integers.json b/spider/yield-db-json/29.divide-two-integers.json new file mode 100644 index 0000000..1911533 --- /dev/null +++ b/spider/yield-db-json/29.divide-two-integers.json @@ -0,0 +1,15 @@ +{ + "question": "29.divide-two-integers", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def divide(self, dividend: int, divisor: int) -> int:\n \"\"\"\n 二分法\n :param int divisor\n :param int dividend\n :return int\n \"\"\"\n # 错误处理\n if divisor == 0:\n raise ZeroDivisionError\n if abs(divisor) == 1:\n result = dividend if 1 == divisor else -dividend\n return min(2**31-1, max(-2**31, result))\n\n # 确定结果的符号\n sign = ((dividend >= 0) == (divisor >= 0))\n \n result = 0\n # abs也可以直接写在while条件中,不过可能会多计算几次\n _divisor = abs(divisor)\n _dividend = abs(dividend)\n \n while _divisor <= _dividend:\n r, _dividend = self._multi_divide(_divisor, _dividend)\n result += r\n \n result = result if sign else -result\n\n # 注意返回值不能超过32位有符号数的表示范围\n return min(2**31-1, max(-2**31, result))\n \n def _multi_divide(self, divisor, dividend):\n \"\"\"\n 翻倍除法,如果可以被除,则下一步除数翻倍,直至除数大于被除数,\n 返回商加总的结果与被除数的剩余值;\n 这里就不做异常处理了;\n :param int divisor\n :param int dividend\n :return tuple result, left_dividend\n \"\"\"\n result = 0\n times_count = 1\n while divisor <= dividend:\n dividend -= divisor\n result += times_count\n times_count += times_count\n divisor += divisor\n return result, dividend\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/295.find-median-from-data-stream.json b/spider/yield-db-json/295.find-median-from-data-stream.json new file mode 100644 index 0000000..2383444 --- /dev/null +++ b/spider/yield-db-json/295.find-median-from-data-stream.json @@ -0,0 +1,10 @@ +{ + "question": "295.find-median-from-data-stream", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/3.longestSubstringWithoutRepeatingCharacters.json b/spider/yield-db-json/3.longestSubstringWithoutRepeatingCharacters.json new file mode 100644 index 0000000..f2e5ab2 --- /dev/null +++ b/spider/yield-db-json/3.longestSubstringWithoutRepeatingCharacters.json @@ -0,0 +1,15 @@ +{ + "question": "3.longestSubstringWithoutRepeatingCharacters", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nfrom collections import defaultdict\n\n\nclass Solution:\n def lengthOfLongestSubstring(self, s: str) -> int:\n l = 0\n ans = 0\n counter = defaultdict(lambda: 0)\n\n for r in range(len(s)):\n while counter.get(s[r], 0) != 0:\n counter[s[l]] = counter.get(s[l], 0) - 1\n l += 1\n counter[s[r]] += 1\n ans = max(ans, r - l + 1)\n\n return ans\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/30.substring-with-concatenation-of-all-words.json b/spider/yield-db-json/30.substring-with-concatenation-of-all-words.json new file mode 100644 index 0000000..e49e5ab --- /dev/null +++ b/spider/yield-db-json/30.substring-with-concatenation-of-all-words.json @@ -0,0 +1,15 @@ +{ + "question": "30.substring-with-concatenation-of-all-words", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nfrom collections import Counter\n\n\nclass Solution:\n def findSubstring(self, s: str, words: List[str]) -> List[int]:\n if not s or not words:\n return []\n res = []\n n = len(words)\n word_len = len(words[0])\n window_len = word_len * n\n target = Counter(words)\n i = 0\n while i < len(s) - window_len + 1:\n sliced = []\n start = i\n for _ in range(n):\n sliced.append(s[start:start + word_len])\n start += word_len\n if Counter(sliced) == target:\n res.append(i)\n i += 1\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/301.remove-invalid-parentheses.json b/spider/yield-db-json/301.remove-invalid-parentheses.json new file mode 100644 index 0000000..27fe3f8 --- /dev/null +++ b/spider/yield-db-json/301.remove-invalid-parentheses.json @@ -0,0 +1,10 @@ +{ + "question": "301.remove-invalid-parentheses", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/309.best-time-to-buy-and-sell-stock-with-cooldown.json b/spider/yield-db-json/309.best-time-to-buy-and-sell-stock-with-cooldown.json new file mode 100644 index 0000000..4832ce9 --- /dev/null +++ b/spider/yield-db-json/309.best-time-to-buy-and-sell-stock-with-cooldown.json @@ -0,0 +1,10 @@ +{ + "question": "309.best-time-to-buy-and-sell-stock-with-cooldown", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/31.next-permutation.json b/spider/yield-db-json/31.next-permutation.json new file mode 100644 index 0000000..2d0ed5f --- /dev/null +++ b/spider/yield-db-json/31.next-permutation.json @@ -0,0 +1,19 @@ +{ + "question": "31.next-permutation", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def nextPermutation(self, nums):\n \"\"\"\n Do not return anything, modify nums in-place instead.\n :param list nums\n \"\"\"\n # 第一步,从后往前,找到下降点\n down_index = None\n for i in range(len(nums)-2, -1, -1):\n if nums[i] < nums[i+1]:\n down_index = i\n break\n # 如果没有下降点,重新排列\n if down_index is None:\n nums.reverse()\n # 如果有下降点\n else:\n # 第二步,从后往前,找到比下降点大的数,对换位置\n for i in range(len(nums)-1, i, -1):\n if nums[down_index] < nums[i]:\n nums[down_index], nums[i] = nums[i], nums[down_index]\n break\n # 第三部,重新排列下降点之后的数\n i, j = down_index+1, len(nums)-1\n while i < j:\n nums[i], nums[j] = nums[j], nums[i]\n i += 1\n j -= 1\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def nextPermutation(self, nums):\n \"\"\"\n Do not return anything, modify nums in-place instead.\n :param list nums\n \"\"\"\n # 第一步,从后往前,找到下降点\n down_index = None\n for i in range(len(nums)-2, -1, -1):\n if nums[i] < nums[i+1]:\n down_index = i\n break\n # 如果没有下降点,重新排列\n if down_index is None:\n nums.reverse()\n # 如果有下降点\n else:\n # 第二步,从后往前,找到比下降点大的数,对换位置\n for i in range(len(nums)-1, i, -1):\n if nums[down_index] < nums[i]:\n nums[down_index], nums[i] = nums[i], nums[down_index]\n break\n # 第三步,重新排列下降点之后的数\n i, j = down_index+1, len(nums)-1\n while i < j:\n nums[i], nums[j] = nums[j], nums[i]\n i += 1\n j -= 1\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/312.burst-balloons.json b/spider/yield-db-json/312.burst-balloons.json new file mode 100644 index 0000000..a05d6f5 --- /dev/null +++ b/spider/yield-db-json/312.burst-balloons.json @@ -0,0 +1,10 @@ +{ + "question": "312.burst-balloons", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/32.longest-valid-parentheses.json b/spider/yield-db-json/32.longest-valid-parentheses.json new file mode 100644 index 0000000..dcb9568 --- /dev/null +++ b/spider/yield-db-json/32.longest-valid-parentheses.json @@ -0,0 +1,15 @@ +{ + "question": "32.longest-valid-parentheses", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\ns = '(())())'\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/322.coin-change.json b/spider/yield-db-json/322.coin-change.json new file mode 100644 index 0000000..bbaddd3 --- /dev/null +++ b/spider/yield-db-json/322.coin-change.json @@ -0,0 +1,19 @@ +{ + "question": "322.coin-change", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def coinChange(self, coins: List[int], amount: int) -> int:\n if amount < 0:\n return - 1\n dp = [[amount + 1 for _ in range(len(coins) + 1)]\n for _ in range(amount + 1)]\n # 初始化第一行为0,其他为最大值(也就是amount + 1)\n\n for j in range(len(coins) + 1):\n dp[0][j] = 0\n\n for i in range(1, amount + 1):\n for j in range(1, len(coins) + 1):\n if i - coins[j - 1] >= 0:\n dp[i][j] = min(\n dp[i][j - 1], dp[i - coins[j - 1]][j] + 1)\n else:\n dp[i][j] = dp[i][j - 1]\n\n return -1 if dp[-1][-1] == amount + 1 else dp[-1][-1]\n " + }, + { + "lang": "python", + "code": "\nclass Solution:\n def coinChange(self, coins: List[int], amount: int) -> int:\n dp = [amount + 1] * (amount + 1)\n dp[0] = 0\n\n for i in range(1, amount + 1):\n for j in range(len(coins)):\n if i >= coins[j]:\n dp[i] = min(dp[i], dp[i - coins[j]] + 1)\n\n return -1 if dp[-1] == amount + 1 else dp[-1]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/328.odd-even-linked-list.json b/spider/yield-db-json/328.odd-even-linked-list.json new file mode 100644 index 0000000..af47732 --- /dev/null +++ b/spider/yield-db-json/328.odd-even-linked-list.json @@ -0,0 +1,10 @@ +{ + "question": "328.odd-even-linked-list", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/33.search-in-rotated-sorted-array.json b/spider/yield-db-json/33.search-in-rotated-sorted-array.json new file mode 100644 index 0000000..3e47aef --- /dev/null +++ b/spider/yield-db-json/33.search-in-rotated-sorted-array.json @@ -0,0 +1,15 @@ +{ + "question": "33.search-in-rotated-sorted-array", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def search(self, nums: List[int], target: int) -> int:\n \"\"\"用二分法,先判断左右两边哪一边是有序的,再判断是否在有序的列表之内\"\"\"\n if len(nums) <= 0:\n return -1\n\n left = 0\n right = len(nums) - 1\n while left < right:\n mid = (right - left) // 2 + left\n if nums[mid] == target:\n return mid\n \n # 如果中间的值大于最左边的值,说明左边有序\n if nums[mid] > nums[left]:\n if nums[left] <= target <= nums[mid]:\n right = mid\n else:\n # 这里 +1,因为上面是 <= 符号\n left = mid + 1\n # 否则右边有序\n else:\n # 注意:这里必须是 mid+1,因为根据我们的比较方式,mid属于左边的序列\n if nums[mid+1] <= target <= nums[right]:\n left = mid + 1\n else:\n right = mid\n \n return left if nums[left] == target else -1\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/334.increasing-triplet-subsequence.json b/spider/yield-db-json/334.increasing-triplet-subsequence.json new file mode 100644 index 0000000..b62c3c2 --- /dev/null +++ b/spider/yield-db-json/334.increasing-triplet-subsequence.json @@ -0,0 +1,10 @@ +{ + "question": "334.increasing-triplet-subsequence", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/335.self-crossing.json b/spider/yield-db-json/335.self-crossing.json new file mode 100644 index 0000000..ff1c24b --- /dev/null +++ b/spider/yield-db-json/335.self-crossing.json @@ -0,0 +1,15 @@ +{ + "question": "335.self-crossing", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def isSelfCrossing(self, x: List[int]) -> bool:\n n = len(x)\n if n < 4:\n return False\n for i in range(3, n):\n if x[i] >= x[i - 2] and x[i - 1] <= x[i - 3]:\n return True\n if x[i - 1] <= x[i - 3] and x[i - 2] <= x[i]:\n return True\n if i > 3 and x[i - 1] == x[i - 3] and x[i] + x[i - 4] == x[i - 2]:\n return True\n if i > 4 and x[i] + x[i - 4] >= x[i - 2] and x[i - 1] >= x[i - 3] - x[i - 5] \\\n and x[i - 1] <= x[i - 3] and x[i - 2] >= x[i - 4] and x[i - 3] >= x[i - 5]:\n return True\n return False\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/342.power-of-four.json b/spider/yield-db-json/342.power-of-four.json new file mode 100644 index 0000000..c3edf8c --- /dev/null +++ b/spider/yield-db-json/342.power-of-four.json @@ -0,0 +1,15 @@ +{ + "question": "342.power-of-four", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def isPowerOfFour(self, num: int) -> bool:\n if num == 1:\n return True\n elif num < 4:\n return False\n else:\n if not num & (num-1) == 0:\n return False\n else:\n return num & 0x55555555 == num\n\n # 另一种解法:将数字转化为二进制表示的字符串,利用字符串的相关操作进行判断\n def isPowerOfFour(self, num: int) -> bool:\n binary_num = bin(num)[2:]\n return binary_num.strip('0') == '1' and len(binary_num) % 2 == 1\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/343.integer-break.json b/spider/yield-db-json/343.integer-break.json new file mode 100644 index 0000000..40b288f --- /dev/null +++ b/spider/yield-db-json/343.integer-break.json @@ -0,0 +1,31 @@ +{ + "question": "343.integer-break", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def integerBreak(self, n: int) -> int:\n dp = [1] * (n + 1)\n for i in range(3, n + 1):\n for j in range(1, i):\n dp[i] = max(j * dp[i - j], j * (i - j), dp[i])\n return dp[n]\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def integerBreak(self, n: int) -> int:\n if n == 2: return 1\n res = 0\n for i in range(1, n):\n res = max(res, max(i * self.integerBreak(n - i),i * (n - i)))\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n @lru_cache()\n def integerBreak(self, n: int) -> int:\n if n == 2: return 1\n res = 0\n for i in range(1, n):\n res = max(res, max(i * self.integerBreak(n - i),i * (n - i)))\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def integerBreak(self, n: int) -> int:\n dp = [1] * (n + 1)\n for i in range(3, n + 1):\n for j in range(1, i):\n dp[i] = max(j * dp[i - j], j * (i - j), dp[i])\n return dp[n]\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def integerBreak(self, n: int) -> int:\n dp = [1] * (n + 1)\n for i in range(3, n + 1):\n for j in range(1, i):\n dp[i] = max(j * dp[i - j], j * (i - j), dp[i])\n return dp[n]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/349.intersection-of-two-arrays.json b/spider/yield-db-json/349.intersection-of-two-arrays.json new file mode 100644 index 0000000..ab78b23 --- /dev/null +++ b/spider/yield-db-json/349.intersection-of-two-arrays.json @@ -0,0 +1,15 @@ +{ + "question": "349.intersection-of-two-arrays", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:\n visited, result = {}, []\n for num in nums1:\n visited[num] = num\n for num in nums2:\n if num in visited:\n result.append(num)\n visited.pop(num)\n return result\n\n # 另一种解法:利用 Python 中的集合进行计算\n def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:\n return set(nums1) & set(nums2)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/365.water-and-jug-problem.json b/spider/yield-db-json/365.water-and-jug-problem.json new file mode 100644 index 0000000..67ee771 --- /dev/null +++ b/spider/yield-db-json/365.water-and-jug-problem.json @@ -0,0 +1,23 @@ +{ + "question": "365.water-and-jug-problem", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def canMeasureWater(self, x: int, y: int, z: int) -> bool:\n if x + y < z:\n return False\n queue = [(0, 0)]\n seen = set((0, 0))\n\n while(len(queue) > 0):\n a, b = queue.pop(0)\n if a ==z or b == z or a + b == z:\n return True\n states = set()\n\n states.add((x, b))\n states.add((a, y))\n states.add((0, b))\n states.add((a, 0)) \n states.add((min(x, b + a), 0 if b < x - a else b - (x - a))) \n states.add((0 if a + b < y else a - (y - b), min(b + a, y)))\n for state in states:\n if state in seen:\n continue;\n queue.append(state)\n seen.add(state)\n return False\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def canMeasureWater(self, x: int, y: int, z: int) -> bool:\n if x + y < z:\n return False\n\n if (z == 0):\n return True\n\n if (x == 0):\n return y == z\n\n if (y == 0):\n return x == z\n\n def GCD(a, b):\n smaller = min(a, b)\n while smaller:\n if a % smaller == 0 and b % smaller == 0:\n return smaller\n smaller -= 1\n\n return z % GCD(x, y) == 0\n" + }, + { + "lang": "python", + "code": "\ndef GCD(a, b):\n if b == 0: return a\n return GCD(b, a % b)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/371.sum-of-two-integers.json b/spider/yield-db-json/371.sum-of-two-integers.json new file mode 100644 index 0000000..cb283be --- /dev/null +++ b/spider/yield-db-json/371.sum-of-two-integers.json @@ -0,0 +1,10 @@ +{ + "question": "371.sum-of-two-integers", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/378.kth-smallest-element-in-a-sorted-matrix.json b/spider/yield-db-json/378.kth-smallest-element-in-a-sorted-matrix.json new file mode 100644 index 0000000..22e550d --- /dev/null +++ b/spider/yield-db-json/378.kth-smallest-element-in-a-sorted-matrix.json @@ -0,0 +1,10 @@ +{ + "question": "378.kth-smallest-element-in-a-sorted-matrix", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/380.insert-delete-getrandom-o1.json b/spider/yield-db-json/380.insert-delete-getrandom-o1.json new file mode 100644 index 0000000..c9fbc7b --- /dev/null +++ b/spider/yield-db-json/380.insert-delete-getrandom-o1.json @@ -0,0 +1,15 @@ +{ + "question": "380.insert-delete-getrandom-o1", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nfrom random import random\n\n\nclass RandomizedSet:\n\n def __init__(self):\n \"\"\"\n Initialize your data structure here.\n \"\"\"\n self.data = dict()\n self.arr = []\n self.n = 0\n\n def insert(self, val: int) -> bool:\n \"\"\"\n Inserts a value to the set. Returns true if the set did not already contain the specified element.\n \"\"\"\n if val in self.data:\n return False\n self.data[val] = self.n\n self.arr.append(val)\n self.n += 1\n\n return True\n\n def remove(self, val: int) -> bool:\n \"\"\"\n Removes a value from the set. Returns true if the set contained the specified element.\n \"\"\"\n if val not in self.data:\n return False\n i = self.data[val]\n # 更新data\n self.data[self.arr[-1]] = i\n self.data.pop(val)\n # 更新arr\n self.arr[i] = self.arr[-1]\n # 删除最后一项\n self.arr.pop()\n self.n -= 1\n\n return True\n\n def getRandom(self) -> int:\n \"\"\"\n Get a random element from the set.\n \"\"\"\n\n return self.arr[int(random() * self.n)]\n\n\n# Your RandomizedSet object will be instantiated and called as such:\n# obj = RandomizedSet()\n# param_1 = obj.insert(val)\n# param_2 = obj.remove(val)\n# param_3 = obj.getRandom()\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/39.combination-sum.json b/spider/yield-db-json/39.combination-sum.json new file mode 100644 index 0000000..bfac139 --- /dev/null +++ b/spider/yield-db-json/39.combination-sum.json @@ -0,0 +1,15 @@ +{ + "question": "39.combination-sum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:\n \"\"\"\n 回溯法,层层递减,得到符合条件的路径就加入结果集中,超出则剪枝;\n 主要是要注意一些细节,避免重复等;\n \"\"\"\n size = len(candidates)\n if size <= 0:\n return []\n \n # 先排序,便于后面剪枝\n candidates.sort()\n \n path = []\n res = []\n self._find_path(target, path, res, candidates, 0, size)\n \n return res\n \n def _find_path(self, target, path, res, candidates, begin, size):\n \"\"\"沿着路径往下走\"\"\"\n if target == 0:\n res.append(path.copy())\n else:\n for i in range(begin, size):\n left_num = target - candidates[i]\n # 如果剩余值为负数,说明超过了,剪枝\n if left_num < 0:\n break\n # 否则把当前值加入路径\n path.append(candidates[i])\n # 为避免重复解,我们把比当前值小的参数也从下一次寻找中剔除,\n # 因为根据他们得出的解一定在之前就找到过了\n self._find_path(left_num, path, res, candidates, i, size)\n # 记得把当前值移出路径,才能进入下一个值的路径\n path.pop()\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/4.median-of-two-sorted-array.json b/spider/yield-db-json/4.median-of-two-sorted-array.json new file mode 100644 index 0000000..630c138 --- /dev/null +++ b/spider/yield-db-json/4.median-of-two-sorted-array.json @@ -0,0 +1,19 @@ +{ + "question": "4.median-of-two-sorted-array", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": " []\nclass MedianTwoSortedArrayBruteForce {\n public double findMedianSortedArrays(int[] nums1, int[] nums2) {\n int[] newArr = mergeTwoSortedArray(nums1, nums2);\n int n = newArr.length;\n if (n % 2 == 0) {\n // even\n return (double) (newArr[n / 2] + newArr[n / 2 - 1]) / 2;\n } else {\n // odd\n return (double) newArr[n / 2];\n }\n }\n private int[] mergeTwoSortedArray(int[] nums1, int[] nums2) {\n int m = nums1.length;\n int n = nums2.length;\n int[] res = new int[m + n];\n int i = 0;\n int j = 0;\n int idx = 0;\n while (i < m && j < n) {\n if (nums1[i] <= nums2[j]) {\n res[idx++] = nums1[i++];\n } else {\n res[idx++] = nums2[j++];\n }\n }\n while (i < m) {\n res[idx++] = nums1[i++];\n }\n while (j < n) {\n res[idx++] = nums2[j++];\n }\n return res;\n }\n}\n" + }, + { + "lang": "java", + "code": " []\nclass MedianSortedTwoArrayBinarySearch {\n public static double findMedianSortedArraysBinarySearch(int[] nums1, int[] nums2) {\n // do binary search for shorter length array, make sure time complexity log(min(m,n)).\n if (nums1.length > nums2.length) {\n return findMedianSortedArraysBinarySearch(nums2, nums1);\n }\n int m = nums1.length;\n int n = nums2.length;\n int lo = 0;\n int hi = m;\n while (lo <= hi) {\n // partition A position i\n int i = lo + (hi - lo) / 2;\n // partition B position j\n int j = (m + n + 1) / 2 - i;\n\n int maxLeftA = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];\n int minRightA = i == m ? Integer.MAX_VALUE : nums1[i];\n\n int maxLeftB = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];\n int minRightB = j == n ? Integer.MAX_VALUE : nums2[j];\n\n if (maxLeftA <= minRightB && maxLeftB <= minRightA) {\n // total length is even\n if ((m + n) % 2 == 0) {\n return (double) (Math.max(maxLeftA, maxLeftB) + Math.min(minRightA, minRightB)) / 2;\n } else {\n // total length is odd\n return (double) Math.max(maxLeftA, maxLeftB);\n }\n } else if (maxLeftA > minRightB) {\n // binary search left half\n hi = i - 1;\n } else {\n // binary search right half\n lo = i + 1;\n }\n }\n return 0.0;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/40.combination-sum-ii.json b/spider/yield-db-json/40.combination-sum-ii.json new file mode 100644 index 0000000..995e1d0 --- /dev/null +++ b/spider/yield-db-json/40.combination-sum-ii.json @@ -0,0 +1,15 @@ +{ + "question": "40.combination-sum-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:\n \"\"\"\n 与39题的区别是不能重用元素,而元素可能有重复;\n 不能重用好解决,回溯的index往下一个就行;\n 元素可能有重复,就让结果的去重麻烦一些;\n \"\"\"\n size = len(candidates)\n if size == 0:\n return []\n \n # 还是先排序,主要是方便去重\n candidates.sort()\n \n path = []\n res = []\n self._find_path(candidates, path, res, target, 0, size)\n \n return res\n \n def _find_path(self, candidates, path, res, target, begin, size):\n if target == 0:\n res.append(path.copy())\n else:\n for i in range(begin, size):\n left_num = target - candidates[i]\n if left_num < 0:\n break\n # 如果存在重复的元素,前一个元素已经遍历了后一个元素与之后元素组合的所有可能\n if i > begin and candidates[i] == candidates[i-1]:\n continue\n path.append(candidates[i])\n # 开始的 index 往后移了一格\n self._find_path(candidates, path, res, left_num, i+1, size)\n path.pop()\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/416.partition-equal-subset-sum.json b/spider/yield-db-json/416.partition-equal-subset-sum.json new file mode 100644 index 0000000..4f4647d --- /dev/null +++ b/spider/yield-db-json/416.partition-equal-subset-sum.json @@ -0,0 +1,10 @@ +{ + "question": "416.partition-equal-subset-sum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/42.trapping-rain-water.json b/spider/yield-db-json/42.trapping-rain-water.json new file mode 100644 index 0000000..8568daf --- /dev/null +++ b/spider/yield-db-json/42.trapping-rain-water.json @@ -0,0 +1,15 @@ +{ + "question": "42.trapping-rain-water", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def trap(self, heights: List[int]) -> int:\n n = len(heights)\n l, r = [0] * (n + 1), [0] * (n + 1)\n ans = 0\n for i in range(1, len(heights) + 1):\n l[i] = max(l[i - 1], heights[i - 1])\n for i in range(len(heights) - 1, 0, -1):\n r[i] = max(r[i + 1], heights[i])\n for i in range(len(heights)):\n ans += max(0, min(l[i + 1], r[i]) - heights[i])\n return ans \n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/437.path-sum-iii.json b/spider/yield-db-json/437.path-sum-iii.json new file mode 100644 index 0000000..fbdd1f0 --- /dev/null +++ b/spider/yield-db-json/437.path-sum-iii.json @@ -0,0 +1,10 @@ +{ + "question": "437.path-sum-iii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/445.add-two-numbers-ii.json b/spider/yield-db-json/445.add-two-numbers-ii.json new file mode 100644 index 0000000..070d47d --- /dev/null +++ b/spider/yield-db-json/445.add-two-numbers-ii.json @@ -0,0 +1,15 @@ +{ + "question": "445.add-two-numbers-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\n# Definition for singly-linked list.\n# class ListNode:\n# def __init__(self, x):\n# self.val = x\n# self.next = None\n\nclass Solution:\n def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:\n def listToStack(l: ListNode) -> list:\n stack, c = [], l\n while c:\n stack.append(c.val)\n c = c.next\n return stack\n \n # transfer l1 and l2 into stacks\n stack1, stack2 = listToStack(l1), listToStack(l2)\n \n # add stack1 and stack2\n diff = abs(len(stack1) - len(stack2))\n stack1 = ([0]*diff + stack1 if len(stack1) < len(stack2) else stack1)\n stack2 = ([0]*diff + stack2 if len(stack2) < len(stack1) else stack2)\n stack3 = [x + y for x, y in zip(stack1, stack2)]\n \n # calculate carry for each item in stack3 and add one to the item before it\n carry = 0\n for i, val in enumerate(stack3[::-1]):\n index = len(stack3) - i - 1\n carry, stack3[index] = divmod(val + carry, 10)\n if carry and index == 0: \n stack3 = [1] + stack3\n elif carry:\n stack3[index - 1] += 1\n \n # transfer stack3 to a linkedList\n result = ListNode(0)\n c = result\n for item in stack3:\n c.next = ListNode(item)\n c = c.next\n \n return result.next\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/454.4-sum-ii.json b/spider/yield-db-json/454.4-sum-ii.json new file mode 100644 index 0000000..d95def7 --- /dev/null +++ b/spider/yield-db-json/454.4-sum-ii.json @@ -0,0 +1,15 @@ +{ + "question": "454.4-sum-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:\n mapper = {}\n res = 0\n for i in A:\n for j in B:\n mapper[i + j] = mapper.get(i + j, 0) + 1\n \n for i in C:\n for j in D:\n res += mapper.get(-1 * (i + j), 0)\n return res\n " + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/455.AssignCookies.json b/spider/yield-db-json/455.AssignCookies.json new file mode 100644 index 0000000..c443434 --- /dev/null +++ b/spider/yield-db-json/455.AssignCookies.json @@ -0,0 +1,10 @@ +{ + "question": "455.AssignCookies", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/46.permutations.json b/spider/yield-db-json/46.permutations.json new file mode 100644 index 0000000..13dd734 --- /dev/null +++ b/spider/yield-db-json/46.permutations.json @@ -0,0 +1,10 @@ +{ + "question": "46.permutations", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/460.lfu-cache.json b/spider/yield-db-json/460.lfu-cache.json new file mode 100644 index 0000000..f984393 --- /dev/null +++ b/spider/yield-db-json/460.lfu-cache.json @@ -0,0 +1,15 @@ +{ + "question": "460.lfu-cache", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\npublic class LC460LFUCache {\n class Node {\n int key, val, freq;\n Node prev, next;\n\n Node(int key, int val) {\n this.key = key;\n this.val = val;\n freq = 1;\n }\n }\n\n class DoubleLinkedList {\n private Node head;\n private Node tail;\n private int size;\n\n DoubleLinkedList() {\n head = new Node(0, 0);\n tail = new Node(0, 0);\n head.next = tail;\n tail.prev = head;\n }\n\n void add(Node node) {\n head.next.prev = node;\n node.next = head.next;\n node.prev = head;\n head.next = node;\n size++;\n }\n\n void remove(Node node) {\n node.prev.next = node.next;\n node.next.prev = node.prev;\n size--;\n }\n\n // always remove last node if last node exists\n Node removeLast() {\n if (size > 0) {\n Node node = tail.prev;\n remove(node);\n return node;\n } else return null;\n }\n }\n\n // cache capacity\n private int capacity;\n // min frequent\n private int minFreq;\n Map nodeMap;\n Map freqMap;\n public LC460LFUCache(int capacity) {\n this.minFreq = 0;\n this.capacity = capacity;\n nodeMap = new HashMap<>();\n freqMap = new HashMap<>();\n }\n\n public int get(int key) {\n Node node = nodeMap.get(key);\n if (node == null) return -1;\n update(node);\n return node.val;\n }\n\n public void put(int key, int value) {\n if (capacity == 0) return;\n Node node;\n if (nodeMap.containsKey(key)) {\n node = nodeMap.get(key);\n node.val = value;\n update(node);\n } else {\n node = new Node(key, value);\n nodeMap.put(key, node);\n if (nodeMap.size() == capacity) {\n DoubleLinkedList lastList = freqMap.get(minFreq);\n nodeMap.remove(lastList.removeLast().key);\n }\n minFreq = 1;\n DoubleLinkedList newList = freqMap.getOrDefault(node.freq, new DoubleLinkedList());\n newList.add(node);\n freqMap.put(node.freq, newList);\n }\n }\n\n private void update(Node node) {\n DoubleLinkedList oldList = freqMap.get(node.freq);\n oldList.remove(node);\n if (node.freq == minFreq && oldList.size == 0) minFreq++;\n node.freq++;\n DoubleLinkedList newList = freqMap.getOrDefault(node.freq, new DoubleLinkedList());\n newList.add(node);\n freqMap.put(node.freq, newList);\n }\n }\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/47.permutations-ii.json b/spider/yield-db-json/47.permutations-ii.json new file mode 100644 index 0000000..fc6f36c --- /dev/null +++ b/spider/yield-db-json/47.permutations-ii.json @@ -0,0 +1,10 @@ +{ + "question": "47.permutations-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/472.concatenated-words.json b/spider/yield-db-json/472.concatenated-words.json new file mode 100644 index 0000000..ab61e61 --- /dev/null +++ b/spider/yield-db-json/472.concatenated-words.json @@ -0,0 +1,15 @@ +{ + "question": "472.concatenated-words", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Trie:\n\n def __init__(self):\n self.Trie = {}\n self.visited = {}\n\n def insert(self, word):\n curr = self.Trie\n for w in word:\n if w not in curr:\n curr[w] = {}\n curr = curr[w]\n curr['#'] = 1\n\n def cntWords(self, word):\n if not word:\n return 0\n if word in self.visited:\n return self.visited[word]\n curr = self.Trie\n res = float('-inf')\n\n for i, w in enumerate(word):\n if w not in curr:\n return res\n curr = curr[w]\n if '#' in curr:\n res = max(res, 1 + self.cntWords(word[i + 1:]))\n self.visited[word] = res\n return res\n\n\nclass Solution:\n def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:\n self.trie = Trie()\n res = []\n\n for word in words:\n self.trie.insert(word)\n for word in words:\n if self.trie.cntWords(word) >= 2:\n res.append(word)\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/474.ones-and-zeros-en.json b/spider/yield-db-json/474.ones-and-zeros-en.json new file mode 100644 index 0000000..59b8615 --- /dev/null +++ b/spider/yield-db-json/474.ones-and-zeros-en.json @@ -0,0 +1,39 @@ +{ + "question": "474.ones-and-zeros-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass OnesAndZerosBFRecursive {\n public int findMaxForm2(String[] strs, int m, int n) {\n return helper(strs, 0, m, n);\n }\n private int helper(String[] strs, int idx, int j, int k) {\n if (idx == strs.length) return 0;\n // count current idx string number of zeros and ones\n int[] counts = countZeroOnes(strs[idx]);\n // if j >= count0 && k >= count1, take current index string\n int takeCurrStr = j - counts[0] >= 0 && k - counts[1] >= 0\n ? 1 + helper(strs, idx + 1, j - counts[0], k - counts[1])\n : -1;\n // don't take current index string strs[idx], continue next string\n int notTakeCurrStr = helper(strs, idx + 1, j, k);\n return Math.max(takeCurrStr, notTakeCurrStr);\n }\n private int[] countZeroOnes(String s) {\n int[] res = new int[2];\n for (char ch : s.toCharArray()) {\n res[ch - '0']++;\n }\n return res;\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass OnesAndZerosMemoRecur {\n public int findMaxForm4(String[] strs, int m, int n) {\n return helper(strs, 0, m, n, new int[strs.length][m + 1][n + 1]);\n }\n private int helper(String[] strs, int idx, int j, int k, int[][][] memo) {\n if (idx == strs.length) return 0;\n // check if already calculated, return value\n if (memo[idx][j][k] != 0) {\n return memo[idx][j][k];\n }\n int[] counts = countZeroOnes(strs[idx]);\n // if satisfy condition, take current string, strs[idx], update count0 and count1\n int takeCurrStr = j - counts[0] >= 0 && k - counts[1] >= 0\n ? 1 + helper(strs, idx + 1, j - counts[0], k - counts[1], memo)\n : -1;\n // not take current string\n int notTakeCurrStr = helper(strs, idx + 1, j, k, memo);\n // always keep track the max value into memory\n memo[idx][j][k] = Math.max(takeCurrStr, notTakeCurrStr);\n return memo[idx][j][k];\n }\n private int[] countZeroOnes(String s) {\n int[] res = new int[2];\n for (char ch : s.toCharArray()) {\n res[ch - '0']++;\n }\n return res;\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass OnesAndZeros3DDP {\n public int findMaxForm(String[] strs, int m, int n) {\n int l = strs.length;\n int [][][] d = new int[l + 1][m + 1][n + 1];\n for (int i = 0; i <= l; i ++){\n int [] nums = new int[]{0,0};\n if (i > 0){\n nums = countZeroOnes(strs[i - 1]);\n }\n for (int j = 0; j <= m; j ++){\n for (int k = 0; k <= n; k ++){\n if (i == 0) {\n d[i][j][k] = 0;\n } else if (j >= nums[0] && k >= nums[1]){\n d[i][j][k] = Math.max(d[i - 1][j][k], d[i - 1][j - nums[0]][k - nums[1]] + 1);\n } else {\n d[i][j][k] = d[i - 1][j][k];\n }\n }\n }\n }\n return d[l][m][n];\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass OnesAndZeros2DDP {\n public int findMaxForm(String[] strs, int m, int n) {\n int[][] dp = new int[m + 1][n + 1];\n for (String s : strs) {\n int[] counts = countZeroOnes(s);\n for (int i = m; i >= counts[0]; i--) {\n for (int j = n; j >= counts[1]; j--) {\n dp[i][j] = Math.max(1 + dp[i - counts[0]][j - counts[1]], dp[i][j]);\n }\n }\n }\n return dp[m][n];\n }\n private int[] countZeroOnes(String s) {\n int[] res = new int[2];\n for (char ch : s.toCharArray()) {\n res[ch - '0']++;\n }\n return res;\n }\n}\n\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def findMaxForm(self, strs: List[str], m: int, n: int) -> int:\n return self.helper(strs, m, n, 0)\n \n def helper(self, strs, m, n, idx):\n if idx == len(strs):\n return 0\n take_curr_str = -1\n count0, count1 = strs[idx].count('0'), strs[idx].count('1')\n if m >= count0 and n >= count1:\n take_curr_str = max(take_curr_str, self.helper(strs, m - count0, n - count1, idx + 1) + 1)\n not_take_curr_str = self.helper(strs, m, n, idx + 1)\n return max(take_curr_str, not_take_curr_str)\n \n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def findMaxForm(self, strs: List[str], m: int, n: int) -> int:\n memo = {k:[[0]*(n+1) for _ in range(m+1)] for k in range(len(strs)+1)}\n return self.helper(strs, 0, m, n, memo)\n \n def helper(self, strs, idx, m, n, memo):\n if idx == len(strs):\n return 0\n if memo[idx][m][n] != 0:\n return memo[idx][m][n]\n take_curr_str = -1\n count0, count1 = strs[idx].count('0'), strs[idx].count('1')\n if m >= count0 and n >= count1:\n take_curr_str = max(take_curr_str, self.helper(strs, idx + 1, m - count0, n - count1, memo) + 1)\n not_take_curr_str = self.helper(strs, idx + 1, m, n, memo)\n memo[idx][m][n] = max(take_curr_str, not_take_curr_str)\n return memo[idx][m][n]\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def findMaxForm(self, strs: List[str], m: int, n: int) -> int:\n l = len(strs)\n dp = [[0]*(n+1) for _ in range(m+1)]\n for i in range(1, l + 1):\n count0, count1 = strs[i - 1].count('0'), strs[i - 1].count('1')\n for i in reversed(range(count0, m + 1)):\n for j in reversed(range(count1, n + 1)):\n dp[i][j] = max(dp[i][j], 1 + dp[i - count0][j - count1])\n return dp[m][n]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/48.rotate-image.json b/spider/yield-db-json/48.rotate-image.json new file mode 100644 index 0000000..e511bf8 --- /dev/null +++ b/spider/yield-db-json/48.rotate-image.json @@ -0,0 +1,10 @@ +{ + "question": "48.rotate-image", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/49.group-anagrams.json b/spider/yield-db-json/49.group-anagrams.json new file mode 100644 index 0000000..02d1d81 --- /dev/null +++ b/spider/yield-db-json/49.group-anagrams.json @@ -0,0 +1,10 @@ +{ + "question": "49.group-anagrams", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/493.reverse-pairs.json b/spider/yield-db-json/493.reverse-pairs.json new file mode 100644 index 0000000..3f85d49 --- /dev/null +++ b/spider/yield-db-json/493.reverse-pairs.json @@ -0,0 +1,23 @@ +{ + "question": "493.reverse-pairs", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution(object):\n def reversePairs(self, nums):\n n = len(nums)\n cnt = 0\n for i in range(n):\n for j in range(i + 1, n):\n if nums[i] > 2 * nums[j]:\n cnt += 1\n return cnt\n" + }, + { + "lang": "python", + "code": "\nl = r = 0\nwhile l < len(left) and r < len(right):\n if left[l] <= 2 * right[r]:\n l += 1\n else:\n self.cnt += len(left) - l\n r += 1\n" + }, + { + "lang": "python", + "code": "\nclass Solution(object):\n def reversePairs(self, nums):\n self.cnt = 0\n\n def mergeSort(lst):\n L = len(lst)\n if L <= 1:\n return lst\n return mergeTwo(mergeSort(lst[:L//2]), mergeSort(lst[L//2:]))\n\n def mergeTwo(left, right):\n l = r = 0\n while l < len(left) and r < len(right):\n if left[l] <= 2 * right[r]:\n l += 1\n else:\n self.cnt += len(left) - l\n r += 1\n return sorted(left+right)\n\n mergeSort(nums)\n return self.cnt\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/494.target-sum.json b/spider/yield-db-json/494.target-sum.json new file mode 100644 index 0000000..1cbf8ce --- /dev/null +++ b/spider/yield-db-json/494.target-sum.json @@ -0,0 +1,10 @@ +{ + "question": "494.target-sum", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/5.longest-palindromic-substring.json b/spider/yield-db-json/5.longest-palindromic-substring.json new file mode 100644 index 0000000..186146b --- /dev/null +++ b/spider/yield-db-json/5.longest-palindromic-substring.json @@ -0,0 +1,15 @@ +{ + "question": "5.longest-palindromic-substring", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def longestPalindrome(self, s: str) -> str:\n n = len(s)\n if n == 0:\n return \"\"\n res = s[0]\n def extend(i, j, s):\n while(i >= 0 and j < len(s) and s[i] == s[j]):\n i -= 1\n j += 1\n return s[i + 1:j]\n\n for i in range(n - 1):\n e1 = extend(i, i, s)\n e2 = extend(i, i + 1, s) \n if max(len(e1), len(e2)) > len(res):\n res = e1 if len(e1) > len(e2) else e2\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/50.pow-x-n.json b/spider/yield-db-json/50.pow-x-n.json new file mode 100644 index 0000000..28d6611 --- /dev/null +++ b/spider/yield-db-json/50.pow-x-n.json @@ -0,0 +1,27 @@ +{ + "question": "50.pow-x-n", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def myPow(self, x: float, n: int) -> float:\n if n == 0:\n return 1\n if n < 0:\n return 1 / self.myPow(x, -n)\n res = 1\n for _ in range(n):\n res *= x\n return res\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def myPow(self, x: float, n: int) -> float:\n if n == 0:\n return 1\n if n == 1:\n return x\n if n < 0:\n return 1 / self.myPow(x, -n)\n return self.myPow(x, n // 2) * self.myPow(x, n - n // 2)\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def myPow(self, x: float, n: int) -> float:\n if n == 0:\n return 1\n if n == 1:\n return x\n if n < 0:\n return 1 / self.myPow(x, -n)\n return self.myPow(x _ x, n // 2) if n % 2 == 0 else x _ self.myPow(x, n - 1)\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def myPow(self, x: float, n: int) -> float:\n if n < 0:\n return 1 / self.myPow(x, -n)\n res = 1\n while n:\n if n & 1 == 1:\n res *= x\n x *= x\n n >>= 1\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/501.Find-Mode-in-Binary-Search-Tree.json b/spider/yield-db-json/501.Find-Mode-in-Binary-Search-Tree.json new file mode 100644 index 0000000..732f3bb --- /dev/null +++ b/spider/yield-db-json/501.Find-Mode-in-Binary-Search-Tree.json @@ -0,0 +1,15 @@ +{ + "question": "501.Find-Mode-in-Binary-Search-Tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nclass Solution { \n List list = new ArrayList<> ();\n TreeNode preNode = null;\n int max = 0, count = 0;\n \n public int[] findMode(TreeNode root) {\n helper(root);\n int[] res = new int[list.size()];\n for (int i=0; i max) {\n list.clear();\n list.add(root.val);\n max = count;\n } else if (max == count) {\n list.add(root.val); \n }\n preNode = root;\n helper(root.right);\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/516.longest-palindromic-subsequence.json b/spider/yield-db-json/516.longest-palindromic-subsequence.json new file mode 100644 index 0000000..6387715 --- /dev/null +++ b/spider/yield-db-json/516.longest-palindromic-subsequence.json @@ -0,0 +1,10 @@ +{ + "question": "516.longest-palindromic-subsequence", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/518.coin-change-2.json b/spider/yield-db-json/518.coin-change-2.json new file mode 100644 index 0000000..2e6f861 --- /dev/null +++ b/spider/yield-db-json/518.coin-change-2.json @@ -0,0 +1,19 @@ +{ + "question": "518.coin-change-2", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def change(self, amount: int, coins: List[int]) -> int:\n dp = [0] * (amount + 1)\n dp[0] = 1\n\n for j in range(len(coins)):\n for i in range(1, amount + 1):\n if i >= coins[j]:\n dp[i] += dp[i - coins[j]]\n\n return dp[-1]\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def change(self, amount: int, coins: List[int]) -> int:\n dp = [[0 for _ in range(len(coins) + 1)] for _ in range(amount + 1)]\n for j in range(len(coins) + 1):\n dp[0][j] = 1\n\n for i in range(amount + 1):\n for j in range(1, len(coins) + 1):\n if i >= coins[j - 1]:\n dp[i][j] = dp[i - coins[j - 1]][j] + dp[i][j - 1]\n else:\n dp[i][j] = dp[i][j - 1]\n return dp[-1][-1]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/52.N-Queens-II.json b/spider/yield-db-json/52.N-Queens-II.json new file mode 100644 index 0000000..28b7a19 --- /dev/null +++ b/spider/yield-db-json/52.N-Queens-II.json @@ -0,0 +1,10 @@ +{ + "question": "52.N-Queens-II", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/53.maximum-sum-subarray-cn.json b/spider/yield-db-json/53.maximum-sum-subarray-cn.json new file mode 100644 index 0000000..4cf44d2 --- /dev/null +++ b/spider/yield-db-json/53.maximum-sum-subarray-cn.json @@ -0,0 +1,43 @@ +{ + "question": "53.maximum-sum-subarray-cn", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass MaximumSubarrayPrefixSum {\n public int maxSubArray(int[] nums) {\n int len = nums.length;\n int maxSum = Integer.MIN_VALUE;\n int sum = 0;\n for (int i = 0; i < len; i++) {\n sum = 0;\n for (int j = i; j < len; j++) {\n sum += nums[j];\n maxSum = Math.max(maxSum, sum);\n }\n }\n return maxSum;\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass MaxSumSubarray {\n public int maxSubArray3(int[] nums) {\n int maxSum = nums[0];\n int sum = 0;\n int minSum = 0;\n for (int num : nums) {\n // prefix Sum\n sum += num;\n // update maxSum\n maxSum = Math.max(maxSum, sum - minSum);\n // update minSum\n minSum = Math.min(minSum, sum);\n }\n return maxSum;\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass MaximumSubarrayDivideConquer {\n public int maxSubArrayDividConquer(int[] nums) {\n if (nums == null || nums.length == 0) return 0;\n return helper(nums, 0, nums.length - 1);\n }\n private int helper(int[] nums, int l, int r) {\n if (l > r) return Integer.MIN_VALUE;\n int mid = (l + r) >>> 1;\n int left = helper(nums, l, mid - 1);\n int right = helper(nums, mid + 1, r);\n int leftMaxSum = 0;\n int sum = 0;\n // left surfix maxSum start from index mid - 1 to l\n for (int i = mid - 1; i >= l; i--) {\n sum += nums[i];\n leftMaxSum = Math.max(leftMaxSum, sum);\n }\n int rightMaxSum = 0;\n sum = 0;\n // right prefix maxSum start from index mid + 1 to r\n for (int i = mid + 1; i <= r; i++) {\n sum += nums[i];\n rightMaxSum = Math.max(sum, rightMaxSum);\n }\n // max(left, right, crossSum)\n return Math.max(leftMaxSum + rightMaxSum + nums[mid], Math.max(left, right));\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass MaximumSubarrayDP {\n public int maxSubArray(int[] nums) {\n int currMaxSum = nums[0];\n int maxSum = nums[0];\n for (int i = 1; i < nums.length; i++) {\n currMaxSum = Math.max(currMaxSum + nums[i], nums[i]);\n maxSum = Math.max(maxSum, currMaxSum);\n }\n return maxSum;\n }\n}\n" + }, + { + "lang": "python", + "code": "\nimport sys\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n n = len(nums)\n maxSum = -sys.maxsize\n sum = 0\n for i in range(n):\n sum = 0\n for j in range(i, n):\n sum += nums[j]\n maxSum = max(maxSum, sum)\n \n return maxSum\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n n = len(nums)\n maxSum = nums[0]\n minSum = sum = 0\n for i in range(n):\n sum += nums[i]\n maxSum = max(maxSum, sum - minSum)\n minSum = min(minSum, sum)\n \n return maxSum\n" + }, + { + "lang": "python", + "code": "\nimport sys\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n return self.helper(nums, 0, len(nums) - 1)\n def helper(self, nums, l, r):\n if l > r:\n return -sys.maxsize\n mid = (l + r) // 2\n left = self.helper(nums, l, mid - 1)\n right = self.helper(nums, mid + 1, r)\n left_suffix_max_sum = right_prefix_max_sum = 0\n sum = 0\n for i in reversed(range(l, mid)):\n sum += nums[i]\n left_suffix_max_sum = max(left_suffix_max_sum, sum)\n sum = 0\n for i in range(mid + 1, r + 1):\n sum += nums[i]\n right_prefix_max_sum = max(right_prefix_max_sum, sum)\n cross_max_sum = left_suffix_max_sum + right_prefix_max_sum + nums[mid]\n return max(cross_max_sum, left, right)\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n n = len(nums)\n max_sum_ending_curr_index = max_sum = nums[0]\n for i in range(1, n):\n max_sum_ending_curr_index = max(max_sum_ending_curr_index + nums[i], nums[i])\n max_sum = max(max_sum_ending_curr_index, max_sum)\n \n return max_sum\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/53.maximum-sum-subarray-en.json b/spider/yield-db-json/53.maximum-sum-subarray-en.json new file mode 100644 index 0000000..b5e6748 --- /dev/null +++ b/spider/yield-db-json/53.maximum-sum-subarray-en.json @@ -0,0 +1,43 @@ +{ + "question": "53.maximum-sum-subarray-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass MaximumSubarrayPrefixSum {\n public int maxSubArray(int[] nums) {\n int len = nums.length;\n int maxSum = Integer.MIN_VALUE;\n int sum = 0;\n for (int i = 0; i < len; i++) {\n sum = 0;\n for (int j = i; j < len; j++) {\n sum += nums[j];\n maxSum = Math.max(maxSum, sum);\n }\n }\n return maxSum;\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass MaxSumSubarray {\n public int maxSubArray3(int[] nums) {\n int maxSum = nums[0];\n int sum = 0;\n int minSum = 0;\n for (int num : nums) {\n // prefix Sum\n sum += num;\n // update maxSum\n maxSum = Math.max(maxSum, sum - minSum);\n // update minSum\n minSum = Math.min(minSum, sum);\n }\n return maxSum;\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass MaximumSubarrayDivideConquer {\n public int maxSubArrayDividConquer(int[] nums) {\n if (nums == null || nums.length == 0) return 0;\n return helper(nums, 0, nums.length - 1);\n }\n private int helper(int[] nums, int l, int r) {\n if (l > r) return Integer.MIN_VALUE;\n int mid = (l + r) >>> 1;\n int left = helper(nums, l, mid - 1);\n int right = helper(nums, mid + 1, r);\n int leftMaxSum = 0;\n int sum = 0;\n // left surfix maxSum start from index mid - 1 to l\n for (int i = mid - 1; i >= l; i--) {\n sum += nums[i];\n leftMaxSum = Math.max(leftMaxSum, sum);\n }\n int rightMaxSum = 0;\n sum = 0;\n // right prefix maxSum start from index mid + 1 to r\n for (int i = mid + 1; i <= r; i++) {\n sum += nums[i];\n rightMaxSum = Math.max(sum, rightMaxSum);\n }\n // max(left, right, crossSum)\n return Math.max(leftMaxSum + rightMaxSum + nums[mid], Math.max(left, right));\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass MaximumSubarrayDP {\n public int maxSubArray(int[] nums) {\n int currMaxSum = nums[0];\n int maxSum = nums[0];\n for (int i = 1; i < nums.length; i++) {\n currMaxSum = Math.max(currMaxSum + nums[i], nums[i]);\n maxSum = Math.max(maxSum, currMaxSum);\n }\n return maxSum;\n }\n}\n" + }, + { + "lang": "python", + "code": "\nimport sys\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n n = len(nums)\n maxSum = -sys.maxsize\n sum = 0\n for i in range(n):\n sum = 0\n for j in range(i, n):\n sum += nums[j]\n maxSum = max(maxSum, sum)\n \n return maxSum\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n n = len(nums)\n maxSum = nums[0]\n minSum = sum = 0\n for i in range(n):\n sum += nums[i]\n maxSum = max(maxSum, sum - minSum)\n minSum = min(minSum, sum)\n \n return maxSum\n" + }, + { + "lang": "python", + "code": "\nimport sys\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n return self.helper(nums, 0, len(nums) - 1)\n def helper(self, nums, l, r):\n if l > r:\n return -sys.maxsize\n mid = (l + r) // 2\n left = self.helper(nums, l, mid - 1)\n right = self.helper(nums, mid + 1, r)\n left_suffix_max_sum = right_prefix_max_sum = 0\n sum = 0\n for i in reversed(range(l, mid)):\n sum += nums[i]\n left_suffix_max_sum = max(left_suffix_max_sum, sum)\n sum = 0\n for i in range(mid + 1, r + 1):\n sum += nums[i]\n right_prefix_max_sum = max(right_prefix_max_sum, sum)\n cross_max_sum = left_suffix_max_sum + right_prefix_max_sum + nums[mid]\n return max(cross_max_sum, left, right)\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def maxSubArray(self, nums: List[int]) -> int:\n n = len(nums)\n max_sum_ending_curr_index = max_sum = nums[0]\n for i in range(1, n):\n max_sum_ending_curr_index = max(max_sum_ending_curr_index + nums[i], nums[i])\n max_sum = max(max_sum_ending_curr_index, max_sum)\n \n return max_sum\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/547.friend-circles-en.json b/spider/yield-db-json/547.friend-circles-en.json new file mode 100644 index 0000000..ae42b72 --- /dev/null +++ b/spider/yield-db-json/547.friend-circles-en.json @@ -0,0 +1,23 @@ +{ + "question": "547.friend-circles-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\nclass FindCirclesDFS {\n public int findCircleNumDFS(int[][] M) {\n if (M == null || M.length == 0 || M[0].length == 0) return 0;\n int n = M.length;\n int numCircles = 0;\n boolean[] visited = new boolean[n];\n for (int i = 0; i < n; i++) {\n if (!visited[i]) {\n dfs(M, i, visited, n);\n numCircles++;\n }\n }\n return numCircles;\n }\n\n private void dfs(int[][] M, int i, boolean[] visited, int n) {\n for (int j = 0; j < n; j++) {\n if (M[i][j] == 1 && !visited[j]) {\n visited[j] = true;\n dfs(M, j, visited, n);\n }\n }\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass FindCircleBFS {\n public int findCircleNumBFS(int[][] M) {\n if (M == null || M.length == 0) return 0;\n int numCircle = 0;\n int n = M.length;\n boolean[] visited = new boolean[n];\n Queue queue = new LinkedList<>();\n for (int i = 0; i < n; i++) {\n // already visited, skip\n if (visited[i]) continue;\n queue.add(i);\n while (!queue.isEmpty()) {\n int curr = queue.poll();\n visited[curr] = true;\n for (int j = 0; j < n; j++) {\n if (M[curr][j] == 1 && !visited[j]) {\n queue.add(j);\n }\n }\n }\n numCircle++;\n }\n return numCircle;\n }\n}\n" + }, + { + "lang": "java", + "code": "\nclass FindCircleUF {\n public int findCircleNumUF(int[][] M) {\n if (M == null || M.length == 0 || M[0].length == 0) return 0;\n int n = M.length;\n UnionFind uf = new UnionFind(n);\n for (int i = 0; i < n - 1; i++) {\n for (int j = i + 1; j < n; j++) {\n // union friends\n if (M[i][j] == 1) {\n uf.union(i, j);\n }\n }\n }\n return uf.count;\n }\n}\n\nclass UnionFind {\n int count;\n int[] parent;\n int[] rank;\n\n public UnionFind(int n) {\n count = n;\n parent = new int[n];\n rank = new int[n];\n for (int i = 0; i < n; i++) {\n parent[i] = i;\n }\n }\n\n public int find(int a) {\n return parent[a] == a ? a : find(parent[a]);\n }\n\n public void union(int a, int b) {\n int rootA = find(a);\n int rootB = find(b);\n if (rootA == rootB) return;\n if (rank[rootA] <= rank[rootB]) {\n parent[rootA] = rootB;\n rank[rootB] += rank[rootA];\n } else {\n parent[rootB] = rootA;\n rank[rootA] += rank[rootB];\n }\n count--;\n }\n\n public int count() {\n return count;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/547.friend-circles.json b/spider/yield-db-json/547.friend-circles.json new file mode 100644 index 0000000..d24f8ae --- /dev/null +++ b/spider/yield-db-json/547.friend-circles.json @@ -0,0 +1,15 @@ +{ + "question": "547.friend-circles", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass UF:\n parent = {}\n cnt = 0\n def __init__(self, M):\n n = len(M)\n for i in range(n):\n self.parent[i] = i\n self.cnt += 1\n\n def find(self, x):\n while x != self.parent[x]:\n x = self.parent[x]\n return x\n def union(self, p, q):\n if self.connected(p, q): return\n self.parent[self.find(p)] = self.find(q)\n self.cnt -= 1\n def connected(self, p, q):\n return self.find(p) == self.find(q)\n\nclass Solution:\n def findCircleNum(self, M: List[List[int]]) -> int:\n n = len(M)\n uf = UF(M)\n for i in range(n):\n for j in range(i):\n if M[i][j] == 1:\n uf.union(i, j)\n return uf.cnt\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/55.jump-game.json b/spider/yield-db-json/55.jump-game.json new file mode 100644 index 0000000..3bcd000 --- /dev/null +++ b/spider/yield-db-json/55.jump-game.json @@ -0,0 +1,10 @@ +{ + "question": "55.jump-game", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/56.merge-intervals.json b/spider/yield-db-json/56.merge-intervals.json new file mode 100644 index 0000000..4d03884 --- /dev/null +++ b/spider/yield-db-json/56.merge-intervals.json @@ -0,0 +1,10 @@ +{ + "question": "56.merge-intervals", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/560.subarray-sum-equals-k.en.json b/spider/yield-db-json/560.subarray-sum-equals-k.en.json new file mode 100644 index 0000000..f412a33 --- /dev/null +++ b/spider/yield-db-json/560.subarray-sum-equals-k.en.json @@ -0,0 +1,10 @@ +{ + "question": "560.subarray-sum-equals-k.en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/560.subarray-sum-equals-k.json b/spider/yield-db-json/560.subarray-sum-equals-k.json new file mode 100644 index 0000000..ea0a709 --- /dev/null +++ b/spider/yield-db-json/560.subarray-sum-equals-k.json @@ -0,0 +1,23 @@ +{ + "question": "560.subarray-sum-equals-k", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def subarraySum(self, nums: List[int], k: int) -> int:\n cnt, n = 0, len(nums)\n for i in range(n):\n sum = 0\n for j in range(i, n):\n sum += nums[j]\n if (sum == k): cnt += 1\n return cnt\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def subarraySum(self, nums: List[int], k: int) -> int:\n cnt, n = 0, len(nums)\n pre = [0] * (n + 1)\n for i in range(1, n + 1):\n pre[i] = pre[i - 1] + nums[i - 1]\n for i in range(1, n + 1):\n for j in range(i, n + 1):\n if (pre[j] - pre[i - 1] == k): cnt += 1\n return cnt\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def subarraySum(self, nums: List[int], k: int) -> int:\n d = {}\n acc = count = 0\n for num in nums:\n acc += num\n if acc == k:\n count += 1\n if acc - k in d:\n count += d[acc-k]\n if acc in d:\n d[acc] += 1\n else:\n d[acc] = 1\n return count\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/575.distribute-candies.json b/spider/yield-db-json/575.distribute-candies.json new file mode 100644 index 0000000..eb33667 --- /dev/null +++ b/spider/yield-db-json/575.distribute-candies.json @@ -0,0 +1,15 @@ +{ + "question": "575.distribute-candies", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def distributeCandies(self, candies: List[int]) -> int:\n return min(len(set(candies)), len(candies) >> 1)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/60.permutation-sequence.json b/spider/yield-db-json/60.permutation-sequence.json new file mode 100644 index 0000000..462a6c7 --- /dev/null +++ b/spider/yield-db-json/60.permutation-sequence.json @@ -0,0 +1,15 @@ +{ + "question": "60.permutation-sequence", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nimport math\n\nclass Solution:\n def getPermutation(self, n: int, k: int) -> str:\n res = \"\"\n candidates = [str(i) for i in range(1, n + 1)]\n\n while n != 0:\n facto = math.factorial(n - 1)\n # i 表示前面被我们排除的组数,也就是k所在的组的下标\n # k // facto 是不行的, 比如在 k % facto == 0的情况下就会有问题\n i = math.ceil(k / facto) - 1\n # 我们把candidates[i]加入到结果集,然后将其弹出candidates(不能重复使用元素)\n res += candidates[i]\n candidates.pop(i)\n # k 缩小了 facto * i\n k -= facto * i\n # 每次迭代我们实际上就处理了一个元素,n 减去 1,当n == 0 说明全部处理完成,我们退出循环\n n -= 1\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/609.find-duplicate-file-in-system.json b/spider/yield-db-json/609.find-duplicate-file-in-system.json new file mode 100644 index 0000000..ec37168 --- /dev/null +++ b/spider/yield-db-json/609.find-duplicate-file-in-system.json @@ -0,0 +1,10 @@ +{ + "question": "609.find-duplicate-file-in-system", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/62.unique-paths.json b/spider/yield-db-json/62.unique-paths.json new file mode 100644 index 0000000..f371fbe --- /dev/null +++ b/spider/yield-db-json/62.unique-paths.json @@ -0,0 +1,23 @@ +{ + "question": "62.unique-paths", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def uniquePaths(self, m: int, n: int) -> int:\n d = [[1] * n for _ in range(m)]\n\n for col in range(1, m):\n for row in range(1, n):\n d[col][row] = d[col - 1][row] + d[col][row - 1]\n\n return d[m - 1][n - 1]\n " + }, + { + "lang": "python", + "code": "\nclass Solution:\n visited = dict()\n\n def uniquePaths(self, m: int, n: int) -> int:\n if (m, n) in self.visited:\n return self.visited[(m, n)]\n if m == 1 or n == 1:\n return 1\n cnt = self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1)\n self.visited[(m, n)] = cnt\n return cnt\n " + }, + { + "lang": "python", + "code": "\nclass Solution:\n\n def uniquePaths(self, m: int, n: int) -> int:\n dp = [1] * n\n for _ in range(1, m):\n for j in range(1, n):\n dp[j] += dp[j - 1]\n return dp[n - 1]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/721.accounts-merge.json b/spider/yield-db-json/721.accounts-merge.json new file mode 100644 index 0000000..3da7820 --- /dev/null +++ b/spider/yield-db-json/721.accounts-merge.json @@ -0,0 +1,15 @@ +{ + "question": "721.accounts-merge", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass UF:\n def __init__(self):\n self.parent = {}\n\n def find(self, x):\n self.parent.setdefault(x, x)\n while x != self.parent[x]:\n x = self.parent[x]\n return x\n def union(self, p, q):\n self.parent[self.find(p)] = self.find(q)\n\n\nclass Solution:\n def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:\n uf = UF()\n email_to_name = {}\n res = collections.defaultdict(list)\n for account in accounts:\n for i in range(1, len(account)):\n email_to_name[account[i]] = account[0]\n if i < len(account) - 1:uf.union(account[i], account[i + 1])\n for email in email_to_name:\n res[uf.find(email)].append(email)\n\n return [[email_to_name[value[0]]] + sorted(value) for value in res.values()]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/73.set-matrix-zeroes.json b/spider/yield-db-json/73.set-matrix-zeroes.json new file mode 100644 index 0000000..6c1d3fe --- /dev/null +++ b/spider/yield-db-json/73.set-matrix-zeroes.json @@ -0,0 +1,19 @@ +{ + "question": "73.set-matrix-zeroes", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def setZeroes(self, matrix: List[List[int]]) -> None:\n \"\"\"\n Do not return anything, modify matrix in-place instead.\n \"\"\"\n def setRowZeros(matrix: List[List[int]], i:int) -> None:\n C = len(matrix[0])\n matrix[i] = [0] * C\n \n def setColZeros(matrix: List[List[int]], j:int) -> None:\n R = len(matrix)\n for i in range(R):\n matrix[i][j] = 0\n \n isCol = False\n R = len(matrix)\n C = len(matrix[0])\n \n for i in range(R):\n if matrix[i][0] == 0:\n isCol = True\n for j in range(1, C):\n if matrix[i][j] == 0:\n matrix[i][0] = 0\n matrix[0][j] = 0\n for j in range(1, C):\n if matrix[0][j] == 0:\n setColZeros(matrix, j)\n \n for i in range(R):\n if matrix[i][0] == 0:\n setRowZeros(matrix, i)\n \n if isCol:\n setColZeros(matrix, 0)\n\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def setZeroes(self, matrix: List[List[int]]) -> None:\n \"\"\"\n 这题要解决的问题是,必须有个地方记录判断结果,但又不能影响下一步的判断条件;\n 直接改为0的话,会影响下一步的判断条件;\n 因此,有一种思路是先改为None,最后再将None改为0;\n 从条件上看,如果可以将第一行、第二行作为记录空间,那么,用None应该也不算违背题目条件;\n \"\"\"\n rows = len(matrix)\n cols = len(matrix[0])\n # 遍历矩阵,用None记录要改的地方,注意如果是0则要保留,否则会影响下一步判断\n for r in range(rows):\n for c in range(cols):\n if matrix[r][c] is not None and matrix[r][c] == 0:\n # 改值\n for i in range(rows):\n matrix[i][c] = None if matrix[i][c] != 0 else 0\n for j in range(cols):\n matrix[r][j] = None if matrix[r][j] != 0 else 0\n # 再次遍历,将None改为0\n for r in range(rows):\n for c in range(cols):\n if matrix[r][c] is None:\n matrix[r][c] = 0\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/75.sort-colors.json b/spider/yield-db-json/75.sort-colors.json new file mode 100644 index 0000000..f35d444 --- /dev/null +++ b/spider/yield-db-json/75.sort-colors.json @@ -0,0 +1,10 @@ +{ + "question": "75.sort-colors", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/78.subsets-en.json b/spider/yield-db-json/78.subsets-en.json new file mode 100644 index 0000000..906f155 --- /dev/null +++ b/spider/yield-db-json/78.subsets-en.json @@ -0,0 +1,10 @@ +{ + "question": "78.subsets-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/78.subsets.json b/spider/yield-db-json/78.subsets.json new file mode 100644 index 0000000..32a5f9a --- /dev/null +++ b/spider/yield-db-json/78.subsets.json @@ -0,0 +1,10 @@ +{ + "question": "78.subsets", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/79.word-search-en.json b/spider/yield-db-json/79.word-search-en.json new file mode 100644 index 0000000..ad177c1 --- /dev/null +++ b/spider/yield-db-json/79.word-search-en.json @@ -0,0 +1,19 @@ +{ + "question": "79.word-search-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\npublic class LC79WordSearch {\n public boolean exist(char[][] board, String word) {\n if (board == null || board.length == 0 || board[0].length == 0\n || word == null || word.length() == 0) return true;\n int rows = board.length;\n int cols = board[0].length;\n for (int r = 0; r < rows; r++) {\n for (int c = 0; c < cols; c++) {\n // scan board, start with word first character \n if (board[r][c] == word.charAt(0)) {\n if (helper(board, word, r, c, 0)) {\n return true;\n }\n }\n }\n }\n return false;\n }\n \n private boolean helper(char[][] board, String word, int r, int c, int start) {\n // already match word all characters, return true\n if (start == word.length()) return true;\n if (!isValid(board, r, c) ||\n board[r][c] != word.charAt(start)) return false;\n // mark visited\n board[r][c] = '*';\n boolean res = helper(board, word, r + 1, c, start + 1)\n || helper(board, word, r, c + 1, start + 1)\n || helper(board, word, r - 1, c, start + 1)\n || helper(board, word, r, c - 1, start + 1);\n // backtracking to start position\n board[r][c] = word.charAt(start);\n return res;\n }\n \n private boolean isValid(char[][] board, int r, int c) {\n return r >= 0 && r < board.length && c >= 0 && c < board[0].length;\n }\n}\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def exist(self, board: List[List[str]], word: str) -> bool:\n m = len(board)\n n = len(board[0])\n \n def dfs(board, r, c, word, index):\n if index == len(word):\n return True\n if r < 0 or r >= m or c < 0 or c >= n or board[r][c] != word[index]:\n return False\n board[r][c] = '*'\n res = dfs(board, r - 1, c, word, index + 1) or dfs(board, r + 1, c, word, index + 1) or dfs(board, r, c - 1, word, index + 1) or dfs(board, r, c + 1, word, index + 1)\n board[r][c] = word[index]\n return res\n \n for r in range(m):\n for c in range(n):\n if board[r][c] == word[0]:\n if dfs(board, r, c, word, 0):\n return True\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/79.word-search.json b/spider/yield-db-json/79.word-search.json new file mode 100644 index 0000000..49de42d --- /dev/null +++ b/spider/yield-db-json/79.word-search.json @@ -0,0 +1,19 @@ +{ + "question": "79.word-search", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\npublic class LC79WordSearch {\n public boolean exist(char[][] board, String word) {\n if (board == null || board.length == 0 || board[0].length == 0\n || word == null || word.length() == 0) return true;\n int rows = board.length;\n int cols = board[0].length;\n for (int r = 0; r < rows; r++) {\n for (int c = 0; c < cols; c++) {\n // scan board, start with word first character \n if (board[r][c] == word.charAt(0)) {\n if (helper(board, word, r, c, 0)) {\n return true;\n }\n }\n }\n }\n return false;\n }\n \n private boolean helper(char[][] board, String word, int r, int c, int start) {\n // already match word all characters, return true\n if (start == word.length()) return true;\n if (!isValid(board, r, c) ||\n board[r][c] != word.charAt(start)) return false;\n // mark visited\n board[r][c] = '*';\n boolean res = helper(board, word, r - 1, c, start + 1) // 上\n || helper(board, word, r + 1, c, start + 1) // 下\n || helper(board, word, r, c - 1, start + 1) // 左\n || helper(board, word, r, c + 1, start + 1); // 右\n // backtracking to start position\n board[r][c] = word.charAt(start);\n return res;\n }\n \n private boolean isValid(char[][] board, int r, int c) {\n return r >= 0 && r < board.length && c >= 0 && c < board[0].length;\n }\n}\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def exist(self, board: List[List[str]], word: str) -> bool:\n m = len(board)\n n = len(board[0])\n \n def dfs(board, r, c, word, index):\n if index == len(word):\n return True\n if r < 0 or r >= m or c < 0 or c >= n or board[r][c] != word[index]:\n return False\n board[r][c] = '*'\n res = dfs(board, r - 1, c, word, index + 1) or dfs(board, r + 1, c, word, index + 1) or dfs(board, r, c - 1, word, index + 1) or dfs(board, r, c + 1, word, index + 1)\n board[r][c] = word[index]\n return res\n \n for r in range(m):\n for c in range(n):\n if board[r][c] == word[0]:\n if dfs(board, r, c, word, 0):\n return True\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/80.remove-duplicates-from-sorted-array-ii.json b/spider/yield-db-json/80.remove-duplicates-from-sorted-array-ii.json new file mode 100644 index 0000000..e3e39d0 --- /dev/null +++ b/spider/yield-db-json/80.remove-duplicates-from-sorted-array-ii.json @@ -0,0 +1,15 @@ +{ + "question": "80.remove-duplicates-from-sorted-array-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def removeDuplicates(self, nums: List[int]) -> int:\n # 写指针\n i = 0\n K = 2\n for num in nums:\n if i < K or num != nums[i-K]:\n nums[i] = num\n i += 1\n return i\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/820.short-encoding-of-words.json b/spider/yield-db-json/820.short-encoding-of-words.json new file mode 100644 index 0000000..b71c872 --- /dev/null +++ b/spider/yield-db-json/820.short-encoding-of-words.json @@ -0,0 +1,15 @@ +{ + "question": "820.short-encoding-of-words", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Trie:\n\n def __init__(self):\n \"\"\"\n Initialize your data structure here.\n \"\"\"\n self.Trie = {}\n\n def insert(self, word):\n \"\"\"\n Inserts a word into the trie.\n :type word: str\n :rtype: void\n \"\"\"\n curr = self.Trie\n for w in word:\n if w not in curr:\n curr[w] = {}\n curr = curr[w]\n curr['#'] = 1\n\n def isTail(self, word):\n \"\"\"\n Returns if the word is in the trie.\n :type word: str\n :rtype: bool\n \"\"\"\n curr = self.Trie\n for w in word:\n curr = curr[w]\n return len(curr) == 1\nclass Solution:\n def minimumLengthEncoding(self, words: List[str]) -> int:\n trie = Trie()\n cnt = 0\n words = set(words)\n for word in words:\n trie.insert(word[::-1])\n for word in words:\n if trie.isTail(word[::-1]):\n cnt += len(word) + 1\n return cnt\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/84.largest-rectangle-in-histogram.json b/spider/yield-db-json/84.largest-rectangle-in-histogram.json new file mode 100644 index 0000000..bd7c269 --- /dev/null +++ b/spider/yield-db-json/84.largest-rectangle-in-histogram.json @@ -0,0 +1,27 @@ +{ + "question": "84.largest-rectangle-in-histogram", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def largestRectangleArea(self, heights: List[int]) -> int:\n n, ans = len(heights), 0\n if n != 0:\n ans = heights[0]\n for i in range(n):\n height = heights[i]\n for j in range(i, n):\n height = min(height, heights[j])\n ans = max(ans, (j - i + 1) * height)\n return ans\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def largestRectangleArea(self, heights: List[int]) -> int:\n n = len(heights)\n l, r, ans = [-1] * n, [n] * n, 0\n for i in range(1, n):\n j = i - 1\n while j >= 0 and heights[j] >= heights[i]:\n j -= 1\n l[i] = j\n for i in range(n - 2, -1, -1):\n j = i + 1\n while j < n and heights[j] >= heights[i]:\n j += 1\n r[i] = j\n for i in range(n):\n ans = max(ans, heights[i] * (r[i] - l[i] - 1))\n return ans\n\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def largestRectangleArea(self, heights: List[int]) -> int:\n n = len(heights)\n l, r, ans = [-1] * n, [n] * n, 0\n\n for i in range(1, n):\n j = i - 1\n while j >= 0 and heights[j] >= heights[i]:\n j = l[j]\n l[i] = j\n for i in range(n - 2, -1, -1):\n j = i + 1\n while j < n and heights[j] >= heights[i]:\n j = r[j]\n r[i] = j\n for i in range(n):\n ans = max(ans, heights[i] * (r[i] - l[i] - 1))\n return ans\n\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def largestRectangleArea(self, heights: List[int]) -> int:\n n, heights, st, ans = len(heights), [0] + heights + [0], [], 0\n for i in range(n + 2):\n while st and heights[st[-1]] > heights[i]:\n ans = max(ans, heights[st.pop(-1)] * (i - st[-1] - 1))\n st.append(i)\n return ans\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/85.maximal-rectangle.json b/spider/yield-db-json/85.maximal-rectangle.json new file mode 100644 index 0000000..e59a301 --- /dev/null +++ b/spider/yield-db-json/85.maximal-rectangle.json @@ -0,0 +1,15 @@ +{ + "question": "85.maximal-rectangle", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def largestRectangleArea(self, heights: List[int]) -> int:\n n, heights, st, ans = len(heights), [0] + heights + [0], [], 0\n for i in range(n + 2):\n while st and heights[st[-1]] > heights[i]:\n ans = max(ans, heights[st.pop(-1)] * (i - st[-1] - 1))\n st.append(i)\n\n return ans\n def maximalRectangle(self, matrix: List[List[str]]) -> int:\n m = len(matrix)\n if m == 0: return 0\n n = len(matrix[0])\n heights = [0] * n\n ans = 0\n for i in range(m):\n for j in range(n):\n if matrix[i][j] == \"0\":\n heights[j] = 0\n else:\n heights[j] += 1\n ans = max(ans, self.largestRectangleArea(heights))\n return ans\n\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/86.partition-list.json b/spider/yield-db-json/86.partition-list.json new file mode 100644 index 0000000..1df2c80 --- /dev/null +++ b/spider/yield-db-json/86.partition-list.json @@ -0,0 +1,15 @@ +{ + "question": "86.partition-list", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def partition(self, head: ListNode, x: int) -> ListNode:\n \"\"\"在原链表操作,思路基本一致,只是通过指针进行区分而已\"\"\"\n # 在链表最前面设定一个初始node作为锚点,方便返回最后的结果\n first_node = ListNode(0)\n first_node.next = head\n # 设计三个指针,一个指向小于x的最后一个节点,即前后分离点\n # 一个指向当前遍历节点的前一个节点\n # 一个指向当前遍历的节点\n sep_node = first_node\n pre_node = first_node\n current_node = head\n \n while current_node is not None:\n if current_node.val < x:\n # 注意有可能出现前一个节点就是分离节点的情况\n if pre_node is sep_node:\n pre_node = current_node\n sep_node = current_node\n current_node = current_node.next\n else:\n # 这段次序比较烧脑\n pre_node.next = current_node.next\n current_node.next = sep_node.next\n sep_node.next = current_node\n sep_node = current_node\n current_node = pre_node.next\n else:\n pre_node = current_node\n current_node = pre_node.next\n \n return first_node.next\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/874.walking-robot-simulation.json b/spider/yield-db-json/874.walking-robot-simulation.json new file mode 100644 index 0000000..b12d92b --- /dev/null +++ b/spider/yield-db-json/874.walking-robot-simulation.json @@ -0,0 +1,15 @@ +{ + "question": "874.walking-robot-simulation", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int:\n pos = [0, 0]\n deg = 90\n ans = 0\n obstaclesSet = set(map(tuple, obstacles))\n\n for command in commands:\n if command == -1:\n deg = (deg + 270) % 360\n elif command == -2:\n deg = (deg + 90) % 360\n else:\n if deg == 0:\n i = 0\n while i < command and not (pos[0] + 1, pos[1]) in obstaclesSet:\n pos[0] += 1\n i += 1\n if deg == 90:\n i = 0\n while i < command and not (pos[0], pos[1] + 1) in obstaclesSet:\n pos[1] += 1\n i += 1\n if deg == 180:\n i = 0\n while i < command and not (pos[0] - 1, pos[1]) in obstaclesSet:\n pos[0] -= 1\n i += 1\n if deg == 270:\n i = 0\n while i < command and not (pos[0], pos[1] - 1) in obstaclesSet:\n pos[1] -= 1\n i += 1\n ans = max(ans, pos[0] ** 2 + pos[1] ** 2)\n return ans\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/875.koko-eating-bananas.json b/spider/yield-db-json/875.koko-eating-bananas.json new file mode 100644 index 0000000..3901c8b --- /dev/null +++ b/spider/yield-db-json/875.koko-eating-bananas.json @@ -0,0 +1,10 @@ +{ + "question": "875.koko-eating-bananas", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/877.stone-game.json b/spider/yield-db-json/877.stone-game.json new file mode 100644 index 0000000..4645c86 --- /dev/null +++ b/spider/yield-db-json/877.stone-game.json @@ -0,0 +1,10 @@ +{ + "question": "877.stone-game", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/88.merge-sorted-array.json b/spider/yield-db-json/88.merge-sorted-array.json new file mode 100644 index 0000000..e0925e0 --- /dev/null +++ b/spider/yield-db-json/88.merge-sorted-array.json @@ -0,0 +1,15 @@ +{ + "question": "88.merge-sorted-array", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:\n \"\"\"\n Do not return anything, modify nums1 in-place instead.\n \"\"\"\n # 整体思路相似,只不过没有使用 current 指针记录当前填补位置\n while m > 0 and n > 0:\n if nums1[m-1] <= nums2[n-1]:\n nums1[m+n-1] = nums2[n-1]\n n -= 1\n else:\n nums1[m+n-1] = nums1[m-1]\n m -=1\n \"\"\"\n 由于没有使用 current,第一步比较结束后有两种情况:\n 1. 指针 m>0,n=0,此时不需要做任何处理\n 2. 指针 n>0,m=0,此时需要将 nums2 指针左侧元素全部拷贝到 nums1 的前 n 位\n \"\"\"\n if n > 0:\n nums1[:n] = nums2[:n]\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/887.super-egg-drop.json b/spider/yield-db-json/887.super-egg-drop.json new file mode 100644 index 0000000..a2c85c5 --- /dev/null +++ b/spider/yield-db-json/887.super-egg-drop.json @@ -0,0 +1,10 @@ +{ + "question": "887.super-egg-drop", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/895.maximum-frequency-stack.json b/spider/yield-db-json/895.maximum-frequency-stack.json new file mode 100644 index 0000000..3554e51 --- /dev/null +++ b/spider/yield-db-json/895.maximum-frequency-stack.json @@ -0,0 +1,15 @@ +{ + "question": "895.maximum-frequency-stack", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass FreqStack:\n\n def __init__(self):\n self.fraq = collections.defaultdict(lambda: 0)\n self.fraq_stack = collections.defaultdict(list)\n self.max_fraq = 0\n \n def push(self, x: int) -> None:\n self.fraq[x] += 1\n if self.fraq[x] > self.max_fraq:\n self.max_fraq = self.fraq[x]\n self.fraq_stack[self.fraq[x]].append(x) \n \n def pop(self) -> int:\n ans = self.fraq_stack[self.max_fraq].pop()\n self.fraq[ans] -= 1\n if not self.fraq_stack[self.max_fraq]:\n self.max_fraq -= 1\n return ans\n\n# Your FreqStack object will be instantiated and called as such:\n# obj = FreqStack()\n# obj.push(x)\n# param_2 = obj.pop()\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/90.subsets-ii-en.json b/spider/yield-db-json/90.subsets-ii-en.json new file mode 100644 index 0000000..9329f22 --- /dev/null +++ b/spider/yield-db-json/90.subsets-ii-en.json @@ -0,0 +1,10 @@ +{ + "question": "90.subsets-ii-en", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/90.subsets-ii.json b/spider/yield-db-json/90.subsets-ii.json new file mode 100644 index 0000000..9c27fb3 --- /dev/null +++ b/spider/yield-db-json/90.subsets-ii.json @@ -0,0 +1,10 @@ +{ + "question": "90.subsets-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/900.rle-iterator.json b/spider/yield-db-json/900.rle-iterator.json new file mode 100644 index 0000000..a13a8b7 --- /dev/null +++ b/spider/yield-db-json/900.rle-iterator.json @@ -0,0 +1,10 @@ +{ + "question": "900.rle-iterator", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/91.decode-ways.json b/spider/yield-db-json/91.decode-ways.json new file mode 100644 index 0000000..ced0c47 --- /dev/null +++ b/spider/yield-db-json/91.decode-ways.json @@ -0,0 +1,10 @@ +{ + "question": "91.decode-ways", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/912.sort-an-array.json b/spider/yield-db-json/912.sort-an-array.json new file mode 100644 index 0000000..e88e07d --- /dev/null +++ b/spider/yield-db-json/912.sort-an-array.json @@ -0,0 +1,10 @@ +{ + "question": "912.sort-an-array", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/92.reverse-linked-list-ii.json b/spider/yield-db-json/92.reverse-linked-list-ii.json new file mode 100644 index 0000000..68508fd --- /dev/null +++ b/spider/yield-db-json/92.reverse-linked-list-ii.json @@ -0,0 +1,23 @@ +{ + "question": "92.reverse-linked-list-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:\n pre = None\n cur = head\n i = 0\n p1 = p2 = p3 = p4 = None\n # ...\n if p1:\n p1.next = p3\n else:\n dummy.next = p3\n if p2:\n p2.next = p4\n return head\n" + }, + { + "lang": "python", + "code": "\n class Solution:\n def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:\n pre = None\n cur = head\n i = 0\n p1 = p2 = p3 = p4 = None\n dummy = ListNode(0)\n dummy.next = head\n\n # ...\n\n if p1:\n p1.next = p3\n else:\n dummy.next = p3\n if p2:\n p2.next = p4\n\n return dummy.next\n " + }, + { + "lang": "python", + "code": "\n while cur:\n i += 1\n if i == m - 1:\n p1 = cur\n next = cur.next\n if m < i <= n:\n cur.next = pre\n\n if i == m:\n p2 = cur\n p2.next = None\n\n if i == n:\n p3 = cur\n\n if i == n + 1:\n p4 = cur\n\n pre = cur\n cur = next\n " + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/935.knight-dialer.json b/spider/yield-db-json/935.knight-dialer.json new file mode 100644 index 0000000..b5bd8d6 --- /dev/null +++ b/spider/yield-db-json/935.knight-dialer.json @@ -0,0 +1,19 @@ +{ + "question": "935.knight-dialer", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def knightDialer(self, N: int) -> int:\n cnt = 0\n jump = [[4, 6], [6, 8], [7, 9], [4, 8], [\n 0, 3, 9], [], [0, 1, 7], [2, 6], [1, 3], [2, 4]]\n visited = dict()\n\n def helper(i, n):\n if (i, n) in visited: return visited[(i, n)]\n if n == 1:\n return 1\n cnt = 0\n for j in jump[i]:\n cnt += helper(j, n - 1)\n visited[(i, n)] = cnt\n return cnt\n for i in range(10):\n cnt += helper(i, N)\n return cnt % (10**9 + 7)\n" + }, + { + "lang": "python", + "code": "\nclass Solution:\n def knightDialer(self, N: int) -> int:\n a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 1\n for _ in range(N - 1):\n a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = a4 + a6, a6 + a8, a7 + \\\n a9, a4 + a8, a0 + a3 + a9, 0, a0 + a1 + a7, a2 + a6, a1 + a3, a2 + a4\n return (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9) % (10**9 + 7)\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/94.binary-tree-inorder-traversal.json b/spider/yield-db-json/94.binary-tree-inorder-traversal.json new file mode 100644 index 0000000..b9494ad --- /dev/null +++ b/spider/yield-db-json/94.binary-tree-inorder-traversal.json @@ -0,0 +1,19 @@ +{ + "question": "94.binary-tree-inorder-traversal", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nclass Solution {\n List res = new LinkedList<>();\n public List inorderTraversal(TreeNode root) {\n inorder(root);\n return res;\n }\n \n public void inorder (TreeNode root) {\n if (root == null) return;\n \n inorder(root.left);\n \n res.add(root.val);\n \n inorder(root.right);\n }\n}\n" + }, + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nclass Solution {\n public List inorderTraversal(TreeNode root) {\n List res = new ArrayList<> ();\n Stack stack = new Stack<> ();\n\n while (root != null || !stack.isEmpty()) {\n while (root != null) {\n stack.push(root);\n root = root.left;\n }\n root = stack.pop();\n res.add(root.val);\n root = root.right;\n }\n return res;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/95.unique-binary-search-trees-ii.json b/spider/yield-db-json/95.unique-binary-search-trees-ii.json new file mode 100644 index 0000000..41ceae5 --- /dev/null +++ b/spider/yield-db-json/95.unique-binary-search-trees-ii.json @@ -0,0 +1,10 @@ +{ + "question": "95.unique-binary-search-trees-ii", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [] +} \ No newline at end of file diff --git a/spider/yield-db-json/96.unique-binary-search-trees.json b/spider/yield-db-json/96.unique-binary-search-trees.json new file mode 100644 index 0000000..a9fc73d --- /dev/null +++ b/spider/yield-db-json/96.unique-binary-search-trees.json @@ -0,0 +1,15 @@ +{ + "question": "96.unique-binary-search-trees", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "python", + "code": "\nclass Solution:\n def numTrees(self, n: int) -> int:\n if n <= 1:\n return 1\n res = 0\n for i in range(1, n + 1):\n res += self.numTrees(i - 1) * self.numTrees(n - i)\n return res\n" + } + ] +} \ No newline at end of file diff --git a/spider/yield-db-json/98.validate-binary-search-tree.json b/spider/yield-db-json/98.validate-binary-search-tree.json new file mode 100644 index 0000000..6c76127 --- /dev/null +++ b/spider/yield-db-json/98.validate-binary-search-tree.json @@ -0,0 +1,19 @@ +{ + "question": "98.validate-binary-search-tree", + "companys": [ + "TODO" + ], + "tags": [ + "TODO" + ], + "reslove": [ + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nclass Solution {\n public boolean isValidBST(TreeNode root) {\n Stack stack = new Stack<> ();\n TreeNode previous = null;\n\n while (root != null || !stack.isEmpty()) {\n while (root != null) {\n stack.push(root);\n root = root.left;\n }\n root = stack.pop();\n if (previous != null && root.val <= previous.val ) return false;\n previous = root;\n root = root.right;\n }\n return true;\n }\n}\n" + }, + { + "lang": "java", + "code": "\n/**\n * Definition for a binary tree node.\n * public class TreeNode {\n * int val;\n * TreeNode left;\n * TreeNode right;\n * TreeNode(int x) { val = x; }\n * }\n */\nclass Solution { \n public boolean isValidBST(TreeNode root) {\n return helper(root, null, null);\n }\n\n private boolean helper(TreeNode root, Integer lower, Integer higher) {\n if (root == null) return true;\n\n if (lower != null && root.val <= lower) return false;\n if (higher != null && root.val >= higher) return false;\n\n if (!helper(root.left, lower, root.val)) return false;\n if (!helper(root.right, root.val, higher)) return false;\n\n return true;\n }\n}\n" + } + ] +} \ No newline at end of file diff --git a/src/db/collection.js b/src/db/collection.js new file mode 100644 index 0000000..f79a6f3 --- /dev/null +++ b/src/db/collection.js @@ -0,0 +1,4 @@ +import * as questions from '../../spider/yield-db-json' + + +console.log(questions) \ No newline at end of file