LeetCode-按顺序刷题备注1-50

  • 2.两数相加
  • ``3.无重复字符的最长子串``
    • 方法1:map做重复值判断
    • 方法2:滑动窗口,通过数组来替换map
  • 4.寻找正序数组的中位数
    • 方法1:合并数组
    • 方法2:二分查找,使时间复杂度为O(log(m+n))
    • 方法3:归并思想
  • ``5.最长回文子串``
    • 方法1:回溯,``超时``
    • 方法2:暴力解法
    • 方法3:DP
  • 6.字形变形
    • 方法1:
  • 7.整数反转
  • 8.字符串转换整数
  • 11.盛最多水的容器
  • 14.最长公共前缀
  • 17.电话号码的字母组合
  • ``18.四数之和``
  • ``23.合并K的升序链表``
    • 方法1:归并排序思想
  • ``31.下一个排列``
  • ``31.最长有效括号``
    • 方法1:DP
    • 方法2:栈
  • 30.串联所有单词的子串
    • 方法1:暴力遍历
    • 方法2:滑动窗口 ``暂留``
  • 33.搜索旋转排序数组
    • 二分法:
  • 81.搜索旋转排序数组 II
    • 方法1:与右比较
    • 方法2:与左比较
  • 34.在排序数组中查找元素的第一个和最后一个位置
    • 二分法:
  • 36.有效的数独
  • ``41.缺失的第一个正数``
    • 方法1:暴力
    • 方法2:进阶要求
  • 剑指offer03:数组中重复的数字
    • 方法1:原地哈希
  • ``42.接雨水``
    • 方法1:栈
    • 方法2:暴力解法
    • 方法3:DP
    • 方法4:双指针
  • 43.字符串相乘
  • ``45. 跳跃游戏 II``
    • 方法1:
    • 方法2:方法1优化
    • 方法3:DP
  • 49.字母异位词分组
    • 方法1:排序
    • 方法2:建立数组映射
  • ``50.Pow(x, n)``
    • 方法1:快速幂
    • 方法2:分治 + 记忆化
    • 方法3:快速幂递归写法

2.两数相加

  • 代码演示
/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {//一次处理两个链表public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode pre = new ListNode(0);ListNode cur = pre;int isBig = 0;while(l1 != null || l2 != null){//对l1与l2分别进行处理,来判断其是否为空int x1 = l1 == null ? 0 : l1.val;int x2 = l2 == null ? 0 : l2.val;int num = x1 + x2 + isBig;isBig = num > 9 ? 1 : 0;num = num % 10;cur.next = new ListNode(num);cur = cur.next;/*必须为l1!= null .而不是 l1.next != null。假设当前条件为l1.next != null。 l1到了最后一个节点,l1.next为空,不能执行l1 = l1.next,l1则一直不为空,循环不会终止同时,while循环条件为两者同时不为空,因此只需判断当前节点是否为空,来决定是否next*/if(l1 != null){l1 = l1.next;}if(l2 != null){l2 = l2.next;}}if(isBig != 0){cur.next = new ListNode(isBig);}return pre.next;}
}

3.无重复字符的最长子串

方法1:map做重复值判断

  • 代码演示:
class Solution {/*[start,end]:表示当前无重复子串*/public int lengthOfLongestSubstring(String s) {int len = s.length();if(len == 0){return 0;}int res = 0;Map<Character,Integer> map = new HashMap<>();for(int end = 0,start = 0 ;end < len ; end++){if(map.containsKey(s.charAt(end))){/*因为[start,end]表示当前无重复子串。因此取出来的start下标需要+1,也就是map.get(s.charAt(end)) + 1同时,可能出现如下情况,如abccb。首先c重复,start = 3,b重复后,若不加max,则start变为2,有误*/start = Math.max(map.get(s.charAt(end)) + 1,start);}//因为每次end都要进行更新,因此每次需要对res进行更新。res = Math.max(res,end - start + 1);map.put(s.charAt(end),end);}return res;}
}

方法2:滑动窗口,通过数组来替换map

  • 代码演示
class Solution {/*flag数组:记录字符出现的次数;数组长度为256,对应其ASCII值。值只可能是0或者1,第一次出现为0,发现重复后就可以去重。*/public int lengthOfLongestSubstring(String s) {int[] flag = new int[256];char[] sChar = s.toCharArray();int len = sChar.length;if(len == 0 ){return 0;}int res = 0;int start = 0;int end = 0;/*若flag[sChar[end]] == 0,则说明当前字符不重复,则继续往后遍历否则,则说明当前字符有重复,则flag[sChar[start]]--,将当前滑动窗口起始位置的字符标记减小,同时起始位置start++。直至当前滑动窗口中没有重复元素。    这两步的操作,实际上为去除当前滑动窗口字符的重复值。实际上,滑动窗口的大小是一直在变化中,且滑动窗口中的字符串是无重复元素的。我们需要比较当前滑动窗口与以往的最大值来得到最终的滑动窗口最大值,*/while(end < len){if(flag[sChar[end]] == 0){flag[sChar[end]] ++;end++;}else{flag[sChar[start]]--;start++;}res = Math.max(res,end-start);}return res;}
}

4.寻找正序数组的中位数

  • 题解:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/he-bing-yi-hou-zhao-gui-bing-guo-cheng-zhong-zhao-/

方法1:合并数组

  • 代码演示:
class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int len1 = nums1.length;int len2 = nums2.length;int len = len1+len2;int[] res = new int[len];if(len1 == 0 && len2 == 0){return 0;}int c1 = 0;int c2 = 0;int rc = 0;while(c1 < len1 && c2 < len2){if(nums1[c1] < nums2[c2]){res[rc++] = nums1[c1++];}else{res[rc++] = nums2[c2++];}}while(c1 < len1){res[rc++] = nums1[c1++];}while(c2 < len2){res[rc++] = nums2[c2++];}return len % 2 == 0 ? (double)(res[len / 2] + res[len/2 - 1]) / 2 : res[len/2];  }
}
  • 分析:时间复杂度为O(M+N)

方法2:二分查找,使时间复杂度为O(log(m+n))

  • 代码演示:
