diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1bbc36c013..e183e0bfb7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,7 +2,7 @@ name: Build and Deploy
on:
push:
- branches: [ master ]
+ branches: [master]
jobs:
build-and-deploy:
@@ -10,20 +10,20 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2.3.1
- with:
+ with:
persist-credentials: false
- - name: Set Ruby 2.7
+ - name: Set Ruby 3.1
uses: actions/setup-ruby@v1
with:
- ruby-version: 2.7
+ ruby-version: 3.1
- name: Install and Build
run: |
gem install bundler
bundle install
bundle exec jekyll build
-
+
- name: Deploy
uses: JamesIves/github-pages-deploy-action@3.6.2
with:
diff --git a/Gemfile.lock b/Gemfile.lock
index 7650455f87..cb433f4262 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,96 +1,95 @@
GEM
remote: https://rubygems.org/
specs:
- activesupport (6.0.3.5)
+ activesupport (6.0.6.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
- addressable (2.8.0)
- public_suffix (>= 2.0.2, < 5.0)
+ addressable (2.8.1)
+ public_suffix (>= 2.0.2, < 6.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
- commonmarker (0.17.13)
- ruby-enum (~> 0.5)
- concurrent-ruby (1.1.8)
- dnsruby (1.61.5)
+ commonmarker (0.23.6)
+ concurrent-ruby (1.2.0)
+ dnsruby (1.61.9)
simpleidn (~> 0.1)
- em-websocket (0.5.2)
+ em-websocket (0.5.3)
eventmachine (>= 0.12.9)
- http_parser.rb (~> 0.6.0)
- ethon (0.12.0)
- ffi (>= 1.3.0)
+ http_parser.rb (~> 0)
+ ethon (0.16.0)
+ ffi (>= 1.15.0)
eventmachine (1.2.7)
- execjs (2.7.0)
- faraday (1.3.0)
- faraday-net_http (~> 1.0)
- multipart-post (>= 1.2, < 3)
- ruby2_keywords
- faraday-net_http (1.0.1)
- ffi (1.14.2)
+ execjs (2.8.1)
+ faraday (2.7.2)
+ faraday-net_http (>= 2.0, < 3.1)
+ ruby2_keywords (>= 0.0.4)
+ faraday-net_http (3.0.2)
+ ffi (1.15.5)
forwardable-extended (2.6.0)
gemoji (3.0.1)
- github-pages (212)
- github-pages-health-check (= 1.17.0)
- jekyll (= 3.9.0)
+ github-pages (227)
+ github-pages-health-check (= 1.17.9)
+ jekyll (= 3.9.2)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
- jekyll-commonmark-ghpages (= 0.1.6)
+ jekyll-commonmark-ghpages (= 0.2.0)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0)
+ jekyll-include-cache (= 0.2.1)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
- jekyll-remote-theme (= 0.4.2)
+ jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
- jekyll-seo-tag (= 2.7.1)
+ jekyll-seo-tag (= 2.8.0)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
- jekyll-theme-architect (= 0.1.1)
- jekyll-theme-cayman (= 0.1.1)
- jekyll-theme-dinky (= 0.1.1)
- jekyll-theme-hacker (= 0.1.2)
- jekyll-theme-leap-day (= 0.1.1)
- jekyll-theme-merlot (= 0.1.1)
- jekyll-theme-midnight (= 0.1.1)
- jekyll-theme-minimal (= 0.1.1)
- jekyll-theme-modernist (= 0.1.1)
- jekyll-theme-primer (= 0.5.4)
- jekyll-theme-slate (= 0.1.1)
- jekyll-theme-tactile (= 0.1.1)
- jekyll-theme-time-machine (= 0.1.1)
+ jekyll-theme-architect (= 0.2.0)
+ jekyll-theme-cayman (= 0.2.0)
+ jekyll-theme-dinky (= 0.2.0)
+ jekyll-theme-hacker (= 0.2.0)
+ jekyll-theme-leap-day (= 0.2.0)
+ jekyll-theme-merlot (= 0.2.0)
+ jekyll-theme-midnight (= 0.2.0)
+ jekyll-theme-minimal (= 0.2.0)
+ jekyll-theme-modernist (= 0.2.0)
+ jekyll-theme-primer (= 0.6.0)
+ jekyll-theme-slate (= 0.2.0)
+ jekyll-theme-tactile (= 0.2.0)
+ jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
- kramdown (= 2.3.0)
+ kramdown (= 2.3.2)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
- nokogiri (>= 1.10.4, < 2.0)
+ nokogiri (>= 1.13.6, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
- github-pages-health-check (1.17.0)
+ github-pages-health-check (1.17.9)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
- public_suffix (>= 2.0.2, < 5.0)
+ public_suffix (>= 3.0, < 5.0)
typhoeus (~> 1.3)
- html-pipeline (2.14.0)
+ html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
- http_parser.rb (0.6.0)
+ http_parser.rb (0.8.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
- jekyll (3.9.0)
+ jekyll (3.9.2)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
@@ -108,12 +107,12 @@ GEM
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
- jekyll-commonmark (1.3.1)
- commonmarker (~> 0.14)
- jekyll (>= 3.7, < 5.0)
- jekyll-commonmark-ghpages (0.1.6)
- commonmarker (~> 0.17.6)
- jekyll-commonmark (~> 1.2)
+ jekyll-commonmark (1.4.0)
+ commonmarker (~> 0.22)
+ jekyll-commonmark-ghpages (0.2.0)
+ commonmarker (~> 0.23.4)
+ jekyll (~> 3.9.0)
+ jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
@@ -124,6 +123,8 @@ GEM
jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0)
+ jekyll-include-cache (0.2.1)
+ jekyll (>= 3.7, < 5.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
@@ -136,57 +137,57 @@ GEM
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
- jekyll-remote-theme (0.4.2)
+ jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
- jekyll-seo-tag (2.7.1)
+ jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
- jekyll-theme-architect (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-architect (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-cayman (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-cayman (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-dinky (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-dinky (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-hacker (0.1.2)
+ jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-leap-day (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-leap-day (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-merlot (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-merlot (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-midnight (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-midnight (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-minimal (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-minimal (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-modernist (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-modernist (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-primer (0.5.4)
+ jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-slate (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-slate (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-tactile (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-tactile (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-time-machine (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-time-machine (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
@@ -196,12 +197,12 @@ GEM
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
- kramdown (2.3.0)
+ kramdown (2.3.2)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
- listen (3.4.1)
+ listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
@@ -209,37 +210,36 @@ GEM
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
- minitest (5.14.4)
- multipart-post (2.1.1)
- nokogiri (1.12.5-x86_64-darwin)
+ minitest (5.17.0)
+ nokogiri (1.13.10-arm64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.13.10-x86_64-darwin)
racc (~> 1.4)
- nokogiri (1.12.5-x86_64-linux)
+ nokogiri (1.13.10-x86_64-linux)
racc (~> 1.4)
- octokit (4.20.0)
- faraday (>= 0.9)
- sawyer (~> 0.8.0, >= 0.5.3)
+ octokit (4.25.1)
+ faraday (>= 1, < 3)
+ sawyer (~> 0.9)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
- public_suffix (4.0.6)
- racc (1.5.2)
- rb-fsevent (0.10.4)
+ public_suffix (4.0.7)
+ racc (1.6.2)
+ rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.26.0)
- ruby-enum (0.9.0)
- i18n
- ruby2_keywords (0.0.4)
- rubyzip (2.3.0)
+ ruby2_keywords (0.0.5)
+ rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
- sawyer (0.8.2)
+ sawyer (0.9.2)
addressable (>= 2.3.5)
- faraday (> 0.8, < 2.0)
+ faraday (>= 0.17.3, < 3)
simpleidn (0.2.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
@@ -247,16 +247,17 @@ GEM
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
- tzinfo (1.2.9)
+ tzinfo (1.2.11)
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.7)
- unicode-display_width (1.7.0)
+ unf_ext (0.0.8.2)
+ unicode-display_width (1.8.0)
webrick (1.7.0)
- zeitwerk (2.4.2)
+ zeitwerk (2.6.6)
PLATFORMS
+ arm64-darwin-22
x86_64-darwin-20
x86_64-linux
@@ -266,4 +267,4 @@ DEPENDENCIES
webrick (~> 1.7)
BUNDLED WITH
- 2.2.13
+ 2.3.26
diff --git a/LICENSE b/LICENSE
index 5ec214b971..27d0e197d4 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2013 Zhuang Ma
+Copyright (c) 2013 Fulong Ma
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
diff --git a/README.md b/README.md
index 995697195a..7c748d8cc8 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
## Usage
-无
+draft: true表示是草稿。
## Acknowledge
diff --git a/_config.yml b/_config.yml
index 4c08f7ba29..85f838eed2 100644
--- a/_config.yml
+++ b/_config.yml
@@ -7,18 +7,17 @@ date_format: "ordinal"
title: Fulongのblog
subtitle: "Hi"
description: "Fulongのblog"
-# subtitle: "Legendary"
-subtitle: "逃跑可耻但有用"
+subtitle: "Logbook"
keywords: logbook, mafulong
timezone: Asia/Shanghai
encoding: "utf-8"
-side_bar_repo_limit: 4
-# 下面涉及js引用,先不能改
+side_bar_repo_limit: 3
repository: mafulong/mafulong.github.io
# 对 css 和 js 资源的 cdn 加速配置
cdn:
jsdelivr:
- enabled: true
+ enabled: true
+ branch: "built"
# 组件配置
components:
# 分享
@@ -27,7 +26,6 @@ components:
# 不蒜子访问统计
busuanzi:
enabled: true
- start_date: 2020-05-03
# 压缩页面内容
compress_html:
clippings: all
@@ -64,29 +62,18 @@ navs:
href: /archives/
label: Achieves
- # -
- # href: /open-source
- # label: Open-Source
+ -
+ href: /open-source
+ label: Open-Source
-# -
-# href: /wiki
-# label: Wiki
-
href: /bookmark
label: Bookmark
-# -
-# href: /links
-# label: Links
-
href: /about
label: About
-# ---------------- #
-# RSS #
-# ---------------- #
-# subscribe_rss: /feed.xml
-
# ---------------- #
# Jekyll #
# ---------------- #
@@ -117,7 +104,7 @@ collections:
# Comments #
# ---------------- #
# support provider: disqus, gitment, gitalk
-comments_provider: gitalk
+# comments_provider: gitalk
# !!!重要!!! 请修改下面这些信息为你自己申请的
# !!!Important!!! Please modify infos below to yours
# https://disqus.com
@@ -131,11 +118,11 @@ comments_provider: gitalk
# client_id: d2e1cbbd298958076462
# client_secret: b42a4178e5fd4a7cf63189ef4b1453b05c375709
# https://github.com/gitalk/gitalk#install
-gitalk:
- owner: mafulong
- repo: blog-comment
- clientID: 99d40aa8c51f2e320555
- clientSecret: 08d7d01185f19e4e205adc2b36a6750d92d640c2
+# gitalk:
+ # owner: mafulong
+ # repo: blog-comment
+ # clientID: 99d40aa8c51f2e320555
+ # clientSecret: 08d7d01185f19e4e205adc2b36a6750d92d640c2
# 在使用其它评论组件时可点击显示 Disqus
lazy_load_disqus : false
@@ -146,14 +133,12 @@ simple_jekyll_search:
# 是否支持全文搜索
fulltext: false
# 最多显示多少条搜索结果
- limit: 16
+ limit: 20
# ---------------- #
# Google #
# ---------------- #
google:
- # analytics_id: UA-80669434-1
- analytics_id: G-SS4VDLWLNC
adsense:
footer: false
sidebar: false
diff --git a/_data/links.yml b/_data/links.yml
deleted file mode 100644
index 71cac97ce9..0000000000
--- a/_data/links.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-
-# - name: Connie 酱
-# url: https://connie99.github.io
-# src: life
-
-# - name: 只宁静不致远
-# url: http://zxning.github.io
-# src: life
-
-# - name: Blog Something
-# url: http://chenxiaoyoyo.github.io
-# src: life
-
-# - name: 日新亭
-# url: http://www.fengerzh.com/
-# src: life
-
-# - name: wanandroid
-# url: http://www.wanandroid.com/
-# src: life
-
-# - name: ZZY补完计划
-# url: https://zzycreate.github.io/
-# src: life
-
-# - name: 村农
-# url: http://www.why-dong.com/
-# src: life
-
-# - name: 求生之路
-# url: http://blog.xiaolaoni.xin/
-# src: life
-
-# - name: 王玉超
-# url: https://yuchao.wang/
-# src: life
-
-# - name: 董小姐的草原
-# url: https://candy961.github.io/
-# src: life
-
-# - name: 水寒的博客
-# url: https://dp2px.com
-# src: www
-
-# - name: 孙不服的博客
-# url: https://sunbufu.github.io/
-# src: www
-
-# - name: HwiLu's 博客
-# url: https://hwilu.github.io/
-# src: www
-
-# - name: 有次博客
-# url: http://you.ci/
-# src: www
-
-# - name: 呓城之城
-# url: http://yicheng.zdyrs.com/
-# src: www
-
-# - name: 秦大圣的博客
-# url: https://qinjisheng.top/
-# src: www
-
-# - name: 极客玩家大白
-# url: https://geekplayers.com/
-# src: www
-
-# - name: 见字如面
-# url: https://hiwannz.com
-# src: www
diff --git a/_data/skills.yml b/_data/skills.yml
deleted file mode 100644
index 4575e85c17..0000000000
--- a/_data/skills.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-# - name: Software Engineer Keywords
-# keywords:
-# - Java
-# - C++
-# - Python
-# - Design Patterns
-
-# - name: Mobile Developer Keywords
-# keywords:
-# - Android
-# - Reverse Engineering
-
-# - name: Windows Developer Keywords
-# keywords:
-# - Win32 SDK
-# - DuiLib
-# - WTL
-# - COM
-# - WinDbg
diff --git a/_data/social.yml b/_data/social.yml
deleted file mode 100644
index 609e4c6ec1..0000000000
--- a/_data/social.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-- sitename: GitHub
- name: mafulong
- url: https://github.com/mafulong
-
-- sitename: 博客
- name: LogBook
- url: http://mafulong.github.io
-
-- sitename: 知乎
- name: mafulong知乎
- url: https://www.zhihu.com/people/ma-fu-long-86
-
diff --git a/_data/template.md b/_data/template.md
deleted file mode 100644
index 5ef1a00a40..0000000000
--- a/_data/template.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-layout: wiki
-title: Wiki Template
-categories: [cate1, cate2]
-description: some word here
-keywords: keyword1, keyword2
----
-
-Content here
diff --git a/_includes/categories.html b/_includes/categories.html
deleted file mode 100644
index de2c117a8c..0000000000
--- a/_includes/categories.html
+++ /dev/null
@@ -1,44 +0,0 @@
----
-layout: default
----
-
-{% assign assets_base_url = site.url %}
-{% if site.cdn.jsdelivr.enabled %}
-{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@master' %}
-{% endif %}
-
-
-
-
-
- {% include sidebar-qrcode.html %}
-
-
-
-
-
-
-
-
-
- {{ content }}
-
-
- {% include sns-share.html %}
-
-
-
-
- {% include sidebar-search.html %}
- {% include sidebar-categories-nav.html %}
-
-
-
-
-
\ No newline at end of file
diff --git a/_includes/footer.html b/_includes/footer.html
index 337f5cc66f..a9476309aa 100755
--- a/_includes/footer.html
+++ b/_includes/footer.html
@@ -43,6 +43,20 @@
+
+
{% if site.components.share.enabled %}
{% endif %}
@@ -84,8 +98,8 @@
{% endif %}
{% if page.mindmap %}
-
-
+
+
{% endif %}
-
diff --git a/_includes/header.html b/_includes/header.html
index 817307bbf8..b5d4f37144 100755
--- a/_includes/header.html
+++ b/_includes/header.html
@@ -16,6 +16,7 @@
+
{% assign highlight_base_url = 'https://mazhuang.org/rouge-themes/dist' %}
{% if site.cdn.jsdelivr.enabled %}
{% assign highlight_base_url = 'https://cdn.jsdelivr.net/gh/mzlogin/rouge-themes@master/dist' %}
diff --git a/_includes/page.html b/_includes/page.html
deleted file mode 100644
index f8c7f371de..0000000000
--- a/_includes/page.html
+++ /dev/null
@@ -1,52 +0,0 @@
----
-layout: default
----
-
-{% assign assets_base_url = site.url %}
-{% if site.cdn.jsdelivr.enabled %}
-{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@master' %}
-{% endif %}
-
-
-
-
-
-
- {% if page.subtitle %}
-
-
- {{ page.subtitle}}
-
-
- {% endif %}
-
-
-
- {% include sidebar-qrcode.html %}
-
-
-
-
-
-
-
-
-
- {{ content }}
-
-
- {% include sns-share.html %}
-
-
-
-
- {% include sidebar-search.html %}
- {% include sidebar-categories-cloud.html %}
-
- {% include sidebar-popular-repo.html %}
-
-
-
-
\ No newline at end of file
diff --git a/_includes/sidebar-ad.html b/_includes/sidebar-ad.html
index 6fbaf11869..e8e5398e91 100755
--- a/_includes/sidebar-ad.html
+++ b/_includes/sidebar-ad.html
@@ -1,8 +1,3 @@
{% if site.google.adsense.sidebar and site.url contains 'mafulong.github.io' %}
-
-
{% endif %}%
\ No newline at end of file
diff --git a/_includes/sidebar-recent-update.html b/_includes/sidebar-recent-update.html
new file mode 100755
index 0000000000..68e612e4ab
--- /dev/null
+++ b/_includes/sidebar-recent-update.html
@@ -0,0 +1,11 @@
+
+
Popular Posts
+
+ {% for post in site.posts %}
+ {% if post.recent_update== true %}
+
+ {% endif %}
+ {% endfor %}
+
diff --git a/_includes/sidebar-search.html b/_includes/sidebar-search.html
index ed6c900857..f6bdf81bf5 100644
--- a/_includes/sidebar-search.html
+++ b/_includes/sidebar-search.html
@@ -1,27 +1,50 @@
-
Search
-
+
-
+
+ SimpleJekyllSearch({
+ searchInput: document.getElementById('search_box'),
+ resultsContainer: document.getElementById('search_results'),
+ {% if site.cdn.jsdelivr.enabled and site.url contains 'mafulong.github.io' %}
+ json: 'https://cdn.jsdelivr.net/gh/mafulong/mafulong.github.io@built/assets/search_data.json',
+ {% else %}
+ json: '{{ site.url }}/assets/search_data.json',
+ {% endif %}
+ searchResultTemplate: '
{title} ',
+ noResultsText: 'No results found',
+ limit: {{ site.simple_jekyll_search.limit }},
+ fuzzy: false,
+ exclude: ['Welcome']
+ });
+ window.onload = function(){
+ var query_text = window.location.search.substring(1);
+ var vars = query_text.split("&");
+ for (var i=0;i
diff --git a/_includes/visit-stat.html b/_includes/visit-stat.html
index b156a3fa45..23fe1ac07a 100644
--- a/_includes/visit-stat.html
+++ b/_includes/visit-stat.html
@@ -8,11 +8,5 @@
/ 本站访客数 人
-
-
-
-
-
-
{% endif %}
\ No newline at end of file
diff --git a/_layouts/categories.html b/_layouts/categories.html
index d07595da2b..414ab8c0e6 100755
--- a/_layouts/categories.html
+++ b/_layouts/categories.html
@@ -4,7 +4,7 @@
{% assign assets_base_url = site.url %}
{% if site.cdn.jsdelivr.enabled %}
-{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@master' %}
+{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@'| append: site.cdn.jsdelivr.branch %}
{% endif %}
diff --git a/_layouts/default.html b/_layouts/default.html
index 9c762fad3d..5d05f3f6a6 100755
--- a/_layouts/default.html
+++ b/_layouts/default.html
@@ -4,9 +4,8 @@
{% assign assets_base_url = site.url %}
{% if site.cdn.jsdelivr.enabled %}
-{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@master' %}
+{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@'| append: site.cdn.jsdelivr.branch %}
{% endif %}
-{% assign assets_images_url = '
-
-
-
-
-
-
-{{ content }}
-
-
-
diff --git a/_layouts/page.html b/_layouts/page.html
index 7ba323b0cb..84f121ade0 100755
--- a/_layouts/page.html
+++ b/_layouts/page.html
@@ -4,7 +4,7 @@
{% assign assets_base_url = site.url %}
{% if site.cdn.jsdelivr.enabled %}
-{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@master' %}
+{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@'| append: site.cdn.jsdelivr.branch %}
{% endif %}
@@ -45,6 +45,7 @@
{% include sidebar-search.html %}
{% include sidebar-categories-cloud.html %}
+ {% include sidebar-recent-update.html %}
{% include sidebar-popular-repo.html %}
diff --git a/_layouts/post.html b/_layouts/post.html
index a544affaf9..93e302cd11 100755
--- a/_layouts/post.html
+++ b/_layouts/post.html
@@ -4,7 +4,7 @@
{% assign assets_base_url = site.url %}
{% if site.cdn.jsdelivr.enabled %}
-{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@master' %}
+{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@'| append: site.cdn.jsdelivr.branch %}
{% endif %}
@@ -61,6 +61,7 @@
{% include sidebar-search.html %}
{% include sidebar-post-nav.html %}
+ {% include sidebar-recent-update.html %}
diff --git a/_layouts/wiki.html b/_layouts/wiki.html
deleted file mode 100755
index 68c3ac2e32..0000000000
--- a/_layouts/wiki.html
+++ /dev/null
@@ -1,46 +0,0 @@
----
-layout: default
----
-
-{% assign assets_base_url = site.url %}
-{% if site.cdn.jsdelivr.enabled %}
-{% assign assets_base_url = "https://cdn.jsdelivr.net/gh/" | append: site.repository | append: '@master' %}
-{% endif %}
-
-
-
-
-
- {% include sidebar-qrcode.html %}
-
-
-
-
-
-
-
-
- {% include content-header-ad.html %}
-
- {{ content }}
-
-
-
- {% include sns-share.html %}
-
- {% include content-footer-ad.html %}
-
-
-
- {% include sidebar-search.html %}
- {% include sidebar-post-nav.html %}
-
-
-
-
diff --git a/_posts/Algorithms/leetcode/2022-07-16-2335. Minimum Amount of Time to Fill Cups.md b/_posts/Algorithms/leetcode/2022-07-16-2335. Minimum Amount of Time to Fill Cups.md
new file mode 100644
index 0000000000..77e574190c
--- /dev/null
+++ b/_posts/Algorithms/leetcode/2022-07-16-2335. Minimum Amount of Time to Fill Cups.md
@@ -0,0 +1,78 @@
+---
+layout: post
+category: leetcode
+title: 2335. Minimum Amount of Time to Fill Cups
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimum-amount-of-time-to-fill-cups/)
+
+You have a water dispenser that can dispense cold, warm, and hot water. Every second, you can either fill up `2` cups with **different** types of water, or `1` cup of any type of water.
+
+You are given a **0-indexed** integer array `amount` of length `3` where `amount[0]`, `amount[1]`, and `amount[2]` denote the number of cold, warm, and hot water cups you need to fill respectively. Return *the **minimum** number of seconds needed to fill up all the cups*.
+
+
+
+**Example 1:**
+
+```
+Input: amount = [1,4,2]
+Output: 4
+Explanation: One way to fill up the cups is:
+Second 1: Fill up a cold cup and a warm cup.
+Second 2: Fill up a warm cup and a hot cup.
+Second 3: Fill up a warm cup and a hot cup.
+Second 4: Fill up a warm cup.
+It can be proven that 4 is the minimum number of seconds needed.
+```
+
+**Example 2:**
+
+```
+Input: amount = [5,4,4]
+Output: 7
+Explanation: One way to fill up the cups is:
+Second 1: Fill up a cold cup, and a hot cup.
+Second 2: Fill up a cold cup, and a warm cup.
+Second 3: Fill up a cold cup, and a warm cup.
+Second 4: Fill up a warm cup, and a hot cup.
+Second 5: Fill up a cold cup, and a hot cup.
+Second 6: Fill up a cold cup, and a warm cup.
+Second 7: Fill up a hot cup.
+```
+
+**Example 3:**
+
+```
+Input: amount = [5,0,0]
+Output: 5
+Explanation: Every second, we fill up a cold cup.
+```
+
+
+
+**Constraints:**
+
+- `amount.length == 3`
+- `0 <= amount[i] <= 100`
+
+## solution
+
+We can use the technique of greedy and category discussion.
+
+At every step only choose the max-2 cups to be filled.
+
+```python
+class Solution:
+ def fillCups(self, amount: List[int]) -> int:
+ a, b, c = sorted(amount, reverse=True)
+ if b + c < a:
+ return a
+ t = b + c - a
+ if t % 2 == 0:
+ return (t // 2) + a
+ # t is odd
+ return ((t - 1) // 2) + a + 1
+```
+
diff --git a/_posts/Algorithms/leetcode/2022-07-16-2336. Smallest Number in Infinite Set.md b/_posts/Algorithms/leetcode/2022-07-16-2336. Smallest Number in Infinite Set.md
new file mode 100644
index 0000000000..9ced85dc92
--- /dev/null
+++ b/_posts/Algorithms/leetcode/2022-07-16-2336. Smallest Number in Infinite Set.md
@@ -0,0 +1,81 @@
+---
+layout: post
+category: leetcode
+title: 2336. Smallest Number in Infinite Set
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/smallest-number-in-infinite-set/)
+
+You have a set which contains all positive integers `[1, 2, 3, 4, 5, ...]`.
+
+Implement the `SmallestInfiniteSet` class:
+
+- `SmallestInfiniteSet()` Initializes the **SmallestInfiniteSet** object to contain **all** positive integers.
+- `int popSmallest()` **Removes** and returns the smallest integer contained in the infinite set.
+- `void addBack(int num)` **Adds** a positive integer `num` back into the infinite set, if it is **not** already in the infinite set.
+
+
+
+**Example 1:**
+
+```
+Input
+["SmallestInfiniteSet", "addBack", "popSmallest", "popSmallest", "popSmallest", "addBack", "popSmallest", "popSmallest", "popSmallest"]
+[[], [2], [], [], [], [1], [], [], []]
+Output
+[null, null, 1, 2, 3, null, 1, 4, 5]
+
+Explanation
+SmallestInfiniteSet smallestInfiniteSet = new SmallestInfiniteSet();
+smallestInfiniteSet.addBack(2); // 2 is already in the set, so no change is made.
+smallestInfiniteSet.popSmallest(); // return 1, since 1 is the smallest number, and remove it from the set.
+smallestInfiniteSet.popSmallest(); // return 2, and remove it from the set.
+smallestInfiniteSet.popSmallest(); // return 3, and remove it from the set.
+smallestInfiniteSet.addBack(1); // 1 is added back to the set.
+smallestInfiniteSet.popSmallest(); // return 1, since 1 was added back to the set and
+ // is the smallest number, and remove it from the set.
+smallestInfiniteSet.popSmallest(); // return 4, and remove it from the set.
+smallestInfiniteSet.popSmallest(); // return 5, and remove it from the set.
+```
+
+
+
+**Constraints:**
+
+- `1 <= num <= 1000`
+- At most `1000` calls will be made **in total** to `popSmallest` and `addBack`.
+
+## solution
+
+One way, we can use the heapq + set. Another way, we can divide it into two parts, maintain the smallest num and a sortedset so that no initial heap in the first.
+
+```python
+import heapq
+
+
+class SmallestInfiniteSet:
+
+ def __init__(self):
+ self.h = list(range(1, 1001, 1))
+ self.s = set(self.h)
+ heapq.heapify(self.h)
+
+ def popSmallest(self) -> int:
+ if self.h:
+ r = heapq.heappop(self.h)
+ self.s.remove(r)
+ return r
+ return -1
+
+ def addBack(self, num: int) -> None:
+ if num in self.s:
+ return
+ self.s.add(num)
+ heapq.heappush(self.h, num)
+
+```
+
+
+
diff --git "a/_posts/Algorithms/leetcode/2022-08-18-2375. \346\240\271\346\215\256\346\250\241\345\274\217\344\270\262\346\236\204\351\200\240\346\234\200\345\260\217\346\225\260\345\255\227.md" "b/_posts/Algorithms/leetcode/2022-08-18-2375. \346\240\271\346\215\256\346\250\241\345\274\217\344\270\262\346\236\204\351\200\240\346\234\200\345\260\217\346\225\260\345\255\227.md"
new file mode 100644
index 0000000000..d918b09610
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-08-18-2375. \346\240\271\346\215\256\346\250\241\345\274\217\344\270\262\346\236\204\351\200\240\346\234\200\345\260\217\346\225\260\345\255\227.md"
@@ -0,0 +1,79 @@
+---
+layout: post
+category: leetcode
+title: 2375. 根据模式串构造最小数字
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/construct-smallest-number-from-di-string/)
+
+给你下标从 **0** 开始、长度为 `n` 的字符串 `pattern` ,它包含两种字符,`'I'` 表示 **上升** ,`'D'` 表示 **下降** 。
+
+你需要构造一个下标从 **0** 开始长度为 `n + 1` 的字符串,且它要满足以下条件:
+
+- `num` 包含数字 `'1'` 到 `'9'` ,其中每个数字 **至多** 使用一次。
+- 如果 `pattern[i] == 'I'` ,那么 `num[i] < num[i + 1]` 。
+- 如果 `pattern[i] == 'D'` ,那么 `num[i] > num[i + 1]` 。
+
+请你返回满足上述条件字典序 **最小** 的字符串 `num`。
+
+
+
+**示例 1:**
+
+```
+输入:pattern = "IIIDIDDD"
+输出:"123549876"
+解释:
+下标 0 ,1 ,2 和 4 处,我们需要使 num[i] < num[i+1] 。
+下标 3 ,5 ,6 和 7 处,我们需要使 num[i] > num[i+1] 。
+一些可能的 num 的值为 "245639871" ,"135749862" 和 "123849765" 。
+"123549876" 是满足条件最小的数字。
+注意,"123414321" 不是可行解因为数字 '1' 使用次数超过 1 次。
+```
+
+**示例 2:**
+
+```
+输入:pattern = "DDD"
+输出:"4321"
+解释:
+一些可能的 num 的值为 "9876" ,"7321" 和 "8742" 。
+"4321" 是满足条件最小的数字。
+```
+
+
+
+**提示:**
+
+- `1 <= pattern.length <= 8`
+- `pattern` 只包含字符 `'I'` 和 `'D'` 。
+
+
+## solution
+
+```python
+'''
+贪心: 数字其实就是123456789,遇到连续的D,就将连续的数字reverse, 其实就是找连续的I,连续的D,然后分段。
+'''
+class Solution:
+ def smallestNumber(self, pattern: str) -> str:
+ n = len(pattern)
+ i = 0
+ ans = []
+ while i < n:
+ if i and pattern[i] == "I":
+ i += 1
+ while i < n and pattern[i] == "I":
+ i += 1
+ ans.append(i)
+ i0 = i
+ while i < n and pattern[i] == "D":
+ i += 1
+ for x in range(i + 1, i0, -1):
+ ans.append(x)
+ return "".join(map(str, ans))
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-08-27-2386. \346\211\276\345\207\272\346\225\260\347\273\204\347\232\204\347\254\254 K \345\244\247\345\222\214.md" "b/_posts/Algorithms/leetcode/2022-08-27-2386. \346\211\276\345\207\272\346\225\260\347\273\204\347\232\204\347\254\254 K \345\244\247\345\222\214.md"
new file mode 100644
index 0000000000..3184ef4b94
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-08-27-2386. \346\211\276\345\207\272\346\225\260\347\273\204\347\232\204\347\254\254 K \345\244\247\345\222\214.md"
@@ -0,0 +1,136 @@
+---
+layout: post
+category: leetcode
+title: 2386. 找出数组的第 K 大和
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/find-the-k-sum-of-an-array/)
+
+给你一个整数数组 `nums` 和一个 **正** 整数 `k` 。你可以选择数组的任一 **子序列** 并且对其全部元素求和。
+
+数组的 **第 k 大和** 定义为:可以获得的第 `k` 个 **最大** 子序列和(子序列和允许出现重复)
+
+返回数组的 **第 k 大和** 。
+
+子序列是一个可以由其他数组删除某些或不删除元素排生而来的数组,且派生过程不改变剩余元素的顺序。
+
+**注意:**空子序列的和视作 `0` 。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [2,4,-2], k = 5
+输出:2
+解释:所有可能获得的子序列和列出如下,按递减顺序排列:
+- 6、4、4、2、2、0、0、-2
+数组的第 5 大和是 2 。
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,-2,3,4,-10,12], k = 16
+输出:10
+解释:数组的第 16 大和是 10 。
+```
+
+
+
+**提示:**
+
+- `n == nums.length`
+- `1 <= n <= 105`
+- `-109 <= nums[i] <= 109`
+- `1 <= k <= min(2000, 2n)`
+
+## solution
+
+[参考](https://leetcode.cn/problems/find-the-k-sum-of-an-array/solution/zhuan-huan-dui-by-endlesscheng-8yiq/)
+
+要记住
+
+- 数组有序后,可以用堆动态生成子序列的和,按递增顺序,每取一个后便加下一个,同时当前也可减掉。
+- 回溯只要控制深度复杂度也可观,可用于二分等
+
+
+
+优先队列做法
+
+```python
+
+class Solution:
+ def kSum(self, nums: List[int], k: int) -> int:
+ s = 0
+ for i, x in enumerate(nums):
+ if x >= 0:
+ s += x
+ else:
+ nums[i] = -x
+ import heapq
+ h = [(-s, 0)]
+ nums.sort()
+ for _ in range(k - 1):
+ l, i = heapq.heappop(h)
+ if i < len(nums):
+ heapq.heappush(h, (l + nums[i], i + 1))
+ if i:
+ heapq.heappush(h, (l + nums[i] - nums[i - 1], i + 1))
+ return - h[0][0]
+```
+
+
+
+二分做法
+
+```python
+class BinarySearch:
+ # If you wanna binary search big integer, plz set data range, which can be used as same as big integer low and high
+ # find the first index that value >= val
+ def bisect_left(data, val, key=None):
+ l, r = 0, len(data) - 1
+ if key is None:
+ key = lambda x: data[mid]
+ while l <= r:
+ mid = (l + r) // 2
+ if key(mid) >= val:
+ r = mid - 1
+ else:
+ l = mid + 1
+ return l
+class Solution:
+ def kSum(self, nums: List[int], k: int) -> int:
+ s = 0
+ for i, x in enumerate(nums):
+ if x >= 0:
+ s += x
+ else:
+ nums[i] = -x
+ total = sum(nums)
+ nums.sort()
+
+ # 不超过limit的子序列数量
+ def count(limit):
+ cnt = 0
+
+ # 算i之后的子序列数量,不包括空序列
+ def f(cur, i):
+ nonlocal cnt
+ if cnt >= k - 1 or i >= len(nums) or cur + nums[i] > limit:
+ return
+ cnt += 1
+ f(cur + nums[i], i + 1)
+ f(cur, i + 1)
+
+ f(0, 0)
+ return cnt
+
+ j = BinarySearch.bisect_left(range(total), k - 1, key=count)
+
+ return s - j
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-09-2430. \345\257\271\345\255\227\346\257\215\344\270\262\345\217\257\346\211\247\350\241\214\347\232\204\346\234\200\345\244\247\345\210\240\351\231\244\346\225\260.md" "b/_posts/Algorithms/leetcode/2022-10-09-2430. \345\257\271\345\255\227\346\257\215\344\270\262\345\217\257\346\211\247\350\241\214\347\232\204\346\234\200\345\244\247\345\210\240\351\231\244\346\225\260.md"
new file mode 100644
index 0000000000..c3ee467c5d
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-09-2430. \345\257\271\345\255\227\346\257\215\344\270\262\345\217\257\346\211\247\350\241\214\347\232\204\346\234\200\345\244\247\345\210\240\351\231\244\346\225\260.md"
@@ -0,0 +1,131 @@
+---
+layout: post
+category: leetcode
+title: 2430. 对字母串可执行的最大删除数
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/maximum-deletions-on-a-string/)
+
+给你一个仅由小写英文字母组成的字符串 `s` 。在一步操作中,你可以:
+
+- 删除 **整个字符串** `s` ,或者
+- 对于满足 `1 <= i <= s.length / 2` 的任意 `i` ,如果 `s` 中的 **前** `i` 个字母和接下来的 `i` 个字母 **相等** ,删除 **前** `i` 个字母。
+
+例如,如果 `s = "ababc"` ,那么在一步操作中,你可以删除 `s` 的前两个字母得到 `"abc"` ,因为 `s` 的前两个字母和接下来的两个字母都等于 `"ab"` 。
+
+返回删除 `s` 所需的最大操作数。
+
+
+
+**示例 1:**
+
+```
+输入:s = "abcabcdabc"
+输出:2
+解释:
+- 删除前 3 个字母("abc"),因为它们和接下来 3 个字母相等。现在,s = "abcdabc"。
+- 删除全部字母。
+一共用了 2 步操作,所以返回 2 。可以证明 2 是所需的最大操作数。
+注意,在第二步操作中无法再次删除 "abc" ,因为 "abc" 的下一次出现并不是位于接下来的 3 个字母。
+```
+
+**示例 2:**
+
+```
+输入:s = "aaabaab"
+输出:4
+解释:
+- 删除第一个字母("a"),因为它和接下来的字母相等。现在,s = "aabaab"。
+- 删除前 3 个字母("aab"),因为它们和接下来 3 个字母相等。现在,s = "aab"。
+- 删除第一个字母("a"),因为它和接下来的字母相等。现在,s = "ab"。
+- 删除全部字母。
+一共用了 4 步操作,所以返回 4 。可以证明 4 是所需的最大操作数。
+```
+
+**示例 3:**
+
+```
+输入:s = "aaaaa"
+输出:5
+解释:在每一步操作中,都可以仅删除 s 的第一个字母。
+```
+
+
+
+**提示:**
+
+- `1 <= s.length <= 4000`
+- `s` 仅由小写英文字母组成
+
+## solution
+
+[参考](https://leetcode.cn/problems/maximum-deletions-on-a-string/solution/xian-xing-dppythonjavacgo-by-endlesschen-gpx9/) 不加特例判断会超时,因此使用hash string更优
+
+```python
+class Solution:
+ def deleteString(self, s: str) -> int:
+ n = len(s)
+ if len(set(s)) == 1: return n # 特判全部相同的情况
+ lcp = [[0] * (n + 1) for _ in range(n + 1)] # lcp[i][j] 表示 s[i:] 和 s[j:] 的最长公共前缀
+ for i in range(n - 1, -1, -1):
+ for j in range(n - 1, i, -1):
+ if s[i] == s[j]:
+ lcp[i][j] = lcp[i + 1][j + 1] + 1
+ f = [0] * n
+ for i in range(n - 1, -1, -1):
+ for j in range(1, (n - i) // 2 + 1):
+ if lcp[i][i + j] >= j: # 说明 s[i:i+j] == s[i+j:i+2*j]
+ f[i] = max(f[i], f[i + j])
+ f[i] += 1
+ return f[0]
+```
+
+hash string也会超时
+
+
+
+```python
+class StringHash:
+ def __init__(self, s=""):
+ self.MOD = 998244353
+ self.BASE = 131
+ # 计算前缀哈希值
+ n = len(s)
+ P = [0] * (n + 1)
+ P[0] = 1
+ for i in range(1, n + 1, 1):
+ P[i] = P[i - 1] * self.BASE % self.MOD
+ H = [0] * (n + 1)
+ for i in range(1, n + 1, 1):
+ H[i] = (H[i - 1] * self.BASE + ord(s[i - 1])) % self.MOD
+ self.H = H
+ self.P = P
+
+ '''
+ s的[l,r]区间的hash值,闭区间, l从1开始
+ '''
+
+ def get_hash(self, l=0, r=0):
+ l, r = l + 1, r + 1
+ return (self.H[r] - self.H[l - 1] * self.P[r - l + 1] % self.MOD + self.MOD) % self.MOD
+
+
+class Solution:
+ def deleteString(self, s: str) -> int:
+ n = len(s)
+ dp = [1] * n
+ hash = StringHash(s)
+ for i in range(n - 1, -1, -1):
+ for j in range(i + 1, n):
+ if (j - i + 1) % 2 == 0:
+ mid = (i + j) // 2
+ if hash.get_hash(i, mid) == hash.get_hash(mid+1, j):
+ # print(i, j, mid)
+ dp[i] = max(dp[i], dp[mid+1]+1)
+ # print(dp[i])
+ # print(dp)
+ return dp[0]
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-09-6202. \344\275\277\347\224\250\346\234\272\345\231\250\344\272\272\346\211\223\345\215\260\345\255\227\345\205\270\345\272\217\346\234\200\345\260\217\347\232\204\345\255\227\347\254\246\344\270\262.md" "b/_posts/Algorithms/leetcode/2022-10-09-6202. \344\275\277\347\224\250\346\234\272\345\231\250\344\272\272\346\211\223\345\215\260\345\255\227\345\205\270\345\272\217\346\234\200\345\260\217\347\232\204\345\255\227\347\254\246\344\270\262.md"
new file mode 100644
index 0000000000..949501f164
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-09-6202. \344\275\277\347\224\250\346\234\272\345\231\250\344\272\272\346\211\223\345\215\260\345\255\227\345\205\270\345\272\217\346\234\200\345\260\217\347\232\204\345\255\227\347\254\246\344\270\262.md"
@@ -0,0 +1,119 @@
+---
+layout: post
+category: leetcode
+title: 6202. 使用机器人打印字典序最小的字符串
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/using-a-robot-to-print-the-lexicographically-smallest-string/)
+
+给你一个字符串 `s` 和一个机器人,机器人当前有一个空字符串 `t` 。执行以下操作之一,直到 `s` 和 `t` **都变成空字符串:**
+
+- 删除字符串 `s` 的 **第一个** 字符,并将该字符给机器人。机器人把这个字符添加到 `t` 的尾部。
+- 删除字符串 `t` 的 **最后一个** 字符,并将该字符给机器人。机器人将该字符写到纸上。
+
+请你返回纸上能写出的字典序最小的字符串。
+
+
+
+**示例 1:**
+
+```
+输入:s = "zza"
+输出:"azz"
+解释:用 p 表示写出来的字符串。
+一开始,p="" ,s="zza" ,t="" 。
+执行第一个操作三次,得到 p="" ,s="" ,t="zza" 。
+执行第二个操作三次,得到 p="azz" ,s="" ,t="" 。
+```
+
+**示例 2:**
+
+```
+输入:s = "bac"
+输出:"abc"
+解释:用 p 表示写出来的字符串。
+执行第一个操作两次,得到 p="" ,s="c" ,t="ba" 。
+执行第二个操作两次,得到 p="ab" ,s="c" ,t="" 。
+执行第一个操作,得到 p="ab" ,s="" ,t="c" 。
+执行第二个操作,得到 p="abc" ,s="" ,t="" 。
+```
+
+**示例 3:**
+
+```
+输入:s = "bdda"
+输出:"addb"
+解释:用 p 表示写出来的字符串。
+一开始,p="" ,s="bdda" ,t="" 。
+执行第一个操作四次,得到 p="" ,s="" ,t="bdda" 。
+执行第二个操作四次,得到 p="addb" ,s="" ,t="" 。
+```
+
+
+
+**提示:**
+
+- `1 <= s.length <= 105`
+- `s` 只包含小写英文字母。
+
+## solution
+
+本题是经典贪心:求出栈序列的最小字典序。
+
+我们首先将题目描述进行转化:有一个初始为空的栈,给定字符的入栈顺序,求字典序最小的出栈序列。
+
+```python
+class Solution:
+ def robotWithString(self, s: str) -> str:
+ stack = []
+ import collections
+ counter = collections.Counter(s)
+ ans = []
+ '''
+ 栈模拟, 栈顶是最小的就弹出,否则就继续入栈等有更小的弹出
+ '''
+ for c in s:
+ # 判断后面是否还有比它小的
+ counter[c] -= 1
+ minc = c
+ for x in string.ascii_lowercase:
+ if counter[x] > 0:
+ minc = x
+ break
+ # print(c, minc)
+ stack.append(c)
+ while stack and stack[-1] <= minc:
+ ans.append(stack.pop())
+ return "".join(ans + stack[::-1])
+
+
+class Solution:
+ def robotWithString(self, s: str) -> str:
+ stack = []
+ ans = []
+ minc = [None] * (len(s) + 1)
+ t = 'z'
+ for i in range(len(s) - 1, -1, -1):
+ t = min(t, s[i])
+ minc[i] = t
+ minc[-1] = chr(ord('z') + 1)
+ '''
+ 栈模拟, 栈顶是最小的就弹出,否则就继续入栈等有更小的弹出
+ '''
+ for i, c in enumerate(s):
+ # 判断后面是否还有比它小的
+ stack.append(c)
+ while stack and stack[-1] <= minc[i + 1]:
+ ans.append(stack.pop())
+ return "".join(ans + stack)
+
+
+if __name__ == '__main__':
+ f = Solution().robotWithString
+ print("actual:", f("caba"), "should:", None)
+ print("actual:", f("bac"), "should:", None)
+ print("actual:", f("bdda"), "should:", None)
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-16-6207. \347\273\237\350\256\241\345\256\232\347\225\214\345\255\220\346\225\260\347\273\204\347\232\204\346\225\260\347\233\256.md" "b/_posts/Algorithms/leetcode/2022-10-16-6207. \347\273\237\350\256\241\345\256\232\347\225\214\345\255\220\346\225\260\347\273\204\347\232\204\346\225\260\347\233\256.md"
new file mode 100644
index 0000000000..3b8f7268b5
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-16-6207. \347\273\237\350\256\241\345\256\232\347\225\214\345\255\220\346\225\260\347\273\204\347\232\204\346\225\260\347\233\256.md"
@@ -0,0 +1,71 @@
+---
+layout: post
+category: leetcode
+title: 6207. 统计定界子数组的数目
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/count-subarrays-with-fixed-bounds/)
+
+给你一个整数数组 `nums` 和两个整数 `minK` 以及 `maxK` 。
+
+`nums` 的定界子数组是满足下述条件的一个子数组:
+
+- 子数组中的 **最小值** 等于 `minK` 。
+- 子数组中的 **最大值** 等于 `maxK` 。
+
+返回定界子数组的数目。
+
+子数组是数组中的一个连续部分。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [1,3,5,2,7,5], minK = 1, maxK = 5
+输出:2
+解释:定界子数组是 [1,3,5] 和 [1,3,5,2] 。
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,1,1,1], minK = 1, maxK = 1
+输出:10
+解释:nums 的每个子数组都是一个定界子数组。共有 10 个子数组。
+```
+
+
+
+**提示:**
+
+- `2 <= nums.length <= 105`
+- `1 <= nums[i], minK, maxK <= 106`
+
+## solution
+
+双指针
+
+```python
+class Solution:
+ def countSubarrays(self, nums: List[int], minK: int, maxK: int) -> int:
+ left = -1
+ minI, maxI = -1, -1
+ ans = 0
+ for i, v in enumerate(nums):
+ if v < minK or v > maxK:
+ # 清空窗口
+ left = i
+ minI = maxI = -1
+ continue
+ if v == minK:
+ minI = i
+ if v == maxK:
+ maxI = i
+ if maxI != -1 and minI != -1:
+ ans += min(minI, maxI) - left
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-16-6211. \345\210\233\345\273\272\344\273\267\345\200\274\347\233\270\345\220\214\347\232\204\350\277\236\351\200\232\345\235\227.md" "b/_posts/Algorithms/leetcode/2022-10-16-6211. \345\210\233\345\273\272\344\273\267\345\200\274\347\233\270\345\220\214\347\232\204\350\277\236\351\200\232\345\235\227.md"
new file mode 100644
index 0000000000..e733848d31
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-16-6211. \345\210\233\345\273\272\344\273\267\345\200\274\347\233\270\345\220\214\347\232\204\350\277\236\351\200\232\345\235\227.md"
@@ -0,0 +1,90 @@
+---
+layout: post
+category: leetcode
+title: 6211. 创建价值相同的连通块
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/create-components-with-same-value/)
+
+有一棵 `n` 个节点的无向树,节点编号为 `0` 到 `n - 1` 。
+
+给你一个长度为 `n` 下标从 **0** 开始的整数数组 `nums` ,其中 `nums[i]` 表示第 `i` 个节点的值。同时给你一个长度为 `n - 1` 的二维整数数组 `edges` ,其中 `edges[i] = [ai, bi]` 表示节点 `ai` 与 `bi` 之间有一条边。
+
+你可以 **删除** 一些边,将这棵树分成几个连通块。一个连通块的 **价值** 定义为这个连通块中 **所有** 节点 `i` 对应的 `nums[i]` 之和。
+
+你需要删除一些边,删除后得到的各个连通块的价值都相等。请返回你可以删除的边数 **最多** 为多少。
+
+
+
+**示例 1:**
+
+
+
+```
+输入:nums = [6,2,2,2,6], edges = [[0,1],[1,2],[1,3],[3,4]]
+输出:2
+解释:上图展示了我们可以删除边 [0,1] 和 [3,4] 。得到的连通块为 [0] ,[1,2,3] 和 [4] 。每个连通块的价值都为 6 。可以证明没有别的更好的删除方案存在了,所以答案为 2 。
+```
+
+**示例 2:**
+
+```
+输入:nums = [2], edges = []
+输出:0
+解释:没有任何边可以删除。
+```
+
+
+
+**提示:**
+
+- `1 <= n <= 2 * 104`
+- `nums.length == n`
+- `1 <= nums[i] <= 50`
+- `edges.length == n - 1`
+- `edges[i].length == 2`
+- `0 <= edges[i][0], edges[i][1] <= n - 1`
+- `edges` 表示一棵合法的树。
+
+## solution
+
+[参考](https://leetcode.cn/problems/create-components-with-same-value/solution/by-endlesscheng-u03q/)
+
+```python
+class Solution:
+ def componentValue(self, nums: List[int], edges: List[List[int]]) -> int:
+ n = len(nums)
+ import collections
+ graph = collections.defaultdict(list)
+ for u, v in edges:
+ graph[u].append(v)
+ graph[v].append(u)
+ total = sum(nums)
+ target = 0
+
+ # return the sum of subtree mod target
+ def dfs(u, fa=-1):
+ cur = nums[u]
+ for v in graph[u]:
+ if v == fa: continue
+ t = dfs(v, u)
+ if t == -1:
+ return -1
+ cur += t
+ if cur == target:
+ return 0
+ elif cur > target:
+ return -1
+ return cur
+
+ for k in range(min(n, total // max(nums)), 1, -1):
+ if total % k == 0:
+ target = total // k
+ if dfs(0, -1) == 0:
+ return k - 1
+ return 0
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-23-407. \346\216\245\351\233\250\346\260\264 II.md" "b/_posts/Algorithms/leetcode/2022-10-23-407. \346\216\245\351\233\250\346\260\264 II.md"
new file mode 100644
index 0000000000..74c45a99b1
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-23-407. \346\216\245\351\233\250\346\260\264 II.md"
@@ -0,0 +1,83 @@
+---
+layout: post
+category: leetcode
+title: 407. 接雨水 II
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/trapping-rain-water-ii/)
+
+给你一个 `m x n` 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。
+
+
+
+**示例 1:**
+
+
+
+```
+输入: heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
+输出: 4
+解释: 下雨后,雨水将会被上图蓝色的方块中。总的接雨水量为1+2+1=4。
+```
+
+**示例 2:**
+
+
+
+```
+输入: heightMap = [[3,3,3,3,3],[3,2,2,2,3],[3,2,1,2,3],[3,2,2,2,3],[3,3,3,3,3]]
+输出: 10
+```
+
+
+
+**提示:**
+
+- `m == heightMap.length`
+- `n == heightMap[i].length`
+- `1 <= m, n <= 200`
+- `0 <= heightMap[i][j] <= 2 * 104`
+
+
+
+## solution
+
+[参考](https://leetcode.cn/problems/trapping-rain-water-ii/solution/gong-shui-san-xie-jing-dian-dijkstra-yun-13ik/)
+
+Dijkstra. 从外向内扩展,路径定义为water高度。
+
+```python
+class Directions:
+ dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)]
+ diagonal_dirs = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
+ all_dirs = dirs + diagonal_dirs
+
+class Solution:
+ def trapRainWater(self, heightMap: List[List[int]]) -> int:
+ m, n = len(heightMap), len(heightMap[0])
+ h = []
+ import heapq
+ dist = {}
+ for i in range(m):
+ heapq.heappush(h, (heightMap[i][0], i, 0))
+ heapq.heappush(h, (heightMap[i][n - 1], i, n - 1))
+ for j in range(1, n - 1):
+ heapq.heappush(h, (heightMap[0][j], 0, j))
+ heapq.heappush(h, (heightMap[m - 1][j], m - 1, j))
+ ans = 0
+ while h:
+ ph, x, y = heapq.heappop(h)
+ if (x, y) in dist: continue
+ dist[(x, y)] = max(heightMap[x][y], ph)
+ if ph > heightMap[x][y]:
+ ans += ph - heightMap[x][y]
+ for dx, dy in Directions.dirs:
+ nx, ny = x + dx, y + dy
+ if 0 <= nx < m and 0 <= ny < n and (nx, ny) not in dist:
+ heapq.heappush(h, (dist[(x, y)], nx, ny))
+ # print(dist)
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-23-6216. \344\275\277\346\225\260\347\273\204\347\233\270\347\255\211\347\232\204\346\234\200\345\260\217\345\274\200\351\224\200.md" "b/_posts/Algorithms/leetcode/2022-10-23-6216. \344\275\277\346\225\260\347\273\204\347\233\270\347\255\211\347\232\204\346\234\200\345\260\217\345\274\200\351\224\200.md"
new file mode 100644
index 0000000000..140d0c7964
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-23-6216. \344\275\277\346\225\260\347\273\204\347\233\270\347\255\211\347\232\204\346\234\200\345\260\217\345\274\200\351\224\200.md"
@@ -0,0 +1,75 @@
+---
+layout: post
+category: leetcode
+title: 6216. 使数组相等的最小开销
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimum-cost-to-make-array-equal/)
+
+给你两个下标从 **0** 开始的数组 `nums` 和 `cost` ,分别包含 `n` 个 **正** 整数。
+
+你可以执行下面操作 **任意** 次:
+
+- 将 `nums` 中 **任意** 元素增加或者减小 `1` 。
+
+对第 `i` 个元素执行一次操作的开销是 `cost[i]` 。
+
+请你返回使 `nums` 中所有元素 **相等** 的 **最少** 总开销。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [1,3,5,2], cost = [2,3,1,14]
+输出:8
+解释:我们可以执行以下操作使所有元素变为 2 :
+- 增加第 0 个元素 1 次,开销为 2 。
+- 减小第 1 个元素 1 次,开销为 3 。
+- 减小第 2 个元素 3 次,开销为 1 + 1 + 1 = 3 。
+总开销为 2 + 3 + 3 = 8 。
+这是最小开销。
+```
+
+**示例 2:**
+
+```
+输入:nums = [2,2,2,2,2], cost = [4,2,8,1,3]
+输出:0
+解释:数组中所有元素已经全部相等,不需要执行额外的操作。
+```
+
+
+
+**提示:**
+
+- `n == nums.length == cost.length`
+- `1 <= n <= 105`
+- `1 <= nums[i], cost[i] <= 106`
+
+## solution
+
+[参考](https://leetcode.cn/circle/discuss/uO4WuN/)
+
+
+
+```python
+class Solution:
+ def minCost(self, nums: List[int], cost: List[int]) -> int:
+ d = list(zip(nums, cost))
+ d = sorted(d)
+ mid = None
+ count = 0
+ total = sum(cost)
+ for a, b in d:
+ count += b
+ if count >= total // 2:
+ mid = a
+ break
+ return sum(abs(a - mid) * c for a, c in d)
+
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-23-6217. \344\275\277\346\225\260\347\273\204\347\233\270\344\274\274\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md" "b/_posts/Algorithms/leetcode/2022-10-23-6217. \344\275\277\346\225\260\347\273\204\347\233\270\344\274\274\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md"
new file mode 100644
index 0000000000..1370155333
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-23-6217. \344\275\277\346\225\260\347\273\204\347\233\270\344\274\274\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md"
@@ -0,0 +1,103 @@
+---
+layout: post
+category: leetcode
+title: 6217. 使数组相似的最少操作次数
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimum-number-of-operations-to-make-arrays-similar/)
+
+给你两个正整数数组 `nums` 和 `target` ,两个数组长度相等。
+
+在一次操作中,你可以选择两个 **不同** 的下标 `i` 和 `j` ,其中 `0 <= i, j < nums.length` ,并且:
+
+- 令 `nums[i] = nums[i] + 2` 且
+- 令 `nums[j] = nums[j] - 2` 。
+
+如果两个数组中每个元素出现的频率相等,我们称两个数组是 **相似** 的。
+
+请你返回将 `nums` 变得与 `target` 相似的最少操作次数。测试数据保证 `nums` 一定能变得与 `target` 相似。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [8,12,6], target = [2,14,10]
+输出:2
+解释:可以用两步操作将 nums 变得与 target 相似:
+- 选择 i = 0 和 j = 2 ,nums = [10,12,4] 。
+- 选择 i = 1 和 j = 2 ,nums = [10,14,2] 。
+2 次操作是最少需要的操作次数。
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,2,5], target = [4,1,3]
+输出:1
+解释:一步操作可以使 nums 变得与 target 相似:
+- 选择 i = 1 和 j = 2 ,nums = [1,4,3] 。
+```
+
+**示例 3:**
+
+```
+输入:nums = [1,1,1,1,1], target = [1,1,1,1,1]
+输出:0
+解释:数组 nums 已经与 target 相似。
+```
+
+
+
+**提示:**
+
+- `n == nums.length == target.length`
+- `1 <= n <= 105`
+- `1 <= nums[i], target[i] <= 106`
+- `nums` 一定可以变得与 `target` 相似。
+
+## solution
+
+[参考](https://leetcode.cn/problems/minimum-number-of-operations-to-make-arrays-similar/solution/by-endlesscheng-lusx/)
+
+
+
+```python
+class Solution:
+ def makeSimilar(self, nums: List[int], target: List[int]) -> int:
+ nums = sorted(nums, key=lambda x: (x % 2, x))
+ target = sorted(target, key=lambda x: (x % 2, x))
+ ans = 0
+ for i in range(len(nums)):
+ ans += abs(nums[i] - target[i])
+ return ans // 4
+
+
+class Solution:
+ def makeSimilar(self, nums: List[int], target: List[int]) -> int:
+ nums = sorted(nums)
+ target = sorted(target)
+ a = []
+ b = []
+ for v in nums:
+ if v % 2 == 1:
+ a.append(v)
+ else:
+ b.append(v)
+ c = []
+ d = []
+ for v in target:
+ if v % 2 == 1:
+ c.append(v)
+ else:
+ d.append(v)
+ ans = 0
+ for i in range(len(a)):
+ ans += abs(a[i] - c[i]) // 2
+ for i in range(len(b)):
+ ans += abs(b[i] - d[i]) // 2
+ return ans // 2
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-24-915. \345\210\206\345\211\262\346\225\260\347\273\204.md" "b/_posts/Algorithms/leetcode/2022-10-24-915. \345\210\206\345\211\262\346\225\260\347\273\204.md"
new file mode 100644
index 0000000000..e6de0d5396
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-24-915. \345\210\206\345\211\262\346\225\260\347\273\204.md"
@@ -0,0 +1,66 @@
+---
+layout: post
+category: leetcode
+title: 915. 分割数组
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/partition-array-into-disjoint-intervals/)
+
+给定一个数组 `nums` ,将其划分为两个连续子数组 `left` 和 `right`, 使得:
+
+- `left` 中的每个元素都小于或等于 `right` 中的每个元素。
+- `left` 和 `right` 都是非空的。
+- `left` 的长度要尽可能小。
+
+*在完成这样的分组后返回 `left` 的 **长度*** 。
+
+用例可以保证存在这样的划分方法。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [5,0,3,8,6]
+输出:3
+解释:left = [5,0,3],right = [8,6]
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,1,1,0,6,12]
+输出:4
+解释:left = [1,1,1,0],right = [6,12]
+```
+
+
+
+**提示:**
+
+- `2 <= nums.length <= 105`
+- `0 <= nums[i] <= 106`
+- 可以保证至少有一种方法能够按题目所描述的那样对 `nums` 进行划分。
+
+## solution
+
+下面为一次遍历,使用后悔法。
+
+```python
+class Solution:
+ def partitionDisjoint(self, nums: List[int]) -> int:
+ n = len(nums)
+ leftpos = 0
+ leftmax = nums[0]
+ currentmax = nums[0]
+ for i,v in enumerate(nums):
+ currentmax = max(currentmax, v)
+ if v < leftmax:
+ leftpos = i
+ leftmax = currentmax
+ return leftpos + 1
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-10-29-862. \345\222\214\350\207\263\345\260\221\344\270\272 K \347\232\204\346\234\200\347\237\255\345\255\220\346\225\260\347\273\204.md" "b/_posts/Algorithms/leetcode/2022-10-29-862. \345\222\214\350\207\263\345\260\221\344\270\272 K \347\232\204\346\234\200\347\237\255\345\255\220\346\225\260\347\273\204.md"
new file mode 100644
index 0000000000..6b83df161c
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-10-29-862. \345\222\214\350\207\263\345\260\221\344\270\272 K \347\232\204\346\234\200\347\237\255\345\255\220\346\225\260\347\273\204.md"
@@ -0,0 +1,120 @@
+---
+layout: post
+category: leetcode
+title: 862. 和至少为 K 的最短子数组
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/shortest-subarray-with-sum-at-least-k/)
+
+给你一个整数数组 `nums` 和一个整数 `k` ,找出 `nums` 中和至少为 `k` 的 **最短非空子数组** ,并返回该子数组的长度。如果不存在这样的 **子数组** ,返回 `-1` 。
+
+**子数组** 是数组中 **连续** 的一部分。
+
+
+
+
+
+**示例 1:**
+
+```
+输入:nums = [1], k = 1
+输出:1
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,2], k = 4
+输出:-1
+```
+
+**示例 3:**
+
+```
+输入:nums = [2,-1,2], k = 3
+输出:3
+```
+
+
+
+**提示:**
+
+- `1 <= nums.length <= 105`
+- `-105 <= nums[i] <= 105`
+- `1 <= k <= 109`
+
+## solution
+
+单调队列
+
+```python
+'''
+主要是去除无用数据,维护右端点
+可以单调栈二分,也可以单调队列
+参考: https://leetcode.cn/problems/shortest-subarray-with-sum-at-least-k/solution/liang-zhang-tu-miao-dong-dan-diao-dui-li-9fvh/
+'''
+
+class Solution:
+ def shortestSubarray(self, nums: List[int], k: int) -> int:
+ ans = float('inf')
+ n = len(nums)
+ pre = [0]
+ for v in nums:
+ pre.append(pre[-1] + v)
+ import collections
+ q = collections.deque()
+ # 单调队列,j< i, 向右, 如果s[i] - s[j] >= k, j则不会再作为可作为答案的左端点了; 递增队列 对于s[j] >= s[i], 则j也可以舍弃
+ for i, v in enumerate(pre):
+ while q and pre[q[-1]] >= v:
+ q.pop()
+ q.append(i)
+ while q and v - pre[q[0]] >= k:
+ ans = min(ans, i - q[0])
+ q.popleft()
+ return ans if ans != float('inf') else -1
+
+
+```
+
+
+
+```python
+# 单调栈 + 二分
+class BinarySearch:
+ # If you wanna binary search big integer, plz set data range, which can be used as same as big integer low and high
+ # find the first index that value >= val
+ def bisect_left(data, val, l=None, r=None, key=None):
+ if l is None or r is None:
+ l, r = 0, len(data) - 1
+ if key is None:
+ key = lambda x: data[mid]
+ while l <= r:
+ mid = (l + r) // 2
+ if key(mid) >= val:
+ r = mid - 1
+ else:
+ l = mid + 1
+ return l
+
+class Solution:
+ def shortestSubarray(self, nums: List[int], k: int) -> int:
+ ans = float('inf')
+ pre = [0]
+ for v in nums:
+ pre.append(pre[-1] + v)
+ # print(pre)
+ q = []
+ # 单调递增栈, 栈上二分
+ for i, v in enumerate(pre):
+ while q and pre[q[-1]] >= v:
+ q.pop()
+ q.append(i)
+ t = BinarySearch.bisect_left(q, True, key=lambda x: v - pre[q[x]] < k)
+ if t - 1 >= 0:
+ ans = min(ans, i - q[t - 1])
+ return ans if ans != float('inf') else -1
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-11-04-1674. \344\275\277\346\225\260\347\273\204\344\272\222\350\241\245\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md" "b/_posts/Algorithms/leetcode/2022-11-04-1674. \344\275\277\346\225\260\347\273\204\344\272\222\350\241\245\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md"
new file mode 100644
index 0000000000..2d9cf05345
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-11-04-1674. \344\275\277\346\225\260\347\273\204\344\272\222\350\241\245\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md"
@@ -0,0 +1,106 @@
+---
+layout: post
+category: leetcode
+title: 1674. 使数组互补的最少操作次数
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimum-moves-to-make-array-complementary/)
+
+给你一个长度为 **偶数** `n` 的整数数组 `nums` 和一个整数 `limit` 。每一次操作,你可以将 `nums` 中的任何整数替换为 `1` 到 `limit` 之间的另一个整数。
+
+如果对于所有下标 `i`(**下标从** `0` **开始**),`nums[i] + nums[n - 1 - i]` 都等于同一个数,则数组 `nums` 是 **互补的** 。例如,数组 `[1,2,3,4]` 是互补的,因为对于所有下标 `i` ,`nums[i] + nums[n - 1 - i] = 5` 。
+
+返回使数组 **互补** 的 **最少** 操作次数。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [1,2,4,3], limit = 4
+输出:1
+解释:经过 1 次操作,你可以将数组 nums 变成 [1,2,2,3](加粗元素是变更的数字):
+nums[0] + nums[3] = 1 + 3 = 4.
+nums[1] + nums[2] = 2 + 2 = 4.
+nums[2] + nums[1] = 2 + 2 = 4.
+nums[3] + nums[0] = 3 + 1 = 4.
+对于每个 i ,nums[i] + nums[n-1-i] = 4 ,所以 nums 是互补的。
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,2,2,1], limit = 2
+输出:2
+解释:经过 2 次操作,你可以将数组 nums 变成 [2,2,2,2] 。你不能将任何数字变更为 3 ,因为 3 > limit 。
+```
+
+**示例 3:**
+
+```
+输入:nums = [1,2,1,2], limit = 2
+输出:0
+解释:nums 已经是互补的。
+```
+
+
+
+**提示:**
+
+- `n == nums.length`
+- `2 <= n <= 105`
+- `1 <= nums[i] <= limit <= 105`
+- `n` 是偶数。
+
+## solution
+
+假设 `res[x]` 表示的是,`nums[i] + nums[n - 1 - i]` 为 `x` 的时候,需要多少次操作。
+
+我们只需要计算出所有的 `x` 对应的 `res[x]`, 取最小值就好了。
+
+根据题意,`nums[i] + nums[n - 1 - i]` 最小是 `2`,即将两个数都修改为 `1`;最大是 `2 * limit`,即将两个数都修改成 `limit`。
+
+所以,`res[x]` 中 `x` 的取值范围是 `[2, 2 * limit]`。我们用一个 `res[2 * limit + 1]` 的数组就好。
+
+```python
+class Diff:
+ def __init__(self, n):
+ self.n = n
+ self.diff = [0] * (n + 1)
+
+ # 给[l,r] + val
+ def add(self, l, r, val):
+ self.diff[l] += val
+ self.diff[r + 1] -= val
+
+ # 差分数组还原成原数组
+ def restore(self):
+ ans = [0] * self.n
+ ans[0] = self.diff[0]
+ for i in range(1, self.n):
+ ans[i] = ans[i - 1] + self.diff[i]
+ return ans
+
+class Solution:
+ def minMoves(self, nums: List[int], limit: int) -> int:
+ diff = Diff(2 * limit + 1)
+ n = len(nums)
+ for i in range((len(nums) + 1) // 2):
+ a, b = nums[i], nums[n - 1 - i]
+ if a > b:
+ a, b = b, a
+ '''
+ 0: a+b
+ 2: [2, a+1) or (b+limit, 2*limit]
+ 1:
+ '''
+ diff.add(2, a, 2)
+ diff.add(b + limit + 1, 2 * limit, 2)
+ diff.add(a + 1, b + limit, 1)
+ diff.add(a + b, a + b, -1)
+ # print(diff.restore())
+ return min(diff.restore()[2:])
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-11-06-6232. \346\234\200\345\260\217\347\247\273\345\212\250\346\200\273\350\267\235\347\246\273.md" "b/_posts/Algorithms/leetcode/2022-11-06-6232. \346\234\200\345\260\217\347\247\273\345\212\250\346\200\273\350\267\235\347\246\273.md"
new file mode 100644
index 0000000000..ddaa802f80
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-11-06-6232. \346\234\200\345\260\217\347\247\273\345\212\250\346\200\273\350\267\235\347\246\273.md"
@@ -0,0 +1,102 @@
+---
+layout: post
+category: leetcode
+title: 6232. 最小移动总距离
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimum-total-distance-traveled/)
+
+X 轴上有一些机器人和工厂。给你一个整数数组 `robot` ,其中 `robot[i]` 是第 `i` 个机器人的位置。再给你一个二维整数数组 `factory` ,其中 `factory[j] = [positionj, limitj]` ,表示第 `j` 个工厂的位置在 `positionj` ,且第 `j` 个工厂最多可以修理 `limitj` 个机器人。
+
+每个机器人所在的位置 **互不相同** 。每个工厂所在的位置也 **互不相同** 。注意一个机器人可能一开始跟一个工厂在 **相同的位置** 。
+
+所有机器人一开始都是坏的,他们会沿着设定的方向一直移动。设定的方向要么是 X 轴的正方向,要么是 X 轴的负方向。当一个机器人经过一个没达到上限的工厂时,这个工厂会维修这个机器人,且机器人停止移动。
+
+**任何时刻**,你都可以设置 **部分** 机器人的移动方向。你的目标是最小化所有机器人总的移动距离。
+
+请你返回所有机器人移动的最小总距离。测试数据保证所有机器人都可以被维修。
+
+**注意:**
+
+- 所有机器人移动速度相同。
+- 如果两个机器人移动方向相同,它们永远不会碰撞。
+- 如果两个机器人迎面相遇,它们也不会碰撞,它们彼此之间会擦肩而过。
+- 如果一个机器人经过了一个已经达到上限的工厂,机器人会当作工厂不存在,继续移动。
+- 机器人从位置 `x` 到位置 `y` 的移动距离为 `|y - x|` 。
+
+
+
+**示例 1:**
+
+
+
+```
+输入:robot = [0,4,6], factory = [[2,2],[6,2]]
+输出:4
+解释:如上图所示:
+- 第一个机器人从位置 0 沿着正方向移动,在第一个工厂处维修。
+- 第二个机器人从位置 4 沿着负方向移动,在第一个工厂处维修。
+- 第三个机器人在位置 6 被第二个工厂维修,它不需要移动。
+第一个工厂的维修上限是 2 ,它维修了 2 个机器人。
+第二个工厂的维修上限是 2 ,它维修了 1 个机器人。
+总移动距离是 |2 - 0| + |2 - 4| + |6 - 6| = 4 。没有办法得到比 4 更少的总移动距离。
+```
+
+**示例 2:**
+
+
+
+```
+输入:robot = [1,-1], factory = [[-2,1],[2,1]]
+输出:2
+解释:如上图所示:
+- 第一个机器人从位置 1 沿着正方向移动,在第二个工厂处维修。
+- 第二个机器人在位置 -1 沿着负方向移动,在第一个工厂处维修。
+第一个工厂的维修上限是 1 ,它维修了 1 个机器人。
+第二个工厂的维修上限是 1 ,它维修了 1 个机器人。
+总移动距离是 |2 - 1| + |(-2) - (-1)| = 2 。没有办法得到比 2 更少的总移动距离。
+```
+
+
+
+**提示:**
+
+- `1 <= robot.length, factory.length <= 100`
+- `factory[j].length == 2`
+- `-109 <= robot[i], positionj <= 109`
+- `0 <= limitj <= robot.length`
+- 测试数据保证所有机器人都可以被维修。
+
+## solution
+
+动态规划 o(nnm) 一定要往局部思考,想到动态规划才行。
+
+```python
+class Solution:
+ def minimumTotalDistance(self, robot: List[int], factory: List[List[int]]) -> int:
+ robot = sorted(robot)
+ factory = sorted(factory)
+ n = len(robot)
+
+ def f(i, j):
+ if j == 0 and i == 0:
+ return 0
+ if j == 0 or i == 0:
+ return float('inf')
+ res = float('inf')
+ cost = 0
+ for k in range(0, factory[j - 1][1] + 1):
+ if i - k < 0: break
+ if k > 0:
+ cost += abs(factory[j - 1][0] - robot[i - k])
+ # print(i, j, k, cost)
+ res = min(res, f(i - k, j - 1) + cost)
+ # print(i, j, res)
+ return res
+
+ ans = f(n, len(factory))
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-12-04-6256. \345\260\206\350\212\202\347\202\271\345\210\206\346\210\220\345\260\275\345\217\257\350\203\275\345\244\232\347\232\204\347\273\204.md" "b/_posts/Algorithms/leetcode/2022-12-04-6256. \345\260\206\350\212\202\347\202\271\345\210\206\346\210\220\345\260\275\345\217\257\350\203\275\345\244\232\347\232\204\347\273\204.md"
new file mode 100644
index 0000000000..a381b04ca4
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-12-04-6256. \345\260\206\350\212\202\347\202\271\345\210\206\346\210\220\345\260\275\345\217\257\350\203\275\345\244\232\347\232\204\347\273\204.md"
@@ -0,0 +1,160 @@
+---
+layout: post
+category: leetcode
+title: 6256. 将节点分成尽可能多的组
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/divide-nodes-into-the-maximum-number-of-groups/)
+
+给你一个正整数 `n` ,表示一个 **无向** 图中的节点数目,节点编号从 `1` 到 `n` 。
+
+同时给你一个二维整数数组 `edges` ,其中 `edges[i] = [ai, bi]` 表示节点 `ai` 和 `bi` 之间有一条 **双向** 边。注意给定的图可能是不连通的。
+
+请你将图划分为 `m` 个组(编号从 **1** 开始),满足以下要求:
+
+- 图中每个节点都只属于一个组。
+- 图中每条边连接的两个点 `[ai, bi]` ,如果 `ai` 属于编号为 `x` 的组,`bi` 属于编号为 `y` 的组,那么 `|y - x| = 1` 。
+
+请你返回最多可以将节点分为多少个组(也就是最大的 `m` )。如果没办法在给定条件下分组,请你返回 `-1` 。
+
+
+
+**示例 1:**
+
+
+
+```
+输入:n = 6, edges = [[1,2],[1,4],[1,5],[2,6],[2,3],[4,6]]
+输出:4
+解释:如上图所示,
+- 节点 5 在第一个组。
+- 节点 1 在第二个组。
+- 节点 2 和节点 4 在第三个组。
+- 节点 3 和节点 6 在第四个组。
+所有边都满足题目要求。
+如果我们创建第五个组,将第三个组或者第四个组中任何一个节点放到第五个组,至少有一条边连接的两个节点所属的组编号不符合题目要求。
+```
+
+**示例 2:**
+
+```
+输入:n = 3, edges = [[1,2],[2,3],[3,1]]
+输出:-1
+解释:如果我们将节点 1 放入第一个组,节点 2 放入第二个组,节点 3 放入第三个组,前两条边满足题目要求,但第三条边不满足题目要求。
+没有任何符合题目要求的分组方式。
+```
+
+
+
+**提示:**
+
+- `1 <= n <= 500`
+- `1 <= edges.length <= 104`
+- `edges[i].length == 2`
+- `1 <= ai, bi <= n`
+- `ai != bi`
+- 两个点之间至多只有一条边。
+
+## solution
+
+```
+二分图才可以分组 / 也可以通过bfs后,比较和start点距离判断,a<->b, 则dis[a]!=dis[b]才可以分组
+```
+
+```python
+
+class Graph:
+ def bfs(graph, start):
+ '''
+ :param graph: collection.defaultdict(list)
+ :param start: start point
+ :return:
+ '''
+ q = collections.deque()
+ q.append(start)
+ visit = set()
+ visit.add(start)
+ level = 0
+ while len(q):
+ level += 1
+ for _ in range(len(q)):
+ u = q.popleft()
+ for v in graph[u]:
+ if v not in visit:
+ visit.add(v)
+ q.append(v)
+ return visit, level
+ '''
+ 划分连同分量, 返回每个联通分量的点list,可以多个联通分量
+ '''
+ def groups(self, points, graph) -> List[List[int]]:
+ groups = []
+ total_visit = set()
+ for i in points:
+ visit = set()
+ def dfs(u):
+ nonlocal visit
+ visit.add(u)
+ for v in graph[u]:
+ if v not in visit:
+ dfs(v)
+
+ if i not in total_visit:
+ dfs(i)
+ if visit:
+ for l in visit:
+ total_visit.add(l)
+ groups.append(list(visit))
+ return groups
+
+ # 判断是否是二分图,input可以是多个子连通图。graph: 链接表
+ def isBipartite(self, graph) -> bool:
+ ans = True
+ color = collections.defaultdict(int)
+ n = len(graph)
+
+ def dfs(i):
+ nonlocal ans
+ if not ans:
+ return
+ if color[i] == 0:
+ color[i] = 1
+ cur = color[i]
+ for neighbor in graph[i]:
+ if color[neighbor] == cur:
+ ans = False
+ break
+ if color[neighbor] == 0:
+ color[neighbor] = 2 if cur == 1 else 1
+ dfs(neighbor)
+
+ for i in range(n):
+ if color[i] == 0:
+ dfs(i)
+ # print(color)
+ return ans
+
+class Solution:
+ def magnificentSets(self, n: int, edges: List[List[int]]) -> int:
+ graph = collections.defaultdict(list)
+ for u, v in edges:
+ graph[u].append(v)
+ graph[v].append(u)
+ # 二分图才可以分组
+ if not Graph().isBipartite(graph):
+ return -1
+ # 划分联通分量
+ groups = Graph().groups(range(1, n + 1), graph)
+ ans = 0
+ for group in groups:
+ t = 0
+ # 对联通分量的每个节点用bfs求最大长度
+ for i in group:
+ t = max(t, Graph.bfs(graph, i)[1])
+ ans += t
+ return ans
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-12-25-6270. \346\257\217\347\247\215\345\255\227\347\254\246\350\207\263\345\260\221\345\217\226 K \344\270\252.md" "b/_posts/Algorithms/leetcode/2022-12-25-6270. \346\257\217\347\247\215\345\255\227\347\254\246\350\207\263\345\260\221\345\217\226 K \344\270\252.md"
new file mode 100644
index 0000000000..adcaed6940
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-12-25-6270. \346\257\217\347\247\215\345\255\227\347\254\246\350\207\263\345\260\221\345\217\226 K \344\270\252.md"
@@ -0,0 +1,76 @@
+---
+layout: post
+category: leetcode
+title: 6270. 每种字符至少取 K 个
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/take-k-of-each-character-from-left-and-right/)
+
+给你一个由字符 `'a'`、`'b'`、`'c'` 组成的字符串 `s` 和一个非负整数 `k` 。每分钟,你可以选择取走 `s` **最左侧** 还是 **最右侧** 的那个字符。
+
+你必须取走每种字符 **至少** `k` 个,返回需要的 **最少** 分钟数;如果无法取到,则返回 `-1` 。
+
+
+
+**示例 1:**
+
+```
+输入:s = "aabaaaacaabc", k = 2
+输出:8
+解释:
+从 s 的左侧取三个字符,现在共取到两个字符 'a' 、一个字符 'b' 。
+从 s 的右侧取五个字符,现在共取到四个字符 'a' 、两个字符 'b' 和两个字符 'c' 。
+共需要 3 + 5 = 8 分钟。
+可以证明需要的最少分钟数是 8 。
+```
+
+**示例 2:**
+
+```
+输入:s = "a", k = 1
+输出:-1
+解释:无法取到一个字符 'b' 或者 'c',所以返回 -1 。
+```
+
+
+
+**提示:**
+
+- `1 <= s.length <= 105`
+- `s` 仅由字母 `'a'`、`'b'`、`'c'` 组成
+- `0 <= k <= s.length`
+
+## solution
+
+双指针。
+
+```python
+class Solution:
+ def takeCharacters(self, s: str, k: int) -> int:
+ cnt = collections.Counter()
+
+ def check(cnt):
+ for c in "abc":
+ if cnt[c] < k:
+ return False
+ return True
+
+ n = len(s)
+ r = n
+ while not check(cnt):
+ r -= 1
+ if r < 0:
+ return -1
+ cnt[s[r]] += 1
+ ans = n - r
+ for l in range(n):
+ cnt[s[l]] += 1
+ while r < n and cnt[s[r]] > k:
+ cnt[s[r]] -= 1
+ r += 1
+ ans = min(ans, l + 1 + n - r)
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-12-25-6272. \345\245\275\345\210\206\345\214\272\347\232\204\346\225\260\347\233\256.md" "b/_posts/Algorithms/leetcode/2022-12-25-6272. \345\245\275\345\210\206\345\214\272\347\232\204\346\225\260\347\233\256.md"
new file mode 100644
index 0000000000..787337d55e
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-12-25-6272. \345\245\275\345\210\206\345\214\272\347\232\204\346\225\260\347\233\256.md"
@@ -0,0 +1,79 @@
+---
+layout: post
+category: leetcode
+title: 6272. 好分区的数目
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/number-of-great-partitions/)
+
+给你一个正整数数组 `nums` 和一个整数 `k` 。
+
+**分区** 的定义是:将数组划分成两个有序的 **组** ,并满足每个元素 **恰好** 存在于 **某一个** 组中。如果分区中每个组的元素和都大于等于 `k` ,则认为分区是一个好分区。
+
+返回 **不同** 的好分区的数目。由于答案可能很大,请返回对 `109 + 7` **取余** 后的结果。
+
+如果在两个分区中,存在某个元素 `nums[i]` 被分在不同的组中,则认为这两个分区不同。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [1,2,3,4], k = 4
+输出:6
+解释:好分区的情况是 ([1,2,3], [4]), ([1,3], [2,4]), ([1,4], [2,3]), ([2,3], [1,4]), ([2,4], [1,3]) 和 ([4], [1,2,3]) 。
+```
+
+**示例 2:**
+
+```
+输入:nums = [3,3,3], k = 4
+输出:0
+解释:数组中不存在好分区。
+```
+
+**示例 3:**
+
+```
+输入:nums = [6,6], k = 2
+输出:2
+解释:可以将 nums[0] 放入第一个分区或第二个分区中。
+好分区的情况是 ([6], [6]) 和 ([6], [6]) 。
+```
+
+
+
+**提示:**
+
+- `1 <= nums.length, k <= 1000`
+- `1 <= nums[i] <= 109`
+
+## solution
+
+[参考](https://leetcode.cn/problems/number-of-great-partitions/solution/ni-xiang-si-wei-01-bei-bao-fang-an-shu-p-v47x/) 考虑计算**坏分区**的数目,即第一个组或第二个组的元素和小于 k*k* 的方案数。根据对称性,我们只需要计算第一个组的元素和小于 k*k* 的方案数,然后乘 22 即可。
+
+因此原问题转换成从 \textit{nums}*nums* 中选择若干元素,使得元素和小于 k*k* 的方案数,这可以用 **01 背包**求解。
+
+```python
+MOD = int(1e9 + 7)
+INF = int(1e20)
+class Math1:
+ pass
+class Solution:
+ def countPartitions(self, nums: List[int], k: int) -> int:
+ # 统计bad数量,总数减去即可。
+ if sum(nums) < 2*k:return 0
+ n = len(nums)
+ dp = [0 for _ in range(k)]
+ dp[0] = 1
+ for i, v in enumerate(nums):
+ for t in range(k-1, 0, -1):
+ if t >= v:
+ dp[t] += dp[t - v] % MOD
+ bad = sum(dp)
+ return (pow(2, n, MOD) - bad*2 + MOD) % MOD
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-12-25-6276. \347\273\237\350\256\241\345\220\214\344\275\215\345\274\202\346\236\204\345\255\227\347\254\246\344\270\262\346\225\260\347\233\256.md" "b/_posts/Algorithms/leetcode/2022-12-25-6276. \347\273\237\350\256\241\345\220\214\344\275\215\345\274\202\346\236\204\345\255\227\347\254\246\344\270\262\346\225\260\347\233\256.md"
new file mode 100644
index 0000000000..6754ad5df7
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-12-25-6276. \347\273\237\350\256\241\345\220\214\344\275\215\345\274\202\346\236\204\345\255\227\347\254\246\344\270\262\346\225\260\347\233\256.md"
@@ -0,0 +1,125 @@
+---
+layout: post
+category: leetcode
+title: 6276. 统计同位异构字符串数目
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/count-anagrams/)
+
+给你一个字符串 `s` ,它包含一个或者多个单词。单词之间用单个空格 `' '` 隔开。
+
+如果字符串 `t` 中第 `i` 个单词是 `s` 中第 `i` 个单词的一个 **排列** ,那么我们称字符串 `t` 是字符串 `s` 的同位异构字符串。
+
+- 比方说,`"acb dfe"` 是 `"abc def"` 的同位异构字符串,但是 `"def cab"` 和 `"adc bef"` 不是。
+
+请你返回 `s` 的同位异构字符串的数目,由于答案可能很大,请你将它对 `109 + 7` **取余** 后返回。
+
+
+
+**示例 1:**
+
+```
+输入:s = "too hot"
+输出:18
+解释:输入字符串的一些同位异构字符串为 "too hot" ,"oot hot" ,"oto toh" ,"too toh" 以及 "too oht" 。
+```
+
+**示例 2:**
+
+```
+输入:s = "aa"
+输出:1
+解释:输入字符串只有一个同位异构字符串。
+```
+
+
+
+**提示:**
+
+- `1 <= s.length <= 105`
+- `s` 只包含小写英文字母和空格 `' '` 。
+- 相邻单词之间由单个空格隔开。
+
+## solution
+
+方法1: 大数阶乘除法,要用费马小定理。
+
+方法2: 用comb换种思路,原来是阶乘相除,可以通过comb相乘,此时无除法。
+
+```python
+MOD = 10 ** 9 + 7
+class BigIntDivide:
+ def mod_inverse(i):
+ # 调用取模的乘幂运算, pow复杂度是log(exp)即log(MOD)
+ return pow(i, MOD - 2, MOD)
+
+ def divide_mod(a, b):
+ '''
+ 计算(a/b) % MOD, 除法变乘法,前提是b和MOD互为质数
+ '''
+ # 如果有多个b,比如a/b1/b2, 那就可以递归。a*mod_inverse(b1) % mod * mod_inverse(b2) % mod这样
+ return a * BigIntDivide.mod_inverse(b) % MOD
+
+ def divide_mods(a, b=[]):
+ '''
+ 计算a /(b1*b2*b3) % MOD等形式,前提是b和MOD互为质数
+ '''
+ r = a % MOD
+ for i, v in enumerate(b):
+ r *= BigIntDivide.mod_inverse(v)
+ r %= MOD
+ return r
+
+class Math1:
+
+ import functools
+ @functools.lru_cache(None)
+ def factorial_mod_cache(n):
+ if n == 0 or n == 1:
+ return 1
+ return Math1.factorial_mod_cache(n - 1) * n % MOD
+class Solution:
+ def countAnagrams(self, s: str) -> int:
+ d = s.split(' ')
+
+ factorial_mod = Math1.factorial_mod_cache
+
+ def calcu(x):
+ import collections
+ counter = collections.Counter(x)
+ n = len(x)
+ return BigIntDivide.divide_mods(factorial_mod(n), [factorial_mod(v) for v in counter.values()])
+
+ # print(calcu("too"))
+
+ ans = 1
+ for v in d:
+ ans *= calcu(v)
+ ans %= MOD
+ return ans % MOD
+```
+
+
+
+方法2 [参考](https://leetcode.cn/problems/count-anagrams/solution/python3pailiezuh-by-musing-clarkeeae-o2zg/)
+
+
+
+```python
+MOD = 10 ** 9 + 7
+
+
+class Solution:
+ def countAnagrams(self, s: str) -> int:
+ ans = 1
+ for word in s.split():
+ n = len(word)
+ for v in Counter(word).values():
+ ans *= comb(n, v)
+ ans %= MOD
+ n -= v
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2022-12-25-6295. \346\234\200\345\260\217\345\214\226\344\270\244\344\270\252\346\225\260\347\273\204\344\270\255\347\232\204\346\234\200\345\244\247\345\200\274.md" "b/_posts/Algorithms/leetcode/2022-12-25-6295. \346\234\200\345\260\217\345\214\226\344\270\244\344\270\252\346\225\260\347\273\204\344\270\255\347\232\204\346\234\200\345\244\247\345\200\274.md"
new file mode 100644
index 0000000000..2147956263
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2022-12-25-6295. \346\234\200\345\260\217\345\214\226\344\270\244\344\270\252\346\225\260\347\273\204\344\270\255\347\232\204\346\234\200\345\244\247\345\200\274.md"
@@ -0,0 +1,87 @@
+---
+layout: post
+category: leetcode
+title: 6295. 最小化两个数组中的最大值
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimize-the-maximum-of-two-arrays/)
+
+给你两个数组 `arr1` 和 `arr2` ,它们一开始都是空的。你需要往它们中添加正整数,使它们满足以下条件:
+
+- `arr1` 包含 `uniqueCnt1` 个 **互不相同** 的正整数,每个整数都 **不能** 被 `divisor1` **整除** 。
+- `arr2` 包含 `uniqueCnt2` 个 **互不相同** 的正整数,每个整数都 **不能** 被 `divisor2` **整除** 。
+- `arr1` 和 `arr2` 中的元素 **互不相同** 。
+
+给你 `divisor1` ,`divisor2` ,`uniqueCnt1` 和 `uniqueCnt2` ,请你返回两个数组中 **最大元素** 的 **最小值** 。
+
+
+
+**示例 1:**
+
+```
+输入:divisor1 = 2, divisor2 = 7, uniqueCnt1 = 1, uniqueCnt2 = 3
+输出:4
+解释:
+我们可以把前 4 个自然数划分到 arr1 和 arr2 中。
+arr1 = [1] 和 arr2 = [2,3,4] 。
+可以看出两个数组都满足条件。
+最大值是 4 ,所以返回 4 。
+```
+
+**示例 2:**
+
+```
+输入:divisor1 = 3, divisor2 = 5, uniqueCnt1 = 2, uniqueCnt2 = 1
+输出:3
+解释:
+arr1 = [1,2] 和 arr2 = [3] 满足所有条件。
+最大值是 3 ,所以返回 3 。
+```
+
+**示例 3:**
+
+```
+输入:divisor1 = 2, divisor2 = 4, uniqueCnt1 = 8, uniqueCnt2 = 2
+输出:15
+解释:
+最终数组为 arr1 = [1,3,5,7,9,11,13,15] 和 arr2 = [2,6] 。
+上述方案是满足所有条件的最优解。
+```
+
+
+
+**提示:**
+
+- `2 <= divisor1, divisor2 <= 105`
+- `1 <= uniqueCnt1, uniqueCnt2 < 109`
+- `2 <= uniqueCnt1 + uniqueCnt2 <= 109`
+
+## solution
+
+二分最大元素的可行值,得到的下界即为最大值的最小值。
+
+判断过程中分为三类:保证在范围内有充足的数不是第一个数的倍数;不是第二个数的倍数;不为公倍数的数总数不少于总共要取的数。根据这三个条件即得到结果。
+
+```python
+class Math1:
+ def lcm(a, b):
+ import math
+ gcd = math.gcd(a, b)
+ return int(a * b / gcd)
+
+class Solution:
+ def minimizeSet(self, divisor1: int, divisor2: int, uniqueCnt1: int, uniqueCnt2: int) -> int:
+ lcm = Math1.lcm(divisor1, divisor2)
+
+ def can(x):
+ a = x - x // divisor1 # arr1能放的数量
+ b = x - x // divisor2 # arr2能放的数量
+ c = x // lcm # arr1和2都不能放的
+ return (a >= uniqueCnt1) and (b >= uniqueCnt2) and (x - c) >= uniqueCnt1+uniqueCnt2
+ import bisect
+ r = bisect.bisect_left(range(2*uniqueCnt1 +2*uniqueCnt2), True, key=can)
+ return r
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-14-1819. \345\272\217\345\210\227\344\270\255\344\270\215\345\220\214\346\234\200\345\244\247\345\205\254\347\272\246\346\225\260\347\232\204\346\225\260\347\233\256.md" "b/_posts/Algorithms/leetcode/2023-01-14-1819. \345\272\217\345\210\227\344\270\255\344\270\215\345\220\214\346\234\200\345\244\247\345\205\254\347\272\246\346\225\260\347\232\204\346\225\260\347\233\256.md"
new file mode 100644
index 0000000000..7933268bd0
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-14-1819. \345\272\217\345\210\227\344\270\255\344\270\215\345\220\214\346\234\200\345\244\247\345\205\254\347\272\246\346\225\260\347\232\204\346\225\260\347\233\256.md"
@@ -0,0 +1,94 @@
+---
+layout: post
+category: leetcode
+title: 1819. 序列中不同最大公约数的数目
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/number-of-different-subsequences-gcds/)
+
+给你一个由正整数组成的数组 `nums` 。
+
+数字序列的 **最大公约数** 定义为序列中所有整数的共有约数中的最大整数。
+
+- 例如,序列 `[4,6,16]` 的最大公约数是 `2` 。
+
+数组的一个 **子序列** 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。
+
+- 例如,`[2,5,10]` 是 `[1,2,1,**2**,4,1,**5**,**10**]` 的一个子序列。
+
+计算并返回 `nums` 的所有 **非空** 子序列中 **不同** 最大公约数的 **数目** 。
+
+
+
+**示例 1:**
+
+
+
+```
+输入:nums = [6,10,3]
+输出:5
+解释:上图显示了所有的非空子序列与各自的最大公约数。
+不同的最大公约数为 6 、10 、3 、2 和 1 。
+```
+
+**示例 2:**
+
+```
+输入:nums = [5,15,40,5,6]
+输出:7
+```
+
+
+
+**提示:**
+
+- `1 <= nums.length <= 105`
+- `1 <= nums[i] <= 2 * 105`
+
+## solution
+
+
+
+
+
+O(nlogn) 其中遍历每个数的倍数总时间复杂度为o(nlogn) 参考调和级数。 Or this [link](https://leetcode.cn/problems/number-of-different-subsequences-gcds/solution/ji-bai-100mei-ju-gcdxun-huan-you-hua-pyt-get7/)
+
+```python
+MOD = int(1e9 + 7)
+INF = int(1e20)
+
+import sortedcontainers
+import bisect
+import heapq
+class Math1:
+ def gcd_list(self, nums):
+ import math
+ cur = nums[0]
+ for i in range(1, len(nums)):
+ cur = math.gcd(cur, nums[i])
+ return cur
+
+class Solution:
+ def countDifferentSubsequenceGCDs(self, nums: List[int]) -> int:
+ n, mx = len(nums), max(nums)
+ ans = 0
+ has = [False for _ in range(mx+1)]
+ for v in nums:
+ has[v] += 1
+ gcd_list = Math1().gcd_list
+ for i in range(1, mx + 1):
+ x = []
+ for j in range(i, mx + 1, i):
+ if has[j]:
+ x.append(j)
+ if x:
+ # print(i, x)
+ p = gcd_list(x)
+ if p == i:
+ ans += 1
+ return ans
+
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-28-2541. \344\275\277\346\225\260\347\273\204\344\270\255\346\211\200\346\234\211\345\205\203\347\264\240\347\233\270\347\255\211\347\232\204\346\234\200\345\260\217\346\223\215\344\275\234\346\225\260 II.md" "b/_posts/Algorithms/leetcode/2023-01-28-2541. \344\275\277\346\225\260\347\273\204\344\270\255\346\211\200\346\234\211\345\205\203\347\264\240\347\233\270\347\255\211\347\232\204\346\234\200\345\260\217\346\223\215\344\275\234\346\225\260 II.md"
new file mode 100644
index 0000000000..c440f8c3ea
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-28-2541. \344\275\277\346\225\260\347\273\204\344\270\255\346\211\200\346\234\211\345\205\203\347\264\240\347\233\270\347\255\211\347\232\204\346\234\200\345\260\217\346\223\215\344\275\234\346\225\260 II.md"
@@ -0,0 +1,76 @@
+---
+layout: post
+category: leetcode
+title: 2541. 使数组中所有元素相等的最小操作数 II
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimum-operations-to-make-array-equal-ii/)
+
+给你两个整数数组 `nums1` 和 `nums2` ,两个数组长度都是 `n` ,再给你一个整数 `k` 。你可以对数组 `nums1` 进行以下操作:
+
+- 选择两个下标 `i` 和 `j` ,将 `nums1[i]` 增加 `k` ,将 `nums1[j]` 减少 `k` 。换言之,`nums1[i] = nums1[i] + k` 且 `nums1[j] = nums1[j] - k` 。
+
+如果对于所有满足 `0 <= i < n` 都有 `num1[i] == nums2[i]` ,那么我们称 `nums1` **等于** `nums2` 。
+
+请你返回使 `nums1` 等于 `nums2` 的 **最少** 操作数。如果没办法让它们相等,请你返回 `-1` 。
+
+
+
+**示例 1:**
+
+```
+输入:nums1 = [4,3,1,4], nums2 = [1,3,7,1], k = 3
+输出:2
+解释:我们可以通过 2 个操作将 nums1 变成 nums2 。
+第 1 个操作:i = 2 ,j = 0 。操作后得到 nums1 = [1,3,4,4] 。
+第 2 个操作:i = 2 ,j = 3 。操作后得到 nums1 = [1,3,7,1] 。
+无法用更少操作使两个数组相等。
+```
+
+**示例 2:**
+
+```
+输入:nums1 = [3,8,5,2], nums2 = [2,4,1,6], k = 1
+输出:-1
+解释:无法使两个数组相等。
+```
+
+
+
+**提示:**
+
+- `n == nums1.length == nums2.length`
+- `2 <= n <= 105`
+- `0 <= nums1[i], nums2[j] <= 109`
+- `0 <= k <= 105`
+
+## solution
+
+任选两个元素,一个+k,一个-k,问最少操作次数,使这个数组和另一个数组相同。累计操作次数即可,注意k为0的情况
+
+```python
+
+class Solution:
+ def minOperations(self, nums1: List[int], nums2: List[int], k: int) -> int:
+ op1, op2 = 0, 0
+ d = []
+ for a, b in zip(nums1, nums2):
+ d.append(a - b)
+ if sum(d) != 0: return -1
+ for v in d:
+ if k == 0:
+ # k==0时特判,不能相除法了。
+ if v != 0: return -1
+ continue
+ if abs(v) % k != 0: return -1
+ if v > 0:
+ op1 += v // k
+ else:
+ op2 += (-v) // k
+ if op1 != op2:
+ return -1
+ return op1
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-28-2542. \346\234\200\345\244\247\345\255\220\345\272\217\345\210\227\347\232\204\345\210\206\346\225\260.md" "b/_posts/Algorithms/leetcode/2023-01-28-2542. \346\234\200\345\244\247\345\255\220\345\272\217\345\210\227\347\232\204\345\210\206\346\225\260.md"
new file mode 100644
index 0000000000..3697889093
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-28-2542. \346\234\200\345\244\247\345\255\220\345\272\217\345\210\227\347\232\204\345\210\206\346\225\260.md"
@@ -0,0 +1,90 @@
+---
+layout: post
+category: leetcode
+title: 2542. 最大子序列的分数
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/maximum-subsequence-score/)
+
+给你两个下标从 **0** 开始的整数数组 `nums1` 和 `nums2` ,两者长度都是 `n` ,再给你一个正整数 `k` 。你必须从 `nums1` 中选一个长度为 `k` 的 **子序列** 对应的下标。
+
+对于选择的下标 `i0` ,`i1` ,..., `ik - 1` ,你的 **分数** 定义如下:
+
+- `nums1` 中下标对应元素求和,乘以 `nums2` 中下标对应元素的 **最小值** 。
+- 用公示表示: `(nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] , nums2[i1], ... ,nums2[ik - 1])` 。
+
+请你返回 **最大** 可能的分数。
+
+一个数组的 **子序列** 下标是集合 `{0, 1, ..., n-1}` 中删除若干元素得到的剩余集合,也可以不删除任何元素。
+
+
+
+**示例 1:**
+
+```
+输入:nums1 = [1,3,3,2], nums2 = [2,1,3,4], k = 3
+输出:12
+解释:
+四个可能的子序列分数为:
+- 选择下标 0 ,1 和 2 ,得到分数 (1+3+3) * min(2,1,3) = 7 。
+- 选择下标 0 ,1 和 3 ,得到分数 (1+3+2) * min(2,1,4) = 6 。
+- 选择下标 0 ,2 和 3 ,得到分数 (1+3+2) * min(2,3,4) = 12 。
+- 选择下标 1 ,2 和 3 ,得到分数 (3+3+2) * min(1,3,4) = 8 。
+所以最大分数为 12 。
+```
+
+**示例 2:**
+
+```
+输入:nums1 = [4,2,3,1,1], nums2 = [7,5,10,9,6], k = 1
+输出:30
+解释:
+选择下标 2 最优:nums1[2] * nums2[2] = 3 * 10 = 30 是最大可能分数。
+```
+
+
+
+**提示:**
+
+- `n == nums1.length == nums2.length`
+- `1 <= n <= 105`
+- `0 <= nums1[i], nums2[j] <= 105`
+- `1 <= k <= n`
+
+## solution
+
+排序后,按从小到大枚举
+
+```python
+class Solution:
+ def maxScore(self, nums1: List[int], nums2: List[int], k: int) -> int:
+ a1, a2 = nums1, nums2
+ n = len(a1)
+ d = zip(a2, a1)
+ # 排序
+ d = sorted(d, key=lambda x: (x[0], x[1]))
+ # 统计每个a2元素大于a2元素对应的最大a1和
+ right_max_sumv = collections.defaultdict(int)
+ cur = 0
+ import heapq
+ h = []
+ # print(d)
+ for i in range(len(d) - 1, -1, -1):
+ b, c = d[i]
+ heapq.heappush(h, c)
+ cur += c
+ if len(h) > k:
+ x = heapq.heappop(h)
+ cur -= x
+ # print(h, cur)
+ if len(h) == k:
+ right_max_sumv[b] = cur
+ ans = 0
+ # print(right_max_sumv)
+ for k, v in right_max_sumv.items():
+ ans = max(ans, v * k)
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-28-2546. \346\211\247\350\241\214\351\200\220\344\275\215\350\277\220\347\256\227\344\275\277\345\255\227\347\254\246\344\270\262\347\233\270\347\255\211.md" "b/_posts/Algorithms/leetcode/2023-01-28-2546. \346\211\247\350\241\214\351\200\220\344\275\215\350\277\220\347\256\227\344\275\277\345\255\227\347\254\246\344\270\262\347\233\270\347\255\211.md"
new file mode 100644
index 0000000000..e067a7d306
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-28-2546. \346\211\247\350\241\214\351\200\220\344\275\215\350\277\220\347\256\227\344\275\277\345\255\227\347\254\246\344\270\262\347\233\270\347\255\211.md"
@@ -0,0 +1,58 @@
+---
+layout: post
+category: leetcode
+title: 2546. 执行逐位运算使字符串相等
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/apply-bitwise-operations-to-make-strings-equal/)
+
+给你两个下标从 **0** 开始的 **二元** 字符串 `s` 和 `target` ,两个字符串的长度均为 `n` 。你可以对 `s` 执行下述操作 **任意** 次:
+
+- 选择两个 **不同** 的下标 `i` 和 `j` ,其中 `0 <= i, j < n` 。
+- 同时,将 `s[i]` 替换为 (`s[i]` **OR** `s[j]`) ,`s[j]` 替换为 (`s[i]` **XOR** `s[j]`) 。
+
+例如,如果 `s = "0110"` ,你可以选择 `i = 0` 和 `j = 2`,然后同时将 `s[0]` 替换为 (`s[0]` **OR** `s[2]` = `0` **OR** `1` = `1`),并将 `s[2]` 替换为 (`s[0]` **XOR** `s[2]` = `0` **XOR** `1` = `1`),最终得到 `s = "1110"` 。
+
+如果可以使 `s` 等于 `target` ,返回 `true` ,否则,返回 `false` 。
+
+
+
+**示例 1:**
+
+```
+输入:s = "1010", target = "0110"
+输出:true
+解释:可以执行下述操作:
+- 选择 i = 2 和 j = 0 ,得到 s = "0010".
+- 选择 i = 2 和 j = 1 ,得到 s = "0110".
+可以使 s 等于 target ,返回 true 。
+```
+
+**示例 2:**
+
+```
+输入:s = "11", target = "00"
+输出:false
+解释:执行任意次操作都无法使 s 等于 target 。
+```
+
+
+
+**提示:**
+
+- `n == s.length == target.length`
+- `2 <= n <= 105`
+- `s` 和 `target` 仅由数字 `0` 和 `1` 组成
+
+## solution
+
+找规律。 [参考](https://leetcode.cn/problems/apply-bitwise-operations-to-make-strings-equal/solution/nao-jin-ji-zhuan-wan-yi-xing-dai-ma-by-e-0fce/)
+
+```python
+class Solution:
+ def makeStringsEqual(self, s: str, target: str) -> bool:
+ return ('1' in s) == ('1' in target)
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-28-2547. \346\213\206\345\210\206\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\344\273\243\344\273\267.md" "b/_posts/Algorithms/leetcode/2023-01-28-2547. \346\213\206\345\210\206\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\344\273\243\344\273\267.md"
new file mode 100644
index 0000000000..c345b2e99a
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-28-2547. \346\213\206\345\210\206\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\344\273\243\344\273\267.md"
@@ -0,0 +1,102 @@
+---
+layout: post
+category: leetcode
+title: 2547. 拆分数组的最小代价
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/minimum-cost-to-split-an-array/)
+
+给你一个整数数组 `nums` 和一个整数 `k` 。
+
+将数组拆分成一些非空子数组。拆分的 **代价** 是每个子数组中的 **重要性** 之和。
+
+令 `trimmed(subarray)` 作为子数组的一个特征,其中所有仅出现一次的数字将会被移除。
+
+- 例如,`trimmed([3,1,2,4,3,4]) = [3,4,3,4]` 。
+
+子数组的 **重要性** 定义为 `k + trimmed(subarray).length` 。
+
+- 例如,如果一个子数组是 `[1,2,3,3,3,4,4]` ,`trimmed([1,2,3,3,3,4,4]) = [3,3,3,4,4]` 。这个子数组的重要性就是 `k + 5` 。
+
+找出并返回拆分 `nums` 的所有可行方案中的最小代价。
+
+**子数组** 是数组的一个连续 **非空** 元素序列。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [1,2,1,2,1,3,3], k = 2
+输出:8
+解释:将 nums 拆分成两个子数组:[1,2], [1,2,1,3,3]
+[1,2] 的重要性是 2 + (0) = 2 。
+[1,2,1,3,3] 的重要性是 2 + (2 + 2) = 6 。
+拆分的代价是 2 + 6 = 8 ,可以证明这是所有可行的拆分方案中的最小代价。
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,2,1,2,1], k = 2
+输出:6
+解释:将 nums 拆分成两个子数组:[1,2], [1,2,1] 。
+[1,2] 的重要性是 2 + (0) = 2 。
+[1,2,1] 的重要性是 2 + (2) = 4 。
+拆分的代价是 2 + 4 = 6 ,可以证明这是所有可行的拆分方案中的最小代价。
+```
+
+**示例 3:**
+
+```
+输入:nums = [1,2,1,2,1], k = 5
+输出:10
+解释:将 nums 拆分成一个子数组:[1,2,1,2,1].
+[1,2,1,2,1] 的重要性是 5 + (3 + 2) = 10 。
+拆分的代价是 10 ,可以证明这是所有可行的拆分方案中的最小代价。
+```
+
+
+
+**提示:**
+
+- `1 <= nums.length <= 1000`
+- `0 <= nums[i] < nums.length`
+- `1 <= k <= 109`
+
+
+
+## solution
+
+一维DP。
+
+dp(i)表示以0...i的代价,求dp(n-1)。
+
+用map维护出现不止一次的元素个数。
+
+```python
+INF = int(1e20)
+class Solution:
+ def minCost(self, nums: List[int], k: int) -> int:
+ n = len(nums)
+ dp = [INF for _ in range(n)]
+ for i in range(n):
+ res = INF
+ cnt = collections.Counter()
+ t = 0
+ for j in range(i, -1, -1):
+ cnt[nums[j]] += 1
+ if cnt[nums[j]] == 2:
+ t += 2
+ elif cnt[nums[j]] > 2:
+ t += 1
+ res = min(res, (dp[j - 1] if j - 1 >= 0 else 0) + k + t)
+ # if i == n-1 and j == 2:
+ # print("x")
+ dp[i] = res
+ # print(dp)
+ return dp[n - 1]
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-29-6339. \345\260\206\347\217\240\345\255\220\346\224\276\345\205\245\350\203\214\345\214\205\344\270\255.md" "b/_posts/Algorithms/leetcode/2023-01-29-6339. \345\260\206\347\217\240\345\255\220\346\224\276\345\205\245\350\203\214\345\214\205\344\270\255.md"
new file mode 100644
index 0000000000..6a74e28a91
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-29-6339. \345\260\206\347\217\240\345\255\220\346\224\276\345\205\245\350\203\214\345\214\205\344\270\255.md"
@@ -0,0 +1,74 @@
+---
+layout: post
+category: leetcode
+title: 6339. 将珠子放入背包中
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/put-marbles-in-bags/)
+
+你有 `k` 个背包。给你一个下标从 **0** 开始的整数数组 `weights` ,其中 `weights[i]` 是第 `i` 个珠子的重量。同时给你整数 `k` 。
+
+请你按照如下规则将所有的珠子放进 `k` 个背包。
+
+- 没有背包是空的。
+- 如果第 `i` 个珠子和第 `j` 个珠子在同一个背包里,那么下标在 `i` 到 `j` 之间的所有珠子都必须在这同一个背包中。
+- 如果一个背包有下标从 `i` 到 `j` 的所有珠子,那么这个背包的价格是 `weights[i] + weights[j]` 。
+
+一个珠子分配方案的 **分数** 是所有 `k` 个背包的价格之和。
+
+请你返回所有分配方案中,**最大分数** 与 **最小分数** 的 **差值** 为多少。
+
+
+
+**示例 1:**
+
+```
+输入:weights = [1,3,5,1], k = 2
+输出:4
+解释:
+分配方案 [1],[3,5,1] 得到最小得分 (1+1) + (3+1) = 6 。
+分配方案 [1,3],[5,1] 得到最大得分 (1+3) + (5+1) = 10 。
+所以差值为 10 - 6 = 4 。
+```
+
+**示例 2:**
+
+```
+输入:weights = [1, 3], k = 2
+输出:0
+解释:唯一的分配方案为 [1],[3] 。
+最大最小得分相等,所以返回 0 。
+```
+
+
+
+**提示:**
+
+- `1 <= k <= weights.length <= 105`
+- `1 <= weights[i] <= 109`
+
+## solution
+
+脑筋急转弯
+
+不要关注端点,要关注分割位置,收益就是分割位置左右两边
+
+```python
+
+class Solution:
+ def putMarbles(self, weights: List[int], k: int) -> int:
+ # 不要关注端点,要关注分割位置,收益就是分割位置左右两边
+ d = []
+ for i in range(len(weights) - 1):
+ a, b = weights[i], weights[i + 1]
+ d.append(a + b)
+ d.sort()
+ # print(d)
+ ans = -sum(d[:k - 1])
+ d = list(reversed(d))
+ ans += sum(d[:k - 1])
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-29-6340. \347\273\237\350\256\241\344\270\212\345\215\207\345\233\233\345\205\203\347\273\204.md" "b/_posts/Algorithms/leetcode/2023-01-29-6340. \347\273\237\350\256\241\344\270\212\345\215\207\345\233\233\345\205\203\347\273\204.md"
new file mode 100644
index 0000000000..8bd342be32
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-29-6340. \347\273\237\350\256\241\344\270\212\345\215\207\345\233\233\345\205\203\347\273\204.md"
@@ -0,0 +1,85 @@
+---
+layout: post
+category: leetcode
+title: 6340. 统计上升四元组
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/count-increasing-quadruplets/)
+
+给你一个长度为 `n` 下标从 **0** 开始的整数数组 `nums` ,它包含 `1` 到 `n` 的所有数字,请你返回上升四元组的数目。
+
+如果一个四元组 `(i, j, k, l)` 满足以下条件,我们称它是上升的:
+
+- `0 <= i < j < k < l < n` 且
+- `nums[i] < nums[k] < nums[j] < nums[l]` 。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [1,3,2,4,5]
+输出:2
+解释:
+- 当 i = 0 ,j = 1 ,k = 2 且 l = 3 时,有 nums[i] < nums[k] < nums[j] < nums[l] 。
+- 当 i = 0 ,j = 1 ,k = 2 且 l = 4 时,有 nums[i] < nums[k] < nums[j] < nums[l] 。
+没有其他的四元组,所以我们返回 2 。
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,2,3,4]
+输出:0
+解释:只存在一个四元组 i = 0 ,j = 1 ,k = 2 ,l = 3 ,但是 nums[j] < nums[k] ,所以我们返回 0 。
+```
+
+
+
+**提示:**
+
+- `4 <= nums.length <= 4000`
+- `1 <= nums[i] <= nums.length`
+- `nums` 中所有数字 **互不相同** ,`nums` 是一个排列。
+
+## solution
+
+统计四元组。
+
+枚举中间的两个数。O(n2)
+
+需要预处理简化时间复杂度。
+
+```python
+class Solution:
+ def countQuadruplets(self, nums: List[int]) -> int:
+ n = len(nums)
+ # i,j,k,l. i j:
+ cnt_greater_j[j][i] = cnt
+ if nums[i] > nums[j]:
+ cnt += 1
+ i -= 1
+ ans = 0
+ for j in range(n):
+ for k in range(j + 1, n):
+ if nums[j] > nums[k]:
+ ans += cnt_less_k[k][j] * cnt_greater_j[j][k]
+ return ans
+```
+
diff --git "a/_posts/Algorithms/leetcode/2023-01-30-1664. \347\224\237\346\210\220\345\271\263\350\241\241\346\225\260\347\273\204\347\232\204\346\226\271\346\241\210\346\225\260.md" "b/_posts/Algorithms/leetcode/2023-01-30-1664. \347\224\237\346\210\220\345\271\263\350\241\241\346\225\260\347\273\204\347\232\204\346\226\271\346\241\210\346\225\260.md"
new file mode 100644
index 0000000000..9df6dbaaba
--- /dev/null
+++ "b/_posts/Algorithms/leetcode/2023-01-30-1664. \347\224\237\346\210\220\345\271\263\350\241\241\346\225\260\347\273\204\347\232\204\346\226\271\346\241\210\346\225\260.md"
@@ -0,0 +1,98 @@
+---
+layout: post
+category: leetcode
+title: 1664. 生成平衡数组的方案数
+tags: leetcode
+---
+
+## title
+[problem link](https://leetcode.cn/problems/ways-to-make-a-fair-array/)
+
+给你一个整数数组 `nums` 。你需要选择 **恰好** 一个下标(下标从 **0** 开始)并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。
+
+比方说,如果 `nums = [6,1,7,4,1]` ,那么:
+
+- 选择删除下标 `1` ,剩下的数组为 `nums = [6,7,4,1]` 。
+- 选择删除下标 `2` ,剩下的数组为 `nums = [6,1,4,1]` 。
+- 选择删除下标 `4` ,剩下的数组为 `nums = [6,1,7,4]` 。
+
+如果一个数组满足奇数下标元素的和与偶数下标元素的和相等,该数组就是一个 **平衡数组** 。
+
+请你返回删除操作后,剩下的数组 `nums` 是 **平衡数组** 的 **方案数** 。
+
+
+
+**示例 1:**
+
+```
+输入:nums = [2,1,6,4]
+输出:1
+解释:
+删除下标 0 :[1,6,4] -> 偶数元素下标为:1 + 4 = 5 。奇数元素下标为:6 。不平衡。
+删除下标 1 :[2,6,4] -> 偶数元素下标为:2 + 4 = 6 。奇数元素下标为:6 。平衡。
+删除下标 2 :[2,1,4] -> 偶数元素下标为:2 + 4 = 6 。奇数元素下标为:1 。不平衡。
+删除下标 3 :[2,1,6] -> 偶数元素下标为:2 + 6 = 8 。奇数元素下标为:1 。不平衡。
+只有一种让剩余数组成为平衡数组的方案。
+```
+
+**示例 2:**
+
+```
+输入:nums = [1,1,1]
+输出:3
+解释:你可以删除任意元素,剩余数组都是平衡数组。
+```
+
+**示例 3:**
+
+```
+输入:nums = [1,2,3]
+输出:0
+解释:不管删除哪个元素,剩下数组都不是平衡数组。
+```
+
+
+
+**提示:**
+
+- `1 <= nums.length <= 105`
+- `1 <= nums[i] <= 104`
+
+## solution
+
+找规律题
+
+当删除某个下标后,新的偶数和 = 这个下标左边的偶数和 + 这个下标右边的奇数和
+
+当删除某个下标后,新的奇数和 = 这个下标左边的奇数数和 + 这个下标右边的偶数数和
+
+```python
+
+class Solution:
+ def waysToMakeFair(self, nums: List[int]) -> int:
+ odd, even = 0, 0
+ for i, v in enumerate(nums):
+ if i % 2 == 0:
+ even += v
+ else:
+ odd += v
+ lo, le = 0, 0
+ total = sum(nums)
+ # print(total, odd, even)
+ ans = 0
+ for i, v in enumerate(nums):
+ if i % 2 == 0:
+ teven = odd - lo + le
+ if teven == total - v - teven:
+ ans += 1
+ # print(i, v, teven)
+ le += v
+ else:
+ todd = even - le + lo
+ if todd == total - v - todd:
+ ans += 1
+ # print(i, v, todd)
+ lo += v
+ return ans
+```
+
diff --git "a/_posts/DailyLife/2018-02-07-\347\202\222\350\217\234.md" "b/_posts/DailyLife/2018-02-07-\347\202\222\350\217\234.md"
deleted file mode 100644
index 49258f5d0b..0000000000
--- "a/_posts/DailyLife/2018-02-07-\347\202\222\350\217\234.md"
+++ /dev/null
@@ -1,132 +0,0 @@
----
-layout: post
-category: DailyLife
-title: 炒菜
-tags: DailyLife
----
-
-## 炒菜
-
-### 土豆丝+肉丝
-
-土豆去皮变成丝。 需要先洗一遍,去掉淀粉,否则氧化发黑,可以放水里,用到再捞出来。
-
-
-
-肉丝洗3遍。
-
-
-
-热锅, 放油, 底部全湿, 放肉丝, 2勺 料酒, 2勺生抽, 半勺老抽。
-
-
-
-放土豆丝, 每5s翻炒,放鸡精, 如果老抽多了可以不放盐。 菜基本熟时放葱。
-
-
-
-
-
-### 炒卷心菜
-
-大小 长3*3大小,不要梗。
-
-
-
-热锅冷油, 油比肉丝少点。 放卷心菜, 生抽2勺, 鸡精, 葱。
-
-
-
-**要干锅时加热水。**
-
-
-
-### 五花肉+荷兰豆
-
-不需要豆油
-
-五花肉过于肥腻,需要锅里不放油 闷一会,因为不是肉丝所以没那么容易老。
-
-直到肉变色,炸出油。
-
-加蒜 加料酒,生抽老抽。因为肉比较大,可以加点水让配料入味
-
-然后放荷兰豆炒。
-
-
-
-### 蒜薹+肉丝
-
-蒜薹切段,煮50秒,捞出来,这是为了避免蒜薹熟的慢。
-
-肉丝做法 + 蒜薹。
-
-### 红烧鸡翅根
-
-鸡翅根切几道,红烧时入味
-
-鸡翅根煮熟。
-
-放油,鸡翅根,料酒,生抽,老抽
-
-加水,4分之一高度。
-
-加盐。
-
-放葱。
-
-味素。
-
-红烧到无水
-
-
-### 茄子肉丝
-茄子 切成丝:
-
-1. 先斜着切片,5mm厚即可,茄子熟时缩的多。
-
-2. 片再切丝,5mm宽
-
-肉丝做法
-
-茄子含水少,避免干锅需要加点水。
-
-
-### 芹菜肉丝
-
-芹菜:
-1. 长度2cm
-2. 宽的芹菜要中间切一刀分开
-3. 先去叶子,再去根,再切
-
-肉丝做法
-
-芹菜含水多
-
-### 红烧鸡爪
-
-洗干净 去指甲
-
-鸡爪炖2min,快熟那种
-
-油,白砂糖让溶解,蒜,
-
-放鸡爪,生抽2勺,老抽和耗油各1勺, 耗油是提现的
-
-一罐300ml的啤酒,没有啤酒就热水, 水大概刚好到鸡爪上限那, 挺多的
-
-一个八角
-
-中火20min, 直到快没有汤了
-
-葱花,味素。
-
-
-
-## 韭菜鸡蛋
-
-- 一把韭菜,4个鸡蛋。
-- 韭菜洗干净,去死皮,切根,切长度为1.5-2cm左右
-- 锅里放油,放韭菜大概8-9分熟,颜色变了就可以,捞出来韭菜去水。
-- 放油,放鸡蛋,7-8分熟,成块了,放韭菜,加鸡精,加盐。
-- 注意:韭菜2-3s就变颜色了,要勤翻
diff --git "a/_posts/English/2021-01-02-\345\217\221\351\237\263-\345\217\221\351\237\263\350\247\204\345\210\231.md" "b/_posts/English/2021-01-02-\345\217\221\351\237\263-\345\217\221\351\237\263\350\247\204\345\210\231.md"
index 03912e5f8b..e19dd35695 100644
--- "a/_posts/English/2021-01-02-\345\217\221\351\237\263-\345\217\221\351\237\263\350\247\204\345\210\231.md"
+++ "b/_posts/English/2021-01-02-\345\217\221\351\237\263-\345\217\221\351\237\263\350\247\204\345\210\231.md"
@@ -5,43 +5,7 @@ title: 发音-发音规则
tags: English
---
-## 总结
-
-发音规则 昂克
-
-- 辅音元音连读: not at all, 如果辅音是/r/ /l/ /ŋ/, 辅音双写: for a
-- 元+元,添加连读,自动添加/j/或/w/, 只有i和u。do it, go out. /ɔː/自动加r, saw in
-- 特殊添加元音: /n/+/s/=/n ts/ since
-- 辅+辅, 三组内的略读只读后面的,所有辅音相同略读,浊音在前清辅音在后可略读前面的:v f, z s,ð θ. 不可略读:/tʃ/ /dʒ/
-- 特殊略读 nt+元音, 省略t :advantage
-- 吞音,三组里碰到后面是三组里非兄弟辅音就吞音(也包含其他非爆破辅音)。吞音保留时值和状态不发音, that cat
-- 吞音喉音停顿:/tən/ /dən/ 只留ən, written
-- 略读 h-droping: him, his, he, her
-- 略读 g-droping: doing. ing里的
-- 变音: about you. would you, rock you. /t/+/ju/;/d/+/ju/。 miss you: sh
-- 清辅音+元,清辅音浊化
-- 不同意群不连读
-- 元音+元音,如果读音相近,可以连一起,比如law office. lawwfis
-- schewa: for, of, have, or, and等,元音变成ə
-
-**总结2:**
-
-> 视频: https://www.bilibili.com/video/BV1SZ4y1K7Lr?p=6&spm_id_from=pageDriver
-
-- 元音挨着元音不容易读,所以才会区分a和an
-- 同化&异化
- - 同化:前面音 改变
- - 常见爆破音: k,t,d, 后加辅音,前面音发一半,也叫失去爆破。
- - 浊音变清音,比如have to, of course, 的v变f.
- - inperson读imperson, n->m,嘴唇闭合。
- - 同化:后面音 改变
- - 比如变复数读音
- - 相互作用
- - s+j: bless you. z+j:as you wish. t+j: meet you. d+j: did you. 类似的educate, tissue.
- - 辅音连读
- - 异化, r接元音会读r, 否则不发音
-- 省音: t,d。 来自其他视频,**t+辅音里的t省略,nt+元的t省略, nd+辅的d省略**
-- 节奏: 等时性。
+-
## 重音
@@ -58,6 +22,22 @@ tags: English
> 链接: https://www.bilibili.com/video/av19992217?from=search&seid=14758661060311518388
+### 总结
+
+- 辅+元,**连读**: not at all, 如果辅音是/r/ /l/ /ŋ/, 辅音双写: for a
+- 元+元,添加连读,当尾元音是i和u时,自动添加/j/或/w/。do it, go out. /ɔː/自动加r, saw in
+- 特殊添加连读: /n/+/s/=/n ts/ since
+- 辅+辅,**连读**, 三组内的略读只读后面的,所有辅音相同略读,浊音在前清辅音在后可略读前面的:v f, z s,ð θ. 不可略读:/tʃ/ /dʒ/
+- 辅+辅,**吞音**,三组里碰到后面是三组里非兄弟辅音就吞音(也包含其他非爆破辅音)。吞音保留时值和状态不发音, that cat
+- 吞音喉音停顿:/tən/ /dən/ 只留ən, written
+- 略读 h-droping: him, his, he, her。 give him /givim/
+- 略读 g-droping: doing. ing里的
+- 变音: about you. would you, rock you. /t/+/ju/;/d/+/ju/。 miss you: sh
+- ~~清辅音+元,清辅音浊化~~
+- 不同意群不连读
+- 元音+元音,如果读音相近,可以连一起,比如law office. lawwfis
+- schewa: for, of, have, or, and等,元音变成ə
+
### 清辅音浊化
S后面的清辅音浊化现象可以这样归纳:清辅音跟着一个元音,前面又有一个 s ,无论是在单词的最前面还是中间,只要是在重读音节或次重读音节里,一般都读成对应浊辅音,如stand,strike,speak,sky 等等,值得一提的是strike不是不用变,而是它“tr”本来所发的音已是浊辅音,但也要变成“dr”所发的那个音 (如dream中的“dr”所发的音).
@@ -177,7 +157,225 @@ i经常弱读为e,所以give hime读为后面的,这个经常用后面的

-### 弱读 缩写 其他
--
+
+
+## 100个最常见的英语单词发音
+
+> [参考](https://www.zhihu.com/zvideo/1390373231258382336) , 包含了常见单词的弱读,比如him, to, do, of等。
+
+笔记
+
+
+
+正常schewa:
+
+- a,an,that, for, as( he's as tall as me), do, at, but, from, or, an, one, should, could, so, some, than
+
+不弱读的:
+
+- This, by, they, we, say, out, also.
+
+意群结尾p不发音,what's up
+
+1期:
+
+- the: the发音后面的/ə/ 当the后面接元音时可变成/i/
+- I am: I'm 有时只有一个音/m/, I'm sorry / m_ 'sorry/
+- you are: yer.
+- It is: /its/ 有时可省略元音 /ts/ ts cool
+- we are: /wər/
+- they are: /ðər/
+- to: tə, go to时, t变d
+- Of: /əv/ 在kind of, sort of里省略/v/, kanda
+- and: no /d/ or just /n/, ex: And I
+
+2期:
+
+- With: 后面轻音化, /θ/
+- he, him, 省略/h/, ex: what does he want
+- You: /jə/
+
+5期:
+
+- Who /u/, ex: Anyone who wants to come can come.
+
+6期:
+
+- Can /cən/
+- Him /əm/. Give him: /givem/
+
+7期:
+
+- into /ində/. 这里的t不遵循t发音规则。
+
+8期下:
+
+- Its: /ts/ 没有前面/i/了。
+
+10期下:
+
+- give是实词,但give me时弱读, give me that: gimme 省略v
+- us: əs
+
+
+
+
+
+## /t/发音
+
+[参考](https://rachelsenglish.com/podcast/004-t-pronunciations-flap-t-stop-t-true-t/)
+
+### True T
+
+开头或者重音节,或者后面接r。
+
+- True T Rule 1: At the beginning of a word
+ - Exception #1: in the TR cluster (train, try) – then it can sound like a CH
+ - Exception #2: the words to, today, tomorrow. These may begin with a Flap T.
+- True T Rule 2: At the beginning of a stressed syllable (attain, until). This includes secondary stress. In a dictionary, secondary stress is marked with this: ˌ Primary stress is marked with this: ˈ
+ - Exception: when it’s followed by R (attribute, attract)
+
+### Stop T
+
+- How to make a Stop sound: Stop T vs. No T: Buy vs. bite
+- Stop T Rule 1: When the T is followed by a consonant sound (definitely, bluntly) 后面接辅音
+ - Exception: when the sound before the T is an R. Then it’s a Stop T (partly) : r+t+辅音 ,t不变
+- Stop T Rule 2: Make the T a Stop T when it’s the last sound in a thought group. :意群结尾
+ - Exception: when the T is in a cluster, then we usually pronounce it (fact, best) :
+
+
+
+如果后面 是元音或者双元音 或者是意群的结尾,t就发音。可能是flap T, stop T
+
+### Flap T
+
+> [参考](https://www.goalsenglish.com/lessons/flap-t-sound-american-english-accent)
+
+- 类似d的发音
+- 发生flap T情况
+ - Flap T Rule 1: a T is a Flap T between two vowels or diphthongs (beautiful, city) 元音间 If a ‘t’ is between two vowels, whether in a word or between two words, it will be pronounced as a ‘soft d.’
+ - Exception: If the T begins a stressed syllable. Then it’s a True T (attain, attack) 重音上
+ - Flap T Rule 2: a T is a Flap T after an R before a vowel or diphthong (party, dirty). Applies to linked phrase: (a lot of, about it)
+ - Exception: if the T begins a stressed syllable. Then it’s a True T (partake)
+
+例子
+
+- it always
+
+### Drop T
+
+- Dropped T Rule 1: T can be dropped after N (center, internet) nt的t会省略
+ - Exception: when there is a syllable split between N and T (until, intense)
+- Dropped T Rule 2: Americans often drop the T between two other consonants (exactly, perfectly). This applies to phrases where two words link (just because)
+ - Exception: Not when the consonant before the T is an R (partly)
+
+例子
+
+- shouldn't, didn't,won't
+
+### 总结
+
+t前面是n? drop T
+
+t前面是辅音?
+
+- 后面是辅音? drop T
+- 后面是元音? stop T
+
+t前面是元音?
+
+- 后面是元音? flap T
+- 后面是辅音? drop T
+
+t是意群结尾? Stop T. p也类似。
+
+只有两个元音间的t是d,否则stop / drop
+
+
+
+杂记:
+
+t+辅音里的t省略, 其实是停顿,但和省略差不多
+
+nt比较特殊: nt+元的t省略, nd+辅的d省略
+
+## /d/发音
+
+nd+辅的d省略
+
+## 重读和弱读
+
+### 重读
+
+**一般来讲我们应该重读content words, 就是有实际内容、实际意义的词**,例如:名词,实义动词,形容词,副词,数量词。名词方面,比如像mountain, history等;实义动词就是真正发出动作的词,比如像establish, jump等;形容词比如像stunning, terrifying这样的词;副词方面比如quickly, extremely等。这些词都是有实际意义的,也就是我所说的内容词,来表达句子意义的词,所以我们应该把它们做重读的处理。
+
+
+
+**一般来讲哪些单词不重读,就是function words功能词,即那些起到语法功能作用的词,**比如像代词,介词,限定词,连词以及助动词等等,都是语法结构会运用到的词,这些词对句子的意义并不构成直接的影响。什么样的词属于限定词,比如像冠词the, a/an; some, few, my都是限定词;助动词像be动词,be, do, must这些都属于助动词;介词after, of, above, opposite, out of, on behalf of这些有介词意义的短语也包括在内。还有像连词,比如and, so, 还有代词this, him, our, you, it, 这些词在句子当中是起到语法意义的词。
+
+
+
+总结: 重读的只有副词、名词、形容词、动词。但content words有时也不会重读,如果还有其他的重读的词的话。
+
+
+
+### 弱读
+
+1、重读的单词不会出现弱读现象,要读的响亮
+
+这些词一般是表示句子含义的词,如名词,动词,副词,形容词 (today 今天, apple 苹果)
+
+
+
+2、非重读的部分的单词要读轻
+
+这些词一般起到语法功能,如介词、连词、助动词等 (and 和, but但是,for为了)
+
+
+
+
+
+弱读现象存在于句子的非重读单词部分
+
+对于句子非重读部分的单词
+
+1、如果有弱读发音,就可以进行弱读
+
+2、如果没有弱读发音,发本来的音即可
+
+
+
+不能弱读情况
+
+1、句子最后一个单词不能弱读
+
+2、特意强调的单词不能弱读,要重读
+
+
+
+## 英音美音区别
+
+todo
+
+
+
+## 其它
+
+> 视频: https://www.bilibili.com/video/BV1SZ4y1K7Lr?p=6&spm_id_from=pageDriver
+
+- 元音挨着元音不容易读,所以才会区分a和an
+- 同化&异化
+ - 同化:前面音 改变
+ - 常见爆破音: k,t,d, 后加辅音,前面音发一半,也叫失去爆破。
+ - 浊音变清音,比如have to, of course, 的v变f.
+ - inperson读imperson, n->m,嘴唇闭合。
+ - 同化:后面音 改变
+ - 比如变复数读音
+ - 相互作用
+ - s+j: bless you. z+j:as you wish. t+j: meet you. d+j: did you. 类似的educate, tissue.
+ - 辅音连读
+ - 异化, r接元音会读r, 否则不发音
+- 省音: t,d。 来自其他视频,**t+辅音里的t省略,nt+元的t省略, nd+辅的d省略**
+- 节奏: 等时性。
diff --git "a/_posts/English/2021-01-02-\345\217\221\351\237\263-\351\237\263\346\240\207.md" "b/_posts/English/2021-01-02-\345\217\221\351\237\263-\351\237\263\346\240\207.md"
index 3db6572c3d..e36709805e 100644
--- "a/_posts/English/2021-01-02-\345\217\221\351\237\263-\351\237\263\346\240\207.md"
+++ "b/_posts/English/2021-01-02-\345\217\221\351\237\263-\351\237\263\346\240\207.md"
@@ -7,6 +7,12 @@ tags: English
## 发音-音标
+欧陆词典用的是DJ音标新版。也是咱们常用的
+
+影响发音的因素:圆唇度、舌位高低、舌位前后。舌位影响了开头大小。因此学音标应以舌位为主。
+
+### 音标分类
+
分类1

@@ -17,14 +23,14 @@ tags: English
-æ : ai, such as trap.
-
-
+### BBC经典发音教程
[可学习的bilibili视频: BBC经典发音教程](https://www.bilibili.com/video/BV1Y4411M7Ac?p=2)
+### 音标发音文字注解
+
元音:
- /ɪ/ 舌抵下齿,双唇扁平分开,牙床近于全舌,发短促之“一”音。 是字母i或y在单词中的发音,发此音要短促而轻快。 **bit, hit, minute/minit/**
@@ -68,6 +74,7 @@ tags: English
- /r/ 唇形稍圆,舌身略凹,舌尖上卷,振动声带。
- /w/ 双唇突出,呈尖圆形,舌后升向软腭,气息流过,须振动声带。
- /j/ 双唇微开,舌抵下齿贴近硬腭,气流摩擦而出。
+- /dz/ 类似汉语里资。对比/ts/
@@ -84,6 +91,8 @@ tags: English
+### 音标区分
+
**长元音和短元音区别:不是长短,是松和紧。松元音只动舌头和声带,不动嘴唇。**
**双元音和单元音区别:[e]是单元音,发声短促:dead [ded] , [ai]是双元音,有从[a]到[i]的一个过渡过程:die [dai] (双元音过渡在汉语里是没有的)**
@@ -92,10 +101,36 @@ tags: English
常见区别:
-- [辅音/m/、/n/与/ŋ/](https://www.bilibili.com/video/BV1Ae41147Ng/?spm_id_from=trigger_reload)
-- [/æ/ 和 /e/](/æ/ 和 /e/)
-- [/u:/和/u/](/u:/和/u/)
-- [清辅音θ与s](https://www.bilibili.com/video/BV1X7411S7V8?spm_id_from=333.337.search-card.all.click)
+- [辅音/m/、/n/与/ŋ/](https://www.bilibili.com/video/BV1Ae41147Ng/?spm_id_from=trigger_reload) m是闭口,n嘴唇微张但牙齿闭合,最后那个是中度张嘴。
+- [/æ/ 和 /e/](https://www.bilibili.com/video/BV1o7411M7cV?spm_id_from=333.999.0.0&vd_source=4c51dba622ffb91bed5205311847907b) ae和/e/的区别,前者两指宽,像绵羊叫,后者一指宽。
+- [双元音/aɪ/与 单元音/æ/](https://www.bilibili.com/video/BV1xg4y187CT?spm_id_from=333.999.0.0&vd_source=4c51dba622ffb91bed5205311847907b) 前者双元音后者单元音 但语速快了就无法区分了
+- [/u:/和/u/](https://www.bilibili.com/video/BV1d7411M7i1?spm_id_from=333.999.0.0)
+- [清辅音θ与s](https://www.bilibili.com/video/BV1X7411S7V8?spm_id_from=333.337.search-card.all.click) 前者 上下齿咬舌尖。 后者双唇微开,上下齿接近于合拢状态
+
+### 元音图
+
+元音图
+
+
+
+注意: 红色是汉语拼音,黄色是美国英语。不圆唇的在前,圆唇在后。开口大小就是舌位高低
+
+
+
+元音的舌面不能与硬腭接触,否则就成了辅音。
+
+
+
+这有一个看和听发音的[网站](https://tfcs.baruch.cuny.edu/consonants-vowels/)
+
+
+
+### 英语兔学习笔记
+
+可每日英语听力上看,免费。
+
+- /ɪ/舌位比/i:/低,类似军训一二一里的一。bit, fit, hit, fish. 舌位过高是错误方式,不能读 中文 币 的韵母。
+-
## 音节
@@ -117,7 +152,39 @@ tags: English
比如单词later和latter。我们把这两个词按照这种原理分开,分别就是la/ter和lat/ter。
-那么这样分完有什么意义呢,当然有意义,而且意义重大,因为它能让你正确判断单词的发音。不用看音标。看下面
+那么这样分完有什么意义呢,当然有意义,而且意义重大,因为它能让你正确判断单词的发音。不用看音标。
+
+
+
+另外 辅音+l/e结尾,也可以构成音节 apple/pl/ bicycle/baskl/
+
+### 重读音节
+
+什么是重读音节呢?首先普及一下单音节的单词是没有重读符号的,但是要重读。比如:get,let,must.say等。
+
+1. 一个音节就重读:(没有重读符号)me/mi/ lake/lek/ bread/bred/
+
+2. 一般2、3个音节的单词,重读在第一音节上 sister/'sst/ tiger/tag/
+
+ 特俗
+
+ ```python
+ \1. a开头+辅音
+
+ 举例:away/ we/ ago/gu/
+
+ \2. be/re开头
+
+ 举例:begin/bgn/ reply/rpla/
+
+ \3. de/es/im/mis开头
+
+ 举例:delay/dle/ improve/mpruv/
+ ```
+
+
+
+3. 3个或以上音节的单词,重读在倒数第三个音节上。 'family de'mocracy phy'losophy
@@ -133,22 +200,26 @@ tags: English
2、**闭音节**:英语中以一个或几个辅音字母(r w y 除外)结尾而中间只有一个元音字母的音节,称为**闭音节**。闭音节的元音字母不发它字母本身的音。
-如果这个音节在单词中是重读,那就是**重读闭音节**了。
+总结: 开音节:only元 或 者元+辅+不发音e; 闭音节: 剩下的
+
+### 重读闭音节
+
+如果这个音节在单词中是闭音节并且重读,那就是**重读闭音节**了。
重读闭音节即两个辅音中间夹一个短元音(即**“辅元辅”结尾**。)
-重读闭音节结尾,且词尾只有一个辅音字母,要**双写**。
+重读闭音节结尾,且词尾只有一个辅音字母,变ing要**双写**。
重读闭音节三要素
1.必须是重读音节;
-2.最后只有一个辅音字母;只有一个元音;
+2.最后只有一个辅音字母
3.只有一个元音,元音字母发短元音
-总结: 开音节:only元 或 者元+辅+不发音e; 闭音节: 剩下的
+
## 字母发音规则
@@ -158,6 +229,8 @@ tags: English
+
+
aeiou在非重读闭音节里,一般发/ə/, 比如doctor后面的o
@@ -241,4 +314,27 @@ z [ z ]
-
\ No newline at end of file
+
+
+
+
+## 常见单词音标
+
+who when where why what whom which
+
+while [/waɪl/](cmd://Speak/_us_/while)
+
+why [ /waɪ/](cmd://Speak/_us_/why)
+
+when [/wɛn/](cmd://Speak/_us_/when)
+
+
+
+Allow: [美 /əˈlaʊ/](cmd://Speak/_us_/allow) a lao.
+
+provide. [美 /prə'vaɪd/](cmd://Speak/_us_/provide) p rou
+
+Begin: [美 /bɪˈɡɪn/](cmd://Speak/_us_/begin) bi gin
+
+Again: [美 /ə'ɡɛn/](cmd://Speak/_us_/again) a gan
+
diff --git "a/_posts/English/2021-01-02-\350\257\255\346\263\225-\345\215\225\350\257\215\345\220\204\347\247\215\345\275\242\345\274\217\345\217\230\345\214\226\350\247\204\345\210\231.md" "b/_posts/English/2021-01-02-\350\257\255\346\263\225-\345\215\225\350\257\215\345\220\204\347\247\215\345\275\242\345\274\217\345\217\230\345\214\226\350\247\204\345\210\231.md"
index add11756d2..95c5f8eeb9 100644
--- "a/_posts/English/2021-01-02-\350\257\255\346\263\225-\345\215\225\350\257\215\345\220\204\347\247\215\345\275\242\345\274\217\345\217\230\345\214\226\350\247\204\345\210\231.md"
+++ "b/_posts/English/2021-01-02-\350\257\255\346\263\225-\345\215\225\350\257\215\345\220\204\347\247\215\345\275\242\345\274\217\345\217\230\345\214\226\350\247\204\345\210\231.md"
@@ -17,7 +17,7 @@ tags: English

-这里的辅音字母指除元音字母aeiou之外的字母,非音标发音指写法。
+下面的辅音字母指除元音字母aeiou之外的字母,非音标发音指写法。
**名词所有格's 的读音与名词复数和动词第三人称单数相同**
diff --git "a/_posts/English/2021-12-11-English\350\257\255\346\263\225.md" "b/_posts/English/2021-12-11-English\350\257\255\346\263\225.md"
index 49c0659b8b..65c6abe165 100644
--- "a/_posts/English/2021-12-11-English\350\257\255\346\263\225.md"
+++ "b/_posts/English/2021-12-11-English\350\257\255\346\263\225.md"
@@ -74,3 +74,95 @@ he tells me that u have died
[参考个人单独blog](https://mafulong.github.io/2021/01/02/%E8%AF%AD%E6%B3%95-%E8%99%9A%E6%8B%9F%E8%AF%AD%E6%B0%94/)
+## “限制性定语从句”和“非限制性定语从句”的区别
+
+> [参考](https://zhuanlan.zhihu.com/p/30548008)
+
+> She despised people ***who flattered her***. 这是限制性的。非限制性就是表定语 非限制的
+> (她看不起**那些吹捧她的**人。)
+
+在上面的示例中,定语从句“who flattered her”起到了**限制名词**的作用(即缩小了名词的表示范围)。
+
+因此,我们称这类定语从句为**限制性定语从句**。
+
+
+
+在有些场景下,先行词的指向已经是唯一的了,此时就无法再缩小这个词的表示范围了。例如:
+
+> I made a card for mom ***who loves me most**.* (×)
+> (我给**最爱我的**那个妈妈做了一张卡片。)
+
+每个人只有一个妈妈,所以“最爱我的那个妈妈”的表述明显不合逻辑,此时我们就需要用到**非限制性定语从句**。
+
+所谓的非限制性定语从句,就是**使用“逗号”将定语从句与先行词隔开**,即:
+
+> I made a card for mom, ***who loves me most**.*
+> (我给妈妈做了一张卡片,**她最爱我**。)
+
+因为非限制性定语从句的作用是:**不直接修饰先行词,只为先行词提供一些补充的信息。**
+
+
+
+①限定性定语从句: 从句不能省略,如果省略整个句子意思不完整。
+
+非限定性定语从句: 从句可以省略,如果省略整个句子意思仍然完整 。
+
+②限定性定语从句: 先行词可以用that 引导。
+
+非限定性定语从句: 先行词不可以用that 引导。
+
+eg. I like read the book that you lend me.
+
+③限定性定语从句: 引导词有时可以省略。
+
+非限定性定语从句: 引导词不可以省略。
+
+④限定性定语从句: 主句与从句不需要用逗号隔开。
+
+非限定性定语从句: 主句与从句需要用逗号隔开。
+
+⑤限定性定语从句: 从句只修饰先行词。
+
+非限定性定语从句:从句既可以修饰先行词,也可以修饰整个句子或句子的一部分。
+
+
+
+## 逗号使用
+
+> [参考](https://zhuanlan.zhihu.com/p/46736877)
+
+1、当有三个或三个以上并列的单词或短语时,这些单词或短语要用逗号隔开,而且最后一个单词或短语一般都会用and或or连接,如:
+
+We had coffee, cheese and crackers and grapes.
+
+2、当两个前置形容词并列且可以调换顺序时,要用逗号隔开,如:
+
+He is a strong, healthy man. vs. He is a healthy, strong man.
+
+
+
+1、如果是以从句开头,则要在从句末尾用逗号隔开,如:
+
+If you are not sure about this, let me know now.
+
+2、如果开头的是介绍性短语,一般也要用逗号隔开,如:
+
+Having finally arrived in town, we went shopping.
+
+3、如果介绍性短语是以介词开头引导的,介词后面如果跟的是句子的主语,则要用逗号。则无论这个短语包含多少个单词,都无需用逗号隔开,如:
+
+Between your house on Main Street and my house on Grand Avenue, the mayor's mansion stands proudly.
+
+
+
+1、同位语,如:
+
+My best friend, Joe, arrived.
+
+2、非限定性定语从句(非限制作用,也不能用that),如:
+
+Jill, who is my sister, shut the door.
+
+3、分词短语,如:
+
+The man, knowing it was late, hurried home.
diff --git "a/_posts/English/2022-08-26-\350\213\261\350\257\255-\350\277\236\350\257\215.md" "b/_posts/English/2022-08-26-\350\213\261\350\257\255-\350\277\236\350\257\215.md"
new file mode 100644
index 0000000000..2c077f1550
--- /dev/null
+++ "b/_posts/English/2022-08-26-\350\213\261\350\257\255-\350\277\236\350\257\215.md"
@@ -0,0 +1,612 @@
+---
+layout: post
+category: English
+title: 英语-连词
+tags: English
+---
+
+## 连词
+
+
+
+## 不仅而且Not only but also
+
+[参考](https://en-grammar.xiao84.com/201612/27635.html)
+
+比较自由。also可省略, but also之间也可以加词。
+
+可连接主语、谓语动词...
+
+The Americans and the British **not only** speak the same language **but also** share a large number of social customs.
+
+
+
+Note:
+
+- ”not only A but also B”结构中的A和B通常是同等成分。因此这句话是错误的“He not only plays the piano, but also the violin.” 可以改成“He plays **not only** the piano, but also the violin”
+
+## 也(too, as well, also, either)
+
+too和as well两者都可用在肯定句或疑问句的句末。两者通常可以换用。
+
+She likes pizza as well.
+
+=She likes pizza too.
+
+
+
+- also: 常在**肯定句句中**
+- too: 常在**肯定句句末**,前面常有逗号
+- either: 常在**否定句句末** He isn't a singer either.
+
+
+
+来自欧陆词典:
+
+[also](dic://also) 比too正式一些,语气较重,只用于肯定句,一般紧靠动词。
+[too](dic://too) 语气较轻,多用于口语,在肯定句中使用,通常位于句末。
+[as well](dic://as well) 一般不用否定句,通常放在句末,强调时可放在句中。
+[either](dic://either) 用于否定句,放在句末,之前加逗号。
+[likewise](dic://likewise) 是书面语用词。
+
+
+
+也不nor
+
+He can't speak english, **nor** can I.
+
+## 除了
+
+I did **nothing but** watch it
+
+## 然而
+
+whereas
+
+Some praise him, **whereas** others condemn him
+
+
+
+## 尽管
+
+**Although** she's young, she knows a lot.
+
+In spite of sth
+
+Despite sth
+
+## 只要
+
+As long as I'm free, I will help you.
+
+**only if (连词)只有**
+
+The lawyer is paid only if he wins.
+
+当且仅当: if and only if xx
+
+## 要是xx就好了
+
+if only
+
+There had to be an answer — he was sure he could tease it out if only he had time.
+
+## 以免
+
+in case
+
+You should be careful **in case** there's a fire.
+
+## 为了
+
+We study hard in order that we can pass the team.
+
+
+
+## 刚一。。。就。
+
+推荐as soon as.
+
+**As soon as** I stepped inside,my glasses misted over.
+
+The stars came out **as soon as** darkness fell.
+
+
+
+**Hardly** I entered the room **when** the bell rang.
+
+**No sooner** had I come home **than** it began to rain.
+
+**Scarcely** had she entered the room **when** the phone rang.
+
+## 既然现在
+
+**Now that** you are on duty, you should clean the classroom.
+
+## 无论
+
+**Whether** you are sick **or** not, I'll help you.
+
+**No matter** how bad the weather is, the children will play foot-ball on the playground, notwithstanding
+
+**No matter** what it takes I will do the work.
+
+**Whatever** the reason, just hang in there.
+
+## 而不是
+
+They relied on brains **rather than** brawn
+
+He preferred to die **instead of** stealing.
+
+## 尽可能地快
+
+as soon as possible, soon: *adv.* 不久;即刻,马上
+
+We must correct our defects **as soon as possible.**
+
+as quickly as possible.
+
+## 如果...将会怎么样?
+
+**What if** the car breaks down?
+
+
+
+## 15类英语连接词
+
+https://zhuanlan.zhihu.com/p/277394043
+
+整理分享15类英语连接词,超级全。
+
+### 表示强调
+
+still 然而,仍然
+
+indeed 事实上
+
+apparently 显然
+
+oddly enough 奇怪的是
+
+of course 当然
+
+after all 毕竟
+
+significantly 明显地;显著地
+
+interestingly 有趣的是
+
+also 并且,另外
+
+surely 肯定/必定地
+
+certainly 当然
+
+undoubtedly 毫无疑问地
+
+in any case 在任何情况下;无论如何
+
+anyway 反正;不管怎样;总之
+
+above all 首先,尤其是;最重要的是
+
+in fact 事实上
+
+especially 特别是
+
+obviously 很明显 [ /'ɑbvɪəsli/](cmd://Speak/_us_/obviously)
+
+clearly 无疑的
+
+例:In fact, he is not an honest man.
+
+事实上,他不是个诚实的人。
+
+
+
+### 表示比较
+
+like 就像
+
+similarly 类似的 be similar to
+
+likewise 同样的;照样的 副词。
+
+in the same way 以同样的方式
+
+in the same manner 以类似的方式
+
+equally 同样地;相等程度地
+
+例:I will help you solve this problem, but equally you need to give me some reward.
+
+我会帮你们解决这个问题,但是同样地,你们需要付出一些回报。
+
+
+
+### 表示对比
+
+by contrast 相比之下
+
+on the contrary 相反
+
+while 而;虽然,尽管
+
+whereas 而
+
+on the other hand 另一方面
+
+unlike 不像
+
+instead 而不是;而;相反
+
+but 但
+
+conversely 相反
+
+different from 不同于
+
+however 然而
+
+nevertheless 不过
+
+otherwise 否则
+
+yet 然而, 但是
+
+in contrast 与此相反;比较起来
+
+例:On the other hand, they are also unwilling to adopt our advice.
+
+另一方面,他们也不愿意采纳我们的建议。
+
+
+
+### 表示列举
+
+for example 例如
+
+for instance 例如
+
+such as 如
+
+take …for example 以……为例
+
+except (for) 要不是由于 *except for* 除了…以外;要不是由于
+
+to illustrate 为了说明(举例说明)
+
+例:We bought some fruits such as apples, oranges and pears.
+
+我们买了一些水果,有苹果橘子还有梨。
+
+
+
+### 表示时间
+
+later 后来;稍后;随后
+
+next 然后;其次;接下来;下一...
+
+then 然后
+
+finally 最终终于
+
+at last 最后
+
+eventually 最终 [ɪ'vɛntʃuəli/](cmd://Speak/_us_/eventually)
+
+meanwhile 与此同时
+
+from now on 从现在开始 I have made up my mind not to go skating from now on. 我决心从此不再去滑冰.
+
+at the same time 同时
+
+for the time being 暂时 adv
+
+in the end 最后
+
+immediately 立即
+
+in the meantime 在此期间;于此际;与此同时
+
+in the meanwhile 同时;在此期间
+
+recently 最近
+
+soon 很快
+
+now and then 偶尔;有时;不时 occasionally
+
+during 在…...的期间;在......期间的某个时候 The pond iced over during the night.
+
+nowadays 如今
+
+since 自……以后;自……以来;此后;之前
+
+lately 最近
+
+as soon as 一旦
+
+afterwards 后来
+
+temporarily 暂时
+
+earlier 早些时候
+
+now 现在
+
+after a while 不久;过了一会儿
+
+例:She answered the question immediately.
+
+她迅速回答了这个问题。
+
+
+
+### 表示顺序
+
+first 首先,第一
+
+second 第二
+
+third 第三
+
+then 然后
+
+finally 最后
+
+to begin with 首先,本来,一方面 To begin with, we must consider the faculties of the staff all-sidedly.
+
+first of all 首先
+
+in the first place 首先
+
+last 最后
+
+next 下一个
+
+above all 最重要的是
+
+last but not the least 最后一点,也是非常重要的一点
+
+first and most important 第一点也是最重要的一点
+
+例:First of all, you should obey rules as a student.
+
+作为一个学生,首先你要遵守学校里的规章制度。
+
+
+
+### 表示可能
+
+presumably 大概
+
+probably 可能
+
+perhaps 也许
+
+例:Perhaps he will not show up today.
+
+他今天可能不会露面了。
+
+
+
+### 表示解释
+
+in other words 换句话说
+
+in fact 事实上
+
+as a matter of fact 事实上
+
+that is 即;就是说;换言之
+
+namely 也就是;即是;换句话说 Namely, a return to white supremacy and institutional slavery.
+
+in simpler terms 简单来说 **To put it simply**, everything happens instantaneously. **In short,** the building would consist of two floors.
+
+例:He departed from his hometown, namely, London.
+
+他离开了自己的故乡,也就是伦敦。
+
+
+
+### 表示递进
+
+What is more 更重要的是;此外,而且
+
+in addition 另外,此外
+
+and 并且,以及
+
+besides 况且,再说;此外,以及
+
+also 而且;同样;还有
+
+furthermore 此外
+
+too 也;还
+
+moreover 此外;而且
+
+furthermore 此外
+
+as well as 以及
+
+additionally 另外
+
+again 再说;又
+
+例:Susan is a beautiful girl, what is more, she works hard all the time.
+
+苏珊是个漂亮的女孩,而且,她也一直努力工作。
+
+
+
+### 表示让步
+
+although 虽然
+
+after all 毕竟
+
+in spite of …尽管……
+
+despite 尽管
+
+even if 即使
+
+even though 尽管
+
+though 虽然
+
+admittedly 不可否认
+
+whatever may happen 不管三七二十一
+
+例:Although you told a lie before, we believe in you now.
+
+虽然你以前说过谎,但我们现在相信你。
+
+
+
+### 表示转折
+
+however 然而
+
+rather than 而不是;宁可…也不愿
+
+instead of 而不是...
+
+but 但
+
+yet 然而
+
+on the other hand 另一方面
+
+unfortunately 不幸的是
+
+whereas 然而;鉴于; 反之
+
+例:However, he did not pass the exam.
+
+然而,他没有通过考试。
+
+
+
+### 表示原因
+
+for this reason 因为这个原因
+
+due to 由于
+
+thanks to 多亏了
+
+because 因为
+
+because of 由于
+
+as 因为,由于
+
+since 因为,由于
+
+owing to 由于
+
+例:She broke up with her boyfriend because of a terrible quarrel.
+
+因为大吵了一架,她和男友分手了。
+
+
+
+### 表示结果
+
+as a result 结果....
+
+thus 因此
+
+hence 因此
+
+so 所以
+
+therefore 因此
+
+accordingly 因此,于是
+
+consequently 因此;结果;所以; 从而
+
+as a consequence 因此,结果
+
+例:Therefore, I decide to make an apology to him.
+
+因此,我决定向他道歉。
+
+
+
+### 表示总结
+
+on the whole 基本上,大体上;总的来说
+
+in conclusion 总之;最后
+
+in a word 总之
+
+to sum up 总而言之;概括地说
+
+in brief 简言之
+
+in summary 总之
+
+to conclude 最后;总之
+
+to summarize 简而言之
+
+in short 总之;简言之
+
+例:In conclusion, we d better take measures as soon as possible.
+
+总之,我们最好尽可能快采取措施。
+
+
+
+### 其他连接词
+
+mostly 主要是;通常;多半地
+
+occasionally 偶尔;有时
+
+currently 目前
+
+naturally 自然而然地
+
+mainly 主要是
+
+exactly 恰好地;正是
+
+evidently 毫无疑问地; 显然
+
+frankly 坦率地说;老实说 to be honest
+
+commonly 一般;通常;普遍
+
+for this purpose 为此;有鉴于此
+
+to a large extent 在很大程度上
+
+for most of us 对我们大多数人来说
+
+in many cases 在许多情况下
+
+in this case 在这种情况下
+
+例:Frankly, I do not mind her opinions at all.
+
+坦白说,我一点都不在乎她的看法。
+
+
+
+according to 根据
+
+## 参考
+
+- https://www.sohu.com/a/330378162_100219060
diff --git "a/_posts/Games/Xbox/2021-10-03-xbox\345\267\264\350\245\277\346\234\215\350\264\255\344\271\260\346\225\231\347\250\213.md" "b/_posts/Games/Xbox/2021-10-03-xbox\345\267\264\350\245\277\346\234\215\350\264\255\344\271\260\346\225\231\347\250\213.md"
deleted file mode 100644
index d8dd198080..0000000000
--- "a/_posts/Games/Xbox/2021-10-03-xbox\345\267\264\350\245\277\346\234\215\350\264\255\344\271\260\346\225\231\347\250\213.md"
+++ /dev/null
@@ -1,26 +0,0 @@
----
-layout: post
-category: Xbox
-title: xbox巴西服购买教程
-tags: Xbox
----
-
-## xbox巴西服购买教程
-
-
-
-1. 微软账号个人信息编辑,编辑所在国家,添加账单和送货地址,选巴西的。https://account.microsoft.com/profile/?fref=home.banner.profile-column.title
-
- ```
- 平台如果无法编辑删除,就新加个然后设为首选账单地址。
-
- Rua Estados Unidos, No. 1071
- 城市: CRISOLOGO
- 洲: 圣保罗州01427-001
- 巴西
- 61-21958270
- ```
-
-2. 添加付款方式,信用卡支付
-
-3. xbox登录西班牙服,记住购买时不能开加速器。选择已有购买方式就可以了。
\ No newline at end of file
diff --git a/_posts/Tech/AWS/2021-09-30-AWS Overall.md b/_posts/Tech/AWS/2021-09-30-AWS Overall.md
new file mode 100644
index 0000000000..4ee54bd11f
--- /dev/null
+++ b/_posts/Tech/AWS/2021-09-30-AWS Overall.md
@@ -0,0 +1,268 @@
+---
+layout: post
+category: AWS
+title: AWS Overall
+tags: AWS
+---
+
+## Cloud Notes
+
+IaaS、PaaS 和SaaS 的区别: 基础设施即服务(IaaS) 为云服务提供硬件,其中包括服务器、网络和存储。 平台即服务(PaaS) 除了提供IaaS 可提供的所有硬件之外,还提供操作系统和数据库。 软件即服务(SaaS) 提供了最多的支持,即为您的最终用户提供除其数据之外的所有服务。
+
+[参考](https://www.zhihu.com/question/20387284)
+
+如果你是一个网站站长,想要建立一个网站。不采用云服务,你所需要的投入大概是:买服务器,安装服务器软件,编写网站程序。
+
+现在你追随潮流,采用流行的云计算,
+
+如果你采用IaaS服务,那么意味着你就不用自己买服务器了,随便在哪家购买虚拟机,但是还是需要自己装服务器软件
+
+而如果你采用PaaS的服务,那么意味着你既不需要买服务器,也不需要自己装服务器软件,只需要自己开发网站程序
+
+如果你再进一步,购买某些在线论坛或者在线网店的服务,这意味着你也不用自己开发网站程序,只需要使用它们开发好的程序,而且他们会负责程序的升级、维护、增加服务器等,而你只需要专心运营即可,此即为SaaS。
+
+
+
+## AWS Overall Notes
+
+云从业者Note: https://github.com/Matthewow/AWS-CLF-StudyNotes
+
+
+
+很好overall: https://www.zhihu.com/question/22314873
+
+
+
+云的基础是计算、存储、网络,这三部分涵盖了互联网应用的各个方面,所有的云服务也是围绕这三部分去展开。
+
+
+
+AWS的服务是按照region来划分的,在部署自己的应用之前,需要选择region,比如美国有us-west, us-east regions, 中国有cn-north, cn-west regions。基本上按照服务用户所在的区域来选择region,服务中国的用户就选择中国的region,服务美国的用户就选择美国的region。否则这个网络传输的成本就非常高,而且中国区其独有的网络环境,导致其他地区的服务是无法访问的。一个region又划分为多个AZ (availability zone), 一般情况下,我们需要把服务器均匀分布在多个AZ,为了避免单点故障,也就是我们所说的灾备多活。
+
+
+
+选择好region后,就需要部署自己的[VPC](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/vpc/home) (virtual private cloud),一个VPC定义了一个私有隔离的网络环境。在VPC里面,我们部署所有的计算、网络资源。计算资源就是我们的服务器,AWS最出名的就是[EC2](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/ec2) (elastic compute cloud)。在部署EC2时,我们首先预估应用需要消耗的计算资源(cpu,磁盘,带宽等等),选择EC2的型号和数量。然后将所有的EC2分割成多个[ASG](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/ec2autoscaling/home) (auto scaling group), 一个ASG就相当于一个可弹性收缩的机器群,只要定义好扩容和缩容的指标,ASG就可以自己分配机器的数量。比如我们要求在EC2 CPU升到40%就扩容一倍,在CPU降到10%就缩容一倍,这样一个ASG里面机器CPU的消耗就一直均衡地保持在20%左右。具体分割成几个ASG,一般依据这个region有几个AZ来定,比如[us-east-1 region](https://www.zhihu.com/search?q=us-east-1+region&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra={"sourceType"%3A"answer"%2C"sourceId"%3A2333079486})有3个AZ,就分割成三个ASG,一个AZ部署一个ASG,这三个ASG在接受流量方面没有任何区别。接下来就是网络资源,每个VPC都有自己的ACL(acess control list),一个ACL定义了inbound rules和outbound rules,分别限制了访问IP的限制和访出IP的限制。VPC的网络资源被划分成多个子网subnets,一个subnet是一组IP地址的集合,前面说到的ASG就部署在[subnet](https://www.zhihu.com/search?q=subnet&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra={"sourceType"%3A"answer"%2C"sourceId"%3A2333079486})里面。一般来说subnet的数据量跟region AZ的数据成正比,每个AZ分配一个public subnet和一个private subnet,那么us-east-1的VPC就会有6个subnets。我们将ASG部署在private subnet里面,只允许vpc内部的IP访问,用于保护机器资源。因为public subnet是对外的,所以我们在public subnet里面部署ELB (elastic load balancer),用于接受vpc外的请求。有人会问如果我们想登录到ASG的EC2上面,应该怎么做?解决办法是在public subnet里面launch一个跳板机,我们先登录到跳板机,然后从跳板机里面登录到EC2上面。
+
+接下来就是存储资源,AWS提供多种选择,我们最熟悉的应该就是[S3](https://link.zhihu.com/?target=https%3A//s3.console.aws.amazon.com/s3/home) (simple storage service)。S3是面向对象存储的服务,可以用来做数据归档、备份、恢复,或者作为数据分析、AI、Machine learning的数据湖来使用。通俗的理解就是我们的磁盘,它存储的key就是一个目录路径,相当于磁盘的目录,value是一个object,相当于文件或者子目录。在线的存储根据功能的不同也有很多选择,比较出名的而且是我用过的有三个。第一个是[DynamoDB](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/dynamodb/home),它是document-based NoSQL DB。DynamoDB是Amazon内部使用最频繁的数据,几乎90%的存储都会选择DynamoDB,绝对地超过RDS。这个现象的原因在这篇文章[Dynamo: Amazon’s Highly Available Key-value Store](https://link.zhihu.com/?target=https%3A//www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf)里面有解释,同时DDIA (Design [data-intensive application](https://www.zhihu.com/search?q=data-intensive+application&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra={"sourceType"%3A"answer"%2C"sourceId"%3A2333079486})) 这本书也给了同样的解释。总结就是:Amazon内部的存储90%以上都是单对多的关系,DynamoDB作为一个分布式的key-value DB,在可用性、扩展性方面非常适合这种单对多的存储结构。而且DynamoDB是最终一致性,进一步增加了它的可用性。关于DynamoDB我后面会单独出一篇介绍它的blog。而对于多对多的存储,我们就会用[RDS](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/rds) (relational database service),RDS字面理解就是[关系型数据库](https://www.zhihu.com/search?q=关系型数据库&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra={"sourceType"%3A"answer"%2C"sourceId"%3A2333079486})。AWS RDS上面托管了多种关系型数据库,包括mysql、oracle、MS SQL、aurora、MariaDB和PostgreSQL这六种数据库,其中我使用过mysql和aurora。在Amazon内部,[aurora](https://link.zhihu.com/?target=https%3A//docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/CHAP_AuroraOverview.html)使用的更频繁,它是兼容mysql和PostgreSQL的结合体,具体内容可见这篇文章[Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases](https://link.zhihu.com/?target=https%3A//www.allthingsdistributed.com/files/p1041-verbitski.pdf)。我使用的最后一种存储是[AWS elasticsearch](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/esv3/home) ,当时为了实现一个搜索功能,因为涉及到模糊匹配,全文搜索,就采用了[aws es](https://www.zhihu.com/search?q=aws+es&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra={"sourceType"%3A"answer"%2C"sourceId"%3A2333079486})。aws es跟主流的es已经分道扬镳,目前在aws上面称为openSearch service。
+
+介绍完计算、网络、存储,接下来我想从应用的角度,讲讲在实际应用中,我们应该怎样使用AWS的服务。首先说消息队列,这个广泛应用的基础功能,AWS提供了[SQS](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/sqs/v2/home)和[SNS](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/sns/v3/home)。SQS是一个分布式的队列消息service,SNS是一个分布式的发布-订阅消息service。具体有人会问这两者有什么区别,这里给出了回答: [What is the difference between Amazon SNS and Amazon SQS?](https://link.zhihu.com/?target=https%3A//stackoverflow.com/questions/13681213/what-is-the-difference-between-amazon-sns-and-amazon-sqs)。 在我的实践中,SQS和SNS会结合起来使用,首先应用发布消息到SQS的queue里面,然后SNS消费这个queue的消息,放到自身的topic里面持久保存,然后其他的应用订阅这个topic,消费里面的消息。
+
+
+
+建设完一个应用,然后就是DevOps。AWS在[托管代码](https://www.zhihu.com/search?q=托管代码&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra={"sourceType"%3A"answer"%2C"sourceId"%3A2333079486})、编译代码、部署应用、监控应用方面也提供了一整套服务,从前到后,[codeCommit](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/codesuite/codecommit) -> [codeArtifact](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/codesuite/codeartifact) -> [codeBuild](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/codesuite/codebuild) -> [codeDeploy](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/codesuite/codedeploy) -> [codePipeline](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/codesuite/codepipeline)。这一套实现了应用的continuous integration和continuous deployment。在监控方面,AWS提供了[cloudWatch](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/cloudwatch),可以以应用维度收集日志,视图化监控指标。AWS还提供了一个服务叫cloudFormation,这个服务在应用迁移的过程中,非常有用。Amazon内部很多都是国际化业务,应用需要部署到各个region。cloudFormation以yaml文本的形式记录下一个应用涉及到的各个服务资源配置,放在一个template里面。迁移到不同的region时,只需要一键run coudFormation template, 就可以部署好所有的AWS资源。
+
+
+
+Notes:
+
+- region: 包含多个AZ, named by location 用aws需要选个region
+
+- AZ: availability zone. 包含一主多从的cluster,多个data center, 可以有另一个AZ继续保持主从。 region分多个AZ主要是为了容灾。
+
+- region ---> AZ ----> data center 都是一对多。 一般情况下,region之间不会保持同步,互相独立,除非客户允许。
+
+
+
+
+
+
+
+- 选择region考量: compliance, latency, price, service availability
+
+## 术语
+
+- IAM: identify and access management. 同account也是aws account level, account每月会进行计费,可以任意region里创建资源, work globally. 像s3等存储都是region level. EC2等就是AZ level. 意味着一个ec2不能分布在两个AZ。 IAM可以创建用户,然后授予权限给某个group
+
+- SQS: simple queue service
+
+- SNS: simple notification service. 发一些同事用的,比如发短信等。
+
+- Aws route 53是 aws DNS
+
+- Amazon CouldFront 是CDN
+
+- 对象存储
+
+ - S3: simple storage service
+
+- cloudwatch for monitoring
+
+- ELB: elastic load balancer
+
+- EC2是 virtual machines. 全称: elastic compute cloud. 一共三种compute资源: vm, container services, serverless
+
+- AMI: amazon machine image 就是一堆配置,比如什么系统,安装哪些附加软件。可使用AMI启动一个同配置的实例。 类似docker的image
+
+- AWS Elastic Beanstalk 是一个应用程序管理平台,可以帮助客户轻松部署和扩展 Web 应用程序和服务。它将构建块(例如 EC2、Amazon RDS、Elastic Load Balancing、AWS Auto Scaling 和 Amazon CloudWatch)的预置、应用程序的部署、运行状况监控从用户身上分离出来,让用户可以集中精力编写代码。您只需指定要部署的容器映像、CPU 和内存要求、端口映射和容器链接即可。
+
+ Elastic Beanstalk 将自动处理所有的具体事务,包括预置 Amazon ECS 集群、均衡负载、自动扩展、监控以及在集群中放置容器。如果您希望利用容器的各种优势,但只想通过上传容器映像,在开发到生产等环节部署应用程序时享受到简易性,则 Elastic Beanstalk 非常适合。如果您需要对自定义应用程序架构进行更多精细化的控制,则可以直接使用 Amazon ECS。
+
+- EBS: elastic block store. EC2也需要本地存储,这就是EBS 块存储。例如SSD等。它是外部挂载形式提供的,实例关机了,数据也还在,也可以做备份。适合那种临时数据,而非长期存储。一次只能挂载到一个AZ里的一个实例。 如果想多个实例连一个存储,可以用EFS/FSx, 前者linux,后者windows。
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Example: build an application like facebook ,a social media app.
+
+AWS介绍视频: [youtube](https://www.youtube.com/watch?v=Z3SYDTMP3ME&ab_channel=AWSTrainingCenter)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+加一些安全组件,IAM负责每个附件是否可访问,account管理范围等。 KMS负责数据的加密。 ACM负责access certificate management, 比如https证书等,在ELB这块。 WAF是防火墙,比如防止Ddos攻击之类的,在elb之前。Inspectoer负责监控每个service的安全,类似容器里一个agent。
+
+
+
+
+
+
+
+codeCommit类似github这样代码仓库。
+
+## Example: WordPress
+
+[link](http://www.cloudbin.cn/?p=2647)
+
+## 考证
+
+[参考](https://zhuanlan.zhihu.com/p/138652055)
+
+先考**AWS Certified Solutions Architect - Associate** AWS 认证助理级解决方案架构师考试,这门考试更注重 AWS 的架构设计。助理级解决方案架构师需要基本了解 AWS 的几个基础的组件,比如 EC2,VPC, IAM, S3, Route53 等,掌握它们分别是什么,使用场景是什么,和传统数据中心的区别和优势等等
+
+
+
+云从业者那个可以看这个: https://github.com/Matthewow/AWS-CLF-StudyNotes
+
+
+
+
+
+## 对象存储: S3及S3 Glacier
+
+> [官网](https://aws.amazon.com/s3/storage-classes/)
+
+Amazon S3 is object-level storage, which means that if you want to change a part of a file, you have to make the change and then re-upload the entire modified file. 对象存储,比较像字节的TOS。 也是以bucket隔离的,然后bucket可设置是否公开,可设置每个文件多版本, 可作为一个静态博客的host。 [对象存储参考](https://mafulong.github.io/2022/10/06/%E5%9D%97%E5%AD%98%E5%82%A8%E5%92%8C%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8%E5%92%8C%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8/)
+
+Amazon S3 Glacier is a great storage choice when low storage cost is paramount, your data is rarely retrieved, and retrieval latency of several hours is acceptable. If your application requires fast or frequent access to your data, consider using Amazon S3. Objects stored in Amazon S3 Glacier are called *archives*. 相比s3,价格便宜,适合平时不太访问的归档数据。
+
+
+
+## 计算层:EC2
+
+
+
+3种付费方案:
+
+1. on-demand, 运行时收费,按秒计费,价格固定。
+2. Reserved instances. (RIs) 预订 选定期的,有折扣。这种情况下即便选择不预付,非运行时也算收费。 它需要绑定一个instance type.
+3. Spot instances. 类似出钱,然后aws自己评估这价格可以给几个实例这样。如果不够就掐掉实例。是最便宜的,但需要容忍突然停。
+
+Dedicated hosts: 把物理机控制也给你,贵。和其他公司隔离开。
+
+
+
+## 数据库
+
+RDB: Amazon RDS, Redshit, Aurora.
+
+NoSQL: DynamoDB, Nepture, ElastiCache
+
+
+
+
+
+## IAM
+
+
+
+IAM (Identity Access Management) 由这些东西组成:
+
+- Users
+- Groups 用户组
+- Roles 角色可以分配给AWS服务,让AWS服务有访问其他AWS资源的权限。 举个例子,我们可以赋予EC2实例一个角色,让其有访问S3的读写权限(后面课程会有关于这一点的实操)
+- Policy Documents 策略。 策略具体定义了能访问哪些AWS资源,并且能执行哪些操作(比如List, Read, Write等) 策略的文档以JSON的格式展现
+
+```
+// An example policy: allowing any access to any resource
+{
+ "Version": "2012-10-17"
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "*",
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+
+
+IAM 是 Global的,不属于任何一个 region
+
+Root 账号是你第一次配置账号的时候创建的,它拥有完全的 Admin aceess
+
+新 User 刚创建时是没有权限的。
+
+
+
+首先要知道, AWS 提供了许许多多种类的服务或者说资源供我们使用, 这些资源挂在我们的 AWS 账户下, 这个账户就是我们第一次用 AWS 时用邮箱和密码申请的, 以后我们所有的资源申请, 账单费用都会挂到这个户头.
+
+那么 IAM 算什么呢? IAM 不是 AWS 的专有名词, 它是一个通用概念, 全称是 Identity and Access Management, 其要解决的两个问题就是身份认证 (Authtication) 和授权 (Authorization). 为此 AWS IAM 设计了用户, 角色, 用户组, 权限策略等概念和机制
+
+
+
+场景
+
+1. 自己公司的员工想访问 AWS Console 查看所在项目组的基础设施
+2. AWS 账户里的 EC2/Lambda 实例想访问同账户下的一台 RDS
+3. 公网里用户的手机想要访问我们的后端存储(借助 API Gateway)
+
+
+
+AWS IAM 并不关心你创建的 IAM User 是给人用还是给程序用
+
+
+
+AWS 官方建议 root 用户的唯一用途, 就是[用来创建你的第一个 IAM 用户](https://link.zhihu.com/?target=https%3A//docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html%23lock-away-credentials), 把这第一个 IAM 用户设置为管理员, 然后以后的工作都用这个管理员用户来进行.
+
+
+
+## SNS vs SQS
+
+AWS提供了[SQS](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/sqs/v2/home)和[SNS](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/sns/v3/home)。SQS是一个分布式的队列消息service,SNS是一个分布式的发布-订阅消息service。具体有人会问这两者有什么区别,这里给出了回答: [What is the difference between Amazon SNS and Amazon SQS?](https://link.zhihu.com/?target=https%3A//stackoverflow.com/questions/13681213/what-is-the-difference-between-amazon-sns-and-amazon-sqs)。 在我的实践中,SQS和SNS会结合起来使用,首先应用发布消息到SQS的queue里面,然后SNS消费这个queue的消息,放到自身的topic里面持久保存,然后其他的应用订阅这个topic,消费里面的消息。
+
+
+
+sqs是一对一,不能一对多,消息可持久化,不推只能等拉,拉完就删除。
+
+sns可一对多,不能持久化,push模型。
+
+sqs及aws笔记,更全, [link](http://www.cloudbin.cn/?p=2530)
+
+
+
+## 参考
+
+[参考](http://www.cloudbin.cn/?tag=aws)
+
diff --git a/_posts/Tech/AWS/2022-10-04-AWS network.md b/_posts/Tech/AWS/2022-10-04-AWS network.md
new file mode 100644
index 0000000000..a0826ac349
--- /dev/null
+++ b/_posts/Tech/AWS/2022-10-04-AWS network.md
@@ -0,0 +1,324 @@
+---
+layout: post
+category: AWS
+title: AWS Network
+tags: AWS
+---
+
+# AWS network
+
+## 名词解释
+
+[参考](https://docs.amazonaws.cn/vpc/latest/userguide/what-is-amazon-vpc.html)
+
+- **Virtual Private Cloud (VPC)**
+
+ [VPC](https://docs.amazonaws.cn/vpc/latest/userguide/configure-your-vpc.html) 是一个虚拟网络,与您在自己的数据中心中运行的传统网络极为相似。创建 VPC 后,您可以添加子网。翻译成中文是虚拟私有云。
+
+- **子网**
+
+ [子网](https://docs.amazonaws.cn/vpc/latest/userguide/configure-subnets.html)是您的 VPC 内的 IP 地址范围。子网必须位于单个可用区中。在添加子网后,您可以在 VPC 中部署 Amazon 资源。
+
+- **IP 寻址**
+
+ 您可以将 IPv4 地址和 IPv6 地址分配到 VPC 和子网。您还可以将您的公有 IPv4 和 IPv6 GUA 地址带到 Amazon 并将其分配到 VPC 中的资源,例如 EC2 实例、NAT 网关和网络负载均衡器。创建 VPC 时,需要为其分配一个 IPv4 CIDR 块(一系列私有 IPv4 地址)、一个 IPv6 CIDR 块或同时分配两种 CIDR 块(双堆栈)。
+
+ 私有 IPv4 地址无法通过 Internet 访问。IPv6 地址具有全球唯一性,可以配置为保持私有或通过互联网进行访问。
+
+- **路由选择**
+
+ 使用[路由表](https://docs.amazonaws.cn/vpc/latest/userguide/VPC_Route_Tables.html)决定将来自您的子网或网关的网络流量定向到何处。
+
+- **网关和端点**
+
+ [网关](https://docs.amazonaws.cn/vpc/latest/userguide/extend-intro.html)将您的 VPC 连到其他网络。例如,使用[互联网网关](https://docs.amazonaws.cn/vpc/latest/userguide/VPC_Internet_Gateway.html)将您的 VPC 连接到网络。使用 [VPC 端点](https://docs.amazonaws.cn/vpc/latest/privatelink/privatelink-access-aws-services.html)私下连接到 Amazon Web Services,无需使用互联网网关或 NAT 设备。
+
+- **对等连接**
+
+ 使用 [VPC 对等连接](https://docs.amazonaws.cn/vpc/latest/peering/)在两个 VPC 中的资源之间路由流量。
+
+- **流量镜像**
+
+ 从网络接口[复制网络流量](https://docs.amazonaws.cn/vpc/latest/mirroring/),然后将其发送到安全和监控设备进行深度数据包检查。
+
+- **中转网关**
+
+ 将[中转网关](https://docs.amazonaws.cn/vpc/latest/userguide/extend-tgw.html)用作中央枢纽,以在 VPC、VPN 连接和 Amazon Direct Connect 连接之间路由流量。
+
+- **VPC 流日志**
+
+ [流日志](https://docs.amazonaws.cn/vpc/latest/userguide/flow-logs.html)捕获有关在 VPC 中传入和传出网络接口的 IP 流量的信息。
+
+- **VPN 连接**
+
+ 使用 [Amazon Virtual Private Network (Amazon VPN)](https://docs.amazonaws.cn/vpc/latest/userguide/vpn-connections.html) 将 VPC 连接到您的本地网络。
+
+## VPC
+
+**Amazon Virtual Private Cloud (Amazon VPC)**允许你在已定义的虚拟网络内启动AWS资源。这个虚拟网络与你在数据中心中运行的传统网络极其相似,并会为你提供使用AWS的可扩展基础设施的优势。
+
+简单来说,VPC就是一个AWS用来隔离你的网络与其他客户网络的虚拟网络服务。在一个VPC里面,用户的数据会逻辑上地与其他AWS租户分离,用以保障数据安全。
+
+**可以简单地理解为一个VPC就是一个虚拟的数据中心**,在这个虚拟数据中心内我们可以创建不同的子网(公有网络和私有网络),搭建我们的网页服务器,应用服务器,数据库服务器等等服务。
+
+### VPC有如下特点
+
+- VPC内可以创建多个子网
+
+- 可以在选择的子网上启动EC2实例
+
+- 在每一个子网上分配自己规划的IP地址
+
+- 每一个子网配置自己的路由表
+
+- 创建一个Internet Gateway并且绑定到VPC上,让EC2实例可以访问互联网
+
+- VPC对你的AWS资源有更安全的保护
+
+- 部署针对实例的安全组(Security Group)
+
+- 部署针对子网的**网络控制列表(Network Access Control List)**
+
+- 一个VPC可以跨越多个可用区(AZ)
+
+- **一个子网只能在一个可用区(AZ)内**
+
+- 安全组(Security Group)是
+
+ 有状态的
+
+ ,而网络控制列表(Network Access Control List)是
+
+ 无状态的
+
+ - 有状态:如果入向流量被允许,则出向的响应流量会被自动允许
+ - 无状态:入向规则和出向规则需要分别单独配置,互不影响
+ - 具体的区别挨踢小茶会在后续的章节详细讲解
+
+- VPC的子网掩码范围是从/28到/16,不能设置在这个范围外的子网掩码
+
+- VPC可以通过Virtual Private Gateway (VGW) 来与企业本地的数据中心相连
+
+- VPC可以通过AWS PrivateLink访问其他AWS账户托管的服务(VPC终端节点服务)
+
+
+
+### VPC Peering
+
+**VPC Peering**可是两个VPC之间的网络连接,通过此连接,你可以使用IPv4地址在两个VPC之间传输流量。这两个VPC内的实例会和如果在同一个网络一样彼此通信。
+
+- 可以通过AWS内网将一个VPC与另一个VPC相连
+- 同一个AWS账号内的2个VPC可以进行VPC Peering
+- 不同AWS账号内的VPC也可以进行VPC Peering
+- 不支持VPC Transitive Peering
+ - 如果VPC A和VPC B做了Peering
+ - 而且VPC B和VPC C做了Peering
+ - 那么VPC A是**不能**和VPC C进行通信的
+ - 要通信,只能将VPC A和VPC C进行Peering
+
+### 默认VPC
+
+- 在每一个区域(Region),AWS都有一个默认的VPC
+- 在这个VPC里面所有子网都绑定了一个路由表,其中有默认路由(目的地址 0.0.0.0/0)到互联网
+- 所有在默认VPC内启动的EC2实例都可以直接访问互联网
+- 在默认VPC内启动的EC2实例都会被分配公网地址和私有地址
+
+如下图所示,我们在某一个区域内有一个VPC,这个VPC的网络是172.31.0.0/16
+
+在这个VPC内有2个子网,分别是172.31.0.0/20 和 172.31.16.0/20。这两个子网内都有一个EC2实例,每一个实例拥有一个该子网的私有地址(172.31.x.x)以及一个AWS分配的公网IP地址(203.0.113.x)。
+
+这两个实例关联了一个主路由表,该路由表拥有一个访问172.31.0.0/16 VPC内流量的路由条目;还有一个目的为 0.0.0.0/0 的默认路由条目,指向Internet网关。
+
+因此这两个实例都可以通过Internet网关访问外网。
+
+
+
+### VPC终端节点(VPC Endpoints)
+
+在一般的情况下,如果你需要访问S3服务,EC2实例或者DynamoDB的资源,你需要通过Internet公网来访问这些服务。有没有更快速、更安全的访问方式呢?
+
+**VPC终端节点(VPC Endpoints)**提供了这种可能性。
+
+VPC终端节点能建立VPC和一些AWS服务之间的高速、私密的“专线”。这个专线叫做PrivateLink,使用了这个技术,你无需再使用Internet网关、NAT网关、VPN或AWS Direct Connect连接就可以访问到一些AWS资源了!
+
+
+
+## 工作原理
+
+[参考](https://docs.amazonaws.cn/vpc/latest/userguide/how-it-works.html)
+
+### IP 寻址
+创建 VPC 时,需要为其分配一个 IPv4 CIDR 块(一系列私有 IPv4 地址)、一个 IPv6 CIDR 块或同时分配两种 CIDR 块(双堆栈)。
+
+私有 IPv4 地址无法通过 Internet 访问。IPv6 地址具有全球唯一性,可以配置为保持私有或通过互联网进行访问。
+
+公有 IP 地址将从 Amazon 的公有 IP 地址池分配,它不与您的账户关联。在公有 IP 地址与您的实例取消关联后,该地址即释放回该池,并且不再可供您使用。您不能手动关联或取消关联公有 IP 地址。而是在某些情况下,我们从您的实例释放该公有 IP 地址,或向其分配新地址。有关更多信息,请参阅适用于 Linux 实例的 Amazon EC2 用户指南 中的公有 IP 地址。
+
+### 访问 Internet
+
+> 私有网络不能访问互联网,需要互联网网关,私有网络内部之间可通信。
+
+原定设置 VPC 包含一个互联网网关,而且每个原定设置子网都是公有子网。您在默认子网中启动的每个实例都有一个私有 IPv4 地址和一个公有 IPv4 地址。这些实例可以通过 Internet 网关与 Internet 通信。通过互联网网关,您的实例可通过 Amazon EC2 网络边界连接到 Internet。
+
+默认情况下,您启动到非默认子网中的每个实例都有一个私有 IPv4 地址,但没有公有 IPv4 地址,除非您在启动时特意指定一个,或者修改子网的公有 IP 地址属性。这些实例可以相互通信,但无法访问 Internet。
+
+您可以通过以下方式为在非默认子网中启动的实例启用 Internet 访问:将一个互联网网关附加到该实例的 VPC(如果其 VPC 不是默认 VPC),然后将一个弹性 IP 地址与该实例相关联。
+
+或者,您还可以使用网络地址转换 (NAT) 设备,以允许 VPC 中的实例发起到互联网的出站连接,但阻止来自互联网的未经请求的入站连接。NAT 将多个私有 IPv4 地址映射到一个公有 IPv4 地址。您可以使用弹性 IP 地址配置 NAT 设备,并通过互联网网关将其与互联网相连。您可以通过 NAT 设备将私有子网中的实例连接到互联网,NAT 设备会将来自实例的流量路由到互联网网关,并将所有响应路由到该实例。
+
+如果您将 IPv6 CIDR 块与 VPC 关联并为实例分配 IPv6 地址,则实例可以通过互联网网关通过 IPv6 连接到互联网。或者,实例也可以使用仅出口互联网网关经由 IPv6 发起到互联网的出站连接。IPv6 流量独立于 IPv4 流量;您的路由表必须包含单独的 IPv6 流量路由。
+
+
+
+默认情况下,默认子网为公有子网,因为主路由表会将指定发往 Internet 的子网流量发送到 Internet 网关。
+
+
+
+### NAT
+
+NAT的全程是“**Network Address Translation**”,中文解释是“**网络地址转换**”,它可以让整个机构只使用一个公有的IP地址出现在Internet上。
+
+NAT是一种把内部私有地址(192.168.1.x,10.x.x.x等)转换为Internet公有地址的协议,它一定程度上解决了公网地址不足的问题。
+
+- NAT实例需要创建在公有子网内
+
+
+
+
+
+**堡垒机(Bastion Host)**又叫做跳板机(Jump Box),主要用于运维人员远程登陆服务器的集中管理。运维人员首先登陆到这台堡垒机(公网),然后再通过堡垒机管理位于内网的所有服务器。
+
+堡垒机可以对运维人员的操作行为进行控制和审计,同时可以结合Token等技术达到更加安全的效果。
+
+## VPC场景
+
+**带单个公有子网的 VPC**: 此场景的配置包含一个有单一公有子网的 Virtual Private Cloud (VPC),以及一个 Internet 网关以启用 Internet 通信。如果您要运行单一层级且面向公众的 Web 应用程序,如博客或简单的网站,则我们建议您使用此配置。
+
+**带有公有和私有子网的 VPC (NAT)**:这个场景的配置包括一个有公有子网和私有子网的 Virtual Private Cloud (VPC)。如果您希望运行面向公众的 Web 应用程序,并同时保留不可公开访问的后端服务器,我们建议您使用此场景。常用例子是一个多层网站,其 Web 服务器位于公有子网之内,数据库服务器则位于私有子网之内。您可以设置安全性和路由,以使 Web 服务器能够与数据库服务器建立通信。
+
+公有子网中的实例可直接将出站流量发往 Internet,而私有子网中的实例不能这样做。但是,私有子网中的实例可使用位于公有子网中的网络地址转换 (NAT) 网关访问 Internet。数据库服务器可以使用 NAT 网关连接到 Internet 进行软件更新,但 Internet 不能建立到数据库服务器的连接。
+
+## **Security Groups(安全组)**
+
+[参考](https://zhuanlan.zhihu.com/p/151419823)
+
+VPC 网络安全组标志 VPC 中的哪些流量可以发往 EC2 实例或从 EC2 发出。安全组指定具体的入向和出向流量规则,并精确到源地址(入向)和目的地址(出向)。这些安全组是与 EC2 实例而非子网关联的。
+默认情况下,流量只允许出,不允许入。
+
+
+
+Security Group(SG)通过控制IP和端口来控制出站入站规则,可以用于EC2,RDS及下面将要用到的VPC Endpoint。
+
+
+
+## 网络ACL(NACL)
+
+**网络访问控制列表(NACL)**与安全组(Security Group)类似,它能在子网的层面控制所有入站和出站的流量,为VPC提供更加安全的保障。
+
+
+
+- 在你的**默认VPC**内会有一个默认的网络ACL(NACL),它会**允许**所有入向和出向的流量
+- 你可以创建一个自定义的网络ACL,在创建之初所有的入向和出向的流量都会被**拒绝**,除非进行手动更改
+- 对于所有VPC内的子网,每一个子网都需要关联一个网络ACL。如果没有关联任何网络ACL,那么子网会关联默认的网络ACL
+- 一个网络ACL可以关联多个子网,但一个子网只能关联一个网络ACL
+- 网络ACL包含了一系列(允许或拒绝)的规则,网络ACL会按顺序执行,一旦匹配就结束,不会再继续往下匹配
+- 网络ACL有入向和出向的规则,每一条规则都可以配置允许或者拒绝
+- 网络ACL是无状态的(安全组是有状态的)
+ - 被允许的入向流量的响应流量必须被精准的出向规则所允许(反之亦然)
+ - 一般至少需要允许临时端口(TCP 1024-65535)
+ - 关于临时端口的知识,可以参见[这里](https://docs.aws.amazon.com/zh_cn/AmazonVPC/latest/UserGuide/VPC_ACLs.html#VPC_ACLs_Ephemeral_Ports)
+
+## Difference between Internet Gateway and NAT Gateway
+
+
+
+参考
+
+- Internet Gateway (IGW) allows instances with public IPs to access the internet.
+- NAT Gateway (NGW) allows instances with no public IPs to access the internet.
+
+## 参考
+
+[参考](https://juejin.cn/post/6949072638145003556)
+
+大部分 AWS 服务都需要以 VPC 为基础进行构建,比如最常用的 EC2,ALB,及无服务器服务 ECS Fargate。 vb
+
+当我们在一个 VPC 中创建 Subnet 时需要给 Subnet 选择一个 AZ(Availability Zone),一个 Subnet 只能选择建在一个 AZ 中。
+
+
+
+**选择region**
+
+因为国内政策法规原因,AWS 在中国的服务与 AWS Global 服务略有不同。
+
+AWS Global 的 Region 之间是通过主干网相连的,AWS 中国区的服务没有通过主干网与 AWS Global 相连,只有中国区内部两个 Region,北京和宁夏是相连接的。
+
+在创建 VPC 时并不需要添写 AZ(Availability Zone)信息,VPC 只与 Region 有关。
+
+
+
+Subnet 是最终承载大部分 AWS 服务的组件,比如 EC2, ECS Fargate,RDS。
+
+Subnet 分为两种 Private Subnet 和 Public Subnet。
+
+简单来说,不能直接访问 internet 的 Subnet 就是 Private Subnet,能直接访问 internet 的就是 Public Subnet。
+
+
+
+Security Group(SG)通过控制IP和端口来控制出站入站规则,可以用于EC2,RDS及下面将要用到的VPC Endpoint。
+
+
+
+VPC Endpoint用来直接连接VPC与AWS相关服务,比如RDS AIP,S3。
+
+当系统安全要求比较高时,EC2处于的Subnet可能被限制,无法访问internet,这时EC2就无法访问AWS的一些服务,比如SSM。
+
+这时我们可以利用VPC Endpoint把VPC和所需要访问的服务连接起来,然后EC2就可以不经internet访问到所需的服务。
+
+
+
+[参考](https://juejin.cn/post/6954169148318433288)
+
+RT(Route Table)与Subnet相关连,用来描述网络路由。IGW: Internet gateway IGW是一个独立的组件配置在VPC上,使得VPC可以访问internet
+
+我们给VPC加了IGW之后,需要修改Subnet相关的路由,确保访问Internet的请求发送到IGW。
+
+每个VPC中有一个默认的主RT,自动关联VPC内的每一个Subnet。我们现在为Subnet “ts-public-1”单独创建一个新的RT。
+
+
+
+- 新建的Subnet就是Private Subnet
+- 在Private Subnet中配置了到IGW的路由后,就变成Public Subnet
+- Public Subnet中的EC2还要再配置一个Public IP或者EIP就可以访问Internet
+- 如果EC2可以访问internet,其关联的Security Group入站规则如果允许从internet访问,那么这个EC2就可以从internet中直接访问到。
+
+
+
+1. 实践中我们把应用程序,数据库放在Private Subnet中,阻止从internet访问。把堡垒机和ALB(Application Load balancer)放在Public Subnet,允许从internet访问。
+
+2. 一般我们会建两套Public Subnet和Private Subnet,分别放在不同的AZ中,防止其中一个AZ出问题。这时如果配置NAT,也需要在两个Public Subnet中各配置一个NAT。
+
+
+
+[参考](http://www.cloudbin.cn/?tag=aws) 暂无Note
+
+## 总结
+
+VPC里多个AZ, 每个AZ都需要至少一个子网,默认是公有子网。但如果有internet访问不到的实例或者数据库,则需建个私有子网,私有子网默认不能访问internet,internet也不能访问私有子网。
+
+要走互联网必须走internet gateway,它对整个vpc生效, public subnet可直接通过IGW与互联网互联,私有子网再通过NAT走公有子网是可以访问internet的,反向不能。
+
+和互联网连接时都需要有个公网ip,这个是从amazon分配的。
+
+
+
+## Route 53
+
+**Amazon Route 53**是一种高可用、高扩展性的云DNS服务。
+
+不同的DNS记录:
+
+- **CNAME** – CNAME (Canonical Name)可以将一个域名指向另一个域名。比如将aws.xiaopeiqing.com指向xiaopeiqing.com
+- Alias记录 – 和CNAME类似,又叫做别名记录,可以将一个域名指向另一个域名。
+ - **和CNAME最大的区别是,Alias可以应用在根域(Zone Apex)。即可以为xiaopeiqing.com的根域创建Alias记录,而不能创建CNAME**
+ - 别名记录可以节省你的时间,因为Route53会自动识别别名记录所指的记录中的更改。例如,假设example.com的一个别名记录指向位于lb1-1234.us-east-2.elb.amazonaws.com上的一个ELB负载均衡器。如果该负载均衡器的IP地址发生更改,Route53将在example.com的DNS应答中自动反映这些更改,而无需对包含example.com的记录的托管区域做出任何更改。 弹性负载均衡器(ELB)没有固定的IPv4地址,在使用ELB的时候永远使用它的DNS名字。很多场景下我们需要绑定DNS记录到ELB的endpoint地址,而不绑定任何IP
diff --git a/_posts/Tech/AWS/2022-11-18-AWS Compute.md b/_posts/Tech/AWS/2022-11-18-AWS Compute.md
new file mode 100644
index 0000000000..5c602ab6fa
--- /dev/null
+++ b/_posts/Tech/AWS/2022-11-18-AWS Compute.md
@@ -0,0 +1,130 @@
+---
+layout: post
+category: AWS
+title: AWS Compute
+tags: AWS
+---
+
+## AWS Compute
+
+## AMI
+
+AMI: amazon machine image 就是一堆配置,比如什么系统,安装哪些附加软件。可使用AMI启动一个同配置的实例。 类似docker的image
+
+**Amazon Machine Image (AMI)** 是亚马逊AWS提供的系统镜像,这个AMI包含了如下的信息:
+
+- 由实例的操作系统、应用程序和应用程序相关的配置组成的模板
+- 一个指定的需要在实例启动时附加到实例的卷的信息(比方说定义了使用8 GB的General Purpose SSD卷)
+
+下图所示的是AMI的生命周期,你可以创建并注册一个AMI,并且可以使用这个AMI来创建一个EC2实例。同时你也可以将这个AMI复制到同一个AWS区域或者不同的AWS区域。你同样也可以注销这个AMI镜像。
+
+
+
+- **AMI是区域化的**,只能使用本区域的AMI来创建实例;但你可以将AMI从一个区域复制到另一个区域
+
+
+
+
+
+## 弹性伸缩(Auto Scaling)
+
+**亚马逊弹性伸缩(Auto Scaling)**能**自动地**增加/减少EC2实例的数量,从而让你的应用程序一直能保持可用的状态。
+
+你可以预定义Auto Scaling,使其在需求高峰期自动增加EC2实例,而在需求低谷自动减少EC2实例。这样不仅能让你的应用程序一直保持健康的状态,而且也节省了你为EC2实例所付出的费用。
+
+Auto Scaling 适用于那些需求稳定的应用程序,同时也适用于在每小时、每天、甚至每周都有需求变化的应用程序。
+
+- Auto Scaling能保证你一直拥有一定数量的EC2实例来分担应用程序的负载
+- Auto Scaling能带来更高的容错性、更好的可用性和更高的性价比
+- 你可以控制伸缩的策略来决定在什么时候终止和创建EC2实例,以处理动态变化的需求
+- 默认情况下,Auto Scaling能控制每一个可用区内所运行的实例数量尽量平均
+ - 为了达到这个目标,Auto Scaling在需要启动新实例的时候,会选择一个目前拥有运行实例最少的可用区
+
+Auto Scaling的构成组件:
+
+
+
+### 启动配置(Launch Configuration)
+
+- 启动配置是弹性伸缩组用来启动EC2实例的时候所使用的模板
+- 启动配置包含了镜像文件(AMI),实例类型、密钥对、安全组和挂载的存储设备
+- 一个启动配置可以关联多个Auto Scaling组
+- **启动配置一经创建不能被更改,只能删除重建**
+- 启动配置中可以使用CloudWatch的基础监控(Basic Monitoring)或者详细监控(Detail Monitoring)
+- Auto Scaling automatically creates a launch configuration directly from an EC2 instance.
+
+### 弹性伸缩组(Auto Scaling Group)
+
+- 弹性伸缩组(ASG)是弹性伸缩的核心,它包含了多个拥有类似配置/类型的EC2实例,这些实例被逻辑上认为是一样的
+- 弹性伸缩组需要的几个参数:
+ - **启动配置(Launch Configuration)**:它决定了EC2使用什么模板,模板内容包括了镜像文件(AMI),实例类型、密钥对、安全组和挂载的存储设备
+ - **最小和最大的性能**:决定了在弹性伸缩的情况下,EC2实例数量的浮动范围
+ - **所需的性能**:决定了这个弹性伸缩组要保持的运作所需要的基本的EC2实例数量;如果没有填写,则默认为其数值等同于最小的性能
+ - **可用区和子网**:定义EC2实例启动时候所在的可用区和子网信息
+ - **参数和健康检查**:参数定义了何时启动新实例,何时终止旧实例;健康检查决定了实例的健康状态。
+- **如果一个EC2实例的健康状态变成“不健康”,那么ASG会终止这个EC2实例,并且自动启动一个新的EC2实例**
+- 弹性伸缩组(ASG)只能在某一个AWS区域内运行,不能跨越多个区域
+- 如果启动配置(Launch Configuration)有更新,那么之后启动的新EC2实例会使用新的启动配置,而旧的EC2实例不受影响
+- 从AWS管理平台你可以直接删除一个弹性伸缩组(ASG);从AWS CLI你只能先将最小的性能和需求的性能两个参数设置为0,才能删除这个弹性伸缩组。
+
+
+
+## ECS
+
+**Amazon Elastic Container Service (ECS)**是一个有高度扩展性的**容器管理服务**。它可以轻松运行、停止和管理集群上的Docker容器,你可以将容器安装在EC2实例上,或者使用**Fargate**来启动你的服务和任务。
+
+Amazon ECS可以在一个区域内的多个可用区中创建高可用的应用程序容器,你可以定义集群中运行的Docker镜像和服务。而且你可以充分利用AWS内部的**Amazon ECR (Elastic Container Registry)**或者外部的Registry(比如Docker Hub或自建的Registry)来存储和提取容器镜像。
+
+
+
+我们可以将标准化的代码、运行环境、系统工具等等打包成一个标准的集装箱,这个集装箱叫做**Docker镜像**(Docker Image)。这个Docker镜像的概念类似于EC2中的AMI (Amazon Machine Image)。
+
+这些镜像文件通常会通过Dockerfile来构建,并且最终存放到**注册表(Registry)**内。这个Registry可以理解为摆放集装箱的码头,我们在需要某个类型的集装箱的时候就到码头去取。这类Registry可以是Amazon的ECR,也可以是公网上的Docker Hub,或者自己私有的Registry。
+
+
+
+
+
+### ECS创建举例
+
+
+
+
+
+## **Lambda**
+
+使用**AWS Lambda**,你无需配置和管理任何服务器和应用程序就能运行你的代码。只需要上传代码,Lambda就会处理运行并且根据需要自动进行横向扩展。因此Lambda也被称为**无服务(Serverless)**函数。
+
+要让AWS Lambda的代码执行,需要设定一些触发器(比如CloudWatch Log,CloudWatch Event,API Gateway等),因此Lambda函数被认为是**事件驱动的(Event-Driven)**。
+
+在传统的应用部署过程中,我们往往需要安装操作系统 -> 安装应用程序 -> 配置环境并部署代码,而且往往还需要不定时地为操作系统和应用程序打补丁和进行维护。使用AWS Lambda就方便很多,只需要上传代码,AWS就会在需要的时候帮你运行。我们不再需要(也无法接触)任何操作系统层面的东西,也节省了非常多的部署时间,可以更专心地编写代码。
+
+
+
+### AWS Lambda的特点
+
+- 没有服务器/无服务,或者说真实的服务器由AWS管理
+- 只需要为运行的代码付费,不需要管理服务器和操作系统
+- **持续性/自动的性能伸缩**
+- 非常便宜
+- AWS只会在代码运行期间收取相应的费用,代码未运行时不产生任何费用
+- **代码的最长执行时间是15分钟,如果代码执行时间超过15分钟,则需要将1个代码细分为多个**
+
+### 触发器有哪些
+
+- **API Gateway**
+- **AWS IoT**
+- **CloudWatch Events** 比如cron job定时任务
+- CloudWatch Logs
+- CodeCommit
+- DynamoDB
+- S3
+- SNS
+- Cognito Sync Trigger
+- SQS应该也可以?
+
+
+
+## 参考
+
+[参考](http://www.cloudbin.cn/?tag=aws)
diff --git a/_posts/Tech/AWS/2022-11-18-AWS MQ.md b/_posts/Tech/AWS/2022-11-18-AWS MQ.md
new file mode 100644
index 0000000000..d8e16b7db2
--- /dev/null
+++ b/_posts/Tech/AWS/2022-11-18-AWS MQ.md
@@ -0,0 +1,85 @@
+---
+layout: post
+category: AWS
+title: AWS MQ
+tags: AWS
+---
+
+## AWS MQ
+
+## SQS(Simple Queue Service)
+
+SQS有两种不同类型的队列,它们分别是:
+
+- **标准队列**(Standard Queue)
+- **FIFO队列**(先进先出队列)
+
+### 标准队列
+
+标准队列拥有**无限的吞吐量**,所有消息都会**至少传递一次**,并且它会尽最大努力进行排序。
+
+标准队列是默认的队列类型。
+
+
+
+### FIFO队列
+
+FIFO (First-in-first-out)队列在不使用批处理的情况下,**最多支持300TPS**(每秒300个发送、接受或删除操作)。
+
+在队列中的消息都只会**不多不少地被处理一次**。
+
+FIFO队列严格保持消息的**发送和接收顺序**。
+
+
+
+更多关于标准队列和FIFO队列的区别,可以查看[我需要哪种类型的队列?](https://docs.aws.amazon.com/zh_cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html#sqs-queue-types)
+
+### SQS的其他特点
+
+- SQS是靠应用程序去**拉取的**,而不能主动推送给应用程序,推送服务我们使用**SNS(Simple Notification Service)**
+- 消息会以256 KB的大小存放
+- 消息会在队列中保存1分钟~14天,默认时间是4天
+- 可见性超时(Visibility Timeout)
+ - 即当SQS队列收到新的消息并且被拉取走进行处理时,会触发Visibility Timeout的时间。这个消息不会被删除,而是会被设置为不可见,用来防止该消息在处理的过程中再一次被拉取
+ - 当这个消息被处理完成后,这个消息会在SQS中被删除,表示这个任务已经处理完毕
+ - 如果这个消息在Visibility Timeout时间结束之后还没有被处理完,则这个消息会设置为可见状态,等待另一个程序来进行处理
+ - 因此**同一个消息可能会被处理两次(或以上)**
+ - 这个超时时间最大可以设置为**12小时**
+- 标准SQS队列保证了每一个在队列内的消息都至少会被处理一次
+- 长轮询(Long Polling)
+ - 默认情况下,Amazon SQS使用**短轮询(Short Polling)**,即应用程序每次去查询SQS队列,SQS都会做回应(哪怕队列一直是空的)
+ - 使用了长轮训,应用程序每次去查询SQS队列,SQS队列不会马上做回应。而是等到队列里有消息可处理时,或者等到设定的超时时间再做出回应。
+ - 长轮询可以一定程度减少SQS的花销
+
+## SNS (Simple Notification Service)
+
+**SNS (Simple Notification Service)** 是一种完全托管的发布/订阅消息收发和移动通知服务,用于协调向订阅终端节点和客户端的消息分发。
+
+和**SQS (Simple Queue Service)**一样,SNS也可以轻松分离和扩展微服务,分布式系统和无服务应用程序,对程序进行**解耦**。
+
+我们可以使用SNS将消息推送到SQS消息队列中、AWS Lambda函数或者HTTP终端节点上。
+
+SNS通知还可以发送推送通知到IOS,安卓,Windows和基于百度的设备,也可以通过电子邮箱或者SMS短信的形式发送到各种不同类型的设备上。
+
+
+
+### SNS的一些特点
+
+- SNS是实时的**推送服务(Push)**,有别于SQS的**拉取服务(Pull/Poll)**
+- 拥有简单的API,可以和其他应用程序兼容
+- 可以通过多种不同的传输协议进行集成
+- 便宜、用多少付费多少的服务模型
+- 在AWS管理控制台上就可以进行简单的操作
+
+## SNS vs SQS
+
+AWS提供了[SQS](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/sqs/v2/home)和[SNS](https://link.zhihu.com/?target=https%3A//console.aws.amazon.com/sns/v3/home)。SQS是一个分布式的队列消息service,SNS是一个分布式的发布-订阅消息service。具体有人会问这两者有什么区别,这里给出了回答: [What is the difference between Amazon SNS and Amazon SQS?](https://link.zhihu.com/?target=https%3A//stackoverflow.com/questions/13681213/what-is-the-difference-between-amazon-sns-and-amazon-sqs)。 在我的实践中,SQS和SNS会结合起来使用,首先应用发布消息到SQS的queue里面,然后SNS消费这个queue的消息,放到自身的topic里面持久保存,然后其他的应用订阅这个topic,消费里面的消息。
+
+
+
+sqs是一对一,不能一对多,消息可持久化,不推只能等拉,拉完就删除。
+
+sns可一对多,不能持久化,push模型。
+
+sqs及aws笔记,更全, [link](http://www.cloudbin.cn/?p=2530)
+
diff --git a/_posts/Tech/AWS/2022-11-18-AWS Storage.md b/_posts/Tech/AWS/2022-11-18-AWS Storage.md
new file mode 100644
index 0000000000..ed5683197f
--- /dev/null
+++ b/_posts/Tech/AWS/2022-11-18-AWS Storage.md
@@ -0,0 +1,214 @@
+---
+layout: post
+category: AWS
+title: AWS Storage
+tags: AWS
+---
+
+## AWS Storage
+
+## dynamoDB
+
+[论文讲解](http://systemdesigns.blogspot.com/2016/01/dynamodb.html)
+
+[深入探讨 Amazon DynamoDB 的设计模 式、流复制和全局表](https://sides-share.s3.cn-north-1.amazonaws.com.cn/AWS+Webinar+2019/PDF/Amazon+DynamoDB+webinar.pdf)
+
+[官网](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html#Programming.LowLevelAPI.DataTypeDescriptors)
+
+[AWS 如何实现数据跨区域同步](https://techsummit.ctrip.com/pdf/songye.pdf)
+
+[MongoDB 与 DynamoDB 正面交锋](https://www.modb.pro/db/432414)
+
+
+
+## EBS
+
+### EBS的特点
+
+- 亚马逊EBS卷提供了**高可用、可靠、持续性的块存储**,EBS可以依附到一个正在运行的EC2实例上
+- 如果你的EC2实例需要使用数据库或者文件系统,那么建议使用EBS作为首选的存储设备
+- EBS卷的存活可以脱离EC2实例的存活状态。也就是说在终止一个实例的时候,你可以选择保留该实例所绑定的EBS卷
+- EBS卷可以依附到**同一个可用区(AZ)**内的任何实例上
+- EBS卷可以被加密,如果进行了加密那么它存有的所有已有数据,传输的数据,以及制造的镜像都会被加密
+- **EBS卷可以通过快照(Snapshot)来进行(增量)备份,这个快照会保存在S3 (Simple Storage System)上**
+- 你可以使用任何快照来创建一个基于该快照的EBS卷,并且随时将这个EBS卷应用到**该区域**的任何实例上
+- EBS卷创建的时候已经固定了可用区,并且**只能给该可用区的实例使用**。如果需要在其他可用区使用该EBS,那么可以创建快照,并且使用该快照创建一个在其他可用区的新的EBS卷
+- **快照还可以复制到其他的AWS区域**
+
+### EBS (Elastic Block Storage)小结
+
+- EBS的不同类型,需要了解不同类型的EBS主要的使用场景
+ - 通用型SSD – GP2 (高达10,000 IOPS),适用于启动盘,低延迟的应用程序等
+ - 预配置型SSD – IO1 (超过10,000 IOPS),适用于IO密集型的数据库
+ - 吞吐量优化型HDD -ST1,适用于数据仓库,日志处理
+ - HDD Cold – SC1 – 适合较少使用的冷数据
+ - HDD, Magnetic
+- 不能将EBS挂载到多个EC2实例上,一个EBS只能挂载到1个EC2实例上。
+ - 如果有共享数据盘的需求,请使用EFS (Elastic File System)
+- 根EBS卷默认是不能进行加密的,但可以使用第三方的加密工具(例如BitLocker)对其进行加密
+ - *除了根磁盘外的其他卷是可以加密的*
+
+### EBS快照(Snapshot)小结
+
+- *EBS的快照会被保存到S3(Simple Storage System)上*
+
+- *你可以对一个EBS卷创建一个快照,这个快照会被保存到S3上*
+
+- 快照实际上是
+
+ 增量备份
+
+ ,只有在上次进行快照之后更改的数据才会被添加的S3上
+
+ - 因此第一次快照所花费的时间比较长
+ - 而第二次以后的快照所花费的时间相对短很多
+
+- 对加密的EBS卷创建快照,创建后的快照也会是加密的
+
+- 从加密的快照恢复的EBS卷也会是加密的
+
+- 你可以分享快照给其他账户或AWS市场,但仅限于这个快照是没有进行过加密的
+
+- 要为一个作为根设备的EBS卷创建快照的话,建议停止这个实例再做快照
+
+### 实例存储(Instance Store)
+
+- 实例存储也叫做**短暂性存储(Ephemeral Storage)**
+- 实例存储的实例不能被停止(只能重启或终止),如果这个实例出现故障,那么在上面的所有数据将会丢失
+- 使用EBS的实例可以被停止,停止后EBS上的数据不会丢失
+- 重启使用实例存储的实例或者重启使用EBS的实例都不会导致数据丢失
+
+
+
+## AWS EBS, S3和EFS的区别
+
+- AWS S3对于静态页面的托管、多媒体分发、版本管理、大数据分析、数据存档来说都非常有用。S3可以和AWS CloudFront结合使用而达到更快的上传和下载速度。
+- AWS EBS是可以用来做数据库或托管应用程序的持续性文件系统,EBS具有很高的IO读写速度并且即插即用。 只能被单个EC2实例访问
+- 相比前面两种存储,AWS EFS是比较新的一项服务。它提供了可以在多个EC2实例之间共享的网络文件系统,功能类似于NAS设备。可以用EFS来处理大数据分析、多媒体处理和内容管理。
+
+## S3
+
+Amazon **Simple Storage Service (S3)** 是互联网存储解决方案,它提供了一个简单的Web接口,让其存储的数据和文件在互联网的任何地方给任何人访问。
+
+文件对象存储。
+
+
+
+### S3基本特性
+
+- S3是**对象存储**,可以在S3上存储各种类型的文件,它不是**块存储**(EBS是块存储)
+- 文件大小可以从0 字节到5 TB
+ - 使用Single Operation上传只能上传*最大5 GB*的文件
+ - 使用分段上传(Multipart Upload)可以对文件进行分段上传,最大支持上传*5 TB*的文件
+- S3的总存储空间是**无限大**的
+- 文件存储在**存储桶(Bucket)**内,可以理解存储桶就是一个文件夹
+- S3的名字是需要**全球唯一**的,不能与任何区域的任何人拥有的S3重名
+- 存储桶创建之后会生成一个URL,命名类似于https://s3-ap-northeast-1.amazonaws.com/aws_xiaopeiqing_com
+ - **S3是以HTTPS的形式展现的,而非HTTP**
+ - ap-northeast-1表示了当前桶所在的区域
+ - aws_xiaopeiqing_com表示了S3存储桶的名字,全球唯一
+- S3拥有99.99%(4个9)的可用性(Availability)
+ - 可用性可以理解为系统的uptime时间,即在一个自然年内(365天)有52.56分钟系统不可用
+- S3拥有99.999999999%(11个9)的持久性(Durability)
+ - 持久性可以认为是数据完整性/数据安全性,即在一千亿个存储在S3上的文件会有大概 1 个文件是不可读的
+- S3的存储桶创建的时候可以选择所在区域(Region),但不能选择可用区(AZ),AWS会负责S3的高可用、容灾问题
+ - S3创建的时候可以选择某个AWS区域,一旦选择了就不能更改
+ - 如果要在其他区域使用该S3的内容,可以使用**跨区域复制**
+- S3拥有不同的等级(Standard, Stantard-IA, Onezone-IA, RRS, Glacier)
+- 启用了**版本控制(Version Control)**你可以恢复S3内的文件到之前的版本
+- S3可以开启生命周期管理,对文件在不同的生命周期进行不同的操作
+ - 比如,文件在创建30天后迁移到便宜的S3等级(S3-IA),再经过30天进行归档(迁移到Glacier),再过30天就进行删除
+- 要启用生命周期管理需要先启用版本控制功能
+- S3支持加密功能
+- 使用访问控制列表(Access Control Lists)和桶策略(Bucket Policy)可以控制S3的访问安全
+- 在S3上成功上传了文件,你将会得到一个**HTTP 200**的状态反馈
+
+### 不同的S3存储类型
+
+- **Standard – 默认的存储类:**如果上传对象时未注明则S3会分配这个类型的存储
+- **Standard – IA(Infrequently Accessed):**用于保存不经常访问的数据,但是需要访问的时候也能很快地访问到。存储的价格比标准S3便宜,但是读取的费用比标准的S3高,也因为如此才要把不经常访问的数据放到这种类型的S3上。并且数据跨了多个AWS地理位置。
+- **Intelligent_Tiering** 智能分层(S3 智能分层): 这种储存类别将对象存储在两个访问层中,一个是频繁访问的层,一个是不频繁访问的层;如果对象`30`天内未访问,则会被移动至不频繁访问的层,如果不频繁访问层中的对象被访问,则会被移动至频繁访问的层;频繁访问的层的存储费用与`STANDARD`一样,不频繁访问层的存储费用与`STANDARD_IA`一样,该储存类别的请求费用与`STANDARD`一样,**该储存类别有额外的监控费用**;
+- **Onezone – IA:**同上,但数据只保存到一个AWS可用区内
+- **Glacier:**非常便宜,仅用于做归档。从Glacier读取数据需要花费3-5个小时。
+- **Glacier Deep Archive:** S3 Glacier Deep Archive 是 Amazon S3 成本最低的存储类,支持每年可能访问一两次的数据的长期保留和数字预留。它是为客户设计的 – 特别是那些监管严格的行业,如金融服务、医疗保健和公共部门 – 为了满足监管合规要求,将数据集保留 7-10 年或更长时间。S3 Glacier Deep Archive 还可用于备份和灾难恢复使用案例,是成本效益高、易于管理的磁带系统替代,无论磁带系统是本地库还是非本地服务都是如此。S3 Glacier Deep Archive 是 Amazon S3 Glacier 的补充,后者适合存档,其中会定期检索数据并且每隔几分钟可能需要一些数据。存储在 S3 Glacier Deep Archive 中的所有对象都将接受复制并存储在至少三个地理分散的可用区中,受 99.999999999% 的持久性保护,并且可在 12 小时内恢复。
+
+## CloudFront CDN
+
+**Amazon CloudFront**是一种全球**内容分发网络(CDN)**服务,可以安全地以低延迟和高传输速度向浏览者分发数据、视频、应用程序和API。
+
+
+
+- **边缘站点(Edge Location)**:边缘站点是内容缓存的地方,它存在于多个网络服务提供商的机房,它和AWS区域和可用区是完全不一样的概念。截至2018年中,AWS目前一共有100多个边缘站点。
+- **源(Origin)**:这是CDN缓存的内容所使用的源,源可以是一个S3存储桶,可以是一个EC2实例,一个弹性负载均衡器(ELB)或Route53,甚至可以是AWS之外的资源。
+- **分配(Distribution)**:AWS CloudFront创建后的名字
+- 分配分为两种类型,分别是
+ - **Web Distribution**:一般的网站应用
+ - **RTMP (Real-Time Messaging Protocol)**:媒体流
+- 你不只是可以从边缘站点读取数据,你还可以往边缘站点写入数据(比如上传一个文件),边缘站点会将你写入的数据同步到源上
+- 在CloudFront上的文件会被缓存在边缘节点,缓存的时间是**TTL(Time To Live)**。文件存在超过这个时间,缓存会被自动清除
+- 如果在到达TTL时间之前,你希望更新文件,那么你也可以**手动清除缓存**,但你将会被AWS**收取一定的费用**
+
+
+
+## Multi-AZ高可用
+
+我们可以把AWS RDS数据库部署在多个**可用区(AZ)**内,以提供高可用性和故障转移支持。
+
+使用Multi-AZ部署模式,RDS会在不同的可用区内配置和维护一个主数据库和一个备用数据库,主数据库的数据会自动复制到备用数据库中。
+
+使用这种部署模式,可以为我们提供数据冗余,减少在系统备份期间的I/O冻结(上面有提到)。同时,更重要的是可以防止数据库实例的故障和单个可用区的故障。
+
+如下图所示,我们可以在两个可用区内分别部署主数据库和备用数据库。
+
+
+
+目前Multi-AZ支持以下数据库:
+
+- Oracle
+- PostgreSQL
+- MySQL
+- MariaDB
+- SQL Server
+
+值得注意的是,Aurora数据库本身就支持多可用区部署的高可用设置,因此不需要为Aurora数据库特别开启这个功能。
+
+在上次实验中我们有讲到,创建了RDS数据库之后我们会得到一个数据库的URL Endpoint。在开启Multi-AZ的情况下,这个URL Endpoints会根据主/备数据库的健康状态自动解析到IP地址。对于应用程序来说,我们只需要连接这个URL地址即可。
+
+**高可用的设置只是用来解决灾备的问题,并不能解决读取性能的问题;要提升数据库读取性能,我们需要用到Read Replicas。**
+
+
+
+### 只读副本(Read Replicas)
+
+我们可以在源数据库实例的基础上,复制一种新类型的数据库实例,称之为**只读副本(Read Replicas)**。我们对源数据库的任何更新,都会**异步**更新到只读副本中。
+
+因此,我们可以将应用程序的数据库读取功能转移到Read Replicas上,来减轻源数据库的负载。
+
+对于有大量读取需求的数据库,我们可以使用这种方式来进行灵活的数据库扩展,同时突破单个数据库实例的性能限制。
+
+Read Replicas还有如下的特点:
+
+- Read Replicas是用来提高读取性能的,不是用来做灾备的
+- 要创建Read Replicas需要源RDS实例开启了自动备份的功能
+- 可以为数据库创建最多**5个**Read Replicas
+- 可以为Read Replicas创建Read Replicas(如下图所示)
+- 每一个Read Replicas都有自己的URL Endpoint
+- 可以为一个启用了Multi-AZ的数据库创建Read Replicas
+- Read Replicas可以提升成为独立的数据库
+- 可以创建位于另一个区域(Region)的Read Replicas
+
+
+
+目前Read Replicas支持以下数据库:
+
+- Aurora
+- PostgreSQL
+- MySQL
+- MariaDB
+- Oracle
+
+https://amazonaws-china.com/cn/rds/details/read-replicas/
+
+## 参考
+
+[参考](http://www.cloudbin.cn/?p=1968)
diff --git a/_posts/Tech/AWS/2022-11-26-AWS DynamoDB.md b/_posts/Tech/AWS/2022-11-26-AWS DynamoDB.md
new file mode 100644
index 0000000000..306c83421e
--- /dev/null
+++ b/_posts/Tech/AWS/2022-11-26-AWS DynamoDB.md
@@ -0,0 +1,131 @@
+---
+layout: post
+category: AWS
+title: AWS DynamoDB
+tags: AWS
+---
+
+## AWS DynamoDB
+
+> [论文讲解](http://systemdesigns.blogspot.com/2016/01/dynamodb.html)
+
+Dynamo在某些故障的场景中将牺牲一致性。
+
+Dynamo的系统假设和要求:
+1)query model:对数据项简单的读,写是通过一个主键唯一性标识。状态存储为一个由唯一性键确定二进制对象。没有横跨多个数据项的操作,也不需要关系方案(relational schema)。这项规定是基于观察相当一部分Amazon的服务可以使用这个简单的查询模型,并不需要任何关系模式。Dynamo的目标应用程序需要存储的对象都比较小(通常小于1MB)。
+
+2)ACID属性:ACID是一种保证数据库事务可靠地处理的属性。在数据库方面的,对数据的单一的逻辑操作被称作所谓的交易。Amazon的经验表明,在保证ACID的数据存储提往往有很差的可用性。Dynamo的目标应用程序是高可用性,弱一致性(ACID“中的C”)。Dynamo不提供任何数据隔离(Isolation)保证,只允许单一的关键更新。
+
+3)efficiency:系统需运作在一般的commodity hardware上。Amazon平台的服务都有着严格的延时要求, 鉴于对状态的访问在服务操作中起着至关重要的作用,存储系统必须能够满足那些严格的SLA,服务必须能够通过配置Dynamo,使他们不断达到延时和吞吐量的要求。因此,必须在成本效率,可用性和耐用性保证之间做权衡。
+
+
+
+提供get, put操作。
+
+
+
+最终一致性。
+
+### Partition
+
+按key做partition, 一致性Hash。
+
+### Replication
+
+replica, 复制,用了NWR,让用户做一致性的选择。读数据时如果有不同版本,会所有版本数据都返回回去。
+
+### Data Versioning
+
+多版本。Vector Clock 一个Vector Clock可以理解为一个<节点编号,计数器>对的列表。每一个版本的数据都会带上一个Vector Clock。Dynamo中,最重要的是要保证写操作的高可用性,即“Always Writeable”,这样就不可避免的牺牲掉数据的一致性。如上所述,Dynamo中并没有对数据做强一致性要求,而是采用的最终一致性(eventual consistency)。若不保证各个副本的强一致性,则用户在读取数据的时候很可能读到的不是最新的数据。Dynamo中将数据的增加或删除这种操作都视为一种增加操作,即每一次操作的结果都作为一份全新的数据保存,这样也就造成了一份数据会存在多个版本,分布在不同的节点上。这种情况类似于版本管理中的多份副本同时有多人在修改。多数情况下,系统会自动合并这些版本,一旦合并尝试失败,那么冲突的解决就交给应用层来解决。这时系统表现出来的现象就是,一个GET(KEY)操作,返回的不是单一的数据,而是一个多版本的数据列表,由用户决定如何合并。这其中的关键技术就是Vector Clock。
+
+
+
+其实就是读修复。
+
+### Failure Detection
+
+临时性故障,采用Hinted Handoff提示移交机制
+
+为防止要写入节点宕机导致操作失败,采用提示移交机制将操作相关数据写入到随机节点,宕机节点恢复后可根据这些数据进行重放,最终获得数据一致性。
+
+
+
+ 以N=3为例,如果在一次写操作时发现节点A挂了,那么本应该存在A上的副本就会发送到D上,同时在D中会记录这个副本的元信息(MetaData)。其中有个标示,表明这份数据是本应该存在A上的,一旦节点D之后检测到A从故障中恢复了,D就会将这个本属于A的副本回传给A,之后删除这份数据。Dynamo中称这种技术为“Hinted Handoff”。
+
+
+
+另外为了应对整个机房掉线的故障,Dynamo中应用了一个很巧妙的方案。每次读写都会从”Preference List”列表中取出R或W个节点。那么只要在这个列表生成的时候,让其中的节点是分布于不同机房的,自然数据就写到了不同机房的节点上。
+
+
+
+对于某节点非临时性故障,利用反熵得到丢失数据进行恢复。一些数据存储有后台进程,不断查找副本之间的数据差异,将任何缺少的数据从一个副本复制到另一个副本。和基于主节点复制的复制日志不同,此反熵过程不保证任何特定的顺序复制写入,并且会引入明显的同步滞后
+
+
+
+### 表、索引
+
+> [深入探讨 Amazon DynamoDB 的设计模 式、流复制和全局表](https://sides-share.s3.cn-north-1.amazonaws.com.cn/AWS+Webinar+2019/PDF/Amazon+DynamoDB+webinar.pdf)
+
+
+
+分区键和排序键共同唯一的标识一条记录
+
+本地二级索引 Local Secondary Index (LSI) 单表上的。可以选择与表不同的排序键。同一个分区键。强一致性更新。
+
+
+
+全局二级索引 - Global Secondary Index (GSI) 可以选择与表不同的分区键以及排序键 每个索引分区会对应所有的表分区
+
+
+
+
+
+
+
+对比
+
+- Global Secondary
+ - 索引的尺寸没有上限
+ - 读写容量和表是独立的
+ - 只支持最终一致性
+- Index Local Secondary Index
+ - 索引保存在表的分区中,因此一个表 分区的尺寸的上限是10GB
+ - 使用的是表上定义的RCU和WCU
+ - 强一致性
+
+
+
+
+## 其他
+
+
+
+> [官网](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html#Programming.LowLevelAPI.DataTypeDescriptors)
+
+begin_with这个操作要记得。其他后面看。
+
+
+
+> [AWS 如何实现数据跨区域同步](https://techsummit.ctrip.com/pdf/songye.pdf)
+
+没啥子东西,数据操作优先同区域内,主要靠复制。
+
+
+
+> [MongoDB 与 DynamoDB 正面交锋](https://www.modb.pro/db/432414)
+
+没啥东西
+
+
+
+> [通俗易懂之DynamoDB(一) ----分区键、排序键、GSI](https://zhuanlan.zhihu.com/p/101965292)
+
+**getItem、query和scan**
+
+这三个操作都是查询操作,效率分别是:getItem > query > scan
+
+getItem是根据primary key进行查询,可以理解为通过primary key在hashMap上查询,速度是最快的,缺点是必须知道primary key且只能查询单个,使用情况相对较少。
+
+scan是全表扫描,是最慢的一个,理论上能不用就不用,只有实在走投无路才考虑全表扫描。
+
+query是最常见的方式,在dynamoDB的使用中,我们唯一的目的就是写出高效的查询query。
diff --git a/_posts/Tech/AWS/2022-12-14-AWS CloudWatch.md b/_posts/Tech/AWS/2022-12-14-AWS CloudWatch.md
new file mode 100644
index 0000000000..38746d77c0
--- /dev/null
+++ b/_posts/Tech/AWS/2022-12-14-AWS CloudWatch.md
@@ -0,0 +1,19 @@
+---
+layout: post
+category: AWS
+title: AWS CloudWatch
+tags: AWS
+published: false
+---
+
+## AWS CloudWatch
+
+主要是Dashboard, metrics, alarms等。
+
+metrics的dimension不能用in操作。只能取1个或者不取。
+
+
+
+## 待更新
+
+期待后续...
diff --git "a/_posts/Tech/Algorithms/2018-01-18-\345\210\206\346\236\220\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246.md" "b/_posts/Tech/Algorithms/2018-01-18-\345\210\206\346\236\220\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246.md"
index 85488e17cd..4025af158b 100644
--- "a/_posts/Tech/Algorithms/2018-01-18-\345\210\206\346\236\220\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246.md"
+++ "b/_posts/Tech/Algorithms/2018-01-18-\345\210\206\346\236\220\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246.md"
@@ -20,8 +20,6 @@ T(n) = n^klogn if k==log(b)a
[递归的时间复杂度分析](https://blog.csdn.net/qq_36582604/article/details/81661236)
-
-
我们先看下面这个例子

@@ -30,8 +28,6 @@ T(n) = n^klogn if k==log(b)a

-
-
[归并排序时间复杂度分析](https://blog.csdn.net/qq_32534441/article/details/95098059)
```
@@ -39,7 +35,7 @@ T(n)=2*T(n/2)+n
第一层n, 第二层2*(n/2), 第三层4*(n/4), 每层都有个n,高度Logn
```
-[合并k个链表的时间复杂度分析](https://blog.csdn.net/qq_22080999/article/details/80669993)
+[合并 k 个链表的时间复杂度分析](https://blog.csdn.net/qq_22080999/article/details/80669993)
分治的话:
@@ -49,45 +45,42 @@ T(kn) = 2T(k/2*n) + kn
高度log2(k),每层累加都是kn, 因此最终是log2(k) * kn
```
-方法1:暴力,k个链表按顺序合并
+方法 1:暴力,k 个链表按顺序合并
时间复杂度:
(n+n)+(2n+n)+...+ ((k-1)n + n) = (1+2+...+k-1)n + (k-1)n = (1+2+...+k-1+k)n -n = (k^2+k-1)/2*n = O(k^2*n)
-方法2:将k*n个结点放到vector,再将vector排序,再将结点顺序相连
+方法 2:将 k\*n 个结点放到 vector,再将 vector 排序,再将结点顺序相连
-设有K个链表,平均每个链表有n个结点,时间复杂度:
+设有 K 个链表,平均每个链表有 n 个结点,时间复杂度:
kN*logkN +kN = O(kN*logkN)
-方法3:对k个链表进行分治,两两进行合并
+方法 3:对 k 个链表进行分治,两两进行合并
-设有k个链表,平均每个链表有n个结点,时间复杂度:
+设有 k 个链表,平均每个链表有 n 个结点,时间复杂度:
-第一轮:进行k/2次,每次处理2n个数字
+第一轮:进行 k/2 次,每次处理 2n 个数字
-第2轮,进行k/4次,每次处理4n个数字
+第 2 轮,进行 k/4 次,每次处理 4n 个数字
...
-最后一次,进行k/(2^logk)次,每次处理2^logk*n个数
-
-2n*k/2+...+2^logk*n * k/(2^logk)
-
+最后一次,进行 k/(2^logk)次,每次处理 2^logk\*n 个数
+2n*k/2+...+2^logk*n \* k/(2^logk)
## 常见算法时间复杂度
时间复杂度总结:
-prim o(e+vlogv), 主要是优先队列top v次,每次log(v), 然后边遍历总计2e.
+prim o(e+vlogv), 主要是优先队列 top v 次,每次 log(v), 然后边遍历总计 2e.
kruskal o(eloge), 主要是边的排序耗时上。
-dijsktra o(e+vlogv), 边总计e, 优先队列取了v次,每次top log(v), 这里指的斐波那契堆,该堆insert 为o(1),其他和二叉堆一致。
-
-floyd wallshal, o(n3)
+dijsktra o(e+vlogv), 边总计 e, 优先队列取了 v 次,每次 top log(v), 这里指的斐波那契堆,该堆 insert 为 o(1),其他和二叉堆一致。
-bellman-ford, o(ve), 每个边松弛一次,共循环v次,o(ve);
+floyd wallshal, o(n3)
+bellman-ford, o(ve), 每个边松弛一次,共循环 v 次,o(ve);
diff --git "a/_posts/Tech/Algorithms/2018-03-13-\345\212\250\346\200\201\350\247\204\345\210\222\344\271\213\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227\345\255\220\344\270\262.md" "b/_posts/Tech/Algorithms/2018-03-13-\345\212\250\346\200\201\350\247\204\345\210\222\344\271\213\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227\345\255\220\344\270\262.md"
index 4913182da9..f941661942 100644
--- "a/_posts/Tech/Algorithms/2018-03-13-\345\212\250\346\200\201\350\247\204\345\210\222\344\271\213\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227\345\255\220\344\270\262.md"
+++ "b/_posts/Tech/Algorithms/2018-03-13-\345\212\250\346\200\201\350\247\204\345\210\222\344\271\213\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227\345\255\220\344\270\262.md"
@@ -1,7 +1,7 @@
---
layout: post
category: Algorithms
-title: 动态规划之公共子序列子串
+title: 动态规划之公共子序列/子串/前缀
tags: Algorithms
---
@@ -183,3 +183,23 @@ public class LCString {
}
```
+
+## 最长前缀LCP Longest common prefix
+
+求两个字符串任意两个位置开头的最长公共前缀。时间复杂度o(n2) 如果是暴力需要o(n3) 枚举i,j然后到头。
+
+
+
+```scala
+class Strings:
+ def LongestCommonPrefix(a, b):
+ # lcp[i][j] 表示 s[i:] 和 s[j:] 的最长公共前缀
+ n, m = len(a), len(b)
+ lcp = [[0] * (m + 1) for _ in range(n + 1)]
+ for i in range(n - 1, -1, -1):
+ for j in range(m - 1, -1, -1):
+ if a[i] == b[j]:
+ lcp[i][j] = lcp[i + 1][j + 1] + 1
+ return lcp
+```
+
diff --git "a/_posts/Tech/Algorithms/2018-08-01-\351\230\237\345\210\227\345\222\214\346\240\210.md" "b/_posts/Tech/Algorithms/2018-08-01-\351\230\237\345\210\227\345\222\214\346\240\210.md"
index af863894ef..ef2859e924 100644
--- "a/_posts/Tech/Algorithms/2018-08-01-\351\230\237\345\210\227\345\222\214\346\240\210.md"
+++ "b/_posts/Tech/Algorithms/2018-08-01-\351\230\237\345\210\227\345\222\214\346\240\210.md"
@@ -165,4 +165,13 @@ class Solution:
-类似题目: [394. 字符串解码](https://leetcode-cn.com/problems/decode-string/)
\ No newline at end of file
+类似题目: [394. 字符串解码](https://leetcode-cn.com/problems/decode-string/)
+
+
+
+
+
+给定入栈顺序,求某个出栈顺序。
+
+1. [6202. 使用机器人打印字典序最小的字符串](https://mafulong.github.io/2022/10/09/6202.-%E4%BD%BF%E7%94%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%89%93%E5%8D%B0%E5%AD%97%E5%85%B8%E5%BA%8F%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2/)
+2. [栈的压入、弹出序列](https://mafulong.github.io/2018/10/20/%E6%A0%88%E7%9A%84%E5%8E%8B%E5%85%A5-%E5%BC%B9%E5%87%BA%E5%BA%8F%E5%88%97/)
\ No newline at end of file
diff --git "a/_posts/Tech/algorithms/2018-08-13-\346\254\247\346\213\211\345\233\236\350\267\257.md" "b/_posts/Tech/Algorithms/2018-08-13-\346\254\247\346\213\211\350\267\257\345\276\204.md"
similarity index 87%
rename from "_posts/Tech/algorithms/2018-08-13-\346\254\247\346\213\211\345\233\236\350\267\257.md"
rename to "_posts/Tech/Algorithms/2018-08-13-\346\254\247\346\213\211\350\267\257\345\276\204.md"
index 6b221feac6..3e19382e31 100644
--- "a/_posts/Tech/algorithms/2018-08-13-\346\254\247\346\213\211\345\233\236\350\267\257.md"
+++ "b/_posts/Tech/Algorithms/2018-08-13-\346\254\247\346\213\211\350\267\257\345\276\204.md"
@@ -1,14 +1,16 @@
---
layout: post
category: Algorithms
-title: 欧拉回路
+title: 欧拉路径
tags: Algorithms
---
## 欧拉回路定义及判断
-如果能从图的某一顶点出发,每条边恰好经过一次,这样的路线称为欧拉道路(Eulerian Path)。
+如果能从图的某一顶点出发,每条边恰好经过一次,这样的路线称为**欧拉道路(Eulerian Path)。也叫欧拉路径**
+
+如果每条边恰好经过一次,且能回到起点,这样的路线称为**欧拉回路**(Eulerian Circuit)。
+
-如果每条边恰好经过一次,且能回到起点,这样的路线称为欧拉回路(Eulerian Circuit)。
对于无向图G,当且仅当G 是连通的,且最多有两个奇点,则存在欧拉道路。
@@ -22,7 +24,7 @@ tags: Algorithms
- 通过图中所有边恰好一次且行遍所有顶点的通路称为欧拉通路。
- 通过图中所有边恰好一次且行遍所有顶点的回路称为欧拉回路。
-- 具有欧拉回路的无向图称为欧拉图。
+- **具有欧拉回路的无向图称为欧拉图。**
- 具有欧拉通路但不具有欧拉回路的无向图称为半欧拉图。
@@ -41,6 +43,10 @@ tags: Algorithms
给定一个 *n* 个点 *m* 条边的图,要求从指定的顶点出发,经过所有的边恰好一次(可以理解为给定起点的「一笔画」问题)其实就是求欧拉路径。
+如果在有欧拉回路中的图,它就求的是欧拉回路。如果非欧拉回路的图就是欧拉路径。
+
+
+
Hierholzer 算法用于在连通图中寻找欧拉路径,其流程如下:[参考](https://leetcode-cn.com/problems/reconstruct-itinerary/solution/zhong-xin-an-pai-xing-cheng-by-leetcode-solution/)
@@ -70,11 +76,17 @@ def dfs(u):
stack = stack[::-1]
```
+以上是求点的路径。 有向图还是无向图都没关系,无向图就变两个有向的边就行。
+
+
+
+如果是求边路径,pop后进入stack即可。
+
## 相关题目
-- [332. 重新安排行程](https://leetcode-cn.com/problems/reconstruct-itinerary/)
-- [753. 破解保险箱](https://leetcode-cn.com/problems/cracking-the-safe/) 求锁所有密码,就是抽象出多个节点,然后求欧拉回路.
+- [332. 重新安排行程](https://leetcode-cn.com/problems/reconstruct-itinerary/) 求欧拉路径 点的顺序
+- [753. 破解保险箱](https://leetcode-cn.com/problems/cracking-the-safe/) 求锁所有密码,就是抽象出多个节点,然后求欧拉路径.
- [5932. 合法重新排列数对](https://leetcode-cn.com/problems/valid-arrangement-of-pairs/)
diff --git "a/_posts/Tech/Algorithms/2021-01-25-\345\215\232\345\274\210\350\256\272.md" "b/_posts/Tech/Algorithms/2021-01-25-\345\215\232\345\274\210\350\256\272.md"
index 2273a453fe..b86928dd25 100644
--- "a/_posts/Tech/Algorithms/2021-01-25-\345\215\232\345\274\210\350\256\272.md"
+++ "b/_posts/Tech/Algorithms/2021-01-25-\345\215\232\345\274\210\350\256\272.md"
@@ -3,6 +3,7 @@ layout: post
category: Algorithms
title: 博弈论
tags: Algorithms
+recent_update: true
---
## 博弈论
diff --git "a/_posts/Tech/Algorithms/2021-03-11-\344\270\221\346\225\260.md" "b/_posts/Tech/Algorithms/2021-03-11-\344\270\221\346\225\260.md"
deleted file mode 100644
index b28798fa3a..0000000000
--- "a/_posts/Tech/Algorithms/2021-03-11-\344\270\221\346\225\260.md"
+++ /dev/null
@@ -1,57 +0,0 @@
----
-layout: post
-category: Algorithms
-title: 丑数
-tags: Algorithms
----
-
-## 丑数
-
-[[剑指 Offer 49. 丑数](https://leetcode-cn.com/problems/chou-shu-lcof/)
-
-[313. 超级丑数](https://leetcode-cn.com/problems/super-ugly-number/)
-
-### 使用优先队列
-
-```python
-class Solution:
- def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
- import heapq
- hq = [1]
- res = []
- for _ in range(n):
- top = heapq.heappop(hq)
- res.append(top)
- while hq and hq[0] == top:
- heapq.heappop(hq)
- for k in primes:
- heapq.heappush(hq, top * k)
- print(res)
- return res[-1]
-```
-
-
-
-### 使用多指针
-
-```c++
-//cpp:
-class Solution {
-public://别人的代码就是精简,惭愧啊,继续学习。
- int GetUglyNumber_Solution(int index) {
- if (index < 7)return index;
- vector res(index);
- res[0] = 1;
- int t2 = 0, t3 = 0, t5 = 0, i;
- for (i = 1; i < index; ++i)
- {
- res[i] = min(res[t2] * 2, min(res[t3] * 3, res[t5] * 5));
- if (res[i] == res[t2] * 2)t2++;
- if (res[i] == res[t3] * 3)t3++;
- if (res[i] == res[t5] * 5)t5++;
- }
- return res[index - 1];
- }
-};
-```
-
diff --git "a/_posts/Tech/Algorithms/2021-03-11-\345\244\232\350\267\257\345\275\222\345\271\266 \344\270\221\346\225\260.md" "b/_posts/Tech/Algorithms/2021-03-11-\345\244\232\350\267\257\345\275\222\345\271\266 \344\270\221\346\225\260.md"
new file mode 100644
index 0000000000..bbf460d84d
--- /dev/null
+++ "b/_posts/Tech/Algorithms/2021-03-11-\345\244\232\350\267\257\345\275\222\345\271\266 \344\270\221\346\225\260.md"
@@ -0,0 +1,124 @@
+---
+layout: post
+category: Algorithms
+title: 多路归并 丑数
+tags: Algorithms
+---
+
+[找第k小及变种,个人另一篇博客,内容有重合](https://mafulong.github.io/2022/01/03/%E6%89%BE%E7%AC%ACk%E5%B0%8F%E5%8F%8A%E5%8F%98%E7%A7%8D/)
+
+
+
+## 丑数
+
+[[剑指 Offer 49. 丑数](https://leetcode-cn.com/problems/chou-shu-lcof/)
+
+
+
+### 使用优先队列
+
+```python
+class Solution:
+ def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
+ import heapq
+ hq = [1]
+ res = []
+ for _ in range(n):
+ top = heapq.heappop(hq)
+ res.append(top)
+ while hq and hq[0] == top:
+ heapq.heappop(hq)
+ for k in primes:
+ heapq.heappush(hq, top * k)
+ print(res)
+ return res[-1]
+```
+
+
+
+### 使用多指针
+
+```c++
+//cpp:
+class Solution {
+public:/
+ int GetUglyNumber_Solution(int index) {
+ if (index < 7)return index;
+ vector res(index);
+ res[0] = 1;
+ int t2 = 0, t3 = 0, t5 = 0, i;
+ for (i = 1; i < index; ++i)
+ {
+ res[i] = min(res[t2] * 2, min(res[t3] * 3, res[t5] * 5));
+ if (res[i] == res[t2] * 2)t2++;
+ if (res[i] == res[t3] * 3)t3++;
+ if (res[i] == res[t5] * 5)t5++;
+ }
+ return res[index - 1];
+ }
+};
+```
+
+多路归并。
+
+## 超级丑数
+
+不只2,3,5
+
+
+
+[313. 超级丑数](https://leetcode-cn.com/problems/super-ugly-number/)
+
+```python
+class Solution:
+ def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
+ import heapq
+ hpush, hpop = heapq.heappush,heapq.heappop
+ h = []
+ for i in range(len(primes)):
+ hpush(h, (primes[i], i, 0))
+ ans = [1]
+ for i in range(1,n):
+ if not h:
+ return -1
+ val = h[0][0]
+ ans.append(val)
+ while h and h[0][0] == val:
+ _,j,idx = hpop(h)
+ # print(idx,ans)
+ hpush(h, (ans[idx]*primes[j], j, idx+1))
+ return ans[-1]
+
+
+```
+
+
+
+## 其它多路归并
+
+- [373. 查找和最小的K对数字](https://mafulong.github.io/2022/01/03/373.-%E6%9F%A5%E6%89%BE%E5%92%8C%E6%9C%80%E5%B0%8F%E7%9A%84K%E5%AF%B9%E6%95%B0%E5%AD%97/) 给定两个以升序排列的整数数组 `nums1` 和 `nums2` , 以及一个整数 `k` 。定义一对值 `(u,v)`,其中第一个元素来自 `nums1`,第二个元素来自 `nums2` 。请找到和最小的 `k` 个数对 `(u1,v1)`, ` (u2,v2)` ... `(uk,vk)` 。
+
+```python
+class Solution:
+ def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
+ # equal with 多路链表归并,用heap取最小那个,然后移动指针,也就是超级丑数
+ # 性能o(klog(k))
+ import heapq
+ h = []
+ for j in range(min(len(nums2),k)):
+ heapq.heappush(h, (nums1[0]+nums2[j], 0, j))
+ res = []
+ while k > 0 and h:
+ _,i,j = heapq.heappop(h)
+ res.append([nums1[i], nums2[j]])
+ if i+1 < len(nums1):
+ heapq.heappush(h, (nums1[i+1]+nums2[j], i+1,j))
+ k-=1
+ return res
+```
+
+
+
+- [有序矩阵的 Kth Element](https://leetcode-cn.com/problems/kth-smallest-element-in-a-sorted-matrix/description/)
+ - 多路归并
+ - 二分法更优。
diff --git "a/_posts/Tech/Algorithms/2021-06-21-\345\215\225\350\260\203\351\230\237\345\210\227\345\222\214\345\215\225\350\260\203\346\240\210.md" "b/_posts/Tech/Algorithms/2021-06-21-\345\215\225\350\260\203\351\230\237\345\210\227\345\222\214\345\215\225\350\260\203\346\240\210.md"
index ceae6d6f9c..84eeee3fd0 100644
--- "a/_posts/Tech/Algorithms/2021-06-21-\345\215\225\350\260\203\351\230\237\345\210\227\345\222\214\345\215\225\350\260\203\346\240\210.md"
+++ "b/_posts/Tech/Algorithms/2021-06-21-\345\215\225\350\260\203\351\230\237\345\210\227\345\222\214\345\215\225\350\260\203\346\240\210.md"
@@ -96,6 +96,11 @@ class Solution:
求左边右边, 最小的大于等于arr[i]的位置,一种方式是sortedList, 一种方式是sorted(range(N), lambda x:arr[x])
+### 最大宽度
+
+求最大坡度, 坡度定义: i < j 且 A[i] <= A[j]。这样的坡的宽度为 j - i。找每个元素比它大的最后一个位置
+可以按https://leetcode.cn/submissions/detail/208988818/ 中,按val对range(n)排序,o(nlogn),此时对排序位置i的元素最大坡度就是右边最大j
+也可以单调栈o(n)求,先求递减栈,然后倒序枚举,如果比栈顶大,则栈顶元素后续就无用可pop了
## 单调队列
@@ -146,4 +151,3 @@ class Solution:
- [862. 和至少为 K 的最短子数组](https://leetcode-cn.com/problems/shortest-subarray-with-sum-at-least-k/) 求前缀和,对前缀和队列递增,求最大差值。
-
diff --git "a/_posts/Tech/Algorithms/2021-08-12-\345\233\236\346\226\207.md" "b/_posts/Tech/Algorithms/2021-08-12-\345\233\236\346\226\207.md"
index e782af0844..ce69a52ac5 100644
--- "a/_posts/Tech/Algorithms/2021-08-12-\345\233\236\346\226\207.md"
+++ "b/_posts/Tech/Algorithms/2021-08-12-\345\233\236\346\226\207.md"
@@ -9,7 +9,7 @@ tags: Algorithms
-#### Manacher 算法
+#### Manacher 算法
给你一个字符串 `s`,找到 `s` 中最长的回文子串。
@@ -19,8 +19,12 @@ tags: Algorithms
这里边长0表示a,边长1表示aaa
-```
- n = len(s)
+```python
+ '''
+ 须先变为回文皆奇数长度, 可提前转换: s1 = '#' + '#'.join(list(s)) + '#'
+ '''
+
+ n = len(s)
arm_len = [0] * n
def expand(left, right):
@@ -42,6 +46,23 @@ tags: Algorithms
right = i + arm_len[i]
```
+时间复杂度o(n).
+
+
+
+根据以上得到的arm_len 判断某个子串是不是回文。
+
+```python
+ def is_palindrome(s, i, j, armlen):
+ mid = (i + j) // 2 # 前半部分或中间
+ # 找中心点,然后对应到s1上
+ t = 2 * mid + 1
+ if (j - i + 1) % 2 == 0:
+ t += 1
+ return armlen[t] >= j - i + 1
+
+```
+
## 回文技巧
@@ -49,3 +70,10 @@ tags: Algorithms
DP:
- 用 P(i,j) 表示字符串 s 的第 i到 j 个字母组成的串(下文表示成 s[i:j])是否为回文串 . 变成区间dp
+
+
+
+## 应用
+
+- [647. 回文子串](https://leetcode.cn/problems/palindromic-substrings/) 给你一个字符串 `s` ,请你统计并返回这个字符串中 **回文子串** 的数目。1.中心扩展o(n2), 2. manacher o(n)
+- [6236. 不重叠回文子字符串的最大数目](https://leetcode.cn/problems/maximum-number-of-non-overlapping-palindrome-substrings/) 实际是dp,判断s(i,j)是不是回文。
diff --git "a/_posts/Tech/Algorithms/2021-09-08-\347\212\266\346\200\201\345\216\213\347\274\251.md" "b/_posts/Tech/Algorithms/2021-09-08-\347\212\266\346\200\201\345\216\213\347\274\251.md"
index ea30e809e2..85843010a6 100644
--- "a/_posts/Tech/Algorithms/2021-09-08-\347\212\266\346\200\201\345\216\213\347\274\251.md"
+++ "b/_posts/Tech/Algorithms/2021-09-08-\347\212\266\346\200\201\345\216\213\347\274\251.md"
@@ -3,6 +3,7 @@ layout: post
category: Algorithms
title: 状态压缩
tags: Algorithms
+recent_update: true
---
## 状态压缩
diff --git a/_posts/Tech/Algorithms/2021-12-05-BFS.md b/_posts/Tech/Algorithms/2021-12-05-BFS.md
index d5097a7ac7..ffd0c10075 100644
--- a/_posts/Tech/Algorithms/2021-12-05-BFS.md
+++ b/_posts/Tech/Algorithms/2021-12-05-BFS.md
@@ -11,29 +11,22 @@ tags: Algorithms
- 在append时检查visit标记和设置visit标记
- 只能解决长度为1的问题
-```
-const visited = {}
-function bfs() {
- let q = new Queue()
- q.push(初始状态)
- while(q.length) {
- let i = q.pop()
- if (visited[i]) continue
- for (i的可抵达状态j) {
- if (j 合法) {
- q.push(j)
- }
- }
- }
- // 找到所有合法解
-}
-```
+
+
+也可以在queue pop时再check 是否visit和标记visit,时间复杂度加边数。
+
+
题目:
- [求最少转弯的路径](https://mafulong.github.io/2018/08/27/bfs%E6%9C%80%E5%B0%8F%E8%BD%AC%E5%BC%AF%E8%B7%AF%E5%BE%84/) 每次转弯时加1
- [126. 单词接龙 II](https://leetcode.cn/problems/word-ladder-ii/) 输入所有bfs路径,层次遍历 + dfs回溯pre.
+## 从外向内扩展
+
+- [407. 接雨水 II](https://leetcode.cn/problems/trapping-rain-water-ii/) 从外向内dijkstra。
+- [417. 太平洋大西洋水流问题](https://leetcode.cn/problems/pacific-atlantic-water-flow/) 从外向内bfs/dfs。
+
## 双向BFS
> [双向bfs模板参考](https://leetcode-cn.com/problems/open-the-lock/solution/gong-shui-san-xie-yi-ti-shuang-jie-shuan-wyr9/)
diff --git "a/_posts/Tech/Algorithms/2021-12-23-\344\270\200\350\207\264\346\200\247hash.md" "b/_posts/Tech/Algorithms/2021-12-23-\344\270\200\350\207\264\346\200\247hash.md"
index 8b0b8fa32a..cf90d17eaa 100644
--- "a/_posts/Tech/Algorithms/2021-12-23-\344\270\200\350\207\264\346\200\247hash.md"
+++ "b/_posts/Tech/Algorithms/2021-12-23-\344\270\200\350\207\264\346\200\247hash.md"
@@ -5,6 +5,8 @@ title: 一致性hash
tags: Algorithms
---
+# 一致性hash
+
## 一致性hash
1. 首先,我们将hash算法的值域映射成一个具有232 次方个桶的空间中,即0~(232)-1的数字空间。现在我们可以将这些数字头尾相连,组合成一个闭合的环形。
@@ -104,4 +106,44 @@ class HashSeverMgr(object):
## 参考
- [一致性 hash 原理及实现(python 版)](https://xie.infoq.cn/article/e7182d18df48bc26eeb30b207)
-- [图解一致性hash算法和实现](https://aijishu.com/a/1060000000007241)
\ No newline at end of file
+- [图解一致性hash算法和实现](https://aijishu.com/a/1060000000007241)
+
+## 补充
+
+增加节点/删除节点都需要先执行挪数据这个操作,如果没这个操作,可能会读空,但读空范围因为一致性hash的存在,导致影响有限,对于缓存应该是没关系的,如果是持久化的就需要备份,不能让读空。
+
+
+
+# hash slot
+
+集群:
+是一个提供多个Redis(分布式)节点间共享数据的程序集。
+集群部署
+Redis 集群的键空间被分割为 16384 hash个槽(slot), 集群的最大节点数量也是 16384 个
+
+分片:
+ Redis Cluster在设计中没有使用一致性哈希(Consistency Hashing),而是使用数据分片引入哈希槽(hash slot)来实现;
+
+一个 Redis Cluster包含16384(0~16383)即2^14个哈希槽,存储在Redis Cluster中的所有键都会被映射到这些slot中,集群中的每个键都属于这16384个哈希槽中的一个,集群使用公式slot=CRC16(key)/16384来计算key属于哪个槽,其中CRC16(key)语句用于计算key的CRC16 校验和。
+
+
+
+这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我像移除节点A,需要将A中得槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务, 所**以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.**
+
+
+
+数据迁移
+数据迁移可以理解为slot(槽)和key的迁移,这个功能很重要,极大地方便了集群做线性扩展,以及**实现平滑的扩容或缩容。**
+
+
+
+
+
+和一致性哈希相比
+
+1. 它并不是闭合的,key的定位规则是**根据CRC-16(key)%16384的值来判断属于哪个槽区,从而判断该key属于哪个节点**,而一致性哈希是根据hash(key)的值来顺时针找第一个hash(ip)的节点,从而确定key存储在哪个节点。
+2. 一致性哈希是创建虚拟节点来实现节点宕机后的数据转移并保证数据的安全性和集群的可用性的, 当节点不可用时,分摊给多个其他节点,因为虚节点的存在。redis cluster是采用master节点有多个slave节点机制来保证数据的完整性的,master节点写入数据,slave节点同步数据。当master节点挂机后,slave节点会通过选举机制选举出一个节点变成master节点,实现高可用。但是这里有一点需要考虑,如果master节点存在热点缓存,某一个时刻某个key的访问急剧增高,这时该mater节点可能操劳过度而死,随后从节点选举为主节点后,同样宕机,一次类推,造成缓存雪崩即热点缓存问题。
+
+
+
+两者都是要挪数据的!
\ No newline at end of file
diff --git "a/_posts/Tech/Algorithms/2022-05-01-\346\225\260\345\255\246.md" "b/_posts/Tech/Algorithms/2022-05-01-\346\225\260\345\255\246.md"
index d776a249c9..c0fdbde4a9 100644
--- "a/_posts/Tech/Algorithms/2022-05-01-\346\225\260\345\255\246.md"
+++ "b/_posts/Tech/Algorithms/2022-05-01-\346\225\260\345\255\246.md"
@@ -5,8 +5,6 @@ title: 数学
tags: Algorithms
---
-
-
## 排列组合
> [参考](https://baike.baidu.com/item/%E6%8E%92%E5%88%97%E7%BB%84%E5%90%88/706498)
@@ -19,6 +17,52 @@ tags: Algorithms

+
+
+另外 C(0,0) = 1, 0 的为 1。
+
+组合数性质
+
+
+
+### 大组合数求解边模
+
+利用组合数性质. o(n2)
+
+```python
+ def comb_mod(self, n, m, mod=10 ** 9 + 7):
+ '''
+ 大组合数计算C(n,m),边求边mod, 利用组合数性质C(n,m) = 1*C(n-1,m-1) + C(n-1,m)
+ '''
+ dp = [[0 for _ in range(n+1)] for _ in range(n+1)]
+ dp[0][0] = 1
+ for i in range(1, n+1):
+ dp[i][0] = 1
+ for j in range(1, i+1):
+ dp[i][j] = (dp[i-1][j-1] + dp[i-1][j]) % mod
+ return dp[n][m]
+
+```
+
+组合数求和公式
+
+
+
+
+
+### python中排列组合
+
+```python
+ # 组合
+ math.comb # n! / (k! * (n - k)!)
+ math.perm # n! / (n - k)!
+
+```
+
+
+
+
+
## 等差等比数列
@@ -29,20 +73,18 @@ tags: Algorithms
-
-
## 复杂的复杂度计算
### 幂函数和对数函数和指数函数对比
-
-

### 调和级数

+这里有用到: [link](https://leetcode.cn/problems/number-of-different-subsequences-gcds/solution/ji-bai-100mei-ju-gcdxun-huan-you-hua-pyt-get7/)
+
### 二项式定理

@@ -53,16 +95,20 @@ tags: Algorithms
## 中位数
-在一步操作中,你可以使数组中的一个元素加 `1` 或者减 `1` ,所有数都靠近**中位数**可使所有数组元素相等时移动数最少。 相关题目: [最少移动次数使数组元素相等 II](https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements-ii/)
+在一步操作中,你可以使数组中的一个元素加 `1` 或者减 `1` ,所有数都靠近**中位数**可使所有数组元素相等时移动数最少。 相关题目: [最少移动次数使数组元素相等 II](https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements-ii/)
+即中位数到所有数距离和最小,如果是偶数,可以在中位数两侧的数据构成的区间内任意取值,对结果无影响证明:
+
+
+另一个相似题目:有cost,需转化拆分,然后再算中位数,[6216. 使数组相等的最小开销](https://mafulong.github.io/2022/10/23/6216.-%E4%BD%BF%E6%95%B0%E7%BB%84%E7%9B%B8%E7%AD%89%E7%9A%84%E6%9C%80%E5%B0%8F%E5%BC%80%E9%94%80/)
## 素数
-### 判断是否素数和求1-n的素数求某数的素数
+### 判断是否素数 o(sqrt(N))
```python
-# 判断某数是否是素数
+# 判断某数是否是素数 o(sqrt(n))
def is_prime(a):
if a <= 1: return False
import math
@@ -71,7 +117,16 @@ def is_prime(a):
return True
-# 求1-n每个数的素数,以下时间复杂度O(n) 朴素筛法
+```
+
+### 求 1-n 的所有素数 筛法 o(N)
+
+#### 埃氏筛法
+
+```python
+# 求1-n每个数的素数,以下时间复杂度O(nloglogn) 接近o(n)
+# 如果我们从小到大考虑每个数,然后同时把当前这个数的所有(比自己大的)倍数记为合数,那么运行结束的时候没有被标记的数就是素数了。
+# Eratosthenes 筛法(埃拉托斯特尼筛法,简称埃氏筛法)
def get_all_prime(n):
a = [False] * n
res = []
@@ -82,21 +137,31 @@ def get_all_prime(n):
for j in range(2 * i, n, i):
a[j] = True
return res
+```
+
+#### **线性筛法** 也称为 **Euler 筛法**(欧拉筛法)
+
+埃氏筛法仍有优化空间,它会将一个合数重复多次标记。有没有什么办法省掉无意义的步骤呢?答案是肯定的。
-# 求某数的质因数列表,比如8,是[(2,3)], 6是[(2,1),(3,1)]
-def calcu(a):
- counter = collections.Counter()
- prime = get_all_prime(a + 1)
- for p in prime:
- while a % p == 0:
- counter[p] += 1
- a /= p
- return counter.items()
+如果能让每个合数都只被标记一次,那么时间复杂度就可以降到 o(n)了。
+
+```python
+def get_all_prime(n):
+ a = [False] * n
+ res = []
+ for i in range(2, n):
+ if a[i]: continue
+ # a[i]是素数
+ res.append(i)
+ for j in range(2 * i, n, i):
+ if a[j]: break # 多了个这行
+ a[j] = True
+ return res
```
## 平方数
-[先看Cyc2018](http://www.cyc2018.xyz/%E7%AE%97%E6%B3%95/Leetcode%20%E9%A2%98%E8%A7%A3/Leetcode%20%E9%A2%98%E8%A7%A3%20-%20%E6%95%B0%E5%AD%A6.html#_1-%E5%B9%B3%E6%96%B9%E6%95%B0)
+[先看 Cyc2018](http://www.cyc2018.xyz/%E7%AE%97%E6%B3%95/Leetcode%20%E9%A2%98%E8%A7%A3/Leetcode%20%E9%A2%98%E8%A7%A3%20-%20%E6%95%B0%E5%AD%A6.html#_1-%E5%B9%B3%E6%96%B9%E6%95%B0)
### 生成所有平方数
@@ -106,8 +171,6 @@ def calcu(a):
间隔为等差数列,使用这个特性可以得到从 1 开始的平方序列。
-
-
### 3 的 n 次方
[Power of Three (Easy)](https://leetcode-cn.com/problems/power-of-three/description/)
@@ -118,33 +181,96 @@ public boolean isPowerOfThree(int n) {
}
```
-## 因数
+## 除法
+
+```python
+ # b % a == 0
+ # 表示b能被a整除,a可以整除b, 被除数永远都是有这个『被』
+```
+
+表示b能被a整除,a可以整除b, 被除数永远都是有这个『被』
+
+
+
+大整数除法,除法中取模。
+
+
+
+## 因数理论
### 素数分解
-每一个数都可以分解成素数的乘积,例如 84 = 22 * 31 * 50 * 71 * 110 * 130 * 170 * …
+每一个数都可以分解成素数的乘积,例如 84 = 22 _ 31 _ 50 _ 71 _ 110 _ 130 _ 170 \* …
### 整除
-令 x = 2m0 * 3m1 * 5m2 * 7m3 * 11m4 * …
+令 x = 2m0 _ 3m1 _ 5m2 _ 7m3 _ 11m4 \* …
-令 y = 2n0 * 3n1 * 5n2 * 7n3 * 11n4 * …
+令 y = 2n0 _ 3n1 _ 5n2 _ 7n3 _ 11n4 \* …
如果 x 整除 y(y mod x == 0),则对于所有 i,mi <= ni。
-### 最大公约数最小公倍数
+### 最大公约数最小公倍数的素数表示
+
+每个质因数的乘积
+
+x 和 y 的最大公约数为:gcd(x,y) = 2min(m0,n0) _ 3min(m1,n1) _ 5min(m2,n2) \* ...
+
+x 和 y 的最小公倍数为:lcm(x,y) = 2max(m0,n0) _ 3max(m1,n1) _ 5max(m2,n2) \* ...
+
+### 约数个数和约数之和
+
+如果 N = p1^c1 _ p2^c2 _ ... _pk^ck
+约数个数: (c1 + 1) _ (c2 + 1) _ ... _ (ck + 1)
+约数之和: (p1^0 + p1^1 + ... + p1^c1) _ ... _ (pk^0 + pk^1 + ... + pk^ck)
+
+
-x 和 y 的最大公约数为:gcd(x,y) = 2min(m0,n0) * 3min(m1,n1) * 5min(m2,n2) * ...
+## 因数相关问题
-x 和 y 的最小公倍数为:lcm(x,y) = 2max(m0,n0) * 3max(m1,n1) * 5max(m2,n2) * ...
+### 试除法求所有约数:
-### 求质因数和对应计数
+#### 求一个数的因子列表 o(sqrt(n))
-o(n)近似
+o(sqrt(n))
+
+```python
+divisors = []
+d = 1
+while d * d <= k: # 预处理 k 的所有因子
+ if k % d == 0:
+ divisors.append(d)
+ if d * d < k: # 避免 d= k/d的情况,此时如果append会重复
+ divisors.append(k / d)
+ d += 1
+```
+
+#### 统计 1-n 每个数的因子列表 o(nlogn)
+
+o(nlogn)
+
+```python
+MX = 100001
+divisors = [[] for _ in range(MX)] # 每个value就是key的因子列表,乘积肯定>value,因为因子之间可能有倍数
+for i in range(1, MX): # 预处理每个数的所有因子,时间复杂度 O(MlogM),M=1e5
+ for j in range(i, MX, i):
+ divisors[j].append(i)
+```
+
+### 分解质因数
+
+#### 求某数质因数列表 o(sqrt(N))
+
+o(sqrt(N))
+
+求某数的质因数列表,比如 8,是[2,2,2]
+
+枚举[2, sqrt(n)+1), 如果是质因数,就接着除,最大大于 1,它本身就是质数。
+
+也叫 求欧拉函数
```python
# 求质因数列表
-# Python Version
def breakdown(N):
result = []
from math import sqrt
@@ -158,54 +284,175 @@ def breakdown(N):
return result
```
-### 统计1-n每个数的因子列表
+#### 统计 1-n 每个数的质因数列表
-o(nlogn)
+筛法求欧拉函数
+
+类似,暂时不写。
+
+### gcd 求最大公约数和最小公倍数 欧几里得算法
+
+欧几里得算法
```python
-MX = 100001
-divisors = [[] for _ in range(MX)] # 每个value就是key的因子列表,乘积肯定>value,因为因子之间可能有倍数
-for i in range(1, MX): # 预处理每个数的所有因子,时间复杂度 O(MlogM),M=1e5
- for j in range(i, MX, i):
- divisors[j].append(i)
+class Math1:
+ def gcd(self, a, b):
+ if b == 0:
+ return a
+ return self.gcd(b, a % b)
```
-### 求一个数的因子列表
+最小公倍数就是 a\*b/gcd(a,b)
-o(sqrt(n))
+
+
+### 多个数求最大公约数和最小公倍数
+
+多个数的最大公约数:
```python
-divisors = []
-d = 1
-while d * d <= k: # 预处理 k 的所有因子
- if k % d == 0:
- divisors.append(d)
- if d * d < k: # 避免 d= k/d的情况,此时如果append会重复
- divisors.append(k / d)
- d += 1
+def gcd_list(self, nums):
+ import math
+ cur = nums[0]
+ for i in range(1, len(nums)):
+ cur = math.gcd(cur, nums[i])
+ return cur
```
-### gcd求最大公约数:
+多个数的最小公倍数:
-```c++
-int gcd(int a, int b) {
- return b == 0 ? a : gcd(b, a%b);
-}
+> 注意这里不是直接多个数乘积除以他们的gcd呀,而且不断一个一个加计算的。
-int gcd(int a, int b) {
- while (b != 0) {
- int t = a%b;
- a = b;
- b = t;
- }
- return a;
-}
+```python
+def lcm_list(self, nums):
+ import math
+ prod = 1
+ for v in nums:
+ prod = prod * v / math.gcd(prod, v)
+ return prod
+```
+
+### 1到n里有多少个数可整除a?
+
+```python
+n//a
+```
+
+
+
+### 1到n里有多少个a的因数?
+
+[参考另一个博客](https://mafulong.github.io/2018/04/30/%E8%AE%A1%E7%AE%97n%E7%9A%84%E9%98%B6%E4%B9%98%E4%B8%AD%E6%9C%89%E5%A4%9A%E5%B0%91%E4%B8%AAk/)
+
+```python
+ def calcu(x,a):
+ '''
+ 1-x中有多少个因数a, 比如1-26里有5,10, 15, 20, 各自1个5, 5*5两个5,一共6个
+ '''
+ r = 0
+ while x:
+ # 贡献5的数量,贡献5*5的数量,贡献5*5*5的数量
+ r += x //a
+ x //= a
+ return r
+ print(calcu(26, 5))
+```
+
+
+
+## 大整数取模问题
+
+### 大数相乘取模
+
+```python
+ def prod(d=[], mod=10 ** 9 + 7):
+ r = d[0] % mod
+ for v in d[1:]:
+ r *= v
+ r %= mod
+ return r
+```
+
+
+
+### 大数相除取模 费马小定理
+
+如果a/b,然后a和b都是大数要取模,这时不能相乘取模来计算
+
+`(a/b)%c=(a%c)/(b%c)`是**不成立**的
+
+
+
+> [除法取模](https://leetcode.cn/problems/count-anagrams/solution/by-simpleson-crwb/)
+
+```python
+
+# 原: i//j%MOD
+# 现: i*modInverse(j)%MOD
+MOD = int(1e9 + 7)
+
+class BigIntDivide:
+ def mod_inverse(sefl, i):
+ # 调用取模的乘幂运算, pow复杂度是log(exp)即log(MOD)
+ return pow(i, MOD - 2, MOD)
+
+ def divide_mod(self, a, b):
+ '''
+ 计算(a/b) % MOD, 除法变乘法,前提是b和MOD互为质数
+ '''
+ # 如果有多个b,比如a/b1/b2, 那就可以递归。a*mod_inverse(b1) % mod * mod_inverse(b2) % mod这样
+ return a * self.mod_inverse(b) % MOD
+
+ def divide_mods(self, a, b=[]):
+ '''
+ 计算a /(b1*b2*b3) % MOD等形式,前提是b和MOD互为质数
+ '''
+ r = a % MOD
+ for i, v in enumerate(b):
+ r *= self.mod_inverse(v)
+ r %= MOD
+ return r
+
+
+```
+
+
+
+### 大数幂取模
+
+```python
+r = pow(base=2, exp=3, mod=3)
+print(r)
+```
+
+
+
+## 阶乘
+
+```python
+import math
+math.factorial(3)
```
-最小公倍数就是a*b/gcd(a,b)
+
+
+## 分配问题
+
+### a能否分成满足条件的两份,其中只能分给指定一份
+
+[2513. 最小化两个数组中的最大值](https://leetcode.cn/problems/minimize-the-maximum-of-two-arrays/) 给你两个数组 arr1 和 arr2 ,它们一开始都是空的。你需要往它们中添加正整数,使它们满足以下条件:
+
+arr1 包含 uniqueCnt1 个 互不相同 的正整数,每个整数都 不能 被 divisor1 整除 。
+arr2 包含 uniqueCnt2 个 互不相同 的正整数,每个整数都 不能 被 divisor2 整除 。
+arr1 和 arr2 中的元素 互不相同 。
+给你 divisor1 ,divisor2 ,uniqueCnt1 和 uniqueCnt2 ,请你返回两个数组中 最大元素 的 最小值 。
+参考, [link](https://leetcode.cn/circle/discuss/YeBDQY/view/B8caF0/)
+
+**Key**: 判断过程中分为三类:保证在范围内有充足的数不是第一个数的倍数;不是第二个数的倍数;不为公倍数的数总数不少于总共要取的数。根据这三个条件即得到结果。
+
## 进制转换
```c++
@@ -222,11 +469,9 @@ int gcd(int a, int b) {
[可以参考](https://blog.csdn.net/u013349653/article/details/51367453)
- 十进制小数转二进制数:“乘以2取整,顺序排列”(乘2取整法)
-
- 例: (0.625)10= (0.101)2
-
+十进制小数转二进制数:“乘以 2 取整,顺序排列”(乘 2 取整法)
+例: (0.625)10= (0.101)2
@@ -242,7 +487,23 @@ int gcd(int a, int b) {
## 幂
-### 快速幂
+### 快速幂 O(logk)
+
+求 m^k mod p,时间复杂度 O(logk)。
+
+```c++
+int qmi(int m, int k, int p)
+{
+ int res = 1 % p, t = m;
+ while (k)
+ {
+ if (k&1) res = res * t % p;
+ t = t * t % p;
+ k >>= 1;
+ }
+ return res;
+}
+```
### 求根号
@@ -252,7 +513,7 @@ int gcd(int a, int b) {
### 求根号变种 小数精度
-`while l<=r`不用变,只需要变步长即可。eps可以比期望精度再小一个量级。
+`while l<=r`不用变,只需要变步长即可。eps 可以比期望精度再小一个量级。
```python
@@ -277,8 +538,6 @@ if __name__ == '__main__':
print(f(0.04, 1e-10))
```
+## Acwing 数学
-
-## Acwing数学
-
-[参考](https://www.acwing.com/file_system/file/content/whole/index/content/3273/) 本文只涉及部分
+[参考](https://www.acwing.com/file_system/file/content/whole/index/content/3273/) 本文只涉及部分
diff --git "a/_posts/Tech/Algorithms/2022-07-31-\347\256\200\345\215\225\345\233\276\347\232\204\346\234\200\345\244\247\347\216\257\346\234\200\351\225\277\351\223\276.md" "b/_posts/Tech/Algorithms/2022-07-31-\347\256\200\345\215\225\345\233\276\347\232\204\346\234\200\345\244\247\347\216\257\346\234\200\351\225\277\351\223\276.md"
new file mode 100644
index 0000000000..60c620721d
--- /dev/null
+++ "b/_posts/Tech/Algorithms/2022-07-31-\347\256\200\345\215\225\345\233\276\347\232\204\346\234\200\345\244\247\347\216\257\346\234\200\351\225\277\351\223\276.md"
@@ -0,0 +1,127 @@
+---
+layout: post
+category: Algorithms
+title: 简单图的最大环最长链
+tags: Algorithms
+---
+
+## 最大环最长链
+
+https://www.cnblogs.com/lfri/p/15758120.html
+
+最大环是针对的是出度为1的图,否则会多环重合。
+
+最长链是无环的图,求一个最长路径的长度。
+
+
+
+## 最大环
+
+### 有向图
+
+有多种方法:
+
+- 一种是先用拓扑排序将外链去掉,再dfs每一个环
+- DFS: 另一种是从某一点出发,记录途径的点,如果遇到已经访问过的点,说明找到了环的入口。减去起始点到入口的距离,就是环的长度。
+- 还有一种有并查集,对于`x->y`,如果`x`和`y`同属于一个集合,说明形成了一个环。
+
+
+
+dfs代码
+
+```python
+class Solution:
+ def longestCycle(self, edges: List[int]) -> int:
+ n = len(edges)
+ vis = collections.defaultdict(bool)
+ ans = -1
+ for i in range(n):
+ if vis[i]: continue
+ path = []
+ cur = i
+ while not vis[cur]:
+ vis[cur] = True
+ path.append(cur)
+ cur = edges[cur]
+ if cur == -1: break
+ if cur == -1: continue
+ for j in range(len(path)):
+ if path[j] == cur:
+ t = len(path) - j
+ ans = max(ans, t)
+ break
+ return ans
+```
+
+### 无向图
+
+和有向图类似,略
+
+## 最长链
+
+等价问题: [310. 最小高度树](https://leetcode.cn/problems/minimum-height-trees/)
+
+### 有向图
+
+这里有一个很重要的问题,有环怎么办?
+有环的情况下,求最长链是没有意义的。要么保证无环,要么是求连接到环上的链的长度。
+例如求连接到环上的链的长度,需要从入度为0的节点开始,递推计算,于是采用拓扑序。
+
+
+
+```c++
+int TopologicalSort(vector& favorite) {
+ int n = favorite.size();
+ vector vis(n, false);
+ vectorin(n, 0);
+ vectordp(n, 1);
+ queue q;
+ for(int i = 0;i < n;i++) in[favorite[i]]++;
+ for(int i = 0;i < n;i++) {
+ if(in[i] == 0) q.push(i);
+ }
+ while(!q.empty()) {
+ int cur = q.front();
+ q.pop();
+ // cout << cur << " ";
+ dp[favorite[cur]] = max(dp[favorite[cur]], dp[cur] + 1);
+ if(--in[favorite[cur]] == 0) q.push(favorite[cur]);
+ }
+ // dp[i] 表示到达i的最长链的长度
+ int two_point_sum = 0; // 题目相关部分
+ for(int i = 0;i < n;i++) {
+ if(i == favorite[favorite[i]]) two_point_sum += dp[i];
+ }
+ return two_point_sum;
+}
+```
+
+### 无向无环图
+
+- 也可以和有向图一样,拓扑序+dp
+- 还有一种有趣的方法,两次dfs。可以证明,从任一点出发,dfs能走到的最远点一定是"直径"的一个端点,然后从这个端点出发,dfs得到另一个端点。 参考下面【路径最长的两个叶子节点】
+
+例如[Leetcode310最小树高度](https://leetcode.cn/problems/minimum-height-trees/solution/zui-xiao-gao-du-shu-by-leetcode-solution-6v6f/),等价于求树的直径
+第一次dfs找到一个端点,再从这个端点出发dfs找到另一个端点,最后在写个dfs得到路径
+
+
+
+### DFS/BFS 求最长链
+
+> [参考](https://leetcode.cn/problems/minimum-height-trees/solution/zui-xiao-gao-du-shu-by-leetcode-solution-6v6f/)
+
+可以利用以下算法找到图中距离最远的两个节点与它们之间的路径:
+
+以任意节点 pp 出现,利用广度优先搜索或者深度优先搜索找到以 pp 为起点的最长路径的终点 xx;
+
+以节点 xx 出发,找到以 xx 为起点的最长路径的终点 yy;
+
+xx 到 yy 之间的路径即为图中的最长路径,找到路径的中间节点即为根节点。
+
+上述算法的证明可以参考「[算法导论习题解答 9-1](http://courses.csail.mit.edu/6.046/fall01/handouts/ps9sol.pdf)」。
+
+
+
+## 参考
+
+- [图的最大环最长链](https://www.cnblogs.com/lfri/p/15758120.html)
diff --git "a/_posts/Tech/Algorithms/2022-08-19-\346\225\260\344\275\215DP.md" "b/_posts/Tech/Algorithms/2022-08-19-\346\225\260\344\275\215DP.md"
new file mode 100644
index 0000000000..ffdd366c48
--- /dev/null
+++ "b/_posts/Tech/Algorithms/2022-08-19-\346\225\260\344\275\215DP.md"
@@ -0,0 +1,91 @@
+---
+layout: post
+category: Algorithms
+title: 数位DP
+tags: Algorithms
+---
+
+## 数位DP
+
+数位:把一个数字按照个、十、百、千等等一位一位地拆开,关注它每一位上的数字。如果拆的是十进制数,那么每一位数字都是 0~9,其他进制可类比十进制。
+
+数位 DP:用来解决一类特定问题,这种问题比较好辨认,一般具有这几个特征:
+
+1. 要求统计满足一定条件的数的数量(即,最终目的为计数);
+2. 这些条件经过转化后可以使用「数位」的思想去理解和判断;
+3. 输入会提供一个数字区间(有时也只提供上界)来作为统计的限制;
+4. 上界很大(比如 ),暴力枚举验证会超时。
+
+
+
+比如统计[a,b] 之间的满足某个条件的数,这个b可能是1e15这样。 注定无法枚举。此类就可以数位DP, 然后a到b形式也可以变成f(b) -f(a)差分来统一处理。记得a这个本身单个可能要额外减去。
+
+## 模板
+
+1. 记忆化搜索
+2. 关键参数: 数位i, 用过数字mask, is_limit是否是受限,is_num前面是否填了数字.后面两个参数可适用于其它数位 DP 题目。
+
+该模板对应[视频](https://www.bilibili.com/video/BV1rS4y1s721?vd_source=9d3646ab1738010f91f766880db9c1c6)
+
+题目: [2376. 统计特殊整数](https://leetcode.cn/problems/count-special-integers/)
+
+> 如果一个正整数每一个数位都是 **互不相同** 的,我们称它是 **特殊整数** 。
+>
+> 给你一个 **正** 整数 `n` ,请你返回区间 `[1, n]` 之间特殊整数的数目。
+
+```python
+class Solution:
+ def countSpecialNumbers(self, n: int) -> int:
+ # 数位dp
+ s = str(n)
+ import functools
+ '''
+ 记忆化搜索,i表示计算数位i, mark表示用过的数字
+ 返回从数位i开始填数字,前面填数字的集合为mask, 能构造出整数的数量
+ is_limit表示是否前i-1位是s对应位上的,即最大受限值max了,如果是则当前数字上线是s[i],而不是'9'
+ is_num表示前面是否填了数字,如果为True,则当前可从0开始,否则只能从1开始,后续会有个数位变成True, 从该数位开始是真实数字
+ '''
+ @functools.lru_cache(None)
+ def f(i: int, mask: int, is_limit: bool, is_num: bool):
+ if i == len(s):
+ # 最后一位了,合法则return 1
+ return int(is_num)
+ res = 0
+ if not is_num:
+ # 此时已经有前缀0了,因此不受限
+ res += f(i + 1, mask, False, False)
+ # 数位i的上限
+ up = int(s[i]) if is_limit else 9
+ # 如果是is_num, 则可以从0开始,否则只能从1开始,毕竟是第一位数字
+ for d in range(1 - int(is_num), up + 1):
+ if (mask >> d) & 1 == 0:
+ # 没用过该数字
+ res += f(i + 1, mask | (1 << d), is_limit and d == up, True)
+ return res
+
+ # 第一位就受限,因此is_limit = True
+ return f(0, 0, True, False)
+
+```
+
+## 应用
+
+- [902. 最大为 N 的数字组合](https://leetcode.cn/problems/numbers-at-most-n-given-digit-set/) 求1-N的使用了digits里数字的数量,没有0, f(i: int, is_limit: bool, is_num: bool)
+
+- [233. 数字 1 的个数](https://leetcode.cn/problems/number-of-digit-one/) 给定一个整数 `n`,计算所有小于等于 `n` 的非负整数中数字 `1` 出现的个数。def f(i: int, ones: int, is_limit: bool, is_num: bool): ones是当前已用ones的数量。
+
+- [面试题 17.06. 2出现的次数](https://leetcode.cn/problems/number-of-2s-in-range-lcci/) 和数字1的个数类似。
+
+- [600. 不含连续1的非负整数](https://leetcode.cn/problems/non-negative-integers-without-consecutive-ones/) 给定一个正整数 `n` ,返回范围在 `[0, n]` 都非负整数中,其二进制表示不包含 **连续的 1** 的个数。def f(i: int, last_is_one: bool, is_limit: bool)
+
+- [1012. 至少有 1 位重复的数字](https://leetcode.cn/problems/numbers-with-repeated-digits/) 等价为n-完全不重复个数
+
+- [1397. 找到所有好字符串](https://leetcode.cn/problems/find-all-good-strings/)
+
+- 给你两个长度为 n 的字符串 s1 和 s2 ,以及一个字符串 evil 。请你返回 好字符串 的数目。好字符串 的定义为:它的长度为 n ,字典序大于等于 s1 ,字典序小于等于 s2 ,且不包含 evil 为子字符串。 难点在于要动态维护kmp,先求evil的next数组,然后把匹配j当dp参数传递下去。
+
+
+
+## 参考
+
+https://leetcode.cn/problems/count-special-integers/solution/shu-wei-dp-mo-ban-by-endlesscheng-xtgx/
diff --git "a/_posts/Tech/Algorithms/2022-10-10-\345\255\227\347\254\246\344\270\262hash.md" "b/_posts/Tech/Algorithms/2022-10-10-\345\255\227\347\254\246\344\270\262hash.md"
new file mode 100644
index 0000000000..83d09a4b43
--- /dev/null
+++ "b/_posts/Tech/Algorithms/2022-10-10-\345\255\227\347\254\246\344\270\262hash.md"
@@ -0,0 +1,73 @@
+---
+layout: post
+category: Algorithms
+title: 字符串hash
+tags: Algorithms
+---
+
+## 字符串hash
+
+字符串hash得到hash值,用于o(1)时间复杂度判断是否相等。在提前计算好整个字符串的预处理情况下,可快速比较某两子串是否相等。
+
+
+
+[oi wiki参考](https://oi-wiki.org/string/hash/)
+
+
+
+
+
+
+
+## 模板
+
+```python
+class StringHash:
+ def __init__(self, s=""):
+ self.MOD = 998244353
+ self.BASE = 131
+ # 计算前缀哈希值
+ n = len(s)
+ P = [0] * (n + 1)
+ P[0] = 1
+ for i in range(1, n + 1, 1):
+ P[i] = P[i - 1] * self.BASE % self.MOD
+ H = [0] * (n + 1)
+ for i in range(1, n + 1, 1):
+ H[i] = (H[i - 1] * self.BASE + ord(s[i - 1])) % self.MOD
+ self.H = H
+ self.P = P
+
+ '''
+ s的[l,r]区间的hash值,闭区间, l从1开始
+ '''
+
+ def get_hash(self, l=0, r=0):
+ l, r = l + 1, r + 1
+ return (self.H[r] - self.H[l - 1] * self.P[r - l + 1] % self.MOD + self.MOD) % self.MOD
+
+示例: https://leetcode.cn/problems/maximum-deletions-on-a-string/submissions/
+class Solution:
+ def deleteString(self, s: str) -> int:
+ n = len(s)
+ dp = [1] * n
+ hash = StringHash(s)
+ for i in range(n - 1, -1, -1):
+ for j in range(i + 1, n):
+ if (j - i + 1) % 2 == 0:
+ mid = (i + j) // 2
+ if hash.get_hash(i, mid) == hash.get_hash(mid+1, j):
+ # print(i, j, mid)
+ dp[i] = max(dp[i], dp[mid+1]+1)
+ # print(dp[i])
+ # print(dp)
+ return dp[0]
+```
+
+
+
+## 题目
+
+
+
+题目: https://leetcode.cn/problems/maximum-deletions-on-a-string/solution/by-tsreaper-9xkh/
diff --git "a/_posts/Tech/Algorithms/2022-10-16-\345\217\214\346\214\207\351\222\210.md" "b/_posts/Tech/Algorithms/2022-10-16-\345\217\214\346\214\207\351\222\210.md"
new file mode 100644
index 0000000000..66fdad41f9
--- /dev/null
+++ "b/_posts/Tech/Algorithms/2022-10-16-\345\217\214\346\214\207\351\222\210.md"
@@ -0,0 +1,39 @@
+---
+layout: post
+category: Algorithms
+title: 双指针
+tags: Algorithms
+---
+
+## 双指针
+
+
+
+1. 统计子数组数目,枚举右边界,左边界视情况而定。比如求子数组数目,要求子数组包含两个值,那枚举i,j就等于有两个值的最后最小坐标,每次结果可加i-j+1, 实例题目 [6207. 统计定界子数组的数目](https://leetcode.cn/problems/count-subarrays-with-fixed-bounds/) [题解](https://leetcode.cn/problems/count-subarrays-with-fixed-bounds/solution/hua-dong-chuang-by-yi-wei-8-c7h7/)
+
+2. [3Sum](https://leetcode-cn.com/problems/3sum/) 排序+双指针
+
+3. [Longest Repeating Character Replacement](https://leetcode-cn.com/problems/longest-repeating-character-replacement/) 给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
+
+ 解答: **双指针。这个双指针属于left每次只移动一次,记得看下。**
+
+4. [11. 盛最多水的容器](https://leetcode.cn/problems/container-with-most-water/) 多个柱子,挑两个柱子,统计最多能接多少水,双指针,不断缩小两边矮的那个
+
+5. [1438. 绝对差不超过限制的最长连续子数组](https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/) 给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。 维护max, min的队列,同时双指针,不断移动左指针。
+
+6. [6270. 每种字符至少取 K 个](https://mafulong.github.io/2022/12/25/6270.-%E6%AF%8F%E7%A7%8D%E5%AD%97%E7%AC%A6%E8%87%B3%E5%B0%91%E5%8F%96-K-%E4%B8%AA/) 给你一个由字符 `'a'`、`'b'`、`'c'` 组成的字符串 `s` 和一个非负整数 `k` 。每分钟,你可以选择取走 `s` **最左侧** 还是 **最右侧** 的那个字符。
+
+ 你必须取走每种字符 **至少** `k` 个,返回需要的 **最少** 分钟数
+
+7. [1658. 将 x 减到 0 的最小操作数](https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/)
+
+8. 给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。
+
+ 如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。
+
+ 反向思考,找最大子数组。
+
+
+
+
+
diff --git "a/_posts/Tech/Algorithms/2023-01-15-\346\240\221\345\275\242DP\345\222\214\346\215\242\346\240\271DP.md" "b/_posts/Tech/Algorithms/2023-01-15-\346\240\221\345\275\242DP\345\222\214\346\215\242\346\240\271DP.md"
new file mode 100644
index 0000000000..e6bbb31406
--- /dev/null
+++ "b/_posts/Tech/Algorithms/2023-01-15-\346\240\221\345\275\242DP\345\222\214\346\215\242\346\240\271DP.md"
@@ -0,0 +1,227 @@
+---
+layout: post
+category: Algorithms
+title: 树形DP和换根DP
+tags: Algorithms
+---
+
+## 树形DP和换根DP
+
+[oi wiki](https://oi-wiki.org/dp/tree/)
+
+## 树形DP
+
+固定一个根节点。在树上做DP. 往往是树dfs遍历,先子树再基于子树结果对当前节点DP递推到根节点。
+
+
+
+对于图转树的DFS遍历,其实就是无向树。
+
+```python
+class DoubleTree:
+ def tree_dfs(graph, root):
+ '''
+ 这种树上dfs不需要维护visit记录,只需要记录遍历刀当前节点的parent就可以了。时间复杂度o(n)
+ '''
+ import collections
+ p = collections.defaultdict(lambda: -1)
+
+ def dfs(u):
+ if len(graph[u]) == 1 and u in p:
+ print("is leaf")
+ for v in graph[u]:
+ if p[u] != v: # 非访问过
+ # 多次生效,针对多个v
+ p[v] = u
+ dfs(v)
+
+ def dfs_p(u, p):
+ if len(graph[u]) == 1 and u != root:
+ # 判断叶子节点时要用和这个双重判断
+
+ print("is leaf")
+ for v in graph[u]:
+ if v != p:
+ dfs_p(v, u)
+
+
+```
+
+
+
+也可以通过 g[0].append(-1) # 防止根节点被认作叶子
+
+
+
+
+
+经典树形DP
+
+- [124. 二叉树中的最大路径和](https://leetcode.cn/problems/binary-tree-maximum-path-sum/) 给你一个二叉树的根节点 `root` ,返回其 **最大路径和** 。
+
+ ```python
+ class Solution:
+ ans = float('-inf')
+
+ def maxPathSum(self, root: TreeNode) -> int:
+ def dfs(node):
+ if not node:
+ return 0
+ l = dfs(node.left)
+ r = dfs(node.right)
+ self.ans = max(self.ans, max(l, 0) + max(r, 0) + node.val)
+ return max(l, r, 0) + node.val
+ dfs(root)
+ return self.ans
+ ```
+
+
+
+- [310. 最小高度树](https://leetcode.cn/problems/minimum-height-trees/)
+- [6294. 最大价值和与最小价值和的差值](https://leetcode.cn/problems/difference-between-maximum-and-minimum-price-sum/) 求最长直径,随便固定一个点为root。 树形DP
+- [2246. 相邻字符不同的最长路径](https://leetcode.cn/problems/longest-path-with-different-adjacent-characters/) 和最大路径和一样
+
+
+
+
+
+## 换根DP
+
+- [参考](https://leetcode.cn/problems/difference-between-maximum-and-minimum-price-sum/solution/huan-gen-dong-tai-gui-hua-jie-fa-by-vcli-gaii/)
+
+树形 DP 中的换根 DP 问题又被称为二次扫描,通常不会指定根结点,并且根结点的变化会对一些值,例如子结点深度和、点权和等产生影响。
+
+通常需要两次 DFS,第一次 DFS 预处理诸如深度,点权和之类的信息,在第二次 DFS 开始运行换根动态规划。
+
+第二次dfs时,把父节点作为子树。来调整。比如 [参考](https://zhuanlan.zhihu.com/p/437753260)
+
+
+
+需要计算出换根后的值的变化。 然后枚举根。
+
+
+
+每次换根只能换相邻的。否则影响其它节点计算。只有相邻时只影响相邻的。而且枚举的一定是根,而不是第三个点为根的情况的相邻递推。
+
+换根后不用恢复数据,因为是邻接点递推的。其它的没用。
+
+
+
+
+记住每次改变只有u 和 v的dp值改变。[详细](https://leetcode.cn/problems/sum-of-distances-in-tree/solution/shu-zhong-ju-chi-zhi-he-by-leetcode-solution/)
+
+
+- [834. 树中距离之和](https://leetcode.cn/problems/sum-of-distances-in-tree/) 给定一个无向、连通的树。树中有 `n` 个标记为 `0...n-1` 的节点以及 `n-1` 条边 。返回长度为 `n` 的数组 `answer` ,其中 `answer[i]` 是树中第 `i` 个节点与所有其他节点之间的距离之和。
+- [310. 最小高度树](https://leetcode.cn/problems/minimum-height-trees/) [参考题解](https://leetcode.cn/problems/difference-between-maximum-and-minimum-price-sum/solution/huan-gen-dong-tai-gui-hua-jie-fa-by-vcli-gaii/)
+
+```python
+class Solution:
+ def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
+ graph = collections.defaultdict(list)
+ for a, b in edges:
+ graph[a].append(b)
+ graph[b].append(a)
+ h0 = [0 for _ in range(n)]
+
+ def dfs(u, p):
+ nonlocal h0
+ l = 0
+ for v in graph[u]:
+ if v == p: continue
+ l = max(l, dfs(v, u) + 1)
+ h0[u] = l
+ return l
+
+ dfs(0, -1)
+ # print(h0)
+
+ dp = [0] * n
+
+ def dfs2(u, p):
+ nonlocal dp
+ # 此时就是u为root,每次进入函数都是已经换根为u了。此时孩子的h0是准的,h0[u]是不准的,需要根据孩子重新计算
+ first, second = -1, -1
+ for v in graph[u]:
+ if h0[v] >= first:
+ second = first
+ first = h0[v]
+ elif h0[v] >= second:
+ second = h0[v]
+ dp[u] = first + 1
+ # print(u, dp[u])
+ for v in graph[u]:
+ if v == p: continue
+ # 假设u与v换根
+ h0[u] = first if h0[v] != first else second
+ h0[u] += 1
+ dfs2(v, u)
+
+ dfs2(0, -1)
+ # print(dp)
+ minv = min(dp)
+ ans = []
+ for i in range(n):
+ if dp[i] == minv:
+ ans.append(i)
+ return ans
+
+```
+
+
+
+- [6294. 最大价值和与最小价值和的差值](https://leetcode.cn/problems/difference-between-maximum-and-minimum-price-sum/) 换根DP
+
+```python
+class Solution:
+ def maxOutput(self, n: int, edges: List[List[int]], price: List[int]) -> int:
+ graph = collections.defaultdict(list)
+ for a, b in edges:
+ graph[a].append(b)
+ graph[b].append(a)
+ # 求最大价值和
+ h0 = [0 for _ in range(n)]
+
+
+ # 第一次遍历,统计以0为根的结果
+ def dfs(u, p):
+ nonlocal h0
+ l = price[u]
+ for v in graph[u]:
+ if v == p: continue
+ dfs(v, u)
+ l = max(l, price[u] + h0[v])
+ h0[u] = l
+ return l
+
+ dfs(0, -1)
+ # print(h0)
+
+ dp = [0] * n
+
+ def dfs2(u, p):
+ nonlocal dp
+ # 此时就是u为root,每次进入函数都是已经换根为u了。此时孩子的h0是准的,h0[u]是不准的,需要根据孩子重新计算下h0[u]
+ first, second = 0, 0
+ dp[u] = 0
+ for v in graph[u]:
+ # 此时不能continue,因为p是有用的,u为root,无p
+ # if v == p: continue
+ if h0[v] >= first:
+ second = first
+ first = h0[v]
+ elif h0[v] >= second:
+ second = h0[v]
+ # 以u为根情况下 h0和dp的值
+ dp[u] = first
+ h0[u] = first + price[u]
+ # print(u, dp[u], first, second)
+ for v in graph[u]:
+ if v == p: continue
+ # 假设u与v换根
+ h0[u] = price[u] + (first if (h0[v] != first) else second)
+ dfs2(v, u)
+
+ dfs2(0, -1)
+ return max(dp)
+```
+
diff --git "a/_posts/Tech/Algorithms/2023-01-29-\347\273\237\350\256\241\345\233\233\345\205\203\347\273\204\344\271\213\344\270\255\351\227\264\346\236\232\344\270\276.md" "b/_posts/Tech/Algorithms/2023-01-29-\347\273\237\350\256\241\345\233\233\345\205\203\347\273\204\344\271\213\344\270\255\351\227\264\346\236\232\344\270\276.md"
new file mode 100644
index 0000000000..087462b364
--- /dev/null
+++ "b/_posts/Tech/Algorithms/2023-01-29-\347\273\237\350\256\241\345\233\233\345\205\203\347\273\204\344\271\213\344\270\255\351\227\264\346\236\232\344\270\276.md"
@@ -0,0 +1,23 @@
+---
+layout: post
+category: Algorithms
+title: 统计四元组之中间枚举
+tags: Algorithms
+---
+
+## 统计四元组之技巧 中间枚举
+
+有些题目是让统计四元组之类的数量。
+
+此时就可以枚举中间的。
+
+通常可以应用些预处理来降低时间复杂度。
+
+
+
+应用
+
+- [6340. 统计上升四元组](https://leetcode.cn/contest/weekly-contest-330/problems/count-increasing-quadruplets/) [参考](https://leetcode.cn/circle/discuss/LWLEFc/view/4dIQzE/)
+
+- [2242. 节点序列的最大得分](https://leetcode.cn/problems/maximum-score-of-a-node-sequence/)
+
diff --git "a/_posts/Tech/Database/2021-01-09-\346\225\260\346\215\256\345\272\223\345\257\271\346\257\224.md" "b/_posts/Tech/Database/2021-01-09-\346\225\260\346\215\256\345\272\223\345\257\271\346\257\224.md"
index 0f45d5872d..1d12cfacdb 100644
--- "a/_posts/Tech/Database/2021-01-09-\346\225\260\346\215\256\345\272\223\345\257\271\346\257\224.md"
+++ "b/_posts/Tech/Database/2021-01-09-\346\225\260\346\215\256\345\272\223\345\257\271\346\257\224.md"
@@ -270,4 +270,19 @@ Google 发布了第一个列型存储数据库 [Bigtable](http://www.read.seas.h
- 排行榜或者得分数据
- 临时数据,如购物车
- 频繁访问的(“热”)表
-- 元数据/查找表
\ No newline at end of file
+- 元数据/查找表
+
+
+
+## NoSQL
+
+> [参考](https://aws.amazon.com/cn/nosql/)
+
+### 为什么应该使用 NoSQL 数据库?
+
+NoSQL 数据库非常适合许多现代应用程序,例如移动、Web 和游戏等应用程序,它们需要灵活、可扩展、高性能和功能强大的数据库以提供卓越的用户体验。
+
+- **灵活性:**NoSQL 数据库通常提供灵活的架构,以实现更快速、更多的迭代开发。灵活的数据模型使 NoSQL 数据库成为半结构化和非结构化数据的理想之选。
+- **可扩展性:**NoSQL 数据库通常被设计为通过使用分布式硬件集群来横向扩展,而不是通过添加昂贵和强大的服务器来纵向扩展。一些云提供商在后台将这些操作处理为完全托管服务。
+- **高性能:**NoSQL 数据库针对特定的数据模型和访问模式进行了优化,这与尝试使用关系数据库完成类似功能相比可实现更高的性能。
+- **强大的功能:**NoSQL 数据库提供功能强大的 API 和数据类型,专门针对其各自的数据模型而构建。
\ No newline at end of file
diff --git a/_posts/Tech/DistributedSystem/2020-12-15-SOA.md b/_posts/Tech/DistributedSystem/2020-12-15-SOA.md
index 9242fbf352..eda984b5d1 100644
--- a/_posts/Tech/DistributedSystem/2020-12-15-SOA.md
+++ b/_posts/Tech/DistributedSystem/2020-12-15-SOA.md
@@ -63,3 +63,55 @@ SOA粗暴理解:把系统按照实际业务,拆分成刚刚好大小的、
## SOA和微服务microservice的区别
+我们应该将SOA视为微服务的超集。
+
+
+
+| **SOA架构** | **微服务架构** |
+| ---------------------------------------- | ---------------------------------------- |
+| 最大化应用服务的可重用性 | 关注于解耦 |
+| 系统的变化需要修改整体结构 | 系统的变化是创造一种新的服务 |
+| DevOps和持续交付正在变得流行,但不是主流 | 专注于DevOps和持续交付 |
+| 专注于业务功能的可重用性 | 更加重视“边界上下文”的概念 |
+| 对于通信,它使用企业服务总线(ESB) | 对于通信使用不那么复杂和简单的消息系统 |
+| 支持多种消息协议 | 使用轻量级协议,如HTTP,REST或Thrift API |
+| 为部署到它的所有服务使用通用平台 | 应用服务器并未真正使用,通常使用云平台 |
+| 使用容器(如Docker)不太受欢迎 | 容器与微服务一起工作得很好 |
+| SOA服务共享数据存储 | 每个微服务可以具有独立的数据存储 |
+| 共同治理和标准 | 轻松治理,更加注重团队协作和选择自由度 |
+
+我将在上表中显示的某些方面进一步详细说明,并进一步解释其中的差异:
+
+-
+
+ 开发 - 在这两种体系结构中,可以使用不同的编程语言和工具开发服务,从而为开发团队带来技术多样性。可以在多个团队中组织开发,但是,在SOA中,每个团队都需要了解常见的通信机制。另一方面,通过微服务,服务可以独立于其他服务运行和部署。因此,更容易经常部署新版本的微服务或独立扩展服务。您可以在此处进一步了解微服务的这些优点。
+
+-
+
+ “绑定上下文” - SOA鼓励共享组件,而微服务试图通过“绑定上下文”最小化共享。绑定上下文指的是将组件及其数据作为单个单元耦合,具有最小的依赖性。由于SOA依赖于多种服务来满足业务请求,因此基于SOA构建的系统可能比微服务慢。
+
+-
+
+ 通信 - 在SOA中,ESB可能成为影响整个系统的单点故障。由于每个服务都通过ESB进行通信,如果其中一个服务速度变慢,它可能会阻塞ESB请求该服务。另一方面,微服务在容错方面要好得多。例如,如果一个微服务有内存故障,那么只有那个微服务会受到影响。所有其他微服务将继续定期处理请求。
+
+-
+
+ 互操作性 - SOA通过其消息传递中间件组件促进多个异构协议的使用。微服务试图通过减少集成选择的数量来简化架构模式。**因此,如果要在异构环境中使用不同协议集成多个系统,则需要考虑SOA。如果可以通过相同的远程访问协议访问所有服务,那么微服务对您来说是更好的选择。**
+
+-
+
+ 大小 - 最后但并非最不重要的是,**SOA和微服务之间的主要区别在于大小和范围。微服务中的前缀“微”指的是内部组件的粒度,这意味着它们必须比SOA趋向于小得多。微服务中的服务组件通常只有一个目的,他们做得很好。另一方面,在SOA中,服务通常包含更多的业务功能,并且它们通常作为完整的子系统实现。**
+
+
+
+人们不能简单地说一个架构比另一个架构好。它主要取决于您正在构建的应用程序的目的。**SOA更适合需要与许多其他应用程序集成的大型复杂企业应用程序环境。** 话虽这么说,**较小的应用程序不适合SOA,因为它们不需要消息传递中间件组件。** 另一方面,**微服务更适合于较小且分区良好的基于Web的系统。此外,如果您正在开发移动或Web应用程序,那么微服务可以让您作为开发人员获得更大的控制权。** 最后,我们可以得出结论,因为它们用于不同的目的 - **微服务和SOA确实是不同类型的架构。**
+
+
+
+
+
+SOA范围大,着眼于整个企业,而微服务范围小,着眼于应用。
+
+**SOA是与企业服务的公开性密切相关的,关注的范围更大,是应用与应用之间的通信、服务公开。**
+
+**微服务是与应用架构紧密相关的,关注的范围小,只关注应用本身的范围。**
diff --git "a/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md" "b/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
index 451b6f264b..cde54a6f67 100644
--- "a/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
+++ "b/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\344\272\213\345\212\241.md"
@@ -96,6 +96,11 @@ __两阶段提交协议解决的是分布式数据库数据强一致性问题__
针对两阶段提交存在的问题,三阶段提交协议通过引入一个 **预询盘** 阶段,以及超时策略来减少整个集群的阻塞时间,提升系统性能。三阶段提交的三个阶段分别为:预询盘(can_commit)、预提交(pre_commit),以及事务提交(do_commit)。
+
+
+1. 引入canCommit阶段减少**同步阻塞**。
+2. 引入超时减少**单点故障**,没有协调者消息并超时了,直接 commit
+
#### 第一阶段:预询盘
该阶段协调者会去询问各个参与者是否能够正常执行事务,参与者根据自身情况回复一个预估值,相对于真正的执行事务,这个过程是轻量的,具体步骤如下:
diff --git "a/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\347\256\227\346\263\225\345\222\214\345\215\217\350\256\256.md" "b/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\347\256\227\346\263\225\345\222\214\345\215\217\350\256\256.md"
index 98418ccab5..6b202f985b 100644
--- "a/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\347\256\227\346\263\225\345\222\214\345\215\217\350\256\256.md"
+++ "b/_posts/Tech/DistributedSystem/2021-01-09-\345\210\206\345\270\203\345\274\217\347\256\227\346\263\225\345\222\214\345\215\217\350\256\256.md"
@@ -3,6 +3,7 @@ layout: post
category: DistributedSystem
title: 分布式算法和协议
tags: DistributedSystem
+recent_update: true
---
## 分布式算法和协议-思维导图
@@ -37,6 +38,14 @@ tags: DistributedSystem
+这里的ZAB为何是最终一致性而不是强一致性?[参考](https://www.zhihu.com/question/455703356/answer/1847949827)
+
+- 写是强一致性,单领导者模型,写需要majority保证,脑裂情况下也可以写强一致
+- 读两种接口,1:读单个机器的,2:只读主的。但脑裂时多个主还是不能强一致性。
+- etcd做了读的优化,读时也需要majority,需要大伙同意认为它是主,但牺牲了效率。
+
+这里的一致性是从读写方面,写一致性,都写成功,读一致性,从提供的读接口任意时刻咋读都一样。和事务一致性不太一样。
+
## 分布式互斥方法(集中,民主协商,轮值ceo(令牌))

diff --git "a/_posts/Tech/DistributedSystem/2021-12-26-etcd\345\222\214raft.md" "b/_posts/Tech/DistributedSystem/2021-12-26-etcd\345\222\214raft.md"
index 3fd12cdff4..0bf8fbfdf5 100644
--- "a/_posts/Tech/DistributedSystem/2021-12-26-etcd\345\222\214raft.md"
+++ "b/_posts/Tech/DistributedSystem/2021-12-26-etcd\345\222\214raft.md"
@@ -3,6 +3,7 @@ layout: post
category: DistributedSystem
title: etcd和raft
tags: DistributedSystem
+recent_update: true
---
# etcd
diff --git "a/_posts/Tech/DistributedSystem/2022-11-26-\346\227\240\344\270\273\345\244\215\345\210\266\347\263\273\347\273\237.md" "b/_posts/Tech/DistributedSystem/2022-11-26-\346\227\240\344\270\273\345\244\215\345\210\266\347\263\273\347\273\237.md"
new file mode 100644
index 0000000000..ee018bc3b1
--- /dev/null
+++ "b/_posts/Tech/DistributedSystem/2022-11-26-\346\227\240\344\270\273\345\244\215\345\210\266\347\263\273\347\273\237.md"
@@ -0,0 +1,63 @@
+---
+layout: post
+category: DistributedSystem
+title: 无主复制系统
+tags: DistributedSystem
+---
+
+为什么需要复制数据? - 允许系统在部分节点出现故障后继续工作(增加可用性) - 地理上保持数据离用户更近(减少延迟) - 扩展可以提供查询的机器数量(增加读吞吐)
+
+复制算法: 1. 单主复制:所有客户端都将写入操作发送到主节点上,该节点负责将数据更改事件发送到其它副本。每个副本都可以接受读请求,但内容可能是过期值。 2. 多主复制:系统中存在多个主节点,每个都可以接受请求,客户端将写请求发送到其中一个主节点上,该节点负责将数据更改事件同步到其它主节点和自己的从节点。 3. 无主复制:客户端将写请求发送多个节点上,读取时从多个节点上并行读取,以此检测和纠正某些过期数据。
+
+主从复制可参考 [link](https://iswade.github.io/database/replication/)
+
+## 无主复制
+
+单主、多主复制思路都是:客户端向一个主节点发写请求,而DB系统负责将写请求复制到其他副本。主节点决定写顺序,从节点按相同顺序应用主节点发送的写日志。
+
+某些数据存储系统采用不同设计:放弃主节点,允许任何副本直接接受客户端的写。最早的复制数据系统就是无主节点的(或称之为去中心复制、无中心复制),但后来在关系数据库主导时代,这个想法几乎被忘却。在亚马逊将其用于其内部的Dynamo系统后,它再一次成为流行的DB架构。 Riak,Cassandra和Voldemort都是由Dynamo启发的无主复制模型的开源数据存储,所以这类数据库也被称为*Dynamo风格*。
+
+
+
+在一些无主实现中,客户端直接将写请求发到多副本,而另一些实现中,有一个协调者(coordinator)节点代表客户端进行写入,但与主节点的数据库不同,协调者不负责维护写入顺序。这种设计差异对DB使用方式有深远影响。
+
+
+
+失效节点重新上线,而客户端开始读取它。节点失效期间发生的任何写入在该节点都尚未同步,因此读取可能得到过期数据。
+
+为解决该问题,当一个客户端从DB读数据时,它不是向1个副本发送请求,而是并行发送到多副本。客户端可能会从不同节点获得不同响应,即来自一个节点的最新值和来自另一个节点的旧值。可利用版本号确定哪个值更新。
+
+### 读修复和反熵
+
+复制模型应确保所有数据最终复制到所有副本。在一个失效节点重新上线后,它如何赶上错过的写入呢?
+
+Dynamo风格的数据存储系统常机制:
+
+#### 读修复(Read repair)
+
+当客户端并行读取多副本时,可检测到过期的返回值。客户端可判断副本3是过期值,然后将新值写入该副本。适用于读密集场景
+
+#### 反熵过程(Anti-entropy process)
+
+一些数据存储有后台进程,不断查找副本之间的数据差异,将任何缺少的数据从一个副本复制到另一个副本。和基于主节点复制的复制日志不同,此反熵过程不保证任何特定的顺序复制写入,并且会引入明显的同步滞后
+
+
+
+并非所有系统都实现这俩方案。如Voldemort目前无反熵过程。若无反熵过程,由于【读修复】只在发生读取时才可能执行修复,那些很少访问的数据有可能在某些副本中已丢失而无法再检测到,从而降低了写的持久性。
+
+
+
+反熵就是树形的hash,用于快速比较数据是否一致的。
+
+
+
+## 参考
+
+- [**无主复制系统(1)-节点故障时写DB**](https://blog.51cto.com/u_11440114/5550577)
+- [**无主复制系统(2)-读写quorum**](https://blog.51cto.com/u_11440114/5550582)
+
+
+
+
+
+TODO: 需要读下ddia.
diff --git a/_posts/Tech/ElasticSearch/2020-12-08-ElasticSearch.md b/_posts/Tech/ElasticSearch/2020-12-08-ElasticSearch.md
index de4939df98..5eda1601ec 100644
--- a/_posts/Tech/ElasticSearch/2020-12-08-ElasticSearch.md
+++ b/_posts/Tech/ElasticSearch/2020-12-08-ElasticSearch.md
@@ -3,6 +3,7 @@ layout: post
category: ElasticSearch
title: ElasticSearch(ES)原理
tags: ElasticSearch
+recent_update: true
---
## Part1: ES介绍及核心概念
diff --git "a/_posts/Tech/FrontEnd/2017-12-03-css\345\255\246\344\271\240\347\254\224\350\256\260.md" "b/_posts/Tech/FrontEnd/2017-12-03-css\345\255\246\344\271\240\347\254\224\350\256\260.md"
index 1df5eb98e6..a76bfdfb2d 100644
--- "a/_posts/Tech/FrontEnd/2017-12-03-css\345\255\246\344\271\240\347\254\224\350\256\260.md"
+++ "b/_posts/Tech/FrontEnd/2017-12-03-css\345\255\246\344\271\240\347\254\224\350\256\260.md"
@@ -4,7 +4,39 @@ category: FrontEnd
title: CSS笔记
tags: FrontEnd
---
+# 概述
+
+CSS:Cascading Style Sheet,层叠样式表。CSS 的作用就是给 HTML 页面标签添加各种样式,**定义网页的显示效果**。简单一句话:CSS 将网页**内容和显示样式进行分离**,提高了显示功能。
+
+**CSS 优点:**
+
+1. 使数据和显示分开
+2. 降低网络流量
+3. 使整个网站视觉效果一致
+4. 使开发效率提高了(耦合性降低,一个人负责写 html,一个人负责写 css)
+
+比如说,有一个样式需要在一百个页面上显示,如果是 html 来实现,那要写一百遍,现在有了 css,只要写一遍。现在,html 只提供数据和一些控件,完全交给 css 提供各种各样的样式。
+
+重点:盒子模型、浮动、定位
+
+
+
+CSS 的书写方式,实就是问你 CSS 的代码放在哪个位置。CSS 代码理论上的位置是任意的,**但通常写在`
+
+
+
+
+
+