劍指offer第二版總結(jié)——基于趴裉粒客網(wǎng)

劍指offer第二版總結(jié)——基于牛客網(wǎng)

1. 在一個二維數(shù)組中(每個一維數(shù)組的長度相同)捞稿,每一行都按照從左到右遞增的順序排序又谋,每一列都按照從上到下遞增的順序排序。請完成一個函數(shù)娱局,輸入這樣的一個二維數(shù)組和一個整數(shù)彰亥,判斷數(shù)組中是否含有該整數(shù)。

public class Solution {
    public boolean Find(int target, int [][] array) {
        
        int row = array.length; 
        int col = array[0].length;
        // 從數(shù)組的左下角(或者右上角開始判斷)
        int i = row-1, j = 0;
        while( i>=0 && j< col)
        {           
            if( target == array[i][j]) {
                return true;
            }
            if( target > array[i][j] ){
                j++;
            }
            else {
                i--;
            }
        }
        return false;
    }
}

注解:解題的關鍵在于找到排好序的規(guī)則衰齐,左下角和右上角的位置數(shù)正好處于一個可以通過大小進行判斷上下走向任斋。

2. 請實現(xiàn)一個函數(shù),將一個字符串中的每個空格替換成“%20”耻涛。例如仁卷,當字符串為We Are Happy.則經(jīng)過替換之后的字符串為We%20Are%20Happy。

public class Solution {
    public String replaceSpace(StringBuffer str) {
            if(str.length() == 0 )  return "";       
        // 找出被替換字符的數(shù)目犬第,java可以省略這一步锦积。
         int numOfEmpty = 0;
         for(int i =0; i<str.length(); i++ ) {
             if( str.charAt(i) == ' ') numOfEmpty++;
         }
        // 若是C++可以根據(jù)numOfEmpty開辟新空間,而java可以直接使用StringBuffer
         StringBuffer outStr = new StringBuffer();
         for(int i = 0; i<str.length(); i++ ) {
             if( str.charAt(i) == ' ') outStr.append("%20");
             else  outStr.append(str.charAt(i));     
         }
         return outStr.toString(); 
    }
}

3. 輸入一個鏈表歉嗓,按鏈表值從尾到頭的順序返回一個ArrayList丰介。

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*/

import java.util.Stack;
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> arrayList= new ArrayList<>();
        Stack<Integer> stack = new Stack<>();
        
        if(listNode == null) return arrayList;
        // 遍歷鏈表存入stack中
        while( listNode.next != null )
        {
            stack.push(listNode.val);   
            listNode = listNode.next;
        }
        stack.push(listNode.val);
        // 將stack中的數(shù)據(jù)放入ArrayList中
        while( !stack.isEmpty() ) {
            arrayList.add(stack.pop());
        }
        return arrayList;
    }
}

4. 輸入某二叉樹的前序遍歷和中序遍歷的結(jié)果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復的數(shù)字哮幢。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}带膀,則重建二叉樹并返回。

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        
        TreeNode rootNode=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
        return rootNode;    
    }
    
    private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
        
        if(startPre>endPre||startIn>endIn)return null;
    // 新建根節(jié)點
        TreeNode rootNode=new TreeNode(pre[startPre]);
          
        for(int i=startIn;i<=endIn;i++){
        // 找到中序中的根節(jié)點
        if(in[i]==pre[startPre]){
                rootNode.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
                rootNode.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
            }
    }        
        return rootNode;
    }
}

5. 用兩個棧來實現(xiàn)一個隊列橙垢,完成隊列的Push和Pop操作垛叨。 隊列中的元素為int類型。

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
   // 在一個stack中進
    public void push(int node) {
        stack1.push(node);
    }
   // 從stack2中出柜某,若stack2為空嗽元,則從stack1中把數(shù)據(jù)輸出到stack2中
    public int pop() {
        if(stack2.isEmpty())
        {
            while(!stack1.isEmpty())
            {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }   
}

注解:先進后出兩次為先進先出。

6. 把一個數(shù)組最開始的若干個元素搬到數(shù)組的末尾喂击,我們稱之為數(shù)組的旋轉(zhuǎn)剂癌。 輸入一個非減排序的數(shù)組的一個旋轉(zhuǎn),輸出旋轉(zhuǎn)數(shù)組的最小元素翰绊。 例如數(shù)組{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉(zhuǎn)佩谷,該數(shù)組的最小值為1。 NOTE:給出的所有元素都大于0监嗜,若數(shù)組大小為0谐檀,請返回0。

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array.length == 0) return 0;
        int left = 0;
        int right = array.length - 1;
     // 折半查找
        while(left < right) {
            int mid = (left + right) / 2;
        // 統(tǒng)一與右邊比
            if(array[mid] > array[right]) {
                left = mid + 1;
            } else if(array[mid] < array[right]){
         // 存在向下取整的情況
                right = mid;
            } else {
        // 相等的情況
                right--;
            }
        }
        return array[left];
    }
}

7. 大家都知道斐波那契數(shù)列裁奇,現(xiàn)在要求輸入一個整數(shù)n稚补,請你輸出斐波那契數(shù)列的第n項(從0開始,第0項為0)框喳。 n<=39

public class Solution {
    public int Fibonacci(int n) {
        if(n<=0) return 0;
        if(n<=2)return 1;
        
        int preNum =1;
        int pre2Num =1;
        int outNum = 0;
        
        for(int i = 3; i<=n; i++){
            outNum = preNum + pre2Num;
            pre2Num = preNum;
            preNum = outNum;
        }
        
        return outNum;
    }
}

8. 一只青蛙一次可以跳上1級臺階课幕,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先后次序不同算不同的結(jié)果)五垮。

public class Solution {
    public int JumpFloor(int target) {
        if(target<=0) return 0;
        if(target<=2) return target;
        
        int preNum =2;
        int pre2Num =1;
        int outNum = 0;
        
        for(int i = 3; i<=target; i++){
            outNum = preNum + pre2Num;
            pre2Num = preNum;
            preNum = outNum;
        }
        return outNum;
    }
}

9. 一只青蛙一次可以跳上1級臺階乍惊,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法放仗。

public class Solution {
    public int JumpFloorII(int target) {
        if(target<=0) return 0;

        return 1<<(--target);
    }
}

注解:f(n) = f(n-1)+f(n-2)...f(1)+1; 由于f(1)=1润绎,遞推可得:f(n)=2^(n-1);

10. 我們可以用21的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個21的小矩形無重疊地覆蓋一個2*n的大矩形诞挨,總共有多少種方法莉撇?

public class Solution {
    public int RectCover(int target) {
        if(target<=0) return 0;
        if(target<=2) return target;
        
        int preNum =2;
        int pre2Num =1;
        int outNum = 0;
        
        for(int i = 3; i<=target; i++){
            outNum = preNum + pre2Num;
            pre2Num = preNum;
            preNum = outNum;
        }
        return outNum;
    }
}

注解:這題和青蛙跳沒區(qū)別。

11. 輸入一個整數(shù)惶傻,輸出該數(shù)二進制表示中1的個數(shù)棍郎。其中負數(shù)用補碼表示。

public class Solution {
    public int NumberOf1(int n) {
        int temp = 1;
        int count1 = 0;
        while(temp!=0)
        {
            if( (temp&n)!=0 ) count1++;
        // 移動1银室,避免出現(xiàn)負數(shù)移動補1的情況
            temp = temp <<1;
        }
        return count1;
    }
}

12. 給定一個double類型的浮點數(shù)base和int類型的整數(shù)exponent涂佃。求base的exponent次方励翼。

public class Solution {
    public double Power(double base, int exponent) {
        if(exponent==0) return 1;
     // 由于要考慮正負數(shù),先統(tǒng)一絕對值計算
        int absE = Math.abs(exponent);
         
        if(exponent<0) {
        return 1/subPower(base,absE);
      }
        else{
            return subPower(base,absE);
        }
    }
    