class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {//始终使得数组1的长度较小,方便后续处理if(nums1.length > nums2.length){int[] temp = nums1;nums1 = nums2;nums2 = temp;}int m = nums1.length;int n = nums2.length;/*totalLeft:表示分割线左边的元素总和。做了特殊处理,定义数组总长度为奇数时,我们使左边元素比右边元素个数多1,因此totalLeft可以用统一公式来计算。*/int totalLeft = (m+n+1)/2;int left = 0;int right = m;/*i:数组1的分界线,j:数组2的分界线。分界线的值等于分界线左边的值的个数,也就是说,分界线的值始终等于分界线右边第第一个值的下标。通过二分查找,在数组1[0...m]中,找到符合“分界线左边的值始终小于分界线右边的值”的分界线位置。因为两个数组都为有序数组,因此通过比较两个数组分界线旁值的大小,来确定分界线的移动。最终找到一个合适的位置,使得 nums1[i - 1] <= nums2[j] && nums2[j - 1] <= nums1[i]若数组1的分界线确定,则通过分界线左边的总值为一个定值,可确定数组2的分界线。*/while(left < right){int i = left + (right - left  + 1) / 2;int j = totalLeft - i;if(nums1[i-1] > nums2[j]){right = i-1;}else{left = i;}}int i = left;int j = totalLeft - i;/*边界判断,分界线可能会在数组的边界。因为要对分界线左边取最大值与右边取最小值,因此定义左边的边界情况,值最小,不影响输出时取最大。右边的边界状况同理分析。*/int nums1LeftMax = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];int nums1RightMin = i == m ? Integer.MAX_VALUE : nums1[i];int nums2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j -1];int nums2RightMin = j == n ? Integer.MAX_VALUE : nums2[j]; if((m+n)  % 2 == 1){return Math.max(nums1LeftMax,nums2LeftMax);}else{return (double)((Math.max(nums1LeftMax,nums2LeftMax) + Math.min(nums1RightMin,nums2RightMin))) / 2;}}
}

方法3:归并思想

class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int len1 = nums1.length;int len2 = nums2.length;int index = (len1 + len2) / 2;  //目标索引,找到目标索引值即可停止。int[] res = new int[index + 1];int count = 0;int index1 = 0;int index2 = 0;while(count < index + 1){//越界判断if(index1 == len1){res[count++] = nums2[index2++];continue;}if(index2 == len2){res[count++] = nums1[index1++];continue;}//比较判断if(nums1[index1] < nums2[index2]){res[count++] = nums1[index1++];}else{res[count++] = nums2[index2++];}}//判断奇偶性进行输出if((len1+ len2) % 2 == 1){return (double)res[index];}else{return (double)(res[index] + res[index -1]) / 2;}}
}

5.最长回文子串

-题解: https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/

方法1:回溯,超时

  • 思路:按照题目131的思路,运用递归的方式找出所有回文子串,通过比较选择最大的那个。但是,运行结果会超时。
  • 代码演示:
class Solution {int max = 0;String res  = "";public String longestPalindrome(String s) {int len = s.length();if(len == 0){return "";}if(len == 1){return s;}dfs(s,0,len);return res;}public void dfs(String s , int begin ,int len){if(begin == len){return;}for(int i = begin; i < len ;i++){String substr = s.substring(begin,i + 1);if(isHuiWen(substr)){if(substr.length() > max){res = substr;max = substr.length();}dfs(s,i+1,len);}}}public boolean isHuiWen(String s){int left = 0;int right = s.length() -1;while(left < right){if(s.charAt(left) != s.charAt(right)){return false;}left ++;right --;}return true;}
}

方法2:暴力解法

  • 思路:通过双重循环遍历所有的字符串,返回长度最大的字符串。
  • 代码演示:
class Solution {/*begin:记录最大长度回文串的起始地址max:记录回文串的最大长度通过begin与max,则可分割出最大长度的回文串。*/public String longestPalindrome(String s) {int len = s.length();int max = 1;int begin = 0;if(len == 0){return "";}char[] sChar = s.toCharArray();for(int i = 0; i < len;i++){for(int j = i; j < len ; j++){if(j-i+1 > max && isHuiWen(sChar,i,j)){max = j - i + 1;begin = i;}}}return s.substring(begin,begin+max);}public boolean isHuiWen(char[] sChar, int left, int right){while(left < right){if(sChar[left] != sChar[right]){return false;}left ++;right --;}return true;}
}

方法3:DP

  • 思路:一个字符串,如果字符串的两边相等,则字符串是否回文是由字符串去头去尾所得到的子字符串决定的。

  • 代码演示:
class Solution {//dp[i][j]代表字符串[i..j]是否为回文字符串boolean[][] dp;public String longestPalindrome(String s) {int len = s.length();if(len < 2){return s;}this.dp = new boolean[len][len];int max = 1;int begin = 0;//对角线上的元素肯定为回文字符串for(int i = 0 ; i < len ;i++){dp[i][i] = true;}/*状态转移方程为dp[i][j] = (s[i]==s[j]) and (j - i < 3 or dp[i+1][j-1] )由dp转移方程可以得到,在二维数组中。当前位置的状态与左下角位置的状态相关。因此,先填充列,后填充行同时,边界条件,j-1+(i+1)+1 < 2 => j-i < 3,当前字符串的长度为2或者3时,且两头字符相等时,不需要做缩减     */for(int j = 1 ; j < len ;j++){for(int i = 0 ; i < j ;i++){if(s.charAt(i) != s.charAt(j)){dp[i][j] = false;}else{if(j - i < 3){dp[i][j] = true;}if(dp[i+1][j-1]){dp[i][j] = true;}}//若当前子字符串为回文串,判断其长度并且距离最大长度以及起始位置if(dp[i][j] && j -i + 1 > max){max = j - i + 1;begin = i;}}}return s.substring(begin,begin+max);}
}

6.字形变形

  • 题解:https://leetcode-cn.com/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/

方法1:

  • 代码演示:
class Solution {/*由分析可知,Z字形字符串转为从左往右依次读取,那么需要将字符串受限存储为Z字形。因为最终结果为从左往右依次读取,因此,字符存在具体的那一列不是很重要,只需要字符列的前后关系,也就是在每一行的前后关系,得出Z字形每一行的字符,最终进行拼接即可。*/public String convert(String s, int numRows) {//若行数为0或者1,则不需要进行处理,直接输出即可if(numRows < 2 || s.length() < 2){return s;}int flag = -1;//表示方向是下还是上,1为下,-1为上int row = 0; //遍历字符串时行的相应变化值List<StringBuilder> list = new ArrayList<StringBuilder>();//为每行创建一个新的StringBulderfor(int i = 0 ; i < numRows ;i++){list.add(new StringBuilder());}//遍历挣个字符串,按行依次存储,到达首行与尾行,需要转变方向。将每一个字符拼接在相应的行字符串中即可。for(char c : s.toCharArray()){list.get(row).append(c);if(row == 0 || row == numRows -1){flag = -flag;}row += flag;}//按行遍历,拼接挣个结果StringBuilder res = new StringBuilder();for(StringBuilder sb : list){res.append(sb);}return res.toString();}
}

7.整数反转

