LeetCode刷題 -- 部分周賽題

哈哈,今天整活上癮了.
複習了一下最近兩場周賽感受能作出來可是實際沒有作出來的題目
感受有幾點不足,但願之後能夠逐漸改過來:
1. 基礎知識不紮實,有時候會在細節上栽跟頭
2. 有時候容易腦子一熱,想到一部分就開始寫,簡單題還能處理,中等或困難就有點難搞了,太局部,不全面
3. 心態仍是須要調整一下,不能提交沒過就內心有點緊張~~node

但願今年內能夠AK一次吧,哈哈,加油,廢話很少,上題目。網絡

199期 第三題
給你二叉樹的根節點 root 和一個整數 distance 。this

若是二叉樹中兩個 葉 節點之間的 最短路徑長度 小於或者等於 distance ,那它們就能夠構成一組 好葉子節點對 。spa

返回樹中 好葉子節點對的數量 。code

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/number-of-good-leaf-nodes-pairs
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。排序

二狗把作題的一些感想和思路也寫在註釋裏了,因此就直接上代碼吧:
`
using CSharpLeetCode.Common;遞歸

namespace CSharpLeetCode.Core
{
/*
這道題是199次周賽的第三題,筆者當時沒有作出來
記錄一下
當時印象深入的錯誤是如何去重。
考慮到須要遞歸的計算左右子樹的好節點對,但當時禁錮於細節,陷入了去重影響當前邏輯,不去重結果必然錯誤的窘境.leetcode

官方題解在這方面處理的方法值得思考。每次計算到能夠做爲子數根的結點P時,判斷結點對是否知足條件的時候,人爲增長了一個條件:
     兩個結點必須分別在P的左右子數中,這樣其實就會避免我上面遇到的問題.
     而且在這種狀況下,好節點對之間的舉例就等於A到Left的距離 + B到Right的距離 + 2.
*/
public class CountPairs_1530
{
    public int CountPairs(TreeNode root, int distance)
    {
        var pair = DFS(root, distance);
        return pair.count;
    }

    private Pair DFS(TreeNode root, int distance)
    {
        int[] depth = new int[distance + 1];
        bool isLeaf = root.left == null && root.right == null;

        //這個結點是葉子結點,所以depth[0] = 1, 且它沒有子樹,所以count = 0
        if (isLeaf)
        {
            depth[0] = 1;
            return new Pair(depth, 0);
        }

        int[] leftDepth = new int[distance + 1];
        int[] rightDepth = new int[distance + 1];
        int leftCount = 0;
        int rightCount = 0;

        //分別計算左右子樹
        if (root.left != null)
        {
            var pair = DFS(root.left, distance);
            leftDepth = pair.depth;
            leftCount = pair.count;
        }

        if (root.right != null)
        {
            var pair = DFS(root.right, distance);
            rightDepth = pair.depth;
            rightCount = pair.count;
        }

        //注意這裏結合depth的定義,這裏計算的時當前結點爲根的子樹的 到當前結點長度爲n的 葉子結點的個數
        //若是這個結點有子樹,它必定不是葉子結點,也就沒有必要計算 i = 0的狀況,此外,還要額外加上1 爲P的子樹到p的距離.
        for (int i = 0; i < distance; i++)
        {
            depth[i + 1] += leftDepth[i];
            depth[i + 1] += rightDepth[i];
        }

        int count = 0;
        //排列組合,注意這裏計算的都是當前結點爲根的子樹中的好結點對數,且必定是一個是在左子樹,一個在右子樹.
        for (int i = 0; i <= distance; i++)
        {
            for (int j = 0; j + i + 2 <= distance; j++)
            {
                count += leftDepth[i] * rightDepth[j];
            }
        }

        //注意這裏的count + leftCount + rightCount
        //其中count是P的好結點對個數,leftCount是P的左子樹的對個數,rightCount相似.
        return new Pair(depth, count + leftCount + rightCount);
    }

    #region 沒完成的Code
    //下面註釋掉的是參賽時的代碼:
    /*
        Dictionary<List<TreeNode>, int> dic = new Dictionary<List<TreeNode>, int>();

        public int CountPairs(TreeNode root, int distance)
        {
            if (distance <= 1)
                return 0;

            return GetResult(root, distance);
        }

        public int GetResult(TreeNode root, int height)
        {
            if (root == null)
                return 0;

            int result = 0;

            var left = new List<TreeNode>();
            var right = new List<TreeNode>();

            for (int i = 1; i <= height - 1; i++)
            {
                var tempLeft = GetLeaf(root.left, i).Except(left).ToList();
                var tempRight = GetLeaf(root.right, height - i).Except(right).ToList();

                if (tempLeft.Count != 0 && tempRight.Count != 0)
                {
                    left.AddRange(tempLeft);
                    right.AddRange(tempRight);

                    result += tempLeft.Count * tempRight.Count;
                }
            }

            if (root.left != null)
                result += GetResult(root.left, height);
            if (root.right != null)
                result += GetResult(root.right, height);

            return result;
        }

        public List<TreeNode> GetLeaf(TreeNode root, int height)
        {
            if (height == 0 || root == null)
                return new List<TreeNode>();

            var result = new List<TreeNode>();

            if (root.left == null && root.right == null)
            {
                result.Add(root);
                return result;
            }

            if (root.left != null)
            {
                result.AddRange(GetLeaf(root.left, height - 1));
            }

            if (root.right != null)
            {
                result.AddRange(GetLeaf(root.right, height - 1));
            }


            return result;
        }
    */
    #endregion
}

/// <summary>
/// 注意這個類 用於描述某個子數的根結點的相關信息
/// depth[i] 表明葉子結點到當前子樹結點P的距離爲i的葉子節點個數。例如 depth[2] = 1 表明到P的距離爲2的葉子結點的個數爲1
/// count 表明以當前結點P爲根的樹中,好結點的對數
/// </summary>
public class Pair {
    public int[] depth;
    public int count;

    public Pair(int[] depth, int count)
    {
        this.depth = depth;
        this.count = count;
    }
}

}
`rem

