題目:你總共有 n 枚硬幣,你須要將它們擺成一個階梯形狀,第 k 行就必須正好有 k 枚硬幣。java
給定一個數字 n,找出可造成完整階梯行的總行數。n 是一個非負整數,而且在32位有符號整型的範圍內。node
示例 1:算法
n = 5數組
硬幣可排列成如下幾行: ¤ ¤ ¤ ¤ ¤markdown
由於第三行不完整,因此返回2. 示例 2:函數
n = 8oop
硬幣可排列成如下幾行: ¤ ¤ ¤ ¤ ¤ ¤ ¤ ¤spa
思路一:rest
等差數列通項公式、求和公式code
已知等差數列的和Sn,首項a1=1,d=1,求n
public int arrangeCoins(int n) {
return (int) (-1 + Math.sqrt(1 + 8 * (long) n)) / 2;
}
複製代碼
題目:實現 pow(x, n) ,即計算 x 的 n 次冪函數(即,xn)。
示例 1:
輸入:x = 2.00000, n = 10 輸出:1024.00000 示例 2:
輸入:x = 2.10000, n = 3 輸出:9.26100 示例 3:
輸入:x = 2.00000, n = -2 輸出:0.25000 解釋:2-2 = 1/22 = 1/4 = 0.25
public static double myPow(double x, int n) {
if(n==0) return 1;
if(n==1) return x;
if(n==-1) return 1/x;
double half=myPow(x,n/2);
double rest=myPow(x,n%2);
return half*half*rest;
}
複製代碼
給定一個二叉樹,找出其最大深度。
二叉樹的深度爲根節點到最遠葉子節點的最長路徑上的節點數。
說明: 葉子節點是指沒有子節點的節點。
示例: 給定二叉樹 [3,9,20,null,null,15,7],
3
複製代碼
/
9 20 /
15 7 返回它的最大深度 3 。
public static int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return (left > right?left:right)+1;
}
複製代碼
題目: 請實現一個函數,用來判斷一顆二叉樹是否是對稱的。注意,若是一個二叉樹同此二叉樹的鏡像是一樣的,定義其爲對稱的。
思路:首先根節點以及其左右子樹,左子樹的左子樹和右子樹的右子樹相同,左子樹的右子樹和右子樹的左子樹相同便可,採用遞歸,另外非遞歸也可,採用棧或隊列存取各級子樹根節點。
方法一:
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null) return true;
return isSymmetrical(pRoot.left,pRoot.right);
}
private boolean isSymmetrical(TreeNode left, TreeNode right) {
if(left==null&&right==null) return true;
if(left==null||right==null) return false;
if(left.data==right.data)
return isSymmetrical(left.left, right.right)&&isSymmetrical(left.right, right.left);
return false;
}
複製代碼
題目:給定一個二叉搜索樹的根節點 root,返回樹中任意兩節點的差的最小值。
示例:
輸入: root = [4,2,6,1,3,null,null] 輸出: 1 解釋: 注意,root是樹節點對象(TreeNode object),而不是數組。
給定的樹 [4,2,6,1,3,null,null] 可表示爲下圖:
4
/ \
2 6
/ \
1 3
複製代碼
最小的差值是 1, 它是節點1和節點2的差值, 也是節點3和節點2的差值。
定義: 二叉查找樹(Binary Search Tree),(又:二叉搜索樹,二叉排序樹)它或者是一棵空樹,或者是具備下列性質的二叉樹: 若它的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹。
class Solution {
Integer prev = null, ans = Integer.MAX_VALUE;
public int minDiffInBST(TreeNode root) {
test(root);
return ans;
}
public void test(TreeNode treeNode) {
if (treeNode == null) {
return;
}
test(treeNode.left);
if (prev != null) {
ans = Math.min(ans, treeNode.val - prev);
}
prev = treeNode.val;
test(treeNode.right);
}
}
複製代碼
給定一個二叉樹,返回全部從根節點到葉子節點的路徑。
算法分析:
null
;故遞歸至上一個節點2搜索左子節點5,繼續搜索判斷5節點無左右子節點,故遞歸返回至1節點;public void sreachPaths(TreeNode root, List<String> paths, String path) {
if(root != null) {
path += Integer.toString(root.data);
if(root.left == null && root.right == null) {
paths.add(path);
}else {
path += "->";
sreachPaths(root.left, paths, path);
sreachPaths(root.right, paths, path);
}
}
}
複製代碼
給定二叉搜索樹的根結點 root,返回 L 和 R(含)之間的全部結點的值的和。
二叉搜索樹保證具備惟一的值。
示例 1:
輸入:root = [10,5,15,3,7,null,18], L = 7, R = 15 輸出:32
示例 2: 輸入:root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10 輸出:23
提示:
樹中的結點數量最多爲 10000 個。 最終的答案保證小於 2^31。
條件給出了根結點,從上往下遍歷.可使用遞歸,來求解.重複的條件就是結點的左右子樹,結束條件就是左右子樹的值是否在L,R的範圍內,返回結點在範圍內的值的和
public int rangeSumBST(TreeNode root, int L, int R) {
if (root == null) {
return 0;
}
if (root.data < L) {
return rangeSumBST(root.right, L, R);
}
if (root.data > R) {
return rangeSumBST(root.left, L, R);
}
return root.data + rangeSumBST(root.left, L, R) + rangeSumBST(root.right, L, R);
}
複製代碼
題目描述 給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。
百度百科中最近公共祖先的定義爲:「對於有根樹 T 的兩個結點 p、q,最近公共祖先表示爲一個結點 x,知足 x 是 p、q 的祖先且 x 的深度儘量大(一個節點也能夠是它本身的祖先)。」
例如,給定以下二叉樹: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1: 輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 輸出: 3 解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。
示例 2: 輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 輸出: 5 解釋: 節點 5 和節點 4 的最近公共祖先是節點 5。由於根據定義最近公共祖先節點能夠爲節點自己。
說明: 全部節點的值都是惟一的。 p、q 爲不一樣節點且均存在於給定的二叉樹中。
思路:
一、在左、右子樹中分別查找是否包含p或q,若是(兩種狀況:左子樹包含p,右子樹包含q/左子樹包含q,右子樹包含p),
那麼此時的根節點就是最近公共祖先
二、若是左子樹包含p和q,那麼到root->left中查找,最近公共祖先在左子樹裏面
三、若是右子樹包含p和q,那麼到root->right中查找,最近公共祖先在右子樹裏面
四、注意:不可能left和right的返回值同時都是nullptr
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == root || q == root) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left!=null && right!=null) {
return root;
}
return left == null ? right : left;
}
複製代碼
思路二(非遞歸):
public TreeNode lowestCommonAncestorII(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == root || q == root) {
return root;
}
List<TreeNode> pPath = findPath(root, p);
List<TreeNode> qPath = findPath(root, q);
TreeNode common = null;
for (int i=0, j=0; i<pPath.size() && j<qPath.size(); i++,j++) {
if (pPath.get(i) == qPath.get(j)) {
common = pPath.get(i);
}
}
return common;
}
private List<TreeNode> findPath(TreeNode root, TreeNode node) {
List<TreeNode> path = new ArrayList<>();
dfs(root, node, new ArrayList<>(), path);
return path;
}
private void dfs(TreeNode root, TreeNode node, List<TreeNode> tmp, List<TreeNode> path) {
if (root == null) {
return;
}
tmp.add(root);
if (root == node) {
path.addAll(new ArrayList<>(tmp));
}
dfs(root.left, node, tmp, path);
dfs(root.right, node, tmp, path);
tmp.remove(tmp.size()-1);
}
複製代碼
一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(前後次序不一樣算不一樣的結果)。
考慮使用 斐波那契數列(遞歸)
方法一:使用遞歸的思想
public class Solution {
public int JumpFloor(int target) {
if(target<1)
return 0;
if(target==1)
return 1;
if(target==2)
return 2;
return JumpFloor(target-1)+ JumpFloor(target-2);
}
}
複製代碼
方法二:使用迭代的思想
public class Solution {
public int JumpFloor(int target) {
int f1=1,f2=2;
while(--target>0){
f2=f2+f1;
f1=f2-f1;
}
return f1;
}
}
複製代碼