面试算法:

2021-02-07  本文已影响0人  书虫大王X

第一题:
一个机器人在m×n大小的地图的左上角(起点)。
机器人每次向下或向右移动。机器人要到达地图的右下角(终点)。
可以有多少种不同的路径从起点走到终点?


示例:

输入:(2,1)
返回:1
输入:(2,2)
返回:2

    public int uniquePaths (int m, int n) {
// 动态规划,三行代码。
// 建立坐标系为起点(1, 1),终点(m, n)。
// 到达m,n的路径是到达(m-1, n)的路径之和加上到达(m, n-1)的路径之和,当m或n为1时,
// 说明到达了边界,只有一条路径。
        if(m == 1 || n == 1)
            return 1;
        return uniquePaths(m-1, n) + uniquePaths(m, n-1);
    }

第二题:进制转化

1、栈:Stack<Integer> s = new Stack();
push、pop、peek
2、StringBuilder :StringBuilder str = new StringBuilder();
str.append(字符串);
3、数据转化为字符串:String.valueOf(数据);

    public String solve (int M, int N) {
        // write code here
        Stack<Integer> s = new Stack();
        if(M == 0 || N == 10){
            return String.valueOf(M);
        }
        StringBuilder str = new StringBuilder();
        if(M < 0){
            str.append("-");
            M = Math.abs(M);
        }
        while(M != 0){
            s.push(M % N);
            M = M / N;
        }
        int n = s.size();
        for(int i = 0; i < n; i++){
            if(s.peek() > 9){
                str.append((char)(s.pop()-10+'A'));
            }else{
                str.append(s.pop());
            }
        }
        return String.valueOf(str);
    }

第三题:青蛙跳台阶

    public int JumpFloor(int target) {
        int a = 1;
        int b = 1;
        for(int i = 1; i < target; i++){
            a = a + b;
            b = a - b;
        }
        return a;
    }

第四题:判断链表是否是回文结构

ArrayList:
ArrayList<Integer> list = new ArrayList();
list.add(数据);
list.get(数组的下标)
比较链表的两个节点是否相等:node1.equals(node2)

    public boolean isPail2 (ListNode head) {
        // write code here
        ArrayList<Integer> list = new ArrayList();
        while(head != null){
            list.add(head.val);
            head = head.next;
        }
        
        int l = 0;
        int h = list.size() -1;
        while(l < h){
            if(! list.get(l++).equals(list.get(h--))){
                return false;
            }
        }
        return true;
    }

//  仅供参考,不能通过全部用例(创建一个反转链表,将其与原数组进行比较)
    public boolean isPail (ListNode head){
        ListNode yk = resover(head);
        while(head != null){
            if(!yk.equals(head)){
                return false;
            }
            yk = yk.next;
            head = head.next;
        }
        return true;
    }
    
    public ListNode resover(ListNode head){
        if(head == null){
            return head;
        }
        ListNode current = head;
        ListNode previous = null;
        while(current != null){
            ListNode temp = current.next;
            current.next = previous;
            previous = current;
            current = temp;
        }
        return previous;
    }

第五题:判断链表是否有环

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

第六题:树节点的和

    public int sumNumbers(TreeNode root) {
      if(root == null){
          return 0;
      }
      return sumOfTree(root,root.val);
    }
    public int sumOfTree(TreeNode root,int sum){
        if(root.left == null && root.right == null){
            return sum;
        }
        int yk = 0;
        if(root.left != null){
            yk += sumOfTree(root.left,sum * 10 + root.left.val);
        }
        if(root.right != null){
            yk += sumOfTree(root.right,sum * 10 + root.right.val);
        }
        return yk;
    }

第七题:树路径的最大值

    public int sumNumbers (TreeNode root) {
        if(root == null){
            return 0;
        }
        if(root.left == null && root.right == null){
            return root.val;
        }
        return Math.max(sumNumbers(root.right),sumNumbers(root.left)) + root.val;
    }

