劍指Offer題目詳解(CPP、JAVA)

2019.10.11更新

最近開始學習c++,在本文中增加c++的解法,並更新一部分題目的解法。

前言(2018.6.1)

雖然已經度過了艱辛的找實習的日子,到了公司實習。但依然非常懷念那段準備面試、坐在實驗室裏刷劍指offer的日子。

1.二維數組的查找

在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。

解題思路: 從右上角或者左下角進行查找,以減少判斷次數。
JAVA求解

public class Solution {
     public boolean Find(int target, int [][] array) {
         int rows = array.length;
         int cols = array[0].length;
         for(int i = rows-1;i>=0;i--){
             for(int j = 0;j<cols;j++){
                 if(target == array[i][j]) return true;
             }
         }
         return false;
    }
}

CPP求解

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int rows = array.size();
        int cols = array[0].size();
        for(int i = rows-1;i>=0;i--){
            for(int j = 0;j<cols;j++){
                if(target == array[i][j]){
                    return true;
                }
            }
        }
        return false;
    }
};

2.替換空格

請實現一個函數,將一個字符串中的空格替換成“%20”。例如,當字符串爲We Are Happy.則經過替換之後的字符串爲We%20Are%20Happy。

解題思路:使用StringBuffer或StringBuilder類,進行替換。
JAVA求解

    public String replaceSpace(StringBuffer str) {
        StringBuffer newStr = new StringBuffer();
        if (str == null ){
            return  null;
        }
        int len = str.length();
        for (int i=0; i <len; i++){
            if (String.valueOf(str.charAt(i)).equals(" ")){
                newStr.append("%20");
            }else {
                newStr.append(str.charAt(i));
            }
        }
        return String.valueOf(newStr);
    }

CPP求解

class Solution {
public:
	void replaceSpace(char *str,int length) {
        int blank = 0;
        for(int i = 0; i < length; i++){
            if(str[i] == ' '){
                blank++;
            }
        }
        int newLen = length+ 2*blank;
        for(int i = length-1;i>=0;i--){
            if(str[i] == ' '){
                str[--newLen] = '0';
                str[--newLen] = '2';
                str[--newLen] = '%';
            }else{
                str[--newLen] = str[i];
            }
        }
	}
};

3.從尾到頭打印鏈表

輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList。

解題思路:利用棧來存放遍歷得到的鏈表的值,這樣會浪費O(n)的空間。可以先反轉鏈表,再做輸出,這樣時間複雜度爲O(n),空間複雜度爲O(1)。
Java求解

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        //反轉鏈表後輸出,O(n)
        ArrayList<Integer> res = new ArrayList<>();
        if(listNode==null) return res;
        if(listNode.next==null){
            res.add(listNode.next.val);
            return res;
        }
        ListNode newHead = new ListNode(-1);
        while(listNode!=null){
            ListNode temp = listNode.next;
            listNode.next = newHead.next;
            newHead.next = listNode;
            listNode = temp;
        }
        newHead = newHead.next;
        while(newHead!=null){
            res.add(newHead.val);
            newHead = newHead.next;
        }
        return res;
    }
}

CPP求解

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> res;
        if(head==NULL) return res;
        if(head->next==NULL){
            res.push_back(head->val);
            return res;
        }
        ListNode* newHead =new ListNode(-1);
        while(head!=NULL){
            ListNode* temp = head->next;
            head->next = newHead->next;
            newHead->next = head;
            head = temp;
        }
        newHead = newHead->next;
        while(newHead!=NULL){
            res.push_back(newHead->val);
            newHead = newHead->next;
        }
        return res;
    }
};

}


## 4.重建二叉樹

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。

解題思路:使用遞歸的方法,在中序遍歷的結果中找到根結點,該節點左邊是左子樹,右邊是又子樹。不斷遞歸,求解。

import java.util.Arrays;

public class Solution {
public TreeNode reConstructBinaryTree(int [] pre, int [] in) {

    if(pre.length == 0 ||in.length ==0){
        return  null;
    }
    if (pre.length!= in.length){
        return null;
    }
    TreeNode res = new TreeNode(pre[0]);
    for (int i = 0;i<pre.length;i++){
        if (pre[0] == in[i]){
            res.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
            res.right = reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
        }
    }
    return res;
}

}


## 5.用兩個棧實現隊列

用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素爲int類型。

解題思路:一個棧壓入元素,而另一個棧作爲緩衝,將棧1的元素出棧後壓入棧2中。

public void push(int node) {
stack1.push(node);
}

public int pop() throws Exception {
if (stack1.isEmpty() && stack2.isEmpty()) {
throw new Exception(“stack is empty”);
}

if (stack2.isEmpty()) {
    while(!stack1.isEmpty()) {
        stack2.push(stack1.pop());
    }
}
return stack2.pop();

}


## 6.旋轉數組的最小數字

把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。

