牛客網刷題總結


1.二維數組中的查找

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

誤區:以斜對角的數組為比較對象,並不是大於array[i][i],小於array[i+1][i+1]的數字還很多很多;滿足這個條件只能排除左上角的一小塊。

 1 //思路:矩陣是有序的,從左下角來看,向上數字遞減,向右數字遞增,因此從左下角開始查找,當要查找數字比左下角數字大時。右移要查找數字比左下角數字小時,上移。
 2 class Solution {
 3 public:
 4     bool Find(vector<vector<int> > array,int target) {
 5         int rowCount = array.size();
 6         int colCount = array[0].size();
 7         int i,j;
 8         for(i=rowCount-1,j=0;i>=0&&j<colCount;){
 9             if(target == array[i][j])
10                 return true;
11             if(target < array[i][j]){
12                 i--;
13                 continue;
14             }
15             if(target > array[i][j]){
16                 j++;
17                 continue;
18             }
19         }
20         return false;
21     }
22 };
View Code

 2.替換空格

題目描述:請實現一個函數,將一個字符串中的每個空格替換成“%20”。例如,當字符串為We Are Happy.則經過替換之后的字符串為We%20Are%20Happy。

誤區:用循環時,注意到每替換一個空格,字符串的長度都會增加。所以循環必定不能遍歷新的字符串。

 1 public class Solution {
 2     public String replaceSpace(StringBuffer str) {
 3         int l=str.length();
 4         for(int i=0;i<l;i++){
 5             if(str.charAt(i)==' ')
 6                 str.replace(i, i+1, "%20");
 7         }
 8         return str.toString();
 9     }
10 }
View Code
 1 //新建一個字符串,在后面疊加。但是這個方法並不是在原有數組上進行改動。
 2 public class Solution {
 3     public String replaceSpace(StringBuffer str) {
 4         int l=str.length();
 5         String ans="";
 6         for(int i=0;i<l;i++){
 7             if(str.charAt(i)==' ')
 8                 ans+="%20";
 9             else
10                 ans+=str.charAt(i);
11         }
12         return ans;
13     }
14 }
15 
16 //這個就比較投機了
17 public class Solution {
18     public static String replaceSpace(StringBuffer str) {
19           String str1=str.toString();  
20           String str2=str1.replace(" ","%20");  
21           return str2;  
22 
23     }
24 }
View Code

3.從尾到頭打印鏈表

題目描述:輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList

誤區:當java中new了一個對象之后,這個實例就不等於null了,就已經分配內存了;返回的時候不要返回null,會報空指針異常,要用return new ArrayList<>();

 1 //這段代碼超時了
 2 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
 3         ArrayList<Integer> ans=new ArrayList<>();
 4         if(listNode==null)
 5             return new ArrayList<>();
 6         else if(listNode.next==null){
 7             ans.add(listNode.val);
 8             return ans;
 9         }
10         ListNode head=listNode;
11         ListNode temphead=listNode;
12         ListNode first=null,second=null;
13         while(listNode.next!=null){
14             first=listNode;
15             second=listNode.next;
16             listNode=listNode.next;
17         }
18         while(true){
19             ans.add(second.val);
20             ans.add(first.val);
21             if(first==head)
22                 break;
23             second=first;
24             while(temphead.next!=null){
25                 if(temphead.next==first)
26                     first=temphead;
27             }
28             temphead=listNode;
29         }
30         return ans;
31     }
32 
33 //這段用了一個數據結構:棧,很簡單
34 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
35         ArrayList<Integer> ans=new ArrayList<>();
36         if(listNode==null)
37             return new ArrayList<>();
38        
39         Stack<Integer> temp=new Stack<>();
40         while(listNode!=null){
41             temp.push(listNode.val);
42             listNode=listNode.next;
43         }
44         while(!temp.empty()){
45             ans.add(temp.pop());
46         }
47         return ans;
48     }
49 
50 //這段用了兩個arraylist,一個前向一個逆向
51 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
52         ArrayList<Integer> list = new ArrayList<Integer>();
53         ArrayList<Integer> result = new ArrayList<Integer>();
54         ListNode temp = listNode;
55         while ( temp != null ) {
56             list.add( temp.val );
57             temp = temp.next;
58         }
59         for ( int i = list.size()-1; i>=0; i-- ) {
60             result.add( list.get(i) );
61         }
62         return result;
63     }
View Code

