LeetCode习题集 有些题可能直接略过了,整理一下之前刷leetcode

661. 图片平滑器

包含整数的二维矩阵 M 表示一个图片的灰度。你需要设计一个平滑器来让每一个单元的灰度成为平均灰度 (向下舍入) ,平均灰度的计算是周围的8个单元和它本身的值求平均,如果周围的单元格不足八个,则尽可能多的利用它们。

示例 1:

输入: [[1,1,1], [1,0,1], [1,1,1]] 输出: [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 解释: 对于点 (0,0), (0,2), (2,0), (2,2): 平均(3/4) = 平均(0.75) = 0 对于点 (0,1), (1,0), (1,2), (2,1): 平均(5/6) = 平均(0.83333333) = 0 对于点 (1,1): 平均(8/9) = 平均(0.88888889) = 0 注意:

给定矩阵中的整数范围为 [0, 255]。 矩阵的长和宽的范围均为 [1, 150]。

class Solution {
    public int[][] imageSmoother(int[][] M) {
        int l1=M.length,l2=M[0].length;
        int[][] r=new int[l1][l2];
        for(int i=0;i<l1;i++)
            for(int j=0;j<l2;j++){
                int sum=M[i][j];
                int num=1;
                if(i>0 && j>0)
                    {sum+=M[i-1][j-1];num++;}
                if(i>0)
                    {sum+=M[i-1][j];num++;}
                if(i>0 && j<l2-1)
                    {sum+=M[i-1][j+1];num++;}
                if(j>0)
                    {sum+=M[i][j-1];num++;}
                if(j<l2-1)
                    {sum+=M[i][j+1];num++;}
                if(i<l1-1 && j>0)
                    {sum+=M[i+1][j-1];num++;}
                if(i<l1-1)
                    {sum+=M[i+1][j];num++;}
                if(i<l1-1 && j<l2-1)
                    {sum+=M[i+1][j+1];num++;}
                r[i][j]=sum/num;                
            }
        return r;
    }
}

662. 二叉树最大宽度

给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空。

每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。

示例 1:

输入:

       1
     /   \
    3     2
   / \     \  
  5   3     9 

输出: 4 解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。 示例 2:

输入:

      1
     /  
    3    
   / \       
  5   3     

输出: 2 解释: 最大值出现在树的第 3 层,宽度为 2 (5,3)。 示例 3:

输入:

      1
     / \
    3   2 
   /        
  5      

输出: 2 解释: 最大值出现在树的第 2 层,宽度为 2 (3,2)。 示例 4:

输入:

      1
     / \
    3   2
   /     \  
  5       9 
 /         \
6           7

输出: 8 解释: 最大值出现在树的第 4 层,宽度为 8 (6,null,null,null,null,null,null,7)。 注意: 答案在32位有符号整数的表示范围内。

PS: min就是我这一层最左面的点 max就是我右面的点,每一次进去,只要比最左面大,就保存 右面的点--左面的点=我这一层的大小 左面的就是val2-1,我如果有左面的就是我每一层会乘2,然后左面就是减去1 右面的就是val2; 自己带一个树试试就明白了,我当时也想了半天才明白

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     class Node {
        int min, max;
        Node next;
    }
    
    private void calNode(TreeNode node, int val, Node level ){
        if (level.min==0) {
            level.min=val;
            level.max=val;
        } else if (val>level.max) {
            level.max=val;
        }
        if (node.left==null && node.right==null) return;
        if (level.next==null) level.next = new Node();
        if (node.left!=null) calNode(node.left, val*2-1, level.next);
        if (node.right!=null) calNode(node.right, val*2, level.next);
    }
    
    public int widthOfBinaryTree(TreeNode root) {
        if (root==null) return 0;
        
        Node level = new Node();
        calNode(root, 1, level);
        int k, res=0;
        while (level!=null){
            k = level.max - level.min + 1;
            if (k>res) res = k;
            level = level.next;
        }
        return res;
        
    }
}

664. 奇怪的打印机

有台奇怪的打印机有以下两个特殊要求:

打印机每次只能打印同一个字符序列。 每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符。 给定一个只包含小写英文字母的字符串,你的任务是计算这个打印机打印它需要的最少次数。

示例 1:

输入: "aaabbb" 输出: 2 解释: 首先打印 "aaa" 然后打印 "bbb"。 示例 2:

输入: "aba" 输出: 2 解释: 首先打印 "aaa" 然后在第二个位置打印 "b" 覆盖掉原来的字符 'a'。 提示: 输入字符串的长度不会超过 100。

class Solution {
      int[][] memo;
    public int strangePrinter(String s) {
        int N = s.length();
        memo = new int[N][N];
        return dp(s, 0, N - 1);
    }
    //我当前的字符可以第一次打印,也可以被盖上去
    //肯定要不同的覆盖,覆盖的范围是我这个字符到我下一个这个字符相同的位置
    public int dp(String s, int i, int j) {
        if (i > j) return 0;
        if (memo[i][j] == 0) {
            int ans = dp(s, i+1, j) + 1;
            for (int k = i+1; k <= j; ++k)
            //我可以在j之前找到和i相同的这一块进行打印
                if (s.charAt(k) == s.charAt(i))
                    ans = Math.min(ans, dp(s, i, k-1) + dp(s, k+1, j));
            memo[i][j] = ans;
        }
        return memo[i][j];
    }
 
}

665. 非递减数列

给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。

我们是这样定义一个非递减数列的: 对于数组中所有的 i (1 <= i < n),总满足 array[i] <= array[i + 1]。

