剑指offer(Java实现)

来源:互联网 发布:手机音乐合成剪辑软件 编辑:程序博客网 时间:2024/06/05 17:01

02、实现Singleton模式

多种单例模式比较


03、二维数组中的查找

public static boolean findInPartiallySortedMatrix(int[][] array, int targetNumber) {int row = array.length;int col = array[0].length;int i = 0, j = col - 1;while (i < row && j >= 0) {if (array[i][j] > targetNumber) {j--;} else if (array[i][j] < targetNumber) {i++;} else return true;}return false;}


04、替换空格

str.replace(" """); 


05、从尾到头打印链表

    public static void printListReversingly_Iteratively(Node head) {if (head == null) {return;}stack<Node> nodes = new stack<Node>();while (head != null) {nodes.push(head);head = head.next;}while (!nodes.isEmpty) {System.out.println(nodes.pop().value);}}    public static void printListReversingly_Recursively(Node head) {if (head != null) {if (head.next != null) {printListReversingly_Recursively(head.next);    } else System.out.println(head.value);}}


06、重建二叉树

根据先序遍历序列和中序遍历序列重建二叉树
        public TreeNode reConstructBinaryTree(int[] preOrder,int[] inOrder) {if (preOrder.length != inOrder.length) throws Exception;int index = preOrder.length - 1;if (index == 0) return null;return reConstructBinaryTree(preOrder, 0, index, inOrder, 0, index);}private TreeNode reConstructBinaryTree(int[] preOrder,int preStart, int preEnd, int[] inOrder, int inStart, int inEnd) {if (preStart > preEnd || inStart > inEnd)return null;TreeNode root = new TreeNode(preOrder[preStart]);for (int i = inStart; i <= inEnd; i++) {if (inOrder[i] == preOrder[preStart]) {root.left = reConstructBinaryTree(preOrder, preStart + i - inStart, index, inOrder, inStart, i - 1);root.right = reConstructBinaryTree(preOrder, preStart + i - inStart + 1, preEnd, inOrder, i + 1, inEnd);}}return root;}


07、用两个栈实现队列

        private Stack<Item> appendStack = new Stack<Item>(); private Stack<Item> deleteStack = new Stack<Item>(); public void appendTail(Item item) {appendStack.push(item);}public item deleteHead() {if (deleteStack.isEmpty()) {while(!appendStack.isEmpty()) {deleteStack.push(appendStack.pop());}}if (deleteStack.isEmpty())throws new Exception("队列为空,不能删");return deleteStack.pop();}


08、旋转数组的最小数字

借鉴二分查找法
public int minInReversingList(int[] numbers) {if(numbers == null)throws new Exception("数组为空"):int index1 = 0;int index2 = numbers.length - 1;int indexMid = (index1 + index2) / 2;while (numbers[index1] >= numbers[index2]) {if (index2 - index1 == 1) {indexMid = index2;break;}if (numbers[index1] == numbers[index2] || numbers[indexMid] == numbers[index2])return minInOrder(numbers, index1, index2);if (numbers[indexMid] >= numbers[index1]) {index1 = indexMid;} else if(numbers[indexMid] <= numbers[index2]) {index2 = indexMid;}}}private int minInOrder(int[] arr, int startIndex, int endIndex) {int result = numbers[startIndex];for (int i = startIndex; i <= endIndex; i++) {if (numbers[i] < result)result = numbers[i];}return result;}


09、斐波那契数列求和

调用递归效率低下,因此选择从下往上计算。拓展:青蛙跳台阶。
public int fibonacciNormal(int n) {if (n < 0)throws new Exception("n 必须 >= 0");int[] result = {0, 1};if (n < 2) return result[n];int n1 = 1, n2 = 1, sn = 0;          for(int i = 2; i < n; i++) {              sn = n1 + n2;              n1 = n2;              n2 = sn;          }          return sn;}


10、二进制中1的个数

除法效率低下,尽量使用与运算。右移数字i并判1,如果遇到负数会陷入死循环。因此左移1,依次与运算。
public int countOfNumberOne_1(int number) {int count = 0;int flag = 1;
while(flag != 0) {if(number & flag != 0)count++;flag << 1;}return count;}public int countOfNumberOne_1(int number) {int count = 0;while (num != 0) {              count++;              num = num & (num - 1);           }return count;}




DAY 2    2017/3/28