    public double subPower(double base, int exponent) {
        if( exponent>1 ){
        //折半乘辜荠,提高效率
            if( exponent%2 != 0) {
            return base * subPower(base, exponent/2) * subPower(base, exponent/2);
            }
        else{
                return subPower(base, exponent/2) * subPower(base, exponent/2);
        }
        }
        return base;        
    }
}

13. 輸入一個整數(shù)數(shù)組汽抚,實現(xiàn)一個函數(shù)來調(diào)整該數(shù)組中數(shù)字的順序,使得所有的奇數(shù)位于數(shù)組的前半部分伯病,所有的偶數(shù)位于數(shù)組的后半部分造烁,并保證奇數(shù)和奇數(shù),偶數(shù)和偶數(shù)之間的相對位置不變午笛。

import java.util.LinkedList;
import java.util.Queue;

public class Solution {
    public void reOrderArray(int [] array) {
        Queue<Integer> queue1 = new LinkedList<Integer>();
        Queue<Integer> queue2 = new LinkedList<Integer>();
        
        for(int i=0;i<array.length;i++){
            if(array[i]%2==1){
                queue1.add(array[i]);
            }
            else {
                queue2.add(array[i]);
            }
        }

        for(int i=0;i<array.length;i++){
            if(!queue1.isEmpty()) {
                array[i]=queue1.poll();
            }
            else {
                array[i]=queue2.poll();
            }
        }
    }
}

14. 輸入一個鏈表惭蟋,輸出該鏈表中倒數(shù)第k個結(jié)點。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
// 雙指針實現(xiàn)
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if ( head == null || k <= 0) {
            return null;
        }
       ListNode fastHead = head;
        
    // 先走k-1步
        for(int i=1; i< k; i++) {
            if(fastHead.next != null) {
                fastHead = fastHead.next;       
            }
            else{
                return null;
            }
        }
        // 以前走
        while(fastHead.next != null){
            head = head.next;
            fastHead = fastHead.next;
        }
        return head;
    }
}

15. 輸入一個鏈表季研,反轉(zhuǎn)鏈表后,輸出新鏈表的表頭誉察。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/

public class Solution {
    public ListNode ReverseList(ListNode head) {
    if ( head == null ) {
            return null;
        }
        // 需要前一個与涡,當前,后一個持偏,三個節(jié)點處理轉(zhuǎn)向.               
        ListNode preNode = head;
        ListNode nextNode = null;
    //處理首節(jié)點
        if(head.next != null){
            head = head.next;
            preNode.next = null;
        }
        else{
            return head;
        }
        // 遞歸處理         
        while(head.next != null) {
            nextNode = head.next;
            head.next = preNode;        
            preNode = head;
            head = nextNode;
        }
        // 尾節(jié)點處理
        head.next = preNode;    
        return head;
    }
}

16. 輸入兩個單調(diào)遞增的鏈表驼卖,輸出兩個鏈表合成后的鏈表,當然我們需要合成后的鏈表滿足單調(diào)不減規(guī)則鸿秆。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 ==null){
            return list2;
        }
        if(list2 ==null){
            return list1;
        }
        
        ListNode head = new ListNode(0);
        ListNode indexNode = head;
        while(list1 != null && list2 !=null){       
            if(list1.val <= list2.val){
                indexNode.next = list1;
                list1 = list1.next;
            }
            else{
                indexNode.next = list2;
                list2 = list2.next;
            }
            
            indexNode = indexNode.next;
        }
        
        if(list1 == null){
            indexNode.next = list2;
        }
        else{
            indexNode.next = list1;
        }
    
        return head.next;
    }
}

17. 輸入兩棵二叉樹A酌畜,B,判斷B是不是A的子結(jié)構(gòu)卿叽。(ps:我們約定空樹不是任意一個樹的子結(jié)構(gòu))

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}
*/

public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1 == null || root2 == null){
            return false;
        }
        
        if( root1.val == root2.val ){
            if(sameHasSubtree( root1.left, root2.left) && sameHasSubtree( root1.right, root2.right)){
                return true;
            }
        }
        
        if( HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2)){
            return true;
        }
        
        return false;
    }
    
    public boolean sameHasSubtree(TreeNode root1,TreeNode root2) {
        
        if(root2 == null){
            return true;        
        }
        if(root1 == null){
            return false;       
        }
        if( root1.val == root2.val){
            if(sameHasSubtree( root1.left, root2.left) && sameHasSubtree( root1.right, root2.right)){
                return true;
            }
        }

        return false;
    }
}

18. 操作給定的二叉樹桥胞,將其變換為源二叉樹的鏡像。

public class Solution {
    public void Mirror(TreeNode root) {
        if(root == null){
        return ;    
      }
        if(root.left != null ){ 
            Mirror(root.left);
        }
        if(root.right != null){
            Mirror(root.right); 
        }
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;     
    }
}

19. 輸入一個矩陣考婴,按照從外向里以順時針的順序依次打印出每一個數(shù)字贩虾,例如,如果輸入如下4 X 4矩陣: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 則依次打印出數(shù)字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        if(matrix == null){
            return null;
        }
        ArrayList<Integer> outList = new ArrayList<>();
    
        int row = matrix.length;
        int col = matrix[0].length;
        // 分四個方向討論遍歷沥阱,注意截止條件就好缎罢。
        int left = 0,top = 0,bottom = row - 1,right = col - 1;
        while(left <= right && top <= bottom){
            for(int i = left;i<=right;i++){
                outList.add(matrix[top][i]);
            }
            for(int j = top+1;j<=bottom;j++){
                outList.add(matrix[j][right]);
            }
            if (top != bottom){
                for(int t = right-1;t>=left;t--){
                    outList.add(matrix[bottom][t]);
                }
            }
            if(left != right){
                for(int k = bottom-1;k>top;k--){
                    outList.add(matrix[k][left]);
                }
            }        
            top++;left++;right--;bottom--;
        }  
        return outList;
    }   
}

20. 定義棧的數(shù)據(jù)結(jié)構(gòu),請在該類型中實現(xiàn)一個能夠得到棧中所含最小元素的min函數(shù)(時間復雜度應為O(1))考杉。

import java.util.Stack;

public class Solution {
    Stack<Integer> stack = new Stack<>();
    Stack<Integer> minStack = new Stack<>();

    public void push(int node) {
        stack.push(node);
        if( minStack.isEmpty() || node < minStack.peek()){
            minStack.push(node);
        }
        else{
            minStack.push(minStack.peek()); // 壓自己
        }
    }
    
    public void pop() {
        stack.pop();
        minStack.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int min() {
        return minStack.peek();
    }
}

21. 輸入兩個整數(shù)序列策精,第一個序列表示棧的壓入順序,請判斷第二個序列是否可能為該棧的彈出順序崇棠。假設壓入棧的所有數(shù)字均不相等咽袜。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列枕稀,但4,3,5,1,2就不可能是該壓棧序列的彈出序列酬蹋。(注意:這兩個序列的長度是相等的)

import java.util.ArrayList;
import java.util.Stack;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        if(pushA.length != popA.length || pushA.length<=0 || popA.length<=0){
            return false;
        }
        Stack<Integer> stack = new Stack<>();
        stack.push(pushA[0]);
        for (int i = 0,j = 0; i < popA.length; i++) {
            while (j < popA.length && stack.peek() != popA[i]) {
                stack.push(pushA[j++]);
            }
            if(stack.peek() != popA[i]){
                return false;
            }
            stack.pop();
        }     
        return true;
    }
}

22. 從上往下打印出二叉樹的每個節(jié)點及老,同層節(jié)點從左至右打印。

