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;
}
}