力扣第101、104、119、121、125題

力扣第101、104、119、121、125題

101題、對稱二叉樹

題目:

1

方法一:

解題思路:

在這裏使用的是一種遞歸的方法來遍歷比較樹是否一樣,開始時我們先判斷一下根節點的狀態,然後我們再遞歸的時候,比較的東西就不一樣了,當左子樹遍歷到左孩子的時候,對應的,就應該遍歷到右子樹的右孩子,比較他們的值是否相同,就結束了。

代碼:

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return check(root, root);
    }

    public boolean check(TreeNode p, TreeNode q) {
        if (p == null && q == null) {
            return true;
        }
        if (p == null || q == null) {
            return false;
        }
        return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
    }
}

方法二:

解題思路:

這種方法使用了隊列的思想,不太容易想到,我們可以將一棵樹,從中間一分兩半,按照對應的位置,將對應的值存放到隊列中,然後進行比較相鄰的兩個數字,如果是對稱的樹,那麼相鄰的兩個數字就是應該相同的,然後直到遍歷結束!初始化時我們把根節點入隊兩次。每次提取兩個結點並比較它們的值(隊列中每兩個連續的結點應該是相等的,而且它們的子樹互爲鏡像),然後將兩個結點的左右子結點按相反的順序插入隊列中。當隊列爲空時,或者我們檢測到樹不對稱(即從隊列中取出兩個不相等的連續結點)時,該算法結束。

代碼:

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return check(root, root);
    }

    public boolean check(TreeNode u, TreeNode v) {
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        q.offer(u);
        q.offer(v);
        while (!q.isEmpty()) {
            u = q.poll();
            v = q.poll();
            if (u == null && v == null) {
                continue;
            }
            if ((u == null || v == null) || (u.val != v.val)) {
                return false;
            }

            q.offer(u.left);
            q.offer(v.right);

            q.offer(u.right);
            q.offer(v.left);
        }
        return true;
    }
}

104、二叉樹的最大深度

題目:

給定一個二叉樹,找出其最大深度。

二叉樹的深度爲根節點到最遠葉子節點的最長路徑上的節點數。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定二叉樹 [3,9,20,null,null,15,7],

  3
 / \
9  20
  /  \
 15   7

返回它的最大深度 3 。

解題思路:

關於這道題,使用了DFS(深度優先搜索)的方法,說白了也就是一種變相的遞歸,判斷的當前是否有節點有的話+1繼續遍歷。

image.png

代碼:

class Solution {
    public int maxDepth(TreeNode root) {
        if(root==null){
            return 0;
        }else{
            int left_height=maxDepth(root.left);
            int right_height=maxDepth(root.right);
            return java.lang.Math.max(left_height,right_height)+1;
        }
    }
}

119、楊輝三角(獲取當前行的數據)

題目:

給定一個非負索引 k,其中 k ≤ 33,返回楊輝三角的第 k 行。

示例:

輸入: 3
輸出: [1,3,3,1]

解題思路:

關於這道題,我看到有的人有的方法不便於理解,我這裏使用一個較爲好理解的方法,就是我們可以看到假如我們需要獲取到第三行的數據,就是1,2,1 我們可以觀察到中間位置的2,其實就是上一層的對應位置的數,加上上一層的對應位置的前一個位置的數字之和,同理,第四行數據1,3,3,1,也是這樣,這樣我們就可以在需要獲取的那一行進行倒着操作,先給末尾的那個進行1的賦值,然後一次進行相加處理。

代碼:

class Solution{
    public:
        vector<int> getRow(int rowIndex){
            vector<int> kRows(rowIndex+1);
            for(int i=0;i<=rowIndex;i++){
                kRows[i]=1;
                for(int j=i;j>1;j--){
                    kRows[j-1]=kRows[j-2]+kRows[j-1];
                }
            }
            return kRows;
        }
};

121、買賣股票的最佳時機

題目:

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

如果你最多隻允許完成一筆交易(即買入和賣出一支股票一次),設計一個算法來計算你所能獲取的最大利潤。

