牛客面试高频榜单(第一组)难度:简单&中等

(1)NC78反转链表

(2)NC140 排序

两种常用排序

用快排实现

 public int[] MySort (int[] arr) {
        fastSort(arr,0,arr.length-1);
        return arr;
        
    }
    private void fastSort(int[] arr,int l,int r){
        if(l>=r)
            return;
        int num = arr[r];
        int sl = l,sr=r;
        while(lnum)r--;
            //在填入前一定要进行判断
            if(l

 用归并法实现

public class Solution {

    public int[] MySort (int[] arr) {
        // write code here
        mergeSort(arr,0,arr.length-1);
        return arr;
        
    }
    private void mergeSort(int[] arr , int l , int r){
        if(l>=r)
            return;
        int mid = (l+r)>>1;
        //分两边继续递归
        mergeSort(arr,l,mid);
        mergeSort(arr,mid+1,r);
        //两边都递归结束,才合并此层
        merge(arr,l,mid,r);
    }
    private void merge(int[] arr,int l,int mid,int r){
        int[] t = new int[r-l+1];
        int index = 0;
        int h1 = l, h2 = mid+1;
        while(h1<=mid&&h2<=r){
            if(arr[h1]

堆排序 

优先队列

(3)NC45 实现二叉树先序,中序和后序遍历

返回形式

public int[][] threeOrders (TreeNode root) {
        // 分辨用链表先存储
        ArrayList prelist = new ArrayList();
        ArrayList inlist = new ArrayList();
        ArrayList postlist = new ArrayList();
        
        preOrder(root,prelist);
        inOrder(root,inlist);
        postOrder(root,postlist);
        
        //再根据链表长创建二维数组
        int[][] res = new int[3][prelist.size()];
        for(int i=0;i

(4)NC119 最小的K个数

本题可采用分会分治,可大顶堆。大顶堆实现起来更容易。或使用Array自带sort排序

import java.util.*;

public class Solution {
    public ArrayList GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList res = new ArrayList();
        if(k<=0||input.length==0)
            return res;
        if(input.length<=k){
            for(int i =0;i queue = new PriorityQueue((o1,o2)->(o2-o1));
        for(int i = 0;i=k){
                if(queue.peek()>input[i]){
                    queue.poll();
                    queue.offer(input[i]);
                }
                   
            }
            else{
                queue.offer(input[i]);
            }
           
        }
        while(!queue.isEmpty()){
            res.add(queue.poll());
        }
        return res;
    }
}

(5)NC15 求二叉树的层序遍历

(6)NC88 寻找第K大

使用快排,有两个注意的点

1、一定记住把,暂存的t放入

2、递归时,范围缩小的操作

public class Solution {
    public int findKth(int[] a, int n, int K) {
        // write code here
        if(n<=0||K>n)
            return -1;
        sortInt(a,0,n-1,K-1);
        return a[K-1];
    }
    private void sortInt(int[] a, int l,int r,int k){
        int t = a[r];
        int nl = l,nr=r;
        while(nlt)nl++;
            if(nl

(7)NC61 两数之和

没便利到一个数,target-当前 若在map中则将(当前值,下标)存入。若存在则找到了和为target的值。 

public int[] twoSum (int[] numbers, int target) {
        // write code here
        Map map = new HashMap();
        int[] res = new int[2];
        for(int i = 0;i

(8)NC33 合并两个排序的链表

(9)NC76 用两个栈实现队列

(10)NC50 链表中的节点每k个一组翻转

public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        //寻找第k个结点。过程中出现null则不反转,直接但会当前链表
        ListNode tail = head;
        for(int i=0;i

(11) NC19 连续子数组的最大和

sum记录当前和,sum+nextNumber大于nextNumber则将nextNumber加入总和,不然说明不能继续连续,以nextNumber为新起点。

每次计算后都比较更新max

(12)NC41 最长无重复子数组

1、l,r分别指向无重复数组头尾

2、新进加入数组的元素,若map中已存在,则需要重新更新起点。新起点为重复数字的下标的下一个。若此位置小于当先l,则说面重复数字不再当前范围内,故不更新

   public int maxLength (int[] arr) {
        // write code here
        if(arr.length==0)
            return 0;
        int max = 1;
        int l = 0, r=1;
        Map map = new HashMap();
        map.put(arr[0],0);
        while(rl){
                    l = map.get(arr[r])+1;
            }
            map.put(arr[r],r);
            //每次更新完l,r重新判断是否活得最大长度
            if(r-l+1>max){
                max=r-l+1;
            }
            r++;
        }
        if(r-l>max){
                max=r-l;
            }
        return max;
    }

(13)NC4 判断链表中是否有环 

当由于后续为null,fast,slow不移动的情况。此时要将其直接置null。不然会世中卡在当前不能后移的结点位置

public boolean hasCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        int index = 0;
        while(index==0||slow!=fast){
            if(slow!=null)
                slow=slow.next;
            else
                slow =null;
            if(fast!=null&&fast.next!=null){
                fast = fast.next.next;
            }
            else
                fast = null;
            index = 1;
        }
        if(slow==null)
            return false;
        return true;
    }

 (14)NC22 合并两个有序的数组

(15)NC3 链表中环的入口结点

(16)NC52 有效括号序列

(17)NC53 删除链表的倒数第n个节点

(18)NC1 大数加法

注意数据类型的选择,当需要一个可变长度的字符串时用StringBuffer

(19)NC14 按之字形顺序打印二叉树

注意如何Collections.reverse用于list集合的反转。Collections.reverse(arr);

不需要通过改变左右孩子入队顺序去实现,只需将需从右到左遍历的行反转

(20)NC127 最长公共子串

dp[i][j]表示字符串str1中第i个字符和str2种第j个字符为最后一个元素所构成的最长公共子串。 

  • 如果不相等,那么他们就不能构成公共子串,也就是
    dp[i][j]=0;

  • 如果相等,我们还需要计算前面相等字符的个数,其实就是dp[i-1][j-1],所以
    dp[i][j]=dp[i-1][j-1]+1;(即其前一位为连续,则长度会增加1,前一位不为联系则此处为开始即0)

在实现是考虑到下表0减一为负。故二维数组i+1相当于i位置

public String LCS (String str1, String str2) {
        // write code here
        int[][] dp = new int[str1.length()+1][str2.length()+1];
        int maxindex = 0;
        int maxlength = 0;
        //maxindex与maxlength在每次找到相等字符时进行递增。
        for(int i = 0;imaxlength){
                        maxlength=dp[i+1][j+1];
                        maxindex = i;
                    }
                }else{
                    dp[i+1][j+1]=0;
                }
            }
        }
        return str1.substring(maxindex-maxlength+1,maxindex+1);
    }

 (21)NC66 两个链表的第一个公共结点

(22)NC40 链表相加(二)

(23)NC102 在二叉树中找到两个节点的最近公共

递归方法:

注:若路径下无匹配则会遍历到叶子结点,一路向上返回null

1、当前结点为空,或与寻找值匹配。则返回当前结点。

        对当前结点的左右进行递归,有以下几种情况

        left=null right=null 返回null

        left为空 返回right(若right不为null则说明其有匹配结点)

        right为空 返回left(若left不为null则说明其有匹配结点)

若lef与right均不为空则,说明结果在两侧,则返回当前结点。

 public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // write code here
        return dfs(root,o1,o2).val;
    }
    private TreeNode dfs(TreeNode root, int o1, int o2){
       if(root==null||root.val==o1||root.val==o2){
           return root;
       }
        TreeNode left = dfs(root.left,o1,o2);
        TreeNode right = dfs(root.right,o1,o2);
        if(left==null)
            return right;
        if(right==null)
            return left;
        return root;
    }

非递归当打实现:

(1)map记录每个结点值对应的父节点值

        如何对map进行初始化?采用层遍历,结束标志,map的key中包含o1和o2

(2)先将o1路径记录下来,用set记录,一路向上寻找父节点记录进set,直道不存在父节点(即map中无此key)

        从o2向上依次遍历其父节点,若存在于set中则为最近公共结点

 public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // write code here
        Map map = new HashMap();
        Queue queue = new LinkedList();
        map.put(root.val,Integer.MAX_VALUE);
        queue.add(root);
        while(!map.containsKey(o1)||!map.containsKey(o2)){
            TreeNode node = queue.poll();
            if(node.left!=null){
                queue.offer(node.left);
                map.put(node.left.val,node.val);
            }
            if(node.right!=null){
                queue.offer(node.right);
                map.put(node.right.val,node.val);
            }
        }
        Set set = new HashSet();
        while(map.containsKey(o1)){
            set.add(o1);
            o1 = map.get(o1);
        }
        while(!set.contains(o2)){
            o2 = map.get(o2);
        }
        return o2;
    }

(24)NC103 反转字符串

这里主要是String几个方法

预将String当成数组操作时 ch=str.toCharArray()

用char[] 生成String 时  new String(ch)

(25)NC38 螺旋矩阵

这里面有两个注意点

1、圈数:取row和col最小值计算圈

2、边界控制:输入下时判断此行,上是都已输入过

                        输入左时判断此列,右是否已输入过

public ArrayList spiralOrder(int[][] matrix) {
        ArrayList arr = new ArrayList();
        if(matrix.length==0)
            return arr;
        int row = matrix.length;
        int col = matrix[0].length;
        int cir = (row=c;i--)
                arr.add(matrix[row-c-1][i]);
            //是否输出左行判断
            if(c=c+1;i--)
                arr.add(matrix[i][c]);
        }
        return arr;
    }

(26)NC65 斐波那契数列

(27)NC17 最长回文子串

方法一:两种情况

偶数以当前位置i,i+1发散寻找

奇数当前位置为中心,i,i发散寻找

public int getLongestPalindrome (String A) {
        // write code here
        if(A==null||A.length()==0){
            return 0;
        }
        int maxl = Integer.MIN_VALUE;
        for(int i = 0;i=0&&r

(28)NC54 三数之和

1、将数组排序

2、i指向元组第一个位置元素, 

                当i对应值大于0时则说明后面均大于零。可以停止寻找

                当i对应值小于0,可转化为将后面的有序数组中两个值的和等于固定值0-num[i]

                                            和大于0-num[i],r减小即指向更小一点儿的数

                                            和小于0-num[i],l增大即指向更大一点儿的数

                                            和与0-num[i]相等,则加入集合

3、可以加入集合,并不能停止寻找合等于0-num[i]的对

        但需先去除重复元素,l,r从新的位置开始继续寻找

public ArrayList> threeSum(int[] num) {
        ArrayList> res = new ArrayList>();
        if(num.length<3)
            return res;
        Arrays.sort(num);
        for(int i = 0;i < num.length-2;i++){
            if(num[i]>0)
                break;
            if(i>0&&num[i-1]==num[i])
                continue;
            int l = i+1;
            int r = num.length-1;
            while(l arr = new ArrayList();
                    arr.add(num[i]);
                    arr.add(num[l]);
                    arr.add(num[r]);
                    res.add(arr);
                    //去除重复
                    while(l0-num[i])
                    r--;
                else
                    l++;
            }
        }
        return res;
    }

(29)NC12 重建二叉树

(30)NC91 最长上升子序列(三)

import java.util.*;

public class Solution {
    /**
     * retrun the longest increasing subsequence
     * @param arr int整型一维数组 the array
     * @return int整型一维数组
     */
    public int[] LIS (int[] arr) {
        int[] tail = new int[arr.length];
        int[] dp = new int[arr.length];
        int len = 0;
        //构建dp,dp记录每一位最长升子序列长度
        for(int i = 0;i=0;i--){
            if(dp[i]==len){
                res[--len] = arr[i];
            }
        }
        return res; 
    }
    private int search(int[] tail,int len, int num){
        int low=0,high=len-1;
        while(low=num)
                high=mid;
            else
                low=mid+1;
        }
        return high;
    }
}

(31)NC32 求平方根

注意处理0,1特殊情况

范围;i<=x/2+1,加1不能省略

(32)NC48 在旋转过的有序数组中寻找目标值

注意二分查找的范围控制

public int search (int[] nums, int target) {
        // write code here
        int l = 0,r = nums.length-1;
        while(l<=r){//等号
            int mid = (l+r)/2;
            if(nums[mid]==target)return mid;
            if(nums[mid]>=nums[l]){//前段有序
                if(target>=nums[l]&&targetnums[mid])
                    l = mid+1;
                else
                    r = mid-1;
            }
        }
            return -1; 
    }

(33)NC90 包含min函数的栈

(34)NC7 买卖股票的最好时机(一)

从右往左存储目前最小值,计算的总是当前范围内的最小值,故一定符合先买后卖原则

    public int maxProfit (int[] prices) {
        // write code here
        int minprice = Integer.MAX_VALUE;
        int ans = 0;
        for(int i = 0;ians)
                ans = prices[i]-minprice;
        }
        return ans;
    }

(35)JZ38 字符串的排列

 每次递归传入当前一组成的字符串,和可以继续组的字符串

 public ArrayList Permutation(String str) {
        ArrayList result = new ArrayList();
        if(str==null||str.length()==0)
            return null;
        newString(str,"",result);
        return result;
    }
    public void newString(String str,String newstr,ArrayList result){
        if(str.length()==0){
            if(!result.contains(newstr.toString()))
                result.add(newstr.toString());
            return ;
        }
        for(int i = 0;i

(36)NC136 输出二叉树的右视图

(37)NC109 岛屿数量

可以用递归法解决。将一个岛屿的起点进行递归,经历过的填都改为0

       // write code here
        int sum = 0;
        //每遇到一个不为零的值,则说明出现一个岛屿sum++
        //从此点为起点,利用递归将此岛屿上的错油都置为0,即记录过就删除
        for(int i = 0;i=grid.length||j<0||j>=grid[0].length||grid[i][j]=='0')
            return;
        grid[i][j] = '0';
        dfs(grid,i-1,j);
        dfs(grid,i+1,j);
        dfs(grid,i,j-1);
        dfs(grid,i,j+1);
    }
}

(38)NC13 二叉树的最大深度

(39)NC141 判断是否为回文字符串

(40)NC137 表达式求值

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
    public int solve (String s) {
        // write code here
        Stack snum = new Stack();
        Stack sop = new Stack();
        Map map = new HashMap();
        //建立优先级关系
        map.put('-',1);
        map.put('+',1);
        map.put('*',2);
        map.put('(',0);
        int index = 0;
        while(index='0'){
                //因可能超过各位数字,故组合数组。直至找到非数字字符
                String str = "";
                while(index='0'){
                    str += s.charAt(index++);
                }
                int sum = Integer.parseInt(str);
                //将数组入栈
                snum.push(sum);
            }
            else{
                //计算字符为空直接入栈
                if(sop.isEmpty())
                    sop.push(s.charAt(index));
                //输入字符为(直接入栈
                else if(s.charAt(index)=='(')
                    sop.push(s.charAt(index));
                //输入字符为),找到一个匹配的(
                else if(s.charAt(index)==')'){
                    //不是(就一致出栈计算
                    while(sop.peek()!='('){
                        int num = compute(snum.pop(),snum.pop(),sop.pop());
                        snum.push(num);
                    }
                    //最好将(出战
                    sop.pop();
                }
                //输入字符的优先级高于当前栈顶,直接入栈
                else if(map.get(s.charAt(index))>map.get(sop.peek()))
                    sop.push(s.charAt(index));
                else{
                //输入字符的优先级低或等于当前栈顶,需计算
                //特例情况,肯能遇见下一个字符是(则停止计算,其仅当)来临才消失。故优先及中加入了‘(’将其优先级设为最低
                    while(!sop.isEmpty()&&map.get(s.charAt(index))<=map.get(sop.peek())){
                        int num = compute(snum.pop(),snum.pop(),sop.pop());
                        snum.push(num);
                    }
                //计算完成再将字符入栈
                    sop.push(s.charAt(index));
                    }
                index++;
            }
        }
        if(!sop.isEmpty()){
            int num = compute(snum.pop(),snum.pop(),sop.pop());
            snum.push(num);
        }
        return snum.pop();
    }
    private int compute(int num1, int num2,char op){
        switch(op){
                case'-':return num2-num1;
                case'+':return num1+num2;
                case'*':return num1*num2;
                default:return Integer.MIN_VALUE;
        }
    }
}

(41)NC97 字符串出现次数的TopK问题

前k个最大或最小就想到用堆排序

1、这里有几个重点,语法需要注意

//Map的遍历,对实体,key,value的分别遍历
for(Map.Entry m : map.entrySet())

若key map.keySet()
若value map.valueSet()

2、如何对Map实体构建排序比较器Map.Entry是重点

 Comparator> com = new Comparator>(){
            public int compare(Map.Entry o1,Map.Entry o2){
                if(o1.getValue().equals(o2.getValue())){
                   return o2.getKey().compareTo(o1.getKey()); 
                }
                else{
                    return o1.getValue()-o2.getValue();
                }
            }
        };

完成代码

public class Solution {
    /**
     * return topK string
     * @param strings string字符串一维数组 strings
     * @param k int整型 the k
     * @return string字符串二维数组
     */
    
    public String[][] topKstrings (String[] strings, int k) {
        // write code here
        String[][] res = new String[k][2];
        if(k==0)
            return new String[][]{};
        //加入Map中,不断更新key
        Map map = new HashMap();
        for(int i = 0;i> com = new Comparator>(){
        //值不同,值小的放前面;值同字典大的放前面
            public int compare(Map.Entry o1,Map.Entry o2){
                if(o1.getValue().equals(o2.getValue())){
                   return o2.getKey().compareTo(o1.getKey()); 
                }
                else{
                    return o1.getValue()-o2.getValue();
                }
            }
        };
        //构建顶堆
        Queue> queue = new PriorityQueue>(com);
        for(Map.Entry m : map.entrySet()){
            if(queue.size()=0;i--){
            Map.Entry m = queue.poll();
            res[i][0]=m.getKey();
            res[i][1]=m.getValue().toString();
        }
        return res;
    }
}

(42)NC112 进制转换

char s = '' 错误写法不能为空字符

int转String :Integer.toString(num)

正弦转char注意要强制类型转换char ch =(char) ('A'+num-10)

你可能感兴趣的:(剑指offer,大数据)