近日LeetCode算法
前言:最近刷了好多leetcode算法题,大家知道,程序=数据结构+算法,由此可见,算法真的是很重要的呢。闲话少谈,切入正题,来看看小编觉得有点意思的5题算法题吧...
1. LeetCode 73:矩阵置零难度等级:中等
题目
给定一个 mn 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。
示例
解题思路
- 这是一个二维数组,我们只需要遍历一遍这个二维数组,把元素为0的那个位置所在的行与列分别标记起来,可以放在一个HashSet中,我们都知道,Set是一种无序不重复的集合,而List是有序可重复的,因此在这里小编选用两个Set来存储标记好的下标索引,遍历完得到这两个HashSet后,从HashSet中取得这些所有为0行列的索引后,我们就可以把原二维数组的某一行,某一列全部置为0即可。
- 值得注意的是,我们不可以一边标记一边置零,因为这样操作会影响结果,所以我们只可以遍历一遍,用来标记,再遍历一遍。用来置零。
图解
代码实现
package com.hx.leetcode.L_201910;
import java.util.HashSet;
import java.util.Set;
/**
* @author: wenhx
* @date: Created in 2019/10/1 23:03
* @description: LeetCode_73:矩阵置零
* @level: middle
* @status: finish
* @version: $1.0
*/
public class LeetCode_73 {
/**
* 将矩阵中所有0的行列置为0
*/
public void setZeroes(int[][] matrix) {
// 定义两个集合用来存放为0所有的下标
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j] == 0) {
set1.add(i);
set2.add(j);
}
}
}
// 行置为0
for (Integer a : set1
) {
for (int j = 0; j < matrix[0].length; j++) {
matrix[a][j] = 0;
}
}
// 列置为0
for (Integer b : set2
) {
for (int i = 0; i < matrix.length; i++) {
matrix[i][b] = 0;
}
}
}
/**
* 主方法:用来测试算法
* @param args
*/
public static void main(String[] args) {
LeetCode_73 leetCode_73 = new LeetCode_73();
int[][] matrix = {{0,1,2,0}, {3,4,5,2}, {1,3,1,5}};
leetCode_73.setZeroes(matrix);
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
System.out.print(matrix[i][j] + " ");
}
}
}
}
2. LeetCode 495:提莫攻击难度等级:中等
题目
在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄,他的攻击可以让敌方英雄艾希(寒冰射手)进入中毒状态。现在,给出提莫对艾希的攻击时间序列和提莫攻击的中毒持续时间,你需要输出艾希的中毒状态总时长。
你可以认为提莫在给定的时间点进行攻击,并立即使艾希处于中毒状态。
示例
解题思路
- 这条题目的入参是一个数组,用来记录提莫攻击的时间点,还有一个中毒的持续时间。我们可以先处理一下这个关于时间点的数组,相邻时间点的差值就是时间间隔,因此可以推出一个关于时间间隔的数组。假设时间点数组长度为n,那么时间间隔数组的长度就是n-1。得到这个时间间隔数组之后,再来处理中毒时间就很容易了
- 我们先有一个记录总中毒时间的变量,然后遍历时间间隔数组,假如间隔值大于或者等于中毒持续时间,则总中毒时间加单次中毒持续的时间;假如间隔值小于中毒持续时间,则加上间隔值即可。
图解
代码实现
package com.hx.leetcode.L_201910;
/**
* @author: wenhx
* @date: Created in 2019/10/5 12:03
* @description: LeetCode_495:提莫攻击
* @level: middle
* @status: finish
* @version: $1.0
*/
public class LeetCode_495 {
/**
* 计算中毒状态总时长
*/
public int findPoisonedDuration(int[] timeSeries, int duration) {
int sum = 0;
if (timeSeries.length == 0) {
return 0;
}
if (timeSeries.length == 1) {
return duration;
}
// n个时间点有n-1个时间间隔
int[] timeInterval = new int[timeSeries.length - 1];
for (int i = 0; i < timeInterval.length; i++) {
timeInterval[i] = timeSeries[i + 1] - timeSeries[i];
}
// 根据时间间隔来判断中毒秒数
for (int i = 0; i < timeInterval.length; i++) {
if (timeInterval[i] >= duration) {
sum += duration;
} else {
sum += timeInterval[i];
}
}
return sum + duration;
}
public static void main(String[] args) {
LeetCode_495 leetCode_495 = new LeetCode_495();
int[] timeSeries = {1, 4};
int duration = 2;
System.out.println("中毒状态总时长为:" + leetCode_495.findPoisonedDuration(timeSeries, duration));
}
}
3. LeetCode 41:缺失的第一个正数难度等级:困难
题目
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
解题思路
- 求缺失的第一个正数,那个先定义一个变量j来记录,j从1开始。
- 先对原数组进行排序,然后遍历,如果遍历元素大于j,那么找到缺失的第一个正数;如果遍历元素大于0并且小于j,那么j自增;这里还要判断遍历元素是否有重复,因此我们可以定义一个临时变量temp来记录上一个遍历元素的值,当连续相等时则continue,j不自增。
图解
代码实现
package com.hx.leetcode.L_201909;
import java.util.Arrays;
/**
* @author: wenhx
* @date: Created in 2019/9/26 09:23
* @description: LeetCode_41:缺失的第一个正数
* @level: hard
* @status: finish
* @version: $1.0
*/
public class LeetCode_41 {
/**
* 计算缺失的第一个正数
*/
public int firstMissingPositive(int[] nums) {
// 对数组进行排序
Arrays.sort(nums);
// 定义一个从1开始自增的正数
int j = 1;
// 定义一个临时变量,用来判断相邻值是否相同
int temp = 0;
for (int i = 0; i < nums.length; i++) {
// 当数组中某值大于自增j时
if (nums[i] > j) {
return j;
}
// 当数组中某值大于0并且不大于j时
else if (nums[i] > 0 && nums[i] <= j) {
// 数组中连续一样
if (temp == nums[i]) {
continue;
}
j++;
} else {
continue;
}
// 更新临时变量
temp = nums[i];
}
return j;
}
public static void main(String[] args) {
LeetCode_41 leetCode_41 = new LeetCode_41();
int[] nums = {1, 2, 0};
System.out.println("缺失的第一个正数为:" + leetCode_41.firstMissingPositive(nums));
}
}
4. LeetCode 535:TinyURL的加密与解密难度等级:中等
题目
TinyURL是一种URL简化服务。要求:设计一个 TinyURL 的加密 encode 和解密 decode 的方法。你的加密和解密算法如何设计和运作是没有限制的,你只需要保证一个URL可以被加密成一个TinyURL,并且这个TinyURL可以用解密方法恢复成原本的URL。
示例
当你输入一个URL https://leetcode.com/problems/design-tinyurl 时
它将返回一个简化的URL http://tinyurl.com/4e9iAk.
解题思路
- 这条题目主要是模拟对url的加密与解密,通过HashMap可以很好的处理加密前与加密后的映射。
- 加密后的url前缀格式有“http://tinyurl.com/”,问题是后面的6位随机码如何产生呢?很简单,自己写一个算法呗!看下列代码,可复用喔~
图解
代码实现
package com.hx.leetcode.L_201910;
import java.util.HashMap;
import java.util.Random;
/**
* @author: wenhx
* @date: Created in 2019/10/7 11:44
* @description: LeetCode_535:TinyURL的加密与解密
* @level: middle
* @status: finish
* @version: $1.0
*/
public class LeetCode_535 {
private HashMap hashMap = new HashMap<String, String>();
/**
* 加密:将一个长的url转换为一个短的url
* @param longUrl
* @return
*/
public String encode(String longUrl) {
String keyString = "http://tinyurl.com/" + getRandomString(6);
hashMap.put(keyString, longUrl);
return keyString;
}
/**
* 解密:将一个短的url转换为一个长的url
* @param shortUrl
* @return
*/
public String decode(String shortUrl) {
return (String) hashMap.get(shortUrl);
}
/**
* 自定义方法:产生6位数的字符串随机码
* @param length
* @return
*/
public static String getRandomString(int length) {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}
/**
* 主方法:用来测试一下
* @param args
*/
public static void main(String[] args) {
LeetCode_535 codec = new LeetCode_535();
String longUrl = "https://leetcode.com/problems/design-tinyurl";
String shortUrl = codec.encode(longUrl);
System.out.println("加密后的url是:" + shortUrl);
System.out.println("解密后的url是:" + codec.decode(shortUrl));
}
}
5. LeetCode 20:有效的括号难度等级:简单
题目
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例
解题思路
这里括号的匹配,用栈可以很好地解决这个问题。我们都知道,栈是一个后进先出的数据结构,将一个具有()[]{}的字符串从后面开始,一个一个地压入栈中,压第一个,然后再拿字符串中相对最后一个括号与栈中栈顶元素匹配,例如 ")"与"("匹配,"]"与"["匹配,"}"与"{"匹配。这里值得注意的是,栈顶的括号必须是右括号,而字符串尾部的括号必须是左括号。
图解
代码实现
package com.hx.leetcode.L_Before;
import java.util.Stack;
/**
* @author: wenhx
* @date: Created in 2019/9/25 10:58 (之前)
* @description: LeetCode_20:有效的括号
* @level: simple
* @status: finish
* @version: $1.0
*/
public class LeetCode_20 {
/**
* 计算是否有效的括号
*/
public boolean isValid(String s) {
Stack<String> m = new Stack<>();
while (!s.isEmpty()) {
if (m.empty()) {
m.push(s.substring(s.length() - 1));
} else {
if (m.peek().equals(")") && s.substring(s.length() - 1).equals("(")
|| m.peek().equals("]") && s.substring(s.length() - 1).equals("[")
|| m.peek().equals("}") && s.substring(s.length() - 1).equals("{")) {
m.pop();
} else {
m.push(s.substring(s.length() - 1));
}
}
s = s.substring(0, s.length() - 1);
}
if (m.empty()) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
LeetCode_20 leetCode_20 = new LeetCode_20();
String s = "{[]}()";
System.out.println(leetCode_20.isValid(s));
}
}
好啦,今天就先到这啦,以上算法纯属小编个人想法,如有疑惑可以留言,蟹蟹大家。一起谈论,一起进步。
小伙伴们后续有时间小编会经常跟新的嘿嘿...
后续