注意:你不能在買入股票前賣出股票。

示例 1:

輸入: [7,1,5,3,6,4]
輸出: 5
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。
注意利潤不能是 7-1 = 6, 因爲賣出價格需要大於買入價格;同時,你不能在買入前賣出股票。

示例 2:

輸入: [7,6,4,3,1]
輸出: 0
解釋: 在這種情況下, 沒有交易完成, 所以最大利潤爲 0。

解題思路:

我們需要找出給定數組中兩個數字之間的最大差值(即,最大利潤)。此外,第二個數字(賣出價格)必須大於第一個數字(買入價格)。

形式上,對於每組 i 和 j(其中 j > i)我們需要找出max(prices[j]−prices[i])。

代碼:

public class Solution {
    public int maxProfit(int prices[]) {
        int maxprofit = 0;
        for (int i = 0; i < prices.length - 1; i++) {
            for (int j = i + 1; j < prices.length; j++) {
                int profit = prices[j] - prices[i];
                if (profit > maxprofit)
                    maxprofit = profit;
            }
        }
        return maxprofit;
    }
}

125、驗證迴文字符串

題目:

給定一個字符串,驗證它是否是迴文串,只考慮字母和數字字符,可以忽略字母的大小寫。

說明:本題中,我們將空字符串定義爲有效的迴文串。

示例 1:

輸入: “A man, a plan, a canal: Panama”
輸出: true

示例 2:

輸入: “race a car”
輸出: false

解題思路一:

最簡單的方法是對字符串 s 進行一次遍歷,並將其中的字母和數字字符進行保留,放在另一個字符串中。這樣我們只需要判斷這個字符串是否是一個普通的迴文串即可。

判斷的方法有兩種。第一種是使用語言中的字符串翻轉 API 得到該字符串的逆序字符串sgood_rev,只要這兩個字符串相同,那麼sgood 就是迴文串。

代碼一:

class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer sgood = new StringBuffer();
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char ch = s.charAt(i);
            if (Character.isLetterOrDigit(ch)) {
                sgood.append(Character.toLowerCase(ch));
            }
        }
        StringBuffer sgood_rev = new StringBuffer(sgood).reverse();
        return sgood.toString().equals(sgood_rev.toString());
    }
}

解題思路二:

第二種是使用雙指針。初始時,左右指針分別指向sgood 的兩側,隨後我們不斷地將這兩個指針相向移動,

每次移動一步,並判斷這兩個指針指向的字符是否相同。當這兩個指針相遇時,就說明sgood 時迴文串。

代碼二:

class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer sgood = new StringBuffer();
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char ch = s.charAt(i);
            if (Character.isLetterOrDigit(ch)) {
                sgood.append(Character.toLowerCase(ch));
            }
        }
        int n = sgood.length();
        int left = 0, right = n - 1;
        while (left < right) {
            if (Character.toLowerCase(sgood.charAt(left)) != Character.toLowerCase(sgood.charAt(right))) {
                return false;
            }
            ++left;
            --right;
        }
        return true;
    }
}

解題思路三:

我們直接在原字符串 ss 上使用雙指針。在移動任意一個指針時,需要不斷地向另一指針的方向移動,直到遇到一個字母或數字字符,

或者兩指針重合爲止。也就是說,我們每次將指針移到下一個字母字符或數字字符,再判斷這兩個指針指向的字符是否相同。

代碼三:

class Solution {
    public boolean isPalindrome(String s) {
        int n=s.length();
        int left=0,right=n-1;
        while(left<right){
            while(left<right&&!Character.isLetterOrDigit(s.charAt(left))){
                ++left;
            }
            while(left<right&&!Character.isLetterOrDigit(s.charAt(right))){
                --right;
            }
            if(left<right){
                if(Character.toLowerCase(s.charAt(left))!=Character.toLowerCase(s.charAt(right))){
                    return false;
                }
                ++left;
                --right;
            }
        }
        return true;
    }
}

添加公衆號:奈斯雜文,菜鳥小謝帶你學習java和算法

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章