  • 思路:

    • 如下图所示,整数的最大值为2147483647。在倒数第二位进行判断,也就是判断214748364。如果当前数值大于214748364,则说明溢出。如果等于214748364,则判断最后一位,如果大于7,则溢出。
  • 最小值的情况如上类似。
  • 代码演示:
class Solution {int max = Integer.MAX_VALUE / 10;int min = Integer.MIN_VALUE / 10;public int reverse(int x) {if(x > -10 && x < 10){return x;}int res = 0;int num = 0; while(x != 0){num = x % 10;x = x / 10;//判断最大if(res > max || (res == max && num > 7)){return 0;}//判断最小if(res < min || (res == min && num < -8)){return 0;}res = res * 10 + num;}return  res;}
}

8.字符串转换整数

  • 注意点:有效字符串的要求

    • 依据题目所给思路来进行编码。
  • 代码演示:
public class Solution {public int myAtoi(String str) {int len = str.length();// str.charAt(i) 方法回去检查下标的合法性,一般先转换成字符数组char[] charArray = str.toCharArray();// 1、去除前导空格int index = 0;while (index < len && charArray[index] == ' ') {index++;}// 2、如果已经遍历完成(针对极端用例 "      ")if (index == len) {return 0;}// 3、如果出现符号字符,仅第 1 个有效,并记录正负int sign = 1;char firstChar = charArray[index];if (firstChar == '+') {index++;} else if (firstChar == '-') {index++;sign = -1;}// 4、将后续出现的数字字符进行转换// 不能使用 long 类型,这是题目说的int res = 0;while (index < len) {char currChar = charArray[index];// 4.1 先判断不合法的情况,因为if (currChar > '9' || currChar < '0') {break;}// 题目中说:环境只能存储 32 位大小的有符号整数,因此,需要提前判:断乘以 10 以后是否越界if (res > Integer.MAX_VALUE / 10 || (res == Integer.MAX_VALUE / 10 && (currChar - '0') > Integer.MAX_VALUE % 10)) {return Integer.MAX_VALUE;}if (res < Integer.MIN_VALUE / 10 || (res == Integer.MIN_VALUE / 10 && (currChar - '0') > -(Integer.MIN_VALUE % 10))) {return Integer.MIN_VALUE;}// 4.2 合法的情况下,才考虑转换,每一步都把符号位乘进去res = res * 10 + sign * (currChar - '0');index++;}return res;}}

11.盛最多水的容器

  • 代码演示:
class Solution {public int maxArea(int[] height) {int left = 0;int right = height.length - 1;int max = 0;/*因为从两边往中心寻找面积最大的过程中,长始终是减小的。因此,只有当宽增大时,取得的面积才有可能比之前的面积大因此,对左右的宽进行比较,让小的一边改变。*/while(left < right){int h = Math.min(height[left],height[right]);max = Math.max(h * (right - left) , max);if(height[left] < height[right]){left++;}else{right--;}}return max;}
}

14.最长公共前缀

  • 代码演示:
class Solution {public String longestCommonPrefix(String[] strs) {int strlen = strs.length;if(strlen == 0){return "";}int minlen = Integer.MAX_VALUE;//找出字符串的最小长度for(int i = 0 ; i < strlen ; i++){minlen = Math.min(minlen,strs[i].length());}StringBuilder sb = new StringBuilder();/*外循环:字符遍历;内循环:字符串数组遍历原理就是每次取一个字符,来依次在字符串数组中判断当前字符串的字符是否与其相等。*/for(int i = 0; i < minlen;i++){char c = strs[0].charAt(i);for(int j = 1 ; j < strlen ;j++){if(strs[j].charAt(i) != c){return sb.toString();}}sb.append(c);}return sb.toString();}
}

17.电话号码的字母组合

  • 思路:递归
  • 代码演示
class Solution {String[] chars = new String[]{"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};int len;List<String> res = new ArrayList<>();public List<String> letterCombinations(String digits) {this.len = digits.length();if(digits.length() == 0){return res;}StringBuilder sb = new StringBuilder();dfs(digits,0,sb);return res;}/*c:为当前的遍历数字;str:取出当前数字所对应的字符串遍历当前字符串的字符,进行递归处理。输出:直至拼接的位置index==len,说明当前字符串拼接完成*/public void dfs(String digits,int index,StringBuilder sb){if(index == len){res.add(sb.toString());return;}char c = digits.charAt(index);String str = chars[c-'0'-2];for(int i = 0 ; i < str.length() ; i++){dfs(digits,index+1,sb.append(str.charAt(i)));sb.deleteCharAt(sb.length()-1);}}
}

18.四数之和

  • 思路:与三数之和类似,只是我们当前进行双重循环。固定两个数值,从而在[left,right]中寻找合适的数值,使得nums[i] + nums[j] + nums[left] + nums[right] == target。
  • 代码演示:
class Solution {List<List<Integer>> res = new ArrayList<>();public List<List<Integer>> fourSum(int[] nums, int target) {int len = nums.length;if(len == 0){return res;}Arrays.sort(nums);for(int i = 0; i < len - 3 ;i++){//去重操作if(i > 0 &&  nums[i] == nums[i-1]) continue;/*若当前[i..len-1]中前四个数值加起来大于target,因为整个数组递增,则可判断此序列中不会有等于target的结果,执行break若当前[i..len-1]中,固定nums[i],且与最后三个数值的和小于target,则当前nums[i]过于小,直接continue跳出当前循环*/if(target < nums[i] + nums[i+1] + nums[i+2] + nums[i+3]) break;if(target > nums[i] + nums[len-1] + nums[len -2] + nums[len -3]) continue;for(int j = i + 1 ; j <len-2 ;j++){//去重if(j > i+1 &&  nums[j] == nums[j-1]) continue;/*与i的剪枝操作类似,只是此时需要固定nums[i],从而判断当前nums[j]的相应操作数值大小*/if(target < nums[i] + nums[j] + nums[j+1] + nums[j+2]) break;if(target > nums[i] + nums[j] + nums[len-1] + nums[len -2]) continue;int left = j+1;int right = len-1;while(left < right){int sum = nums[i] + nums[j] + nums[left] + nums[right];if(sum == target){res.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));left ++ ;right --;while(left < right && nums[left] == nums[left-1]) left++;while(left < right && nums[right] == nums[right+1]) right--;}else if(sum < target){left++;}else{right--;}}}}return res;}
}

23.合并K的升序链表

方法1:归并排序思想