4.重建二叉樹(中等題)

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

注意點:遞歸傳入的參數要仔細斟酌

 1 public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
 2         if(pre==null || in==null || pre.length!=in.length)
 3             return null;
 4         return  help(pre,in,0,pre.length-1,0,in.length-1);
 5     }
 6     public TreeNode help(int [] pre,int [] in,int startpre,int endpre,int startin,int endin){
 7         if(startin>endin || startpre>endpre)
 8             return null;
 9         int root=pre[startpre];
10         int i=0;
11         for(i=startin;i<=endin;i++){
12             if(in[i]==root)
13                 break;
14         }
15         TreeNode ans=new TreeNode(root);
16         ans.left=help(pre,in,startpre+1,startpre+i-startin,startin,i-1);
17         ans.right=help(pre,in,startpre+i-startin+1,endpre,i+1,endin);
18         return ans;
19     }
View Code

5.反轉鏈表

題目描述:輸入一個鏈表,反轉鏈表后,輸出新鏈表的表頭。

誤區:是在原鏈表的基礎上反轉,盡量不要借助外部存儲結構

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

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode cur=head;
        ListNode pre=null;
        ListNode next=null;
        while(cur!=null){
            next=cur.next;
            cur.next=pre;
            
            pre=cur;
            cur=next;    
        }
        return pre;
    }
}
View Code

6.合並兩個排序的鏈表

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

誤區:用遞歸會比較簡單;鏈表題要注意空指針異常和最后要返回頭指針

//遞歸
鏈接:https://www.nowcoder.com/questionTerminal/d8b6b4358f774294a89de2a6ac4d9337
來源:牛客網

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



//非遞歸

public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode temp1=list1;
        ListNode temp2=list2;
        while(temp2 != null){
            //System.out.println(temp1.val);

            //System.out.println();
            if (temp2.val >= temp1.val && temp1.next != null && temp2.val <= temp1.next.val ) {
                ListNode node = new ListNode(temp2.val);
                node.next = temp1.next;
                temp1.next = node;
                temp1 = temp1.next;
                temp2 = temp2.next;
            } else if (temp2.val < temp1.val) {
                ListNode node = new ListNode(temp2.val);
                node.next = temp1;
                temp1 = node;
                temp2 = temp2.next;
            } else if (temp2.val >= temp1.val && temp1.next==null) {
                ListNode node = new ListNode(temp2.val);
                temp1.next = node;
                temp1=temp1.next;
                temp2 = temp2.next;
            } else
                temp1 = temp1.next;

        }
        return list1;
    }
View Code

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

題目描述:輸入一個鏈表,輸出該鏈表中倒數第k個結點。

誤區:在java中,判斷一個數據結構是否為空,需要與null比較,!=或者==

 1 public class Solution {//復雜度為2n-k
 2     public ListNode FindKthToTail(ListNode head,int k) {
 3         if(!head)
 4             return null;
 5         int n=0;
 6         ListNode listnode=new ListNode(0);
 7         listnode=head;
 8         while(listnode){
 9             listnode=listnode.next;
10             n++;
11         }
12         if(k>n)
13             return null;
14         for(int i=0;i<n-k;i++){
15             head=head.next;
16         }
17         return head;
18     }
19 }
20 
21 
22 public class Solution {//復雜度為n
23     public ListNode FindKthToTail(ListNode head,int k) {
24         if(head==null||k<=0){
25             return null;
26         }
27         ListNode pre=head;
28         ListNode last=head;       
29         for(int i=1;i<k;i++){
30             if(pre.next!=null){
31                 pre=pre.next;
32             }else{
33                 return null;
34             }
35         }
36         while(pre.next!=null){
37             pre = pre.next;
38             last=last.next;
39         }
40         return last;
41     }
42 }
View Code

 8.樹的子結構

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

