1. 程式人生 > >第七章 兩個面試案例

第七章 兩個面試案例

== 一個 nbsp 復雜 else font null 整數 lse

7.1 案例一 面試題49:把字符串轉換成整數
  • 題目:將一個字符串轉換成一個整數,要求不能使用字符串轉換整數的庫函數。 數值為0或者字符串不是一個合法 的數值則返回0
  • 思路:若為負數,則輸出負數,字符0對應48,9對應57,不在範圍內則返回false。
  • 代碼實現
    • public class TestMain {
    • public static void main(String[] args) {
    • TestMain t = new TestMain();
    • System.out.println(t.StrToInt("12"));
    • }
    • public int StrToInt(String str) {
    • if (str == null || str.length() == 0)
    • return 0;
    • int mark = 0;
    • int start = 0;
    • int number = 0;
    • char[] chars = str.toCharArray();
    • if (chars[0] == ‘-‘) {
    • mark = 1;
    • start = 1;
    • } else if (chars[0] == ‘+‘) {
    • start = 1;
    • }
    • for (int i = start; i < chars.length; i++) {
    • if (chars[i] < 48 || chars[i] > 57) {
    • return 0;
    • }
    • number = number * 10 + chars[i] - 48;
    • }
    • return mark == 0 ? number : -number;
    • }
    • }
  • 測試用例:
    • 功能測試(輸入的字符串表示正數、負數和0)。
    • 邊界值測試(最大的正整數、最小的負整數)。
    • 特殊輸入測試(輸入字符串為NULL指針、輸入字符串為空字符串、輸入的字符串中有非數字字符等)。
