Java算法:牛客網Java版劍指Offer全套算法面試題目整理及電子檔,Java算法與數據結構面試題,面試刷題、背題必備!牛客網劍指offer

劍指offer(java版)

牛客網Java版劍指Offer全套題目67道

資源來源於網絡

目錄

1.二維數組中的查找

2.替換空格

3.從尾到頭打印鏈表

4.重建二叉樹

5.用兩個棧實現隊列

6.旋轉數組的最小數字

7.斐波那契數列

8.跳臺階

9.變態跳臺階

10.矩形覆蓋

11.二進制中1的個數

12.數值的整數次方

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

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

15.反轉鏈表

16.合併兩個排序的鏈表

17.樹的子結構

18.二叉樹的鏡像

19.順時針打印矩陣

20.包含min函數的棧

21.棧的壓入、彈出序列

22.從上往下打印二叉樹

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

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

25.複雜鏈表的複製

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

27.字符串的排列

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

29.最小的K個數

30.連續子數組的最大和

31.整數中1出現的次數(從1到n整數中1出現的)

32.把數組排成最小的數

33.醜數

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

35.歸併排序

36.數組中的逆序對

37.兩個鏈表的第一個公共結點

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

39.二叉樹的深度

40.平衡二叉樹

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

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

43.和爲S的兩個數字

44.左旋轉字符串

45.翻轉單詞順序列

46.撲克牌順子

47.孩子們的遊戲(圓圈中最後剩下的數)

48.求1+2+3+...+n

49.不用加減乘除做加法

50.把字符串轉換成整數

51.數組中重複的數字

52.構建乘積數組

53.正則表達式匹配

54.表示數值的字符串

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

56.鏈表中環的入口結點

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

58.二叉樹的下一個結點

59.對稱的二叉樹

60.按之字形順序打印二叉樹

61.把二叉樹打印成多行

62.序列化二叉樹

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

64.數據流中的中位數

65.滑動窗口的最大值

66.矩陣中的路徑

67.機器人的運動範圍


1.二維數組中的查找

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

public class Solution {

    public boolean Find(int target, int [][] array) {

        int row = 0;

        int column = array[0].length-1;

        while(row<array.length && column>=0){

            if(target == array[row][column]){

               return true;

            }

            else if(target > array[row][column]){

               row++;

            }

            else{

               column--;

            }

        }

        return false;

    }

}

2.替換空格

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

public class Solution {

    public String replaceSpace(StringBuffer str) {

        if(str==null && str.length()<=0){

           return null;

        }

        StringBuffer newString = new StringBuffer();

        for(int i=0;i<str.length();i++){

           if(str.charAt(i)==' '){

               newString.append('%');

               newString.append('2');

               newString.append('0');

           }

           else{

               newString.append(str.charAt(i));

           }

        }

        return newString.toString();   

    }

}

3.從尾到頭打印鏈表

輸入一個鏈表,從尾到頭打印鏈表每個節點的值。

import java.util.ArrayList;

import java.util.Stack;

public class Solution {

    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {

        Stack<ListNode> stack = new  Stack<ListNode>();

        while(listNode!=null){

            stack.push(listNode);

            listNode = listNode.next;

        }

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

        while(!stack.empty()){

            list.add(stack.pop().val);

        }

        return list;

    }

}

4.重建二叉樹

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

import java.util.HashMap;

public class Solution {

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

        if(pre==null && in==null){

           return null;

        }

        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();

        for(int i=0;i<in.length;i++){

           map.put(in[i], i);

        }

        TreeNode root = ConstructCore(pre,0,pre.length-1,in,0,in.length-1,map);

        return root;

    }

    public TreeNode ConstructCore(int[] pre,int pstart,int pend,int[] in,

           int istart,int iend,HashMap<Integer, Integer> map){

        if(pstart > pend){

           return null;

        }

        //根據前序遍歷獲取根節點

        int val = pre[pstart];

        TreeNode root = new TreeNode(val);

        //根據中序遍歷獲取左右子樹

        int index = map.get(val);

        root.left = ConstructCore(pre,pstart+1,pstart+index-istart,in,istart,index-1,map);

        root.right = ConstructCore(pre,pstart+index-istart+1,pend,in,index+1,iend,map);

        return root;

    }

}

5.用兩個棧實現隊列

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

import java.util.Stack;

public class Solution {

    Stack<Integer> stack1 = new Stack<Integer>();

    Stack<Integer> stack2 = new Stack<Integer>();

    public void push(int node) {

        stack1.push(node);

    }

    public int pop() {

        if(stack1.empty()&&stack2.isEmpty()){

           throw new RuntimeException("Queue is empty!");

        }

        else if(stack2.empty()){

           while(!stack1.empty()){

               stack2.push(stack1.pop());

           }

        }

        return stack2.pop();

    }

}

6.旋轉數組的最小數字

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

import java.util.ArrayList;

public class Solution {

    public int minNumberInRotateArray(int [] array) {

        if(array==null && array.length<=0){

           return 0;

        }

        int index1 = 0;

        int index2 = array.length-1;

        int midIndex = index1;

        while(array[index1]>=array[index2]){

           if(index2-index1==1){

               midIndex = index2;

               break;

           }

           midIndex = (index1+index2)/2;

           if(array[midIndex]>=array[index1]){

               index1 = midIndex;

           }

           else if(array[midIndex]<=array[index2]){

               index2 = midIndex;

           }

           else if(array[index1]==array[index2]&&array[index1]==array[midIndex]){

               return MinInOrder(array,index1,index2);

           }

        }

        return array[midIndex];

  

    }

   public int MinInOrder(int [] array,int index1,int index2){

       int result = array[index1];

       for(int i=index1+1;i<=index2;i++){

          if(result>array[i]){

              result = array[i];

          }

       }

       return result;

   }

}

7.斐波那契數列

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

public class Solution {

    public int Fibonacci(int n) {

        if(n<=1){

            return n;

        }

        int finOne = 0;

        int finTwo = 1;

        int fin = 0;

        for(int i=2;i<=n;i++){

            fin = finOne+finTwo;

            finOne = finTwo;

            finTwo = fin;

        }

      

        return fin;

    }

}

8.跳臺階

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

public class Solution {

    public int JumpFloor(int target) {

        if(target<=2){

               return target;

        }

        int finOne = 1;

        int finTwo = 2;

        int fin = 0;

        for(int i=3;i<=target;i++){

               fin = finOne+finTwo;

               finOne = finTwo;

               finTwo = fin;

        }

      

        return fin;

 

    }

}

9.變態跳臺階

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

public class Solution {

    public int JumpFloorII(int target) {

        if(target==1){

            return 1;

        }

        int num = 1;

        int result = 0;

        for(int i=2;i<=target;i++){

            result = 2*num;

            num = result;

        }

        return result;

    }

}

10.矩形覆蓋

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

public class Solution {

    public int RectCover(int target) {

              if(target<=2){

               return target;

        }

        int finOne = 1;

        int finTwo = 2;

        int fin = 0;

        for(int i=3;i<=target;i++){

               fin = finOne+finTwo;

               finOne = finTwo;

               finTwo = fin;

        }

      

        return fin;

 

    }

}

11.二進制中1的個數

輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。

public class Solution {

    public int NumberOf1(int n) {

        int count = 0;

        while(n!=0){

            count++;

            n = (n-1)&n;

        }

        return count;

 

    }

}

12.數值的整數次方

給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方.

public class Solution {

    boolean InvalidInput = false;

    public double Power(double base, int exponent) {

        if(base==0.0 && exponent<0){

           InvalidInput = true;

           return 0.0;

        }

        int absexponent = exponent;

        if(exponent<0){

           absexponent = (-1)*exponent;

        }

        double result = PowerWithExponent(base,absexponent);

        if(exponent<0){

           result = 1.0/result;

        }

        return result;

  }

  

