从0开始刷剑指Offer

剑指Offer题解

剑指 Offer 03. 数组中重复的数字

思路一:哈希表O(n)

class Solution {
    public int findRepeatDocument(int[] documents) {
        int len = documents.length;
        int[] arr = new int[100010];
        for(int i = 0; i < len; i ++ ) {
            arr[documents[i]] ++;
            if (arr[documents[i]] == 2) {
                return documents[i];
            }
        }
        return 0;
    }
}

思路二: 原地交换O(n)

class Solution {
    public int findRepeatDocument(int[] documents) {
      int len = documents.length;
      for(int i = 0; i < len; i ++ ){
        while (documents[i] != i) {
        if(documents[i] == documents[documents[i]]) {
            return documents[i];
        }
        int t = documents[i];
        documents[i] =  documents[t];
        documents[t] = t;
        }
      }
      return -1;
    }
}

剑指 Offer 04. 二维数组中的查找

思路一:单调性扫描O(n+m)

class Solution {
    public boolean findTargetIn2DPlants(int[][] plants, int target) {
        int len1 = plants.length;
        if (len1 <= 0) return false;
        int len2 = plants[0].length;
        if (len2 <= 0) return false;
        for(int i = len1 - 1, j = 0; ;) {
            if(plants[i][j] <target) {
                j ++;
            } else if(plants[i][j] > target){
                i --;
            } else {
                return true;
            }
            if(i < 0 || j >= len2) {
                break;
            }
        }
        return false;
    }
}

思路二:二分O(nlogn)

class Solution {
    public boolean findTargetIn2DPlants(int[][] plants, int target) {
        int len1 = plants.length;
        if (len1 <= 0) return false;
        int len2 = plants[0].length;
        if (len2 <= 0) return false;
        for(int i = 0; i < len1; i ++ ) {
           if (midf(plants, i, target)) {
               return true;
           }
        }
        return false;
    }
    public boolean midf(int[][] plants, int i, int target) {
        int l = 0;
        int r = plants[i].length - 1;
        while(l < r) {
            int mid = l + r >> 1;
            if(plants[i][mid] >= target) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        if(plants[i][l] == target) return true;
        return false;
    }
}

剑指 Offer 05. 替换空格

思路一:遍历添加O(n)

class Solution {
    public String pathEncryption(String path) {
        StringBuilder sb = new StringBuilder();
        char[] c = path.toCharArray();
        for(char ct : c) {
            if(ct == '.') sb.append(' ');
            else sb.append(ct);
        }
        return sb.toString();
    }
}

思路二:正则表达式替换O(n)

class Solution {
    public String pathEncryption(String path) {
        return path.replaceAll("\\.", " ");
    }
}

剑指 Offer 06. 从尾到头打印链表

思路一:辅助栈法O(n)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public int[] reverseBookList(ListNode head) {
            Stack<Integer> stack = new Stack();
            int[] q;
            ListNode dummy = head;
            int length = 0;
            while(dummy != null) {
                stack.push(dummy.val);
                dummy = dummy.next;
                length ++;
            }
            q = new int[length];
            for(int i = 0; i < length; i++ ) {
                q[i] = stack.pop();
            }
            return q;
    }
}

思路二:递归法O(n)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
        ArrayList<Integer> temp = new ArrayList();
    public int[] reverseBookList(ListNode head) {
        recur(head);  
        int[] res = new int[temp.size()];
        for(int i = 0; i < res.length; i ++) {
            res[i] = temp.get(i);
        }     
        return res;
    }

    void recur(ListNode head) {
        if(head == null) return;
        recur(head.next);
        temp.add(head.val);
    }
}

思路三:遍历反转法O(n)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
        ArrayList<Integer> list = new ArrayList();
    public int[] reverseBookList(ListNode head) {
        int length = 0;
        ListNode dummy = head;
        while(dummy != null) {
           list.add(dummy.val);
           dummy = dummy.next;
           length ++;
        }

        Collections.reverse(list);
        int[] q = new int[list.size()];
        for(int i = 0; i < q.length; i ++) {
            q[i] = list.get(i);
        }
        
        return q;
    }
}

剑指 Offer 07. 重建二叉树