誤區:子結構的題,要想着從大的樹每個結點出發,然后遍歷小的樹,看看能不能遍歷完全

 1 public class Solution {
 2     public boolean HasSubtree(TreeNode root1,TreeNode root2){
 3         if(root1==null || root2==null)
 4             return false;
 5         else
 6             return help(root1,root2) || help(root1.left,root2) || help(root1.right,root2);
 7     }
 8 
 9     public boolean help(TreeNode root1,TreeNode root2){
10         if(root2==null)
11             return true;
12         if(root1==null)
13             return false;
14         if(root1.val==root2.val)
15             return help(root1.left,root2.left) && help(root1.right,root2.right);
16         else 
17             return false;
18     }
19 }
View Code

9.順時針打印矩陣(中等題)

題目描述:輸入一個矩陣,按照從外向里以順時針的順序依次打印出每一個數字,例如,如果輸入如下4 X 4矩陣: 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.

誤區:邊界條件很重要,看這篇博客https://blog.csdn.net/weixin_37672169/article/details/80207479

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        int rows = matrix.length;
        int cols = matrix[0].length;
        if(matrix == null || cols <= 0 || rows <= 0){
            return null;
        }
        int start = 0;
        while(cols > start*2 && rows > start*2){
            printMatrixInCircle(list, matrix, cols, rows, start);
            ++start;
        }
        return list;
    }
    private void printMatrixInCircle(ArrayList<Integer> list, int[][] nums,
                                    int cols, int rows, int start) {
        int endX = cols - 1 - start;
        int endY = rows - 1 - start;

        //從左到右打印一行
        for (int i = start; i <= endX; ++i) {
            int number = nums[start][i];
            list.add(number);
        }
        //從上到下打印一列
        if(start < endY){
            for (int i = start + 1; i <= endY; ++i) {
                int number = nums[i][endX];
                list.add(number);
            }
        }
        //從右向左打印一行
        if(start < endX && start < endY){
            for (int i = endX-1; i >= start; --i) {
                int number = nums[endY][i];
                list.add(number);
            }
        }
        //從下向上打印一列
        if(start < endX && start < endY - 1){
            for (int i = endY-1; i >= start + 1; --i) {
                int number = nums[i][start];
                list.add(number);
            }
        }
    }
}
View Code

 10.棧的壓入、彈出序列

題目描述:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否可能為該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列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.length==0) return false;
        Stack<Integer> stack=new Stack<Integer> ();
        for(int i=0,j=0;i<pushA.length;i++){
            stack.push(pushA[i]);
            while(j < pushA.length && stack.peek() == popA[j]){
                stack.pop();
                j++;
            }
        }
        return stack.empty();
    }
}
View Code

 11.二叉搜索樹的后序遍歷序列

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

誤區:當有多個情況需要考慮的時候,並行可以轉化成串行

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        int len=sequence.length;
        if(len==0)
            return false;
        return help(sequence,0,len-1);
    }
    boolean help(int [] sequence,int start,int end){
        if(start>=end)
            return true;
        int i=end;
        while(i > start && sequence[i-1] > sequence[end])
            i--;
        for(int j=i-1;j>=start;j--){
            if(sequence[j]>sequence[end])
                return false;
        }
        return help(sequence,start,i-1) && help(sequence,i,end-1);


    }
}
View Code

 12.機器人的運動范圍

題目描述:地上有一個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 ans=0;
    public int movingCount(int threshold, int rows, int cols){

        int [][]nums=new int[rows+5][cols+5];
        help(0,0,threshold,rows, cols,nums);
        return ans;
    }

    private void help(int i,int j,int threshold,int rows, int cols,int [][]nums){
        if(i>rows-1 || j>cols-1 || !check(i,j,threshold))
            return;
        if(nums[i][j]==0){
            ans++;
            nums[i][j]=1;
            help(i+1,j, threshold, rows, cols, nums);
            help(i,j+1, threshold, rows, cols, nums);
        }

    }

    private boolean check(int i,int j,int threshold){
        int ans=0;
        while(i>0){
            ans+=i%10;
            i=(i-(i%10))/10;
        }
        while(j>0){
            ans+=j%10;
            j=(j-(j%10))/10;
        }
        //System.out.println(ans);
        return ans<=threshold;
    }


    public static void main(String [] args){
        Solution s=new Solution();
        System.out.println(s.movingCount(5,10,10));
    }

}