    public double PowerWithExponent(double base, int exponent){

        if(exponent==0){

           return 1;

        }

        if(exponent==1){

           return base;

        }

        double result = PowerWithExponent(base,exponent>>1);

        result = result*result;

        if((exponent & 0x1) == 1){

           result = result*base;

        }

        return result;

    }

}

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

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

第一個思路:類似冒泡算法,前偶後奇數就交換:

public class Solution {   

    public static void reOrderArray(int [] array) {

        for(int i= 0;i<array.length-1;i++){

            for(int j=0;j<array.length-1-i;j++){

                  if((array[j]&1)==0&&(array[j+1]&1)==1){

                      int temp = array[j];

                      array[j]=array[j+1];

                      array[j+1]=temp;

                  }

            }

        }

     }

}

第二個思路:以空間換時間:

import java.util.ArrayList;

import java.util.List;

 

public class Solution {   

    public static void reOrderArray(int [] array) {

        if(array==null && array.length==0){

           return ;

        }

        List<Integer> odd = new ArrayList<Integer>();

        List<Integer> even = new ArrayList<Integer>();

        for(int i=0;i<array.length;i++){

           int temp = array[i];

           if((temp & 1)==1){

               odd.add(temp);

           }

           else{

               even.add(temp);

           }

        }

        int m = 0;

        for(int i=0;i<odd.size();i++){

           array[m] = odd.get(i);

           m++;

        }

        for(int k=0;k<even.size();k++){

           array[m] = even.get(k);

           m++;

        }

    }

}

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

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

public class Solution {

    public ListNode FindKthToTail(ListNode head,int k) {

        if(head==null || k<=0){

           return null;

        }

        ListNode ahead = head;

        ListNode behind = null;

        for(int i=0;i<k-1;i++){

           //如果k大於鏈表長度,返回空

           if(ahead.next!=null){

               ahead = ahead.next;

           }

           else{

               return null;

           }

        }

        behind = head;

        while(ahead.next!=null){

           ahead = ahead.next;

           behind = behind.next;

        }

        return behind;

    }

}

15.反轉鏈表

輸入一個鏈表,反轉鏈表後,輸出鏈表的所有元素.

public class Solution {

    public ListNode ReverseList(ListNode head) {

        if(head==null){

           return null;

        }

        ListNode preNode = null;

        ListNode nextNode = null;

        ListNode currentNode = head;

        ListNode reverseHead = null;

        while(currentNode!=null){

           nextNode = currentNode.next;

           if(nextNode == null){

               reverseHead = currentNode;

           }

           currentNode.next = preNode;

           preNode = currentNode;

           currentNode = nextNode;

        }

        return reverseHead;

    }

}

16.合併兩個排序的鏈表

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

方法一:

public class Solution {

    public ListNode Merge(ListNode list1,ListNode list2) {

        if(list1==null && list2==null){

            return null;

        }

        if(list1==null){

            return list2;

        }

        if(list2==null){

            return list1;

        }

        ListNode head = null;

        if(list1.val<=list2.val){

            head = list1;

            list1 = list1.next;

        }

        else{

            head = list2;

            list2 = list2.next;

        }

        ListNode currentNode = head;

        while(list1!=null || list2!=null){

            if(list1==null){

               currentNode.next = list2;

               currentNode = currentNode.next;

               list2 = list2.next;

            }

            else if(list2==null){

               currentNode.next = list1;

               currentNode = currentNode.next;

               list1 = list1.next;

            }

          

            else if(list1!=null && list2!=null){

               if(list1.val<=list2.val){

   currentNode.next = list1;

   currentNode = currentNode.next;

   list1 = list1.next;

               }

               else{

   currentNode.next = list2;

   currentNode = currentNode.next;

   list2 = list2.next;

               }

            }

        }

        return head;

    }

}

方法二:採用遞歸

public class Solution {

    public ListNode Merge(ListNode list1,ListNode list2) {

        if(list1==null && list2==null){

            return null;

        }

        if(list1==null){

            return list2;

        }

        if(list2==null){

            return list1;

        }

        ListNode head = null;

        if(list1.val<=list2.val){

            head = list1;

            head.next = Merge(list1.next,list2);

        }

        else{

            head = list2;

            head.next = Merge(list1,list2.next);

        }

        return head;

      

    }

}

17.樹的子結構

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

public class Solution {

    /**

     * 遍歷樹的根節點

     */

    public  boolean HasSubtree(TreeNode root1,TreeNode root2) {

        boolean result = false;

        if(root1==null){

           return false;

        }

        if(root2==null){

           return false;

        }

        if(root1!=null && root2!=null){

           if(root1.val==root2.val){

               result = DoesTree1HaveTree2(root1,root2);

           }

        }

        if(!result){

           result = HasSubtree(root1.left,root2);

        }

        if(!result){

           result = HasSubtree(root1.right,root2);

        }

        return result;     

    }

   

    /**

     * 判斷根節點下面的子樹

     */

    public  boolean DoesTree1HaveTree2(TreeNode root1,TreeNode root2){

        if(root2 == null){

           return true;

        }

        if(root1 == null){

           return false;

        }

        if(root1.val!=root2.val){

           return false;

        }

        return DoesTree1HaveTree2(root1.left,root2.left) &&

               DoesTree1HaveTree2(root1.right,root2.right);

    }

}

18.二叉樹的鏡像

操作給定的二叉樹,將其變換爲源二叉樹的鏡像。

輸入描述:

二叉樹的鏡像定義:源二叉樹

            8

           /  \

          6   10

         / \  / \

        5  7 9 11

        鏡像二叉樹

            8

           /  \

          10   6

         / \  / \

        11 9 7  5

public class Solution {

    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;

      

        /**

         * 循環遍歷每一個節點

         */

        if(root.left!=null){

            Mirror(root.left);

        }