import java.util.LinkedList;
import java.util.Queue;
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        ArrayList<Integer> list = new ArrayList<>();
        
        while(root != null){
            list.add(root.val);
            if( root.left != null){
                queue.add(root.left);
            }
            if( root.right != null){
                queue.add(root.right);
            }
            root = queue.poll();
        }
        
        return list;
    }
}

23. 輸入一個整數(shù)數(shù)組范抓,判斷該數(shù)組是不是某二叉搜索樹的后序遍歷的結(jié)果骄恶。如果是則輸出Yes,否則輸出No。假設輸入的數(shù)組的任意兩個數(shù)字都互不相同匕垫。

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence.length == 0) return false;
        return IsTreeBST(sequence, 0, sequence.length-1);
    }
    public boolean IsTreeBST(int [] sequence,int start,int end ){
        if(end <= start) return true;     
        for (int i = start; i < end; i++) {
            if(sequence[i] > sequence[end]) break;
        }
    // 驗證后面的是否都大于根值
        for (int j = i; j < end; j++) {
            if(sequence[j] < sequence[end]) return false;
        }
        return IsTreeBST(sequence, start, i-1) && IsTreeBST(sequence, i, end-1);
    }   
}

24. 輸入一顆二叉樹的根節(jié)點和一個整數(shù)僧鲁,打印出二叉樹中結(jié)點值的和為輸入整數(shù)的所有路徑。路徑定義為從樹的根結(jié)點開始往下一直到葉結(jié)點所經(jīng)過的結(jié)點形成一條路徑象泵。(注意: 在返回值的list中寞秃,數(shù)組長度大的數(shù)組靠前)

import java.util.ArrayList;

public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
            
        ArrayList<Integer> a1=new ArrayList<Integer>();
        ArrayList<ArrayList<Integer>> arr=new ArrayList<ArrayList<Integer>>();               

        path( root, target, arr, a1);
        return arr; 
    }   
    
    public void path(TreeNode root, int target, ArrayList<ArrayList<Integer>> arr, ArrayList<Integer> a1 ){
        if(root==null){
        return ;
     }
        
        target -= root.val;
        a1.add(root.val);
    
        if(root.left!=null){
            path( root.left, target, arr, a1);
        }
        if(root.right!=null){
            path( root.right, target, arr, a1);
        }

        if(root.left==null && root.right==null && target==0){ 
            arr.add(new ArrayList<Integer>(a1));
        }   
        a1.remove(a1.size()-1);   
    }
}

注解:本題為保證數(shù)組長度大的在前也通過,若需要保證偶惠,只要加一級的排序就好春寿。

25. 輸入一個復雜鏈表(每個節(jié)點中有節(jié)點值,以及兩個指針忽孽,一個指向下一個節(jié)點绑改,另一個特殊指針指向任意一個節(jié)點),返回結(jié)果為復制后復雜鏈表的head兄一。(注意厘线,輸出結(jié)果中請不要返回參數(shù)中的節(jié)點引用,否則判題程序會直接返回空)

public class Solution {
    public RandomListNode Clone(RandomListNode pHead){
        if(pHead == null){
            return null;
        }
        
        RandomListNode p=pHead;
        RandomListNode t=pHead;
        // next 賦值
        while(p!=null){
            RandomListNode q=new RandomListNode(p.label);
            q.next=p.next;
            p.next=q;
            p=q.next;
        }
        // random 賦值
        while(t!=null){
            RandomListNode q=t.next;
            if(t.random!=null)
                q.random=t.random.next;
            t=q.next;
        }
        
        // 拆分
        RandomListNode s = new RandomListNode(0);
        RandomListNode s1 = s;
        while (pHead != null) {
            RandomListNode q = pHead.next;
            pHead.next = q.next;
                
            s.next = q;
            s = s.next;
            pHead = pHead.next;

        }
        return s1.next;
    }
}

26. 輸入一棵二叉搜索樹出革,將該二叉搜索樹轉(zhuǎn)換成一個排序的雙向鏈表造壮。要求不能創(chuàng)建任何新的結(jié)點,只能調(diào)整樹中結(jié)點指針的指向骂束。

public class Solution {
    TreeNode head = null;
    TreeNode realHead = null;

    public TreeNode Convert(TreeNode pRootOfTree) {
        if (pRootOfTree == null)
            return null;
        
        Convert(pRootOfTree.left);
        
        if (realHead == null) {
            head = pRootOfTree;
            realHead = pRootOfTree;
        } else {
            head.right = pRootOfTree;
            pRootOfTree.left = head;
            head = pRootOfTree;
        }
        
        Convert(pRootOfTree.right);
        return realHead;
    }
}

27. 輸入一個字符串,按字典序打印出該字符串中字符的所有排列耳璧。例如輸入字符串a(chǎn)bc,則打印出由字符a,b,c所能排列出來的所有字符串a(chǎn)bc,acb,bac,bca,cab和cba。

import java.util.ArrayList;
import java.util.Collections;

public class Solution {
    public ArrayList<String> Permutation(String str)
    {
        ArrayList<String> res=new ArrayList<String>();
        if(str.length()==0||str==null)return res;
        char[] chars = str.toCharArray();
        
        Permutation(chars,  0, res);
        
        // 字典序排序
        Collections.sort(res);
        return res;
         
    }
    
    public void Permutation(char[] chars, int begin, ArrayList<String> result) {
        if(chars==null || chars.length==0 || begin<0 || begin>chars.length-1) { 
            return ; 
        }
 
        if(begin==chars.length-1){
            result.add(new String(chars));
        }
        
        // 最初自己的排序也是要算上的
        for(int i=begin;i<chars.length;i++)
        {
            if(i==begin||chars[begin]!=chars[i])
            {
                swap(chars,begin,i);
                Permutation( chars, begin+1, result);   
                swap(chars,begin,i);
            }
        }
    }
 
    public void swap(char[]t,int i,int j)
     {
        char c=t[i];
        t[i]=t[j];
        t[j]=c;
    }
    
}

注解:這種都是典型的回溯法(1展箱,n-1)

28. 數(shù)組中有一個數(shù)字出現(xiàn)的次數(shù)超過數(shù)組長度的一半楞抡,請找出這個數(shù)字。例如輸入一個長度為9的數(shù)組{1,2,3,2,2,2,5,4,2}析藕。由于數(shù)字2在數(shù)組中出現(xiàn)了5次召廷,超過數(shù)組長度的一半,因此輸出2账胧。如果不存在則輸出0竞慢。

import java.util.HashMap;

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) { 
        HashMap<Integer, Integer> map = new HashMap<>();

        for(int i = 0; i<array.length; i++){
            if(map.containsKey(array[i])){
                map.put(array[i], map.get(array[i]) + 1 );
            } 
            else{
                map.put(array[i], 1 );
            }
        }
        
        for (Integer key : map.keySet()) { 
            if ( map.get(key) > array.length/2){
                return key;
            }   
        } 
        return 0;
    }
}

注解:由于不存在的可能性,故劍指offer中的技巧不能用治泥。

29. 輸入n個整數(shù)筹煮,找出其中最小的K個數(shù)。例如輸入4,5,1,6,2,7,3,8這8個數(shù)字居夹,則最小的4個數(shù)字是1,2,3,4,败潦。

import java.util.Collections;
import java.util.ArrayList;

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> res = new ArrayList<Integer>();
        if(input.length < 1 || k > input.length) return res;
        
        for(int i =0; i<input.length; i++){
            res.add(input[i]);
        }
        Collections.sort(res);
         
        ArrayList<Integer> out = new ArrayList<Integer>();
        for(int i =0; i<k; i++){
            out.add(res.get(i));
        }           
        return out;
    }
}

注解:這題真扯淡