面試題50:樹中兩個節點的最低公共祖先
  • 題目:求樹中兩個節點的最低公共祖先
  • (1)樹是二叉搜索樹
  • 思路:從樹的根節點開始遍歷,如果根節點的值大於其中一個節點,小於另外一個節點,則根節點就是最低公 共祖先。否則如果根節點的值小於兩個節點的值,則遞歸求根節點的右子樹,如果大於兩個節點的值則遞歸求 根的左子樹。如果根節點正好是其中的一個節點,那麽說明這兩個節點在一條路徑上,所以最低公共祖先則是 根節點的父節點,時間復雜度是O(logn),空間復雜度是O(1)
  • 代碼實現
    • class TreeNode {
    • public int value;
    • public TreeNode left;
    • public TreeNode right;
    • public TreeNode(int value) {
    • this.value = value;
    • }
    • public TreeNode() {
    • }
    • }
    • public class TestTree {
    • public static int n;
    • ArrayList<ArrayList<Integer>> resultList = new ArrayList<ArrayList<Integer>>();
    • ArrayList<Integer> list = new ArrayList<Integer>();
    • public static void main(String[] args) {
    • int[] array = new int[] { 7,1,0,3,2,0,0,5,0,0,8,0,9,0,0};
    • TestTree t = new TestTree();
    • TreeNode root = t.CreateTreeBinary(new TreeNode(), array);
    • System.out.println(t.getLowestCommonAncestor(root, root, new TreeNode(2), new TreeNode(5)).value);
    • }
    • public TreeNode CreateTreeBinary(TreeNode treeNode, int[] array) {
    • if (array[n] == 0) {
    • n++;
    • return null;
    • } else {
    • treeNode.value = array[n++];
    • treeNode.left = CreateTreeBinary(new TreeNode(0), array);
    • treeNode.right = CreateTreeBinary(new TreeNode(0), array);
    • return treeNode;
    • }
    • }
    • public static TreeNode getLowestCommonAncestor(TreeNode rootParent, TreeNode root,
    • TreeNode node1, TreeNode node2) {
    • if (root == null || node1 == null || node2 == null) {
    • return null;
    • }
    • if ((root.value - node1.value) * (root.value - node2.value) < 0) {
    • return root;
    • } else if ((root.value - node1.value) * (root.value - node2.value) > 0) {
    • TreeNode newRoot = ((root.value > node1.value) && (root.value > node2.value)) ? root.left
    • : root.right;
    • return getLowestCommonAncestor(root, newRoot, node1, node2);
    • } else {
    • return rootParent;
    • }
    • }
    • }
  • (2)若樹是普通樹,但有指向父節點的指針
  • 思路:兩個節點如果在兩條路徑上,類似於求兩個鏈表的第一個公共節點。由於每個節點的深度最多為logn,所以時間復雜度為O(logn),空間復雜度O(1)
  • 思路二:循環兩次 第一次長度差 第二次求值
  • 代碼實現
    • public BinaryTreeNode getLowestCommonAncestor1(BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2) {
    • if (root == null || node1 == null || node2 == null) {
    • return null;
    • }
    • int depth1 = findTheDepthOfTheNode(root, node1, node2);
    • if (depth1 == -1) {
    • return node2.parentNode;
    • }
    • int depth2 = findTheDepthOfTheNode(root, node2, node1);
    • if (depth2 == -1) {
    • return node1.parentNode;
    • }
    • // p指向較深的節點q指向較淺的節點
    • BinaryTreeNode p = depth1 > depth2 ? node1 : node2;
    • BinaryTreeNode q = depth1 > depth2 ? node2 : node1;
    • int depth = Math.abs(depth1 - depth2);
    • while (depth > 0) {
    • p = p.parentNode;
    • depth--;
    • }
    • while (p != q) {
    • p = p.parentNode;
    • q = q.parentNode;
    • }
    • return p;
    • }
    • // 求node1的深度,如果node1和node2在一條路徑上,則返回-1,否則返回node1的深度
    • public int findTheDepthOfTheNode(BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2) {
    • int depth = 0;
    • while (node1.parentNode != null) {
    • node1 = node1.parentNode;
    • depth++;
    • if (node1 == node2) {
    • return -1;
    • }
    • }
    • return depth;
    • }
  • (3)若樹是普通樹,並沒有指向父節點的指針
  • 思路:用棧來實現類似於指向父節點指針的功能,獲取node節點的路徑時間復雜度為O(n),所以總的時間復雜度是O(n),空間復雜度是O(logn)
  • 代碼實現
    • public BinaryTreeNode getLowestCommonAncestor2(BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2) {
    • if (root == null || node1 == null || node2 == null) {
    • return null;
    • }
    • Stack<BinaryTreeNode> path1 = new Stack<BinaryTreeNode>();
    • boolean flag1 = getThePathOfTheNode(root, node1, path1);
    • if (!flag1) {// 樹上沒有node1節點
    • return null;
    • }
    • Stack<BinaryTreeNode> path2 = new Stack<BinaryTreeNode>();
    • boolean flag2 = getThePathOfTheNode(root, node2, path2);
    • if (!flag2) {// 樹上沒有node2節點
    • return null;
    • }
    • if (path1.size() > path2.size()) { // 讓兩個路徑等長
    • while (path1.size() != path2.size()) {
    • path1.pop();
    • }
    • } else {
    • while (path1.size() != path2.size()) {
    • path2.pop();
    • }
    • }
    • if (path1 == path2) {// 當兩個節點在一條路徑上時
    • path1.pop();
    • return path1.pop();
    • } else {
    • BinaryTreeNode p = path1.pop();
    • BinaryTreeNode q = path2.pop();
    • while (q != p) {
    • p = path1.pop();
    • q = path2.pop();
    • }
    • return p;
    • }
    • }
    • // 獲得根節點到node節點的路徑
    • public boolean getThePathOfTheNode(BinaryTreeNode root, BinaryTreeNode node, Stack<BinaryTreeNode> path) {
    • path.push(root);
    • if (root == node) {
    • return true;
    • }
    • boolean found = false;
    • if (root.leftNode != null) {
    • found = getThePathOfTheNode(root.leftNode, node, path);
    • }
    • if (!found && root.rightNode != null) {
    • found = getThePathOfTheNode(root.rightNode, node, path);
    • }
    • if (!found) {
    • path.pop();
    • }
    • return found;
    • }

第七章 兩個面試案例