二刷hot100,坚持每天打卡!!!
Today:2023-8-10
1. 两数之和
// 先求差,再查哈希表
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++){
int key = target - nums[i];
if(map.containsKey(key)){
return new int[]{map.get(key),i};
}
map.put(nums[i],i);
}
return new int[0];
}
2. 两数相加
// 对应位置相加,记录进位,然后链表尾插法即可
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int flag = 0,lv1,lv2;
ListNode answer = null,target = null;
while (l1 != null || l2 != null){
lv1 = l1 == null ? 0:l1.val;
lv2 = l2 == null ? 0:l2.val;
l1 = l1 == null ? null:l1.next;
l2 = l2 == null ? null:l2.next;
int sum = lv1+lv2+flag;
flag = sum / 10;
ListNode listNode = new ListNode(sum % 10);
if (target == null){
target = listNode;
answer = target;
}else {
target.next = listNode;
target = target.next;
}
}
if (flag >0){
target.next = new ListNode(flag);
}
return answer;
}
3. 无重复字符的最长字串
// 滑动窗口
public int lengthOfLongestSubstring(String s){
Set<Character> set = new HashSet<>();
int start = 0,end = 0,answer=0;
while (end < s.length()){
if (set.contains(s.charAt(end))){
set.remove(s.charAt(start++));
}else {
set.add(s.charAt(end++));
answer = Math.max(answer,end - start);
}
}
return answer;
}
4. 最长回文子串
// 动态规划
public String longestPalindrome(String s) {
if (s == null || s.length() < 2) {
return s;
}
int strLen = s.length();
int maxStart = 0; //最长回文串的起点
int maxEnd = 0; //最长回文串的终点
int maxLen = 1; //最长回文串的长度
boolean[][] dp = new boolean[strLen][strLen];
for (int r = 1; r < strLen; r++) {
for (int l = 0; l < r; l++) {
if (s.charAt(l) == s.charAt(r) && (r - l <= 2 || dp[l + 1][r - 1])) {
dp[l][r] = true;
if (r - l + 1 > maxLen) {
maxLen = r - l + 1;
maxStart = l;
maxEnd = r;
}
}
}
}
return s.substring(maxStart, maxEnd + 1);
}
5. 寻找两个正序数组的中位数
/*
总体思路:模拟合并数组,合并到中位数停止
时间:1ms, 击败 100.00%使用 Java 的用户
内存:42.03mb 击败 63.77%使用 Java 的用户
*/
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int num = 0; // 偶数中位数数字,奇数中位数右侧数字
int len = nums1.length + nums2.length;
boolean b = len % 2 == 0; // 是否为偶数
len /= 2; // 偶数中位数位置,奇数中位数右侧位置
if (nums1.length + nums2.length == 0) return 0; // 空数组返回0
if (nums1.length == 0) return b ? (nums2[len - 1] + nums2[len]) / 2.0 : nums2[len]; // 数组1为空返回数组2中位数
if (nums2.length == 0) return b ? (nums1[len - 1] + nums1[len]) / 2.0 : nums1[len]; // 数组2为空返回数组1中位数
int i = 0,j = 0;
int oldNum = num; // 奇数中位数左侧数字
while (i + j != len + 1) { // 判断是否循环至中位数
oldNum = num;
if (i >= nums1.length || (j < nums2.length && nums1[i] > nums2[j])) num = nums2[j++];
else num = nums1[i++];
}
return b ? (num + oldNum) / 2.0 : num; // 返回中位数
}
6. 正则表达式匹配
// 动态规划
public boolean isMatch(String s, String p) {
//此处为length+1的目的是放入一个额外的为空的字符情况,以便于判断当*时,添加的字符情况
boolean table[][]=new boolean[s.length()+1][p.length()+1];
table[0][0]=true;
for(int i =1;i<table[0].length;i++){
char ch=p.charAt(i-1);
if(i>1){
//若ch=='*',则看同一行内回退两格的boolean值:
//(因为相当于若回退两格为true,即在选择添加该字符时可以选择数量为0(因为是'*'))
if(ch=='*'){
table[0][i]=table[0][i-2];
}
//因为第0行的s字符为空,所以和除了*以外的都不匹配,直接false
else table[0][i]=false;
}
else {
//如果填第一个空格,且字符为*,则赋值为true(因为*的匹配可以选择0个字符)
if(ch=='*') table[0][i]=true;
}
}
//接下来按照行优先的顺序填充表格
for(int j =1;j<table.length;j++){
char ch01=s.charAt(j-1);
for(int h =1;h<table[j].length;h++){
char ch02=p.charAt(h-1);
//如果行和列对应的字符相等 || 列的字符为'.',则当前位置的值由左斜上方的值确定
if(ch02==ch01||ch02=='.'){
table[j][h]=table[j-1][h-1];
}
//如果列的字符为'*'
else if(ch02=='*'){
if(h>1){
//按照规则,先在同一行回退两格,若该值为true则直接赋值true
if(table[j][h-2]==true) table[j][h]=true;
else {
//若不为true,则比较当前行的字符(s里的)与当前列-1的字符(p里的)是否相等
char prev=p.charAt(h-2);
//若相等 || 当前列-1的字符(p里的)为'.',将当前位置上方的值赋给当前位置
if(ch01==prev||prev=='.') table[j][h]=table[j-1][h];
}
}
}
}
}
//返回table表的最右下方元素,即为整个字符串的匹配结果
return table[s.length()][p.length()];
}