第八题:树路径的和

    public boolean hasPathSum (TreeNode root, int sum) {
        // write code here
        if(root==null){
            return false;
        }
        //处理叶子节点
        if(root.left==null && root.right==null){
            if(root.val==sum){
                return true;
            }else{
                return false;
            }
        }
        boolean leftHas=hasPathSum(root.left,sum-root.val);
        boolean rightHas=hasPathSum(root.right,sum-root.val);
        boolean cur=leftHas||rightHas;
        return cur;
    }

    ArrayList<ArrayList<Integer>>  AllList = new ArrayList<>();
    public ArrayList<ArrayList<Integer>> pathSum (TreeNode root, int sum) {
        // 树空
        if(root==null){
            return AllList;
        }
        //1.初始当前的列表
        ArrayList<Integer> path = new ArrayList<>();
        //2.深度优先遍历
       dfs(AllList,path,root,sum); 
        //3.返回路径集合
        return AllList;
    }
    //一、对root进行深度优先遍历
    //result:所有路径和为sum的结果集  list:当前路径结点集  root:当前根节点  sum:当前所需的路径和
    public void dfs(ArrayList<ArrayList<Integer>> result,ArrayList<Integer> list,TreeNode root,int sum){
        if(root==null){
            return;
        }
        if(root.left==null && root.right==null){//为叶子节点
            if(sum-root.val==0){//加上该结点后,满足路径和sum
                list.add(root.val);//将当前结点加入list
                result.add(new ArrayList<>(list));//将当前路径 加入 结果集
                list.remove(list.size()-1); //去掉当前结点,继续下面的遍历
            }
            return;
        }
        list.add(root.val);
        dfs(result,list,root.left,sum-root.val);
        dfs(result,list,root.right,sum-root.val);
        list.remove(list.size()-1); 
    }

第八题:合并二叉树

    public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {
        if(t1 == null){
            return t2;
        }
        if(t2 == null){
            return t1;
        }
        t1.val = t1.val + t2.val;
        t1.left = mergeTrees(t1.left,t2.left);
        t1.right = mergeTrees(t1.right,t2.right);
        return t1;
    }