解題思路:這個很簡單,找出第一個遞減的位置即可。
JAVA求解
```java
import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array.length <=0) return 0;
        for(int i = 0;i < array.length-1;i++){
            if(array[i]>array[i+1]){
                return array[i+1];
            }
        }
        return 0;
    }
}

CPP求解

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size()==0) return 0;
        for(int i =0;i < rotateArray.size()-1;i++){
            if(rotateArray[i]>rotateArray[i+1]){
                return rotateArray[i+1];
            }
        }
        return 0;
    }
};

7.斐波那契數列

大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項。n<=39

解題思路:用非遞歸的形式寫斐波那契數列,效率更高

    public int Fibonacci(int n) {
        int res = 0;
        int lost2 = 0;
        int lost1 = 1;
        if (n==0){
            return  lost2;
        }
        if(n==1){
            return  lost1;
        }
        for (int i = 2;i <=n; i++){
            res = lost1+lost2;
            lost2 = lost1;
            lost1 = res;
        }
        return res;
    }

8.跳臺階

一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。

解題思路:這個題目其實就是斐波那契數列的變形。

    public int JumpFloor(int target) {
        int step1 = 1;
        int step2 = 2;
        if (target==0){
            return 0;
        }
        if (target==1){
            return 1;
        }
        if (target==2){
            return 2;
        }
        int res = 0;
        for (int i=3;i<=target;i++){
            res = step1+step2;
            step1 = step2;
            step2 = res;
        }
        return res;
    }

9.變態跳青蛙

一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

解題思路:Fib(n)=Fib(n-1)+Fib(n-2)+Fib(n-3)+…+Fib(n-n)=Fib(0)+Fib(1)+Fib(2)+…+Fib(n-1)
Fib(n) = 2Fib(n-1)

10.矩形覆蓋

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

解題思路:填充一個的時候,問題規模變成n-1,填充2個的時候,問題規模變成n-2

    public int RectCover(int target) {
        if(target == 0){
            return  0;
        }

        if (target == 1){
            return  1;
        }

        if (target == 2){
            return 2;
        }

        return  RectCover(target-1)+RectCover(target-2);

    }

11.二進制中1的個數

輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。
解題思路:移位計算即可。

    public int NumberOf1(int n) {
        int count = 0;
        int flag = 1;
        while(flag != 0){
            if ((flag&n) != 0){
                count++;
            }
            flag = flag <<1;
        }
        return count;

    }

12.數值的整數次方

給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。
解題思路:考慮輸入值的多種情況。

public class Solution {
public double Power(double base, int exponent) {
    double res = 0;
    if (equal(base,0)) {
        return 0;
    }
    if (exponent == 0) {
        return 1.0;
    }
    if (exponent > 0) {
        res = mutiply(base,exponent);
    }else {
        res = mutiply(1/base,-exponent);
    }
    return res;
}

public double mutiply(double base, int e) {
    double sum = 1;
    for (int i = 0; i < e; i++) {
        sum = sum * base;
    }
    return sum;
}

public boolean equal(double a, double b) {
    if (a - b < 0.000001 && a - b > -0.000001) {
        return true;
    }
    return false;
}
}

13.調整數組順序使奇數位於偶數前面

輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,所有的偶數位於位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。

解題思路:通過輔助隊列解題。

import java.util.LinkedList;
import java.util.Queue;
public class Solution {
    public void reOrderArray(int [] array) {
        if(array==null || array.length==0){
            return;
        }
        Queue<Integer> qe = new LinkedList<Integer>();
        for (int i= 0;i< array.length;i++){
            if(array[i]%2==1){
                qe.offer(array[i]);
            }
        }
        for (int j =0;j< array.length;j++){
            if (array[j]%2==0) {
                qe.offer(array[j]);
            }
        }
        for(int k=0;k<array.length;k++){
            array[k]= qe.poll();
        }
    }
}

14.鏈表中倒數第k個節點

輸入一個鏈表,輸出該鏈表中倒數第k個結點。

解題思路:快慢指針,快指針先走k-1

    public ListNode FindKthToTail(ListNode head,int k) {
        if (head==null||k<=0){
            return  null;
        }
        ListNode fast = head;
        ListNode slow = head;
        for (int i = 1;i<k;i++){
            if (fast.next!=null){
                fast = fast.next;
            }else {
                return null;
            }
        }
        while (fast.next!=null){
            fast = fast.next;
            slow = slow.next;

        }
        return  slow;
    }

15.反轉鏈表

輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。

解題思路:遍歷鏈表,採用頭插法。
JAVA求解

public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head==null || head.next==null) return head;
        ListNode newHead = new ListNode(-1);
        while(head!=null){
            ListNode temp = head.next;
            head.next = newHead.next;
            newHead.next = head;
            head = temp;
        }
        return newHead.next;
    }
}

CPP求解

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==NULL ||pHead->next==NULL) return pHead;
        ListNode* newHead = new ListNode(-1);
        while(pHead!=NULL){
            ListNode* temp = pHead->next;
            pHead->next = newHead->next;
            newHead->next = pHead;
            pHead = temp;
        }
        return newHead->next;
    }
};

16.合併兩個排序鏈表

輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。

解題思路:遞歸求解

    public ListNode Merge(ListNode list1,ListNode list2) {
        if (list1 == null){
            return list2;
        }
        if (list2 == null){
            return list1;
        }
        ListNode res = null;
        if (list1.val <= list2.val){
            res = list1;
            res.next = Merge(list1.next,list2);
        }else {
            res = list2;
            res.next = Merge(list1,list2.next);
        }

        return res;

    }

17.樹的子結構

輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)

解題思路:遞歸判斷

    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if (root2 == null || root1 == null){
            return false;
        }

        if (root1 == root2){
            return reallyHasSubTree(root1,root2);
        }else {
            return reallyHasSubTree(root1.left,root2)||reallyHasSubTree(root1.right,root2);
        }

    }


    public boolean reallyHasSubTree(TreeNode root1,TreeNode root2){
        if (root1==null&&root2!=null){
            return false;
        }
        if (root2 ==null){
            return true;
        }

        if (root1.val != root2.val){
            return false;
        }
        return reallyHasSubTree(root1.left,root2.left)&&reallyHasSubTree(root1.right,root2.right);

    }

18.二叉樹的鏡像

操作給定的二叉樹,將其變換爲源二叉樹的鏡像。
解題思路:對於樹的問題,基本都採用遞歸求解,比較方便。

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

19.順時針打印矩陣

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

解題思路:

21.包含min函數的棧

定義棧的數據結構,請在該類型中實現一個能夠得到棧中所含最小元素的min函數(時間複雜度應爲O(1))。

解題思路:定義2個棧,其中一個記錄min元素

        Stack<Integer> stackData = new Stack<>();
        Stack<Integer> stackMin = new Stack<>();
        public void push(int node) {
                stackData.push(node);
                if(stackMin.isEmpty()){
                        stackMin.push(node);
                }else {
                        if(stackMin.peek()>node){
                                stackMin.push(node);
                        }
                }
        }

        public void pop() {
                int temp = stackData.pop();
                if(stackMin.peek()==temp){
                        stackMin.pop();
                }
        }

        public int top() {
                return stackData.peek();
        }

        public int min() {
                return stackMin.peek();
        }

22.棧的壓入、彈出序列

輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否可能爲該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)

解題思路:模擬棧的壓入過程,不斷和pop序列進行比較。

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

23.從上往下打印二叉樹

從上往下打印出二叉樹的每個節點,同層節點從左至右打印。

解題思路:實則爲二叉樹的層次遍歷,用一個隊列依次記錄順序。

        public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
                ArrayList<Integer> arr = new ArrayList<>();
                if(root == null) return arr;
                LinkedList<TreeNode> queue = new LinkedList<>();
                queue.add(root);
                while(!queue.isEmpty()){
                        TreeNode temp = queue.pop();
                        arr.add(temp.val);
                        if(temp.left != null){
                                queue.add(temp.left);
                        }

                        if(temp.right != null){
                                queue.add(temp.right);
                        }
                }
                return arr;
        }

24.二叉搜索樹的後序遍歷序列

輸入一個整數數組,判斷該數組是不是某二叉搜索樹的後序遍歷的結果。如果是則輸出Yes,否則輸出No。假設輸入的數組的任意兩個數字都互不相同。

解題思路:後序遍歷最後一個節點是樹的根結點,以根結點去切分,類似於遞歸形式的後序遍歷,結合搜索樹的特點,去判斷序列是不是我們想要的序列。

        public boolean VerifySquenceOfBST(int [] sequence) {
                if(sequence.length == 0) return false;
                if(sequence.length == 1) return true;
                return judge(sequence,0,sequence.length -1);
        }

        public boolean judge(int [] sequence, int start, int end){
                if(start>=end) return true;
                int i = start;
                while(i < end && sequence[i] < sequence[end])
                        i++;
                for(int j = i;j<end;j++){
                        if(sequence[j] < sequence[end]) return false;
                }
                return judge(sequence,start,i-1)&&judge(sequence,i,end-1);
        }

25.二叉樹中和爲某一值的路徑

輸入一顆二叉樹的跟節點和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑。路徑定義爲從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(注意: 在返回值的list中,數組長度大的數組靠前)

解題思路:用先序遍歷來遍歷二叉樹,用target-root.val不斷更新target。

         ArrayList<ArrayList<Integer>> res = new ArrayList<>();
         ArrayList<Integer> temp = new ArrayList<>();
        public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
                if(root==null) return res;
                target -= root.val;
                temp.add(root.val);
                if(target==0 && root.left==null && root.right==null){
                        res.add(new ArrayList<Integer>(temp));
                }else {
                        FindPath(root.left,target);
                        FindPath(root.right,target);
                }
                temp.remove(temp.size()-1);
                return res;
        }

27.二叉搜索樹與雙向鏈表

輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。
解題思路:

28.字符串的排列

輸入一個字符串,按字典序打印出該字符串中字符的所有排列。例如輸入字符串abc,則打印出由字符a,b,c所能排列出來的所有字符串abc,acb,bac,bca,cab和cba。
解題思路:

29.數組中出現次數超過一半的數字

數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度爲9的數組{1,2,3,2,2,2,5,4,2}。由於數字2在數組中出現了5次,超過數組長度的一半,因此輸出2。如果不存在則輸出0。
解題思路:先找出出現次數最多的數字,再判斷該數字出現次數是否超過一半

public int MoreThanHalfNum_Solution(int [] array) {
        int res = array[0], count = 1;
        for(int i=1; i<array.length; i++){
            if(array[i] == res)
                count++;
            else{
                count--;
            }
            if(count == 0){
                res = array[i];
                count = 1;
            }
        }
        count = 0;
        for(int i=0; i<array.length; i++){
            if(array[i] == res)
                count++;
        }
        return count > array.length/2 ? res : 0;
    }

30.最小的k個數

輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。
解題思路:利用最大堆,每次和堆頂元素比較,最後剩下的就是最小的k個數。

        public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
                ArrayList<Integer> res = new ArrayList<>();
                if(input==null || k==0 ||k >input.length) return res;
                PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
                                @Override
                                public int compare(Integer o1, Integer o2) {
                                        return o2 - o1;
                                }
                        });
                for(int i =0; i<input.length;i++){
                        if(maxHeap.size()!=k){
                                maxHeap.offer(input[i]);
                        }else {
                                if(maxHeap.peek()>input[i]){
                                        maxHeap.poll();
                                        maxHeap.offer(input[i]);
                                }
                        }
                }
                for(Integer i: maxHeap){
                        res.add(i);
                }
                return res;

        }

31.連續子數組的和

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

解題思路:對於一個數組中的一個數x,若是x的左邊的數加起來非負,那麼加上x能使得值變大,這樣我們認爲x之前的數的和對整體和是有貢獻的。如果前幾項加起來是負數,則認爲有害於總和。
我們用cur記錄當前值, 用max記錄最大值,如果cur<0,則捨棄之前的數,讓cur等於當前的數字,否則,cur = cur+當前的數字。若cur和大於max更新max。

        public int FindGreatestSumOfSubArray(int[] array) {
                if(array.length < 1) return -1;
                int cur = array[0];
                int max = array[0];
                for(int i = 1;i<array.length;i++){
                        cur = cur > 0 ? cur +array[i] : array[i];
                        if(cur > max) max = cur;
                }
                return max;
        }

32.整數中1出現的次數

求出1到13的整數中1出現的次數,並算出1001300的整數中1出現的次數?爲此他特別數了一下113中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。

解題思路:把數字變成字符串,遍歷

    public int NumberOf1Between1AndN_Solution(int n) {
        int res = 0;
        StringBuffer s = new StringBuffer();
        for(int i = 1; i<=n; i++){
            s.append(i);
        }
        String str = s.toString();
        for(int i=0; i<str.length(); i++){
            if(str.charAt(i) == '1')
                res++;
        }
        return res;
    }

33.把數組排成最小的數

輸入一個正整數數組,把數組裏所有數字拼接起來排成一個數,打印能拼接出的所有數字中最小的一個。例如輸入數組{3,32,321},則打印出這三個數字能排成的最小數字爲321323。

解題思路:把數字轉換爲字符串,通過比較大小進行排序,然後合併輸出。

        public String PrintMinNumber(int [] numbers) {
                if(numbers.length <= 0) return "";
                if(numbers.length == 1) return String.valueOf(numbers[0]);
                StringBuffer res = new StringBuffer();
                String [] strArr = new String[numbers.length];
                for(int i =0;i<numbers.length;i++){
                        strArr[i] = String.valueOf(numbers[i]);
                }
                Arrays.sort(strArr, new Comparator<String>() {
                        public int compare(String o1, String o2) {
                                String s1 = o1 + o2;
                                String s2 = o2 + o1;
                                return s1.compareTo(s2);
                        }
                });
                for(int i = 0; i<numbers.length;i++){
                        res.append(strArr[i]);
                }
                return res.toString();
        }

34.醜數

把只包含質因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因爲它包含質因子7。 習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。

public int GetUglyNumber_Solution(int index) {
        if(index <= 0)
            return 0;
        if(index == 1)
            return 1;
        int t2 = 0, t3 = 0, t5 = 0;
        int [] res = new int[index];
        res[0] = 1;
        for(int i = 1; i<index; i++){
            res[i] = Math.min(res[t2]*2, Math.min(res[t3]*3, res[t5]*5));
            if(res[i] == res[t2]*2) t2++;
            if(res[i] == res[t3]*3) t3++;
            if(res[i] == res[t5]*5) t5++;
        }
        return res[index-1];
    }

35.第一個只出現一次的字符

在一個字符串(0<=字符串長度<=10000,全部由字母組成)中找到第一個只出現一次的字符,並返回它的位置, 如果沒有則返回 -1(需要區分大小寫)
解題思路:利用hashmap映射,遍歷map

public int FirstNotRepeatingChar(String str) {
        int len = str.length();
        if(len == 0)
            return -1;
        HashMap<Character, Integer> map = new HashMap<>();
        for(int i = 0; i < len; i++){
            if(map.containsKey(str.charAt(i))){
                int value = map.get(str.charAt(i));
                map.put(str.charAt(i), value+1);
            }else{
                map.put(str.charAt(i), 1);
            }
        }
        for(int i = 0; i < len; i++){
            if(map.get(str.charAt(i)) == 1)
                return i;
        }
        return -1;
    }

36.數組中的逆序對

在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007
解題思路:用歸併排序的思想,在排序的過程中計算逆序對

    public int InversePairs(int [] array) {
        int len = array.length;
        if(array== null || len <= 0){
            return 0;
        }
        return mergeSort(array, 0, len-1);
    }
    public int mergeSort(int [] array, int start, int end){
        if(start == end)
            return 0;
        int mid = (start + end) / 2;
        int left_count = mergeSort(array, start, mid);
        int right_count = mergeSort(array, mid + 1, end);
        int i = mid, j = end;
        int [] copy = new int[end - start + 1];
        int copy_index = end - start;
        int count = 0;
        while(i >= start && j >= mid + 1){
            if(array[i] > array[j]){
                copy[copy_index--] = array[i--];
                count += j - mid;
                if(count > 1000000007){
                    count %= 1000000007;
                }
            }else{
                copy[copy_index--] = array[j--];
            }
        }
        while(i >= start){
            copy[copy_index--] = array[i--];
        }
        while(j >= mid + 1){
            copy[copy_index--] = array[j--];
        }
        i = 0;
        while(start <= end) {
            array[start++] = copy[i++];
        }
        return (left_count+right_count+count)%1000000007;
    }

37.兩個鏈表的第一個公公節點

輸入兩個鏈表,找出它們的第一個公共結點。
解題思路:第一個公共節點後都是公共節點,只需找到兩個鏈表的差值,然後讓一個指針先走diff步

    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1==null ||pHead2==null) return null;
        int count1 = 1;
        int count2 = 1;
        ListNode p1 = pHead1;
        while (p1.next!=null){
            count1++;
            p1 = p1.next;
        }
        ListNode p2 = pHead2;
        while(p2.next!=null){
            count2++;
            p2 = p2.next;
        }
        if(count1-count2>0){
            int diff = count1 -count2;
            while(diff!=0){
                pHead1 = pHead1.next;
                diff--;
            }
        }else {
            int diff = count2 - count1;
            while(diff!=0){
                pHead2 = pHead2.next;
                diff--;
            }
        }
        while(pHead1!=null&&pHead2!=null){
            if(pHead1==pHead2){
                return pHead1;
            }
            pHead1=pHead1.next;
            pHead2=pHead2.next;
        }
        return null;
    }

38.數字在排序數組中出現的次數

統計一個數字在排序數組中出現的次數。
解題思路:用二分查找的思想,比如我們要查找2,就在整數數組裏查找1.5和2.5,找到這兩個應該插入的位置,做差。

    public int GetNumberOfK(int [] array , int k) {
        if(array.length<=0) return 0;
        return find(array,k+0.5) - find(array,k-0.5);
    }

    public int find(int[] array,double k){
        int low = 0;
        int high = array.length - 1;
        while(low<=high){
            int mid = (low+high)/2;
            if(array[mid]>k){
                high = mid-1;
            }else {
                low = mid+1;

            }
        }
        return low;
    }

39.二叉樹的深度

輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度爲樹的深度。
解題思路:常規問題,遞歸。

    public int TreeDepth(TreeNode root) {
        if(root==null) return 0;
        int left = treeDepth(root.left) +1;
        int right = treeDepth(root.right)+1;
        return left>right?left:right;
    }

40.平衡二叉樹

輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。
解題思路:平衡二叉樹的定義,每一個棵樹的左右子樹的最大深度都小於等於1,對於空樹,是平衡二叉樹。

    public boolean IsBalanced_Solution(TreeNode root) {
        if(root==null) return true;
        return IsBalanced_Solution(root.left)&& IsBalanced_Solution(root.right)&&
                Math.abs(MaxDeep(root.left)-MaxDeep(root.right))<=1;
    }
    public int MaxDeep(TreeNode root){
        if(root==null) return 0;
        return 1+Math.max(MaxDeep(root.left),MaxDeep(root.right));
    }

41.數組中只出現一次的數

一個整型數組裏除了兩個數字之外,其他的數字都出現了偶數次。請寫程序找出這兩個只出現一次的數字。
解題思路:hashmap法

import java.util.HashMap;
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        HashMap<Integer, Integer> temp = new HashMap<Integer, Integer>();
        for(int i = 0; i < array.length; i++){
            if(temp.containsKey(array[i]))
                temp.remove(array[i]);
            else
                temp.put(array[i], 1);
        }
        int [] a = new int [array.length];
        int i = 0;
        for(Integer k: temp.keySet()){
            a[i] = k;
            i++;
        }
        num1[0] = a[0];
        num2[0] = a[1];
    }
}

42. 和爲s的連續正數序列

小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和爲100(至少包括兩個數)。沒多久,他就得到另一組連續正數和爲100的序列:18,19,20,21,22。現在把問題交給你,你能不能也很快的找出所有和爲S的連續正數序列? Good Luck!
解題思路:滑動窗口的思想,一點一點擴張

   public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(sum <3) return res;
        int start = 1;
        int end = 2;
        int mid = (1+sum)/2;
        while(start<end){
            int all = totalSum(start,end);
            if(sum == all){
                res.add(getSequence(start,end)); 
                end++;
            }else if(sum > all){
                end++;
            }else if(sum <all){
                start++;
            }
        }
        return res;
    }

    public  int totalSum(int start,int end){
        int ans=0;
        for(int i = start;i<=end;i++){
            ans+=i;
        }
        return ans;
    }

    public ArrayList<Integer> getSequence(int start, int end){
        ArrayList<Integer> temp = new ArrayList<>();
        for(int i = start; i <= end; i++){
            temp.add(i);
        }
        return temp;
    }

43.和爲s的兩個數字

輸入一個遞增排序的數組和一個數字S,在數組中查找兩個數,使得他們的和正好是S,如果有多對數字的和等於S,輸出兩個數的乘積最小的。
解題思路:數組順序遞增,從左右逼近

    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> res = new ArrayList<Integer>();
        if(array.length < 2)
            return res;
        int i = 0, j = array.length - 1;
        while(i != j){
            if(array[i] + array[j] == sum){
                res.add(array[i]);
                res.add(array[j]);
                break;
            }else if(array[i] + array[j] < sum){
                i++;
            }else{
                j--;
            }
        }
        return res;
    }

44.左旋轉字符串

彙編語言中有一種移位指令叫做循環左移(ROL),現在有個簡單的任務,就是用字符串模擬這個指令的運算結果。對於一個給定的字符序列S,請你把其循環左移K位後的序列輸出。例如,字符序列S=”abcXYZdef”,要求輸出循環左移3位後的結果,即“XYZdefabc”。是不是很簡單?OK,搞定它!
解題思路:在移動位數的地方一刀切。

    public String LeftRotateString(String str,int n) {
        if(str.length() ==0) return "";
        String s1 = str.substring(0,n);
        String s2 = str.substring(n,str.length());
        return s2+s1;
    }

45.翻轉單詞順序

牛客最近來了一個新員工Fish,每天早晨總是會拿着一本英文雜誌,寫些句子在本子上。同事Cat對Fish寫的內容頗感興趣,有一天他向Fish借來翻看,但卻讀不懂它的意思。例如,“student. a am I”。後來才意識到,這傢伙原來把句子單詞的順序翻轉了,正確的句子應該是“I am a student.”。Cat對一一的翻轉這些單詞順序可不在行,你能幫助他麼?

解題思路:以空格split,翻轉。。

    public String ReverseSentence(String str) {
        if(str.trim().length() == 0)
            return str;
        String [] temp = str.split(" ");
        String res = "";
        for(int i = temp.length - 1; i >= 0; i--){
            res += temp[i];
            if(i != 0)
                res += " ";
        }
        return res;
    }

46.撲克牌順子

LL今天心情特別好,因爲他去買了一副撲克牌,發現裏面居然有2個大王,2個小王(一副牌原本是54張_)…他隨機從中抽出了5張牌,想測測自己的手氣,看看能不能抽到順子,如果抽到的話,他決定去買體育彩票,嘿嘿!!“紅心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是順子…LL不高興了,他想了想,決定大\小 王可以看成任何數字,並且A看作1,J爲11,Q爲12,K爲13。上面的5張牌就可以變成“1,2,3,4,5”(大小王分別看作2和4),“So Lucky!”。LL決定去買體育彩票啦。 現在,要求你使用這幅牌模擬上面的過程,然後告訴我們LL的運氣如何, 如果牌能組成順子就輸出true,否則就輸出false。爲了方便起見,你可以認爲大小王是0。
解題思路:跟着題目的思路。。設置好邊界條件

    public boolean isContinuous(int [] numbers) {
        int zero = 0, dis = 0;
        if(numbers.length != 5)
            return false;
        Arrays.sort(numbers);
        for(int i = 0; i < 4; i++){
            if(numbers[i] == 0){
                zero ++;
                continue;
            }
            if(numbers[i] == numbers[i+1])
                return false;
            if(numbers[i+1] - numbers[i] > 1){
                dis += numbers[i+1] - numbers[i] - 1;
            }
        }
        if(zero >= dis)
            return true;
        else
            return false;
    }

47.孩子們的遊戲

每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。HF作爲牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的:首先,讓小朋友們圍成一個大圈。然後,他隨機指定一個數m,讓編號爲0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中,從他的下一個小朋友開始,繼續0…m-1報數…這樣下去…直到剩下最後一個小朋友,可以不用表演,並且拿到牛客名貴的“名偵探柯南”典藏版(名額有限哦!!_)。請你試着想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)

解題思路:用環形鏈表模擬圓圈。

    public int LastRemaining_Solution(int n, int m) {
        if(n < 1 || m < 1)
            return -1;
        LinkedList<Integer> link = new LinkedList<Integer>();
        for(int i = 0; i < n; i++)
            link.add(i);
        int index = -1;  
        while(link.size() > 1){
            index = (index + m) % link.size();  //對 link的長度求餘不是對 n
            link.remove(index);
            index --;
        }
        return link.get(0);
    }

48.求1+2+3…+n

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。
解題思路:遞歸調用

    public int Sum_Solution(int n) {
        int sum = n;
        boolean t = (n > 0) && (sum += Sum_Solution(n-1))>0;
        return sum;
    }

49.不用加減乘除做加法

寫一個函數,求兩個整數之和,要求在函數體內不得使用+、-、*、/四則運算符號。

public int Add(int num1, int num2) {
        if(num2 == 0)
            return num1;
        int sum = 0, carry = 0;
        while(num2 != 0){
            sum = num1 ^ num2;
            carry = (num1 & num2) << 1;
            num1 = sum;
            num2 = carry;
        }
        return num1;
    }

50.把字符串轉換成整數

將一個字符串轉換成一個整數(實現Integer.valueOf(string)的功能,但是string不符合數字要求時返回0),要求不能使用字符串轉換整數的庫函數。 數值爲0或者字符串不是一個合法的數值則返回0。
解題思路:判斷正負,判斷字符是否爲數字字符

        public int StrToInt(String str) {
                if(str.length()==0) return 0;
                int flag= 0;
                if(str.charAt(0)=='+') flag = 1;
                if(str.charAt(0)=='-') flag = 2;
                int start = flag>0?1:0;
                long res = 0;
                while (start<str.length()){
                        if(str.charAt(start)<'0'||str.charAt(start)>'9') return 0;
                        res = res*10 + str.charAt(start) - '0';
                        start++;
                }
                return flag ==2?-(int)res:(int)res;
        }

51.數組中重複的數字

在一個長度爲n的數組裏的所有數字都在0到n-1的範圍內。 數組中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出數組中任意一個重複的數字。 例如,如果輸入長度爲7的數組{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字2。

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

52.構建乘積數組

給定一個數組A[0,1,…,n-1],請構建一個數組B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。

        public int[] multiply(int[] A) {
                if(A.length<=1) return A;
                int[] res = new int[A.length];
                res[0] = 1;
                for(int i = 1;i<A.length;i++){
                        res[i] = res[i-1]*A[i-1];
                }

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

53.正則表達式匹配

請實現一個函數用來匹配包括’.‘和’‘的正則表達式。模式中的字符’.‘表示任意一個字符,而’'表示它前面的字符可以出現任意次(包含0次)。 在本題中,匹配是指字符串的所有字符匹配整個模式。例如,字符串"aaa"與模式"a.a"和"abaca"匹配,但是與"aa.a"和"ab*a"均不匹配

54.表示數值的字符串

請實現一個函數用來判斷字符串是否表示數值(包括整數和小數)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示數值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

public boolean isNumeric(char[] str) {
        int len = str.length;
        boolean sign = false, decimal = false, hasE = false;
        for(int i = 0; i < len; i++){
            if(str[i] == '+' || str[i] == '-'){
                if(!sign && i > 0 && str[i-1] != 'e' && str[i-1] != 'E')
                    return false;
                if(sign && str[i-1] != 'e' && str[i-1] != 'E')
                    return false;
                sign = true;
            }else if(str[i] == 'e' || str[i] == 'E'){
                if(i == len - 1)
                    return false;
                if(hasE)
                    return false;
                hasE = true;
            }else if(str[i] == '.'){
                if(hasE || decimal)
                    return false;
                decimal = true;
            }else if(str[i] < '0' || str[i] > '9')
                return false;
        }
        return true;
    }

55.字符流中第一個不重複的字符

請實現一個函數用來找出字符流中第一個只出現一次的字符。例如,當從字符流中只讀出前兩個字符"go"時,第一個只出現一次的字符是"g"。當從該字符流中讀出前六個字符“google"時,第一個只出現一次的字符是"l"。

解題思路:哈希

import java.util.HashMap;
public class Solution {
    HashMap<Character, Integer> map = new HashMap<Character, Integer>();
    StringBuffer s = new StringBuffer();
    //Insert one char from stringstream
    public void Insert(char ch)
    {
        s.append(ch);
        if(map.containsKey(ch)){
            map.put(ch, map.get(ch)+1);
        }else{
            map.put(ch, 1);
        }
    }
  //return the first appearence once char in current stringstream
    public char FirstAppearingOnce()
    {
        for(int i = 0; i < s.length(); i++){
            if(map.get(s.charAt(i)) == 1)
                return s.charAt(i);
        }
        return '#';
    }
}

56.鏈表中的入口節點

給一個鏈表,若其中包含環,請找出該鏈表的環的入口結點,否則,輸出null。
解題思路:數組記錄

        public ListNode EntryNodeOfLoop(ListNode pHead){
                if(pHead==null ||pHead.next==null) return null;
                ArrayList<ListNode> arr = new ArrayList<ListNode>();
                arr.add(pHead);
                pHead = pHead.next;
                while (!arr.contains(pHead)){
                        arr.add(pHead);
                        pHead = pHead.next;
                }
                return pHead;
        }

57.刪除鏈表中重複的節點

在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。 例如,鏈表1->2->3->3->4->4->5 處理後爲 1->2->5

public ListNode deleteDuplication(ListNode pHead)
    {
        if(pHead == null || pHead.next == null)
            return pHead;
        ListNode head = new ListNode(-1);
        head.next = pHead;
        ListNode first = head;
        ListNode second = first.next;
        while(second != null){
            if(second.next != null && second.val == second.next.val){
                while(second.next != null && second.val == second.next.val){
                    second = second.next;
                }
                first.next = second.next;
            }else{
                first = first.next;
            }
            second = second.next;
        }
        return head.next;
    }

58.二叉樹的下一個節點

給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指針。

public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode == null){
            return null;
        }
        if(pNode.right != null){
            TreeLinkNode node = pNode.right;
            while(node.left != null){
                node = node.left;
            }
            return node;
        }
        while(pNode.next != null){
            TreeLinkNode root = pNode.next;
            if(pNode == root.left)
                return root;
            pNode = root;
        }
        return null;
    }

59.對稱的二叉樹

請實現一個函數,用來判斷一顆二叉樹是不是對稱的。注意,如果一個二叉樹同此二叉樹的鏡像是同樣的,定義其爲對稱的。

    boolean isSymmetrical(TreeNode pRoot)
    {
        if(pRoot == null)
            return true;
        return isSymmetrical(pRoot.left, pRoot.right);
    }
    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;
    }

60.按之字形順序遍歷二叉樹

請實現一個函數按照之字形打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其他行以此類推。

public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer> > res = new ArrayList<ArrayList<Integer> >();
        Stack<TreeNode> s1 = new Stack<TreeNode>();
        Stack<TreeNode> s2 = new Stack<TreeNode>();
        int flag = 1;
        if(pRoot == null)
            return res;
        s2.push(pRoot);
        ArrayList<Integer> temp = new ArrayList<Integer>();
        while(!s1.isEmpty() || !s2.isEmpty()){
            if(flag % 2 != 0){
                while(!s2.isEmpty()){
                    TreeNode node = s2.pop();
                    temp.add(node.val);
                    if(node.left != null){
                        s1.push(node.left);
                    }
                    if(node.right != null){
                        s1.push(node.right);
                    }
                }
            }
            if(flag % 2 == 0){
                while(!s1.isEmpty()){
                    TreeNode node = s1.pop();
                    temp.add(node.val);
                    if(node.right != null){
                        s2.push(node.right);
                    }
                    if(node.left != null){
                        s2.push(node.left);
                    }
                }
            }
            res.add(new ArrayList<Integer>(temp));
            temp.clear();
            flag ++;
        }
        return res;
    }

61.把二叉樹打印成多行

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


    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer> > res = new ArrayList<ArrayList<Integer> >();
        if(pRoot == null)
            return res;
        ArrayList<Integer> temp = new ArrayList<Integer>();
        Queue<TreeNode> layer = new LinkedList<TreeNode>();
        layer.offer(pRoot);
        int start = 0, end = 1;
        while(!layer.isEmpty()){
            TreeNode node = layer.poll();
            temp.add(node.val);
            start ++;
            if(node.left != null)
                layer.add(node.left);
            if(node.right != null)
                layer.add(node.right);
            if(start == end){
                start = 0;
                res.add(temp);
                temp = new ArrayList<Integer>();
                end = layer.size();
            }
        }
        return res;
    }

62.序列化二叉樹

請實現兩個函數,分別用來序列化和反序列化二叉樹

import java.util.Queue;
import java.util.LinkedList;
public class Solution {
    String Serialize(TreeNode root) {
        if(root == null){
            return "#,";
        }
        StringBuffer res = new StringBuffer(root.val + ",");
        res.append(Serialize(root.left));
        res.append(Serialize(root.right));
        return res.toString();
    }
    TreeNode Deserialize(String str) {
        String [] res = str.split(",");
        Queue<String> queue = new LinkedList<String>();
        for(int i = 0; i < res.length; i++){
            queue.offer(res[i]);
        }
        return pre(queue);
    }
    TreeNode pre(Queue<String> queue){
        String val = queue.poll();
        if(val.equals("#"))
            return null;
        TreeNode node = new TreeNode(Integer.parseInt(val));
        node.left = pre(queue);
        node.right = pre(queue);
        return node;
    }
}

63.二叉搜索樹的第k個節點

給定一棵二叉搜索樹,請找出其中的第k小的結點。例如, (5,3,7,2,4,6,8) 中,按結點數值大小順序第三小結點的值爲4。

public class Solution {
    int index = 0;
    TreeNode KthNode(TreeNode pRoot, int k)
    {
        if(pRoot != null){
            TreeNode node = KthNode(pRoot.left, k);
            if(node != null)
                return node;
            index ++;
            if(index == k)
                return pRoot;
            node = KthNode(pRoot.right, k);
            if(node != null)
                return node;
        }
        return null;
    }
}

64.數據流中的中位數

如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數。

65.滑動窗口的最大值

給定一個數組和滑動窗口的大小,找出所有滑動窗口裏數值的最大值。例如,如果輸入數組{2,3,4,2,6,2,5,1}及滑動窗口的大小3,那麼一共存在6個滑動窗口,他們的最大值分別爲{4,4,6,6,6,5}; 針對數組{2,3,4,2,6,2,5,1}的滑動窗口有以下6個: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> res = new ArrayList<Integer>();
        if(num.length < size || size == 0)
            return res;
        for(int i = 0; i < num.length - size + 1; i++){
            res.add(max(num, i, size));
        }
        return res;
    }
    public int max(int [] num, int index, int size){
        int res = num[index];
        for(int i = index + 1; i < index + size; i++){
            if(num[i] > res)
                res = num[i];
        }
        return res;
    }
}

66.矩陣中的路徑

請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則之後不能再次進入這個格子。 例如 a b c e s f c s a d e e 這樣的3 X 4 矩陣中包含一條字符串"bcced"的路徑,但是矩陣中不包含"abcb"路徑,因爲字符串的第一個字符b佔據了矩陣中的第一行第二個格子之後,路徑不能再次進入該格子。

67.機器人的運動軌跡

地上有一個m行和n列的方格。一個機器人從座標0,0的格子開始移動,每一次只能向左,右,上,下四個方向移動一格,但是不能進入行座標和列座標的數位之和大於k的格子。 例如,當k爲18時,機器人能夠進入方格(35,37),因爲3+5+3+7 = 18。但是,它不能進入方格(35,38),因爲3+5+3+8 = 19。請問該機器人能夠達到多少個格子?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章