public class Solution2 {
    public int movingCount(int threshold, int rows, int cols) {
        if (threshold < 0) return 0;
        int[] board = new int[rows * cols];
        setBoard(board, cols, threshold);
        UnionFind uf = new UnionFind(rows * cols);
        for (int i = 0; i < rows * cols; i++) {
            int row = i / cols;
            int col = i % cols;
            if (board[i] == 1) {
                if (col + 1 < cols && board[row * cols + col + 1] == 1)
                    uf.union(i, row * cols + col + 1);
                if (row + 1 < rows && board[(row + 1) * cols + col] == 1)
                    uf.union(i, (row + 1) * cols + col);
            }
        }
        return uf.getCount();
    }

    private void setBoard(int[] board, int cols, int threshold) {
        for (int i = 0; i < board.length; i++) {
            int row = i / cols;
            int col = i % cols;
            if (getSum(row) + getSum(col) <= threshold) {
                board[i] = 1;
            }
        }
    }

    private int getSum(int i) {
        int sum = 0;
        while (i != 0) {
            sum += i % 10;
            i = i / 10;
        }
        return sum;
    }

    class UnionFind {
        private int count = 1;
        private int[] parent;

        UnionFind(int n) {
            parent = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        int getCount() {
            return count;
        }

        int find(int i) {
            if (parent[i] != i) {
                parent[i] = find(parent[i]);
            }
            return parent[i];
        }

        void union(int i, int j) {
            int pi = find(i);
            int pj = find(j);
            if (pi == pj) return;
            int pos = find(0);
            if (pi == pos || pj == pos) {
                parent[pi] = pj;
                count++;
            }
        }
    }
}
View Code

 13.復雜鏈表的復制(中等題)

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

誤區:這道題的解決方法是散步,1.將每個結點的數值進行復制,賦給新的結點,把新的結點插在相應的結點后面;2.依次復制每個結點的隨機指針;3.分離。要注意的是,原鏈表的結構不能改變,不然通不過,所以最后還有一個還原的操作

 1 public class Solution {
 2     public RandomListNode Clone(RandomListNode pHead) {
 3         if(pHead==null)
 4             return null;
 5 
 6         RandomListNode head=pHead;
 7         while(head!=null){
 8             RandomListNode temp=new RandomListNode(head.label);
 9             temp.next=head.next;
10             head.next=temp;
11             head=head.next.next;
12         }
13 
14         RandomListNode head2=pHead;
15         while(head2!=null){
16             head2.next.random=head2.random==null?null:head2.random.next;
17             head2=head2.next.next;
18         }
19 
20         RandomListNode head3=pHead.next;
21         RandomListNode newhead=pHead.next;
22          RandomListNode head4=pHead;
23         while(head3.next!=null){
24             RandomListNode temp=head3.next;
25             head3.next=head3.next.next;
26             head4.next=temp;
27             head3=head3.next;
28             head4=head4.next;
29         }
30         head4.next=null;
31         return newhead;
32 
33     }
34 }
View Code

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

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

誤區:

 1 /**
 2 public class TreeNode {
 3     int val = 0;
 4     TreeNode left = null;
 5     TreeNode right = null;
 6 
 7     public TreeNode(int val) {
 8         this.val = val;
 9 
10     }
11 
12 }
13 */
14 
15 
16 public class Solution {
17     TreeNode head = null;
18     TreeNode realHead = null;
19     public TreeNode Convert(TreeNode pRootOfTree) {
20         ConvertSub(pRootOfTree);
21         return realHead;
22     }
23      
24     private void ConvertSub(TreeNode pRootOfTree) {
25         if(pRootOfTree==null) return;
26         ConvertSub(pRootOfTree.left);
27         if (head == null) {
28             head = pRootOfTree;
29             realHead = pRootOfTree;
30         } else {
31             head.right = pRootOfTree;
32             pRootOfTree.left = head;
33             head = pRootOfTree;
34         }
35         ConvertSub(pRootOfTree.right);
36     }
37 }
View Code

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

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

誤區:這道題如果用hash就很簡單,難的是怎么找空間復雜度為常數的方法,這里推薦“陣地攻守的思想”:第一個數字作為第一個士兵,守陣地;count = 1;遇到相同元素,count++;遇到不相同元素,即為敵人,同歸於盡,count--;當遇到count為0的情況,又以新的i值作為守陣地的士兵,繼續下去,到最后還留在陣地上的士兵,有可能是主元素。再加一次循環,記錄這個士兵的個數看是否大於數組一般即可。