        if(root.right!=null){

            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.

public class Solution {

    public ArrayList<Integer> printMatrix(int[][] matrix) {

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

       if(matrix==null){

           return null;

       }

       int rows = matrix.length;

       int columns = matrix[0].length;

       int start = 0;

       while(2*start<rows && 2*start<columns){

           printMatrilCircle(arrayList,start,rows,columns,matrix);

           start++;

       }

       return arrayList;

    }

  

    public void printMatrilCircle(ArrayList<Integer> arrayList,int start,int rows,int columns,int[][] matrix){

       int endX = columns-1-start;

       int endY = rows-1-start;

       /**

        * 從左到右打印一行

        */

       for(int i=start;i<=endX;i++){

           int num = matrix[start][i];

           arrayList.add(num);

       }

     

       /**

        * 從上到下打印(行數要大於等於兩行)start<endY

        */

       if(start<endY){

           for(int i=start+1;i<=endY;i++){

              int num = matrix[i][endX];

              arrayList.add(num);

           }

       }

       /**

        * 從右往左打印一行(至少要有兩行兩列)

        */

       if(start<endY && start<endX){

           for(int i=endX-1;i>=start;i--){

              int num = matrix[endY][i];

              arrayList.add(num);

           }

       }

     

       /**

        * 從下往上打印一列(至少要有三行兩列)

        */

       if(start<(endY-1) && start<endX){

           for(int i=endY-1;i>start;i--){

              int num = matrix[i][start];

              arrayList.add(num);

           }

       }

    }

}

20.包含min函數的棧

定義棧的數據結構,請在該類型中實現一個能夠得到棧最小元素的min函數。

import java.util.Stack;

 

public class Solution {

  

    Stack<Integer> stack = new Stack<Integer>();

    Stack<Integer> stackMin = new Stack<Integer>();

    public void push(int node) {

        stack.push(node);

        if(stackMin.isEmpty()){

           stackMin.push(node);

        }

        else{

           if(node<=stackMin.peek()){

               stackMin.push(node);

           }

           else{

               stackMin.push(stackMin.peek());

           }

        }

    }

  

    public void pop() {

        stack.pop();

        stackMin.pop();

    }

  

    public int top() {

       return  stack.peek();

    }

  

    public int min() {

        return stackMin.peek();

    }

}

21.棧的壓入、彈出序列

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

import java.util.Stack;

 

public class Solution {

    public boolean IsPopOrder(int [] pushA,int [] popA) {

        if(pushA==null && popA==null){

           return false;

        }

        Stack<Integer> stack = new Stack<Integer>();

        int j = 0;

        /**

         * 將壓入序列放入數組中

         */

        for(int i=0;i<pushA.length;i++){

           while(!stack.isEmpty() && stack.peek()==popA[j]){

               stack.pop();

               j++;        

           }

           stack.push(pushA[i]);      

        }

        while(j<popA.length){

           if(stack.peek()==popA[j]){

               stack.pop();

               j++;

           }

           else{

               return false;

           }

        }

      return true;

    }

}

22.從上往下打印二叉樹

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

import java.util.ArrayList;

import java.util.LinkedList;

import java.util.Queue;

public class Solution {

    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {

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

        if(root==null){

           return arrayList;

        }     

        Queue<TreeNode> queue = new LinkedList<>();

        queue.add(root);

        while(!queue.isEmpty()){

           TreeNode hQueue = queue.poll();

           if(hQueue.left!=null){

               queue.add(hQueue.left);

           }

           if(hQueue.right!=null){

               queue.add(hQueue.right);

           }

           arrayList.add(hQueue.val);

        }

        return arrayList;

    }

}

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

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

方法一:

import java.util.ArrayList;

public class Solution {

    public boolean VerifySquenceOfBST(int [] sequence) {

        if(sequence==null || sequence.length<=0){

           return false;

        }

        if(sequence.length==1){

           return true;

        }

        int length = sequence.length;

        int root = sequence[length-1];

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

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

        boolean left = true;

        boolean right = true;

        int k = 0;

        /**

         * 左子樹

         */

        if(sequence[k]<root){

           leftList.add(sequence[k]);

           k++;

           for(int i=k;i<length-1;i++){

               if(sequence[i]<root){

                    leftList.add(sequence[i]);

                    k++;

               }

               else{

                    break;

               }

           }

        }

        /**

         * 右子樹

         */

        if(sequence[k]>root){

           rightList.add(sequence[k]);

           k++;

           for(int i=k;i<length-1;i++){

               if(sequence[i]>root){

                   rightList.add(sequence[i]);

               }

               else{

                    return false;

               }

           }

        }

        if(leftList.size()>0){

            int[] leftArray = new int[leftList.size()];

            for(int i=0;i<leftArray.length;i++){

               leftArray[i] = leftList.get(i);

            }

            left = VerifySquenceOfBST(leftArray);

        }

        if(rightList.size()>0){

            int[] rightArray = new int[rightList.size()];

            for(int i=0;i<rightArray.length;i++){

               rightArray[i] = rightList.get(i);

            } 

            right = VerifySquenceOfBST(rightArray);

        }

        return left&&right;

    }

}

 方法二:

public class Solution {

    public boolean VerifySquenceOfBST(int [] sequence) {

    int length  = sequence.length;

    if(sequence==null || length<=0){

         return false;

    }

    if(length==1){

         return true;

    }

    int root = sequence[length-1];

    int i=0;

    /**

     * 在二叉搜索樹中左子樹的節點小於根節點

     */

    for(;i<length-1;i++){

         if(sequence[i]>root){

             break;

         }

    }

    int leftLength = i;

    /**

     * 在二叉搜索樹中右子樹的節點大於根節點

     */

    for(int j=i;j<length-1;j++){

         if(sequence[j]<root){

             return false;

         }

    }

    //判斷左子樹是不是二叉搜索樹

    boolean left = true;

    if(leftLength>0){

         int[] leftSequence = new int[leftLength];

         for(int k=0;k<leftLength-1;k++){

             leftSequence[k] = sequence[k];

         }

         left = VerifySquenceOfBST(leftSequence);

    }

    //判斷右子樹是不是二叉樹

    boolean right = true;

    if(leftLength<length-1){

         int[] rightSequence = new int[length-leftLength-1];

         for(int k=0;k<length-leftLength-1;k++){

             rightSequence[k] = sequence[k];

         }

         right = VerifySquenceOfBST(rightSequence);

    }

    return left&&right;

    }

}

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

輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑。路徑定義爲從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。

import java.util.ArrayList;

public class Solution {

    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {

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

        if(root==null){

           return pathList;

        }     

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

        Integer currentSum = 0;

        find(root,target,pathList,currentSum,path);

        return pathList;

      

    }

  

    public void find(TreeNode root,int target,

           ArrayList<ArrayList<Integer>> pathList,Integer currentSum,ArrayList<Integer> path){

        currentSum = currentSum + root.val;

        path.add(root.val);

        boolean isLeaf = false;

        if(root.left==null && root.right==null){

           isLeaf = true;

        }

        if(currentSum==target && isLeaf){

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

           for(int i=0;i<path.size();i++){

               list.add(path.get(i));

           }

           pathList.add(list);

         

        }

      

        if(root.left!=null){

           find(root.left,target,pathList,currentSum,path);

        }

        if(root.right!=null){

           find(root.right,target,pathList,currentSum,path);

        }

        path.remove(path.size()-1);

    }

}

25.複雜鏈表的複製

輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)

public class Solution {

    public RandomListNode Clone(RandomListNode pHead)

    {

       RandomListNode p=pHead;

        RandomListNode t=pHead;

        /**

         * 複製原始鏈表的任意節點n

         */

        while(p!=null){

             RandomListNode q=new RandomListNode(p.label);

            q.next=p.next;

            p.next=q;

            p=q.next;

        }

        /**

         * 複製指向的任意節點

         */

        while(t!=null){

            RandomListNode q=t.next;

            if(t.random!=null)

            q.random=t.random.next;

            t=q.next;

           

        }

        /**

         * 分離鏈表

         */

        RandomListNode rNode = pHead;

        RandomListNode rCloneNode = null;

        RandomListNode rCloneHead = null;

      

        if(rNode!=null){

            rCloneHead = rCloneNode = rNode.next;

            rNode.next = rCloneNode.next;

            rNode = rNode.next;

        }

        while(rNode!=null){

            rCloneNode.next = rNode.next;     

            rCloneNode = rCloneNode.next;

            rNode.next = rCloneNode.next;

            rNode = rNode.next;

        }

        return rCloneHead;

    }

}

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

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

public class Solution {

    public  TreeNode pLastNodeInList = null;

    public TreeNode Convert(TreeNode pRootOfTree) {

        ConvertNode(pRootOfTree);

        TreeNode pHeadNode = pLastNodeInList;

        //得到頭結點

        while(pHeadNode!=null && pHeadNode.left!=null){

            pHeadNode = pHeadNode.left;

        }

        return pHeadNode;

      

    }

    public void ConvertNode(TreeNode pRootOfTree){

        if(pRootOfTree==null){

           return;

        }

        TreeNode pCurrentNode = pRootOfTree;

        //遍歷左子樹

        if(pCurrentNode.left!=null){

           ConvertNode(pCurrentNode.left);

        }

        pCurrentNode.left = pLastNodeInList;

        if(pLastNodeInList!=null){

           pLastNodeInList.right = pCurrentNode;

        }

        pLastNodeInList = pCurrentNode;

        System.out.println(pLastNodeInList.val);

        //遍歷右子樹

        if(pCurrentNode.right!=null){

           ConvertNode(pCurrentNode.right);

        }

    }

}

27.字符串的排列

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

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collections;

public class Solution {

    public ArrayList<String> Permutation(String str) {

        ArrayList<String> list = new ArrayList<String>();

        if(str==null || str.length()==0){

           return list;

        }

        char[] cs = str.toCharArray();

        Arrays.sort(cs);

        Permutation(str.toCharArray(),0,list);

        Collections.sort(list);

        return list;

    }