30. HZ偶爾會拿些專業(yè)問題來忽悠那些非計算機專業(yè)的同學本冲。今天測試組開完會后,他又發(fā)話了:在古老的一維模式識別中,常常需要計算連續(xù)子向量的最大和,當向量全為正數(shù)的時候,問題很好解決。但是,如果向量中包含負數(shù),是否應該包含某個負數(shù),并期望旁邊的正數(shù)會彌補它呢劫扒?例如:{6,-3,-2,7,-15,1,2,2},連續(xù)子向量的最大和為8(從第0個開始,到第3個為止)檬洞。給一個數(shù)組,返回它的最大連續(xù)子序列的和沟饥,你會不會被他忽悠滋碚?(子向量的長度至少是1)

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        if(array == null){
            return 0;
        }
        int[] arr2 = new int[array.length];
        arr2[0] = array[0];
        for(int i=1; i< array.length; i++){
        // 核心思想
            if(arr2[i-1] < 0){
                arr2[i] = array[i];
            }
            else{
                arr2[i] = arr2[i-1] + array[i];
            }
        }
        
        int max = arr2[0];
        for(int i=1; i< array.length; i++){
            if(arr2[i]>max){
                max = arr2[i];
            }
        }
        return max;
    }
}

31. 求出113的整數(shù)中1出現(xiàn)的次數(shù),并算出1001300的整數(shù)中1出現(xiàn)的次數(shù)贤旷?為此他特別數(shù)了一下1~13中包含1的數(shù)字有1广料、10、11幼驶、12艾杏、13因此共出現(xiàn)6次,但是對于后面問題他就沒轍了。ACMer希望你們幫幫他,并把問題更加普遍化,可以很快的求出任意非負整數(shù)區(qū)間中1出現(xiàn)的次數(shù)(從1 到 n 中1出現(xiàn)的次數(shù))盅藻。

public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        int base = 1;
        int count =0;
        int round = n;
        int weight = 0购桑;

        while(round>0){
            weight = round%10;
            round = round /10;
            // 按位計算1的數(shù)目
            count += round * base;
            if(weight==1){
                count += (n % base) + 1;
            }
            else if (weight>1) {
                count += base;
            }
            
            base *= 10;
        } 
        return count;
    }
}

32. 輸入一個正整數(shù)數(shù)組,把數(shù)組里所有數(shù)字拼接起來排成一個數(shù)萧求,打印能拼接出的所有數(shù)字中最小的一個其兴。例如輸入數(shù)組{3顶瞒,32夸政,321},則打印出這三個數(shù)字能排成的最小數(shù)字為321323榴徐。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        if(numbers == null || numbers.length == 0) return "";
        int len = numbers.length;
        String[] str = new String[len];
        StringBuilder sb = new StringBuilder();
    // 數(shù)字可能越界守问,轉(zhuǎn)字符串計算
        for(int i = 0; i < len; i++){
            str[i] = String.valueOf(numbers[i]);
        }
        Arrays.sort(str,new Comparator<String>(){
            @Override
            public int compare(String s1, String s2) {
                String c1 = s1 + s2;
                String c2 = s2 + s1;
                return c1.compareTo(c2);
            }
        });
        for(int i = 0; i < len; i++){
            sb.append(str[i]);
        }
        return sb.toString();
    }
}

33. 把只包含質(zhì)因子2、3和5的數(shù)稱作丑數(shù)(Ugly Number)坑资。例如6耗帕、8都是丑數(shù),但14不是袱贮,因為它包含質(zhì)因子7仿便。 習慣上我們把1當做是第一個丑數(shù)。求按從小到大的順序的第N個丑數(shù)攒巍。

public class Solution {
    public int GetUglyNumber_Solution(int index) {
        if( index<=1 ) return index;
        int[] list = new int[index];
        
        list[0] = 1;
        int temp2=0,temp3=0,temp5=0;
        
        int count = 0;
        while( count<index-1 ){
            while(list[temp2]*2<=list[count]){
                temp2++;
            }
            while(list[temp3]*3<=list[count]){
                temp3++;
            }
            while(list[temp5]*5<=list[count]){
                temp5++;
            }
            list[++count] = Math.min(Math.min(2*list[temp2], 3*list[temp3]) , 5*list[temp5]);
        }   
        return list[list.length-1];
    }
}

注解:空間換時間算法

34. 在一個字符串(0<=字符串長度<=10000嗽仪,全部由字母組成)中找到第一個只出現(xiàn)一次的字符,并返回它的位置, 如果沒有則返回 -1(需要區(qū)分大小寫).

import java.util.LinkedHashMap;

public class Solution {
    public static int FirstNotRepeatingChar(String str) {
        LinkedHashMap <Character, Integer> map = new LinkedHashMap<Character, Integer>();
        for(int i=0;i<str.length();i++){
            if(map.containsKey(str.charAt(i))){
                map.put(str.charAt(i), map.get(str.charAt(i)) + 1 );
            }
            else {
                map.put(str.charAt(i), 1);
            }
        }
        
        int i=0;
        for(;i<str.length();i++){
            char c = str.charAt(i);
            if (map.get(c) == 1) {
                return i;
            }
        }
        return -1;
    }
}

注解:借助hashmap

35. 在數(shù)組中的兩個數(shù)字,如果前面一個數(shù)字大于后面的數(shù)字柒莉,則這兩個數(shù)字組成一個逆序?qū)ξ偶帷]斎胍粋€數(shù)組,求出這個數(shù)組中的逆序?qū)Φ目倲?shù)P。并將P對1000000007取模的結(jié)果輸出兢孝。 即輸出P%1000000007

public class Solution {
public static int InversePairs(int [] array) {
        if(array==null||array.length==0){
            return 0;
        }
        int[] copy = new int[array.length];
        int count = InversePairsCore( array, copy, 0, array.length-1);//數(shù)值過大求余
        return count;  
    }
    
    private  static int InversePairsCore( int[] array, int[] copy, int low, int high)
    {
        if(low==high){
            return 0;
        }

        int mid = (low+high)>>1;
        int leftCount = InversePairsCore( array, copy, low, mid);
        int rightCount = InversePairsCore( array, copy, mid+1, high);
        
        int count = 0;
        int i=mid;
        int j=high;
        int locCopy = high;
    // 歸并排序窿凤,保證有序
        while(i>=low&&j>mid){
            if(array[i]>array[j]){
                count += j-mid;     // 核心計算逆序?qū)Υa
                copy[locCopy--] = array[i--];
                if(count>=1000000007){
                    count%=1000000007;
                }
            }
            else{
                copy[locCopy--] = array[j--];
            }
        }

        for(;i>=low;i--)
        {
            copy[locCopy--]=array[i];
        }
        for(;j>mid;j--)
        {
            copy[locCopy--]=array[j];
        }
    // 復制回去仅偎,保證有序
        for(int s=low;s<=high;s++)
        {
            array[s] = copy[s];
        }

        return (leftCount+rightCount+count)%1000000007;
    }
}

注解:這一題肯定可以簡化,懶得改了

36. 輸入兩個鏈表雳殊,找出它們的第一個公共結(jié)點橘沥。

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { 
        if(pHead1==null||pHead2==null){
            return null;
        }
        if(pHead1==pHead2){
            return pHead1;
        }
    
        int len1=0;
        int len2=0;
        ListNode curr1=pHead1;
        ListNode curr2=pHead2;
        while(curr1!=null){
            len1++;
            curr1=curr1.next;
        }
        while(curr2!=null){
            len2++;
            curr2=curr2.next;
        }

        curr1=pHead1;
        curr2=pHead2;
        if(len1>len2){
            int moreLen=len1-len2;
            while(moreLen!=0){
                curr1=curr1.next;
                moreLen--;
            }
        }
        else{
            int moreLen=len2-len1;
            while(moreLen!=0){
                curr2=curr2.next;
                moreLen--;
            }
        }
 
        while(curr1!=curr2&&curr1!=null){
            curr1=curr1.next;
            curr2=curr2.next;
        }
         
        return curr1;
    }
}