  • 代码演示
/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {//利用归并排序的方式思想来进行public ListNode mergeKLists(ListNode[] lists) {int len = lists.length;if(len == 0 || lists == null){return null;}return merge(lists,0,len-1);}public ListNode merge(ListNode[] lists,int left ,int right){if(left == right) return lists[left];int mid = (left + right + 1) / 2;//选择两个链表ListNode leftNode =  merge(lists,left,mid-1);ListNode rightNode = merge(lists,mid,right);//合并return mergeList(leftNode,rightNode);}public ListNode mergeList(ListNode l1 ,ListNode l2){ListNode sentry = new ListNode(0);ListNode pre = sentry;while(l1 != null && l2 != null){if(l1.val < l2.val){pre.next = l1;l1 = l1.next;}else{pre.next = l2;l2 = l2.next;}pre = pre.next;}if(l1 != null){pre.next = l1;}if(l2 != null){pre.next = l2;}return sentry.next;}
}

31.下一个排列

  • 题解:https://leetcode-cn.com/problems/next-permutation/solution/xia-yi-ge-pai-lie-suan-fa-xiang-jie-si-lu-tui-dao-/
  • 代码演示:
class Solution {public void nextPermutation(int[] nums) {int len = nums.length;if(len == 1){return;}int min = -1;int max = -1;/*例如:14231。首先从尾找到第一个相邻的递减序列,如23,min=2。再从尾找到第一个比nums[min]=2大的数,也就是3。交换得14321。这样既可保证[i-1...len-1]为一个递减序列。因为nums[i-1]已增大,所以整个数组排列增大。因此,想要使得此排列为增大最小。翻转[i...len-1],使得[i...len-1]为一个递增序列。这样,则得到最小值。14312*/for(int i = len - 1 ; i >= 1 ;i--){if(nums[i-1] < nums[i]){min = i-1;break;}}//特殊情况,数组已然最大  if(min == -1){reverseNums(nums,0);return;}for(int i = len-1 ;i > min; i--){if(nums[i] > nums[min]){max = i;break;}}change(nums,min,max);reverseNums(nums,min+1);return;}public void change(int[] nums,int left ,int right){int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}public void reverseNums(int[] nums,int start){int left = start;int right = nums.length-1;while(left < right){change(nums,left,right);left++;right--;}}
}

31.最长有效括号

  • 题解:官方题解+题解评论

方法1:DP

  • 代码演示
class Solution {public int longestValidParentheses(String s) {int len = s.length();if(len == 0){return 0;}//dp[i] 表示以当前下标i为结尾的字符串匹配的最大长度int[] dp = new int[len+1];dp[0] = 0;char[] schar = s.toCharArray();int max = 0;for(int i = 1 ; i < len ; i++){if(schar[i] == '('){dp[i] = 0;}/*()((())碰到')',首先寻找最后一个未匹配位置。dp[i-1] == 0,说明i-1位置未匹配,pre=i-1-predp=i-1。dp[i-1] != 0,则predp存储的为当前匹配的长度则,pre = i-1 - predp,寻找到未匹配位置假设当前i=6,dp[i-1]=2,则pre= i-1-2=3,寻找到了当前未匹配位置*/if(schar[i] == ')'){int predp = dp[i-1];int pre = i - 1 - predp;//进行匹配if(pre >= 0 && schar[pre] == '('){dp[i] = dp[i-1]+2;/*判断匹配位置的前一个位置是否还有有效匹配。若有,则说明匹配序列连续,则加上前一个位置的dp。若无,则+0.因为前一个位置无匹配,则dp[pre-1] = 0,因此直接加dp[pre-1]即可。*/if(pre - 1 >= 0){dp[i] += dp[pre-1];}}}max = Math.max(dp[i],max);}return max;}
}

方法2:栈

  • 思路:对于字符串的匹配问题,一般情况都可以运用栈来解决
  • 代码演示
class Solution {public int longestValidParentheses(String s) {int len = s.length();if(len == 0){return 0;}Deque<Integer> stack = new LinkedList<>();char[] schar = s.toCharArray();int max = 0;/*始终保持栈底元素是最后一个未匹配的右括号的下标。为了方便处理,保证第一个元素为右括号时,栈为空不能执行pop,因此初始时push(-1)。*/stack.push(-1);for(int i = 0; i < len ;i++){if(schar[i] == '('){stack.push(i);}else{stack.pop();//如果当前栈为空,说明当前右括号未匹配,下标压入//否则说明当前右括号有匹配,则当前i减去未匹配右括号的下标(栈底元素),则为长度if(stack.size() == 0){stack.push(i);}else{max = Math.max(max,i - stack.peek());}}}return max;}
}

30.串联所有单词的子串

  • 题解:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/solution/chuan-lian-suo-you-dan-ci-de-zi-chuan-by-powcai/

方法1:暴力遍历

