牛客网刷题总结

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.反转链表

题目描述:输入一个链表,反转链表后,输出新链表的表头。

误区:是在原链表的基础上反转,尽量不要借助外部存储结构

posted @ 2018-11-01 22:42  yuanninesuns  阅读(3921)  评论(0编辑  收藏  举报