劍指offer題目答案集合
阿新 • • 發佈:2018-12-17
package org.nix.learn.offer; import org.junit.jupiter.api.Test; import sun.rmi.transport.tcp.TCPChannel; import java.util.*; import java.util.concurrent.*; /** * 在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序, * 每一列都按照從上到下遞增的順序排序。請完成一個函式, * 輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。 * * @author zhangpei * @version 1.0 * @date 2018/10/8 */ public class Solution { public static boolean Find(int target, int[][] array) { int len = array.length; if (array[0].length == 0 || array[0][0] > target) { return false; } if (array[0][len - 1] < target) { if (serch(target, array, len, len)) { return true; } } for (int i = 1; i < len; i++) { // 找到在第一排找到一個大於他的值,那麼存在 // 等於他的值就在i-1列中的 if (array[0][i] > target) { if (serch(target, array, len, i)) { return true; } } } return false; } private static boolean serch(int target, int[][] array, int len, int i) { for (int[] anArray : array) { if (anArray[i - 1] == target) { return true; } if (anArray[len - 1] > target) { for (int k = len - 1; k > 0; k--) { if (anArray[k] == target) { return true; } } } } return false; } // ------------------------------------------------------- /** * 請實現一個函式,將一個字串中的每個空格替換成“%20”。例如,當字串為We Are Happy.則經過替換之後的字串為We%20Are%20Happy。 * * @param str * @return */ public String replaceSpace(StringBuffer str) { return str.toString().replace(" ", "%20"); } // ------------------------------------------------------- /** * 輸入一個連結串列,按連結串列值從尾到頭的順序返回一個ArrayList */ private class ListNode { int val; ListNode next; public ListNode(int val) { this.val = val; } public ListNode() { } } public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { ArrayList<Integer> list = new ArrayList<>(); while (listNode != null) { list.add(listNode.val); listNode = listNode.next; } int len = list.size(); ArrayList<Integer> returnV = new ArrayList<>(len); for (int i = len - 1; i >= 0; i--) { returnV.add(list.get(i)); } return returnV; } public ArrayList<Integer> printListFromTailToHeadTwo(ListNode listNode) { Stack<Integer> stack = new Stack<>(); while (listNode != null) { stack.push(listNode.val); listNode = listNode.next; } int len = stack.size(); ArrayList<Integer> va = new ArrayList<>(len); while (true) { try { Integer value = stack.peek(); if (value == null) { return va; } va.add(stack.pop()); } catch (Exception e) { return va; } } } // ------------------------------------------------------- /** * 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。 * 例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 */ class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(int val) { this.val = val; } } public TreeNode reConstructBinaryTree(int[] pre, int[] in) { if (pre.length == 0 || in.length == 0) { return null; } TreeNode node = new TreeNode(pre[0]); for (int i = 0; i < in.length; i++) { if (pre[0] == in[i]) { node.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i)); node.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length)); } } return node; } @Test public void reConstructBinaryTreeTest() { int[] pre = {1, 2, 4, 7, 3, 5, 6, 8}; int[] in = {4, 7, 2, 1, 5, 3, 8, 6}; reConstructBinaryTree(pre, in); System.out.println(); } // ------------------------------------------------------- /** * 把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。 輸入一個非減排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。 * 例如陣列{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該陣列的最小值為1。 NOTE:給出的所有元素都大於0,若陣列大小為0,請返回0。 * * @param array * @return */ public int minNumberInRotateArray(int[] array) { int len = array.length; if (len == 0) { return 0; } Integer integer = null; for (int value : array) { if (integer == null) { integer = value; } else { if (integer > value) { return value; } else { integer = value; } } } return 0; } @Test public void minNumberInRotateArray() { System.out.println(minNumberInRotateArray(new int[]{3, 4, 5, 1, 2})); } // ------------------------------------------------------- /** * 用兩個棧來實現一個佇列,完成佇列的Push和Pop操作。 佇列中的元素為int型別。 */ Stack<Integer> stack1 = new Stack<Integer>(); Stack<Integer> stack2 = new Stack<Integer>(); public void push(int node) { stack1.push(node); } public int pop() { List<Integer> integers = new ArrayList<>(stack2.size()); while (!stack2.empty()) { integers.add(stack2.pop()); } while (!stack1.empty()) { stack2.push(stack1.pop()); } for (int i = integers.size() - 1; i >= 0; i--) { stack2.push(integers.get(i)); } return stack2.pop(); } @Test public void stackTest() { for (int i = 0; i < 20; i++) { push(i); } for (int i = 0; i < 10; i++) { System.out.print(pop() + " "); } for (int i = 20; i < 40; i++) { push(i); } for (int i = 0; i < 30; i++) { System.out.print(pop() + " "); } } /** * 大家都知道斐波那契數列,現在要求輸入一個整數n, * 請你輸出斐波那契數列的第n項(從0開始,第0項為0)。 * n<=39 * * @param n * @return */ public int fibonacci(int n) { if (n <= 0) { return 0; } if (0 < n && n <= 2) { return 1; } int v1 = 0; int v2 = 1; for (int i = 2; i < n; i++) { int temp = v1 + v2; v1 = v2; v2 = temp; } return v2 + v1; } @Test public void fidbonacciTest() { System.out.println(fibonacci(6)); } /** * 一隻青蛙一次可以跳上1級臺階,也可以跳上2級。 * 求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果) * * @param n * @return */ public int jumpFloor(int n) { if (n <= 0) { return 0; } if (n <= 1) { return 1; } if (n == 2) { return 2; } int v1 = 1; int v2 = 2; for (int i = 3; i < n; i++) { int temp = v1 + v2; v1 = v2; v2 = temp; } return v2 + v1; } /** * 一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。 * <p> * 連結:https://www.nowcoder.com/questionTerminal/22243d016f6b47f2a6928b4313c85387 * 來源:牛客網 * <p> * 因為n級臺階,第一步有n種跳法:跳1級、跳2級、到跳n級 * 跳1級,剩下n-1級,則剩下跳法是f(n-1) * 跳2級,剩下n-2級,則剩下跳法是f(n-2) * 所以f(n)=f(n-1)+f(n-2)+...+f(1) * 因為f(n-1)=f(n-2)+f(n-3)+...+f(1) * 所以f(n)=2*f(n-1) * * @param target * @return */ public int jumpFloorII(int target) { return (int) Math.pow(2, target - 1); } /** * 輸入一個整數,輸出該數二進位制表示中1的個數。其中負數用補碼錶示。 * * @param n * @return */ public int numberOf1(int n) { long start = System.currentTimeMillis(); int temp = n; int mi = 0; int bijiao; while (temp >= (bijiao = (int) Math.pow(2, mi))) { if (temp == bijiao) { return 1; } mi++; } mi--; int number = 0; while (temp != 0) { // 如果相減大於0說明符合要求 int pow = (int) Math.pow(2, mi); if (temp - pow < 0) { mi--; continue; } temp = temp - pow; mi--; number++; } if (n < 0) { return ++number; } start = System.currentTimeMillis() - start; System.out.println(start); return number; } @Test public void numberOf1Test() { System.out.println(numberOf1(1000000000)); } /** * 給定一個double型別的浮點數base和int型別的整數exponent。求base的exponent次方。 * * @param base * @param exponent * @return */ public double Power(double base, int exponent) { if (exponent == 0) { return 1; } if (base == 0) { return 0; } double temp = base; if (exponent > 0) { while (exponent > 1) { temp *= base; exponent--; } } else { while (exponent < 1) { temp /= base; exponent++; } } return temp; } /** * 輸入一個連結串列,輸出該連結串列中倒數第k個結點。 * * @param head * @param k * @return */ public ListNode FindKthToTail(ListNode head, int k) { int size = 0; ListNode temp = head; while (temp != null) { temp = temp.next; size++; } System.out.println(size); size = size - k; System.out.println(size); if (size < 0) { return null; } while (size > 0) { head = head.next; size--; } return head; } @Test public void FindKthToTailTest() { ListNode node = new ListNode(1); node.next = new ListNode(1); node.next.next = new ListNode(3); node.next.next.next = new ListNode(4); node.next.next.next.next = new ListNode(5); node = deleteDuplication(node); while (node != null) { System.out.print(node.val + " "); node = node.next; } } /** * 輸入一個連結串列,反轉連結串列後,輸出新連結串列的表頭。 * * @param head * @return */ public ListNode ReverseList(ListNode head) { if (head == null) { return null; } else if (head.next == null) { return head; } ListNode node = ReverseList(head.next); head.next.next = head; head.next = null; return node; } public ListNode myReverseList(ListNode head) { ListNode pre = null; ListNode next = null; while (head != null) { next = head.next; head.next = pre; pre = head; head = next; } return pre; } /** * 輸入一棵二叉樹,求該樹的深度。 * 從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑, * 最長路徑的長度為樹的深度。 */ public int TreeDepth(TreeNode root) { if (root == null) { return 0; } int left = TreeDepth(root.left); int rigth = TreeDepth(root.right); return left > rigth ? left + 1 : rigth + 1; } /** * 在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 * 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->5 * * @param pHead * @return */ public ListNode deleteDuplication(ListNode pHead) { if (pHead == null || pHead.next == null) { return pHead; } // 建立一個頭節點 p1記錄沒有重複的節點 ListNode p1 = new ListNode(); p1.next = null; ListNode head = p1; // p2用於跳過重複的節點 ListNode p2 = pHead; while (p2 != null) { if (p2.next != null && p2.val == p2.next.val) { while (p2.next != null && p2.val == p2.next.val) { p2 = p2.next; } // 跳過重複的最後個節點 p2 = p2.next; //防止連結串列尾部出現重複值,p2==null跳出迴圈而p1沒有跳過尾部重複 p1.next = p2; } else { // 如果沒有重複 p1.next = p2; p1 = p2; p2 = p2.next; } } // 返回時去掉頭節點 return head.next; } /** * HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。 * 今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和, * 當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數, * 並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和為8(從第0個開始,到第3個為止)。 * 給一個數組,返回它的最大連續子序列的和,你會不會被他忽悠住?(子向量的長度至少是1) * * @param array * @return */ public int FindGreatestSumOfSubArray(int[] array) { if (array == null) { return 0; } int sum = array[0]; int tempsum = array[0]; int len = array.length; for (int i = 1; i < len; i++) { tempsum = tempsum < 0 ? array[i] : tempsum + array[i]; sum = tempsum > sum ? tempsum : sum; } return sum; } /** * 寫一個函式,求兩個整數之和,要求在函式體內不得使用+、-、*、/四則運算子號。 * * @param num1 * @param num2 * @return */ public int Add(int num1, int num2) { if (num2 == 0) { return num1; } int tempNum2 = num2 > 0 ? num2 : -num2; for (int i = 0; i < tempNum2; i++) { if (num2 > 0) { num1++; } else { num1--; } } return num1; } /** * 從上往下打印出二叉樹的每個節點,同層節點從左至右列印。 * 公式: 父節點 i 左節點 2*i+1 右節點 2*i+2 * * @param root * @return */ public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) { ArrayList<Integer> list = new ArrayList<>(); Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { TreeNode node = queue.poll(); if (node != null) { list.add(node.val); if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } } } return list; } }