  • 代码演示1:
class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> res = new ArrayList<>();Map<String,Integer> map = new HashMap<>();//所给条件,words中每个字符串的长度相等int oneLen = words[0].length();int allLen = oneLen * words.length;//map:存储的words字符串键值对,key:当前字符串;value:当前单词出现的次数for(int i = 0;i < words.length;i++){map.put(words[i],map.getOrDefault(words[i],0) + 1);}/*每次从s中截取总长度的字符串,将此字符串依次进行分割。首先判断字符串是否合理,不合理(words中没有此字符串),直接跳出。合理,则压入tempMap,最终比较两个map是否相等即可。*/for(int i = 0 ; i < s.length() - allLen + 1 ;i++){String substr = s.substring(i,i + allLen);Map<String,Integer> tempMap = new HashMap<>();for(int j = 0 ; j < allLen; j += oneLen){String ss = substr.substring(j, j + oneLen);if(!map.containsKey(ss)){break;}tempMap.put(ss,tempMap.getOrDefault(ss,0) + 1);}                     if(map.equals(tempMap)){res.add(i);}}return res;}
}
  • 代码演示2:与代码1的思路一致,只是写法不同。
class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> res = new ArrayList<>();Map<String,Integer> map = new HashMap<>();//所给条件,words中每个字符串的长度相等int oneLen = words[0].length();int allLen = oneLen * words.length;//map:存储的words字符串键值对,key:当前字符串;value:当前单词出现的次数for(int i = 0;i < words.length;i++){map.put(words[i],map.getOrDefault(words[i],0) + 1);}/*每次从s中截取总长度的字符串,将此字符串依次进行分割。首先判断字符串是否合理,不合理(words中没有此字符串),直接跳出。合理,则将tempMap中的字符串key的value-1。如果value == 0,则说明words中的key字符串已匹配完,移除此key。最终,tempMapsize == 0,则说明全部匹配成功*/for(int i = 0 ; i < s.length() - allLen + 1 ;i++){String substr = s.substring(i,i + allLen);//必须这样写。若直接用map进行判断,则每一次循环都是用的同一个map对象。//这样写,每一次循环都是用的tempMap,只是将map的值赋值给tempMapMap<String,Integer> tempMap = new HashMap<>(map);;for(int j = 0 ; j < allLen; j += oneLen){String ss = substr.substring(j, j + oneLen);if(!tempMap.containsKey(ss)){break;}tempMap.put(ss,tempMap.get(ss)-1);if(tempMap.get(ss) == 0){tempMap.remove(ss);}}                     if(tempMap.size() == 0){res.add(i);}}return res;}
}

方法2:滑动窗口 暂留

33.搜索旋转排序数组

二分法:

  • 题解:二分法总结(35题):https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/
  • 代码演示
class Solution {public int search(int[] nums, int target) {int left = 0;int right = nums.length-1;//二分法while(left < right){int mid = left + (right- left + 1) /2;if(nums[mid] == target){return mid;}//在mid的两边,肯定有一边是有序的。//在中间元素小于有边界元素时,[mid,right]肯定是有序的。否则[left,mid-1]区间肯定是有序的、if(nums[mid] < nums[right]){//通过此判断条件,说明target在[left,right]的右半部分if(nums[mid] <= target && target <= nums[right]){left = mid;}else{right = mid-1;}}else{//通过此判断条件,说明target在[left,right]的左半部分if(nums[left] <= target && target <= nums[mid-1]){right = mid-1;}else{left = mid;}}}//因为mid=left+(right -left + 1) /2;因此将数组分为[left,mid-1],[mid,right]两部分。//如果数组长度为1.mid=1,[mid,left] == null,因此需要进行特殊判断if(nums[left] == target){return left;}return -1;}
}

81.搜索旋转排序数组 II

方法1:与右比较

  • 代码演示:
class Solution {public boolean search(int[] nums, int target) {int len = nums.length;int left = 0;int right = len - 1;while(left < right){int mid = left + (right - left + 1) / 2;if(nums[mid] == target){return true;}/*当数组为10111时,此时nums[mid]与nums[right]都是1,无法判断当前数组哪一边有序,因此需要去重。去重,因为后面mid与right进行比较,因此对右边进行去重,直至nums[mid]与nums[right]不相等。*/if(nums[mid] == nums[right]){right--;continue;}//[mid,right]单调不减if(nums[mid] < nums[right]){if(nums[mid] <= target && target <= nums[right]){left = mid;}else{right = mid - 1;}}else{//[left,mid]单调不增if(nums[mid] >= target && target >= nums[left]){right = mid - 1;}else{left = mid;}}}if(nums[left] == target){return true;}return false;}
}

方法2:与左比较

  • 思路:与方法1类似,只是比较的处理不同。
  • 代码演示:
class Solution {public boolean search(int[] nums, int target) {int len = nums.length;int left = 0;int right = len - 1;while(left < right){int mid = left + (right - left) / 2;if(nums[mid] == target){return true;}if(nums[mid] == nums[left]){left++;continue;}if(nums[mid] > nums[left]){if(nums[left] <= target && target <= nums[mid]){right = mid -1;}else{left = mid;}}else{if(nums[mid] < target && target <= nums[right]){left = mid;}else{right = mid-1;}}}if(nums[left] == target){return true;}return false;}
}

34.在排序数组中查找元素的第一个和最后一个位置

二分法:

  • 代码演示:
class Solution {int len;public int[] searchRange(int[] nums, int target) {this.len = nums.length;if(len == 0 || nums[len-1] < target){return new int[]{-1,-1};}/*。first:将区间分为[left,mid],[mid+1,right]。因为mid==target时,起始位置只可能在mid之前(包括mid),往前找。last:将区间分为[left,mid-1],[mid,right]。因此mid==target时,结束位置只可能在mid之后(包括mid),往后找*/int first = findFirst(nums,target);//若first未找到,则说明数组中无目标值,直接返回if(first == -1){return new int[]{-1,-1};}int last = findLast(nums,target);return new int[]{first,last};}public int findFirst(int[] nums,int target){int left = 0;int right = len -1;while(left < right){int mid = left + (right - left) /2;if(nums[mid] < target){left = mid + 1;}else if(nums[mid] > target){right = mid-1;}else{right = mid;}}//判断是否找到,last不用判断,因为若first可找到,last肯定会找到。极端情况,first==lastif(nums[left] == target){return left;}return -1;}public int findLast(int[] nums,int target){int left = 0;int right = len -1;while(left < right){int mid = left + (right - left + 1) /2;if(nums[mid] < target){left = mid + 1;}else if(nums[mid] > target){right = mid - 1;}else{left = mid;}}return left;}
}

36.有效的数独

  • 代码演示
class Solution {public boolean isValidSudoku(char[][] board) {boolean[][] rowF = new boolean[9][9];//行标记,判断每一行是否有重复元素boolean[][] colF = new boolean[9][9];//列标记,判断每一列是否有重复元素boolean[][] boxF = new boolean[9][9];//box标记,判断每一个box是否有重复元素for(int i = 0 ; i < 9 ; i++){for(int j = 0 ; j < 9 ; j++){if(board[i][j] == '.'){continue;}//将1-9字符转换为0-8下标int num = board[i][j] - '0' - 1;if(rowF[i][num]){return false;}else{rowF[i][num] = true; }if(colF[j][num]){return false;}else{colF[j][num] = true; }//box下标转换。算出当前[i][j]属于第几个boxint boxIndex = (i / 3) * 3 + j / 3;if(boxF[boxIndex][num]){return false;}else{boxF[boxIndex][num] = true;}}}return true;}
}

41.缺失的第一个正数

方法1:暴力

