leetcode刷题 650~

题目650

只有两个键的键盘

最初在一个记事本上只有一个字符 'A'。你每次可以对这个记事本进行两种操作:

Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。
Paste (粘贴) : 你可以粘贴你上一次复制的字符。
给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 'A'。输出能够打印出 n 个 'A' 的最少操作次数。

思路

1.动态规划

2.素数分解

实现

1.
class Solution {
    public int minSteps(int n) {
        int[][] dp = new int [n+1][n+1];
        dp[1][1] = 1;
        int temp;
        for(int i=1; i < n+1; i++){
            temp = Integer.MAX_VALUE;
            for(int j=1; j < i; j++){
                if(dp[i-j][j] != 0){
                    dp[i][j] = dp[i-j][j] + 1;
                    temp = Math.min(temp, dp[i][j]);
                }
            }
            if(i != 1)
                dp[i][i] = temp+1;
        }
        return dp[n][n]-1;

    }
}
2.
class Solution {
    public int minSteps(int n) {
        int count = 0;
        while(n != 1){
            int i = findMaxDivisor(n);
            count += n/i;
            n = i;
        }
        return count;
    }

    private int findMaxDivisor(int n){
        int max = n / 2;
        for (int i = max ; i >= 2; i--) {
            if ( n % i == 0) return i;
        }
        return 1;
    }
}

题目652

寻找重复的子树

给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

两棵树重复是指它们具有相同的结构以及相同的结点值。

思路

假设每棵子树都有一个唯一标识符:只有当两个子树的 id 相同时,认为这两个子树是相同的。

一个节点 node 的左孩子 id 为 x,右孩子 id 为 y,那么该节点的 id 为 (node.val, x, y)。

实现

class Solution {
    int curID;
    Map<String, Integer> trees;
    Map<Integer, Integer> count;
    List<TreeNode> ans;

    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        curID = 1;
        trees = new HashMap<>();
        count = new HashMap<>();
        ans = new ArrayList();
        lookUP(root);
        return ans;
    }

    private int lookUP(TreeNode node){
        if (node == null) return 0;
        String serial = node.val + "," + lookUP(node.left) + "," + lookUP(node.right);
        int id = trees.computeIfAbsent(serial, key -> curID++);
        count.put(id, count.getOrDefault(id, 0) + 1);
        if (count.get(id) == 2)
            ans.add(node);
        return id;
    }
}

题目653

两数之和

给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。

思路

中序遍历出数组,双指针寻找元素

实现

class Solution {
    private ArrayList<Integer> nums = new ArrayList<>();
    public boolean findTarget(TreeNode root, int k) {
        inorder(root);
        int sum;
        int left = 0;
        int right = nums.size()-1;
        while(left < right){
            sum = nums.get(left) + nums.get(right);
            if(sum == k) return true;
            else if (sum < k) left++;
            else right--;
        }
        return false;
    }

    private void inorder(TreeNode node){
        if(node != null){
            inorder(node.left);
            nums.add(node.val);
            inorder(node.right);
        }
    }
}

题目654

最大二叉树

思路

递归

实现

class Solution {
    private int[] nums;
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        this.nums = nums;
        return construct(0, nums.length);
    }

    private TreeNode construct(int left, int right){
        if(left == right) return null;
        int maxIndex = getMaxIndex(left, right);
        TreeNode root = new TreeNode(nums[maxIndex]);
        root.left = construct(left, maxIndex);
        root.right = construct(maxIndex+1, right);
        return root;
    }

    private int getMaxIndex(int left, int right){
        int maxIndex=left;//假设第一个元素为最大值 那么下标设为0
        for(int i =left; i < right; i++){
            if(nums[maxIndex]<nums[i]){
                maxIndex=i;
            }
        }
        return maxIndex;
    }
}

题目655

输出二叉树

在一个 m*n 的二维字符串数组中输出二叉树,并遵守以下规则:

行数 m 应当等于给定二叉树的高度。
列数 n 应当总是奇数。
根节点的值(以字符串格式给出)应当放在可放置的第一行正中间。根节点所在的行与列会将剩余空间划分为两部分(左下部分和右下部分)。你应该将左子树输出在左下部分,右子树输出在右下部分。左下和右下部分应当有相同的大小。即使一个子树为空而另一个非空,你不需要为空的子树输出任何东西,但仍需要为另一个子树留出足够的空间。然而,如果两个子树都为空则不需要为它们留出任何空间。
每个未使用的空间应包含一个空的字符串""。
使用相同的规则输出子树。

思路实现

class Solution {
    private String[][] res;
    public List<List<String>> printTree(TreeNode root) {
        int depth = getDepth(root);
        res = new String[depth][(1 << depth) - 1];
        for(String[] arr: res)
            Arrays.fill(arr,"");
        dfs(root, 0, 0, (1 << depth)-1);
        List<List<String>> ans = new ArrayList<>();
        for(String[] arr:res)
            ans.add(Arrays.asList(arr));
        return ans;
    }
    private void dfs(TreeNode node, int depth, int left, int right){
        if(node == null) return;
        int mid = (left+right)/2;
        res[depth][mid] = "" + node.val;
        dfs(node.left, depth+1, left, mid-1);
        dfs(node.right, depth+1, mid+1, right);
    }

    private int getDepth(TreeNode node){
        if(node == null) return 0;
        return Math.max(getDepth(node.left), getDepth(node.right))+1;
    }
}

 

题目657

机器人能否返回原点

在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束。

移动顺序由字符串表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R(右),L(左),U(上)和 D(下)。如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。

注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L” 将始终向左移动等。此外,假设每次移动机器人的移动幅度相同。

思路实现

class Solution {
    public boolean judgeCircle(String moves) {
        int x = 0, y = 0;
        int length = moves.length();
        for(int i=0;i<length;i++){
            char ch = moves.charAt(i);
            if(ch == 'R') x++;
            else if(ch == 'L') x--;
            else if(ch == 'U') y++;
            else y--;
        }
        return x == 0 && y == 0;
    }
}

题目658

找到k个最接近的元素

给定一个排序好的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。

整数 a 比整数 b 更接近 x 需要满足:

|a - x| < |b - x| 或者
|a - x| == |b - x| 且 a < b

思路

利用二分法找到左区间

实现

class Solution {
    public List<Integer> findClosestElements(int[] arr, int k, int x) {
        int left = 0, right = arr.length-k;
        while(left < right){
            int mid = left + (right-left)/2;
            if(x - arr[mid] > arr[mid + k] - x){
                left = mid +1;
            }else{
                right = mid;
            }
        }
        List<Integer> res = new ArrayList<>();
        for (int i = left; i < left + k; i++) {
            res.add(arr[i]);
        }
        return res;

    }
}

题目633

思路实现

题目648

思路实现

题目633

思路实现

题目633

思路实现

题目648

思路实现

题目633

思路实现

posted @ 2021-02-17 11:44  maoguai  阅读(39)  评论(0编辑  收藏  举报