第九题:两个线程交替执行

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (count < 100) {
                    synchronized (lock) {
                        if ((count & 1) == 0) {
                            System.out.println(Thread.currentThread().getName() + ":" + count++);
                        }
                    }
                }
            }
        }, "偶数线程").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (count < 100){
                    synchronized (lock){
                        if ((count & 1) == 1){
                            System.out.println(Thread.currentThread().getName() + ":" + count++);
                        }
                    }
                }
            }
        },"奇数线程").start();
    }
    private static class ThreadTest implements Runnable{
        @Override
        public void run() {
            while (count < 100){
                synchronized (lock){
                    System.out.println(Thread.currentThread().getName() + ":" + count++);
                    lock.notify();
                    if (count < 100){
                        try {
                            lock.wait();
                        }catch ( InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        new Thread(new ThreadTest(),"偶数线程").start();
        new Thread(new ThreadTest(),"奇数线程").start();
    }

第十题:

第十一题:逆波兰表达式求值

在反向波兰表示法中计算算术表达式的值,遇到操作符就计算前两个数值,例 ["2", "1", "+", "3", "*"] -> (2 + 1) * 3 -> 9

public int evalRPN(String[] tokens) {
    Stack<Integer> s = new Stack<Integer>();
    String operators = "+-*/";
    for (String token : tokens) {
        if (!operators.contains(token)) {
            s.push(Integer.valueOf(token));
            continue;
        }

        int a = s.pop();
        int b = s.pop();
        if (token.equals("+")) {
            s.push(b + a);
        } else if(token.equals("-")) {
            s.push(b - a);
        } else if(token.equals("*")) {
            s.push(b * a);
        } else {
            s.push(b / a);
        }
    }
    return s.pop();
}

第十二题:返回一个数组的前X个大的数

PriorityQueue默认是一个小顶堆,然而可以通过传入自定义的Comparator函数来实现大顶堆。

public int[] topk(int[] nums, int k) {
    int[] result = new int[k];
    if (nums == null || nums.length < k) {
        return result;
    }
    Queue<Integer> pq = new PriorityQueue<>();
    for (int num : nums) {
        pq.add(num);
        if (pq.size() > k) {
            pq.poll();
        }
    }
    for (int i = k - 1; i >= 0; i--) {
        result[i] = pq.poll(); 
    }
    return result;
}

十三题:判断一棵树是否是二叉搜索树:

public boolean isValidBST(TreeNode root) {
    return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private boolean isValidBST(TreeNode root, long min, long max){
    if (root == null) {
        return true;
    }
    if (root.val <= min || root.val >= max){
        return false;
    }
    return isValidBST(root.left, min, root.val) && isValidBST(root.right, root.val, max);
}

十四题:寻找二叉树第K小的值:

public int kthSmallest(TreeNode root, int k) {
    if (root == null) {
        return 0;
    }
//  获取左边节点的个数
    int leftCount = getCount(root.left);
//   进入左循环
    if (leftCount >= k) {
        return kthSmallest(root.left, k);
    } else if (leftCount + 1 == k) {
//   就是当前节点
        return root.val;
    } else {
//    进入右循环
        return kthSmallest(root.right, k - leftCount - 1);
    }
}
private int getCount(TreeNode root) {
    if (root == null) {
        return 0;
    }
    return getCount(root.left) + getCount(root.right) + 1;
}

十五题:数组加一

public int[] plusOne(int[] digits) {
    int carries = 1;
    for(int i = digits.length - 1; i >= 0 && carries > 0; i--){  
        int sum = digits[i] + carries;
        digits[i] = sum % 10;
        carries = sum / 10;
    }
    if(carries == 0) {
        return digits;
    }
        
    int[] rst = new int[digits.length + 1];
    rst[0] = 1;
    for(int i = 1; i < rst.length; i++){
        rst[i] = digits[i - 1];
    }
    return rst;
}

十六题:数组删重复值

public int removeElement(int[] A, int elem) {
    if (A == null || A.length == 0) {
        return 0;
    }
    int index = 0;
    for (int i = 0; i < A.length; i++) {
        if (A[i] != elem) {
            A[index++] = A[i];
        } 
    }
    return index;
}

十七题:数组删值

public int removeDuplicates(int[] A) {
    if (A == null || A.length == 0) {
        return 0;
    }
    int size = 0;
    for (int i = 0; i < A.length; i++) {
        if (A[i] != A[size]) {
            A[++size] = A[i];
        }
    }
    return size + 1;
}

十九题:给一个无序链表排序:

 public ListNode sortInList (ListNode head) {
     // write code here
     if(head == null || head.next == null)
         return head;
     
     ArrayList<Integer> list = new ArrayList<>();
     ListNode tmp = head;
     while(tmp != null){
         list.add(tmp.val);
         tmp = tmp.next;
     }
//   将list升序排序
     list.sort(Comparator.naturalOrder());
     
     ListNode temp = head;
     int i = 0;
     while(temp != null){
         temp.val = list.get(i++);
         temp = temp.next;
     }
     return head;
 }

二十题:数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

    public int FindGreatestSumOfSubArray(int[] array) {
        int max = array[0];
        for(int i = 1; i < array.length; i++){
            max = Math.max(arr[i] + max, 0);
        }
        return max;
    }

二十一题:判断一个数字是否是回文结构:

    public boolean isPalindrome (int x) {
        if(x < 0){
            return false;
        }
        int temp = 0;
        int y = x;
        while(y != 0){
            temp = temp * 10 + y % 10;
            y = y / 10;
        }
        return temp == x;
    }

二十二题:

二十三题:用一个升序数组创建平衡二叉树:

public TreeNode sortedArrayToBST (int[] num) {
        if(num == null){
            return null;
        }
        return createTree(num, 0, num.length - 1);
    }
    private TreeNode createTree(int[] num, int left, int right){
        if(left > right){
            return null;
        }
        int mid = left + (right - left + 1) / 2;
        TreeNode lNode = createTree(num, left, mid - 1);
        TreeNode rNode = createTree(num, mid + 1, right);
        TreeNode node = new TreeNode(num[mid]);
        if(lNode != null) node.left  = lNode;
        if(rNode != null) node.right = rNode;
        return node;
    }

二十四题:根据一颗二叉树的前序和中序遍历,创建二叉树:

    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if (pre.length == 0 || in.length == 0) {
            return null;
        }
        TreeNode root = new TreeNode(pre[0]);
        // 在中序中找到前序的根
        for (int i = 0; i < in.length; i++) {
            if (in[i] == pre[0]) {
                // 左子树,注意 copyOfRange 函数,左闭右开
                root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1),
                                                  Arrays.copyOfRange(in, 0, i));
                // 右子树,注意 copyOfRange 函数,左闭右开
                root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length),
                                                   Arrays.copyOfRange(in, i + 1, in.length));
                break;
            }
        }
        return root;
    }

最长回文子串:

//    字符串的最长回文子串
    public static int maxHuiwen(String str){
        int maxLength = 0;
        for (int i = 0; i < str.length() - 1; i ++){
            int len1 = huiWenLength(str,i, i);
            int len2 = huiWenLength(str,i, i + 1);
            maxLength = Math.max(maxLength,len1);
            maxLength = Math.max(maxLength,len2);
        }
        return maxLength;
    }
    public static int huiWenLength(String str, int left, int right){ 
        while (left > 0 && right < str.length() - 1){
            if (str.charAt(left) == str.charAt(right)){
                left --;
                right ++;
            }else {
                break;
            }
        }
        return right - left - 2 + 1;
    }
上一篇 下一篇

猜你喜欢

热点阅读