37. 統(tǒng)計一個數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù)。

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        if(array.length<1) return 0;    
        int begin =0;
        int end = array.length-1;
        
        return GetNumberOfK(array , k, begin, end);
    }
    
    public int GetNumberOfK(int[] array,int k, int begin, int end){
        if(begin>end)
            return 0;
        int mid=(end-begin)/2+begin;
        
        if(k>array[mid])
            return GetNumberOfK(array,k,mid+1,end);
        else if(k<array[mid])
            return GetNumberOfK(array,k,begin,mid-1);
        else {
            return 1+GetNumberOfK(array,k,begin,mid-1)+GetNumberOfK(array,k,mid+1,end);
        }   
    }
}

注解:折半查找提高效率

38. 輸入一棵二叉樹相种,求該樹的深度威恼。從根結(jié)點到葉結(jié)點依次經(jīng)過的結(jié)點(含根、葉結(jié)點)形成樹的一條路徑寝并,最長路徑的長度為樹的深度箫措。

public class Solution {
    public int TreeDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }

        return Math.max(TreeDepth(root.left), TreeDepth(root.right)) + 1;
    }
}

39. 輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹衬潦。

public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        if (root == null) {
            return true;
        }
        int left = getTreeDepth(root.left);
        int right = getTreeDepth(root.right);
        int diff = Math.abs(left - right);
        if (diff > 1)
            return false;
        return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
         
    }

    public  int getTreeDepth(TreeNode root) {
        if (root == null)
            return 0;
        else
            return Math.max(getTreeDepth(root.left), getTreeDepth(root.right)) + 1;
    }
}

40. 一個整型數(shù)組里除了兩個數(shù)字之外斤蔓,其他的數(shù)字都出現(xiàn)了偶數(shù)次。請寫程序找出這兩個只出現(xiàn)一次的數(shù)字镀岛。

//num1,num2分別為長度為1的數(shù)組弦牡。傳出參數(shù)
//將num1[0],num2[0]設置為返回結(jié)果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if (array == null) return ;
        
        int binaryVal = array[0];

        for(int i=1; i< array.length; i++){
            binaryVal ^= array[i];
        }
        // 找到第一個bit不為1的數(shù)
        int binary1 = 1;
        while((binary1&binaryVal)==0){
            binary1 = binary1<<1;           
        }
        
        boolean flag1 = true;
        boolean flag2 = true;    
        for(int i=0; i< array.length; i++){
            if( (binary1 & array[i]) !=0 && flag1){
                num1[0] = array[i];
            flag1 = false;
            }
        else if( (binary1 & array[i]) !=0){
            num1[0] = num1[0] ^array[i];
        }
            else if(flag2){
                num2[0] = array[i];
            flag2 = false;
            }
        else{
            num2[0] = num2[0] ^array[i];
        }
        }
    }
}

41. 小明很喜歡數(shù)學,有一天他在做數(shù)學作業(yè)時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他并不滿足于此,他在想究竟有多少種連續(xù)的正數(shù)序列的和為100(至少包括兩個數(shù))漂羊。沒多久,他就得到另一組連續(xù)正數(shù)和為100的序列:18,19,20,21,22〖菝蹋現(xiàn)在把問題交給你,你能不能也很快的找出所有和為S的連續(xù)正數(shù)序列? Good Luck!

import java.util.ArrayList;
public class Solution {
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
         ArrayList<ArrayList<Integer> >  list = new ArrayList<ArrayList<Integer> > ();
         if(sum<=1)return list;
      // 這里是一個優(yōu)化,前提單個數(shù)為100不行
         for(int i=1;i<=sum/2;i++){
             ArrayList<Integer> List2=new ArrayList<Integer>();
             int count=0;
             for(int j=i;j<sum;j++){
                 count+=j;
                 List2.add(j);
                 if(count>sum)
                     break;
                 else if(count==sum){
                     list.add(List2);
                     break;  
                 }
             }
         }
          
         return list;
    }
}

42. 輸入一個遞增排序的數(shù)組和一個數(shù)字S走越,在數(shù)組中查找兩個數(shù)椭豫,使得他們的和正好是S,如果有多對數(shù)字的和等于S旨指,輸出兩個數(shù)的乘積最小的赏酥。

import java.util.ArrayList;

public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        if(array.length<2) return list;
        
        int begin = 0;
        int end = array.length - 1;
        
        while(begin<end){
            if( (array[begin] + array[end])< sum){
                begin++;
            }
            else if( (array[begin] + array[end])> sum){
                end--;
            }
            else{
                list.add(array[begin]);
                list.add(array[end]);
                break;
            }
        }
        
        return list;
    }
}

43. 匯編語言中有一種移位指令叫做循環(huán)左移(ROL),現(xiàn)在有個簡單的任務谆构,就是用字符串模擬這個指令的運算結(jié)果裸扶。對于一個給定的字符序列S,請你把其循環(huán)左移K位后的序列輸出搬素。例如瑟匆,字符序列S=”abcXYZdef”,要求輸出循環(huán)左移3位后的結(jié)果蒂教,即“XYZdefabc”。是不是很簡單?OK论悴,搞定它嗜闻!

public class Solution {
    public String LeftRotateString(String str,int n) {
        
        if(str.length()<0 || n<0 || n>str.length()) return str;
        
        char[] chars = str.toCharArray();

        for(int i = 0; i<chars.length/2; i++){
            char temp = chars[i];
            chars[i] = chars[chars.length-1-i];
            chars[chars.length-1-i] = temp;
        }
        for(int i = 0; i<(chars.length-n)/2; i++){
            char temp = chars[i];
            chars[i] = chars[chars.length-n-1-i];
            chars[chars.length-n-1-i] = temp;
        }
        
        for(int i = chars.length-n; i<(chars.length-n/2); i++){
            char temp = chars[i];
            chars[i] = chars[chars.length-1-i + chars.length-n];
            chars[chars.length-1-i + chars.length-n] = temp;
        }
        
        return new String(chars);
    }
}

注解:不借助輔助空間的算法病袄,需要兩次翻轉(zhuǎn)纠亚。為了避免混亂,也可以使用前后兩指針交換的算法皂吮。

44. 沤渖担客最近來了一個新員工Fish税手,每天早晨總是會拿著一本英文雜志,寫些句子在本子上需纳。同事Cat對Fish寫的內(nèi)容頗感興趣芦倒,有一天他向Fish借來翻看,但卻讀不懂它的意思不翩。例如兵扬,“student. a am I”。后來才意識到口蝠,這家伙原來把句子單詞的順序翻轉(zhuǎn)了器钟,正確的句子應該是“I am a student.”。Cat對一一的翻轉(zhuǎn)這些單詞順序可不在行妙蔗,你能幫助他么傲霸?

public class Solution {
    public String ReverseSentence(String str) {
        if(str.length()<1 ) return str;

        char[] chars = str.toCharArray();        
        // 先翻轉(zhuǎn)
        for(int i = 0; i<chars.length/2; i++){
            char temp = chars[i];
            chars[i] = chars[chars.length-1-i];
            chars[chars.length-1-i] = temp;
        }

        int end;
        int begin = 0;
        for(int i = 0; i<=chars.length-1; i++){
            if( chars[i]== ' ' || i==chars.length-1){
                end = i - 1;
                if(i==chars.length-1){
                    end++;
                }
                while(begin<end){
                    char temp = chars[begin];
                    chars[begin] = chars[end];
                    chars[end] = temp;
                    begin++;
                    end--;
                }
                begin = i + 1;
            }
        }
        return new String(chars);
    }
}

注解:上一題的一般化