  • 空间复杂度为O(N),题目的进阶要求为常数级别
  • 代码演示
class Solution {public int firstMissingPositive(int[] nums) {int len = nums.length;if(len == 0){return 1;}Set<Integer> set = new HashSet<>();int max = 0;//将正数存入set并记录最大值for(int i = 0 ; i < nums.length;i++){if(nums[i] > 0){set.add(nums[i]);max = Math.max(max,nums[i]);}}//从1开始遍历到最大值,判断set中是否包含此值for(int i = 1 ; i <= max ; i++){if(!set.contains(i)){return i;}}//特殊情况,当数组的最大值为0时,或者数组为一个正数连续递增序列。//此时寻找位置为0+1,max+1。max初值为0,因此return max+1;return max +1;}
}
  • 优化思路:取消max,用数组长度来进行遍历。

    • 对于一个长度为n的数组,其中没有出现的最小正正数只可能在[1…n+1]中。
class Solution {public int firstMissingPositive(int[] nums) {int len = nums.length;if(len == 0){return 1;}Set<Integer> set = new HashSet<>();for(int i = 0 ; i < nums.length;i++){if(nums[i] > 0){set.add(nums[i]);}}//只需判断当前小于或者数组长度的字符是否在数组中。//因为若数组中出现负数,肯定缺失小于数组长度的正数。//若数组从1开始连续递增,则返回len+1,返回数组长度的后一位。for(int i = 1 ; i <= len ; i++){if(!set.contains(i)){return i;}}return len + 1;}
}

方法2:进阶要求

  • 思路:原地哈希
  • 代码演示:
class Solution {public int firstMissingPositive(int[] nums) {int len = nums.length;if(len == 0){return 1;}for(int i = 0 ; i < len ; i++){//将nums[i]放入nums[i] - 1的位置上。也就是将i位置与nums[i]-1位置的数值进行交换//因为长度为n的数组,未出现的最小正整数的只可能在[1...n+1]中,判断条件如下。//正数 && 满足大小 && 去除重复while(nums[i] > 0 && nums[i] <= len && nums[nums[i] - 1] != nums[i]){swap(nums,nums[i] - 1,i);}}for(int i = 0 ; i < len ;i ++){if(nums[i] - 1 != i){return i + 1;}}return len + 1;}public void swap(int[] nums,int left, int right){int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}
}

剑指offer03:数组中重复的数字

方法1:原地哈希

  • 思路:在当前数字放在以当前数字为下标的位置上。如果碰到重复,则返回,否则交换。
  • 代码演示
class Solution {public int findRepeatNumber(int[] nums) {int len = nums.length;for(int i = 0 ; i < len ; i++){//当当前数字不在位置上时,判断重复且交换。//用while重复判断一直交换,因为每次换来的nums[nums[i]]可能还不在合适的位置。while(nums[i] != i){if(nums[i] == nums[nums[i]]){return nums[i];}swap(nums,nums[i],i);}}return -1;}public void swap(int[] nums,int left, int right){int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}
}

42.接雨水

  • 题解:

    • https://leetcode-cn.com/problems/trapping-rain-water/solution/dan-diao-zhan-jie-jue-jie-yu-shui-wen-ti-by-sweeti/

方法1:栈

  • 代码演示:
class Solution {public int trap(int[] height) {int len = height.length;if(len == 0){return 0;}//存储的为height的下标,stack存储的一直为单调不增序列Deque<Integer> stack = new LinkedList<>();int res = 0;for(int i = 0  ; i < len ; i++){//因为stack为单调不增。当栈不为空,且栈顶元素小于当前元素,说明数组有可能有“坑”。//(两种情况[2,2,3],[4,2,3])。[2,2,3]这种情况处理重复元素时已经删除,[4,2,3]则说明有坑。while(!stack.isEmpty() && height[i] > height[stack.peek()]){//栈顶元素出栈,记录上次的处理的深度索引,且如去除重复深度索引int oldIndex = stack.pop();while(!stack.isEmpty() && height[stack.peek()] == height[oldIndex]){stack.pop();}if(!stack.isEmpty()){//记录坑的左高度的索引int stackTop = stack.peek();//与坑的右高度取最小值,且减去上次处理的深度,就为当前填充区域的深度。  //i-stackTop-1为宽度。[若]res += (Math.min(height[i],height[stackTop]) - height[oldIndex]) * (i - stackTop - 1);}}stack.push(i);}return res;}
}

方法2:暴力解法

  • 代码演示:
class Solution {public int trap(int[] height) {int len = height.length;if(len == 0){return 0;}int res = 0;/*依次遍历height数组,找到每一个数组的坐标最大值与右边最大值。最终两者取最小减去当前值,就是在当前下标i下所能接的雨水*/for(int i = 1 ; i < len ; i++){int leftMax = 0;int rightMax = 0;for(int j = i ; j >=0 ; j--){leftMax = Math.max(leftMax,height[j]);}for(int j = i ; j < len ;j++){rightMax = Math.max(rightMax,height[j]);}res += Math.min(leftMax,rightMax) - height[i];}return res;}
}

方法3:DP

  • 思路:因为在暴力解法中,每次都需要搜索左边与右边的最大值,消耗时间较长。因此,可以提前将最大值求出,分别求出从左到右与从右到左的最大值数组。在遍历期间就不需要遍历求解,直接寻找对应下标的最大值即可。

    • 求最大值数组采用的为动态规划的思想。
  • 代码演示:
class Solution {public int trap(int[] height) {int len = height.length;if(len == 0){return 0;}int[] leftMax = new int[len];int[] rightMax = new int[len];int res = 0;leftMax[0] = height[0];//从左往右for(int i = 1 ; i < len ; i++){leftMax[i] = Math.max(leftMax[i-1],height[i]);}rightMax[len-1] = height[len-1];//从右到左for(int i = len-2; i >= 0 ;i--){rightMax[i] = Math.max(rightMax[i+1],height[i]);}//求每个下标的雨水值for(int i = 0 ; i < len ; i++){res += Math.min(rightMax[i],leftMax[i]) - height[i];}return res;}
}

方法4:双指针