 1 package hash;
 2 
 3 import java.util.HashMap;
 4 //數組中出現次數超過一半的數字
 5 
 6 //別人的思路:采用陣地攻守的思想:
 7 //第一個數字作為第一個士兵,守陣地;count = 1;
 8 //遇到相同元素,count++;
 9 //遇到不相同元素,即為敵人,同歸於盡,count--;當遇到count為0的情況,又以新的i值作為守陣地的士兵,繼續下去,到最后還留在陣地上的士兵,有可能是主元素。
10 //再加一次循環,記錄這個士兵的個數看是否大於數組一般即可。
11 public class Solution2 {
12     public int MoreThanHalfNum_Solution(int [] array) {
13         int len=array.length;
14         HashMap<Integer,Integer> hash=new HashMap<>();
15         for(int i=0;i<len;i++){
16 
17             if(hash.get(array[i])==null)
18                 hash.put(array[i],1);
19             else{
20 
21                 hash.put(array[i],hash.get(array[i])+1);
22             }
23             if(hash.get(array[i])>len/2)
24                 return array[i];
25         }
26         return 0;
27     }
28 
29     public int MoreThanHalfNum_Solution2(int [] array) {
30         int flag=array[0];
31         int count=1;
32         int nums=0;
33         for(int i=1;i<array.length;i++){
34             if(array[i]==flag)
35                 count++;
36             else
37                 count--;
38             if(count==0) {
39                 flag = array[i];
40                 count++;
41             }
42         }
43         for(int i=0;i<array.length;i++){
44             if(array[i]==flag)
45                 nums++;
46         }
47         if(nums>array.length/2)
48             return flag;
49         return 0;
50 
51     }
52 
53 }
View Code

 16.最小的k個數

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

誤區:這道題第一個想法是hash,也比較簡單,但是空間復雜度不定。網上常用方法是最大堆和分治。

 1 package 最大堆;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Iterator;
 5 import java.util.TreeSet;
 6 //最小的K個數
 7 public class Solution {
 8     public static ArrayList<Integer> getLeastNumbers(int []nums, int k) {
 9         ArrayList<Integer> list = new ArrayList<Integer>();
10         int lens = nums.length;
11         if (nums == null || lens == 0 || k > lens || k <= 0) {
12             return list;
13         }
14         TreeSet<Integer> kSet = new TreeSet<Integer>();
15         for (int i = 0; i < lens; i++) {
16             if (kSet.size() < k) {
17                 kSet.add(nums[i]);
18             } else if (nums[i] < kSet.last()) {
19                 kSet.remove(kSet.last());
20                 kSet.add(nums[i]);
21             }
22         }
23         Iterator<Integer> iterator = kSet.iterator();
24         while (iterator.hasNext()) {
25             list.add(iterator.next());
26         }
27         return list;
28     }
29 }
View Code

 17.矩陣中的路徑

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

誤區:如何把代碼寫的簡潔美觀是很重要的一點