11、数值的整数次方

    public double pow(double base, int exponent) {        if (exponent == 0)            return 1;        if (exponent<0) {            exponent = - exponent;            base = 1/base;                   //数学上规定n个a相乘表示为a×a×a×a×...=a^n,其中 a≠0。        }        return (exponent % 2 == 0) ? pow(base*base, exponent >> 1) : base*pow(base*base, exponent >> 1);    //右移比除法效率高    }

12、打印1到最大的n位数

当输入n很大的时候,我们求最大的n位数是不是用整型(int)或者长整型(long long)都会溢出?也就是说我们需要考虑大数问题。最常用的也是最容易的用字符串或者数组表达大数。

public void print1ToMaxOfNDigits(int n) {        if (n <= 0) {             System.out.println("输入出错!");  return;}        int[] number = new int[n];          while (!increment(number)) {             print(number);         }}private boolean increment(int[] number) {          boolean isOverflow = false;          int nTakeOver = 0;          // 进位          for (int i = number.length - 1; i >= 0; i--) {             int nSum = number[i] + nTakeOver;//nTakeOver使用一次后即跳出循环,不用清零                       if (i == number.length - 1)            // 如果是最低位加1                  nSum++;              if (nSum >= 10) {                  if (i == 0)                      isOverflow = true;                  else {                      nTakeOver = 1;                      number[i] = nSum - 10;                  }              } else {                  number[i] = nSum;                  break;                       // 最低位加1后有进位会循环改变前面的位,没有进位跳出循环,前面的位不变                             }          }          return isOverflow;      }        // 打印一个数,循环遍历数组,从不为0的位开始打印      private void print(int[] number) {          boolean isValid = false;          for (int i = 0; i < number.length; i++) {              if (!isValid && number[i] != 0)                  isValid = true;            if (isValid)                System.out.print(number[i]);        }System.out.println();    } 


13、O(1)时间删除链表节点

public void deleteNode(ListNode head, ListNode deListNode){          if (deListNode == null || head == null)             return;  if (deListNode.next != null){                     //要删除的不是尾节点deListNode.data = deListNode.next.data;              deListNode.next = deListNode.next.next; } else if (head == deListNode) {                  //只有一个节点,删除头(尾)结点head = null;} else {                                          //有多个节点,删除尾结点ListNode pinitListNode = head;              while (pinitListNode.next.next != null) {                  pinitListNode = pinitListNode.next;              }              pinitListNode.next = null;}    }


14、调整数组使奇数位于前面

public void reorderArray(int[] array) {if (array == null) return;int pLeft = 0;int pRight = array.length - 1;while (pLeft < pRight) {while (pLeft < pRight && isOdd(array[pLeft])) {pLeft++;}while (pLeft < pRight && !isOdd(array[pRight])) {pRight--;}if (pLeft < pRight) {int temp = array[pLeft];array[pLeft] = array[pRight];array[pRight] = temp;}}} private boolean isOdd(int num) {return num % 2 != 0;}

15、链表中倒数第K个节点

public ListNode findKthToTail(ListNode head, int k) {if (head == null || k <= 0)return null;ListNode pAhead = head, pBehind;for (int i = 0; i < k - 1; i++) {if (pAhead.next != null) {pAhead = pAhead.next;} else return null;}pBehind = head;while (pAhead.next != null) {pAhead = pAhead.next;pBehind = pBehind.next;}return pBehind;}


16、反转链表

public ListNode reverseListNode(ListNode head) {  ListNode pPrev = null, pNode = head;while (pNode != null) {ListNode pNext = pNode.next;pNode.next = pPrev;pPrev = pNode;pNode = pNext;}return pPrev;}

17、合并两个排序的链表

public ListNode mergeSortedListNode(ListNode pHead1, ListNode pHead2) {if (pHead1 == null) return pHead2;          else if (pHead2 == null) return pHead1;ListNode pMergedHead = null;if (pHead1.value < pHead2.value){              pMergedHead = pHead1;              pMergedHead.next = Merge(pHead1.next, pHead2);          }else{              pMergedHead = pHead2;              pMergedHead.next = Merge(pHead1, pHead2.next);          }          return pMergedHead;  }

18、树的子结构

分两步:第一步在树A中找到和B的根节点的值一样的结点R,第二步再判断树A中以R为根结点的子树是不是包含和树B一样的结构。
public boolean isSubtree(Node root1, Node root2) {if (root2 == null) return true;if (root1 == null) return false;return equals(root1, root2) || isSubtree(root1.left, root2) || isSubtree(root1.right, root2);}private boolean equals(Node root1, Node root2) {if (root2 == null) return true;if (root1 == null) return false;if (root1.data != root2.data) return false;         // Should use .equals if Node.data isn't primitivereturn equals(root1.left, root2.left) && equals(root1.right, root2.right);}



0 0
原创粉丝点击