思路一:递归法O(n)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int[] preorder;
    HashMap<Integer, Integer> hmap = new HashMap();
    public TreeNode deduceTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        for(int i = 0; i < inorder.length; i ++ ) {
            hmap.put(inorder[i], i);
        }
        return recur(0, 0, inorder.length - 1);
    }
    TreeNode recur(int root, int left, int right) {
        if(left > right) return null;
        TreeNode node = new TreeNode(preorder[root]);
        int i = hmap.get(preorder[root]);
        node.left = recur(root + 1, left, i - 1);
        node.right = recur(root + i - left + 1, i + 1, right);
        return node;
    }
}

剑指 Offer 08. 二叉树的下一个结点

思路一:中序遍历法O(n)

import java.util.*;
public class Solution {
    ArrayList<TreeLinkNode> nodes = new ArrayList<>();
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        // 获取根节点
        TreeLinkNode root = pNode;
        while(root.next != null) root = root.next;
        
        // 中序遍历打造nodes
        InOrder(root);
        
        // 进行匹配
        int n = nodes.size();
        for(int i = 0; i < n - 1; i++) {
            TreeLinkNode cur = nodes.get(i);
            if(pNode == cur) {
                return nodes.get(i+1);
            }
        }
        return null;
    }
    
    // 中序遍历
    void InOrder(TreeLinkNode root) {
        if(root != null) {
            InOrder(root.left);
            nodes.add(root);
            InOrder(root.right);
        }
    }
}

思路二:分类直接查找法O(n)

import java.util.*;
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        // 情况一
        if(pNode.right != null) {
            TreeLinkNode rchild = pNode.right;
            // 一直找到右子树的最左下的结点为返回值
            while(rchild.left != null) rchild = rchild.left; 
            return rchild;
        }
        
        // 情况二
        if(pNode.next != null && pNode.next.left == pNode) {
            return pNode.next;
        }
        
        // 情况三
        if(pNode.next != null) {
            TreeLinkNode ppar = pNode.next;
            // 沿着左上一直爬树,爬到当前结点是其父节点的左自己结点为止
            while(ppar.next != null && ppar.next.right == ppar) ppar = ppar.next; 
            return ppar.next;
        }
        return null;
    }
}

剑指 Offer 09. 用两个栈实现队列

思路:栈模拟O(n)

class CQueue {
        Stack<Integer> stack1;
        Stack<Integer> stack2;
    public CQueue() {
         stack1 = new Stack();
         stack2 = new Stack();
    }
    
    public void appendTail(int value) {
        stack1.push(value);
    }
    
    public int deleteHead() {
        if (stack2.isEmpty()) {
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.isEmpty() ? -1 : stack2.pop();
    }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue obj = new CQueue();
 * obj.appendTail(value);
 * int param_2 = obj.deleteHead();
 */

剑指 Offer 10- I. 斐波那契数列

思路一:暴力递归O(2^n) 超出时间限制

class Solution {
    public int fib(int n) {
       if(n < 2) return n;
       
       return (fib(n - 1) + fib(n - 2)) % 1000000007;
    }
}

**思路二:记忆化递归O(n) **

class Solution {
    public int fib(int n) {
       if(n < 2) return n;
       int[] fib = new int[n + 1];
       fib[0] = 0;
       fib[1] = 1;
       
       for(int i = 2; i <= n; i ++) {
           fib[i] = (fib[i - 1] + fib[i - 2]) % 1000000007;
       }
       
       return fib[n];
    }
}

**思路三:动态规划O(n) **

class Solution {
    public int fib(int n) {
        if (n < 2) return n;
        int a = 0;
        int b = 1;
        int sum;
        for(int i = 0; i < n; i ++) {
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }
        // i =0 时, a就是fib[1]的值
        return a;
    }
}

剑指 Offer 10- II. 青蛙跳台阶问题

**思路一:记忆化递归O(n) **

class Solution {
    public int trainWays(int num) {
        if(num < 2) return 1;
        int[] fib = new int[num + 1];
        fib[0] = 1;
        fib[1] = 1;
        for(int i = 2; i <= num; i++ ){
            fib[i] = (fib[i - 1] + fib[i - 2]) % 1000000007;
        }
        return fib[num];
    }
}

思路二:动态规划O(n)

class Solution {
    public int trainWays(int num) {
        int a = 0;
        int b = 1;
        int sum;
        for(int i = 0; i < num; i ++) {
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }
        //i= 0时,b就是fib[1]的值,和上一题的区别就是num = 0时,有一种方法
        return b;
    }
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值