示例 1:

输入: nums = [4,2,3] 输出: true 解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。 示例 2:

输入: nums = [4,2,1] 输出: false 解释: 你不能在只改变一个元素的情况下将其变为非递减数列。

说明:

1 <= n <= 10 ^ 4

  • 10 ^ 5 <= nums[i] <= 10 ^ 5 通过次数16,232提交次数73,484
class Solution {
     public boolean checkPossibility(int[] nums) {
        if(nums.length<=2) return true;
        int i;
        boolean flag = true;
        for(i = 0; i< nums.length-1; i++){
            if(nums[i]>nums[i+1]){
                if(flag){
                    if(i>0 && nums[i-1]>nums[i+1]){
                        //前面的值大就让我下一个等于我当前的
                        nums[i+1] = nums[i];
                    } else{
                        //前面的小就让后面这俩相等
                        nums[i] = nums[i+1];
                    }
                    flag = false;
                } else{
                    return false;
                }
            }
        }
        return true;
    }
}

667. 优美的排列 II

给定两个整数 n 和 k,你需要实现一个数组,这个数组包含从 1 到 n 的 n 个不同整数,同时满足以下条件:

① 如果这个数组是 [a1, a2, a3, ... , an] ,那么数组 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中应该有且仅有 k 个不同整数;.

② 如果存在多种答案,你只需实现并返回其中任意一种.

示例 1:

输入: n = 3, k = 1 输出: [1, 2, 3] 解释: [1, 2, 3] 包含 3 个范围在 1-3 的不同整数, 并且 [1, 1] 中有且仅有 1 个不同整数 : 1

示例 2:

输入: n = 3, k = 2 输出: [1, 3, 2] 解释: [1, 3, 2] 包含 3 个范围在 1-3 的不同整数, 并且 [2, 1] 中有且仅有 2 个不同整数: 1 和 2

提示:

n 和 k 满足条件 1 <= k < n <= 104.

class Solution {
     public int[] constructArray(int n, int k) {
        int[] res = new int[n];
        int count = n;
        int rec = 1;
        for (int i = 0; i < n-k; i++) {
            res[i] = rec++;
        }
        boolean flag = true;
        for (int i = n-k; i < n; i++) {
            if (flag){
                res[i] = count--;
                flag =false;
            }else {
                flag = true;
                res[i] = rec++;
            }
        }
        return res;
    }
}

668. 乘法表中第k小的数

几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第k小的数字吗?

给定高度m 、宽度n 的一张 m * n的乘法表,以及正整数k,你需要返回表中第k 小的数字。

例 1:

输入: m = 3, n = 3, k = 5 输出: 3 解释: 乘法表: 1 2 3 2 4 6 3 6 9

第5小的数字是 3 (1, 2, 2, 3, 3). 例 2:

输入: m = 2, n = 3, k = 6 输出: 6 解释: 乘法表: 1 2 3 2 4 6

第6小的数字是 6 (1, 2, 2, 3, 4, 6). 注意:

m 和 n 的范围在 [1, 30000] 之间。 k 的范围在 [1, m * n] 之间。

class Solution {
   public int findKthNumber(int m, int n, int k) {
       int left = 1, right = m*n;
        while(left < right){
            int mid = left + (right-left)/2;
            if(counter(m, n, mid) >= k){
                right = mid;
            }else{
                left = mid + 1;
            }
        }
        return left;
    }
    public int counter(int m, int n, int mid) {
        int x = m;
        int y = 1;
        int counter = 0;
        while (x >= 1 && y <= n) {
            if (x * y <= mid) {
                counter += x;
                y++;
            } else {
                x--;
            }
        }
        return counter;
    }
}

669. 修剪二叉搜索树

给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。

示例 1:

输入: 
    1
   / \
  0   2

  L = 1
  R = 2

输出: 
    1
      \
       2

示例 2:

输入: 
    3
   / \
  0   4
   \
    2
   /
  1

  L = 1
  R = 3

输出: 
      3
     / 
   2   
  /
 1
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
     public TreeNode trimBST(TreeNode root, int L, int R) {
        if (root == null)
            return root; 
        if (root.val < L)
            return trimBST(root.right, L, R); 
        if (root.val > R)
            return trimBST(root.left, L, R); 
 
        root.left = trimBST(root.left, L, R);
        root.right = trimBST(root.right, L, R);
        return root;
    }
}

670. 最大交换

给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。

示例 1 :

输入: 2736 输出: 7236 解释: 交换数字2和数字7。 示例 2 :

输入: 9973 输出: 9973 解释: 不需要交换。 注意:

给定数字的范围是 [0, 108]

class Solution {
       public int maximumSwap(int num) {
        if(num<10) return num;
        int[] nums = new int[9];
        int size=0;
        while(num !=0){
            nums[size++] = num%10;
            num = num/10;
        }

        for(int tmp = size-1;tmp>=0;tmp--){
            int max = -1;
            int point = -1;
            for(int j = tmp-1;j>=0;j--){
                if(nums[j] >= max){
                    max = nums[j];
                    point = j;
                }
            }
            if(max > nums[tmp]){
                swap(nums, point, tmp);
                break;
            }
        }

        int sum = 0;
        for(int i =size-1;i>=0;i--){
            sum = sum*10 + nums[i];
        }
        return sum;
    }
private static void swap (int[] arr, int l, int r) {
    int temp = arr[l];
    arr[l] = arr[r];
    arr[r] = temp;
}
}