    public void Permutation(char[] str,int begin,ArrayList<String> list){

        if(begin==str.length-1){

           list.add(String.valueOf(str));

           return;

        }

        for(int index=begin;index<str.length;index++){

           if(index!=begin&&(str[index-1]==str[index] ||str[index]==str[begin])){

               continue;

           }

           //第一個字符和剩下的字符進行交換

           char temp = str[index];

           str[index] = str[begin];

           str[begin] = temp;

         

           Permutation(str,begin+1,list);

         

           //復位

           temp = str[index];

           str[index] = str[begin];

           str[begin] = temp;

           }

        }

}

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

數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度爲9的數組{1,2,3,2,2,2,5,4,2}。由於數字2在數組中出現了5次,超過數組長度的一半,因此輸出2。如果不存在則輸出0。

方法一:利用快排思想

public class Solution {

    public int MoreThanHalfNum_Solution(int [] array) {

        if(array==null || array.length==0){

           return 0;

        }

        int middle = array.length/2;

        int start = 0;

        int end = array.length-1;

        int index = sort(array,start,end);

        while(index!=middle){

           if(index > middle){

               end = index - 1;

               index = sort(array, start, end);

           }

           else{

               start = index+1;

               index = sort(array, start, end);

           }

        }

        int result = array[middle];

        int time = 0;

        for(int i=0;i<array.length;i++){

           if(array[i]==result){

               time++;

           }

           if(time*2 > array.length){

               return result;

           }

        }

        if(time*2 <= array.length){

           return 0;

        }

        return 0;

    }

  

    public int sort(int[] array,int start,int end){

        int i = start;

        int j = end;

        int current = array[i];

        while(i < j){

           //從右往左掃描

           while(i < j && array[j]>=current){

               j--;

           }

           if(i < j){

               array[i] = array[j];

               i++;

           }

           //從左往右掃描

           while(i < j && array[i]<=current){

               i++;

           }

           if(i < j){

               array[j] = array[i];

               j--;

           }        

        }

        array[i] = current;

        return i;

    }

}

 方法二:

public class Solution {

    public int MoreThanHalfNum_Solution(int [] array) {

        //遍歷數組是保存兩個值:一個是數組中的數字,另一個是次數。

        if(array==null || array.length==0){

           return 0;

        }

        int result = array[0];

        int time = 1;

        for(int i=1;i<array.length;i++){

           //次數爲0時,保存當前數字,並把次數置爲1

           if(time==0){

               result = array[i];

               time = 1;

           }

           //當前數字和之前保存的數字相同時,次數加1

           else if(result == array[i]){

               time++;

           }

           //當前數字和之前保存的數字不相同時,次數減1

           else {

              time--;

           }

        }

        int count = 0;

        for(int i=0;i<array.length;i++){

           if(array[i] == result){

               count++;

           }

           if(count*2 > array.length){

               return result;

           }

        }

        return 0;

      

    }

}

29.最小的K個數

輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。

方法一:利用快排思想

public class Solution {

    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {

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

        if(input==null || input.length==0 || k==0 || k > input.length){

           return list;

        }

        int start = 0;

        int end = input.length-1;

        int index = sort(input,start,end);

        while(index!=(k-1)){

           if(index > (k-1)){

               end = index-1;

               index = sort(input,start,end);

           }

           else{

               start = index+1;

               index = sort(input,start,end);

           }

        }

        for(int i=0;i<=index;i++){

           list.add(input[i]);

        }

      

        return list;

    }

  

    public int sort(int [] input,int start,int end){

        int i = start;

        int j = end;

        int current = input[i];

        while(i < j){

           while(i < j && input[j]>=current){

               j--;

           }

           if(i < j){

               input[i] = input[j];

               i++;

           }

           while(i < j && input[i] <= current){

               i++;

           }

           if(i < j){

               input[j] = input[i];

               j--;

           }

        }

        input[i] = current;

        return i;

}

}

方法二:利用紅黑樹

30.連續子數組的最大和

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

public class Solution {

    boolean invalidInput = false;

    public int FindGreatestSumOfSubArray(int[] array) {

        if(array==null || array.length==0){

            invalidInput = false;

            return 0;

        }

        int curSum = 0;

        int greatSum = 0x80000000;  //32位的int,正數的範圍是(0,0x7FFFFFFF),負數(0x80000000,0xFFFFFFFF)

        for(int i=0;i<array.length;i++){

            if(curSum<0){

               curSum = array[i];

            }

            else{

               curSum = curSum + array[i];

            }

            if(curSum > greatSum){

               greatSum = curSum;

            }

        }

        return greatSum;

}

}

31.整數中1出現的次數(從1到n整數中1出現的)

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

public class Solution {

    public int NumberOf1Between1AndN_Solution(int n) {

        if(n<=0){

           return 0;

        }

        String string = Integer.toString(n);

        char[] cs = string.toCharArray();

        return NumberOf1(cs,0,cs.length);

      

    }

  

    public int NumberOf1(char[] cs,int start,int length){

        if(cs==null || length==0 || cs[0]<'0' || cs[0]>'9'){

           return 0;

        }

        int first = cs[start]-'0';

        if(length==1 && first==0){

           return 0;

        }

        if(length==1 && first>0){

           return 1;

        }

        //求最高位爲1的數目

        int numFirstDigit = 0;

        if(first>1){

           numFirstDigit = PowerBase10(length-1);

        }

        else if(first==1) {

           //得到除開最高位的數字

           char[] s = new char[length-1];

           int j=0;

           for(int i=start+1;i<cs.length;i++){

               s[j] = cs[i];

               j++;

           }

           numFirstDigit = Integer.parseInt(String.valueOf(s))+1;

       }

        //除開最高位的數字

        int numOtherDigits = first * (length-1) * PowerBase10(length-2);

      

        //1-1345中的數字,遞歸

        int numRecursive = NumberOf1(cs,start+1,length-1);

        return numFirstDigit + numOtherDigits + numRecursive;

    }

  

    public int PowerBase10(int n){

        int result = 1;

        for(int i=0;i<n;i++){

           result = result*10;

        }

        return result;

}

}

32.把數組排成最小的數

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

public class Solution {

    public String PrintMinNumber(int [] numbers) {

        if(numbers==null && numbers.length==0){

           return null;        

        }

        int length = numbers.length;

        //採用冒泡排序

        for(int i=0;i<length-1;i++){

           for(int j=length-1;j>i;j--){

               int m = numbers[j-1];

               int n = numbers[j];

               String mn = Integer.toString(m).concat(Integer.toString(n));

               String nm = Integer.toString(n).concat(Integer.toString(m));

               boolean isBig = compare(mn,nm);

               if(isBig){

                int temp = numbers[j-1];

                numbers[j-1] = numbers[j];

                numbers[j] = temp;

               }

           }

        }

        StringBuilder sb = new StringBuilder();

        for(int i=0;i<numbers.length;i++){

           sb.append(Integer.toString(numbers[i]));

        }

        return sb.toString();

    }

    /**

     * 返回true:m>n 返回false: m<n

     */

    public boolean compare(String mn,String nm){

        int i = mn.compareTo(nm);

        if(i>=0){

           return true;

        }

        else {

           return false;

       }

}

}

33.醜數

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

public class Solution {

    public int GetUglyNumber_Solution(int index) {

        if(index<=0){

           return 0;

        }

        int[] num = new int[index];

        num[0] = 1;

        int next = 1;

        int p2 = 0; //在醜數基礎上乘以2

        int p3 = 0; //在醜數基礎上乘以3

        int p5 = 0; //在醜數基礎上乘以5

        while(next<index){

           int min = getMin(num[p2]*2, num[p3]*3, num[p5]*5);

           num[next] = min;

           while(num[p2]*2<=num[next]){

               p2++;

           }

           while(num[p3]*3<=num[next]){

               p3++;

           }

           while(num[p5]*5<=num[next]){

               p5++;

           }

            next++;      

        }

        int ugly = num[next-1];

        return ugly;    

    }

  

    public int getMin(int number1,int number2,int number3){

        int number = number1<number2 ? number1:number2;

        return number<number3 ? number:number3;

    }

}

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

在一個字符串(1<=字符串長度<=10000,全部由字母組成)中找到第一個只出現一次的字符,並返回它的位置

import java.util.HashMap;

import java.util.Map;

public class Solution {

    public int FirstNotRepeatingChar(String str) {

        if(str==null || str.length()==0){

           return -1;

        }

        Map<Character, Integer> map = new HashMap<Character, Integer>();

        for(int i=0;i<str.length();i++){

           if(map.containsKey(str.charAt(i))){

               int time = map.get(str.charAt(i));

               time++;

               map.put(str.charAt(i), time);

           }

           else {

              map.put(str.charAt(i), 1);

           }

        }

        for(int i=0;i<str.length();i++){

           int time = map.get(str.charAt(i));

           if(time==1){

               return i;

           }

        }

        return -1;

    }

}

35.歸併排序

public class Solution {

    public void Merge(int[] array,int start,int middle,int end){

       int leftLength = middle-start+1;

       int rightLength = end-middle;

       int[] L = new int[middle-start+1];

       int[] R = new int[end-middle];

       int lIndex;

       int rIndex;

       int k;

       for(k=start,lIndex=0;lIndex<leftLength;k++){

           L[lIndex] = array[k];

           lIndex++;

       }

       for(k=middle+1,rIndex=0;rIndex<rightLength;k++){

           R[rIndex] = array[k];

           rIndex++;

       }

       for(k=start,lIndex=0,rIndex=0;lIndex<leftLength && rIndex<rightLength;k++){

           if(L[lIndex]<=R[rIndex]){

              array[k] = L[lIndex];

              lIndex++;

           }

           else {

              array[k] = R[rIndex];

              rIndex++;

           }

       }

       if(lIndex<leftLength){

           for(int i=lIndex;i<leftLength;i++,k++){

              array[k] = L[i];

           }

         

       }

       if(rIndex<rightLength){

           for(int i=rIndex;i<rightLength;i++,k++){

              array[k] = R[i];

           }

         

       }

    }

  

    public void MergeSort(int[] array,int start,int end){

       if(start<end){

           int middle = (start+end)/2;

           MergeSort(array,start,middle);

           MergeSort(array, middle+1, end);

           Merge(array, start, middle, end);

       }

    }

    @Test

    public void mytest(){

       int[] array = {9,8,7,5,6,7,8,7,6,5,4,3,2,1,0,9,8,7,8};

       int length = array.length;

       MergeSort(array,0,length-1);

       for(int i=0;i<length;i++){

           System.out.print(array[i]+"  ");

       }

    }

}

36.數組中的逆序對

在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007

public class Solution {

    public int InversePairs(int [] array) {

        if(array==null || array.length==0){

           return -1;

        }

        int[] copy = new int[array.length];

        for(int i=0;i<array.length;i++){

           copy[i] = array[i];

        }

        int count = InversePairsCore(copy,array,0,array.length-1);

        return count;

    }

    public int InversePairsCore(int[] copy,int[] array,int start,int end){

        if(start == end){

           copy[start] = array[start];

           return 0;

        }

        int middle = (start+end)/2;

        int left = InversePairsCore(array,copy,start,middle)%1000000007;

        int right = InversePairsCore(array,copy,middle+1,end)%1000000007;

        //指向前半段的最後一個數字下標

        int i = middle;

        //指向後半段最後一個數字的下標

        int j = end;

        int indexCopy = end;

        int count = 0;

        while(i>=start && j>=middle+1){

           if(array[i] > array[j]){

               count = count + j - middle;

               copy[indexCopy] = array[i];

               indexCopy--;

               i--;

              if(count>=1000000007)//數值過大求餘

                     {

                  count%=1000000007;

                     }

           }

           else {

              copy[indexCopy] = array[j];

              indexCopy--;

              j--;

           }

        }

        for(;i>=start;i--){

           copy[indexCopy] = array[i];

           indexCopy--;

        }

        for(;j>=middle+1;j--){

           copy[indexCopy] = array[j];

           indexCopy--;

        }

        return (left+right+count)%1000000007;

        }

}

37.兩個鏈表的第一個公共結點

輸入兩個鏈表,找出它們的第一個公共結點。

public class Solution {

    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {

        if(pHead1==null || pHead2==null){

           return null;

        }

        int length1 = getLength(pHead1);

        int length2 = getLength(pHead2);

        int length;

        ListNode listNodeLong = null;

        ListNode listNodeShort = null;

        if(length1 > length2){

           length = length1 - length2;

           listNodeLong = pHead1;

           listNodeShort = pHead2;

        }

        else {

           length = length2 - length1;

           listNodeLong = pHead2;

           listNodeShort = pHead1;

       }

        for(int i=0;i<length;i++){

           listNodeLong = listNodeLong.next;

        }

        while(listNodeLong!=null && listNodeShort!=null && listNodeLong!=listNodeShort){

           listNodeLong = listNodeLong.next;

           listNodeShort = listNodeShort.next;

        }

      

        ListNode commonNode = listNodeLong;

        return commonNode;

    } 

    public int getLength(ListNode head){

        if(head==null){

           return 0;

        }

        int count = 0;

        while(head!=null){

           count++;

           head = head.next;

        }

        return count;

    }

}

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

統計一個數字在排序數組中出現的次數。

public class Solution {

    public int GetNumberOfK(int [] array , int k) {

        if(array==null || array.length==0){

           return 0;

        }

        int number = 0;

        int first = getFirstK(array, k, 0, array.length-1);

        int last = getLastK(array, k, 0, array.length-1);

        if(first>=0 && last>=0){

           number = last - first +1;

        }

        return number;  

    }

    public int getLastK(int[] array,int k,int start,int end){

        if(start > end){

           return -1;

        }

        int middle = (end+start)/2;

        if(array[middle] > k){

           end = end-1;

        }

        else if(array[middle]<k) {

           start = start+1;

       }

        else{

           if((middle<array.length-1 && array[middle+1]!=k) || middle==array.length-1){

               return middle;

           }

           else {

              start = middle+1;

           }

        }

        return getLastK(array,k,start,end);

      

    }

    public int getFirstK(int[] array,int k,int start,int end){

        if(start>end){

           return -1;

        }

        int middle = (end+start)/2;

        if(array[middle]>k){

           end = middle-1;

        }

        else if(array[middle]<k){

           start = middle+1;

        }

        else {

           if((middle>0 && array[middle-1]!=k) || middle==0){

              return middle;

           }

           else{

              end = middle-1;

           }

       }

        return getFirstK(array,k,start,end);

    }

}

39.二叉樹的深度

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

public class Solution {

    public int TreeDepth(TreeNode root) {

        if(root == null){

            return 0;

        }

        int left = TreeDepth(root.left);

        int right = TreeDepth(root.right);

      

        int depth = left>right ? (left+1) : (right+1);

        return depth;

    }

}

40.平衡二叉樹

輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹

方法一:

public class Solution {

    public int TreeDepth(TreeNode root) {

        if(root == null){

            return 0;

        }

        int left = TreeDepth(root.left);

        int right = TreeDepth(root.right);

      

        int depth = left>right ? (left+1) : (right+1);

        return depth;

    }

    public boolean IsBalanced_Solution(TreeNode root) {

        if(root == null){

            return true;

        }

        int left = TreeDepth(root.left);

        int right = TreeDepth(root.right);

        int differ = left-right;

        if(differ>1 || differ<-1){

            return false;

        }

        return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);

    }

}

方法二:採用後序遍歷

public class Solution {

    private boolean isBalanced = true;

    public boolean IsBalanced_Solution(TreeNode root) {

        getDepth(root);

        return isBalanced;

      

    }

    public int getDepth(TreeNode root){

        if(root==null){

           return 0;

        }

        int left = getDepth(root.left);

        int right = getDepth(root.right);

        int differ = left - right;

        if(differ>1 || differ<-1){

           isBalanced = false;

        }

        return left > right ? (left+1) : (right+1);

    }

}

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

一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。

public class Solution {

    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {

        if(array==null || array.length==0){

            return;

        }

        int resultOR = 0; // 異或結果

        for(int i=0;i<array.length;i++){

            resultOR = resultOR ^ array[i];

        }

        int indexOf1 = findFirst1(resultOR); //找到第一個爲1的位置

        num1[0] = 0;

        num2[0] = 0;

        for(int j=0;j<array.length;j++){

            //根據第一個爲1的位置,分離數組

            if(isBit1(array[j],indexOf1)){

               num1[0] = num1[0] ^ array[j];

            }

            else{

               num2[0] = num2[0] ^ array[j];

            }

        }

      

    }

    //找到第一個出現1的位置

    public int findFirst1(int num){

        int indexBit = 0;

        while(((num & 1)==0) && (indexBit<32)){

           num = num >> 1; // 右移

           indexBit++;

        }

        return indexBit;

    }

    //判斷第n位是否是1

    public boolean isBit1(int num,int indexBit){

        num = num >> indexBit;

        if(((num&1)==0)){

           return false;

        }

        return true;

    }

}

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

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

import java.util.ArrayList;

public class Solution {

    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {

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

        if(sum < 3){

           return lists;

        }

        int small = 1;

        int big = 2;

        int curSum = small + big;

        int middle = (sum+1)/2;

        while(small < middle){

           if(curSum == sum){

               lists.add(getNum(small, big));

           }

           while(curSum>sum && small<middle){

               curSum = curSum -small;

               small = small+1;

               if(curSum==sum){

  lists.add(getNum(small, big));

               }

           }

           big++;

           curSum = curSum+big;

        }

        return lists;

     

    }

    public ArrayList<Integer> getNum(int small,int big){

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

        for(int i=small;i<=big;i++){

           list.add(i);

        }

        return list;

    }

}

43.和爲S的兩個數字

輸入一個遞增排序的數組和一個數字S,在數組中查找兩個數,是的他們的和正好是S,如果有多對數字的和等於S,輸出兩個數的乘積最小的。

public class Solution {

    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {

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

        if(array==null || array.length==0){

           return list;

        }

        int small = 0;

        int big = array.length-1;

        int curSum;

        while(small<big){

           curSum = array[small]+array[big];

           if(curSum<sum){

               small++;

           }

           else if(curSum>sum){

               big--;

           }

           else {

               list.add(array[small]);

               list.add(array[big]);

               return list;

           }

        }

        return list;     

    }

}

44.左旋轉字符串

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

public class Solution {

    public String LeftRotateString(String str,int n) {

        if(str==null){

           return null;

        }

        if(n>=str.length()){

           return str;

        }

        char[] cs = str.toCharArray();

        //全部翻轉

        Reverse(cs,0,cs.length-1);

        //翻轉前部分

        Reverse(cs,0,cs.length-1-n);

        //翻轉後部分

        Reverse(cs,cs.length-n,cs.length-1);

        return String.valueOf(cs);

      

    }

    public void Reverse(char[] str,int begin,int end){

        int i=begin;

        int j = end;

        char temp;

        while(i <= j){

           temp = str[i];

           str[i] = str[j];

           str[j] = temp;

           i++;

           j--;     

        }

}

}

45.翻轉單詞順序列

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

public class Solution {

    public String ReverseSentence(String str) {

        if(str==null){

           return null;

        }

        char[] cs = str.toCharArray();

        Reverse(cs,0,cs.length-1);

        int length = 0;

        int i;

        for(i=0;i<cs.length;i++){

            if(cs[i]==' '){

               int begin = i-length;

               int end = i-1;

               Reverse(cs,begin,end);

               length = 0;

            }

            else {

               length++;

           }

        }

        //最後一個單詞進行翻轉

        Reverse(cs,i-length,i-1);

      

        return String.valueOf(cs);

      

    }

    public void Reverse(char[] str,int begin,int end){

        int i=begin;

        int j = end;

        char temp;

        while(i <= j){

           temp = str[i];

           str[i] = str[j];

           str[j] = temp;

           i++;

           j--;     

        }

}

}

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的運氣如何。爲了方便起見,你可以認爲大小王是0。

import java.util.Arrays;

public class Solution {

    public boolean isContinuous(int [] numbers) {

        if(numbers==null || numbers.length<5){

           return false;

        }

        Arrays.sort(numbers);

        int count1 = 0; // 記錄有多少個大小王

        int count2 = 0; //記錄有多少個空缺

        int i=0;

        while(numbers[i]==0){

           i++;

           count1++;

        }

        int lastNum = numbers[i];

        for(i=i+1;i<numbers.length;i++){

           if(numbers[i]==0){

               count1++;

           }

           else {

               //出現了對子,不可能是連子

              if(numbers[i] == lastNum){

              return false;

              }

              else if(numbers[i] != lastNum+1){

                    int differ = numbers[i] - lastNum -1;

                    count2 = count2+differ;

              }

              lastNum = numbers[i];

           }

        }

        if(count2<=count1){

           return true;

        }

        return false;

}

}

47.孩子們的遊戲(圓圈中最後剩下的數)

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

方法一:用環形鏈表模擬圓圈

public class Solution {

    public int LastRemaining_Solution(int n, int m) {

        if(n==0 || m==0){

           return -1;

        }

        ListNode head = new ListNode(0);

        ListNode curNode = head;

        for(int i=1;i<n;i++){

            ListNode node = new ListNode(i);

            curNode.next = node;

            curNode = curNode.next;

        }

        curNode.next = head;

        ListNode last = curNode;

        int count = 1;

        while(last!=head){

            if(count<m){

               head = head.next;

               last = last.next;

               count++;

            }

            else if(count==m){

             

               last.next = head.next;

               head = head.next;

               count = 1;

            }

          

        }

        return head.val;

    }

方法二:

public class Solution {

    public int LastRemaining_Solution(int n, int m) {

        if(n<1 || m<1){

           return -1;

        }

        int last = 0;

        for(int i=2;i<=n;i++){

           last = (last+m) % i;

        }

        return last;

    }

}

48.求1+2+3+...+n

求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+Sum_Solution(n-1))>0;

        return sum;

    }

}

49.不用加減乘除做加法

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

public class Solution {

    public int Add(int num1,int num2) {

       int sum;

       int carry;

       do{

           sum = num1 ^ num2;

           carry = (num1 & num2) << 1;  //進位

           num1 = sum;

           num2 = carry;

       }while(carry!=0);

       return sum;

    }

}

50.把字符串轉換成整數

將一個字符串轉換成一個整數,要求不能使用字符串轉換整數的庫函數。 數值爲0或者字符串不是一個合法的數值則返回0

public class Solution {

    public int StrToInt(String str) {

        if(str.equals("") ||str.length()==0){

            return 0;

        }

        char[] cs = str.toCharArray();

        int minus = 1;

        if(cs[0]=='-'){

            minus = -1;

        }

        int i=0;

        if(cs[i]=='-'){

            if(cs.length==1){

               return 0;

            }

            minus = -1;

            i++;

        }

        if(cs[i]=='+'){

            if(cs.length==1){

               return 0;

            }

            minus = 1;

            i++;

        }

        int sum=0;

        int common = 1;

        for(int j=cs.length-1;j>=i;j--){

            if(cs[j]>='0' && cs[j]<='9'){

               sum = sum + (cs[j]-'0')*common;

               common = common*10;

               System.out.println(sum);

            }

            else{

               return 0;

            }

            if(sum>0x7FFFFFFF || sum<0x80000000){

               return 0;

            }

        }

        return sum*minus;

    }

51.數組中重複的數字

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

public class Solution {