  1 package shensou;
  2 
  3 //矩陣中的路徑
  4 public class Solution {
  5     public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
  6         int flag[] = new int[matrix.length];
  7         for (int i = 0; i < rows; i++) {
  8             for (int j = 0; j < cols; j++) {
  9                 if (helper(matrix, rows, cols, i, j, str, 0, flag))
 10                     return true;
 11             }
 12         }
 13         return false;
 14     }
 15 
 16     private boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) {
 17         int index = i * cols + j;
 18         if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1)
 19             return false;
 20         if(k == str.length - 1) return true;
 21         flag[index] = 1;
 22         if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag)
 23                 || helper(matrix, rows, cols, i + 1, j, str, k + 1, flag)
 24                 || helper(matrix, rows, cols, i, j - 1, str, k + 1, flag)
 25                 || helper(matrix, rows, cols, i, j + 1, str, k + 1, flag)) {
 26             return true;
 27         }
 28         flag[index] = 0;
 29         return false;
 30     }
 31 
 32     boolean ans=false;
 33     public boolean hasPath(char[] matrix, int rows, int cols, char[] str){
 34         int len=matrix.length;
 35         boolean [] flag=new boolean[len];
 36         if(len==0)
 37             return false;
 38         for(int i=0;i<len;i++){
 39             help(matrix,i,str,0,rows,cols,flag);
 40             System.out.println("yuanxu");
 41             if(ans)
 42                 return true;
 43         }
 44         return false;
 45     }
 46     void help2(char[] matrix, int i, char[] str,int index,int rows,int cols,boolean []flag){
 47 
 48         if(i>=matrix.length || i<0 || flag[i] || matrix[i]!=str[index])
 49             return;
 50         if(matrix[i]==str[index] && index==str.length-1){
 51             ans=true;
 52             return;
 53         }
 54 
 55         flag[i]=true;
 56         System.out.print("i: ");
 57         System.out.print(i);
 58         System.out.println(matrix[i]);
 59         if(i%cols==0) {
 60             help(matrix,i+cols,str,index+1,rows,cols,flag);
 61             if(ans)
 62                 return;
 63             help(matrix,i-cols,str,index+1,rows,cols,flag);
 64             if(ans)
 65                 return;
 66             help(matrix,i+1,str,index+1,rows,cols,flag);
 67             if(ans)
 68                 return;
 69         }
 70 
 71         else if(i%cols==cols-1){
 72             help(matrix,i+cols,str,index+1,rows,cols,flag);
 73             if(ans)
 74                 return;
 75             help(matrix,i-cols,str,index+1,rows,cols,flag);
 76             if(ans)
 77                 return;
 78             help(matrix,i-1,str,index+1,rows,cols,flag);
 79             if(ans)
 80                 return;
 81         }
 82 
 83         else{
 84             help(matrix,i+1,str,index+1,rows,cols,flag);
 85             if(ans)
 86                 return;
 87             help(matrix,i-1,str,index+1,rows,cols,flag);
 88             if(ans)
 89                 return;
 90             help(matrix,i+cols,str,index+1,rows,cols,flag);
 91             if(ans)
 92                 return;
 93             help(matrix,i-cols,str,index+1,rows,cols,flag);
 94             if(ans)
 95                 return;
 96         }
 97         flag[i]=false;
 98 
 99 
100 }
View Code

 18.求1+2+3+...+n

題目描述:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。

誤區:想不到

1 public class Solution {
2     public int Sum_Solution(int n) {
3         int ans=n;
4         boolean a=(ans>0) && ((ans+=Sum_Solution(n-1))>0);
5         return ans;
6 
7     }
8 }
View Code

 19.和為S的連續正數序列

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

誤區:用滑動窗口的思想,做過了就會做了

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
 4         if(sum<=0)
 5             return new ArrayList<>();
 6         ArrayList<ArrayList<Integer>> ans=new ArrayList<>();
 7         
 8         int low=1,high=2;
 9         
10         while(high>low){
11             int num=(low+high)*(high-low+1)/2;
12             if(num==sum){
13                 ArrayList<Integer> temp=new ArrayList<>();
14                 for(int i=low;i<=high;i++)
15                     temp.add(i);
16                 ans.add(temp);
17                 low++;
18             }
19             else if(num<sum)
20                 high++;
21             else
22                 low++;
23         }
24         return ans;
25     }
26 }
View Code

 20.和為S的兩個數字

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

誤區:當兩個數和相同時,越靠近乘積越大

 1 import java.util.ArrayList;
 2 
 3 public class Solution {
 4     public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
 5         int len=array.length;
 6         if(len<=1)
 7             return new ArrayList<>();
 8         ArrayList<Integer> ans=new ArrayList<>();
 9         int i=0;
10         int j=len-1;
11         while(i<j){
12             if (array[i] + array[j]<sum)
13                 i++;
14             else if(array[i] + array[j]>sum)
15                 j--;
16             else{
17                 ans.add(array[i]);
18                 ans.add(array[j]);
19                 break;
20                 
21             }
22         }
23 
24         
25         return ans;
26 
27     }
28 }
View Code

 21.左旋轉字符串

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

