二刷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; // 空数组返回0if (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字符为空,所以和除了*以外的都不匹配,直接falseelse 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则直接赋值trueif(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()];}
7. 盛水最多的容器
/*** 高往低走,长度变小、高度变小、面积一定变小* 低往高走,长度变小、高度可能变大、面积可能变大*/public int maxArea(int[] height) {int i = 0, j = height.length - 1, res = 0;while(i < j) {res = height[i] < height[j]? Math.max(res, (j - i) * height[i++]): Math.max(res,(j - i) * height[j--]);}return res;}