  • 代码演示

class Solution {public int trap(int[] height) {int len = height.length;if(len == 0){return 0;}int left = 0;int right = len - 1;int leftMax = 0;//记录从左边开始的最大值int rightMax = 0;//记录从右边开始的最大值int res = 0;while(left < right){//右边柱子更高if(height[left] < height[right]){//积水的深度由左边柱子高度决定。更新最大值且求积水if(height[left] >= leftMax){leftMax = height[left];}else{res += (leftMax - height[left]);}left++;}else{//左边柱子更高,积水的深度由右边柱子高度决定。更新最大值且求积水if(height[right] >= rightMax){rightMax = height[right];}else{res += (rightMax - height[right]);}right--;}}return res;}
}

43.字符串相乘

  • 思路:按照普通的乘法过程来逐位计算
  • 代码演示:
class Solution {public String multiply(String num1, String num2) {if(num1.length() == 0 || num2.length() == 0){return "";}if(num1.equals("0") || num2.equals("0")){return "0";}if(num1.length() < num2.length()){String s = num1;num1 = num2;num2 = s;}String res = "";for(int i = num2.length()-1 ; i >= 0 ; i--){StringBuilder temp = new StringBuilder();//末尾补0for (int j = num2.length() - 1; j > i; j--) {temp.append(0);}int count = 0;for(int j = num1.length()-1 ; j >= 0 ; j--){int x = (num2.charAt(i) - '0') * (num1.charAt(j) - '0') + count;count = x / 10;x = x % 10;temp.insert(0,x);}//对进位进行特殊处理,最终还有进位,则继续压入if(count != 0){temp.insert(0,count );}res = addString(res,new String(temp));}return res;}public String addString(String s1,String s2){int index1 = s1.length()-1;int index2 = s2.length()-1;StringBuilder res =  new StringBuilder();int count = 0;while(index1 >=0 || index2 >= 0){int x1 = index1 >= 0 ? s1.charAt(index1) - '0' : 0;int x2 = index2 >= 0 ? s2.charAt(index2) - '0' : 0;int addNumber = x1 + x2 + count;count = addNumber / 10;addNumber = addNumber % 10;res.insert(0,addNumber);index1--;index2--;}//对进位进行特殊处理,最终还有进位,则继续压入if(count != 0){res.insert(0,count);}return res.toString();}
}

45. 跳跃游戏 II

  • 题解:https://leetcode-cn.com/problems/jump-game-ii/solution/45-tiao-yue-you-xi-iiliang-chong-tan-xin-q48k/

方法1:

  • 记录当前步与下一步的位置,进行判断
  • 代码演示
class Solution {/*curIndex:当前步可到达的最大位置nextIndex:下一步可到达的最大位置res:跳数*/public int jump(int[] nums) {int curIndex = 0;int nextIndex = 0;int res = 0;for(int i = 0; i < nums.length; i++){//记录下一步所能到达最大位置nextIndex = Math.max(nextIndex,i+nums[i]);if(i == curIndex){//若已到达当前步最大位置且最大位置在末尾,跳出直接返回if(curIndex == nums.length - 1){break;}else{//否则更新步数,且更新当前步最大位置res++;curIndex = nextIndex;}}}return res;}
}

方法2:方法1优化

class Solution {/*curIndex:当前步可到达的最大位置nextIndex:下一步可到达的最大位置res:跳数*/public int jump(int[] nums) {int curIndex = 0;int nextIndex = 0;int res = 0;//最多只能遍历到末尾位置的上一个位置for(int i = 0; i < nums.length-1; i++){//记录下一步所能到达最大位置nextIndex = Math.max(nextIndex,i+nums[i]);//i已经到达末尾位置的上一个位置,不需要进行再进行其余特殊判断,直接加1即可到达末尾位置。if(i == curIndex){//否则更新步数,且更新当前步最大位置res++;curIndex = nextIndex;}}return res;}
}

方法3:DP

  • 思路:https://leetcode-cn.com/problems/jump-game-ii/solution/xiang-jie-dp-tan-xin-shuang-zhi-zhen-jie-roh4/
  • 代码演示:
class Solution {public int jump(int[] nums) {//dp[i]表示最少经过几步可以到达iint[] dp = new int[nums.length];dp[0] = 0;int j = 0; //外循环:记录dp数组。内循环:记录可以经过一跳到达dp位置的最远位置。for(int i = 1 ; i < nums.length ;i++){while(j + nums[j] < i){j++;}dp[i] = dp[j] + 1;}return dp[nums.length-1];}
}

49.字母异位词分组

  • 本题重点:如何将不同顺序字符串进行匹配。

方法1:排序

  • 代码演示
class Solution {/* 排序本题一个重点:如何将不同顺序字符串进行匹配。因此将不同顺序字符串转为字符数组,从而将字符数组排序,因此不同顺序字符串就可以进行匹配。*/public List<List<String>> groupAnagrams(String[] strs) {int len = strs.length;if(len == 0){return new ArrayList<>();}Map<String,List<String>> res = new HashMap<>();for(String s : strs){char[] schar = s.toCharArray();Arrays.sort(schar);String subs = String.valueOf(schar);if(!res.containsKey(subs)){res.put(subs,new ArrayList<String>());}res.get(subs).add(s);}//res.values()  返回collection集合。return new ArrayList<>(res.values());}
}

方法2:建立数组映射

  • 代码演示
class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String,List<String>> res = new HashMap<>();for(String str : strs){int[] count = new int[26];//记录当前str的每一个字符出现的次数for(int i = 0 ; i < str.length();i++){count[str.charAt(i) - 'a'] ++;}StringBuilder sb = new StringBuilder();/*将当前str中字符与其出现的次数进行拼接,作为key若当前字符与出现次数拼接后,存在key,就说明当前字符有字母异位词,压入当前List。否则,新建List压入。*/for(int i = 0 ; i < 26;i++){if(count[i] != 0){sb.append('a' + i);sb.append(count[i]);}}String s = sb.toString();List<String> list = res.getOrDefault(s,new ArrayList<>());list.add(str);res.put(s,list);}return new ArrayList<>(res.values());}
}

50.Pow(x, n)

  • 题解:https://leetcode-cn.com/problems/powx-n/solution/50-powx-n-kuai-su-mi-qing-xi-tu-jie-by-jyd/

方法1:快速幂

