力扣第101、104、119、121、125題
101題、對稱二叉樹
題目:
方法一:
解題思路:
在這裏使用的是一種遞歸的方法來遍歷比較樹是否一樣,開始時我們先判斷一下根節點的狀態,然後我們再遞歸的時候,比較的東西就不一樣了,當左子樹遍歷到左孩子的時候,對應的,就應該遍歷到右子樹的右孩子,比較他們的值是否相同,就結束了。
代碼:
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繼續遍歷。
代碼:
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;
}
}