誤區:如果左移的不是字符串而是數組,就要三次反轉來做

 1 class Solution {
 2 public:
 3     string LeftRotateString(string str, int n) 
 4     {
 5       int len = str.size();
 6         if(len == 0) return str;
 7         n %= len;
 8         for(int i = 0, j = n - 1; i < j; ++i, --j) swap(str[i], str[j]);
 9         for(int i = n, j = len - 1; i < j; ++i, --j) swap(str[i], str[j]);
10         for(int i = 0, j = len - 1; i < j; ++i, --j) swap(str[i], str[j]);
11         return str;
12     }
13 };
14 
15 public class Solution {
16     public String LeftRotateString(String str,int n) {
17         
18          String ans="";
19         return ans = (str.length()==0) ? "" : str.substring(n%str.length(),str.length()).concat(str.substring(0,n%str.length()));
20 
21     }
22 }
View Code

22.撲克牌順子

題目描述: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。

誤區:有沒有一種方法可以不排序

 1 import java.util.Arrays;
 2 
 3 public class Solution {
 4     public boolean isContinuous(int [] numbers) {
 5         Arrays.sort(numbers);
 6         int temp=0;
 7         for(int i=0;i<numbers.length-1;i++){
 8             if(numbers[i]!=0){
 9                 if(numbers[i+1]==numbers[i])
10                     return false;
11                 else
12                     temp=temp+numbers[i+1]-numbers[i];
13             }
14         }
15         return temp+1<=numbers.length;
16     }
17 }
View Code

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

題目描述:統計一個數字在排序數組中出現的次數。

誤區:兩次二分,一次找開頭,一次找結尾

 1 public class Solution {
 2         public  int GetNumberOfK(int[] array,int k){
 3         if(array==null||array.length==0)
 4             return 0;
 5         int first=getFirstK(array,k,0,array.length-1);
 6         int last=getLastK(array,k,0,array.length-1);
 7         if(first==-1 ||last==-1){
 8             return 0;
 9         }
10         else{
11             return last-first+1;
12         }
13          
14     }
15      
16     public  int getFirstK(int[] array,int k,int start,int end){
17         while(start<=end){
18             int mid=(start+end)/2;
19             if(k<array[mid])
20                 end=mid-1;
21             else if(k>array[mid])
22                 start=mid+1;
23             else{
24                 if((mid>0&&array[mid-1]!=k)||mid==0)
25                     return mid;
26                 else{
27                     end=mid-1;
28                 }
29             }
30         }
31         return -1;
32     }
33      
34     public  int getLastK(int[] array,int k ,int start,int end){
35         while(start<=end){
36             int mid=(start+end)/2;
37             if(k<array[mid])
38                 end=mid-1;
39             else if(k>array[mid])
40                 start=mid+1;
41             else{
42                 if((mid<array.length-1&&array[mid+1]!=k)||mid==array.length-1)
43                     return mid;
44                 else{
45                     start=mid+1;
46                 }
47             }
48         }
49         return -1;
50     }
51 }
View Code

 24.平衡二叉樹

題目描述:輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。

誤區:遞歸,代碼要寫的好看。從最底下開始

 1 //重復計算的代碼
 2 public classSolution {
 3     public boolean IsBalanced_Solution(TreeNode root) {
 4         if(root == null) {
 5             return true;
 6         }
 7         return Math.abs(maxDepth(root.left) - maxDepth(root.right)) <= 1 &&
 8             IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
 9     }
10       
11     private int maxDepth(TreeNode root) {
12         if(root == null) {
13             return 0;
14         }
15         return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
16     }
17 }
18 
19 
20 //不重復計算的代碼
21 public class Solution {
22     public boolean IsBalanced_Solution(TreeNode root) {
23         return getDepth(root) != -1;
24     }
25      
26     private int getDepth(TreeNode root) {
27         if (root == null) return 0;
28         int left = getDepth(root.left);
29         if (left == -1) return -1;
30         int right = getDepth(root.right);
31         if (right == -1) return -1;
32         return Math.abs(left - right) > 1 ? -1 : 1 + Math.max(left, right);
33     }
34 }
View Code

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

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