    public boolean duplicate(int numbers[],int length,int [] duplication) {

      

        if(numbers==null || length<=1){

            return false;

        }

        int temp;

        for(int index=0;index<length-1;index++){

            while(numbers[index]!=index){

               if(numbers[numbers[index]]==numbers[index]){

   duplication[0] = numbers[index];

   return true;

               }

               temp = numbers[numbers[index]];

               numbers[numbers[index]] = numbers[index];

               numbers[index] = 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 class Solution {

    public int[] multiply(int[] A) {

        if(A==null || A.length==0){

           return null;

        }

        int length = A.length;

        int[] B = new int[length];

        int[] C = new int[length];

        int[] D = new int[length];

        C[0] = 1;

        D[length-1] = 1;

        for(int i=1;i<length;i++){

           C[i] = A[i-1] * C[i-1];

           D[length-1-i] = A[length-i] * D[length-i];

        }

        for(int i=0;i<length;i++){

           B[i] = C[i] * D[i];

        }

        return B;

    }

}

53.正則表達式匹配

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

public class Solution {

    public boolean match(char[] str, char[] pattern) {

    if (str == null || pattern == null) {

        return false;

    }

    int strIndex = 0;

    int patternIndex = 0;

    return matchCore(str, strIndex, pattern, patternIndex);

}

 

public boolean matchCore(char[] str, int strIndex, char[] pattern, int patternIndex) {

    //有效性檢驗:str到尾,pattern到尾,匹配成功

    if (strIndex == str.length && patternIndex == pattern.length) {

        return true;

    }

    //pattern先到尾,匹配失敗

    if (strIndex != str.length && patternIndex == pattern.length) {

        return false;

    }

    //模式第2個是*,且字符串第1個跟模式第1個匹配,分3種匹配模式;如不匹配,模式後移2位

    if (patternIndex + 1 < pattern.length && pattern[patternIndex + 1] == '*') {

        if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex != str.length)) {

            return matchCore(str, strIndex, pattern, patternIndex + 2)//模式後移2,視爲x*匹配0個字符

    || matchCore(str, strIndex + 1, pattern, patternIndex + 2)//視爲模式匹配1個字符

    || matchCore(str, strIndex + 1, pattern, patternIndex);//*匹配1個,再匹配str中的下一個

        } else {

            return matchCore(str, strIndex, pattern, patternIndex + 2);

        }

    }

    //模式第2個不是*,且字符串第1個跟模式第1個匹配,則都後移1位,否則直接返回false

if ((strIndex != str.length && pattern[patternIndex] == str[strIndex]) || (pattern[patternIndex] == '.' && strIndex !=

      str.length)) {

        return matchCore(str, strIndex + 1, pattern, patternIndex + 1);

    }

    return false;

    }

}

54.表示數值的字符串

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

public class Solution {

    public boolean isNumeric(char[] str) {

        String string = String.valueOf(str);

        return string.matches("[\\+-]?[0-9]*(\\.[0-9]*)?([eE][\\+-]?[0-9]+)?");

    }

}

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

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

public class Solution {

    StringBuilder str = new StringBuilder();

    int[] hashtable = new int[256]; //一共有256個字符

 

    public void Insert(char ch)

    {

        str.append(ch);

        //第一次讀入

        if(hashtable[ch]==0){

            hashtable[ch]=1;

        }

        //不是第一次讀入

        else{

            hashtable[ch] = hashtable[ch] +1;

        }

    }

 

    public char FirstAppearingOnce()

    {

        char[] ch = str.toString().toCharArray();

        for(int i=0;i<ch.length;i++){

           if(hashtable[ch[i]]==1){

               return ch[i];

           }

        }

        return '#';

    }

}

56.鏈表中環的入口結點

一個鏈表中包含環,請找出該鏈表的環的入口結點。

public class Solution {

 

    public ListNode EntryNodeOfLoop(ListNode pHead)

    {

        if(pHead==null || pHead.next==null){

            return null;

        }

        int count = isLoop(pHead);

        if(count == 0){

            return null;

        }

        ListNode fast = pHead;

        ListNode slow = pHead;

        for(int i=0;i<count;i++){

           fast = fast.next;

        }

        while(fast!=slow){

           fast = fast.next;

           slow = slow.next;

        }

        return fast;

    }

    //判斷是否存在環

    public int isLoop(ListNode pHead){

        ListNode fast = pHead.next.next;

        ListNode slow = pHead.next;

        while(fast!=slow){

           //不存在環

           if(fast==null || fast.next==null){

               return 0;

           }

           fast = fast.next.next;

           slow = slow.next;

        }

        ListNode nextNode = slow.next;

        int count = 1;

        while(nextNode!=slow){

           nextNode = nextNode.next;

           count++;

        }

        return count;   

}

}

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

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

public class Solution {

    public ListNode deleteDuplication(ListNode pHead)

    {

        if(pHead==null){

           return null;

        }

        if(pHead.next==null){

           return pHead;

        }

        ListNode lastNode = null;

        ListNode curNode = pHead;

        int count = 0;

        while(curNode!=null && curNode.next!=null){

           if(curNode.next.val != curNode.val){

               if(count>0){

  if(lastNode==null){

      pHead = curNode.next;

      count = 0;

  }

  else{

      lastNode.next = curNode.next;

      count = 0;

  }

               }

               else{

  lastNode = curNode;

               }

               curNode = curNode.next;

             

           }

           else{

               curNode = curNode.next;

               count++;

           }

        }

        if(count>0){

           if(lastNode==null){

               return null;

           }

           lastNode.next = null;

        }

        return pHead;   

}

}

58.二叉樹的下一個結點

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

public class Solution {

    public TreeLinkNode GetNext(TreeLinkNode pNode)

    {

        if(pNode==null){

            return pNode;

        }

       if (pNode.right != null) {

           TreeLinkNode node = pNode.right;

           while (node.left != null) {

              node = node.left;

           }

           return node;

       }

        while(pNode.next!=null){

            if(pNode.next.left==pNode){

               return pNode.next;

            }

            pNode = pNode.next;

        }

        return null;

}

}

59.對稱的二叉樹

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

public class Solution {

    boolean isSymmetrical(TreeNode pRoot)

    {

        return isSymmetricalCore(pRoot,pRoot);

    }

    public boolean isSymmetricalCore(TreeNode root1,TreeNode root2){

        if(root1==null && root2==null){

           return true;

        }

        if(root1==null || root2==null){

           return false;

        }

        if(root1.val!=root2.val){

           return false;

        }

        return isSymmetricalCore(root1.left,root2.right) && isSymmetricalCore(root1.right,root2.left);

}

}

60.按之字形順序打印二叉樹

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

import java.util.ArrayList;

import java.util.Stack;  

public class Solution {

    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {

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

       if (pRoot == null) {

           return lists;

       }

       Stack<TreeNode> leftToRight = new Stack<TreeNode>();

       Stack<TreeNode> rightToLeft = new Stack<TreeNode>();

       leftToRight.push(pRoot);

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

       root.add(pRoot.val);

       lists.add(root);

       while ((leftToRight.isEmpty() && !rightToLeft.isEmpty()) || (!leftToRight.isEmpty() && rightToLeft.isEmpty())) {

 

           if (!leftToRight.isEmpty()) {

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

              while (!leftToRight.isEmpty()) {

                    TreeNode curNode = leftToRight.pop();

                    if (curNode.right != null) {

                       rightToLeft.push(curNode.right);

                       list1.add(curNode.right.val);

                    }

                    if (curNode.left != null) {

                 rightToLeft.push(curNode.left);

                 list1.add(curNode.left.val);

                    }

              }

              if(list1.size()==0){

              return lists;

              }

              lists.add(list1);

           }

 

           if (!rightToLeft.isEmpty()) {

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

              while (!rightToLeft.isEmpty()) {

              TreeNode curNode = rightToLeft.pop();

  if (curNode.left != null) {

     leftToRight.push(curNode.left);

      list2.add(curNode.left.val);

  }

  if (curNode.right != null) {

     leftToRight.push(curNode.right);

     list2.add(curNode.right.val);

  }

              }

              if(list2.size()==0){

  return lists;

              }

              lists.add(list2);

           }

       }

       return lists;

       }

}

61.把二叉樹打印成多行

從上到下按層打印二叉樹,同一層結點從左至右輸出。每一層輸出一行。

import java.util.ArrayList;

import java.util.LinkedList;

import java.util.Queue;

public class Solution {

    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {

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

        if(pRoot==null){

           return lists;

        }

        Queue<TreeNode> queue1 = new LinkedList<TreeNode>();

        TreeNode node = new TreeNode(0);

        queue1.add(pRoot);

        queue1.add(node);

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

        lists.add(root);

        root.add(pRoot.val);

        while(!queue1.isEmpty()){

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

         

           while(queue1.peek()!=node){

               TreeNode curNode = queue1.poll();

               if(curNode.left!=null){

               queue1.add(curNode.left);

               list.add(curNode.left.val);

               }

               if(curNode.right!=null){

               queue1.add(curNode.right);

               list.add(curNode.right.val);

               }

           }

         

           queue1.add(queue1.poll());

           if(list.size()==0){

               return lists;

           }

           lists.add(list);

        }

        return lists;

    }

}

62.序列化二叉樹

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

public class Solution {

    String Serialize(TreeNode root) {

       if (root == null) {

           return "";

       }

       StringBuilder sb = new StringBuilder();

       Serialize1(root, sb);

       return sb.toString();

    }

 

    void Serialize1(TreeNode root, StringBuilder sb) {

       if (root == null) {

           sb.append("#,");

           return;

       }

       sb.append(root.val);

       sb.append(",");

       Serialize1(root.left, sb);

       Serialize1(root.right, sb);

    }

    int index=0;

    TreeNode Deserialize(String str) {

       if(str.length()==0){

           return null;

       }

       String[] s = str.split(",");

       return Deserialize1(s);

    }

    TreeNode Deserialize1(String[] s){

       if(s[index].equals("#")){

           index++;

           return null;

       }

       int val = Integer.parseInt(s[index]);

       System.out.println(val);

       index++;

       TreeNode node = new TreeNode(val);

       node.left = Deserialize1(s);

       node.right = Deserialize1(s);

       return node;

    }

}

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

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

public class Solution {

    private int count;

    TreeNode KthNode(TreeNode pRoot, int k)

    {

        if(pRoot==null || k==0){

            return null;

        }

        count = k;

        return KthNodeCore(pRoot);

    }

  

    TreeNode KthNodeCore(TreeNode pRoot){

        TreeNode targe = null;

        if(pRoot.left!=null){

           targe = KthNodeCore(pRoot.left);

        }

        if(count==1){

           targe = pRoot;

        }

        count--;

        if(targe==null && pRoot.right!=null){

           targe = KthNodeCore(pRoot.right);

        }

        return targe;

    }

}

64.數據流中的中位數

如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。

import java.util.Comparator;

import java.util.PriorityQueue;

public class Solution {

    private int count = 0;

    private PriorityQueue<Integer> minHeap = new PriorityQueue<>();

    private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(15,new Comparator<Integer>() {

 

       @Override

       public int compare(Integer o1, Integer o2) {

           // TODO Auto-generated method stub

           return o2 - o1;

       }

     

    });      

    

    public void Insert(Integer num) {

        if (count %2 == 0) {//當數據總數爲偶數時,新加入的元素,應當進入小根堆

            //(注意不是直接進入小根堆,而是經大根堆篩選後取大根堆中最大元素進入小根堆)

            //1.新加入的元素先入到大根堆,由大根堆篩選出堆中最大的元素

            maxHeap.offer(num);

            int filteredMaxNum = maxHeap.poll();

            //2.篩選後的【大根堆中的最大元素】進入小根堆

            minHeap.offer(filteredMaxNum);

        } else {//當數據總數爲奇數時,新加入的元素,應當進入大根堆

            //(注意不是直接進入大根堆,而是經小根堆篩選後取小根堆中最大元素進入大根堆)

            //1.新加入的元素先入到小根堆,由小根堆篩選出堆中最小的元素

            minHeap.offer(num);

            int filteredMinNum = minHeap.poll();

            //2.篩選後的【小根堆中的最小元素】進入大根堆

            maxHeap.offer(filteredMinNum);

        }

        count++;

    }

    

    public Double GetMedian() {

        if (count %2 == 0) {

            return new Double((minHeap.peek() + maxHeap.peek())) / 2;

        } else {

            return new Double(minHeap.peek());

        }

    }

}

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;

import java.util.LinkedList;

public class Solution {

    public ArrayList<Integer> maxInWindows(int [] num, int size)

    {

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

        if(num==null || num.length==0 || size>num.length || size==0){

            return list;

        }

        LinkedList<Integer> queue = new LinkedList<>(); // 雙端隊列

        for(int i=0;i<num.length;i++){

          

            while(!queue.isEmpty() && num[queue.getLast()]<=num[i]){

               queue.removeLast();

            }

            queue.add(i);

            //移除無效的數字

            if(queue.peek() == i-size){

               queue.poll();

            }

            if(i >= size-1){

               list.add(num[queue.peek()]);

            }

        }

        return list;

}

}

66.矩陣中的路徑

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

public class Solution {

    int index=0;

    int m_row;

    int m_col;

    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)

    {

        if(matrix==null || matrix.length==0 || matrix.length<rows*cols

               || str==null || str.length==0 || str.length>matrix.length){

           return false;

        }

        if(rows<=0 || cols<=0){

           return false;

        }

        m_row = rows;

        m_col = cols;

        int[] visited = new int[rows*cols];

        boolean flag = false;

        for(int i=0;i<rows;i++){

           for(int j=0;j<cols;j++){

               flag = hasPathCore(matrix,i,j,str,visited);

               if(flag){

              return true;

               }

           }

        }

        return false;

    }

    public boolean hasPathCore(char[] matrix, int row, int col, char[] str,int[] visited){

        boolean flag = false;

        //當前格子的字符相等時的情況

        if(row>=0 && row<m_row && col>=0 && col<m_col

               && visited[row*m_col+col]!=1 && matrix[row*m_col+col]==str[index] ){

           index++;

           System.out.println("index:"+index+"-----matrix:"+matrix[row*m_col+col]);

           visited[row*m_col+col] = 1;

      

        if(index==str.length){

           return true;

        }

         flag = hasPathCore(matrix,row,col+1,str,visited) ||

               hasPathCore(matrix,row+1,col,str,visited) ||

               hasPathCore(matrix,row,col-1,str,visited) ||

               hasPathCore(matrix,row-1,col,str,visited);

        if(!flag){

           index--;

           visited[row*m_col+col] = 0;

           return false;

        }

        }

        return flag;

}

}

67.機器人的運動範圍

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

public class Solution {

   int m_rows;

   int m_cols;

   int m_threshold;

    public int movingCount(int threshold, int rows, int cols)

    {

        int[] visited = new int[rows*cols];

        m_rows = rows;

        m_cols = cols;

        m_threshold = threshold;

        return movingCountCore(0,0,visited);

      

    }

  

    public int movingCountCore(int row,int col,int[] visited){

       if(row<0 || row>=m_rows || col<0 || col>=m_cols){

          return 0;

       }

       int index = row*m_cols+col;

       if(visited[index]==1 || !checkSum(row,col)){

          return 0;

       }

       visited[index]=1;

       return 1+movingCountCore(row+1,col,visited)+

              movingCountCore(row-1,col,visited)+

              movingCountCore(row,col-1,visited)+

              movingCountCore(row,col+1,visited);

    } 

    public boolean checkSum(int row,int col){

       int sum = 0;

       while(row!=0){

          sum = sum + row%10;

          row = row/10;

       }

       while(col!=0){

          sum = sum + col%10;

          col = col/10;

       }

     

       if(sum>m_threshold){

          return false;

       }

       return true;

}

}

 

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