45. LL今天心情特別好,因為他去買了一副撲克牌,發(fā)現(xiàn)里面居然有2個大王,2個小王(一副牌原本是54張_)...他隨機從中抽出了5張牌,想測測自己的手氣,看看能不能抽到順子,如果抽到的話,他決定去買體育彩票,嘿嘿!眉反!“紅心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是順子.....LL不高興了,他想了想,決定大\小 王可以看成任何數(shù)字,并且A看作1,J為11,Q為12,K為13昙啄。上面的5張牌就可以變成“1,2,3,4,5”(大小王分別看作2和4),“So Lucky!”。LL決定去買體育彩票啦寸五。 現(xiàn)在,要求你使用這幅牌模擬上面的過程,然后告訴我們LL的運氣如何梳凛, 如果牌能組成順子就輸出true,否則就輸出false梳杏。為了方便起見,你可以認為大小王是0韧拒。

import java.util.Arrays;

public class Solution {
    public boolean isContinuous(int [] numbers) {
        if(numbers.length <1)
            return false;
        Arrays.sort(numbers);  //先排序
        int zero = 0, i = 0;
        for(; i < numbers.length && numbers[i] == 0; i++){
            zero ++;  //統(tǒng)計0的個數(shù)
        }
        for(i = zero; i < numbers.length - 1; i++){
            if(numbers[i] == numbers[i+1]) //有對子,則返回false
                return false;
        }
    
        if( (numbers[numbers.length -1] - numbers[zero]+1) <=5 )
            return true;
        else
            return false;
    }
}

46. 每年六一兒童節(jié),琶啬客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此叭莫。HF作為诺讣客的資深元老,自然也準備了一些小游戲烁试。其中,有個游戲是這樣的:首先,讓小朋友們圍成一個大圈。然后,他隨機指定一個數(shù)m,讓編號為0的小朋那個小朋友友開始報數(shù)拢肆。每次喊到m-1的要出列唱首歌,然后可以在禮品箱中任意的挑選禮物,并且不再回到圈中,從他的下一個小朋友開始,繼續(xù)0...m-1報數(shù)....這樣下去....直到剩下最后一個小朋友,可以不用表演,并且拿到偶跸欤客名貴的“名偵探柯南”典藏版(名額有限哦!!_)。請你試著想下,哪個小朋友會得到這份禮品呢郭怪?(注:小朋友的編號是從0到n-1)

public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n==0||m==0)return -1;
        int s=0;
        for(int i=2;i<=n;i++)
        {
            s=(s+m)%i;
        }   
       return s ;
    }
}

注解:每一次都看成一個新的排序f[i-1]支示,但是下標是從k=m%n開始的。所以上一次的結(jié)果f[i]等于(f[i-1]+k)%n鄙才。于是有:

遞推公式:f[i]=(f[i-1]+k)%n => f[1]=0颂鸿,f[i]=(f[i-1]+m)%i;

47. 求1+2+3+...+n,要求不能使用乘除法攒庵、for嘴纺、while败晴、if、else栽渴、switch尖坤、case等關鍵字及條件判斷語句(A?B:C)。

public class Solution {
public int Sum_Solution(int n) {
int sum = n;
boolean flag = (n>0)&&((sum +=Sum_Solution(n-1))>0);
return sum;
}
}
注解:利用了邏輯&&的截斷功能闲擦。

48. 寫一個函數(shù)慢味,求兩個整數(shù)之和,要求在函數(shù)體內(nèi)不得使用+墅冷、-纯路、*、/四則運算符號寞忿。

public class Solution {
public int Add(int num1, int num2) {
int num3;
int num4;
do {
num3 = num1 ^ num2;
num4 = (num1 & num2) << 1;
num1 = num3;
num2 = num4;
} while (num4 != 0);
return num1;
}
}
注解:通過位運算

49. 將一個字符串轉(zhuǎn)換成一個整數(shù)(實現(xiàn)Integer.valueOf(string)的功能感昼,但是string不符合數(shù)字要求時返回0),要求不能使用字符串轉(zhuǎn)換整數(shù)的庫函數(shù)罐脊。 數(shù)值為0或者字符串不是一個合法的數(shù)值則返回0定嗓。

public class Solution {
    public int StrToInt(String str)
    {
        if ( str.length() < 1)
            return 0;
        char[] a = str.toCharArray();
        
        boolean fuhao = true;
        int begin = 0;
        
        if (a[0] == '-'){
            fuhao = false;
            begin = 1;
        }
        else if(a[0] == '+'){
            begin = 1;
        }

        int sum = 0;
        for (int i = begin; i < a.length; i++){
            if (a[i] < 48 || a[i] > 57)
                return 0;
            sum = sum * 10 + a[i] - 48;
        }  
        return fuhao ? sum : sum * -1;
    }
}

注解:主要符號的判斷。字符0的ASCII碼是48

50. 在一個長度為n的數(shù)組里的所有數(shù)字都在0到n-1的范圍內(nèi)萍桌。 數(shù)組中某些數(shù)字是重復的宵溅,但不知道有幾個數(shù)字是重復的。也不知道每個數(shù)字重復幾次上炎。請找出數(shù)組中任意一個重復的數(shù)字恃逻。 例如,如果輸入長度為7的數(shù)組{2,3,1,0,2,5,3}藕施,那么對應的輸出是第一個重復的數(shù)字2寇损。

public boolean duplicate(int numbers[],int length,int [] duplication) {
    if(length <1 ) return false; 
    
    for(int i=0;i<length;i++){
        while(numbers[i]!=i){
            if(numbers[i]==numbers[numbers[i]]){
                duplication[0]=numbers[i];
                return true;
            }
            int temp=numbers[i];
            numbers[i]=numbers[temp];
            numbers[temp]=temp;
        }
    }
    return false;
}

注解:利用數(shù)組值與下標的關系

51. 給定一個數(shù)組A[0,1,...,n-1],請構(gòu)建一個數(shù)組B[0,1,...,n-1],其中B中的元素B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1]。不能使用除法裳食。

import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        if(A.length<1) return A;
        
        int[] B = new int[A.length];
        
        B[0] = 1;
        for(int i=1; i< A.length; i++){
            B[i] = B[i-1] * A[i-1];
        }
        

        int temp = 1;
        for(int i=A.length-2; i>=0; i--){ 
            temp *= A[i+1];
            B[i] = B[i] * temp;
        }
        
        return B;
    }
}

注解:利用前后兩次乘矛市,逃離中間乘。

52. 請實現(xiàn)一個函數(shù)用來匹配包括'.'和''的正則表達式诲祸。模式中的字符'.'表示任意一個字符浊吏,而''表示它前面的字符可以出現(xiàn)任意次(包含0次)。 在本題中救氯,匹配是指字符串的所有字符匹配整個模式找田。例如,字符串"aaa"與模式"a.a"和"abaca"匹配着憨,但是與"aa.a"和"ab*a"均不匹配

public class Solution {
    public boolean match(char[] str, char[] pattern) {
        return matchTwo(str, 0, str.length, pattern, 0, pattern.length);
    }

    private boolean matchTwo(char[] str, int i, int length1, char[] pattern, int j, int length2) {
        if (i == length1 && j == length2) {
            return true;
        }
        if (i == length1 && j != length2) {
            while (j != length2) {
                if (pattern[j] != '*' && (j + 1 >= length2 || pattern[j + 1] != '*')) {
                    return false;
                }
                j++;
            }
            return true;
        }
        if (i != length1 && j == length2) {
            return false;
        }
        if (j + 1 == length2) {
            if (str[i] == pattern[j] || pattern[j] == '.')
                return matchTwo(str, i + 1, length1, pattern, j + 1, length2);
            else {
                return false;
            }
        }
        if ((str[i] == pattern[j] || pattern[j] == '.') && pattern[j + 1] != '*')
            return matchTwo(str, i + 1, length1, pattern, j + 1, length2);
        if ((str[i] == pattern[j] || pattern[j] == '.') && pattern[j + 1] == '*')
            return matchTwo(str, i, length1, pattern, j + 2, length2)
                    || matchTwo(str, i + 1, length1, pattern, j, length2);
        if (pattern[j + 1] == '*')
            return matchTwo(str, i, length1, pattern, j + 2, length2);
        return false;
    }
}