200期 第三題
5477. 排布二進制網格的最少交換次數
給你一個 n x n 的二進制網格 grid,每一次操做中,你能夠選擇網格的 相鄰兩行 進行交換。get

一個符合要求的網格須要知足主對角線以上的格子所有都是 0 。

請你返回使網格知足要求的最少操做次數,若是沒法使網格符合要求,請你返回 -1 。

主對角線指的是從 (1, 1) 到 (n, n) 的這些格子。

提示:

n == grid.length
n == grid[i].length
1 <= n <= 200
grid[i][j] 要麼是 0 要麼是 1 。

連接: https://leetcode-cn.com/problems/minimum-swaps-to-arrange-a-binary-grid/

同樣,上代碼:
`
namespace CSharpLeetCode.Core
{
/*
這是第200次周賽的第三題
*/
public class MinSwaps_5477
{
public int MinSwaps(int[][] grid)
{
// 規模
int n = grid.Length;
var array = new int[n]; //記錄每行 從後向前連續的0的個數

for (int i = 0; i < n; i++)
        {
            int count = 0;
            for (int j = n - 1; j >= 0; j--)
            {
                if (grid[i][j] == 0)
                {
                    count++;
                }
                else
                {
                    break;
                }
            }
            array[i] = count;
        }

        //記錄一下交換順序
        int result = 0;

        for (int i = 0; i < n - 1; i++)
        {
            //不須要交換的狀況,這裏很容易發現,每行須要的從後向前連續的0的個數是依次遞減的.因此即便超過了 n - i - 1 也不要緊的
            if (array[i] >= n - i - 1)
            {
                continue;
            }
            else //須要交換的狀況
            {
                int j = i;

                for (j = i; j < n; j++)
                {
                    //找到了!
                    if (array[j] >= n - i - 1)
                        break;
                }

                //找不到知足條件的結果了,直接判斷不能完成,返回-1
                if (j == n)
                    return -1;

                for (; j > i; j--)
                {
                    //經典冒泡向上浮動,哈哈
                    var temp = array[j - 1];
                    array[j - 1] = array[j];
                    array[j] = temp;

                    //別忘了計算操做的次數
                    result++;
                }
            }
        }

        return result;
    }
}

#region 比賽版本
/*
 先貼一個沒有完成的版本吧。感受仍是沒有適應比賽的狀態,和某位大佬的思路開頭幾乎一毛同樣。
 惋惜後來爲啥想不開要去套個冒泡排序,哈哈哈

public class Solution {
    public int MinSwaps(int[][] grid)
    {
        int n = grid.Length;
        var dict = new Dictionary<int, List<List<int>>>();
        var dict2 = new int[n];

        for (int i = 0; i < n; i++)
        {
            int count = 0;
            for (int j = n - 1; j >= 0; j--)
            {
                if (grid[i][j] == 0)
                {
                    count++;
                }
                else
                {
                    dict2[i] = count;
                    if (dict.ContainsKey(count))
                    {
                        dict[count].Add(grid[i].ToList());
                    }
                    else
                    {
                        var temp = new List<List<int>>();
                        temp.Add(grid[i].ToList());
                        dict.Add(count, temp);
                    }
                }
            }
        }

        int remind = 0;

        for (int i = n - 1; i >= 1; i--)
        {
            if (!dict.ContainsKey(i) && remind <= 0)
            {
                return -1;
            }
            else if (dict.ContainsKey(i))
            {
                remind += dict[i].Count() - 1;
            }
            else if (!dict.ContainsKey(i) && remind > 0)
            {
                remind--;
            }
        }

        int result = 0;

        for (int i = 0; i < n - 1; i ++)
        {
            for (int j = i + 1; j < n; j++)
            {
                if (dict2[i] < dict2[j])
                {
                    var zzz = dict2[i];
                    dict2[i] = dict2[j];
                    dict2[j] = zzz;
                    result++;
                }
            }
        }

        return result;
    }
}

 */
#endregion

} `

相關文章
相關標籤/搜索