  • 思路:
  • 代码演示:
class Solution {public double myPow(double x, int n) {if(n == 0 || x == 1){return 1;}if(n == 0){return 0;}double res = 1;long b = n;/*Java 代码中 int32 变量 n∈[−2147483648,2147483647] ,因此当 n=−2147483648 时执行 n = -n 会因越界而赋值出错。解决方法是先将 n 存入 long 变量 b ,后面用 b 操作即可。*/if(b < 0){b = -b;x = 1/x;}while(b > 0){//b是奇数,if((b & 1) == 1){res = res * x;}x *= x;b >>= 1;}return res;}
}

方法2:分治 + 记忆化

class Solution {int res = 0;Map<Integer,Double> map = new HashMap<>();public double myPow(double x, int n) {if(n == 0 || x == 1){return 1;}if(n == 0){return 0;}if(n < 0){n = -n;x = 1/x;}return pow(x,n);}public double pow(double x,int n){//必须为n==0 return 1 不能为n==1 rutrun x 。具体原因经过debug调试未知...if( n == 0){return 1;}double half = 0;//看当前n/2是否运算过if(map.containsKey(n/2)){half = map.get(n/2);}else{half = pow(x,n/2);map.put(n/2,half);}if(n % 2 == 0){return half * half;}else{return half * half * x;}}
}

方法3:快速幂递归写法

class Solution {int flag = 1;public double myPow(double x, int n) {//简化计算,flag判断的当前x正负,输出时做处理if(n < 0){flag = -flag;n = Math.abs(n);}if(n == 0){return 1;}if(n == 1){return flag == 1 ? x : 1 / x;}double result = quickPow(x,n);return flag == 1 ? result : 1 / result;}//快速幂:x5 = (x2)2 * x;public double quickPow(double x ,int n){if(n == 0){return 1;}if(n == 1){return x;}double res = 0;if(n % 2 == 0){res = quickPow(Math.pow(x,2),n / 2);}else{res = quickPow(Math.pow(x,2), n /2) * x;}return res;}
}

LeetCode-按顺序刷题备注1-50相关推荐

  1. 《剑指 Offer I》刷题笔记 41 ~ 50 题

    <剑指 Offer I>刷题笔记 41_50 排序(中等) 41. 最小的k个数# _解法1:排序 API + 数组复制 API 42. 数据流中的中位数 _解法1:暴力 搜索和回溯算法( ...

  2. 合并的数组会有顺序么_咱就别按顺序刷题了,看看大佬怎么刷

    1. 碎碎念 今天完成了体育测试,大学生活真的就快要将近了,未来什么时候还能和这些可爱的同学们聚一聚呢?祝大家都好吧!比较让我高兴的是,公众号终于有了一个粉丝,哈哈哈,非常感谢关注哇!每天都要好好敲代 ...

  3. LeetCode:数组刷题(17道经典题目)

    LeetCode 数组刷题(17道经典题目) 本文带来的是以数组为主题的经典题目,主要实现是C++,部分题目也用Python实现了. 704. 二分查找 35.搜索插入位置 34. 在排序数组中查找元 ...

  4. LeetCode按知识点刷题,额外附带题解

    刷题顺序转自:ACM金牌选手整理的[LeetCode刷题顺序]_清澈不在远方-CSDN博客 题解为本人自刷 数据结构 数组&双指针 LeetCode 1. 两数之和 /*** 给定一个整数数组 ...

  5. 力扣(LeetCode)打卡刷题交流计划(长期维护)

    前言 忙忙活活暑期过去了一半,在即将升学的日子里,打算干点什么东西,由于实力以及经验的欠缺没有创群和大家讨论,但我更喜欢以更实在的方式--能作点什么--和大家一起从0打开力扣LeetCode, 对,没 ...

  6. leetcode 高薪_LeetCode刷题实战69:x 的平方根

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...

  7. Leetcode按Tag刷题

    按照Leetcode的Tag来刷题,从easy到hard刷题 关于如何让Leetcode按难易程度排序,可按以下步骤: 1. 进入Leetcode后,点击code 2.点击code后,可查看所有题目, ...

  8. 力扣(LeetCode)怎么刷题,以排序算法为例

    掌握 LeetCode 刷题方法再开始刷题,属于磨刀不误砍柴工.掌握正确方法是非常重要的. 如果你在刷题的时候发现怎么也写不出来,别担心,这是正常的.如果你还发现,之前明明刷过的题,过段时间再做的时候 ...

  9. 力扣题目归类,顺序刷题不再难

    目录 介绍 前奏-基础篇 中篇-链表.树的相关操作 进阶-回溯.动态规划 脑筋急转弯 介绍 大家好,相信很多人都知道刷力扣的重要性,但是如果不能将题目很好的归类整理专一练习,而是东做一道西做一道,那么 ...

最新文章

  1. 【每日DP】day7P1064 金明的预算方案 (分组背包,我又悟了)难度⭐⭐★
  2. 计算机产业深度报告:云计算与人工智能开启新一轮技术变革周期
  3. Windows把内存变成快速虚拟硬盘
  4. Linux下运行Jmeter脚本
  5. Flex里监听mouseDownOutside事件解决弹出窗口点击空白关闭功能
  6. ie浏览器在线使用_微软加速反IE战略,超过1000个网站将拒绝渲染
  7. 英特尔第11代台式机处理器发布:或将是14nm最后的倔强
  8. Java 8 中的 java.util.Optional
  9. ironpython使用dictionary_Ironpython引用C#数据结构
  10. 在中国知网下载 PDF 格式的学位论文
  11. WMS 系统出入库理解
  12. H5营销海报如何制作,在线制作平台分享
  13. 计算机等级考试excel试题,计算机等级考试试题及答案解析(Excel) -电脑资料
  14. 自动驾驶系统中视觉感知模块的安全测试
  15. 中专计算机教研组活动总结,教研活动总结(精选6篇)
  16. 中国地区的手机号正则表达式
  17. 【愚公系列】2022年10月 微信小程序-电商项目-UI设计之蓝湖的使用
  18. 机器学习:朴素贝叶斯算法+中文情感分类+python
  19. Linux安装tomcat详细教程
  20. mac装python3问题_Mac下使用homebrew安装Python3问题-Go语言中文社区

热门文章

  1. USB 驱动程序堆栈体系结构
  2. jquery获取和设置html title标签值
  3. WebView白屏优化的一些整理
  4. 发个好玩的:椰子de鼠标键盘记录器 V1.3
  5. 他们在云南乡村卖车:到村里发礼物,拿普洱抵车款
  6. 怎么把图片做成画中画的效果
  7. 广告监测学习笔记(三)
  8. Linux查看硬件信息命令
  9. 搜遍整个淘宝,这8家礼物店最值得收藏!
  10. MongoDB过关测试二