注解:不是我說墩衙,讓你寫一個這種函數(shù)還真不好寫!!F岣摹植袍!

53. 請實現(xiàn)一個函數(shù)用來判斷字符串是否表示數(shù)值(包括整數(shù)和小數(shù))。例如籽懦,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示數(shù)值于个。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

public class Solution {
    public boolean isNumeric(char[] str) {
        String s=String.valueOf(str);
        return s.matches("[+-]?[0-9]*(\\.[0-9]*)?([eE][+-]?[0-9]+)?");  
    }
}

54. 請實現(xiàn)一個函數(shù)用來找出字符流中第一個只出現(xiàn)一次的字符暮顺。例如厅篓,當從字符流中只讀出前兩個字符"go"時,第一個只出現(xiàn)一次的字符是"g"捶码。當從該字符流中讀出前六個字符“google"時羽氮,第一個只出現(xiàn)一次的字符是"l"。如果當前字符流沒有存在出現(xiàn)一次的字符惫恼,返回#字符档押。

import java.util.HashMap;
import java.util.ArrayList;

public class Solution {
    HashMap<Character, Integer> map=new HashMap<>();
    ArrayList<Character> list=new ArrayList<Character>();

    public void Insert(char ch)
    {
        if(map.containsKey(ch)){
            map.put(ch,map.get(ch)+1);
        }else{
            map.put(ch,1);
        }
          
        list.add(ch);
    }
      
    public char FirstAppearingOnce()
    {   
        char c='#';
        for(char key : list){
            if(map.get(key)==1){
                c=key;
                break;
            }
        }
          
        return c;
    }
}

55. 給一個鏈表,若其中包含環(huán)祈纯,請找出該鏈表的環(huán)的入口結(jié)點令宿,否則,輸出null腕窥。

public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead){
        if (pHead == null || pHead.next == null || pHead.next.next == null)
              return null;
          ListNode slow = pHead.next;
          ListNode quick = pHead.next.next;
          
          // 1 找到是否有環(huán)粒没,兩個指針
          while (slow != quick) {
              if (slow.next != null && quick.next.next != null) {
                  slow = slow.next;
                  quick = quick.next.next;
              } else{
                  return null;
              }
          }
        // 2 確定環(huán)的大小k      但是其大小正好是 slow走的距離。 // 3 先走k步簇爆,相遇點為入口癞松。
          quick = pHead;
          while (quick != slow) {
              quick = quick.next;
              slow = slow.next;
          }
          return slow; 
      }
}

56. 在一個排序的鏈表中,存在重復的結(jié)點入蛆,請刪除該鏈表中重復的結(jié)點响蓉,重復的結(jié)點不保留,返回鏈表頭指針哨毁。 例如枫甲,鏈表1->2->3->3->4->4->5 處理后為 1->2->5

public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
        ListNode result;
        ListNode temp = pHead;
        ListNode index = new ListNode(1);
        index.next = pHead;
        result = index;
        while (temp != null) {
            if (temp.next != null && temp.next.val == temp.val) {
                while (temp.next != null && temp.next.val == temp.val) {
                    temp = temp.next;
                }
                temp = temp.next;
                index.next = temp;
            } else {
                index = index.next;
                temp = temp.next;
            }
        }
        return result.next;
    }
}

57. 給定一個二叉樹和其中的一個結(jié)點,請找出中序遍歷順序的下一個結(jié)點并且返回挑庶。注意言秸,樹中的結(jié)點不僅包含左右子結(jié)點软能,同時包含指向父結(jié)點的指針迎捺。

public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode==null) return null;
        // 右節(jié)點不為空
        if(pNode.right!=null)
        {
        // 找到右節(jié)點的最左節(jié)點
            pNode=pNode.right;
            while(pNode.left!=null)
            {
                pNode=pNode.left;
               
            }
            return pNode;
        }
        // 右節(jié)點為空,找到其為父節(jié)點的左節(jié)點的那個最近的父節(jié)點查排。
        while(pNode.next!=null)
        {
            if(pNode.next.left==pNode) return pNode.next;
            pNode=pNode.next;
        }
        return null;
    }
    
}

58. 請實現(xiàn)一個函數(shù)凳枝,用來判斷一顆二叉樹是不是對稱的。注意,如果一個二叉樹同此二叉樹的鏡像是同樣的岖瑰,定義其為對稱的叛买。

public class Solution {
    public boolean isSymmetrical(TreeNode pRoot) {
        if(pRoot==null) return true;
        return isSymmetrical(pRoot.left,pRoot.right);
    }

    public boolean isSymmetrical(TreeNode left, TreeNode right) {
        if (left == null && right == null)
            return true;
        if (left == null || right == null)
            return false;
        if (left.val == right.val)
            // 左左相比,右右相比蹋订,這是最核心的思想了率挣。
            return isSymmetrical(left.left, right.right) && isSymmetrical(left.right, right.left);
        return false;
    }
}

59. 請實現(xiàn)一個函數(shù)按照之字形打印二叉樹,即第一行按照從左到右的順序打印露戒,第二層按照從右至左的順序打印椒功,第三行按照從左到右的順序打印,其他行以此類推智什。

import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
        if(pRoot==null){
            return res;
        }
        ArrayList<Integer> list;
        Queue<TreeNode> queue=new LinkedList<TreeNode>();
        int rows=1;
        queue.add(pRoot);
        while(!queue.isEmpty()){
            list=new ArrayList<>();
            int size=queue.size();
            for(int i=0;i<size;i++){
                TreeNode t=queue.poll();
                // 分層考慮
                if(rows%2==0){
                    list.add(0,t.val); // 每次都插入到最前面
                }else{
                    list.add(t.val);
                }
                if(t.left!=null){
                    queue.offer(t.left);
                }
                if(t.right!=null){
                    queue.offer(t.right);
                }
            }
            res.add(list);
            rows++;
        }
        return res;
    }

}

60. 從上到下按層打印二叉樹动漾,同一層結(jié)點從左至右輸出。每一層輸出一行荠锭。

public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer> > result = new ArrayList<>();
        if(pRoot == null) {
            return result;
        }
        ArrayList<TreeNode> nodes = new ArrayList<>();
        nodes.add(pRoot);
        Print(result, nodes);
        return result;
    }
     
    public void Print(ArrayList<ArrayList<Integer> > result, ArrayList<TreeNode> nodes) {
        if(!nodes.isEmpty()) {
            ArrayList<Integer> temp = new ArrayList<>();
            ArrayList<TreeNode> next = new ArrayList<>();
            for(TreeNode t : nodes) {
                temp.add(t.val);
                if(t.left != null) {
                    next.add(t.left);
                }
                if(t.right != null) {
                    next.add(t.right);
                }
            }
            result.add(temp);
            Print(result, next);
        }
    }
}

注解:借助隊列會更好做吧

62. 給定一棵二叉搜索樹旱眯,請找出其中的第k小的結(jié)點。例如证九, (5删豺,3,7愧怜,2吼鳞,4,6叫搁,8) 中赔桌,按結(jié)點數(shù)值大小順序第三小結(jié)點的值為4。

public class Solution {
    int index = 0; 
    TreeNode KthNode(TreeNode root, int k) {
        if (root != null) { // 中序遍歷尋找第k個
            TreeNode node = KthNode(root.left, k);
            if (node != null)
                return node;
            index++;
            if (index == k)
                return root;
            node = KthNode(root.right, k);
            if (node != null)
                return node;
        }
        return null;
    }
}