誤區:第一檔是遍歷,第二檔是hash,第三檔是位運算

 1 import java.util.Arrays;
 2 import java.util.HashMap;
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 public class Solution {
 7     public void FindNumsAppearOnce2(int [] array,int num1[] , int num2[]) {
 8         if(array.length>1){
 9             Arrays.sort(array);
10             int i=1;
11             int flag=0;
12             while(i<array.length){
13                 if(array[i]==array[i-1]){
14                     if(i+2>=array.length){
15                         num2[0]=array[i+1];
16                         break;
17                     }
18                     else
19                         i+=2;
20                 }
21 
22                 else{
23                     if(flag==0){
24                         if(i==array.length-1){
25                             num1[0]=array[i-1];
26                             num2[0]=array[i];
27                             break;
28                         }
29                         num1[0]=array[i-1];
30                         flag++;
31                     }
32                     else{
33                         num2[0]=array[i-1];
34                         break;
35                     }
36                     i++;
37                 }
38 
39             }
40         }
41 
42     }
43 
44     public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
45         Set<Integer> hm=new HashSet<>();
46         for(int i=0;i<array.length;i++){
47             if(hm.contains(array[i]))
48                 hm.remove(array[i]);
49             else
50                 hm.add(array[i]);
51         }
52         int []temp={0,0};
53         int j=0;
54         for(int i :hm){
55             temp[j]=i;
56             j++;
57         }
58         num1[0]=temp[0];
59         num2[0]=temp[1];
60 
61     }
62 }
View Code

 26.把數組排成最小的數

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

誤區:自定義比較器很奇妙

 1 package 數組;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collections;
 5 import java.util.Comparator;
 6 
 7 public class Solution {
 8     public String PrintMinNumber(int [] numbers) {
 9         int n;
10         String s="";
11         ArrayList<Integer> list= new ArrayList<Integer>();
12         n=numbers.length;
13         for(int i=0;i<n;i++){
14             list.add(numbers[i]);
15 
16         }
17         list.sort(new Comparator<Integer>() {
18 
19             public int compare(Integer str1, Integer str2) {
20                 String s1 = str1 + "" + str2;
21                 String s2 = str2 + "" + str1;
22                 return s1.compareTo(s2);
23             }
24         });
25 
26         for(int j:list){
27             s+=j;
28         }
29         return s;
30 
31     }
32 }
View Code

 27.把字符串轉換成整數

題目描述:將一個字符串轉換成一個整數(實現Integer.valueOf(string)的功能,但是string不符合數字要求時返回0),要求不能使用字符串轉換整數的庫函數。 數值為0或者字符串不是一個合法的數值則返回0。

誤區:溢出判斷

 1 public class Solution {
 2     public int StrToInt(String str) {
 3         if(str.length()==0)
 4             return 0;
 5         int ans=0;
 6         int flag=0;
 7         if(str.charAt(0)=='-')
 8             flag=-1;
 9         else
10             flag=1;
11 
12         for(int i=0;i<str.length();i++){
13             if(i==0 && ((str.charAt(i)=='+' || str.charAt(i)=='-')))
14                 continue;
15             else if(str.charAt(i)>='0' && str.charAt(i)<='9'){
16                 int temp=ans;
17                 ans=ans*10+(str.charAt(i)-'0');
18                 if((temp-(str.charAt(i)-'0')/10!=ans))//溢出判斷
19                     return 0;
20 
21             }
22 
23             else
24                 return 0;
25         }
26         return ans*flag;
27 
28     }
29 
30     public static void main(String[] args) {
31         Solution s=new Solution();
32         int a=s.StrToInt("2147483648");
33         System.out.println(a);
34     }
35 }
View Code

 

 

8.反轉鏈表

題目描述:輸入一個鏈表,反轉鏈表后,輸出新鏈表的表頭。

誤區:是在原鏈表的基礎上反轉,盡量不要借助外部存儲結構


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM