diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml deleted file mode 100644 index 9dfbb40..0000000 --- a/.github/workflows/pr-preview.yml +++ /dev/null @@ -1,133 +0,0 @@ -name: PR Preview (Changed Files Only) - -on: - pull_request: - types: [opened, synchronize, reopened, closed] - -jobs: - preview: - runs-on: ubuntu-latest - if: github.event.action != 'closed' - permissions: - contents: read - pages: write - id-token: write - pull-requests: write - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: actions/setup-node@v4 - with: - node-version: 18 - - # 変更されたMDファイルを取得 - - name: Get changed markdown files - id: changed-files - run: | - # PRで変更されたMDファイルを取得 - git diff --name-only origin/main...HEAD | grep '\.md$' > changed_files.txt || true - echo "Changed MD files:" - cat changed_files.txt - echo "files<> $GITHUB_OUTPUT - cat changed_files.txt >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - # 変更されたファイルのみでプレビューサイトを構築 - - name: Create preview structure - run: | - mkdir -p preview-site - - # 変更されたファイルをコピー - if [ -s changed_files.txt ]; then - while IFS= read -r file; do - if [ -n "$file" ] && [ -f "$file" ]; then - mkdir -p "preview-site/$(dirname "$file")" - cp "$file" "preview-site/$file" - echo "Copied: $file" - fi - done < changed_files.txt - fi - - # index.mdがない場合は作成 - if [ ! -f "preview-site/index.md" ] && [ ! -f "preview-site/README.md" ]; then - cat > preview-site/index.md << 'EOF' - # PR変更ファイルプレビュー - - このPRで変更されたMarkdownファイル一覧: - - EOF - if [ -s changed_files.txt ]; then - while IFS= read -r file; do - if [ -n "$file" ]; then - echo "- [$file]($file)" >> preview-site/index.md - fi - done < changed_files.txt - else - echo "変更されたMarkdownファイルがありません。" >> preview-site/index.md - fi - fi - - echo "Preview site structure:" - find preview-site -type f - - - run: | - cd preview-site - npm init -y - npm install -D vitepress - - - run: | - cd preview-site - mkdir -p .vitepress - cat > .vitepress/config.js << 'EOF' - export default { - title: 'PR Preview (Changed Files)', - base: '/${{ github.event.repository.name }}/pr-${{ github.event.number }}/', - markdown: { lineNumbers: true } - } - EOF - - - name: Build VitePress - run: | - cd preview-site && npx vitepress build - echo "Build completed. Contents:" - find .vitepress/dist -type f | head -10 - - - name: Deploy to GitHub Pages - run: | - cd preview-site/.vitepress/dist - git init - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add . - git commit -m "Deploy PR ${{ github.event.number }} preview" - git push --force --quiet "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" main:gh-pages - - - uses: actions/github-script@v7 - with: - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: `📝 Changed files preview: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-${{ github.event.number }}/` - }); - - cleanup: - runs-on: ubuntu-latest - if: github.event.action == 'closed' - permissions: - contents: write - pull-requests: write - steps: - - uses: actions/checkout@v4 - with: - ref: gh-pages - - run: | - rm -rf pr-${{ github.event.number }} || true - git config user.name github-actions - git config user.email github-actions@github.com - git add . - git commit -m "Remove PR ${{ github.event.number }} preview" || exit 0 - git push \ No newline at end of file diff --git a/42. Trapping Rain Water.md b/42. Trapping Rain Water.md new file mode 100644 index 0000000..b1c61ce --- /dev/null +++ b/42. Trapping Rain Water.md @@ -0,0 +1,142 @@ +## step1 とりあえず解く +- 計算量 + - 時間:O(N^2) + - 空間:O(N) +- 解けなかったが考えたアプローチとしては + - 与えられた配列から、前後より高いBarを探してそのindexを配列に保持する + - index配列からその高いBarの間に溜まっている水の堆積を計算する +- このアプローチがうまく行かないケース + - input + - height=[4,2,0,3,2,5] + - 局所的な高いBarしか探していないため上記のような入力では正しい回答が得られない +- 上記アプローチをもとに実装した内容 + +```java +class Solution { + public int trap(int[] height) { + List heigherBarIndex = new ArrayList<>(); + for (int i = 0; i < height.length - 1; i++) { + if (i == 0 && height[i] > height[i+1]) { + heigherBarIndex.add(i); + continue; + } + if (i > 0 && height[i] > height[i-1] && height[i] > height[i+1]) { + heigherBarIndex.add(i); + } + } + int ans = 0; + for (int i = 0; i < heigherBarIndex.size() - 1; i++) { + int size = Math.min(height[heigherBarIndex.get(i)], height[heigherBarIndex.get(i+1)]) + * (heigherBarIndex.get(i + 1) - heigherBarIndex.get(i) -1); + int start = heigherBarIndex.get(i) + 1; + while (start < heigherBarIndex.get(i+1)){ + size -= height[start]; + start++; + } + ans += size; + } + return ans; + } +} + +``` + +## step2 他の人の回答を見る +- 計算量 + - 時間:O(N) + - 空間:O(N) +- 考え方としては、そのBarにためられる水の量は「そのBarから見た時のmin(leftMax, rightMax)-そのBarの高さ」 + - 上記計算が負の場合は水が溢れるのでたまらないと判断 +- 各Barに対してleftMax, rightMaxを配列で保持し最後に上記考え方で算出する + +```java +public class Solution { + public int trap(int[] height) { + int n = height.length; + if (n == 0) { + return 0; + } + + int[] leftMax = new int[n]; + int[] rightMax = new int[n]; + + leftMax[0] = height[0]; + for (int i = 1; i < n; i++) { + leftMax[i] = Math.max(leftMax[i - 1], height[i]); + } + + rightMax[n - 1] = height[n - 1]; + for (int i = n - 2; i >= 0; i--) { + rightMax[i] = Math.max(rightMax[i + 1], height[i]); + } + + int res = 0; + for (int i = 0; i < n; i++) { + res += Math.min(leftMax[i], rightMax[i]) - height[i]; + } + return res; + } +} +``` + +- 計算量 + - 時間:O(N) + - 空間:O(1) +- Two Pointerで各Barに対してleftMax, rightMaxを配列で保持することなく算出する + - 両端から算出していくので正確なLeftMax, rightMaxがわからないが結局欲しいのはmin(LeftMax, rightMax)であるため問題ないという発想 + - 低いBarが見つかった時点でそれ以上水の量は増えない + + +```java +public class Solution { + public int trap(int[] height) { + if (height == null || height.length == 0) { + return 0; + } + + int l = 0, r = height.length - 1; + int leftMax = height[l], rightMax = height[r]; + int res = 0; + while (l < r) { + if (leftMax < rightMax) { + l++; + leftMax = Math.max(leftMax, height[l]); + res += leftMax - height[l]; + } else { + r--; + rightMax = Math.max(rightMax, height[r]); + res += rightMax - height[r]; + } + } + return res; + } +} +``` + +## step3 3回とく +- step2のTwo Pointerで回答 + +```java +class Solution { + public int trap(int[] height) { + int left = 0; + int right = height.length - 1; + int leftMax = height[left]; + int rightMax = height[right]; + int ans = 0; + while (left < right) { + if (leftMax < rightMax) { + left++; + leftMax = Math.max(leftMax, height[left]); + ans += leftMax - height[left]; + } else { + right--; + rightMax = Math.max(rightMax, height[right]); + ans += rightMax - height[right]; + } + } + return ans; + } +} + +``` \ No newline at end of file