63. 如何得到一個數(shù)據(jù)流中的中位數(shù)渴逻?如果從數(shù)據(jù)流中讀出奇數(shù)個數(shù)值疾党,那么中位數(shù)就是所有數(shù)值排序之后位于中間的數(shù)值。如果從數(shù)據(jù)流中讀出偶數(shù)個數(shù)值惨奕,那么中位數(shù)就是所有數(shù)值排序之后中間兩個數(shù)的平均值雪位。我們使用Insert()方法讀取數(shù)據(jù)流,使用GetMedian()方法獲取當前讀取數(shù)據(jù)的中位數(shù)梨撞。

import java.util.ArrayList;
import java.util.Collections;

public class Solution {

    ArrayList<Integer> al = new ArrayList<Integer>();

    public void Insert(Integer num) {
        al.add(num);
        Collections.sort(al);
    }

    public Double GetMedian() {
        int mid = al.size() / 2;
        if ((al.size() & 1) == 0) {
            Integer n1 = al.get(mid);
            Integer n2 = al.get(mid - 1);
            double s = (Double.valueOf(n1 + "") + Double.valueOf(n2 + "")) / 2;
            return s;
        } else {
            double s = Double.valueOf(al.get(mid) + "");
            return s;
        }
    }
}

65. 請設計一個函數(shù)雹洗,用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中的任意一個格子開始卧波,每一步可以在矩陣中向左时肿,向右,向上港粱,向下移動一個格子螃成。如果一條路徑經(jīng)過了矩陣中的某一個格子旦签,則之后不能再次進入這個格子。 例如 a b c e s f c s a d e e 這樣的3 X 4 矩陣中包含一條字符串"bcced"的路徑寸宏,但是矩陣中不包含"abcb"路徑宁炫,因為字符串的第一個字符b占據(jù)了矩陣中的第一行第二個格子之后,路徑不能再次進入該格子氮凝。

public class Solution {
    // 65
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        int []flag=new int[matrix.length];
    // 可選開始值
        for(int i=0;i<rows;i++) {
            for(int j=0;j<cols;j++) {
               if(hasPath(matrix,rows,cols,i,j,0,str,flag))
                  return  true;
            }
        }
      return false;
    }
    public boolean hasPath(char[]matrix,int rows,int cols,int i,int j,int k,char[]str,int[]flag)
    {
        int index=i*cols+j;
        if(i<0||i>=rows||j<0||j>=cols||flag[index]==1||matrix[index]!=str[k])return false;
        if(k==str.length-1) return true;
        
        flag[index]=1;
        // 核心遍歷
        if(hasPath(matrix,rows,cols,i+1,j,k+1,str,flag)||hasPath(matrix,rows,cols,i-1,j,k+1,str,flag)||hasPath(matrix,rows,cols,i,j+1,k+1,str,flag)||hasPath(matrix,rows,cols,i,j-1,k+1,str,flag))
          return  true;
        
        flag[index]=0;
        return false;
    }
}

66. 地上有一個m行和n列的方格羔巢。一個機器人從坐標0,0的格子開始移動,每一次只能向左罩阵,右朵纷,上,下四個方向移動一格永脓,但是不能進入行坐標和列坐標的數(shù)位之和大于k的格子袍辞。 例如,當k為18時常摧,機器人能夠進入方格(35,37)搅吁,因為3+5+3+7 = 18。但是落午,它不能進入方格(35,38)谎懦,因為3+5+3+8 = 19。請問該機器人能夠達到多少個格子溃斋?

public class Solution {
 public int movingCount(int threshold, int rows, int cols)
        {
            boolean[] visited=new boolean[rows*cols];
            // 與上一題相比界拦,課題初始值只有一個
            return movingCountCore(threshold, rows, cols, 0,0,visited);
        }
        private int movingCountCore(int threshold, int rows, int cols,
                int row,int col,boolean[] visited) {
            if(row<0||row>=rows||col<0||col>=cols) return 0;
            int i=row*cols+col;
            if(visited[i]||!checkSum(threshold,row,col)) return 0;
            visited[i]=true;
            // 這里保持統(tǒng)一,而在返回推薦控制越界梗劫。
            return 1+movingCountCore(threshold, rows, cols,row,col+1,visited)
                    +movingCountCore(threshold, rows, cols,row,col-1,visited)
                    +movingCountCore(threshold, rows, cols,row+1,col,visited)
                    +movingCountCore(threshold, rows, cols,row-1,col,visited);
        }
        //指定規(guī)則
        private boolean checkSum(int threshold, int row, int col) {
            int sum=0;
            while(row!=0){
                sum+=row%10;
                row=row/10;
            }
            while(col!=0){
                sum+=col%10;
                col=col/10;
            }
            if(sum>threshold) return false;
            return true;
        }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末享甸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子梳侨,更是在濱河造成了極大的恐慌蛉威,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件走哺,死亡現(xiàn)場離奇詭異蚯嫌,居然都是意外死亡,警方通過查閱死者的電腦和手機丙躏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門择示,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人晒旅,你說我怎么就攤上這事栅盲。” “怎么了敢朱?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵剪菱,是天一觀的道長摩瞎。 經(jīng)常有香客問我拴签,道長孝常,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任蚓哩,我火速辦了婚禮构灸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘岸梨。我一直安慰自己喜颁,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布曹阔。 她就那樣靜靜地躺著半开,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赃份。 梳的紋絲不亂的頭發(fā)上寂拆,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音抓韩,去河邊找鬼纠永。 笑死,一個胖子當著我的面吹牛谒拴,可吹牛的內(nèi)容都是我干的尝江。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼英上,長吁一口氣:“原來是場噩夢啊……” “哼炭序!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起苍日,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤少态,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后易遣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彼妻,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年豆茫,在試婚紗的時候發(fā)現(xiàn)自己被綠了侨歉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡揩魂,死狀恐怖幽邓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情火脉,我是刑警寧澤牵舵,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布柒啤,位于F島的核電站,受9級特大地震影響畸颅,放射性物質(zhì)發(fā)生泄漏担巩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一没炒、第九天 我趴在偏房一處隱蔽的房頂上張望涛癌。 院中可真熱鬧,春花似錦送火、人聲如沸拳话。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弃衍。三九已至,卻和暖如春坚俗,著一層夾襖步出監(jiān)牢的瞬間镜盯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工坦冠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留形耗,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓辙浑,卻偏偏與公主長得像激涤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子判呕,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 一些概念 數(shù)據(jù)結(jié)構(gòu)就是研究數(shù)據(jù)的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)以及它們之間相互關系倦踢,并對這種結(jié)構(gòu)定義相應的運算,而且確保經(jīng)過這...
    Winterfell_Z閱讀 5,660評論 0 13
  • 本文是我自己在秋招復習時的讀書筆記侠草,整理的知識點辱挥,也是為了防止忘記,尊重勞動成果边涕,轉(zhuǎn)載注明出處哦晤碘!如果你也喜歡,那...
    波波波先森閱讀 4,080評論 0 23
  • 前言 2. 實現(xiàn) Singleton 3. 數(shù)組中重復的數(shù)字 4. 二維數(shù)組中的查找 5. 替換空格 6. 從尾到...
    Observer_____閱讀 2,919評論 0 1
  • 經(jīng)過一輪又一輪的“水戰(zhàn)”,飲用水市場形成了三足鼎立的格局:娃哈哈式撼、樂百氏、農(nóng)夫山泉著隆,就連實力強大的康師傅也曾一度被...
    葡萄大課堂閱讀 695評論 0 0
  • 回家又看不到我家孩子了呀癣,我爸還怪我六親不認來著弦赖,我只是想做好一件事情,善始善終~不輕易說開始腾节,不輕易說放棄~堅持也...
    貝妮_56d5閱讀 125評論 0 0